WM: Prevent secondary display focus while keyguard is up
Fixes an issue where input intended for the keyguard could end up going to a different display. To prevent this, make sure that only the default display can get focused when the keyguard is showing. Change-Id: I6463c44aedca06930d2c9bda7c45ffd93141308c Fixes: 71786287 Test: atest DisplayContentTests
This commit is contained in:
@@ -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;
|
||||
@@ -2287,6 +2286,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
||||
public void onTrustedChanged() {
|
||||
mWindowManagerFuncs.notifyKeyguardTrustedChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onShowingChanged() {
|
||||
mWindowManagerFuncs.onKeyguardShowingAndNotOccludedChanged();
|
||||
}
|
||||
});
|
||||
mScreenshotHelper = new ScreenshotHelper(mContext);
|
||||
}
|
||||
|
||||
@@ -660,6 +660,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. */
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2837,6 +2837,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
|
||||
@@ -4611,6 +4616,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.
|
||||
@@ -5037,6 +5043,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");
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user