Manifest文件解析过程

一、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:nameandroid:labelandroid: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:保存包的基本信息(包名、版本等)
  • ActivityInfoServiceInfo等组件信息类
  • PermissionInfo:保存声明的权限信息
  • FeatureInfo:保存硬件特性需求

这些信息会被存入 PMS 的内部数据库(通常是内存中的 Map 结构),供以下场景使用:

  • 组件启动:ActivityManager 启动 Activity 时查询 Manifest 声明
  • 权限校验:系统服务检查应用是否声明对应权限
  • 资源加载:根据 Manifest 中的资源引用加载 APK 资源
  • 应用管理:设置界面显示应用信息(版本号、图标等)
五、典型异常处理

PMS 在解析 Manifest 时会处理多种异常情况:

  • 格式错误:如 XML 标签不闭合、属性值格式错误
  • 权限冲突:声明未定义的权限或重复声明
  • 组件配置错误:如 Activity 未声明MAIN action 和LAUNCHER category
  • 版本不兼容:如 targetSdkVersion 高于系统支持版本

遇到严重错误时,PMS 会拒绝安装应用或标记为 "损坏" 状态(如在设置中显示 "应用解析错误")。

六、与其他系统服务的交互

PMS 解析 Manifest 后会与以下服务交互:

  • ResourceManager:关联 Manifest 中的资源 ID 到实际资源
  • PermissionManager:注册或验证应用声明的权限
  • ActivityManager:提供组件信息供 AM 启动时使用
  • WindowManager:获取 Activity 的主题配置用于窗口渲染
七、优化与性能考虑

PMS 解析 Manifest 时的优化手段:

  • 缓存机制:首次解析后缓存 PackageInfo,避免重复解析
  • 增量更新:仅重新解析变更部分(如 Android 5.0 + 的 APK 签名方案 v2 支持)
  • 异步解析:在系统启动时使用后台线程解析 APK,避免阻塞主线程
  • 二进制格式:AXML 格式比文本 XML 解析效率更高
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值