android 多用户管理UserManager

一.概述Android从4.2开始支持多用户模式,不同的用户运行在不同的用户空间,相关的系统设置是各不相同而且不同用户安装的应用和应用数据也是不一样的,但是系统中和硬件相关的设计则是共用的。Android的多用户实现主要通过UserManagerService(UMS)对多用户进行创建、删除等操作。*Binder服务端:UMS继承于IUserManager.Stub,作为Binder服务端;...
摘要由CSDN通过智能技术生成

一.概述

Android从4.2开始支持多用户模式,不同的用户运行在不同的用户空间,相关的系统设置是各不相同而且不同用户安装的应用和应用数据也是不一样的,但是系统中和硬件相关的设计则是共用的。

Android的多用户实现主要通过UserManagerService(UMS)对多用户进行创建、删除等操作。

*Binder服务端:UMS继承于IUserManager.Stub,作为Binder服务端;

*Binder服务器:UserManager的成员变量mService继承于IUserManager.Stub.Proxy,该变量作为binder客户端。采用标准的binder通信进行信息传递

二.概念

2.1 userId,uid,appId

userId:用户id; appId:跟用户空间无关的应用程序id;取值范围0<=appId<100000;uid:跟用户空间紧密相关的应用程序id.

    uid = userId * 100000 + appId复制代码

2.2 UserHandler

常见方法:

方法 描述
isSameUser 比较两个uid的userId是否相同
isSameApp 比较两个uid的appId是否相同
isApp appId是否属于区间[10000,19999]
isIsolated appId是否属于区间[99000,99999]
getIdentifier 获取UserHandler所对应的userId

常见成员变量:

userId 赋值 含义
USER_OWNER 0 拥有者
USER_ALL -1 所有用户
USER_CURRENT -2 当前活动用户
USER_CURRENT_OR_SELF -3 当前用户或者调用者所在用户
USER_NULL -1000 未定义用户

2.3 UserInfo

UserInfo代表的是一个用户的信息,涉及到的flags及其含义,如下:

flags 含义
FLAG_PRIMARY 主用户,只有一个user具有该标识
FLAG_ADMIN 具有管理特权的用户,例如创建或删除其他用户
FLAG_GUEST 访客用户,可能是临时的
FLAG_RESTRICTED 限制性用户,较普通用户具有更多限制,例如禁止安装app或者管理wifi等
FLAG_INITIALIZED 表明用户已初始化
FLAG_MANAGED_PROFILE 表明该用户是另一个用户的轮廓
FLAG_DISABLED 表明该用户处于不可用状态

2.4 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;复制代码

三.UMS的启动

UMS在PMS中初始化

    public PackageManagerService(Context context, Installer installer,
                boolean factoryTest, boolean onlyCore) {
            ......
                 sUserManager = new UserManagerService(context, this, mPackages);
            .....
                }复制代码

UMS的初始化操作

    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();
                //创建目录/data/system/users/0
                File userZeroDir = new File(mUsersDir, String.valueOf(UserHandle.USER_SYSTEM));
                userZeroDir.mkdirs();
                FileUtils.setPermissions(mUsersDir.toString(),
                        FileUtils.S_IRWXU | FileUtils.S_IRWXG | FileUtils.S_IROTH | FileUtils.S_IXOTH,
                        -1, -1);
                //mYserListFile文件路径为/data/system/users/userlist.xml
                mUserListFile = new File(mUsersDir, USER_LIST_FILENAME);
                initDefaultGuestRestrictions();
                //解析userlist.xml文件
                readUserListLP();
                sInstance = this;
            }
            mLocalService = new LocalService();
            LocalServices.addService(UserManagerInternal.class, mLocalService);
            mLockPatternUtils = new LockPatternUtils(mContext);
            //表示System正处于启动阶段
            mUserStates.put(UserHandle.USER_SYSTEM, UserState.STATE_BOOTING);
        }复制代码

四.创建一个用户

创建一个多用户主要是在UMS中createUserInternalUnchecked中执行

    private UserInfo createUserInternalUnchecked(String name, int flags, int parentId) {
        //检查一下手机是否处于低内存设备
        if (ActivityManager.isLowRamDeviceStatic()) {
            return null;
        }
        //判断需要创建的user是否是guest用户
        final boolean isGuest = (flags & UserInfo.FLAG_GUEST) != 0;
        //判断需要创建的user是否是profile用户
        final boolean isManagedProfile = (flags & UserInfo.FLAG_MANAGED_PROFILE) != 0;
        //判断需要创建的user是否是restricted用户
        final boolean isRestricted = (flags & UserInfo.FLAG_RESTRICTED) != 0;
        final boolean isDemo = (flags & UserInfo.FLAG_DEMO) != 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) {
                        parent = getUserDataLU(parentId);
                    }
                    if (parent == null) return null;
                }
                if (isManagedProfile && !canAddMoreManagedProfiles(parentId, false)) {
                    Log.e(LOG_TAG, "Cannot add more managed profiles for user " + parentId);
                    return null;
                }
                if (!isGuest && !isManagedProfile && !isDemo && isUserLimitReached()) {
                    // If we're not adding a guest/demo 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.
                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
                        && (flags & UserInfo.FLAG_DEMO) == 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/{usdId}
                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
                    userInfo = new UserInfo(userId, name, null, flags);
                    //设置序列号
                    userInfo.serialNumber = mNextSerialNumber++;
                    //设置创建时间
                    long now = System.currentTimeMillis();
                    userInfo.creationTime = (now > EPOCH_PLUS_30_YEARS) ? now : 0;
                    //设置partial,表示正在创建
                    userInfo.partial = true;
                    userInfo.lastLoggedInFingerprint = Build.FINGERPRINT;
                    userData = new UserData();
                    userData.info = userInfo;
                    mUsers.put(userId, userData);
                }
                //将新建的用户信息写入到/data/system/users/{userId}/{userId}.xml
                writeUserLP(userData);
                //将用户信息写入到userlist.xml
                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());
            //为新建的user准备存储区域
            mPm.prepareUserData(userId, userInfo.serialNumber,
                    StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE);
            //给上步为新建user准备的存储区域写入数据
            mPm.createNewUser(userId);
            //设置partial,表示创建结束
            userInfo.partial = false;
            synchronized (mPackagesLock) {
                //更新/data/system/users/{userId}/{userId}.xml
                writeUserLP(userData);
            }
            //更新mUserIds数据组
            updateUserIds();
            Bundle restrictions = new Bundle();
            if (isGuest) {
                synchronized (mGuestRestrictions) {
                    restrictions.putAll(mGuestRestrictions);
                }
            }
            synchronized (mRestrictionsLock) {
                mBaseUserRestrictions.append(userId, restrictions);
            }
            //给新创建的用户赋予默认权限
            mPm.onNewUserCreated(userId);
            //发送用户创建完成的广播
            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;
    }复制代码

五.切换用户

用户切换用户通过调用AMS中switchUser方法实现

    public boolean switchUser(final int targetUserId) {
            enforceShellRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES, targetUserId);
            UserInfo currentUserInfo;
            UserInfo targetUserInfo;
            synchronized (this) {
                //获得当前用户的UserInfo
                int currentUserId = mUserController.getCurrentUserIdLocked();
                currentUserInfo = mUserController.getUserInfo(currentUserId);
                //获得目标用户的UserInfo
                targetUserInfo = mUserController.getUserInfo(targetUserId);
                if (targetUserInfo == null) {
                    Slog.w(TAG, "No user info for user #" + targetUserId);
                    
  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值