在SD卡版本和ota升级到Q版本的版本差异的时候,发现一个奇怪的问题:
有一个在data/app目录下的apk(com.application.xxxSub),SD卡版本的版本号比OTA升级上来之后的版本号要高
版本之间的差异对比工具可参考:
https://github.com/chadmXiang/CompareVersionDiff/tree/master/tool/start_getdiff.bat
整个分析过程主要解决2个问题:
- apk从哪里来
- apk为什么版本号不一致
1.apk从哪里来
初步分析:通过包名来看,这个应用不是我们预置的apk,应该是预置的某个应用带进来的,通过排查,发现有个apk(com.applicaion.xxx)的包名和data分区下的很像。
刚开始分析的时候,以为是多个apk打包到一个apk,在PMS安装的时候
PackageManagerServices.java文件
http://androidxref.com/9.0.0_r3/xref/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
在如下方法里面添加Log打印
/**
* Scans a package and returns the newly parsed package.
* @throws PackageManagerException on a parse error.
*/
private PackageParser.Package scanPackageChildLI(PackageParser.Package pkg,
final @ParseFlags int parseFlags, @ScanFlags int scanFlags, long currentTime,
@Nullable UserHandle user)
throws PackageManagerException {
// If the package has children and this is the first dive in the function
// we scan the package with the SCAN_CHECK_ONLY flag set to see whether all
// packages (parent and children) would be successfully scanned before the
// actual scan since scanning mutates internal state and we want to atomically
// install the package and its children.
if ((scanFlags & SCAN_CHECK_ONLY) == 0) {
if (pkg.childPackages != null && pkg.childPackages.size() > 0) {
scanFlags |= SCAN_CHECK_ONLY;
}
} else {
scanFlags &= ~SCAN_CHECK_ONLY;
}
// Scan the parent
PackageParser.Package scannedPkg = addForInitLI(pkg, parseFlags,
scanFlags, currentTime, user);
// Scan the children
final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
for (int i = 0; i < childCount; i++) {
PackageParser.Package childPackage = pkg.childPackages.get(i);
addForInitLI(childPackage, parseFlags, scanFlags,
currentTime, user);
}
if ((scanFlags & SCAN_CHECK_ONLY) != 0) {
return scanPackageChildLI(pkg, parseFlags, scanFlags, currentTime, user);
}
return scannedPkg;
}
发现没有相关的打印,方向搞错了。
后来把apk解压后,发现在asserts目录下有一个apk文件,包名就是在data目录下安装的那个应用
2.为什么apk版本号不一样
从结果来看,OTA升级上来的apk,版本号没有更新,应该是从升级前继承过来的,通过和升级瓣版本对比,也确认是一致的
SD卡刷机的apk和assert目录下的版本号是一致的
由于应用是三方的,反编译也不行,只能通过几组测试来排查:
- 删除data下的apk后重启
- root后手动删除data下的文件
- 手动卸载apk
现象都一样,没有重新安装,应该是由某个触发条件来控制是否安装的
2.添加多用户
通过查看Log,每次新建一个用户,都会走一次应用安装流程的,都是通过一个action来启动安装
基本上可以确认和系统的某个状态开关和关系,于是把data/system/users/目录下的3个配置文件全部删除了
- global.xml
- secure.xml
- system.xml
测试发现删除文件和apk后重启,apk重新安装了,应该就是这3个文件里面的某一个配置项引起的
首先排查开机向导,因为每次新建一个用户,都会走一次开机向导,手动把
- user_setup_complete
- device_provisioned
2个配置项的值改一下,重新删除apk后重启,应用重新安装了一次,证明就是这2个配置影响了安装流程,进一步排查,确认是如下配置项影响
user_setup_complete
为了从Log层面证实这个,添加Log打印了了所有rigister这个
Settings.Secure.USER_SETUP_COMPLETE
发现有源apk(com.application.xxx)文件里面有注册监听这个状态值的变化,继续对比测试后发现,是否安装这个应用,也和机器里面是否有安装这个应用有关
整理了一下com.application.xxx安装com.appicatation.xxxSub的流程如下:
- 注册监听Settings.Secure.USER_SETUP_COMPLETE,
- 判断com.application.xxxSub是否安装
完成了开机向导且应用未安装的情况下,才会安装