UMS 与 PMS
本文承接 多用户包管理,不再重复 PackageUserState 字段,而是回答一个调用链问题:用户生命周期由谁驱动,UMS 什么时候调用 PMS,PMS 返回前完成什么,删除时为什么要等待 ActivityManager 和广播回调。
Android 17 中,UserManagerService(UMS)拥有用户记录、用户类型、限制和存储 key 生命周期;PackageManagerService(PMS)拥有包的全局记录、per-user 包状态、权限/安装器清理。两者不是互相轮询,而是 UMS 在生命周期屏障处调用 PMS 的窄接口。
1. 交互边界
| 生命周期动作 | UMS owner | PMS 入口 | 主要副作用 |
|---|---|---|---|
| 创建普通用户 | createUserInternal... | createNewUser、onNewUserCreated | per-user 包状态、DE 数据、权限默认值 |
| 转换预创建用户 | pre-created UserInfo | onNewUserCreated(..., true) | 读取/升级权限状态 |
| 删除用户 | removeUserUnchecked / finishRemoveUser | cleanUpUser | 删除包状态、权限、过滤器、安装器记录 |
| 用户 ID 列表 | UMS mUsers | getUserIds 等查询 | 展开 USER_ALL、过滤包结果 |
UMS 不把 PackageSetting 直接暴露给调用方;PMS 也不负责生成 UserInfo。这条边界让用户类型策略和包安装策略分别归属两个服务。
2. PMS 引用注入
源码文件:frameworks/base/services/core/java/com/android/server/pm/UserManagerService.java,符号:构造函数字段初始化
private final PackageManagerService mPm;
UserManagerService(Context context,
PackageManagerService pm,
UserDataPreparer userDataPreparer,
...) {
mContext = context;
mPm = pm;
mUserDataPreparer = userDataPreparer;
LocalServices.addService(
UserManagerInternal.class, mLocalService);
}UMS 持有 PMS 引用,用于生命周期回调;同时注册 UserManagerInternal,让 system_server 其他服务在同进程访问用户状态。这个依赖是有方向的:UMS 调用 PMS 的包管理接口,PMS 查询用户列表时通过注入的 UMS/内部服务读取 user IDs。
3. 创建入口
源码文件:frameworks/base/services/core/java/com/android/server/pm/UserManagerService.java,符号:createUserInternal
private UserInfo createUserInternal(
@Nullable String name,
@NonNull String userType,
@UserInfoFlag int flags,
@UserIdInt int parentId,
@Nullable String[] disallowedPackages)
throws UserManager.CheckedUserOperationException {
String restriction = UserManager.DISALLOW_ADD_USER;
if (UserManager.isUserTypeCloneProfile(userType)) {
restriction = UserManager.DISALLOW_ADD_CLONE_PROFILE;
} else if (UserManager.isUserTypeManagedProfile(userType)) {
restriction = UserManager.DISALLOW_ADD_MANAGED_PROFILE;
} else if (UserManager.isUserTypePrivateProfile(userType)) {
restriction = UserManager.DISALLOW_ADD_PRIVATE_PROFILE;
}
enforceUserRestriction(restriction,
UserHandle.getCallingUserId(),
"Cannot add user");
return createUserInternalUnchecked(name, userType,
flags, parentId, false /* preCreate */,
disallowedPackages, null /* token */);
}用户类型先决定限制键,再进入真正的创建流程。设备策略可以允许创建某类 profile,同时禁止普通 secondary user;PMS 不重新判断这些限制,只接收 UMS 已经筛选出的 userTypeInstallablePackages 和 denylist。
4. 创建时的调用顺序
源码文件:frameworks/base/services/core/java/com/android/server/pm/UserManagerService.java,符号:createUserInternalUncheckedNoTracing 的生命周期阶段
getStorageManagerInternal().createUserStorageKeys(
userId, userInfo.isEphemeral());
mUserDataPreparer.prepareUserData(
userInfo, StorageManager.FLAG_STORAGE_DE);
getLockSettingsInternal().createNewUser(
userId, userInfo.serialNumber);
Set<String> installable =
mSystemPackageInstaller
.getInstallablePackagesForUserType(userType);
mPm.createNewUser(userId, installable,
disallowedPackages);顺序不是装饰性的:先创建用户存储 key,再准备 DE,再初始化 lock settings,最后让 PMS 建立 per-user 包状态和 DE app data。CE 数据延后到用户解锁,避免在 CE key 尚未持久化时创建可访问目录。
源码文件:frameworks/base/services/core/java/com/android/server/pm/UserManagerService.java,符号:用户创建收尾
userInfo.partial = false;
UserManager.invalidateCacheOnUserListChange();
synchronized (mPackagesLock) {
writeUserLP(userData);
}
updateUserIds();
mPm.onNewUserCreated(userId,
false /* convertedFromPreCreated */);
applyDefaultUserSettings(userTypeDetails, userId);
setDefaultCrossProfileIntentFilters(
userId, userTypeDetails, restrictions, parentId);PMS 的 createNewUser 完成包状态后,UMS 才把用户从 partial 状态写成完整用户,并调用 onNewUserCreated 初始化权限默认值。也就是说,PMS 包状态创建和 UMS 用户记录落盘是两个阶段,不是一个跨服务事务。
5. 预创建用户转换
Android 17 可以先创建预创建用户,再把它转换为真正用户。转换路径不会重新调用 PMS.createNewUser,因为预创建阶段已经准备了用户和包状态。
源码文件:frameworks/base/services/core/java/com/android/server/pm/UserManagerService.java,符号:pre-created user conversion
preCreatedUser.name = name;
preCreatedUser.flags = newFlags;
preCreatedUser.preCreated = false;
preCreatedUser.convertedFromPreCreated = true;
preCreatedUser.creationTime = getCreationTime();
synchronized (mPackagesLock) {
writeUserLP(preCreatedUserData);
writeUserListLP();
}
updateUserIds();
Binder.withCleanCallingIdentity(() -> {
mPm.onNewUserCreated(preCreatedUser.id,
true /* convertedFromPreCreated */);
dispatchUserAdded(preCreatedUser, token);
});convertedFromPreCreated=true 让 PMS 的权限初始化分支尝试读取已有权限状态;否则普通创建会授予默认权限。这里的布尔参数不是日志信息,而是影响权限数据迁移的状态输入。
6. PMS 的创建动作
源码文件:frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java,符号:createNewUser
void createNewUser(int userId,
@Nullable Set<String> installablePackages,
String[] disallowedPackages) {
try (PackageManagerTracedLock lock =
mInstallLock.acquireLock()) {
mSettings.createNewUserLI(this, mInstaller,
userId, installablePackages,
disallowedPackages);
}
synchronized (mLock) {
scheduleWritePackageRestrictions(userId);
scheduleWritePackageListLocked(userId);
mAppsFilter.onUserCreated(
snapshotComputer(), userId);
}
}PMS 只在 mInstallLock 下修改包状态并构造 installd 批次;AppsFilter.onUserCreated 和异步持久化在包状态阶段之后发生。UMS 的用户类型 allowlist 在进入 PMS 前已经变成集合参数,PMS 不知道其策略来源。
7. 权限初始化回调
源码文件:frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java,符号:onNewUserCreated
void onNewUserCreated(int userId,
boolean convertedFromPreCreated) {
if (!convertedFromPreCreated
|| !readPermissionStateForUser(userId)) {
mPermissionManager.onUserCreated(userId);
mLegacyPermissionManager
.grantDefaultPermissions(userId);
mPermissionManager
.setDefaultPermissionGrantFingerprint(
Build.FINGERPRINT, userId);
mDomainVerificationManager.clearUser(userId);
mInstallerService.onUserAdded(userId);
}
}普通新用户直接初始化权限和默认授权指纹;预创建用户若能读取有效权限状态,PMS 会跳过整套默认授权,否则继续初始化。DomainVerificationManager.clearUser 和 InstallerService.onUserAdded 与包状态同属于 PMS 收尾,但不是 Settings.createNewUserLI 的一部分。
8. 删除的前置阶段
源码文件:frameworks/base/services/core/java/com/android/server/pm/UserManagerService.java,符号:removeUserUnchecked
final long ident = Binder.clearCallingIdentity();
try {
synchronized (mPackagesLock) {
synchronized (mUsersLock) {
int result = getUserRemovabilityLockedLU(userId);
if (result != UserManager
.REMOVE_RESULT_USER_IS_REMOVABLE) {
return UserManager
.isRemoveResultSuccessful(result);
}
userData = mUsers.get(userId);
addRemovingUserIdLU(userId);
}
userData.info.partial = true;
addUserInfoFlags(userData.info,
UserInfo.FLAG_DISABLED);
writeUserLP(userData);
}删除先验证 system user、device owner、最后管理员等不可删除条件,再把用户标记为 removing/partial/disabled。此时用户已经不应继续出现在 profile 查询结果,但数据和 PMS 状态尚未删除,系统仍需要停止该用户上的进程。
int res = ActivityManager.getService()
.stopUserWithCallback(userId,
new IStopUserCallback.Stub() {
@Override
public void userStopped(int id) {
finishRemoveUser(id);
}
@Override
public void userStopAborted(int id) {
// 删除流程保持未完成,等待后续处理。
}
});
return res == ActivityManager.USER_OP_SUCCESS;UMS 不会在用户仍运行时直接调用 PMS 清理。只有 ActivityManager 确认 user stopped,才进入 finishRemoveUser;停止失败或被中止时,PMS 的 cleanUpUser 不应提前执行。
9. 删除回调屏障
源码文件:frameworks/base/services/core/java/com/android/server/pm/UserManagerService.java,符号:finishRemoveUser、removeUserState
for (UserLifecycleListener listener
: mUserLifecycleListeners) {
listener.onUserRemoved(user);
}
Intent removedIntent = new Intent(
Intent.ACTION_USER_REMOVED);
removedIntent.addFlags(
Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
getActivityManagerInternal()
.broadcastIntentWithCallback(removedIntent,
callback, new String[] {
android.Manifest.permission.MANAGE_USERS
}, UserHandle.USER_ALL, ...);UMS 先通知内部生命周期监听器,再广播 ACTION_USER_REMOVED,等待广播回调后才调用 removeUserState。这给其他服务一个机会清理自己的 user state;PMS 的清理不是最早发生的动作。
源码文件:frameworks/base/services/core/java/com/android/server/pm/UserManagerService.java,符号:removeUserState
getLockSettingsInternal().removeUser(userId);
getStorageManagerInternal().destroyUserStorageKeys(userId);
mPm.cleanUpUser(this, userId);
mUserDataPreparer.destroyUserData(userId,
StorageManager.FLAG_STORAGE_DE
| StorageManager.FLAG_STORAGE_CE);
synchronized (mUsersLock) {
removeUserDataLU(userId);
getActivityManagerInternal().onUserRemoved(userId);
}删除顺序也有资源约束:先清 lock settings,再销毁 CE/DE key,调用 PMS 清理包状态,然后删除用户数据目录,最后从 UMS 用户列表移除。PMS 接到回调时,用户元数据仍然存在,但存储 key 已不可用或正在被销毁;因此 PMS 的 cleanUpUser 不能假设自己负责删除 CE/DE 文件。
10. 删除时 PMS 清理
源码文件:frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java,符号:cleanUpUser
void cleanUpUser(UserManagerService userManager,
int userId) {
synchronized (mLock) {
synchronized (mDirtyUsers) {
mDirtyUsers.remove(userId);
}
mUserNeedsBadging.delete(userId);
mDeletePackageHelper
.removeUnusedPackagesLPw(userManager, userId);
mSettings.removeUserLPw(userId);
mPendingBroadcasts.remove(userId);
mAppsFilter.onUserDeleted(
snapshotComputer(), userId);
mPermissionManager.onUserRemoved(userId);
mInstallerService.onUserRemoved(userId);
}
mInstantAppRegistry.onUserRemoved(userId);
mPackageMonitorCallbackHelper.onUserRemoved(userId);
}PMS 清理包含四类状态:包的 user state、未使用包、AppsFilter/权限/Installer 的 user 记录,以及 instant app/package monitor 的回调状态。真正的用户目录销毁仍由 UMS 的 UserDataPreparer 完成。
11. 用户 ID 查询方向
UMS → PMS 是生命周期回调,PMS → UMS 更多是查询当前用户集合。
源码文件:frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java,符号:resolveUserIds
int[] resolveUserIds(@CanBeALL int userId) {
return (userId == UserHandle.USER_ALL)
? mUserManager.getUserIds()
: new int[]{userId};
}PMS 在清应用数据、删除包、同步状态等路径中使用这个展开。UMS 的 getUserIds() 是当前用户列表的 owner;PMS 不能从 PackageSetting 的 user state 反推“系统存在的所有用户”,因为没有状态记录的 user 也可能真实存在。
12. 失败与恢复
| 阶段 | 失败/中断 | 保护机制 |
|---|---|---|
| 创建用户 | 用户类型无效或数量超限 | UMS 在调用 PMS 前拒绝 |
| 创建存储 | DE key/目录准备失败 | UMS 不进入完整用户状态 |
| PMS 创建包状态 | installd 批次异常 | 记录 warning,保留可重建状态 |
| 权限初始化 | 预创建状态读取失败 | onNewUserCreated 重新授予默认权限 |
| 删除用户 | ActivityManager stop aborted | 不调用最终 PMS 清理 |
| 删除回调 | 进程仍需收到 USER_REMOVED | 广播 callback 后再销毁数据 |
| PMS 清理 | 某个子系统失败 | 其他 user 状态和组件继续按 owner 清理 |
用户生命周期跨越 UMS、PMS、ActivityManager、StorageManager、LockSettings 和 PermissionManager,不存在一个 Java 方法包住全部事务。源码采用 partial/disabled 标志、停止回调、广播屏障和可重复清理来承受中断。
13. 阅读检查
读者可以沿下面两条路径复述源码:
- 创建:UMS 校验限制 → 创建 storage keys/DE →
mPm.createNewUser→ PMS 设置 per-user 包状态 →mPm.onNewUserCreated→ 默认权限和跨 profile 设置。 - 删除:UMS 标记 partial/disabled → ActivityManager 停止用户 →
ACTION_USER_REMOVED回调 → 销毁 storage keys →mPm.cleanUpUser→ 删除 CE/DE 数据和用户元数据。
然后判断:PMS 是否负责创建 UserInfo?普通用户创建时 CE 数据是否已经可用?删除用户时 PMS 是否先于 ActivityManager 停止用户?三个答案分别是“否”“否”“否”。这些边界正是 UMS 与 PMS 之间最重要的所有权契约。
