Skip to content

UMS 与 PMS

追踪 UserManagerService 与 PackageManagerService 在用户创建、预创建转换、删除和状态清理中的真实交互。

基于android-17.0.0_r1
AndroidPMSUserManagerServiceMultiUser

UMS 与 PMS ​

本文承接 多用户包管理,不再重复 PackageUserState 字段,而是回答一个调用链问题:用户生命周期由谁驱动,UMS 什么时候调用 PMS,PMS 返回前完成什么,删除时为什么要等待 ActivityManager 和广播回调。

Android 17 中,UserManagerService(UMS)拥有用户记录、用户类型、限制和存储 key 生命周期;PackageManagerService(PMS)拥有包的全局记录、per-user 包状态、权限/安装器清理。两者不是互相轮询,而是 UMS 在生命周期屏障处调用 PMS 的窄接口。

1. 交互边界 ​

生命周期动作UMS ownerPMS 入口主要副作用
创建普通用户createUserInternal...createNewUser、onNewUserCreatedper-user 包状态、DE 数据、权限默认值
转换预创建用户pre-created UserInfoonNewUserCreated(..., true)读取/升级权限状态
删除用户removeUserUnchecked / finishRemoveUsercleanUpUser删除包状态、权限、过滤器、安装器记录
用户 ID 列表UMS mUsersgetUserIds 等查询展开 USER_ALL、过滤包结果

UMS 不把 PackageSetting 直接暴露给调用方;PMS 也不负责生成 UserInfo。这条边界让用户类型策略和包安装策略分别归属两个服务。

2. PMS 引用注入 ​

源码文件:frameworks/base/services/core/java/com/android/server/pm/UserManagerService.java,符号:构造函数字段初始化

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

java
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 的生命周期阶段

java
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,符号:用户创建收尾

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

java
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

java
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

java
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

java
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 状态尚未删除,系统仍需要停止该用户上的进程。

java
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

java
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

java
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

java
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

java
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. 阅读检查 ​

读者可以沿下面两条路径复述源码:

  1. 创建:UMS 校验限制 → 创建 storage keys/DE → mPm.createNewUser → PMS 设置 per-user 包状态 → mPm.onNewUserCreated → 默认权限和跨 profile 设置。
  2. 删除:UMS 标记 partial/disabled → ActivityManager 停止用户 → ACTION_USER_REMOVED 回调 → 销毁 storage keys → mPm.cleanUpUser → 删除 CE/DE 数据和用户元数据。

然后判断:PMS 是否负责创建 UserInfo?普通用户创建时 CE 数据是否已经可用?删除用户时 PMS 是否先于 ActivityManager 停止用户?三个答案分别是“否”“否”“否”。这些边界正是 UMS 与 PMS 之间最重要的所有权契约。