本篇文章只是作为指南引导去看PkMS,不会贴大段代码进行分析,更多是基于方法分析实现的逻辑,另外就是代码是基于Android 11,与Android 10之前代码有比较大的差别。
本文的内容
- PkMS是怎么知道apk的位置
- 系统应用和普通应用的区别
- 应用扫描的过程以及应用信息的保存
PkMS怎么知道apk的位置
答案是按照路径,对于手机用户安装应用都是放在/data/app
,对于系统应用则是分布各个分区中,可以简单的认为是目录,/data
就是data分区,以下的分区都会被扫描,并且只会扫描priv-app和app目录:
- system分区下的priv-app,app目录
/system/priv-app
,/system/app
- product分区
- odm分区
- oem分区
- vendor分区
- system_ext分区
- data分区,最后扫描
不过这些分区都执行不是特别严格,没涉及到gms测试的基本都不怎么管,那么apk是存在什么地方呢?例如:Settings就放在/system_ext/priv-app/Settings/Settings.apk
,其他分区都是类似的,下面分析应用扫描过程还会说到。这里解释一下,为什么要分priv-app和app两个目录进行扫描? priv-app意思是这个目录里面都是privileged应用,可以获取privilege权限,权限的定义frameworks/base/core/res/AndroidManifest.xml
中找到
系统应用和普通应用的区别
答案还是路径,data分区内的应用是普通应用,其他分区安装的应用都是系统应用,系统应用均不可卸载
应用扫描过程
scanDirLI
scanDirLI的几个参数说明一下,
- scanDir,应用目录的集合,以上面Settings为例,目录是
/system_ext/priv-app
- scanFlags,扫描的标志,当为系统应用时,会加上
SCAN_AS_SYSTEM
标志,如果是priv-app目录还要加上SCAN_AS_PRIVILGED
- packageParser,这个就是解析AndroidManifest.xml主要工具类
- executorService,生产者线程
scanDirLI的逻辑比较简单,
- 以上面
/system_ext/priv-app
为例,遍历目录下的每个目录和apk - 使用ExecutorService(线程池)对所有目录和apk进行解析
- 获取ParsedPackage并进行调用
addForInitLI()
addForInitLI
逻辑相当的复杂