将 gradle 构建工具从 3.6.1 升级到 4.1.0 时,特权应用程序的 dlopen 失败
dlopen failed for privileged app when upgrade gradle build tools from 3.6.1 to 4.1.0
我有一个位于 /system/priv-app/MyTestApp 的应用程序。
android源码环境为AndroidP(API28).
最初,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 有问题。
仍在研究中。
Android 只要 属性 DONT_UNCOMPRESS_PRIV_APPS_DEXS 未定义,构建系统将为特权应用程序解压缩嵌入在 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+ 起,此 属性 的默认值为真。所以应该不是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
我有一个位于 /system/priv-app/MyTestApp 的应用程序。 android源码环境为AndroidP(API28).
最初,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 有问题。
仍在研究中。
Android 只要 属性 DONT_UNCOMPRESS_PRIV_APPS_DEXS 未定义,构建系统将为特权应用程序解压缩嵌入在 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+ 起,此 属性 的默认值为真。所以应该不是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