Merge "UI test automation cannot get the root node and gets null children."
diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java
index 54c62ee..e3f5b96 100644
--- a/core/java/android/view/AccessibilityInteractionController.java
+++ b/core/java/android/view/AccessibilityInteractionController.java
@@ -58,9 +58,14 @@
private final AccessibilityNodePrefetcher mPrefetcher;
+ private final long mMyLooperThreadId;
+
+ private final int mMyProcessId;
+
public AccessibilityInteractionController(ViewRootImpl viewRootImpl) {
- // mView is never null - the caller has already checked.
- Looper looper = viewRootImpl.mView.mContext.getMainLooper();
+ Looper looper = viewRootImpl.mHandler.getLooper();
+ mMyLooperThreadId = looper.getThread().getId();
+ mMyProcessId = Process.myPid();
mHandler = new PrivateHandler(looper);
mViewRootImpl = viewRootImpl;
mPrefetcher = new AccessibilityNodePrefetcher();
@@ -137,8 +142,7 @@
// thread in this process, set the message as a static reference so
// after this call completes the same thread but in the interrogating
// client can handle the message to generate the result.
- if (interrogatingPid == Process.myPid()
- && interrogatingTid == Looper.getMainLooper().getThread().getId()) {
+ if (interrogatingPid == mMyProcessId && interrogatingTid == mMyLooperThreadId) {
AccessibilityInteractionClient.getInstanceForThread(
interrogatingTid).setSameThreadMessage(message);
} else {
@@ -169,7 +173,7 @@
} else {
root = findViewByAccessibilityId(accessibilityViewId);
}
- if (root != null && isDisplayedOnScreen(root)) {
+ if (root != null && root.isDisplayedOnScreen()) {
mPrefetcher.prefetchAccessibilityNodeInfos(root, virtualDescendantId, flags, infos);
}
} finally {
@@ -199,8 +203,7 @@
// thread in this process, set the message as a static reference so
// after this call completes the same thread but in the interrogating
// client can handle the message to generate the result.
- if (interrogatingPid == Process.myPid()
- && interrogatingTid == Looper.getMainLooper().getThread().getId()) {
+ if (interrogatingPid == mMyProcessId && interrogatingTid == mMyLooperThreadId) {
AccessibilityInteractionClient.getInstanceForThread(
interrogatingTid).setSameThreadMessage(message);
} else {
@@ -232,7 +235,7 @@
}
if (root != null) {
View target = root.findViewById(viewId);
- if (target != null && isDisplayedOnScreen(target)) {
+ if (target != null && target.isDisplayedOnScreen()) {
info = target.createAccessibilityNodeInfo();
}
}
@@ -263,8 +266,7 @@
// thread in this process, set the message as a static reference so
// after this call completes the same thread but in the interrogating
// client can handle the message to generate the result.
- if (interrogatingPid == Process.myPid()
- && interrogatingTid == Looper.getMainLooper().getThread().getId()) {
+ if (interrogatingPid == mMyProcessId && interrogatingTid == mMyLooperThreadId) {
AccessibilityInteractionClient.getInstanceForThread(
interrogatingTid).setSameThreadMessage(message);
} else {
@@ -295,7 +297,7 @@
} else {
root = mViewRootImpl.mView;
}
- if (root != null && isDisplayedOnScreen(root)) {
+ if (root != null && root.isDisplayedOnScreen()) {
AccessibilityNodeProvider provider = root.getAccessibilityNodeProvider();
if (provider != null) {
infos = provider.findAccessibilityNodeInfosByText(text,
@@ -312,7 +314,7 @@
final int viewCount = foundViews.size();
for (int i = 0; i < viewCount; i++) {
View foundView = foundViews.get(i);
- if (isDisplayedOnScreen(foundView)) {
+ if (foundView.isDisplayedOnScreen()) {
provider = foundView.getAccessibilityNodeProvider();
if (provider != null) {
List<AccessibilityNodeInfo> infosFromProvider =
@@ -356,8 +358,7 @@
// thread in this process, set the message as a static reference so
// after this call completes the same thread but in the interrogating
// client can handle the message to generate the result.
- if (interogatingPid == Process.myPid()
- && interrogatingTid == Looper.getMainLooper().getThread().getId()) {
+ if (interogatingPid == mMyProcessId && interrogatingTid == mMyLooperThreadId) {
AccessibilityInteractionClient.getInstanceForThread(
interrogatingTid).setSameThreadMessage(message);
} else {
@@ -388,7 +389,7 @@
} else {
root = mViewRootImpl.mView;
}
- if (root != null && isDisplayedOnScreen(root)) {
+ if (root != null && root.isDisplayedOnScreen()) {
switch (focusType) {
case AccessibilityNodeInfo.FOCUS_ACCESSIBILITY: {
View host = mViewRootImpl.mAccessibilityFocusedHost;
@@ -409,7 +410,7 @@
case AccessibilityNodeInfo.FOCUS_INPUT: {
// Input focus cannot go to virtual views.
View target = root.findFocus();
- if (target != null && isDisplayedOnScreen(target)) {
+ if (target != null && target.isDisplayedOnScreen()) {
focused = target.createAccessibilityNodeInfo();
}
} break;
@@ -444,8 +445,7 @@
// thread in this process, set the message as a static reference so
// after this call completes the same thread but in the interrogating
// client can handle the message to generate the result.
- if (interogatingPid == Process.myPid()
- && interrogatingTid == Looper.getMainLooper().getThread().getId()) {
+ if (interogatingPid == mMyProcessId && interrogatingTid == mMyLooperThreadId) {
AccessibilityInteractionClient.getInstanceForThread(
interrogatingTid).setSameThreadMessage(message);
} else {
@@ -476,7 +476,7 @@
} else {
root = mViewRootImpl.mView;
}
- if (root != null && isDisplayedOnScreen(root)) {
+ if (root != null && root.isDisplayedOnScreen()) {
if ((direction & View.FOCUS_ACCESSIBILITY) == View.FOCUS_ACCESSIBILITY) {
AccessibilityNodeProvider provider = root.getAccessibilityNodeProvider();
if (provider != null) {
@@ -530,8 +530,7 @@
// thread in this process, set the message as a static reference so
// after this call completes the same thread but in the interrogating
// client can handle the message to generate the result.
- if (interogatingPid == Process.myPid()
- && interrogatingTid == Looper.getMainLooper().getThread().getId()) {
+ if (interogatingPid == mMyProcessId && interrogatingTid == mMyLooperThreadId) {
AccessibilityInteractionClient.getInstanceForThread(
interrogatingTid).setSameThreadMessage(message);
} else {
@@ -562,7 +561,7 @@
} else {
target = mViewRootImpl.mView;
}
- if (target != null && isDisplayedOnScreen(target)) {
+ if (target != null && target.isDisplayedOnScreen()) {
AccessibilityNodeProvider provider = target.getAccessibilityNodeProvider();
if (provider != null) {
succeeded = provider.performAccessibilityAction(action, virtualDescendantId);
@@ -586,31 +585,13 @@
return null;
}
View foundView = root.findViewByAccessibilityId(accessibilityId);
- if (foundView != null && !isDisplayedOnScreen(foundView)) {
+ if (foundView != null && !foundView.isDisplayedOnScreen()) {
return null;
}
return foundView;
}
/**
- * Computes whether a view is visible on the screen.
- *
- * @param view The view to check.
- * @return Whether the view is visible on the screen.
- */
- private boolean isDisplayedOnScreen(View view) {
- // The first two checks are made also made by isShown() which
- // however traverses the tree up to the parent to catch that.
- // Therefore, we do some fail fast check to minimize the up
- // tree traversal.
- return (view.mAttachInfo != null
- && view.mAttachInfo.mWindowVisibility == View.VISIBLE
- && view.getAlpha() > 0
- && view.isShown()
- && view.getGlobalVisibleRect(mViewRootImpl.mTempRect));
- }
-
- /**
* This class encapsulates a prefetching strategy for the accessibility APIs for
* querying window content. It is responsible to prefetch a batch of
* AccessibilityNodeInfos in addition to the one for a requested node.
@@ -684,7 +665,7 @@
}
View child = children.getChildAt(i);
if (child.getAccessibilityViewId() != current.getAccessibilityViewId()
- && isDisplayedOnScreen(child)) {
+ && child.isDisplayedOnScreen()) {
AccessibilityNodeInfo info = null;
AccessibilityNodeProvider provider = child.getAccessibilityNodeProvider();
if (provider == null) {
@@ -718,7 +699,7 @@
return;
}
View child = children.getChildAt(i);
- if ( isDisplayedOnScreen(child)) {
+ if (child.isDisplayedOnScreen()) {
AccessibilityNodeProvider provider = child.getAccessibilityNodeProvider();
if (provider == null) {
AccessibilityNodeInfo info = child.createAccessibilityNodeInfo();
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index ab3413e..ce02113 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -4680,6 +4680,23 @@
}
/**
+ * Computes whether this view is visible on the screen.
+ *
+ * @return Whether the view is visible on the screen.
+ */
+ boolean isDisplayedOnScreen() {
+ // The first two checks are made also made by isShown() which
+ // however traverses the tree up to the parent to catch that.
+ // Therefore, we do some fail fast check to minimize the up
+ // tree traversal.
+ return (mAttachInfo != null
+ && mAttachInfo.mWindowVisibility == View.VISIBLE
+ && getAlpha() > 0
+ && isShown()
+ && getGlobalVisibleRect(mAttachInfo.mTmpInvalRect));
+ }
+
+ /**
* Sets a delegate for implementing accessibility support via compositon as
* opposed to inheritance. The delegate's primary use is for implementing
* backwards compatible widgets. For more details see {@link AccessibilityDelegate}.
@@ -6301,9 +6318,9 @@
boolean includeForAccessibility() {
if (mAttachInfo != null) {
if (!mAttachInfo.mIncludeNotImportantViews) {
- return isImportantForAccessibility();
+ return isImportantForAccessibility() && isDisplayedOnScreen();
} else {
- return true;
+ return isDisplayedOnScreen();
}
}
return false;