Android系统中PMS原理解析

242 阅读16分钟

PMS 是 Android 框架中最核心、最复杂的服务之一,它负责管理设备上所有应用程序生命周期的核心方面,是系统安全、稳定性和功能性的基石。

核心职责概述

PMS 的核心职责可以概括为:

  1. 应用安装、卸载与更新: 处理 APK/AAB 文件的复制、解析、验证、优化和数据库记录。
  2. 应用信息解析与管理: 解析应用的 AndroidManifest.xml,提取组件、权限、特性、元数据等信息,并维护全局数据库(packages.xml, packages.list)。
  3. 权限管理: 管理权限的定义、授予、撤销和检查,是系统安全模型的关键执行者。
  4. 组件查询与解析: 根据 Intent 查找匹配的 Activity/Service/BroadcastReceiver/ContentProvider。
  5. APK 资源管理基础: 提供对已安装应用资源的访问路径(Resources 对象的基础)。
  6. 系统状态维护: 管理安装位置(内部存储、SD卡)、默认应用设置、用户安装的应用等。

超深度剖析

我们将从多个维度深入 PMS 的内部机制:

一、 启动与初始化 (SystemServer)

  1. 时机: PMS 在 SystemServer 启动过程的早期阶段 (startBootstrapServices) 被创建和启动。这是因为它为其他服务(如 ActivityManagerService, UserManagerService)提供应用信息基础。
  2. 关键步骤:
    • 创建 PMS 实例: new PackageManagerService(context)
    • main 方法: 静态 main 方法作为入口点,创建实例并注册到 ServiceManager
    • 构造函数 (PackageManagerService): 这是初始化的核心。
      • 依赖注入: 获取 Installer (连接 installd), ApexManager, UserManagerService, PermissionManagerService 等服务的引用。
      • 创建关键对象: Settings (管理 packages.xml, packages.list, 用户状态等), PackageParser (解析 APK), PackageManagerTracedLock (主锁,保护 PMS 内部状态)。
      • 扫描阶段 (Intensive!):
        • 系统分区扫描 (/system, /vendor, /product, /system_ext, /odm, /oem): 扫描预装应用目录 (/system/app, /system/priv-app, /vendor/app 等),解析 APK,创建 Package 对象。区分特权应用 (priv-app)。
        • BOOTCLASSPATH 扫描: 确保框架 JAR (core-oj.jar, core-libart.jar, okhttp.jar, bouncycastle.jar 等) 被识别。
        • apex 扫描: 处理 APEX 模块(更新系统组件)。
        • overlay 扫描: 收集静态资源叠加包(RRO, SRO)。
        • Privileged Permission Whitelist: 处理特权应用权限白名单。
        • PrepareAppData 阶段: 为系统应用准备私有数据目录 (/data/user/0//),设置正确的权限和 SELinux 上下文。
      • 非系统分区扫描: 扫描 /data/app (用户安装应用), /data/app-private (前向锁定应用,已废弃), /data/app-asec (加密 SD 卡应用,已较少使用)。
      • packages.xml 读取与同步: 读取存储所有包详细状态、权限授予、首选活动、安装位置等的 XML 文件。将内存中的 Package 对象状态与文件同步,处理可能的不一致(如应用已卸载但记录仍在)。
      • DexOpt (至关重要): 调用 Installer 服务触发 installd 对扫描到的所有应用执行 Dex 文件优化 (AOT 编译为 OAT 文件)。这是首次启动慢的主要原因之一。涉及 dex2oat 工具。
      • 多用户支持: 初始化所有现有用户的包状态 (UserManagerService 配合)。
      • 广播 ACTION_PACKAGE_SCAN_FINISHED: 通知系统扫描完成。
    • 注册服务:IPackageManager.Stub (Binder 接口) 注册到 ServiceManager (package)。
    • 阶段回调: 通知 SystemServer PMS 启动完成,SystemServer 继续启动其他服务(如 AMS)。

二、 APK 解析 (PackageParser)

  • 目的: 将物理的 APK/AAB 文件(本质是 ZIP)解析为内存中的结构化数据 (Package / ParsedPackage)。
  • 关键过程 (parseBaseApk):
    1. 解析 AndroidManifest.xml: 使用 XmlPullParser 解析二进制 XML。
    2. 填充 Package 对象: 提取所有关键信息:
      • 包名、版本号 (code/name)、UID、目标/最低 SDK 版本。
      • 组件: Activity, Service, BroadcastReceiver (IntentFilter!), ContentProvider。包括它们的名称、权限要求、intent-filter (action, category, data scheme/mime/type)、启动模式、主题等。
      • 权限: 应用声明的权限 (<permission>),应用请求的权限 (<uses-permission>, <uses-permission-sdk-23>)。
      • 特性与库: 硬件/软件特性 (<uses-feature>), 共享库 (<uses-library>), 覆盖 (<overlay>)。
      • 安装约束: 所需共享用户 ID (sharedUserId), 配置要求 (<compatible-screens>, <supports-screens>), 签名 (<protected-broadcast> 关联)。
      • 元数据 (<meta-data>): Key-value 对,供系统或其他应用查询。
      • <application> 属性: 标签、图标、主题、allowBackup, fullBackupOnly, largeHeap, vmSafeMode, enabled, persistent 等。
    3. 资源与 Assets: 创建 AssetManager 并加载 APK 资源,验证资源 ID 等(但 PMS 本身不管理运行时资源)。
    4. 签名验证 (collectCertificates): 提取 APK 签名 (META-INF/*.RSA/DSA/EC) 并验证其完整性(V1, V2, V3, V4 签名方案)。签名信息是 PMS 安全模型的核心。
    5. Native 库扫描: 记录 APK 中包含的 native 库 (armeabi-v7a, arm64-v8a, x86 等) 路径。
  • Package 对象: 解析的结果是一个复杂的 Package 对象(或 ParsedPackage 接口),它是 PMS 内部表示一个应用的核心数据结构。包含所有解析出的信息。

三、 应用安装流程

  1. 入口点: 通常通过 PackageInstaller 应用(系统 UI)、adb (pm install)、Play Store 或其他拥有 INSTALL_PACKAGES 权限的应用发起。
  2. PackageInstallerService: 处理安装会话的创建、文件拷贝、用户确认(如果需要)。
  3. PackageManagerService.installStage: PMS 接收安装请求。
  4. 验证阶段 (Verification):
    • 完整性检查: APK 文件校验。
    • 权限检查: 调用者是否具有 INSTALL_PACKAGESREQUEST_INSTALL_PACKAGES (受限安装) 权限。安装位置(内部/SD)权限检查。
    • 安装器验证 (可选): 如果请求指定了安装来源 (installSource),可能触发其他验证服务。
  5. 拷贝 APK: 将 APK 文件从临时位置(PackageInstaller 会话)拷贝到最终位置:
    • 用户应用:/data/app//base.apk (或分拆 APK 的目录 /data/app/-*/)
    • 系统更新/特权应用:可能需要写到特定分区(需 remount rw)。
  6. 解析 (scanPackageTracedLI): 调用 PackageParser 解析新安装的 APK,创建新的 Package 对象。
  7. 冲突与升级检查:
    • 包名冲突: 新安装的包名是否已存在?
    • 签名验证 (升级时至关重要):
      • 如果存在旧版本,必须验证新 APK 的签名是否与旧 APK 的签名一致(或者属于同一签名密钥的升级链)。签名不匹配是升级失败最常见的原因。
      • 共享 UID 应用的签名必须匹配。
    • 版本检查: 新版本号必须大于旧版本号(除非是覆盖安装或 adb install -d)。
  8. 优化 (performDexOpt): 通过 Installer 调用 installd 执行 Dex 优化 (dex2oat),生成 OAT/VDEX/ART 文件到 /data/dalvik-cache/ 或应用的私有目录 (/data/app//oat/)。优化策略(速度、空间、验证)由系统属性控制。
  9. PrepareAppData (installd): 为应用创建私有数据目录 (/data/user/0//),设置正确的 Linux 用户/组 ID (UID/GID) 和 SELinux 上下文 (u:object_r:app_data_file:s0:c,c)。迁移旧数据(如果升级)。
  10. 更新 PMS 内部状态:
    • 将新的 Package 对象添加到 PMS 内部的各种数据结构(包名映射、组件解析器等)。
    • 更新 Settings:将新包的信息(包名、路径、UID、版本、权限、首选项)写入 packages.xmlpackages.list
    • 处理权限:如果安装时自动授予权限 (installPermissions),更新授予状态。
    • 更新 IntentResolver:添加新包的组件和 intent-filter,使它们可被查询。
  11. 广播通知:
    • ACTION_PACKAGE_ADDED (如果是新安装) / ACTION_PACKAGE_REPLACED (如果是升级)
    • ACTION_MY_PACKAGE_REPLACED (仅发送给被更新的应用本身)
    • ACTION_PACKAGE_CHANGED (如果组件状态等发生变化)
    • ACTION_PACKAGE_RESTARTED (如果需要重启应用)
  12. 回调其他服务: 通知 ActivityManagerService (清理进程、任务栈), StorageManagerService (更新存储统计), UserManagerService (多用户) 等。

四、 权限管理 (PermissionManagerService - PMS 的紧密伴侣)

  • 权限定义 (<permission>): 系统权限定义在 framework/base/core/res/AndroidManifest.xml 中。第三方权限定义在应用的 AndroidManifest.xml 中。
  • 权限树 (<permission-tree>): 定义权限命名空间。
  • 权限保护级别 (protectionLevel):
    • normal: 自动授予。
    • dangerous: 运行时请求 (Android 6.0+)。
    • signature: 只有与定义者签名相同的应用才能获得。
    • signatureOrSystem: (已废弃) 签名相同或位于系统镜像中。
    • internal: 系统内部使用,不公开。
    • appop: 与 AppOps 机制关联。
    • development: 开发相关权限。
    • preinstalled: 预装应用专用。
    • pre23: 针对 TargetSDK < 23 的遗留处理。
    • installer: 安装器专用。
    • verifier: 验证器专用。
    • knownSigner: 已知签名者专用。
    • role: 角色专用。
    • retailDemo: 零售演示模式专用。
  • 权限授予 (grantPermission):
    • 安装时授予 (installPermissions): 对于 normalsignature 权限(符合条件时),以及 pre23 应用的 dangerous 权限。
    • 运行时授予 (requestPermissions): 对于 dangerous 权限 (API 23+),由用户决定。记录在 packages.xml<perms> 块中。
    • ADB 授予 (pm grant)。
  • 权限检查 (checkPermission): 当应用尝试执行受权限保护的操作(如启动 Activity、访问 ContentProvider、调用敏感 API)时,由框架(AMS, ContextImpl, WMS 等)调用 PMS 的 checkPermissioncheckUidPermission 方法。PMS 查询内部状态(UID 对应的包名,包名对应的已授权权限列表)进行验证。
  • 权限组: 将相关权限分组 (<permission-group>),便于运行时请求和用户管理。
  • 特殊权限: 一些权限(如 WRITE_SETTINGS, SYSTEM_ALERT_WINDOW) 需要特殊途径(系统设置界面)授予。记录在 package.xml<special-permissions> 块。
  • 权限固化 (PermissionController): Android 10+ 引入了权限固化,即使应用更新,某些权限的拒绝状态也会被保留。

五、 组件解析 (IntentResolver)

  • 目的: 根据一个 Intent (Action, Category, Data, Type, Flags, Component 等) 查找最匹配的组件 (Activity/Service/BroadcastReceiver)。
  • 核心数据结构: PMS 内部维护多个 IntentResolver 的子类实例:
    • ActivityIntentResolver: 解析启动 Activity 的 Intent。
    • ServiceIntentResolver: 解析绑定/启动 Service 的 Intent。
    • ReceiverIntentResolver: 解析发送给 BroadcastReceiver 的 Intent (静态注册)。
    • ProviderIntentResolver: 解析访问 ContentProvider 的 Intent (较少直接使用,通常通过 Authority 查找)。
  • 工作流程:
    1. 注册 (addFilter): 在应用安装/解析时,将其组件声明的 <intent-filter> 信息添加到对应的 IntentResolver
    2. 查询 (queryIntent): 当需要启动组件时 (e.g., startActivity, bindService, sendBroadcast),框架调用 PackageManager.queryIntentActivities/Services/Receivers,最终委托给 PMS 内部的 IntentResolver
    3. 匹配算法:
      • 基于 Intent 属性: 严格匹配 Action、Category、Data (Scheme, MimeType, Path 等)。
      • 优先级排序: 根据 <intent-filter>priority 属性排序。
      • 系统级过滤: 过滤掉对调用者不可见的组件(根据权限、exported 属性、匹配的 UID 等)。
      • 用户级过滤: 过滤掉被用户禁用的组件或应用。
      • 返回最佳匹配: 通常返回一个有序列表 (List),由调用者(如 ActivityManagerService)决定最终启动哪个(可能弹出选择器给用户)。
  • ResolveInfo: 查询结果对象,包含匹配的组件信息 (ActivityInfo, ServiceInfo, BroadcastReceiverInfo) 以及对应的 IntentFilter 信息。

六、 关键数据结构与机制

  1. Settings 类:
    • 职责: PMS 的持久化状态管理器。是 packages.xmlpackages.list 文件的内存表示和读写接口。
    • packages.xml: XML 文件,存储所有包的详细状态:
      • <package>: 包名、路径、UID、版本、首次安装/最后更新时间、安装者、签名证书、共享 UID。
      • <perms>: 每个包被授予的权限列表(包括运行时授予的 dangerous 权限)。
      • <proper-signing-keyset> / <signing>: 签名信息(Android 9+ 使用 KeySet 管理)。
      • <disabled-components>: 被用户或管理员禁用的组件列表。
      • <enabled-components>: (已废弃)。
      • <preferred-activities>: 用户为特定 Intent 模式设置的首选 Activity。
      • <changed-packages>: 最近更改过的包列表(用于优化广播)。
      • <hidden-system-packages>: 被隐藏的系统包。
      • <install-permissions>: 安装时权限状态(较旧)。
      • <last-platform-version>: 上次安装/升级时的平台版本。
      • <permission-trees> / <permissions>: 系统定义的权限树和权限(补充框架定义)。
      • <shared-user>: 共享 UID 定义及其权限。
      • <special-permissions>: 特殊权限(WRITE_SETTINGS, SYSTEM_ALERT_WINDOW)的授予状态。
      • <updated-package>: 保留旧包信息用于回滚(很少用)。
    • packages.list: 简单文本文件,每行格式 。被 zygoteinstalld 等原生进程快速读取,用于映射包名到 UID 和确定数据目录路径。
    • RuntimePermissions: Android 6.0+ 后,运行时权限的持久化也在这里管理。
    • 同步 (writeLPr): PMS 状态改变后(安装、卸载、权限变更等),需要调用 Settings.writeLPr() 将内存状态同步回 packages.xml。这是一个昂贵的 IO 操作,PMS 主锁 (mLock) 会持有较长时间。
  2. Package / AndroidPackage / ParsedPackage: 内存中表示一个已解析应用的核心接口/类。包含从 AndroidManifest.xml 解析出的所有信息。是 PMS 内部操作的主要对象。
  3. PackageManagerTracedLock (mLock): PMS 内部使用的全局锁(通常是 ReentrantLock)。几乎所有 PMS 的内部操作(扫描、安装、卸载、查询、状态更新)都需要先获取这把锁。这是 PMS 成为性能瓶颈的关键原因之一,尤其是在低端设备上或安装大量应用时。
  4. Installerinstalld: PMS 通过 Installer 这个 Binder 接口与守护进程 installd 通信。installd 以 root 权限运行,执行 PMS 自身(运行在 system_server 的非 root 进程)无法执行的低级文件操作:
    • 创建/删除应用数据目录 (/data/data//, /data/user//, /data/app/ 下的目录)。
    • 设置目录权限和 SELinux 上下文 (chown, chmod, restorecon).
    • 执行 Dex 优化 (dexopt, dex2oat).
    • 管理配置文件的创建 (/data/misc/profiles/cur/0//primary.prof for ART Profile)。
    • 创建/销毁加密存储 (Asec)。
    • 移动应用 (pm move-package).
    • 清除应用数据 (pm clear).
  5. DexManager: (Android 7.0+) 管理应用的 Dex 文件状态(编译过滤器、优化状态、依赖关系),与 ART 和 installd 交互,支持后台 DexOpt (如 bg-dexopt 服务) 和应用动态特性的按需加载。
  6. ApexManager: (Android 10+) 管理 APEX 模块(更新核心系统组件)的安装、激活和版本控制。与 PMS 紧密集成,确保 APEX 中更新的系统模块(如原生库、JAR、配置文件)能被正确加载和覆盖旧版本。
  7. OverlayConfig: 管理系统资源叠加包 (RRO - Runtime Resource Overlay, SRO - Static Resource Overlay) 的配置和启用状态。PMS 在资源查找路径中考虑叠加包。
  8. ComponentNamePackageName: 系统内标识组件和包的稳定方式。

七、 性能考量与优化

  1. 启动耗时: PMS 启动时扫描所有分区是系统启动 (boot) 过程中最耗时的步骤之一。优化包括:
    • 并行扫描: 在支持的设备上,对不同分区进行并行扫描。
    • 缓存: 使用 package-cache.list 等机制减少 XML 解析次数(但需注意缓存一致性)。
    • DexOpt 策略: 使用 speed-profile 等更快的编译过滤器,或在首次启动时延迟部分优化 (bg-dexopt)。
    • 减少 IO: 优化文件系统访问。
  2. 安装/更新耗时:
    • APK 大小与 DexOpt: 大应用优化时间长。Split APKs 有助于按需加载。
    • 签名验证: V1 签名验证慢(需要解压 ZIP),V2/V3/V4 签名验证更快(基于 APK 整体签名块)。
    • IO: 文件拷贝和数据库 (packages.xml) 写入是瓶颈。设备存储性能是关键。
    • PMS 锁 (mLock): 安装操作持有全局锁时间长,阻塞其他 PMS 操作。Google 在持续努力拆分和优化锁粒度(如引入 mInstallLock 处理安装相关操作)。
  3. 查询性能: IntentResolver 的查询效率依赖于其内部数据结构(通常是基于 Intent 属性的 HashMap 组合)。组件数量庞大时,查询可能变慢。
  4. 内存占用: PMS 需要在内存中维护所有已安装应用的 Package 对象及其组件、权限信息。这对拥有大量应用(特别是包含大量组件/权限的应用)的设备是一个挑战。

八、 安全机制深度

  1. Linux UID/GID 隔离: 每个应用分配唯一 UID(或共享 UID),其数据目录 (/data/data//) 和文件权限 (0700) 确保其他应用无法直接访问。PMS 是 UID 分配和目录权限设置的核心。
  2. 签名验证:
    • 完整性: 确保 APK 未被篡改 (V1/V2/V3/V4 签名)。
    • 授权: 系统签名 (android.uid.system) 用于特权操作。signature 权限要求调用者和定义者签名一致。共享 UID 要求签名一致。升级应用要求新签名与旧签名匹配(或兼容升级链)。
    • KeySet Management (Android 9+): 更精细地管理定义权限和依赖权限的应用所使用的签名密钥集。
  3. 权限模型: 如前所述,dangerous 权限的运行时控制是核心安全特性。PMS/PermissionManagerService 是权限授予和检查的执行者。
  4. exported 属性: 组件(Activity, Service, Receiver, Provider)的 android:exported 属性决定它是否能被其他应用启动/绑定/访问。PMS 在组件解析时强制执行此规则。
  5. protectionLevel: 如前所述,不同的保护级别控制着权限的授予严格程度。
  6. SELinux: installd 在创建应用数据目录时设置正确的 SELinux 上下文 (u:object_r:app_data_file:s0:c,c)。PMS 本身也运行在受限的 SELinux 域 (system_server) 中。
  7. 安装来源限制: REQUEST_INSTALL_PACKAGES 权限控制哪些应用可以触发安装未知来源的应用。PackageInstaller 和 Play Protect 提供额外的用户确认和安全扫描。

九、 调试与分析

  1. dumpsys package: 最重要 的工具。输出 PMS 的完整状态:
    • 所有已安装包列表(包名、路径、UID、版本、安装标志、安装来源)。
    • 每个包的详细信息(组件、权限请求/授予、首选项、签名、KeySet)。
    • 权限定义列表。
    • 解析器状态 (IntentResolver)。
    • 共享 UID 信息。
    • 默认应用设置。
    • 叠加包状态。
    • Dex 优化状态。
    • 用户状态。
    • 使用 dumpsys package 获取特定包的详细信息。
  2. dumpsys permission: 更详细地输出权限管理状态。
  3. Logcat: 关键日志标签:
    • PackageManager: 一般 PMS 操作日志。
    • PackageInstaller: 安装会话日志。
    • dex2oat: Dex 优化日志。
    • installd: installd 守护进程的操作日志。
    • 查找错误、警告、安装失败原因。
  4. 文件检查:
    • /data/system/packages.xml, packages.list, packages-stopped.xml (旧版)。
    • /data/app/:用户安装的 APK。
    • /data/data//data/user/:应用私有数据。
    • /data/dalvik-cache/:优化后的 Dex 文件。
  5. pm 命令 (adb shell):
    • pm list packages [options]: 列出包。
    • pm path :显示 APK 路径。
    • pm install/uninstall: 安装/卸载。
    • pm grant/revoke :授予/撤销权限。
    • pm dump :类似 dumpsys package
    • pm clear :清除应用数据。
    • pm set-install-location:设置默认安装位置。
  6. Xposed / Frida: 用于动态 Hook PMS 方法调用,进行深度行为分析(需 root)。

总结

Package Manager Service (PMS) 是 Android 系统的 基石服务。它深刻地影响着系统的:

  • 启动性能: 初始化扫描和优化耗时。
  • 安装体验: 安装、更新、卸载的速度和可靠性。
  • 运行时性能与稳定性: 组件查找效率、权限检查速度、内存占用。
  • 安全性: 应用隔离、权限控制、签名验证的核心执行者。
  • 功能特性: 支持多用户、APEX 更新、资源叠加、按需模块化 (Split APKs, Feature Delivery) 等。

理解 PMS 的内部机制,包括其复杂的启动过程、精细的 APK 解析、严格的权限模型、高效的组件解析、与 installd 的协作、关键数据结构 (Settings, Package) 以及其面临的性能和安全挑战,对于深入掌握 Android 系统工作原理、进行系统级开发、优化 ROM、诊断复杂问题(尤其是安装、权限、组件查找相关)至关重要。它是一个持续演进的复杂系统,Google 在每次 Android 版本更新中都会对其进行优化和功能增强(如权限模型改进、KeySet、APEX、Dex 管理优化等)。