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

Commit a0327f0b authored by Yasin Kilicdere's avatar Yasin Kilicdere
Browse files

Reset mTargetUserId and dismiss UserSwitchingDialog if startUser fails

UserController.switchUser and UserController.startUserInternal both
share a validation check logic but the validation code is duplicated.

When switching a user, switchUser runs the validation checks, and if
they pass it sets mTargetUserId and starts a call chain that
eventually calls startUserInternal.

Currently the validation checks are in sync, but if some other
validation would be added to startUserInternal but not in switchUser
we would end up with a wrong mTargetUserId and an undismissed
UserSwitchingDialog.

If UserSwitchingDialog is not dismissed, device would be unusable.
If mTargetUserId holds wrong value, ActivityManager.getCurrentUser()
would return a wrong current user id since the call chain ends in
UserController.getCurrentOrTargetUserId(), which would return the
mTargetUserId since it won't be UserHandle.USER_NULL.

This CL resets mTargetUserId and dismisses UserSwitchingDialog if
UserController.startUserInForeground() fails.

Bug: 264999003
Test: atest FrameworksServicesTests:UserControllerTest
Change-Id: I308cc017518a0899b10fc87a86273a9e84f6b70f
parent 719d7559
Loading
Loading
Loading
Loading
+26 −5
Original line number Diff line number Diff line
@@ -61,7 +61,6 @@ import android.app.ActivityManagerInternal;
import android.app.AppGlobals;
import android.app.AppOpsManager;
import android.app.BroadcastOptions;
import android.app.Dialog;
import android.app.IStopUserCallback;
import android.app.IUserSwitchObserver;
import android.app.KeyguardManager;
@@ -1683,6 +1682,7 @@ class UserController implements Handler.Callback {
                        R.anim.screen_user_exit, R.anim.screen_user_enter);
                t.traceEnd();
            }
            dismissUserSwitchDialog(); // so that we don't hold a reference to mUserSwitchingDialog

            boolean needStart = false;
            boolean updateUmState = false;
@@ -1869,6 +1869,8 @@ class UserController implements Handler.Callback {
        boolean success = startUser(targetUserId, USER_START_MODE_FOREGROUND);
        if (!success) {
            mInjector.getWindowManager().setSwitchingUser(false);
            mTargetUserId = UserHandle.USER_NULL;
            dismissUserSwitchDialog();
        }
    }

@@ -2017,6 +2019,10 @@ class UserController implements Handler.Callback {
        return true;
    }

    private void dismissUserSwitchDialog() {
        mInjector.dismissUserSwitchingDialog();
    }

    private void showUserSwitchDialog(Pair<UserInfo, UserInfo> fromToUserPair) {
        // The dialog will show and then initiate the user switch by calling startUserInForeground
        mInjector.showUserSwitchingDialog(fromToUserPair.first, fromToUserPair.second,
@@ -3462,6 +3468,9 @@ class UserController implements Handler.Callback {
        private UserManagerService mUserManager;
        private UserManagerInternal mUserManagerInternal;
        private Handler mHandler;
        private final Object mUserSwitchingDialogLock = new Object();
        @GuardedBy("mUserSwitchingDialogLock")
        private UserSwitchingDialog mUserSwitchingDialog;

        Injector(ActivityManagerService service) {
            mService = service;
@@ -3637,6 +3646,15 @@ class UserController implements Handler.Callback {
            mService.mCpHelper.installEncryptionUnawareProviders(userId);
        }

        void dismissUserSwitchingDialog() {
            synchronized (mUserSwitchingDialogLock) {
                if (mUserSwitchingDialog != null) {
                    mUserSwitchingDialog.dismiss();
                    mUserSwitchingDialog = null;
                }
            }
        }

        void showUserSwitchingDialog(UserInfo fromUser, UserInfo toUser,
                String switchingFromSystemUserMessage, String switchingToSystemUserMessage) {
            if (mService.mContext.getPackageManager()
@@ -3647,10 +3665,13 @@ class UserController implements Handler.Callback {
                Slogf.w(TAG, "Showing user switch dialog on UserController, it could cause a race "
                        + "condition if it's shown by CarSystemUI as well");
            }
            final Dialog d = new UserSwitchingDialog(mService, mService.mContext, fromUser,
                    toUser, true /* above system */, switchingFromSystemUserMessage,
            synchronized (mUserSwitchingDialogLock) {
                dismissUserSwitchingDialog();
                mUserSwitchingDialog = new UserSwitchingDialog(mService, mService.mContext,
                        fromUser, toUser, true /* above system */, switchingFromSystemUserMessage,
                        switchingToSystemUserMessage);
            d.show();
                mUserSwitchingDialog.show();
            }
        }

        void reportGlobalUsageEvent(int event) {