一、PMS 解析 Manifest 的核心时机与入口
PMS 对 Manifest 的解析主要发生在以下场景:
- 系统启动阶段:扫描 /system/app、/vendor/app 等系统目录中的 APK
- 应用安装时:通过 PackageInstaller 安装新 APK 时
- 应用更新时:覆盖安装或增量更新时
- 手动触发扫描:如通过
pm scan命令触发
核心入口方法是PackageManagerService.scanPackageLI,该方法会根据 APK 路径解析 Manifest 并构建 PackageInfo 对象。
二、解析流程的关键阶段
1. APK 文件校验与提取
- 校验 APK 完整性:验证签名、文件结构是否合法
- 提取 Manifest 二进制数据:从 APK 的
AndroidManifest.xml文件中读取编译后的二进制 XML 数据(AXML 格式) - 解码 AXML:将二进制 XML 转换为可解析的节点结构,使用
XmlBlock类处理
2. 核心解析逻辑:从 XML 到 PackageInfo
PMS 通过PackageParser类解析 Manifest,关键步骤如下:
// PackageParser.parsePackage()核心流程简化
public Package parsePackage(File packageFile, int flags) {
// 1. 读取APK中的AndroidManifest.xml二进制数据
byte[] data = readApkFile(packageFile, "AndroidManifest.xml");
// 2. 解析AXML为XmlBlock对象
XmlBlock block = new XmlBlock(data);
XmlNode manifestNode = block.getRootNode();
// 3. 解析根节点<manifest>
String packageName = manifestNode.getAttributeValue(null, "package");
int versionCode = parseInt(manifestNode.getAttributeValue(null, "android:versionCode"));
String versionName = manifestNode.getAttributeValue(null, "android:versionName");
// 4. 解析<application>节点及子组件
XmlNode applicationNode = findNode(manifestNode, "application");
parseApplication(applicationNode, package);
// 5. 解析四大组件
parseComponents(manifestNode, package); // 解析activity/service/receiver/provider
// 6. 解析权限
parsePermissions(manifestNode, package);
// 7. 解析其他声明(如uses-sdk、uses-feature等)
parseSdkVersion(manifestNode, package);
parseFeatures(manifestNode, package);
// 8. 构建PackageInfo对象并返回
return createPackageInfo(package, flags);
}
3. 组件解析的深度逻辑
以 Activity 解析为例,PMS 会:
- 提取
android:name、android:label、android:theme等属性 - 解析 IntentFilter(如
<action>、<category>、<data>) - 解析权限声明(
android:permission) - 记录组件间的依赖关系(如 Activity 的父 Activity 配置)
4. 权限与资源关联
- 解析
uses-permission标签,验证权限是否在系统中注册 - 解析
uses-feature标签,记录硬件 / 软件特性需求 - 关联 Manifest 中的资源引用(如
android:icon)到 APK 中的实际资源文件
三、AXML 格式的特殊处理
Android 的 Manifest 会被编译为二进制 AXML 格式,相比普通 XML:
- 结构优化:使用偏移量引用字符串池,减少文件体积
- 解析效率:二进制格式更适合系统快速解析
- 关键结构:
- StringPool:存储所有字符串常量的索引表
- ResourceIdPool:存储资源 ID(如 android:id="@+id/name")
- XmlNode 结构:每个节点包含标签名、属性列表、子节点引用
PMS 通过XmlBlock类解析 AXML,核心方法包括:
getStringReference(int index):从字符串池获取字符串getAttributeIntValue(int namespace, int name):获取属性的 int 值getChildNodes():获取子节点列表
四、解析结果的存储与使用
解析后的信息会存储在以下数据结构中:
- PackageInfo:保存包的基本信息(包名、版本等)
- ActivityInfo、ServiceInfo等组件信息类
- PermissionInfo:保存声明的权限信息
- FeatureInfo:保存硬件特性需求
这些信息会被存入 PMS 的内部数据库(通常是内存中的 Map 结构),供以下场景使用:
- 组件启动:ActivityManager 启动 Activity 时查询 Manifest 声明
- 权限校验:系统服务检查应用是否声明对应权限
- 资源加载:根据 Manifest 中的资源引用加载 APK 资源
- 应用管理:设置界面显示应用信息(版本号、图标等)
五、典型异常处理
PMS 在解析 Manifest 时会处理多种异常情况:
- 格式错误:如 XML 标签不闭合、属性值格式错误
- 权限冲突:声明未定义的权限或重复声明
- 组件配置错误:如 Activity 未声明
MAINaction 和LAUNCHERcategory - 版本不兼容:如 targetSdkVersion 高于系统支持版本
遇到严重错误时,PMS 会拒绝安装应用或标记为 "损坏" 状态(如在设置中显示 "应用解析错误")。
六、与其他系统服务的交互
PMS 解析 Manifest 后会与以下服务交互:
- ResourceManager:关联 Manifest 中的资源 ID 到实际资源
- PermissionManager:注册或验证应用声明的权限
- ActivityManager:提供组件信息供 AM 启动时使用
- WindowManager:获取 Activity 的主题配置用于窗口渲染
七、优化与性能考虑
PMS 解析 Manifest 时的优化手段:
- 缓存机制:首次解析后缓存 PackageInfo,避免重复解析
- 增量更新:仅重新解析变更部分(如 Android 5.0 + 的 APK 签名方案 v2 支持)
- 异步解析:在系统启动时使用后台线程解析 APK,避免阻塞主线程
- 二进制格式:AXML 格式比文本 XML 解析效率更高


1192

被折叠的 条评论
为什么被折叠?



