Loading packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +33 −201 Original line number Diff line number Diff line Loading @@ -16,7 +16,6 @@ package com.android.systemui.keyguard; import static android.app.KeyguardManager.LOCK_ON_USER_SWITCH_CALLBACK; import static android.app.StatusBarManager.SESSION_KEYGUARD; import static android.provider.Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT; import static android.provider.Settings.System.LOCKSCREEN_SOUNDS_ENABLED; Loading Loading @@ -76,7 +75,6 @@ import android.os.Bundle; import android.os.DeadObjectException; import android.os.Handler; import android.os.IBinder; import android.os.IRemoteCallback; import android.os.Looper; import android.os.Message; import android.os.PowerManager; Loading Loading @@ -194,8 +192,6 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.Objects; import java.util.concurrent.Executor; import java.util.function.Consumer; Loading Loading @@ -286,9 +282,6 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, private static final int SYSTEM_READY = 18; private static final int CANCEL_KEYGUARD_EXIT_ANIM = 19; private static final int BOOT_INTERACTOR = 20; private static final int BEFORE_USER_SWITCHING = 21; private static final int USER_SWITCHING = 22; private static final int USER_SWITCH_COMPLETE = 23; /** Enum for reasons behind updating wakeAndUnlock state. */ @Retention(RetentionPolicy.SOURCE) Loading @@ -306,8 +299,6 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, int WAKE_AND_UNLOCK = 3; } private final List<LockNowCallback> mLockNowCallbacks = new ArrayList<>(); /** * The default amount of time we stay awake (used for all key input) */ Loading Loading @@ -366,18 +357,13 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, private final Lazy<NotificationShadeDepthController> mNotificationShadeDepthController; private final Lazy<ShadeController> mShadeController; private final Lazy<CommunalSceneInteractor> mCommunalSceneInteractor; /* * Records the user id on request to go away, for validation when WM calls back to start the * exit animation. */ private int mGoingAwayRequestedForUserId = -1; private boolean mSystemReady; private boolean mBootCompleted; private boolean mBootSendUserPresent; private boolean mShuttingDown; private boolean mDozing; private boolean mAnimatingScreenOff; private boolean mIgnoreDismiss; private final Context mContext; private final FalsingCollector mFalsingCollector; Loading Loading @@ -640,92 +626,41 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, } }; @VisibleForTesting protected UserTracker.Callback mUserChangedCallback = new UserTracker.Callback() { @Override public void onBeforeUserSwitching(int newUser, @NonNull Runnable resultCallback) { mHandler.sendMessage(mHandler.obtainMessage(BEFORE_USER_SWITCHING, newUser, 0, resultCallback)); } @Override public void onUserChanging(int newUser, @NonNull Context userContext, @NonNull Runnable resultCallback) { mHandler.sendMessage(mHandler.obtainMessage(USER_SWITCHING, newUser, 0, resultCallback)); } KeyguardUpdateMonitorCallback mUpdateCallback = new KeyguardUpdateMonitorCallback() { @Override public void onUserChanged(int newUser, Context userContext) { mHandler.sendMessage(mHandler.obtainMessage(USER_SWITCH_COMPLETE, newUser, 0)); } }; /** * Handle {@link #BEFORE_USER_SWITCHING} */ @VisibleForTesting void handleBeforeUserSwitching(int userId, Runnable resultCallback) { Log.d(TAG, String.format("onBeforeUserSwitching %d", userId)); public void onKeyguardVisibilityChanged(boolean visible) { synchronized (KeyguardViewMediator.this) { mHandler.removeMessages(DISMISS); notifyTrustedChangedLocked(mUpdateMonitor.getUserHasTrust(userId)); resetKeyguardDonePendingLocked(); adjustStatusBarLocked(); mKeyguardStateController.notifyKeyguardGoingAway(false); if (mLockPatternUtils.isSecure(userId) && !mShowing) { if (!visible && mPendingPinLock) { Log.i(TAG, "PIN lock requested, starting keyguard"); // Bring the keyguard back in order to show the PIN lock mPendingPinLock = false; doKeyguardLocked(null); } else { resetStateLocked(); } resultCallback.run(); } } /** * Handle {@link #USER_SWITCHING} */ @VisibleForTesting void handleUserSwitching(int userId, Runnable resultCallback) { @Override public void onUserSwitching(int userId) { Log.d(TAG, String.format("onUserSwitching %d", userId)); synchronized (KeyguardViewMediator.this) { if (!mLockPatternUtils.isSecure(userId)) { dismiss(null, null); } resultCallback.run(); mIgnoreDismiss = true; notifyTrustedChangedLocked(mUpdateMonitor.getUserHasTrust(userId)); resetKeyguardDonePendingLocked(); resetStateLocked(); adjustStatusBarLocked(); } } /** * Handle {@link #USER_SWITCH_COMPLETE} */ @VisibleForTesting void handleUserSwitchComplete(int userId) { @Override public void onUserSwitchComplete(int userId) { mIgnoreDismiss = false; Log.d(TAG, String.format("onUserSwitchComplete %d", userId)); // Calling dismiss on a secure user will show the bouncer if (mLockPatternUtils.isSecure(userId)) { // We are calling dismiss with a delay as there are race conditions in some scenarios // caused by async layout listeners mHandler.postDelayed(() -> dismiss(null /* callback */, null /* message */), 500); } } KeyguardUpdateMonitorCallback mUpdateCallback = new KeyguardUpdateMonitorCallback() { @Override public void onKeyguardVisibilityChanged(boolean visible) { synchronized (KeyguardViewMediator.this) { if (!visible && mPendingPinLock) { Log.i(TAG, "PIN lock requested, starting keyguard"); // Bring the keyguard back in order to show the PIN lock mPendingPinLock = false; doKeyguardLocked(null); } } } @Override public void onDeviceProvisioned() { Loading Loading @@ -1736,13 +1671,7 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, com.android.internal.R.anim.lock_screen_behind_enter); mWorkLockController = new WorkLockActivityController(mContext, mUserTracker); mUserTracker.addCallback(mUserChangedCallback, mContext.getMainExecutor()); // start() can be invoked in the middle of user switching, so check for this state and issue // the call manually as that important event was missed. if (mUserTracker.isUserSwitching()) { handleBeforeUserSwitching(mUserTracker.getUserId(), () -> {}); handleUserSwitching(mUserTracker.getUserId(), () -> {}); } mJavaAdapter.alwaysCollectFlow( mWallpaperRepository.getWallpaperSupportsAmbientMode(), this::setWallpaperSupportsAmbientMode); Loading Loading @@ -1791,7 +1720,7 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, // System ready can be invoked in the middle of user switching, so check for this state // and issue the call manually as that important event was missed. if (mUserTracker.isUserSwitching()) { mUserChangedCallback.onUserChanging(mUserTracker.getUserId(), mContext, () -> {}); mUpdateCallback.onUserSwitching(mUserTracker.getUserId()); } } // Most services aren't available until the system reaches the ready state, so we Loading Loading @@ -2432,23 +2361,12 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, mCommunalSceneInteractor.get().showHubFromPowerButton(); } int currentUserId = mSelectedUserInteractor.getSelectedUserId(); if (options != null && options.getBinder(LOCK_ON_USER_SWITCH_CALLBACK) != null) { LockNowCallback callback = new LockNowCallback(currentUserId, IRemoteCallback.Stub.asInterface( options.getBinder(LOCK_ON_USER_SWITCH_CALLBACK))); synchronized (mLockNowCallbacks) { mLockNowCallbacks.add(callback); } Log.d(TAG, "LockNowCallback required for user: " + callback.mUserId); } // if another app is disabling us, don't show if (!mExternallyEnabled && !mLockPatternUtils.isUserInLockdown( mSelectedUserInteractor.getSelectedUserId())) { if (DEBUG) Log.d(TAG, "doKeyguard: not showing because externally disabled"); notifyLockNowCallback(); mNeedToReshowWhenReenabled = true; return; } Loading @@ -2466,7 +2384,6 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, // We're removing "reset" in the refactor - "resetting" the views will happen // as a reaction to the root cause of the "reset" signal. if (KeyguardWmStateRefactor.isEnabled()) { notifyLockNowCallback(); return; } Loading @@ -2479,7 +2396,6 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, + "previously hiding. It should be safe to short-circuit " + "here."); resetStateLocked(/* hideBouncer= */ false); notifyLockNowCallback(); return; } } else { Loading @@ -2506,7 +2422,6 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, Log.d(TAG, "doKeyguard: not showing because device isn't provisioned and the sim is" + " not locked or missing"); } notifyLockNowCallback(); return; } Loading @@ -2514,7 +2429,6 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, if (mLockPatternUtils.isLockScreenDisabled(mSelectedUserInteractor.getSelectedUserId()) && !lockedOrMissing && !forceShow) { if (DEBUG) Log.d(TAG, "doKeyguard: not showing because lockscreen is off"); notifyLockNowCallback(); return; } Loading Loading @@ -2562,6 +2476,11 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, } public void dismiss(IKeyguardDismissCallback callback, CharSequence message) { if (mIgnoreDismiss) { android.util.Log.i(TAG, "Ignoring request to dismiss (user switch in progress?)"); return; } if (mKeyguardStateController.isKeyguardGoingAway()) { Log.i(TAG, "Ignoring dismiss because we're already going away."); return; Loading @@ -2579,7 +2498,7 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, } private void resetStateLocked(boolean hideBouncer) { if (DEBUG) Log.d(TAG, "resetStateLocked"); if (DEBUG) Log.e(TAG, "resetStateLocked"); Message msg = mHandler.obtainMessage(RESET, hideBouncer ? 1 : 0, 0); mHandler.sendMessage(msg); } Loading Loading @@ -2827,18 +2746,6 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, message = "BOOT_INTERACTOR"; handleBootInteractor(); break; case BEFORE_USER_SWITCHING: message = "BEFORE_USER_SWITCHING"; handleBeforeUserSwitching(msg.arg1, (Runnable) msg.obj); break; case USER_SWITCHING: message = "USER_SWITCHING"; handleUserSwitching(msg.arg1, (Runnable) msg.obj); break; case USER_SWITCH_COMPLETE: message = "USER_SWITCH_COMPLETE"; handleUserSwitchComplete(msg.arg1); break; } Log.d(TAG, "KeyguardViewMediator queue processing message: " + message); } Loading Loading @@ -2980,9 +2887,6 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, mUiBgExecutor.execute(() -> { Log.d(TAG, "updateActivityLockScreenState(" + showing + ", " + aodShowing + ", " + reason + ")"); if (showing) { notifyLockNowCallback(); } if (KeyguardWmStateRefactor.isEnabled()) { // Handled in WmLockscreenVisibilityManager if flag is enabled. Loading Loading @@ -3027,7 +2931,6 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, synchronized (KeyguardViewMediator.this) { if (!mSystemReady) { if (DEBUG) Log.d(TAG, "ignoring handleShow because system is not ready."); notifyLockNowCallback(); return; } if (DEBUG) Log.d(TAG, "handleShow"); Loading Loading @@ -3086,11 +2989,12 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, } } final Runnable mKeyguardGoingAwayRunnable = new Runnable() { private final Runnable mKeyguardGoingAwayRunnable = new Runnable() { @SuppressLint("MissingPermission") @Override public void run() { Trace.beginSection("KeyguardViewMediator.mKeyGuardGoingAwayRunnable"); Log.d(TAG, "keyguardGoingAwayRunnable"); mKeyguardViewControllerLazy.get().keyguardGoingAway(); int flags = 0; Loading Loading @@ -3127,10 +3031,6 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, // Handled in WmLockscreenVisibilityManager if flag is enabled. if (!KeyguardWmStateRefactor.isEnabled()) { mGoingAwayRequestedForUserId = mSelectedUserInteractor.getSelectedUserId(); Log.d(TAG, "keyguardGoingAway requested for userId: " + mGoingAwayRequestedForUserId); // Don't actually hide the Keyguard at the moment, wait for window manager // until it tells us it's safe to do so with startKeyguardExitAnimation. // Posting to mUiOffloadThread to ensure that calls to ActivityTaskManager Loading Loading @@ -3269,30 +3169,6 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, RemoteAnimationTarget[] nonApps, IRemoteAnimationFinishedCallback finishedCallback) { Log.d(TAG, "handleStartKeyguardExitAnimation startTime=" + startTime + " fadeoutDuration=" + fadeoutDuration); int currentUserId = mSelectedUserInteractor.getSelectedUserId(); if (!KeyguardWmStateRefactor.isEnabled() && mGoingAwayRequestedForUserId != currentUserId) { Log.e(TAG, "Not executing handleStartKeyguardExitAnimationInner() due to userId " + "mismatch. Requested: " + mGoingAwayRequestedForUserId + ", current: " + currentUserId); if (finishedCallback != null) { // There will not execute animation, send a finish callback to ensure the remote // animation won't hang there. try { finishedCallback.onAnimationFinished(); } catch (RemoteException e) { Slog.w(TAG, "Failed to call onAnimationFinished", e); } } mHiding = false; if (mLockPatternUtils.isSecure(currentUserId)) { doKeyguardLocked(null); } else { resetStateLocked(); dismiss(null, null); } return; } synchronized (KeyguardViewMediator.this) { mIsKeyguardExitAnimationCanceled = false; // Tell ActivityManager that we canceled the keyguard animation if Loading Loading @@ -3537,13 +3413,6 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, * app transition before finishing the current RemoteAnimation, or the keyguard being re-shown). */ private void handleCancelKeyguardExitAnimation() { if (!KeyguardWmStateRefactor.isEnabled() && mGoingAwayRequestedForUserId != mSelectedUserInteractor.getSelectedUserId()) { Log.e(TAG, "Setting pendingLock = true due to userId mismatch. Requested: " + mGoingAwayRequestedForUserId + ", current: " + mSelectedUserInteractor.getSelectedUserId()); setPendingLock(true); } if (mPendingLock) { Log.d(TAG, "#handleCancelKeyguardExitAnimation: keyguard exit animation cancelled. " + "There's a pending lock, so we were cancelled because the device was locked " Loading Loading @@ -3644,7 +3513,6 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, mSurfaceBehindRemoteAnimationRequested = true; if (ENABLE_NEW_KEYGUARD_SHELL_TRANSITIONS && !KeyguardWmStateRefactor.isEnabled()) { mGoingAwayRequestedForUserId = mSelectedUserInteractor.getSelectedUserId(); startKeyguardTransition(false /* keyguardShowing */, false /* aodShowing */); return; } Loading @@ -3665,9 +3533,6 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, if (!KeyguardWmStateRefactor.isEnabled()) { // Handled in WmLockscreenVisibilityManager. mGoingAwayRequestedForUserId = mSelectedUserInteractor.getSelectedUserId(); Log.d(TAG, "keyguardGoingAway requested for userId: " + mGoingAwayRequestedForUserId); mActivityTaskManagerService.keyguardGoingAway(flags); } } catch (RemoteException e) { Loading Loading @@ -4123,29 +3988,6 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, mUiBgExecutor.execute(mTrustManager::reportKeyguardShowingChanged); } private void notifyLockNowCallback() { List<LockNowCallback> callbacks; synchronized (mLockNowCallbacks) { callbacks = new ArrayList<LockNowCallback>(mLockNowCallbacks); mLockNowCallbacks.clear(); } Iterator<LockNowCallback> iter = callbacks.listIterator(); while (iter.hasNext()) { LockNowCallback callback = iter.next(); iter.remove(); if (callback.mUserId != mSelectedUserInteractor.getSelectedUserId()) { Log.i(TAG, "Not notifying lockNowCallback due to user mismatch"); continue; } Log.i(TAG, "Notifying lockNowCallback"); try { callback.mRemoteCallback.sendResult(null); } catch (RemoteException e) { Log.e(TAG, "Could not issue LockNowCallback sendResult", e); } } } private void notifyTrustedChangedLocked(boolean trusted) { int size = mKeyguardStateCallbacks.size(); for (int i = size - 1; i >= 0; i--) { Loading Loading @@ -4310,14 +4152,4 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, } }; } private class LockNowCallback { final int mUserId; final IRemoteCallback mRemoteCallback; LockNowCallback(int userId, IRemoteCallback remoteCallback) { mUserId = userId; mRemoteCallback = remoteCallback; } } } packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java +13 −153 File changed.Preview size limit exceeded, changes collapsed. Show changes services/core/java/com/android/server/am/UserController.java +28 −10 Original line number Diff line number Diff line Loading @@ -31,7 +31,6 @@ import static android.app.ActivityManagerInternal.ALLOW_FULL_ONLY; import static android.app.ActivityManagerInternal.ALLOW_NON_FULL; import static android.app.ActivityManagerInternal.ALLOW_NON_FULL_IN_PROFILE; import static android.app.ActivityManagerInternal.ALLOW_PROFILES_OR_NON_FULL; import static android.app.KeyguardManager.LOCK_ON_USER_SWITCH_CALLBACK; import static android.os.PowerWhitelistManager.REASON_BOOT_COMPLETED; import static android.os.PowerWhitelistManager.REASON_LOCKED_BOOT_COMPLETED; import static android.os.PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED; Loading Loading @@ -3905,6 +3904,10 @@ class UserController implements Handler.Callback { return mService.mWindowManager; } ActivityTaskManagerInternal getActivityTaskManagerInternal() { return mService.mAtmInternal; } void activityManagerOnUserStopped(@UserIdInt int userId) { LocalServices.getService(ActivityTaskManagerInternal.class).onUserStopped(userId); } Loading Loading @@ -4119,25 +4122,40 @@ class UserController implements Handler.Callback { } void lockDeviceNowAndWaitForKeyguardShown() { if (getWindowManager().isKeyguardLocked()) { Slogf.w(TAG, "Not locking the device since the keyguard is already locked"); return; } final TimingsTraceAndSlog t = new TimingsTraceAndSlog(); t.traceBegin("lockDeviceNowAndWaitForKeyguardShown"); final CountDownLatch latch = new CountDownLatch(1); Bundle bundle = new Bundle(); bundle.putBinder(LOCK_ON_USER_SWITCH_CALLBACK, new IRemoteCallback.Stub() { public void sendResult(Bundle data) { ActivityTaskManagerInternal.ScreenObserver screenObserver = new ActivityTaskManagerInternal.ScreenObserver() { @Override public void onAwakeStateChanged(boolean isAwake) { } @Override public void onKeyguardStateChanged(boolean isShowing) { if (isShowing) { latch.countDown(); } }); getWindowManager().lockNow(bundle); } }; getActivityTaskManagerInternal().registerScreenObserver(screenObserver); getWindowManager().lockDeviceNow(); try { if (!latch.await(20, TimeUnit.SECONDS)) { throw new RuntimeException("User controller expected a callback while waiting " + "to show the keyguard. Timed out after 20 seconds."); throw new RuntimeException("Keyguard is not shown in 20 seconds"); } } catch (InterruptedException e) { throw new RuntimeException(e); } finally { getActivityTaskManagerInternal().unregisterScreenObserver(screenObserver); t.traceEnd(); } } Loading services/tests/servicestests/src/com/android/server/am/UserControllerTest.java +13 −6 Original line number Diff line number Diff line Loading @@ -25,7 +25,6 @@ import static android.app.ActivityManagerInternal.ALLOW_FULL_ONLY; import static android.app.ActivityManagerInternal.ALLOW_NON_FULL; import static android.app.ActivityManagerInternal.ALLOW_NON_FULL_IN_PROFILE; import static android.app.ActivityManagerInternal.ALLOW_PROFILES_OR_NON_FULL; import static android.app.KeyguardManager.LOCK_ON_USER_SWITCH_CALLBACK; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.testing.DexmakerShareClassLoaderRule.runWithDexmakerShareClassLoader; Loading Loading @@ -116,6 +115,7 @@ import com.android.server.pm.UserManagerInternal; import com.android.server.pm.UserManagerService; import com.android.server.pm.UserTypeDetails; import com.android.server.pm.UserTypeFactory; import com.android.server.wm.ActivityTaskManagerInternal; import com.android.server.wm.WindowManagerService; import com.google.common.collect.Range; Loading Loading @@ -1563,11 +1563,11 @@ public class UserControllerTest { // and the thread is still alive assertTrue(threadStartUser.isAlive()); // mock the binder response for the user switch completion ArgumentCaptor<Bundle> captor = ArgumentCaptor.forClass(Bundle.class); verify(mInjector.mWindowManagerMock).lockNow(captor.capture()); IRemoteCallback.Stub.asInterface(captor.getValue().getBinder( LOCK_ON_USER_SWITCH_CALLBACK)).sendResult(null); // mock send the keyguard shown event ArgumentCaptor<ActivityTaskManagerInternal.ScreenObserver> captor = ArgumentCaptor.forClass( ActivityTaskManagerInternal.ScreenObserver.class); verify(mInjector.mActivityTaskManagerInternal).registerScreenObserver(captor.capture()); captor.getValue().onKeyguardStateChanged(true); // verify the switch now moves on... Thread.sleep(1000); Loading Loading @@ -1757,6 +1757,7 @@ public class UserControllerTest { private final IStorageManager mStorageManagerMock; private final UserManagerInternal mUserManagerInternalMock; private final WindowManagerService mWindowManagerMock; private final ActivityTaskManagerInternal mActivityTaskManagerInternal; private final PowerManagerInternal mPowerManagerInternal; private final AlarmManagerInternal mAlarmManagerInternal; private final KeyguardManager mKeyguardManagerMock; Loading @@ -1778,6 +1779,7 @@ public class UserControllerTest { mUserManagerMock = mock(UserManagerService.class); mUserManagerInternalMock = mock(UserManagerInternal.class); mWindowManagerMock = mock(WindowManagerService.class); mActivityTaskManagerInternal = mock(ActivityTaskManagerInternal.class); mStorageManagerMock = mock(IStorageManager.class); mPowerManagerInternal = mock(PowerManagerInternal.class); mAlarmManagerInternal = mock(AlarmManagerInternal.class); Loading Loading @@ -1840,6 +1842,11 @@ public class UserControllerTest { return mWindowManagerMock; } @Override ActivityTaskManagerInternal getActivityTaskManagerInternal() { return mActivityTaskManagerInternal; } @Override PowerManagerInternal getPowerManagerInternal() { return mPowerManagerInternal; Loading Loading
packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +33 −201 Original line number Diff line number Diff line Loading @@ -16,7 +16,6 @@ package com.android.systemui.keyguard; import static android.app.KeyguardManager.LOCK_ON_USER_SWITCH_CALLBACK; import static android.app.StatusBarManager.SESSION_KEYGUARD; import static android.provider.Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT; import static android.provider.Settings.System.LOCKSCREEN_SOUNDS_ENABLED; Loading Loading @@ -76,7 +75,6 @@ import android.os.Bundle; import android.os.DeadObjectException; import android.os.Handler; import android.os.IBinder; import android.os.IRemoteCallback; import android.os.Looper; import android.os.Message; import android.os.PowerManager; Loading Loading @@ -194,8 +192,6 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.Objects; import java.util.concurrent.Executor; import java.util.function.Consumer; Loading Loading @@ -286,9 +282,6 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, private static final int SYSTEM_READY = 18; private static final int CANCEL_KEYGUARD_EXIT_ANIM = 19; private static final int BOOT_INTERACTOR = 20; private static final int BEFORE_USER_SWITCHING = 21; private static final int USER_SWITCHING = 22; private static final int USER_SWITCH_COMPLETE = 23; /** Enum for reasons behind updating wakeAndUnlock state. */ @Retention(RetentionPolicy.SOURCE) Loading @@ -306,8 +299,6 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, int WAKE_AND_UNLOCK = 3; } private final List<LockNowCallback> mLockNowCallbacks = new ArrayList<>(); /** * The default amount of time we stay awake (used for all key input) */ Loading Loading @@ -366,18 +357,13 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, private final Lazy<NotificationShadeDepthController> mNotificationShadeDepthController; private final Lazy<ShadeController> mShadeController; private final Lazy<CommunalSceneInteractor> mCommunalSceneInteractor; /* * Records the user id on request to go away, for validation when WM calls back to start the * exit animation. */ private int mGoingAwayRequestedForUserId = -1; private boolean mSystemReady; private boolean mBootCompleted; private boolean mBootSendUserPresent; private boolean mShuttingDown; private boolean mDozing; private boolean mAnimatingScreenOff; private boolean mIgnoreDismiss; private final Context mContext; private final FalsingCollector mFalsingCollector; Loading Loading @@ -640,92 +626,41 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, } }; @VisibleForTesting protected UserTracker.Callback mUserChangedCallback = new UserTracker.Callback() { @Override public void onBeforeUserSwitching(int newUser, @NonNull Runnable resultCallback) { mHandler.sendMessage(mHandler.obtainMessage(BEFORE_USER_SWITCHING, newUser, 0, resultCallback)); } @Override public void onUserChanging(int newUser, @NonNull Context userContext, @NonNull Runnable resultCallback) { mHandler.sendMessage(mHandler.obtainMessage(USER_SWITCHING, newUser, 0, resultCallback)); } KeyguardUpdateMonitorCallback mUpdateCallback = new KeyguardUpdateMonitorCallback() { @Override public void onUserChanged(int newUser, Context userContext) { mHandler.sendMessage(mHandler.obtainMessage(USER_SWITCH_COMPLETE, newUser, 0)); } }; /** * Handle {@link #BEFORE_USER_SWITCHING} */ @VisibleForTesting void handleBeforeUserSwitching(int userId, Runnable resultCallback) { Log.d(TAG, String.format("onBeforeUserSwitching %d", userId)); public void onKeyguardVisibilityChanged(boolean visible) { synchronized (KeyguardViewMediator.this) { mHandler.removeMessages(DISMISS); notifyTrustedChangedLocked(mUpdateMonitor.getUserHasTrust(userId)); resetKeyguardDonePendingLocked(); adjustStatusBarLocked(); mKeyguardStateController.notifyKeyguardGoingAway(false); if (mLockPatternUtils.isSecure(userId) && !mShowing) { if (!visible && mPendingPinLock) { Log.i(TAG, "PIN lock requested, starting keyguard"); // Bring the keyguard back in order to show the PIN lock mPendingPinLock = false; doKeyguardLocked(null); } else { resetStateLocked(); } resultCallback.run(); } } /** * Handle {@link #USER_SWITCHING} */ @VisibleForTesting void handleUserSwitching(int userId, Runnable resultCallback) { @Override public void onUserSwitching(int userId) { Log.d(TAG, String.format("onUserSwitching %d", userId)); synchronized (KeyguardViewMediator.this) { if (!mLockPatternUtils.isSecure(userId)) { dismiss(null, null); } resultCallback.run(); mIgnoreDismiss = true; notifyTrustedChangedLocked(mUpdateMonitor.getUserHasTrust(userId)); resetKeyguardDonePendingLocked(); resetStateLocked(); adjustStatusBarLocked(); } } /** * Handle {@link #USER_SWITCH_COMPLETE} */ @VisibleForTesting void handleUserSwitchComplete(int userId) { @Override public void onUserSwitchComplete(int userId) { mIgnoreDismiss = false; Log.d(TAG, String.format("onUserSwitchComplete %d", userId)); // Calling dismiss on a secure user will show the bouncer if (mLockPatternUtils.isSecure(userId)) { // We are calling dismiss with a delay as there are race conditions in some scenarios // caused by async layout listeners mHandler.postDelayed(() -> dismiss(null /* callback */, null /* message */), 500); } } KeyguardUpdateMonitorCallback mUpdateCallback = new KeyguardUpdateMonitorCallback() { @Override public void onKeyguardVisibilityChanged(boolean visible) { synchronized (KeyguardViewMediator.this) { if (!visible && mPendingPinLock) { Log.i(TAG, "PIN lock requested, starting keyguard"); // Bring the keyguard back in order to show the PIN lock mPendingPinLock = false; doKeyguardLocked(null); } } } @Override public void onDeviceProvisioned() { Loading Loading @@ -1736,13 +1671,7 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, com.android.internal.R.anim.lock_screen_behind_enter); mWorkLockController = new WorkLockActivityController(mContext, mUserTracker); mUserTracker.addCallback(mUserChangedCallback, mContext.getMainExecutor()); // start() can be invoked in the middle of user switching, so check for this state and issue // the call manually as that important event was missed. if (mUserTracker.isUserSwitching()) { handleBeforeUserSwitching(mUserTracker.getUserId(), () -> {}); handleUserSwitching(mUserTracker.getUserId(), () -> {}); } mJavaAdapter.alwaysCollectFlow( mWallpaperRepository.getWallpaperSupportsAmbientMode(), this::setWallpaperSupportsAmbientMode); Loading Loading @@ -1791,7 +1720,7 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, // System ready can be invoked in the middle of user switching, so check for this state // and issue the call manually as that important event was missed. if (mUserTracker.isUserSwitching()) { mUserChangedCallback.onUserChanging(mUserTracker.getUserId(), mContext, () -> {}); mUpdateCallback.onUserSwitching(mUserTracker.getUserId()); } } // Most services aren't available until the system reaches the ready state, so we Loading Loading @@ -2432,23 +2361,12 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, mCommunalSceneInteractor.get().showHubFromPowerButton(); } int currentUserId = mSelectedUserInteractor.getSelectedUserId(); if (options != null && options.getBinder(LOCK_ON_USER_SWITCH_CALLBACK) != null) { LockNowCallback callback = new LockNowCallback(currentUserId, IRemoteCallback.Stub.asInterface( options.getBinder(LOCK_ON_USER_SWITCH_CALLBACK))); synchronized (mLockNowCallbacks) { mLockNowCallbacks.add(callback); } Log.d(TAG, "LockNowCallback required for user: " + callback.mUserId); } // if another app is disabling us, don't show if (!mExternallyEnabled && !mLockPatternUtils.isUserInLockdown( mSelectedUserInteractor.getSelectedUserId())) { if (DEBUG) Log.d(TAG, "doKeyguard: not showing because externally disabled"); notifyLockNowCallback(); mNeedToReshowWhenReenabled = true; return; } Loading @@ -2466,7 +2384,6 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, // We're removing "reset" in the refactor - "resetting" the views will happen // as a reaction to the root cause of the "reset" signal. if (KeyguardWmStateRefactor.isEnabled()) { notifyLockNowCallback(); return; } Loading @@ -2479,7 +2396,6 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, + "previously hiding. It should be safe to short-circuit " + "here."); resetStateLocked(/* hideBouncer= */ false); notifyLockNowCallback(); return; } } else { Loading @@ -2506,7 +2422,6 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, Log.d(TAG, "doKeyguard: not showing because device isn't provisioned and the sim is" + " not locked or missing"); } notifyLockNowCallback(); return; } Loading @@ -2514,7 +2429,6 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, if (mLockPatternUtils.isLockScreenDisabled(mSelectedUserInteractor.getSelectedUserId()) && !lockedOrMissing && !forceShow) { if (DEBUG) Log.d(TAG, "doKeyguard: not showing because lockscreen is off"); notifyLockNowCallback(); return; } Loading Loading @@ -2562,6 +2476,11 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, } public void dismiss(IKeyguardDismissCallback callback, CharSequence message) { if (mIgnoreDismiss) { android.util.Log.i(TAG, "Ignoring request to dismiss (user switch in progress?)"); return; } if (mKeyguardStateController.isKeyguardGoingAway()) { Log.i(TAG, "Ignoring dismiss because we're already going away."); return; Loading @@ -2579,7 +2498,7 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, } private void resetStateLocked(boolean hideBouncer) { if (DEBUG) Log.d(TAG, "resetStateLocked"); if (DEBUG) Log.e(TAG, "resetStateLocked"); Message msg = mHandler.obtainMessage(RESET, hideBouncer ? 1 : 0, 0); mHandler.sendMessage(msg); } Loading Loading @@ -2827,18 +2746,6 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, message = "BOOT_INTERACTOR"; handleBootInteractor(); break; case BEFORE_USER_SWITCHING: message = "BEFORE_USER_SWITCHING"; handleBeforeUserSwitching(msg.arg1, (Runnable) msg.obj); break; case USER_SWITCHING: message = "USER_SWITCHING"; handleUserSwitching(msg.arg1, (Runnable) msg.obj); break; case USER_SWITCH_COMPLETE: message = "USER_SWITCH_COMPLETE"; handleUserSwitchComplete(msg.arg1); break; } Log.d(TAG, "KeyguardViewMediator queue processing message: " + message); } Loading Loading @@ -2980,9 +2887,6 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, mUiBgExecutor.execute(() -> { Log.d(TAG, "updateActivityLockScreenState(" + showing + ", " + aodShowing + ", " + reason + ")"); if (showing) { notifyLockNowCallback(); } if (KeyguardWmStateRefactor.isEnabled()) { // Handled in WmLockscreenVisibilityManager if flag is enabled. Loading Loading @@ -3027,7 +2931,6 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, synchronized (KeyguardViewMediator.this) { if (!mSystemReady) { if (DEBUG) Log.d(TAG, "ignoring handleShow because system is not ready."); notifyLockNowCallback(); return; } if (DEBUG) Log.d(TAG, "handleShow"); Loading Loading @@ -3086,11 +2989,12 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, } } final Runnable mKeyguardGoingAwayRunnable = new Runnable() { private final Runnable mKeyguardGoingAwayRunnable = new Runnable() { @SuppressLint("MissingPermission") @Override public void run() { Trace.beginSection("KeyguardViewMediator.mKeyGuardGoingAwayRunnable"); Log.d(TAG, "keyguardGoingAwayRunnable"); mKeyguardViewControllerLazy.get().keyguardGoingAway(); int flags = 0; Loading Loading @@ -3127,10 +3031,6 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, // Handled in WmLockscreenVisibilityManager if flag is enabled. if (!KeyguardWmStateRefactor.isEnabled()) { mGoingAwayRequestedForUserId = mSelectedUserInteractor.getSelectedUserId(); Log.d(TAG, "keyguardGoingAway requested for userId: " + mGoingAwayRequestedForUserId); // Don't actually hide the Keyguard at the moment, wait for window manager // until it tells us it's safe to do so with startKeyguardExitAnimation. // Posting to mUiOffloadThread to ensure that calls to ActivityTaskManager Loading Loading @@ -3269,30 +3169,6 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, RemoteAnimationTarget[] nonApps, IRemoteAnimationFinishedCallback finishedCallback) { Log.d(TAG, "handleStartKeyguardExitAnimation startTime=" + startTime + " fadeoutDuration=" + fadeoutDuration); int currentUserId = mSelectedUserInteractor.getSelectedUserId(); if (!KeyguardWmStateRefactor.isEnabled() && mGoingAwayRequestedForUserId != currentUserId) { Log.e(TAG, "Not executing handleStartKeyguardExitAnimationInner() due to userId " + "mismatch. Requested: " + mGoingAwayRequestedForUserId + ", current: " + currentUserId); if (finishedCallback != null) { // There will not execute animation, send a finish callback to ensure the remote // animation won't hang there. try { finishedCallback.onAnimationFinished(); } catch (RemoteException e) { Slog.w(TAG, "Failed to call onAnimationFinished", e); } } mHiding = false; if (mLockPatternUtils.isSecure(currentUserId)) { doKeyguardLocked(null); } else { resetStateLocked(); dismiss(null, null); } return; } synchronized (KeyguardViewMediator.this) { mIsKeyguardExitAnimationCanceled = false; // Tell ActivityManager that we canceled the keyguard animation if Loading Loading @@ -3537,13 +3413,6 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, * app transition before finishing the current RemoteAnimation, or the keyguard being re-shown). */ private void handleCancelKeyguardExitAnimation() { if (!KeyguardWmStateRefactor.isEnabled() && mGoingAwayRequestedForUserId != mSelectedUserInteractor.getSelectedUserId()) { Log.e(TAG, "Setting pendingLock = true due to userId mismatch. Requested: " + mGoingAwayRequestedForUserId + ", current: " + mSelectedUserInteractor.getSelectedUserId()); setPendingLock(true); } if (mPendingLock) { Log.d(TAG, "#handleCancelKeyguardExitAnimation: keyguard exit animation cancelled. " + "There's a pending lock, so we were cancelled because the device was locked " Loading Loading @@ -3644,7 +3513,6 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, mSurfaceBehindRemoteAnimationRequested = true; if (ENABLE_NEW_KEYGUARD_SHELL_TRANSITIONS && !KeyguardWmStateRefactor.isEnabled()) { mGoingAwayRequestedForUserId = mSelectedUserInteractor.getSelectedUserId(); startKeyguardTransition(false /* keyguardShowing */, false /* aodShowing */); return; } Loading @@ -3665,9 +3533,6 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, if (!KeyguardWmStateRefactor.isEnabled()) { // Handled in WmLockscreenVisibilityManager. mGoingAwayRequestedForUserId = mSelectedUserInteractor.getSelectedUserId(); Log.d(TAG, "keyguardGoingAway requested for userId: " + mGoingAwayRequestedForUserId); mActivityTaskManagerService.keyguardGoingAway(flags); } } catch (RemoteException e) { Loading Loading @@ -4123,29 +3988,6 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, mUiBgExecutor.execute(mTrustManager::reportKeyguardShowingChanged); } private void notifyLockNowCallback() { List<LockNowCallback> callbacks; synchronized (mLockNowCallbacks) { callbacks = new ArrayList<LockNowCallback>(mLockNowCallbacks); mLockNowCallbacks.clear(); } Iterator<LockNowCallback> iter = callbacks.listIterator(); while (iter.hasNext()) { LockNowCallback callback = iter.next(); iter.remove(); if (callback.mUserId != mSelectedUserInteractor.getSelectedUserId()) { Log.i(TAG, "Not notifying lockNowCallback due to user mismatch"); continue; } Log.i(TAG, "Notifying lockNowCallback"); try { callback.mRemoteCallback.sendResult(null); } catch (RemoteException e) { Log.e(TAG, "Could not issue LockNowCallback sendResult", e); } } } private void notifyTrustedChangedLocked(boolean trusted) { int size = mKeyguardStateCallbacks.size(); for (int i = size - 1; i >= 0; i--) { Loading Loading @@ -4310,14 +4152,4 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, } }; } private class LockNowCallback { final int mUserId; final IRemoteCallback mRemoteCallback; LockNowCallback(int userId, IRemoteCallback remoteCallback) { mUserId = userId; mRemoteCallback = remoteCallback; } } }
packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java +13 −153 File changed.Preview size limit exceeded, changes collapsed. Show changes
services/core/java/com/android/server/am/UserController.java +28 −10 Original line number Diff line number Diff line Loading @@ -31,7 +31,6 @@ import static android.app.ActivityManagerInternal.ALLOW_FULL_ONLY; import static android.app.ActivityManagerInternal.ALLOW_NON_FULL; import static android.app.ActivityManagerInternal.ALLOW_NON_FULL_IN_PROFILE; import static android.app.ActivityManagerInternal.ALLOW_PROFILES_OR_NON_FULL; import static android.app.KeyguardManager.LOCK_ON_USER_SWITCH_CALLBACK; import static android.os.PowerWhitelistManager.REASON_BOOT_COMPLETED; import static android.os.PowerWhitelistManager.REASON_LOCKED_BOOT_COMPLETED; import static android.os.PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED; Loading Loading @@ -3905,6 +3904,10 @@ class UserController implements Handler.Callback { return mService.mWindowManager; } ActivityTaskManagerInternal getActivityTaskManagerInternal() { return mService.mAtmInternal; } void activityManagerOnUserStopped(@UserIdInt int userId) { LocalServices.getService(ActivityTaskManagerInternal.class).onUserStopped(userId); } Loading Loading @@ -4119,25 +4122,40 @@ class UserController implements Handler.Callback { } void lockDeviceNowAndWaitForKeyguardShown() { if (getWindowManager().isKeyguardLocked()) { Slogf.w(TAG, "Not locking the device since the keyguard is already locked"); return; } final TimingsTraceAndSlog t = new TimingsTraceAndSlog(); t.traceBegin("lockDeviceNowAndWaitForKeyguardShown"); final CountDownLatch latch = new CountDownLatch(1); Bundle bundle = new Bundle(); bundle.putBinder(LOCK_ON_USER_SWITCH_CALLBACK, new IRemoteCallback.Stub() { public void sendResult(Bundle data) { ActivityTaskManagerInternal.ScreenObserver screenObserver = new ActivityTaskManagerInternal.ScreenObserver() { @Override public void onAwakeStateChanged(boolean isAwake) { } @Override public void onKeyguardStateChanged(boolean isShowing) { if (isShowing) { latch.countDown(); } }); getWindowManager().lockNow(bundle); } }; getActivityTaskManagerInternal().registerScreenObserver(screenObserver); getWindowManager().lockDeviceNow(); try { if (!latch.await(20, TimeUnit.SECONDS)) { throw new RuntimeException("User controller expected a callback while waiting " + "to show the keyguard. Timed out after 20 seconds."); throw new RuntimeException("Keyguard is not shown in 20 seconds"); } } catch (InterruptedException e) { throw new RuntimeException(e); } finally { getActivityTaskManagerInternal().unregisterScreenObserver(screenObserver); t.traceEnd(); } } Loading
services/tests/servicestests/src/com/android/server/am/UserControllerTest.java +13 −6 Original line number Diff line number Diff line Loading @@ -25,7 +25,6 @@ import static android.app.ActivityManagerInternal.ALLOW_FULL_ONLY; import static android.app.ActivityManagerInternal.ALLOW_NON_FULL; import static android.app.ActivityManagerInternal.ALLOW_NON_FULL_IN_PROFILE; import static android.app.ActivityManagerInternal.ALLOW_PROFILES_OR_NON_FULL; import static android.app.KeyguardManager.LOCK_ON_USER_SWITCH_CALLBACK; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.testing.DexmakerShareClassLoaderRule.runWithDexmakerShareClassLoader; Loading Loading @@ -116,6 +115,7 @@ import com.android.server.pm.UserManagerInternal; import com.android.server.pm.UserManagerService; import com.android.server.pm.UserTypeDetails; import com.android.server.pm.UserTypeFactory; import com.android.server.wm.ActivityTaskManagerInternal; import com.android.server.wm.WindowManagerService; import com.google.common.collect.Range; Loading Loading @@ -1563,11 +1563,11 @@ public class UserControllerTest { // and the thread is still alive assertTrue(threadStartUser.isAlive()); // mock the binder response for the user switch completion ArgumentCaptor<Bundle> captor = ArgumentCaptor.forClass(Bundle.class); verify(mInjector.mWindowManagerMock).lockNow(captor.capture()); IRemoteCallback.Stub.asInterface(captor.getValue().getBinder( LOCK_ON_USER_SWITCH_CALLBACK)).sendResult(null); // mock send the keyguard shown event ArgumentCaptor<ActivityTaskManagerInternal.ScreenObserver> captor = ArgumentCaptor.forClass( ActivityTaskManagerInternal.ScreenObserver.class); verify(mInjector.mActivityTaskManagerInternal).registerScreenObserver(captor.capture()); captor.getValue().onKeyguardStateChanged(true); // verify the switch now moves on... Thread.sleep(1000); Loading Loading @@ -1757,6 +1757,7 @@ public class UserControllerTest { private final IStorageManager mStorageManagerMock; private final UserManagerInternal mUserManagerInternalMock; private final WindowManagerService mWindowManagerMock; private final ActivityTaskManagerInternal mActivityTaskManagerInternal; private final PowerManagerInternal mPowerManagerInternal; private final AlarmManagerInternal mAlarmManagerInternal; private final KeyguardManager mKeyguardManagerMock; Loading @@ -1778,6 +1779,7 @@ public class UserControllerTest { mUserManagerMock = mock(UserManagerService.class); mUserManagerInternalMock = mock(UserManagerInternal.class); mWindowManagerMock = mock(WindowManagerService.class); mActivityTaskManagerInternal = mock(ActivityTaskManagerInternal.class); mStorageManagerMock = mock(IStorageManager.class); mPowerManagerInternal = mock(PowerManagerInternal.class); mAlarmManagerInternal = mock(AlarmManagerInternal.class); Loading Loading @@ -1840,6 +1842,11 @@ public class UserControllerTest { return mWindowManagerMock; } @Override ActivityTaskManagerInternal getActivityTaskManagerInternal() { return mActivityTaskManagerInternal; } @Override PowerManagerInternal getPowerManagerInternal() { return mPowerManagerInternal; Loading