Compute the focused window in display focus order
A WindowContainer's children are sorted so the focused child is at the
end of the list, so RootWindowContainer needs to iterate from end to
start when looking for the focused window.
Bug: 36590788
Test: DisplayContentTests#testFocusedWindowMultipleDisplays
Change-Id: I56e6b7d2054bc1e74b54a4f99706a08d278fa2e1
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 68d0f24..b0e3e32 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -152,8 +152,7 @@
}
WindowState computeFocusedWindow() {
- final int count = mChildren.size();
- for (int i = 0; i < count; i++) {
+ for (int i = mChildren.size() - 1; i >= 0; i--) {
final DisplayContent dc = mChildren.get(i);
final WindowState win = dc.findFocusedWindow();
if (win != null) {
diff --git a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
index 3868242..dd94a21 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
@@ -21,6 +21,7 @@
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
+import static com.android.server.wm.WindowContainer.POSITION_TOP;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
@@ -233,6 +234,26 @@
assertEquals(currentOverrideConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
}
+ @Test
+ public void testFocusedWindowMultipleDisplays() throws Exception {
+ // Create a focusable window and check that focus is calcualted correctly
+ final WindowState window1 =
+ createWindow(null, TYPE_BASE_APPLICATION, sDisplayContent, "window1");
+ assertEquals(window1, sWm.mRoot.computeFocusedWindow());
+
+ // Check that a new display doesn't affect focus
+ final DisplayContent dc = createNewDisplay();
+ assertEquals(window1, sWm.mRoot.computeFocusedWindow());
+
+ // Add a window to the second display, and it should be focused
+ final WindowState window2 = createWindow(null, TYPE_BASE_APPLICATION, dc, "window2");
+ assertEquals(window2, sWm.mRoot.computeFocusedWindow());
+
+ // Move the first window to the to including parents, and make sure focus is updated
+ window1.getParent().positionChildAt(POSITION_TOP, window1, true);
+ assertEquals(window1, sWm.mRoot.computeFocusedWindow());
+ }
+
private void assertForAllWindowsOrder(List<WindowState> expectedWindows) {
final LinkedList<WindowState> actualWindows = new LinkedList();
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
index 65efd9c..b67080d 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
@@ -16,6 +16,8 @@
package com.android.server.wm;
+import static android.view.View.VISIBLE;
+
import android.app.ActivityManager.TaskDescription;
import android.content.res.Configuration;
import android.graphics.Rect;
@@ -226,7 +228,7 @@
attrs.setTitle(name);
final WindowState w = new WindowState(sWm, sMockSession, sIWindow, token, parent, OP_NONE,
- 0, attrs, 0, 0, ownerCanAddInternalSystemWindow);
+ 0, attrs, VISIBLE, 0, ownerCanAddInternalSystemWindow);
// TODO: Probably better to make this call in the WindowState ctor to avoid errors with
// adding it to the token...
token.addWindow(w);