Update windows before sending a window state change event

Change-Id: Ie25b75ccc739dcacbbffd2b3a32fe65086882c64
diff --git a/core/java/android/view/WindowManagerInternal.java b/core/java/android/view/WindowManagerInternal.java
index 610dff8..653e583 100644
--- a/core/java/android/view/WindowManagerInternal.java
+++ b/core/java/android/view/WindowManagerInternal.java
@@ -287,4 +287,9 @@
      * @return True if and only if the docked divider is currently in resize mode.
      */
     public abstract boolean isDockedDividerResizing();
+
+    /**
+     * Requests the window manager to recompute the windows for accessibility.
+     */
+    public abstract void computeWindowsForAccessibility();
 }
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 7a12289..e06b9c5 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -426,6 +426,8 @@
 
     @Override
     public boolean sendAccessibilityEvent(AccessibilityEvent event, int userId) {
+        boolean dispatchEvent = false;
+
         synchronized (mLock) {
             // We treat calls from a profile as if made by its parent as profiles
             // share the accessibility state of the parent. The call below
@@ -440,15 +442,31 @@
                 mSecurityPolicy.updateActiveAndAccessibilityFocusedWindowLocked(event.getWindowId(),
                         event.getSourceNodeId(), event.getEventType(), event.getAction());
                 mSecurityPolicy.updateEventSourceLocked(event);
-                notifyAccessibilityServicesDelayedLocked(event, false);
-                notifyAccessibilityServicesDelayedLocked(event, true);
+                dispatchEvent = true;
             }
             if (mHasInputFilter && mInputFilter != null) {
                 mMainHandler.obtainMessage(MainHandler.MSG_SEND_ACCESSIBILITY_EVENT_TO_INPUT_FILTER,
                         AccessibilityEvent.obtain(event)).sendToTarget();
             }
-            event.recycle();
         }
+
+        if (dispatchEvent) {
+            // Make sure clients receiving this event will be able to get the
+            // current state of the windows as the window manager may be delaying
+            // the computation for performance reasons.
+            if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
+                    && mWindowsForAccessibilityCallback != null) {
+                WindowManagerInternal wm = LocalServices.getService(WindowManagerInternal.class);
+                wm.computeWindowsForAccessibility();
+            }
+            synchronized (mLock) {
+                notifyAccessibilityServicesDelayedLocked(event, false);
+                notifyAccessibilityServicesDelayedLocked(event, true);
+            }
+        }
+
+        event.recycle();
+
         return (OWN_PROCESS_ID != Binder.getCallingPid());
     }
 
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index a5ddf5a..894c27c 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -115,6 +115,16 @@
         }
     }
 
+    public void performComputeChangedWindowsNotLocked() {
+        WindowsForAccessibilityObserver observer = null;
+        synchronized (mWindowManagerService) {
+            observer = mWindowsForAccessibilityObserver;
+        }
+        if (observer != null) {
+            observer.performComputeChangedWindowsNotLocked();
+        }
+    }
+
     public void setMagnificationSpecLocked(MagnificationSpec spec) {
         if (mDisplayMagnifier != null) {
             mDisplayMagnifier.setMagnificationSpecLocked(spec);
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index eed751f..5b97a01 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -11525,5 +11525,16 @@
                 return getDefaultDisplayContentLocked().getDockedDividerController().isResizing();
             }
         }
+
+        @Override
+        public void computeWindowsForAccessibility() {
+            final AccessibilityController accessibilityController;
+            synchronized (mWindowMap) {
+                accessibilityController = mAccessibilityController;
+            }
+            if (accessibilityController != null) {
+                accessibilityController.performComputeChangedWindowsNotLocked();
+            }
+        }
     }
 }