Loading services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java +116 −6 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ import android.os.IBinder; import android.os.Process; import android.os.RemoteException; import android.os.UserHandle; import android.text.TextUtils; import android.util.Slog; import android.util.SparseArray; import android.view.IWindow; Loading Loading @@ -83,6 +84,7 @@ public class AccessibilityWindowManager mInteractionConnections = new SparseArray<>(); private final SparseArray<SparseArray<IBinder>> mWindowTokens = new SparseArray<>(); private final List<WindowInfo> mCachedWindowInfos = new ArrayList<>(); private List<AccessibilityWindowInfo> mWindows; private RemoteAccessibilityConnection mPictureInPictureActionReplacingConnection; Loading Loading @@ -173,24 +175,132 @@ public class AccessibilityWindowManager } /** * Callbacks from from window manager when there's an accessibility change in windows. * Callbacks from window manager when there's an accessibility change in windows. * * @param forceSend Send the windows for accessibility even if they haven't changed. * @param windows The windows of current display for accessibility. */ @Override public void onWindowsForAccessibilityChanged(@NonNull List<WindowInfo> windows) { public void onWindowsForAccessibilityChanged(boolean forceSend, @NonNull List<WindowInfo> windows) { synchronized (mLock) { if (DEBUG) { Slog.i(LOG_TAG, "Windows changed: " + windows); } if (shouldUpdateWindowsLocked(forceSend, windows)) { cacheWindows(windows); // Let the policy update the focused and active windows. updateWindowsLocked(mAccessibilityUserManager.getCurrentUserIdLocked(), windows); // Someone may be waiting for the windows - advertise it. mLock.notifyAll(); } } } private boolean shouldUpdateWindowsLocked(boolean forceSend, @NonNull List<WindowInfo> windows) { if (forceSend) { return true; } final int windowCount = windows.size(); // We computed the windows and if they changed notify the client. if (mCachedWindowInfos.size() != windowCount) { // Different size means something changed. return true; } else if (!mCachedWindowInfos.isEmpty() || !windows.isEmpty()) { // Since we always traverse windows from high to low layer // the old and new windows at the same index should be the // same, otherwise something changed. for (int i = 0; i < windowCount; i++) { WindowInfo oldWindow = mCachedWindowInfos.get(i); WindowInfo newWindow = windows.get(i); // We do not care for layer changes given the window // order does not change. This brings no new information // to the clients. if (windowChangedNoLayer(oldWindow, newWindow)) { return true; } } } return false; } private void cacheWindows(List<WindowInfo> windows) { final int oldWindowCount = mCachedWindowInfos.size(); for (int i = oldWindowCount - 1; i >= 0; i--) { mCachedWindowInfos.remove(i).recycle(); } final int newWindowCount = windows.size(); for (int i = 0; i < newWindowCount; i++) { WindowInfo newWindow = windows.get(i); mCachedWindowInfos.add(WindowInfo.obtain(newWindow)); } } private boolean windowChangedNoLayer(WindowInfo oldWindow, WindowInfo newWindow) { if (oldWindow == newWindow) { return false; } if (oldWindow == null) { return true; } if (newWindow == null) { return true; } if (oldWindow.type != newWindow.type) { return true; } if (oldWindow.focused != newWindow.focused) { return true; } if (oldWindow.token == null) { if (newWindow.token != null) { return true; } } else if (!oldWindow.token.equals(newWindow.token)) { return true; } if (oldWindow.parentToken == null) { if (newWindow.parentToken != null) { return true; } } else if (!oldWindow.parentToken.equals(newWindow.parentToken)) { return true; } if (oldWindow.activityToken == null) { if (newWindow.activityToken != null) { return true; } } else if (!oldWindow.activityToken.equals(newWindow.activityToken)) { return true; } if (!oldWindow.boundsInScreen.equals(newWindow.boundsInScreen)) { return true; } if (oldWindow.childTokens != null && newWindow.childTokens != null && !oldWindow.childTokens.equals(newWindow.childTokens)) { return true; } if (!TextUtils.equals(oldWindow.title, newWindow.title)) { return true; } if (oldWindow.accessibilityIdOfAnchor != newWindow.accessibilityIdOfAnchor) { return true; } if (oldWindow.inPictureInPicture != newWindow.inPictureInPicture) { return true; } if (oldWindow.hasFlagWatchOutsideTouch != newWindow.hasFlagWatchOutsideTouch) { return true; } if (oldWindow.displayId != newWindow.displayId) { return true; } return false; } /** * Start tracking windows changes from window manager. Loading services/core/java/com/android/server/wm/AccessibilityController.java +4 −108 Original line number Diff line number Diff line Loading @@ -43,9 +43,7 @@ import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.Message; import android.text.TextUtils; import android.util.ArraySet; import android.util.Log; import android.util.Slog; import android.util.SparseArray; import android.util.TypedValue; Loading Loading @@ -1036,12 +1034,9 @@ final class AccessibilityController { private static final boolean DEBUG = false; private final SparseArray<WindowState> mTempWindowStates = new SparseArray<WindowState>(); private final SparseArray<WindowState> mTempWindowStates = new SparseArray<>(); private final List<WindowInfo> mOldWindows = new ArrayList<WindowInfo>(); private final Set<IBinder> mTempBinderSet = new ArraySet<IBinder>(); private final Set<IBinder> mTempBinderSet = new ArraySet<>(); private final RectF mTempRectF = new RectF(); Loading Loading @@ -1098,8 +1093,7 @@ final class AccessibilityController { Slog.i(LOG_TAG, "computeChangedWindows()"); } boolean windowsChanged = false; List<WindowInfo> windows = new ArrayList<WindowInfo>(); List<WindowInfo> windows = new ArrayList<>(); synchronized (mService.mGlobalLock) { // Do not send the windows if there is no current focus as Loading Loading @@ -1169,46 +1163,9 @@ final class AccessibilityController { visibleWindows.clear(); addedWindows.clear(); if (!forceSend) { // We computed the windows and if they changed notify the client. if (mOldWindows.size() != windows.size()) { // Different size means something changed. windowsChanged = true; } else if (!mOldWindows.isEmpty() || !windows.isEmpty()) { // Since we always traverse windows from high to low layer // the old and new windows at the same index should be the // same, otherwise something changed. for (int i = 0; i < windowCount; i++) { WindowInfo oldWindow = mOldWindows.get(i); WindowInfo newWindow = windows.get(i); // We do not care for layer changes given the window // order does not change. This brings no new information // to the clients. if (windowChangedNoLayer(oldWindow, newWindow)) { windowsChanged = true; break; } } } } if (forceSend || windowsChanged) { cacheWindows(windows); } } // Now we do not hold the lock, so send the windows over. if (forceSend || windowsChanged) { if (DEBUG) { Log.i(LOG_TAG, "Windows changed or force sending:" + windows); } mCallback.onWindowsForAccessibilityChanged(windows); } else { if (DEBUG) { Log.i(LOG_TAG, "No windows changed."); } } mCallback.onWindowsForAccessibilityChanged(forceSend, windows); // Recycle the windows as we do not need them. clearAndRecycleWindows(windows); Loading Loading @@ -1313,67 +1270,6 @@ final class AccessibilityController { tokenOut.add(window.token); } private void cacheWindows(List<WindowInfo> windows) { final int oldWindowCount = mOldWindows.size(); for (int i = oldWindowCount - 1; i >= 0; i--) { mOldWindows.remove(i).recycle(); } final int newWindowCount = windows.size(); for (int i = 0; i < newWindowCount; i++) { WindowInfo newWindow = windows.get(i); mOldWindows.add(WindowInfo.obtain(newWindow)); } } private boolean windowChangedNoLayer(WindowInfo oldWindow, WindowInfo newWindow) { if (oldWindow == newWindow) { return false; } if (oldWindow == null) { return true; } if (newWindow == null) { return true; } if (oldWindow.type != newWindow.type) { return true; } if (oldWindow.focused != newWindow.focused) { return true; } if (oldWindow.token == null) { if (newWindow.token != null) { return true; } } else if (!oldWindow.token.equals(newWindow.token)) { return true; } if (oldWindow.parentToken == null) { if (newWindow.parentToken != null) { return true; } } else if (!oldWindow.parentToken.equals(newWindow.parentToken)) { return true; } if (!oldWindow.boundsInScreen.equals(newWindow.boundsInScreen)) { return true; } if (oldWindow.childTokens != null && newWindow.childTokens != null && !oldWindow.childTokens.equals(newWindow.childTokens)) { return true; } if (!TextUtils.equals(oldWindow.title, newWindow.title)) { return true; } if (oldWindow.accessibilityIdOfAnchor != newWindow.accessibilityIdOfAnchor) { return true; } if (oldWindow.displayId != newWindow.displayId) { return true; } return false; } private static void clearAndRecycleWindows(List<WindowInfo> windows) { final int windowCount = windows.size(); for (int i = windowCount - 1; i >= 0; i--) { Loading services/core/java/com/android/server/wm/WindowManagerInternal.java +2 −1 Original line number Diff line number Diff line Loading @@ -51,9 +51,10 @@ public abstract class WindowManagerInternal { /** * Called when the windows for accessibility changed. * * @param forceSend Send the windows for accessibility even if they haven't changed. * @param windows The windows for accessibility. */ public void onWindowsForAccessibilityChanged(List<WindowInfo> windows); void onWindowsForAccessibilityChanged(boolean forceSend, List<WindowInfo> windows); } /** Loading services/tests/servicestests/src/com/android/server/accessibility/AccessibilityWindowManagerTest.java +60 −12 Original line number Diff line number Diff line Loading @@ -70,6 +70,8 @@ import java.util.List; */ public class AccessibilityWindowManagerTest { private static final String PACKAGE_NAME = "com.android.server.accessibility"; private static final boolean FORCE_SEND = true; private static final boolean SEND_ON_WINDOW_CHANGES = false; private static final int USER_SYSTEM_ID = UserHandle.USER_SYSTEM; private static final int NUM_GLOBAL_WINDOWS = 4; private static final int NUM_APP_WINDOWS = 4; Loading Loading @@ -122,7 +124,7 @@ public class AccessibilityWindowManagerTest { mWindowInfos.get(DEFAULT_FOCUSED_INDEX).focused = true; // Turn on windows tracking, and update window info mA11yWindowManager.startTrackingWindows(); mA11yWindowManager.onWindowsForAccessibilityChanged(mWindowInfos); mA11yWindowManager.onWindowsForAccessibilityChanged(FORCE_SEND, mWindowInfos); assertEquals(mA11yWindowManager.getWindowListLocked().size(), mWindowInfos.size()); Loading Loading @@ -169,16 +171,16 @@ public class AccessibilityWindowManagerTest { @Test public void onWindowsChanged_duringTouchInteractAndFocusChange_shouldChangeActiveWindow() { final int activeWindowId = mA11yWindowManager.getActiveWindowId(USER_SYSTEM_ID); WindowInfo focuedWindowInfo = mWindowInfos.get(DEFAULT_FOCUSED_INDEX); WindowInfo focusedWindowInfo = mWindowInfos.get(DEFAULT_FOCUSED_INDEX); assertEquals(activeWindowId, mA11yWindowManager.findWindowIdLocked( USER_SYSTEM_ID, focuedWindowInfo.token)); USER_SYSTEM_ID, focusedWindowInfo.token)); focuedWindowInfo.focused = false; focuedWindowInfo = mWindowInfos.get(DEFAULT_FOCUSED_INDEX + 1); focuedWindowInfo.focused = true; focusedWindowInfo.focused = false; focusedWindowInfo = mWindowInfos.get(DEFAULT_FOCUSED_INDEX + 1); focusedWindowInfo.focused = true; mA11yWindowManager.onTouchInteractionStart(); mA11yWindowManager.onWindowsForAccessibilityChanged(mWindowInfos); mA11yWindowManager.onWindowsForAccessibilityChanged(SEND_ON_WINDOW_CHANGES, mWindowInfos); assertNotEquals(activeWindowId, mA11yWindowManager.getActiveWindowId(USER_SYSTEM_ID)); } Loading Loading @@ -207,6 +209,52 @@ public class AccessibilityWindowManagerTest { } } @Test public void onWindowsChangedAndForceSend_shouldUpdateWindows() { final WindowInfo windowInfo = mWindowInfos.get(0); final int correctLayer = mA11yWindowManager.getWindowListLocked().get(0).getLayer(); windowInfo.layer += 1; mA11yWindowManager.onWindowsForAccessibilityChanged(FORCE_SEND, mWindowInfos); assertNotEquals(correctLayer, mA11yWindowManager.getWindowListLocked().get(0).getLayer()); } @Test public void onWindowsChangedNoForceSend_layerChanged_shouldNotUpdateWindows() { final WindowInfo windowInfo = mWindowInfos.get(0); final int correctLayer = mA11yWindowManager.getWindowListLocked().get(0).getLayer(); windowInfo.layer += 1; mA11yWindowManager.onWindowsForAccessibilityChanged(SEND_ON_WINDOW_CHANGES, mWindowInfos); assertEquals(correctLayer, mA11yWindowManager.getWindowListLocked().get(0).getLayer()); } @Test public void onWindowsChangedNoForceSend_windowChanged_shouldUpdateWindows() throws RemoteException { final AccessibilityWindowInfo oldWindow = mA11yWindowManager.getWindowListLocked().get(0); final IWindow token = addAccessibilityInteractionConnection(true); final WindowInfo windowInfo = WindowInfo.obtain(); windowInfo.type = AccessibilityWindowInfo.TYPE_APPLICATION; windowInfo.token = token.asBinder(); windowInfo.layer = 0; windowInfo.boundsInScreen.set(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); mWindowInfos.set(0, windowInfo); mA11yWindowManager.onWindowsForAccessibilityChanged(SEND_ON_WINDOW_CHANGES, mWindowInfos); assertNotEquals(oldWindow, mA11yWindowManager.getWindowListLocked().get(0)); } @Test public void onWindowsChangedNoForceSend_focusChanged_shouldUpdateWindows() { final WindowInfo focusedWindowInfo = mWindowInfos.get(DEFAULT_FOCUSED_INDEX); final WindowInfo windowInfo = mWindowInfos.get(0); focusedWindowInfo.focused = false; windowInfo.focused = true; mA11yWindowManager.onWindowsForAccessibilityChanged(SEND_ON_WINDOW_CHANGES, mWindowInfos); assertTrue(mA11yWindowManager.getWindowListLocked().get(0).isFocused()); } @Test public void removeAccessibilityInteractionConnection_byWindowToken_shouldRemoved() { for (int i = 0; i < NUM_OF_WINDOWS; i++) { Loading Loading @@ -264,7 +312,7 @@ public class AccessibilityWindowManagerTest { windowInfo = mWindowInfos.get(1); windowInfo.boundsInScreen.set(0, SCREEN_HEIGHT / 2, SCREEN_WIDTH, SCREEN_HEIGHT); mA11yWindowManager.onWindowsForAccessibilityChanged(mWindowInfos); mA11yWindowManager.onWindowsForAccessibilityChanged(SEND_ON_WINDOW_CHANGES, mWindowInfos); final List<AccessibilityWindowInfo> a11yWindows = mA11yWindowManager.getWindowListLocked(); final Region outBounds = new Region(); Loading @@ -291,7 +339,7 @@ public class AccessibilityWindowManagerTest { windowInfo = mWindowInfos.get(1); windowInfo.boundsInScreen.set(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); mA11yWindowManager.onWindowsForAccessibilityChanged(mWindowInfos); mA11yWindowManager.onWindowsForAccessibilityChanged(SEND_ON_WINDOW_CHANGES, mWindowInfos); final List<AccessibilityWindowInfo> a11yWindows = mA11yWindowManager.getWindowListLocked(); final Region outBounds = new Region(); int windowId = a11yWindows.get(1).getId(); Loading @@ -309,7 +357,7 @@ public class AccessibilityWindowManagerTest { windowInfo.boundsInScreen.set(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); windowInfo = mWindowInfos.get(1); windowInfo.boundsInScreen.set(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); mA11yWindowManager.onWindowsForAccessibilityChanged(mWindowInfos); mA11yWindowManager.onWindowsForAccessibilityChanged(SEND_ON_WINDOW_CHANGES, mWindowInfos); final List<AccessibilityWindowInfo> a11yWindows = mA11yWindowManager.getWindowListLocked(); final Region outBounds = new Region(); Loading Loading @@ -498,7 +546,7 @@ public class AccessibilityWindowManagerTest { public void getPictureInPictureWindow_shouldNotNull() { assertNull(mA11yWindowManager.getPictureInPictureWindow()); mWindowInfos.get(1).inPictureInPicture = true; mA11yWindowManager.onWindowsForAccessibilityChanged(mWindowInfos); mA11yWindowManager.onWindowsForAccessibilityChanged(SEND_ON_WINDOW_CHANGES, mWindowInfos); assertNotNull(mA11yWindowManager.getPictureInPictureWindow()); } Loading @@ -511,7 +559,7 @@ public class AccessibilityWindowManagerTest { mA11yWindowManager.getConnectionLocked( USER_SYSTEM_ID, outsideWindowId).getRemote(); mWindowInfos.get(0).hasFlagWatchOutsideTouch = true; mA11yWindowManager.onWindowsForAccessibilityChanged(mWindowInfos); mA11yWindowManager.onWindowsForAccessibilityChanged(SEND_ON_WINDOW_CHANGES, mWindowInfos); mA11yWindowManager.notifyOutsideTouch(USER_SYSTEM_ID, targetWindowId); verify(mockRemoteConnection).notifyOutsideTouch(); Loading Loading
services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java +116 −6 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ import android.os.IBinder; import android.os.Process; import android.os.RemoteException; import android.os.UserHandle; import android.text.TextUtils; import android.util.Slog; import android.util.SparseArray; import android.view.IWindow; Loading Loading @@ -83,6 +84,7 @@ public class AccessibilityWindowManager mInteractionConnections = new SparseArray<>(); private final SparseArray<SparseArray<IBinder>> mWindowTokens = new SparseArray<>(); private final List<WindowInfo> mCachedWindowInfos = new ArrayList<>(); private List<AccessibilityWindowInfo> mWindows; private RemoteAccessibilityConnection mPictureInPictureActionReplacingConnection; Loading Loading @@ -173,24 +175,132 @@ public class AccessibilityWindowManager } /** * Callbacks from from window manager when there's an accessibility change in windows. * Callbacks from window manager when there's an accessibility change in windows. * * @param forceSend Send the windows for accessibility even if they haven't changed. * @param windows The windows of current display for accessibility. */ @Override public void onWindowsForAccessibilityChanged(@NonNull List<WindowInfo> windows) { public void onWindowsForAccessibilityChanged(boolean forceSend, @NonNull List<WindowInfo> windows) { synchronized (mLock) { if (DEBUG) { Slog.i(LOG_TAG, "Windows changed: " + windows); } if (shouldUpdateWindowsLocked(forceSend, windows)) { cacheWindows(windows); // Let the policy update the focused and active windows. updateWindowsLocked(mAccessibilityUserManager.getCurrentUserIdLocked(), windows); // Someone may be waiting for the windows - advertise it. mLock.notifyAll(); } } } private boolean shouldUpdateWindowsLocked(boolean forceSend, @NonNull List<WindowInfo> windows) { if (forceSend) { return true; } final int windowCount = windows.size(); // We computed the windows and if they changed notify the client. if (mCachedWindowInfos.size() != windowCount) { // Different size means something changed. return true; } else if (!mCachedWindowInfos.isEmpty() || !windows.isEmpty()) { // Since we always traverse windows from high to low layer // the old and new windows at the same index should be the // same, otherwise something changed. for (int i = 0; i < windowCount; i++) { WindowInfo oldWindow = mCachedWindowInfos.get(i); WindowInfo newWindow = windows.get(i); // We do not care for layer changes given the window // order does not change. This brings no new information // to the clients. if (windowChangedNoLayer(oldWindow, newWindow)) { return true; } } } return false; } private void cacheWindows(List<WindowInfo> windows) { final int oldWindowCount = mCachedWindowInfos.size(); for (int i = oldWindowCount - 1; i >= 0; i--) { mCachedWindowInfos.remove(i).recycle(); } final int newWindowCount = windows.size(); for (int i = 0; i < newWindowCount; i++) { WindowInfo newWindow = windows.get(i); mCachedWindowInfos.add(WindowInfo.obtain(newWindow)); } } private boolean windowChangedNoLayer(WindowInfo oldWindow, WindowInfo newWindow) { if (oldWindow == newWindow) { return false; } if (oldWindow == null) { return true; } if (newWindow == null) { return true; } if (oldWindow.type != newWindow.type) { return true; } if (oldWindow.focused != newWindow.focused) { return true; } if (oldWindow.token == null) { if (newWindow.token != null) { return true; } } else if (!oldWindow.token.equals(newWindow.token)) { return true; } if (oldWindow.parentToken == null) { if (newWindow.parentToken != null) { return true; } } else if (!oldWindow.parentToken.equals(newWindow.parentToken)) { return true; } if (oldWindow.activityToken == null) { if (newWindow.activityToken != null) { return true; } } else if (!oldWindow.activityToken.equals(newWindow.activityToken)) { return true; } if (!oldWindow.boundsInScreen.equals(newWindow.boundsInScreen)) { return true; } if (oldWindow.childTokens != null && newWindow.childTokens != null && !oldWindow.childTokens.equals(newWindow.childTokens)) { return true; } if (!TextUtils.equals(oldWindow.title, newWindow.title)) { return true; } if (oldWindow.accessibilityIdOfAnchor != newWindow.accessibilityIdOfAnchor) { return true; } if (oldWindow.inPictureInPicture != newWindow.inPictureInPicture) { return true; } if (oldWindow.hasFlagWatchOutsideTouch != newWindow.hasFlagWatchOutsideTouch) { return true; } if (oldWindow.displayId != newWindow.displayId) { return true; } return false; } /** * Start tracking windows changes from window manager. Loading
services/core/java/com/android/server/wm/AccessibilityController.java +4 −108 Original line number Diff line number Diff line Loading @@ -43,9 +43,7 @@ import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.Message; import android.text.TextUtils; import android.util.ArraySet; import android.util.Log; import android.util.Slog; import android.util.SparseArray; import android.util.TypedValue; Loading Loading @@ -1036,12 +1034,9 @@ final class AccessibilityController { private static final boolean DEBUG = false; private final SparseArray<WindowState> mTempWindowStates = new SparseArray<WindowState>(); private final SparseArray<WindowState> mTempWindowStates = new SparseArray<>(); private final List<WindowInfo> mOldWindows = new ArrayList<WindowInfo>(); private final Set<IBinder> mTempBinderSet = new ArraySet<IBinder>(); private final Set<IBinder> mTempBinderSet = new ArraySet<>(); private final RectF mTempRectF = new RectF(); Loading Loading @@ -1098,8 +1093,7 @@ final class AccessibilityController { Slog.i(LOG_TAG, "computeChangedWindows()"); } boolean windowsChanged = false; List<WindowInfo> windows = new ArrayList<WindowInfo>(); List<WindowInfo> windows = new ArrayList<>(); synchronized (mService.mGlobalLock) { // Do not send the windows if there is no current focus as Loading Loading @@ -1169,46 +1163,9 @@ final class AccessibilityController { visibleWindows.clear(); addedWindows.clear(); if (!forceSend) { // We computed the windows and if they changed notify the client. if (mOldWindows.size() != windows.size()) { // Different size means something changed. windowsChanged = true; } else if (!mOldWindows.isEmpty() || !windows.isEmpty()) { // Since we always traverse windows from high to low layer // the old and new windows at the same index should be the // same, otherwise something changed. for (int i = 0; i < windowCount; i++) { WindowInfo oldWindow = mOldWindows.get(i); WindowInfo newWindow = windows.get(i); // We do not care for layer changes given the window // order does not change. This brings no new information // to the clients. if (windowChangedNoLayer(oldWindow, newWindow)) { windowsChanged = true; break; } } } } if (forceSend || windowsChanged) { cacheWindows(windows); } } // Now we do not hold the lock, so send the windows over. if (forceSend || windowsChanged) { if (DEBUG) { Log.i(LOG_TAG, "Windows changed or force sending:" + windows); } mCallback.onWindowsForAccessibilityChanged(windows); } else { if (DEBUG) { Log.i(LOG_TAG, "No windows changed."); } } mCallback.onWindowsForAccessibilityChanged(forceSend, windows); // Recycle the windows as we do not need them. clearAndRecycleWindows(windows); Loading Loading @@ -1313,67 +1270,6 @@ final class AccessibilityController { tokenOut.add(window.token); } private void cacheWindows(List<WindowInfo> windows) { final int oldWindowCount = mOldWindows.size(); for (int i = oldWindowCount - 1; i >= 0; i--) { mOldWindows.remove(i).recycle(); } final int newWindowCount = windows.size(); for (int i = 0; i < newWindowCount; i++) { WindowInfo newWindow = windows.get(i); mOldWindows.add(WindowInfo.obtain(newWindow)); } } private boolean windowChangedNoLayer(WindowInfo oldWindow, WindowInfo newWindow) { if (oldWindow == newWindow) { return false; } if (oldWindow == null) { return true; } if (newWindow == null) { return true; } if (oldWindow.type != newWindow.type) { return true; } if (oldWindow.focused != newWindow.focused) { return true; } if (oldWindow.token == null) { if (newWindow.token != null) { return true; } } else if (!oldWindow.token.equals(newWindow.token)) { return true; } if (oldWindow.parentToken == null) { if (newWindow.parentToken != null) { return true; } } else if (!oldWindow.parentToken.equals(newWindow.parentToken)) { return true; } if (!oldWindow.boundsInScreen.equals(newWindow.boundsInScreen)) { return true; } if (oldWindow.childTokens != null && newWindow.childTokens != null && !oldWindow.childTokens.equals(newWindow.childTokens)) { return true; } if (!TextUtils.equals(oldWindow.title, newWindow.title)) { return true; } if (oldWindow.accessibilityIdOfAnchor != newWindow.accessibilityIdOfAnchor) { return true; } if (oldWindow.displayId != newWindow.displayId) { return true; } return false; } private static void clearAndRecycleWindows(List<WindowInfo> windows) { final int windowCount = windows.size(); for (int i = windowCount - 1; i >= 0; i--) { Loading
services/core/java/com/android/server/wm/WindowManagerInternal.java +2 −1 Original line number Diff line number Diff line Loading @@ -51,9 +51,10 @@ public abstract class WindowManagerInternal { /** * Called when the windows for accessibility changed. * * @param forceSend Send the windows for accessibility even if they haven't changed. * @param windows The windows for accessibility. */ public void onWindowsForAccessibilityChanged(List<WindowInfo> windows); void onWindowsForAccessibilityChanged(boolean forceSend, List<WindowInfo> windows); } /** Loading
services/tests/servicestests/src/com/android/server/accessibility/AccessibilityWindowManagerTest.java +60 −12 Original line number Diff line number Diff line Loading @@ -70,6 +70,8 @@ import java.util.List; */ public class AccessibilityWindowManagerTest { private static final String PACKAGE_NAME = "com.android.server.accessibility"; private static final boolean FORCE_SEND = true; private static final boolean SEND_ON_WINDOW_CHANGES = false; private static final int USER_SYSTEM_ID = UserHandle.USER_SYSTEM; private static final int NUM_GLOBAL_WINDOWS = 4; private static final int NUM_APP_WINDOWS = 4; Loading Loading @@ -122,7 +124,7 @@ public class AccessibilityWindowManagerTest { mWindowInfos.get(DEFAULT_FOCUSED_INDEX).focused = true; // Turn on windows tracking, and update window info mA11yWindowManager.startTrackingWindows(); mA11yWindowManager.onWindowsForAccessibilityChanged(mWindowInfos); mA11yWindowManager.onWindowsForAccessibilityChanged(FORCE_SEND, mWindowInfos); assertEquals(mA11yWindowManager.getWindowListLocked().size(), mWindowInfos.size()); Loading Loading @@ -169,16 +171,16 @@ public class AccessibilityWindowManagerTest { @Test public void onWindowsChanged_duringTouchInteractAndFocusChange_shouldChangeActiveWindow() { final int activeWindowId = mA11yWindowManager.getActiveWindowId(USER_SYSTEM_ID); WindowInfo focuedWindowInfo = mWindowInfos.get(DEFAULT_FOCUSED_INDEX); WindowInfo focusedWindowInfo = mWindowInfos.get(DEFAULT_FOCUSED_INDEX); assertEquals(activeWindowId, mA11yWindowManager.findWindowIdLocked( USER_SYSTEM_ID, focuedWindowInfo.token)); USER_SYSTEM_ID, focusedWindowInfo.token)); focuedWindowInfo.focused = false; focuedWindowInfo = mWindowInfos.get(DEFAULT_FOCUSED_INDEX + 1); focuedWindowInfo.focused = true; focusedWindowInfo.focused = false; focusedWindowInfo = mWindowInfos.get(DEFAULT_FOCUSED_INDEX + 1); focusedWindowInfo.focused = true; mA11yWindowManager.onTouchInteractionStart(); mA11yWindowManager.onWindowsForAccessibilityChanged(mWindowInfos); mA11yWindowManager.onWindowsForAccessibilityChanged(SEND_ON_WINDOW_CHANGES, mWindowInfos); assertNotEquals(activeWindowId, mA11yWindowManager.getActiveWindowId(USER_SYSTEM_ID)); } Loading Loading @@ -207,6 +209,52 @@ public class AccessibilityWindowManagerTest { } } @Test public void onWindowsChangedAndForceSend_shouldUpdateWindows() { final WindowInfo windowInfo = mWindowInfos.get(0); final int correctLayer = mA11yWindowManager.getWindowListLocked().get(0).getLayer(); windowInfo.layer += 1; mA11yWindowManager.onWindowsForAccessibilityChanged(FORCE_SEND, mWindowInfos); assertNotEquals(correctLayer, mA11yWindowManager.getWindowListLocked().get(0).getLayer()); } @Test public void onWindowsChangedNoForceSend_layerChanged_shouldNotUpdateWindows() { final WindowInfo windowInfo = mWindowInfos.get(0); final int correctLayer = mA11yWindowManager.getWindowListLocked().get(0).getLayer(); windowInfo.layer += 1; mA11yWindowManager.onWindowsForAccessibilityChanged(SEND_ON_WINDOW_CHANGES, mWindowInfos); assertEquals(correctLayer, mA11yWindowManager.getWindowListLocked().get(0).getLayer()); } @Test public void onWindowsChangedNoForceSend_windowChanged_shouldUpdateWindows() throws RemoteException { final AccessibilityWindowInfo oldWindow = mA11yWindowManager.getWindowListLocked().get(0); final IWindow token = addAccessibilityInteractionConnection(true); final WindowInfo windowInfo = WindowInfo.obtain(); windowInfo.type = AccessibilityWindowInfo.TYPE_APPLICATION; windowInfo.token = token.asBinder(); windowInfo.layer = 0; windowInfo.boundsInScreen.set(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); mWindowInfos.set(0, windowInfo); mA11yWindowManager.onWindowsForAccessibilityChanged(SEND_ON_WINDOW_CHANGES, mWindowInfos); assertNotEquals(oldWindow, mA11yWindowManager.getWindowListLocked().get(0)); } @Test public void onWindowsChangedNoForceSend_focusChanged_shouldUpdateWindows() { final WindowInfo focusedWindowInfo = mWindowInfos.get(DEFAULT_FOCUSED_INDEX); final WindowInfo windowInfo = mWindowInfos.get(0); focusedWindowInfo.focused = false; windowInfo.focused = true; mA11yWindowManager.onWindowsForAccessibilityChanged(SEND_ON_WINDOW_CHANGES, mWindowInfos); assertTrue(mA11yWindowManager.getWindowListLocked().get(0).isFocused()); } @Test public void removeAccessibilityInteractionConnection_byWindowToken_shouldRemoved() { for (int i = 0; i < NUM_OF_WINDOWS; i++) { Loading Loading @@ -264,7 +312,7 @@ public class AccessibilityWindowManagerTest { windowInfo = mWindowInfos.get(1); windowInfo.boundsInScreen.set(0, SCREEN_HEIGHT / 2, SCREEN_WIDTH, SCREEN_HEIGHT); mA11yWindowManager.onWindowsForAccessibilityChanged(mWindowInfos); mA11yWindowManager.onWindowsForAccessibilityChanged(SEND_ON_WINDOW_CHANGES, mWindowInfos); final List<AccessibilityWindowInfo> a11yWindows = mA11yWindowManager.getWindowListLocked(); final Region outBounds = new Region(); Loading @@ -291,7 +339,7 @@ public class AccessibilityWindowManagerTest { windowInfo = mWindowInfos.get(1); windowInfo.boundsInScreen.set(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); mA11yWindowManager.onWindowsForAccessibilityChanged(mWindowInfos); mA11yWindowManager.onWindowsForAccessibilityChanged(SEND_ON_WINDOW_CHANGES, mWindowInfos); final List<AccessibilityWindowInfo> a11yWindows = mA11yWindowManager.getWindowListLocked(); final Region outBounds = new Region(); int windowId = a11yWindows.get(1).getId(); Loading @@ -309,7 +357,7 @@ public class AccessibilityWindowManagerTest { windowInfo.boundsInScreen.set(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); windowInfo = mWindowInfos.get(1); windowInfo.boundsInScreen.set(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); mA11yWindowManager.onWindowsForAccessibilityChanged(mWindowInfos); mA11yWindowManager.onWindowsForAccessibilityChanged(SEND_ON_WINDOW_CHANGES, mWindowInfos); final List<AccessibilityWindowInfo> a11yWindows = mA11yWindowManager.getWindowListLocked(); final Region outBounds = new Region(); Loading Loading @@ -498,7 +546,7 @@ public class AccessibilityWindowManagerTest { public void getPictureInPictureWindow_shouldNotNull() { assertNull(mA11yWindowManager.getPictureInPictureWindow()); mWindowInfos.get(1).inPictureInPicture = true; mA11yWindowManager.onWindowsForAccessibilityChanged(mWindowInfos); mA11yWindowManager.onWindowsForAccessibilityChanged(SEND_ON_WINDOW_CHANGES, mWindowInfos); assertNotNull(mA11yWindowManager.getPictureInPictureWindow()); } Loading @@ -511,7 +559,7 @@ public class AccessibilityWindowManagerTest { mA11yWindowManager.getConnectionLocked( USER_SYSTEM_ID, outsideWindowId).getRemote(); mWindowInfos.get(0).hasFlagWatchOutsideTouch = true; mA11yWindowManager.onWindowsForAccessibilityChanged(mWindowInfos); mA11yWindowManager.onWindowsForAccessibilityChanged(SEND_ON_WINDOW_CHANGES, mWindowInfos); mA11yWindowManager.notifyOutsideTouch(USER_SYSTEM_ID, targetWindowId); verify(mockRemoteConnection).notifyOutsideTouch(); Loading