Loading services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java +66 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.server.accessibility; import static android.accessibilityservice.AccessibilityService.SoftKeyboardController.ENABLE_IME_FAIL_UNKNOWN; import static android.accessibilityservice.AccessibilityService.SoftKeyboardController.ENABLE_IME_SUCCESS; import static android.content.IntentFilter.SYSTEM_HIGH_PRIORITY; import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage; Loading @@ -39,10 +40,13 @@ import android.app.PendingIntent; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothManager; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ParceledListSlice; import android.content.pm.ResolveInfo; import android.hardware.usb.UsbDevice; import android.hardware.usb.UsbManager; import android.os.Binder; Loading Loading @@ -81,6 +85,7 @@ import java.util.Set; */ class AccessibilityServiceConnection extends AbstractAccessibilityServiceConnection { private static final String LOG_TAG = "AccessibilityServiceConnection"; private static final int UID_UNKNOWN = -1; /* Holding a weak reference so there isn't a loop of references. AccessibilityUserState keeps Loading @@ -99,6 +104,7 @@ class AccessibilityServiceConnection extends AbstractAccessibilityServiceConnect private List<Bundle> mTestBrailleDisplays = null; private final Handler mMainHandler; private UsbDeviceReceiver mUsbDeviceReceiverReceiver; private static final class AccessibilityInputMethodSessionCallback extends IAccessibilityInputMethodSessionCallback.Stub { Loading @@ -124,6 +130,24 @@ class AccessibilityServiceConnection extends AbstractAccessibilityServiceConnect } } private class UsbDeviceReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (!Flags.enableBrailleSuwImmediateConnections()) { return; } UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE, UsbDevice.class); if (device != null) { String action = intent.getAction(); if (action != null && action.equals(UsbManager.ACTION_USB_DEVICE_ATTACHED)) { onDeviceAttached(device); } } } } AccessibilityServiceConnection(@Nullable AccessibilityUserState userState, Context context, ComponentName componentName, AccessibilityServiceInfo accessibilityServiceInfo, int id, Handler mainHandler, Loading Loading @@ -177,6 +201,14 @@ class AccessibilityServiceConnection extends AbstractAccessibilityServiceConnect mActivityTaskManagerService.setAllowAppSwitches(mComponentName.flattenToString(), mAccessibilityServiceInfo.getResolveInfo().serviceInfo.applicationInfo.uid, userState.mUserId); if (Flags.enableBrailleSuwImmediateConnections() && isInSetupWizard()) { IntentFilter filter = new IntentFilter(); filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED); filter.setPriority(SYSTEM_HIGH_PRIORITY); mUsbDeviceReceiverReceiver = new UsbDeviceReceiver(); mContext.registerReceiver(mUsbDeviceReceiverReceiver, filter); } } public void unbindLocked() { Loading @@ -191,6 +223,9 @@ class AccessibilityServiceConnection extends AbstractAccessibilityServiceConnect mActivityTaskManagerService.setAllowAppSwitches(mComponentName.flattenToString(), -1, userState.mUserId); resetLocked(); if (Flags.enableBrailleSuwImmediateConnections() && mUsbDeviceReceiverReceiver != null) { mContext.unregisterReceiver(mUsbDeviceReceiverReceiver); } } public boolean canRetrieveInteractiveWindowsLocked() { Loading Loading @@ -799,6 +834,37 @@ class AccessibilityServiceConnection extends AbstractAccessibilityServiceConnect } } private void onDeviceAttached(UsbDevice device) { if (!Flags.enableBrailleSuwImmediateConnections()) { return; } if (isInSetupWizard()) { int clientUid = getClientUid(); if (clientUid == UID_UNKNOWN) { return; } UsbManager usbManager = mContext.getSystemService(UsbManager.class); usbManager.grantPermission(device, /* uid of client's App */ clientUid); } } private int getClientUid() { ResolveInfo resolveInfo = mAccessibilityServiceInfo.getResolveInfo(); if (resolveInfo != null && resolveInfo.serviceInfo != null && resolveInfo.serviceInfo.applicationInfo != null) { return resolveInfo.serviceInfo.applicationInfo.uid; } return UID_UNKNOWN; } private boolean isInSetupWizard() { return Settings.Secure.getIntForUser(mContext.getContentResolver(), Settings.Secure.USER_SETUP_COMPLETE, 0, mUserId) == 0; } @Override @EnforcePermission(Manifest.permission.MANAGE_ACCESSIBILITY) public void setTestBrailleDisplayData(List<Bundle> brailleDisplays) { Loading services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java +122 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.server.accessibility; import static android.content.IntentFilter.SYSTEM_HIGH_PRIORITY; import static com.google.common.truth.Truth.assertThat; import static junit.framework.Assert.assertFalse; Loading @@ -26,6 +28,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.notNull; import static org.mockito.ArgumentMatchers.same; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; Loading @@ -41,9 +44,11 @@ import android.accessibilityservice.GestureDescription; import android.accessibilityservice.IAccessibilityServiceClient; import android.accessibilityservice.IBrailleDisplayConnection; import android.accessibilityservice.IBrailleDisplayController; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.ParceledListSlice; import android.content.pm.ResolveInfo; Loading @@ -56,13 +61,18 @@ import android.os.IBinder; import android.os.RemoteException; import android.os.UserHandle; import android.os.test.FakePermissionEnforcer; import android.platform.test.annotations.EnableFlags; import android.platform.test.annotations.RequiresFlagsEnabled; import android.platform.test.flag.junit.CheckFlagsRule; import android.platform.test.flag.junit.DeviceFlagsValueProvider; import android.platform.test.flag.junit.SetFlagsRule; import android.provider.Settings; import android.test.mock.MockContentResolver; import android.testing.DexmakerShareClassLoaderRule; import android.view.Display; import android.view.WindowManager; import com.android.internal.util.test.FakeSettingsProvider; import com.android.server.accessibility.magnification.MagnificationProcessor; import com.android.server.accessibility.test.MessageCapturingHandler; import com.android.server.wm.ActivityTaskManagerInternal; Loading Loading @@ -98,6 +108,9 @@ public class AccessibilityServiceConnectionTest { @Rule public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); AccessibilityServiceConnection mConnection; @Mock AccessibilityUserState mMockUserState; Loading Loading @@ -132,6 +145,7 @@ public class AccessibilityServiceConnectionTest { FakePermissionEnforcer mFakePermissionEnforcer = new FakePermissionEnforcer(); MessageCapturingHandler mHandler = new MessageCapturingHandler(null); MockContentResolver mContentResolver; @Before public void setup() { Loading @@ -154,6 +168,10 @@ public class AccessibilityServiceConnectionTest { when(mMockContext.getSystemService(Context.PERMISSION_ENFORCER_SERVICE)) .thenReturn(mFakePermissionEnforcer); mContentResolver = new MockContentResolver(); mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider()); when(mMockContext.getContentResolver()).thenReturn(mContentResolver); mConnection = new AccessibilityServiceConnection(mMockUserState, mMockContext, COMPONENT_NAME, mServiceInfo, SERVICE_ID, mHandler, new Object(), mMockSecurityPolicy, mMockSystemSupport, mMockA11yTrace, Loading Loading @@ -476,4 +494,108 @@ public class AccessibilityServiceConnectionTest { verify(mMockSecurityPolicy).canEnableDisableInputMethod( eq(imeId), any(), eq(callingUserId)); } @Test @EnableFlags( com.android.server.accessibility.Flags.FLAG_ENABLE_BRAILLE_SUW_IMMEDIATE_CONNECTIONS) public void bindUnbindInSuw_registerUsbReceiver() { // Set USER_SETUP_COMPLETE = 0 to simulate running in SUW. Settings.Secure.putIntForUser(mContentResolver, Settings.Secure.USER_SETUP_COMPLETE, 0, mMockUserState.mUserId); mConnection.bindLocked(); // Register the receiver. ArgumentCaptor<IntentFilter> intentFilterCaptor = ArgumentCaptor.forClass( IntentFilter.class); ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor = ArgumentCaptor.forClass( BroadcastReceiver.class); verify(mMockContext).registerReceiver(broadcastReceiverCaptor.capture(), intentFilterCaptor.capture()); IntentFilter intentFilter = intentFilterCaptor.getValue(); assertThat(intentFilter.getAction(0)).isEqualTo(UsbManager.ACTION_USB_DEVICE_ATTACHED); assertThat(intentFilter.getPriority()).isEqualTo(SYSTEM_HIGH_PRIORITY); // Unregister the receiver. mConnection.unbindLocked(); verify(mMockContext).unregisterReceiver(same(broadcastReceiverCaptor.getValue())); } @Test @EnableFlags( com.android.server.accessibility.Flags.FLAG_ENABLE_BRAILLE_SUW_IMMEDIATE_CONNECTIONS) public void bindOutsideSuw_dontRegisterUsbReceiver() { // Set USER_SETUP_COMPLETE = 1 to simulate running outside of SUW. Settings.Secure.putIntForUser(mContentResolver, Settings.Secure.USER_SETUP_COMPLETE, 1, mMockUserState.mUserId); mConnection.bindLocked(); verify(mMockContext, never()).registerReceiver(any(), any()); } @Test @EnableFlags( com.android.server.accessibility.Flags.FLAG_ENABLE_BRAILLE_SUW_IMMEDIATE_CONNECTIONS) public void sendUsbAttachedIntentInSuw_grantPermissionToUsbDevice() { // Set USER_SETUP_COMPLETE = 0 to simulate running in SUW. Settings.Secure.putIntForUser(mContentResolver, Settings.Secure.USER_SETUP_COMPLETE, 0, mMockUserState.mUserId); mConnection.bindLocked(); // Get the registered UsbDeviceReceiver. ArgumentCaptor<BroadcastReceiver> usbDeviceReceiverCaptor = ArgumentCaptor.forClass( BroadcastReceiver.class); verify(mMockContext).registerReceiver(usbDeviceReceiverCaptor.capture(), any()); // Setup USB device attach intent. Intent intent = new Intent(UsbManager.ACTION_USB_DEVICE_ATTACHED); UsbDevice usbDevice = Mockito.mock(UsbDevice.class); intent.putExtra(UsbManager.EXTRA_DEVICE, usbDevice); int expectedUid = 74859; mMockResolveInfo.serviceInfo.applicationInfo.uid = expectedUid; // Send intent and verify permission is granted to the USB device. 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).grantPermission(usbDevice, expectedUid); } @Test @EnableFlags( com.android.server.accessibility.Flags.FLAG_ENABLE_BRAILLE_SUW_IMMEDIATE_CONNECTIONS) public void sendUsbAttachedIntentOutsideSuw_doNotGrantPermissionToUsbDevice() { // Set USER_SETUP_COMPLETE = 0 to simulate running in SUW. Settings.Secure.putIntForUser(mContentResolver, Settings.Secure.USER_SETUP_COMPLETE, 0, mMockUserState.mUserId); mConnection.bindLocked(); // After registering the USB receiver in SUW, set USER_SETUP_COMPLETE = 1 to simulate // plugging in the USB device outside of SUW. Settings.Secure.putIntForUser(mContentResolver, Settings.Secure.USER_SETUP_COMPLETE, 1, mMockUserState.mUserId); // Get the registered UsbDeviceReceiver. ArgumentCaptor<BroadcastReceiver> usbDeviceReceiverCaptor = ArgumentCaptor.forClass( BroadcastReceiver.class); verify(mMockContext).registerReceiver(usbDeviceReceiverCaptor.capture(), any()); // Setup USB device attach intent. Intent intent = new Intent(UsbManager.ACTION_USB_DEVICE_ATTACHED); UsbDevice usbDevice = Mockito.mock(UsbDevice.class); intent.putExtra(UsbManager.EXTRA_DEVICE, usbDevice); // Send intent and verify permission isn't granted to the USB device because it's outside // the SUW. 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, never()).grantPermission(any(), any()); } } Loading
services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java +66 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.server.accessibility; import static android.accessibilityservice.AccessibilityService.SoftKeyboardController.ENABLE_IME_FAIL_UNKNOWN; import static android.accessibilityservice.AccessibilityService.SoftKeyboardController.ENABLE_IME_SUCCESS; import static android.content.IntentFilter.SYSTEM_HIGH_PRIORITY; import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage; Loading @@ -39,10 +40,13 @@ import android.app.PendingIntent; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothManager; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ParceledListSlice; import android.content.pm.ResolveInfo; import android.hardware.usb.UsbDevice; import android.hardware.usb.UsbManager; import android.os.Binder; Loading Loading @@ -81,6 +85,7 @@ import java.util.Set; */ class AccessibilityServiceConnection extends AbstractAccessibilityServiceConnection { private static final String LOG_TAG = "AccessibilityServiceConnection"; private static final int UID_UNKNOWN = -1; /* Holding a weak reference so there isn't a loop of references. AccessibilityUserState keeps Loading @@ -99,6 +104,7 @@ class AccessibilityServiceConnection extends AbstractAccessibilityServiceConnect private List<Bundle> mTestBrailleDisplays = null; private final Handler mMainHandler; private UsbDeviceReceiver mUsbDeviceReceiverReceiver; private static final class AccessibilityInputMethodSessionCallback extends IAccessibilityInputMethodSessionCallback.Stub { Loading @@ -124,6 +130,24 @@ class AccessibilityServiceConnection extends AbstractAccessibilityServiceConnect } } private class UsbDeviceReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (!Flags.enableBrailleSuwImmediateConnections()) { return; } UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE, UsbDevice.class); if (device != null) { String action = intent.getAction(); if (action != null && action.equals(UsbManager.ACTION_USB_DEVICE_ATTACHED)) { onDeviceAttached(device); } } } } AccessibilityServiceConnection(@Nullable AccessibilityUserState userState, Context context, ComponentName componentName, AccessibilityServiceInfo accessibilityServiceInfo, int id, Handler mainHandler, Loading Loading @@ -177,6 +201,14 @@ class AccessibilityServiceConnection extends AbstractAccessibilityServiceConnect mActivityTaskManagerService.setAllowAppSwitches(mComponentName.flattenToString(), mAccessibilityServiceInfo.getResolveInfo().serviceInfo.applicationInfo.uid, userState.mUserId); if (Flags.enableBrailleSuwImmediateConnections() && isInSetupWizard()) { IntentFilter filter = new IntentFilter(); filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED); filter.setPriority(SYSTEM_HIGH_PRIORITY); mUsbDeviceReceiverReceiver = new UsbDeviceReceiver(); mContext.registerReceiver(mUsbDeviceReceiverReceiver, filter); } } public void unbindLocked() { Loading @@ -191,6 +223,9 @@ class AccessibilityServiceConnection extends AbstractAccessibilityServiceConnect mActivityTaskManagerService.setAllowAppSwitches(mComponentName.flattenToString(), -1, userState.mUserId); resetLocked(); if (Flags.enableBrailleSuwImmediateConnections() && mUsbDeviceReceiverReceiver != null) { mContext.unregisterReceiver(mUsbDeviceReceiverReceiver); } } public boolean canRetrieveInteractiveWindowsLocked() { Loading Loading @@ -799,6 +834,37 @@ class AccessibilityServiceConnection extends AbstractAccessibilityServiceConnect } } private void onDeviceAttached(UsbDevice device) { if (!Flags.enableBrailleSuwImmediateConnections()) { return; } if (isInSetupWizard()) { int clientUid = getClientUid(); if (clientUid == UID_UNKNOWN) { return; } UsbManager usbManager = mContext.getSystemService(UsbManager.class); usbManager.grantPermission(device, /* uid of client's App */ clientUid); } } private int getClientUid() { ResolveInfo resolveInfo = mAccessibilityServiceInfo.getResolveInfo(); if (resolveInfo != null && resolveInfo.serviceInfo != null && resolveInfo.serviceInfo.applicationInfo != null) { return resolveInfo.serviceInfo.applicationInfo.uid; } return UID_UNKNOWN; } private boolean isInSetupWizard() { return Settings.Secure.getIntForUser(mContext.getContentResolver(), Settings.Secure.USER_SETUP_COMPLETE, 0, mUserId) == 0; } @Override @EnforcePermission(Manifest.permission.MANAGE_ACCESSIBILITY) public void setTestBrailleDisplayData(List<Bundle> brailleDisplays) { Loading
services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java +122 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.server.accessibility; import static android.content.IntentFilter.SYSTEM_HIGH_PRIORITY; import static com.google.common.truth.Truth.assertThat; import static junit.framework.Assert.assertFalse; Loading @@ -26,6 +28,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.notNull; import static org.mockito.ArgumentMatchers.same; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; Loading @@ -41,9 +44,11 @@ import android.accessibilityservice.GestureDescription; import android.accessibilityservice.IAccessibilityServiceClient; import android.accessibilityservice.IBrailleDisplayConnection; import android.accessibilityservice.IBrailleDisplayController; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.ParceledListSlice; import android.content.pm.ResolveInfo; Loading @@ -56,13 +61,18 @@ import android.os.IBinder; import android.os.RemoteException; import android.os.UserHandle; import android.os.test.FakePermissionEnforcer; import android.platform.test.annotations.EnableFlags; import android.platform.test.annotations.RequiresFlagsEnabled; import android.platform.test.flag.junit.CheckFlagsRule; import android.platform.test.flag.junit.DeviceFlagsValueProvider; import android.platform.test.flag.junit.SetFlagsRule; import android.provider.Settings; import android.test.mock.MockContentResolver; import android.testing.DexmakerShareClassLoaderRule; import android.view.Display; import android.view.WindowManager; import com.android.internal.util.test.FakeSettingsProvider; import com.android.server.accessibility.magnification.MagnificationProcessor; import com.android.server.accessibility.test.MessageCapturingHandler; import com.android.server.wm.ActivityTaskManagerInternal; Loading Loading @@ -98,6 +108,9 @@ public class AccessibilityServiceConnectionTest { @Rule public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); AccessibilityServiceConnection mConnection; @Mock AccessibilityUserState mMockUserState; Loading Loading @@ -132,6 +145,7 @@ public class AccessibilityServiceConnectionTest { FakePermissionEnforcer mFakePermissionEnforcer = new FakePermissionEnforcer(); MessageCapturingHandler mHandler = new MessageCapturingHandler(null); MockContentResolver mContentResolver; @Before public void setup() { Loading @@ -154,6 +168,10 @@ public class AccessibilityServiceConnectionTest { when(mMockContext.getSystemService(Context.PERMISSION_ENFORCER_SERVICE)) .thenReturn(mFakePermissionEnforcer); mContentResolver = new MockContentResolver(); mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider()); when(mMockContext.getContentResolver()).thenReturn(mContentResolver); mConnection = new AccessibilityServiceConnection(mMockUserState, mMockContext, COMPONENT_NAME, mServiceInfo, SERVICE_ID, mHandler, new Object(), mMockSecurityPolicy, mMockSystemSupport, mMockA11yTrace, Loading Loading @@ -476,4 +494,108 @@ public class AccessibilityServiceConnectionTest { verify(mMockSecurityPolicy).canEnableDisableInputMethod( eq(imeId), any(), eq(callingUserId)); } @Test @EnableFlags( com.android.server.accessibility.Flags.FLAG_ENABLE_BRAILLE_SUW_IMMEDIATE_CONNECTIONS) public void bindUnbindInSuw_registerUsbReceiver() { // Set USER_SETUP_COMPLETE = 0 to simulate running in SUW. Settings.Secure.putIntForUser(mContentResolver, Settings.Secure.USER_SETUP_COMPLETE, 0, mMockUserState.mUserId); mConnection.bindLocked(); // Register the receiver. ArgumentCaptor<IntentFilter> intentFilterCaptor = ArgumentCaptor.forClass( IntentFilter.class); ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor = ArgumentCaptor.forClass( BroadcastReceiver.class); verify(mMockContext).registerReceiver(broadcastReceiverCaptor.capture(), intentFilterCaptor.capture()); IntentFilter intentFilter = intentFilterCaptor.getValue(); assertThat(intentFilter.getAction(0)).isEqualTo(UsbManager.ACTION_USB_DEVICE_ATTACHED); assertThat(intentFilter.getPriority()).isEqualTo(SYSTEM_HIGH_PRIORITY); // Unregister the receiver. mConnection.unbindLocked(); verify(mMockContext).unregisterReceiver(same(broadcastReceiverCaptor.getValue())); } @Test @EnableFlags( com.android.server.accessibility.Flags.FLAG_ENABLE_BRAILLE_SUW_IMMEDIATE_CONNECTIONS) public void bindOutsideSuw_dontRegisterUsbReceiver() { // Set USER_SETUP_COMPLETE = 1 to simulate running outside of SUW. Settings.Secure.putIntForUser(mContentResolver, Settings.Secure.USER_SETUP_COMPLETE, 1, mMockUserState.mUserId); mConnection.bindLocked(); verify(mMockContext, never()).registerReceiver(any(), any()); } @Test @EnableFlags( com.android.server.accessibility.Flags.FLAG_ENABLE_BRAILLE_SUW_IMMEDIATE_CONNECTIONS) public void sendUsbAttachedIntentInSuw_grantPermissionToUsbDevice() { // Set USER_SETUP_COMPLETE = 0 to simulate running in SUW. Settings.Secure.putIntForUser(mContentResolver, Settings.Secure.USER_SETUP_COMPLETE, 0, mMockUserState.mUserId); mConnection.bindLocked(); // Get the registered UsbDeviceReceiver. ArgumentCaptor<BroadcastReceiver> usbDeviceReceiverCaptor = ArgumentCaptor.forClass( BroadcastReceiver.class); verify(mMockContext).registerReceiver(usbDeviceReceiverCaptor.capture(), any()); // Setup USB device attach intent. Intent intent = new Intent(UsbManager.ACTION_USB_DEVICE_ATTACHED); UsbDevice usbDevice = Mockito.mock(UsbDevice.class); intent.putExtra(UsbManager.EXTRA_DEVICE, usbDevice); int expectedUid = 74859; mMockResolveInfo.serviceInfo.applicationInfo.uid = expectedUid; // Send intent and verify permission is granted to the USB device. 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).grantPermission(usbDevice, expectedUid); } @Test @EnableFlags( com.android.server.accessibility.Flags.FLAG_ENABLE_BRAILLE_SUW_IMMEDIATE_CONNECTIONS) public void sendUsbAttachedIntentOutsideSuw_doNotGrantPermissionToUsbDevice() { // Set USER_SETUP_COMPLETE = 0 to simulate running in SUW. Settings.Secure.putIntForUser(mContentResolver, Settings.Secure.USER_SETUP_COMPLETE, 0, mMockUserState.mUserId); mConnection.bindLocked(); // After registering the USB receiver in SUW, set USER_SETUP_COMPLETE = 1 to simulate // plugging in the USB device outside of SUW. Settings.Secure.putIntForUser(mContentResolver, Settings.Secure.USER_SETUP_COMPLETE, 1, mMockUserState.mUserId); // Get the registered UsbDeviceReceiver. ArgumentCaptor<BroadcastReceiver> usbDeviceReceiverCaptor = ArgumentCaptor.forClass( BroadcastReceiver.class); verify(mMockContext).registerReceiver(usbDeviceReceiverCaptor.capture(), any()); // Setup USB device attach intent. Intent intent = new Intent(UsbManager.ACTION_USB_DEVICE_ATTACHED); UsbDevice usbDevice = Mockito.mock(UsbDevice.class); intent.putExtra(UsbManager.EXTRA_DEVICE, usbDevice); // Send intent and verify permission isn't granted to the USB device because it's outside // the SUW. 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, never()).grantPermission(any(), any()); } }