Cannot interact with dialogs when IME is up and on not touch explored popups.

1. If the last touch explored location is within the active window we
   used to click on exact location if it is within the accessibility
   focus otherwise in the accessibility focus center. If the last touch
   explored location is not within the active window we used to just
   click there. This breaks in the case were one has touch explored
   at a given place in the current window and now a dialog opens *not*
   covering the touch explored location. If one uses swipes to move
   accessibility focus i.e. to traverse the dialog without touching
   it one cannot activate anything because the touch explorer is using
   the last touch explored location that is outside of the active
   window e.g the dialog.

   The solution is to clear the last touch explored location when a
   window opens or accessibility focus moves. If the last touch
   explored location is null we are clicking in the accessibility
   focus location.

bug:6620911

2. There is a bug in the window manager that does not notify a
   window that its location has changed (bug:6623031). This breaks
   accessibility interaction with dialogs that have input because
   when the IME is up the dialog is moved but not notified. Now
   the accessibility layer gets incorrect location for the
   accessibility focus and the window bounds.

   The soluion is when the accessibility manager service calls
   into the remove thress to obtain some accessibility node infos
   it passes the window left and top which it gets from the
   window manager. These values are used to update the attach info
   window left and top so all accessibility node infos emitted
   from that window had correct bounds in screen coordinates.

bug:6620796

Change-Id: I18914f2095c55cfc826acf5277bd94b776bda0c8
diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java
index bd86a8d..29926ca 100644
--- a/core/java/android/view/AccessibilityInteractionController.java
+++ b/core/java/android/view/AccessibilityInteractionController.java
@@ -138,18 +138,26 @@
     }
 
     public void findAccessibilityNodeInfoByAccessibilityIdClientThread(
-            long accessibilityNodeId, int interactionId,
+            long accessibilityNodeId, int windowLeft, int windowTop, int interactionId,
             IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid,
             long interrogatingTid) {
         Message message = mHandler.obtainMessage();
         message.what = PrivateHandler.MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_ACCESSIBILITY_ID;
         message.arg1 = flags;
+
         SomeArgs args = mPool.acquire();
         args.argi1 = AccessibilityNodeInfo.getAccessibilityViewId(accessibilityNodeId);
         args.argi2 = AccessibilityNodeInfo.getVirtualDescendantId(accessibilityNodeId);
         args.argi3 = interactionId;
         args.arg1 = callback;
+
+        SomeArgs moreArgs = mPool.acquire();
+        moreArgs.argi1 = windowLeft;
+        moreArgs.argi2 = windowTop;
+        args.arg2 = moreArgs;
+
         message.obj = args;
+
         // If the interrogation is performed by the same thread as the main UI
         // thread in this process, set the message as a static reference so
         // after this call completes the same thread but in the interrogating
@@ -164,13 +172,21 @@
 
     private void findAccessibilityNodeInfoByAccessibilityIdUiThread(Message message) {
         final int flags = message.arg1;
+
         SomeArgs args = (SomeArgs) message.obj;
         final int accessibilityViewId = args.argi1;
         final int virtualDescendantId = args.argi2;
         final int interactionId = args.argi3;
         final IAccessibilityInteractionConnectionCallback callback =
             (IAccessibilityInteractionConnectionCallback) args.arg1;
+
+        SomeArgs moreArgs = (SomeArgs) args.arg2;
+        mViewRootImpl.mAttachInfo.mActualWindowLeft = moreArgs.argi1;
+        mViewRootImpl.mAttachInfo.mActualWindowTop = moreArgs.argi2;
+
+        mPool.release(moreArgs);
         mPool.release(args);
+
         List<AccessibilityNodeInfo> infos = mTempAccessibilityNodeInfoList;
         infos.clear();
         try {
@@ -200,17 +216,26 @@
     }
 
     public void findAccessibilityNodeInfoByViewIdClientThread(long accessibilityNodeId,
-            int viewId, int interactionId, IAccessibilityInteractionConnectionCallback callback,
-            int flags, int interrogatingPid, long interrogatingTid) {
+            int viewId, int windowLeft, int windowTop, int interactionId,
+            IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid,
+            long interrogatingTid) {
         Message message = mHandler.obtainMessage();
         message.what = PrivateHandler.MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_VIEW_ID;
         message.arg1 = flags;
         message.arg2 = AccessibilityNodeInfo.getAccessibilityViewId(accessibilityNodeId);
+
         SomeArgs args = mPool.acquire();
         args.argi1 = viewId;
         args.argi2 = interactionId;
         args.arg1 = callback;
+
+        SomeArgs moreArgs = mPool.acquire();
+        moreArgs.argi1 = windowLeft;
+        moreArgs.argi2 = windowTop;
+        args.arg2 = moreArgs;
+
         message.obj = args;
+
         // If the interrogation is performed by the same thread as the main UI
         // thread in this process, set the message as a static reference so
         // after this call completes the same thread but in the interrogating
@@ -226,12 +251,20 @@
     private void findAccessibilityNodeInfoByViewIdUiThread(Message message) {
         final int flags = message.arg1;
         final int accessibilityViewId = message.arg2;
+
         SomeArgs args = (SomeArgs) message.obj;
         final int viewId = args.argi1;
         final int interactionId = args.argi2;
         final IAccessibilityInteractionConnectionCallback callback =
             (IAccessibilityInteractionConnectionCallback) args.arg1;
+
+        SomeArgs moreArgs = (SomeArgs) args.arg2;
+        mViewRootImpl.mAttachInfo.mActualWindowLeft = moreArgs.argi1;
+        mViewRootImpl.mAttachInfo.mActualWindowTop = moreArgs.argi2;
+
+        mPool.release(moreArgs);
         mPool.release(args);
+
         AccessibilityNodeInfo info = null;
         try {
             if (mViewRootImpl.mView == null || mViewRootImpl.mAttachInfo == null) {
@@ -262,18 +295,27 @@
     }
 
     public void findAccessibilityNodeInfosByTextClientThread(long accessibilityNodeId,
-            String text, int interactionId, IAccessibilityInteractionConnectionCallback callback,
-            int flags,  int interrogatingPid, long interrogatingTid) {
+            String text, int windowLeft, int windowTop, int interactionId,
+            IAccessibilityInteractionConnectionCallback callback, int flags,
+            int interrogatingPid, long interrogatingTid) {
         Message message = mHandler.obtainMessage();
         message.what = PrivateHandler.MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_TEXT;
         message.arg1 = flags;
+
         SomeArgs args = mPool.acquire();
         args.arg1 = text;
         args.argi1 = AccessibilityNodeInfo.getAccessibilityViewId(accessibilityNodeId);
         args.argi2 = AccessibilityNodeInfo.getVirtualDescendantId(accessibilityNodeId);
         args.argi3 = interactionId;
-        args.arg2 = callback;
+
+        SomeArgs moreArgs = mPool.acquire();
+        moreArgs.arg1 = callback;
+        moreArgs.argi1 = windowLeft;
+        moreArgs.argi2 = windowTop;
+        args.arg2 = moreArgs;
+
         message.obj = args;
+
         // If the interrogation is performed by the same thread as the main UI
         // thread in this process, set the message as a static reference so
         // after this call completes the same thread but in the interrogating
@@ -288,14 +330,22 @@
 
     private void findAccessibilityNodeInfosByTextUiThread(Message message) {
         final int flags = message.arg1;
+
         SomeArgs args = (SomeArgs) message.obj;
         final String text = (String) args.arg1;
         final int accessibilityViewId = args.argi1;
         final int virtualDescendantId = args.argi2;
         final int interactionId = args.argi3;
+
+        SomeArgs moreArgs = (SomeArgs) args.arg2;
         final IAccessibilityInteractionConnectionCallback callback =
-            (IAccessibilityInteractionConnectionCallback) args.arg2;
+            (IAccessibilityInteractionConnectionCallback) moreArgs.arg1;
+        mViewRootImpl.mAttachInfo.mActualWindowLeft = moreArgs.argi1;
+        mViewRootImpl.mAttachInfo.mActualWindowTop = moreArgs.argi2;
+
+        mPool.release(moreArgs);
         mPool.release(args);
+
         List<AccessibilityNodeInfo> infos = null;
         try {
             if (mViewRootImpl.mView == null || mViewRootImpl.mAttachInfo == null) {
@@ -353,19 +403,27 @@
         }
     }
 
-    public void findFocusClientThread(long accessibilityNodeId, int interactionId, int focusType,
-            IAccessibilityInteractionConnectionCallback callback,  int flags, int interogatingPid,
-            long interrogatingTid) {
+    public void findFocusClientThread(long accessibilityNodeId, int focusType, int windowLeft,
+            int windowTop, int interactionId, IAccessibilityInteractionConnectionCallback callback,
+            int flags, int interogatingPid, long interrogatingTid) {
         Message message = mHandler.obtainMessage();
         message.what = PrivateHandler.MSG_FIND_FOCUS;
         message.arg1 = flags;
         message.arg2 = focusType;
+
         SomeArgs args = mPool.acquire();
         args.argi1 = interactionId;
         args.argi2 = AccessibilityNodeInfo.getAccessibilityViewId(accessibilityNodeId);
         args.argi3 = AccessibilityNodeInfo.getVirtualDescendantId(accessibilityNodeId);
         args.arg1 = callback;
+
+        SomeArgs moreArgs = mPool.acquire();
+        moreArgs.argi1 = windowLeft;
+        moreArgs.argi2 = windowTop;
+        args.arg2 = moreArgs;
+
         message.obj = args;
+
         // If the interrogation is performed by the same thread as the main UI
         // thread in this process, set the message as a static reference so
         // after this call completes the same thread but in the interrogating
@@ -381,13 +439,21 @@
     private void findFocusUiThread(Message message) {
         final int flags = message.arg1;
         final int focusType = message.arg2;
+
         SomeArgs args = (SomeArgs) message.obj;
         final int interactionId = args.argi1;
         final int accessibilityViewId = args.argi2;
         final int virtualDescendantId = args.argi3;
         final IAccessibilityInteractionConnectionCallback callback =
             (IAccessibilityInteractionConnectionCallback) args.arg1;
+
+        SomeArgs moreArgs = (SomeArgs) args.arg2;
+        mViewRootImpl.mAttachInfo.mActualWindowLeft = moreArgs.argi1;
+        mViewRootImpl.mAttachInfo.mActualWindowTop = moreArgs.argi2;
+
+        mPool.release(moreArgs);
         mPool.release(args);
+
         AccessibilityNodeInfo focused = null;
         try {
             if (mViewRootImpl.mView == null || mViewRootImpl.mAttachInfo == null) {
@@ -440,19 +506,27 @@
         }
     }
 
-    public void focusSearchClientThread(long accessibilityNodeId, int interactionId, int direction,
-            IAccessibilityInteractionConnectionCallback callback, int flags, int interogatingPid,
-            long interrogatingTid) {
+    public void focusSearchClientThread(long accessibilityNodeId, int direction, int windowLeft,
+            int windowTop, int interactionId, IAccessibilityInteractionConnectionCallback callback,
+            int flags, int interogatingPid, long interrogatingTid) {
         Message message = mHandler.obtainMessage();
         message.what = PrivateHandler.MSG_FOCUS_SEARCH;
         message.arg1 = flags;
         message.arg2 = AccessibilityNodeInfo.getAccessibilityViewId(accessibilityNodeId);
+
         SomeArgs args = mPool.acquire();
         args.argi1 = AccessibilityNodeInfo.getVirtualDescendantId(accessibilityNodeId);
         args.argi2 = direction;
         args.argi3 = interactionId;
         args.arg1 = callback;
+
+        SomeArgs moreArgs = mPool.acquire();
+        moreArgs.argi1 = windowLeft;
+        moreArgs.argi2 = windowTop;
+        args.arg2 = moreArgs;
+
         message.obj = args;
+
         // If the interrogation is performed by the same thread as the main UI
         // thread in this process, set the message as a static reference so
         // after this call completes the same thread but in the interrogating
@@ -468,13 +542,21 @@
     private void focusSearchUiThread(Message message) {
         final int flags = message.arg1;
         final int accessibilityViewId = message.arg2;
+
         SomeArgs args = (SomeArgs) message.obj;
         final int virtualDescendantId = args.argi1;
         final int direction = args.argi2;
         final int interactionId = args.argi3;
         final IAccessibilityInteractionConnectionCallback callback =
             (IAccessibilityInteractionConnectionCallback) args.arg1;
+
+        SomeArgs moreArgs = (SomeArgs) args.arg2;
+        mViewRootImpl.mAttachInfo.mActualWindowLeft = moreArgs.argi1;
+        mViewRootImpl.mAttachInfo.mActualWindowTop = moreArgs.argi2;
+
+        mPool.release(moreArgs);
         mPool.release(args);
+
         AccessibilityNodeInfo next = null;
         try {
             if (mViewRootImpl.mView == null || mViewRootImpl.mAttachInfo == null) {
@@ -541,13 +623,16 @@
         message.what = PrivateHandler.MSG_PERFORM_ACCESSIBILITY_ACTION;
         message.arg1 = flags;
         message.arg2 = AccessibilityNodeInfo.getAccessibilityViewId(accessibilityNodeId);
+
         SomeArgs args = mPool.acquire();
         args.argi1 = AccessibilityNodeInfo.getVirtualDescendantId(accessibilityNodeId);
         args.argi2 = action;
         args.argi3 = interactionId;
         args.arg1 = callback;
         args.arg2 = arguments;
+
         message.obj = args;
+
         // If the interrogation is performed by the same thread as the main UI
         // thread in this process, set the message as a static reference so
         // after this call completes the same thread but in the interrogating
@@ -563,6 +648,7 @@
     private void perfromAccessibilityActionUiThread(Message message) {
         final int flags = message.arg1;
         final int accessibilityViewId = message.arg2;
+
         SomeArgs args = (SomeArgs) message.obj;
         final int virtualDescendantId = args.argi1;
         final int action = args.argi2;
@@ -570,7 +656,9 @@
         final IAccessibilityInteractionConnectionCallback callback =
             (IAccessibilityInteractionConnectionCallback) args.arg1;
         Bundle arguments = (Bundle) args.arg2;
+
         mPool.release(args);
+
         boolean succeeded = false;
         try {
             if (mViewRootImpl.mView == null || mViewRootImpl.mAttachInfo == null) {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 0a2b76c..f005eeb 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -3609,6 +3609,7 @@
                 case R.styleable.View_importantForAccessibility:
                     setImportantForAccessibility(a.getInt(attr,
                             IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
+                    break;
             }
         }
 
@@ -4902,6 +4903,30 @@
     }
 
     /**
+     * Returns the delta between the actual and last reported window left.
+     *
+     * @hide
+     */
+    public int getActualAndReportedWindowLeftDelta() {
+        if (mAttachInfo != null) {
+            return mAttachInfo.mActualWindowLeft - mAttachInfo.mWindowLeft; 
+        }
+        return 0;
+    }
+
+    /**
+     * Returns the delta between the actual and last reported window top.
+     *
+     * @hide
+     */
+    public int getActualAndReportedWindowTopDelta() {
+        if (mAttachInfo != null) {
+            return mAttachInfo.mActualWindowTop - mAttachInfo.mWindowTop;
+        }
+        return 0;
+    }
+
+    /**
      * 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.
@@ -17307,6 +17332,20 @@
         int mWindowTop;
 
         /**
+         * Left actual position of this view's window.
+         *
+         * TODO: This is a workaround for 6623031. Remove when fixed.
+         */
+        int mActualWindowLeft;
+
+        /**
+         * Actual top position of this view's window.
+         *
+         * TODO: This is a workaround for 6623031. Remove when fixed.
+         */
+        int mActualWindowTop;
+
+        /**
          * Indicates whether views need to use 32-bit drawing caches
          */
         boolean mUse32BitDrawingCache;
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 3138692..b5fff8a 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -5172,13 +5172,15 @@
 
         @Override
         public void findAccessibilityNodeInfoByAccessibilityId(long accessibilityNodeId,
-                int interactionId, IAccessibilityInteractionConnectionCallback callback,
-                int flags, int interrogatingPid, long interrogatingTid) {
+                int windowLeft, int windowTop, int interactionId,
+                IAccessibilityInteractionConnectionCallback callback, int flags,
+                int interrogatingPid, long interrogatingTid) {
             ViewRootImpl viewRootImpl = mViewRootImpl.get();
             if (viewRootImpl != null && viewRootImpl.mView != null) {
                 viewRootImpl.getAccessibilityInteractionController()
                     .findAccessibilityNodeInfoByAccessibilityIdClientThread(accessibilityNodeId,
-                        interactionId, callback, flags, interrogatingPid, interrogatingTid);
+                            windowLeft, windowTop, interactionId, callback, flags, interrogatingPid,
+                            interrogatingTid);
             } else {
                 // We cannot make the call and notify the caller so it does not wait.
                 try {
@@ -5211,13 +5213,15 @@
 
         @Override
         public void findAccessibilityNodeInfoByViewId(long accessibilityNodeId, int viewId,
-                int interactionId, IAccessibilityInteractionConnectionCallback callback,
-                int flags, int interrogatingPid, long interrogatingTid) {
+                int windowLeft, int windowTop, int interactionId,
+                IAccessibilityInteractionConnectionCallback callback, int flags,
+                int interrogatingPid, long interrogatingTid) {
             ViewRootImpl viewRootImpl = mViewRootImpl.get();
             if (viewRootImpl != null && viewRootImpl.mView != null) {
                 viewRootImpl.getAccessibilityInteractionController()
                     .findAccessibilityNodeInfoByViewIdClientThread(accessibilityNodeId, viewId,
-                            interactionId, callback, flags, interrogatingPid, interrogatingTid);
+                            windowLeft, windowTop, interactionId, callback, flags, interrogatingPid,
+                            interrogatingTid);
             } else {
                 // We cannot make the call and notify the caller so it does not wait.
                 try {
@@ -5230,13 +5234,15 @@
 
         @Override
         public void findAccessibilityNodeInfosByText(long accessibilityNodeId, String text,
-                int interactionId, IAccessibilityInteractionConnectionCallback callback,
-                int flags, int interrogatingPid, long interrogatingTid) {
+                int windowLeft, int windowTop, int interactionId,
+                IAccessibilityInteractionConnectionCallback callback, int flags,
+                int interrogatingPid, long interrogatingTid) {
             ViewRootImpl viewRootImpl = mViewRootImpl.get();
             if (viewRootImpl != null && viewRootImpl.mView != null) {
                 viewRootImpl.getAccessibilityInteractionController()
                     .findAccessibilityNodeInfosByTextClientThread(accessibilityNodeId, text,
-                            interactionId, callback, flags, interrogatingPid, interrogatingTid);
+                            windowLeft, windowTop, interactionId, callback, flags, interrogatingPid,
+                            interrogatingTid);
             } else {
                 // We cannot make the call and notify the caller so it does not wait.
                 try {
@@ -5248,14 +5254,15 @@
         }
 
         @Override
-        public void findFocus(long accessibilityNodeId, int interactionId, int focusType,
-                IAccessibilityInteractionConnectionCallback callback,  int flags,
+        public void findFocus(long accessibilityNodeId, int focusType, int windowLeft,
+                int windowTop, int interactionId,
+                IAccessibilityInteractionConnectionCallback callback, int flags,
                 int interrogatingPid, long interrogatingTid) {
             ViewRootImpl viewRootImpl = mViewRootImpl.get();
             if (viewRootImpl != null && viewRootImpl.mView != null) {
                 viewRootImpl.getAccessibilityInteractionController()
-                    .findFocusClientThread(accessibilityNodeId, interactionId, focusType,
-                            callback, flags, interrogatingPid, interrogatingTid);
+                    .findFocusClientThread(accessibilityNodeId, focusType, windowLeft, windowTop,
+                            interactionId, callback, flags, interrogatingPid, interrogatingTid);
             } else {
                 // We cannot make the call and notify the caller so it does not wait.
                 try {
@@ -5267,14 +5274,15 @@
         }
 
         @Override
-        public void focusSearch(long accessibilityNodeId, int interactionId, int direction,
+        public void focusSearch(long accessibilityNodeId, int direction, int windowLeft,
+                int windowTop, int interactionId,
                 IAccessibilityInteractionConnectionCallback callback, int flags,
                 int interrogatingPid, long interrogatingTid) {
             ViewRootImpl viewRootImpl = mViewRootImpl.get();
             if (viewRootImpl != null && viewRootImpl.mView != null) {
                 viewRootImpl.getAccessibilityInteractionController()
-                    .focusSearchClientThread(accessibilityNodeId, interactionId, direction,
-                            callback, flags, interrogatingPid, interrogatingTid);
+                    .focusSearchClientThread(accessibilityNodeId, direction, windowLeft, windowTop,
+                            interactionId, callback, flags, interrogatingPid, interrogatingTid);
             } else {
                 // We cannot make the call and notify the caller so it does not wait.
                 try {
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index d3c9055..0daf78b 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -382,6 +382,10 @@
 
     private int mConnectionId = UNDEFINED;
 
+    // TODO: These are a workaround for 6623031. Remove when fixed.
+    private int mActualAndReportedWindowLeftDelta;
+    private int mActualAndReportedWindowTopDelta;
+
     /**
      * Hide constructor from clients.
      */
@@ -428,6 +432,8 @@
         final int rootAccessibilityViewId =
             (root != null) ? root.getAccessibilityViewId() : UNDEFINED;
         mSourceNodeId = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
+        mActualAndReportedWindowLeftDelta = root.getActualAndReportedWindowLeftDelta();
+        mActualAndReportedWindowTopDelta = root.getActualAndReportedWindowTopDelta();
     }
 
     /**
@@ -831,6 +837,7 @@
     public void setBoundsInScreen(Rect bounds) {
         enforceNotSealed();
         mBoundsInScreen.set(bounds.left, bounds.top, bounds.right, bounds.bottom);
+        mBoundsInScreen.offset(mActualAndReportedWindowLeftDelta, mActualAndReportedWindowTopDelta);
     }
 
     /**
diff --git a/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl b/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl
index 9d7a928..292702a 100644
--- a/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl
@@ -28,25 +28,25 @@
  */
 oneway interface IAccessibilityInteractionConnection {
 
-    void findAccessibilityNodeInfoByAccessibilityId(long accessibilityNodeId, int interactionId,
-        IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid,
-        long interrogatingTid);
+    void findAccessibilityNodeInfoByAccessibilityId(long accessibilityNodeId, int windowLeft,
+        int windowTop, int interactionId, IAccessibilityInteractionConnectionCallback callback,
+        int flags, int interrogatingPid, long interrogatingTid);
 
-    void findAccessibilityNodeInfoByViewId(long accessibilityNodeId, int id, int interactionId,
-        IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid,
-        long interrogatingTid);
+    void findAccessibilityNodeInfoByViewId(long accessibilityNodeId, int viewId, int windowLeft,
+        int windowTop, int interactionId, IAccessibilityInteractionConnectionCallback callback,
+        int flags, int interrogatingPid, long interrogatingTid);
 
-    void findAccessibilityNodeInfosByText(long accessibilityNodeId, String text, int interactionId,
-        IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid,
-        long interrogatingTid);
+    void findAccessibilityNodeInfosByText(long accessibilityNodeId, String text, int windowLeft,
+        int windowTop, int interactionId, IAccessibilityInteractionConnectionCallback callback,
+        int flags, int interrogatingPid, long interrogatingTid);
 
-    void findFocus(long accessibilityNodeId, int interactionId, int focusType,
-        IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid,
-        long interrogatingTid);
+    void findFocus(long accessibilityNodeId, int focusType, int windowLeft, int windowTop,
+        int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags,
+        int interrogatingPid, long interrogatingTid);
 
-    void focusSearch(long accessibilityNodeId, int interactionId, int direction,
-        IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid,
-        long interrogatingTid);
+    void focusSearch(long accessibilityNodeId, int direction, int windowLeft, int windowTop,
+        int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags,
+        int interrogatingPid, long interrogatingTid);
 
     void performAccessibilityAction(long accessibilityNodeId, int action, in Bundle arguments,
         int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags,
diff --git a/services/java/com/android/server/accessibility/AccessibilityInputFilter.java b/services/java/com/android/server/accessibility/AccessibilityInputFilter.java
index 3e35b20d..baa2f54 100644
--- a/services/java/com/android/server/accessibility/AccessibilityInputFilter.java
+++ b/services/java/com/android/server/accessibility/AccessibilityInputFilter.java
@@ -25,6 +25,7 @@
 import android.view.InputEvent;
 import android.view.MotionEvent;
 import android.view.WindowManagerPolicy;
+import android.view.accessibility.AccessibilityEvent;
 
 /**
  * Input filter for accessibility.
@@ -120,4 +121,8 @@
             super.onInputEvent(event, policyFlags);
         }
     }
+
+    public void onAccessibilityEvent(AccessibilityEvent event) {
+        mTouchExplorer.onAccessibilityEvent(event);
+    }
 }
diff --git a/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
index 5c814d2..3bddd9d 100644
--- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -141,8 +141,6 @@
 
     private final SimpleStringSplitter mStringColonSplitter = new SimpleStringSplitter(COMPONENT_NAME_SEPARATOR);
 
-    private final Rect mTempRect = new Rect();
-
     private PackageManager mPackageManager;
 
     private int mHandledFeedbackTypes = 0;
@@ -403,7 +401,9 @@
                 notifyAccessibilityServicesDelayedLocked(event, false);
                 notifyAccessibilityServicesDelayedLocked(event, true);
             }
-
+            if (mHasInputFilter && mInputFilter != null) {
+                mInputFilter.onAccessibilityEvent(event);
+            }
             event.recycle();
             mHandledFeedbackTypes = 0;
         }
@@ -543,17 +543,12 @@
     }
 
     /**
-     * Gets the bounds of the accessibility focus if the provided,
-     * point coordinates are within the currently active window
-     * and accessibility focus is found within the latter.
+     * Gets the bounds of the accessibility focus in the active window.
      *
-     * @param x X coordinate.
-     * @param y Y coordinate
      * @param outBounds The output to which to write the focus bounds.
-     * @return The accessibility focus rectangle if the point is in the
-     *     window and the window has accessibility focus.
+     * @return Whether accessibility focus was found and the bounds are populated.
      */
-    boolean getAccessibilityFocusBounds(int x, int y, Rect outBounds) {
+    boolean getAccessibilityFocusBoundsInActiveWindow(Rect outBounds) {
         // Instead of keeping track of accessibility focus events per
         // window to be able to find the focus in the active window,
         // we take a stateless approach and look it up. This is fine
@@ -568,11 +563,6 @@
             if (root == null) {
                 return false;
             }
-            Rect bounds = mTempRect;
-            root.getBoundsInScreen(bounds);
-            if (!bounds.contains(x, y)) {
-                return false;
-            }
             AccessibilityNodeInfo focus = root.findFocus(
                     AccessibilityNodeInfo.FOCUS_ACCESSIBILITY);
             if (focus == null) {
@@ -585,6 +575,19 @@
         }
     }
 
+    /**
+     * Gets the bounds of the active window.
+     *
+     * @param outBounds The output to which to write the bounds.
+     */
+    void getActiveWindowBounds(Rect outBounds) {
+        synchronized (mLock) {
+            final int windowId = mSecurityPolicy.mActiveWindowId;
+            IBinder token = mWindowIdToWindowTokenMap.get(windowId);
+            mWindowManagerService.getWindowFrame(token, outBounds);
+        }
+    }
+
     private Service getQueryBridge() {
         if (mQueryBridge == null) {
             AccessibilityServiceInfo info = new AccessibilityServiceInfo();
@@ -1316,6 +1319,8 @@
                 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
                 throws RemoteException {
             final int resolvedWindowId = resolveAccessibilityWindowId(accessibilityWindowId);
+            final int windowLeft;
+            final int windowTop;
             IAccessibilityInteractionConnection connection = null;
             synchronized (mLock) {
                 mSecurityPolicy.enforceCanRetrieveWindowContent(this);
@@ -1328,6 +1333,10 @@
                         return 0;
                     }
                 }
+                IBinder token = mWindowIdToWindowTokenMap.get(resolvedWindowId);
+                mWindowManagerService.getWindowFrame(token, mTempBounds);
+                windowLeft = mTempBounds.left;
+                windowTop = mTempBounds.top;
             }
             final int flags = (mIncludeNotImportantViews) ?
                     AccessibilityNodeInfo.INCLUDE_NOT_IMPORTANT_VIEWS : 0;
@@ -1335,7 +1344,8 @@
             final long identityToken = Binder.clearCallingIdentity();
             try {
                 connection.findAccessibilityNodeInfoByViewId(accessibilityNodeId, viewId,
-                        interactionId, callback, flags, interrogatingPid, interrogatingTid);
+                        windowLeft, windowTop, interactionId, callback, flags, interrogatingPid,
+                        interrogatingTid);
             } catch (RemoteException re) {
                 if (DEBUG) {
                     Slog.e(LOG_TAG, "Error findAccessibilityNodeInfoByViewId().");
@@ -1352,6 +1362,8 @@
                 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
                 throws RemoteException {
             final int resolvedWindowId = resolveAccessibilityWindowId(accessibilityWindowId);
+            final int windowLeft;
+            final int windowTop;
             IAccessibilityInteractionConnection connection = null;
             synchronized (mLock) {
                 mSecurityPolicy.enforceCanRetrieveWindowContent(this);
@@ -1365,14 +1377,19 @@
                         return 0;
                     }
                 }
+                IBinder token = mWindowIdToWindowTokenMap.get(resolvedWindowId);
+                mWindowManagerService.getWindowFrame(token, mTempBounds);
+                windowLeft = mTempBounds.left;
+                windowTop = mTempBounds.top;
             }
             final int flags = (mIncludeNotImportantViews) ?
                     AccessibilityNodeInfo.INCLUDE_NOT_IMPORTANT_VIEWS : 0;
             final int interrogatingPid = Binder.getCallingPid();
             final long identityToken = Binder.clearCallingIdentity();
             try {
-                connection.findAccessibilityNodeInfosByText(accessibilityNodeId, text,
-                        interactionId, callback, flags, interrogatingPid, interrogatingTid);
+                connection.findAccessibilityNodeInfosByText(accessibilityNodeId, text, windowLeft,
+                        windowTop, interactionId, callback, flags, interrogatingPid,
+                        interrogatingTid);
             } catch (RemoteException re) {
                 if (DEBUG) {
                     Slog.e(LOG_TAG, "Error calling findAccessibilityNodeInfosByText()");
@@ -1389,6 +1406,8 @@
                 IAccessibilityInteractionConnectionCallback callback, int flags,
                 long interrogatingTid) throws RemoteException {
             final int resolvedWindowId = resolveAccessibilityWindowId(accessibilityWindowId);
+            final int windowLeft;
+            final int windowTop;
             IAccessibilityInteractionConnection connection = null;
             synchronized (mLock) {
                 mSecurityPolicy.enforceCanRetrieveWindowContent(this);
@@ -1402,6 +1421,10 @@
                         return 0;
                     }
                 }
+                IBinder token = mWindowIdToWindowTokenMap.get(resolvedWindowId);
+                mWindowManagerService.getWindowFrame(token, mTempBounds);
+                windowLeft = mTempBounds.left;
+                windowTop = mTempBounds.top;
             }
             final int allFlags = flags | ((mIncludeNotImportantViews) ?
                     AccessibilityNodeInfo.INCLUDE_NOT_IMPORTANT_VIEWS : 0);
@@ -1409,7 +1432,8 @@
             final long identityToken = Binder.clearCallingIdentity();
             try {
                 connection.findAccessibilityNodeInfoByAccessibilityId(accessibilityNodeId,
-                        interactionId, callback, allFlags, interrogatingPid, interrogatingTid);
+                        windowLeft, windowTop, interactionId, callback, allFlags, interrogatingPid,
+                        interrogatingTid);
             } catch (RemoteException re) {
                 if (DEBUG) {
                     Slog.e(LOG_TAG, "Error calling findAccessibilityNodeInfoByAccessibilityId()");
@@ -1426,6 +1450,8 @@
                 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
                 throws RemoteException {
             final int resolvedWindowId = resolveAccessibilityWindowId(accessibilityWindowId);
+            final int windowLeft;
+            final int windowTop;
             IAccessibilityInteractionConnection connection = null;
             synchronized (mLock) {
                 mSecurityPolicy.enforceCanRetrieveWindowContent(this);
@@ -1439,14 +1465,18 @@
                         return 0;
                     }
                 }
+                IBinder token = mWindowIdToWindowTokenMap.get(resolvedWindowId);
+                mWindowManagerService.getWindowFrame(token, mTempBounds);
+                windowLeft = mTempBounds.left;
+                windowTop = mTempBounds.top;
             }
             final int flags = (mIncludeNotImportantViews) ?
                     AccessibilityNodeInfo.INCLUDE_NOT_IMPORTANT_VIEWS : 0;
             final int interrogatingPid = Binder.getCallingPid();
             final long identityToken = Binder.clearCallingIdentity();
             try {
-                connection.findFocus(accessibilityNodeId, interactionId, focusType, callback,
-                        flags, interrogatingPid, interrogatingTid);
+                connection.findFocus(accessibilityNodeId, focusType, windowLeft, windowTop,
+                        interactionId, callback, flags, interrogatingPid, interrogatingTid);
             } catch (RemoteException re) {
                 if (DEBUG) {
                     Slog.e(LOG_TAG, "Error calling findAccessibilityFocus()");
@@ -1463,6 +1493,8 @@
                 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
                 throws RemoteException {
             final int resolvedWindowId = resolveAccessibilityWindowId(accessibilityWindowId);
+            final int windowLeft;
+            final int windowTop;
             IAccessibilityInteractionConnection connection = null;
             synchronized (mLock) {
                 mSecurityPolicy.enforceCanRetrieveWindowContent(this);
@@ -1476,14 +1508,18 @@
                         return 0;
                     }
                 }
+                IBinder token = mWindowIdToWindowTokenMap.get(resolvedWindowId);
+                mWindowManagerService.getWindowFrame(token, mTempBounds);
+                windowLeft = mTempBounds.left;
+                windowTop = mTempBounds.top;
             }
             final int flags = (mIncludeNotImportantViews) ?
                     AccessibilityNodeInfo.INCLUDE_NOT_IMPORTANT_VIEWS : 0;
             final int interrogatingPid = Binder.getCallingPid();
             final long identityToken = Binder.clearCallingIdentity();
             try {
-                connection.focusSearch(accessibilityNodeId, interactionId, direction, callback,
-                        flags, interrogatingPid, interrogatingTid);
+                connection.focusSearch(accessibilityNodeId, direction, windowLeft, windowTop,
+                        interactionId, callback, flags, interrogatingPid, interrogatingTid);
             } catch (RemoteException re) {
                 if (DEBUG) {
                     Slog.e(LOG_TAG, "Error calling accessibilityFocusSearch()");
diff --git a/services/java/com/android/server/accessibility/TouchExplorer.java b/services/java/com/android/server/accessibility/TouchExplorer.java
index 7e88373..14784dc 100644
--- a/services/java/com/android/server/accessibility/TouchExplorer.java
+++ b/services/java/com/android/server/accessibility/TouchExplorer.java
@@ -33,6 +33,7 @@
 import android.view.VelocityTracker;
 import android.view.ViewConfiguration;
 import android.view.WindowManagerPolicy;
+import android.view.accessibility.AccessibilityEvent;
 
 import com.android.internal.R;
 import com.android.server.input.InputFilter;
@@ -293,6 +294,21 @@
         }
     }
 
+    public void onAccessibilityEvent(AccessibilityEvent event) {
+        // If a new window opens or the accessibility focus moves we no longer
+        // want to click/long press on the last touch explored location.
+        final int eventType = event.getEventType();
+        switch (eventType) {
+            case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED:
+            case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED: {
+                if (mInjectedPointerTracker.mLastInjectedHoverEvent != null) {
+                    mInjectedPointerTracker.mLastInjectedHoverEvent.recycle();
+                    mInjectedPointerTracker.mLastInjectedHoverEvent = null;
+                }
+            } break;
+        }
+    }
+
     /**
      * Handles a motion event in touch exploring state.
      *
@@ -1037,30 +1053,40 @@
             // is actually clicked.
             sendExitEventsIfNeeded(policyFlags);
 
-            // If the last touched explored location is not within the focused
-            // window we will click at that exact spot, otherwise we find the
-            // accessibility focus and if the tap is within its bounds we click
-            // there, otherwise we pick the middle of the focus rectangle.
-            MotionEvent lastEvent = mInjectedPointerTracker.getLastInjectedHoverEvent();
-            if (lastEvent == null) {
-                return;
-            }
-
-            final int exploreLocationX = (int) lastEvent.getX(lastEvent.getActionIndex());
-            final int exploreLocationY = (int) lastEvent.getY(lastEvent.getActionIndex());
-
-            Rect bounds = mTempRect;
-            boolean useLastHoverLocation = false;
+            int clickLocationX;
+            int clickLocationY;
 
             final int pointerId = secondTapUp.getPointerId(secondTapUp.getActionIndex());
             final int pointerIndex = secondTapUp.findPointerIndex(pointerId);
-            if (mAms.getAccessibilityFocusBounds(exploreLocationX, exploreLocationY, bounds)) {
-                // If the user's last touch explored location is not
-                // within the accessibility focus bounds we use the center
-                // of the accessibility focused rectangle.
-                if (!bounds.contains((int) secondTapUp.getX(pointerIndex),
-                        (int) secondTapUp.getY(pointerIndex))) {
-                    useLastHoverLocation = true;
+
+            MotionEvent lastExploreEvent = mInjectedPointerTracker.getLastInjectedHoverEvent();
+            if (lastExploreEvent == null) {
+                // No last touch explored event but there is accessibility focus in
+                // the active window. We click in the middle of the focus bounds.
+                Rect focusBounds = mTempRect;
+                if (mAms.getAccessibilityFocusBoundsInActiveWindow(focusBounds)) {
+                    clickLocationX = focusBounds.centerX();
+                    clickLocationY = focusBounds.centerY();
+                } else {
+                    // Out of luck - do nothing.
+                    return;
+                }
+            } else {
+                // If the click is within the active window but not within the
+                // accessibility focus bounds we click in the focus center.
+                final int lastExplorePointerIndex = lastExploreEvent.getActionIndex();
+                clickLocationX = (int) lastExploreEvent.getX(lastExplorePointerIndex);
+                clickLocationY = (int) lastExploreEvent.getY(lastExplorePointerIndex);
+                Rect activeWindowBounds = mTempRect;
+                mAms.getActiveWindowBounds(activeWindowBounds);
+                if (activeWindowBounds.contains(clickLocationX, clickLocationY)) {
+                    Rect focusBounds = mTempRect;
+                    if (mAms.getAccessibilityFocusBoundsInActiveWindow(focusBounds)) {
+                        if (!focusBounds.contains(clickLocationX, clickLocationY)) {
+                            clickLocationX = focusBounds.centerX();
+                            clickLocationY = focusBounds.centerY();
+                        }
+                    }
                 }
             }
 
@@ -1070,8 +1096,8 @@
             secondTapUp.getPointerProperties(pointerIndex, properties[0]);
             PointerCoords[] coords = new PointerCoords[1];
             coords[0] = new PointerCoords();
-            coords[0].x = (useLastHoverLocation) ? bounds.centerX() : exploreLocationX;
-            coords[0].y = (useLastHoverLocation) ? bounds.centerY() : exploreLocationY;
+            coords[0].x = clickLocationX;
+            coords[0].y = clickLocationY;
             MotionEvent event = MotionEvent.obtain(secondTapUp.getDownTime(),
                     secondTapUp.getEventTime(), MotionEvent.ACTION_DOWN, 1, properties,
                     coords, 0, 0, 1.0f, 1.0f, secondTapUp.getDeviceId(), 0,
@@ -1257,44 +1283,46 @@
                 return;
             }
 
-            // If the last touched explored location is not within the focused
-            // window we will long press at that exact spot, otherwise we find the
-            // accessibility focus and if the tap is within its bounds we long press
-            // there, otherwise we pick the middle of the focus rectangle.
-            MotionEvent lastEvent = mInjectedPointerTracker.getLastInjectedHoverEvent();
-            if (lastEvent == null) {
-                return;
-            }
-
-            final int exploreLocationX = (int) lastEvent.getX(lastEvent.getActionIndex());
-            final int exploreLocationY = (int) lastEvent.getY(lastEvent.getActionIndex());
-
-            Rect bounds = mTempRect;
-            boolean useFocusedBounds = false;
+            int clickLocationX;
+            int clickLocationY;
 
             final int pointerId = mEvent.getPointerId(mEvent.getActionIndex());
             final int pointerIndex = mEvent.findPointerIndex(pointerId);
-            if (mAms.getAccessibilityFocusBounds(exploreLocationX, exploreLocationY, bounds)) {
-                // If the user's last touch explored location is not
-                // within the accessibility focus bounds we use the center
-                // of the accessibility focused rectangle.
-                if (!bounds.contains((int) mEvent.getX(pointerIndex),
-                        (int) mEvent.getY(pointerIndex))) {
-                    useFocusedBounds = true;
+
+            MotionEvent lastExploreEvent = mInjectedPointerTracker.getLastInjectedHoverEvent();
+            if (lastExploreEvent == null) {
+                // No last touch explored event but there is accessibility focus in
+                // the active window. We click in the middle of the focus bounds.
+                Rect focusBounds = mTempRect;
+                if (mAms.getAccessibilityFocusBoundsInActiveWindow(focusBounds)) {
+                    clickLocationX = focusBounds.centerX();
+                    clickLocationY = focusBounds.centerY();
+                } else {
+                    // Out of luck - do nothing.
+                    return;
+                }
+            } else {
+                // If the click is within the active window but not within the
+                // accessibility focus bounds we click in the focus center.
+                final int lastExplorePointerIndex = lastExploreEvent.getActionIndex();
+                clickLocationX = (int) lastExploreEvent.getX(lastExplorePointerIndex);
+                clickLocationY = (int) lastExploreEvent.getY(lastExplorePointerIndex);
+                Rect activeWindowBounds = mTempRect;
+                mAms.getActiveWindowBounds(activeWindowBounds);
+                if (activeWindowBounds.contains(clickLocationX, clickLocationY)) {
+                    Rect focusBounds = mTempRect;
+                    if (mAms.getAccessibilityFocusBoundsInActiveWindow(focusBounds)) {
+                        if (!focusBounds.contains(clickLocationX, clickLocationY)) {
+                            clickLocationX = focusBounds.centerX();
+                            clickLocationY = focusBounds.centerY();
+                        }
+                    }
                 }
             }
 
-            mLongPressingPointerId = mEvent.getPointerId(pointerIndex);
-
-            final int eventX = (int) mEvent.getX(pointerIndex);
-            final int eventY = (int) mEvent.getY(pointerIndex);
-            if (useFocusedBounds) {
-                mLongPressingPointerDeltaX = eventX - bounds.centerX();
-                mLongPressingPointerDeltaY = eventY - bounds.centerY();
-            } else {
-                mLongPressingPointerDeltaX = eventX - exploreLocationX;
-                mLongPressingPointerDeltaY = eventY - exploreLocationY;
-            }
+            mLongPressingPointerId = pointerId;
+            mLongPressingPointerDeltaX = (int) mEvent.getX(pointerIndex) - clickLocationX;
+            mLongPressingPointerDeltaY = (int) mEvent.getY(pointerIndex) - clickLocationY;
 
             sendExitEventsIfNeeded(mPolicyFlags);
 
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 5f63934..9e08584 100755
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -6675,6 +6675,7 @@
         }
     }
 
+    // TODO: Put this on the IWindowManagerService and guard with a permission.
     public IBinder getFocusedWindowClientToken() {
         synchronized (mWindowMap) {
             WindowState windowState = getFocusedWindowLocked();
@@ -6685,6 +6686,18 @@
         }
     }
 
+    // TODO: This is a workaround - remove when 6623031 is fixed.
+    public boolean getWindowFrame(IBinder token, Rect outBounds) {
+        synchronized (mWindowMap) {
+            WindowState windowState = mWindowMap.get(token);
+            if (windowState != null) {
+                outBounds.set(windowState.getFrameLw());
+                return true;
+            }
+        }
+        return false;
+    }
+
     private WindowState getFocusedWindow() {
         synchronized (mWindowMap) {
             return getFocusedWindowLocked();