我們可以感遭到,在Android 4.2中的1個(gè)比較顯著的改變就是加入了多用戶的支持。因多用戶手機(jī)專利早已被Symbian雇員注冊(cè),故 android官方的多用戶切換目前僅支持平板裝備。
系統(tǒng)判斷當(dāng)前裝備是不是支持多用戶模式的根據(jù)是配置文件config.xml中的config_multiuserMaximumUsers配置項(xiàng)。 其取值為整型,決定著當(dāng)前裝備支持的最大用戶上限。默許值為1,即不支持多用戶。如需啟用多用戶,則設(shè)置此值 為大于1的值。在Nexus 7中,此值為8。
具體代碼的判斷位置在UserManager.java:
對(duì)用戶的操作目前未對(duì)普通利用開放,其相干API都有hide注解,并需要system權(quán)限。另外,用戶的添加和移除還 要需android.Manifest.permission.MANAGE_USERS權(quán)限。
用戶添加是通過(guò)調(diào)用UserManager的public UserInfo createUser(String name, int flags)方法進(jìn)行的。其具體實(shí)現(xiàn)在UserManagerService的同名方法中。
在調(diào)用時(shí),系統(tǒng)進(jìn)行以下操作:
用戶創(chuàng)建后,會(huì)首先在/data/system/users/userlist.xml文件中保存新增加用戶的id,創(chuàng)建/data/system/users/ 用戶id 目錄,并將用戶信息保存至其下的用戶id.xml 文件中。其內(nèi)容包括1些基本的用戶信息。
用戶切換是通過(guò)調(diào)用ActivityManager的public boolean switchUser(int userId)方法進(jìn)行。1般通過(guò) ActivityManagerNative.getDefault().switchUser(int userId)進(jìn)行調(diào)用。
在調(diào)用時(shí),系統(tǒng)進(jìn)行以下操作
用戶移除是通過(guò)調(diào)用UserManager的 public boolean removeUser(int userHandle) 方法進(jìn)行的。其具體實(shí)現(xiàn)一樣 是在UserManagerService的同名方法中。
在調(diào)用時(shí),系統(tǒng)進(jìn)行以下操作:
另外UserManager還提供了 public void wipeUser(int userHandle) 方法,用于刪除單個(gè)用戶的所有數(shù)據(jù),但保存 用戶賬號(hào)。 此方法目前對(duì)應(yīng)的底層實(shí)現(xiàn)還沒有完成。
與其它系統(tǒng)服務(wù)的實(shí)現(xiàn)類似,用戶管理也采取了經(jīng)過(guò)Binder調(diào)用的遠(yuǎn)程服務(wù)機(jī)制。UserManager為暴露給用戶的接 口,UserManagerService為接口的底層實(shí)現(xiàn)。其類圖以下所示:
UserManager是暴露出來(lái)的利用程序接口。對(duì)普通利用程序,提供用戶數(shù)查詢,用戶狀態(tài)判斷和用戶序列號(hào)查詢 等基本功能。 普通利用沒有用戶操作權(quán)限。
對(duì)系統(tǒng)利用,UserManager提供了創(chuàng)建/刪除/擦除用戶、用戶信息獲得、用戶句柄獲得等用戶操作的接口。均由遠(yuǎn) 程調(diào)用UserManagerService服務(wù)的對(duì)應(yīng)方法實(shí)現(xiàn)。
UserManager中提供了1個(gè)名為isUserAGoat()的方法。源碼中此方法直接返回了false。此方法的加入純潔是為了給 枯燥的編程生活帶來(lái)1絲樂趣,以便寫出:
這樣的語(yǔ)句。
與其它大部份Service1樣,UserManagerService的實(shí)現(xiàn)采取了 單例模式。在服務(wù)中,由組成為UserInfo類的散列 表mUsers保護(hù)所有的用戶狀態(tài)。
mUsers在系統(tǒng)啟動(dòng)時(shí)由/data/system/users/userlist.xml讀取生成,并在運(yùn)行期間動(dòng)態(tài)改變。所有用戶的添加、刪 除操作,都終究序列化回此文件中。
ActivityManagerService目前加入了多用戶支持。負(fù)責(zé)保護(hù)裝備中存在的所有用戶狀態(tài)。服務(wù)以下述變量來(lái)記錄當(dāng) 前處于“啟動(dòng)”狀態(tài)的用戶。
用戶的啟動(dòng)狀態(tài)對(duì)象為com.android.server.am.UserStartedState。其中指定的用戶狀態(tài)有4種:
完全的用戶生命周期為:
BOOTING->RUNNING->STOPPING->SHUTDOWN
用戶必須處于RUNNING狀態(tài)時(shí),才能作為切換的目標(biāo)用戶。所以在用戶切換流程中,首先要判斷當(dāng)前用戶的狀態(tài), 并啟動(dòng)STOPPING/SHUTDOWN狀態(tài)的用戶。
用戶最早體驗(yàn)到多用戶的入口位置即為鎖屏界面。鎖屏界面中加入了用戶切換組件: KeyguardMultiUserSelectorView類。
該類在裝備允許多用戶存在的情況下,顯示當(dāng)前所有用戶的列表。并在用戶進(jìn)行選擇后,調(diào)用 ActivityManagerNative.getDefault().switchUser(int userId)方法進(jìn)行用戶切換。
對(duì)每一個(gè)用戶,Android都為其分配了單獨(dú)的存儲(chǔ)空間。標(biāo)準(zhǔn)的支持多用戶的外部存儲(chǔ)空間是由init.rc定義的環(huán)境 變量所指定:
在Dalvik虛擬機(jī)初始化的進(jìn)程中,會(huì)以dalvik_system_Zygote.cpp中的mountEmulatedStorage函數(shù),使用帶有 MS_BIND參數(shù)的mount命令, 將用戶對(duì)應(yīng)的外部存儲(chǔ)卡目錄mount到上述定義的TARGET目錄下。其判斷利用userid的 方式為: 以當(dāng)前利用的uid/100000,取得對(duì)應(yīng)的userid,這段邏輯位于system/core/libcutils/multiuser.c中。
而Environment類中相應(yīng)的獲得外部存儲(chǔ)目錄的方法,也是由上述環(huán)境變量所取得。對(duì)每一個(gè)用戶,其標(biāo)準(zhǔn)外部存 儲(chǔ)路徑為:
EMULATED_STORAGE_TARGET/userid/
比如:
/storage/emulated/0 為主用戶的外部存儲(chǔ)路徑。
在多用戶環(huán)境下,所有用戶安裝的利用依然同之前1樣,放置于/data/app目錄下。但本來(lái)/data/data的數(shù)據(jù)存儲(chǔ)位 置目前僅對(duì)主用戶有效,其余用戶的數(shù)據(jù)存儲(chǔ)目錄則位于/data/user/用戶id/目錄下。 此目錄的創(chuàng)建是在創(chuàng)建用戶 時(shí)由前述的MountService完成的。
對(duì)每一個(gè)用戶,系統(tǒng)都會(huì)以PackageuserState類來(lái)保護(hù)其安裝的軟件狀態(tài)。此列表以散列表的情勢(shì)存在,由 PackageSettingBase類保護(hù)。所有的包――用戶關(guān)系和狀態(tài)終究依然序列化至/data/system/package.xml中,并保存 /data/system/package-backup.xml作為備份。
目前代碼中已存在諸如 isGuestEnabled() 之類的方法。但沒有對(duì)開發(fā)公然,可以預(yù)計(jì)今后會(huì)加入Guest用戶, 實(shí)現(xiàn)“隨手玩玩”模式