package manager service是怎樣選擇armeabi/armeabi-v7a中的庫檔案的?

大頭發表於2013-06-07

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的行為有異?

相關文章