Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e6fe7f5d authored by Felipe Leme's avatar Felipe Leme Committed by Android (Google) Code Review
Browse files

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

parents 12f4fbf7 5f5c13ed
Loading
Loading
Loading
Loading
+65 −0
Original line number Diff line number Diff line
@@ -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);
+15 −0
Original line number Diff line number Diff line
@@ -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);