diff options
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); |