PMS 是 Android 框架中最核心、最复杂的服务之一,它负责管理设备上所有应用程序生命周期的核心方面,是系统安全、稳定性和功能性的基石。
核心职责概述
PMS 的核心职责可以概括为:
- 应用安装、卸载与更新: 处理 APK/AAB 文件的复制、解析、验证、优化和数据库记录。
- 应用信息解析与管理: 解析应用的
AndroidManifest.xml,提取组件、权限、特性、元数据等信息,并维护全局数据库(packages.xml,packages.list)。 - 权限管理: 管理权限的定义、授予、撤销和检查,是系统安全模型的关键执行者。
- 组件查询与解析: 根据 Intent 查找匹配的 Activity/Service/BroadcastReceiver/ContentProvider。
- APK 资源管理基础: 提供对已安装应用资源的访问路径(
Resources对象的基础)。 - 系统状态维护: 管理安装位置(内部存储、SD卡)、默认应用设置、用户安装的应用等。
超深度剖析
我们将从多个维度深入 PMS 的内部机制:
一、 启动与初始化 (SystemServer)
- 时机: PMS 在
SystemServer启动过程的早期阶段 (startBootstrapServices) 被创建和启动。这是因为它为其他服务(如ActivityManagerService,UserManagerService)提供应用信息基础。 - 关键步骤:
- 创建 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)。 - 阶段回调: 通知
SystemServerPMS 启动完成,SystemServer继续启动其他服务(如AMS)。
- 创建 PMS 实例:
二、 APK 解析 (PackageParser)
- 目的: 将物理的 APK/AAB 文件(本质是 ZIP)解析为内存中的结构化数据 (
Package/ParsedPackage)。 - 关键过程 (
parseBaseApk):- 解析
AndroidManifest.xml: 使用XmlPullParser解析二进制 XML。 - 填充
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等。
- 资源与 Assets: 创建
AssetManager并加载 APK 资源,验证资源 ID 等(但 PMS 本身不管理运行时资源)。 - 签名验证 (
collectCertificates): 提取 APK 签名 (META-INF/*.RSA/DSA/EC) 并验证其完整性(V1, V2, V3, V4 签名方案)。签名信息是 PMS 安全模型的核心。 - Native 库扫描: 记录 APK 中包含的 native 库 (armeabi-v7a, arm64-v8a, x86 等) 路径。
- 解析
Package对象: 解析的结果是一个复杂的Package对象(或ParsedPackage接口),它是 PMS 内部表示一个应用的核心数据结构。包含所有解析出的信息。
三、 应用安装流程
- 入口点: 通常通过
PackageInstaller应用(系统 UI)、adb (pm install)、Play Store 或其他拥有INSTALL_PACKAGES权限的应用发起。 PackageInstallerService: 处理安装会话的创建、文件拷贝、用户确认(如果需要)。PackageManagerService.installStage: PMS 接收安装请求。- 验证阶段 (
Verification):- 完整性检查: APK 文件校验。
- 权限检查: 调用者是否具有
INSTALL_PACKAGES或REQUEST_INSTALL_PACKAGES(受限安装) 权限。安装位置(内部/SD)权限检查。 - 安装器验证 (可选): 如果请求指定了安装来源 (
installSource),可能触发其他验证服务。
- 拷贝 APK: 将 APK 文件从临时位置(
PackageInstaller会话)拷贝到最终位置:- 用户应用:
/data/app//base.apk(或分拆 APK 的目录/data/app/-*/) - 系统更新/特权应用:可能需要写到特定分区(需 remount rw)。
- 用户应用:
- 解析 (
scanPackageTracedLI): 调用PackageParser解析新安装的 APK,创建新的Package对象。 - 冲突与升级检查:
- 包名冲突: 新安装的包名是否已存在?
- 签名验证 (升级时至关重要):
- 如果存在旧版本,必须验证新 APK 的签名是否与旧 APK 的签名一致(或者属于同一签名密钥的升级链)。签名不匹配是升级失败最常见的原因。
- 共享 UID 应用的签名必须匹配。
- 版本检查: 新版本号必须大于旧版本号(除非是覆盖安装或
adb install -d)。
- 优化 (
performDexOpt): 通过Installer调用installd执行 Dex 优化 (dex2oat),生成 OAT/VDEX/ART 文件到/data/dalvik-cache/或应用的私有目录 (/data/app//oat/)。优化策略(速度、空间、验证)由系统属性控制。 PrepareAppData(installd): 为应用创建私有数据目录 (/data/user/0//),设置正确的 Linux 用户/组 ID (UID/GID) 和 SELinux 上下文 (u:object_r:app_data_file:s0:c,c)。迁移旧数据(如果升级)。- 更新 PMS 内部状态:
- 将新的
Package对象添加到 PMS 内部的各种数据结构(包名映射、组件解析器等)。 - 更新
Settings:将新包的信息(包名、路径、UID、版本、权限、首选项)写入packages.xml和packages.list。 - 处理权限:如果安装时自动授予权限 (
installPermissions),更新授予状态。 - 更新
IntentResolver:添加新包的组件和intent-filter,使它们可被查询。
- 将新的
- 广播通知:
ACTION_PACKAGE_ADDED(如果是新安装) /ACTION_PACKAGE_REPLACED(如果是升级)ACTION_MY_PACKAGE_REPLACED(仅发送给被更新的应用本身)ACTION_PACKAGE_CHANGED(如果组件状态等发生变化)ACTION_PACKAGE_RESTARTED(如果需要重启应用)
- 回调其他服务: 通知
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): 对于normal和signature权限(符合条件时),以及pre23应用的dangerous权限。 - 运行时授予 (
requestPermissions): 对于dangerous权限 (API 23+),由用户决定。记录在packages.xml的<perms>块中。 - ADB 授予 (
pm grant)。
- 安装时授予 (
- 权限检查 (
checkPermission): 当应用尝试执行受权限保护的操作(如启动 Activity、访问 ContentProvider、调用敏感 API)时,由框架(AMS,ContextImpl, WMS 等)调用 PMS 的checkPermission或checkUidPermission方法。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 查找)。
- 工作流程:
- 注册 (
addFilter): 在应用安装/解析时,将其组件声明的<intent-filter>信息添加到对应的IntentResolver。 - 查询 (
queryIntent): 当需要启动组件时 (e.g.,startActivity,bindService,sendBroadcast),框架调用PackageManager.queryIntentActivities/Services/Receivers,最终委托给 PMS 内部的IntentResolver。 - 匹配算法:
- 基于 Intent 属性: 严格匹配 Action、Category、Data (Scheme, MimeType, Path 等)。
- 优先级排序: 根据
<intent-filter>的priority属性排序。 - 系统级过滤: 过滤掉对调用者不可见的组件(根据权限、
exported属性、匹配的 UID 等)。 - 用户级过滤: 过滤掉被用户禁用的组件或应用。
- 返回最佳匹配: 通常返回一个有序列表 (
List),由调用者(如ActivityManagerService)决定最终启动哪个(可能弹出选择器给用户)。
- 注册 (
ResolveInfo: 查询结果对象,包含匹配的组件信息 (ActivityInfo,ServiceInfo,BroadcastReceiverInfo) 以及对应的IntentFilter信息。
六、 关键数据结构与机制
Settings类:- 职责: PMS 的持久化状态管理器。是
packages.xml和packages.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: 简单文本文件,每行格式。被zygote和installd等原生进程快速读取,用于映射包名到 UID 和确定数据目录路径。RuntimePermissions: Android 6.0+ 后,运行时权限的持久化也在这里管理。- 同步 (
writeLPr): PMS 状态改变后(安装、卸载、权限变更等),需要调用Settings.writeLPr()将内存状态同步回packages.xml。这是一个昂贵的 IO 操作,PMS 主锁 (mLock) 会持有较长时间。
- 职责: PMS 的持久化状态管理器。是
Package/AndroidPackage/ParsedPackage: 内存中表示一个已解析应用的核心接口/类。包含从AndroidManifest.xml解析出的所有信息。是 PMS 内部操作的主要对象。PackageManagerTracedLock(mLock): PMS 内部使用的全局锁(通常是ReentrantLock)。几乎所有 PMS 的内部操作(扫描、安装、卸载、查询、状态更新)都需要先获取这把锁。这是 PMS 成为性能瓶颈的关键原因之一,尤其是在低端设备上或安装大量应用时。Installer与installd: 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.proffor ART Profile)。 - 创建/销毁加密存储 (Asec)。
- 移动应用 (
pm move-package). - 清除应用数据 (
pm clear).
- 创建/删除应用数据目录 (
DexManager: (Android 7.0+) 管理应用的 Dex 文件状态(编译过滤器、优化状态、依赖关系),与 ART 和installd交互,支持后台 DexOpt (如bg-dexopt服务) 和应用动态特性的按需加载。ApexManager: (Android 10+) 管理 APEX 模块(更新核心系统组件)的安装、激活和版本控制。与 PMS 紧密集成,确保 APEX 中更新的系统模块(如原生库、JAR、配置文件)能被正确加载和覆盖旧版本。OverlayConfig: 管理系统资源叠加包 (RRO - Runtime Resource Overlay, SRO - Static Resource Overlay) 的配置和启用状态。PMS 在资源查找路径中考虑叠加包。ComponentName与PackageName: 系统内标识组件和包的稳定方式。
七、 性能考量与优化
- 启动耗时: PMS 启动时扫描所有分区是系统启动 (
boot) 过程中最耗时的步骤之一。优化包括:- 并行扫描: 在支持的设备上,对不同分区进行并行扫描。
- 缓存: 使用
package-cache.list等机制减少 XML 解析次数(但需注意缓存一致性)。 DexOpt策略: 使用speed-profile等更快的编译过滤器,或在首次启动时延迟部分优化 (bg-dexopt)。- 减少 IO: 优化文件系统访问。
- 安装/更新耗时:
- APK 大小与
DexOpt: 大应用优化时间长。Split APKs 有助于按需加载。 - 签名验证: V1 签名验证慢(需要解压 ZIP),V2/V3/V4 签名验证更快(基于 APK 整体签名块)。
- IO: 文件拷贝和数据库 (
packages.xml) 写入是瓶颈。设备存储性能是关键。 PMS锁 (mLock): 安装操作持有全局锁时间长,阻塞其他 PMS 操作。Google 在持续努力拆分和优化锁粒度(如引入mInstallLock处理安装相关操作)。
- APK 大小与
- 查询性能:
IntentResolver的查询效率依赖于其内部数据结构(通常是基于 Intent 属性的 HashMap 组合)。组件数量庞大时,查询可能变慢。 - 内存占用: PMS 需要在内存中维护所有已安装应用的
Package对象及其组件、权限信息。这对拥有大量应用(特别是包含大量组件/权限的应用)的设备是一个挑战。
八、 安全机制深度
- Linux UID/GID 隔离: 每个应用分配唯一 UID(或共享 UID),其数据目录 (
/data/data//) 和文件权限 (0700) 确保其他应用无法直接访问。PMS 是 UID 分配和目录权限设置的核心。 - 签名验证:
- 完整性: 确保 APK 未被篡改 (V1/V2/V3/V4 签名)。
- 授权: 系统签名 (
android.uid.system) 用于特权操作。signature权限要求调用者和定义者签名一致。共享 UID 要求签名一致。升级应用要求新签名与旧签名匹配(或兼容升级链)。 - KeySet Management (Android 9+): 更精细地管理定义权限和依赖权限的应用所使用的签名密钥集。
- 权限模型: 如前所述,
dangerous权限的运行时控制是核心安全特性。PMS/PermissionManagerService 是权限授予和检查的执行者。 exported属性: 组件(Activity, Service, Receiver, Provider)的android:exported属性决定它是否能被其他应用启动/绑定/访问。PMS 在组件解析时强制执行此规则。protectionLevel: 如前所述,不同的保护级别控制着权限的授予严格程度。- SELinux:
installd在创建应用数据目录时设置正确的 SELinux 上下文 (u:object_r:app_data_file:s0:c,c)。PMS 本身也运行在受限的 SELinux 域 (system_server) 中。 - 安装来源限制:
REQUEST_INSTALL_PACKAGES权限控制哪些应用可以触发安装未知来源的应用。PackageInstaller和 Play Protect 提供额外的用户确认和安全扫描。
九、 调试与分析
dumpsys package: 最重要 的工具。输出 PMS 的完整状态:- 所有已安装包列表(包名、路径、UID、版本、安装标志、安装来源)。
- 每个包的详细信息(组件、权限请求/授予、首选项、签名、KeySet)。
- 权限定义列表。
- 解析器状态 (IntentResolver)。
- 共享 UID 信息。
- 默认应用设置。
- 叠加包状态。
- Dex 优化状态。
- 用户状态。
- 使用
dumpsys package获取特定包的详细信息。
dumpsys permission: 更详细地输出权限管理状态。- Logcat: 关键日志标签:
PackageManager: 一般 PMS 操作日志。PackageInstaller: 安装会话日志。dex2oat: Dex 优化日志。installd:installd守护进程的操作日志。- 查找错误、警告、安装失败原因。
- 文件检查:
/data/system/packages.xml,packages.list,packages-stopped.xml(旧版)。/data/app/:用户安装的 APK。/data/data/和/data/user/:应用私有数据。/data/dalvik-cache/:优化后的 Dex 文件。
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:设置默认安装位置。
- 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 管理优化等)。