基于Android P版本PKMS详解一

本文详细解析了Android P版本中PackageManagerService(PKMS)的启动过程,包括SystemServer如何启动PKMS,以及PKMS在启动后进行的系统服务初始化、系统优化和系统就绪等关键步骤。通过分析`SystemServer`的`startBootstrapServices`和`startOtherServices`方法,揭示了PKMS在Android系统启动过程中的重要角色。
摘要由CSDN通过智能技术生成


[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
         

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值