原创内容,转载请注明出处,多谢配合。
PackageManagerService(简称 PMS),是 Android 系统核心服务之一,处理包管理相关的工作,常见的比如安装、卸载应用等。这个系列文章就简单了解下PMS,只简单梳理流程,不抠代码细节,文章牵涉到的源码来自Android 8.0。
一、ApplicationPackageManager
PMS是系统服务,那么应用层肯定有个PackageManager作为binder call client端来供使用,但是这里要注意,PackageManager是个抽象类,一般使用的是它的实现类:ApplicationPackageManager。
PackageManager提供的功能主要包含如下几点:
- 提供一个应用程序的所有信息(ApplicationInfo)。
- 提供四大组件的信息。
- 查询permission相关信息。
- 提供包的信息。
- 安装、卸载APK。
二、PMS初始化
PMS作为系统服务,自然还是在SystemServer中启动:
frameworks/base/services/java/com/android/server/SystemServer.java
private void startBootstrapServices() {
…
//启动installer服务
Installer installer = mSystemServiceManager.startService(Installer.class);
…
//启动PMS服务
mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
...
}
private void startOtherServices() {
...
mPackageManagerService.systemReady();
…
}
Installer是一个负责package安装、删除、迁移、更新的系统服务。
PMS的main方法:
public static PackageManagerService main(Context context, Installer installer,
boolean factoryTest, boolean onlyCore) {
// Self-check for initial settings.
PackageManagerServiceCompilerMapping.checkProperties();
//初始化PMS
PackageManagerService m = new PackageManagerService(context, installer,
factoryTest, onlyCore);
m.enableSystemUserPackages();
//向ServiceManager注册服务,将service写入/dev/binder中
ServiceManager.addService("package", m);
return m;
}
接下来看看PMS的构造方法,这部分代码非常多,主要分5个阶段:
PMS_START阶段
- 构造Settings类:这个是Android的全局管理者,用于协助PMS保存所有的安装包信息;
- 保存Installer对象;
- 初始化SystemConfig,获取系统配置信息,包括全局属性、groupid以及系统权限。初始化一些功能类,包括:PackageDexOptimizer (dex优化工具类) 、 DexManager(dex管理类)、PackageHandler(建立package相关操作的消息循环)等;
- 创建data下的各种目录,比如data/app, data/app-private等。
PMS_SYSTEM_SCAN_START阶段
- 通过scanDirTracedLI扫描系统目录文件,包括:/system/framework 、/system/priv-app 、/system/app 这俩都是放系统app、/vendor/overlay、/vendor/app、oem/app。
PMS_DATA_SCAN_START阶段
- 通过scanDirTracedLI扫描/data/app和/data/app-private目录下的文件。
PMS_SCAN_END阶段
- 将上述信息写回/data/system/packages.xml。
PMS_READY阶段
- 创建服务PackageInstallerService。
三、构造函数中重点??榻馕?/h5>
3.1 Settings
frameworks/base/services/core/java/com/android/server/pm/Settings.java
Settings的构造函数主要用于创建”data/system”目录和一些xml文件,并配置相应的权限,其中:
- packages.xml 记录所有安装app的信息,当系统进行程序安装、卸载和更新等操作时,均会更新该文件。
- packages-backup.xml 备份文件
- packages-stopped.xml 记录被用户强行停止的应用的Package信息
- packages-stopped-backup.xml 备份文件
- packages.list 记录非系统自带的APK的数据信息,这些APK有变化时会更新该文件
readLPw()函数
:
从/data/system/packages.xml或packages-backup.xml文件中获得packages、permissions相关信息,添加到相关内存列表中。packages.xml文件记录了系统的permisssions以及每个APK的name、codePath、flags、version等信息这些信息主要通过APK的AndroidManifest.xml解析获取,解析完APK后将更新信息写入这个文件,下次开机直接从里面读取相关信息添加到内存相关结构中。当有APK升级、安装或删除时会更新这个文件。
writeLPr函数
:
将解析出的每个APK的配置信息(mSetting.mPackages)保存到packages.xml和packages.list文件。packages.list记录了如下数据:pkgName, userId, debugFlag, dataPath(包的数据路径)。
3.2 SystemConfig
frameworks/base/services/core/java/com/android/server/SystemConfig.java
通过readPermissions解析指定目录下的xml文件:
- /system/etc/sysconfig
- /system/etc/permissions
- /odm/etc/sysconfig
- /odm/etc/permissions
- /oem/etc/sysconfig
- /oem/etc/permissions
readPermissions函数最终会调用readPermissionsFromXml()使用XMLPullParser的方式解析这些XML文件,然后把解析出来的数据结构保存到PMS中。
3.3 scanDirTracedLI
这里就是Apk的解析流程,针对的是系统开机时安装系统应用的场景,遍历对应目录下的所有apk。解析出包信息保存到Package中。
最后总结整个启动过程:
参考:
http://liuwangshu.cn/tags/Android%E5%8C%85%E7%AE%A1%E7%90%86%E6%9C%BA%E5%88%B6/
https://maoao530.github.io/2017/01/10/packagemanager/