Merge "Do not prefetching accessibility nodes while a view is scrolling" into rvc-dev
diff --git a/core/java/android/view/accessibility/AccessibilityInteractionClient.java b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
index b4c8795..299ae2f0 100644
--- a/core/java/android/view/accessibility/AccessibilityInteractionClient.java
+++ b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
@@ -31,7 +31,9 @@
import android.util.Log;
import android.util.LongSparseArray;
import android.util.SparseArray;
+import android.util.SparseLongArray;
import android.view.Display;
+import android.view.ViewConfiguration;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
@@ -89,6 +91,9 @@
private static final long TIMEOUT_INTERACTION_MILLIS = 5000;
+ private static final long DISABLE_PREFETCHING_FOR_SCROLLING_MILLIS =
+ (long) (ViewConfiguration.getSendRecurringAccessibilityEventsInterval() * 1.5);
+
private static final Object sStaticLock = new Object();
private static final LongSparseArray<AccessibilityInteractionClient> sClients =
@@ -97,6 +102,10 @@
private static final SparseArray<IAccessibilityServiceConnection> sConnectionCache =
new SparseArray<>();
+ /** List of timestamps which indicate the latest time an a11y service receives a scroll event
+ from a window, mapping from windowId -> timestamp. */
+ private static final SparseLongArray sScrollingWindows = new SparseLongArray();
+
private static AccessibilityCache sAccessibilityCache =
new AccessibilityCache(new AccessibilityCache.AccessibilityNodeRefresher());
@@ -422,6 +431,14 @@
Log.i(LOG_TAG, "Node cache miss for "
+ idToString(accessibilityWindowId, accessibilityNodeId));
}
+ } else {
+ // No need to prefech nodes in bypass cache case.
+ prefetchFlags &= ~AccessibilityNodeInfo.FLAG_PREFETCH_MASK;
+ }
+ // Skip prefetching if window is scrolling.
+ if ((prefetchFlags & AccessibilityNodeInfo.FLAG_PREFETCH_MASK) != 0
+ && isWindowScrolling(accessibilityWindowId)) {
+ prefetchFlags &= ~AccessibilityNodeInfo.FLAG_PREFETCH_MASK;
}
final int interactionId = mInteractionIdCounter.getAndIncrement();
final long identityToken = Binder.clearCallingIdentity();
@@ -718,6 +735,18 @@
}
public void onAccessibilityEvent(AccessibilityEvent event) {
+ switch (event.getEventType()) {
+ case AccessibilityEvent.TYPE_VIEW_SCROLLED:
+ updateScrollingWindow(event.getWindowId(), SystemClock.uptimeMillis());
+ break;
+ case AccessibilityEvent.TYPE_WINDOWS_CHANGED:
+ if (event.getWindowChanges() == AccessibilityEvent.WINDOWS_CHANGE_REMOVED) {
+ deleteScrollingWindow(event.getWindowId());
+ }
+ break;
+ default:
+ break;
+ }
sAccessibilityCache.onAccessibilityEvent(event);
}
@@ -986,4 +1015,48 @@
Log.e(LOG_TAG, disconnectedCount + " Disconnected nodes.");
}
}
+
+ /**
+ * Update scroll event timestamp of a given window.
+ *
+ * @param windowId The window id.
+ * @param uptimeMillis Device uptime millis.
+ */
+ private void updateScrollingWindow(int windowId, long uptimeMillis) {
+ synchronized (sScrollingWindows) {
+ sScrollingWindows.put(windowId, uptimeMillis);
+ }
+ }
+
+ /**
+ * Remove a window from the scrolling windows list.
+ *
+ * @param windowId The window id.
+ */
+ private void deleteScrollingWindow(int windowId) {
+ synchronized (sScrollingWindows) {
+ sScrollingWindows.delete(windowId);
+ }
+ }
+
+ /**
+ * Whether or not the window is scrolling.
+ *
+ * @param windowId
+ * @return true if it's scrolling.
+ */
+ private boolean isWindowScrolling(int windowId) {
+ synchronized (sScrollingWindows) {
+ final long latestScrollingTime = sScrollingWindows.get(windowId);
+ if (latestScrollingTime == 0) {
+ return false;
+ }
+ final long currentUptime = SystemClock.uptimeMillis();
+ if (currentUptime > (latestScrollingTime + DISABLE_PREFETCHING_FOR_SCROLLING_MILLIS)) {
+ sScrollingWindows.delete(windowId);
+ return false;
+ }
+ }
+ return true;
+ }
}
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index eb4f9db..9f83862 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -138,6 +138,9 @@
public static final int FLAG_PREFETCH_DESCENDANTS = 0x00000004;
/** @hide */
+ public static final int FLAG_PREFETCH_MASK = 0x00000007;
+
+ /** @hide */
public static final int FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 0x00000008;
/** @hide */