本文主要是介绍Android多用户之UserManagerService源码分析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
Android可以支持多个用户使用系统,通常第一个在系统中注册的用户将默认成为系统管理员。不同用户的设置各不相同,并且不同用户安装的应用及应用数据也不相同。但是系统中和硬件相关的设置则是共用的,如网络设置等。
用户切换后前面用户运行的后台进程还可以继续运行,这样进行用户切换时无须中断一些后台进行的耗时操作(如下载)。
管理用户的系统服务--UserManagerService
UserManagerService的主要功能是创建和删除用户,以及查询用户信息。
1.在PackageManagerService中进行初始化
- final ArrayMap<String, PackageParser.Package> mPackages =
- new ArrayMap<String, PackageParser.Package>();
- public PackageManagerService(Context context, Installer installer,
- boolean factoryTest, boolean onlyCore) {
- ...
- synchronized (mInstallLock) {
- // writer
- synchronized (mPackages) {
- ...
- sUserManager = new UserManagerService(context, this, mPackages);
- ...
- } // synchronized (mPackages)
- } // synchronized (mInstallLock)
- ...
- }
- @Override
- public void systemReady() {
- ...
- sUserManager.systemReady();
- ...
- }
UserManagerService的构造方法如下:
- UserManagerService(Context context, PackageManagerService pm, Object packagesLock) {
- this(context, pm, packagesLock, Environment.getDataDirectory());
- }
调用了另一个构造方法,并多传递了一个参数:/data目录
- private static final String USER_INFO_DIR = "system" + File.separator + "users";
- private UserManagerService(Context context, PackageManagerService pm,
- Object packagesLock, File dataDir) {
- mContext = context;
- mPm = pm;
- mPackagesLock = packagesLock;
- mHandler = new MainHandler();
- synchronized (mPackagesLock) {
- // /data/system/users
- mUsersDir = new File(dataDir, USER_INFO_DIR);
- mUsersDir.mkdirs();
- // Make zeroth user directory, for services to migrate their files to that location
- File userZeroDir = new File(mUsersDir, String.valueOf(UserHandle.USER_SYSTEM));
- // 创建第一个用户目录:/data/system/users/0
- userZeroDir.mkdirs();
- // 设置访问文件的权限
- FileUtils.setPermissions(mUsersDir.toString(),
- FileUtils.S_IRWXU | FileUtils.S_IRWXG | FileUtils.S_IROTH | FileUtils.S_IXOTH,
- -1, -1);
- // /data/system/users/userlist.xml
- mUserListFile = new File(mUsersDir, USER_LIST_FILENAME);
- // 初始化来宾账户的默认限制条件
- initDefaultGuestRestrictions();
- // 从/data/system/users/userlist.xml文件读取用户信息
- readUserListLP();
- sInstance = this;
- }
- mLocalService = new LocalService();
- LocalServices.addService(UserManagerInternal.class, mLocalService);
- mLockPatternUtils = new LockPatternUtils(mContext);
- mUserStates.put(UserHandle.USER_SYSTEM, UserState.STATE_BOOTING);
- }
- private final Bundle mGuestRestrictions = new Bundle();
- // 初始化来宾账户的默认限制条件
- private void initDefaultGuestRestrictions() {
- synchronized (mGuestRestrictions) {
- if (mGuestRestrictions.isEmpty()) {
- // "no_config_wifi",不允许配置WiFi
- mGuestRestrictions.putBoolean(UserManager.DISALLOW_CONFIG_WIFI, true);
- // "no_install_unknown_sources",不允许安装未知来源的应用
- mGuestRestrictions.putBoolean(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, true);
- // "no_outgoing_calls",不允许呼叫电话
- mGuestRestrictions.putBoolean(UserManager.DISALLOW_OUTGOING_CALLS, true);
- // "no_sms",不允许收发短信
- mGuestRestrictions.putBoolean(UserManager.DISALLOW_SMS, true);
- }
- }
- }
先看下/data/system/users/userlist.xml文件的内容,再分析读取过程,文件内容如下:
- <?xml version='1.0' encoding='utf-8' standalone='yes' ?>
- <users nextSerialNumber="10" version="5">
- <guestRestrictions>
- <restrictions no_config_wifi="true" no_outgoing_calls="true" no_sms="true" />
- </guestRestrictions>
- <user id="0" />
- </users>
- // 从/data/system/users/userlist.xml文件读取用户信息
- private final SparseArray<UserData> mUsers = new SparseArray<>();
- private void readUserListLP() {
- // 如果文件不存在,则创建管理员用户并返回
- if (!mUserListFile.exists()) {
- fallbackToSingleUserLP();
- return;
- }
- FileInputStream fis = null;
- AtomicFile userListFile = new AtomicFile(mUserListFile);
- try {
- fis = userListFile.openRead();
- XmlPullParser parser = Xml.newPullParser();
- parser.setInput(fis, StandardCharsets.UTF_8.name());
- int type;
- while ((type = parser.next()) != XmlPullParser.START_TAG
- && type != XmlPullParser.END_DOCUMENT) {
- // Skip
- }
- if (type != XmlPullParser.START_TAG) {
- Slog.e(LOG_TAG, "Unable to read user list");
- // 如果文件异常,则创建管理员用户并返回
- fallbackToSingleUserLP();
- return;
- }
- mNextSerialNumber = -1;
- // 解析文件
- if (parser.getName().equals(TAG_USERS)) {
- String lastSerialNumber = parser.getAttributeValue(null, ATTR_NEXT_SERIAL_NO);
- if (lastSerialNumber != null) {
- mNextSerialNumber = Integer.parseInt(lastSerialNumber);
- }
- String versionNumber = parser.getAttributeValue(null, ATTR_USER_VERSION);
- if (versionNumber != null) {
- mUserVersion = Integer.parseInt(versionNumber);
- }
- }
- final Bundle newDevicePolicyGlobalUserRestrictions = new Bundle();
- while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
- if (type == XmlPullParser.START_TAG) {
- final String name = parser.getName();
- if (name.equals(TAG_USER)) {
- String id = parser.getAttributeValue(null, ATTR_ID);
- // 初始化UserData对象保存从 /data/system/users/${id}.xml 文件中读取到的用户信息
- UserData userData = readUserLP(Integer.parseInt(id));
- if (userData != null) {
- synchronized (mUsersLock) {
- // 把解析到的用户信息保存到mUsers中
- mUsers.put(userData.info.id, userData);
- if (mNextSerialNumber < 0
- || mNextSerialNumber <= userData.info.id) {
- mNextSerialNumber = userData.info.id + 1;
- }
- }
- }
- } else if (name.equals(TAG_GUEST_RESTRICTIONS)) {
- while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
- && type != XmlPullParser.END_TAG) {
- if (type == XmlPullParser.START_TAG) {
- if (parser.getName().equals(TAG_RESTRICTIONS)) {
- synchronized (mGuestRestrictions) {
- UserRestrictionsUtils
- .readRestrictions(parser, mGuestRestrictions);
- }
- } else if (parser.getName().equals(TAG_DEVICE_POLICY_RESTRICTIONS)
- ) {
- UserRestrictionsUtils.readRestrictions(parser,
- newDevicePolicyGlobalUserRestrictions);
- }
- break;
- }
- }
- } else if (name.equals(TAG_GLOBAL_RESTRICTION_OWNER_ID)) {
- String ownerUserId = parser.getAttributeValue(null, ATTR_ID);
- if (ownerUserId != null) {
- mGlobalRestrictionOwnerUserId = Integer.parseInt(ownerUserId);
- }
- }
- }
- }
- synchronized (mRestrictionsLock) {
- mDevicePolicyGlobalUserRestrictions = newDevicePolicyGlobalUserRestrictions;
- }
- // 解析完文件后,更新用户ID
- updateUserIds();
- // 如果有必要,则升级Version
- upgradeIfNecessaryLP();
- } catch (IOException | XmlPullParserException e) {
- fallbackToSingleUserLP();
- } finally {
- IoUtils.closeQuietly(fis);
- }
- }
- // 创建管理员用户
- private void fallbackToSingleUserLP() {
- int flags = UserInfo.FLAG_INITIALIZED;
- // In split system user mode, the admin and primary flags are assigned to the first human
- // user.
- if (!UserManager.isSplitSystemUser()) {
- flags |= UserInfo.FLAG_ADMIN | UserInfo.FLAG_PRIMARY;
- }
- // Create the system user
- UserInfo system = new UserInfo(UserHandle.USER_SYSTEM, null, null, flags);
- UserData userData = new UserData();
- userData.info = system;
- synchronized (mUsersLock) {
- mUsers.put(system.id, userData);
- }
- mNextSerialNumber = MIN_USER_ID;
- mUserVersion = USER_VERSION;
- Bundle restrictions = new Bundle();
- synchronized (mRestrictionsLock) {
- mBaseUserRestrictions.append(UserHandle.USER_SYSTEM, restrictions);
- }
- // 更新用户ID
- updateUserIds();
- // 初始化来宾账户的默认限制条件
- initDefaultGuestRestrictions();
- /*
- * 把用户信息写到 /data/system/users/${id}.xml文件中,简单的写文件,不再看源码
- * Writes the user file in this format:
- *
- * <user flags="20039023" id="0">
- * <name>Primary</name>
- * </user>
- */
- writeUserLP(userData);
- /*
- * 把用户信息写到 /data/system/users/userlist.xml文件中
- * Writes the user list file in this format:
- *
- * <users nextSerialNumber="3">
- * <user id="0"></user>
- * <user id="2"></user>
- * </users>
- */
- writeUserListLP();
- }
这样UserManagerService的初始化工作就完成了,主要的工作就是解析userlist.xml文件,并创建了mUsers列表中的UserData对象。
2.UserData的定义
- private static class UserData {
- // Basic user information and properties
- UserInfo info;
- // Account name used when there is a strong association between a user and an account
- String account;
- // Account information for seeding into a newly created user. This could also be
- // used for login validation for an existing user, for updating their credentials.
- // In the latter case, data may not need to be persisted as it is only valid for the
- // current login session.
- String seedAccountName;
- String seedAccountType;
- PersistableBundle seedAccountOptions;
- // Whether to perist the seed account information to be available after a boot
- boolean persistSeedData;
- void clearSeedAccountData() {
- seedAccountName = null;
- seedAccountType = null;
- seedAccountOptions = null;
- persistSeedData = false;
- }
- }
- public class UserInfo implements Parcelable {
- /** 8 bits for user type 用户类型*/
- public static final int FLAG_MASK_USER_TYPE = 0x000000FF;
- /**
- * *************************** NOTE ***************************
- * These flag values CAN NOT CHANGE because they are written
- * directly to storage.
- */
- /**
- * Primary user. Only one user can have this flag set. It identifies the first human user
- * on a device.主用户标志,通常是第一个ID为0的用户
- */
- public static final int FLAG_PRIMARY = 0x00000001;
- /**
- * User with administrative privileges. Such a user can create and
- * delete users.admin用户标志,有此标志才有创建和删除用户的权限
- */
- public static final int FLAG_ADMIN = 0x00000002;
- /**
- * Indicates a guest user that may be transient.guest用户标志
- */
- public static final int FLAG_GUEST = 0x00000004;
- /**
- * Indicates the user has restrictions in privileges, in addition to those for normal users.
- * Exact meaning TBD. For instance, maybe they can't install apps or administer WiFi access pts.
- * 标志权限受限的用户,具体受限功能未定
- */
- public static final int FLAG_RESTRICTED = 0x00000008;
- /**
- * Indicates that this user has gone through its first-time initialization.
- * 标志该用户是否已经初始化
- */
- public static final int FLAG_INITIALIZED = 0x00000010;
- /**
- * Indicates that this user is a profile of another user, for example holding a users
- * corporate data.标志该UserInfo是另一个用户的profile
- */
- public static final int FLAG_MANAGED_PROFILE = 0x00000020;
- /**
- * Indicates that this user is disabled.标志该用户已被禁止
- *
- * <p>Note: If an ephemeral user is disabled, it shouldn't be later re-enabled. Ephemeral users
- * are disabled as their removal is in progress to indicate that they shouldn't be re-entered.
- */
- public static final int FLAG_DISABLED = 0x00000040;
- public static final int FLAG_QUIET_MODE = 0x00000080;
- /**
- * Indicates that this user is ephemeral. I.e. the user will be removed after leaving
- * the foreground.
- */
- public static final int FLAG_EPHEMERAL = 0x00000100;
- public static final int NO_PROFILE_GROUP_ID = UserHandle.USER_NULL;
- public int id; // 用户ID
- public int serialNumber; // 用户的序列号,不会重复
- public String name; // 用户名称
- public String iconPath; // 用户头像路径
- public int flags; // 用户标志
- public long creationTime; // 创建用户的时间
- public long lastLoggedInTime; // 最后一次登录的时间
- public String lastLoggedInFingerprint; // 最后一次用指纹登录的时间
- public int profileGroupId; // 用户profile的group ID
- public int restrictedProfileParentId;
- /** User is only partially created. */
- public boolean partial; // true表示该用户没有创建完成
- public boolean guestToRemove;
- ...
- }
3.添加用户
UserManagerService中添加用户的方法是createUser():
- @Override
- public UserInfo createUser(String name, int flags) {
- if (DBG) Slog.i(LOG_TAG, "createUser name " + name);
- // 检查添加用户的权限
- checkManageOrCreateUsersPermission(flags);
- return createUserInternal(name, flags, UserHandle.USER_NULL);
- }
- private UserInfo createUserInternal(String name, int flags, int parentId) {
- // 如果没有添加用户的权限则返回null
- if (hasUserRestriction(UserManager.DISALLOW_ADD_USER, UserHandle.getCallingUserId())) {
- Log.w(LOG_TAG, "Cannot add user. DISALLOW_ADD_USER is enabled.");
- return null;
- }
- return createUserInternalUnchecked(name, flags, parentId);
- }
- private UserInfo createUserInternalUnchecked(String name, int flags, int parentId) {
- // 如果是一个低内存设备,则返回null
- if (ActivityManager.isLowRamDeviceStatic()) {
- return null;
- }
- final boolean isGuest = (flags & UserInfo.FLAG_GUEST) != 0;
- final boolean isManagedProfile = (flags & UserInfo.FLAG_MANAGED_PROFILE) != 0;
- final boolean isRestricted = (flags & UserInfo.FLAG_RESTRICTED) != 0;
- final long ident = Binder.clearCallingIdentity();
- UserInfo userInfo;
- UserData userData;
- final int userId;
- try {
- synchronized (mPackagesLock) {
- UserData parent = null;
- if (parentId != UserHandle.USER_NULL) {
- synchronized (mUsersLock) {
- // 根据userId获取UserData信息
- parent = getUserDataLU(parentId);
- }
- if (parent == null) return null;
- }
- // 判断是否可以添加更多profile
- if (isManagedProfile && !canAddMoreManagedProfiles(parentId, false)) {
- Log.e(LOG_TAG, "Cannot add more managed profiles for user " + parentId);
- return null;
- }
- // 判断是否达到用户上限
- if (!isGuest && !isManagedProfile && isUserLimitReached()) {
- // If we're not adding a guest user or a managed profile and the limit has
- // been reached, cannot add a user.
- return null;
- }
- // If we're adding a guest and there already exists one, bail.
- // 如果创建的是guest用户且guest用户已经存在则返回
- if (isGuest && findCurrentGuestUser() != null) {
- return null;
- }
- // In legacy mode, restricted profile's parent can only be the owner user
- if (isRestricted && !UserManager.isSplitSystemUser()
- && (parentId != UserHandle.USER_SYSTEM)) {
- Log.w(LOG_TAG, "Cannot add restricted profile - parent user must be owner");
- return null;
- }
- if (isRestricted && UserManager.isSplitSystemUser()) {
- if (parent == null) {
- Log.w(LOG_TAG, "Cannot add restricted profile - parent user must be "
- + "specified");
- return null;
- }
- if (!parent.info.canHaveProfile()) {
- Log.w(LOG_TAG, "Cannot add restricted profile - profiles cannot be "
- + "created for the specified parent user id " + parentId);
- return null;
- }
- }
- if (!UserManager.isSplitSystemUser() && (flags & UserInfo.FLAG_EPHEMERAL) != 0) {
- Log.e(LOG_TAG,
- "Ephemeral users are supported on split-system-user systems only.");
- return null;
- }
- // In split system user mode, we assign the first human user the primary flag.
- // And if there is no device owner, we also assign the admin flag to primary user.
- if (UserManager.isSplitSystemUser()
- && !isGuest && !isManagedProfile && getPrimaryUser() == null) {
- flags |= UserInfo.FLAG_PRIMARY;
- synchronized (mUsersLock) {
- if (!mIsDeviceManaged) {
- flags |= UserInfo.FLAG_ADMIN;
- }
- }
- }
- // 获取下一个可用的userId
- userId = getNextAvailableId();
- // 创建/data/system/users/userId文件夹
- Environment.getUserSystemDirectory(userId).mkdirs();
- boolean ephemeralGuests = Resources.getSystem()
- .getBoolean(com.android.internal.R.bool.config_guestUserEphemeral);
- synchronized (mUsersLock) {
- // Add ephemeral flag to guests/users if required. Also inherit it from parent.
- if ((isGuest && ephemeralGuests) || mForceEphemeralUsers
- || (parent != null && parent.info.isEphemeral())) {
- flags |= UserInfo.FLAG_EPHEMERAL;
- }
- // 初始化新用户
- userInfo = new UserInfo(userId, name, null, flags);
- userInfo.serialNumber = mNextSerialNumber++;
- long now = System.currentTimeMillis();
- userInfo.creationTime = (now > EPOCH_PLUS_30_YEARS) ? now : 0;
- // 设置partial变量为true,表示用户还没有创建完成
- userInfo.partial = true;
- userInfo.lastLoggedInFingerprint = Build.FINGERPRINT;
- userData = new UserData();
- userData.info = userInfo;
- mUsers.put(userId, userData);
- }
- // 保存用户信息
- writeUserLP(userData);
- writeUserListLP();
- if (parent != null) {
- if (isManagedProfile) {
- if (parent.info.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID) {
- parent.info.profileGroupId = parent.info.id;
- writeUserLP(parent);
- }
- userInfo.profileGroupId = parent.info.profileGroupId;
- } else if (isRestricted) {
- if (parent.info.restrictedProfileParentId == UserInfo.NO_PROFILE_GROUP_ID) {
- parent.info.restrictedProfileParentId = parent.info.id;
- writeUserLP(parent);
- }
- userInfo.restrictedProfileParentId = parent.info.restrictedProfileParentId;
- }
- }
- }
- // 为新建用户准备存储区域
- final StorageManager storage = mContext.getSystemService(StorageManager.class);
- storage.createUserKey(userId, userInfo.serialNumber, userInfo.isEphemeral());
- mPm.prepareUserData(userId, userInfo.serialNumber,
- StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE);
- // 保存所有安装应用在新建用户目录下的安装状态
- mPm.createNewUser(userId);
- // 创建完新用户后修改partial变量为false,表示用户创建完成,并重新保存用户信息
- userInfo.partial = false;
- synchronized (mPackagesLock) {
- writeUserLP(userData);
- }
- updateUserIds();
- Bundle restrictions = new Bundle();
- if (isGuest) {
- synchronized (mGuestRestrictions) {
- restrictions.putAll(mGuestRestrictions);
- }
- }
- synchronized (mRestrictionsLock) {
- mBaseUserRestrictions.append(userId, restrictions);
- }
- // 发送成功添加新用户的广播
- Intent addedIntent = new Intent(Intent.ACTION_USER_ADDED);
- addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
- mContext.sendBroadcastAsUser(addedIntent, UserHandle.ALL,
- android.Manifest.permission.MANAGE_USERS);
- MetricsLogger.count(mContext, isGuest ? TRON_GUEST_CREATED : TRON_USER_CREATED, 1);
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- return userInfo;
- }
- // 根据userId获取UserData信息
- private UserData getUserDataLU(int userId) {
- final UserData userData = mUsers.get(userId);
- // If it is partial and not in the process of being removed, return as unknown user.
- if (userData != null && userData.info.partial && !mRemovingUserIds.get(userId)) {
- return null;
- }
- return userData;
- }
- final Settings mSettings;
- /** Called by UserManagerService */
- // 保存所有安装应用在新建用户目录下的安装状态
- void createNewUser(int userId) {
- synchronized (mInstallLock) {
- // 把所有已安装的应用数据拷贝到新建用户对应目录(/data/user/0/)下
- mSettings.createNewUserLI(this, mInstaller, userId);
- }
- synchronized (mPackages) {
- // 在/data/system/users/0/package-restrictions.xml文件中保存应用的限制信息
- scheduleWritePackageRestrictionsLocked(userId);
- // 更新/data/system/packages.list文件
- scheduleWritePackageListLocked(userId);
- // 保存默认浏览器应用,并更新/data/system/users/0/package-restrictions.xml文件
- applyFactoryDefaultBrowserLPw(userId);
- // 主要域名验证
- primeDomainVerificationsLPw(userId);
- }
- }
- /** Map from package name to settings 每个包名对应一个PackageSetting*/
- final ArrayMap<String, PackageSetting> mPackages = new ArrayMap<>();
- // 把所有已安装的系统应用数据拷贝到新建用户对应目录下
- void createNewUserLI(@NonNull PackageManagerService service, @NonNull Installer installer,
- int userHandle) {
- String[] volumeUuids;
- String[] names;
- int[] appIds;
- String[] seinfos;
- int[] targetSdkVersions;
- int packagesCount;
- synchronized (mPackages) {
- // 从map中获取出所有的settings
- Collection<PackageSetting> packages = mPackages.values();
- packagesCount = packages.size();
- volumeUuids = new String[packagesCount];
- names = new String[packagesCount];
- appIds = new int[packagesCount];
- seinfos = new String[packagesCount];
- targetSdkVersions = new int[packagesCount];
- Iterator<PackageSetting> packagesIterator = packages.iterator();
- // 遍历所有的PackageSetting
- for (int i = 0; i < packagesCount; i++) {
- PackageSetting ps = packagesIterator.next();
- if (ps.pkg == null || ps.pkg.applicationInfo == null) {
- continue;
- }
- // Only system apps are initially installed.初始化时只安装系统应用
- /** M: [Operator] Operator package should also be installed @{ */
- boolean curInstalledStatus = ps.isSystem()
- || (ps.pkgFlagsEx & ApplicationInfo.FLAG_EX_OPERATOR) != 0;
- // 设置每一个应用在新创建用户下的安装状态,系统应用为true
- ps.setInstalled(curInstalledStatus, userHandle);
- /** @} */
- // Need to create a data directory for all apps under this user. Accumulate all
- // required args and call the installer after mPackages lock has been released
- volumeUuids[i] = ps.volumeUuid;
- names[i] = ps.name;
- appIds[i] = ps.appId;
- seinfos[i] = ps.pkg.applicationInfo.seinfo;
- targetSdkVersions[i] = ps.pkg.applicationInfo.targetSdkVersion;
- }
- }
- for (int i = 0; i < packagesCount; i++) {
- if (names[i] == null) {
- continue;
- }
- // TODO: triage flags!
- final int flags = StorageManager.FLAG_STORAGE_CE | StorageManager.FLAG_STORAGE_DE;
- try {
- // 在新建用户目录(/data/user/0/)下创建每个应用的数据目录(包名命名的文件夹)
- installer.createAppData(volumeUuids[i], names[i], userHandle, flags, appIds[i],
- seinfos[i], targetSdkVersions[i]);
- } catch (InstallerException e) {
- Slog.w(TAG, "Failed to prepare app data", e);
- }
- }
- synchronized (mPackages) {
- // 解析"etc/preferred-apps"目录下所有XML文件,XML文件中保存的是设备使用者指定的响应某个Intent
- // 的最合适的组件信息
- applyDefaultPreferredAppsLPw(service, userHandle);
- }
- }
4.删除用户
- /**
- * Removes a user and all data directories created for that user. This method should be called
- * after the user's processes have been terminated.
- * @param userHandle the user's id
- */
- @Override
- public boolean removeUser(int userHandle) {
- // 检查调用者是否有删除用户的权限
- checkManageOrCreateUsersPermission("Only the system can remove users");
- if (getUserRestrictions(UserHandle.getCallingUserId()).getBoolean(
- UserManager.DISALLOW_REMOVE_USER, false)) {
- Log.w(LOG_TAG, "Cannot remove user. DISALLOW_REMOVE_USER is enabled.");
- return false;
- }
- long ident = Binder.clearCallingIdentity();
- try {
- final UserData userData;
- int currentUser = ActivityManager.getCurrentUser();
- if (currentUser == userHandle) {
- Log.w(LOG_TAG, "Current user cannot be removed");
- return false;
- }
- synchronized (mPackagesLock) {
- synchronized (mUsersLock) {
- userData = mUsers.get(userHandle);
- if (userHandle == 0 || userData == null || mRemovingUserIds.get(userHandle)) {
- return false;
- }
- // We remember deleted user IDs to prevent them from being
- // reused during the current boot; they can still be reused
- // after a reboot.保存要删除的userId,防止重复删除
- mRemovingUserIds.put(userHandle, true);
- }
- try {
- mAppOpsService.removeUser(userHandle);
- } catch (RemoteException e) {
- Log.w(LOG_TAG, "Unable to notify AppOpsService of removing user", e);
- }
- // Set this to a partially created user, so that the user will be purged
- // on next startup, in case the runtime stops now before stopping and
- // removing the user completely.
- // 删除用户并没有删除相关用户文件,只是把partial变量修改为true,
- // 开机后如果该变量还是true会删除相关文件
- userData.info.partial = true;
- // Mark it as disabled, so that it isn't returned any more when
- // profiles are queried.
- userData.info.flags |= UserInfo.FLAG_DISABLED;
- // 更新/data/system/users/${id}.xml文件
- writeUserLP(userData);
- }
- if (userData.info.profileGroupId != UserInfo.NO_PROFILE_GROUP_ID
- && userData.info.isManagedProfile()) {
- // Send broadcast to notify system that the user removed was a
- // managed user.发送删除用户的广播
- sendProfileRemovedBroadcast(userData.info.profileGroupId, userData.info.id);
- }
- if (DBG) Slog.i(LOG_TAG, "Stopping user " + userHandle);
- int res;
- try {
- // 停止正在运行的用户
- res = ActivityManagerNative.getDefault().stopUser(userHandle, /* force= */ true,
- new IStopUserCallback.Stub() {
- @Override
- public void userStopped(int userId) {
- // 删除用户相关应用信息
- finishRemoveUser(userId);
- }
- @Override
- public void userStopAborted(int userId) {
- }
- });
- } catch (RemoteException e) {
- return false;
- }
- return res == ActivityManager.USER_OP_SUCCESS;
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
5.多用户管理
UserManagerService主要管理用户的账号信息,运行中的用户管理由ActivityManagerService来负责。
用户的状态有5种,定义在UserState类中:
- public final class UserState {
- // User is first coming up.启动中
- public final static int STATE_BOOTING = 0;
- // User is in the locked state.锁定
- public final static int STATE_RUNNING_LOCKED = 1;
- // User is in the unlocking state.未锁定
- public final static int STATE_RUNNING_UNLOCKING = 2;
- // User is in the running state.运行中
- public final static int STATE_RUNNING_UNLOCKED = 3;
- // User is in the initial process of being stopped.停止的初始过程中
- public final static int STATE_STOPPING = 4;
- // User is in the final phase of stopping, sending Intent.ACTION_SHUTDOWN.停止的最后阶段
- public final static int STATE_SHUTDOWN = 5;
- ...
- }
- @Override
- public boolean switchUser(final int targetUserId) {
- // 检查调用者是否有切换用户的权限
- enforceShellRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES, targetUserId);
- UserInfo currentUserInfo;
- UserInfo targetUserInfo;
- synchronized (this) {
- // 获取当用用户的相关信息
- int currentUserId = mUserController.getCurrentUserIdLocked();
- currentUserInfo = mUserController.getUserInfo(currentUserId);
- // 获取切换目标用户的相关信息
- targetUserInfo = mUserController.getUserInfo(targetUserId);
- if (targetUserInfo == null) {
- Slog.w(TAG, "No user info for user #" + targetUserId);
- return false;
- }
- // 如果目标用户不支持切换,则返回
- if (!targetUserInfo.supportsSwitchTo()) {
- Slog.w(TAG, "Cannot switch to User #" + targetUserId + ": not supported");
- return false;
- }
- // 如果目标用户是另一个用户的profile,则返回
- if (targetUserInfo.isManagedProfile()) {
- Slog.w(TAG, "Cannot switch to User #" + targetUserId + ": not a full user");
- return false;
- }
- mUserController.setTargetUserIdLocked(targetUserId);
- }
- // 发送切换用户的消息
- Pair<UserInfo, UserInfo> userNames = new Pair<>(currentUserInfo, targetUserInfo);
- mUiHandler.removeMessages(START_USER_SWITCH_UI_MSG);
- mUiHandler.sendMessage(mUiHandler.obtainMessage(START_USER_SWITCH_UI_MSG, userNames));
- return true;
- }
- final class UiHandler extends Handler {
- public UiHandler() {
- super(com.android.server.UiThread.get().getLooper(), null, true);
- }
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- ...
- case START_USER_SWITCH_UI_MSG: {
- mUserController.showUserSwitchDialog((Pair<UserInfo, UserInfo>) msg.obj);
- break;
- }
- ...
- }
- }
- }
- void showUserSwitchDialog(Pair<UserInfo, UserInfo> fromToUserPair) {
- // The dialog will show and then initiate the user switch by calling startUserInForeground
- Dialog d = new UserSwitchingDialog(mService, mService.mContext, fromToUserPair.first,
- fromToUserPair.second, true /* above system */);
- d.show();
- }
- @Override
- public void show() {
- // Slog.v(TAG, "show called");
- super.show();
- final View decorView = getWindow().getDecorView();
- if (decorView != null) {
- decorView.getViewTreeObserver().addOnWindowShownListener(this);
- }
- // Add a timeout as a safeguard, in case a race in screen on/off causes the window
- // callback to never come.
- mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_START_USER),
- WINDOW_SHOWN_TIMEOUT_MS);
- }
- private final Handler mHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_START_USER:
- // 调用startUser()方法
- startUser();
- break;
- }
- }
- };
- void startUser() {
- synchronized (this) {
- if (!mStartedUser) {
- // 调用startUserInForeground方法
- mService.mUserController.startUserInForeground(mUserId, this);
- mStartedUser = true;
- final View decorView = getWindow().getDecorView();
- if (decorView != null) {
- decorView.getViewTreeObserver().removeOnWindowShownListener(this);
- }
- mHandler.removeMessages(MSG_START_USER);
- }
- }
- }
- /**
- * Start user, if its not already running, and bring it to foreground.
- * 开启用户,如果用户没有在运行,则开启它
- */
- boolean startUserInForeground(final int userId, Dialog dlg) {
- boolean result = startUser(userId, /* foreground */ true);
- dlg.dismiss();
- return result;
- }
- /**
- * Start user, if its not already running.
- * <p>The user will be brought to the foreground, if {@code foreground} parameter is set.
- * When starting the user, multiple intents will be broadcast in the following order:</p>
- * <ul>
- * <li>{@link Intent#ACTION_USER_STARTED} - sent to registered receivers of the new user
- * <li>{@link 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
- * <li>{@link 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
- * <li>{@link Intent#ACTION_USER_SWITCHED} - sent to registered receivers of the new user.
- * Sent only if {@code foreground} parameter is true
- * <li>{@link Intent#ACTION_USER_STARTING} - ordered broadcast sent to registered receivers
- * of the new fg user
- * <li>{@link Intent#ACTION_LOCKED_BOOT_COMPLETED} - ordered broadcast sent to receivers of
- * the new user
- * <li>{@link Intent#ACTION_USER_UNLOCKED} - sent to registered receivers of the new user
- * <li>{@link 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.
- * <li>{@link Intent#ACTION_USER_INITIALIZE} - ordered broadcast sent to receivers of the
- * new user. Sent only the first time a user is starting.
- * <li>{@link Intent#ACTION_BOOT_COMPLETED} - ordered broadcast sent to receivers of the new
- * user. Indicates that the user has finished booting.
- * </ul>
- *
- * @param userId ID of the user to start
- * @param foreground true if user should be brought to the foreground
- * @return true if the user has been successfully started
- */
- boolean startUser(final int userId, final boolean foreground) {
- // 检查调用者权限
- if (mService.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 {
- synchronized (mService) {
- final int oldUserId = mCurrentUserId;
- // 如果要开启的用户已经存在,则直接返回true
- if (oldUserId == userId) {
- return true;
- }
- mService.mStackSupervisor.setLockTaskModeLocked(null,
- ActivityManager.LOCK_TASK_MODE_NONE, "startUser", false);
- // 获取目标用户的相关信息
- final UserInfo userInfo = getUserInfo(userId);
- if (userInfo == null) {
- Slog.w(TAG, "No user info for user #" + userId);
- return false;
- }
- if (foreground && userInfo.isManagedProfile()) {
- 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);
- }
- boolean needStart = false;
- // If the user we are switching to is not currently started, then
- // we need to start it now.如果目标用户不存在,则修改用户状态为正在开启
- // UserState的状态默认值是STATE_BOOTING
- if (mStartedUsers.get(userId) == null) {
- UserState userState = new UserState(UserHandle.of(userId));
- mStartedUsers.put(userId, userState);
- getUserManagerInternal().setUserState(userId, userState.state);
- // 根据用户状态更新已经开启的用户列表
- updateStartedUserArrayLocked();
- needStart = true;
- }
- final UserState uss = mStartedUsers.get(userId);
- final Integer userIdInt = userId;
- mUserLru.remove(userIdInt);
- // 调整用户在mUserLru中的位置,当前用户位于末尾
- mUserLru.add(userIdInt);
- if (foreground) {
- // 修改当前用户的Id
- mCurrentUserId = userId;
- // 更新用户配置信息
- mService.updateUserConfigurationLocked();
- mTargetUserId = UserHandle.USER_NULL; // reset, mCurrentUserId has caught up
- // 更新与当前用户相关的用户列表
- updateCurrentProfileIdsLocked();
- 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) {
- // Send 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);
- mService.broadcastIntentLocked(null, null, intent,
- null, null, 0, null, null, null, AppOpsManager.OP_NONE,
- null, false, false, MY_PID, SYSTEM_UID, userId);
- }
- if (foreground) {
- // 把开启的用户设为前台用户
- moveUserToForegroundLocked(uss, oldUserId, userId);
- } else {
- // 用户启动结束,则切换用户到STATE_RUNNING_LOCKED状态
- mService.mUserController.finishUserBoot(uss);
- }
- if (needStart) {
- // 如果需要开启用户,则发送相应广播
- Intent intent = new Intent(Intent.ACTION_USER_STARTING);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
- intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
- mService.broadcastIntentLocked(null, null, 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;
- }
- // 根据用户状态更新已经开启的用户列表mStartedUserArray
- private void updateStartedUserArrayLocked() {
- int num = 0;
- for (int i = 0; i < mStartedUsers.size(); i++) {
- UserState uss = mStartedUsers.valueAt(i);
- // This list does not include stopping users.
- if (uss.state != UserState.STATE_STOPPING
- && uss.state != UserState.STATE_SHUTDOWN) {
- num++;
- }
- }
- mStartedUserArray = new int[num];
- num = 0;
- for (int i = 0; i < mStartedUsers.size(); i++) {
- UserState uss = mStartedUsers.valueAt(i);
- if (uss.state != UserState.STATE_STOPPING
- && uss.state != UserState.STATE_SHUTDOWN) {
- mStartedUserArray[num++] = mStartedUsers.keyAt(i);
- }
- }
- }
- 发送的msg消息是在ActivityManagerService中处理的:
- final class UiHandler extends Handler {
- public UiHandler() {
- super(com.android.server.UiThread.get().getLooper(), null, true);
- }
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- ...
- case SYSTEM_USER_START_MSG: {
- mBatteryStatsService.noteEvent(BatteryStats.HistoryItem.EVENT_USER_RUNNING_START,
- Integer.toString(msg.arg1), msg.arg1);
- // 新建用户时调用
- mSystemServiceManager.startUser(msg.arg1);
- break;
- }
- case SYSTEM_USER_CURRENT_MSG: {
- mBatteryStatsService.noteEvent(
- BatteryStats.HistoryItem.EVENT_USER_FOREGROUND_FINISH,
- Integer.toString(msg.arg2), msg.arg2);
- mBatteryStatsService.noteEvent(
- BatteryStats.HistoryItem.EVENT_USER_FOREGROUND_START,
- Integer.toString(msg.arg1), msg.arg1);
- // 切换用户时调用
- mSystemServiceManager.switchUser(msg.arg1);
- break;
- }
- case REPORT_USER_SWITCH_MSG: {
- mUserController.dispatchUserSwitch((UserState) msg.obj, msg.arg1, msg.arg2);
- break;
- }
- case CONTINUE_USER_SWITCH_MSG: {
- mUserController.continueUserSwitch((UserState) msg.obj, msg.arg1, msg.arg2);
- break;
- }
- case USER_SWITCH_TIMEOUT_MSG: {
- mUserController.timeoutUserSwitch((UserState) msg.obj, msg.arg1, msg.arg2);
- break;
- }
- case REPORT_USER_SWITCH_COMPLETE_MSG: {
- mUserController.dispatchUserSwitchComplete(msg.arg1);
- break;
- }
- ...
- }
- };
- // 该方法主要是调用mUserSwitchObservers列表中的IUserSwitchObserver对象的onUserSwitching方法
- // 如果想知道用户切换,可以调用AMS的registerUserSwitchObserver()方法来注册一个观察者对象
- 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 IRemoteCallback callback = new IRemoteCallback.Stub() {
- int mCount = 0;
- @Override
- public void sendResult(Bundle data) throws RemoteException {
- synchronized (mService) {
- if (mCurUserSwitchCallback == this) {
- // 收到一条回调,就加一
- mCount++;
- // 所有注册的回调方法都执行了,发送继续处理的消息
- if (mCount == observerCount) {
- sendContinueUserSwitchLocked(uss, oldUserId, newUserId);
- }
- }
- }
- }
- };
- synchronized (mService) {
- uss.switching = true;
- mCurUserSwitchCallback = callback;
- }
- // 遍历调用所有注册回调对象的onUserSwitching方法
- for (int i = 0; i < observerCount; i++) {
- try {
- mUserSwitchObservers.getBroadcastItem(i).onUserSwitching(
- newUserId, callback);
- } catch (RemoteException e) {
- }
- }
- } else {
- synchronized (mService) {
- // 如果没有注册回调方法的,直接调用继续执行用户切换的方法
- sendContinueUserSwitchLocked(uss, oldUserId, newUserId);
- }
- }
- mUserSwitchObservers.finishBroadcast();
- }
- void sendContinueUserSwitchLocked(UserState uss, int oldUserId, int newUserId) {
- mCurUserSwitchCallback = null;
- mHandler.removeMessages(USER_SWITCH_TIMEOUT_MSG);
- mHandler.sendMessage(mHandler.obtainMessage(ActivityManagerService.CONTINUE_USER_SWITCH_MSG,
- oldUserId, newUserId, uss));
- }
- 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或临时用户
- stopGuestOrEphemeralUserIfBackground();
- // 强制停止后台用户
- stopBackgroundUsersIfEnforced(oldUserId);
- }
- /** Called on handler thread */
- void dispatchUserSwitchComplete(int userId) {
- final int observerCount = mUserSwitchObservers.beginBroadcast();
- for (int i = 0; i < observerCount; i++) {
- try {
- // 遍历调用所有观察者的onUserSwitchComplete方法
- mUserSwitchObservers.getBroadcastItem(i).onUserSwitchComplete(userId);
- } catch (RemoteException e) {
- }
- }
- mUserSwitchObservers.finishBroadcast();
- }
- /**
- * Stops the guest or ephemeral user if it has gone to the background.
- * 停止切换到后台的Guest或临时用户
- */
- private void stopGuestOrEphemeralUserIfBackground() {
- synchronized (mService) {
- final int num = mUserLru.size();
- for (int i = 0; i < num; i++) {
- Integer oldUserId = mUserLru.get(i);
- UserState oldUss = mStartedUsers.get(oldUserId);
- if (oldUserId == UserHandle.USER_SYSTEM || oldUserId == mCurrentUserId
- || oldUss.state == UserState.STATE_STOPPING
- || oldUss.state == UserState.STATE_SHUTDOWN) {
- continue;
- }
- UserInfo userInfo = getUserInfo(oldUserId);
- if (userInfo.isEphemeral()) {
- LocalServices.getService(UserManagerInternal.class)
- .onEphemeralUserStop(oldUserId);
- }
- if (userInfo.isGuest() || userInfo.isEphemeral()) {
- // This is a user to be stopped.
- stopUsersLocked(oldUserId, true, null);
- break;
- }
- }
- }
- }
- // 强制停止后台用户
- private void stopBackgroundUsersIfEnforced(int oldUserId) {
- // Never stop system user
- if (oldUserId == UserHandle.USER_SYSTEM) {
- return;
- }
- // For now, only check for user restriction. Additional checks can be added here
- boolean disallowRunInBg = hasUserRestriction(UserManager.DISALLOW_RUN_IN_BACKGROUND,
- oldUserId);
- if (!disallowRunInBg) {
- return;
- }
- synchronized (mService) {
- if (DEBUG_MU) Slog.i(TAG, "stopBackgroundUsersIfEnforced stopping " + oldUserId
- + " and related users");
- stopUsersLocked(oldUserId, false, null);
- }
- }
- void timeoutUserSwitch(UserState uss, int oldUserId, int newUserId) {
- synchronized (mService) {
- /// M: Change Slog.wtf to Slog.w to avoid having WTF easily after adding new user
- Slog.w(TAG, "User switch timeout: from " + oldUserId + " to " + newUserId);
- sendContinueUserSwitchLocked(uss, oldUserId, newUserId);
- }
- }
Activity进入Idle状态时会调用activityIdleInternalLocked方法,该方法中会修改用户的状态到STATE_RUNNING_LOCKED状态
这篇关于Android多用户之UserManagerService源码分析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!