summaryrefslogtreecommitdiffstats
path: root/core/java/android/view/accessibility
diff options
context:
space:
mode:
authorSvetoslav <svetoslavganov@google.com>2013-06-04 17:22:14 -0700
committerSvetoslav <svetoslavganov@google.com>2013-06-05 15:16:05 -0700
commit6254f4806dd3db53b7380e77fbb183065685573e (patch)
tree554ff88119ae63465cbd4bd51a7e26ef0869cddb /core/java/android/view/accessibility
parent85de5f420efaaf20c9dcaf09035b0fb3980b76ab (diff)
downloadframeworks_base-6254f4806dd3db53b7380e77fbb183065685573e.zip
frameworks_base-6254f4806dd3db53b7380e77fbb183065685573e.tar.gz
frameworks_base-6254f4806dd3db53b7380e77fbb183065685573e.tar.bz2
Optimizing AccessibilityNodeInfo caching.
1. Before we were firing an accessibility event from the common predecessor of views with accessibility related state changes every X amount of time. These events designate that the tree rooted at the source is invalid and should not be cached. However, some of the state changes do not affect the view tree structure and we can just refresh the node instead of evicting and recaching nodes infos for views that did not change. Hence, we need a way to distinguish between a subtree changed over a node changed. Adding a new event type will not work since if say two siblings have local changes and their predecessor fires a window state change event, the client will drop the subtree rooted at the parent including the two views with changes. Subsequent, more specialized events emitted from the two changed siblings will be useless since the parent which did not changed is already evicted from the cache. Conversely, if the specialized events are fired from the two siblings with local changes and they are refreshed in the cache the subsequent window state change event from the common predecessor will force the refreshed nodes to be evicted. Hence, to enable distinction between node being changed and a subtree baing changed while not changing existing behavior, we will fire only window content change event with an additional argument specifying what changed - node or a subtree for now. Also if the changes are local to a view we fire the window content changed event from the view. So, the two siblings will fire such an event independently and the client will know that these are local changes and can just refresh the node. If the changes are structural, then we fire the window state change event from the common predecessor. 2. Added the input type of a text view as one of the properties reported by an AccessibilityNodeInfo. It is nice to prompt the user what input is expected. 3. Added a bundle for optional information to AccessiiblityNodeInfo. For example, it will be used for putting web specific properties that do not map cleanly to Android specific ones in WebView. 4. AccessibilityInteractionController was not taking into account whether the current accessibility focused node is shown before returing it. Hence, a disconnected node would be returned and caching it puts our cahche in an inconsistent state. Change-Id: I8ed19cfb4a70bdd7597c3f105487f1651cffd9e0
Diffstat (limited to 'core/java/android/view/accessibility')
-rw-r--r--core/java/android/view/accessibility/AccessibilityEvent.java46
-rw-r--r--core/java/android/view/accessibility/AccessibilityInteractionClient.java18
-rw-r--r--core/java/android/view/accessibility/AccessibilityNodeInfo.java100
-rw-r--r--core/java/android/view/accessibility/AccessibilityNodeInfoCache.java114
-rw-r--r--core/java/android/view/accessibility/AccessibilityRecord.java2
5 files changed, 201 insertions, 79 deletions
diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java
index dbeca1f..82c8163 100644
--- a/core/java/android/view/accessibility/AccessibilityEvent.java
+++ b/core/java/android/view/accessibility/AccessibilityEvent.java
@@ -326,6 +326,7 @@ import java.util.List;
* <em>Properties:</em></br>
* <ul>
* <li>{@link #getEventType()} - The type of the event.</li>
+ * <li>{@link #getContentChangeType()} - The type of content change.</li>
* <li>{@link #getSource()} - The source info (for registered clients).</li>
* <li>{@link #getClassName()} - The class name of the source.</li>
* <li>{@link #getPackageName()} - The package name of the source.</li>
@@ -661,6 +662,18 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
public static final int TYPE_TOUCH_INTERACTION_END = 0x00200000;
/**
+ * Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event:
+ * The subtree rooted at the source node changed.
+ */
+ public static final int CONTENT_CHANGE_TYPE_SUBTREE = 0;
+
+ /**
+ * Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event:
+ * Only the source node changed.
+ */
+ public static final int CONTENT_CHANGE_TYPE_NODE = 1;
+
+ /**
* Mask for {@link AccessibilityEvent} all types.
*
* @see #TYPE_VIEW_CLICKED
@@ -695,6 +708,7 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
private long mEventTime;
int mMovementGranularity;
int mAction;
+ int mContentChangeType;
private final ArrayList<AccessibilityRecord> mRecords = new ArrayList<AccessibilityRecord>();
@@ -714,6 +728,7 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
mEventType = event.mEventType;
mMovementGranularity = event.mMovementGranularity;
mAction = event.mAction;
+ mContentChangeType = event.mContentChangeType;
mEventTime = event.mEventTime;
mPackageName = event.mPackageName;
}
@@ -777,6 +792,33 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
}
/**
+ * Gets the type of node tree change signaled by an
+ * {@link #TYPE_WINDOW_CONTENT_CHANGED} event.
+ *
+ * @see #CONTENT_CHANGE_TYPE_NODE
+ * @see #CONTENT_CHANGE_TYPE_SUBTREE
+ *
+ * @return The change type.
+ */
+ public int getContentChangeType() {
+ return mContentChangeType;
+ }
+
+ /**
+ * Sets the type of node tree change signaled by an
+ * {@link #TYPE_WINDOW_CONTENT_CHANGED} event.
+ *
+ * @see #CONTENT_CHANGE_TYPE_NODE
+ * @see #CONTENT_CHANGE_TYPE_SUBTREE
+ *
+ * @param changeType The change type.
+ */
+ public void setContentChangeType(int changeType) {
+ enforceNotSealed();
+ mContentChangeType = changeType;
+ }
+
+ /**
* Sets the event type.
*
* @param eventType The event type.
@@ -943,6 +985,7 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
mEventType = 0;
mMovementGranularity = 0;
mAction = 0;
+ mContentChangeType = 0;
mPackageName = null;
mEventTime = 0;
while (!mRecords.isEmpty()) {
@@ -961,6 +1004,7 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
mEventType = parcel.readInt();
mMovementGranularity = parcel.readInt();
mAction = parcel.readInt();
+ mContentChangeType = parcel.readInt();
mPackageName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
mEventTime = parcel.readLong();
mConnectionId = parcel.readInt();
@@ -1013,6 +1057,7 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
parcel.writeInt(mEventType);
parcel.writeInt(mMovementGranularity);
parcel.writeInt(mAction);
+ parcel.writeInt(mContentChangeType);
TextUtils.writeToParcel(mPackageName, parcel, 0);
parcel.writeLong(mEventTime);
parcel.writeInt(mConnectionId);
@@ -1074,6 +1119,7 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
builder.append(super.toString());
if (DEBUG) {
builder.append("\n");
+ builder.append("; ContentChangeType: ").append(mContentChangeType);
builder.append("; sourceWindowId: ").append(mSourceWindowId);
builder.append("; mSourceNodeId: ").append(mSourceNodeId);
for (int i = 0; i < mRecords.size(); i++) {
diff --git a/core/java/android/view/accessibility/AccessibilityInteractionClient.java b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
index 84d7e72..139df3e 100644
--- a/core/java/android/view/accessibility/AccessibilityInteractionClient.java
+++ b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
@@ -163,7 +163,7 @@ public final class AccessibilityInteractionClient
public AccessibilityNodeInfo getRootInActiveWindow(int connectionId) {
return findAccessibilityNodeInfoByAccessibilityId(connectionId,
AccessibilityNodeInfo.ACTIVE_WINDOW_ID, AccessibilityNodeInfo.ROOT_NODE_ID,
- AccessibilityNodeInfo.FLAG_PREFETCH_DESCENDANTS);
+ false, AccessibilityNodeInfo.FLAG_PREFETCH_DESCENDANTS);
}
/**
@@ -177,18 +177,22 @@ public final class AccessibilityInteractionClient
* where to start the search. Use
* {@link android.view.accessibility.AccessibilityNodeInfo#ROOT_NODE_ID}
* to start from the root.
+ * @param bypassCache Whether to bypass the cache while looking for the node.
* @param prefetchFlags flags to guide prefetching.
* @return An {@link AccessibilityNodeInfo} if found, null otherwise.
*/
public AccessibilityNodeInfo findAccessibilityNodeInfoByAccessibilityId(int connectionId,
- int accessibilityWindowId, long accessibilityNodeId, int prefetchFlags) {
+ int accessibilityWindowId, long accessibilityNodeId, boolean bypassCache,
+ int prefetchFlags) {
try {
IAccessibilityServiceConnection connection = getConnection(connectionId);
if (connection != null) {
- AccessibilityNodeInfo cachedInfo = sAccessibilityNodeInfoCache.get(
- accessibilityNodeId);
- if (cachedInfo != null) {
- return cachedInfo;
+ if (!bypassCache) {
+ AccessibilityNodeInfo cachedInfo = sAccessibilityNodeInfoCache.get(
+ accessibilityNodeId);
+ if (cachedInfo != null) {
+ return cachedInfo;
+ }
}
final int interactionId = mInteractionIdCounter.getAndIncrement();
final boolean success = connection.findAccessibilityNodeInfoByAccessibilityId(
@@ -350,7 +354,7 @@ public final class AccessibilityInteractionClient
}
} catch (RemoteException re) {
if (DEBUG) {
- Log.w(LOG_TAG, "Error while calling remote findAccessibilityFocus", re);
+ Log.w(LOG_TAG, "Error while calling remote findFocus", re);
}
}
return null;
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index d9c9b69..750e022 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -21,6 +21,7 @@ import android.graphics.Rect;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
+import android.text.InputType;
import android.util.Pools.SynchronizedPool;
import android.util.SparseLongArray;
import android.view.View;
@@ -482,6 +483,9 @@ public class AccessibilityNodeInfo implements Parcelable {
private int mTextSelectionStart = UNDEFINED;
private int mTextSelectionEnd = UNDEFINED;
+ private int mInputType = InputType.TYPE_NULL;
+
+ private Bundle mBundle;
private int mConnectionId = UNDEFINED;
@@ -594,16 +598,20 @@ public class AccessibilityNodeInfo implements Parcelable {
* since it represents a view that is no longer in the view tree and should
* be recycled.
* </p>
+ *
+ * @param bypassCache Whether to bypass the cache.
* @return Whether the refresh succeeded.
+ *
+ * @hide
*/
- public boolean refresh() {
+ public boolean refresh(boolean bypassCache) {
enforceSealed();
if (!canPerformRequestOverConnection(mSourceNodeId)) {
return false;
}
AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
AccessibilityNodeInfo refreshedInfo = client.findAccessibilityNodeInfoByAccessibilityId(
- mConnectionId, mWindowId, mSourceNodeId, 0);
+ mConnectionId, mWindowId, mSourceNodeId, bypassCache, 0);
if (refreshedInfo == null) {
return false;
}
@@ -613,6 +621,19 @@ public class AccessibilityNodeInfo implements Parcelable {
}
/**
+ * Refreshes this info with the latest state of the view it represents.
+ * <p>
+ * <strong>Note:</strong> If this method returns false this info is obsolete
+ * since it represents a view that is no longer in the view tree and should
+ * be recycled.
+ * </p>
+ * @return Whether the refresh succeeded.
+ */
+ public boolean refresh() {
+ return refresh(false);
+ }
+
+ /**
* @return The ids of the children.
*
* @hide
@@ -652,7 +673,7 @@ public class AccessibilityNodeInfo implements Parcelable {
final long childId = mChildNodeIds.get(index);
AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId, mWindowId,
- childId, FLAG_PREFETCH_DESCENDANTS);
+ childId, false, FLAG_PREFETCH_DESCENDANTS);
}
/**
@@ -878,7 +899,7 @@ public class AccessibilityNodeInfo implements Parcelable {
}
AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId,
- mWindowId, mParentNodeId, FLAG_PREFETCH_DESCENDANTS | FLAG_PREFETCH_SIBLINGS);
+ mWindowId, mParentNodeId, false, FLAG_PREFETCH_DESCENDANTS | FLAG_PREFETCH_SIBLINGS);
}
/**
@@ -1470,7 +1491,7 @@ public class AccessibilityNodeInfo implements Parcelable {
}
AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId,
- mWindowId, mLabelForId, FLAG_PREFETCH_DESCENDANTS | FLAG_PREFETCH_SIBLINGS);
+ mWindowId, mLabelForId, false, FLAG_PREFETCH_DESCENDANTS | FLAG_PREFETCH_SIBLINGS);
}
/**
@@ -1527,7 +1548,7 @@ public class AccessibilityNodeInfo implements Parcelable {
}
AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId,
- mWindowId, mLabeledById, FLAG_PREFETCH_DESCENDANTS | FLAG_PREFETCH_SIBLINGS);
+ mWindowId, mLabeledById, false, FLAG_PREFETCH_DESCENDANTS | FLAG_PREFETCH_SIBLINGS);
}
/**
@@ -1600,6 +1621,52 @@ public class AccessibilityNodeInfo implements Parcelable {
}
/**
+ * Gets the input type of the source as defined by {@link InputType}.
+ *
+ * @return The input type.
+ */
+ public int getInputType() {
+ return mInputType;
+ }
+
+ /**
+ * Sets the input type of the source as defined by {@link InputType}.
+ * <p>
+ * <strong>Note:</strong> Cannot be called from an
+ * {@link android.accessibilityservice.AccessibilityService}.
+ * This class is made immutable before being delivered to an
+ * AccessibilityService.
+ * </p>
+ *
+ * @param inputType The input type.
+ *
+ * @throws IllegalStateException If called from an AccessibilityService.
+ */
+ public void setInputType(int inputType) {
+ mInputType = inputType;
+ }
+
+ /**
+ * Gets an optional bundle with additional data. The bundle
+ * is lazily created and never <code>null</code>.
+ * <p>
+ * <strong>Note:</strong> It is recommended to use the package
+ * name of your application as a prefix for the keys to avoid
+ * collisions which may confuse an accessibility service if the
+ * same key has different meaning when emitted from different
+ * applications.
+ * </p>
+ *
+ * @return The bundle.
+ */
+ public Bundle getBundle() {
+ if (mBundle == null) {
+ mBundle = new Bundle();
+ }
+ return mBundle;
+ }
+
+ /**
* Gets the value of a boolean property.
*
* @param property The property.
@@ -1845,6 +1912,14 @@ public class AccessibilityNodeInfo implements Parcelable {
parcel.writeInt(mTextSelectionStart);
parcel.writeInt(mTextSelectionEnd);
+ parcel.writeInt(mInputType);
+
+ if (mBundle != null) {
+ parcel.writeInt(1);
+ parcel.writeBundle(mBundle);
+ } else {
+ parcel.writeInt(0);
+ }
// Since instances of this class are fetched via synchronous i.e. blocking
// calls in IPCs we always recycle as soon as the instance is marshaled.
@@ -1880,6 +1955,10 @@ public class AccessibilityNodeInfo implements Parcelable {
}
mTextSelectionStart = other.mTextSelectionStart;
mTextSelectionEnd = other.mTextSelectionEnd;
+ mInputType = other.mInputType;
+ if (other.mBundle != null && !other.mBundle.isEmpty()) {
+ getBundle().putAll(other.mBundle);
+ }
}
/**
@@ -1927,6 +2006,11 @@ public class AccessibilityNodeInfo implements Parcelable {
mTextSelectionStart = parcel.readInt();
mTextSelectionEnd = parcel.readInt();
+ mInputType = parcel.readInt();
+
+ if (parcel.readInt() == 1) {
+ getBundle().putAll(parcel.readBundle());
+ }
}
/**
@@ -1953,6 +2037,10 @@ public class AccessibilityNodeInfo implements Parcelable {
mActions = 0;
mTextSelectionStart = UNDEFINED;
mTextSelectionEnd = UNDEFINED;
+ mInputType = InputType.TYPE_NULL;
+ if (mBundle != null) {
+ mBundle.clear();
+ }
}
/**
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfoCache.java b/core/java/android/view/accessibility/AccessibilityNodeInfoCache.java
index 28518aa..dded74c 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfoCache.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfoCache.java
@@ -39,9 +39,9 @@ public class AccessibilityNodeInfoCache {
private static final boolean ENABLED = true;
- private static final boolean DEBUG = false;
+ private static final boolean DEBUG = true;
- private static final boolean CHECK_INTEGRITY = true;
+ private static final boolean CHECK_INTEGRITY_IF_DEBUGGABLE_BUILD = true;
private final Object mLock = new Object();
@@ -67,16 +67,12 @@ public class AccessibilityNodeInfoCache {
if (ENABLED) {
final int eventType = event.getEventType();
switch (eventType) {
- case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED: {
- // New window so we clear the cache.
- mWindowId = event.getWindowId();
- clear();
- } break;
+ case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED:
case AccessibilityEvent.TYPE_VIEW_HOVER_ENTER:
case AccessibilityEvent.TYPE_VIEW_HOVER_EXIT: {
final int windowId = event.getWindowId();
+ // If a new window, we clear the cache.
if (mWindowId != windowId) {
- // New window so we clear the cache.
mWindowId = windowId;
clear();
}
@@ -87,34 +83,48 @@ public class AccessibilityNodeInfoCache {
case AccessibilityEvent.TYPE_VIEW_SELECTED:
case AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED:
case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
- // Since we prefetch the descendants of a node we
- // just remove the entire subtree since when the node
- // is fetched we will gets its descendant anyway.
- synchronized (mLock) {
- final long sourceId = event.getSourceNodeId();
- clearSubTreeLocked(sourceId);
- if (eventType == AccessibilityEvent.TYPE_VIEW_FOCUSED) {
- clearSubtreeWithOldInputFocusLocked(sourceId);
- }
- if (eventType == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED) {
- clearSubtreeWithOldAccessibilityFocusLocked(sourceId);
- }
- }
+ refreshCachedNode(event.getSourceNodeId());
} break;
- case AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED:
case AccessibilityEvent.TYPE_VIEW_SCROLLED: {
+ clearSubTreeLocked(event.getSourceNodeId());
+ } break;
+ case AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED: {
synchronized (mLock) {
- final long accessibilityNodeId = event.getSourceNodeId();
- clearSubTreeLocked(accessibilityNodeId);
+ final long sourceId = event.getSourceNodeId();
+ if (event.getContentChangeType()
+ == AccessibilityEvent.CONTENT_CHANGE_TYPE_NODE) {
+ refreshCachedNode(sourceId);
+ } else {
+ clearSubTreeLocked(sourceId);
+ }
}
} break;
}
- if (Build.IS_DEBUGGABLE && CHECK_INTEGRITY) {
+ if (Build.IS_DEBUGGABLE && CHECK_INTEGRITY_IF_DEBUGGABLE_BUILD) {
checkIntegrity();
}
}
}
+ private void refreshCachedNode(long sourceId) {
+ if (DEBUG) {
+ Log.i(LOG_TAG, "Refresing cached node.");
+ }
+ synchronized (mLock) {
+ AccessibilityNodeInfo cachedInfo = mCacheImpl.get(sourceId);
+ // If the source is not in the cache - nothing to do.
+ if (cachedInfo == null) {
+ return;
+ }
+ // The node changed so we will just refresh it right now.
+ if (cachedInfo.refresh(false)) {
+ return;
+ }
+ // Weird, we could not refresh. Just evict the entire sub-tree.
+ clearSubTreeLocked(sourceId);
+ }
+ }
+
/**
* Gets a cached {@link AccessibilityNodeInfo} given its accessibility node id.
*
@@ -131,7 +141,7 @@ public class AccessibilityNodeInfoCache {
info = AccessibilityNodeInfo.obtain(info);
}
if (DEBUG) {
- Log.i(LOG_TAG, "get(" + accessibilityNodeId + ") = " + info);
+// Log.i(LOG_TAG, "get(" + accessibilityNodeId + ") = " + info);
}
return info;
}
@@ -149,7 +159,7 @@ public class AccessibilityNodeInfoCache {
if (ENABLED) {
synchronized(mLock) {
if (DEBUG) {
- Log.i(LOG_TAG, "add(" + info + ")");
+// Log.i(LOG_TAG, "add(" + info + ")");
}
final long sourceId = info.getSourceNodeId();
@@ -212,6 +222,13 @@ public class AccessibilityNodeInfoCache {
* @param rootNodeId The root id.
*/
private void clearSubTreeLocked(long rootNodeId) {
+ if (DEBUG) {
+ Log.i(LOG_TAG, "Clearing cached subtree.");
+ }
+ clearSubTreeRecursiveLocked(rootNodeId);
+ }
+
+ private void clearSubTreeRecursiveLocked(long rootNodeId) {
AccessibilityNodeInfo current = mCacheImpl.get(rootNodeId);
if (current == null) {
return;
@@ -221,41 +238,7 @@ public class AccessibilityNodeInfoCache {
final int childCount = childNodeIds.size();
for (int i = 0; i < childCount; i++) {
final long childNodeId = childNodeIds.valueAt(i);
- clearSubTreeLocked(childNodeId);
- }
- }
-
- /**
- * We are enforcing the invariant for a single input focus.
- *
- * @param currentInputFocusId The current input focused node.
- */
- private void clearSubtreeWithOldInputFocusLocked(long currentInputFocusId) {
- final int cacheSize = mCacheImpl.size();
- for (int i = 0; i < cacheSize; i++) {
- AccessibilityNodeInfo info = mCacheImpl.valueAt(i);
- final long infoSourceId = info.getSourceNodeId();
- if (infoSourceId != currentInputFocusId && info.isFocused()) {
- clearSubTreeLocked(infoSourceId);
- return;
- }
- }
- }
-
- /**
- * We are enforcing the invariant for a single accessibility focus.
- *
- * @param currentAccessibilityFocusId The current input focused node.
- */
- private void clearSubtreeWithOldAccessibilityFocusLocked(long currentAccessibilityFocusId) {
- final int cacheSize = mCacheImpl.size();
- for (int i = 0; i < cacheSize; i++) {
- AccessibilityNodeInfo info = mCacheImpl.valueAt(i);
- final long infoSourceId = info.getSourceNodeId();
- if (infoSourceId != currentAccessibilityFocusId && info.isAccessibilityFocused()) {
- clearSubTreeLocked(infoSourceId);
- return;
- }
+ clearSubTreeRecursiveLocked(childNodeId);
}
}
@@ -327,16 +310,17 @@ public class AccessibilityNodeInfoCache {
}
// Check for disconnected nodes or ones from another window.
- final int cacheSize = mCacheImpl.size();
- for (int i = 0; i < cacheSize; i++) {
+ for (int i = 0; i < mCacheImpl.size(); i++) {
AccessibilityNodeInfo info = mCacheImpl.valueAt(i);
if (!seen.contains(info)) {
if (info.getWindowId() == windowId) {
- Log.e(LOG_TAG, "Disconneced node: ");
+ Log.e(LOG_TAG, "Disconneced node: " + info);
} else {
Log.e(LOG_TAG, "Node from: " + info.getWindowId() + " not from:"
+ windowId + " " + info);
}
+ mCacheImpl.removeAt(i);
+ i--;
}
}
}
diff --git a/core/java/android/view/accessibility/AccessibilityRecord.java b/core/java/android/view/accessibility/AccessibilityRecord.java
index 7147c57..3fcd218 100644
--- a/core/java/android/view/accessibility/AccessibilityRecord.java
+++ b/core/java/android/view/accessibility/AccessibilityRecord.java
@@ -164,7 +164,7 @@ public class AccessibilityRecord {
}
AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId, mSourceWindowId,
- mSourceNodeId, GET_SOURCE_PREFETCH_FLAGS);
+ mSourceNodeId, false, GET_SOURCE_PREFETCH_FLAGS);
}
/**