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

Commit bdbb2d15 authored by Badhri Jagan Sridharan's avatar Badhri Jagan Sridharan Committed by Ricky Niu
Browse files

Add limitPowerTransfer SystemAPI to UsbPort



limitPowerTransfer when invoked limits the power transfer
in and out of the USB port. limitPortTransfer is deactivated
either when limitPowerTransfer is deactivated by the caller
or when Usb disconnect event is observed by the Usb service.

limitPowerTransfer API is asynchronous and the caller gets
notified by invoking UsbOperationCallback.onUsbOperationComplete
callback to notify the status of the operation.

USB_PORT_CHANGED event is broadcasted when port's limitPowerTransfer
status changes. UsbPortStatus object is updated to reflect the
current status.

limitPowerTransfer is protected by android.permission.MANAGE_USB.

Bug: 199357330
Bug: 199358576
Test: Tested on Pixel
CTS-Coverage-Bug: 215019881
Signed-off-by: default avatarBadhri Jagan Sridharan <badhri@google.com>
Change-Id: Iabd1187f7527e14ed758abe355ba94a511d8c859
parent bbfa92e6
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -4686,9 +4686,15 @@ package android.hardware.usb {
  }
  public final class UsbPort {
    method @CheckResult @RequiresPermission(android.Manifest.permission.MANAGE_USB) public int enableLimitPowerTransfer(boolean);
    method @CheckResult @RequiresPermission(android.Manifest.permission.MANAGE_USB) public int enableUsbData(boolean);
    method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_USB) public android.hardware.usb.UsbPortStatus getStatus();
    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
    field public static final int ENABLE_LIMIT_POWER_TRANSFER_ERROR_OTHER = 4; // 0x4
    field public static final int ENABLE_LIMIT_POWER_TRANSFER_ERROR_PORT_MISMATCH = 3; // 0x3
    field public static final int ENABLE_LIMIT_POWER_TRANSFER_SUCCESS = 0; // 0x0
    field public static final int ENABLE_USB_DATA_ERROR_INTERNAL = 1; // 0x1
    field public static final int ENABLE_USB_DATA_ERROR_NOT_SUPPORTED = 2; // 0x2
    field public static final int ENABLE_USB_DATA_ERROR_OTHER = 4; // 0x4
@@ -4703,6 +4709,7 @@ package android.hardware.usb {
    method public int getCurrentPowerRole();
    method public int getSupportedRoleCombinations();
    method public boolean isConnected();
    method public boolean isPowerTransferLimited();
    method public boolean isRoleCombinationSupported(int, int);
    method public void writeToParcel(android.os.Parcel, int);
    field @NonNull public static final android.os.Parcelable.Creator<android.hardware.usb.UsbPortStatus> CREATOR;
+5 −0
Original line number Diff line number Diff line
@@ -157,6 +157,11 @@ interface IUsbManager
    /* Sets the port's current role. */
    void setPortRoles(in String portId, int powerRole, int dataRole);

    /* Limit power transfer in & out of the port within the allowed limit by the USB
     * specification.
     */
    void enableLimitPowerTransfer(in String portId, boolean limit, int operationId, in IUsbOperationInternal callback);

    /* Enable/disable contaminant detection */
    void enableContaminantDetection(in String portId, boolean enable);

+32 −0
Original line number Diff line number Diff line
@@ -1291,6 +1291,38 @@ public class UsbManager {
        }
    }

    /**
     * Should only be called by {@link UsbPort#enableLimitPowerTransfer}.
     * <p>
     * limits or restores power transfer in and out of USB port.
     *
     * @param port USB port for which power transfer has to be limited or restored.
     * @param limit limit power transfer when true.
     *              relax power transfer restrictions when false.
     * @param operationId operationId for the request.
     * @param callback callback object to be invoked when the operation is complete.
     *
     * @hide
     */
    @RequiresPermission(Manifest.permission.MANAGE_USB)
    void enableLimitPowerTransfer(@NonNull UsbPort port, boolean limit, int operationId,
            IUsbOperationInternal callback) {
        Objects.requireNonNull(port, "enableLimitPowerTransfer:port must not be null. opId:"
                + operationId);
        try {
            mService.enableLimitPowerTransfer(port.getId(), limit, operationId, callback);
        } catch (RemoteException e) {
            Log.e(TAG, "enableLimitPowerTransfer failed. opId:" + operationId, e);
            try {
                callback.onOperationComplete(UsbOperationInternal.USB_OPERATION_ERROR_INTERNAL);
            } catch (RemoteException r) {
                Log.e(TAG, "enableLimitPowerTransfer failed to call onOperationComplete. opId:"
                        + operationId, r);
            }
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Should only be called by {@link UsbPort#enableUsbData}.
     * <p>
+77 −0
Original line number Diff line number Diff line
@@ -118,6 +118,42 @@ public final class UsbPort {
    @Retention(RetentionPolicy.SOURCE)
    @interface EnableUsbDataStatus{}

    /**
     * The {@link #enableLimitPowerTransfer} request was successfully completed.
     */
    public static final int ENABLE_LIMIT_POWER_TRANSFER_SUCCESS = 0;

    /**
     * The {@link #enableLimitPowerTransfer} request failed due to internal error.
     */
    public static final int ENABLE_LIMIT_POWER_TRANSFER_ERROR_INTERNAL = 1;

    /**
     * The {@link #enableLimitPowerTransfer} request failed as it's not supported.
     */
    public static final int ENABLE_LIMIT_POWER_TRANSFER_ERROR_NOT_SUPPORTED = 2;

    /**
     * The {@link #enableLimitPowerTransfer} request failed as port id mismatched.
     */
    public static final int ENABLE_LIMIT_POWER_TRANSFER_ERROR_PORT_MISMATCH = 3;

    /**
     * The {@link #enableLimitPowerTransfer} request failed due to other reasons.
     */
    public static final int ENABLE_LIMIT_POWER_TRANSFER_ERROR_OTHER = 4;

    /** @hide */
    @IntDef(prefix = { "ENABLE_LIMIT_POWER_TRANSFER_" }, value = {
            ENABLE_LIMIT_POWER_TRANSFER_SUCCESS,
            ENABLE_LIMIT_POWER_TRANSFER_ERROR_INTERNAL,
            ENABLE_LIMIT_POWER_TRANSFER_ERROR_NOT_SUPPORTED,
            ENABLE_LIMIT_POWER_TRANSFER_ERROR_PORT_MISMATCH,
            ENABLE_LIMIT_POWER_TRANSFER_ERROR_OTHER
    })
    @Retention(RetentionPolicy.SOURCE)
    @interface EnableLimitPowerTransferStatus{}

    /** @hide */
    public UsbPort(@NonNull UsbManager usbManager, @NonNull String id, int supportedModes,
            int supportedContaminantProtectionModes,
@@ -271,6 +307,47 @@ public final class UsbPort {
        }
    }

    /**
     * Limits power transfer In and out of the port.
     * <p>
     * Disables charging and limits sourcing power(when permitted by the USB spec) until
     * port disconnect event.
     * </p>
     * @param enable limits power transfer when true.
     * @return {@link #ENABLE_LIMIT_POWER_TRANSFER_SUCCESS} when request completes successfully or
     *         {@link #ENABLE_LIMIT_POWER_TRANSFER_ERROR_INTERNAL} when request fails due to
     *         internal error or
     *         {@link ENABLE_LIMIT_POWER_TRANSFER_ERROR_NOT_SUPPORTED} when not supported or
     *         {@link ENABLE_LIMIT_POWER_TRANSFER_ERROR_PORT_MISMATCH} when request fails due to
     *         port id mismatch or
     *         {@link ENABLE_LIMIT_POWER_TRANSFER_ERROR_OTHER} when fails due to other reasons.
     */
    @CheckResult
    @RequiresPermission(Manifest.permission.MANAGE_USB)
    public @EnableLimitPowerTransferStatus int enableLimitPowerTransfer(boolean enable) {
        // UID is added To minimize operationID overlap between two different packages.
        int operationId = sUsbOperationCount.incrementAndGet() + Binder.getCallingUid();
        Log.i(TAG, "enableLimitPowerTransfer opId:" + operationId
                + " callingUid:" + Binder.getCallingUid());
        UsbOperationInternal opCallback =
                new UsbOperationInternal(operationId, mId);
        mUsbManager.enableLimitPowerTransfer(this, enable, operationId, opCallback);
        opCallback.waitForOperationComplete();
        int result = opCallback.getStatus();
        switch (result) {
            case USB_OPERATION_SUCCESS:
                return ENABLE_LIMIT_POWER_TRANSFER_SUCCESS;
            case USB_OPERATION_ERROR_INTERNAL:
                return ENABLE_LIMIT_POWER_TRANSFER_ERROR_INTERNAL;
            case USB_OPERATION_ERROR_NOT_SUPPORTED:
                return ENABLE_LIMIT_POWER_TRANSFER_ERROR_NOT_SUPPORTED;
            case USB_OPERATION_ERROR_PORT_MISMATCH:
                return ENABLE_LIMIT_POWER_TRANSFER_ERROR_PORT_MISMATCH;
            default:
                return ENABLE_LIMIT_POWER_TRANSFER_ERROR_OTHER;
        }
    }

    /**
     * @hide
     **/
+20 −2
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@ public final class UsbPortStatus implements Parcelable {
    private final @ContaminantProtectionStatus int mContaminantProtectionStatus;
    private final @ContaminantDetectionStatus int mContaminantDetectionStatus;
    private final boolean mUsbDataEnabled;
    private final boolean mPowerTransferLimited;

    /**
     * Power role: This USB port does not have a power role.
@@ -224,7 +225,8 @@ public final class UsbPortStatus implements Parcelable {
    /** @hide */
    public UsbPortStatus(int currentMode, int currentPowerRole, int currentDataRole,
            int supportedRoleCombinations, int contaminantProtectionStatus,
            int contaminantDetectionStatus, boolean usbDataEnabled) {
            int contaminantDetectionStatus, boolean usbDataEnabled,
            boolean powerTransferLimited) {
        mCurrentMode = currentMode;
        mCurrentPowerRole = currentPowerRole;
        mCurrentDataRole = currentDataRole;
@@ -232,6 +234,7 @@ public final class UsbPortStatus implements Parcelable {
        mContaminantProtectionStatus = contaminantProtectionStatus;
        mContaminantDetectionStatus = contaminantDetectionStatus;
        mUsbDataEnabled = usbDataEnabled;
        mPowerTransferLimited = powerTransferLimited;
    }

    /** @hide */
@@ -245,6 +248,7 @@ public final class UsbPortStatus implements Parcelable {
        mContaminantProtectionStatus = contaminantProtectionStatus;
        mContaminantDetectionStatus = contaminantDetectionStatus;
        mUsbDataEnabled = true;
        mPowerTransferLimited = false;
    }

    /**
@@ -336,6 +340,16 @@ public final class UsbPortStatus implements Parcelable {
        return mUsbDataEnabled;
    }

    /**
     * Returns whether power transfer is limited.
     *
     * @return true when power transfer is limited.
     *         false otherwise.
     */
    public boolean isPowerTransferLimited() {
        return mPowerTransferLimited;
    }

    @NonNull
    @Override
    public String toString() {
@@ -351,6 +365,8 @@ public final class UsbPortStatus implements Parcelable {
                        + getContaminantProtectionStatus()
                + ", usbDataEnabled="
                        + getUsbDataStatus()
                + ", isPowerTransferLimited="
                        + isPowerTransferLimited()
                + "}";
    }

@@ -368,6 +384,7 @@ public final class UsbPortStatus implements Parcelable {
        dest.writeInt(mContaminantProtectionStatus);
        dest.writeInt(mContaminantDetectionStatus);
        dest.writeBoolean(mUsbDataEnabled);
        dest.writeBoolean(mPowerTransferLimited);
    }

    public static final @NonNull Parcelable.Creator<UsbPortStatus> CREATOR =
@@ -381,9 +398,10 @@ public final class UsbPortStatus implements Parcelable {
            int contaminantProtectionStatus = in.readInt();
            int contaminantDetectionStatus = in.readInt();
            boolean usbDataEnabled = in.readBoolean();
            boolean powerTransferLimited = in.readBoolean();
            return new UsbPortStatus(currentMode, currentPowerRole, currentDataRole,
                    supportedRoleCombinations, contaminantProtectionStatus,
                    contaminantDetectionStatus, usbDataEnabled);
                    contaminantDetectionStatus, usbDataEnabled, powerTransferLimited);
        }

        @Override
Loading