Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 476cd2e3 authored by Ricky Niu's avatar Ricky Niu
Browse files

Support USB Port Reset



Verify the USB Gadget HAL already implement.

Bug: 197300598
Test: Verify the API working manually

Signed-off-by: default avatarRicky Niu <rickyniu@google.com>
Change-Id: I8a4a4966237c925c87b32f74a382b7a56f82ab7d
parent 7212c8fd
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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
+3 −0
Original line number Diff line number Diff line
@@ -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);

+37 −0
Original line number Diff line number Diff line
@@ -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>
+40 −0
Original line number Diff line number Diff line
@@ -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.
     *
+43 −0
Original line number Diff line number Diff line
@@ -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) {
Loading