Skip to content

Commit 42d840b

Browse files
sganovAndroid (Google) Code Review
authored andcommitted
Merge "Fixing issues with the AccessibilityNodeInfo cache."
2 parents 6caa030 + 57c7fd5 commit 42d840b

File tree

9 files changed

+310
-176
lines changed

9 files changed

+310
-176
lines changed

core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,12 @@ interface IAccessibilityServiceConnection {
4242
* @param interactionId The id of the interaction for matching with the callback result.
4343
* @param callback Callback which to receive the result.
4444
* @param threadId The id of the calling thread.
45+
* @param prefetchFlags flags to guide prefetching.
4546
* @return The current window scale, where zero means a failure.
4647
*/
4748
float findAccessibilityNodeInfoByAccessibilityId(int accessibilityWindowId,
4849
long accessibilityNodeId, int interactionId,
49-
IAccessibilityInteractionConnectionCallback callback, long threadId);
50+
IAccessibilityInteractionConnectionCallback callback, long threadId, int prefetchFlags);
5051

5152
/**
5253
* Finds {@link android.view.accessibility.AccessibilityNodeInfo}s by View text.

core/java/android/accessibilityservice/UiTestAutomationBridge.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,11 @@ public class UiTestAutomationBridge {
5757

5858
public static final int UNDEFINED = -1;
5959

60+
private static final int FIND_ACCESSIBILITY_NODE_INFO_PREFETCH_FLAGS =
61+
AccessibilityNodeInfo.FLAG_PREFETCH_PREDECESSORS
62+
| AccessibilityNodeInfo.FLAG_PREFETCH_SIBLINGS
63+
| AccessibilityNodeInfo.FLAG_PREFETCH_DESCENDANTS;
64+
6065
private final Object mLock = new Object();
6166

6267
private volatile int mConnectionId = AccessibilityInteractionClient.NO_ID;
@@ -351,13 +356,15 @@ public AccessibilityNodeInfo findAccessibilityNodeInfoByAccessibilityId(
351356
ensureValidConnection(connectionId);
352357
return AccessibilityInteractionClient.getInstance()
353358
.findAccessibilityNodeInfoByAccessibilityId(mConnectionId,
354-
accessibilityWindowId, accessibilityNodeId);
359+
accessibilityWindowId, accessibilityNodeId,
360+
FIND_ACCESSIBILITY_NODE_INFO_PREFETCH_FLAGS);
355361
}
356362

357363
/**
358364
* Finds an {@link AccessibilityNodeInfo} by View id in the active
359365
* window. The search is performed from the root node.
360366
*
367+
* @param viewId The id of a View.
361368
* @return The current window scale, where zero means a failure.
362369
*/
363370
public AccessibilityNodeInfo findAccessibilityNodeInfoByViewIdInActiveWindow(int viewId) {
@@ -373,6 +380,7 @@ public AccessibilityNodeInfo findAccessibilityNodeInfoByViewIdInActiveWindow(int
373380
* {@link #ACTIVE_WINDOW_ID} to query the currently active window.
374381
* @param accessibilityNodeId A unique view id or virtual descendant id from
375382
* where to start the search. Use {@link #ROOT_NODE_ID} to start from the root.
383+
* @param viewId The id of a View.
376384
* @return The current window scale, where zero means a failure.
377385
*/
378386
public AccessibilityNodeInfo findAccessibilityNodeInfoByViewId(int accessibilityWindowId,
@@ -460,7 +468,7 @@ public AccessibilityNodeInfo getRootAccessibilityNodeInfoInActiveWindow() {
460468
ensureValidConnection(connectionId);
461469
return AccessibilityInteractionClient.getInstance()
462470
.findAccessibilityNodeInfoByAccessibilityId(connectionId, ACTIVE_WINDOW_ID,
463-
ROOT_NODE_ID);
471+
ROOT_NODE_ID, AccessibilityNodeInfo.FLAG_PREFETCH_DESCENDANTS);
464472
}
465473

466474
private void ensureValidConnection(int connectionId) {

core/java/android/view/ViewRootImpl.java

Lines changed: 212 additions & 87 deletions
Large diffs are not rendered by default.

core/java/android/view/accessibility/AccessibilityInteractionClient.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
import android.util.Log;
2525
import android.util.LongSparseArray;
2626
import android.util.SparseArray;
27-
import android.view.AccessibilityNodeInfoCache;
2827

2928
import java.util.ArrayList;
3029
import java.util.Collections;
@@ -102,7 +101,7 @@ public final class AccessibilityInteractionClient
102101
// The connection cache is shared between all interrogating threads since
103102
// at any given time there is only one window allowing querying.
104103
private static final AccessibilityNodeInfoCache sAccessibilityNodeInfoCache =
105-
AccessibilityNodeInfoCache.newSynchronizedAccessibilityNodeInfoCache();
104+
new AccessibilityNodeInfoCache();
106105

107106
/**
108107
* @return The client for the current thread.
@@ -159,10 +158,11 @@ public void setSameThreadMessage(Message message) {
159158
* where to start the search. Use
160159
* {@link android.view.accessibility.AccessibilityNodeInfo#ROOT_NODE_ID}
161160
* to start from the root.
161+
* @param prefetchFlags flags to guide prefetching.
162162
* @return An {@link AccessibilityNodeInfo} if found, null otherwise.
163163
*/
164164
public AccessibilityNodeInfo findAccessibilityNodeInfoByAccessibilityId(int connectionId,
165-
int accessibilityWindowId, long accessibilityNodeId) {
165+
int accessibilityWindowId, long accessibilityNodeId, int prefetchFlags) {
166166
try {
167167
IAccessibilityServiceConnection connection = getConnection(connectionId);
168168
if (connection != null) {
@@ -174,7 +174,7 @@ public AccessibilityNodeInfo findAccessibilityNodeInfoByAccessibilityId(int conn
174174
final int interactionId = mInteractionIdCounter.getAndIncrement();
175175
final float windowScale = connection.findAccessibilityNodeInfoByAccessibilityId(
176176
accessibilityWindowId, accessibilityNodeId, interactionId, this,
177-
Thread.currentThread().getId());
177+
Thread.currentThread().getId(), prefetchFlags);
178178
// If the scale is zero the call has failed.
179179
if (windowScale > 0) {
180180
List<AccessibilityNodeInfo> infos = getFindAccessibilityNodeInfosResultAndClear(

core/java/android/view/accessibility/AccessibilityNodeInfo.java

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,15 @@ public class AccessibilityNodeInfo implements Parcelable {
6161
/** @hide */
6262
public static final int ACTIVE_WINDOW_ID = UNDEFINED;
6363

64+
/** @hide */
65+
public static final int FLAG_PREFETCH_PREDECESSORS = 0x00000001;
66+
67+
/** @hide */
68+
public static final int FLAG_PREFETCH_SIBLINGS = 0x00000002;
69+
70+
/** @hide */
71+
public static final int FLAG_PREFETCH_DESCENDANTS = 0x00000003;
72+
6473
// Actions.
6574

6675
/**
@@ -181,7 +190,7 @@ public static long makeNodeId(int accessibilityViewId, int virtualDescendantId)
181190
private CharSequence mText;
182191
private CharSequence mContentDescription;
183192

184-
private SparseLongArray mChildIds = new SparseLongArray();
193+
private SparseLongArray mChildNodeIds = new SparseLongArray();
185194
private int mActions;
186195

187196
private int mConnectionId = UNDEFINED;
@@ -243,13 +252,22 @@ public int getWindowId() {
243252
return mWindowId;
244253
}
245254

255+
/**
256+
* @return The ids of the children.
257+
*
258+
* @hide
259+
*/
260+
public SparseLongArray getChildNodeIds() {
261+
return mChildNodeIds;
262+
}
263+
246264
/**
247265
* Gets the number of children.
248266
*
249267
* @return The child count.
250268
*/
251269
public int getChildCount() {
252-
return mChildIds.size();
270+
return mChildNodeIds.size();
253271
}
254272

255273
/**
@@ -271,9 +289,10 @@ public AccessibilityNodeInfo getChild(int index) {
271289
if (!canPerformRequestOverConnection(mSourceNodeId)) {
272290
return null;
273291
}
274-
final long childId = mChildIds.get(index);
292+
final long childId = mChildNodeIds.get(index);
275293
AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
276-
return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId, mWindowId, childId);
294+
return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId, mWindowId,
295+
childId, FLAG_PREFETCH_DESCENDANTS);
277296
}
278297

279298
/**
@@ -308,11 +327,11 @@ public void addChild(View child) {
308327
*/
309328
public void addChild(View root, int virtualDescendantId) {
310329
enforceNotSealed();
311-
final int index = mChildIds.size();
330+
final int index = mChildNodeIds.size();
312331
final int rootAccessibilityViewId =
313332
(root != null) ? root.getAccessibilityViewId() : UNDEFINED;
314333
final long childNodeId = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
315-
mChildIds.put(index, childNodeId);
334+
mChildNodeIds.put(index, childNodeId);
316335
}
317336

318337
/**
@@ -408,7 +427,16 @@ public AccessibilityNodeInfo getParent() {
408427
}
409428
AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
410429
return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId,
411-
mWindowId, mParentNodeId);
430+
mWindowId, mParentNodeId, FLAG_PREFETCH_DESCENDANTS | FLAG_PREFETCH_SIBLINGS);
431+
}
432+
433+
/**
434+
* @return The parent node id.
435+
*
436+
* @hide
437+
*/
438+
public long getParentNodeId() {
439+
return mParentNodeId;
412440
}
413441

414442
/**
@@ -1070,7 +1098,7 @@ public void writeToParcel(Parcel parcel, int flags) {
10701098
parcel.writeLong(mParentNodeId);
10711099
parcel.writeInt(mConnectionId);
10721100

1073-
SparseLongArray childIds = mChildIds;
1101+
SparseLongArray childIds = mChildNodeIds;
10741102
final int childIdsSize = childIds.size();
10751103
parcel.writeInt(childIdsSize);
10761104
for (int i = 0; i < childIdsSize; i++) {
@@ -1120,7 +1148,7 @@ private void init(AccessibilityNodeInfo other) {
11201148
mContentDescription = other.mContentDescription;
11211149
mActions= other.mActions;
11221150
mBooleanProperties = other.mBooleanProperties;
1123-
mChildIds = other.mChildIds.clone();
1151+
mChildNodeIds = other.mChildNodeIds.clone();
11241152
}
11251153

11261154
/**
@@ -1135,7 +1163,7 @@ private void initFromParcel(Parcel parcel) {
11351163
mParentNodeId = parcel.readLong();
11361164
mConnectionId = parcel.readInt();
11371165

1138-
SparseLongArray childIds = mChildIds;
1166+
SparseLongArray childIds = mChildNodeIds;
11391167
final int childrenSize = parcel.readInt();
11401168
for (int i = 0; i < childrenSize; i++) {
11411169
final long childId = parcel.readLong();
@@ -1171,7 +1199,7 @@ private void clear() {
11711199
mParentNodeId = ROOT_NODE_ID;
11721200
mWindowId = UNDEFINED;
11731201
mConnectionId = UNDEFINED;
1174-
mChildIds.clear();
1202+
mChildNodeIds.clear();
11751203
mBoundsInParent.set(0, 0, 0, 0);
11761204
mBoundsInScreen.set(0, 0, 0, 0);
11771205
mBooleanProperties = 0;
@@ -1249,7 +1277,7 @@ public String toString() {
12491277
builder.append("; accessibilityViewId: " + getAccessibilityViewId(mSourceNodeId));
12501278
builder.append("; virtualDescendantId: " + getVirtualDescendantId(mSourceNodeId));
12511279
builder.append("; mParentNodeId: " + mParentNodeId);
1252-
SparseLongArray childIds = mChildIds;
1280+
SparseLongArray childIds = mChildNodeIds;
12531281
builder.append("; childAccessibilityIds: [");
12541282
for (int i = 0, count = childIds.size(); i < count; i++) {
12551283
builder.append(childIds.valueAt(i));

core/java/android/view/AccessibilityNodeInfoCache.java renamed to core/java/android/view/accessibility/AccessibilityNodeInfoCache.java

Lines changed: 32 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,11 @@
1414
* limitations under the License.
1515
*/
1616

17-
package android.view;
17+
package android.view.accessibility;
1818

1919
import android.os.Process;
2020
import android.util.Log;
2121
import android.util.LongSparseArray;
22-
import android.view.accessibility.AccessibilityEvent;
23-
import android.view.accessibility.AccessibilityNodeInfo;
2422

2523
/**
2624
* Simple cache for AccessibilityNodeInfos. The cache is mapping an
@@ -38,53 +36,11 @@ public class AccessibilityNodeInfoCache {
3836

3937
private static final boolean DEBUG = false;
4038

41-
/**
42-
* @return A new <strong>not synchronized</strong> AccessibilityNodeInfoCache.
43-
*/
44-
public static AccessibilityNodeInfoCache newAccessibilityNodeInfoCache() {
45-
return new AccessibilityNodeInfoCache();
46-
}
47-
48-
/**
49-
* @return A new <strong>synchronized</strong> AccessibilityNodeInfoCache.
50-
*/
51-
public static AccessibilityNodeInfoCache newSynchronizedAccessibilityNodeInfoCache() {
52-
return new AccessibilityNodeInfoCache() {
53-
private final Object mLock = new Object();
54-
55-
@Override
56-
public void clear() {
57-
synchronized(mLock) {
58-
super.clear();
59-
}
60-
}
61-
62-
@Override
63-
public AccessibilityNodeInfo get(long accessibilityNodeId) {
64-
synchronized(mLock) {
65-
return super.get(accessibilityNodeId);
66-
}
67-
}
68-
69-
@Override
70-
public void put(long accessibilityNodeId, AccessibilityNodeInfo info) {
71-
synchronized(mLock) {
72-
super.put(accessibilityNodeId, info);
73-
}
74-
}
75-
76-
@Override
77-
public void remove(long accessibilityNodeId) {
78-
synchronized(mLock) {
79-
super.remove(accessibilityNodeId);
80-
}
81-
}
82-
};
83-
}
39+
private final Object mLock = new Object();
8440

8541
private final LongSparseArray<AccessibilityNodeInfo> mCacheImpl;
8642

87-
private AccessibilityNodeInfoCache() {
43+
public AccessibilityNodeInfoCache() {
8844
if (ENABLED) {
8945
mCacheImpl = new LongSparseArray<AccessibilityNodeInfo>();
9046
} else {
@@ -124,13 +80,15 @@ public void onAccessibilityEvent(AccessibilityEvent event) {
12480
*/
12581
public AccessibilityNodeInfo get(long accessibilityNodeId) {
12682
if (ENABLED) {
127-
if (DEBUG) {
128-
AccessibilityNodeInfo info = mCacheImpl.get(accessibilityNodeId);
129-
Log.i(LOG_TAG, "Process: " + Process.myPid() +
130-
" get(" + accessibilityNodeId + ") = " + info);
131-
return info;
132-
} else {
133-
return mCacheImpl.get(accessibilityNodeId);
83+
synchronized(mLock) {
84+
if (DEBUG) {
85+
AccessibilityNodeInfo info = mCacheImpl.get(accessibilityNodeId);
86+
Log.i(LOG_TAG, "Process: " + Process.myPid() +
87+
" get(" + accessibilityNodeId + ") = " + info);
88+
return info;
89+
} else {
90+
return mCacheImpl.get(accessibilityNodeId);
91+
}
13492
}
13593
} else {
13694
return null;
@@ -145,11 +103,13 @@ public AccessibilityNodeInfo get(long accessibilityNodeId) {
145103
*/
146104
public void put(long accessibilityNodeId, AccessibilityNodeInfo info) {
147105
if (ENABLED) {
148-
if (DEBUG) {
149-
Log.i(LOG_TAG, "Process: " + Process.myPid()
150-
+ " put(" + accessibilityNodeId + ", " + info + ")");
106+
synchronized(mLock) {
107+
if (DEBUG) {
108+
Log.i(LOG_TAG, "Process: " + Process.myPid()
109+
+ " put(" + accessibilityNodeId + ", " + info + ")");
110+
}
111+
mCacheImpl.put(accessibilityNodeId, info);
151112
}
152-
mCacheImpl.put(accessibilityNodeId, info);
153113
}
154114
}
155115

@@ -161,7 +121,9 @@ public void put(long accessibilityNodeId, AccessibilityNodeInfo info) {
161121
*/
162122
public boolean containsKey(long accessibilityNodeId) {
163123
if (ENABLED) {
164-
return (mCacheImpl.indexOfKey(accessibilityNodeId) >= 0);
124+
synchronized(mLock) {
125+
return (mCacheImpl.indexOfKey(accessibilityNodeId) >= 0);
126+
}
165127
} else {
166128
return false;
167129
}
@@ -174,11 +136,13 @@ public boolean containsKey(long accessibilityNodeId) {
174136
*/
175137
public void remove(long accessibilityNodeId) {
176138
if (ENABLED) {
177-
if (DEBUG) {
178-
Log.i(LOG_TAG, "Process: " + Process.myPid()
179-
+ " remove(" + accessibilityNodeId + ")");
139+
synchronized(mLock) {
140+
if (DEBUG) {
141+
Log.i(LOG_TAG, "Process: " + Process.myPid()
142+
+ " remove(" + accessibilityNodeId + ")");
143+
}
144+
mCacheImpl.remove(accessibilityNodeId);
180145
}
181-
mCacheImpl.remove(accessibilityNodeId);
182146
}
183147
}
184148

@@ -187,10 +151,12 @@ public void remove(long accessibilityNodeId) {
187151
*/
188152
public void clear() {
189153
if (ENABLED) {
190-
if (DEBUG) {
191-
Log.i(LOG_TAG, "Process: " + Process.myPid() + "clear()");
154+
synchronized(mLock) {
155+
if (DEBUG) {
156+
Log.i(LOG_TAG, "Process: " + Process.myPid() + "clear()");
157+
}
158+
mCacheImpl.clear();
192159
}
193-
mCacheImpl.clear();
194160
}
195161
}
196162
}

0 commit comments

Comments
 (0)