做高通项目时碰高一个问题:有些apk在32位平台上运行没问题,但是在64位平台上出现crash,出错信息如下:
java.lang.UnsatisfiedLinkError: dlopen failed: "/data/data/com.droidhen.game.racingmototer/.cache/libsecexe.so" is 32-bit instead of 64-bit
at java.lang.Runtime.load(Runtime.java:332)
at java.lang.System.load(System.java:1069)
at com.secneo.guard.ACall.<clinit>(ACall.java:31)
at com.secneo.guard.Util.addProvider(Util.java:52)
at com.droidhen.api.scoreclient.ScoreClientProvider.onCreate(ContentProviderTemplate.java:155)
at android.content.ContentProvider.attachInfo(ContentProvider.java:1748)
at android.content.ContentProvider.attachInfo(ContentProvider.java:1723)
at android.app.ActivityThread.installProvider(ActivityThread.java:5153)
at android.app.ActivityThread.installContentProviders(ActivityThread.java:4748)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4688)
at android.app.ActivityThread.access$1600(ActivityThread.java:150)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1405)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
从crash log 来看好像是apk没有64位下的so库,确实是这样。但,奇怪的是在有些Android6.0 64位系统上同样的apk运行没问题。
后来抓了下log发现,apk在安装的时候。PackageManagerService 会调用 derivePackageAbi 推导apk可用的ABI。如果apk有so文件(32bit),
但找不到合适的ABI,运行时就会crash。初步判断是so的路径有问题。接着分析log,发现非系统的apk并且不支持多架构的,会先找lib文件夹,如果没有lib文件夹就扫描apk的assets
文件夹,来调整支持此apk的ABI。
最后跟到了,在扫描 assets 文件夹的时候 会调用 initAssetsVerifierLib打开一个库(libassetsverifier.so),悲剧的是,平台里面没有 这个库。扫描的结果是,系统认为 此apk没有 native code,也就是 没有so库。
解决办法:
修改 device-vendor.mk 文件添加
COMMON_LIBS := libassetsverifier
PRODUCT_PACKAGES += $(COMMON_LIBS)
将 libassetsverifier.so 编译进系统。问题解决。
涉及到的文件:
PackageManagerService.java
NativeLibraryHelper.java
PackageManager.java
com_android_internal_content_NativeLibraryHelper.cpp
verify_assets.cpp