diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java index af559808d880f..8049a3adeb5fe 100644 --- a/services/core/java/com/android/server/am/UserController.java +++ b/services/core/java/com/android/server/am/UserController.java @@ -134,6 +134,7 @@ import java.util.Iterator; import java.util.List; import java.util.Objects; import java.util.concurrent.ThreadLocalRandom; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; /** @@ -199,6 +200,14 @@ class UserController implements Handler.Callback { */ private static final int USER_SWITCH_CALLBACKS_TIMEOUT_MS = 5 * 1000; + /** + * Amount of time waited for {@link WindowManagerService#dismissKeyguard} callbacks to be + * called after dismissing the keyguard. + * Otherwise, we should move on to unfreeze the screen {@link #unfreezeScreen} + * and report user switch is complete {@link #REPORT_USER_SWITCH_COMPLETE_MSG}. + */ + private static final int DISMISS_KEYGUARD_TIMEOUT_MS = 2 * 1000; + /** * Time after last scheduleOnUserCompletedEvent() call at which USER_COMPLETED_EVENT_MSG will be * scheduled (although it may fire sooner instead). @@ -3653,20 +3662,28 @@ class UserController implements Handler.Callback { } protected void dismissKeyguard(Runnable runnable, String reason) { + final AtomicBoolean isFirst = new AtomicBoolean(true); + final Runnable runOnce = () -> { + if (isFirst.getAndSet(false)) { + runnable.run(); + } + }; + + mHandler.postDelayed(runOnce, DISMISS_KEYGUARD_TIMEOUT_MS); getWindowManager().dismissKeyguard(new IKeyguardDismissCallback.Stub() { @Override public void onDismissError() throws RemoteException { - mHandler.post(runnable); + mHandler.post(runOnce); } @Override public void onDismissSucceeded() throws RemoteException { - mHandler.post(runnable); + mHandler.post(runOnce); } @Override public void onDismissCancelled() throws RemoteException { - mHandler.post(runnable); + mHandler.post(runOnce); } }, reason); }