硬件平台:QCS6125
软件平台:Android 11
问题背景:系统版本从低版本升级到高版本后,apk崩溃启动失败。启动失败的activity为apk新增加的组件,报错的信息为:
ActivityNotFoundException: Unable to find explicit activity class {com.yuanfudao.android.megrez.system.settings/com.yuanfudao.android.megrez.launcher.upgrade.activity.AutoUpgradeActivity}; have you declared this activity in your AndroidManifest.xml? - sentry - megrez-app-s2-launcher
表面意思是找不到这个新添加的activity,但是从系统升级之后的apk源文件dump信息看,apk文件是升级成功的,而且如果不是最新的话就不会启动这个新添加的activity,怀疑是此apk的数据缓存未更新,导致系统不识别新增的组件;
1、在PKMS和PackageParser、PackageCacher等类加日志,发现在复现问题的场景下,data分区下apk对应的cache缓存是不更新的,日志线索:
18:33:04.661990 1402 1402 D PackageManager: Keeping known cache f440076f74442ad4fdc9b67da03a644a795c4079
这行日志之所以打印出来,从代码上下文来看,就是升级之后系统fingerprint的hash值较之前旧版本无变化所致,正常情况下,Android每个版本都会对应唯一的fingerprint,不会有高低版本的fingerprint 哈希值一样的情况,即都会打印上述日志的else情况:
08:05:39.665153 1241 1241 D PackageManager: Destroying unknown cache e0ba64a1887994e81e808eab35d295e97ea17523
这样的话系统应用在data分区创建的cache目录就会被删除而从新创建,那新增的组件就会解析成功并写入新的缓存文件,就不会报错;
缓存目录:/data/system/package_cache/指纹哈希值/
也就是说,我们这个高低版本是fingerprint相同的情况,这个问题追述到jenkins编译,启动job时会初始化一个BUILD_NUMBER值,这个值正好跟Android的build系统的名称重复,这就导致Android build系统那一套拼接时间戳的值不会走,因为jenkins一启动就会定义该值,而我们jenkins服务器迁移过,这个值又会从1开始累计,导致前后版本都是16,从而导致fingerprint一致。
2、还有一种情况是,这个问题并不是必现,比如A、B、C从低到高依次三个版本,B、C的fingerprint一致,那么1说的情况就是A->B->C必现更新失败,如果直接刷B,升级C却没有问题,那么这个原因是什么呢?这种情况理论上并不会删除cache跟目录,通过加日志,跟代码,发现fingerprint只是第一道关卡,后边即使cache目录不重建,apk也会逐个比对apk源文件和当前cache文件的时间戳先后,如果源文件更新则更新cache,因此这种情况就解释了为什么fingerprint一致,但也会apk更新成功的问题。
Mark it~~~~