diff options
8 files changed, 58 insertions, 4 deletions
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index c73ab75a885d..aef8f078a243 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -234,7 +234,6 @@ import android.util.SparseArray; import android.util.proto.ProtoOutputStream; import android.view.Display; import android.view.DisplayCutout; -import android.view.DisplayInfo; import android.view.Gravity; import android.view.HapticFeedbackConstants; import android.view.IApplicationToken; @@ -2292,6 +2291,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { public void onTrustedChanged() { mWindowManagerFuncs.notifyKeyguardTrustedChanged(); } + + @Override + public void onShowingChanged() { + mWindowManagerFuncs.onKeyguardShowingAndNotOccludedChanged(); + } }); mScreenshotHelper = new ScreenshotHelper(mContext); } diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java index 89ae46851d46..a1e54b6b9852 100644 --- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java +++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java @@ -653,6 +653,11 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants { * abort animations that have no timeout, in case they got stuck. */ void triggerAnimationFailsafe(); + + /** + * The keyguard showing state has changed + */ + void onKeyguardShowingAndNotOccludedChanged(); } /** Window has been added to the screen. */ diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java b/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java index e56caf849aac..1cba1c7bed1b 100644 --- a/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java +++ b/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java @@ -94,6 +94,7 @@ public class KeyguardStateMonitor extends IKeyguardStateCallback.Stub { public void onShowingStateChanged(boolean showing) { mIsShowing = showing; + mCallback.onShowingChanged(); try { mKeystoreService.onKeyguardVisibilityChanged(showing, mCurrentUserId); } catch (RemoteException e) { @@ -132,6 +133,7 @@ public class KeyguardStateMonitor extends IKeyguardStateCallback.Stub { public interface StateCallback { void onTrustedChanged(); + void onShowingChanged(); } public void dump(String prefix, PrintWriter pw) { diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index 50d0d0a5f1f9..a709c55bbd30 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -157,10 +157,18 @@ class RootWindowContainer extends WindowContainer<DisplayContent> { } WindowState computeFocusedWindow() { + // While the keyguard is showing, we must focus anything besides the main display. + // Otherwise we risk input not going to the keyguard when the user expects it to. + final boolean forceDefaultDisplay = mService.isKeyguardShowingAndNotOccluded(); + for (int i = mChildren.size() - 1; i >= 0; i--) { final DisplayContent dc = mChildren.get(i); final WindowState win = dc.findFocusedWindow(); if (win != null) { + if (forceDefaultDisplay && !dc.isDefaultDisplay) { + EventLog.writeEvent(0x534e4554, "71786287", win.mOwnerUid, ""); + continue; + } return win; } } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 05626eb719ce..ab19b823241b 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -2845,6 +2845,11 @@ public class WindowManagerService extends IWindowManager.Stub mH.sendEmptyMessage(H.ANIMATION_FAILSAFE); } + @Override + public void onKeyguardShowingAndNotOccludedChanged() { + mH.sendEmptyMessage(H.RECOMPUTE_FOCUS); + } + /** * Starts deferring layout passes. Useful when doing multiple changes but to optimize * performance, only one layout pass should be done. This can be called multiple times, and @@ -4615,6 +4620,7 @@ public class WindowManagerService extends IWindowManager.Stub public static final int SET_HAS_OVERLAY_UI = 58; public static final int SET_RUNNING_REMOTE_ANIMATION = 59; public static final int ANIMATION_FAILSAFE = 60; + public static final int RECOMPUTE_FOCUS = 61; /** * Used to denote that an integer field in a message will not be used. @@ -5041,6 +5047,13 @@ public class WindowManagerService extends IWindowManager.Stub } } break; + case RECOMPUTE_FOCUS: { + synchronized (mWindowMap) { + updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, + true /* updateInputWindows */); + } + } + break; } if (DEBUG_WINDOW_TRACE) { Slog.v(TAG_WM, "handleMessage: exit"); 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 845095ae19b9..ac196f9c80dc 100644 --- a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java +++ b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java @@ -329,6 +329,21 @@ public class DisplayContentTests extends WindowTestsBase { assertEquals(window1, sWm.mRoot.computeFocusedWindow()); } + @Test + public void testKeyguard_preventsSecondaryDisplayFocus() throws Exception { + final WindowState keyguard = createWindow(null, TYPE_STATUS_BAR, + sWm.getDefaultDisplayContentLocked(), "keyguard"); + assertEquals(keyguard, sWm.mRoot.computeFocusedWindow()); + + // Add a window to a second display, and it should be focused + final DisplayContent dc = createNewDisplay(); + final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, dc, "win"); + assertEquals(win, sWm.mRoot.computeFocusedWindow()); + + mWmRule.getWindowManagerPolicy().keyguardShowingAndNotOccluded = true; + assertEquals(keyguard, sWm.mRoot.computeFocusedWindow()); + } + /** * This tests setting the maximum ui width on a display. */ diff --git a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java index 765b3d5957c4..50f3fbefaf40 100644 --- a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java +++ b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java @@ -51,6 +51,7 @@ class TestWindowManagerPolicy implements WindowManagerPolicy { private final Supplier<WindowManagerService> mWmSupplier; int rotationToReport = 0; + boolean keyguardShowingAndNotOccluded = false; private Runnable mRunnableWhenAddingSplashScreen; @@ -338,7 +339,7 @@ class TestWindowManagerPolicy implements WindowManagerPolicy { @Override public boolean isKeyguardLocked() { - return false; + return keyguardShowingAndNotOccluded; } @Override @@ -358,7 +359,7 @@ class TestWindowManagerPolicy implements WindowManagerPolicy { @Override public boolean isKeyguardShowingAndNotOccluded() { - return false; + return keyguardShowingAndNotOccluded; } @Override diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowManagerServiceRule.java b/services/tests/servicestests/src/com/android/server/wm/WindowManagerServiceRule.java index 32bfda32de7f..d91079e3bb1b 100644 --- a/services/tests/servicestests/src/com/android/server/wm/WindowManagerServiceRule.java +++ b/services/tests/servicestests/src/com/android/server/wm/WindowManagerServiceRule.java @@ -59,6 +59,7 @@ import org.mockito.invocation.InvocationOnMock; public class WindowManagerServiceRule implements TestRule { private WindowManagerService mService; + private TestWindowManagerPolicy mPolicy; @Override public Statement apply(Statement base, Description description) { @@ -108,7 +109,7 @@ public class WindowManagerServiceRule implements TestRule { } mService = WindowManagerService.main(context, ims, true, false, - false, new TestWindowManagerPolicy( + false, mPolicy = new TestWindowManagerPolicy( WindowManagerServiceRule.this::getWindowManagerService)); mService.onInitReady(); @@ -132,6 +133,7 @@ public class WindowManagerServiceRule implements TestRule { waitUntilWindowManagerHandlersIdle(); removeServices(); mService = null; + mPolicy = null; } }; } @@ -140,6 +142,10 @@ public class WindowManagerServiceRule implements TestRule { return mService; } + public TestWindowManagerPolicy getWindowManagerPolicy() { + return mPolicy; + } + public void waitUntilWindowManagerHandlersIdle() { final WindowManagerService wm = getWindowManagerService(); if (wm != null) { |