PackageManagerService分析(一)

         PackageManagerService(以下简称PKMS)是Android系统中最重要的几个服务之一。PKMS负责管理系统的Package,包括APK的安装,卸载,信息的查询等等。它的功能非常的多,也非常的强大。这里从开机入手,分析PKMS的启动流程,本文源码基于Android6.0.1。

PKMS启动流程分为以下几个部分

1.   PKMS的创建

2.   扫描XML文件并解析成对应的数据结构

3.   扫描apk目录并解析成对应的数据结构

4.   解析完文件后的收尾工作


一  PKMS的创建

PackageManagerService作为系统核心服务,由SystemServer创建。

PackageManagerService分析(一)_第1张图片

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()调用了PKMSmain函数

1.4 PKMSmian函数中首先创建了PKMS的对象,然后将该对象添加到ServiceManager中。创建PKMS对象就是我们本文需要分析的重点。


二  扫描XML文件并解析成对应的数据结构

PackageManagerService分析(一)_第2张图片

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 解析library标签所得,Key为库的名字,value为库文件位置

mSystemPermissionsSparseArray> 解析assign-permission标签所得,UID为索引,HashSet存储的是UID所拥有的权限

mAvailableFeatures HashMap解析feature标签所得,Key为feature的字符串描述,value为FeatureInfo对象

mSettings.mPermissions Hashmap 解析permission标签所得,Key为权限名,value为BasePermission对象,BasePermission对象中一个gids数组,用于保存权限对应的gid。


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是保留给特权用户使用的。


2)permissions

        
        
        
        
…..

     权限的集合,以及每个权限所属的包。保存到mPermissions中,前面解析etc/permissions等目录的权限是这里面的一小部分。


3)share-user


        
            
        
        
            
            
            
            
            
            
            
            
            
            
        
    

        一个共享用户ID,包含了name 、userId、所拥有的权限等。


        由于解析package.xml 这步涉及较多的数据结构来保存上面解析的数据,下面梳理一下

PackageManagerService分析(一)_第3张图片

         主要涉及的是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文件完成。








你可能感兴趣的:(Android源码)