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

Commit 1df27431 authored by Gavin Williams's avatar Gavin Williams Committed by Android (Google) Code Review
Browse files

Merge "Braille: Allow sticky USB permission" into main

parents ea666b27 2bf4e086
Loading
Loading
Loading
Loading
+14 −1
Original line number Diff line number Diff line
@@ -105,6 +105,10 @@ class AccessibilityServiceConnection extends AbstractAccessibilityServiceConnect

    private final Handler mMainHandler;
    private UsbDeviceReceiver mUsbDeviceReceiverReceiver;
    // The serial number of the braille display which USB permission was last granted for. Needed to
    // automatically re-grant USB permission to this same braille display if unplugged and connected
    // again in the same accessibility service session.
    private String mConnectedBrailleDisplaySerialNumber = null;

    private static final class AccessibilityInputMethodSessionCallback
            extends IAccessibilityInputMethodSessionCallback.Stub {
@@ -225,6 +229,7 @@ class AccessibilityServiceConnection extends AbstractAccessibilityServiceConnect
        resetLocked();
        if (Flags.enableBrailleSuwImmediateConnections() && mUsbDeviceReceiverReceiver != null) {
            mContext.unregisterReceiver(mUsbDeviceReceiverReceiver);
            mConnectedBrailleDisplaySerialNumber = null;
        }
    }

@@ -839,7 +844,8 @@ class AccessibilityServiceConnection extends AbstractAccessibilityServiceConnect
            return;
        }

        if (isInSetupWizard()) {
        if (isInSetupWizard() || (mConnectedBrailleDisplaySerialNumber != null
                && mConnectedBrailleDisplaySerialNumber.equals(device.getSerialNumber()))) {
            int clientUid = getClientUid();
            if (clientUid == UID_UNKNOWN) {
                return;
@@ -847,6 +853,13 @@ class AccessibilityServiceConnection extends AbstractAccessibilityServiceConnect

            UsbManager usbManager = mContext.getSystemService(UsbManager.class);
            usbManager.grantPermission(device, /* uid of client's App */ clientUid);

            String usbSerialNumber = device.getSerialNumber();
            if (!TextUtils.isEmpty(usbSerialNumber)) {
                // Store the serial number to re-grant USB permission to this braille display if it
                // is unplugged and reconnected.
                mConnectedBrailleDisplaySerialNumber = usbSerialNumber;
            }
        }
    }

+44 −0
Original line number Diff line number Diff line
@@ -598,4 +598,48 @@ public class AccessibilityServiceConnectionTest {
        usbDeviceReceiverCaptor.getValue().onReceive(mMockContext, intent);
        verify(usbManager, never()).grantPermission(any(), any());
    }

    @Test
    @EnableFlags(
            com.android.server.accessibility.Flags.FLAG_ENABLE_BRAILLE_SUW_IMMEDIATE_CONNECTIONS)
    public void sendUsbAttachedIntentOutsideSuw_grantPermissionToSavedUsbDevice() {
        // Set USER_SETUP_COMPLETE = 0 to simulate running in SUW.
        Settings.Secure.putIntForUser(mContentResolver, Settings.Secure.USER_SETUP_COMPLETE, 0,
                mMockUserState.mUserId);

        mConnection.bindLocked();

        ArgumentCaptor<BroadcastReceiver> usbDeviceReceiverCaptor = ArgumentCaptor.forClass(
                BroadcastReceiver.class);
        verify(mMockContext).registerReceiver(usbDeviceReceiverCaptor.capture(), any());

        // Create USB device with a serial number for identification.
        UsbDevice usbDevice = Mockito.mock(UsbDevice.class);
        when(usbDevice.getSerialNumber()).thenReturn("UsbSerialNo");

        // Setup USB device attach intent.
        Intent intent = new Intent(UsbManager.ACTION_USB_DEVICE_ATTACHED);
        intent.putExtra(UsbManager.EXTRA_DEVICE, usbDevice);

        // Send intent to simulate the USB device was unplugged and plugged in again and verify
        // permission is granted to the device because it was previously connected.
        UsbManager usbManager = Mockito.mock(UsbManager.class);
        when(mMockContext.getSystemService(Context.USB_SERVICE)).thenReturn(usbManager);
        when(mMockContext.getSystemServiceName(UsbManager.class)).thenReturn(Context.USB_SERVICE);
        usbDeviceReceiverCaptor.getValue().onReceive(mMockContext, intent);
        verify(usbManager, times(1)).grantPermission(usbDevice, 0);

        // After registering the USB device in the SUW, set USER_SETUP_COMPLETE = 1 to simulate
        // plugging in the USB device again outside of SUW.
        Settings.Secure.putIntForUser(mContentResolver, Settings.Secure.USER_SETUP_COMPLETE, 1,
                mMockUserState.mUserId);

        // Reset the USB manager mock for the next call.
        Mockito.clearInvocations(usbManager);

        // Send intent to simulate the USB device was unplugged and plugged in again and verify
        // permission is granted to the device because it was previously connected.
        usbDeviceReceiverCaptor.getValue().onReceive(mMockContext, intent);
        verify(usbManager, times(1)).grantPermission(usbDevice, 0);
    }
}