PackageManagerService(以下简称PKMS)是Android系统中最重要的几个服务之一。PKMS负责管理系统的Package,包括APK的安装,卸载,信息的查询等等。它的功能非常的多,也非常的强大。这里从开机入手,分析PKMS的启动流程,本文源码基于Android6.0.1。
PKMS启动流程分为以下几个部分
1. PKMS的创建
2. 扫描XML文件并解析成对应的数据结构
3. 扫描apk目录并解析成对应的数据结构
4. 解析完文件后的收尾工作
一 PKMS的创建
PackageManagerService作为系统核心服务,由SystemServer创建。
1.1 Zygote fork出SystemServer后,SystemServer执行其main函数。在main函数中调用其静态方法run().
public static void main(String[] args) {
new SystemServer().run();
}
1.2 在run方法中首先设置系统的语言环境、设置虚拟机运行内存,加载运行库等。然后启动服务,分别调用startBootstrapServices()、startCoreServices()、startOtherServices()。
1.3 PKMS就是在startBootstrapServices()中被启动起来的,startBootstrapServices()调用了PKMS的main函数
1.4 在PKMS的mian函数中首先创建了PKMS的对象,然后将该对象添加到ServiceManager中。创建PKMS对象就是我们本文需要分析的重点。
二 扫描XML文件并解析成对应的数据结构
2.1 PKMS会获取SystemConfig的实例,SystemConfig是一个单例,其构造函数中会调用readPermissions(),分别从手机目录etc/sysconfig、etc/permissions、oem/sysconfig、oem/permissions文件中读取权限。
文件中权限主要有以下几类
1)permission
建立权限名和gid的映射关系,因为这些权限涉及和linux内核交互,所以需要在底层权限(有不同的用户组界定)和Android层权限(由不同的字符串界定)之间建立映射关系。
2)assign-permission
赋予uid相应的权限
3)library
4)feature
例如在文件android.hardware.camera.xml:
表示手机相机所应该支持的特性。
2.2. 解析完这些文件后PKMS会调用getGlobalGids()等方法获取解析后的数据,并保存在自己的数据结构中,数据结构如下
mGlobalGids int[] 用于存储group标签定义的gid
mSharedlibraries HashMap
mSystemPermissionsSparseArray
mAvailableFeatures HashMap
mSettings.mPermissions Hashmap
2.3. 接着PKMS调用Settings的readLpw()解析上一次安装的信息,xml文件保存在data/system/package.xml和data/system/package-backup.xml,其中后一个是用来备份前一个文件的。
package.xml内容标签如下:
1)package
上次安装的apk信息,一个package标签会解析为一个PackageSetting对象,当标签为UserID时,保存在mPackages中,当标签为shareUserID,表示使用共享ID,暂时保存在mPendingPackages中,待解析完shareUserID后保存在mPackages中。
Android系统中,大于或者等于FIRST_APPLICATION_UID(10000)并且小于(FIRST_APPLICATION_UID+ MAX_APPLICATION_UIDS(1000))的linux用户ID是保留给应用程序使用的,而小于FIRST_APPLICATION_UID的Linux用户ID是保留给特权用户使用的。
…..
权限的集合,以及每个权限所属的包。保存到mPermissions中,前面解析etc/permissions等目录的权限是这里面的一小部分。
一个共享用户ID,包含了name 、userId、所拥有的权限等。
由于解析package.xml 这步涉及较多的数据结构来保存上面解析的数据,下面梳理一下
主要涉及的是Settings类,Settings的作用是管理Android系统运行过程中的一些设置信息。
上面解析XML过程主要涉及到以下的几个类
Settings
mPackages:解析package.xml或package-backup.xml中package标签,存储了上次安装APK的信息。
mPermissions:Key为权限名称,value为BasePermission对象。解析permissions标签所得
BasePermission成员变量如下
name:权限名称
sourcePackage:定义权限的包名,由解析etc/sysconfig、etc/permissions oem/sysconfig、 oem/permissions这几个文件的包名都为Android,且权限都有对应的gid。
gids:权限对应的gid
mShareUsers: 解析package.xm中shared-user标签,Key为shared-user名称,value为ShareUserSetting对象
ShareUserSetting成员变量如下:
name:共享用户名称
userId:共享用户ID
packages:使用共享ID的包的集合
mUserIds: ArrayList Object为PackageSetting对象,索引为UID。解析package标签,和mPackages内容类似,只是为了提高读 取速度
mOtherUserIds: SparseArray Object为ShareUserSetting对象 索引为UID。解析share-user标签 和mShareUsers类似,只是为 了提高读取速度
以索引获取数组的元素的速度,比以key获取HashMap中元素的速度要快很多,这是以时间换空间的做法。
至此,PackageManagerService第一部分解析XML文件完成。