Framwork源码解析(3)_PackageManagerService(PMS或PKMS)启动流程

PackageManagerServic简介

包管理机制是Android中的重要机制,是应用开发和系统开发需要掌握的知识点之一。包指的是Apk、jar和so文件等等,它们被加载到Android内存中,由一个包转变成可执行的代码,这就需要一个机制来进行包的加载、解析、管理等操作,这就是包管理机制。包管理机制由许多类一起组成,其中核心为PackageManagerService(PMS),PackageManagerService包管理服务,简称PMS或者PKMS,是Android系统中非常重要的一个管理服务,它是在system_server进程中启动的。主要是负责应用的安装卸载更新等工作。查看PMS源码之前一定要先看一下前文System_Server进程启动过程:https://blog.csdn.net/u010982507/article/details/104123531

PMS启动流程分析

一、启动入口
从上文中的system_server进程启动流程分析中可以得知,在SystemServer.java类(路径是:/frameworks/base/services/java/com/android/server/SystemServer.java)中的run方法中调用了启动引导服务,代码如下:

private void run() {
   
    ...
    // 启动引导服务
	startBootstrapServices();
	...
}

找到startBootstrapServices方法如下,可以看到在这里调用了PackageManagerService类的main方法,从而实现PMS的启动。

private void startBootstrapServices() {
   
	...
	// Only run "core" apps if we're encrypting the device.
	// 读取init.rc的vold.decrypt属性,如果它的值为"trigger_restart_min_framework",说明我们加密了设备,这时mOnlyCore的值为true,表示只运行“核心”程序,这是为了创建一个极简的启动环境。
     String cryptState = SystemProperties.get("vold.decrypt");
	// 启动AMS
    mPackageManagerService = PackageManagerService.main(mSystemContext, installer,mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
    // 是否首次启动PMS,mFirstBoot是后续WMS创建时所需要的参数,从这里就可以看出系统服务之间是有依赖关系的,它们的启动顺序不能随意被更改。
	mFirstBoot = mPackageManagerService.isFirstBoot();
	...
}

二、PackageManagerService类

1、调用main方法
PackageManagerService类,路径在frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java,找到main方法如下:

public static PackageManagerService main(Context context, Installer installer,
         boolean factoryTest, boolean onlyCore) {
   
     // Self-check for initial settings.
     // 检测初始化设置
     PackageManagerServiceCompilerMapping.checkProperties();
	 // 创建PackageManagerService对象,传入上下文,installer等参数
     PackageManagerService m = new PackageManagerService(context, installer,
             factoryTest, onlyCore);
     m.enableSystemUserPackages();
     // 将PMS服务注册到ServiceManager
     ServiceManager.addService("package", m);
     return m;
 }

main方法中主要做了

  • 检测初始化设置
  • 创建PackageManagerService对象,传入上下文,installer实例,factoryTest是否为测试模式,onlyCore,onlyCore为true表明当前的设置正在加密或者已经是加密的,说明此时只能运行核心app,刚开始不会扫描非系统app。
  • 将PMS服务注册到ServiceManager,然后将service写入/dev/binder中,可以实现用户空间和内核空间的通信。

2、调用PackageManagerService构造方法

构造方法中按功能划分可以分为五个阶段,对应着5个log:

  • BOOT_PROGRESS_PMS_START(开始阶段)
  • BOOT_PROGRESS_PMS_SYSTEM_SCAN_START(扫描系统阶段)
  • BOOT_PROGRESS_PMS_DATA_SCAN_START(扫描Data分区阶段)
  • BOOT_PROGRESS_PMS_SCAN_END(扫描结束阶段)
  • BOOT_PROGRESS_PMS_READY(准备阶段)

第一阶段:扫描并解析XML文件,并将信息保存到特定的数据结构中;

 public PackageManagerService(Context context, Installer installer,
           boolean factoryTest, boolean onlyCore) {
   
       ......
       //用于存储屏幕的相关信息
        mMetrics = new DisplayMetrics();
       // 存储系统过程中的设置信息
       // Settings用于保存所有包的动态设置
       mSettings = new Settings(mPackages);
       // 在Settings中添加多个默认的sharedUserId,将系统进程的sharedUserId添加到Settings中,sharedUserId用于进程间共享数据,比如两个App的之间的数据是不共享的,如果它们有了共同的sharedUserId,就可以运行在同一个进程中共享数据。
       mSettings.addSharedUserLPw("android.uid.system", Process.SYSTEM_UID,
               ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
       mSettings.addSharedUserLPw("android.uid.phone", RADIO_UID,
               ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
       mSettings.addSharedUserLPw("android.uid.log", LOG_UID,
               ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
       mSettings.addSharedUserLPw("android.uid.nfc", NFC_UID,
               ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
       mSettings.addSharedUserLPw("android.uid.bluetooth", BLUETOOTH_UID,
               ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
       mSettings.addSharedUserLPw("android.uid.shell", SHELL_UID,
               ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
       // Installer继承自SystemService,和PMS、AMS一样是系统的服务(虽然名称不像是服务),PMS很多的操作都是由Installer来完成的,比如APK的安装和卸载。在Installer内部,通过IInstalld和installd进行Binder通信,由位于nativie层的installd来完成具体的操作。
	   mInstaller = installer;
       // 创建Dex优化工具类
       mPackageDexOptimizer = new PackageDexOptimizer(installer, mInstallLock, context,"*dexopt*");
       // 创建DexManager实例
       mDexManager = new DexManager(this, mPackageDexOptimizer, installer, mInstallLock);
       ......
		//得到全局系统配置信息。比如系统的权限就可以通过SystemConfig来获取。
        SystemConfig systemConfig = SystemConfig.getInstance();
        //获取全局的groupId 
        mGlobalGids = systemConfig.getGlobalGids();
       //获取系统权限
        mSystemPermissions = systemConfig.getSystemPermissions();
        ......
        //安装APK时需要的锁,保护所有对installd的访问。
       synchronized (mInstallLock) {
   
       //更新APK时需要的锁,保护内存中已经解析的包信息等内容
       synchronized (mPackages) {
   
	       ......
	       // 创建ServiceThread后台线程并启动
	       mHandlerThread = new ServiceThread(TAG,
	                    Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/);
	            mHandlerThread.start();
	    
	       // 创建PackageHandler绑定到ServiceThread的消息队列,PackageHandler继承自Handler,绑定之后PMS可以通过PackageHandler驱动APK的复制和安装工作,binder机制。
	       mHandler = new PackageHandler(mHandlerThread.getLooper());
	       mProcessLoggingHandler = new ProcessLoggingHandler();
	       // PackageHandler处理的消息队列如果过于繁忙,有可能导致系统卡住, 因此将它添加到Watchdog的监测集中。Watchdog主要有两个用途,一个是定时检测系统关键服务(AMS和WMS等)是否可能发生死锁,还有一个是定时检测线程的消息队列是否长时间处于工作状态(可能阻塞等待了很长时间)。如果出现上述问题,Watchdog会将日志保存起来,必要时还会杀掉自己所在的进程,也就是SystemServer进程。
	       Watchdog.getInstance().addThread(mHandler, WATCHDOG_TIMEOUT);
	
	       ......
	
			// 创建各种目录
	       File dataDir = Environment.getDataDirectory();
	       mAppInstallDir = new File(dataDir, "app");
	       mAppLib32InstallDir = new File(dataDir, "app-lib");
	       mAsecInternalPath = new File(dataDir, "app-asec").getPath();
	       mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
	       // 多用户管理服务
	       sUserManager = new UserManagerService(context, this,
                    new UserDataPreparer(mInstaller, mInstallLock, mContext, mOnlyCore), mPackages);
	       ......
	       
	       // 解析packages.xml等文件的信息,保存到Settings的对应字段中。packages.xml中记录系统中所有安装的应用信息,包括基本信息、签名和权限。如果packages.xml有安装的应用信息,那么Settings的readLPw方法会返回true,mFirstBoot的值为false,说明PMS不是首次被启动。
	       mFirstBoot = !mSettings.readLPw(sUserManager.getUsers(false));
	       ......
}   

第二阶段:扫描系统目录,其中/system/framework目录中文件都是系统库,例如:framework.jar、services.jar、framework-res.apk,看过scanDirTracedLI方法之后会发现只扫描apk文件,所以只扫描framework-res.apk文件;/vendor/app目录下文件是厂商特定的apk文件,不过市面上的厂商都把字节的应用放在/system/app目录下。

 public PackageManagerService(Context context, Installer installer,
           boolean factoryTest, boolean onlyCore) {
   
       ......
       // 创建framework目录
 	   File frameworkDir = new File(Environment.getRootDirectory(), "framework");
       ......
	   // 扫描/vendor/overlay目录下的文件
	   
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ruiurrui

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值