问题描述
我有一个位于 /system/priv-app/MyTestApp 中的应用程序。 android源代码环境为Android P(API 28)。
起初,MyTestApp.apk 是使用 gradle 构建工具 3.6.1 构建的。然后我将它升级到 4.1.0 并构建一个新的 MyTestApp.apk 并在 rom 中预构建它。所以崩溃发生了。
E AndroidRuntime: java.lang.UnsatisfiedLinkError: dlopen Failed: library "/system/priv-app/MyTestApp/MyTestApp.apk!/lib/armeabi-v7a/libmytest.so" not found
E AndroidRuntime: at java.lang.Runtime.loadLibrary0(Runtime.java:1016)
E AndroidRuntime: at java.lang.System.loadLibrary(System.java:1669)
我拉取文件/system/priv-app/MyTestApp/MyTestApp.apk,解压后发现libmytest.so存在。这肯定是由 gradle 构建工具升级引起的。但我找不到原因。有人可以帮忙吗?
解决方法
查看源代码后,我发现在bionic/linker/linker.cpp
if (entry.method != kCompressStored || (entry.offset % PAGE_SIZE) != 0) {
close(fd);
return -1;
}
entry.offset % PAGE_SIZE != 0 此条件失败。
所以我猜 AGP 4.1+ 的 zipalign 有问题。
还在研究中。
,只要未定义属性 DONT_UNCOMPRESS_PRIV_APPS_DEXS,Android 构建系统就会为特权应用解压嵌入在 apk 中的 dex 文件。解压定义如下
# Uncompress dex files embedded in an apk.
#
define uncompress-dexs
$(hide) if (zipinfo $@ '*.dex' 2>/dev/null | grep -v ' stor ' >/dev/null) ; then \
tmpdir=$@.tmpdir; \
rm -rf $$tmpdir && mkdir $$tmpdir; \
unzip -q $@ '*.dex' -d $$tmpdir && \
zip -qd $@ '*.dex' && \
( cd $$tmpdir && find . -type f | sort | zip -qD -X -0 ../$(notdir $@) -@ ) && \
rm -rf $$tmpdir; \
fi
endef
使用AGP 4.0构建apk时,解压dexs后,通过zipalign工具可以验证成功。
zipalign -v -c -p 4 MyTestApp.apk
但是当使用 AGP 4.1+(也包括 7.0-alpha)构建时,它无法通过 zipalign 工具进行验证。
但是我还没有找到原因。只是猜测 AGP 4.1+ 中的 apk 存档有一些新的变化。
,android.useNewApkCreator=false
在 gradle.properties 中添加这一行可以解决这个问题。
但是从 AGP 3.6+ 开始,这个属性的默认值为 true。所以应该不是AGP 4.0和AGP 4.1的区别。
我很困惑。可能还有一些其他条件才能生效。
,参考最新代码,uncompress-dexs 方法如下
https://android.googlesource.com/platform/build/+/master/core/definitions.mk#2385
# Uncompress dex files embedded in an apk.
#
define uncompress-dexs
if (zipinfo $@ '*.dex' 2>/dev/null | grep -v ' stor ' >/dev/null) ; then \
$(ZIP2ZIP) -i $@ -o $@.tmp -0 "classes*.dex" && \
mv -f $@.tmp $@ ; \
fi
endef