Asynchronous the resetUsbPort

Modify the resetUsbPort be asynchronous

Bug: 217369748
Signed-off-by: Ricky Niu <rickyniu@google.com>
Change-Id: I5d799691f2f3fce4df97a960c8628194236d9f81
This commit is contained in:
Ricky Niu 2022-03-25 04:17:50 +08:00 committed by Chien Kun Niu
parent 4ca3b32345
commit dc74aff111
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 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<java.lang.Integer>);
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 {

View File

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

View File

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

View File

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

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 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<Integer> 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);
}
/**

View File

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

View File

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

View File

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

View File

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

View File

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