Merge "Do not prefetching accessibility nodes while a view is scrolling" into rvc-dev am: 7fc16f7c32
Change-Id: If89fcb3809f15fd1e6593956c9cbb37ffa20c6c5
This commit is contained in:
@@ -31,7 +31,9 @@ import android.os.SystemClock;
|
||||
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 @@ public final class AccessibilityInteractionClient
|
||||
|
||||
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 @@ public final class AccessibilityInteractionClient
|
||||
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 @@ public final class AccessibilityInteractionClient
|
||||
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 final class AccessibilityInteractionClient
|
||||
}
|
||||
|
||||
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 @@ public final class AccessibilityInteractionClient
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,6 +137,9 @@ public class AccessibilityNodeInfo implements Parcelable {
|
||||
/** @hide */
|
||||
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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user