[TOC]
# 一 修改记录
| 版本 | 修改日期 | 作者 | 修改内容 |
| :----| ----------| ----- | ------- |
| v1.0 | 2019.05.09 | 初版 |
# 二 概述
PackageManagerService (简称 `PKMS`),是 Android 系统中核心服务之一,管理着所有跟 package 相关的工作,常见的比如安装、卸载、更新应用等。
![image](res/IPackageManager.png)
- IPackageManager.aidl 中定义了 Binder 通信中的业务方法,编译后生成的 IPackageManager.java 接口类中定义了内部类 Stub,该类继承自 Binder 并实现了 IPackageManager 接口;
- PackageManagerService 继承自 IPackageManager.Stub 类,作为服务端参与 Binder 通信;
- IPackageManager.Stub 类中定义了一个内部类 Proxy,该类有一个 IBinder 类型的成员变量 mRemote,mRemote 用于和服务端 PackageManagerService 通信;
- 客户端一般通过 Context 的 getPackageManager 方法获取一个类型为 PackageManager 的对象,该对象的实际类型是 PackageManager 的子类 ApplicationPackageManager。ApplicationPackageManager 并没有直接参与 Binder 通信,而是通过其 IPackageManager 类型的成员变量 mPM,它指向一个 IPackageManager.Stub.Proxy 类型的对象。
本文基于 Android P 分析。
# 三 SystemServer 启动 PKMS
`SystemServer` 是由 `Zygote` 孵化而来的一个进程(进程名为:`system_server`),Android 系统中几乎所有的核心服务都是在这个进程中,例如:ActivityManagerService、PackageManagerService、PowerManagerService 和 WindowManagerService 等。
> frameworks/base/services/java/com/android/server/SystemServer.java
```java {.line-numbers}
public final class SystemServer {
...
private final int mFactoryTestMode;
private Context mSystemContext;
private SystemServiceManager mSystemServiceManager;
...
/**
* The main entry point from zygote.
*/
public static void main(String[] args) {
// 创建 SystemServer 对象并执行其 run 方法
new SystemServer().run();
}
public SystemServer() {
// Check for factory test mode.
mFactoryTestMode = FactoryTest.getMode();
...
}
private void run() {
try {
traceBeginAndSlog("InitBeforeStartServices");
...
// Initialize the system context.
// 初始化系统上下文
createSystemContext();
// Create the system service manager.
// 创建 SystemServiceManager 对象,用于管理 system_server 进程中的各种 service.
mSystemServiceManager = new SystemServiceManager(mSystemContext);
...
} finally {
traceEnd(); // InitBeforeStartServices
}
...
// Start services.
try {
traceBeginAndSlog("StartServices");
// 启动引导服务
startBootstrapServices();
...
// 启动核心服务
startCoreServices();
...
// 启动其他服务
startOtherServices();
...
} catch (Throwable ex) {
Slog.e("System", "******************************************");
Slog.e("System", "************ Failure starting system services", ex);
throw ex;
} finally {
traceEnd();
}
...
// Loop forever.
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
...
private void createSystemContext() {
ActivityThread activityThread = ActivityThread.systemMain();
mSystemContext = activityThread.getSystemContext();
...
}
...
}
```
## 3.1 startBootstrapServices
`system_server` 的 `startBootstrapServices` 方法会启动一些引导服务,其中 `PKMS` 就是在这里启动:
```java {.line-numbers}
private PackageManagerService mPackageManagerService;
private PackageManager mPackageManager;
...
private boolean mOnlyCore;
private boolean mFirstBoot;
...
/**
* Starts the small tangle of critical services that are needed to get
* the system off the ground. These services have complex mutual dependencies
* which is why we initialize them all in one place here. Unless your service
* is also entwined in these dependencies, it should be initialized in one of
* the other functions.
*/
private void startBootstrapServices() {
Slog.i(TAG, "Reading configuration...");
...
// Wait for installd to finish starting up so that it has a chance to
// create critical directories such as /data/user with the appropriate
// permissions. We need this to complete before we initialize other services.
traceBeginAndSlog("StartInstaller");
// 启动 Installer 服务
Installer installer = mSystemServiceManager.startService(Installer.class);
traceEnd();
...
// We need the default display before we can initialize the package manager.
traceBeginAndSlog("WaitForDisplay");
mSystemServiceManager.startBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);
traceEnd();
// 处于加密状态则仅仅解析核心应用
// Only run "core" apps if we're encrypting the device.
String cryptState = SystemProperties.get("vold.decrypt");
if (ENCRYPTING_STATE.equals(cryptState)) {
Slog.w(TAG, "Detected encryption in progress - only parsing core apps");
mOnlyCore = true;
} else if (ENCRYPTED_STATE.equals(cryptState)) {
Slog.w(TAG, "Device encrypted - only parsing core apps");
mOnlyCore = true;
}
...
traceBeginAndSlog("StartPackageManagerService");
// 创建 PKMS 对象并注册到 ServiceManager
mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
// 判断本次是否为初次启动,当 Zygote 或 SystemServer 退出时,init 会再次启动他们
// 这里 FirstBoot 是指开机后的第一次启动
mFirstBoot = mPackageManagerService.isFirstBoot();
// 获取 PackageManager
mPackageManager = mSystemContext.getPackageManager();
traceEnd();
...
}
```
## 3.2 startOtherServices
`system_server` 的 `startOtherServices` 方法会启动其他服务,其中也会对 `PKMS` 做一些操作:
```java {.line-numbers}
...
private ActivityManagerService mActivityManagerService;
...
/**
* Starts a miscellaneous grab bag of stuff that has yet to be refactored
* and organized.
*/
private void startOtherServices() {
...
if (!mOnlyCore) {
traceBeginAndSlog("UpdatePackagesIfNeeded");
try {
// 将调用 performDexOptUpgrade
mPackageManagerService.updatePackagesIfNeeded();
} catch (Throwable e) {
reportWtf("update packages", e);
}
traceEnd();
}
traceBeginAndSlog("PerformFstrimIfNeeded");
try {
// 执行 FSTRIM,即磁盘维护操作。
// 对整个分区执行 TRIM 操作,将标记为删除的文件彻底从磁盘上移除
// 而不是等到写入时再移除,目的是提高写入时效率。
mPackageManagerService.performFstrimIfNeeded();
} catch (Throwable e) {
reportWtf("performing fstrim", e);
}
traceEnd();
...
traceBeginAndSlog("StartBootPhaseSystemServicesReady");
mSystemServiceManager.startBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);
traceEnd();
...
traceBeginAndSlog("MakePackageManagerServiceReady");
// 通知系统 PKMS 就绪
mPackageManagerService.systemReady();
traceEnd();
...
traceBeginAndSlog("StartBootPhaseDeviceSpecificServicesReady");
mSystemServiceManager.startBootPhase(SystemService.PHASE_DEVICE_SPECIFIC_SERVICES_READY);
traceEnd();
...
// We now tell the activity manager it is okay to run third party
// code. It will call back into us once it has gotten to the state
// where third party code can really run (but before it has actually
// started launching the initial applications), for us to complete our
// initialization.
mActivityManagerService.systemReady(() -> {
Slog.i(TAG, "Making services ready");
traceBeginAndSlog("StartActivityManagerReadyPhase");
mSystemServiceManager.startBootPhase(
SystemService.PHASE_ACTIVITY_MANAGER_READY);
traceEnd();
...
// Wait for all packages to be prepared
mPackageManagerService.waitForAppDataPrepared();
...
}, BOOT_TIMINGS_TRACE_LOG);
}
```
`PKMS` 启动后将参与一些系统优化的工作,然后调用 systemReady 方法通知系统进入就绪状态。
整个 `system_server` 进程启动过程,涉及 `PKMS` 的主要有以下几个操作:
- PKMS.main
- PKMS.updatePackagesIfNeeded
- PKMS.performFstrimIfNeeded
- PKMS.systemReady
- PKMS.waitForAppDataPrepared
# 四 PKMS.main
PackageManagerService.main 过程主要是创建 PKMS 服务,并注册到 ServiceManager:
> frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
```java {.line-numbers}
public class PackageManagerService extends IPackageManager.Stub
implements PackageSender {
...
public static PackageManagerService main(Context context, Installer installer,
boolean factoryTest, boolean onlyCore) {
// Self-check for initial settings.
// 检查系统属性
PackageManagerServiceCompilerMapping.checkProperties();
// 创建 PKMS
PackageManagerService m = new PackageManagerService(context, installer,
factoryTest, onlyCore);
// split system user
m.enableSystemUserPackages();
// 注册到 ServiceManager
ServiceManager.addService("package", m);
final PackageManagerNative pmn = m.new PackageManagerNative();
ServiceManager.addService("package_native", pmn);
return m;
}
...
}
```
main 方法看似只有几行代码很简单,但执行时间却很长,主要原因是 `PKMS` 在其构造方法中做了很多“重体力活”,这也是影响 Android 启动速度慢的主要原因之一。
`PKMS` 构造方法的主要功能是:扫描 Android 系统中几个目标目录中的 APK 并进行解析,从而建立合适的数据结构以管理诸如 Package 信息、四大组件信息、权限信息等各种信息。
`PKMS` 的工作流程相对简单,复杂的是其中用于保存各种信息的数据结构和他们之间的关系,以及影响最终结果的策略控制(例如前面代码中的 mOnlyCore 变量,用于判断是否只扫面系统目录)。
```java {.line-numbers}
...
// Lock for state used when installing and doing other long running
// operations. Methods that must be called with this lock held have
// the suffix "LI".
final Object mInstallLock = new Object();
// ----------------------------------------------------------------
// Keys are String (package name), values are Package. This also serves
// as the lock for the global state. Methods that must be called with
// this lock held have the prefix "LP".
@GuardedBy("mPackages")
final ArrayMap<String, PackageParser.Package> mPackages =
new ArrayMap<String, PackageParser.Package>();
...
public PackageManagerService(Context context, Installer installer,
boolean factoryTest, boolean onlyCore) {
...
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "create package manager");
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
SystemClock.uptimeMillis());
...
synchronized (mInstallLock) {
// writer
synchronized (mPackages) {
...
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
startTime);
...
if (!mOnlyCore) {
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
SystemClock.uptimeMillis());
...
}
...
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,
SystemClock.uptimeMillis());
...
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
SystemClock.uptimeMillis());
...
} // synchronized (mPackages)
} // synchronized (mInstallLock)
...
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
...
```
`PKMS` 的构造方法涉及的知识点较多,代码段也很长,分为以下几个阶段,每个阶段会输出相对应的 EventLog:除了第一阶段的开头部分代码,后续代码都是同时持有同步锁 mPackages 和 mInstallLock 的过程中执行的。
- BOOT_PROGRESS_PMS_START
- BOOT_PROGRESS_PMS_SYSTEM_SCAN_START
- BOOT_PROGRESS_PMS_DATA_SCAN_START
- BOOT_PROGRESS_PMS_SCAN_END
- BOOT_PROGRESS_PMS_READY
接下来分别分析这 5 个阶段:
## 4.1 PMS_START
第一阶段 `PMS_START` 主要由两部分组成,无需加锁的部分和同时持有两个锁的部分。由于代码较长,大致分成三段,先分析开头一段代码:
```java {.line-numbers}
...
private static final int RADIO_UID = Process.PHONE_UID;
private static final int LOG_UID = Process.LOG_UID;
private static final int NFC_UID = Process.NFC_UID;
private static final int BLUETOOTH_UID = Process.BLUETOOTH_UID;
private static final int SHELL_UID = Process.SHELL_UID;
private static final int SE_UID = Process.SE_UID;
...
final int mSdkVersion = Build.VERSION.SDK_INT;
final Context mContext;
final boolean mFactoryTest;
final boolean mOnlyCore;
final DisplayMetrics mMetrics;
...
@GuardedBy("mPackages")
final Settings mSettings;
...
// Used for privilege escalation. MUST NOT BE CALLED WITH mPackages
// LOCK HELD. Can be called with mInstallLock held.
@GuardedBy("mInstallLock")
final Installer mInstaller;
...
// TODO remove this and go through mPermissonManager directly
final DefaultPermissionGrantPolicy mDefaultPermissionPolicy;
private final PermissionManagerInternal mPermissionManager;
...
static UserManagerService sUserManager;
public PackageManagerService(Context context, Installer installer,
boolean factoryTest, boolean onlyCore) {
...
// SDK 版本检查
if (mSdkVersion <= 0) {
Slog.w(TAG, "**** ro.build.version.sdk not set!");
}
mContext = context;
// 假定为 false,即运行在非工厂模式下
mFactoryTest = factoryTest;
// 假定为 false,即运行在普通模式下,不仅仅加载核心服务
mOnlyCore = onlyCore;
// 存储与显示屏相关的一些属性,例如屏幕的宽高尺寸,分辨率信息等
mMetrics = new DisplayMetrics();
// 创建 Installer 对象,该对象与 Native 进程 installd 交互
mInstaller = installer;
// Create sub-components that provide services / data. Order here is important.
synchronized (mInstallLock) {
synchronized (mPackages) {
// Expose private service for system components to use.
LocalServices.addService(
PackageManagerInternal.class, new PackageManagerInternalImpl());
// 创建用户管理服务
sUserManager = new UserManagerService(context, this,
new UserDataPreparer(mInstaller, mInstallLock, mContext, mOnlyCore), mPackages);
// 创建权限管理服务
mPermissionManager = PermissionManagerService.create(context,
new DefaultPermissionGrantedCallback() {
@Override