Merge "Prefetching of accessibility node infos getting incorrect views." into jb-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
67d10a5867
@@ -29,7 +29,6 @@ import android.util.Poolable;
|
||||
import android.util.PoolableManager;
|
||||
import android.util.Pools;
|
||||
import android.util.SparseLongArray;
|
||||
import android.view.ViewGroup.ChildListForAccessibility;
|
||||
import android.view.accessibility.AccessibilityInteractionClient;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
import android.view.accessibility.AccessibilityNodeProvider;
|
||||
@@ -623,6 +622,8 @@ final class AccessibilityInteractionController {
|
||||
|
||||
private static final int MAX_ACCESSIBILITY_NODE_INFO_BATCH_SIZE = 50;
|
||||
|
||||
private final ArrayList<View> mTempViewList = new ArrayList<View>();
|
||||
|
||||
public void prefetchAccessibilityNodeInfos(View view, int virtualViewId, int prefetchFlags,
|
||||
List<AccessibilityNodeInfo> outInfos) {
|
||||
AccessibilityNodeProvider provider = view.getAccessibilityNodeProvider();
|
||||
@@ -663,8 +664,6 @@ final class AccessibilityInteractionController {
|
||||
while (parent instanceof View
|
||||
&& outInfos.size() < MAX_ACCESSIBILITY_NODE_INFO_BATCH_SIZE) {
|
||||
View parentView = (View) parent;
|
||||
final long parentNodeId = AccessibilityNodeInfo.makeNodeId(
|
||||
parentView.getAccessibilityViewId(), AccessibilityNodeInfo.UNDEFINED);
|
||||
AccessibilityNodeInfo info = parentView.createAccessibilityNodeInfo();
|
||||
if (info != null) {
|
||||
outInfos.add(info);
|
||||
@@ -678,19 +677,21 @@ final class AccessibilityInteractionController {
|
||||
ViewParent parent = current.getParentForAccessibility();
|
||||
if (parent instanceof ViewGroup) {
|
||||
ViewGroup parentGroup = (ViewGroup) parent;
|
||||
ChildListForAccessibility children = ChildListForAccessibility.obtain(parentGroup,
|
||||
false);
|
||||
ArrayList<View> children = mTempViewList;
|
||||
children.clear();
|
||||
try {
|
||||
final int childCount = children.getChildCount();
|
||||
parentGroup.addChildrenForAccessibility(children);
|
||||
final int childCount = children.size();
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
if (outInfos.size() >= MAX_ACCESSIBILITY_NODE_INFO_BATCH_SIZE) {
|
||||
return;
|
||||
}
|
||||
View child = children.getChildAt(i);
|
||||
View child = children.get(i);
|
||||
if (child.getAccessibilityViewId() != current.getAccessibilityViewId()
|
||||
&& isShown(child)) {
|
||||
AccessibilityNodeInfo info = null;
|
||||
AccessibilityNodeProvider provider = child.getAccessibilityNodeProvider();
|
||||
AccessibilityNodeProvider provider =
|
||||
child.getAccessibilityNodeProvider();
|
||||
if (provider == null) {
|
||||
info = child.createAccessibilityNodeInfo();
|
||||
} else {
|
||||
@@ -703,7 +704,7 @@ final class AccessibilityInteractionController {
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
children.recycle();
|
||||
children.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -716,14 +717,16 @@ final class AccessibilityInteractionController {
|
||||
ViewGroup rootGroup = (ViewGroup) root;
|
||||
HashMap<View, AccessibilityNodeInfo> addedChildren =
|
||||
new HashMap<View, AccessibilityNodeInfo>();
|
||||
ChildListForAccessibility children = ChildListForAccessibility.obtain(rootGroup, false);
|
||||
ArrayList<View> children = mTempViewList;
|
||||
children.clear();
|
||||
try {
|
||||
final int childCount = children.getChildCount();
|
||||
root.addChildrenForAccessibility(children);
|
||||
final int childCount = children.size();
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
if (outInfos.size() >= MAX_ACCESSIBILITY_NODE_INFO_BATCH_SIZE) {
|
||||
return;
|
||||
}
|
||||
View child = children.getChildAt(i);
|
||||
View child = children.get(i);
|
||||
if (isShown(child)) {
|
||||
AccessibilityNodeProvider provider = child.getAccessibilityNodeProvider();
|
||||
if (provider == null) {
|
||||
@@ -743,7 +746,7 @@ final class AccessibilityInteractionController {
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
children.recycle();
|
||||
children.clear();
|
||||
}
|
||||
if (outInfos.size() < MAX_ACCESSIBILITY_NODE_INFO_BATCH_SIZE) {
|
||||
for (Map.Entry<View, AccessibilityNodeInfo> entry : addedChildren.entrySet()) {
|
||||
|
||||
@@ -19,6 +19,7 @@ package android.view.accessibility;
|
||||
import android.accessibilityservice.IAccessibilityServiceConnection;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Binder;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Message;
|
||||
import android.os.Process;
|
||||
@@ -27,10 +28,14 @@ import android.os.SystemClock;
|
||||
import android.util.Log;
|
||||
import android.util.LongSparseArray;
|
||||
import android.util.SparseArray;
|
||||
import android.util.SparseLongArray;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
@@ -74,6 +79,8 @@ public final class AccessibilityInteractionClient
|
||||
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
private static final boolean CHECK_INTEGRITY = true;
|
||||
|
||||
private static final long TIMEOUT_INTERACTION_MILLIS = 5000;
|
||||
|
||||
private static final Object sStaticLock = new Object();
|
||||
@@ -491,6 +498,9 @@ public final class AccessibilityInteractionClient
|
||||
result = Collections.emptyList();
|
||||
}
|
||||
clearResultLocked();
|
||||
if (Build.IS_DEBUGGABLE && CHECK_INTEGRITY) {
|
||||
checkFindAccessibilityNodeInfoResultIntegrity(result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -696,4 +706,56 @@ public final class AccessibilityInteractionClient
|
||||
sConnectionCache.remove(connectionId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the infos are a fully connected tree with no duplicates.
|
||||
*
|
||||
* @param infos The result list to check.
|
||||
*/
|
||||
private void checkFindAccessibilityNodeInfoResultIntegrity(List<AccessibilityNodeInfo> infos) {
|
||||
if (infos.size() == 0) {
|
||||
return;
|
||||
}
|
||||
// Find the root node.
|
||||
AccessibilityNodeInfo root = infos.get(0);
|
||||
final int infoCount = infos.size();
|
||||
for (int i = 1; i < infoCount; i++) {
|
||||
for (int j = i; j < infoCount; j++) {
|
||||
AccessibilityNodeInfo candidate = infos.get(j);
|
||||
if (root.getParentNodeId() == candidate.getSourceNodeId()) {
|
||||
root = candidate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (root == null) {
|
||||
Log.e(LOG_TAG, "No root.");
|
||||
}
|
||||
// Check for duplicates.
|
||||
HashSet<AccessibilityNodeInfo> seen = new HashSet<AccessibilityNodeInfo>();
|
||||
Queue<AccessibilityNodeInfo> fringe = new LinkedList<AccessibilityNodeInfo>();
|
||||
fringe.add(root);
|
||||
while (!fringe.isEmpty()) {
|
||||
AccessibilityNodeInfo current = fringe.poll();
|
||||
if (!seen.add(current)) {
|
||||
Log.e(LOG_TAG, "Duplicate node.");
|
||||
return;
|
||||
}
|
||||
SparseLongArray childIds = current.getChildNodeIds();
|
||||
final int childCount = childIds.size();
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
final long childId = childIds.valueAt(i);
|
||||
for (int j = 0; j < infoCount; j++) {
|
||||
AccessibilityNodeInfo child = infos.get(j);
|
||||
if (child.getSourceNodeId() == childId) {
|
||||
fringe.add(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
final int disconnectedCount = infos.size() - seen.size();
|
||||
if (disconnectedCount > 0) {
|
||||
Log.e(LOG_TAG, disconnectedCount + " Disconnected nodes.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -244,7 +244,7 @@ public class AccessibilityNodeInfoCache {
|
||||
/**
|
||||
* We are enforcing the invariant for a single accessibility focus.
|
||||
*
|
||||
* @param currentInputFocusId The current input focused node.
|
||||
* @param currentAccessibilityFocusId The current input focused node.
|
||||
*/
|
||||
private void clearSubtreeWithOldAccessibilityFocusLocked(long currentAccessibilityFocusId) {
|
||||
final int cacheSize = mCacheImpl.size();
|
||||
|
||||
@@ -2490,7 +2490,7 @@ public class NumberPicker extends LinearLayout {
|
||||
info.addChild(NumberPicker.this, VIRTUAL_VIEW_ID_INCREMENT);
|
||||
}
|
||||
|
||||
info.setParent((View) getParent());
|
||||
info.setParent((View) getParentForAccessibility());
|
||||
info.setEnabled(NumberPicker.this.isEnabled());
|
||||
info.setScrollable(true);
|
||||
Rect boundsInParent = mTempRect;
|
||||
|
||||
Reference in New Issue
Block a user