现如今手机这样的移动设备已经是人手一台了,但是汽车依然是以家庭为单位使用,不同的家庭成员对于汽车的使用存在着差异,比如空间、功能、影音风格等。因此,“智能汽车”需要具备千人千面的特性,能够适应不同的用户和场景。这就要求车载信息娱乐系统必须实现这一关键目标,为不同的驾驶员提供个性化的服务和体验。
Android是一个基于Linux内核的操作系统,它支持多用户模式,即可以在同一台设备上创建多个用户账户,每个用户都有自己的应用、数据和设置。这样可以保护用户的隐私,也可以方便不同的使用场景。但是,Android的多用户机制并不完全等同于Linux的用户组机制,它们之间依然有较大的差异。
本系列文章将从Linux用户的概念入手,逐步分析车载Android多用户机制的原理和特点,以及它们在车载系统中的应用和适配。分为以下章节:
【车载Android】多用户(一) - Linux用户与Android多用户
【车载Android】多用户(二) - Android Automotive 多用户原理
【车载Android】多用户(三) - 构建可感知多用户的车载应用
首先我们先来介绍,linux中用户和用户组的概念。
在 Linux系统中用户
和用户组
是一种用来标识和分类系统中的不同实体的方法。它与文件操作权限息息相关。
Linux 用户是指可以登录到系统或运行某些进程的实体,它们有一个唯一的用户名和用户 ID(UID)。
Linux 用户分为两种类型:系统用户和普通用户。
Linux中的root用户就是系统用户,它具有系统中所有的权限,它不需要登录,也不需要密码,它只是用来运行系统或服务的,root可以访问和修改任何文件和设置,也可以创建和删除其他用户。
root用户是系统的超级管理员,也是系统的默认用户。root用户的UID是0,这是一个特殊的值,表示这个账号是管理员账号。
Linux 用户组是指一组具有相同或相似属性或角色的用户的集合,它们有一个唯一的组名和组 ID(GID)。
Linux 用户组分为两种类型:主用户组
和次用户组
。
Linux 用户和用户组一般认为有以下4点作用:
Linux 的文件系统中,每个文件或目录都有一个所有者(owner)和一个所属组(group),以及三种类型的权限(read、write、execute)。
文件或目录的所有者(owner)是指创建该文件或目录的用户,或者被授权修改该文件或目录的用户。所有者通常拥有对该文件或目录的最高权限。
文件或目录的所属组(group)是指与该文件或目录相关联的用户组,或者被授权访问该文件或目录的用户组。所属组通常拥有对该文件或目录的次高权限。
文件或目录的权限(read、write、execute)是指对该文件或目录的操作能力,分为三种类型:
不同的用户类型(所有者、所属组、其他用户)可以拥有不同的权限,这些权限可以用数字或字母来表示。例如,rwx 表示拥有读取、写入和执行的权限,而 7 表示拥有所有权限(4+2+1),如何计算得出,后面会解释。
我们简单举个例子,在控制台执行ls -l
命令,输出的结果如下:
-rw-r--r--
第一个字段表示文件的类型和权限。第一个字符表示文件的类型,-
表示普通文件,d
表示目录,l
表示链接文件。后面的九个字符分为三组,每组三个字符,分别表示文件所有者
、文件所属组
和其他用户
对该文件的权限。r表示可读,w
表示可写,x
表示可执行,-
表示没有该权限。
link
第三个字段表示文件的所有者。这是一个用户名,表示该文件属于哪个用户。
link
第四个字段表示文件所属的组。这是一个用户组名,表示该文件可以被哪些用户共享。
在Linux系统我们可以使用chmod
指令修改文件或目录权限,它的格式是:
chmod [选项] 权限 文件或目录
其中,权限可以用数字或字母来表示,数字表示的权限是三位数,每一位数的范围是0到7,分别表示不同的权限组合。每一位数又可以分解为三个二进制位,分别表示读、写和执行权限,1表示有该权限,0表示没有该权限。例如:
三位数的权限分别表示文件所有者、文件所属组和其他用户对该文件或目录的权限。例如:
例如:我们在控制台中执行chmod 777 06.SystemUI功能与源码结构分析.pptx
指令,输出结果如下《06.SystemUI功能与源码结构分析.pptx 》这个文件权限,已经被成功修改了。
chmod 777
会把指定的文件或目录的权限设置为所有者、所属组和其他用户都有读、写和执行权限。这是一种非常宽松的权限设置,一般不推荐使用,在Android中系统甚至可能会阻止你设定如此宽松的权限,因为它可能会导致文件或目录被任意修改或删除。除非你确实需要让所有用户都能访问和操作该文件或目录,否则你应该使用更严格的权限设置。
在Linux系统我们可以使用chown
指令修改文件或目录所有者和所属组,它的格式是:
chown [选项] 用户名[:组名] 文件或目录
其中,用户名表示要把文件或目录的所有者改为该用户,组名表示要把文件或目录的所属组改为该组。如果省略组名,表示只修改所有者,不修改所属组。如果用户名和组名都省略,表示不修改所有者和所属组。
举个例子:
chown link 06.SystemUI功能与源码结构分析.pptx
把《06.SystemUI功能与源码结构分析.pptx》这个文件的所有者改为link用户,不修改所属组。
chown link:root 06.SystemUI功能与源码结构分析.pptx
把《06.SystemUI功能与源码结构分析.pptx》这个文件的所有者改为link用户,所属组改为root组。
chown :root 06.SystemUI功能与源码结构分析.pptx
把《06.SystemUI功能与源码结构分析.pptx》这个文件的所属组改为root组,不修改所有者。
chown
命令的作用是改变文件或目录的归属关系,从而影响到文件或目录的访问权限。一般来说,只有文件或目录的所有者或者root用户才能使用chown
命令。
在介绍Android多用户之前,我们还需要把Android系统中UID的概念搞清楚,因为在日常口语交流中,我们经常会把Android系统的多用户模式和Android UID中的用户搞混。
Android应用程序的UID是指用户标识符,承袭自Linux的UID体系。它是Android在安装应用程序时分配给每个应用程序的一个唯一的数字。UID在应用程序不重新安装的情况下保持不变。
UID对每个应用程序是唯一的,除非应用程序明确请求与另一个应用程序共享一个用户标识符,可以在AndroidManifest.xml中使用sharedUserId
标签设定。但是两个应用程序必须用相同的签名。
android:sharedUserId="android.uid.system"
如果我们想要查找某个应用程序的UID,至少有以下两种方法:
在终端中执行下面的指令查看SystemUI的userId。
/data/system/packages.xml 存储了系统中已安装的应用程序的详细信息,比如包名、用户标识符、权限、版本、签名等。这个文件由PackageManager服务管理,它会在应用程序安装、更新或卸载时更新这个文件。这个文件对于系统的正常运行和应用程序的状态维护非常重要,因此它的访问权限受到严格的限制,只有系统应用程序才能读写这个文件。
每个已安装的应用程序都会有一个条目在那里。如果packages . xml显示乱码,需要先执行adb shell setprop persist.sys.binary_xml false
再重启设备即可。
例如,SystemUI
它的条目如下,sharedUserId="10141"就是SystemUI的userId。
再比如,Settings的它的条目如下,可以看出系统设置的userId=1000。
Android系统在linux用户的基础上扩展了很多具有特殊权限的用户,一些常见的系统应用或者服务的userid如下:
在Android系统中,具有特殊权限的应用的userid是在系统编译时分配,userId从1000开始分配,而普通些常见的系统应用或者服务的userid是在应用安装时分配的,userId从10000开始分配。
注意:SystemUI的AndroidManifest.xml中android:sharedUserId是"android.uid.systemui"而不是"android.uid.system" ,所以SystemUI的userid是从10000开始计数。
系统设置的android:sharedUserId="android.uid.system"所以它的userid会固定是1000。
有经验的同学可能会有一个疑问,当我们在开发时,在控制台执行adb shell ps -A|grep systemui
出现第一端标识符是什么含义?
这个u0_a141 表示该应用是机主用户(也称 系统用户userId=U0)下面的应用,id是 141,普通应用程序的UID 都是从 10000开始的,所以我们可以计算出SystemUI的 UID 就是 10141。而这里提到的机主用户就是本系列文章将会重点介绍的Android多用户模式中一种重要的用户!机主用户的userID和应用的userID共同组成了当前进程的用户标识符。
Android 多用户是一种系统功能,可以让一台 Android 设备上添加多个用户,每个用户都有自己的应用数据和设置。这样,不同的人可以在同一台设备上使用不同的帐号和应用,互不干扰。
在原生的Android系统中可以按照【系统设置】->【系统】->【多用户】的步骤开启多用户功能。如图所示:
仔细观察的话,会发现两个用户Launcher显示的壁纸并不相同,这是因为,不同用户之间用户空间不同应用数据也并不共享。如果我们在新用户中安装一个应用,机主用户也是无法看到的。
在控制台中执行ps -A|grep launcher
或ps -A|grep systemui
可以看到当前系统中分别存在两个launcher和systemui进程,而这两进程最大区别就是进程的用户名不同,分别是u0_a138和u10_a138。U0是系统用户而U10是次要用户。
Android 设备管理使用以下用户类别。
在拥有的权限上,系统用户>管理员用户>非管理员用户(次要用户)>访客用户。其中系统用户的默认userid为0,此后新创建的userid从10开始依次累加。
注意:当系统切换到新用户时,系统用户的应用进程会一直运行在后台,但是当切换到系统用户时,所有非系统用户都会休眠。
在同一台设备上创建多个用户账户时,每个用户都有自己的应用、数据和设置。这样可以保护用户的隐私,也可以方便不同的使用场景。不同用户间,有着不同应用和数据的原理是基于Linux的用户和权限机制,以及Android的沙箱机制。不同用户安装的应用apk会存放在/data/app/目录下,被不同的用户共用,当一个用户更新应用时,另一个用户下的apk也会被同步更新。
每个用户都有一个唯一的用户名,每个应用也有一个唯一的用户ID。每个用户都有自己的存储空间,每个应用都有自己的数据目录。系统会根据UID来区分和隔离不同用户和应用的数据,只有拥有相应权限的用户或应用才能访问或修改数据。
例如,假设设备上有两个用户机主用户和新用户,每个用户都安装了一个相同的应用Launcher。那么,Launcher在每个用户下都会有一个不同的UID,比如U0_a和U10_a。Launcher在每个用户下也会有一个不同的数据目录,内置存储路径是:/data/user/{userid},外置空间路径是:/storage/emulated/{userid}。
系统会保证只有U0才能访问/data/user/0/launcher,只有U10才能访问/data/user/10/launcher,而其他用户都不能访问这些目录。
本篇介绍了从linux用户、权限到Android多用户的基础知识和概念,Android Automotive中的多用户以及实现原理将在下一篇介绍,如何构建可感知多用户的车载应用,这会在第三篇着重讲解。
好了,感谢你的阅读,希望对你有所帮助。
参考资料:
https://source.android.com/docs/security/app-sandbox?hl=zh-cn
https://source.android.com/docs/devices/automotive/users_accounts/multi_user?hl=zh_cn