2. Android系统架构与PackageManager定位

要理解PackageManagerService(下文简称PMS)在Android系统中的位置,必须先建立一张“系统分层地图”。Android并不是一个单体进程,而是由内核、原生库、运行时、系统服务框架和应用层共同构成的纵向栈式架构。PMS恰好位于系统服务框架层,是应用包世界的“户籍管理者”和“准入裁判”。

一、系统服务分层:PMS站在哪一层

Android系统自上而下大致可分为五层,每一层承担不同职责,并通过明确的接口向下依赖、向上暴露能力:

  • 应用层(App Layer):普通APK、系统应用、Launcher、Settings等,通过Context API调用系统能力。
  • 应用框架层(Java API Framework):ActivityManager、PackageManager、WindowManager等Java服务接口,是应用开发者直接接触的API。
  • 系统服务层(System Services):运行在system_server进程中的核心服务,包括AMS、PMS、WMS、IMS等,是系统真正的“大脑”。
  • 原生库与运行时(Native Libraries & ART):libc、binder、skia、ART虚拟机等,为上层提供底层能力。
  • Linux内核层(Kernel):进程调度、内存管理、Binder驱动、文件系统等。

PMS属于系统服务层,但它与内核层的Binder驱动、原生库层的libbinder、框架层的PackageManager API都有直接或间接的交互。它既不是纯Java服务,也不是纯Native服务,而是“Java服务 + Native支撑”的典型代表。

二、Binder通信:PMS如何被跨进程访问

PMS运行在system_server进程中,而应用进程、其他系统服务进程都需要访问它。这种跨进程访问依赖Binder机制。Binder通信的核心角色包括:

  • Binder驱动:位于内核层,负责进程间数据传递和线程调度。
  • ServiceManager:Native层服务注册中心,PMS通过它注册为“package”服务。
  • Binder代理(Proxy):客户端持有的远程接口,调用时自动打包参数并发送到服务端。
  • Binder实体(Stub):服务端实现,接收请求并执行实际逻辑。

应用调用getPackageManager()时,实际拿到的是ApplicationPackageManager,它内部持有一个IPackageManager的Binder代理。当应用调用getPackageInfo()时,请求会经过Binder驱动,最终到达system_server中的PMS实体,由PMS完成查询并返回结果。

// 应用侧调用链示意
Context.getPackageManager()
  → ApplicationPackageManager
    → IPackageManager.Stub.Proxy
      → Binder驱动
        → system_server中的PMS
          → PackageManagerService.getPackageInfo()
            → 返回PackageInfo
Binder通信是单向调用、双向返回的同步模型。PMS的很多接口是同步阻塞的,因此PMS内部执行效率会直接影响应用启动和系统响应速度。

三、PackageManagerService在系统启动中的角色

PMS并不是在系统启动完成后才“按需创建”的,而是在system_server启动阶段就被初始化。它的启动过程大致分为以下几个关键阶段:

  1. SystemServer启动:Zygote孵化出system_server进程,进入SystemServer.main()。
  2. 启动Bootstrap服务:包括ActivityManagerService、PowerManagerService等。
  3. 启动Core服务:PMS在此阶段被创建,开始扫描系统目录。
  4. 扫描已安装包:PMS遍历/system/framework、/system/priv-app、/data/app等目录,解析AndroidManifest.xml。
  5. 建立包索引:生成PackageSetting、SharedUserSetting、权限映射等内部数据结构。
  6. 注册Binder服务:PMS将自身注册到ServiceManager,服务名为“package”。
  7. 进入就绪状态:PMS完成扫描后,其他服务和应用才能正常查询包信息。

如果PMS启动失败或扫描异常,系统可能卡在开机动画,甚至无法进入Launcher。因此PMS是系统启动的关键路径服务之一。

四、PMS与其他核心服务的关系

PMS并非孤立存在,它与多个系统服务存在强耦合关系。下表列出主要协作对象及其交互内容:

协作服务 交互内容 典型场景
ActivityManagerService 获取应用组件信息、权限校验 启动Activity时校验包是否存在
WindowManagerService 获取应用主题、屏幕适配信息 窗口创建时读取应用配置
PermissionManagerService 权限定义、权限授予状态 运行时权限申请与校验
Installd APK安装、 dex优化、目录创建 应用安装与卸载
ServiceManager Binder服务注册与查询 客户端获取PMS代理

五、核心原理:PMS的“数据中枢”定位

PMS维护着整个系统中所有已安装包的元数据,包括包名、版本号、签名、权限、组件列表、安装位置、UID等。这些数据在系统启动时被扫描并缓存,后续查询大多走内存索引,只有安装、卸载、更新等操作才会触发磁盘写入和重新扫描。

从数据流角度看,PMS是“磁盘 → 内存 → Binder接口”的三级结构:

  • 磁盘层:APK文件、packages.xml、packages.list等持久化数据。
  • 内存层:PackageSetting、PackageParser.Package、ArrayMap索引等运行时结构。
  • 接口层:IPackageManager定义的AIDL接口,供跨进程调用。
PMS的定制往往集中在三个位置:扫描策略(哪些目录、哪些包被识别)、权限与签名校验逻辑、以及安装/卸载流程的扩展点。理解分层和Binder通信,是后续定制工作的前提。

六、案例场景:应用启动时的PMS参与

以点击Launcher图标启动一个应用为例,PMS在其中的参与如下:

  1. Launcher通过PackageManager查询已安装应用列表,PMS返回ResolveInfo。
  2. 用户点击图标,Launcher调用startActivity,请求进入AMS。
  3. AMS向PMS查询该Intent对应的Activity信息,确认组件存在且导出属性合法。
  4. AMS检查权限,必要时通过PMS获取权限定义。
  5. AMS创建进程,最终加载APK并启动Activity。

可以看到,PMS并不直接启动应用,但它为AMS提供了“这个包能不能启动、由谁启动、需要什么权限”的决策依据。

七、常见误区与复盘

误区一:PMS只负责安装应用。实际上PMS还负责包查询、权限映射、组件解析、签名校验、共享UID管理等,安装只是其对外最显眼的功能之一。
误区二:PMS是独立进程。PMS运行在system_server进程中,与AMS、WMS等共享同一进程空间,因此PMS的阻塞会影响整个系统服务。
误区三:修改PMS只需改Java代码。PMS与Installd、Binder驱动、SELinux策略、packages.xml格式都有耦合,定制时需同步考虑Native层和权限配置。

复盘来看,掌握PMS定位的关键在于三点:第一,明确它在系统分层中的位置;第二,理解Binder如何把客户端请求送到PMS;第三,清楚它在系统启动中的初始化时序。这三点构成了后续所有PMS定制工作的基础坐标系。

Android系统分层与PackageManagerService定位 应用层 Launcher / Settings / 普通APK / 系统应用 Context.getPackageManager() 应用框架层 PackageManager API / ActivityManager API / WindowManager API ApplicationPackageManager 系统服务层(system_server进程) AMS 活动管理 PMS 包管理服务 WMS 窗口管理 其他系统服务 Permission / Installd 原生库与运行时 libbinder / ART / libc / PackageParser Native支撑 ServiceManager Linux内核层 Binder驱动 / 进程调度 / 内存管理 / 文件系统 /dev/binder 核心定位 启动时序:Zygote → system_server → Bootstrap服务 → PMS创建 → 扫描APK → 注册Binder → 就绪