Add limitPowerTransfer SystemAPI to UsbPort

limitPowerTransfer when invoked limits the power transfer
in and out of the USB port. limitPortTransfer is deactivated
either when limitPowerTransfer is deactivated by the caller
or when Usb disconnect event is observed by the Usb service.

limitPowerTransfer API is asynchronous and the caller gets
notified by invoking UsbOperationCallback.onUsbOperationComplete
callback to notify the status of the operation.

USB_PORT_CHANGED event is broadcasted when port's limitPowerTransfer
status changes. UsbPortStatus object is updated to reflect the
current status.

limitPowerTransfer is protected by android.permission.MANAGE_USB.

Bug: 199357330
Bug: 199358576
Test: Tested on Pixel
CTS-Coverage-Bug: 215019881
Signed-off-by: Badhri Jagan Sridharan <badhri@google.com>
Change-Id: Iabd1187f7527e14ed758abe355ba94a511d8c859
This commit is contained in:
Badhri Jagan Sridharan
2021-11-26 22:56:17 -08:00
committed by Ricky Niu
parent bbfa92e694
commit bdbb2d15be
13 changed files with 350 additions and 16 deletions

View File

@@ -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;

View File

@@ -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);

View File

@@ -1291,6 +1291,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>

View File

@@ -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,
@@ -271,6 +307,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
**/

View File

@@ -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

View File

@@ -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);
}
}

View File

@@ -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 {

View File

@@ -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,
@@ -339,6 +340,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
*
@@ -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;
}

View File

@@ -733,6 +733,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");

View File

@@ -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

View File

@@ -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);
}
}
}
}

View File

@@ -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);
}

View File

@@ -270,6 +270,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) {
@@ -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);