Android应用中使用到C代码,编译成so文件打包进apk的libs路径下。因为要支持ARMv5和ARMv7,libs下有armeabi和armeabi-v7a两个目录。安全的做法是编译库C代码时,Application.mk中打开,

APP_ABI := armeabi armeabi-v7a

编译生成的两份so文件各自放到项目工程的armeabi/armeabi-v7a目录中。有时还需要针对v7a平台编译支持NEON和不支持NEON的库。譬如这个例子,

in armeabi/: libp.so, libd.so, libvh.so, libvn.so
in armeabi-v7a/: libp.so, libd.so, libd_neon.so, libvh.so, libvn.so

需要注意这一点:The 'armeabi-v7a' machine code will not run on ARMv5 or ARMv6 based devices. 如果损失一些应用的性能是可以接受的,不希望保留库的两份拷贝,可以移除armeabi-v7a目录和其下的库文件,只保留armeabi目录。在安装应用时,行为是这样的,

When installing an application, the package manager service will scan the .apk and look for any shared library of the form:

lib/<primary-abi>/lib<name>.so

If one is found, then it is copied under $APPDIR/lib/lib.so, where $APPDIR corresponds to the application's specific data directory.
If none is found, and a secondary ABI is defined, the service will then scan for shared libraries of the form:

lib/<secondary-abi>/lib<name>.so

If anything is found, then it is copied under $APPDIR/lib/lib.so.

什么是primary abi和secondary abi呢,

The Android system knows at runtime which ABI(s) it supports. More precisely, up to two build-specific system properties are used to indicate:
the 'primary' ABI for the device, corresponding to the machine code used in the system image itself.
an optional 'secondary' ABI, corresponding to another ABI that is also supported by the system image.
For example, a typical ARMv5TE-based device would only define the primary ABI as 'armeabi' and not define a secondary one.
On the other hand, a typical ARMv7-based device would define the primary ABI to 'armeabi-v7a' and the secondary one to 'armeabi' since it can run application native binaries generated for both of them.
This mechanism ensures that the best machine code for the target device is automatically extracted from the package at installation time.

考虑这样一个情况,在打包apk时,armeabi-v7a目录下放了所需的部分so文件。还是上面那个例子,

in armeabi/: libp.so, libd.so, libvh.so, libvn.so
in armeabi-v7a/: libd.so, libd_neon.so

如此,安装运行在v7a的设备上,会发生什么? 尝试了一些手机和平板,CPU都是ARMv7的,Android都是4.x的。行为是拷贝以下库文件到$APPDIR/lib/目录下,

armeabi-v7a/libd.so, armeabi-v7a/libd_neon.so, armeabi/libp.so, armeabi/libvh.so, armeabi/libvn.so

符合特殊需求,libd对性能影响较大,针对ARMv7设备,使用armeabi-v7a的库,其他都使用armeabi的库。
但是遇到在一台ARMv7+Android2.3.4的手机上,加载libp.so报错。
再尝试另一台ARMv7+Android2.3.5的手机,一样的现象。
针对这两台手机,如果打包apk时移除armeabi-v7a目录,不会报错。
难道Android2.3的设备,package manager service的行为有异?