From a9350fe43cf32b20b94e95cc6cf449aab1093e1a Mon Sep 17 00:00:00 2001 From: Louis Chang Date: Thu, 25 Apr 2019 17:14:20 +0800 Subject: [PATCH] Displays that have focused apps can also be top focused There was no focus window during activity switches. - While starting an activity, the previous top activity was paused and set the AppWindowToken.hiddenRequested to true (while #setVisibility) - While finishing current top activity, the focused window was updated a bit early, which was before the next top activity resumed. In both two cases, the focused window was set to null for a small amount of time. So, we tried to look up the focus in other displays and resulted the extra onWindowFocusChanged() calls for activities on other displays. Bug: 131374329 Test: DisplayContentTests Change-Id: Ia77bf697c237696cad7b42ca6b38157eff497b23 --- .../java/com/android/server/wm/DisplayContent.java | 27 ++++++++++++++-------- .../com/android/server/wm/RootWindowContainer.java | 7 +++++- .../com/android/server/wm/DisplayContentTests.java | 8 +++++++ 3 files changed, 32 insertions(+), 10 deletions(-) diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 652f7ee48b9f..7a989036becc 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -78,6 +78,8 @@ import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_W import static com.android.server.wm.DisplayContentProto.ABOVE_APP_WINDOWS; import static com.android.server.wm.DisplayContentProto.APP_TRANSITION; import static com.android.server.wm.DisplayContentProto.BELOW_APP_WINDOWS; +import static com.android.server.wm.DisplayContentProto.CHANGING_APPS; +import static com.android.server.wm.DisplayContentProto.CLOSING_APPS; import static com.android.server.wm.DisplayContentProto.DISPLAY_FRAMES; import static com.android.server.wm.DisplayContentProto.DISPLAY_INFO; import static com.android.server.wm.DisplayContentProto.DOCKED_STACK_DIVIDER_CONTROLLER; @@ -85,14 +87,12 @@ import static com.android.server.wm.DisplayContentProto.DPI; import static com.android.server.wm.DisplayContentProto.FOCUSED_APP; import static com.android.server.wm.DisplayContentProto.ID; import static com.android.server.wm.DisplayContentProto.IME_WINDOWS; +import static com.android.server.wm.DisplayContentProto.OPENING_APPS; import static com.android.server.wm.DisplayContentProto.PINNED_STACK_CONTROLLER; import static com.android.server.wm.DisplayContentProto.ROTATION; import static com.android.server.wm.DisplayContentProto.SCREEN_ROTATION_ANIMATION; import static com.android.server.wm.DisplayContentProto.STACKS; import static com.android.server.wm.DisplayContentProto.WINDOW_CONTAINER; -import static com.android.server.wm.DisplayContentProto.OPENING_APPS; -import static com.android.server.wm.DisplayContentProto.CHANGING_APPS; -import static com.android.server.wm.DisplayContentProto.CLOSING_APPS; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_BOOT; @@ -2945,9 +2945,16 @@ class DisplayContent extends WindowContainer int topFocusedDisplayId = INVALID_DISPLAY; for (int i = mChildren.size() - 1; i >= 0; --i) { final DisplayContent dc = mChildren.get(i); - changed |= dc.updateFocusedWindowLocked(mode, updateInputWindows); + changed |= dc.updateFocusedWindowLocked(mode, updateInputWindows, topFocusedDisplayId); final WindowState newFocus = dc.mCurrentFocus; if (newFocus != null) { final int pidOfNewFocus = newFocus.mSession.mPid; @@ -180,6 +180,11 @@ class RootWindowContainer extends WindowContainer if (topFocusedDisplayId == INVALID_DISPLAY) { topFocusedDisplayId = dc.getDisplayId(); } + } else if (topFocusedDisplayId == INVALID_DISPLAY && dc.mFocusedApp != null) { + // The top-most display that has a focused app should still be the top focused + // display even when the app window is not ready yet (process not attached or + // window not added yet). + topFocusedDisplayId = dc.getDisplayId(); } } if (topFocusedDisplayId == INVALID_DISPLAY) { diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java index e60e54c9e44f..04f897ed1bdb 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java @@ -380,6 +380,14 @@ public class DisplayContentTests extends WindowTestsBase { assertTrue(window1.isFocused()); assertEquals(perDisplayFocusEnabled && targetSdk >= Q, window2.isFocused()); assertEquals(window1, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus); + + // Make sure top focused display not changed if there is a focused app. + window1.mAppToken.hiddenRequested = true; + window1.getDisplayContent().setFocusedApp(window1.mAppToken); + updateFocusedWindow(); + assertTrue(!window1.isFocused()); + assertEquals(window1.getDisplayId(), + mWm.mRoot.getTopFocusedDisplayContent().getDisplayId()); } /** -- 2.11.0