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

Commit 15cd688e authored by Amith Yamasani's avatar Amith Yamasani Committed by Android (Google) Code Review
Browse files

Merge "Dismiss keyguard when target user has no password"

parents bab70a55 c7400f7c
Loading
Loading
Loading
Loading
+63 −7
Original line number Diff line number Diff line
@@ -103,6 +103,7 @@ import android.util.proto.ProtoOutputStream;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
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.widget.LockPatternUtils;
@@ -162,6 +163,7 @@ class UserController implements Handler.Callback {
    static final int USER_UNLOCKED_MSG = 105;
    static final int REPORT_LOCKED_BOOT_COMPLETE_MSG = 110;
    static final int START_USER_SWITCH_FG_MSG = 120;
    static final int COMPLETE_USER_SWITCH_MSG = 130;

    // Message constant to clear {@link UserJourneySession} from {@link mUserIdToUserJourneyMap} if
    // the user journey, defined in the UserLifecycleJourneyReported atom for statsd, is not
@@ -385,6 +387,7 @@ class UserController implements Handler.Callback {
    @VisibleForTesting
    UserController(Injector injector) {
        mInjector = injector;
        // This should be called early to avoid a null mHandler inside the injector
        mHandler = mInjector.getHandler(this);
        mUiHandler = mInjector.getUiHandler(this);
        // User 0 is the first and only user that runs at boot.
@@ -1535,8 +1538,11 @@ class UserController implements Handler.Callback {
                // with the option to show the user switcher on the keyguard.
                if (userSwitchUiEnabled) {
                    mInjector.getWindowManager().setSwitchingUser(true);
                    // Only lock if the user has a secure keyguard PIN/Pattern/Pwd
                    if (mInjector.getKeyguardManager().isDeviceSecure(userId)) {
                        mInjector.getWindowManager().lockNow(null);
                    }
                }
            } else {
                final Integer currentUserIdInt = mCurrentUserId;
                updateCurrentProfileIds();
@@ -1967,11 +1973,10 @@ class UserController implements Handler.Callback {

        EventLog.writeEvent(EventLogTags.UC_CONTINUE_USER_SWITCH, oldUserId, newUserId);

        if (isUserSwitchUiEnabled()) {
            t.traceBegin("stopFreezingScreen");
            mInjector.getWindowManager().stopFreezingScreen();
            t.traceEnd();
        }
        // Do the keyguard dismiss and unfreeze later
        mHandler.removeMessages(COMPLETE_USER_SWITCH_MSG);
        mHandler.sendMessage(mHandler.obtainMessage(COMPLETE_USER_SWITCH_MSG, newUserId, 0));

        uss.switching = false;
        mHandler.removeMessages(REPORT_USER_SWITCH_COMPLETE_MSG);
        mHandler.sendMessage(mHandler.obtainMessage(REPORT_USER_SWITCH_COMPLETE_MSG, newUserId, 0));
@@ -1981,6 +1986,34 @@ class UserController implements Handler.Callback {
        t.traceEnd(); // end continueUserSwitch
    }

    @VisibleForTesting
    void completeUserSwitch(int newUserId) {
        if (isUserSwitchUiEnabled()) {
            // If there is no challenge set, dismiss the keyguard right away
            if (!mInjector.getKeyguardManager().isDeviceSecure(newUserId)) {
                // Wait until the keyguard is dismissed to unfreeze
                mInjector.dismissKeyguard(
                        new Runnable() {
                            public void run() {
                                unfreezeScreen();
                            }
                        },
                        "User Switch");
                return;
            } else {
                unfreezeScreen();
            }
        }
    }

    @VisibleForTesting
    void unfreezeScreen() {
        TimingsTraceAndSlog t = new TimingsTraceAndSlog();
        t.traceBegin("stopFreezingScreen");
        mInjector.getWindowManager().stopFreezingScreen();
        t.traceEnd();
    }

    private void moveUserToForeground(UserState uss, int oldUserId, int newUserId) {
        boolean homeInFront = mInjector.taskSupervisorSwitchUser(newUserId, uss);
        if (homeInFront) {
@@ -2772,6 +2805,9 @@ class UserController implements Handler.Callback {
            case CLEAR_USER_JOURNEY_SESSION_MSG:
                logAndClearSessionId(msg.arg1);
                break;
            case COMPLETE_USER_SWITCH_MSG:
                completeUserSwitch(msg.arg1);
                break;
        }
        return false;
    }
@@ -2961,13 +2997,14 @@ class UserController implements Handler.Callback {
        private final ActivityManagerService mService;
        private UserManagerService mUserManager;
        private UserManagerInternal mUserManagerInternal;
        private Handler mHandler;

        Injector(ActivityManagerService service) {
            mService = service;
        }

        protected Handler getHandler(Handler.Callback callback) {
            return new Handler(mService.mHandlerThread.getLooper(), callback);
            return mHandler = new Handler(mService.mHandlerThread.getLooper(), callback);
        }

        protected Handler getUiHandler(Handler.Callback callback) {
@@ -3165,5 +3202,24 @@ class UserController implements Handler.Callback {
        protected IStorageManager getStorageManager() {
            return IStorageManager.Stub.asInterface(ServiceManager.getService("mount"));
        }

        protected void dismissKeyguard(Runnable runnable, String reason) {
            getWindowManager().dismissKeyguard(new IKeyguardDismissCallback.Stub() {
                @Override
                public void onDismissError() throws RemoteException {
                    mHandler.post(runnable);
                }

                @Override
                public void onDismissSucceeded() throws RemoteException {
                    mHandler.post(runnable);
                }

                @Override
                public void onDismissCancelled() throws RemoteException {
                    mHandler.post(runnable);
                }
            }, reason);
        }
    }
}
+49 −4
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import static android.testing.DexmakerShareClassLoaderRule.runWithDexmakerShareC

import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;

import static com.android.server.am.UserController.COMPLETE_USER_SWITCH_MSG;
import static com.android.server.am.UserController.CONTINUE_USER_SWITCH_MSG;
import static com.android.server.am.UserController.REPORT_LOCKED_BOOT_COMPLETE_MSG;
import static com.android.server.am.UserController.REPORT_USER_SWITCH_COMPLETE_MSG;
@@ -59,6 +60,7 @@ import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.IUserSwitchObserver;
import android.app.KeyguardManager;
import android.content.Context;
import android.content.IIntentReceiver;
import android.content.Intent;
@@ -325,8 +327,16 @@ public class UserControllerTest {
        assertWithMessage("No messages should be sent").that(actualCodes).isEmpty();
    }

    private void continueAndCompleteUserSwitch(UserState userState, int oldUserId, int newUserId) {
        mUserController.continueUserSwitch(userState, oldUserId, newUserId);
        mInjector.mHandler.removeMessages(UserController.COMPLETE_USER_SWITCH_MSG);
        mUserController.completeUserSwitch(newUserId);
    }

    @Test
    public void testContinueUserSwitch() throws RemoteException {
        mUserController.setInitialConfig(/* userSwitchUiEnabled= */ true,
                /* maxRunningUsers= */ 3, /* delayUserDataLocking= */ false);
        // Start user -- this will update state of mUserController
        mUserController.startUser(TEST_USER_ID, true);
        Message reportMsg = mInjector.mHandler.getMessageForCode(REPORT_USER_SWITCH_MSG);
@@ -336,7 +346,28 @@ public class UserControllerTest {
        int newUserId = reportMsg.arg2;
        mInjector.mHandler.clearAllRecordedMessages();
        // Verify that continueUserSwitch worked as expected
        mUserController.continueUserSwitch(userState, oldUserId, newUserId);
        continueAndCompleteUserSwitch(userState, oldUserId, newUserId);
        verify(mInjector, times(0)).dismissKeyguard(any(), anyString());
        verify(mInjector.getWindowManager(), times(1)).stopFreezingScreen();
        continueUserSwitchAssertions(TEST_USER_ID, false);
    }

    @Test
    public void testContinueUserSwitchDismissKeyguard() throws RemoteException {
        when(mInjector.mKeyguardManagerMock.isDeviceSecure(anyInt())).thenReturn(false);
        mUserController.setInitialConfig(/* userSwitchUiEnabled= */ true,
                /* maxRunningUsers= */ 3, /* delayUserDataLocking= */ false);
        // Start user -- this will update state of mUserController
        mUserController.startUser(TEST_USER_ID, true);
        Message reportMsg = mInjector.mHandler.getMessageForCode(REPORT_USER_SWITCH_MSG);
        assertNotNull(reportMsg);
        UserState userState = (UserState) reportMsg.obj;
        int oldUserId = reportMsg.arg1;
        int newUserId = reportMsg.arg2;
        mInjector.mHandler.clearAllRecordedMessages();
        // Verify that continueUserSwitch worked as expected
        continueAndCompleteUserSwitch(userState, oldUserId, newUserId);
        verify(mInjector, times(1)).dismissKeyguard(any(), anyString());
        verify(mInjector.getWindowManager(), times(1)).stopFreezingScreen();
        continueUserSwitchAssertions(TEST_USER_ID, false);
    }
@@ -355,7 +386,7 @@ public class UserControllerTest {
        int newUserId = reportMsg.arg2;
        mInjector.mHandler.clearAllRecordedMessages();
        // Verify that continueUserSwitch worked as expected
        mUserController.continueUserSwitch(userState, oldUserId, newUserId);
        continueAndCompleteUserSwitch(userState, oldUserId, newUserId);
        verify(mInjector.getWindowManager(), never()).stopFreezingScreen();
        continueUserSwitchAssertions(TEST_USER_ID, false);
    }
@@ -363,6 +394,7 @@ public class UserControllerTest {
    private void continueUserSwitchAssertions(int expectedUserId, boolean backgroundUserStopping)
            throws RemoteException {
        Set<Integer> expectedCodes = new LinkedHashSet<>();
        expectedCodes.add(COMPLETE_USER_SWITCH_MSG);
        expectedCodes.add(REPORT_USER_SWITCH_COMPLETE_MSG);
        if (backgroundUserStopping) {
            expectedCodes.add(0); // this is for directly posting in stopping.
@@ -397,7 +429,7 @@ public class UserControllerTest {
    }

    @Test
    public void testExplicitSystenUserStartInBackground() {
    public void testExplicitSystemUserStartInBackground() {
        setUpUser(UserHandle.USER_SYSTEM, 0);
        assertFalse(mUserController.isSystemUserStarted());
        assertTrue(mUserController.startUser(UserHandle.USER_SYSTEM, false, null));
@@ -646,7 +678,7 @@ public class UserControllerTest {
        mUserStates.put(newUserId, userState);
        mInjector.mHandler.clearAllRecordedMessages();
        // Verify that continueUserSwitch worked as expected
        mUserController.continueUserSwitch(userState, oldUserId, newUserId);
        continueAndCompleteUserSwitch(userState, oldUserId, newUserId);
        verify(mInjector.getWindowManager(), times(expectedNumberOfCalls))
                .stopFreezingScreen();
        continueUserSwitchAssertions(newUserId, expectOldUserStopping);
@@ -701,6 +733,7 @@ public class UserControllerTest {
        private final IStorageManager mStorageManagerMock;
        private final UserManagerInternal mUserManagerInternalMock;
        private final WindowManagerService mWindowManagerMock;
        private final KeyguardManager mKeyguardManagerMock;

        private final Context mCtx;

@@ -715,6 +748,8 @@ public class UserControllerTest {
            mUserManagerInternalMock = mock(UserManagerInternal.class);
            mWindowManagerMock = mock(WindowManagerService.class);
            mStorageManagerMock = mock(IStorageManager.class);
            mKeyguardManagerMock = mock(KeyguardManager.class);
            when(mKeyguardManagerMock.isDeviceSecure(anyInt())).thenReturn(true);
        }

        @Override
@@ -753,6 +788,11 @@ public class UserControllerTest {
            return mWindowManagerMock;
        }

        @Override
        KeyguardManager getKeyguardManager() {
            return mKeyguardManagerMock;
        }

        @Override
        void updateUserConfiguration() {
            Log.i(TAG, "updateUserConfiguration");
@@ -787,6 +827,11 @@ public class UserControllerTest {
        protected IStorageManager getStorageManager() {
            return mStorageManagerMock;
        }

        @Override
        protected void dismissKeyguard(Runnable runnable, String reason) {
            runnable.run();
        }
    }

    private static class TestHandler extends Handler {