Support USB Port Reset
Verify the USB Gadget HAL already implement. Bug: 197300598 Test: Verify the API working manually Signed-off-by: Ricky Niu <rickyniu@google.com> Change-Id: I8a4a4966237c925c87b32f74a382b7a56f82ab7d
This commit is contained in:
@@ -4690,6 +4690,7 @@ package android.hardware.usb {
|
||||
method @CheckResult @RequiresPermission(android.Manifest.permission.MANAGE_USB) public int enableUsbData(boolean);
|
||||
method @CheckResult @RequiresPermission(android.Manifest.permission.MANAGE_USB) public int enableUsbDataWhileDocked();
|
||||
method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_USB) public android.hardware.usb.UsbPortStatus getStatus();
|
||||
method @CheckResult @RequiresPermission(android.Manifest.permission.MANAGE_USB) public int resetUsbPort();
|
||||
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
|
||||
|
||||
@@ -136,6 +136,9 @@ interface IUsbManager
|
||||
/* Resets the USB gadget. */
|
||||
void resetUsbGadget();
|
||||
|
||||
/* Resets the USB port. */
|
||||
boolean resetUsbPort(in String portId, int operationId, in IUsbOperationInternal callback);
|
||||
|
||||
/* Set USB data on or off */
|
||||
boolean enableUsbData(in String portId, boolean enable, int operationId, in IUsbOperationInternal callback);
|
||||
|
||||
|
||||
@@ -1323,6 +1323,43 @@ public class UsbManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Should only be called by {@link UsbPort#resetUsbPort}.
|
||||
* <p>
|
||||
* Disable and then re-enable USB data signaling.
|
||||
*
|
||||
* Reset USB first port..
|
||||
* It will force to stop and restart USB data signaling.
|
||||
* Call UsbPort API if the device has more than one UsbPort.
|
||||
* </p>
|
||||
*
|
||||
* @param port reset the USB Port
|
||||
* @return true enable or disable USB data successfully
|
||||
* false if something wrong
|
||||
*
|
||||
* Should only be called by {@link UsbPort#resetUsbPort}.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
@RequiresPermission(Manifest.permission.MANAGE_USB)
|
||||
boolean resetUsbPort(@NonNull UsbPort port, int operationId,
|
||||
IUsbOperationInternal callback) {
|
||||
Objects.requireNonNull(port, "resetUsbPort: port must not be null. opId:" + operationId);
|
||||
try {
|
||||
return mService.resetUsbPort(port.getId(), operationId, callback);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "resetUsbPort: failed. ", e);
|
||||
try {
|
||||
callback.onOperationComplete(UsbOperationInternal.USB_OPERATION_ERROR_INTERNAL);
|
||||
} catch (RemoteException r) {
|
||||
Log.e(TAG, "resetUsbPort: failed to call onOperationComplete. opId:"
|
||||
+ operationId, r);
|
||||
}
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Should only be called by {@link UsbPort#enableUsbData}.
|
||||
* <p>
|
||||
|
||||
@@ -128,6 +128,9 @@ public final class UsbPort {
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@interface EnableUsbDataStatus{}
|
||||
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@interface ResetUsbPortStatus{}
|
||||
|
||||
/**
|
||||
* The {@link #enableLimitPowerTransfer} request was successfully completed.
|
||||
*/
|
||||
@@ -318,6 +321,43 @@ public final class UsbPort {
|
||||
mUsbManager.setPortRoles(this, powerRole, dataRole);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset Usb data on the port.
|
||||
*
|
||||
* @return {@link #ENABLE_USB_DATA_SUCCESS} when request completes successfully or
|
||||
* {@link #ENABLE_USB_DATA_ERROR_INTERNAL} when request fails due to internal
|
||||
* error or
|
||||
* {@link ENABLE_USB_DATA_ERROR_NOT_SUPPORTED} when not supported or
|
||||
* {@link ENABLE_USB_DATA_ERROR_PORT_MISMATCH} when request fails due to port id
|
||||
* mismatch or
|
||||
* {@link ENABLE_USB_DATA_ERROR_OTHER} when fails due to other reasons.
|
||||
*/
|
||||
@CheckResult
|
||||
@RequiresPermission(Manifest.permission.MANAGE_USB)
|
||||
public @ResetUsbPortStatus int resetUsbPort() {
|
||||
// UID is added To minimize operationID overlap between two different packages.
|
||||
int operationId = sUsbOperationCount.incrementAndGet() + Binder.getCallingUid();
|
||||
Log.i(TAG, "resetUsbData opId:" + operationId);
|
||||
UsbOperationInternal opCallback =
|
||||
new UsbOperationInternal(operationId, mId);
|
||||
if (mUsbManager.resetUsbPort(this, operationId, opCallback) == true) {
|
||||
opCallback.waitForOperationComplete();
|
||||
}
|
||||
int result = opCallback.getStatus();
|
||||
switch (result) {
|
||||
case USB_OPERATION_SUCCESS:
|
||||
return ENABLE_USB_DATA_SUCCESS;
|
||||
case USB_OPERATION_ERROR_INTERNAL:
|
||||
return ENABLE_USB_DATA_ERROR_INTERNAL;
|
||||
case USB_OPERATION_ERROR_NOT_SUPPORTED:
|
||||
return ENABLE_USB_DATA_ERROR_NOT_SUPPORTED;
|
||||
case USB_OPERATION_ERROR_PORT_MISMATCH:
|
||||
return ENABLE_USB_DATA_ERROR_PORT_MISMATCH;
|
||||
default:
|
||||
return ENABLE_USB_DATA_ERROR_OTHER;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables/Disables Usb data on the port.
|
||||
*
|
||||
|
||||
@@ -503,6 +503,49 @@ public class UsbPortManager {
|
||||
return HAL_MODE_DFP;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset USB port.
|
||||
*
|
||||
* @param portId port identifier.
|
||||
*/
|
||||
public boolean resetUsbPort(@NonNull String portId, int transactionId,
|
||||
@NonNull IUsbOperationInternal callback, IndentingPrintWriter pw) {
|
||||
synchronized (mLock) {
|
||||
Objects.requireNonNull(callback);
|
||||
Objects.requireNonNull(portId);
|
||||
final PortInfo portInfo = mPorts.get(portId);
|
||||
if (portInfo == null) {
|
||||
logAndPrint(Log.ERROR, pw, "resetUsbPort: No such port: " + portId
|
||||
+ " opId:" + transactionId);
|
||||
try {
|
||||
callback.onOperationComplete(
|
||||
USB_OPERATION_ERROR_PORT_MISMATCH);
|
||||
} catch (RemoteException e) {
|
||||
logAndPrintException(pw,
|
||||
"resetUsbPort: Failed to call OperationComplete. opId:"
|
||||
+ transactionId, e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
try {
|
||||
return mUsbPortHal.resetUsbPort(portId, transactionId, callback);
|
||||
} catch (Exception e) {
|
||||
logAndPrintException(pw,
|
||||
"reseetUsbPort: Failed to resetUsbPort. opId:"
|
||||
+ transactionId , e);
|
||||
callback.onOperationComplete(USB_OPERATION_ERROR_INTERNAL);
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
logAndPrintException(pw,
|
||||
"resetUsbPort: Failed to call onOperationComplete. opId:"
|
||||
+ transactionId, e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void setPortRoles(String portId, int newPowerRole, int newDataRole,
|
||||
IndentingPrintWriter pw) {
|
||||
synchronized (mLock) {
|
||||
|
||||
@@ -679,6 +679,35 @@ public class UsbService extends IUsbManager.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean resetUsbPort(String portId, int operationId,
|
||||
IUsbOperationInternal callback) {
|
||||
Objects.requireNonNull(portId, "resetUsbPort: portId must not be null. opId:"
|
||||
+ operationId);
|
||||
Objects.requireNonNull(callback, "resetUsbPort: callback must not be null. opId:"
|
||||
+ operationId);
|
||||
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
|
||||
|
||||
final long ident = Binder.clearCallingIdentity();
|
||||
boolean wait;
|
||||
|
||||
try {
|
||||
if (mPortManager != null) {
|
||||
wait = mPortManager.resetUsbPort(portId, operationId, callback, null);
|
||||
} else {
|
||||
wait = false;
|
||||
try {
|
||||
callback.onOperationComplete(USB_OPERATION_ERROR_INTERNAL);
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "resetUsbPort: Failed to call onOperationComplete", e);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(ident);
|
||||
}
|
||||
return wait;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ParcelableUsbPort> getPorts() {
|
||||
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
|
||||
|
||||
@@ -237,6 +237,50 @@ public final class UsbPortAidl implements UsbPortHal {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean resetUsbPort(String portName, long operationID,
|
||||
IUsbOperationInternal callback) {
|
||||
Objects.requireNonNull(portName);
|
||||
Objects.requireNonNull(callback);
|
||||
long key = operationID;
|
||||
synchronized (mLock) {
|
||||
try {
|
||||
if (mProxy == null) {
|
||||
logAndPrint(Log.ERROR, mPw,
|
||||
"resetUsbPort: Proxy is null. Retry !opID:"
|
||||
+ operationID);
|
||||
callback.onOperationComplete(USB_OPERATION_ERROR_INTERNAL);
|
||||
return false;
|
||||
}
|
||||
while (sCallbacks.get(key) != null) {
|
||||
key = ThreadLocalRandom.current().nextInt();
|
||||
}
|
||||
if (key != operationID) {
|
||||
logAndPrint(Log.INFO, mPw, "resetUsbPort: operationID exists ! opID:"
|
||||
+ operationID + " key:" + key);
|
||||
}
|
||||
try {
|
||||
sCallbacks.put(operationID, callback);
|
||||
mProxy.resetUsbPort(portName, operationID);
|
||||
} catch (RemoteException e) {
|
||||
logAndPrintException(mPw,
|
||||
"resetUsbPort: Failed to resetUsbPort: portID="
|
||||
+ portName + "opId:" + operationID, e);
|
||||
callback.onOperationComplete(USB_OPERATION_ERROR_INTERNAL);
|
||||
sCallbacks.remove(key);
|
||||
return false;
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
logAndPrintException(mPw,
|
||||
"resetUsbPort: Failed to call onOperationComplete portID="
|
||||
+ portName + "opID:" + operationID, e);
|
||||
sCallbacks.remove(key);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean enableUsbData(String portName, boolean enable, long operationID,
|
||||
IUsbOperationInternal callback) {
|
||||
@@ -605,5 +649,27 @@ public final class UsbPortAidl implements UsbPortHal {
|
||||
e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyResetUsbPortStatus(String portName, int retval,
|
||||
long operationID) {
|
||||
if (retval == Status.SUCCESS) {
|
||||
UsbPortManager.logAndPrint(Log.INFO, mPw, "notifyResetUsbPortStatus:"
|
||||
+ portName + ": opID:" + operationID);
|
||||
} else {
|
||||
UsbPortManager.logAndPrint(Log.ERROR, mPw, portName
|
||||
+ "notifyEnableUsbDataStatus: opID:"
|
||||
+ operationID + " failed. err:" + retval);
|
||||
}
|
||||
try {
|
||||
sCallbacks.get(operationID).onOperationComplete(retval == Status.SUCCESS
|
||||
? USB_OPERATION_SUCCESS
|
||||
: USB_OPERATION_ERROR_INTERNAL);
|
||||
} catch (RemoteException e) {
|
||||
logAndPrintException(mPw,
|
||||
"notifyResetUsbPortStatus: Failed to call onOperationComplete",
|
||||
e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,4 +193,18 @@ public interface UsbPortHal {
|
||||
*/
|
||||
public void enableLimitPowerTransfer(String portName, boolean limit, long transactionId,
|
||||
IUsbOperationInternal callback);
|
||||
|
||||
/**
|
||||
* Invoked to reset UsbData on the specified port.
|
||||
*
|
||||
* @param portName Port Identifier.
|
||||
* @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.
|
||||
* @param callback callback object to be invoked to invoke the status of the operation upon
|
||||
* completion.
|
||||
*/
|
||||
public boolean resetUsbPort(String portName, long transactionId,
|
||||
IUsbOperationInternal callback);
|
||||
}
|
||||
|
||||
@@ -317,6 +317,19 @@ public final class UsbPortHidl implements UsbPortHal {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean resetUsbPort(String portName, long transactionId,
|
||||
IUsbOperationInternal callback) {
|
||||
try {
|
||||
callback.onOperationComplete(USB_OPERATION_ERROR_NOT_SUPPORTED);
|
||||
} catch (RemoteException e) {
|
||||
logAndPrintException(mPw, "Failed to call onOperationComplete. opID:"
|
||||
+ transactionId
|
||||
+ " portId:" + portName, e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean enableUsbData(String portName, boolean enable, long transactionId,
|
||||
IUsbOperationInternal callback) {
|
||||
|
||||
Reference in New Issue
Block a user