summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/api/system-current.txt7
-rw-r--r--core/java/android/hardware/usb/IUsbManager.aidl5
-rw-r--r--core/java/android/hardware/usb/UsbManager.java32
-rw-r--r--core/java/android/hardware/usb/UsbPort.java77
-rw-r--r--core/java/android/hardware/usb/UsbPortStatus.java22
-rw-r--r--core/java/com/android/internal/usb/DumpUtils.java2
-rw-r--r--core/proto/android/service/usb.proto1
-rw-r--r--services/usb/java/com/android/server/usb/UsbPortManager.java83
-rw-r--r--services/usb/java/com/android/server/usb/UsbService.java22
-rw-r--r--services/usb/java/com/android/server/usb/hal/port/RawPortInfo.java11
-rw-r--r--services/usb/java/com/android/server/usb/hal/port/UsbPortAidl.java69
-rw-r--r--services/usb/java/com/android/server/usb/hal/port/UsbPortHal.java15
-rw-r--r--services/usb/java/com/android/server/usb/hal/port/UsbPortHidl.java20
13 files changed, 350 insertions, 16 deletions
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 0c8ee6e07c2f..7a76f7a3b534 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -4686,9 +4686,15 @@ package android.hardware.usb {
}
public final class UsbPort {
+ method @CheckResult @RequiresPermission(android.Manifest.permission.MANAGE_USB) public int enableLimitPowerTransfer(boolean);
method @CheckResult @RequiresPermission(android.Manifest.permission.MANAGE_USB) public int enableUsbData(boolean);
method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_USB) public android.hardware.usb.UsbPortStatus getStatus();
method @RequiresPermission(android.Manifest.permission.MANAGE_USB) public void setRoles(int, int);
+ field public static final int ENABLE_LIMIT_POWER_TRANSFER_ERROR_INTERNAL = 1; // 0x1
+ field public static final int ENABLE_LIMIT_POWER_TRANSFER_ERROR_NOT_SUPPORTED = 2; // 0x2
+ field public static final int ENABLE_LIMIT_POWER_TRANSFER_ERROR_OTHER = 4; // 0x4
+ field public static final int ENABLE_LIMIT_POWER_TRANSFER_ERROR_PORT_MISMATCH = 3; // 0x3
+ field public static final int ENABLE_LIMIT_POWER_TRANSFER_SUCCESS = 0; // 0x0
field public static final int ENABLE_USB_DATA_ERROR_INTERNAL = 1; // 0x1
field public static final int ENABLE_USB_DATA_ERROR_NOT_SUPPORTED = 2; // 0x2
field public static final int ENABLE_USB_DATA_ERROR_OTHER = 4; // 0x4
@@ -4703,6 +4709,7 @@ package android.hardware.usb {
method public int getCurrentPowerRole();
method public int getSupportedRoleCombinations();
method public boolean isConnected();
+ method public boolean isPowerTransferLimited();
method public boolean isRoleCombinationSupported(int, int);
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.hardware.usb.UsbPortStatus> CREATOR;
diff --git a/core/java/android/hardware/usb/IUsbManager.aidl b/core/java/android/hardware/usb/IUsbManager.aidl
index 3e79f18a4d65..1d0837e3f118 100644
--- a/core/java/android/hardware/usb/IUsbManager.aidl
+++ b/core/java/android/hardware/usb/IUsbManager.aidl
@@ -157,6 +157,11 @@ interface IUsbManager
/* Sets the port's current role. */
void setPortRoles(in String portId, int powerRole, int dataRole);
+ /* Limit power transfer in & out of the port within the allowed limit by the USB
+ * specification.
+ */
+ void enableLimitPowerTransfer(in String portId, boolean limit, int operationId, in IUsbOperationInternal callback);
+
/* Enable/disable contaminant detection */
void enableContaminantDetection(in String portId, boolean enable);
diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java
index 03eb461cc8d3..eb3e84d27c7c 100644
--- a/core/java/android/hardware/usb/UsbManager.java
+++ b/core/java/android/hardware/usb/UsbManager.java
@@ -1292,6 +1292,38 @@ public class UsbManager {
}
/**
+ * Should only be called by {@link UsbPort#enableLimitPowerTransfer}.
+ * <p>
+ * limits or restores power transfer in and out of USB port.
+ *
+ * @param port USB port for which power transfer has to be limited or restored.
+ * @param limit limit power transfer when true.
+ * relax power transfer restrictions when false.
+ * @param operationId operationId for the request.
+ * @param callback callback object to be invoked when the operation is complete.
+ *
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.MANAGE_USB)
+ void enableLimitPowerTransfer(@NonNull UsbPort port, boolean limit, int operationId,
+ IUsbOperationInternal callback) {
+ Objects.requireNonNull(port, "enableLimitPowerTransfer:port must not be null. opId:"
+ + operationId);
+ try {
+ mService.enableLimitPowerTransfer(port.getId(), limit, operationId, callback);
+ } catch (RemoteException e) {
+ Log.e(TAG, "enableLimitPowerTransfer failed. opId:" + operationId, e);
+ try {
+ callback.onOperationComplete(UsbOperationInternal.USB_OPERATION_ERROR_INTERNAL);
+ } catch (RemoteException r) {
+ Log.e(TAG, "enableLimitPowerTransfer failed to call onOperationComplete. opId:"
+ + operationId, r);
+ }
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Should only be called by {@link UsbPort#enableUsbData}.
* <p>
* Enables or disables USB data on the specific port.
diff --git a/core/java/android/hardware/usb/UsbPort.java b/core/java/android/hardware/usb/UsbPort.java
index f469a3e66d50..e908c245fc8e 100644
--- a/core/java/android/hardware/usb/UsbPort.java
+++ b/core/java/android/hardware/usb/UsbPort.java
@@ -118,6 +118,42 @@ public final class UsbPort {
@Retention(RetentionPolicy.SOURCE)
@interface EnableUsbDataStatus{}
+ /**
+ * The {@link #enableLimitPowerTransfer} request was successfully completed.
+ */
+ public static final int ENABLE_LIMIT_POWER_TRANSFER_SUCCESS = 0;
+
+ /**
+ * The {@link #enableLimitPowerTransfer} request failed due to internal error.
+ */
+ public static final int ENABLE_LIMIT_POWER_TRANSFER_ERROR_INTERNAL = 1;
+
+ /**
+ * The {@link #enableLimitPowerTransfer} request failed as it's not supported.
+ */
+ public static final int ENABLE_LIMIT_POWER_TRANSFER_ERROR_NOT_SUPPORTED = 2;
+
+ /**
+ * The {@link #enableLimitPowerTransfer} request failed as port id mismatched.
+ */
+ public static final int ENABLE_LIMIT_POWER_TRANSFER_ERROR_PORT_MISMATCH = 3;
+
+ /**
+ * The {@link #enableLimitPowerTransfer} request failed due to other reasons.
+ */
+ public static final int ENABLE_LIMIT_POWER_TRANSFER_ERROR_OTHER = 4;
+
+ /** @hide */
+ @IntDef(prefix = { "ENABLE_LIMIT_POWER_TRANSFER_" }, value = {
+ ENABLE_LIMIT_POWER_TRANSFER_SUCCESS,
+ ENABLE_LIMIT_POWER_TRANSFER_ERROR_INTERNAL,
+ ENABLE_LIMIT_POWER_TRANSFER_ERROR_NOT_SUPPORTED,
+ ENABLE_LIMIT_POWER_TRANSFER_ERROR_PORT_MISMATCH,
+ ENABLE_LIMIT_POWER_TRANSFER_ERROR_OTHER
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ @interface EnableLimitPowerTransferStatus{}
+
/** @hide */
public UsbPort(@NonNull UsbManager usbManager, @NonNull String id, int supportedModes,
int supportedContaminantProtectionModes,
@@ -272,6 +308,47 @@ public final class UsbPort {
}
/**
+ * Limits power transfer In and out of the port.
+ * <p>
+ * Disables charging and limits sourcing power(when permitted by the USB spec) until
+ * port disconnect event.
+ * </p>
+ * @param enable limits power transfer when true.
+ * @return {@link #ENABLE_LIMIT_POWER_TRANSFER_SUCCESS} when request completes successfully or
+ * {@link #ENABLE_LIMIT_POWER_TRANSFER_ERROR_INTERNAL} when request fails due to
+ * internal error or
+ * {@link ENABLE_LIMIT_POWER_TRANSFER_ERROR_NOT_SUPPORTED} when not supported or
+ * {@link ENABLE_LIMIT_POWER_TRANSFER_ERROR_PORT_MISMATCH} when request fails due to
+ * port id mismatch or
+ * {@link ENABLE_LIMIT_POWER_TRANSFER_ERROR_OTHER} when fails due to other reasons.
+ */
+ @CheckResult
+ @RequiresPermission(Manifest.permission.MANAGE_USB)
+ public @EnableLimitPowerTransferStatus int enableLimitPowerTransfer(boolean enable) {
+ // UID is added To minimize operationID overlap between two different packages.
+ int operationId = sUsbOperationCount.incrementAndGet() + Binder.getCallingUid();
+ Log.i(TAG, "enableLimitPowerTransfer opId:" + operationId
+ + " callingUid:" + Binder.getCallingUid());
+ UsbOperationInternal opCallback =
+ new UsbOperationInternal(operationId, mId);
+ mUsbManager.enableLimitPowerTransfer(this, enable, operationId, opCallback);
+ opCallback.waitForOperationComplete();
+ int result = opCallback.getStatus();
+ switch (result) {
+ case USB_OPERATION_SUCCESS:
+ return ENABLE_LIMIT_POWER_TRANSFER_SUCCESS;
+ case USB_OPERATION_ERROR_INTERNAL:
+ return ENABLE_LIMIT_POWER_TRANSFER_ERROR_INTERNAL;
+ case USB_OPERATION_ERROR_NOT_SUPPORTED:
+ return ENABLE_LIMIT_POWER_TRANSFER_ERROR_NOT_SUPPORTED;
+ case USB_OPERATION_ERROR_PORT_MISMATCH:
+ return ENABLE_LIMIT_POWER_TRANSFER_ERROR_PORT_MISMATCH;
+ default:
+ return ENABLE_LIMIT_POWER_TRANSFER_ERROR_OTHER;
+ }
+ }
+
+ /**
* @hide
**/
public void enableContaminantDetection(boolean enable) {
diff --git a/core/java/android/hardware/usb/UsbPortStatus.java b/core/java/android/hardware/usb/UsbPortStatus.java
index bd2f9aa55bda..934c5067c11f 100644
--- a/core/java/android/hardware/usb/UsbPortStatus.java
+++ b/core/java/android/hardware/usb/UsbPortStatus.java
@@ -43,6 +43,7 @@ public final class UsbPortStatus implements Parcelable {
private final @ContaminantProtectionStatus int mContaminantProtectionStatus;
private final @ContaminantDetectionStatus int mContaminantDetectionStatus;
private final boolean mUsbDataEnabled;
+ private final boolean mPowerTransferLimited;
/**
* Power role: This USB port does not have a power role.
@@ -224,7 +225,8 @@ public final class UsbPortStatus implements Parcelable {
/** @hide */
public UsbPortStatus(int currentMode, int currentPowerRole, int currentDataRole,
int supportedRoleCombinations, int contaminantProtectionStatus,
- int contaminantDetectionStatus, boolean usbDataEnabled) {
+ int contaminantDetectionStatus, boolean usbDataEnabled,
+ boolean powerTransferLimited) {
mCurrentMode = currentMode;
mCurrentPowerRole = currentPowerRole;
mCurrentDataRole = currentDataRole;
@@ -232,6 +234,7 @@ public final class UsbPortStatus implements Parcelable {
mContaminantProtectionStatus = contaminantProtectionStatus;
mContaminantDetectionStatus = contaminantDetectionStatus;
mUsbDataEnabled = usbDataEnabled;
+ mPowerTransferLimited = powerTransferLimited;
}
/** @hide */
@@ -245,6 +248,7 @@ public final class UsbPortStatus implements Parcelable {
mContaminantProtectionStatus = contaminantProtectionStatus;
mContaminantDetectionStatus = contaminantDetectionStatus;
mUsbDataEnabled = true;
+ mPowerTransferLimited = false;
}
/**
@@ -336,6 +340,16 @@ public final class UsbPortStatus implements Parcelable {
return mUsbDataEnabled;
}
+ /**
+ * Returns whether power transfer is limited.
+ *
+ * @return true when power transfer is limited.
+ * false otherwise.
+ */
+ public boolean isPowerTransferLimited() {
+ return mPowerTransferLimited;
+ }
+
@NonNull
@Override
public String toString() {
@@ -351,6 +365,8 @@ public final class UsbPortStatus implements Parcelable {
+ getContaminantProtectionStatus()
+ ", usbDataEnabled="
+ getUsbDataStatus()
+ + ", isPowerTransferLimited="
+ + isPowerTransferLimited()
+ "}";
}
@@ -368,6 +384,7 @@ public final class UsbPortStatus implements Parcelable {
dest.writeInt(mContaminantProtectionStatus);
dest.writeInt(mContaminantDetectionStatus);
dest.writeBoolean(mUsbDataEnabled);
+ dest.writeBoolean(mPowerTransferLimited);
}
public static final @NonNull Parcelable.Creator<UsbPortStatus> CREATOR =
@@ -381,9 +398,10 @@ public final class UsbPortStatus implements Parcelable {
int contaminantProtectionStatus = in.readInt();
int contaminantDetectionStatus = in.readInt();
boolean usbDataEnabled = in.readBoolean();
+ boolean powerTransferLimited = in.readBoolean();
return new UsbPortStatus(currentMode, currentPowerRole, currentDataRole,
supportedRoleCombinations, contaminantProtectionStatus,
- contaminantDetectionStatus, usbDataEnabled);
+ contaminantDetectionStatus, usbDataEnabled, powerTransferLimited);
}
@Override
diff --git a/core/java/com/android/internal/usb/DumpUtils.java b/core/java/com/android/internal/usb/DumpUtils.java
index 744fe595d283..b06a7f4e56e4 100644
--- a/core/java/com/android/internal/usb/DumpUtils.java
+++ b/core/java/com/android/internal/usb/DumpUtils.java
@@ -246,6 +246,8 @@ public class DumpUtils {
status.getContaminantDetectionStatus());
dump.write("usb_data_enabled", UsbPortStatusProto.USB_DATA_ENABLED,
status.getUsbDataStatus());
+ dump.write("is_power_transfer_limited", UsbPortStatusProto.IS_POWER_TRANSFER_LIMITED,
+ status.isPowerTransferLimited());
dump.end(token);
}
}
diff --git a/core/proto/android/service/usb.proto b/core/proto/android/service/usb.proto
index c27aab551073..b3f54f9afce2 100644
--- a/core/proto/android/service/usb.proto
+++ b/core/proto/android/service/usb.proto
@@ -265,6 +265,7 @@ message UsbPortStatusProto {
repeated UsbPortStatusRoleCombinationProto role_combinations = 5;
optional android.service.ContaminantPresenceStatus contaminant_presence_status = 6;
optional bool usb_data_enabled = 7;
+ optional bool is_power_transfer_limited = 8;
}
message UsbPortStatusRoleCombinationProto {
diff --git a/services/usb/java/com/android/server/usb/UsbPortManager.java b/services/usb/java/com/android/server/usb/UsbPortManager.java
index d4726397b5eb..98173adfd0eb 100644
--- a/services/usb/java/com/android/server/usb/UsbPortManager.java
+++ b/services/usb/java/com/android/server/usb/UsbPortManager.java
@@ -226,6 +226,7 @@ public class UsbPortManager {
intent.setComponent(ComponentName.unflattenFromString(r.getString(
com.android.internal.R.string.config_usbContaminantActivity)));
intent.putExtra(UsbManager.EXTRA_PORT, ParcelableUsbPort.of(currentPortInfo.mUsbPort));
+ intent.putExtra(UsbManager.EXTRA_PORT_STATUS, currentPortInfo.mUsbPortStatus);
// Simple notification clicks are immutable
PendingIntent pi = PendingIntent.getActivityAsUser(mContext, 0,
@@ -340,6 +341,49 @@ public class UsbPortManager {
}
/**
+ * Limits power transfer in/out of USB-C port.
+ *
+ * @param portId port identifier.
+ * @param limit limit power transfer when true.
+ */
+ public void enableLimitPowerTransfer(@NonNull String portId, boolean limit, long transactionId,
+ IUsbOperationInternal callback, IndentingPrintWriter pw) {
+ Objects.requireNonNull(portId);
+ final PortInfo portInfo = mPorts.get(portId);
+ if (portInfo == null) {
+ logAndPrint(Log.ERROR, pw, "enableLimitPowerTransfer: No such port: " + portId
+ + " opId:" + transactionId);
+ try {
+ if (callback != null) {
+ callback.onOperationComplete(USB_OPERATION_ERROR_PORT_MISMATCH);
+ }
+ } catch (RemoteException e) {
+ logAndPrintException(pw,
+ "enableLimitPowerTransfer: Failed to call OperationComplete. opId:"
+ + transactionId, e);
+ }
+ return;
+ }
+
+ try {
+ try {
+ mUsbPortHal.enableLimitPowerTransfer(portId, limit, transactionId, callback);
+ } catch (Exception e) {
+ logAndPrintException(pw,
+ "enableLimitPowerTransfer: Failed to limit power transfer. opId:"
+ + transactionId , e);
+ if (callback != null) {
+ callback.onOperationComplete(USB_OPERATION_ERROR_INTERNAL);
+ }
+ }
+ } catch (RemoteException e) {
+ logAndPrintException(pw,
+ "enableLimitPowerTransfer:Failed to call onOperationComplete. opId:"
+ + transactionId, e);
+ }
+ }
+
+ /**
* Enable/disable the USB data signaling
*
* @param enable enable or disable USB data signaling
@@ -715,7 +759,8 @@ public class UsbPortManager {
portInfo.contaminantProtectionStatus,
portInfo.supportsEnableContaminantPresenceDetection,
portInfo.contaminantDetectionStatus,
- portInfo.usbDataEnabled, pw);
+ portInfo.usbDataEnabled,
+ portInfo.powerTransferLimited, pw);
}
} else {
for (RawPortInfo currentPortInfo : newPortInfo) {
@@ -728,7 +773,8 @@ public class UsbPortManager {
currentPortInfo.contaminantProtectionStatus,
currentPortInfo.supportsEnableContaminantPresenceDetection,
currentPortInfo.contaminantDetectionStatus,
- currentPortInfo.usbDataEnabled, pw);
+ currentPortInfo.usbDataEnabled,
+ currentPortInfo.powerTransferLimited, pw);
}
}
@@ -765,6 +811,7 @@ public class UsbPortManager {
boolean supportsEnableContaminantPresenceDetection,
int contaminantDetectionStatus,
boolean usbDataEnabled,
+ boolean powerTransferLimited,
IndentingPrintWriter pw) {
// Only allow mode switch capability for dual role ports.
// Validate that the current mode matches the supported modes we expect.
@@ -823,7 +870,8 @@ public class UsbPortManager {
currentPowerRole, canChangePowerRole,
currentDataRole, canChangeDataRole,
supportedRoleCombinations, contaminantProtectionStatus,
- contaminantDetectionStatus, usbDataEnabled);
+ contaminantDetectionStatus, usbDataEnabled,
+ powerTransferLimited);
mPorts.put(portId, portInfo);
} else {
// Validate that ports aren't changing definition out from under us.
@@ -860,7 +908,8 @@ public class UsbPortManager {
currentPowerRole, canChangePowerRole,
currentDataRole, canChangeDataRole,
supportedRoleCombinations, contaminantProtectionStatus,
- contaminantDetectionStatus, usbDataEnabled)) {
+ contaminantDetectionStatus, usbDataEnabled,
+ powerTransferLimited)) {
portInfo.mDisposition = PortInfo.DISPOSITION_CHANGED;
} else {
portInfo.mDisposition = PortInfo.DISPOSITION_READY;
@@ -882,6 +931,7 @@ public class UsbPortManager {
private void handlePortChangedLocked(PortInfo portInfo, IndentingPrintWriter pw) {
logAndPrint(Log.INFO, pw, "USB port changed: " + portInfo);
enableContaminantDetectionIfNeeded(portInfo, pw);
+ disableLimitPowerTransferIfNeeded(portInfo, pw);
handlePortLocked(portInfo, pw);
}
@@ -938,6 +988,19 @@ public class UsbPortManager {
}
}
+ private void disableLimitPowerTransferIfNeeded(PortInfo portInfo, IndentingPrintWriter pw) {
+ if (!mConnected.containsKey(portInfo.mUsbPort.getId())) {
+ return;
+ }
+
+ if (mConnected.get(portInfo.mUsbPort.getId())
+ && !portInfo.mUsbPortStatus.isConnected()
+ && portInfo.mUsbPortStatus.isPowerTransferLimited()) {
+ // Relax enableLimitPowerTransfer upon unplug.
+ enableLimitPowerTransfer(portInfo.mUsbPort.getId(), false, ++mTransactionId, null, pw);
+ }
+ }
+
private void logToStatsd(PortInfo portInfo, IndentingPrintWriter pw) {
// Port is removed
if (portInfo.mUsbPortStatus == null) {
@@ -1072,7 +1135,7 @@ public class UsbPortManager {
!= supportedRoleCombinations) {
mUsbPortStatus = new UsbPortStatus(currentMode, currentPowerRole, currentDataRole,
supportedRoleCombinations, UsbPortStatus.CONTAMINANT_PROTECTION_NONE,
- UsbPortStatus.CONTAMINANT_DETECTION_NOT_SUPPORTED, true);
+ UsbPortStatus.CONTAMINANT_DETECTION_NOT_SUPPORTED, true, false);
dispositionChanged = true;
}
@@ -1091,7 +1154,8 @@ public class UsbPortManager {
int currentPowerRole, boolean canChangePowerRole,
int currentDataRole, boolean canChangeDataRole,
int supportedRoleCombinations, int contaminantProtectionStatus,
- int contaminantDetectionStatus, boolean usbDataEnabled) {
+ int contaminantDetectionStatus, boolean usbDataEnabled,
+ boolean powerTransferLimited) {
boolean dispositionChanged = false;
mCanChangeMode = canChangeMode;
@@ -1108,10 +1172,13 @@ public class UsbPortManager {
|| mUsbPortStatus.getContaminantDetectionStatus()
!= contaminantDetectionStatus
|| mUsbPortStatus.getUsbDataStatus()
- != usbDataEnabled){
+ != usbDataEnabled
+ || mUsbPortStatus.isPowerTransferLimited()
+ != powerTransferLimited) {
mUsbPortStatus = new UsbPortStatus(currentMode, currentPowerRole, currentDataRole,
supportedRoleCombinations, contaminantProtectionStatus,
- contaminantDetectionStatus, usbDataEnabled);
+ contaminantDetectionStatus, usbDataEnabled,
+ powerTransferLimited);
dispositionChanged = true;
}
diff --git a/services/usb/java/com/android/server/usb/UsbService.java b/services/usb/java/com/android/server/usb/UsbService.java
index 28227fcf0468..51643e7d7d3c 100644
--- a/services/usb/java/com/android/server/usb/UsbService.java
+++ b/services/usb/java/com/android/server/usb/UsbService.java
@@ -734,6 +734,28 @@ public class UsbService extends IUsbManager.Stub {
}
@Override
+ public void enableLimitPowerTransfer(String portId, boolean limit, int operationId,
+ IUsbOperationInternal callback) {
+ Objects.requireNonNull(portId, "portId must not be null. opID:" + operationId);
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
+
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ if (mPortManager != null) {
+ mPortManager.enableLimitPowerTransfer(portId, limit, operationId, callback, null);
+ } else {
+ try {
+ callback.onOperationComplete(USB_OPERATION_ERROR_INTERNAL);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "enableLimitPowerTransfer: Failed to call onOperationComplete", e);
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ @Override
public void enableContaminantDetection(String portId, boolean enable) {
Objects.requireNonNull(portId, "portId must not be null");
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
diff --git a/services/usb/java/com/android/server/usb/hal/port/RawPortInfo.java b/services/usb/java/com/android/server/usb/hal/port/RawPortInfo.java
index 9c6cbbd96460..8dfc85995272 100644
--- a/services/usb/java/com/android/server/usb/hal/port/RawPortInfo.java
+++ b/services/usb/java/com/android/server/usb/hal/port/RawPortInfo.java
@@ -38,6 +38,7 @@ public final class RawPortInfo implements Parcelable {
public boolean supportsEnableContaminantPresenceDetection;
public int contaminantDetectionStatus;
public boolean usbDataEnabled;
+ public boolean powerTransferLimited;
public RawPortInfo(String portId, int supportedModes) {
this.portId = portId;
@@ -48,6 +49,7 @@ public final class RawPortInfo implements Parcelable {
this.supportsEnableContaminantPresenceDetection = false;
this.contaminantDetectionStatus = UsbPortStatus.CONTAMINANT_DETECTION_NOT_SUPPORTED;
this.usbDataEnabled = true;
+ this.powerTransferLimited = false;
}
public RawPortInfo(String portId, int supportedModes, int supportedContaminantProtectionModes,
@@ -58,7 +60,8 @@ public final class RawPortInfo implements Parcelable {
int contaminantProtectionStatus,
boolean supportsEnableContaminantPresenceDetection,
int contaminantDetectionStatus,
- boolean usbDataEnabled) {
+ boolean usbDataEnabled,
+ boolean powerTransferLimited) {
this.portId = portId;
this.supportedModes = supportedModes;
this.supportedContaminantProtectionModes = supportedContaminantProtectionModes;
@@ -75,6 +78,7 @@ public final class RawPortInfo implements Parcelable {
supportsEnableContaminantPresenceDetection;
this.contaminantDetectionStatus = contaminantDetectionStatus;
this.usbDataEnabled = usbDataEnabled;
+ this.powerTransferLimited = powerTransferLimited;
}
@Override
@@ -98,6 +102,7 @@ public final class RawPortInfo implements Parcelable {
dest.writeBoolean(supportsEnableContaminantPresenceDetection);
dest.writeInt(contaminantDetectionStatus);
dest.writeBoolean(usbDataEnabled);
+ dest.writeBoolean(powerTransferLimited);
}
public static final Parcelable.Creator<RawPortInfo> CREATOR =
@@ -118,6 +123,7 @@ public final class RawPortInfo implements Parcelable {
boolean supportsEnableContaminantPresenceDetection = in.readBoolean();
int contaminantDetectionStatus = in.readInt();
boolean usbDataEnabled = in.readBoolean();
+ boolean powerTransferLimited = in.readBoolean();
return new RawPortInfo(id, supportedModes,
supportedContaminantProtectionModes, currentMode, canChangeMode,
currentPowerRole, canChangePowerRole,
@@ -125,7 +131,8 @@ public final class RawPortInfo implements Parcelable {
supportsEnableContaminantPresenceProtection,
contaminantProtectionStatus,
supportsEnableContaminantPresenceDetection,
- contaminantDetectionStatus, usbDataEnabled);
+ contaminantDetectionStatus, usbDataEnabled,
+ powerTransferLimited);
}
@Override
diff --git a/services/usb/java/com/android/server/usb/hal/port/UsbPortAidl.java b/services/usb/java/com/android/server/usb/hal/port/UsbPortAidl.java
index 6f91a2a56280..24602426930d 100644
--- a/services/usb/java/com/android/server/usb/hal/port/UsbPortAidl.java
+++ b/services/usb/java/com/android/server/usb/hal/port/UsbPortAidl.java
@@ -281,6 +281,47 @@ public final class UsbPortAidl implements UsbPortHal {
}
}
+ @Override
+ public void enableLimitPowerTransfer(String portName, boolean limit, long operationID,
+ IUsbOperationInternal callback) {
+ Objects.requireNonNull(portName);
+ long key = operationID;
+ synchronized (mLock) {
+ try {
+ if (mProxy == null) {
+ logAndPrint(Log.ERROR, mPw,
+ "enableLimitPowerTransfer: Proxy is null. Retry !opID:"
+ + operationID);
+ callback.onOperationComplete(USB_OPERATION_ERROR_INTERNAL);
+ return;
+ }
+ while (sCallbacks.get(key) != null) {
+ key = ThreadLocalRandom.current().nextInt();
+ }
+ if (key != operationID) {
+ logAndPrint(Log.INFO, mPw, "enableUsbData: operationID exists ! opID:"
+ + operationID + " key:" + key);
+ }
+ try {
+ sCallbacks.put(key, callback);
+ mProxy.limitPowerTransfer(portName, limit, key);
+ } catch (RemoteException e) {
+ logAndPrintException(mPw,
+ "enableLimitPowerTransfer: Failed while invoking AIDL HAL"
+ + " portID=" + portName + " opID:" + operationID, e);
+ if (callback != null) {
+ callback.onOperationComplete(USB_OPERATION_ERROR_INTERNAL);
+ }
+ sCallbacks.remove(key);
+ }
+ } catch (RemoteException e) {
+ logAndPrintException(mPw,
+ "enableLimitPowerTransfer: Failed to call onOperationComplete portID="
+ + portName + " opID:" + operationID, e);
+ }
+ }
+ }
+
private static class HALCallback extends IUsbCallback.Stub {
public IndentingPrintWriter mPw;
public UsbPortManager mPortManager;
@@ -393,7 +434,8 @@ public final class UsbPortAidl implements UsbPortHal {
toContaminantProtectionStatus(current.contaminantProtectionStatus),
current.supportsEnableContaminantPresenceDetection,
current.contaminantDetectionStatus,
- current.usbDataEnabled);
+ current.usbDataEnabled,
+ current.powerTransferLimited);
newPortInfo.add(temp);
UsbPortManager.logAndPrint(Log.INFO, mPw, "ClientCallback AIDL V1: "
+ current.portName);
@@ -462,5 +504,30 @@ public final class UsbPortAidl implements UsbPortHal {
+ operationID + " failed. err:" + retval);
}
}
+
+ @Override
+ public void notifyLimitPowerTransferStatus(String portName, boolean limit, int retval,
+ long operationID) {
+ if (retval == Status.SUCCESS) {
+ UsbPortManager.logAndPrint(Log.INFO, mPw, portName + ": opID:"
+ + operationID + " successful");
+ } else {
+ UsbPortManager.logAndPrint(Log.ERROR, mPw, portName
+ + "notifyLimitPowerTransferStatus: opID:"
+ + operationID + " failed. err:" + retval);
+ }
+ try {
+ IUsbOperationInternal callback = sCallbacks.get(operationID);
+ if (callback != null) {
+ sCallbacks.get(operationID).onOperationComplete(retval == Status.SUCCESS
+ ? USB_OPERATION_SUCCESS
+ : USB_OPERATION_ERROR_INTERNAL);
+ }
+ } catch (RemoteException e) {
+ logAndPrintException(mPw,
+ "enableLimitPowerTransfer: Failed to call onOperationComplete",
+ e);
+ }
+ }
}
}
diff --git a/services/usb/java/com/android/server/usb/hal/port/UsbPortHal.java b/services/usb/java/com/android/server/usb/hal/port/UsbPortHal.java
index e7f9bc2fe7c3..90c89090ef16 100644
--- a/services/usb/java/com/android/server/usb/hal/port/UsbPortHal.java
+++ b/services/usb/java/com/android/server/usb/hal/port/UsbPortHal.java
@@ -166,4 +166,19 @@ public interface UsbPortHal {
*/
public boolean enableUsbData(String portName, boolean enable, long transactionId,
IUsbOperationInternal callback);
+
+ /**
+ * Invoked to enableLimitPowerTransfer on the specified port.
+ *
+ * @param portName Port Identifier.
+ * @param limit limit power transfer when true. Port wouldn't charge or power USB accessoried
+ * when set.
+ * Lift power transfer restrictions when false.
+ * @param transactionId Used for tracking the current request and is passed down to the HAL
+ * implementation as needed.
+ * @param callback callback object to be invoked to invoke the status of the operation upon
+ * completion.
+ */
+ public void enableLimitPowerTransfer(String portName, boolean limit, long transactionId,
+ IUsbOperationInternal callback);
}
diff --git a/services/usb/java/com/android/server/usb/hal/port/UsbPortHidl.java b/services/usb/java/com/android/server/usb/hal/port/UsbPortHidl.java
index 00d0d06705fc..8a0370ad4909 100644
--- a/services/usb/java/com/android/server/usb/hal/port/UsbPortHidl.java
+++ b/services/usb/java/com/android/server/usb/hal/port/UsbPortHidl.java
@@ -271,6 +271,17 @@ public final class UsbPortHidl implements UsbPortHal {
}
@Override
+ public void enableLimitPowerTransfer(String portName, boolean limit, long transactionId,
+ IUsbOperationInternal callback) {
+ /* Not supported in HIDL hals*/
+ try {
+ callback.onOperationComplete(USB_OPERATION_ERROR_NOT_SUPPORTED);
+ } catch (RemoteException e) {
+ logAndPrintException(mPw, "Failed to call onOperationComplete", e);
+ }
+ }
+
+ @Override
public void switchDataRole(String portId, @HalUsbDataRole int newDataRole, long transactionId) {
synchronized (mLock) {
if (mProxy == null) {
@@ -382,7 +393,8 @@ public final class UsbPortHidl implements UsbPortHal {
current.canChangePowerRole,
current.currentDataRole, current.canChangeDataRole,
false, CONTAMINANT_PROTECTION_NONE,
- false, CONTAMINANT_DETECTION_NOT_SUPPORTED, sUsbDataEnabled);
+ false, CONTAMINANT_DETECTION_NOT_SUPPORTED, sUsbDataEnabled,
+ false);
newPortInfo.add(temp);
UsbPortManager.logAndPrint(Log.INFO, mPw, "ClientCallback V1_0: "
+ current.portName);
@@ -415,7 +427,8 @@ public final class UsbPortHidl implements UsbPortHal {
current.status.canChangePowerRole,
current.status.currentDataRole, current.status.canChangeDataRole,
false, CONTAMINANT_PROTECTION_NONE,
- false, CONTAMINANT_DETECTION_NOT_SUPPORTED, sUsbDataEnabled);
+ false, CONTAMINANT_DETECTION_NOT_SUPPORTED, sUsbDataEnabled,
+ false);
newPortInfo.add(temp);
UsbPortManager.logAndPrint(Log.INFO, mPw, "ClientCallback V1_1: "
+ current.status.portName);
@@ -452,7 +465,8 @@ public final class UsbPortHidl implements UsbPortHal {
current.contaminantProtectionStatus,
current.supportsEnableContaminantPresenceDetection,
current.contaminantDetectionStatus,
- sUsbDataEnabled);
+ sUsbDataEnabled,
+ false);
newPortInfo.add(temp);
UsbPortManager.logAndPrint(Log.INFO, mPw, "ClientCallback V1_2: "
+ current.status_1_1.status.portName);