Merge "Asynchronous the resetUsbPort" into tm-dev

This commit is contained in:
TreeHugger Robot 2022-04-02 01:12:15 +00:00 committed by Android (Google) Code Review
commit c7daca4990
10 changed files with 109 additions and 53 deletions

View File

@ -5365,7 +5365,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 enableUsbData(boolean);
method @CheckResult @RequiresPermission(android.Manifest.permission.MANAGE_USB) public int enableUsbDataWhileDocked(); 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 @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 @CheckResult @RequiresPermission(android.Manifest.permission.MANAGE_USB) public void resetUsbPort(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
method @RequiresPermission(android.Manifest.permission.MANAGE_USB) public void setRoles(int, int); 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_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_NOT_SUPPORTED = 2; // 0x2
@ -5383,6 +5383,11 @@ package android.hardware.usb {
field public static final int ENABLE_USB_DATA_WHILE_DOCKED_ERROR_OTHER = 5; // 0x5 field public static final int ENABLE_USB_DATA_WHILE_DOCKED_ERROR_OTHER = 5; // 0x5
field public static final int ENABLE_USB_DATA_WHILE_DOCKED_ERROR_PORT_MISMATCH = 3; // 0x3 field public static final int ENABLE_USB_DATA_WHILE_DOCKED_ERROR_PORT_MISMATCH = 3; // 0x3
field public static final int ENABLE_USB_DATA_WHILE_DOCKED_SUCCESS = 0; // 0x0 field public static final int ENABLE_USB_DATA_WHILE_DOCKED_SUCCESS = 0; // 0x0
field public static final int RESET_USB_PORT_ERROR_INTERNAL = 1; // 0x1
field public static final int RESET_USB_PORT_ERROR_NOT_SUPPORTED = 2; // 0x2
field public static final int RESET_USB_PORT_ERROR_OTHER = 4; // 0x4
field public static final int RESET_USB_PORT_ERROR_PORT_MISMATCH = 3; // 0x3
field public static final int RESET_USB_PORT_SUCCESS = 0; // 0x0
} }
public final class UsbPortStatus implements android.os.Parcelable { public final class UsbPortStatus implements android.os.Parcelable {

View File

@ -137,7 +137,7 @@ interface IUsbManager
void resetUsbGadget(); void resetUsbGadget();
/* Resets the USB port. */ /* Resets the USB port. */
boolean resetUsbPort(in String portId, int operationId, in IUsbOperationInternal callback); void resetUsbPort(in String portId, int operationId, in IUsbOperationInternal callback);
/* Set USB data on or off */ /* Set USB data on or off */
boolean enableUsbData(in String portId, boolean enable, int operationId, in IUsbOperationInternal callback); boolean enableUsbData(in String portId, boolean enable, int operationId, in IUsbOperationInternal callback);

View File

@ -1360,11 +1360,11 @@ public class UsbManager {
* @hide * @hide
*/ */
@RequiresPermission(Manifest.permission.MANAGE_USB) @RequiresPermission(Manifest.permission.MANAGE_USB)
boolean resetUsbPort(@NonNull UsbPort port, int operationId, void resetUsbPort(@NonNull UsbPort port, int operationId,
IUsbOperationInternal callback) { IUsbOperationInternal callback) {
Objects.requireNonNull(port, "resetUsbPort: port must not be null. opId:" + operationId); Objects.requireNonNull(port, "resetUsbPort: port must not be null. opId:" + operationId);
try { try {
return mService.resetUsbPort(port.getId(), operationId, callback); mService.resetUsbPort(port.getId(), operationId, callback);
} catch (RemoteException e) { } catch (RemoteException e) {
Log.e(TAG, "resetUsbPort: failed. ", e); Log.e(TAG, "resetUsbPort: failed. ", e);
try { try {

View File

@ -15,6 +15,7 @@
*/ */
package android.hardware.usb; package android.hardware.usb;
import android.annotation.CallbackExecutor;
import android.annotation.IntDef; import android.annotation.IntDef;
import android.hardware.usb.IUsbOperationInternal; import android.hardware.usb.IUsbOperationInternal;
import android.hardware.usb.UsbPort; import android.hardware.usb.UsbPort;
@ -24,7 +25,9 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
/** /**
* UsbOperationInternal allows UsbPort to support both synchronous and * UsbOperationInternal allows UsbPort to support both synchronous and
* asynchronous function irrespective of whether the underlying hal * asynchronous function irrespective of whether the underlying hal
@ -39,6 +42,10 @@ public final class UsbOperationInternal extends IUsbOperationInternal.Stub {
private final String mId; private final String mId;
// True implies operation did not timeout. // True implies operation did not timeout.
private boolean mOperationComplete; private boolean mOperationComplete;
private boolean mAsynchronous = false;
private Executor mExecutor;
private Consumer<Integer> mConsumer;
private int mResult = 0;
private @UsbOperationStatus int mStatus; private @UsbOperationStatus int mStatus;
final ReentrantLock mLock = new ReentrantLock(); final ReentrantLock mLock = new ReentrantLock();
final Condition mOperationWait = mLock.newCondition(); final Condition mOperationWait = mLock.newCondition();
@ -78,6 +85,15 @@ public final class UsbOperationInternal extends IUsbOperationInternal.Stub {
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@interface UsbOperationStatus{} @interface UsbOperationStatus{}
UsbOperationInternal(int operationID, String id,
Executor executor, Consumer<Integer> consumer) {
this.mOperationID = operationID;
this.mId = id;
this.mExecutor = executor;
this.mConsumer = consumer;
this.mAsynchronous = true;
}
UsbOperationInternal(int operationID, String id) { UsbOperationInternal(int operationID, String id) {
this.mOperationID = operationID; this.mOperationID = operationID;
this.mId = id; this.mId = id;
@ -94,7 +110,27 @@ public final class UsbOperationInternal extends IUsbOperationInternal.Stub {
mOperationComplete = true; mOperationComplete = true;
mStatus = status; mStatus = status;
Log.i(TAG, "Port:" + mId + " opID:" + mOperationID + " status:" + mStatus); Log.i(TAG, "Port:" + mId + " opID:" + mOperationID + " status:" + mStatus);
mOperationWait.signal(); if (mAsynchronous) {
switch (mStatus) {
case USB_OPERATION_SUCCESS:
mResult = UsbPort.RESET_USB_PORT_SUCCESS;
break;
case USB_OPERATION_ERROR_INTERNAL:
mResult = UsbPort.RESET_USB_PORT_ERROR_INTERNAL;
break;
case USB_OPERATION_ERROR_NOT_SUPPORTED:
mResult = UsbPort.RESET_USB_PORT_ERROR_NOT_SUPPORTED;
break;
case USB_OPERATION_ERROR_PORT_MISMATCH:
mResult = UsbPort.RESET_USB_PORT_ERROR_PORT_MISMATCH;
break;
default:
mResult = UsbPort.RESET_USB_PORT_ERROR_OTHER;
}
mExecutor.execute(() -> mConsumer.accept(mResult));
} else {
mOperationWait.signal();
}
} finally { } finally {
mLock.unlock(); mLock.unlock();
} }

View File

@ -48,6 +48,7 @@ import static android.hardware.usb.UsbPortStatus.DATA_STATUS_DISABLED_FORCE;
import static android.hardware.usb.UsbPortStatus.DATA_STATUS_DISABLED_DEBUG; import static android.hardware.usb.UsbPortStatus.DATA_STATUS_DISABLED_DEBUG;
import android.Manifest; import android.Manifest;
import android.annotation.CallbackExecutor;
import android.annotation.CheckResult; import android.annotation.CheckResult;
import android.annotation.IntDef; import android.annotation.IntDef;
import android.annotation.NonNull; import android.annotation.NonNull;
@ -65,6 +66,8 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.util.Objects; import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
/** /**
* Represents a physical USB port and describes its characteristics. * Represents a physical USB port and describes its characteristics.
@ -128,9 +131,6 @@ public final class UsbPort {
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@interface EnableUsbDataStatus{} @interface EnableUsbDataStatus{}
@Retention(RetentionPolicy.SOURCE)
@interface ResetUsbPortStatus{}
/** /**
* The {@link #enableLimitPowerTransfer} request was successfully completed. * The {@link #enableLimitPowerTransfer} request was successfully completed.
*/ */
@ -197,6 +197,42 @@ public final class UsbPort {
*/ */
public static final int ENABLE_USB_DATA_WHILE_DOCKED_ERROR_OTHER = 5; public static final int ENABLE_USB_DATA_WHILE_DOCKED_ERROR_OTHER = 5;
/**
* The {@link #resetUsbPort} request was successfully completed.
*/
public static final int RESET_USB_PORT_SUCCESS = 0;
/**
* The {@link #resetUsbPort} request failed due to internal error.
*/
public static final int RESET_USB_PORT_ERROR_INTERNAL = 1;
/**
* The {@link #resetUsbPort} request failed as it's not supported.
*/
public static final int RESET_USB_PORT_ERROR_NOT_SUPPORTED = 2;
/**
* The {@link #resetUsbPort} request failed as port id mismatched.
*/
public static final int RESET_USB_PORT_ERROR_PORT_MISMATCH = 3;
/**
* The {@link #resetUsbPort} request failed due to other reasons.
*/
public static final int RESET_USB_PORT_ERROR_OTHER = 4;
/** @hide */
@IntDef(prefix = { "RESET_USB_PORT_" }, value = {
RESET_USB_PORT_SUCCESS,
RESET_USB_PORT_ERROR_INTERNAL,
RESET_USB_PORT_ERROR_NOT_SUPPORTED,
RESET_USB_PORT_ERROR_PORT_MISMATCH,
RESET_USB_PORT_ERROR_OTHER
})
@Retention(RetentionPolicy.SOURCE)
@interface ResetUsbPortStatus{}
/** @hide */ /** @hide */
@IntDef(prefix = { "ENABLE_USB_DATA_WHILE_DOCKED_" }, value = { @IntDef(prefix = { "ENABLE_USB_DATA_WHILE_DOCKED_" }, value = {
ENABLE_USB_DATA_WHILE_DOCKED_SUCCESS, ENABLE_USB_DATA_WHILE_DOCKED_SUCCESS,
@ -324,38 +360,29 @@ public final class UsbPort {
/** /**
* Reset Usb data on the port. * Reset Usb data on the port.
* *
* @return {@link #ENABLE_USB_DATA_SUCCESS} when request completes successfully or * @param executor Executor for the callback.
* {@link #ENABLE_USB_DATA_ERROR_INTERNAL} when request fails due to internal * @param consumer A consumer that consumes the reset result.
* error or * {@link #RESET_USB_PORT_SUCCESS} when request completes
* {@link ENABLE_USB_DATA_ERROR_NOT_SUPPORTED} when not supported or * successfully or
* {@link ENABLE_USB_DATA_ERROR_PORT_MISMATCH} when request fails due to port id * {@link #RESET_USB_PORT_ERROR_INTERNAL} when request
* mismatch or * fails due to internal error or
* {@link ENABLE_USB_DATA_ERROR_OTHER} when fails due to other reasons. * {@link RESET_USB_PORT_ERROR_NOT_SUPPORTED} when not
* supported or
* {@link RESET_USB_PORT_ERROR_PORT_MISMATCH} when request
* fails due to port id mismatch or
* {@link RESET_USB_PORT_ERROR_OTHER} when fails due to
* other reasons.
*/ */
@CheckResult @CheckResult
@RequiresPermission(Manifest.permission.MANAGE_USB) @RequiresPermission(Manifest.permission.MANAGE_USB)
public @ResetUsbPortStatus int resetUsbPort() { public void resetUsbPort(@NonNull @CallbackExecutor Executor executor,
@NonNull @ResetUsbPortStatus Consumer<Integer> consumer) {
// UID is added To minimize operationID overlap between two different packages. // UID is added To minimize operationID overlap between two different packages.
int operationId = sUsbOperationCount.incrementAndGet() + Binder.getCallingUid(); int operationId = sUsbOperationCount.incrementAndGet() + Binder.getCallingUid();
Log.i(TAG, "resetUsbData opId:" + operationId); Log.i(TAG, "resetUsbPort opId:" + operationId);
UsbOperationInternal opCallback = UsbOperationInternal opCallback =
new UsbOperationInternal(operationId, mId); new UsbOperationInternal(operationId, mId, executor, consumer);
if (mUsbManager.resetUsbPort(this, operationId, opCallback) == true) { mUsbManager.resetUsbPort(this, operationId, opCallback);
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;
}
} }
/** /**

View File

@ -508,7 +508,7 @@ public class UsbPortManager {
* *
* @param portId port identifier. * @param portId port identifier.
*/ */
public boolean resetUsbPort(@NonNull String portId, int transactionId, public void resetUsbPort(@NonNull String portId, int transactionId,
@NonNull IUsbOperationInternal callback, IndentingPrintWriter pw) { @NonNull IUsbOperationInternal callback, IndentingPrintWriter pw) {
synchronized (mLock) { synchronized (mLock) {
Objects.requireNonNull(callback); Objects.requireNonNull(callback);
@ -525,12 +525,11 @@ public class UsbPortManager {
"resetUsbPort: Failed to call OperationComplete. opId:" "resetUsbPort: Failed to call OperationComplete. opId:"
+ transactionId, e); + transactionId, e);
} }
return false;
} }
try { try {
try { try {
return mUsbPortHal.resetUsbPort(portId, transactionId, callback); mUsbPortHal.resetUsbPort(portId, transactionId, callback);
} catch (Exception e) { } catch (Exception e) {
logAndPrintException(pw, logAndPrintException(pw,
"reseetUsbPort: Failed to resetUsbPort. opId:" "reseetUsbPort: Failed to resetUsbPort. opId:"
@ -542,7 +541,6 @@ public class UsbPortManager {
"resetUsbPort: Failed to call onOperationComplete. opId:" "resetUsbPort: Failed to call onOperationComplete. opId:"
+ transactionId, e); + transactionId, e);
} }
return false;
} }
} }

View File

@ -685,7 +685,7 @@ public class UsbService extends IUsbManager.Stub {
} }
@Override @Override
public boolean resetUsbPort(String portId, int operationId, public void resetUsbPort(String portId, int operationId,
IUsbOperationInternal callback) { IUsbOperationInternal callback) {
Objects.requireNonNull(portId, "resetUsbPort: portId must not be null. opId:" Objects.requireNonNull(portId, "resetUsbPort: portId must not be null. opId:"
+ operationId); + operationId);
@ -694,13 +694,11 @@ public class UsbService extends IUsbManager.Stub {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
final long ident = Binder.clearCallingIdentity(); final long ident = Binder.clearCallingIdentity();
boolean wait;
try { try {
if (mPortManager != null) { if (mPortManager != null) {
wait = mPortManager.resetUsbPort(portId, operationId, callback, null); mPortManager.resetUsbPort(portId, operationId, callback, null);
} else { } else {
wait = false;
try { try {
callback.onOperationComplete(USB_OPERATION_ERROR_INTERNAL); callback.onOperationComplete(USB_OPERATION_ERROR_INTERNAL);
} catch (RemoteException e) { } catch (RemoteException e) {
@ -710,7 +708,6 @@ public class UsbService extends IUsbManager.Stub {
} finally { } finally {
Binder.restoreCallingIdentity(ident); Binder.restoreCallingIdentity(ident);
} }
return wait;
} }
@Override @Override

View File

@ -274,7 +274,7 @@ public final class UsbPortAidl implements UsbPortHal {
} }
@Override @Override
public boolean resetUsbPort(String portName, long operationID, public void resetUsbPort(String portName, long operationID,
IUsbOperationInternal callback) { IUsbOperationInternal callback) {
Objects.requireNonNull(portName); Objects.requireNonNull(portName);
Objects.requireNonNull(callback); Objects.requireNonNull(callback);
@ -286,7 +286,6 @@ public final class UsbPortAidl implements UsbPortHal {
"resetUsbPort: Proxy is null. Retry !opID:" "resetUsbPort: Proxy is null. Retry !opID:"
+ operationID); + operationID);
callback.onOperationComplete(USB_OPERATION_ERROR_INTERNAL); callback.onOperationComplete(USB_OPERATION_ERROR_INTERNAL);
return false;
} }
while (sCallbacks.get(key) != null) { while (sCallbacks.get(key) != null) {
key = ThreadLocalRandom.current().nextInt(); key = ThreadLocalRandom.current().nextInt();
@ -304,16 +303,13 @@ public final class UsbPortAidl implements UsbPortHal {
+ portName + "opId:" + operationID, e); + portName + "opId:" + operationID, e);
callback.onOperationComplete(USB_OPERATION_ERROR_INTERNAL); callback.onOperationComplete(USB_OPERATION_ERROR_INTERNAL);
sCallbacks.remove(key); sCallbacks.remove(key);
return false;
} }
} catch (RemoteException e) { } catch (RemoteException e) {
logAndPrintException(mPw, logAndPrintException(mPw,
"resetUsbPort: Failed to call onOperationComplete portID=" "resetUsbPort: Failed to call onOperationComplete portID="
+ portName + "opID:" + operationID, e); + portName + "opID:" + operationID, e);
sCallbacks.remove(key); sCallbacks.remove(key);
return false;
} }
return true;
} }
} }

View File

@ -202,9 +202,7 @@ public interface UsbPortHal {
* implementation as needed. * implementation as needed.
* @param callback callback object to be invoked to invoke the status of the operation upon * @param callback callback object to be invoked to invoke the status of the operation upon
* completion. * completion.
* @param callback callback object to be invoked to invoke the status of the operation upon
* completion.
*/ */
public boolean resetUsbPort(String portName, long transactionId, public void resetUsbPort(String portName, long transactionId,
IUsbOperationInternal callback); IUsbOperationInternal callback);
} }

View File

@ -318,7 +318,7 @@ public final class UsbPortHidl implements UsbPortHal {
} }
@Override @Override
public boolean resetUsbPort(String portName, long transactionId, public void resetUsbPort(String portName, long transactionId,
IUsbOperationInternal callback) { IUsbOperationInternal callback) {
try { try {
callback.onOperationComplete(USB_OPERATION_ERROR_NOT_SUPPORTED); callback.onOperationComplete(USB_OPERATION_ERROR_NOT_SUPPORTED);
@ -327,7 +327,6 @@ public final class UsbPortHidl implements UsbPortHal {
+ transactionId + transactionId
+ " portId:" + portName, e); + " portId:" + portName, e);
} }
return false;
} }
@Override @Override