Loading services/accessibility/Android.bp +16 −0 Original line number Diff line number Diff line Loading @@ -27,4 +27,20 @@ java_library_static { "services.core", "androidx.annotation_annotation", ], static_libs: [ "com_android_server_accessibility_flags_lib", ], } aconfig_declarations { name: "com_android_server_accessibility_flags", package: "com.android.server.accessibility", srcs: [ "accessibility.aconfig", ], } java_aconfig_library { name: "com_android_server_accessibility_flags_lib", aconfig_declarations: "com_android_server_accessibility_flags", } services/accessibility/accessibility.aconfig 0 → 100644 +7 −0 Original line number Diff line number Diff line package: "com.android.server.accessibility" flag { name: "proxy_use_apps_on_virtual_device_listener" namespace: "accessibility" description: "Fixes race condition described in b/286587811" bug: "286587811" } services/accessibility/java/com/android/server/accessibility/ProxyManager.java +104 −12 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ import android.os.Handler; import android.os.IBinder; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.util.ArraySet; import android.util.IntArray; import android.util.Slog; import android.util.SparseArray; Loading @@ -42,6 +43,7 @@ import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; import android.view.accessibility.IAccessibilityManagerClient; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.IntPair; import com.android.server.LocalServices; import com.android.server.companion.virtual.VirtualDeviceManagerInternal; Loading Loading @@ -96,6 +98,9 @@ public class ProxyManager { private final SystemSupport mSystemSupport; private VirtualDeviceManagerInternal.AppsOnVirtualDeviceListener mAppsOnVirtualDeviceListener; /** * Callbacks into AccessibilityManagerService. */ Loading Loading @@ -174,6 +179,16 @@ public class ProxyManager { synchronized (mLock) { mProxyA11yServiceConnections.put(displayId, connection); if (Flags.proxyUseAppsOnVirtualDeviceListener()) { if (mAppsOnVirtualDeviceListener == null) { mAppsOnVirtualDeviceListener = allRunningUids -> notifyProxyOfRunningAppsChange(allRunningUids); final VirtualDeviceManagerInternal localVdm = getLocalVdm(); if (localVdm != null) { localVdm.registerAppsOnVirtualDeviceListener(mAppsOnVirtualDeviceListener); } } } } // If the client dies, make sure to remove the connection. Loading Loading @@ -276,11 +291,21 @@ public class ProxyManager { } } }); // If there isn't an existing proxy for the device id, reset clients. Resetting // If there isn't an existing proxy for the device id, reset app clients. Resetting // will usually happen, since in most cases there will only be one proxy for a // device. if (!isProxyedDeviceId(deviceId)) { synchronized (mLock) { if (Flags.proxyUseAppsOnVirtualDeviceListener()) { if (mProxyA11yServiceConnections.size() == 0) { final VirtualDeviceManagerInternal localVdm = getLocalVdm(); if (localVdm != null && mAppsOnVirtualDeviceListener != null) { localVdm.unregisterAppsOnVirtualDeviceListener( mAppsOnVirtualDeviceListener); mAppsOnVirtualDeviceListener = null; } } } mSystemSupport.removeDeviceIdLocked(deviceId); mLastStates.delete(deviceId); } Loading @@ -307,7 +332,7 @@ public class ProxyManager { * Returns {@code true} if {@code deviceId} is being proxy-ed. */ public boolean isProxyedDeviceId(int deviceId) { if (deviceId == DEVICE_ID_DEFAULT && deviceId == DEVICE_ID_INVALID) { if (deviceId == DEVICE_ID_DEFAULT || deviceId == DEVICE_ID_INVALID) { return false; } boolean isTrackingDeviceId; Loading Loading @@ -566,7 +591,7 @@ public class ProxyManager { * This is similar to onUserStateChangeLocked and onClientChangeLocked, but does not require an * A11yUserState and only checks proxy-relevant settings. */ public void onProxyChanged(int deviceId) { private void onProxyChanged(int deviceId, boolean forceUpdate) { if (DEBUG) { Slog.v(LOG_TAG, "onProxyChanged called for deviceId: " + deviceId); } Loading @@ -584,7 +609,7 @@ public class ProxyManager { // Calls A11yManager#setRelevantEventTypes (test these) updateRelevantEventTypesLocked(deviceId); // Calls A11yManager#setState scheduleUpdateProxyClientsIfNeededLocked(deviceId); scheduleUpdateProxyClientsIfNeededLocked(deviceId, forceUpdate); //Calls A11yManager#notifyServicesStateChanged(timeout) scheduleNotifyProxyClientsOfServicesStateChangeLocked(deviceId); // Calls A11yManager#setFocusAppearance Loading @@ -593,17 +618,26 @@ public class ProxyManager { } } /** * Handles proxy changes, but does not force an update of app clients. */ public void onProxyChanged(int deviceId) { onProxyChanged(deviceId, false); } /** * Updates the states of the app AccessibilityManagers. */ private void scheduleUpdateProxyClientsIfNeededLocked(int deviceId) { private void scheduleUpdateProxyClientsIfNeededLocked(int deviceId, boolean forceUpdate) { final int proxyState = getStateLocked(deviceId); if (DEBUG) { Slog.v(LOG_TAG, "State for device id " + deviceId + " is " + proxyState); Slog.v(LOG_TAG, "Last state for device id " + deviceId + " is " + getLastSentStateLocked(deviceId)); Slog.v(LOG_TAG, "force update: " + forceUpdate); } if ((getLastSentStateLocked(deviceId)) != proxyState) { if ((getLastSentStateLocked(deviceId)) != proxyState || (Flags.proxyUseAppsOnVirtualDeviceListener() && forceUpdate)) { setLastStateLocked(deviceId, proxyState); mMainHandler.post(() -> { synchronized (mLock) { Loading Loading @@ -792,7 +826,7 @@ public class ProxyManager { } /** * Updates the device ids of IAccessibilityManagerClients if needed. * Updates the device ids of IAccessibilityManagerClients if needed after a proxy change. */ private void updateDeviceIdsIfNeededLocked(int deviceId, @NonNull RemoteCallbackList<IAccessibilityManagerClient> clients) { Loading @@ -804,6 +838,26 @@ public class ProxyManager { for (int i = 0; i < clients.getRegisteredCallbackCount(); i++) { final AccessibilityManagerService.Client client = ((AccessibilityManagerService.Client) clients.getRegisteredCallbackCookie(i)); if (Flags.proxyUseAppsOnVirtualDeviceListener()) { if (deviceId == DEVICE_ID_DEFAULT || deviceId == DEVICE_ID_INVALID) { continue; } boolean uidBelongsToDevice = localVdm.getDeviceIdsForUid(client.mUid).contains(deviceId); if (client.mDeviceId != deviceId && uidBelongsToDevice) { if (DEBUG) { Slog.v(LOG_TAG, "Packages moved to device id " + deviceId + " are " + Arrays.toString(client.mPackageNames)); } client.mDeviceId = deviceId; } else if (client.mDeviceId == deviceId && !uidBelongsToDevice) { client.mDeviceId = DEVICE_ID_DEFAULT; if (DEBUG) { Slog.v(LOG_TAG, "Packages moved to the default device from device id " + deviceId + " are " + Arrays.toString(client.mPackageNames)); } } } else { if (deviceId != DEVICE_ID_DEFAULT && deviceId != DEVICE_ID_INVALID && localVdm.getDeviceIdsForUid(client.mUid).contains(deviceId)) { if (DEBUG) { Loading @@ -814,6 +868,39 @@ public class ProxyManager { } } } } @VisibleForTesting void notifyProxyOfRunningAppsChange(Set<Integer> allRunningUids) { if (DEBUG) { Slog.v(LOG_TAG, "notifyProxyOfRunningAppsChange: " + allRunningUids); } synchronized (mLock) { if (mProxyA11yServiceConnections.size() == 0) { return; } final VirtualDeviceManagerInternal localVdm = getLocalVdm(); if (localVdm == null) { return; } final ArraySet<Integer> deviceIdsToUpdate = new ArraySet<>(); for (int i = 0; i < mProxyA11yServiceConnections.size(); i++) { final ProxyAccessibilityServiceConnection proxy = mProxyA11yServiceConnections.valueAt(i); if (proxy != null) { final int proxyDeviceId = proxy.getDeviceId(); for (Integer uid : allRunningUids) { if (localVdm.getDeviceIdsForUid(uid).contains(proxyDeviceId)) { deviceIdsToUpdate.add(proxyDeviceId); } } } } for (Integer proxyDeviceId : deviceIdsToUpdate) { onProxyChanged(proxyDeviceId, true); } } } /** * Clears all proxy caches. Loading Loading @@ -843,6 +930,11 @@ public class ProxyManager { return mLocalVdm; } @VisibleForTesting void setLocalVirtualDeviceManager(VirtualDeviceManagerInternal localVdm) { mLocalVdm = localVdm; } /** * Prints information belonging to each display that is controlled by an * AccessibilityDisplayProxy. Loading services/tests/servicestests/src/com/android/server/accessibility/ProxyManagerTest.java +51 −10 Original line number Diff line number Diff line Loading @@ -23,7 +23,14 @@ import static com.android.server.accessibility.ProxyAccessibilityServiceConnecti import static com.android.server.accessibility.ProxyManager.PROXY_COMPONENT_CLASS_NAME; import static com.android.server.accessibility.ProxyManager.PROXY_COMPONENT_PACKAGE_NAME; import static com.google.common.truth.Truth.assertThat; 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.verify; import static org.mockito.Mockito.when; import android.accessibilityservice.AccessibilityGestureEvent; import android.accessibilityservice.AccessibilityServiceInfo; Loading @@ -40,6 +47,7 @@ import android.graphics.Region; import android.os.IBinder; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.platform.test.flag.junit.SetFlagsRule; import android.util.ArraySet; import android.view.KeyEvent; import android.view.MotionEvent; Loading @@ -48,6 +56,8 @@ import android.view.accessibility.AccessibilityManager; import android.view.accessibility.IAccessibilityManagerClient; import android.view.inputmethod.EditorInfo; import androidx.test.InstrumentationRegistry; import com.android.internal.R; import com.android.internal.inputmethod.IAccessibilityInputMethodSession; import com.android.internal.inputmethod.IAccessibilityInputMethodSessionCallback; Loading @@ -58,20 +68,12 @@ import com.android.server.accessibility.test.MessageCapturingHandler; import com.android.server.companion.virtual.VirtualDeviceManagerInternal; import com.android.server.wm.WindowManagerInternal; import static com.google.common.truth.Truth.assertThat; import androidx.test.InstrumentationRegistry; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import java.util.ArrayList; Loading @@ -87,6 +89,10 @@ public class ProxyManagerTest { private static final int DEVICE_ID = 10; private static final int STREAMED_CALLING_UID = 9876; @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); @Mock private Context mMockContext; @Mock private AccessibilitySecurityPolicy mMockSecurityPolicy; @Mock private AccessibilityWindowManager mMockA11yWindowManager; Loading @@ -110,6 +116,8 @@ public class ProxyManagerTest { MockitoAnnotations.initMocks(this); final Resources resources = InstrumentationRegistry.getContext().getResources(); mSetFlagsRule.enableFlags(Flags.FLAG_PROXY_USE_APPS_ON_VIRTUAL_DEVICE_LISTENER); mFocusStrokeWidthDefaultValue = resources.getDimensionPixelSize(R.dimen.accessibility_focus_highlight_stroke_width); mFocusColorDefaultValue = resources.getColor(R.color.accessibility_focus_highlight_color); Loading Loading @@ -217,6 +225,39 @@ public class ProxyManagerTest { verify(mMockProxySystemSupport).notifyClearAccessibilityCacheLocked(); } /** * Tests that the manager's AppsOnVirtualDeviceListener implementation propagates the running * app changes to the proxy device. */ @Test public void testUpdateProxyOfRunningAppsChange_changedUidIsStreamedApp_propagatesChange() { final VirtualDeviceManagerInternal localVdm = Mockito.mock(VirtualDeviceManagerInternal.class); when(localVdm.getDeviceIdsForUid(anyInt())).thenReturn(new ArraySet(Set.of(DEVICE_ID))); mProxyManager.setLocalVirtualDeviceManager(localVdm); registerProxy(DISPLAY_ID); verify(localVdm).registerAppsOnVirtualDeviceListener(any()); final ArraySet<Integer> runningUids = new ArraySet(Set.of(STREAMED_CALLING_UID)); // Flush any existing messages. The messages after this come from onProxyChanged. mMessageCapturingHandler.sendAllMessages(); // The virtual device has been updated with the streamed app's UID, so the proxy is // updated. mProxyManager.notifyProxyOfRunningAppsChange(runningUids); verify(localVdm).getDeviceIdsForUid(STREAMED_CALLING_UID); verify(mMockProxySystemSupport).getCurrentUserClientsLocked(); verify(mMockProxySystemSupport).getGlobalClientsLocked(); // Messages to notify IAccessibilityManagerClients should be posted. assertThat(mMessageCapturingHandler.hasMessages()).isTrue(); mProxyManager.unregisterProxy(DISPLAY_ID); verify(localVdm).unregisterAppsOnVirtualDeviceListener(any()); } /** * Tests that getting the first device id for an app uid, such as when an app queries for * device-specific state, returns the right device id. Loading Loading
services/accessibility/Android.bp +16 −0 Original line number Diff line number Diff line Loading @@ -27,4 +27,20 @@ java_library_static { "services.core", "androidx.annotation_annotation", ], static_libs: [ "com_android_server_accessibility_flags_lib", ], } aconfig_declarations { name: "com_android_server_accessibility_flags", package: "com.android.server.accessibility", srcs: [ "accessibility.aconfig", ], } java_aconfig_library { name: "com_android_server_accessibility_flags_lib", aconfig_declarations: "com_android_server_accessibility_flags", }
services/accessibility/accessibility.aconfig 0 → 100644 +7 −0 Original line number Diff line number Diff line package: "com.android.server.accessibility" flag { name: "proxy_use_apps_on_virtual_device_listener" namespace: "accessibility" description: "Fixes race condition described in b/286587811" bug: "286587811" }
services/accessibility/java/com/android/server/accessibility/ProxyManager.java +104 −12 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ import android.os.Handler; import android.os.IBinder; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.util.ArraySet; import android.util.IntArray; import android.util.Slog; import android.util.SparseArray; Loading @@ -42,6 +43,7 @@ import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; import android.view.accessibility.IAccessibilityManagerClient; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.IntPair; import com.android.server.LocalServices; import com.android.server.companion.virtual.VirtualDeviceManagerInternal; Loading Loading @@ -96,6 +98,9 @@ public class ProxyManager { private final SystemSupport mSystemSupport; private VirtualDeviceManagerInternal.AppsOnVirtualDeviceListener mAppsOnVirtualDeviceListener; /** * Callbacks into AccessibilityManagerService. */ Loading Loading @@ -174,6 +179,16 @@ public class ProxyManager { synchronized (mLock) { mProxyA11yServiceConnections.put(displayId, connection); if (Flags.proxyUseAppsOnVirtualDeviceListener()) { if (mAppsOnVirtualDeviceListener == null) { mAppsOnVirtualDeviceListener = allRunningUids -> notifyProxyOfRunningAppsChange(allRunningUids); final VirtualDeviceManagerInternal localVdm = getLocalVdm(); if (localVdm != null) { localVdm.registerAppsOnVirtualDeviceListener(mAppsOnVirtualDeviceListener); } } } } // If the client dies, make sure to remove the connection. Loading Loading @@ -276,11 +291,21 @@ public class ProxyManager { } } }); // If there isn't an existing proxy for the device id, reset clients. Resetting // If there isn't an existing proxy for the device id, reset app clients. Resetting // will usually happen, since in most cases there will only be one proxy for a // device. if (!isProxyedDeviceId(deviceId)) { synchronized (mLock) { if (Flags.proxyUseAppsOnVirtualDeviceListener()) { if (mProxyA11yServiceConnections.size() == 0) { final VirtualDeviceManagerInternal localVdm = getLocalVdm(); if (localVdm != null && mAppsOnVirtualDeviceListener != null) { localVdm.unregisterAppsOnVirtualDeviceListener( mAppsOnVirtualDeviceListener); mAppsOnVirtualDeviceListener = null; } } } mSystemSupport.removeDeviceIdLocked(deviceId); mLastStates.delete(deviceId); } Loading @@ -307,7 +332,7 @@ public class ProxyManager { * Returns {@code true} if {@code deviceId} is being proxy-ed. */ public boolean isProxyedDeviceId(int deviceId) { if (deviceId == DEVICE_ID_DEFAULT && deviceId == DEVICE_ID_INVALID) { if (deviceId == DEVICE_ID_DEFAULT || deviceId == DEVICE_ID_INVALID) { return false; } boolean isTrackingDeviceId; Loading Loading @@ -566,7 +591,7 @@ public class ProxyManager { * This is similar to onUserStateChangeLocked and onClientChangeLocked, but does not require an * A11yUserState and only checks proxy-relevant settings. */ public void onProxyChanged(int deviceId) { private void onProxyChanged(int deviceId, boolean forceUpdate) { if (DEBUG) { Slog.v(LOG_TAG, "onProxyChanged called for deviceId: " + deviceId); } Loading @@ -584,7 +609,7 @@ public class ProxyManager { // Calls A11yManager#setRelevantEventTypes (test these) updateRelevantEventTypesLocked(deviceId); // Calls A11yManager#setState scheduleUpdateProxyClientsIfNeededLocked(deviceId); scheduleUpdateProxyClientsIfNeededLocked(deviceId, forceUpdate); //Calls A11yManager#notifyServicesStateChanged(timeout) scheduleNotifyProxyClientsOfServicesStateChangeLocked(deviceId); // Calls A11yManager#setFocusAppearance Loading @@ -593,17 +618,26 @@ public class ProxyManager { } } /** * Handles proxy changes, but does not force an update of app clients. */ public void onProxyChanged(int deviceId) { onProxyChanged(deviceId, false); } /** * Updates the states of the app AccessibilityManagers. */ private void scheduleUpdateProxyClientsIfNeededLocked(int deviceId) { private void scheduleUpdateProxyClientsIfNeededLocked(int deviceId, boolean forceUpdate) { final int proxyState = getStateLocked(deviceId); if (DEBUG) { Slog.v(LOG_TAG, "State for device id " + deviceId + " is " + proxyState); Slog.v(LOG_TAG, "Last state for device id " + deviceId + " is " + getLastSentStateLocked(deviceId)); Slog.v(LOG_TAG, "force update: " + forceUpdate); } if ((getLastSentStateLocked(deviceId)) != proxyState) { if ((getLastSentStateLocked(deviceId)) != proxyState || (Flags.proxyUseAppsOnVirtualDeviceListener() && forceUpdate)) { setLastStateLocked(deviceId, proxyState); mMainHandler.post(() -> { synchronized (mLock) { Loading Loading @@ -792,7 +826,7 @@ public class ProxyManager { } /** * Updates the device ids of IAccessibilityManagerClients if needed. * Updates the device ids of IAccessibilityManagerClients if needed after a proxy change. */ private void updateDeviceIdsIfNeededLocked(int deviceId, @NonNull RemoteCallbackList<IAccessibilityManagerClient> clients) { Loading @@ -804,6 +838,26 @@ public class ProxyManager { for (int i = 0; i < clients.getRegisteredCallbackCount(); i++) { final AccessibilityManagerService.Client client = ((AccessibilityManagerService.Client) clients.getRegisteredCallbackCookie(i)); if (Flags.proxyUseAppsOnVirtualDeviceListener()) { if (deviceId == DEVICE_ID_DEFAULT || deviceId == DEVICE_ID_INVALID) { continue; } boolean uidBelongsToDevice = localVdm.getDeviceIdsForUid(client.mUid).contains(deviceId); if (client.mDeviceId != deviceId && uidBelongsToDevice) { if (DEBUG) { Slog.v(LOG_TAG, "Packages moved to device id " + deviceId + " are " + Arrays.toString(client.mPackageNames)); } client.mDeviceId = deviceId; } else if (client.mDeviceId == deviceId && !uidBelongsToDevice) { client.mDeviceId = DEVICE_ID_DEFAULT; if (DEBUG) { Slog.v(LOG_TAG, "Packages moved to the default device from device id " + deviceId + " are " + Arrays.toString(client.mPackageNames)); } } } else { if (deviceId != DEVICE_ID_DEFAULT && deviceId != DEVICE_ID_INVALID && localVdm.getDeviceIdsForUid(client.mUid).contains(deviceId)) { if (DEBUG) { Loading @@ -814,6 +868,39 @@ public class ProxyManager { } } } } @VisibleForTesting void notifyProxyOfRunningAppsChange(Set<Integer> allRunningUids) { if (DEBUG) { Slog.v(LOG_TAG, "notifyProxyOfRunningAppsChange: " + allRunningUids); } synchronized (mLock) { if (mProxyA11yServiceConnections.size() == 0) { return; } final VirtualDeviceManagerInternal localVdm = getLocalVdm(); if (localVdm == null) { return; } final ArraySet<Integer> deviceIdsToUpdate = new ArraySet<>(); for (int i = 0; i < mProxyA11yServiceConnections.size(); i++) { final ProxyAccessibilityServiceConnection proxy = mProxyA11yServiceConnections.valueAt(i); if (proxy != null) { final int proxyDeviceId = proxy.getDeviceId(); for (Integer uid : allRunningUids) { if (localVdm.getDeviceIdsForUid(uid).contains(proxyDeviceId)) { deviceIdsToUpdate.add(proxyDeviceId); } } } } for (Integer proxyDeviceId : deviceIdsToUpdate) { onProxyChanged(proxyDeviceId, true); } } } /** * Clears all proxy caches. Loading Loading @@ -843,6 +930,11 @@ public class ProxyManager { return mLocalVdm; } @VisibleForTesting void setLocalVirtualDeviceManager(VirtualDeviceManagerInternal localVdm) { mLocalVdm = localVdm; } /** * Prints information belonging to each display that is controlled by an * AccessibilityDisplayProxy. Loading
services/tests/servicestests/src/com/android/server/accessibility/ProxyManagerTest.java +51 −10 Original line number Diff line number Diff line Loading @@ -23,7 +23,14 @@ import static com.android.server.accessibility.ProxyAccessibilityServiceConnecti import static com.android.server.accessibility.ProxyManager.PROXY_COMPONENT_CLASS_NAME; import static com.android.server.accessibility.ProxyManager.PROXY_COMPONENT_PACKAGE_NAME; import static com.google.common.truth.Truth.assertThat; 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.verify; import static org.mockito.Mockito.when; import android.accessibilityservice.AccessibilityGestureEvent; import android.accessibilityservice.AccessibilityServiceInfo; Loading @@ -40,6 +47,7 @@ import android.graphics.Region; import android.os.IBinder; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.platform.test.flag.junit.SetFlagsRule; import android.util.ArraySet; import android.view.KeyEvent; import android.view.MotionEvent; Loading @@ -48,6 +56,8 @@ import android.view.accessibility.AccessibilityManager; import android.view.accessibility.IAccessibilityManagerClient; import android.view.inputmethod.EditorInfo; import androidx.test.InstrumentationRegistry; import com.android.internal.R; import com.android.internal.inputmethod.IAccessibilityInputMethodSession; import com.android.internal.inputmethod.IAccessibilityInputMethodSessionCallback; Loading @@ -58,20 +68,12 @@ import com.android.server.accessibility.test.MessageCapturingHandler; import com.android.server.companion.virtual.VirtualDeviceManagerInternal; import com.android.server.wm.WindowManagerInternal; import static com.google.common.truth.Truth.assertThat; import androidx.test.InstrumentationRegistry; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import java.util.ArrayList; Loading @@ -87,6 +89,10 @@ public class ProxyManagerTest { private static final int DEVICE_ID = 10; private static final int STREAMED_CALLING_UID = 9876; @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); @Mock private Context mMockContext; @Mock private AccessibilitySecurityPolicy mMockSecurityPolicy; @Mock private AccessibilityWindowManager mMockA11yWindowManager; Loading @@ -110,6 +116,8 @@ public class ProxyManagerTest { MockitoAnnotations.initMocks(this); final Resources resources = InstrumentationRegistry.getContext().getResources(); mSetFlagsRule.enableFlags(Flags.FLAG_PROXY_USE_APPS_ON_VIRTUAL_DEVICE_LISTENER); mFocusStrokeWidthDefaultValue = resources.getDimensionPixelSize(R.dimen.accessibility_focus_highlight_stroke_width); mFocusColorDefaultValue = resources.getColor(R.color.accessibility_focus_highlight_color); Loading Loading @@ -217,6 +225,39 @@ public class ProxyManagerTest { verify(mMockProxySystemSupport).notifyClearAccessibilityCacheLocked(); } /** * Tests that the manager's AppsOnVirtualDeviceListener implementation propagates the running * app changes to the proxy device. */ @Test public void testUpdateProxyOfRunningAppsChange_changedUidIsStreamedApp_propagatesChange() { final VirtualDeviceManagerInternal localVdm = Mockito.mock(VirtualDeviceManagerInternal.class); when(localVdm.getDeviceIdsForUid(anyInt())).thenReturn(new ArraySet(Set.of(DEVICE_ID))); mProxyManager.setLocalVirtualDeviceManager(localVdm); registerProxy(DISPLAY_ID); verify(localVdm).registerAppsOnVirtualDeviceListener(any()); final ArraySet<Integer> runningUids = new ArraySet(Set.of(STREAMED_CALLING_UID)); // Flush any existing messages. The messages after this come from onProxyChanged. mMessageCapturingHandler.sendAllMessages(); // The virtual device has been updated with the streamed app's UID, so the proxy is // updated. mProxyManager.notifyProxyOfRunningAppsChange(runningUids); verify(localVdm).getDeviceIdsForUid(STREAMED_CALLING_UID); verify(mMockProxySystemSupport).getCurrentUserClientsLocked(); verify(mMockProxySystemSupport).getGlobalClientsLocked(); // Messages to notify IAccessibilityManagerClients should be posted. assertThat(mMessageCapturingHandler.hasMessages()).isTrue(); mProxyManager.unregisterProxy(DISPLAY_ID); verify(localVdm).unregisterAppsOnVirtualDeviceListener(any()); } /** * Tests that getting the first device id for an app uid, such as when an app queries for * device-specific state, returns the right device id. Loading