Loading core/java/android/view/accessibility/AccessibilityCache.java +16 −1 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ package android.view.accessibility; import static android.view.accessibility.AccessibilityNodeInfo.FOCUS_ACCESSIBILITY; import android.os.Build; import android.os.SystemClock; import android.util.ArraySet; import android.util.Log; import android.util.LongArray; Loading Loading @@ -71,6 +72,11 @@ public class AccessibilityCache { private long mAccessibilityFocus = AccessibilityNodeInfo.UNDEFINED_ITEM_ID; private long mInputFocus = AccessibilityNodeInfo.UNDEFINED_ITEM_ID; /** * The event time of the {@link AccessibilityEvent} which presents the populated windows cache * before it is stale. */ private long mValidWindowCacheTimeStamp = 0; private int mAccessibilityFocusedWindow = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID; private int mInputFocusWindow = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID; Loading @@ -97,13 +103,20 @@ public class AccessibilityCache { * The key of SparseArray is display ID. * * @param windowsOnAllDisplays The accessibility windows of all displays. * @param populationTimeStamp The timestamp from {@link SystemClock#uptimeMillis()} when the * client requests the data. */ public void setWindowsOnAllDisplays( SparseArray<List<AccessibilityWindowInfo>> windowsOnAllDisplays) { SparseArray<List<AccessibilityWindowInfo>> windowsOnAllDisplays, long populationTimeStamp) { synchronized (mLock) { if (DEBUG) { Log.i(LOG_TAG, "Set windows"); } if (mValidWindowCacheTimeStamp > populationTimeStamp) { // Discard the windows because it might be stale. return; } clearWindowCacheLocked(); if (windowsOnAllDisplays == null) { return; Loading Loading @@ -224,6 +237,7 @@ public class AccessibilityCache { } break; case AccessibilityEvent.TYPE_WINDOWS_CHANGED: mValidWindowCacheTimeStamp = event.getEventTime(); if (event.getWindowChanges() == AccessibilityEvent.WINDOWS_CHANGE_ACCESSIBILITY_FOCUSED) { // Don't need to clear all cache. Unless the changes are related to Loading @@ -232,6 +246,7 @@ public class AccessibilityCache { break; } case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED: { mValidWindowCacheTimeStamp = event.getEventTime(); clear(); } break; } Loading core/java/android/view/accessibility/AccessibilityInteractionClient.java +3 −1 Original line number Diff line number Diff line Loading @@ -435,8 +435,10 @@ public final class AccessibilityInteractionClient } } long populationTimeStamp; final long identityToken = Binder.clearCallingIdentity(); try { populationTimeStamp = SystemClock.uptimeMillis(); windows = connection.getWindows(); } finally { Binder.restoreCallingIdentity(identityToken); Loading @@ -446,7 +448,7 @@ public final class AccessibilityInteractionClient } if (windows != null) { if (sAccessibilityCache != null) { sAccessibilityCache.setWindowsOnAllDisplays(windows); sAccessibilityCache.setWindowsOnAllDisplays(windows, populationTimeStamp); } return windows; } Loading core/tests/coretests/src/android/view/accessibility/AccessibilityCacheTest.java +49 −2 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.os.SystemClock; import android.util.SparseArray; import android.view.Display; import android.view.View; Loading Loading @@ -299,7 +300,8 @@ public class AccessibilityCacheTest { SparseArray<List<AccessibilityWindowInfo>> allWindows = new SparseArray<>(); allWindows.put(Display.DEFAULT_DISPLAY, windowsIn1); allWindows.put(SECONDARY_DISPLAY_ID, windowsIn2); mAccessibilityCache.setWindowsOnAllDisplays(allWindows); final long populationTimeStamp = SystemClock.uptimeMillis(); mAccessibilityCache.setWindowsOnAllDisplays(allWindows, populationTimeStamp); // Gets windows at default display. windowsOut1 = getWindowsByDisplay(Display.DEFAULT_DISPLAY); window1Out = mAccessibilityCache.getWindow(WINDOW_ID_1); Loading Loading @@ -338,6 +340,46 @@ public class AccessibilityCacheTest { } } @Test public void setInvalidWindowsAfterWindowsChangedEvent_notInCache() { final AccessibilityEvent event = new AccessibilityEvent( AccessibilityEvent.TYPE_WINDOWS_CHANGED); final long eventTime = 1000L; event.setEventTime(eventTime); mAccessibilityCache.onAccessibilityEvent(event); final AccessibilityWindowInfo windowInfo1 = obtainAccessibilityWindowInfo(WINDOW_ID_1, SPECIFIC_WINDOW_LAYER); List<AccessibilityWindowInfo> windowsIn = Arrays.asList(windowInfo1); setWindowsByDisplay(Display.DEFAULT_DISPLAY, windowsIn, eventTime - 10); try { assertNull(getWindowsByDisplay(Display.DEFAULT_DISPLAY)); } finally { windowInfo1.recycle(); } } @Test public void setInvalidWindowsAfterStateChangedEvent_notInCache() { final AccessibilityEvent event = new AccessibilityEvent( AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED); final long eventTime = 1000L; event.setEventTime(eventTime); mAccessibilityCache.onAccessibilityEvent(event); final AccessibilityWindowInfo windowInfo1 = obtainAccessibilityWindowInfo(WINDOW_ID_1, SPECIFIC_WINDOW_LAYER); List<AccessibilityWindowInfo> windowsIn = Arrays.asList(windowInfo1); setWindowsByDisplay(Display.DEFAULT_DISPLAY, windowsIn, eventTime - 10); try { assertNull(getWindowsByDisplay(Display.DEFAULT_DISPLAY)); } finally { windowInfo1.recycle(); } } @Test public void addWindowThenStateChangedEvent_noLongerInCache() { putWindowWithWindowIdAndDisplayIdInCache(WINDOW_ID_1, Display.DEFAULT_DISPLAY, Loading Loading @@ -1063,9 +1105,14 @@ public class AccessibilityCacheTest { } private void setWindowsByDisplay(int displayId, List<AccessibilityWindowInfo> windows) { setWindowsByDisplay(displayId, windows, SystemClock.uptimeMillis()); } private void setWindowsByDisplay(int displayId, List<AccessibilityWindowInfo> windows, long populationTimeStamp) { SparseArray<List<AccessibilityWindowInfo>> allWindows = new SparseArray<>(); allWindows.put(displayId, windows); mAccessibilityCache.setWindowsOnAllDisplays(allWindows); mAccessibilityCache.setWindowsOnAllDisplays(allWindows, populationTimeStamp); } private List<AccessibilityWindowInfo> getWindowsByDisplay(int displayId) { Loading Loading
core/java/android/view/accessibility/AccessibilityCache.java +16 −1 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ package android.view.accessibility; import static android.view.accessibility.AccessibilityNodeInfo.FOCUS_ACCESSIBILITY; import android.os.Build; import android.os.SystemClock; import android.util.ArraySet; import android.util.Log; import android.util.LongArray; Loading Loading @@ -71,6 +72,11 @@ public class AccessibilityCache { private long mAccessibilityFocus = AccessibilityNodeInfo.UNDEFINED_ITEM_ID; private long mInputFocus = AccessibilityNodeInfo.UNDEFINED_ITEM_ID; /** * The event time of the {@link AccessibilityEvent} which presents the populated windows cache * before it is stale. */ private long mValidWindowCacheTimeStamp = 0; private int mAccessibilityFocusedWindow = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID; private int mInputFocusWindow = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID; Loading @@ -97,13 +103,20 @@ public class AccessibilityCache { * The key of SparseArray is display ID. * * @param windowsOnAllDisplays The accessibility windows of all displays. * @param populationTimeStamp The timestamp from {@link SystemClock#uptimeMillis()} when the * client requests the data. */ public void setWindowsOnAllDisplays( SparseArray<List<AccessibilityWindowInfo>> windowsOnAllDisplays) { SparseArray<List<AccessibilityWindowInfo>> windowsOnAllDisplays, long populationTimeStamp) { synchronized (mLock) { if (DEBUG) { Log.i(LOG_TAG, "Set windows"); } if (mValidWindowCacheTimeStamp > populationTimeStamp) { // Discard the windows because it might be stale. return; } clearWindowCacheLocked(); if (windowsOnAllDisplays == null) { return; Loading Loading @@ -224,6 +237,7 @@ public class AccessibilityCache { } break; case AccessibilityEvent.TYPE_WINDOWS_CHANGED: mValidWindowCacheTimeStamp = event.getEventTime(); if (event.getWindowChanges() == AccessibilityEvent.WINDOWS_CHANGE_ACCESSIBILITY_FOCUSED) { // Don't need to clear all cache. Unless the changes are related to Loading @@ -232,6 +246,7 @@ public class AccessibilityCache { break; } case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED: { mValidWindowCacheTimeStamp = event.getEventTime(); clear(); } break; } Loading
core/java/android/view/accessibility/AccessibilityInteractionClient.java +3 −1 Original line number Diff line number Diff line Loading @@ -435,8 +435,10 @@ public final class AccessibilityInteractionClient } } long populationTimeStamp; final long identityToken = Binder.clearCallingIdentity(); try { populationTimeStamp = SystemClock.uptimeMillis(); windows = connection.getWindows(); } finally { Binder.restoreCallingIdentity(identityToken); Loading @@ -446,7 +448,7 @@ public final class AccessibilityInteractionClient } if (windows != null) { if (sAccessibilityCache != null) { sAccessibilityCache.setWindowsOnAllDisplays(windows); sAccessibilityCache.setWindowsOnAllDisplays(windows, populationTimeStamp); } return windows; } Loading
core/tests/coretests/src/android/view/accessibility/AccessibilityCacheTest.java +49 −2 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.os.SystemClock; import android.util.SparseArray; import android.view.Display; import android.view.View; Loading Loading @@ -299,7 +300,8 @@ public class AccessibilityCacheTest { SparseArray<List<AccessibilityWindowInfo>> allWindows = new SparseArray<>(); allWindows.put(Display.DEFAULT_DISPLAY, windowsIn1); allWindows.put(SECONDARY_DISPLAY_ID, windowsIn2); mAccessibilityCache.setWindowsOnAllDisplays(allWindows); final long populationTimeStamp = SystemClock.uptimeMillis(); mAccessibilityCache.setWindowsOnAllDisplays(allWindows, populationTimeStamp); // Gets windows at default display. windowsOut1 = getWindowsByDisplay(Display.DEFAULT_DISPLAY); window1Out = mAccessibilityCache.getWindow(WINDOW_ID_1); Loading Loading @@ -338,6 +340,46 @@ public class AccessibilityCacheTest { } } @Test public void setInvalidWindowsAfterWindowsChangedEvent_notInCache() { final AccessibilityEvent event = new AccessibilityEvent( AccessibilityEvent.TYPE_WINDOWS_CHANGED); final long eventTime = 1000L; event.setEventTime(eventTime); mAccessibilityCache.onAccessibilityEvent(event); final AccessibilityWindowInfo windowInfo1 = obtainAccessibilityWindowInfo(WINDOW_ID_1, SPECIFIC_WINDOW_LAYER); List<AccessibilityWindowInfo> windowsIn = Arrays.asList(windowInfo1); setWindowsByDisplay(Display.DEFAULT_DISPLAY, windowsIn, eventTime - 10); try { assertNull(getWindowsByDisplay(Display.DEFAULT_DISPLAY)); } finally { windowInfo1.recycle(); } } @Test public void setInvalidWindowsAfterStateChangedEvent_notInCache() { final AccessibilityEvent event = new AccessibilityEvent( AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED); final long eventTime = 1000L; event.setEventTime(eventTime); mAccessibilityCache.onAccessibilityEvent(event); final AccessibilityWindowInfo windowInfo1 = obtainAccessibilityWindowInfo(WINDOW_ID_1, SPECIFIC_WINDOW_LAYER); List<AccessibilityWindowInfo> windowsIn = Arrays.asList(windowInfo1); setWindowsByDisplay(Display.DEFAULT_DISPLAY, windowsIn, eventTime - 10); try { assertNull(getWindowsByDisplay(Display.DEFAULT_DISPLAY)); } finally { windowInfo1.recycle(); } } @Test public void addWindowThenStateChangedEvent_noLongerInCache() { putWindowWithWindowIdAndDisplayIdInCache(WINDOW_ID_1, Display.DEFAULT_DISPLAY, Loading Loading @@ -1063,9 +1105,14 @@ public class AccessibilityCacheTest { } private void setWindowsByDisplay(int displayId, List<AccessibilityWindowInfo> windows) { setWindowsByDisplay(displayId, windows, SystemClock.uptimeMillis()); } private void setWindowsByDisplay(int displayId, List<AccessibilityWindowInfo> windows, long populationTimeStamp) { SparseArray<List<AccessibilityWindowInfo>> allWindows = new SparseArray<>(); allWindows.put(displayId, windows); mAccessibilityCache.setWindowsOnAllDisplays(allWindows); mAccessibilityCache.setWindowsOnAllDisplays(allWindows, populationTimeStamp); } private List<AccessibilityWindowInfo> getWindowsByDisplay(int displayId) { Loading