MTK-内置Apk到系统不成功案例分析并解决

提示:MTK-内置Apk到系统不成功案例分析并解决


前言-场景

场景:定制系统中,内置客户apk 作为系统apk,也就是预安装客户apk

  • apk 可能作为普通应用但是不允许卸载、可卸载下恢复出厂设置要求恢复
  • apk 可能是系统LAUNCHER 开机自启
  • 手动安装apk是可以安装成功的

一、实际问题:系统开机后并没有看到内置成功的APK

  • apk 内置成功,编译AOSP后再 out 目录是存在这个apk 的,但是实际开机后并没有看到这个apk。
  • 从用户角度说就是内置不成功;从研发角度就是内置成功但是安装不成功

二、解决方案选型-思路

方案一:静默安装

静默安装实现,这种情况下需要反复验证,方案多样,实现功能即可。但是静默安装的apk 一定是可以被卸载的,不分定制需求达不到要求

方案二:找出安装失败的原因并解决

以MTKAndroid13 版本为例,发现安装失败了,那么就把源码切换到 debug 版本,编译,查看日志到底什么问题

三、实现方案

解决方案

修改文件

/frameworks/base/core/java/android/content/pm/PackageParser.java
/frameworks/base/core/java/android/util/apk/ApkSignatureVerifier.java

实现方案-修改

PackageParser.java 中,去掉V2 签名
在这里插入图片描述

ApkSignatureVerifier.java 中去掉系统标准的判断SIGNING_BLOCK_V2,默认 SignatureSchemeVersion.JAR,如下:
在这里插入图片描述

解决问题步骤分析

1、日志分析

日常开发中,系统工程师都是用的user版本出版本,默认就是user 版本。没法开机后就答应日志,那么先切换到userdebug版本,编译、烧录、打印日志,查看到错误如下:
果然出现在签名上面,日志显示应用签名版本不对 No APK Signature Scheme v2 signature in package /system/app/jst_reeadai/jst_reeadai.apk
在这里插入图片描述

2、查找错误日志关联源码ApkSignatureVerifier.java

搜索大法:grep -rn "No APK Signature Scheme v2 signature in package"

在这里插入图片描述

3、ApkSignatureVerifier 关联点分析-verifyV3AndBelowSignatures方法

根据上面,找到 ApkSignatureVerifier 点对应位置,如下:
路径:frameworks/base/core/java/android/util/apk/ApkSignatureVerifier.java
在这里插入图片描述

反推,分别找到如下调用链代码: verifyV3AndBelowSignatures -> verifySignaturesInternal -> verifySignatures -> unsafeGetCertsWithoutVerification

那么 unsafeGetCertsWithoutVerification 方法是在哪里调用的?
这里就先看 路径:frameworks/base/core/java/android/content/pm/PackageParser.java 文件吧

在这里插入图片描述

4、PackageParser 签名文件方法-unsafeGetCertsWithoutVerification

如上分析,这里就分析 PackageParser 类对应的方法,如下:
在这里插入图片描述

这里最大的收获就是看到了相关的代码:

  • 获取最小的签名SchemeVersionForTaskSDK
  • isStaticSharedLibrary 来判断是否启用 must use v2 signing scheme

在这里插入图片描述

5、PackageParser 签名文件方法去掉must use v2 signing scheme 判断、默认SignatureSchemeVersion.JAR 签名

修改方案如下:
路径:/frameworks/base/core/java/android/content/pm/PackageParser.java 修改如下:
在这里插入图片描述
路径:/frameworks/base/core/java/android/util/apk/ApkSignatureVerifier.java 修改如下:
在这里插入图片描述

优化解决方案-实战修改方案

上面解决方案其实存在一定的局限性:

  • 上面修改方案把所有的APK 软件都给V1签名,这个修改是及其恶心的,不同系统或者Android版本会造成死机问题,有些apk 必须V2 甚至V3 签名才行。

  • 正确的修改方案应该正对性某一个只有V1 签名版本的,单独处理机制最好。

PackageParser 优化单独处理 apk - collectCertificates

路径:/frameworks/base/core/java/android/content/pm/PackageParser.java
如下: 需要V1 签名的应用,根据路径判断,直接设置为V1 签名,
在这里插入图片描述

ApkSignatureVerifier 优化单独处理 apk - verifyV3AndBelowSignatures-直接用V1 签名验证

路径:/frameworks/base/core/java/android/util/apk/ApkSignatureVerifier.java

针对特殊处理的某个apk,直接用V1 签名验证

在这里插入图片描述

解决V1签名应用扫描不到的系统机制

正常情况下,V1 签名的应用 无法扫码到,报错如下: 这个是系统机制决定
在这里插入图片描述
解决方案,更改编译脚本.mk配置:LOCAL_REPLACE_PREBUILT_APK_INSTALLED:= $(LOCAL_PATH)/$(LOCAL_MODULE).apk

完整如下:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# Module name should match apk name to be installed
LOCAL_MODULE := TikTok
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(LOCAL_MODULE).apk
LOCAL_MODULE_CLASS := APPS
LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
LOCAL_CERTIFICATE := PRESIGNED
LOCAL_PRODUCT_MODULE := true
LOCAL_REPLACE_PREBUILT_APK_INSTALLED:= $(LOCAL_PATH)/$(LOCAL_MODULE).apk
##LOCAL_PROPRIETARY_MODULE := true
LOCAL_ENFORCE_USES_LIBRARIES := false
LOCAL_DEX_PREOPT := false
LOCAL_MULTILIB := 64
LOCAL_PREBUILT_JNI_LIBS := $(sort $(shell cd $(LOCAL_PATH) ; find -L lib/arm64-v8a -name "*.so"))
include $(BUILD_PREBUILT)

在这里插入图片描述

四、知识点扩展

签名版本问题

这里了解下签名版本,定义:路径/frameworks/base/core/java/android/content/pm/SigningDetails.java
在这里插入图片描述

签名方案概览

版本引入版本主要特性验证位置向后兼容
JAR (v1)Android 1.0传统 JAR 签名META-INF/所有版本
v2Android 7.0 (API 24)全 APK 完整性保护APK Signing Block
v3Android 9.0 (API 28)密钥轮换支持APK Signing Block
v4Android 11 (API 30)增量安装优化独立 .apk.idsig 文件Android 11+

V1和V2签名对比

特性JAR 签名 (v1)v2 签名 (v2)
签名位置META-INF/ 目录APK Signing Block
完整性保护仅保护文件内容保护整个 APK(包括 ZIP 元数据)
性能逐个文件验证,较慢整体验证,更快
防篡改能力较弱,可修改 ZIP元数据 强,保护所有字节
Android 支持所有版本Android 7.0+
兼容性需要同时包含v1 可单独使用(7.0+)

总结

  • 遇到问题一定要看日志,可能看日志成本蛮高的,后续可以自己写一个日志工具,通过属性来实现是否保存日志
  • 找到问题后,对于签名本身很复杂的问题,在无专业知识情况下根据经验尝试更改下
  • 遇到问题,解决问题时候,多看源码,根据经验靠猜+实践验证,一步一步解决问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

野火少年

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值