diff options
author | Svetoslav <svetoslavganov@google.com> | 2014-12-04 12:50:11 -0800 |
---|---|---|
committer | Svetoslav Ganov <svetoslavganov@google.com> | 2014-12-05 00:37:38 +0000 |
commit | 3a0d878ab56475276c61d574af7651820a5cea5a (patch) | |
tree | 52c7a0e7d8a075102a5797fcd6b000bd78971ed6 /services/core | |
parent | bcaa315d488c18deb1ab4c6169dc4b4236982990 (diff) | |
download | frameworks_base-3a0d878ab56475276c61d574af7651820a5cea5a.zip frameworks_base-3a0d878ab56475276c61d574af7651820a5cea5a.tar.gz frameworks_base-3a0d878ab56475276c61d574af7651820a5cea5a.tar.bz2 |
Ensure all events from a showing window are dispatched.
Accessibility services may opt-in to introspect the interactive
windows on the screen. If window introspection is enabled there
is a case where some events from a showing window are received
before the updated window state from the window manager. Now the
window manager sends over the windows before notifying the app
for the focus change.
bug:18625996
Change-Id: Ic481e01efbe12dc92f090f799feeb236672fc7b3
Diffstat (limited to 'services/core')
-rw-r--r-- | services/core/java/com/android/server/wm/AccessibilityController.java | 66 | ||||
-rw-r--r-- | services/core/java/com/android/server/wm/WindowManagerService.java | 20 |
2 files changed, 46 insertions, 40 deletions
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java index 0cbf03a..08754f9 100644 --- a/services/core/java/com/android/server/wm/AccessibilityController.java +++ b/services/core/java/com/android/server/wm/AccessibilityController.java @@ -159,11 +159,15 @@ final class AccessibilityController { } } - public void onWindowFocusChangedLocked() { + public void onWindowFocusChangedNotLocked() { // Not relevant for the display magnifier. - if (mWindowsForAccessibilityObserver != null) { - mWindowsForAccessibilityObserver.scheduleComputeChangedWindowsLocked(); + WindowsForAccessibilityObserver observer = null; + synchronized (mWindowManagerService) { + observer = mWindowsForAccessibilityObserver; + } + if (observer != null) { + observer.performComputeChangedWindowsNotLocked(); } } @@ -937,14 +941,13 @@ final class AccessibilityController { computeChangedWindows(); } + public void performComputeChangedWindowsNotLocked() { + mHandler.removeMessages(MyHandler.MESSAGE_COMPUTE_CHANGED_WINDOWS); + computeChangedWindows(); + } + public void scheduleComputeChangedWindowsLocked() { - // If focus changed, compute changed windows immediately as the focused window - // is used by the accessibility manager service to determine the active window. - if (mWindowManagerService.mCurrentFocus != null - && mWindowManagerService.mCurrentFocus != mWindowManagerService.mLastFocus) { - mHandler.removeMessages(MyHandler.MESSAGE_COMPUTE_CHANGED_WINDOWS); - computeChangedWindows(); - } else if (!mHandler.hasMessages(MyHandler.MESSAGE_COMPUTE_CHANGED_WINDOWS)) { + if (!mHandler.hasMessages(MyHandler.MESSAGE_COMPUTE_CHANGED_WINDOWS)) { mHandler.sendEmptyMessageDelayed(MyHandler.MESSAGE_COMPUTE_CHANGED_WINDOWS, mRecurringAccessibilityEventsIntervalMillis); } @@ -955,6 +958,9 @@ final class AccessibilityController { Slog.i(LOG_TAG, "computeChangedWindows()"); } + boolean windowsChanged = false; + List<WindowInfo> windows = new ArrayList<WindowInfo>(); + synchronized (mWindowManagerService.mWindowMap) { // Do not send the windows if there is no current focus as // the window manager is still looking for where to put it. @@ -975,8 +981,6 @@ final class AccessibilityController { SparseArray<WindowState> visibleWindows = mTempWindowStates; populateVisibleWindowsOnScreenLocked(visibleWindows); - List<WindowInfo> windows = new ArrayList<WindowInfo>(); - Set<IBinder> addedWindows = mTempBinderSet; addedWindows.clear(); @@ -1074,7 +1078,6 @@ final class AccessibilityController { addedWindows.clear(); // We computed the windows and if they changed notify the client. - boolean windowsChanged = false; if (mOldWindows.size() != windows.size()) { // Different size means something changed. windowsChanged = true; @@ -1096,22 +1099,24 @@ final class AccessibilityController { } if (windowsChanged) { - if (DEBUG) { - Log.i(LOG_TAG, "Windows changed:" + windows); - } - // Remember the old windows to detect changes. cacheWindows(windows); - // Announce the change. - mHandler.obtainMessage(MyHandler.MESSAGE_NOTIFY_WINDOWS_CHANGED, - windows).sendToTarget(); - } else { - if (DEBUG) { - Log.i(LOG_TAG, "No windows changed."); - } - // Recycle the nodes as we do not need them. - clearAndRecycleWindows(windows); } } + + // Now we do not hold the lock, so send the windows over. + if (windowsChanged) { + if (DEBUG) { + Log.i(LOG_TAG, "Windows changed:" + windows); + } + mCallback.onWindowsForAccessibilityChanged(windows); + } else { + if (DEBUG) { + Log.i(LOG_TAG, "No windows changed."); + } + } + + // Recycle the windows as we do not need them. + clearAndRecycleWindows(windows); } private void computeWindowBoundsInScreen(WindowState windowState, Rect outBounds) { @@ -1217,7 +1222,7 @@ final class AccessibilityController { return false; } - private void clearAndRecycleWindows(List<WindowInfo> windows) { + private static void clearAndRecycleWindows(List<WindowInfo> windows) { final int windowCount = windows.size(); for (int i = windowCount - 1; i >= 0; i--) { windows.remove(i).recycle(); @@ -1254,7 +1259,6 @@ final class AccessibilityController { private class MyHandler extends Handler { public static final int MESSAGE_COMPUTE_CHANGED_WINDOWS = 1; - public static final int MESSAGE_NOTIFY_WINDOWS_CHANGED = 2; public MyHandler(Looper looper) { super(looper, null, false); @@ -1267,12 +1271,6 @@ final class AccessibilityController { case MESSAGE_COMPUTE_CHANGED_WINDOWS: { computeChangedWindows(); } break; - - case MESSAGE_NOTIFY_WINDOWS_CHANGED: { - List<WindowInfo> windows = (List<WindowInfo>) message.obj; - mCallback.onWindowsForAccessibilityChanged(windows); - clearAndRecycleWindows(windows); - } break; } } } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index b7857e1..2750941 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -7610,7 +7610,15 @@ public class WindowManagerService extends IWindowManager.Stub WindowState lastFocus; WindowState newFocus; + AccessibilityController accessibilityController = null; + synchronized(mWindowMap) { + // TODO(multidisplay): Accessibility supported only of default desiplay. + if (mAccessibilityController != null && getDefaultDisplayContentLocked() + .getDisplayId() == Display.DEFAULT_DISPLAY) { + accessibilityController = mAccessibilityController; + } + lastFocus = mLastFocus; newFocus = mCurrentFocus; if (lastFocus == newFocus) { @@ -7628,6 +7636,12 @@ public class WindowManagerService extends IWindowManager.Stub } } + // First notify the accessibility manager for the change so it has + // the windows before the newly focused one starts firing eventgs. + if (accessibilityController != null) { + accessibilityController.onWindowFocusChangedNotLocked(); + } + //System.out.println("Changing focus from " + lastFocus // + " to " + newFocus); if (newFocus != null) { @@ -10402,12 +10416,6 @@ public class WindowManagerService extends IWindowManager.Stub mCurrentFocus = newFocus; mLosingFocus.remove(newFocus); - // TODO(multidisplay): Accessibilty supported only of default desiplay. - if (mAccessibilityController != null - && displayContent.getDisplayId() == Display.DEFAULT_DISPLAY) { - mAccessibilityController.onWindowFocusChangedLocked(); - } - int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus); if (imWindowChanged && oldFocus != mInputMethodWindow) { |