Use last focused window to control SysUI while IMC dialog is shown
This change fixes a bug that if a child window hides the system UI
but its parent activity window doesn't, the system UI may keep
showing and hiding infinitely.
Bug: b/111490047
Test: 1. atest WindowManagerSmokeTest
2. atest CtsWindowManagerDeviceTestCases:LayoutTests
Change-Id: Id8bd6e80fe19051b97918089a05f2a12fc1a673d
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index e6195b4..883e939 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -631,8 +631,10 @@
int mPointerLocationMode = 0; // guarded by mLock
- // The last window we were told about in focusChanged.
+ // The windows we were told about in focusChanged.
WindowState mFocusedWindow;
+ WindowState mLastFocusedWindow;
+
IApplicationToken mFocusedApp;
PointerLocationView mPointerLocationView;
@@ -3334,6 +3336,9 @@
mNavigationBar = null;
mNavigationBarController.setWindow(null);
}
+ if (mLastFocusedWindow == win) {
+ mLastFocusedWindow = null;
+ }
mScreenDecorWindows.remove(win);
}
@@ -5879,7 +5884,8 @@
@Override
public int focusChangedLw(WindowState lastFocus, WindowState newFocus) {
mFocusedWindow = newFocus;
- if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) {
+ mLastFocusedWindow = lastFocus;
+ if ((updateSystemUiVisibilityLw() & SYSTEM_UI_CHANGING_LAYOUT) != 0) {
// If the navigation bar has been hidden or shown, we need to do another
// layout pass to update that window.
return FINISH_LAYOUT_REDO_LAYOUT;
@@ -8105,10 +8111,19 @@
if (winCandidate == null) {
return 0;
}
+
+ // The immersive mode confirmation should never affect the system bar visibility, otherwise
+ // it will unhide the navigation bar and hide itself.
if (winCandidate.getAttrs().token == mImmersiveModeConfirmation.getWindowToken()) {
- // The immersive mode confirmation should never affect the system bar visibility,
- // otherwise it will unhide the navigation bar and hide itself.
- winCandidate = isStatusBarKeyguard() ? mStatusBar : mTopFullscreenOpaqueWindowState;
+
+ // The immersive mode confirmation took the focus from mLastFocusedWindow which was
+ // controlling the system ui visibility. So if mLastFocusedWindow can still receive
+ // keys, we let it keep controlling the visibility.
+ final boolean lastFocusCanReceiveKeys =
+ (mLastFocusedWindow != null && mLastFocusedWindow.canReceiveKeys());
+ winCandidate = isStatusBarKeyguard() ? mStatusBar
+ : lastFocusCanReceiveKeys ? mLastFocusedWindow
+ : mTopFullscreenOpaqueWindowState;
if (winCandidate == null) {
return 0;
}
diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
index 1ebbe3ac..7ea6200 100644
--- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
@@ -491,6 +491,9 @@
*/
boolean canAcquireSleepToken();
+ /** @return true if this window desires key events. */
+ boolean canReceiveKeys();
+
/**
* Writes {@link com.android.server.wm.IdentifierProto} to stream.
*/
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index c8c4b58..fb0c3bc 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -2493,8 +2493,8 @@
return getWindowConfiguration().keepVisibleDeadAppWindowOnScreen();
}
- /** @return true if this window desires key events. */
- boolean canReceiveKeys() {
+ @Override
+ public boolean canReceiveKeys() {
return isVisibleOrAdding()
&& (mViewVisibility == View.VISIBLE) && !mRemoveOnExit
&& ((mAttrs.flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) == 0)
diff --git a/services/tests/servicestests/src/com/android/server/policy/FakeWindowState.java b/services/tests/servicestests/src/com/android/server/policy/FakeWindowState.java
index 7487d44..044186f 100644
--- a/services/tests/servicestests/src/com/android/server/policy/FakeWindowState.java
+++ b/services/tests/servicestests/src/com/android/server/policy/FakeWindowState.java
@@ -255,6 +255,9 @@
}
@Override
+ public boolean canReceiveKeys() { return false; }
+
+ @Override
public void writeIdentifierToProto(ProtoOutputStream proto, long fieldId){
throw new UnsupportedOperationException("not implemented");
}