From dc74aff111d49d7cd85f1f45c11a4b7e7c4457c6 Mon Sep 17 00:00:00 2001 From: Ricky Niu Date: Fri, 25 Mar 2022 04:17:50 +0800 Subject: [PATCH] Asynchronous the resetUsbPort Modify the resetUsbPort be asynchronous Bug: 217369748 Signed-off-by: Ricky Niu Change-Id: I5d799691f2f3fce4df97a960c8628194236d9f81 --- core/api/system-current.txt | 7 +- .../android/hardware/usb/IUsbManager.aidl | 2 +- .../java/android/hardware/usb/UsbManager.java | 4 +- .../hardware/usb/UsbOperationInternal.java | 38 ++++++++- core/java/android/hardware/usb/UsbPort.java | 85 ++++++++++++------- .../android/server/usb/UsbPortManager.java | 6 +- .../com/android/server/usb/UsbService.java | 7 +- .../server/usb/hal/port/UsbPortAidl.java | 6 +- .../server/usb/hal/port/UsbPortHal.java | 4 +- .../server/usb/hal/port/UsbPortHidl.java | 3 +- 10 files changed, 109 insertions(+), 53 deletions(-) diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 3f8fc5600eb1..97a0b6dc6009 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -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 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 @CheckResult @RequiresPermission(android.Manifest.permission.MANAGE_USB) public void resetUsbPort(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer); 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 @@ -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_PORT_MISMATCH = 3; // 0x3 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 { diff --git a/core/java/android/hardware/usb/IUsbManager.aidl b/core/java/android/hardware/usb/IUsbManager.aidl index b617e056774b..5a442445d832 100644 --- a/core/java/android/hardware/usb/IUsbManager.aidl +++ b/core/java/android/hardware/usb/IUsbManager.aidl @@ -137,7 +137,7 @@ interface IUsbManager void resetUsbGadget(); /* 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 */ boolean enableUsbData(in String portId, boolean enable, int operationId, in IUsbOperationInternal callback); diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java index 4fb6abdae5ff..2c38f7031eff 100644 --- a/core/java/android/hardware/usb/UsbManager.java +++ b/core/java/android/hardware/usb/UsbManager.java @@ -1360,11 +1360,11 @@ public class UsbManager { * @hide */ @RequiresPermission(Manifest.permission.MANAGE_USB) - boolean resetUsbPort(@NonNull UsbPort port, int operationId, + void 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); + mService.resetUsbPort(port.getId(), operationId, callback); } catch (RemoteException e) { Log.e(TAG, "resetUsbPort: failed. ", e); try { diff --git a/core/java/android/hardware/usb/UsbOperationInternal.java b/core/java/android/hardware/usb/UsbOperationInternal.java index 9bc2b3892a1e..5b6dbbfbe5d7 100644 --- a/core/java/android/hardware/usb/UsbOperationInternal.java +++ b/core/java/android/hardware/usb/UsbOperationInternal.java @@ -15,6 +15,7 @@ */ package android.hardware.usb; +import android.annotation.CallbackExecutor; import android.annotation.IntDef; import android.hardware.usb.IUsbOperationInternal; import android.hardware.usb.UsbPort; @@ -24,7 +25,9 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; +import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; /** * UsbOperationInternal allows UsbPort to support both synchronous and * asynchronous function irrespective of whether the underlying hal @@ -39,6 +42,10 @@ public final class UsbOperationInternal extends IUsbOperationInternal.Stub { private final String mId; // True implies operation did not timeout. private boolean mOperationComplete; + private boolean mAsynchronous = false; + private Executor mExecutor; + private Consumer mConsumer; + private int mResult = 0; private @UsbOperationStatus int mStatus; final ReentrantLock mLock = new ReentrantLock(); final Condition mOperationWait = mLock.newCondition(); @@ -78,6 +85,15 @@ public final class UsbOperationInternal extends IUsbOperationInternal.Stub { @Retention(RetentionPolicy.SOURCE) @interface UsbOperationStatus{} + UsbOperationInternal(int operationID, String id, + Executor executor, Consumer consumer) { + this.mOperationID = operationID; + this.mId = id; + this.mExecutor = executor; + this.mConsumer = consumer; + this.mAsynchronous = true; + } + UsbOperationInternal(int operationID, String id) { this.mOperationID = operationID; this.mId = id; @@ -94,7 +110,27 @@ public final class UsbOperationInternal extends IUsbOperationInternal.Stub { mOperationComplete = true; mStatus = status; 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 { mLock.unlock(); } diff --git a/core/java/android/hardware/usb/UsbPort.java b/core/java/android/hardware/usb/UsbPort.java index 7b695e79018c..7c5a4c6d2b87 100644 --- a/core/java/android/hardware/usb/UsbPort.java +++ b/core/java/android/hardware/usb/UsbPort.java @@ -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 android.Manifest; +import android.annotation.CallbackExecutor; import android.annotation.CheckResult; import android.annotation.IntDef; import android.annotation.NonNull; @@ -65,6 +66,8 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Objects; 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. @@ -128,9 +131,6 @@ public final class UsbPort { @Retention(RetentionPolicy.SOURCE) @interface EnableUsbDataStatus{} - @Retention(RetentionPolicy.SOURCE) - @interface ResetUsbPortStatus{} - /** * 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; + /** + * 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 */ @IntDef(prefix = { "ENABLE_USB_DATA_WHILE_DOCKED_" }, value = { ENABLE_USB_DATA_WHILE_DOCKED_SUCCESS, @@ -324,38 +360,29 @@ public final class UsbPort { /** * 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. + * @param executor Executor for the callback. + * @param consumer A consumer that consumes the reset result. + * {@link #RESET_USB_PORT_SUCCESS} when request completes + * successfully or + * {@link #RESET_USB_PORT_ERROR_INTERNAL} when request + * fails due to internal error or + * {@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 @RequiresPermission(Manifest.permission.MANAGE_USB) - public @ResetUsbPortStatus int resetUsbPort() { + public void resetUsbPort(@NonNull @CallbackExecutor Executor executor, + @NonNull @ResetUsbPortStatus Consumer consumer) { // UID is added To minimize operationID overlap between two different packages. int operationId = sUsbOperationCount.incrementAndGet() + Binder.getCallingUid(); - Log.i(TAG, "resetUsbData opId:" + operationId); + Log.i(TAG, "resetUsbPort 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; - } + new UsbOperationInternal(operationId, mId, executor, consumer); + mUsbManager.resetUsbPort(this, operationId, opCallback); } /** diff --git a/services/usb/java/com/android/server/usb/UsbPortManager.java b/services/usb/java/com/android/server/usb/UsbPortManager.java index f07a4061d717..5e633ab3aef5 100644 --- a/services/usb/java/com/android/server/usb/UsbPortManager.java +++ b/services/usb/java/com/android/server/usb/UsbPortManager.java @@ -508,7 +508,7 @@ public class UsbPortManager { * * @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) { synchronized (mLock) { Objects.requireNonNull(callback); @@ -525,12 +525,11 @@ public class UsbPortManager { "resetUsbPort: Failed to call OperationComplete. opId:" + transactionId, e); } - return false; } try { try { - return mUsbPortHal.resetUsbPort(portId, transactionId, callback); + mUsbPortHal.resetUsbPort(portId, transactionId, callback); } catch (Exception e) { logAndPrintException(pw, "reseetUsbPort: Failed to resetUsbPort. opId:" @@ -542,7 +541,6 @@ public class UsbPortManager { "resetUsbPort: Failed to call onOperationComplete. opId:" + transactionId, e); } - return false; } } diff --git a/services/usb/java/com/android/server/usb/UsbService.java b/services/usb/java/com/android/server/usb/UsbService.java index e06ab022688f..86f877fcd531 100644 --- a/services/usb/java/com/android/server/usb/UsbService.java +++ b/services/usb/java/com/android/server/usb/UsbService.java @@ -685,7 +685,7 @@ public class UsbService extends IUsbManager.Stub { } @Override - public boolean resetUsbPort(String portId, int operationId, + public void resetUsbPort(String portId, int operationId, IUsbOperationInternal callback) { Objects.requireNonNull(portId, "resetUsbPort: portId must not be null. opId:" + operationId); @@ -694,13 +694,11 @@ public class UsbService extends IUsbManager.Stub { 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); + mPortManager.resetUsbPort(portId, operationId, callback, null); } else { - wait = false; try { callback.onOperationComplete(USB_OPERATION_ERROR_INTERNAL); } catch (RemoteException e) { @@ -710,7 +708,6 @@ public class UsbService extends IUsbManager.Stub { } finally { Binder.restoreCallingIdentity(ident); } - return wait; } @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 8c9e80f7e04d..600fc27f5103 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 @@ -274,7 +274,7 @@ public final class UsbPortAidl implements UsbPortHal { } @Override - public boolean resetUsbPort(String portName, long operationID, + public void resetUsbPort(String portName, long operationID, IUsbOperationInternal callback) { Objects.requireNonNull(portName); Objects.requireNonNull(callback); @@ -286,7 +286,6 @@ public final class UsbPortAidl implements UsbPortHal { "resetUsbPort: Proxy is null. Retry !opID:" + operationID); callback.onOperationComplete(USB_OPERATION_ERROR_INTERNAL); - return false; } while (sCallbacks.get(key) != null) { key = ThreadLocalRandom.current().nextInt(); @@ -304,16 +303,13 @@ public final class UsbPortAidl implements UsbPortHal { + 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; } } 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 4fa296da7267..f98c598d4190 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 @@ -202,9 +202,7 @@ public interface UsbPortHal { * 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, + public void resetUsbPort(String portName, 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 c7f077564fd1..23d913cba733 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 @@ -318,7 +318,7 @@ public final class UsbPortHidl implements UsbPortHal { } @Override - public boolean resetUsbPort(String portName, long transactionId, + public void resetUsbPort(String portName, long transactionId, IUsbOperationInternal callback) { try { callback.onOperationComplete(USB_OPERATION_ERROR_NOT_SUPPORTED); @@ -327,7 +327,6 @@ public final class UsbPortHidl implements UsbPortHal { + transactionId + " portId:" + portName, e); } - return false; } @Override