一.overlay 介绍
Android overlay 机制允许在不修改packages中apk的情况下,来自定义 framework和package中的资源文件,实现资源的定制。来达到显示不同的UI的目的.
二.overlay编译流程分析
1.添加overlay 目录
1.1 Product Overlays与Device Overlays
有两种不同的overaly目录定义,来影响最终的效果:
PRODUCT_PACKAGE_OVERLAYS: used by a particular product
DEVICE_PACKAGE_OVERLAYS: used several products that share a common device model
如果包含同一资源,那么 PRODUCT_PACKAGE_OVERLAYS 将覆盖 DEVICE_PACKAGE_OVERLAYS 中的。
PRODUCT_PACKAGE_OVERLAYS 和 DEVICE_PACKAGE_OVERLAYS 功能是一样的,只是优先级不一样:PRODUCT_PACKAGE_OVERLAYS 优先于 DEVICE_PACKAGE_OVERLAYS。
添加overlay目录,为了添加一个overlay目录, 需要修改产品的makefile:
例:
#/device/s3graphics/zx2000/zx2k_hdtv.mk
334 # overlay
335 DEVICE_PACKAGE_OVERLAYS := \
336 device/s3graphics/zx2000/overlay \
337 device/s3graphics/zx2000/overlay/location
2.在overlay目录下创建资源文件
想覆盖Android系统自带package中资源文件, 那么在overlay目录下必须包含和要替换package相同的路径, 该路径是Android源码目录的相对路径.
例:如果我们想要替换以下目录的资源文件: /frameworks/base/core/res/res/values/ 那么在overlay目录下面必须创建一样的目录:/device/s3graphics/zx2000/overlay/frameworks/base/core/res/res/values/
然后放入想要替换的资源(必须和系统package相同路径和文件名)。
3. 编译流程
#/frameworks/base/core/res/Android.mk
16 LOCAL_PATH := $(call my-dir)
#/build/core/package_internal.mk
86 ifeq (,$(LOCAL_RESOURCE_DIR))
87 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
88 else
89 need_compile_res := true
90 endif
93 package_resource_overlays := $(strip \
94 $(wildcard $(foreach dir, $(PRODUCT_PACKAGE_OVERLAYS), \
95 $(addprefix $(dir)/, $(LOCAL_RESOURCE_DIR)))) \
96 $(wildcard $(foreach dir, $(DEVICE_PACKAGE_OVERLAYS), \
97 $(addprefix $(dir)/, $(LOCAL_RESOURCE_DIR)))))
101 LOCAL_RESOURCE_DIR := $(package_resource_overlays) $(LOCAL_RESOURCE_DIR)
为每一个$(LOCAL_RESOURCE_DIR)目录添加$(DEVICE_PACKAGE_OVERLAYS)前缀。
编译执行结果:
package_resource_overlays= device/s3graphics/zx2000/overlay/frameworks/base/core/res/res device/s3graphics/zx2000/overlay/location/frameworks/base/core/res/res
然后将本地resource目录和overlay resource 目录加进 LOCAL_RESOURCE_DIR 中。
编译执行结果:
LOCAL_RESOURCE_DIR=device/s3graphics/zx2000/overlay/frameworks/base/core/res/res ,device/s3graphics/zx2000/overlay/location/frameworks/base/core/res/res , frameworks/base/core/res/res
使用aapt 工具对资源文件进行打包:
#/build/core/package_internal.mk
$(resource_export_package): $(all_res_assets) $(full_android_manifest) $(RenderScript_file_stamp) $(AAPT)
$(create-empty-package)
$(add-assets-to-package)
endif
#/build/core/definitions.mk
define add-assets-to-package
$(hide) $(AAPT) package -u $(PRIVATE_AAPT_FLAGS) \
$(addprefix -c , $(PRIVATE_PRODUCT_AAPT_CONFIG)) \
$(addprefix --preferred-density , $(PRIVATE_PRODUCT_AAPT_PREF_CONFIG)) \
$(addprefix -M , $(PRIVATE_ANDROID_MANIFEST)) \
$(addprefix -S , $(PRIVATE_RESOURCE_DIR))\
$(addprefix -A , $(PRIVATE_ASSET_DIR)) \
$(addprefix -I , $(PRIVATE_AAPT_INCLUDES)) \
$(addprefix --min-sdk-version , $(PRIVATE_DEFAULT_APP_TARGET_SDK)) \
$(addprefix --target-sdk-version , $(PRIVATE_DEFAULT_APP_TARGET_SDK)) \
$(if $(filter --product,$(PRIVATE_AAPT_FLAGS)),,$(addprefix --product , $(TARGET_AAPT_CHARACTERISTICS))) \
$(if $(filter --version-code,$(PRIVATE_AAPT_FLAGS)),,$(addprefix --version-code , $(PLATFORM_SDK_VERSION))) \
$(if $(filter --version-name,$(PRIVATE_AAPT_FLAGS)),,$(addprefix --version-name , $(PLATFORM_VERSION)-$(BUILD_NUMBER))) \
$(addprefix --rename-manifest-package , $(PRIVATE_MANIFEST_PACKAGE_NAME)) \
$(addprefix --rename-instrumentation-target-package , $(PRIVATE_MANIFEST_INSTRUMENTATION_FOR)) \
-F $@
endef
通过以上代码分析最终通过最终通过 aapt -S $(PRIVATE_RESOURCE_DIR) 将res内容加入到 framework-res.apk 中。
#/build/core/base_rules.mk
404 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_RESOURCE_DIR := $(LOCAL_RESOURCE_DIR)
405 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_ASSET_DIR := $(LOCAL_ASSET_DIR)
406 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_STATIC_JAVA_LIBRARIES := $(full_static_java_libs)
由于:PRIVATE_RESOURCE_DIR := $(LOCAL_RESOURCE_DIR)
因此最终执行的命令展开的结果为:
aapt -S device/s3graphics/zx2000/overlay/frameworks/base/core/res/res device/s3graphics/zx2000/overlay/location/frameworks/base/core/res/res frameworks/base/core/res/res
aapt :
-S directory in which to find resources. Multiple directories will be scanned
and the first match found (left to right) will take precedence.
总结:如果DEVICE_PACKAGE_OVERLAYS 里面定义多个目录,如果只修改其中一个目录里的配置文件,那么无论改哪个目录修改都会生效。如果多个目录同时修改,那么最前面定义的那个目录将生效。