Profile User启动的主要逻辑在UserController#startUser
客户端启动的逻辑为:
iActivityManager.startUserInBackground(userId);
主要调用逻辑代码如下:
UserController#startUser
boolean startUser(
final int userId,
final boolean foreground,
@Nullable IProgressListener unlockListener) {
//1.检查权限
if (mInjector.checkCallingPermission(INTERACT_ACROSS_USERS_FULL)
!= PackageManager.PERMISSION_GRANTED) {
String msg = "Permission Denial: switchUser() from pid="
+ Binder.getCallingPid()
+ ", uid=" + Binder.getCallingUid()
+ " requires " + INTERACT_ACROSS_USERS_FULL;
Slog.w(TAG, msg);
throw new SecurityException(msg);
}
Slog.i(TAG, "Starting userid:" + userId + " fg:" + foreground);
final long ident = Binder.clearCallingIdentity();
try {
final int oldUserId = getCurrentUserId();
if (oldUserId == userId) {
return true;
}
if (foreground) {
mInjector.clearAllLockedTasks("startUser");
}
final UserInfo userInfo = getUserInfo(userId);
if (userInfo == null) {
Slog.w(TAG, "No user info for user #" + userId);
return false;
}
//2.manage profile不允许前台启动
if (foreground && userInfo.isManagedProfile()) {
Slog.w(TAG, "Cannot switch to User #" + userId + ": not a full user");
return false;
}
if (foreground && mUserSwitchUiEnabled) {
mInjector.getWindowManager().startFreezingScreen(
R.anim.screen_user_exit, R.anim.screen_user_enter);
}
boolean needStart = false;
boolean updateUmState = false;
UserState uss;
// If the user we are switching to is not currently started, then
// we need to start it now.
synchronized (mLock) {
//3.创建该用户的UserState对象,用于后续启动期间,各个状态的保存和切换
//第一次执行的话,该对象为null,新创建的对象的状态处于初始状态0(BOOTING)
uss = mStartedUsers.get(userId);
if (uss == null) {
uss = new UserState(UserHandle.of(userId));
uss.mUnlockProgress.addListener(new UserProgressListener());
mStartedUsers.put(userId, uss);
updateStartedUserArrayLU();
needStart = true;
updateUmState = true;
} else if (uss.state == UserState.STATE_SHUTDOWN && !isCallingOnHandlerThread()) {
Slog.i(TAG, "User #" + userId
+ " is shutting down - will start after full stop");
mHandler.post(() -> startUser(userId, foreground, unlockListener));
return true;
}
final Integer userIdInt = userId;
mUserLru.remove(userIdInt);
mUserLru.add(userIdInt);
}
if (unlockListener != null) {
uss.mUnlockProgress.addListener(unlockListener);
}
if (updateUmState) {
mInjector.getUserManagerInternal().setUserState(userId, uss.state);
}
if (foreground) {
// Make sure the old user is no longer considering the display to be on.
mInjector.reportGlobalUsageEventLocked(UsageEvents.Event.SCREEN_NON_INTERACTIVE);
synchronized (mLock) {
mCurrentUserId = userId;
mTargetUserId = UserHandle.USER_NULL; // reset, mCurrentUserId has caught up
}
mInjector.updateUserConfiguration();
updateCurrentProfileIds();
mInjector.getWindowManager().setCurrentUser(userId, getCurrentProfileIds());
mInjector.reportCurWakefulnessUsageEvent();
// 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.
if (mUserSwitchUiEnabled) {
mInjector.getWindowManager().setSwitchingUser(true);
mInjector.getWindowManager().lockNow(null);
}
} else {
final Integer currentUserIdInt = mCurrentUserId;
updateCurrentProfileIds();
//4. 保存一个[userid,profileGroupId]数组,profileGroupId是用户创建阶段完成初始化赋值的
mInjector.getWindowManager().setCurrentProfileIds(getCurrentProfileIds());
synchronized (mLock) {
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);
mInjector.getUserManagerInternal().setUserState(userId, uss.state);
synchronized (mLock) {
updateStartedUserArrayLU();
}
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);
mInjector.getUserManagerInternal().setUserState(userId, uss.state);
synchronized (mLock) {
updateStartedUserArrayLU();
}
needStart = true;
}
//5. 发送SYSTEM_USER_START_MSG消息,回调系统指所有systemServer的onStartUser方法,通知user启动
if (uss.state == UserState.STATE_BOOTING) {
// Give user manager a chance to propagate user restrictions
// to other services and prepare app storage
mInjector.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_MS);
}
if (needStart) {
//6. Send ACTION_USER_STARTED broadcast
Intent intent = new Intent(Intent.ACTION_USER_STARTED);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
| Intent.FLAG_RECEIVER_FOREGROUND);
intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
mInjector.broadcastIntent(intent,
null, null, 0, null, null, null, AppOpsManager.OP_NONE,
null, false, false, MY_PID, SYSTEM_UID, userId);
}
if (foreground) {
moveUserToForeground(uss, oldUserId, userId);
} else {
//7. 执行Boot操作,会执行执行user启动的各个状态,并报个每个阶段的进度
finishUserBoot(uss);
}
if (needStart) {
//8.发送ACTION_USER_STARTING广播
Intent intent = new Intent(Intent.ACTION_USER_STARTING);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);//静态注册的广播(AndroidMenifest.xml中注册的)不能接受该广播
intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
mInjector.broadcastIntent(intent,
null, new IIntentReceiver.Stub() {
@Override
public void performReceive(Intent intent, int resultCode,
String data, Bundle extras, boolean ordered,
boolean sticky,
int sendingUser) throws RemoteException {
}
}, 0, null, null,
new String[]{INTERACT_ACROSS_USERS}, AppOpsManager.OP_NONE,
null, true, false, MY_PID, SYSTEM_UID, UserHandle.USER_ALL);
}
} finally {
Binder.restoreCallingIdentity(ident);
}
return true;
}
启动的流程总结如下
- 检查启动该用户的是否具有INTERACT_ACROSS_USERS_FULL权限,如果没有,直接抛出异常,应用崩溃
- 检查改profile user是否是后台启动,如果是前台启动,则直接返回false;这也是profile user和普通user的区别,不同user可用通过
switchUser方法,切换到前台用户 - 创建改用户对象的UserState,第一次启动时,该用户的状态为0(STATE_BOOTING)
- 保存主用户和该用户对应的profileGroupid的对应关系,维护一个{userid,profileGroupId}的数据结构
- 发送SYSTEM_USER_START_MSG消息,回调系统指所有systemServer的onStartUser方法,通知他们,该user启动了
- Send ACTION_USER_STARTED broadcast
该广播特性:只允许动态广播监听;接受者具有FOREGROUND优先级 - 执行finishUserBoot操作,结束Boot状态,详细过程见下面的finishUserBoot章节
- 发送ACTION_USER_STARTING广播
下面看下,以上流程的中,比较重要的阶段的代码逻辑
finishUserBoot
后台用户才会执行该操作,我们创建的profile User是一个ManagedProfile,并且必须后台启动;
改方法的主要代理逻辑是执行user启动的各个状态,并报个每个阶段的进度
将该用户的状态从STATE_BOOTING--->STATE_RUNNING_LOCKED;状态设置成功的情况系,执行以下操作
发送消息REPORT_LOCKED_BOOT_COMPLETE_MSG,告诉其他注册了IUserSwitchObserver的监听模块,该用户完成了BootComplete
发送广播ACTION_LOCKED_BOOT_COMPLETED-
执行maybeUnlockUser操作
首先,执行解锁用户存储操作
主要代码逻辑是通过Ext4Crypt.cpp的e4crypt_unlock_user_key方法,设置profile user的存储为unlock状态TODO: rename to 'install' for consistency, and take flags to know which keys to install bool e4crypt_unlock_user_key(userid_t user_id, int serial, const std::string& token_hex, const std::string& secret_hex) { LOG(DEBUG) << "e4crypt_unlock_user_key " << user_id << " serial=" << serial << " token_present=" << (token_hex != "!"); if (e4crypt_is_native()) { if (s_ce_key_raw_refs.count(user_id) != 0) { LOG(WARNING) << "Tried to unlock already-unlocked key for user " << user_id; return true; } std::string token, secret; if (!parse_hex(token_hex, &token)) return false; if (!parse_hex(secret_hex, &secret)) return false; android::vold::KeyAuthentication auth(token, secret); if (!read_and_install_user_ce_key(user_id, auth)) { LOG(ERROR) << "Couldn't read key for " << user_id; return false; } } else { // When in emulation mode, we just use chmod. However, we also // unlock directories when not in emulation mode, to bring devices // back into a known-good state. if (!emulated_unlock(android::vold::BuildDataSystemCePath(user_id), 0771) || !emulated_unlock(android::vold::BuildDataMiscCePath(user_id), 01771) || !emulated_unlock(android::vold::BuildDataMediaCePath("", user_id), 0770) || !emulated_unlock(android::vold::BuildDataUserCePath("", user_id), 0771)) { LOG(ERROR) << "Failed to unlock user " << user_id; return false; } } return true; }
其次,执行finishUserUnlocking操作
改操作的主要路逻辑如下:
1. 开始进度report,报告unlock进度5%;
2. 回调UserManager的onBeforeUnlockUser方法,
3. 将profile user的状态为从STATE_RUNNING_LOCKED--->STATE_RUNNING_UNLOCKING
4. 将profile user的状态更显到UMS的mUserStates中去
5. report profile user unlock进度20%
6. 处理SYSTEM_USER_UNLOCK_MSG消息
调用系统中所有systemServer的unlockUser方法 更改profile user的状态STATE_RUNNING_UNLOCKING-->STATE_RUNNING_UNLOCKED 将profile user的状态更显到UMS的mUserStates中去 报告unlock进度100% 发送ACTION_USER_UNLOCKED广播 发送ACTION_MANAGED_PROFILE_UNLOCKED广播 发送ACTION_USER_INITIALIZE广播 发送ACTION_BOOT_COMPLETED广播
startUser阶段,各个系统广播发送顺序
- Intent#ACTION_USER_STARTED} sent to registered receivers of the new user
- Intent#ACTION_USER_BACKGROUND} sent to registered receivers of the outgoing user and all profiles of this user. Sent only if {@code foreground} parameter is true
- Intent#ACTION_USER_FOREGROUND} sent to registered receivers of the new user and all profiles of this user. Sent only if {@code foreground} parameter is true
以上两个广播,只在该方法进行了发送。
UserController.java
void sendUserSwitchBroadcasts(int oldUserId, int newUserId) {
long ident = Binder.clearCallingIdentity();
try {
Intent intent;
if (oldUserId >= 0) {
// Send USER_BACKGROUND broadcast to all profiles of the outgoing user
List profiles = mInjector.getUserManager().getProfiles(oldUserId, false);
int count = profiles.size();
for (int i = 0; i < count; i++) {
int profileUserId = profiles.get(i).id;
intent = new Intent(Intent.ACTION_USER_BACKGROUND);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
| Intent.FLAG_RECEIVER_FOREGROUND);
intent.putExtra(Intent.EXTRA_USER_HANDLE, profileUserId);
mInjector.broadcastIntent(intent,
null, null, 0, null, null, null, AppOpsManager.OP_NONE,
null, false, false, MY_PID, SYSTEM_UID, profileUserId);
}
}
if (newUserId >= 0) {
// Send USER_FOREGROUND broadcast to all profiles of the incoming user
List profiles = mInjector.getUserManager().getProfiles(newUserId, false);
int count = profiles.size();
for (int i = 0; i < count; i++) {
int profileUserId = profiles.get(i).id;
intent = new Intent(Intent.ACTION_USER_FOREGROUND);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
| Intent.FLAG_RECEIVER_FOREGROUND);
intent.putExtra(Intent.EXTRA_USER_HANDLE, profileUserId);
mInjector.broadcastIntent(intent,
null, null, 0, null, null, null, AppOpsManager.OP_NONE,
null, false, false, MY_PID, SYSTEM_UID, profileUserId);
}
intent = new Intent(Intent.ACTION_USER_SWITCHED);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
| Intent.FLAG_RECEIVER_FOREGROUND);
intent.putExtra(Intent.EXTRA_USER_HANDLE, newUserId);
mInjector.broadcastIntent(intent,
null, null, 0, null, null,
new String[] {android.Manifest.permission.MANAGE_USERS},
AppOpsManager.OP_NONE, null, false, false, MY_PID, SYSTEM_UID,
UserHandle.USER_ALL);
}
} finally {
Binder.restoreCallingIdentity(ident);
}
}
该方法有两个调用场景
第一个:AMS#systemReady, mUserController.sendUserSwitchBroadcasts(-1, currentUserId);,因为oldUserId为-1,因此只会发送ACTION_USER_FOREGROUND广播
第二个:在startUser的时候,这个场景,只有foreground为true的时候才会发送。两个广播都会发送,因为一个user切换到前台,必然伴随另一个user切换到后台;两个广播携带的userid不一样(不是废话吗)
if (foreground) {
moveUserToForeground(uss, oldUserId, userId);-->sendUserSwitchBroadcasts
} else {
finishUserBoot(uss);
}
Intent#ACTION_USER_SWITCHED} sent to registered receivers of the new user.Sent only if {@code foreground} parameter is true
也是在sendUserSwitchBroadcasts方法中,场景同上面两个广播
//Intent#ACTION_USER_STARTING} 注释找那个标注,这个广播应该在这个位置,实际代码中实在startUser的最后阶段发送的Intent#ACTION_LOCKED_BOOT_COMPLETED} - ordered broadcast sent to receivers of the new user
Intent#ACTION_USER_UNLOCKED} - sent to registered receivers of the new user
Intent#ACTION_PRE_BOOT_COMPLETED} - ordered broadcast sent to receivers of the new user. Sent only when the user is booting after a system update.
Intent#ACTION_USER_INITIALIZE} - ordered broadcast sent to receivers of thenew user. Sent only the first time a user is starting.
Intent#ACTION_BOOT_COMPLETED} - ordered broadcast sent to receivers of the newuser. Indicates that the user has finished booting.
Intent#ACTION_USER_STARTING} - ordered broadcast sent to registered receivers of the new fg user
扩展知识
有序广播
有序广播,即从优先级别最高的广播接收器开始接收,接收完了如果没有丢弃,就下传给下一个次高优先级别的广播接收器进行处理,依次类推,直到最后。如果多个应用程序设置的优先级别相同,则谁先注册的广播,谁就可以优先接收到广播。
通过Context.sendorderBroadCast()方法来发送
sendOrderedBroadcast(intent, receiverPermission, resultReceiver, scheduler, initialCode, initialData, initialExtras)
其中的参数resultReceiver,可以自己重写一个类,作为一个最终的receive 最后都能够接收到广播,最终的receiver 不需要再清单文件里面配置,initialData可以作为传输的数据
广播可以被终止,数据传输过程中可以被修改。