summaryrefslogtreecommitdiffstats
path: root/services/core
diff options
context:
space:
mode:
authorSvetoslav <svetoslavganov@google.com>2014-12-04 12:50:11 -0800
committerSvetoslav Ganov <svetoslavganov@google.com>2014-12-05 00:37:38 +0000
commit3a0d878ab56475276c61d574af7651820a5cea5a (patch)
tree52c7a0e7d8a075102a5797fcd6b000bd78971ed6 /services/core
parentbcaa315d488c18deb1ab4c6169dc4b4236982990 (diff)
downloadframeworks_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.java66
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java20
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) {