Loading services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java +1 −13 Original line number Diff line number Diff line Loading @@ -64,7 +64,6 @@ import android.app.PendingIntent; import android.app.RemoteAction; import android.app.admin.DevicePolicyManager; import android.appwidget.AppWidgetManagerInternal; import android.companion.virtual.VirtualDeviceManager; import android.content.ActivityNotFoundException; import android.content.BroadcastReceiver; import android.content.ComponentName; Loading Loading @@ -1071,18 +1070,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub mContext.registerReceiverAsUser(receiver, UserHandle.ALL, filter, null, mMainHandler, Context.RECEIVER_EXPORTED); if (android.companion.virtual.flags.Flags.vdmPublicApis()) { VirtualDeviceManager vdm = mContext.getSystemService(VirtualDeviceManager.class); if (vdm != null) { vdm.registerVirtualDeviceListener(mContext.getMainExecutor(), new VirtualDeviceManager.VirtualDeviceListener() { @Override public void onVirtualDeviceClosed(int deviceId) { mProxyManager.clearConnections(deviceId); } }); } } else { if (!android.companion.virtual.flags.Flags.vdmPublicApis()) { final BroadcastReceiver virtualDeviceReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { Loading services/accessibility/java/com/android/server/accessibility/ProxyManager.java +33 −0 Original line number Diff line number Diff line Loading @@ -101,6 +101,8 @@ public class ProxyManager { private VirtualDeviceManagerInternal.AppsOnVirtualDeviceListener mAppsOnVirtualDeviceListener; private VirtualDeviceManager.VirtualDeviceListener mVirtualDeviceListener; /** * Callbacks into AccessibilityManagerService. */ Loading Loading @@ -189,6 +191,9 @@ public class ProxyManager { } } } if (mProxyA11yServiceConnections.size() == 1) { registerVirtualDeviceListener(); } } // If the client dies, make sure to remove the connection. Loading @@ -210,6 +215,31 @@ public class ProxyManager { connection.initializeServiceInterface(client); } private void registerVirtualDeviceListener() { VirtualDeviceManager vdm = mContext.getSystemService(VirtualDeviceManager.class); if (vdm == null || !android.companion.virtual.flags.Flags.vdmPublicApis()) { return; } if (mVirtualDeviceListener == null) { mVirtualDeviceListener = new VirtualDeviceManager.VirtualDeviceListener() { @Override public void onVirtualDeviceClosed(int deviceId) { clearConnections(deviceId); } }; } vdm.registerVirtualDeviceListener(mContext.getMainExecutor(), mVirtualDeviceListener); } private void unregisterVirtualDeviceListener() { VirtualDeviceManager vdm = mContext.getSystemService(VirtualDeviceManager.class); if (vdm == null || !android.companion.virtual.flags.Flags.vdmPublicApis()) { return; } vdm.unregisterVirtualDeviceListener(mVirtualDeviceListener); } /** * Unregister the proxy based on display id. */ Loading Loading @@ -258,6 +288,9 @@ public class ProxyManager { deviceId = mProxyA11yServiceConnections.get(displayId).getDeviceId(); mProxyA11yServiceConnections.remove(displayId); removedFromConnections = true; if (mProxyA11yServiceConnections.size() == 0) { unregisterVirtualDeviceListener(); } } } Loading services/tests/servicestests/src/com/android/server/accessibility/ProxyManagerTest.java +107 −0 Original line number Diff line number Diff line Loading @@ -29,6 +29,8 @@ import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.never; import static org.mockito.Mockito.timeout; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; Loading @@ -38,6 +40,7 @@ import android.accessibilityservice.AccessibilityTrace; import android.accessibilityservice.IAccessibilityServiceClient; import android.accessibilityservice.IAccessibilityServiceConnection; import android.accessibilityservice.MagnificationConfig; import android.companion.virtual.IVirtualDeviceListener; import android.companion.virtual.IVirtualDeviceManager; import android.companion.virtual.VirtualDeviceManager; import android.content.ComponentName; Loading @@ -50,6 +53,7 @@ import android.os.RemoteException; 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.util.ArraySet; import android.view.KeyEvent; import android.view.MotionEvent; Loading @@ -74,6 +78,7 @@ import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; Loading @@ -94,6 +99,9 @@ public class ProxyManagerTest { @Rule public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); @Rule public SetFlagsRule mSetFlagsRule = new SetFlagsRule(); @Mock private Context mMockContext; @Mock private AccessibilitySecurityPolicy mMockSecurityPolicy; @Mock private AccessibilityWindowManager mMockA11yWindowManager; Loading @@ -114,6 +122,8 @@ public class ProxyManagerTest { @Before public void setup() throws RemoteException { mSetFlagsRule.initAllFlagsToReleaseConfigDefault(); MockitoAnnotations.initMocks(this); final Resources resources = InstrumentationRegistry.getContext().getResources(); Loading @@ -121,6 +131,8 @@ public class ProxyManagerTest { resources.getDimensionPixelSize(R.dimen.accessibility_focus_highlight_stroke_width); mFocusColorDefaultValue = resources.getColor(R.color.accessibility_focus_highlight_color); when(mMockContext.getResources()).thenReturn(resources); when(mMockContext.getMainExecutor()) .thenReturn(InstrumentationRegistry.getTargetContext().getMainExecutor()); when(mMockVirtualDeviceManagerInternal.getDeviceIdsForUid(anyInt())).thenReturn( new ArraySet(Set.of(DEVICE_ID))); Loading Loading @@ -416,6 +428,101 @@ public class ProxyManagerTest { assertThat(focusStrokeWidth).isEqualTo(mFocusStrokeWidthDefaultValue); } @Test public void testRegisterProxy_registersVirtualDeviceListener() throws RemoteException { mSetFlagsRule.enableFlags(android.companion.virtual.flags.Flags.FLAG_VDM_PUBLIC_APIS); registerProxy(DISPLAY_ID); verify(mMockIVirtualDeviceManager, times(1)).registerVirtualDeviceListener(any()); } @Test public void testRegisterMultipleProxies_registersOneVirtualDeviceListener() throws RemoteException { mSetFlagsRule.enableFlags(android.companion.virtual.flags.Flags.FLAG_VDM_PUBLIC_APIS); registerProxy(DISPLAY_ID); registerProxy(DISPLAY_2_ID); verify(mMockIVirtualDeviceManager, times(1)).registerVirtualDeviceListener(any()); } @Test public void testUnregisterProxy_unregistersVirtualDeviceListener() throws RemoteException { mSetFlagsRule.enableFlags(android.companion.virtual.flags.Flags.FLAG_VDM_PUBLIC_APIS); registerProxy(DISPLAY_ID); mProxyManager.unregisterProxy(DISPLAY_ID); verify(mMockIVirtualDeviceManager, times(1)).unregisterVirtualDeviceListener(any()); } @Test public void testUnregisterProxy_onlyUnregistersVirtualDeviceListenerOnLastProxyRemoval() throws RemoteException { mSetFlagsRule.enableFlags(android.companion.virtual.flags.Flags.FLAG_VDM_PUBLIC_APIS); registerProxy(DISPLAY_ID); registerProxy(DISPLAY_2_ID); mProxyManager.unregisterProxy(DISPLAY_ID); verify(mMockIVirtualDeviceManager, never()).unregisterVirtualDeviceListener(any()); mProxyManager.unregisterProxy(DISPLAY_2_ID); verify(mMockIVirtualDeviceManager, times(1)).unregisterVirtualDeviceListener(any()); } @Test public void testRegisteredProxy_virtualDeviceClosed_proxyClosed() throws RemoteException { mSetFlagsRule.enableFlags(android.companion.virtual.flags.Flags.FLAG_VDM_PUBLIC_APIS); registerProxy(DISPLAY_ID); assertThat(mProxyManager.isProxyedDeviceId(DEVICE_ID)).isTrue(); assertThat(mProxyManager.isProxyedDisplay(DISPLAY_ID)).isTrue(); ArgumentCaptor<IVirtualDeviceListener> listenerArgumentCaptor = ArgumentCaptor.forClass(IVirtualDeviceListener.class); verify(mMockIVirtualDeviceManager, times(1)) .registerVirtualDeviceListener(listenerArgumentCaptor.capture()); listenerArgumentCaptor.getValue().onVirtualDeviceClosed(DEVICE_ID); verify(mMockProxySystemSupport, timeout(5_000)).removeDeviceIdLocked(DEVICE_ID); assertThat(mProxyManager.isProxyedDeviceId(DEVICE_ID)).isFalse(); assertThat(mProxyManager.isProxyedDisplay(DISPLAY_ID)).isFalse(); } @Test public void testRegisteredProxy_unrelatedVirtualDeviceClosed_proxyNotClosed() throws RemoteException { mSetFlagsRule.enableFlags(android.companion.virtual.flags.Flags.FLAG_VDM_PUBLIC_APIS); registerProxy(DISPLAY_ID); assertThat(mProxyManager.isProxyedDeviceId(DEVICE_ID)).isTrue(); assertThat(mProxyManager.isProxyedDisplay(DISPLAY_ID)).isTrue(); ArgumentCaptor<IVirtualDeviceListener> listenerArgumentCaptor = ArgumentCaptor.forClass(IVirtualDeviceListener.class); verify(mMockIVirtualDeviceManager, times(1)) .registerVirtualDeviceListener(listenerArgumentCaptor.capture()); listenerArgumentCaptor.getValue().onVirtualDeviceClosed(DEVICE_ID + 1); assertThat(mProxyManager.isProxyedDeviceId(DEVICE_ID)).isTrue(); assertThat(mProxyManager.isProxyedDisplay(DISPLAY_ID)).isTrue(); } @Test public void testRegisterProxy_doesNotRegisterVirtualDeviceListener_flagDisabled() throws RemoteException { mSetFlagsRule.disableFlags(android.companion.virtual.flags.Flags.FLAG_VDM_PUBLIC_APIS); registerProxy(DISPLAY_ID); mProxyManager.unregisterProxy(DISPLAY_ID); verify(mMockIVirtualDeviceManager, never()).registerVirtualDeviceListener(any()); verify(mMockIVirtualDeviceManager, never()).unregisterVirtualDeviceListener(any()); } private void registerProxy(int displayId) { try { mProxyManager.registerProxy(mMockAccessibilityServiceClient, displayId, anyInt(), Loading Loading
services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java +1 −13 Original line number Diff line number Diff line Loading @@ -64,7 +64,6 @@ import android.app.PendingIntent; import android.app.RemoteAction; import android.app.admin.DevicePolicyManager; import android.appwidget.AppWidgetManagerInternal; import android.companion.virtual.VirtualDeviceManager; import android.content.ActivityNotFoundException; import android.content.BroadcastReceiver; import android.content.ComponentName; Loading Loading @@ -1071,18 +1070,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub mContext.registerReceiverAsUser(receiver, UserHandle.ALL, filter, null, mMainHandler, Context.RECEIVER_EXPORTED); if (android.companion.virtual.flags.Flags.vdmPublicApis()) { VirtualDeviceManager vdm = mContext.getSystemService(VirtualDeviceManager.class); if (vdm != null) { vdm.registerVirtualDeviceListener(mContext.getMainExecutor(), new VirtualDeviceManager.VirtualDeviceListener() { @Override public void onVirtualDeviceClosed(int deviceId) { mProxyManager.clearConnections(deviceId); } }); } } else { if (!android.companion.virtual.flags.Flags.vdmPublicApis()) { final BroadcastReceiver virtualDeviceReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { Loading
services/accessibility/java/com/android/server/accessibility/ProxyManager.java +33 −0 Original line number Diff line number Diff line Loading @@ -101,6 +101,8 @@ public class ProxyManager { private VirtualDeviceManagerInternal.AppsOnVirtualDeviceListener mAppsOnVirtualDeviceListener; private VirtualDeviceManager.VirtualDeviceListener mVirtualDeviceListener; /** * Callbacks into AccessibilityManagerService. */ Loading Loading @@ -189,6 +191,9 @@ public class ProxyManager { } } } if (mProxyA11yServiceConnections.size() == 1) { registerVirtualDeviceListener(); } } // If the client dies, make sure to remove the connection. Loading @@ -210,6 +215,31 @@ public class ProxyManager { connection.initializeServiceInterface(client); } private void registerVirtualDeviceListener() { VirtualDeviceManager vdm = mContext.getSystemService(VirtualDeviceManager.class); if (vdm == null || !android.companion.virtual.flags.Flags.vdmPublicApis()) { return; } if (mVirtualDeviceListener == null) { mVirtualDeviceListener = new VirtualDeviceManager.VirtualDeviceListener() { @Override public void onVirtualDeviceClosed(int deviceId) { clearConnections(deviceId); } }; } vdm.registerVirtualDeviceListener(mContext.getMainExecutor(), mVirtualDeviceListener); } private void unregisterVirtualDeviceListener() { VirtualDeviceManager vdm = mContext.getSystemService(VirtualDeviceManager.class); if (vdm == null || !android.companion.virtual.flags.Flags.vdmPublicApis()) { return; } vdm.unregisterVirtualDeviceListener(mVirtualDeviceListener); } /** * Unregister the proxy based on display id. */ Loading Loading @@ -258,6 +288,9 @@ public class ProxyManager { deviceId = mProxyA11yServiceConnections.get(displayId).getDeviceId(); mProxyA11yServiceConnections.remove(displayId); removedFromConnections = true; if (mProxyA11yServiceConnections.size() == 0) { unregisterVirtualDeviceListener(); } } } Loading
services/tests/servicestests/src/com/android/server/accessibility/ProxyManagerTest.java +107 −0 Original line number Diff line number Diff line Loading @@ -29,6 +29,8 @@ import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.never; import static org.mockito.Mockito.timeout; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; Loading @@ -38,6 +40,7 @@ import android.accessibilityservice.AccessibilityTrace; import android.accessibilityservice.IAccessibilityServiceClient; import android.accessibilityservice.IAccessibilityServiceConnection; import android.accessibilityservice.MagnificationConfig; import android.companion.virtual.IVirtualDeviceListener; import android.companion.virtual.IVirtualDeviceManager; import android.companion.virtual.VirtualDeviceManager; import android.content.ComponentName; Loading @@ -50,6 +53,7 @@ import android.os.RemoteException; 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.util.ArraySet; import android.view.KeyEvent; import android.view.MotionEvent; Loading @@ -74,6 +78,7 @@ import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; Loading @@ -94,6 +99,9 @@ public class ProxyManagerTest { @Rule public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); @Rule public SetFlagsRule mSetFlagsRule = new SetFlagsRule(); @Mock private Context mMockContext; @Mock private AccessibilitySecurityPolicy mMockSecurityPolicy; @Mock private AccessibilityWindowManager mMockA11yWindowManager; Loading @@ -114,6 +122,8 @@ public class ProxyManagerTest { @Before public void setup() throws RemoteException { mSetFlagsRule.initAllFlagsToReleaseConfigDefault(); MockitoAnnotations.initMocks(this); final Resources resources = InstrumentationRegistry.getContext().getResources(); Loading @@ -121,6 +131,8 @@ public class ProxyManagerTest { resources.getDimensionPixelSize(R.dimen.accessibility_focus_highlight_stroke_width); mFocusColorDefaultValue = resources.getColor(R.color.accessibility_focus_highlight_color); when(mMockContext.getResources()).thenReturn(resources); when(mMockContext.getMainExecutor()) .thenReturn(InstrumentationRegistry.getTargetContext().getMainExecutor()); when(mMockVirtualDeviceManagerInternal.getDeviceIdsForUid(anyInt())).thenReturn( new ArraySet(Set.of(DEVICE_ID))); Loading Loading @@ -416,6 +428,101 @@ public class ProxyManagerTest { assertThat(focusStrokeWidth).isEqualTo(mFocusStrokeWidthDefaultValue); } @Test public void testRegisterProxy_registersVirtualDeviceListener() throws RemoteException { mSetFlagsRule.enableFlags(android.companion.virtual.flags.Flags.FLAG_VDM_PUBLIC_APIS); registerProxy(DISPLAY_ID); verify(mMockIVirtualDeviceManager, times(1)).registerVirtualDeviceListener(any()); } @Test public void testRegisterMultipleProxies_registersOneVirtualDeviceListener() throws RemoteException { mSetFlagsRule.enableFlags(android.companion.virtual.flags.Flags.FLAG_VDM_PUBLIC_APIS); registerProxy(DISPLAY_ID); registerProxy(DISPLAY_2_ID); verify(mMockIVirtualDeviceManager, times(1)).registerVirtualDeviceListener(any()); } @Test public void testUnregisterProxy_unregistersVirtualDeviceListener() throws RemoteException { mSetFlagsRule.enableFlags(android.companion.virtual.flags.Flags.FLAG_VDM_PUBLIC_APIS); registerProxy(DISPLAY_ID); mProxyManager.unregisterProxy(DISPLAY_ID); verify(mMockIVirtualDeviceManager, times(1)).unregisterVirtualDeviceListener(any()); } @Test public void testUnregisterProxy_onlyUnregistersVirtualDeviceListenerOnLastProxyRemoval() throws RemoteException { mSetFlagsRule.enableFlags(android.companion.virtual.flags.Flags.FLAG_VDM_PUBLIC_APIS); registerProxy(DISPLAY_ID); registerProxy(DISPLAY_2_ID); mProxyManager.unregisterProxy(DISPLAY_ID); verify(mMockIVirtualDeviceManager, never()).unregisterVirtualDeviceListener(any()); mProxyManager.unregisterProxy(DISPLAY_2_ID); verify(mMockIVirtualDeviceManager, times(1)).unregisterVirtualDeviceListener(any()); } @Test public void testRegisteredProxy_virtualDeviceClosed_proxyClosed() throws RemoteException { mSetFlagsRule.enableFlags(android.companion.virtual.flags.Flags.FLAG_VDM_PUBLIC_APIS); registerProxy(DISPLAY_ID); assertThat(mProxyManager.isProxyedDeviceId(DEVICE_ID)).isTrue(); assertThat(mProxyManager.isProxyedDisplay(DISPLAY_ID)).isTrue(); ArgumentCaptor<IVirtualDeviceListener> listenerArgumentCaptor = ArgumentCaptor.forClass(IVirtualDeviceListener.class); verify(mMockIVirtualDeviceManager, times(1)) .registerVirtualDeviceListener(listenerArgumentCaptor.capture()); listenerArgumentCaptor.getValue().onVirtualDeviceClosed(DEVICE_ID); verify(mMockProxySystemSupport, timeout(5_000)).removeDeviceIdLocked(DEVICE_ID); assertThat(mProxyManager.isProxyedDeviceId(DEVICE_ID)).isFalse(); assertThat(mProxyManager.isProxyedDisplay(DISPLAY_ID)).isFalse(); } @Test public void testRegisteredProxy_unrelatedVirtualDeviceClosed_proxyNotClosed() throws RemoteException { mSetFlagsRule.enableFlags(android.companion.virtual.flags.Flags.FLAG_VDM_PUBLIC_APIS); registerProxy(DISPLAY_ID); assertThat(mProxyManager.isProxyedDeviceId(DEVICE_ID)).isTrue(); assertThat(mProxyManager.isProxyedDisplay(DISPLAY_ID)).isTrue(); ArgumentCaptor<IVirtualDeviceListener> listenerArgumentCaptor = ArgumentCaptor.forClass(IVirtualDeviceListener.class); verify(mMockIVirtualDeviceManager, times(1)) .registerVirtualDeviceListener(listenerArgumentCaptor.capture()); listenerArgumentCaptor.getValue().onVirtualDeviceClosed(DEVICE_ID + 1); assertThat(mProxyManager.isProxyedDeviceId(DEVICE_ID)).isTrue(); assertThat(mProxyManager.isProxyedDisplay(DISPLAY_ID)).isTrue(); } @Test public void testRegisterProxy_doesNotRegisterVirtualDeviceListener_flagDisabled() throws RemoteException { mSetFlagsRule.disableFlags(android.companion.virtual.flags.Flags.FLAG_VDM_PUBLIC_APIS); registerProxy(DISPLAY_ID); mProxyManager.unregisterProxy(DISPLAY_ID); verify(mMockIVirtualDeviceManager, never()).registerVirtualDeviceListener(any()); verify(mMockIVirtualDeviceManager, never()).unregisterVirtualDeviceListener(any()); } private void registerProxy(int displayId) { try { mProxyManager.registerProxy(mMockAccessibilityServiceClient, displayId, anyInt(), Loading