1.Linux uid/gid
Linux下的用戶id(uid)和群組id(gid)。Linux是多用戶系統,每個用戶都擁有一個uid,這個uid由系統和用戶名做映射綁定。同時,為了便於用戶管理(譬如管理文檔權限),Linux引入了群組的概念,可以將多個用戶歸於一個群組。每一個群組擁有一個群組id(gid)。
root用戶:Linux下的唯一的超級用戶,擁有所有的系統權限。root用戶所在的組即root組。
2.Android uid(4.2(API Level 17))
Android4.2開始支持多用戶。Linux的uid/gid多用戶體系已經被用在App管理上。
android重新開發了一套多用戶體系,在UserManagerService中管理,PackageManagerService和ActivityManagerService中也有相關邏輯。Android的多用戶可以做到不同用戶的應用的物理文件級(數據)的區分,以實現不同用戶有不同的壁紙、密碼,以及不同的應用等。
例如:在一個有兩個用戶(用戶id分別為0和10)的安卓設備上,在用戶10下安裝一個應用,此時,在0下是看不到這個應用的。
從data/system/packages.xml查看此應用的uid:userId=”10078”
Process.myUid()得到uid為”1010078”
Process.myUserHandle()得到”userHandle{10}”
在另一個用戶0下安裝此應用。
查看packages.xml,看到uid沒有變化10078
Process.myUid()得到uid為”10078”
Process.myUserHandle()得到”userHandle{0}”
adb shell進入命令行,分別查看data/user/0和data/user/10下面此應用的數據區:
用戶0:
用戶10:
可以看到,實際上應用在內部雖然有多用戶,但只有一個uid,在不同的用戶下,通過uid和用戶id合成一個新的uid,以保證在每個用戶下能夠區分(見chapter3)。
(可以看到文件擁有者是u0_a78,所在群組為u0_a78。從data/system/packages.xml根據包名查看此應用信息,可以看到:userId=”10078”。)
3.android.os.UserHandle
這個類對外提供有關多用戶的接口。 從里面的一些api代碼可以看到uid在多用戶下的處理邏輯:
多用戶支持開關:
注意一個api getUid()。這就清楚了,將用戶id 10作為第一個參數,packages.xml中記錄的該應用的uid 10078作為第二個參數傳入,得到了這個應用在10用戶下的uid——1010078!
通過應用的uid得到當前用戶的userId,以上過程的逆過程:
從另一個核心的api myUserId()更能清楚地看到應用uid和用戶id的關系:
當一個應用使用UserHandle.myUserId()來獲取當前的用戶id的時候,其實就是從他自己的進程得到應用的uid,然后通過上述邏輯計算出當前的用戶id。
從Process.myUserHandle()也能清楚地看到這個邏輯:
從概念和API命名上,確實有些混亂,但Android也情非得已,Process的API Level是1,UserHandle的API Level是17,可見在最初的android上面,已經將Linux uid/gid給了應用id了,當時應該也沒有考慮android有一天需要支持多用戶。直到4.2(API Level 17),引入了多用戶時,已經是若干年過去了,Process已經被無數的開發者使用,無法改變。只能接受這個概念上混淆了。
可以用如下的幾點來簡單地澄清這些id概念:
(1)Process中的xxid相關的概念和API是關於應用id的。
(2)UserHandle中的xxid相關的概念和API是關於Android用戶id的。
(3)Process有接口得到UserHandle實例。