summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java14
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java32
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java272
-rw-r--r--services/core/java/com/android/server/wm/AccessibilityController.java45
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerInternal.java5
-rw-r--r--services/tests/servicestests/src/com/android/server/accessibility/AbstractAccessibilityServiceConnectionTest.java14
-rw-r--r--services/tests/servicestests/src/com/android/server/accessibility/AccessibilityWindowManagerTest.java198
7 files changed, 425 insertions, 155 deletions
diff --git a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
index 135615708037..5a1a8cd91d0d 100644
--- a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
@@ -362,8 +362,10 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ
if (!permissionGranted) {
return null;
}
+ // TODO [Multi-Display] (b/134891479) :
+ // using correct display Id to replace DEFAULT_DISPLAY.
List<AccessibilityWindowInfo> internalWindowList =
- mA11yWindowManager.getWindowListLocked();
+ mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY);
if (internalWindowList == null) {
return null;
}
@@ -1309,23 +1311,25 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ
*/
private void ensureWindowsAvailableTimed() {
synchronized (mLock) {
- if (mA11yWindowManager.getWindowListLocked() != null) {
+ // TODO [Multi-Display] (b/134891479) :
+ // using correct display Id to replace DEFAULT_DISPLAY.
+ if (mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY) != null) {
return;
}
// If we have no registered callback, update the state we
// we may have to register one but it didn't happen yet.
- if (!mA11yWindowManager.isTrackingWindowsLocked()) {
+ if (!mA11yWindowManager.isTrackingWindowsLocked(Display.DEFAULT_DISPLAY)) {
// Invokes client change to make sure tracking window enabled.
mSystemSupport.onClientChangeLocked(false);
}
// We have no windows but do not care about them, done.
- if (!mA11yWindowManager.isTrackingWindowsLocked()) {
+ if (!mA11yWindowManager.isTrackingWindowsLocked(Display.DEFAULT_DISPLAY)) {
return;
}
// Wait for the windows with a timeout.
final long startMillis = SystemClock.uptimeMillis();
- while (mA11yWindowManager.getWindowListLocked() == null) {
+ while (mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY) == null) {
final long elapsedMillis = SystemClock.uptimeMillis() - startMillis;
final long remainMillis = WAIT_WINDOWS_TIMEOUT_MILLIS - elapsedMillis;
if (remainMillis <= 0) {
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 893e4e49020b..ddf5bbec7eb1 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -272,9 +272,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
mSecurityPolicy = new AccessibilitySecurityPolicy(mContext, this);
mMainHandler = new MainHandler(mContext.getMainLooper());
mGlobalActionPerformer = new GlobalActionPerformer(mContext, mWindowManagerService);
- mA11yDisplayListener = new AccessibilityDisplayListener(mContext, mMainHandler);
mA11yWindowManager = new AccessibilityWindowManager(mLock, mMainHandler,
mWindowManagerService, this, mSecurityPolicy, this);
+ mA11yDisplayListener = new AccessibilityDisplayListener(mContext, mMainHandler);
mSecurityPolicy.setAccessibilityWindowManager(mA11yWindowManager);
registerBroadcastReceivers();
@@ -580,9 +580,15 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
// 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.
- // TODO [Multi-Display] : using correct display Id to replace DEFAULT_DISPLAY
- if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
- && mA11yWindowManager.isTrackingWindowsLocked()) {
+ // TODO [Multi-Display] : using correct display Id to replace DEFAULT_DISPLAY.
+ boolean shouldComputeWindows = false;
+ synchronized (mLock) {
+ if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
+ && mA11yWindowManager.isTrackingWindowsLocked(Display.DEFAULT_DISPLAY)) {
+ shouldComputeWindows = true;
+ }
+ }
+ if (shouldComputeWindows) {
WindowManagerInternal wm = LocalServices.getService(WindowManagerInternal.class);
wm.computeWindowsForAccessibility(Display.DEFAULT_DISPLAY);
}
@@ -1656,10 +1662,18 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
}
}
- if (observingWindows) {
- mA11yWindowManager.startTrackingWindows();
- } else {
- mA11yWindowManager.stopTrackingWindows();
+ // Gets all valid displays and start tracking windows of each display if there is at least
+ // one bound service that can retrieve window content.
+ final ArrayList<Display> displays = getValidDisplayList();
+ for (int i = 0; i < displays.size(); i++) {
+ final Display display = displays.get(i);
+ if (display != null) {
+ if (observingWindows) {
+ mA11yWindowManager.startTrackingWindows(display.getDisplayId());
+ } else {
+ mA11yWindowManager.stopTrackingWindows(display.getDisplayId());
+ }
+ }
}
}
@@ -2559,6 +2573,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
}
}
updateMagnificationLocked(userState);
+ updateWindowsForAccessibilityCallbackLocked(userState);
}
}
@@ -2586,6 +2601,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
if (mMagnificationController != null) {
mMagnificationController.onDisplayRemoved(displayId);
}
+ mA11yWindowManager.stopTrackingWindows(displayId);
}
@Override
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java
index c9efe36b2014..82a593cdfd7f 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java
@@ -79,16 +79,25 @@ public class AccessibilityWindowManager {
private final SparseArray<SparseArray<IBinder>> mWindowTokens = new SparseArray<>();
private RemoteAccessibilityConnection mPictureInPictureActionReplacingConnection;
-
+ // There is only one active window in the system. It is updated when the top focused window
+ // of the top focused display changes and when we receive a TYPE_WINDOW_STATE_CHANGED event.
private int mActiveWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
- private int mFocusedWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
+ // There is only one top focused window in the system. It is updated when the window manager
+ // updates the window lists.
+ private int mTopFocusedWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
private int mAccessibilityFocusedWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
private long mAccessibilityFocusNodeId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
+ // The top focused display and window token updated with the callback of window lists change.
+ private int mTopFocusedDisplayId;
+ private IBinder mTopFocusedWindowToken;
+ // The display has the accessibility focused window currently.
+ private int mAccessibilityFocusedDisplayId = Display.INVALID_DISPLAY;
private boolean mTouchInteractionInProgress;
- // TO-DO [Multi-Display] : make DisplayWindowObserver to plural
- private DisplayWindowsObserver mDisplayWindowsObserver;
+ /** List of Display Windows Observer, mapping from displayId -> DisplayWindowsObserver. */
+ private final SparseArray<DisplayWindowsObserver> mDisplayWindowsObservers =
+ new SparseArray<>();
/**
* This class implements {@link WindowManagerInternal.WindowsForAccessibilityCallback} to
@@ -243,6 +252,7 @@ public class AccessibilityWindowManager {
for (int i = 0; i < windowCount; i++) {
AccessibilityWindowInfo window = mWindows.get(i);
if (window.getId() == windowId) {
+ mAccessibilityFocusedDisplayId = mDisplayId;
window.setAccessibilityFocused(true);
mAccessibilityEventSender.sendAccessibilityEventForCurrentUserLocked(
AccessibilityEvent.obtainWindowsChangedEvent(
@@ -318,17 +328,21 @@ public class AccessibilityWindowManager {
* Callbacks from window manager when there's an accessibility change in windows.
*
* @param forceSend Send the windows for accessibility even if they haven't changed.
+ * @param topFocusedDisplayId The display Id which has the top focused window.
+ * @param topFocusedWindowToken The window token of top focused window.
* @param windows The windows for accessibility.
*/
@Override
- public void onWindowsForAccessibilityChanged(boolean forceSend,
- @NonNull List<WindowInfo> windows) {
+ public void onWindowsForAccessibilityChanged(boolean forceSend, int topFocusedDisplayId,
+ IBinder topFocusedWindowToken, @NonNull List<WindowInfo> windows) {
synchronized (mLock) {
if (DEBUG) {
Slog.i(LOG_TAG, "Display Id = " + mDisplayId);
Slog.i(LOG_TAG, "Windows changed: " + windows);
}
if (shouldUpdateWindowsLocked(forceSend, windows)) {
+ mTopFocusedDisplayId = topFocusedDisplayId;
+ mTopFocusedWindowToken = topFocusedWindowToken;
cacheWindows(windows);
// Lets the policy update the focused and active windows.
updateWindowsLocked(mAccessibilityUserManager.getCurrentUserIdLocked(),
@@ -471,6 +485,7 @@ public class AccessibilityWindowManager {
final List<AccessibilityWindowInfo> oldWindowList = new ArrayList<>(mWindows);
final SparseArray<AccessibilityWindowInfo> oldWindowsById = mA11yWindowInfoById.clone();
+ boolean shouldClearAccessibilityFocus = false;
mWindows.clear();
mA11yWindowInfoById.clear();
@@ -480,9 +495,25 @@ public class AccessibilityWindowManager {
}
mWindowInfoById.clear();
mHasWatchOutsideTouchWindow = false;
- mFocusedWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
- if (!mTouchInteractionInProgress) {
- mActiveWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
+
+ final int windowCount = windows.size();
+ final boolean isTopFocusedDisplay = mDisplayId == mTopFocusedDisplayId;
+ final boolean isAccessibilityFocusedDisplay =
+ mDisplayId == mAccessibilityFocusedDisplayId;
+ // Modifies the value of top focused window, active window and a11y focused window
+ // only if this display is top focused display which has the top focused window.
+ if (isTopFocusedDisplay) {
+ if (windowCount > 0) {
+ // Sets the top focus window by top focused window token.
+ mTopFocusedWindowId = findWindowIdLocked(userId, mTopFocusedWindowToken);
+ } else {
+ // Resets the top focus window when stopping tracking window of this display.
+ mTopFocusedWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
+ }
+ // The active window doesn't need to be reset if the touch operation is progressing.
+ if (!mTouchInteractionInProgress) {
+ mActiveWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
+ }
}
// If the active window goes away while the user is touch exploring we
@@ -492,17 +523,17 @@ public class AccessibilityWindowManager {
// filters out such events.
boolean activeWindowGone = true;
- final int windowCount = windows.size();
-
// We'll clear accessibility focus if the window with focus is no longer visible to
- // accessibility services
- boolean shouldClearAccessibilityFocus =
- mAccessibilityFocusedWindowId != AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
+ // accessibility services.
+ if (isAccessibilityFocusedDisplay) {
+ shouldClearAccessibilityFocus = mAccessibilityFocusedWindowId
+ != AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
+ }
if (windowCount > 0) {
for (int i = 0; i < windowCount; i++) {
final WindowInfo windowInfo = windows.get(i);
final AccessibilityWindowInfo window;
- if (isTrackingWindowsLocked()) {
+ if (mTrackingWindows) {
window = populateReportedWindowLocked(userId, windowInfo);
} else {
window = null;
@@ -513,9 +544,10 @@ public class AccessibilityWindowManager {
window.setLayer(windowCount - 1 - window.getLayer());
final int windowId = window.getId();
- if (window.isFocused()) {
- mFocusedWindowId = windowId;
+ if (window.isFocused() && isTopFocusedDisplay) {
if (!mTouchInteractionInProgress) {
+ // This display is top one, and sets the focus window
+ // as active window.
mActiveWindowId = windowId;
window.setActive(true);
} else if (windowId == mActiveWindowId) {
@@ -530,22 +562,28 @@ public class AccessibilityWindowManager {
mWindowInfoById.put(windowId, WindowInfo.obtain(windowInfo));
}
}
-
- if (mTouchInteractionInProgress && activeWindowGone) {
- mActiveWindowId = mFocusedWindowId;
- }
-
- // Focused window may change the active one, so set the
- // active window once we decided which it is.
final int accessibilityWindowCount = mWindows.size();
- for (int i = 0; i < accessibilityWindowCount; i++) {
- final AccessibilityWindowInfo window = mWindows.get(i);
- if (window.getId() == mActiveWindowId) {
- window.setActive(true);
+ if (isTopFocusedDisplay) {
+ if (mTouchInteractionInProgress && activeWindowGone) {
+ mActiveWindowId = mTopFocusedWindowId;
}
- if (window.getId() == mAccessibilityFocusedWindowId) {
- window.setAccessibilityFocused(true);
- shouldClearAccessibilityFocus = false;
+ // Focused window may change the active one, so set the
+ // active window once we decided which it is.
+ for (int i = 0; i < accessibilityWindowCount; i++) {
+ final AccessibilityWindowInfo window = mWindows.get(i);
+ if (window.getId() == mActiveWindowId) {
+ window.setActive(true);
+ }
+ }
+ }
+ if (isAccessibilityFocusedDisplay) {
+ for (int i = 0; i < accessibilityWindowCount; i++) {
+ final AccessibilityWindowInfo window = mWindows.get(i);
+ if (window.getId() == mAccessibilityFocusedWindowId) {
+ window.setAccessibilityFocused(true);
+ shouldClearAccessibilityFocus = false;
+ break;
+ }
}
}
}
@@ -788,42 +826,86 @@ public class AccessibilityWindowManager {
mAccessibilityEventSender = accessibilityEventSender;
mSecurityPolicy = securityPolicy;
mAccessibilityUserManager = accessibilityUserManager;
- mDisplayWindowsObserver = new DisplayWindowsObserver(Display.DEFAULT_DISPLAY);
}
/**
- * Starts tracking windows changes from window manager.
+ * Starts tracking windows changes from window manager for specified display.
+ *
+ * @param displayId The logical display id.
*/
- public void startTrackingWindows() {
+ public void startTrackingWindows(int displayId) {
synchronized (mLock) {
- mDisplayWindowsObserver.startTrackingWindowsLocked();
+ DisplayWindowsObserver observer = mDisplayWindowsObservers.get(displayId);
+ if (observer == null) {
+ observer = new DisplayWindowsObserver(displayId);
+ }
+ if (observer.isTrackingWindowsLocked()) {
+ return;
+ }
+ if (observer.startTrackingWindowsLocked()) {
+ mDisplayWindowsObservers.put(displayId, observer);
+ }
}
}
/**
- * Stops tracking windows changes from window manager, and clear all windows info.
+ * Stops tracking windows changes from window manager, and clear all windows info for specified
+ * display.
+ *
+ * @param displayId The logical display id.
*/
- public void stopTrackingWindows() {
+ public void stopTrackingWindows(int displayId) {
synchronized (mLock) {
- mDisplayWindowsObserver.stopTrackingWindowsLocked();
+ final DisplayWindowsObserver observer = mDisplayWindowsObservers.get(displayId);
+ if (observer != null) {
+ observer.stopTrackingWindowsLocked();
+ mDisplayWindowsObservers.remove(displayId);
+ }
}
}
/**
- * Returns true if windows changes tracking.
+ * Checks if we are tracking windows on any display.
*
- * @return true if windows changes tracking
+ * @return {@code true} if the observer is tracking windows on any display,
+ * {@code false} otherwise.
*/
public boolean isTrackingWindowsLocked() {
- return mDisplayWindowsObserver.isTrackingWindowsLocked();
+ final int count = mDisplayWindowsObservers.size();
+ if (count > 0) {
+ return true;
+ }
+ return false;
}
/**
- * Returns accessibility windows.
+ * Checks if we are tracking windows on specified display.
+ *
+ * @param displayId The logical display id.
+ * @return {@code true} if the observer is tracking windows on specified display,
+ * {@code false} otherwise.
+ */
+ public boolean isTrackingWindowsLocked(int displayId) {
+ final DisplayWindowsObserver observer = mDisplayWindowsObservers.get(displayId);
+ if (observer != null) {
+ return observer.isTrackingWindowsLocked();
+ }
+ return false;
+ }
+
+ /**
+ * Returns accessibility windows for specified display.
+ *
+ * @param displayId The logical display id.
+ * @return accessibility windows for specified display.
*/
@Nullable
- public List<AccessibilityWindowInfo> getWindowListLocked() {
- return mDisplayWindowsObserver.getWindowListLocked();
+ public List<AccessibilityWindowInfo> getWindowListLocked(int displayId) {
+ final DisplayWindowsObserver observer = mDisplayWindowsObservers.get(displayId);
+ if (observer != null) {
+ return observer.getWindowListLocked();
+ }
+ return null;
}
/**
@@ -841,6 +923,8 @@ public class AccessibilityWindowManager {
@NonNull IAccessibilityInteractionConnection connection, @NonNull String packageName,
int userId) throws RemoteException {
final int windowId;
+ boolean shouldComputeWindows = false;
+ final int displayId = mWindowManagerInternal.getDisplayIdForWindow(windowToken.asBinder());
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
@@ -880,9 +964,14 @@ public class AccessibilityWindowManager {
+ " and token: " + windowToken.asBinder());
}
}
+
+ if (isTrackingWindowsLocked(displayId)) {
+ shouldComputeWindows = true;
+ }
+ }
+ if (shouldComputeWindows) {
+ mWindowManagerInternal.computeWindowsForAccessibility(displayId);
}
- // TODO [Multi-Display] : using correct display Id to replace DEFAULT_DISPLAY
- mWindowManagerInternal.computeWindowsForAccessibility(Display.DEFAULT_DISPLAY);
return windowId;
}
@@ -1067,8 +1156,12 @@ public class AccessibilityWindowManager {
*/
public boolean computePartialInteractiveRegionForWindowLocked(int windowId,
@NonNull Region outRegion) {
- return mDisplayWindowsObserver.computePartialInteractiveRegionForWindowLocked(windowId,
- outRegion);
+ final DisplayWindowsObserver observer = getDisplayWindowObserverByWindowIdLocked(windowId);
+ if (observer != null) {
+ return observer.computePartialInteractiveRegionForWindowLocked(windowId, outRegion);
+ }
+
+ return false;
}
/**
@@ -1101,8 +1194,8 @@ public class AccessibilityWindowManager {
// windows are delivered.
synchronized (mLock) {
if (!isTrackingWindowsLocked()) {
- mFocusedWindowId = findFocusedWindowId(userId);
- if (windowId == mFocusedWindowId) {
+ mTopFocusedWindowId = findFocusedWindowId(userId);
+ if (windowId == mTopFocusedWindowId) {
mActiveWindowId = windowId;
}
}
@@ -1140,6 +1233,7 @@ public class AccessibilityWindowManager {
&& (mAccessibilityFocusedWindowId == windowId)
&& (eventAction != AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS)) {
mAccessibilityFocusedWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
+ mAccessibilityFocusedDisplayId = Display.INVALID_DISPLAY;
}
}
} break;
@@ -1172,7 +1266,7 @@ public class AccessibilityWindowManager {
// the active window before all hover accessibility events from
// the touched window are delivered is fine.
final int oldActiveWindow = mActiveWindowId;
- setActiveWindowLocked(mFocusedWindowId);
+ setActiveWindowLocked(mTopFocusedWindowId);
// If there is no service that can operate with interactive windows
// then we keep the old behavior where a window loses accessibility
@@ -1212,7 +1306,14 @@ public class AccessibilityWindowManager {
mActiveWindowId, AccessibilityEvent.WINDOWS_CHANGE_ACTIVE));
mActiveWindowId = windowId;
- mDisplayWindowsObserver.setActiveWindowLocked(windowId);
+ // Goes through all windows for each display.
+ final int count = mDisplayWindowsObservers.size();
+ for (int i = 0; i < count; i++) {
+ final DisplayWindowsObserver observer = mDisplayWindowsObservers.valueAt(i);
+ if (observer != null) {
+ observer.setActiveWindowLocked(windowId);
+ }
+ }
}
}
@@ -1224,7 +1325,14 @@ public class AccessibilityWindowManager {
WINDOWS_CHANGE_ACCESSIBILITY_FOCUSED));
mAccessibilityFocusedWindowId = windowId;
- mDisplayWindowsObserver.setAccessibilityFocusedWindowLocked(windowId);
+ // Goes through all windows for each display.
+ final int count = mDisplayWindowsObservers.size();
+ for (int i = 0; i < count; i++) {
+ final DisplayWindowsObserver observer = mDisplayWindowsObservers.valueAt(i);
+ if (observer != null) {
+ observer.setAccessibilityFocusedWindowLocked(windowId);
+ }
+ }
}
}
@@ -1236,7 +1344,11 @@ public class AccessibilityWindowManager {
*/
@Nullable
public AccessibilityWindowInfo findA11yWindowInfoByIdLocked(int windowId) {
- return mDisplayWindowsObserver.findA11yWindowInfoByIdLocked(windowId);
+ final DisplayWindowsObserver observer = getDisplayWindowObserverByWindowIdLocked(windowId);
+ if (observer != null) {
+ return observer.findA11yWindowInfoByIdLocked(windowId);
+ }
+ return null;
}
/**
@@ -1247,7 +1359,11 @@ public class AccessibilityWindowManager {
*/
@Nullable
public WindowInfo findWindowInfoByIdLocked(int windowId) {
- return mDisplayWindowsObserver.findWindowInfoByIdLocked(windowId);
+ final DisplayWindowsObserver observer = getDisplayWindowObserverByWindowIdLocked(windowId);
+ if (observer != null) {
+ return observer.findWindowInfoByIdLocked(windowId);
+ }
+ return null;
}
/**
@@ -1259,7 +1375,7 @@ public class AccessibilityWindowManager {
*/
public int getFocusedWindowId(int focusType) {
if (focusType == AccessibilityNodeInfo.FOCUS_INPUT) {
- return mFocusedWindowId;
+ return mTopFocusedWindowId;
} else if (focusType == AccessibilityNodeInfo.FOCUS_ACCESSIBILITY) {
return mAccessibilityFocusedWindowId;
}
@@ -1273,7 +1389,17 @@ public class AccessibilityWindowManager {
*/
@Nullable
public AccessibilityWindowInfo getPictureInPictureWindowLocked() {
- return mDisplayWindowsObserver.getPictureInPictureWindowLocked();
+ AccessibilityWindowInfo windowInfo = null;
+ final int count = mDisplayWindowsObservers.size();
+ for (int i = 0; i < count; i++) {
+ final DisplayWindowsObserver observer = mDisplayWindowsObservers.valueAt(i);
+ if (observer != null) {
+ if ((windowInfo = observer.getPictureInPictureWindowLocked()) != null) {
+ break;
+ }
+ }
+ }
+ return windowInfo;
}
/**
@@ -1313,10 +1439,13 @@ public class AccessibilityWindowManager {
final List<Integer> outsideWindowsIds;
final List<RemoteAccessibilityConnection> connectionList = new ArrayList<>();
synchronized (mLock) {
- outsideWindowsIds =
- mDisplayWindowsObserver.getWatchOutsideTouchWindowIdLocked(targetWindowId);
- for (int i = 0; i < outsideWindowsIds.size(); i++) {
- connectionList.add(getConnectionLocked(userId, outsideWindowsIds.get(i)));
+ final DisplayWindowsObserver observer =
+ getDisplayWindowObserverByWindowIdLocked(targetWindowId);
+ if (observer != null) {
+ outsideWindowsIds = observer.getWatchOutsideTouchWindowIdLocked(targetWindowId);
+ for (int i = 0; i < outsideWindowsIds.size(); i++) {
+ connectionList.add(getConnectionLocked(userId, outsideWindowsIds.get(i)));
+ }
}
}
for (int i = 0; i < connectionList.size(); i++) {
@@ -1398,10 +1527,29 @@ public class AccessibilityWindowManager {
}
}
+ private DisplayWindowsObserver getDisplayWindowObserverByWindowIdLocked(int windowId) {
+ final int count = mDisplayWindowsObservers.size();
+ for (int i = 0; i < count; i++) {
+ final DisplayWindowsObserver observer = mDisplayWindowsObservers.valueAt(i);
+ if (observer != null) {
+ if (observer.findWindowInfoByIdLocked(windowId) != null) {
+ return mDisplayWindowsObservers.get(observer.mDisplayId);
+ }
+ }
+ }
+ return null;
+ }
+
/**
* Dumps all {@link AccessibilityWindowInfo}s here.
*/
public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
- mDisplayWindowsObserver.dumpLocked(fd, pw, args);
+ final int count = mDisplayWindowsObservers.size();
+ for (int i = 0; i < count; i++) {
+ final DisplayWindowsObserver observer = mDisplayWindowsObservers.valueAt(i);
+ if (observer != null) {
+ observer.dumpLocked(fd, pw, args);
+ }
+ }
}
}
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index 26ca975bfc8f..30a3aef01fdb 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -124,11 +124,11 @@ final class AccessibilityController {
return false;
}
- final Display display = dc.getDisplay();
if (mWindowsForAccessibilityObserver.get(displayId) != null) {
+ final Display display = dc.getDisplay();
if (display.getType() == Display.TYPE_VIRTUAL && dc.getParentWindow() != null) {
// The window observer of this embedded display had been set from
- // window manager after setting its parent window
+ // window manager after setting its parent window.
return true;
} else {
throw new IllegalStateException(
@@ -136,9 +136,6 @@ final class AccessibilityController {
+ displayId + " already set!");
}
}
- if (display.getType() == Display.TYPE_OVERLAY) {
- return false;
- }
mWindowsForAccessibilityObserver.put(displayId,
new WindowsForAccessibilityObserver(mService, displayId, callback));
} else {
@@ -287,9 +284,8 @@ final class AccessibilityController {
}
public boolean hasCallbacksLocked() {
- // TODO: support multi-display for windows observer
return (mDisplayMagnifiers.size() > 0
- || mWindowsForAccessibilityObserver != null);
+ || mWindowsForAccessibilityObserver.size() > 0);
}
public void setForceShowMagnifiableBoundsLocked(int displayId, boolean show) {
@@ -1158,15 +1154,15 @@ final class AccessibilityController {
}
List<WindowInfo> windows = new ArrayList<>();
+ final int topFocusedDisplayId;
+ IBinder topFocusedWindowToken = null;
synchronized (mService.mGlobalLock) {
- // Do not send the windows if there is no current focus as
+ // Do not send the windows if there is no top focus as
// the window manager is still looking for where to put it.
// We will do the work when we get a focus change callback.
- // TODO [Multi-Display] : only checks top focused window
- if (!isCurrentFocusWindowOnDefaultDisplay()) {
- return;
- }
+ final WindowState topFocusedWindowState = getTopFocusWindow();
+ if (topFocusedWindowState == null) return;
final DisplayContent dc = mService.mRoot.getDisplayContent(mDisplayId);
if (dc == null) {
@@ -1229,9 +1225,13 @@ final class AccessibilityController {
visibleWindows.clear();
addedWindows.clear();
- }
- mCallback.onWindowsForAccessibilityChanged(forceSend, windows);
+ // Gets the top focused display Id and window token for supporting multi-display.
+ topFocusedDisplayId = mService.mRoot.getTopFocusedDisplayContent().getDisplayId();
+ topFocusedWindowToken = topFocusedWindowState.mClient.asBinder();
+ }
+ mCallback.onWindowsForAccessibilityChanged(forceSend, topFocusedDisplayId,
+ topFocusedWindowToken, windows);
// Recycle the windows as we do not need them.
clearAndRecycleWindows(windows);
@@ -1410,22 +1410,9 @@ final class AccessibilityController {
}
return displayParentWindow;
}
- // TODO [Multi-Display] : only checks top focused window
- private boolean isCurrentFocusWindowOnDefaultDisplay() {
- final WindowState focusedWindow =
- mService.mRoot.getTopFocusedDisplayContent().mCurrentFocus;
- if (focusedWindow == null) {
- return false;
- }
-
- final WindowState rootDisplayParentWindow = findRootDisplayParentWindow(focusedWindow);
- if (!focusedWindow.isDefaultDisplay()
- && (rootDisplayParentWindow == null
- || !rootDisplayParentWindow.isDefaultDisplay())) {
- return false;
- }
- return true;
+ private WindowState getTopFocusWindow() {
+ return mService.mRoot.getTopFocusedDisplayContent().mCurrentFocus;
}
private class MyHandler extends Handler {
diff --git a/services/core/java/com/android/server/wm/WindowManagerInternal.java b/services/core/java/com/android/server/wm/WindowManagerInternal.java
index 05cfbd4e39d9..750926f11180 100644
--- a/services/core/java/com/android/server/wm/WindowManagerInternal.java
+++ b/services/core/java/com/android/server/wm/WindowManagerInternal.java
@@ -52,9 +52,12 @@ public abstract class WindowManagerInternal {
* Called when the windows for accessibility changed.
*
* @param forceSend Send the windows for accessibility even if they haven't changed.
+ * @param topFocusedDisplayId The display Id which has the top focused window.
+ * @param topFocusedWindowToken The window token of top focused window.
* @param windows The windows for accessibility.
*/
- void onWindowsForAccessibilityChanged(boolean forceSend, List<WindowInfo> windows);
+ void onWindowsForAccessibilityChanged(boolean forceSend, int topFocusedDisplayId,
+ IBinder topFocusedWindowToken, @NonNull List<WindowInfo> windows);
}
/**
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AbstractAccessibilityServiceConnectionTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AbstractAccessibilityServiceConnectionTest.java
index 1084d625f8a3..f767598e7791 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AbstractAccessibilityServiceConnectionTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AbstractAccessibilityServiceConnectionTest.java
@@ -76,6 +76,7 @@ import android.os.PowerManager;
import android.os.Process;
import android.os.RemoteException;
import android.testing.DexmakerShareClassLoaderRule;
+import android.view.Display;
import android.view.KeyEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityWindowInfo;
@@ -178,7 +179,8 @@ public class AbstractAccessibilityServiceConnectionTest {
// Fake a11yWindowInfo and remote a11y connection for tests.
addA11yWindowInfo(mA11yWindowInfos, WINDOWID, false);
addA11yWindowInfo(mA11yWindowInfos, PIP_WINDOWID, true);
- when(mMockA11yWindowManager.getWindowListLocked()).thenReturn(mA11yWindowInfos);
+ when(mMockA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY))
+ .thenReturn(mA11yWindowInfos);
when(mMockA11yWindowManager.findA11yWindowInfoByIdLocked(WINDOWID))
.thenReturn(mA11yWindowInfos.get(0));
when(mMockA11yWindowManager.findA11yWindowInfoByIdLocked(PIP_WINDOWID))
@@ -289,8 +291,9 @@ public class AbstractAccessibilityServiceConnectionTest {
@Test
public void getWindows_notTrackingWindows_invokeOnClientChange() {
- when(mMockA11yWindowManager.getWindowListLocked()).thenReturn(null);
- when(mMockA11yWindowManager.isTrackingWindowsLocked()).thenReturn(false);
+ when(mMockA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY)).thenReturn(null);
+ when(mMockA11yWindowManager.isTrackingWindowsLocked(Display.DEFAULT_DISPLAY))
+ .thenReturn(false);
mServiceConnection.getWindows();
verify(mMockSystemSupport).onClientChangeLocked(false);
@@ -315,8 +318,9 @@ public class AbstractAccessibilityServiceConnectionTest {
@Test
public void getWindow_notTrackingWindows_invokeOnClientChange() {
- when(mMockA11yWindowManager.getWindowListLocked()).thenReturn(null);
- when(mMockA11yWindowManager.isTrackingWindowsLocked()).thenReturn(false);
+ when(mMockA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY)).thenReturn(null);
+ when(mMockA11yWindowManager.isTrackingWindowsLocked(Display.DEFAULT_DISPLAY))
+ .thenReturn(false);
mServiceConnection.getWindow(WINDOWID);
verify(mMockSystemSupport).onClientChangeLocked(false);
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityWindowManagerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityWindowManagerTest.java
index 93c16fedcc1b..b7b5a4eaacfa 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityWindowManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityWindowManagerTest.java
@@ -79,17 +79,22 @@ public class AccessibilityWindowManagerTest {
private static final int USER_SYSTEM_ID = UserHandle.USER_SYSTEM;
private static final int USER_PROFILE = 11;
private static final int USER_PROFILE_PARENT = 1;
- // TO-DO [Multi-Display] : change the display count to 2
- private static final int DISPLAY_COUNT = 1;
+ private static final int SECONDARY_DISPLAY_ID = Display.DEFAULT_DISPLAY + 1;
private static final int NUM_GLOBAL_WINDOWS = 4;
private static final int NUM_APP_WINDOWS = 4;
- private static final int NUM_OF_WINDOWS = (NUM_GLOBAL_WINDOWS + NUM_APP_WINDOWS)
- * DISPLAY_COUNT;
+ private static final int NUM_OF_WINDOWS = (NUM_GLOBAL_WINDOWS + NUM_APP_WINDOWS);
private static final int DEFAULT_FOCUSED_INDEX = 1;
private static final int SCREEN_WIDTH = 1080;
private static final int SCREEN_HEIGHT = 1920;
private AccessibilityWindowManager mA11yWindowManager;
+ // Window manager will support multiple focused window if config_perDisplayFocusEnabled is true,
+ // i.e., each display would have its current focused window, and one of all focused windows
+ // would be top focused window. Otherwise, window manager only supports one focused window
+ // at all displays, and that focused window would be top focused window.
+ private boolean mSupportPerDisplayFocus = false;
+ private int mTopFocusedDisplayId = Display.INVALID_DISPLAY;
+ private IBinder mTopFocusedWindowToken = null;
// List of window token, mapping from windowId -> window token.
private final SparseArray<IWindow> mA11yWindowTokens = new SparseArray<>();
@@ -123,12 +128,9 @@ public class AccessibilityWindowManagerTest {
mMockA11yEventSender,
mMockA11ySecurityPolicy,
mMockA11yUserManager);
-
- for (int i = 0; i < DISPLAY_COUNT; i++) {
- when(mMockWindowManagerInternal.setWindowsForAccessibilityCallback(eq(i), any()))
- .thenReturn(true);
- startTrackingPerDisplay(i);
- }
+ // Starts tracking window of default display and sets the default display
+ // as top focused display before each testing starts.
+ startTrackingPerDisplay(Display.DEFAULT_DISPLAY);
// AccessibilityEventSender is invoked during onWindowsForAccessibilityChanged.
// Resets it for mockito verify of further test case.
@@ -143,7 +145,7 @@ public class AccessibilityWindowManagerTest {
@Test
public void startTrackingWindows_shouldEnableWindowManagerCallback() {
// AccessibilityWindowManager#startTrackingWindows already invoked in setup.
- assertTrue(mA11yWindowManager.isTrackingWindowsLocked());
+ assertTrue(mA11yWindowManager.isTrackingWindowsLocked(Display.DEFAULT_DISPLAY));
final WindowsForAccessibilityCallback callbacks =
mCallbackOfWindows.get(Display.DEFAULT_DISPLAY);
verify(mMockWindowManagerInternal).setWindowsForAccessibilityCallback(
@@ -152,11 +154,11 @@ public class AccessibilityWindowManagerTest {
@Test
public void stopTrackingWindows_shouldDisableWindowManagerCallback() {
- assertTrue(mA11yWindowManager.isTrackingWindowsLocked());
+ assertTrue(mA11yWindowManager.isTrackingWindowsLocked(Display.DEFAULT_DISPLAY));
Mockito.reset(mMockWindowManagerInternal);
- mA11yWindowManager.stopTrackingWindows();
- assertFalse(mA11yWindowManager.isTrackingWindowsLocked());
+ mA11yWindowManager.stopTrackingWindows(Display.DEFAULT_DISPLAY);
+ assertFalse(mA11yWindowManager.isTrackingWindowsLocked(Display.DEFAULT_DISPLAY));
verify(mMockWindowManagerInternal).setWindowsForAccessibilityCallback(
eq(Display.DEFAULT_DISPLAY), isNull());
@@ -164,11 +166,11 @@ public class AccessibilityWindowManagerTest {
@Test
public void stopTrackingWindows_shouldClearWindows() {
- assertTrue(mA11yWindowManager.isTrackingWindowsLocked());
+ assertTrue(mA11yWindowManager.isTrackingWindowsLocked(Display.DEFAULT_DISPLAY));
final int activeWindowId = mA11yWindowManager.getActiveWindowId(USER_SYSTEM_ID);
- mA11yWindowManager.stopTrackingWindows();
- assertNull(mA11yWindowManager.getWindowListLocked());
+ mA11yWindowManager.stopTrackingWindows(Display.DEFAULT_DISPLAY);
+ assertNull(mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY));
assertEquals(mA11yWindowManager.getFocusedWindowId(AccessibilityNodeInfo.FOCUS_INPUT),
AccessibilityWindowInfo.UNDEFINED_WINDOW_ID);
assertEquals(mA11yWindowManager.getActiveWindowId(USER_SYSTEM_ID),
@@ -176,6 +178,20 @@ public class AccessibilityWindowManagerTest {
}
@Test
+ public void stopTrackingWindows_onNonTopFocusedDisplay_shouldNotResetTopFocusWindow()
+ throws RemoteException {
+ // At setup, the default display sets be the top focused display and
+ // its current focused window sets be the top focused window.
+ // Starts tracking window of second display.
+ startTrackingPerDisplay(SECONDARY_DISPLAY_ID);
+ assertTrue(mA11yWindowManager.isTrackingWindowsLocked(SECONDARY_DISPLAY_ID));
+ // Stops tracking windows of second display.
+ mA11yWindowManager.stopTrackingWindows(SECONDARY_DISPLAY_ID);
+ assertNotEquals(mA11yWindowManager.getFocusedWindowId(AccessibilityNodeInfo.FOCUS_INPUT),
+ AccessibilityWindowInfo.UNDEFINED_WINDOW_ID);
+ }
+
+ @Test
public void onWindowsChanged_duringTouchInteractAndFocusChange_shouldChangeActiveWindow() {
final int activeWindowId = mA11yWindowManager.getActiveWindowId(USER_SYSTEM_ID);
WindowInfo focusedWindowInfo =
@@ -196,10 +212,66 @@ public class AccessibilityWindowManagerTest {
}
@Test
+ public void
+ onWindowsChanged_focusChangeOnNonTopFocusedDisplay_perDisplayFocusOn_notChangeWindow()
+ throws RemoteException {
+ // At setup, the default display sets be the top focused display and
+ // its current focused window sets be the top focused window.
+ // Sets supporting multiple focused window, i.e., config_perDisplayFocusEnabled is true.
+ mSupportPerDisplayFocus = true;
+ // Starts tracking window of second display.
+ startTrackingPerDisplay(SECONDARY_DISPLAY_ID);
+ // Gets the active window.
+ final int activeWindowId = mA11yWindowManager.getActiveWindowId(USER_SYSTEM_ID);
+ // Gets the top focused window.
+ final int topFocusedWindowId =
+ mA11yWindowManager.getFocusedWindowId(AccessibilityNodeInfo.FOCUS_INPUT);
+ // Changes the current focused window at second display.
+ changeFocusedWindowOnDisplayPerDisplayFocusConfig(SECONDARY_DISPLAY_ID,
+ DEFAULT_FOCUSED_INDEX + 1, Display.DEFAULT_DISPLAY, DEFAULT_FOCUSED_INDEX);
+
+ onWindowsForAccessibilityChanged(SECONDARY_DISPLAY_ID, SEND_ON_WINDOW_CHANGES);
+ // The active window should not be changed.
+ assertEquals(activeWindowId, mA11yWindowManager.getActiveWindowId(USER_SYSTEM_ID));
+ // The top focused window should not be changed.
+ assertEquals(topFocusedWindowId,
+ mA11yWindowManager.getFocusedWindowId(AccessibilityNodeInfo.FOCUS_INPUT));
+ }
+
+ @Test
+ public void
+ onWindowChange_focusChangeToNonTopFocusedDisplay_perDisplayFocusOff_shouldChangeWindow()
+ throws RemoteException {
+ // At setup, the default display sets be the top focused display and
+ // its current focused window sets be the top focused window.
+ // Sets not supporting multiple focused window, i.e., config_perDisplayFocusEnabled is
+ // false.
+ mSupportPerDisplayFocus = false;
+ // Starts tracking window of second display.
+ startTrackingPerDisplay(SECONDARY_DISPLAY_ID);
+ // Gets the active window.
+ final int activeWindowId = mA11yWindowManager.getActiveWindowId(USER_SYSTEM_ID);
+ // Gets the top focused window.
+ final int topFocusedWindowId =
+ mA11yWindowManager.getFocusedWindowId(AccessibilityNodeInfo.FOCUS_INPUT);
+ // Changes the current focused window from default display to second display.
+ changeFocusedWindowOnDisplayPerDisplayFocusConfig(SECONDARY_DISPLAY_ID,
+ DEFAULT_FOCUSED_INDEX, Display.DEFAULT_DISPLAY, DEFAULT_FOCUSED_INDEX);
+
+ onWindowsForAccessibilityChanged(Display.DEFAULT_DISPLAY, SEND_ON_WINDOW_CHANGES);
+ onWindowsForAccessibilityChanged(SECONDARY_DISPLAY_ID, SEND_ON_WINDOW_CHANGES);
+ // The active window should be changed.
+ assertNotEquals(activeWindowId, mA11yWindowManager.getActiveWindowId(USER_SYSTEM_ID));
+ // The top focused window should be changed.
+ assertNotEquals(topFocusedWindowId,
+ mA11yWindowManager.getFocusedWindowId(AccessibilityNodeInfo.FOCUS_INPUT));
+ }
+
+ @Test
public void onWindowsChanged_shouldReportCorrectLayer() {
// AccessibilityWindowManager#onWindowsForAccessibilityChanged already invoked in setup.
List<AccessibilityWindowInfo> a11yWindows =
- mA11yWindowManager.getWindowListLocked();
+ mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY);
for (int i = 0; i < a11yWindows.size(); i++) {
final AccessibilityWindowInfo a11yWindow = a11yWindows.get(i);
final WindowInfo windowInfo = mWindowInfos.get(Display.DEFAULT_DISPLAY).get(i);
@@ -212,7 +284,7 @@ public class AccessibilityWindowManagerTest {
public void onWindowsChanged_shouldReportCorrectOrder() {
// AccessibilityWindowManager#onWindowsForAccessibilityChanged already invoked in setup.
List<AccessibilityWindowInfo> a11yWindows =
- mA11yWindowManager.getWindowListLocked();
+ mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY);
for (int i = 0; i < a11yWindows.size(); i++) {
final AccessibilityWindowInfo a11yWindow = a11yWindows.get(i);
final IBinder windowToken = mA11yWindowManager
@@ -226,31 +298,31 @@ public class AccessibilityWindowManagerTest {
public void onWindowsChangedAndForceSend_shouldUpdateWindows() {
final WindowInfo windowInfo = mWindowInfos.get(Display.DEFAULT_DISPLAY).get(0);
final int correctLayer =
- mA11yWindowManager.getWindowListLocked().get(0).getLayer();
+ mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY).get(0).getLayer();
windowInfo.layer += 1;
onWindowsForAccessibilityChanged(Display.DEFAULT_DISPLAY, FORCE_SEND);
assertNotEquals(correctLayer,
- mA11yWindowManager.getWindowListLocked().get(0).getLayer());
+ mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY).get(0).getLayer());
}
@Test
public void onWindowsChangedNoForceSend_layerChanged_shouldNotUpdateWindows() {
final WindowInfo windowInfo = mWindowInfos.get(Display.DEFAULT_DISPLAY).get(0);
final int correctLayer =
- mA11yWindowManager.getWindowListLocked().get(0).getLayer();
+ mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY).get(0).getLayer();
windowInfo.layer += 1;
onWindowsForAccessibilityChanged(Display.DEFAULT_DISPLAY, SEND_ON_WINDOW_CHANGES);
assertEquals(correctLayer,
- mA11yWindowManager.getWindowListLocked().get(0).getLayer());
+ mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY).get(0).getLayer());
}
@Test
public void onWindowsChangedNoForceSend_windowChanged_shouldUpdateWindows()
throws RemoteException {
final AccessibilityWindowInfo oldWindow =
- mA11yWindowManager.getWindowListLocked().get(0);
+ mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY).get(0);
final IWindow token = addAccessibilityInteractionConnection(Display.DEFAULT_DISPLAY,
true, USER_SYSTEM_ID);
final WindowInfo windowInfo = WindowInfo.obtain();
@@ -262,7 +334,7 @@ public class AccessibilityWindowManagerTest {
onWindowsForAccessibilityChanged(Display.DEFAULT_DISPLAY, SEND_ON_WINDOW_CHANGES);
assertNotEquals(oldWindow,
- mA11yWindowManager.getWindowListLocked().get(0));
+ mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY).get(0));
}
@Test
@@ -274,7 +346,8 @@ public class AccessibilityWindowManagerTest {
windowInfo.focused = true;
onWindowsForAccessibilityChanged(Display.DEFAULT_DISPLAY, SEND_ON_WINDOW_CHANGES);
- assertTrue(mA11yWindowManager.getWindowListLocked().get(0).isFocused());
+ assertTrue(mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY).get(0)
+ .isFocused());
}
@Test
@@ -305,7 +378,7 @@ public class AccessibilityWindowManagerTest {
@Test
public void getWindowTokenForUserAndWindowId_shouldNotNull() {
final List<AccessibilityWindowInfo> windows =
- mA11yWindowManager.getWindowListLocked();
+ mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY);
for (int i = 0; i < windows.size(); i++) {
final int windowId = windows.get(i).getId();
@@ -317,7 +390,7 @@ public class AccessibilityWindowManagerTest {
@Test
public void findWindowId() {
final List<AccessibilityWindowInfo> windows =
- mA11yWindowManager.getWindowListLocked();
+ mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY);
for (int i = 0; i < windows.size(); i++) {
final int windowId = windows.get(i).getId();
final IBinder windowToken = mA11yWindowManager.getWindowTokenForUserAndWindowIdLocked(
@@ -339,7 +412,7 @@ public class AccessibilityWindowManagerTest {
onWindowsForAccessibilityChanged(Display.DEFAULT_DISPLAY, SEND_ON_WINDOW_CHANGES);
final List<AccessibilityWindowInfo> a11yWindows =
- mA11yWindowManager.getWindowListLocked();
+ mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY);
final Region outBounds = new Region();
int windowId = a11yWindows.get(0).getId();
@@ -362,7 +435,7 @@ public class AccessibilityWindowManagerTest {
onWindowsForAccessibilityChanged(Display.DEFAULT_DISPLAY, SEND_ON_WINDOW_CHANGES);
final List<AccessibilityWindowInfo> a11yWindows =
- mA11yWindowManager.getWindowListLocked();
+ mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY);
final Region outBounds = new Region();
int windowId = a11yWindows.get(1).getId();
@@ -375,7 +448,7 @@ public class AccessibilityWindowManagerTest {
public void computePartialInteractiveRegionForWindow_notVisible_returnEmptyRegion() {
// Since z-order #0 WindowInfo is full screen, z-order #1 WindowInfo should be invisible.
final List<AccessibilityWindowInfo> a11yWindows =
- mA11yWindowManager.getWindowListLocked();
+ mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY);
final Region outBounds = new Region();
int windowId = a11yWindows.get(1).getId();
@@ -393,7 +466,7 @@ public class AccessibilityWindowManagerTest {
onWindowsForAccessibilityChanged(Display.DEFAULT_DISPLAY, SEND_ON_WINDOW_CHANGES);
final List<AccessibilityWindowInfo> a11yWindows =
- mA11yWindowManager.getWindowListLocked();
+ mA11yWindowManager.getWindowListLocked(Display.DEFAULT_DISPLAY);
final Region outBounds = new Region();
int windowId = a11yWindows.get(1).getId();
@@ -413,7 +486,7 @@ public class AccessibilityWindowManagerTest {
.thenReturn(eventWindowToken);
final int noUse = 0;
- mA11yWindowManager.stopTrackingWindows();
+ mA11yWindowManager.stopTrackingWindows(Display.DEFAULT_DISPLAY);
mA11yWindowManager.updateActiveAndAccessibilityFocusedWindowLocked(USER_SYSTEM_ID,
eventWindowId,
noUse,
@@ -553,7 +626,7 @@ public class AccessibilityWindowManagerTest {
mA11yWindowManager.getConnectionLocked(
USER_SYSTEM_ID, newFocusWindowId).getRemote();
- mA11yWindowManager.stopTrackingWindows();
+ mA11yWindowManager.stopTrackingWindows(Display.DEFAULT_DISPLAY);
final int noUse = 0;
mA11yWindowManager.updateActiveAndAccessibilityFocusedWindowLocked(USER_SYSTEM_ID,
defaultFocusWindowId,
@@ -636,20 +709,27 @@ public class AccessibilityWindowManagerTest {
false, USER_SYSTEM_ID);
addWindowInfo(windowInfosForDisplay, token, layer++);
}
- // Setups default focus.
- windowInfosForDisplay.get(DEFAULT_FOCUSED_INDEX).focused = true;
+ // Sets up current focused window of display.
+ // Each display has its own current focused window if config_perDisplayFocusEnabled is true.
+ // Otherwise only default display needs to current focused window.
+ if (mSupportPerDisplayFocus || displayId == Display.DEFAULT_DISPLAY) {
+ windowInfosForDisplay.get(DEFAULT_FOCUSED_INDEX).focused = true;
+ }
// Turns on windows tracking, and update window info.
- mA11yWindowManager.startTrackingWindows();
+ when(mMockWindowManagerInternal.setWindowsForAccessibilityCallback(eq(displayId), any()))
+ .thenReturn(true);
+ mA11yWindowManager.startTrackingWindows(displayId);
// Puts window lists into array.
mWindowInfos.put(displayId, windowInfosForDisplay);
- // Sets the default display as the top focused display.
+ // Sets the default display is the top focused display and
+ // its current focused window is the top focused window.
if (displayId == Display.DEFAULT_DISPLAY) {
setTopFocusedWindowAndDisplay(displayId, DEFAULT_FOCUSED_INDEX);
}
// Invokes callback for sending window lists to A11y framework.
onWindowsForAccessibilityChanged(displayId, FORCE_SEND);
- assertEquals(mA11yWindowManager.getWindowListLocked().size(),
+ assertEquals(mA11yWindowManager.getWindowListLocked(displayId).size(),
windowInfosForDisplay.size());
}
@@ -700,12 +780,9 @@ public class AccessibilityWindowManagerTest {
private void setTopFocusedWindowAndDisplay(int displayId, int index) {
// Sets the top focus window.
- final IBinder eventWindowToken = mWindowInfos.get(displayId).get(index).token;
- when(mMockWindowManagerInternal.getFocusedWindowToken())
- .thenReturn(eventWindowToken);
+ mTopFocusedWindowToken = mWindowInfos.get(displayId).get(index).token;
// Sets the top focused display.
- when(mMockWindowManagerInternal.getDisplayIdForWindow(eventWindowToken))
- .thenReturn(displayId);
+ mTopFocusedDisplayId = displayId;
}
private void onWindowsForAccessibilityChanged(int displayId, boolean forceSend) {
@@ -714,7 +791,38 @@ public class AccessibilityWindowManagerTest {
callbacks = getWindowsForAccessibilityCallbacks(displayId);
mCallbackOfWindows.put(displayId, callbacks);
}
- callbacks.onWindowsForAccessibilityChanged(forceSend, mWindowInfos.get(displayId));
+ callbacks.onWindowsForAccessibilityChanged(forceSend, mTopFocusedDisplayId,
+ mTopFocusedWindowToken, mWindowInfos.get(displayId));
+ }
+
+ private void changeFocusedWindowOnDisplayPerDisplayFocusConfig(
+ int changeFocusedDisplayId, int newFocusedWindowIndex, int oldTopFocusedDisplayId,
+ int oldFocusedWindowIndex) {
+ if (mSupportPerDisplayFocus) {
+ // Gets the old focused window of display which wants to change focused window.
+ WindowInfo focusedWindowInfo =
+ mWindowInfos.get(changeFocusedDisplayId).get(oldFocusedWindowIndex);
+ // Resets the focus of old focused window.
+ focusedWindowInfo.focused = false;
+ // Gets the new window of display which wants to change focused window.
+ focusedWindowInfo =
+ mWindowInfos.get(changeFocusedDisplayId).get(newFocusedWindowIndex);
+ // Sets the focus of new focused window.
+ focusedWindowInfo.focused = true;
+ } else {
+ // Gets the window of display which wants to change focused window.
+ WindowInfo focusedWindowInfo =
+ mWindowInfos.get(changeFocusedDisplayId).get(newFocusedWindowIndex);
+ // Sets the focus of new focused window.
+ focusedWindowInfo.focused = true;
+ // Gets the old focused window of old top focused display.
+ focusedWindowInfo =
+ mWindowInfos.get(oldTopFocusedDisplayId).get(oldFocusedWindowIndex);
+ // Resets the focus of old focused window.
+ focusedWindowInfo.focused = false;
+ // Changes the top focused display and window.
+ setTopFocusedWindowAndDisplay(changeFocusedDisplayId, newFocusedWindowIndex);
+ }
}
static class WindowIdMatcher extends TypeSafeMatcher<AccessibilityEvent> {