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

Commit d3335bd5 authored by George Chan's avatar George Chan Committed by Android (Google) Code Review
Browse files

Merge "Updated enableUsbDataSignal for UsbManagerInternal to factor in HAL...

Merge "Updated enableUsbDataSignal for UsbManagerInternal to factor in HAL response code when returning data signal change success response." into main
parents 8eb3a662 1c4b4d4c
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -94,7 +94,7 @@ public final class UsbOperationInternal extends IUsbOperationInternal.Stub {
        this.mAsynchronous = true;
    }

    UsbOperationInternal(int operationID, String id) {
    public UsbOperationInternal(int operationID, String id) {
        this.mOperationID = operationID;
        this.mId = id;
    }
+67 −19
Original line number Diff line number Diff line
@@ -46,6 +46,7 @@ import android.content.pm.PackageManager;
import android.hardware.usb.IDisplayPortAltModeInfoListener;
import android.hardware.usb.IUsbManager;
import android.hardware.usb.IUsbOperationInternal;
import android.hardware.usb.UsbOperationInternal;
import android.hardware.usb.ParcelableUsbPort;
import android.hardware.usb.UsbAccessory;
import android.hardware.usb.UsbDevice;
@@ -248,7 +249,8 @@ public class UsbService extends IUsbManager.Stub {
                      UsbPortManager usbPortManager,
                      UsbAlsaManager usbAlsaManager,
                      UserManager userManager,
                      UsbSettingsManager usbSettingsManager) {
                      UsbSettingsManager usbSettingsManager,
                      IUsbOperationInternalProvider usbOperationInternalProvider) {
        mContext = context;
        mPortManager = usbPortManager;
        mAlsaManager = usbAlsaManager;
@@ -257,7 +259,9 @@ public class UsbService extends IUsbManager.Stub {
        mPermissionManager = new UsbPermissionManager(context, this);

        if(android.hardware.usb.flags.Flags.enableUsbDataSignalStakingInternal()) {
            LocalServices.addService(IUsbManagerInternal.class, new UsbManagerInternalImpl());
            LocalServices.addService(
                    IUsbManagerInternal.class,
                    new UsbManagerInternalImpl(usbOperationInternalProvider));
        }
    }

@@ -1637,10 +1641,30 @@ public class UsbService extends IUsbManager.Stub {
        }
    }

    private class UsbManagerInternalImpl extends IUsbManagerInternal.Stub {
    class UsbManagerInternalImpl extends IUsbManagerInternal.Stub {
        private static final AtomicInteger sUsbOperationCount = new AtomicInteger();
        private static final Set<Integer> sValidDisableReasons = Set.of(USB_DISABLE_REASON_APM,
            USB_DISABLE_REASON_LOCKDOWN_MODE, USB_DISABLE_REASON_ENTERPRISE);
        private static final Set<Integer> sValidDisableReasons =
                Set.of(
                        USB_DISABLE_REASON_APM,
                        USB_DISABLE_REASON_LOCKDOWN_MODE,
                        USB_DISABLE_REASON_ENTERPRISE);

        private IUsbOperationInternalProvider mUsbOperationInternalProvider =
                new IUsbOperationInternalProvider() {
                    @Override
                    public UsbOperationInternal getUsbOperationInternal(
                            int operationId, String portId) {
                        return new UsbOperationInternal(operationId, portId);
                    }
                };

        UsbManagerInternalImpl() {}

        @VisibleForTesting
        UsbManagerInternalImpl(IUsbOperationInternalProvider usbOperationInternalProvider) {
            mUsbOperationInternalProvider = usbOperationInternalProvider;
        }

        @Override
        public boolean enableUsbDataSignal(boolean enable, int disableReason) {
            if (!sValidDisableReasons.contains(disableReason)) {
@@ -1649,15 +1673,39 @@ public class UsbService extends IUsbManager.Stub {
            boolean result = true;
            int operationId = sUsbOperationCount.incrementAndGet() + disableReason;
            for (UsbPort port : mPortManager.getPorts()) {
                    boolean success = enableUsbDataInternal(port.getId(), enable, operationId,
                        new IUsbOperationInternal.Default(), disableReason, true);
                UsbOperationInternal opCallback =
                        mUsbOperationInternalProvider.getUsbOperationInternal(
                                operationId, port.getId());
                boolean success =
                        enableUsbDataInternal(
                                port.getId(), enable, operationId, opCallback, disableReason, true);
                if (!success) {
                        Slog.e(TAG, "enableUsbDataInternal failed to change USB port "
                            + port.getId() + "state to " + enable);
                    Slog.e(
                            TAG,
                            "enableUsbDataInternal failed to change USB port "
                                    + port.getId()
                                    + "state to "
                                    + enable);
                    // We continue to the next port even if the current port fails to change.
                    result = false;
                } else {
                    opCallback.waitForOperationComplete();
                    int callbackStatus = opCallback.getStatus();
                    Slog.i(
                            TAG,
                            "enableUsbDataInternal change for portId: "
                                    + port.getId()
                                    + " result: "
                                    + Integer.toString(callbackStatus));
                    result &= callbackStatus == UsbOperationInternal.USB_OPERATION_SUCCESS;
                }
                    result &= success;
            }
            return result;
        }
    }

    @VisibleForTesting
    public interface IUsbOperationInternalProvider {
        UsbOperationInternal getUsbOperationInternal(int operationId, String portId);
    }
}
+154 −84
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@ import static org.mockito.Mockito.when;
import android.content.Context;
import android.hardware.usb.IUsbManagerInternal;
import android.hardware.usb.IUsbOperationInternal;
import android.hardware.usb.UsbOperationInternal;
import android.hardware.usb.flags.Flags;
import android.hardware.usb.UsbPort;
import android.os.RemoteException;
@@ -56,24 +57,20 @@ import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

/**
 * Tests for {@link com.android.server.usb.UsbService}
 */
import com.android.server.usb.UsbService.IUsbOperationInternalProvider;
import com.android.server.usb.UsbService.UsbManagerInternalImpl;

/** Tests for {@link com.android.server.usb.UsbService} atest UsbTests:UsbServiceTest */
@RunWith(AndroidJUnit4.class)
public class UsbServiceTest {

    @Mock
    private Context mContext;
    @Mock
    private UsbPortManager mUsbPortManager;
    @Mock
    private UsbAlsaManager mUsbAlsaManager;
    @Mock
    private UserManager mUserManager;
    @Mock
    private UsbSettingsManager mUsbSettingsManager;
    @Mock
    private IUsbOperationInternal mCallback;
    @Mock private Context mContext;
    @Mock private UsbPortManager mUsbPortManager;
    @Mock private UsbAlsaManager mUsbAlsaManager;
    @Mock private UserManager mUserManager;
    @Mock private UsbSettingsManager mUsbSettingsManager;
    @Mock private IUsbOperationInternal mCallback;
    @Mock private IUsbOperationInternalProvider mUsbOperationInternalProvider;

    private static final String TEST_PORT_ID = "1";

@@ -95,8 +92,7 @@ public class UsbServiceTest {

    private IUsbManagerInternal mIUsbManagerInternal;

    @Rule
    public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
    @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();

    @Before
    public void setUp() {
@@ -105,33 +101,57 @@ public class UsbServiceTest {
        LocalServices.removeAllServicesForTest();
        MockitoAnnotations.initMocks(this);

        when(mUsbPortManager.enableUsbData(eq(TEST_PORT_ID), anyBoolean(),
                 eq(TEST_TRANSACTION_ID), eq(mCallback), any())).thenReturn(true);

        mUsbService = new UsbService(mContext, mUsbPortManager, mUsbAlsaManager,
                mUserManager, mUsbSettingsManager);
        when(mUsbPortManager.enableUsbData(
                        eq(TEST_PORT_ID),
                        anyBoolean(),
                        eq(TEST_TRANSACTION_ID),
                        eq(mCallback),
                        any()))
                .thenReturn(true);

        mUsbService =
                new UsbService(
                        mContext,
                        mUsbPortManager,
                        mUsbAlsaManager,
                        mUserManager,
                        mUsbSettingsManager,
                        mUsbOperationInternalProvider);
        mIUsbManagerInternal = LocalServices.getService(IUsbManagerInternal.class);
        assertWithMessage("LocalServices.getService(IUsbManagerInternal.class)")
            .that(mIUsbManagerInternal).isNotNull();
                .that(mIUsbManagerInternal)
                .isNotNull();
    }

    private void assertToggleUsbSuccessfully(int requester, boolean enable,
        boolean isInternalRequest) {
        assertTrue(mUsbService.enableUsbDataInternal(TEST_PORT_ID, enable,
                TEST_TRANSACTION_ID, mCallback, requester, isInternalRequest));

        verify(mUsbPortManager).enableUsbData(TEST_PORT_ID,
                enable, TEST_TRANSACTION_ID, mCallback, null);
    private void assertToggleUsbSuccessfully(
            int requester, boolean enable, boolean isInternalRequest) {
        assertTrue(
                mUsbService.enableUsbDataInternal(
                        TEST_PORT_ID,
                        enable,
                        TEST_TRANSACTION_ID,
                        mCallback,
                        requester,
                        isInternalRequest));

        verify(mUsbPortManager)
                .enableUsbData(TEST_PORT_ID, enable, TEST_TRANSACTION_ID, mCallback, null);
        verifyNoMoreInteractions(mCallback);

        clearInvocations(mUsbPortManager);
        clearInvocations(mCallback);
    }

    private void assertToggleUsbFailed(int requester, boolean enable,
        boolean isInternalRequest) throws Exception {
        assertFalse(mUsbService.enableUsbDataInternal(TEST_PORT_ID, enable,
                TEST_TRANSACTION_ID, mCallback, requester, isInternalRequest));
    private void assertToggleUsbFailed(int requester, boolean enable, boolean isInternalRequest)
            throws Exception {
        assertFalse(
                mUsbService.enableUsbDataInternal(
                        TEST_PORT_ID,
                        enable,
                        TEST_TRANSACTION_ID,
                        mCallback,
                        requester,
                        isInternalRequest));

        verifyNoMoreInteractions(mUsbPortManager);
        verify(mCallback).onOperationComplete(USB_OPERATION_ERROR_INTERNAL);
@@ -140,26 +160,19 @@ public class UsbServiceTest {
        clearInvocations(mCallback);
    }

    /**
     * Verify enableUsbData successfully disables USB port without error
     */
    /** Verify enableUsbData successfully disables USB port without error */
    @Test
    public void disableUsb_successfullyDisable() {
        assertToggleUsbSuccessfully(TEST_FIRST_CALLER_ID, false, false);
    }

    /**
     * Verify enableUsbData successfully enables USB port without error given
     * no other stakers
     */
    /** Verify enableUsbData successfully enables USB port without error given no other stakers */
    @Test
    public void enableUsbWhenNoOtherStakers_successfullyEnable() {
        assertToggleUsbSuccessfully(TEST_FIRST_CALLER_ID, true, false);
    }

    /**
     * Verify enableUsbData does not enable USB port if other stakers are present
     */
    /** Verify enableUsbData does not enable USB port if other stakers are present */
    @Test
    public void enableUsbPortWithOtherStakers_failsToEnable() throws Exception {
        assertToggleUsbSuccessfully(TEST_FIRST_CALLER_ID, false, false);
@@ -167,10 +180,7 @@ public class UsbServiceTest {
        assertToggleUsbFailed(TEST_SECOND_CALLER_ID, true, false);
    }

    /**
     * Verify enableUsbData successfully enables USB port when the last staker
     * is removed
     */
    /** Verify enableUsbData successfully enables USB port when the last staker is removed */
    @Test
    public void enableUsbByTheOnlyStaker_successfullyEnable() {
        assertToggleUsbSuccessfully(TEST_FIRST_CALLER_ID, false, false);
@@ -179,38 +189,36 @@ public class UsbServiceTest {
    }

    /**
     * Verify enableUsbDataWhileDockedInternal does not enable USB port if other
     * stakers are present
     * Verify enableUsbDataWhileDockedInternal does not enable USB port if other stakers are present
     */
    @Test
    public void enableUsbWhileDockedWhenThereAreOtherStakers_failsToEnable()
            throws RemoteException {
        assertToggleUsbSuccessfully(TEST_FIRST_CALLER_ID, false, false);

        mUsbService.enableUsbDataWhileDockedInternal(TEST_PORT_ID, TEST_TRANSACTION_ID,
                mCallback, TEST_SECOND_CALLER_ID, false);
        mUsbService.enableUsbDataWhileDockedInternal(
                TEST_PORT_ID, TEST_TRANSACTION_ID, mCallback, TEST_SECOND_CALLER_ID, false);

        verifyNoMoreInteractions(mUsbPortManager);
        verify(mCallback).onOperationComplete(USB_OPERATION_ERROR_INTERNAL);
    }

    /**
     * Verify enableUsbDataWhileDockedInternal does enable USB port if other
     * stakers are not present
     * Verify enableUsbDataWhileDockedInternal does enable USB port if other stakers are not present
     */
    @Test
    public void enableUsbWhileDockedWhenThereAreNoStakers_SuccessfullyEnable() {
        mUsbService.enableUsbDataWhileDockedInternal(TEST_PORT_ID, TEST_TRANSACTION_ID,
                mCallback, TEST_SECOND_CALLER_ID, false);
        mUsbService.enableUsbDataWhileDockedInternal(
                TEST_PORT_ID, TEST_TRANSACTION_ID, mCallback, TEST_SECOND_CALLER_ID, false);

        verify(mUsbPortManager).enableUsbDataWhileDocked(TEST_PORT_ID, TEST_TRANSACTION_ID,
                        mCallback, null);
        verify(mUsbPortManager)
                .enableUsbDataWhileDocked(TEST_PORT_ID, TEST_TRANSACTION_ID, mCallback, null);
        verifyNoMoreInteractions(mCallback);
    }

    /**
     * Verify enableUsbData successfully enables USB port without error given no
     * other stakers for internal requests
     * Verify enableUsbData successfully enables USB port without error given no other stakers for
     * internal requests
     */
    @Test
    public void enableUsbWhenNoOtherStakers_forInternalRequest_successfullyEnable() {
@@ -218,8 +226,8 @@ public class UsbServiceTest {
    }

    /**
     * Verify enableUsbData does not enable USB port if other internal stakers
     * are present for internal requests
     * Verify enableUsbData does not enable USB port if other internal stakers are present for
     * internal requests
     */
    @Test
    public void enableUsbPortWithOtherInternalStakers_forInternalRequest_failsToEnable()
@@ -230,8 +238,8 @@ public class UsbServiceTest {
    }

    /**
     * Verify enableUsbData does not enable USB port if other external stakers
     * are present for internal requests
     * Verify enableUsbData does not enable USB port if other external stakers are present for
     * internal requests
     */
    @Test
    public void enableUsbPortWithOtherExternalStakers_forInternalRequest_failsToEnable()
@@ -242,8 +250,8 @@ public class UsbServiceTest {
    }

    /**
     * Verify enableUsbData does not enable USB port if other internal stakers
     * are present for external requests
     * Verify enableUsbData does not enable USB port if other internal stakers are present for
     * external requests
     */
    @Test
    public void enableUsbPortWithOtherInternalStakers_forExternalRequest_failsToEnable()
@@ -254,8 +262,8 @@ public class UsbServiceTest {
    }

    /**
     * Verify enableUsbData successfully enables USB port when the last staker
     * is removed for internal requests
     * Verify enableUsbData successfully enables USB port when the last staker is removed for
     * internal requests
     */
    @Test
    public void enableUsbByTheOnlyStaker_forInternalRequest_successfullyEnable() {
@@ -279,22 +287,32 @@ public class UsbServiceTest {
        assertFalse(runInternalUsbDataSignalTest(true, true, false));
    }

    private boolean runInternalUsbDataSignalTest(boolean desiredEnableState, boolean portOneSuccess,
        boolean portTwoSuccess) {
    private boolean runInternalUsbDataSignalTest(
            boolean desiredEnableState, boolean portOneSuccess, boolean portTwoSuccess) {
        UsbPort port = mock(UsbPort.class);
        UsbPort port2 = mock(UsbPort.class);
        setupUsbOperationInternalProvider(true, true);
        when(port.getId()).thenReturn(TEST_PORT_ID);
        when(port2.getId()).thenReturn(TEST_PORT_ID_2);
        when(mUsbPortManager.getPorts()).thenReturn(new UsbPort[] {port, port2});
        when(mUsbPortManager.enableUsbData(eq(TEST_PORT_ID),
                eq(desiredEnableState), anyInt(), any(IUsbOperationInternal.class), isNull()))
        when(mUsbPortManager.enableUsbData(
                        eq(TEST_PORT_ID),
                        eq(desiredEnableState),
                        anyInt(),
                        any(IUsbOperationInternal.class),
                        isNull()))
                .thenReturn(portOneSuccess);
        when(mUsbPortManager.enableUsbData(eq(TEST_PORT_ID_2),
                eq(desiredEnableState), anyInt(), any(IUsbOperationInternal.class), isNull()))
        when(mUsbPortManager.enableUsbData(
                        eq(TEST_PORT_ID_2),
                        eq(desiredEnableState),
                        anyInt(),
                        any(IUsbOperationInternal.class),
                        isNull()))
                .thenReturn(portTwoSuccess);
        try {
            boolean result = mIUsbManagerInternal.enableUsbDataSignal(desiredEnableState,
                        TEST_INTERNAL_REQUESTER_REASON_1);
            boolean result =
                    mIUsbManagerInternal.enableUsbDataSignal(
                            desiredEnableState, TEST_INTERNAL_REQUESTER_REASON_1);
            clearInvocations(mUsbPortManager);
            return result;
        } catch (RemoteException e) {
@@ -303,6 +321,58 @@ public class UsbServiceTest {
        }
    }

    private void setupUsbOperationInternalProvider(boolean portOneSuccess, boolean portTwoSuccess) {
        UsbOperationInternal usbOperationInternalPortOne = mock(UsbOperationInternal.class);
        UsbOperationInternal usbOperationInternalPortTwo = mock(UsbOperationInternal.class);
        when(usbOperationInternalPortOne.getStatus())
                .thenReturn(
                        portOneSuccess
                                ? UsbOperationInternal.USB_OPERATION_SUCCESS
                                : UsbOperationInternal.USB_OPERATION_ERROR_INTERNAL);
        when(usbOperationInternalPortTwo.getStatus())
                .thenReturn(
                        portTwoSuccess
                                ? UsbOperationInternal.USB_OPERATION_SUCCESS
                                : UsbOperationInternal.USB_OPERATION_ERROR_INTERNAL);
        when(mUsbOperationInternalProvider.getUsbOperationInternal(anyInt(), eq(TEST_PORT_ID)))
                .thenReturn(usbOperationInternalPortOne);
        when(mUsbOperationInternalProvider.getUsbOperationInternal(anyInt(), eq(TEST_PORT_ID_2)))
                .thenReturn(usbOperationInternalPortTwo);
    }

    @Test
    public void usbManagerInternal_enableUsbDataSignal_returnsFalseIfOnePortCallbackFails()
            throws RemoteException {
        boolean desiredEnableState = true;
        UsbPort port = mock(UsbPort.class);
        UsbPort port2 = mock(UsbPort.class);
        setupUsbOperationInternalProvider(true, false);
        when(port.getId()).thenReturn(TEST_PORT_ID);
        when(port2.getId()).thenReturn(TEST_PORT_ID_2);
        when(mUsbPortManager.getPorts()).thenReturn(new UsbPort[] {port, port2});
        when(mUsbPortManager.enableUsbData(
                        eq(TEST_PORT_ID),
                        eq(desiredEnableState),
                        anyInt(),
                        any(IUsbOperationInternal.class),
                        isNull()))
                .thenReturn(true);
        when(mUsbPortManager.enableUsbData(
                        eq(TEST_PORT_ID_2),
                        eq(desiredEnableState),
                        anyInt(),
                        any(IUsbOperationInternal.class),
                        isNull()))
                .thenReturn(true);

        boolean result =
                mIUsbManagerInternal.enableUsbDataSignal(
                        desiredEnableState, TEST_INTERNAL_REQUESTER_REASON_1);

        assertFalse(result);
        clearInvocations(mUsbPortManager);
    }

    @Test(expected = IllegalArgumentException.class)
    public void usbManagerInternal_enableUsbDataSignal_throwsExceptionIfInvalidDisableReason()
            throws IllegalArgumentException, RemoteException {