Merge "Delay user unlocking until boot complete on HSUM." into tm-qpr-dev
This commit is contained in:
@@ -106,6 +106,7 @@ import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.policy.IKeyguardDismissCallback;
|
||||
import com.android.internal.util.ArrayUtils;
|
||||
import com.android.internal.util.FrameworkStatsLog;
|
||||
import com.android.internal.util.Preconditions;
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.server.FactoryResetter;
|
||||
import com.android.server.FgThread;
|
||||
@@ -367,6 +368,11 @@ class UserController implements Handler.Callback {
|
||||
@GuardedBy("mLock")
|
||||
private boolean mDelayUserDataLocking;
|
||||
|
||||
/**
|
||||
* Users are only allowed to be unlocked after boot complete.
|
||||
*/
|
||||
private volatile boolean mAllowUserUnlocking;
|
||||
|
||||
/**
|
||||
* Keep track of last active users for mDelayUserDataLocking.
|
||||
* The latest stopped user is placed in front while the least recently stopped user in back.
|
||||
@@ -426,6 +432,11 @@ class UserController implements Handler.Callback {
|
||||
mUserLru.add(UserHandle.USER_SYSTEM);
|
||||
mLockPatternUtils = mInjector.getLockPatternUtils();
|
||||
updateStartedUserArrayLU();
|
||||
|
||||
// TODO(b/232452368): currently mAllowUserUnlocking is only used on devices with HSUM
|
||||
// (Headless System User Mode), but on master it will be used by all devices (and hence this
|
||||
// initial assignment should be removed).
|
||||
mAllowUserUnlocking = !UserManager.isHeadlessSystemUserMode();
|
||||
}
|
||||
|
||||
void setInitialConfig(boolean userSwitchUiEnabled, int maxRunningUsers,
|
||||
@@ -1742,6 +1753,22 @@ class UserController implements Handler.Callback {
|
||||
|
||||
private boolean unlockUserCleared(final @UserIdInt int userId, byte[] secret,
|
||||
IProgressListener listener) {
|
||||
// Delay user unlocking for headless system user mode until the system boot
|
||||
// completes. When the system boot completes, the {@link #onBootCompleted()}
|
||||
// method unlocks all started users for headless system user mode. This is done
|
||||
// to prevent unlocking the users too early during the system boot up.
|
||||
// Otherwise, emulated volumes are mounted too early during the system
|
||||
// boot up. When vold is reset on boot complete, vold kills all apps/services
|
||||
// (that use these emulated volumes) before unmounting the volumes(b/241929666).
|
||||
// In the past, these killings have caused the system to become too unstable on
|
||||
// some occasions.
|
||||
// Any unlocks that get delayed by this will be done by onBootComplete() instead.
|
||||
if (!mAllowUserUnlocking) {
|
||||
Slogf.i(TAG, "Not unlocking user %d yet because boot hasn't completed", userId);
|
||||
notifyFinished(userId, listener);
|
||||
return false;
|
||||
}
|
||||
|
||||
UserState uss;
|
||||
if (!StorageManager.isUserKeyUnlocked(userId)) {
|
||||
final UserInfo userInfo = getUserInfo(userId);
|
||||
@@ -2331,7 +2358,44 @@ class UserController implements Handler.Callback {
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void setAllowUserUnlocking(boolean allowed) {
|
||||
mAllowUserUnlocking = allowed;
|
||||
if (DEBUG_MU) {
|
||||
// TODO(b/245335748): use Slogf.d instead
|
||||
// Slogf.d(TAG, new Exception(), "setAllowUserUnlocking(%b)", allowed);
|
||||
android.util.Slog.d(TAG, "setAllowUserUnlocking():" + allowed, new Exception());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated TODO(b/232452368): this logic will be merged into sendBootCompleted
|
||||
*/
|
||||
@Deprecated
|
||||
private void onBootCompletedOnHeadlessSystemUserModeDevices() {
|
||||
setAllowUserUnlocking(true);
|
||||
|
||||
// Get a copy of mStartedUsers to use outside of lock.
|
||||
SparseArray<UserState> startedUsers;
|
||||
synchronized (mLock) {
|
||||
startedUsers = mStartedUsers.clone();
|
||||
}
|
||||
// USER_SYSTEM must be processed first. It will be first in the array, as its ID is lowest.
|
||||
Preconditions.checkArgument(startedUsers.keyAt(0) == UserHandle.USER_SYSTEM);
|
||||
for (int i = 0; i < startedUsers.size(); i++) {
|
||||
UserState uss = startedUsers.valueAt(i);
|
||||
int userId = uss.mHandle.getIdentifier();
|
||||
Slogf.i(TAG, "Attempting to unlock user %d on boot complete", userId);
|
||||
maybeUnlockUser(userId);
|
||||
}
|
||||
}
|
||||
|
||||
void sendBootCompleted(IIntentReceiver resultTo) {
|
||||
if (UserManager.isHeadlessSystemUserMode()) {
|
||||
// Unlocking users is delayed until boot complete for headless system user mode.
|
||||
onBootCompletedOnHeadlessSystemUserModeDevices();
|
||||
}
|
||||
|
||||
// Get a copy of mStartedUsers to use outside of lock
|
||||
SparseArray<UserState> startedUsers;
|
||||
synchronized (mLock) {
|
||||
@@ -2773,6 +2837,7 @@ class UserController implements Handler.Callback {
|
||||
pw.println(" mTargetUserId:" + mTargetUserId);
|
||||
pw.println(" mLastActiveUsers:" + mLastActiveUsers);
|
||||
pw.println(" mDelayUserDataLocking:" + mDelayUserDataLocking);
|
||||
pw.println(" mAllowUserUnlocking:" + mAllowUserUnlocking);
|
||||
pw.println(" shouldStopUserOnSwitch():" + shouldStopUserOnSwitch());
|
||||
pw.println(" mStopUserOnSwitch:" + mStopUserOnSwitch);
|
||||
pw.println(" mMaxRunningUsers:" + mMaxRunningUsers);
|
||||
|
||||
@@ -179,6 +179,11 @@ public class UserControllerTest {
|
||||
doNothing().when(mInjector).taskSupervisorRemoveUser(anyInt());
|
||||
// All UserController params are set to default.
|
||||
mUserController = new UserController(mInjector);
|
||||
|
||||
// TODO(b/232452368): need to explicitly call setAllowUserUnlocking(), otherwise most
|
||||
// tests would fail. But we might need to disable it for the onBootComplete() test (i.e,
|
||||
// to make sure the users are unlocked at the right time)
|
||||
mUserController.setAllowUserUnlocking(true);
|
||||
setUpUser(TEST_USER_ID, NO_USERINFO_FLAGS);
|
||||
setUpUser(TEST_PRE_CREATED_USER_ID, NO_USERINFO_FLAGS, /* preCreated=*/ true, null);
|
||||
});
|
||||
@@ -599,6 +604,16 @@ public class UserControllerTest {
|
||||
/* keyEvictedCallback= */ mKeyEvictedCallback, /* expectLocking= */ true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUserNotUnlockedBeforeAllowed() throws Exception {
|
||||
mUserController.setAllowUserUnlocking(false);
|
||||
|
||||
mUserController.startUser(TEST_USER_ID, /* foreground= */ false);
|
||||
|
||||
verify(mInjector.mStorageManagerMock, never())
|
||||
.unlockUserKey(eq(TEST_USER_ID), anyInt(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStartProfile_fullUserFails() {
|
||||
setUpUser(TEST_USER_ID1, 0);
|
||||
|
||||
Reference in New Issue
Block a user