LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES
LOCAL_PREBUILT_LIBS
LOCAL_STATIC_JAVA_LIBRARIES
Android中可能會用到第三方的軟件包,這包括Java包.jar和Native包.so。jar包既可通過Eclipse開發環境集成,也可通過編譯源碼集成,看你的工作環境。
假定自己開發的程序爲MyMaps,需要用到BaiduMaps的庫,包括baidumapapi.jar和libBMapApiEngine_v1_3_1.so。
一、Eclipse中集成第三方jar包及.so動態庫
MyMaps工程下創建目錄libs以及libs/armeabi,把baidumapapi.jar放在的libs/目錄下,把libBMapApiEngine_v1_3_1.so放在libs/armeabi/下。
Eclipse中把第三方jar包baidumapapi.jar打包到MyMaps的步驟:
1. 右擊工程,選擇Properties;
2. JavaBuild Path,選擇Libraries;
3. Libraries頁面點擊右面按鈕“Add Library…”;
4. 選擇“User Library”,點擊“Next”;
5. 點擊“User Libraries”按鈕;
6. 在彈出界面中,點擊“New…”;
7. 輸入“User library name”,點擊“OK”確認;
8. 返回之後,選擇剛剛創建的User library,右面點擊“AddJARs”;
9. 選擇MyMaps/libs/下的baidumapapi.jar;
10. 確認,返回。
這樣,編譯之後,該jar包就會被打進MyMaps.apk中,libBMapApiEngine_v1_3_1.so也被打包在lib/armeabi/中。
程序運行過程中,libBMapApiEngine_v1_3_1.so被放在/data/data/<yourAppPackage>/lib/下,加載動態庫時系統會從程序的該lib/目錄下查找.so庫。
二、源碼中集成第三方集成jar包及.so動態庫
Android源碼中MyMaps放在packages/apps下。
MyMaps下創建目錄libs以及libs/armeabi,並把baidumapapi.jar放在libs/,把libBMapApiEngine_v1_3_1.so放在libs/armeabi。
2.1 修改Android.mk文件
Android.mk文件如下:
1. LOCAL_PATH:= $(call my-dir)
2. include $(CLEAR_VARS)
4. LOCAL_MODULE_TAGS := optional
6. LOCAL_STATIC_JAVA_LIBRARIES := libbaidumapapi
8. LOCAL_SRC_FILES := $(call all-subdir-java-files)
10. LOCAL_PACKAGE_NAME := MyMaps
12. include $(BUILD_PACKAGE)
13.
14. ##################################################
15. include $(CLEAR_VARS)
17. LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES :=libbaidumapapi:libs/baidumapapi.jar
18. LOCAL_PREBUILT_LIBS :=libBMapApiEngine_v1_3_1:libs/armeabi/libBMapApiEngine_v1_3_1.so
19. LOCAL_MODULE_TAGS := optional
20. include $(BUILD_MULTI_PREBUILT)
21.
22. # Use the following include to make our testapk.
23. include $(callall-makefiles-under,$(LOCAL_PATH))
1 集成jar包
LOCAL_STATIC_JAVA_LIBRARIES 取jar庫的別名,可以任意取值;
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES指定prebuiltjar庫的規則,格式:別名:jar文件路徑。注意:別名一定要與LOCAL_STATIC_JAVA_LIBRARIES 裏所取的別名一致,且不含.jar;jar文件路徑一定要是真實的存放第三方jar包的路徑。
編譯用BUILD_MULTI_PREBUILT
2 集成.so動態庫
LOCAL_PREBUILT_LIBS指定prebuilt so的規則,格式:別名:so文件路徑。注意:別名一般不可改變,特別是第三方jar包使用.so庫的情況,且不含.so;so文件路徑一定要是真實的存放第三方so文件的路徑。
編譯拷貝用BUILD_MULTI_PREBUILT。
2.2 加入到GRANDFATHERED_USER_MODULES
在文件user_tags.mk中,把libBMapApiEngine_v1_3_1加入到GRANDFATHERED_USER_MODULES中
1. GRANDFATHERED_USER_MODULES += \
2. … \
3. libBMapApiEngine_v1_3_1
user_tags.mk可以是build/core下的,也可以是$(TARGET_DEVICE_DIR)下的,推薦修改$(TARGET_DEVICE_DIR)下的。
2.3 編譯結果
MyMaps.apk編譯生成在out/target/product/<YourProduct>/system/app/下;
libBMapApiEngine_v1_3_1.so放在out/target/product/<YourProduct>/system/lib/下,這也是系統加載動態庫時搜索的路徑。
附上自己寫的android.mk文件一個
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_STATIC_JAVA_LIBRARIES := lib3party
LOCAL_SRC_FILES := $(call all-subdir-java-files
LOCAL_PACKAGE_NAME := OnlineDownload
include $(BUILD_PACKAGE)
include $(CLEAR_VARS)
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES :=lib3party:libs/android-support-v4.jar
include $(BUILD_MULTI_PREBUILT)
當需要加載多個jar包時,只需要按照mk文件規則,在定義變量的地方先空格,然後輸入”\”符號,然後回車,然後輸入jar包別名就行,附上編譯通過的自己寫的導入多個jar包的mk文件
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_STATIC_JAVA_LIBRARIES := libname1 \
libname2 \
libname3
LOCAL_SRC_FILES := $(callall-subdir-java-files)
LOCAL_PACKAGE_NAME := OnlineDownload
include $(BUILD_PACKAGE)
include $(CLEAR_VARS)
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES :=libname1:libs/android-support-v4.jar \
libname2:libs/commons-net-1.2.2.jar \
libname3:libs/jakarta-oro-2.0.8.jar
include $(BUILD_MULTI_PREBUILT)
LOCAL_MODULE_CLASS and LOCAL_MODULE_PATH
3include $(CLEAR_VARS)
4LOCAL_MODULE := receiver_filter_policy.xml
5LOCAL_MODULE_TAGS := optional
6LOCAL_MODULE_CLASS := ETC
7LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)
8LOCAL_SRC_FILES := $(LOCAL_MODULE)
9include $(BUILD_PREBUILT)
./product/flounder32/obj/ETC/receiver_filter_policy.xml_intermediates
./product/flounder32/obj/ETC/receiver_filter_policy.xml_intermediates/receiver_filter_policy.xml
./product/flounder32/system/etc/receiver_filter_policy.xml
5include $(CLEAR_VARS)
6LOCAL_MODULE := appops
7LOCAL_SRC_FILES := appops
8LOCAL_MODULE_CLASS := EXECUTABLES
9LOCAL_MODULE_TAGS := optional
10include $(BUILD_PREBUILT)
./product/flounder32/obj/EXECUTABLES/appops_intermediates
./product/flounder32/obj/EXECUTABLES/appops_intermediates/appops
./product/flounder32/system/bin/appops
5include $(CLEAR_VARS)
6LOCAL_MODULE := appops
7LOCAL_SRC_FILES := appops
8LOCAL_MODULE_CLASS := EXECUTABLES
9LOCAL_MODULE_TAGS := optional
10include $(BUILD_PREBUILT)
./product/flounder32/obj/EXECUTABLES/appops_intermediates
./product/flounder32/obj/EXECUTABLES/appops_intermediates/appops
./product/flounder32/system/bin/appops
3include $(CLEAR_VARS) 4 5LOCAL_MULTILIB := 32 6LOCAL_SRC_FILES_arm := armeabi/libAlphaInputWrapper.so 9 10LOCAL_MODULE := libAlphaInputWrapper 11LOCAL_MODULE_CLASS := SHARED_LIBRARIES 12LOCAL_MODULE_SUFFIX := .so 13LOCAL_MODULE_TAGS := optional 14 15include $(BUILD_PREBUILT) ./product/flounder32/obj/lib/libAlphaInputWrapper.so ./product/flounder32/obj/SHARED_LIBRARIES/libAlphaInputWrapper_intermediates ./product/flounder32/obj/SHARED_LIBRARIES/libAlphaInputWrapper_intermediates/LINKED/libAlphaInputWrapper.so ./product/flounder32/obj/SHARED_LIBRARIES/libAlphaInputWrapper_intermediates/PACKED/libAlphaInputWrapper.so ./product/flounder32/system/lib/libAlphaInputWrapper.so ./product/flounder32/symbols/system/lib/libAlphaInputWrapper.so
In fireos/prebuilts/middleware/h2clientservice/prebuilts/apk/debug/Android.mk
3# the debug apps are only effective for eng build 4ifneq (,$(filter debug,$(FIREOS_PREBUILT_INSTALL))) if in userdebug build, continue 5 6# enum all the .apk files immediately below current directory 7debug_apps := $(notdir $(wildcard $(LOCAL_PATH)/*.apk)) search for apk file in current folder 8 9# all the debug apps will be signed with the key specified by LOCAL_CERTIFICATE 10# regardless of the original key signed the package with. 11define _add_debug_apps 12include $$(CLEAR_VARS) 13LOCAL_MODULE := $(basename $1) 14LOCAL_SRC_FILES := $1 15LOCAL_MODULE_TAGS := optional 16LOCAL_CERTIFICATE := $(FIREOS_LOCAL_CERTIFICATE_OVERRIDE) 17LOCAL_MODULE_SUFFIX := $$(COMMON_ANDROID_PACKAGE_SUFFIX) 18LOCAL_MODULE_CLASS := APPS 19LOCAL_PRIVILEGED_MODULE := true 20include $$(BUILD_PREBUILT) 21endef 22 23$(foreach _apk, $(debug_apps), \ 24 $(eval $(call _add_debug_apps,$(_apk)))) For each apk file, call _add_debug_apps function, the parameter is the apk path.25 26local_install_packages += $(basename $(debug_apps)) 27 28debug_apps := 29 30endif # ifneq (,$(filter debug,$(FIREOS_PREBUILT_INSTALL))) ./product/flounder32/obj/APPS/com.amazon.h2clientservice_intermediates ./product/flounder32/system/priv-app/com.amazon.h2clientservice ./product/flounder32/system/priv-app/com.amazon.h2clientservice/com.amazon.h2clientservice.apk In fireos/prebuilts/middleware/h2clientservice/prebuilts/jar/Android.mk19_non_dexed_jar_files := com.amazon.h2contracts.jar 21 22# static jar files must be added manually 23_static_jar_files := 24 25# generate install jar file list 26_install_jar_files := $(filter-out $(_static_jar_files),$(_non_dexed_jar_files)) 27 28 29ifneq ($(strip $(SHOW_COMMANDS)),) 30$(info _non_dexed_jar_files=$(_non_dexed_jar_files)) 31$(info _static_jar_files=$(_static_jar_files)) 32$(info _install_jar_files=$(_install_jar_files)) 33endif 34 35 36include $(CLEAR_VARS) 37LOCAL_PREBUILT_JAVA_LIBRARIES := $(_install_jar_files) 38LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := $(_static_jar_files) 39include $(BUILD_MULTI_NONDEX_JAVA_LIBRARIES) 40 41local_install_packages += $(basename $(_install_jar_files))
./product/flounder32/obj/JAVA_LIBRARIES/com.amazon.h2contracts_intermediates
./product/flounder32/system/framework/com.amazon.h2contracts.jar
./common/obj/JAVA_LIBRARIES/com.amazon.h2contracts_intermediates As the jar file may be used by other components, so generate intermediates file for future usage.
In fireos/prebuilts/system/apks/debug/com.amazon.dp.contacts/Android.mk
9LOCAL_MODULE_TAGS := optional 17LOCAL_MODULE := com.amazon.dp.contacts 20LOCAL_CERTIFICATE := $(FIREOS_LOCAL_CERTIFICATE_OVERRIDE) 21 26LOCAL_MODULE_CLASS := APPS 27LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX) 28LOCAL_PRIVILEGED_MODULE := true 39include $(BUILD_PREBUILT)
./product/flounder32/obj/APPS/com.amazon.dp.contacts_intermediates
./product/flounder32/system/priv-app/com.amazon.dp.contacts
./product/flounder32/system/priv-app/com.amazon.dp.contacts/com.amazon.dp.contacts.apk
In In fireos/packages/apps/Precog/Android.mk8LOCAL_MODULE := precog-api 9LOCAL_MODULE_TAGS := optional 10LOCAL_MODULE_CLASS := JAVA_LIBRARIES 11LOCAL_JAVA_LIBRARIES := fireos.sdk.annotations 12 13LOCAL_SRC_FILES := \ 14 src/main/java/com/amazon/precog/api/FeatureCallback.java \ 21include $(BUILD_JAVA_LIBRARY)
./product/flounder32/obj/JAVA_LIBRARIES/precog-api_intermediates
./product/flounder32/system/framework/precog-api.jar
./common/obj/JAVA_LIBRARIES/precog-api_intermediates
In In fireos/packages/apps/FrankDvrServer/test/Android.mk1LOCAL_PATH:= $(call my-dir) 2include $(CLEAR_VARS) 3 4LOCAL_PACKAGE_NAME := FrankMediaServerTest 5LOCAL_MODULE_TAGS := optional 6LOCAL_CERTIFICATE := platform 7LOCAL_PRIVILEGED_MODULE := true 8LOCAL_PROGUARD_ENABLED := disabled 9LOCAL_DEX_PREOPT := false 10 11LOCAL_SRC_FILES := $(call all-java-files-under, src) 15include $(BUILD_PACKAGE)
./product/flounder32/obj/APPS/FrankMediaServerTest_intermediates
./product/flounder32/system/priv-app/FrankMediaServerTest/FrankMediaServerTest.apk
./common/obj/APPS/FrankMediaServerTest_intermediates
In frameworks/opt/vcard/Android.mk16include $(CLEAR_VARS) 19LOCAL_SDK_VERSION := 9 20 21LOCAL_MODULE := com.android.vcard 22LOCAL_SRC_FILES := $(call all-java-files-under, java) 23 24include $(BUILD_STATIC_JAVA_LIBRARY)
./common/obj/JAVA_LIBRARIES/com.android.vcard_intermediates
WITH_DEXPREOPT
所有的 apk 內包含一個 classes.dex 文件。
在 Dalvik上,apk包裏的 dex文件在安裝的時候會通過 dexopt 轉化成另一個格式,叫odex(Opitimized dex),然後存在 /data/dalvik-cache裏面,如:
/data/dalvik-cache/data@[email protected]@classes.dex
雖然文件後綴還是 .dex,但是這個dex和apk內的那個已經不一樣了。這個文件是針對當前機器的硬件對 dex 文件進行了定製化,也就是說把這個放到別的設備上,不一定能運行。
PS: 在要編譯 rom 的時候,如果參數加上 "WITH_DEXPREOPT=true",會在 /system/app/ 下同時生成 .apk 和 .odex 文件(注意,這裏後綴又用的 .odex,但實際上和系統在 /data/dalvik-cache/ 下的 .dex文件是一樣的)
在 ART上,apk 包裏的 dex文件在安裝的時候通過 dex2oat,也會生成一個後綴爲 .dex 的文件,放在 /data/dalvik-cache中,如:
/data/dalvik-cache/arm/system@app@[email protected]@classes.dex
/data/dalvik-cache/arm64/system@vendor@app@[email protected]@classes.dex
這個文件後綴叫 .dex ,但是這個文件又不一樣了,這個既不是 dex 也不是 odex,用 dex2jar 的無法進行反編譯的。文件格式也完全不同,因爲這其實就是一個實打實的 elf文件,這個文件已經可以直接在機器上運行了。
WITH_DEXPREOPT使能編譯時生成 OAT,避免第一次開機時編譯耗時,但會增大 system分區的空間消耗
DONT_DEXPREOPT_PREBUILTS
使能後,將不會對 Android.mk中包含了 include $(BUILD_PREBUILT)的 Apk進行 oat,例如 Gmail,它很可能會在後期通過商店自行升級,而升級後系統中的 oat文件則沒有意義了,但又無法刪除,會造成空間的浪費(oat比dex文件要大)
WITH_DEXPREOPT_BOOT_IMG_ONLY
僅僅針對 boot.img進行oat優化(boot.img中包含 boot.art和 boot.oat)
LOCAL_DEX_PREOPT (from DEX_PREOPT_DEFAULT)
value :
ture | false |
nostripping
可用於各個 Android.mk,對每個 package進行單獨配置,當設置爲 true時,dex文件將會從 apk中剔除,如果不想剔除可使用 nostripping.
PRODUCT_DEX_PREOPT_BOOT_FLAGS
這裏的參數將會傳至 dex2oat,控制 boot.img的編譯優化行爲。
PRODUCT_DEX_PREOPT_DEFAULT_FLAGS
控制除 boot.img 外,其他(如 jar, apk)的 OAT編譯行爲 例如:
PRODUCT_DEX_PREOPT_DEFAULT_FLAGS := --compiler-filter=interpret-only
$(call add-product-dex-preopt-module-config,services,--compiler-filter=space)
WITH_DEXPREOPT_PIC
ture|false
使能 position-independent code,這樣在dex2oat編譯生成的 odex文件在運行時將不必再從 /system 下拷貝到 /data/dalvik-cache/ 目錄下, 可以節省 /data 空間
WITH_ART_SMALL_MODE
true|false
設置爲 true 時,將只編譯處於 boot classpath 裏的類,其他的均不編譯,這樣既能加快第一次開機時間,因爲大部分必要的類已經編譯過了; 同時也能節省不少空間,因爲 APP 都未進行編譯。缺點是可能損失一性能,這可能要平時覺察不出,但在跑分軟件上會有所體現
編譯選項的經典配置
爲了提高第一次開機速度,WITH_DEXPREOPT是必須使能的,這樣則在編譯階段會完成 dex2oat的操作,避免在開機時間去做這個轉碼,節省了開機時間(6min以上縮短2min內)。
但會引起一個缺點,那就是 apk中還是包含了class.dex(dexopt生成的),同時在對應的apk文件夾中又生成了已經轉碼成oat的 class.odex(dex2oat生成的),相當於這部分重複,造成了大量的空間浪費。
爲了把 apk包裏的 class.dex去除,節省空間,可以打開 DEX PREOPT DEFAULT := ture。
然而,這樣開機速度是快了,而且節省了不少system空間,但開機後,我們會發現即使在 system中已經存在 class.odex的 apk,第一次開機後還是會在 /data下面生成 class.odex,如data/dalvik-cache/arm64/system@app@[email protected]@classes.dex,這是何解?原來 Google爲了提高安全性,在每一臺機器開機時都會在之前的機器碼加一個隨機的偏移量,這個偏移量是隨機的,每臺機器都不相同,而 data分區下的這些文件就是從 system下的
class.odex加上偏移而來。
A ref: Android預優化那些事
Our preopt solution
We define a variable USE_FIREOS_DEFAULT_DEXPREOPT. User can set it to "true, false, userdata, cache". If not set, we set the value according to the environment.
367ifeq ($(HOST_OS),linux) 368 ifeq ($(TARGET_BUILD_VARIANT),user) 369 # Use the default dexpreopt parameters for user builds. 370 # Not all devices have sufficient space in system for this 371 # configuration to work on other variants. They will either 372 # not dexpreopt at all (like stock AOSP), or make some compromises 373 # to get some benefit from dexpreopt. 374 USE_FIREOS_DEFAULT_DEXPREOPT ?= userdata 375 else # ! ifeq ($(TARGET_BUILD_VARIANT),user) 376 ifeq ($(TARGET_BUILD_VARIANT),userdebug) 377 USE_FIREOS_DEFAULT_DEXPREOPT ?= userdata 378 endif # ifeq ($(TARGET_BUILD_VARIANT),userdebug) 379 endif # ifeq ($(TARGET_BUILD_VARIANT),user) 380endif # ($(HOST_OS),linux) 381 382# Devices that need a minimal dexpreopt configuration, with only boot.art 383# and boot.oat installed in the system partition should also change the 384# default value of DEX_PREOPT_DEFAULT, typically: 385# DEX_PREOPT_DEFAULT := $(USE_FIREOS_DEFAULT_DEXPREOPT) 386# This will cause non-BOOTCLASSPATH jars and platform applications to 387# get compiled to userdata/cache instead of system. The default value is 388# purposely not overridden here because keeping as much precompiled code 389# in system as possible is optimal for overall storage efficiency and for 390# boot time after system OTA and factory reset. 391 392# Preserve documented AOSP behavior: if WITH_DEXPREOPT is false, we don't 393# want to enable any special FireOS dexpreopt behavior. 394ifeq ($(WITH_DEXPREOPT),false) 395 USE_FIREOS_DEFAULT_DEXPREOPT := 396 DONT_DEXPREOPT_PREBUILTS := true 397 DEXPREOPT_PREBUILTS_INSTALL := false this will be used as default value for LOCAL_DEX_PREOPT 398endif 399 400ifneq ($(USE_FIREOS_DEFAULT_DEXPREOPT),) 401 # shared settings for all FireOS dexpreopt modes 402 ifeq ($(filter-out userdata cache,$(USE_FIREOS_DEFAULT_DEXPREOPT)),) if $(USE_FIREOS_DEFAULT_DEXPREOPT) contain userdata or cache 403 WITH_DEXPREOPT := true 404 # Use this file to indicate that this is a fresh flash. 405 FACTORY_PREOPT_FLAG_FILE := FACTORY_PREOPT 406 # Don't precompile files matching these patterns in 407 # LOCAL_MODULE_PATH. 408 # Note: do not use := here - this must be expanded at use 409 # in order for PRODUCT_OUT to expand correctly. 410 NEVER_DEXPREOPT_DIRS = $(PRODUCT_OUT)/mw_test_apps/% 411 # We should dexpreopt prebuilts unless explicitly overridden 412 DONT_DEXPREOPT_PREBUILTS ?= false 413 endif # ifeq ($(filter-out true userdata cache,$(USE_FIREOS_DEFAULT_DEXPREOPT)),) 414 415 ifeq ($(filter-out userdata,$(USE_FIREOS_DEFAULT_DEXPREOPT)),) if $(USE_FIREOS_DEFAULT_DEXPREOPT) only contain userdata 416 # Install pre-compiled prebuilts to userdata. 417 DEXPREOPT_PREBUILTS_INSTALL := userdata 418 # Unsetting this should compile out run-time entry points for 419 # dalvik-cache in cache. 420 TARGET_DEXOPT_CACHEFS_SPACE_RESERVE := 421 else # ! ifeq ($(filter-out userdata,$(USE_FIREOS_DEFAULT_DEXPREOPT)),) 422 ifeq ($(USE_FIREOS_DEFAULT_DEXPREOPT),cache) if $(USE_FIREOS_DEFAULT_DEXPREOPT) only contain cache 423 # Install pre-compiled prebuilts to cache. 424 DEXPREOPT_PREBUILTS_INSTALL := cache 425 # Space reserved in the cache partition for system OTA use in kilobytes. 426 # Dexopt should leave at least this much space free. 427 TARGET_DEXOPT_CACHEFS_SPACE_RESERVE ?= 256000 428 endif # ifeq ($(USE_FIREOS_DEFAULT_DEXPREOPT),cache) 429 endif # ifeq ($(filter-out userdata,$(USE_FIREOS_DEFAULT_DEXPREOPT)),) 430endif # ifneq ($(USE_FIREOS_DEFAULT_DEXPREOPT),)131# If we don't already have an explicit LOCAL_DEX_PREOPT, set the 132# default from DEXPREOPT_PREBUILTS_INSTALL, if set. 133ifeq ($(LOCAL_DEX_PREOPT),) 134ifneq ($(DEXPREOPT_PREBUILTS_INSTALL),) 135LOCAL_DEX_PREOPT := $(DEXPREOPT_PREBUILTS_INSTALL) 136endif 137endif1354define build-userdataimage-target 1355 $(call pretty,"Target userdata fs image: $(INSTALLED_USERDATAIMAGE_TARGET)") 1356 @mkdir -p $(TARGET_OUT_DATA) 1358 $(if $(DEXPREOPT_PREBUILTS_INSTALL),\ 1359 $(if $(filter-out cache userdata,$(DEXPREOPT_PREBUILTS_INSTALL)),,\ 1360 $(hide) mkdir -p $(TARGET_OUT_DATA)/dalvik-cache/$(TARGET_ARCH) && \ 1361 touch $(TARGET_OUT_DATA)/dalvik-cache/$(TARGET_ARCH)/$(FACTORY_PREOPT_FLAG_FILE) ; \ 1362 $(if $(TARGET_2ND_ARCH),\ 1363 mkdir -p $(TARGET_OUT_DATA)/dalvik-cache/$(TARGET_2ND_ARCH) && \ 1364 touch $(TARGET_OUT_DATA)/dalvik-cache/$(TARGET_2ND_ARCH)/$(FACTORY_PREOPT_FLAG_FILE) \ 1365 ) \ 1366 ) \ 1367 ) ........................ 1380endefLOCAL_DEX_PREOPT initialize
115# Disable dex-preopt of prebuilts to save space, if requested. 116ifeq ($(DONT_DEXPREOPT_PREBUILTS),true) 117LOCAL_DEX_PREOPT := false 118endif 119 120ifneq ($(LOCAL_MODULE_PATH),) 121ifneq ($(NEVER_DEXPREOPT_DIRS),) 122# Test apps that are not pre-installed on the device are pointless to 123# dexpreopt. There may be more cases that should be excluded, so use 124# a general-purpose blacklist. 125ifeq ($(filter-out $(NEVER_DEXPREOPT_DIRS),$(LOCAL_MODULE_PATH)),) if the module path is in the exclusive app list, don't do preopt. 126LOCAL_DEX_PREOPT := false 127endif 128endif 129endif 130 131# If we don't already have an explicit LOCAL_DEX_PREOPT, set the 132# default from DEXPREOPT_PREBUILTS_INSTALL, if set. 133ifeq ($(LOCAL_DEX_PREOPT),) 134ifneq ($(DEXPREOPT_PREBUILTS_INSTALL),) 135LOCAL_DEX_PREOPT := $(DEXPREOPT_PREBUILTS_INSTALL) 136endif 137endif 138 139# Don't use cache space for apps that are installed on userdata if the 140# default will generally write to cache. 141ifneq ($(LOCAL_MODULE_PATH),) 142ifeq ($(LOCAL_DEX_PREOPT)$(filter-out $(TARGET_OUT_DATA)/%,$(LOCAL_MODULE_PATH)), cache) 143LOCAL_DEX_PREOPT := userdata 144endif 145endif207####################################### 208# defines built_odex along with rule to install odex 209include $(BUILD_SYSTEM)/dex_preopt_odex_install.mk 210#######################################284ifeq ($(words $(PRODUCT_RUNTIMES)),1) 285 # If we only have one runtime, we can strip classes.dex by default during dex_preopt 286 DEX_PREOPT_DEFAULT := true 287else 288 # If we have more than one, we leave the classes.dex alone for post-boot analysis 289 DEX_PREOPT_DEFAULT := nostripping 290endif
In dex_preopt_odex_install.mk5# Setting LOCAL_DEX_PREOPT based on WITH_DEXPREOPT, LOCAL_DEX_PREOPT, etc 6LOCAL_DEX_PREOPT := $(strip $(LOCAL_DEX_PREOPT)) 7ifneq (true,$(WITH_DEXPREOPT)) not do dexopt by default 8 LOCAL_DEX_PREOPT := 9else # WITH_DEXPREOPT=true 10 ifeq (,$(TARGET_BUILD_APPS)) # TARGET_BUILD_APPS empty 11 ifndef LOCAL_DEX_PREOPT # LOCAL_DEX_PREOPT undefined 12 ifneq ($(filter $(TARGET_OUT)/%,$(my_module_path)),) # Installed to system.img. 13 ifeq (,$(LOCAL_APK_LIBRARIES)) # LOCAL_APK_LIBRARIES empty 14 # If we have product-specific config for this module? 15 ifeq (disable,$(DEXPREOPT.$(TARGET_PRODUCT).$(LOCAL_MODULE).CONFIG)) 16 LOCAL_DEX_PREOPT := false 17 else 18 LOCAL_DEX_PREOPT := $(DEX_PREOPT_DEFAULT) 19 endif 20 else # LOCAL_APK_LIBRARIES not empty 21 LOCAL_DEX_PREOPT := nostripping 22 endif # LOCAL_APK_LIBRARIES not empty 23 endif # Installed to system.img. 24 endif # LOCAL_DEX_PREOPT undefined 25 endif # TARGET_BUILD_APPS empty 26endif # WITH_DEXPREOPT=true 27ifeq (false,$(LOCAL_DEX_PREOPT)) 28 LOCAL_DEX_PREOPT := 29endif 30ifdef LOCAL_UNINSTALLABLE_MODULE 31LOCAL_DEX_PREOPT := 32endif 33ifeq (,$(strip $(built_dex)$(my_prebuilt_src_file))) # contains no java code 34LOCAL_DEX_PREOPT := 35endif 36# if module oat file requested in data, disable LOCAL_DEX_PREOPT, will default location to dalvik-cache 37ifneq (,$(filter $(LOCAL_MODULE),$(PRODUCT_DEX_PREOPT_PACKAGES_IN_DATA))) 38LOCAL_DEX_PREOPT := 39endif 40# if WITH_DEXPREOPT_BOOT_IMG_ONLY=true and module is not in boot class path skip 41ifeq (true,$(WITH_DEXPREOPT_BOOT_IMG_ONLY)) 42ifeq ($(filter $(DEXPREOPT_BOOT_JARS_MODULES),$(LOCAL_MODULE)),) 43LOCAL_DEX_PREOPT := 44endif 45endif50ifdef LOCAL_DEX_PREOPT 51dexpreopt_boot_jar_module := $(filter $(DEXPREOPT_BOOT_JARS_MODULES),$(LOCAL_MODULE)) 52ifdef dexpreopt_boot_jar_module 53ifeq ($(DALVIK_VM_LIB),libdvm.so) 54built_odex := $(basename $(LOCAL_BUILT_MODULE)).odex 55installed_odex := $(basename $(LOCAL_INSTALLED_MODULE)).odex 56built_installed_odex := $(built_odex):$(installed_odex) 57else # libdvm.so 58# For libart, the boot jars' odex files are replaced by $(DEFAULT_DEX_PREOPT_INSTALLED_IMAGE). 59# We use this installed_odex trick to get boot.art installed. 60installed_odex := $(DEFAULT_DEX_PREOPT_INSTALLED_IMAGE) 61# Append the odex for the 2nd arch if we have one. 62installed_odex += $($(TARGET_2ND_ARCH_VAR_PREFIX)DEFAULT_DEX_PREOPT_INSTALLED_IMAGE) 63endif # libdvm.so 64else # boot jar 65ifeq ($(DALVIK_VM_LIB),libdvm.so) 66built_odex := $(basename $(LOCAL_BUILT_MODULE)).odex 67installed_odex := $(basename $(LOCAL_INSTALLED_MODULE)).odex 68built_installed_odex := $(built_odex):$(installed_odex) 69 70$(built_odex) : $(DEXPREOPT_ONE_FILE_DEPENDENCY_BUILT_BOOT_PREOPT) \ 71 $(DEXPREOPT_ONE_FILE_DEPENDENCY_TOOLS) 72else # libart 74LOCAL_DEX2OAT_TARGET_ARCH := $(DEX2OAT_TARGET_ARCH) 75$(TARGET_2ND_ARCH_VAR_PREFIX)LOCAL_DEX2OAT_TARGET_ARCH := $($(TARGET_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_ARCH) 141ifeq ($(LOCAL_DEX_PREOPT),cache) 142dexpreopt_install_root := $(TARGET_OUT_CACHE)/dalvik-cache/ 143else ifeq ($(LOCAL_DEX_PREOPT),userdata) 144dexpreopt_install_root := $(TARGET_OUT_DATA)/dalvik-cache/ 145else 146dexpreopt_install_root := $(dir $(LOCAL_INSTALLED_MODULE)) 147endif 148 149# Use pattern rule - we may have multiple installed odex files. 150# Ugly syntax - See the definition get-odex-file-path. 151$(installed_odex) : $(dexpreopt_install_root)%$(notdir $(word 1,$(installed_odex))) \ 152 : $(dir $(LOCAL_BUILT_MODULE))%$(notdir $(word 1,$(built_odex))) \ 153 | $(ACP) 154 $(call print-install,$@) #fosmod_build_extensions oneline 155 $(copy-file-to-target) 156endif 159# Add the installed_odex to the list of installed files for this module. 160ALL_MODULES.$(my_register_name).INSTALLED += $(installed_odex) 161ALL_MODULES.$(my_register_name).BUILT_INSTALLED += $(built_installed_odex) 162 163# Make sure to install the .odex when you run "make <module_name>" 164$(my_register_name): $(installed_odex) 165 166endif # LOCAL_DEX_PREOPT220ifdef LOCAL_DEX_PREOPT 222# dexpreopt to cache and userdata should not strip classes.dex 223ifneq ($(filter-out nostripping cache userdata,$(LOCAL_DEX_PREOPT)),) 225 $(call dexpreopt-remove-classes.dex,$@) 226endif 227endif 228 $(align-package) 229 230############################### 231## Rule to build the odex file 232ifdef LOCAL_DEX_PREOPT 233$(built_odex) : $(my_prebuilt_src_file) 234 $(call dexpreopt-one-file,$<,$@) 235endif
odex是從APK中提取出來的可運行文件,即將APK中的class.dex文件通過
dex優化過程將其優化生成odex文件單獨存放。如果沒有odex,系統需要在開機過程中從APK內提取dex再運行;如果在build過程中預先提取,可加快系統啓動速度、節省開機時間。
一般情況下:
User 版本會預先提取有source code的APK的odex文件,因爲有source code的APK在Android.mk中都會通過include $(BUILD_PACKAGE)來編譯,會調用到package.mk來提取odex
但User版本不會預先提取通過prebuilt方式預置的APK的odex文件,因爲採用prebuilt方式預置APK是隻有APK文件而沒有source code時,在Android.mk中通過 include $(BUILD_PREBUILT)預置APK,代碼中原本的prebuilt.mk中不會提取odex。
方法:
實現prebuilt APK提取odex的修改方法如下:修改build/core/prebuilt.mk
1.文件最開始部分添加紅色部分
ifneq (true,$(WITH_DEXPREOPT))
LOCAL_DEX_PREOPT :=
else
ifndef LOCAL_DEX_PREOPT
LOCAL_DEX_PREOPT := $(DEX_PREOPT_DEFAULT)
endif
endif
ifeq (false,$(LOCAL_DEX_PREOPT))
LOCAL_DEX_PREOPT :=
endif
ifeq ($(filter APPS,$(LOCAL_MODULE_CLASS)),)
LOCAL_DEX_PREOPT :=
endif
$(info prebuild $(LOCAL_MODULE)==> $(LOCAL_DEX_PREOPT))
... ...
2.添加紅色部分
... ...
ifdef LOCAL_IS_HOST_MODULE
my_prefix := HOST_
LOCAL_DEX_PREOPT :=
else
my_prefix := TARGET_
endif
... ...
3.添加紅色部分
... ...
ifneq ($(filter APPS,$(LOCAL_MODULE_CLASS)),)
ifdef LOCAL_DEX_PREOPT
$(built_module): $(DEXPREOPT_BOOT_ODEXS) | $(DEXPREOPT) $(DEXOPT)
endif
ifeq ($(LOCAL_CERTIFICATE),PRESIGNED)
# Ensure that presigned .apks have been aligned.
$(built_module) : $(my_prebuilt_src_file) | $(ACP) $(ZIPALIGN)
#$(transform-prebuilt-to-target-with-zipalign)
$(transform-prebuilt-to-target)
ifdef LOCAL_DEX_PREOPT
$(hide) rm -f $(patsubst %.apk,%.odex,$@)
$(call dexpreopt-one-file,$@,$(patsubst %.apk,%.odex,$@))
ifneq (nostripping,$(LOCAL_DEX_PREOPT))
$(call dexpreopt-remove-classes.dex,$@)
endif
endif
$(align-package)
else
# Sign and align non-presigned .apks.
$(built_module) : $(my_prebuilt_src_file) | $(ACP) $(ZIPALIGN) $(SIGNAPK_JAR)
$(transform-prebuilt-to-target)
$(sign-package)
ifdef LOCAL_DEX_PREOPT
$(hide) rm -f $(patsubst %.apk,%.odex,$@)
$(call dexpreopt-one-file,$@,$(patsubst %.apk,%.odex,$@))
ifneq (nostripping,$(LOCAL_DEX_PREOPT))
$(call dexpreopt-remove-classes.dex,$@)
endif
endif
$(align-package)
endif
ifdef LOCAL_DEX_PREOPT
built_odex := $(basename $(built_module)).odex
$(built_odex): $(built_module)
endif
else
... ...
注意:
(1)user build默認開啓dexopt功能,eng build關閉,所以只是build user版本會提取APK的odex文件。
(2)請務必不要忘記把預置的module添加到build/target/product/common.mk(或者[proj].mk)中的PRODUCT_PACKAGES裏面。
(3)只有prebuilt預置APK時會生效,放置在vendor下拷貝的方式來預置APK是不會生效的。