我们可以感遭到,在Android 4.2中的1个比较显著的改变就是加入了多用户的支持。因多用户手机专利早已被Symbian雇员注册,故 android官方的多用户切换目前仅支持平板装备。
系统判断当前装备是不是支持多用户模式的根据是配置文件config.xml中的config_multiuserMaximumUsers配置项。 其取值为整型,决定着当前装备支持的最大用户上限。默许值为1,即不支持多用户。如需启用多用户,则设置此值 为大于1的值。在Nexus 7中,此值为8。
具体代码的判断位置在UserManager.java:
对用户的操作目前未对普通利用开放,其相干API都有hide注解,并需要system权限。另外,用户的添加和移除还 要需android.Manifest.permission.MANAGE_USERS权限。
用户添加是通过调用UserManager的public UserInfo createUser(String name, int flags)方法进行的。其具体实现在UserManagerService的同名方法中。
在调用时,系统进行以下操作:
用户创建后,会首先在/data/system/users/userlist.xml文件中保存新增加用户的id,创建/data/system/users/ 用户id 目录,并将用户信息保存至其下的用户id.xml 文件中。其内容包括1些基本的用户信息。
用户切换是通过调用ActivityManager的public boolean switchUser(int userId)方法进行。1般通过 ActivityManagerNative.getDefault().switchUser(int userId)进行调用。
在调用时,系统进行以下操作
用户移除是通过调用UserManager的 public boolean removeUser(int userHandle) 方法进行的。其具体实现一样 是在UserManagerService的同名方法中。
在调用时,系统进行以下操作:
另外UserManager还提供了 public void wipeUser(int userHandle) 方法,用于删除单个用户的所有数据,但保存 用户账号。 此方法目前对应的底层实现还没有完成。
与其它系统服务的实现类似,用户管理也采取了经过Binder调用的远程服务机制。UserManager为暴露给用户的接 口,UserManagerService为接口的底层实现。其类图以下所示:
UserManager是暴露出来的利用程序接口。对普通利用程序,提供用户数查询,用户状态判断和用户序列号查询 等基本功能。 普通利用没有用户操作权限。
对系统利用,UserManager提供了创建/删除/擦除用户、用户信息获得、用户句柄获得等用户操作的接口。均由远 程调用UserManagerService服务的对应方法实现。
UserManager中提供了1个名为isUserAGoat()的方法。源码中此方法直接返回了false。此方法的加入纯洁是为了给 枯燥的编程生活带来1丝乐趣,以便写出:
这样的语句。
与其它大部份Service1样,UserManagerService的实现采取了 单例模式。在服务中,由组成为UserInfo类的散列 表mUsers保护所有的用户状态。
mUsers在系统启动时由/data/system/users/userlist.xml读取生成,并在运行期间动态改变。所有用户的添加、删 除操作,都终究序列化回此文件中。
ActivityManagerService目前加入了多用户支持。负责保护装备中存在的所有用户状态。服务以下述变量来记录当 前处于“启动”状态的用户。
用户的启动状态对象为com.android.server.am.UserStartedState。其中指定的用户状态有4种:
完全的用户生命周期为:
BOOTING->RUNNING->STOPPING->SHUTDOWN
用户必须处于RUNNING状态时,才能作为切换的目标用户。所以在用户切换流程中,首先要判断当前用户的状态, 并启动STOPPING/SHUTDOWN状态的用户。
用户最早体验到多用户的入口位置即为锁屏界面。锁屏界面中加入了用户切换组件: KeyguardMultiUserSelectorView类。
该类在装备允许多用户存在的情况下,显示当前所有用户的列表。并在用户进行选择后,调用 ActivityManagerNative.getDefault().switchUser(int userId)方法进行用户切换。
对每一个用户,Android都为其分配了单独的存储空间。标准的支持多用户的外部存储空间是由init.rc定义的环境 变量所指定:
在Dalvik虚拟机初始化的进程中,会以dalvik_system_Zygote.cpp中的mountEmulatedStorage函数,使用带有 MS_BIND参数的mount命令, 将用户对应的外部存储卡目录mount到上述定义的TARGET目录下。其判断利用userid的 方式为: 以当前利用的uid/100000,取得对应的userid,这段逻辑位于system/core/libcutils/multiuser.c中。
而Environment类中相应的获得外部存储目录的方法,也是由上述环境变量所取得。对每一个用户,其标准外部存 储路径为:
EMULATED_STORAGE_TARGET/userid/
比如:
/storage/emulated/0 为主用户的外部存储路径。
在多用户环境下,所有用户安装的利用依然同之前1样,放置于/data/app目录下。但本来/data/data的数据存储位 置目前仅对主用户有效,其余用户的数据存储目录则位于/data/user/用户id/目录下。 此目录的创建是在创建用户 时由前述的MountService完成的。
对每一个用户,系统都会以PackageuserState类来保护其安装的软件状态。此列表以散列表的情势存在,由 PackageSettingBase类保护。所有的包――用户关系和状态终究依然序列化至/data/system/package.xml中,并保存 /data/system/package-backup.xml作为备份。
目前代码中已存在诸如 isGuestEnabled() 之类的方法。但没有对开发公然,可以预计今后会加入Guest用户, 实现“随手玩玩”模式