[RK3399/RK3328][Android7.1.1]当uid=system应用强制使用32位库且默认生成odex时,高概率性导致系统应用Setting等(uid=system应用)找不到库报错

测试平台

Platform: RK3399
OS: Android 7.1.1

现象

编写具有系统权限(uid=system)的apk,由于其中用到第三方so且第三方只有32位,所以我们限制该app仅使用32位so.然后开机大概率出现提示Settings(或其他uid=system应用,如KeyChain)找不到对应的odex文件(类),导致报错,log如下

Process: com.android.keychain, PID: 1177
    java.lang.RuntimeException: Unable to instantiate service com.android.keychain.KeyChainService: java.lang.ClassNotFoundException: Didn't find class "com.android.keychain.KeyChainService" on path: DexPathList[[zip file "/system/app/KeyChain/KeyChain.apk"],nativeLibraryDirectories=[/system/app/KeyChain/lib/arm64, /system/app/KeyChain/KeyChain.apk!/lib/armeabi-v7a, /system/lib, /vendor/lib, /system/lib, /vendor/lib]]
        at android.app.ActivityThread.handleCreateService(ActivityThread.java:3186)
        at android.app.ActivityThread.-wrap5(ActivityThread.java)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1577)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:154)
        at android.app.ActivityThread.main(ActivityThread.java:6157)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:912)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:802)
     Caused by: java.lang.ClassNotFoundException: Didn't find class "com.android.keychain.KeyChainService" on path: DexPathList[[zip file "/system/app/KeyChain/KeyChain.apk"],nativeLibraryDirectories=[/system/app/KeyChain/lib/arm64, /system/app/KeyChain/KeyChain.apk!/lib/armeabi-v7a, /system/lib, /vendor/lib, /system/lib, /vendor/lib]]
        at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:380)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
        at android.app.ActivityThread.handleCreateService(ActivityThread.java:3183)
        at android.app.ActivityThread.-wrap5(ActivityThread.java) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1577) 
        at android.os.Handler.dispatchMessage(Handler.java:102) 
        at android.os.Looper.loop(Looper.java:154) 
        at android.app.ActivityThread.main(Activity

我们遇到的问题是,我们自己编写的应用是系统应用,使用了系统的systemuid,就是和setting的uid是一样的,而且我们是32位apk,setting是64位apk,这样开机的时候经常遇到setting到不到lib库。对应的日志如下。

分析

分析了系统代码,发现从7.1开始系统有一个新特性,就是相同uid的应用会使用相同的lib地址,以uid=system的应用举例.如果使用lib64就都是lib64,如果是lib则都是lib,不能32和64混排。而指定32还是64的是以第一个解析到的uid=system的应用为准,所以当他第一个解析到我们的应用时,发现是指定32位的lib,然后当其他uid=system运行时,他就只会去lib下找对应的类,但是其他的都是arm64的,所以会出现找不到类报错的问题.

解决方案

最好的方案当然是找到64位库(方案1)或者将32位的部分单独封装成一个apk通过aidl来交互(方案2).
但是方案1.部分第三方库只有32位找不到64位所以不行
方案2.有的时候出问题的apk我们并没有源码无法修改,所以也否定。

那么就剩下方案3:

1.在apk对应的android.mk中
LOCAL_DEX_PREOPT := nostripping

2./device/rockchip/rk3399/BoardConfig.mk,
DEX_PREOPT_DEFAULT := nostripping 

方案3的意思是生成odex时,不会从apk里面把classes.dex抽取出来,这样查找不到lib下的odex时,可以解析apk中的classes.dex,从而不会报错.

但是这样也有缺点,会导致固件体积变大,没有其他更好的办法先这样解决吧。

你可能感兴趣的:(Android)