AccessibilityNodeInfo for visible views should reported.

1. AccessibilityNodeInfos for visible views should always
   be reported and the clients should be able to check
   whether that node info is shown to the user. For example,
   focus search may return a node that is not on the screen
   and the accessibility layer may decide to give it focus
   which scroll the source view in the screen.

bug:6421991

Change-Id: Idc1fd8512dda767abe802aacedb0c69582e6fc2a
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 5299d58..6ed4e86 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -4657,6 +4657,51 @@
     }
 
     /**
+     * Gets the location of this view in screen coordintates.
+     *
+     * @param outRect The output location
+     */
+    private void getBoundsOnScreen(Rect outRect) {
+        if (mAttachInfo == null) {
+            return;
+        }
+
+        RectF position = mAttachInfo.mTmpTransformRect;
+        position.setEmpty();
+
+        if (!hasIdentityMatrix()) {
+            getMatrix().mapRect(position);
+        }
+
+        position.offset(mLeft, mRight);
+
+        ViewParent parent = mParent;
+        while (parent instanceof View) {
+            View parentView = (View) parent;
+
+            position.offset(-parentView.mScrollX, -parentView.mScrollY);
+
+            if (!parentView.hasIdentityMatrix()) {
+                parentView.getMatrix().mapRect(position);
+            }
+
+            position.offset(parentView.mLeft, parentView.mTop);
+
+            parent = parentView.mParent;
+        }
+
+        if (parent instanceof ViewRootImpl) {
+            ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
+            position.offset(0, -viewRootImpl.mCurScrollY);
+        }
+
+        position.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
+
+        outRect.set((int) (position.left + 0.5f), (int) (position.top + 0.5f),
+                (int) (position.right + 0.5f), (int) (position.bottom + 0.5f));
+    }
+
+    /**
      * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
      *
      * Note: Called from the default {@link AccessibilityDelegate}.
@@ -4666,8 +4711,7 @@
         getDrawingRect(bounds);
         info.setBoundsInParent(bounds);
 
-        getGlobalVisibleRect(bounds);
-        bounds.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
+        getBoundsOnScreen(bounds);
         info.setBoundsInScreen(bounds);
 
         if ((mPrivateFlags & IS_ROOT_NAMESPACE) == 0) {
@@ -4677,6 +4721,8 @@
             }
         }
 
+        info.setVisibleToUser(isVisibleToUser());
+
         info.setPackageName(mContext.getPackageName());
         info.setClassName(View.class.getName());
         info.setContentDescription(getContentDescription());
@@ -4723,11 +4769,13 @@
     }
 
     /**
-     * Computes whether this view is visible on the screen.
+     * Computes whether this view is visible to the user. Such a view is
+     * attached, visible, all its predecessors are visible, it is not clipped
+     * entirely by its predecessors, and has an alpha greater than zero.
      *
      * @return Whether the view is visible on the screen.
      */
-    boolean isDisplayedOnScreen() {
+    private boolean isVisibleToUser() {
         // 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
@@ -6377,9 +6425,9 @@
     boolean includeForAccessibility() {
         if (mAttachInfo != null) {
             if (!mAttachInfo.mIncludeNotImportantViews) {
-                return isImportantForAccessibility() && isDisplayedOnScreen();
+                return isImportantForAccessibility();
             } else {
-                return isDisplayedOnScreen();
+                return true;
             }
         }
         return false;