Merge "Delay user unlocking until boot complete on HSUM." into tm-qpr-dev

This commit is contained in:
Felipe Leme
2022-09-13 21:52:08 +00:00
committed by Android (Google) Code Review
2 changed files with 80 additions and 0 deletions

View File

@@ -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);

View File

@@ -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);