【趣谈】Android多用户导致的UserID、UID、shareUserId、UserHandle术语混乱讨论
备注
2025/07/02 星期三
在与Android打交道时总遇到UserID、UID、shareUserId、UserHandle这些术语,但是这些术语非常混乱,梳理总结一下
一、概述
Android是基于Linux内核实现的操作系统,因此直接复用了Linux为多用户隔离设计的文件权限来实现应用的沙盒隔离,在后续的更新中又引入了多用户的功能,就导致了一定的混乱。
二、概念对比
1.UID
Android的UID直接来自Linux内核的文件权限,Linux为每个用户赋予一个唯一的id值,称为user id,一般简称为uid,Android将每个应用(进程)视为一个Linux用户,由于不同应用的uid不同无法访问其他应用的文件就达到了沙盒隔离的效果。Linux将0设为root,0-1000保留仅供系统重要进程使用,Android将1000设为system、2000设为shell、将1000-2000保留仅供系统重要进程使用,而真正提供给是第三方应用使用的uid是从10000开始的。
2.shareUserId
作为应用开发者,我们有时候会希望打破Android的沙盒隔离,让多个应用可以互相访问,Android也提供了这样的功能,只需要在不同应用的AndroidManifest.xml文件中将android:sharedUserId设置为相同的值(类似对暗号),并且不同应用使用相同的开发者签名,不同应用即可获得相同uid从而打破沙盒隔离。这里使用的是shareUserId而不是shareUID,但是实际上这里实现的是共享uid的操作。
3.UserHandle
Android多用户机制实际通过UserHandle类进行提供,主用户UserHandleID为0,其他用户(次要用户)ID值从10开始依次增长(10、11、12、…)。与UserHandle相关的概念还有一个AppID,简单来说就是相同包名的应用具有相同的AppID,Android通过用UID=UserHandleID*10000+AppID的方式实现了多用户运行相同应用的功能。
4.UserID
其实Android中并没有一个UserID的概念,UserID经常被混用为UID和UserHandleID,如果非要使用的话,其实更建议将UserID作为UID的字符串形式,因为当使用ps命令打印进程信息的时候我们看到的uid默认是Android转换后的root、system、u0_axx形式而不是数字值(想要显示数字格式的uid需要使用ps -n命令),这样也更符合明确使用的android:shareUserId字段功能。
三、结论
Android使用Linux文件权限并引入多用户机制造成了一定的术语混乱,所以应该尽量减少存在争议术语UserID的使用,如果一定要使用更加建议将UserID当作UID的字符形式