开启User流程

起点在ActivityManagerService.java 

public boolean startUserInBackground(final int userId) {
        return mUserController.startUser(userId, /* foreground */ false);
    }
UserController.java

 boolean startUser(final int userId, final boolean foreground) {
        ...

        final long ident = Binder.clearCallingIdentity();
        try {
            synchronized (mService) {
                final int oldUserId = mCurrentUserId;
                if (oldUserId == userId) {
                    return true;
                }

                mService.mStackSupervisor.setLockTaskModeLocked(null,
                        ActivityManager.LOCK_TASK_MODE_NONE, "startUser", false);

                final UserInfo userInfo = getUserInfo(userId);
                ...
                if (foreground && userInfo.isManagedProfile()) {
                    //限制manage profile user只能后台切换
                    Slog.w(TAG, "Cannot switch to User #" + userId + ": not a full user");
                    return false;
                }

                if (foreground) {
          //前台切换要进行动画,并冻屏
                    mService.mWindowManager.startFreezingScreen(
                            R.anim.screen_user_exit, R.anim.screen_user_enter);
                }

                ...

                if (foreground) {
          //只有前台切换的时候才会设置mCurrentUserId
                    mCurrentUserId = userId;
                    mService.updateUserConfigurationLocked();
                    mTargetUserId = UserHandle.USER_NULL; // reset, mCurrentUserId has caught up
                    updateCurrentProfileIdsLocked();
                    //前台切换的话要重新启动锁屏,关闭新user不需要的UI
                    mService.mWindowManager.setCurrentUser(userId, mCurrentProfileIds);
                    // Once the internal notion of the active user has switched, we lock the device
                    // with the option to show the user switcher on the keyguard.
                    mService.mWindowManager.lockNow(null);
                } else {
                    final Integer currentUserIdInt = mCurrentUserId;
                    updateCurrentProfileIdsLocked();
                    mService.mWindowManager.setCurrentProfileIds(mCurrentProfileIds);
                    mUserLru.remove(currentUserIdInt);
                    mUserLru.add(currentUserIdInt);
                }

                // Make sure user is in the started state.  If it is currently
                // stopping, we need to knock that off.
                if (uss.state == UserState.STATE_STOPPING) {
                    // If we are stopping, we haven't sent ACTION_SHUTDOWN,
                    // so we can just fairly silently bring the user back from
                    // the almost-dead.
                    uss.setState(uss.lastState);
                    getUserManagerInternal().setUserState(userId, uss.state);
                    updateStartedUserArrayLocked();
                    needStart = true;
                } else if (uss.state == UserState.STATE_SHUTDOWN) {
                    // This means ACTION_SHUTDOWN has been sent, so we will
                    // need to treat this as a new boot of the user.
                    uss.setState(UserState.STATE_BOOTING);
                    getUserManagerInternal().setUserState(userId, uss.state);
                    updateStartedUserArrayLocked();
                    needStart = true;
                }

                //如果是第一次切换的话会走这里
                if (uss.state == UserState.STATE_BOOTING) {
                    // Give user manager a chance to propagate user restrictions
                    // to other services and prepare app storage
                    getUserManager().onBeforeStartUser(userId);

                    // Booting up a new user, need to tell system services about it.
                    // Note that this is on the same handler as scheduling of broadcasts,
                    // which is important because it needs to go first.
                    mHandler.sendMessage(mHandler.obtainMessage(SYSTEM_USER_START_MSG, userId, 0));
                }

                if (foreground) {
          //通过消息处理
                    mHandler.sendMessage(mHandler.obtainMessage(SYSTEM_USER_CURRENT_MSG, userId,
                            oldUserId));
                    mHandler.removeMessages(REPORT_USER_SWITCH_MSG);
                    mHandler.removeMessages(USER_SWITCH_TIMEOUT_MSG);
                    mHandler.sendMessage(mHandler.obtainMessage(REPORT_USER_SWITCH_MSG,
                            oldUserId, userId, uss));
                    mHandler.sendMessageDelayed(mHandler.obtainMessage(USER_SWITCH_TIMEOUT_MSG,
                            oldUserId, userId, uss), USER_SWITCH_TIMEOUT);
                }

                if (needStart) { //Intent.ACTION_USER_STARTED广播
                    // Send USER_STARTED broadcast
                    Intent intent = new Intent(Intent.ACTION_USER_STARTED);
                    ...
                }

                if (foreground) {
                    moveUserToForegroundLocked(uss, oldUserId, userId);
                } else {
                    mService.mUserController.finishUserBoot(uss);
                }

                if (needStart) { //Intent.ACTION_USER_STARTING广播,这个广播是发送给所有user的
                    Intent intent = new Intent(Intent.ACTION_USER_STARTING);
                    ...
            }
        } finally {
            Binder.restoreCallingIdentity(ident);
        }

        return true;
    }

onBeforeStartUser

UserManagerService.java

    public void onBeforeStartUser(int userId) {
        final int userSerial = getUserSerialNumber(userId);
    //user data 处理
        mPm.prepareUserData(userId, userSerial, StorageManager.FLAG_STORAGE_DE);
        mPm.reconcileAppsData(userId, StorageManager.FLAG_STORAGE_DE);

        if (userId != UserHandle.USER_SYSTEM) {
            synchronized (mRestrictionsLock) {
        //非system用户,user要做限制
                applyUserRestrictionsLR(userId);
            }
        }

        maybeInitializeDemoMode(userId);
    }
建立user相关目录,其中prepareUserData上篇文章已详细分析过。而reconcileAppsData是主要工作是创建app相关目录,创建的核心方法createAppData在上篇文章 点击打开链接中详细分析过


消息处理

SYSTEM_USER_START_MSG

            case SYSTEM_USER_START_MSG: {
                mBatteryStatsService.noteEvent(BatteryStats.HistoryItem.EVENT_USER_RUNNING_START,
                        Integer.toString(msg.arg1), msg.arg1);
                mSystemServiceManager.startUser(msg.arg1);
    public void startUser(final int userHandle) {
        final int serviceLen = mServices.size();
        for (int i = 0; i < serviceLen; i++) {
      //通知每个SystemService,SystemService都运行在system进程中。
            final SystemService service = mServices.get(i);
            Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "onStartUser "
                    + service.getClass().getName());
            try {
                service.onStartUser(userHandle);
            } catch (Exception ex) {
                Slog.wtf(TAG, "Failure reporting start of user " + userHandle
                        + " to service " + service.getClass().getName(), ex);
            }
            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
        }
    }
通知SystemService user开始启动

REPORT_USER_SWITCH_MSG

注意该消息只有前台切换user才会发送
case REPORT_USER_SWITCH_MSG: {
                mUserController.dispatchUserSwitch((UserState) msg.obj, msg.arg1, msg.arg2);
                break;
            }
void dispatchUserSwitch(final UserState uss, final int oldUserId, final int newUserId) {
        Slog.d(TAG, "Dispatch onUserSwitching oldUser #" + oldUserId + " newUser #" + newUserId);
        final int observerCount = mUserSwitchObservers.beginBroadcast();
        if (observerCount > 0) {
            final ArraySet<String> curWaitingUserSwitchCallbacks = new ArraySet<>();
            synchronized (mService) {
                uss.switching = true;
        //这里mCurWaitingUserSwitchCallbacks就是curWaitingUserSwitchCallbacks
                mCurWaitingUserSwitchCallbacks = curWaitingUserSwitchCallbacks;
            }
            final AtomicInteger waitingCallbacksCount = new AtomicInteger(observerCount);
            for (int i = 0; i < observerCount; i++) {
                try {
                    // Prepend with unique prefix to guarantee that keys are unique
                    final String name = "#" + i + " " + mUserSwitchObservers.getBroadcastCookie(i);
                    synchronized (mService) {
                        curWaitingUserSwitchCallbacks.add(name);
                    }
                    final IRemoteCallback callback = new IRemoteCallback.Stub() {
                        @Override
                        public void sendResult(Bundle data) throws RemoteException {
                            synchronized (mService) {
                                // Early return if this session is no longer valid
                //不一致的话,回调就没有必要继续运行了
                                if (curWaitingUserSwitchCallbacks
                                        != mCurWaitingUserSwitchCallbacks) {
                                    return;
                                }
                                curWaitingUserSwitchCallbacks.remove(name);
                                // Continue switching if all callbacks have been notified
                                if (waitingCallbacksCount.decrementAndGet() == 0) {
                                    sendContinueUserSwitchLocked(uss, oldUserId, newUserId);
                                }
                            }
                        }
                    };
                    mUserSwitchObservers.getBroadcastItem(i).onUserSwitching(newUserId, callback);
                } catch (RemoteException e) {
                }
            }
        } else {
            synchronized (mService) {
                sendContinueUserSwitchLocked(uss, oldUserId, newUserId);
            }
        }
        mUserSwitchObservers.finishBroadcast();
    }
这里的mUserSwitchObservers是外界通过下面方法注册进来的,能得到user切换的消息
public void registerUserSwitchObserver(IUserSwitchObserver observer,
            String name) throws RemoteException 
所有观察者通知完毕最后会走sendContinueUserSwitchLocked
   void sendContinueUserSwitchLocked(UserState uss, int oldUserId, int newUserId) {
        mCurWaitingUserSwitchCallbacks = null;
        mHandler.removeMessages(USER_SWITCH_TIMEOUT_MSG);
        mHandler.sendMessage(mHandler.obtainMessage(ActivityManagerService.CONTINUE_USER_SWITCH_MSG,
                oldUserId, newUserId, uss));
    }

CONTINUE_USER_SWITCH_MSG

            case CONTINUE_USER_SWITCH_MSG: {
                mUserController.continueUserSwitch((UserState) msg.obj, msg.arg1, msg.arg2);
                break;
            }
void continueUserSwitch(UserState uss, int oldUserId, int newUserId) {
        Slog.d(TAG, "Continue user switch oldUser #" + oldUserId + ", newUser #" + newUserId);
        synchronized (mService) {
      //冻屏解除
            mService.mWindowManager.stopFreezingScreen();
        }
        uss.switching = false;
        mHandler.removeMessages(REPORT_USER_SWITCH_COMPLETE_MSG);
        mHandler.sendMessage(mHandler.obtainMessage(REPORT_USER_SWITCH_COMPLETE_MSG,
                newUserId, 0));
    //停用Guest或者Ephemeral用户,这两种user都是短暂的,不会往文件中存储
        stopGuestOrEphemeralUserIfBackground();
    //停用后台用户
        stopBackgroundUsersIfEnforced(oldUserId); 
    }

REPORT_USER_SWITCH_COMPLETE_MSG

            case REPORT_USER_SWITCH_COMPLETE_MSG: {
                mUserController.dispatchUserSwitchComplete(msg.arg1);
            } break;
通知mUserSwitchObservers切换完毕
消息处理大部分的工作是通知外界user的状态。

moveUserToForegroundLocked和finishUserBoot

    void moveUserToForegroundLocked(UserState uss, int oldUserId, int newUserId) {
    //设置当前要显示的Activity堆栈
        boolean homeInFront = mService.mStackSupervisor.switchUserLocked(newUserId, uss);
        if (homeInFront) {
            mService.startHomeActivityLocked(newUserId, "moveUserToForeground");
        } else {
            mService.mStackSupervisor.resumeFocusedStackTopActivityLocked();
        }
        EventLogTags.writeAmSwitchUser(newUserId);
        //针对后台user发送Intent.ACTION_USER_BACKGROUND,前台user发送Intent.ACTION_USER_FOREGROUND广播
        sendUserSwitchBroadcastsLocked(oldUserId, newUserId);
    }
两个方法分别对应前台和后台
前台user:调整当前要显示的Activity Stack,并发送Intent.ACTION_USER_FOREGROUND广播
后台user:finishUserBoot设置user的状态,并解锁user的存储。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值