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目录下的文件