Loading services/core/java/com/android/server/am/UserController.java +14 −26 Original line number Original line Diff line number Diff line Loading @@ -113,9 +113,7 @@ import android.os.SystemProperties; import android.os.Trace; import android.os.Trace; import android.os.UserHandle; import android.os.UserHandle; import android.os.UserManager; import android.os.UserManager; import android.os.storage.IStorageManager; import android.os.storage.StorageManager; import android.os.storage.StorageManager; import android.security.KeyStoreAuthorization; import android.text.TextUtils; import android.text.TextUtils; import android.text.format.DateUtils; import android.text.format.DateUtils; import android.util.ArraySet; import android.util.ArraySet; Loading @@ -142,6 +140,7 @@ import com.android.server.LocalServices; import com.android.server.SystemService.UserCompletedEventType; import com.android.server.SystemService.UserCompletedEventType; import com.android.server.SystemServiceManager; import com.android.server.SystemServiceManager; import com.android.server.am.UserState.KeyEvictedCallback; import com.android.server.am.UserState.KeyEvictedCallback; import com.android.server.locksettings.LockSettingsInternal; import com.android.server.pm.UserJourneyLogger; import com.android.server.pm.UserJourneyLogger; import com.android.server.pm.UserJourneyLogger.UserJourneySession; import com.android.server.pm.UserJourneyLogger.UserJourneySession; import com.android.server.pm.UserManagerInternal; import com.android.server.pm.UserManagerInternal; Loading Loading @@ -1652,7 +1651,6 @@ class UserController implements Handler.Callback { } } } } private void dispatchUserLocking(@UserIdInt int userId, private void dispatchUserLocking(@UserIdInt int userId, @Nullable List<KeyEvictedCallback> keyEvictedCallbacks) { @Nullable List<KeyEvictedCallback> keyEvictedCallbacks) { // Evict user secrets that require strong authentication to unlock. This includes locking // Evict user secrets that require strong authentication to unlock. This includes locking Loading @@ -1660,22 +1658,12 @@ class UserController implements Handler.Callback { // Performed on FgThread to make it serialized with call to // Performed on FgThread to make it serialized with call to // UserManagerService.onBeforeUnlockUser in finishUserUnlocking to prevent data corruption. // UserManagerService.onBeforeUnlockUser in finishUserUnlocking to prevent data corruption. FgThread.getHandler().post(() -> { FgThread.getHandler().post(() -> { synchronized (mLock) { if (hasStartedUserState(userId)) { if (mStartedUsers.get(userId) != null) { Slogf.w(TAG, "User was restarted, skipping key eviction"); Slogf.w(TAG, "User was restarted, skipping key eviction"); return; return; } } } mInjector.getLockSettingsInternal().lockUser(userId); try { Slogf.i(TAG, "Locking CE storage for user #" + userId); mInjector.getStorageManager().lockCeStorage(userId); } catch (RemoteException re) { throw re.rethrowAsRuntimeException(); } if (com.android.server.flags.Flags.keystoreInMemoryCleanup()) { // Send communication to keystore to wipe key cache for the given userId. mInjector.getKeyStoreAuthorization().onUserStorageLocked(userId); } if (keyEvictedCallbacks == null) { if (keyEvictedCallbacks == null) { return; return; } } Loading Loading @@ -4245,6 +4233,7 @@ class UserController implements Handler.Callback { private final ActivityManagerService mService; private final ActivityManagerService mService; private UserManagerService mUserManager; private UserManagerService mUserManager; private UserManagerInternal mUserManagerInternal; private UserManagerInternal mUserManagerInternal; private LockSettingsInternal mLockSettingsInternal; private PowerManagerInternal mPowerManagerInternal; private PowerManagerInternal mPowerManagerInternal; private Handler mHandler; private Handler mHandler; private final Object mUserSwitchingDialogLock = new Object(); private final Object mUserSwitchingDialogLock = new Object(); Loading Loading @@ -4335,6 +4324,13 @@ class UserController implements Handler.Callback { return mUserManagerInternal; return mUserManagerInternal; } } LockSettingsInternal getLockSettingsInternal() { if (mLockSettingsInternal == null) { mLockSettingsInternal = LocalServices.getService(LockSettingsInternal.class); } return mLockSettingsInternal; } PowerManagerInternal getPowerManagerInternal() { PowerManagerInternal getPowerManagerInternal() { if (mPowerManagerInternal == null) { if (mPowerManagerInternal == null) { mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class); mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class); Loading @@ -4354,10 +4350,6 @@ class UserController implements Handler.Callback { return mService.mContext.getSystemService(KeyguardManager.class); return mService.mContext.getSystemService(KeyguardManager.class); } } KeyStoreAuthorization getKeyStoreAuthorization() { return KeyStoreAuthorization.getInstance(); } void batteryStatsServiceNoteEvent(int code, String name, int uid) { void batteryStatsServiceNoteEvent(int code, String name, int uid) { mService.mBatteryStatsService.noteEvent(code, name, uid); mService.mBatteryStatsService.noteEvent(code, name, uid); } } Loading Loading @@ -4503,10 +4495,6 @@ class UserController implements Handler.Callback { return mService.mAtmInternal.isCallerRecents(callingUid); return mService.mAtmInternal.isCallerRecents(callingUid); } } protected IStorageManager getStorageManager() { return IStorageManager.Stub.asInterface(ServiceManager.getService("mount")); } boolean isHeadlessSystemUserMode() { boolean isHeadlessSystemUserMode() { return UserManager.isHeadlessSystemUserMode(); return UserManager.isHeadlessSystemUserMode(); } } Loading services/core/java/com/android/server/locksettings/LockSettingsInternal.java +8 −0 Original line number Original line Diff line number Diff line Loading @@ -130,6 +130,14 @@ public abstract class LockSettingsInternal { */ */ public abstract boolean unlockUserWithToken(long tokenHandle, byte[] token, int userId); public abstract boolean unlockUserWithToken(long tokenHandle, byte[] token, int userId); /** * Lock the specified user, i.e. storage, keystore state, and strong auth flags. * * @param userId the ID of the user being locked. */ public abstract void lockUser(@UserIdInt int userId); /** /** * Returns PasswordMetrics object corresponding to the given user's lockscreen password. * Returns PasswordMetrics object corresponding to the given user's lockscreen password. * If the user has a password but its metrics isn't known yet (for example if the device * If the user has a password but its metrics isn't known yet (for example if the device Loading services/core/java/com/android/server/locksettings/LockSettingsService.java +35 −26 Original line number Original line Diff line number Diff line Loading @@ -97,10 +97,8 @@ import android.os.SystemClock; import android.os.SystemProperties; import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserHandle; import android.os.UserManager; import android.os.UserManager; import android.os.storage.ICeStorageLockEventListener; import android.os.storage.IStorageManager; import android.os.storage.IStorageManager; import android.os.storage.StorageManager; import android.os.storage.StorageManager; import android.os.storage.StorageManagerInternal; import android.provider.Settings; import android.provider.Settings; import android.security.AndroidKeyStoreMaintenance; import android.security.AndroidKeyStoreMaintenance; import android.security.KeyStoreAuthorization; import android.security.KeyStoreAuthorization; Loading Loading @@ -335,8 +333,6 @@ public class LockSettingsService extends ILockSettings.Stub { private final CopyOnWriteArrayList<LockSettingsStateListener> mLockSettingsStateListeners = private final CopyOnWriteArrayList<LockSettingsStateListener> mLockSettingsStateListeners = new CopyOnWriteArrayList<>(); new CopyOnWriteArrayList<>(); private final StorageManagerInternal mStorageManagerInternal; private final Object mGcWorkToken = new Object(); private final Object mGcWorkToken = new Object(); // This class manages life cycle events for encrypted users on File Based Encryption (FBE) // This class manages life cycle events for encrypted users on File Based Encryption (FBE) Loading Loading @@ -589,10 +585,6 @@ public class LockSettingsService extends ILockSettings.Stub { return null; return null; } } public StorageManagerInternal getStorageManagerInternal() { return LocalServices.getService(StorageManagerInternal.class); } public SyntheticPasswordManager getSyntheticPasswordManager(LockSettingsStorage storage) { public SyntheticPasswordManager getSyntheticPasswordManager(LockSettingsStorage storage) { return new SyntheticPasswordManager(getContext(), storage, getUserManager(), return new SyntheticPasswordManager(getContext(), storage, getUserManager(), new PasswordSlotManager()); new PasswordSlotManager()); Loading Loading @@ -723,7 +715,6 @@ public class LockSettingsService extends ILockSettings.Stub { mNotificationManager = injector.getNotificationManager(); mNotificationManager = injector.getNotificationManager(); mUserManager = injector.getUserManager(); mUserManager = injector.getUserManager(); mStorageManager = injector.getStorageManager(); mStorageManager = injector.getStorageManager(); mStorageManagerInternal = injector.getStorageManagerInternal(); mStrongAuthTracker = injector.getStrongAuthTracker(); mStrongAuthTracker = injector.getStrongAuthTracker(); mStrongAuthTracker.register(mStrongAuth); mStrongAuthTracker.register(mStrongAuth); mGatekeeperPasswords = new LongSparseArray<>(); mGatekeeperPasswords = new LongSparseArray<>(); Loading Loading @@ -969,24 +960,7 @@ public class LockSettingsService extends ILockSettings.Stub { mStorage.prefetchUser(UserHandle.USER_SYSTEM); mStorage.prefetchUser(UserHandle.USER_SYSTEM); mBiometricDeferredQueue.systemReady(mInjector.getFingerprintManager(), mBiometricDeferredQueue.systemReady(mInjector.getFingerprintManager(), mInjector.getFaceManager(), mInjector.getBiometricManager()); mInjector.getFaceManager(), mInjector.getBiometricManager()); mStorageManagerInternal.registerStorageLockEventListener(mCeStorageLockEventListener); } private final ICeStorageLockEventListener mCeStorageLockEventListener = new ICeStorageLockEventListener() { @Override public void onStorageLocked(int userId) { Slog.i(TAG, "Storage lock event received for " + userId); mHandler.post(() -> { UserProperties userProperties = getUserProperties(userId); if (userProperties != null && userProperties .getAllowStoppingUserWithDelayedLocking()) { int strongAuthRequired = LockPatternUtils.StrongAuthTracker .getDefaultFlags(mContext); requireStrongAuth(strongAuthRequired, userId); } } }); }}; private void loadEscrowData() { private void loadEscrowData() { mRebootEscrowManager.loadRebootEscrowDataIfAvailable(mHandler); mRebootEscrowManager.loadRebootEscrowDataIfAvailable(mHandler); Loading Loading @@ -1552,6 +1526,10 @@ public class LockSettingsService extends ILockSettings.Stub { } } } } private void lockKeystore(int userId) { mKeyStoreAuthorization.onUserStorageLocked(userId); } @VisibleForTesting /** Note: this method is overridden in unit tests */ @VisibleForTesting /** Note: this method is overridden in unit tests */ protected LockscreenCredential getDecryptedPasswordForTiedProfile(int userId) protected LockscreenCredential getDecryptedPasswordForTiedProfile(int userId) throws KeyStoreException, UnrecoverableKeyException, throws KeyStoreException, UnrecoverableKeyException, Loading Loading @@ -3513,6 +3491,32 @@ public class LockSettingsService extends ILockSettings.Stub { return true; return true; } } private void lockUser(@UserIdInt int userId) { // Lock the user's credential-encrypted storage. try { Slogf.i(TAG, "Locking CE storage for user #" + userId); mInjector.getStorageManager().lockCeStorage(userId); } catch (RemoteException re) { throw re.rethrowAsRuntimeException(); } // Lock user's Keystore by wiping the user's super key cache. if (com.android.server.flags.Flags.keystoreInMemoryCleanup()) { lockKeystore(userId); } // Reset user's strong auth flags mHandler.post(() -> { UserProperties userProperties = getUserProperties(userId); if (userProperties != null && userProperties .getAllowStoppingUserWithDelayedLocking()) { int strongAuthRequired = LockPatternUtils.StrongAuthTracker .getDefaultFlags(mContext); requireStrongAuth(strongAuthRequired, userId); } }); } @Override @Override public boolean tryUnlockWithCachedUnifiedChallenge(int userId) { public boolean tryUnlockWithCachedUnifiedChallenge(int userId) { checkPasswordReadPermission(); checkPasswordReadPermission(); Loading Loading @@ -3849,6 +3853,11 @@ public class LockSettingsService extends ILockSettings.Stub { return LockSettingsService.this.unlockUserWithToken(tokenHandle, token, userId); return LockSettingsService.this.unlockUserWithToken(tokenHandle, token, userId); } } @Override public void lockUser(@UserIdInt int userId) { LockSettingsService.this.lockUser(userId); } @Override @Override public PasswordMetrics getUserPasswordMetrics(int userHandle) { public PasswordMetrics getUserPasswordMetrics(int userHandle) { final long identity = Binder.clearCallingIdentity(); final long identity = Binder.clearCallingIdentity(); Loading services/tests/mockingservicestests/src/com/android/server/am/UserControllerMockedTest.java +9 −0 Original line number Original line Diff line number Diff line Loading @@ -21,6 +21,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.never; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.spy; Loading @@ -29,8 +30,10 @@ import static org.mockito.Mockito.when; import android.annotation.UserIdInt; import android.annotation.UserIdInt; import android.content.Context; import android.content.Context; import android.content.pm.UserInfo; import android.os.Handler; import android.os.Handler; import android.os.UserHandle; import android.os.UserHandle; import android.os.UserManager; import com.android.modules.utils.testing.ExtendedMockitoRule; import com.android.modules.utils.testing.ExtendedMockitoRule; import com.android.server.pm.UserManagerInternal; import com.android.server.pm.UserManagerInternal; Loading Loading @@ -166,5 +169,11 @@ public final class UserControllerMockedTest { private void mockSystemUserHeadlessMode(boolean headless) { private void mockSystemUserHeadlessMode(boolean headless) { when(mSpiedUserControllerInjector.isHeadlessSystemUserMode()).thenReturn(headless); when(mSpiedUserControllerInjector.isHeadlessSystemUserMode()).thenReturn(headless); UserInfo sysInfo = new UserInfo(UserHandle.USER_SYSTEM, "User" + UserHandle.USER_SYSTEM, /* iconPath= */ null, headless ? UserInfo.FLAG_SYSTEM : UserInfo.FLAG_FULL | UserInfo.FLAG_SYSTEM, headless ? UserManager.USER_TYPE_SYSTEM_HEADLESS : UserManager.USER_TYPE_FULL_SYSTEM); when(mUserManagerService.getUserInfo(eq(UserHandle.USER_SYSTEM))).thenReturn(sysInfo); } } } } services/tests/servicestests/src/com/android/server/am/UserControllerTest.java +14 −11 Original line number Original line Diff line number Diff line Loading @@ -116,6 +116,7 @@ import com.android.server.AlarmManagerInternal; import com.android.server.FgThread; import com.android.server.FgThread; import com.android.server.SystemService; import com.android.server.SystemService; import com.android.server.am.UserState.KeyEvictedCallback; import com.android.server.am.UserState.KeyEvictedCallback; import com.android.server.locksettings.LockSettingsInternal; import com.android.server.pm.UserJourneyLogger; import com.android.server.pm.UserJourneyLogger; import com.android.server.pm.UserManagerInternal; import com.android.server.pm.UserManagerInternal; import com.android.server.pm.UserManagerService; import com.android.server.pm.UserManagerService; Loading Loading @@ -1150,8 +1151,8 @@ public class UserControllerTest { // Cannot mock FgThread handler, so confirm that there is no posted message left before // Cannot mock FgThread handler, so confirm that there is no posted message left before // checking. // checking. waitForHandlerToComplete(FgThread.getHandler(), HANDLER_WAIT_TIME_MS); waitForHandlerToComplete(FgThread.getHandler(), HANDLER_WAIT_TIME_MS); verify(mInjector.mStorageManagerMock, times(0)) verify(mInjector.mLockSettingsInternalMock, times(0)) .lockCeStorage(anyInt()); .lockUser(anyInt()); addForegroundUserAndContinueUserSwitch(TEST_USER_ID2, TEST_USER_ID1, addForegroundUserAndContinueUserSwitch(TEST_USER_ID2, TEST_USER_ID1, numberOfUserSwitches, true, false); numberOfUserSwitches, true, false); Loading @@ -1164,8 +1165,8 @@ public class UserControllerTest { ussUser1.setState(UserState.STATE_SHUTDOWN); ussUser1.setState(UserState.STATE_SHUTDOWN); mUserController.finishUserStopped(ussUser1, /* allowDelayedLocking= */ true); mUserController.finishUserStopped(ussUser1, /* allowDelayedLocking= */ true); waitForHandlerToComplete(FgThread.getHandler(), HANDLER_WAIT_TIME_MS); waitForHandlerToComplete(FgThread.getHandler(), HANDLER_WAIT_TIME_MS); verify(mInjector.mStorageManagerMock, times(1)) verify(mInjector.mLockSettingsInternalMock, times(1)) .lockCeStorage(TEST_USER_ID); .lockUser(TEST_USER_ID); } } /** Tests that we stop excess users when starting a background user. */ /** Tests that we stop excess users when starting a background user. */ Loading Loading @@ -2119,8 +2120,8 @@ public class UserControllerTest { // no easy way to get that information passed through lambda. // no easy way to get that information passed through lambda. mUserController.finishUserStopped(ussUser, allowDelayedLocking); mUserController.finishUserStopped(ussUser, allowDelayedLocking); waitForHandlerToComplete(FgThread.getHandler(), HANDLER_WAIT_TIME_MS); waitForHandlerToComplete(FgThread.getHandler(), HANDLER_WAIT_TIME_MS); verify(mInjector.mStorageManagerMock, times(expectLocking ? 1 : 0)) verify(mInjector.mLockSettingsInternalMock, times(expectLocking ? 1 : 0)) .lockCeStorage(userId); .lockUser(eq(userId)); } } private void addForegroundUserAndContinueUserSwitch(int newUserId, int expectedOldUserId, private void addForegroundUserAndContinueUserSwitch(int newUserId, int expectedOldUserId, Loading Loading @@ -2288,6 +2289,7 @@ public class UserControllerTest { private final IStorageManager mStorageManagerMock; private final IStorageManager mStorageManagerMock; private final UserManagerInternal mUserManagerInternalMock; private final UserManagerInternal mUserManagerInternalMock; private final LockSettingsInternal mLockSettingsInternalMock; private final WindowManagerService mWindowManagerMock; private final WindowManagerService mWindowManagerMock; private final PowerManagerInternal mPowerManagerInternal; private final PowerManagerInternal mPowerManagerInternal; private final AlarmManagerInternal mAlarmManagerInternal; private final AlarmManagerInternal mAlarmManagerInternal; Loading @@ -2310,6 +2312,7 @@ public class UserControllerTest { mUiHandler = new TestHandler(mHandlerThread.getLooper()); mUiHandler = new TestHandler(mHandlerThread.getLooper()); mUserManagerMock = mock(UserManagerService.class); mUserManagerMock = mock(UserManagerService.class); mUserManagerInternalMock = mock(UserManagerInternal.class); mUserManagerInternalMock = mock(UserManagerInternal.class); mLockSettingsInternalMock = mock(LockSettingsInternal.class); mWindowManagerMock = mock(WindowManagerService.class); mWindowManagerMock = mock(WindowManagerService.class); mStorageManagerMock = mock(IStorageManager.class); mStorageManagerMock = mock(IStorageManager.class); mPowerManagerInternal = mock(PowerManagerInternal.class); mPowerManagerInternal = mock(PowerManagerInternal.class); Loading Loading @@ -2341,6 +2344,11 @@ public class UserControllerTest { return mUserManagerInternalMock; return mUserManagerInternalMock; } } @Override LockSettingsInternal getLockSettingsInternal() { return mLockSettingsInternalMock; } @Override @Override protected Context getContext() { protected Context getContext() { return mCtx; return mCtx; Loading Loading @@ -2426,11 +2434,6 @@ public class UserControllerTest { return true; return true; } } @Override protected IStorageManager getStorageManager() { return mStorageManagerMock; } @Override @Override void showUserSwitchingDialog(UserInfo fromUser, UserInfo toUser, void showUserSwitchingDialog(UserInfo fromUser, UserInfo toUser, String switchingFromSystemUserMessage, String switchingToSystemUserMessage, String switchingFromSystemUserMessage, String switchingToSystemUserMessage, Loading Loading
services/core/java/com/android/server/am/UserController.java +14 −26 Original line number Original line Diff line number Diff line Loading @@ -113,9 +113,7 @@ import android.os.SystemProperties; import android.os.Trace; import android.os.Trace; import android.os.UserHandle; import android.os.UserHandle; import android.os.UserManager; import android.os.UserManager; import android.os.storage.IStorageManager; import android.os.storage.StorageManager; import android.os.storage.StorageManager; import android.security.KeyStoreAuthorization; import android.text.TextUtils; import android.text.TextUtils; import android.text.format.DateUtils; import android.text.format.DateUtils; import android.util.ArraySet; import android.util.ArraySet; Loading @@ -142,6 +140,7 @@ import com.android.server.LocalServices; import com.android.server.SystemService.UserCompletedEventType; import com.android.server.SystemService.UserCompletedEventType; import com.android.server.SystemServiceManager; import com.android.server.SystemServiceManager; import com.android.server.am.UserState.KeyEvictedCallback; import com.android.server.am.UserState.KeyEvictedCallback; import com.android.server.locksettings.LockSettingsInternal; import com.android.server.pm.UserJourneyLogger; import com.android.server.pm.UserJourneyLogger; import com.android.server.pm.UserJourneyLogger.UserJourneySession; import com.android.server.pm.UserJourneyLogger.UserJourneySession; import com.android.server.pm.UserManagerInternal; import com.android.server.pm.UserManagerInternal; Loading Loading @@ -1652,7 +1651,6 @@ class UserController implements Handler.Callback { } } } } private void dispatchUserLocking(@UserIdInt int userId, private void dispatchUserLocking(@UserIdInt int userId, @Nullable List<KeyEvictedCallback> keyEvictedCallbacks) { @Nullable List<KeyEvictedCallback> keyEvictedCallbacks) { // Evict user secrets that require strong authentication to unlock. This includes locking // Evict user secrets that require strong authentication to unlock. This includes locking Loading @@ -1660,22 +1658,12 @@ class UserController implements Handler.Callback { // Performed on FgThread to make it serialized with call to // Performed on FgThread to make it serialized with call to // UserManagerService.onBeforeUnlockUser in finishUserUnlocking to prevent data corruption. // UserManagerService.onBeforeUnlockUser in finishUserUnlocking to prevent data corruption. FgThread.getHandler().post(() -> { FgThread.getHandler().post(() -> { synchronized (mLock) { if (hasStartedUserState(userId)) { if (mStartedUsers.get(userId) != null) { Slogf.w(TAG, "User was restarted, skipping key eviction"); Slogf.w(TAG, "User was restarted, skipping key eviction"); return; return; } } } mInjector.getLockSettingsInternal().lockUser(userId); try { Slogf.i(TAG, "Locking CE storage for user #" + userId); mInjector.getStorageManager().lockCeStorage(userId); } catch (RemoteException re) { throw re.rethrowAsRuntimeException(); } if (com.android.server.flags.Flags.keystoreInMemoryCleanup()) { // Send communication to keystore to wipe key cache for the given userId. mInjector.getKeyStoreAuthorization().onUserStorageLocked(userId); } if (keyEvictedCallbacks == null) { if (keyEvictedCallbacks == null) { return; return; } } Loading Loading @@ -4245,6 +4233,7 @@ class UserController implements Handler.Callback { private final ActivityManagerService mService; private final ActivityManagerService mService; private UserManagerService mUserManager; private UserManagerService mUserManager; private UserManagerInternal mUserManagerInternal; private UserManagerInternal mUserManagerInternal; private LockSettingsInternal mLockSettingsInternal; private PowerManagerInternal mPowerManagerInternal; private PowerManagerInternal mPowerManagerInternal; private Handler mHandler; private Handler mHandler; private final Object mUserSwitchingDialogLock = new Object(); private final Object mUserSwitchingDialogLock = new Object(); Loading Loading @@ -4335,6 +4324,13 @@ class UserController implements Handler.Callback { return mUserManagerInternal; return mUserManagerInternal; } } LockSettingsInternal getLockSettingsInternal() { if (mLockSettingsInternal == null) { mLockSettingsInternal = LocalServices.getService(LockSettingsInternal.class); } return mLockSettingsInternal; } PowerManagerInternal getPowerManagerInternal() { PowerManagerInternal getPowerManagerInternal() { if (mPowerManagerInternal == null) { if (mPowerManagerInternal == null) { mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class); mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class); Loading @@ -4354,10 +4350,6 @@ class UserController implements Handler.Callback { return mService.mContext.getSystemService(KeyguardManager.class); return mService.mContext.getSystemService(KeyguardManager.class); } } KeyStoreAuthorization getKeyStoreAuthorization() { return KeyStoreAuthorization.getInstance(); } void batteryStatsServiceNoteEvent(int code, String name, int uid) { void batteryStatsServiceNoteEvent(int code, String name, int uid) { mService.mBatteryStatsService.noteEvent(code, name, uid); mService.mBatteryStatsService.noteEvent(code, name, uid); } } Loading Loading @@ -4503,10 +4495,6 @@ class UserController implements Handler.Callback { return mService.mAtmInternal.isCallerRecents(callingUid); return mService.mAtmInternal.isCallerRecents(callingUid); } } protected IStorageManager getStorageManager() { return IStorageManager.Stub.asInterface(ServiceManager.getService("mount")); } boolean isHeadlessSystemUserMode() { boolean isHeadlessSystemUserMode() { return UserManager.isHeadlessSystemUserMode(); return UserManager.isHeadlessSystemUserMode(); } } Loading
services/core/java/com/android/server/locksettings/LockSettingsInternal.java +8 −0 Original line number Original line Diff line number Diff line Loading @@ -130,6 +130,14 @@ public abstract class LockSettingsInternal { */ */ public abstract boolean unlockUserWithToken(long tokenHandle, byte[] token, int userId); public abstract boolean unlockUserWithToken(long tokenHandle, byte[] token, int userId); /** * Lock the specified user, i.e. storage, keystore state, and strong auth flags. * * @param userId the ID of the user being locked. */ public abstract void lockUser(@UserIdInt int userId); /** /** * Returns PasswordMetrics object corresponding to the given user's lockscreen password. * Returns PasswordMetrics object corresponding to the given user's lockscreen password. * If the user has a password but its metrics isn't known yet (for example if the device * If the user has a password but its metrics isn't known yet (for example if the device Loading
services/core/java/com/android/server/locksettings/LockSettingsService.java +35 −26 Original line number Original line Diff line number Diff line Loading @@ -97,10 +97,8 @@ import android.os.SystemClock; import android.os.SystemProperties; import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserHandle; import android.os.UserManager; import android.os.UserManager; import android.os.storage.ICeStorageLockEventListener; import android.os.storage.IStorageManager; import android.os.storage.IStorageManager; import android.os.storage.StorageManager; import android.os.storage.StorageManager; import android.os.storage.StorageManagerInternal; import android.provider.Settings; import android.provider.Settings; import android.security.AndroidKeyStoreMaintenance; import android.security.AndroidKeyStoreMaintenance; import android.security.KeyStoreAuthorization; import android.security.KeyStoreAuthorization; Loading Loading @@ -335,8 +333,6 @@ public class LockSettingsService extends ILockSettings.Stub { private final CopyOnWriteArrayList<LockSettingsStateListener> mLockSettingsStateListeners = private final CopyOnWriteArrayList<LockSettingsStateListener> mLockSettingsStateListeners = new CopyOnWriteArrayList<>(); new CopyOnWriteArrayList<>(); private final StorageManagerInternal mStorageManagerInternal; private final Object mGcWorkToken = new Object(); private final Object mGcWorkToken = new Object(); // This class manages life cycle events for encrypted users on File Based Encryption (FBE) // This class manages life cycle events for encrypted users on File Based Encryption (FBE) Loading Loading @@ -589,10 +585,6 @@ public class LockSettingsService extends ILockSettings.Stub { return null; return null; } } public StorageManagerInternal getStorageManagerInternal() { return LocalServices.getService(StorageManagerInternal.class); } public SyntheticPasswordManager getSyntheticPasswordManager(LockSettingsStorage storage) { public SyntheticPasswordManager getSyntheticPasswordManager(LockSettingsStorage storage) { return new SyntheticPasswordManager(getContext(), storage, getUserManager(), return new SyntheticPasswordManager(getContext(), storage, getUserManager(), new PasswordSlotManager()); new PasswordSlotManager()); Loading Loading @@ -723,7 +715,6 @@ public class LockSettingsService extends ILockSettings.Stub { mNotificationManager = injector.getNotificationManager(); mNotificationManager = injector.getNotificationManager(); mUserManager = injector.getUserManager(); mUserManager = injector.getUserManager(); mStorageManager = injector.getStorageManager(); mStorageManager = injector.getStorageManager(); mStorageManagerInternal = injector.getStorageManagerInternal(); mStrongAuthTracker = injector.getStrongAuthTracker(); mStrongAuthTracker = injector.getStrongAuthTracker(); mStrongAuthTracker.register(mStrongAuth); mStrongAuthTracker.register(mStrongAuth); mGatekeeperPasswords = new LongSparseArray<>(); mGatekeeperPasswords = new LongSparseArray<>(); Loading Loading @@ -969,24 +960,7 @@ public class LockSettingsService extends ILockSettings.Stub { mStorage.prefetchUser(UserHandle.USER_SYSTEM); mStorage.prefetchUser(UserHandle.USER_SYSTEM); mBiometricDeferredQueue.systemReady(mInjector.getFingerprintManager(), mBiometricDeferredQueue.systemReady(mInjector.getFingerprintManager(), mInjector.getFaceManager(), mInjector.getBiometricManager()); mInjector.getFaceManager(), mInjector.getBiometricManager()); mStorageManagerInternal.registerStorageLockEventListener(mCeStorageLockEventListener); } private final ICeStorageLockEventListener mCeStorageLockEventListener = new ICeStorageLockEventListener() { @Override public void onStorageLocked(int userId) { Slog.i(TAG, "Storage lock event received for " + userId); mHandler.post(() -> { UserProperties userProperties = getUserProperties(userId); if (userProperties != null && userProperties .getAllowStoppingUserWithDelayedLocking()) { int strongAuthRequired = LockPatternUtils.StrongAuthTracker .getDefaultFlags(mContext); requireStrongAuth(strongAuthRequired, userId); } } }); }}; private void loadEscrowData() { private void loadEscrowData() { mRebootEscrowManager.loadRebootEscrowDataIfAvailable(mHandler); mRebootEscrowManager.loadRebootEscrowDataIfAvailable(mHandler); Loading Loading @@ -1552,6 +1526,10 @@ public class LockSettingsService extends ILockSettings.Stub { } } } } private void lockKeystore(int userId) { mKeyStoreAuthorization.onUserStorageLocked(userId); } @VisibleForTesting /** Note: this method is overridden in unit tests */ @VisibleForTesting /** Note: this method is overridden in unit tests */ protected LockscreenCredential getDecryptedPasswordForTiedProfile(int userId) protected LockscreenCredential getDecryptedPasswordForTiedProfile(int userId) throws KeyStoreException, UnrecoverableKeyException, throws KeyStoreException, UnrecoverableKeyException, Loading Loading @@ -3513,6 +3491,32 @@ public class LockSettingsService extends ILockSettings.Stub { return true; return true; } } private void lockUser(@UserIdInt int userId) { // Lock the user's credential-encrypted storage. try { Slogf.i(TAG, "Locking CE storage for user #" + userId); mInjector.getStorageManager().lockCeStorage(userId); } catch (RemoteException re) { throw re.rethrowAsRuntimeException(); } // Lock user's Keystore by wiping the user's super key cache. if (com.android.server.flags.Flags.keystoreInMemoryCleanup()) { lockKeystore(userId); } // Reset user's strong auth flags mHandler.post(() -> { UserProperties userProperties = getUserProperties(userId); if (userProperties != null && userProperties .getAllowStoppingUserWithDelayedLocking()) { int strongAuthRequired = LockPatternUtils.StrongAuthTracker .getDefaultFlags(mContext); requireStrongAuth(strongAuthRequired, userId); } }); } @Override @Override public boolean tryUnlockWithCachedUnifiedChallenge(int userId) { public boolean tryUnlockWithCachedUnifiedChallenge(int userId) { checkPasswordReadPermission(); checkPasswordReadPermission(); Loading Loading @@ -3849,6 +3853,11 @@ public class LockSettingsService extends ILockSettings.Stub { return LockSettingsService.this.unlockUserWithToken(tokenHandle, token, userId); return LockSettingsService.this.unlockUserWithToken(tokenHandle, token, userId); } } @Override public void lockUser(@UserIdInt int userId) { LockSettingsService.this.lockUser(userId); } @Override @Override public PasswordMetrics getUserPasswordMetrics(int userHandle) { public PasswordMetrics getUserPasswordMetrics(int userHandle) { final long identity = Binder.clearCallingIdentity(); final long identity = Binder.clearCallingIdentity(); Loading
services/tests/mockingservicestests/src/com/android/server/am/UserControllerMockedTest.java +9 −0 Original line number Original line Diff line number Diff line Loading @@ -21,6 +21,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.never; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.spy; Loading @@ -29,8 +30,10 @@ import static org.mockito.Mockito.when; import android.annotation.UserIdInt; import android.annotation.UserIdInt; import android.content.Context; import android.content.Context; import android.content.pm.UserInfo; import android.os.Handler; import android.os.Handler; import android.os.UserHandle; import android.os.UserHandle; import android.os.UserManager; import com.android.modules.utils.testing.ExtendedMockitoRule; import com.android.modules.utils.testing.ExtendedMockitoRule; import com.android.server.pm.UserManagerInternal; import com.android.server.pm.UserManagerInternal; Loading Loading @@ -166,5 +169,11 @@ public final class UserControllerMockedTest { private void mockSystemUserHeadlessMode(boolean headless) { private void mockSystemUserHeadlessMode(boolean headless) { when(mSpiedUserControllerInjector.isHeadlessSystemUserMode()).thenReturn(headless); when(mSpiedUserControllerInjector.isHeadlessSystemUserMode()).thenReturn(headless); UserInfo sysInfo = new UserInfo(UserHandle.USER_SYSTEM, "User" + UserHandle.USER_SYSTEM, /* iconPath= */ null, headless ? UserInfo.FLAG_SYSTEM : UserInfo.FLAG_FULL | UserInfo.FLAG_SYSTEM, headless ? UserManager.USER_TYPE_SYSTEM_HEADLESS : UserManager.USER_TYPE_FULL_SYSTEM); when(mUserManagerService.getUserInfo(eq(UserHandle.USER_SYSTEM))).thenReturn(sysInfo); } } } }
services/tests/servicestests/src/com/android/server/am/UserControllerTest.java +14 −11 Original line number Original line Diff line number Diff line Loading @@ -116,6 +116,7 @@ import com.android.server.AlarmManagerInternal; import com.android.server.FgThread; import com.android.server.FgThread; import com.android.server.SystemService; import com.android.server.SystemService; import com.android.server.am.UserState.KeyEvictedCallback; import com.android.server.am.UserState.KeyEvictedCallback; import com.android.server.locksettings.LockSettingsInternal; import com.android.server.pm.UserJourneyLogger; import com.android.server.pm.UserJourneyLogger; import com.android.server.pm.UserManagerInternal; import com.android.server.pm.UserManagerInternal; import com.android.server.pm.UserManagerService; import com.android.server.pm.UserManagerService; Loading Loading @@ -1150,8 +1151,8 @@ public class UserControllerTest { // Cannot mock FgThread handler, so confirm that there is no posted message left before // Cannot mock FgThread handler, so confirm that there is no posted message left before // checking. // checking. waitForHandlerToComplete(FgThread.getHandler(), HANDLER_WAIT_TIME_MS); waitForHandlerToComplete(FgThread.getHandler(), HANDLER_WAIT_TIME_MS); verify(mInjector.mStorageManagerMock, times(0)) verify(mInjector.mLockSettingsInternalMock, times(0)) .lockCeStorage(anyInt()); .lockUser(anyInt()); addForegroundUserAndContinueUserSwitch(TEST_USER_ID2, TEST_USER_ID1, addForegroundUserAndContinueUserSwitch(TEST_USER_ID2, TEST_USER_ID1, numberOfUserSwitches, true, false); numberOfUserSwitches, true, false); Loading @@ -1164,8 +1165,8 @@ public class UserControllerTest { ussUser1.setState(UserState.STATE_SHUTDOWN); ussUser1.setState(UserState.STATE_SHUTDOWN); mUserController.finishUserStopped(ussUser1, /* allowDelayedLocking= */ true); mUserController.finishUserStopped(ussUser1, /* allowDelayedLocking= */ true); waitForHandlerToComplete(FgThread.getHandler(), HANDLER_WAIT_TIME_MS); waitForHandlerToComplete(FgThread.getHandler(), HANDLER_WAIT_TIME_MS); verify(mInjector.mStorageManagerMock, times(1)) verify(mInjector.mLockSettingsInternalMock, times(1)) .lockCeStorage(TEST_USER_ID); .lockUser(TEST_USER_ID); } } /** Tests that we stop excess users when starting a background user. */ /** Tests that we stop excess users when starting a background user. */ Loading Loading @@ -2119,8 +2120,8 @@ public class UserControllerTest { // no easy way to get that information passed through lambda. // no easy way to get that information passed through lambda. mUserController.finishUserStopped(ussUser, allowDelayedLocking); mUserController.finishUserStopped(ussUser, allowDelayedLocking); waitForHandlerToComplete(FgThread.getHandler(), HANDLER_WAIT_TIME_MS); waitForHandlerToComplete(FgThread.getHandler(), HANDLER_WAIT_TIME_MS); verify(mInjector.mStorageManagerMock, times(expectLocking ? 1 : 0)) verify(mInjector.mLockSettingsInternalMock, times(expectLocking ? 1 : 0)) .lockCeStorage(userId); .lockUser(eq(userId)); } } private void addForegroundUserAndContinueUserSwitch(int newUserId, int expectedOldUserId, private void addForegroundUserAndContinueUserSwitch(int newUserId, int expectedOldUserId, Loading Loading @@ -2288,6 +2289,7 @@ public class UserControllerTest { private final IStorageManager mStorageManagerMock; private final IStorageManager mStorageManagerMock; private final UserManagerInternal mUserManagerInternalMock; private final UserManagerInternal mUserManagerInternalMock; private final LockSettingsInternal mLockSettingsInternalMock; private final WindowManagerService mWindowManagerMock; private final WindowManagerService mWindowManagerMock; private final PowerManagerInternal mPowerManagerInternal; private final PowerManagerInternal mPowerManagerInternal; private final AlarmManagerInternal mAlarmManagerInternal; private final AlarmManagerInternal mAlarmManagerInternal; Loading @@ -2310,6 +2312,7 @@ public class UserControllerTest { mUiHandler = new TestHandler(mHandlerThread.getLooper()); mUiHandler = new TestHandler(mHandlerThread.getLooper()); mUserManagerMock = mock(UserManagerService.class); mUserManagerMock = mock(UserManagerService.class); mUserManagerInternalMock = mock(UserManagerInternal.class); mUserManagerInternalMock = mock(UserManagerInternal.class); mLockSettingsInternalMock = mock(LockSettingsInternal.class); mWindowManagerMock = mock(WindowManagerService.class); mWindowManagerMock = mock(WindowManagerService.class); mStorageManagerMock = mock(IStorageManager.class); mStorageManagerMock = mock(IStorageManager.class); mPowerManagerInternal = mock(PowerManagerInternal.class); mPowerManagerInternal = mock(PowerManagerInternal.class); Loading Loading @@ -2341,6 +2344,11 @@ public class UserControllerTest { return mUserManagerInternalMock; return mUserManagerInternalMock; } } @Override LockSettingsInternal getLockSettingsInternal() { return mLockSettingsInternalMock; } @Override @Override protected Context getContext() { protected Context getContext() { return mCtx; return mCtx; Loading Loading @@ -2426,11 +2434,6 @@ public class UserControllerTest { return true; return true; } } @Override protected IStorageManager getStorageManager() { return mStorageManagerMock; } @Override @Override void showUserSwitchingDialog(UserInfo fromUser, UserInfo toUser, void showUserSwitchingDialog(UserInfo fromUser, UserInfo toUser, String switchingFromSystemUserMessage, String switchingToSystemUserMessage, String switchingFromSystemUserMessage, String switchingToSystemUserMessage, Loading