代码overlay机制意思是,将我们在Android原生代码上修改过的文件,单独放在一个目录下,而在编译代码的时候就会去检测这个目录下的文件,如果这个目录下的文件与原生有相同的文件,那么就将这个文件放入编译的源文件中,而将原生相同文件名的文件从编译的源文件中去除。
Overlay
Overlay机制及编译时覆盖,可以解决系统定制时候,代码杂乱冗余结构不清晰的问题。其从机制上无非是对编译脚本Android.mk进行了相关设定,主要设计到源代码的Overlay以及资源文件的Overlay。
代码overlay
代码上的Overlay机制相对繁杂,不仅需要修改对应的编译文件,还需要将Overlay的代码放于指定的目录下。具体示例操作,我们以PowerManagerService为例进行说明:
建立相应overlay文件夹
安卓源码root路径下建立源文件对应的目录层级,顶层文件以overlay命名
原文件目录层级:frameworks/base/services/core/java/com/android/server/power/
新建overlay目录层级:/overlay/frameworks/base/services/core/java/com/android/server/power/
拷贝对应源代码到overlay文件夹下进行定制修改
拷贝PowerManagerService.java文件到新建overlay底层目录下,修改其相应逻辑,例如打开logcat打印开关
private static final String TAG = "PowerManagerService";
private static final boolean DEBUG = true;
修改原文件夹下对应的Android.mk文件
代码添加完成,接下来就需要对其编译脚本进行修改。
添加原文件到编译系统中
# 为当前目录层级添加overlay顶层目录 services_ext_subdirs := $(addprefix ../../../../overlay/, $(LOCAL_PATH)/) $(warning $(services_ext_subdirs)) # 获取新建层级目录下的java文件 services_ext_files := $(call all-java-files-under, $(services_ext_subdirs)) $(warning $(services_ext_files)) # 添加到编译系统中去 LOCAL_SRC_FILES += $(services_ext_files)删除编译系统重复的原文件
# 定义空变量用来字串替换 empty := # 用空字串替换掉services_ext_files中存在的services_ext_subdirs,即得到重复的文件名 services_ext_overlay_files := $(subst $(services_ext_subdirs), $(empty), $(services_ext_files)) $(warning $(services_ext_overlay_files)) # 过滤编译系统中存在的重复文件 LOCAL_SRC_FILES := $(filter-out $(services_ext_overlay_files), $(LOCAL_SRC_FILES))注:
$(warning $(...))用于打印log调试, addprefix等文件名操作函数见下链接编译验证
初始编译环境 跳转到当前文件下 mm -B 拷贝生成的services.jar,替换文件system/framework/services.jar 提权,重启查看logcat参考及扩展链接
资源文件overlay
资源文件的Overlay相比代码Overlay相对简单,一般的定制系统都会建立相应的层级结构,其具体步骤总结如下
为产品添加Overlay目录
资源文件的Overlay方式有两种
Product Overlay PRODUCT_PACKAGE_OVERLAYS
Device Overlay DEVICE_PACKAGE_OVERLAYS
Product Overlay 的优先级高于 Device Overlay
即同一资源下,PRODUCT_PACKAGE_OVERLAYS将覆盖DEVICE_PACKAGE_OVERLAYS
改变Makefile来添加overlay的编译项
为了添加一个overlay目录,需要修改产品的makefile
例如:device/vendor/vendor-name/device-name/product-name.mk
在其中添加以下编译项:
LOCAL_PATH := device/vendor/vendor-name/device-name
$(PRODUCT_PACKAGE_OVERLAYS) := $(LOCAL_PATH)/overlay
OR
$(DEVICE_PACKAGE_OVERLAYS) := $(LOCAL_PATH)/overlay
在对应的overlay目录下创建相对应的资源文件
想覆盖Android系统自带package中的资源文件,那么在overlay目录下必须包含喝替换package相同的路径,该路径是Android源码路径的相对路径
例如我们需要更改一下目录的资源文件:
frameworks/base/core/res/res/values/dimens.xml
那么就需要在overlay路径下创建相同的层级目录及文件:
.../overlay/frameworks/base/core/res/res/values/dimens.xml
修改overlay目录下dimens内容即可在打包时将对应数据替换到原来的资源文件中
使用aapt或者apktool查看对应文件apk中的res是否改变
apktool d. *.apk
下面具体分析一下MSTAR平台下资源文件overlay的层级结构
目录层级如下:
Overlay层级如下: device/mstar/avocado/overlay/frameworks/base/core/res/res/* 原文件目录层级: frameworks/base/core/res/res/*overlay层级下mk文件编译说明
overlay文件下的device-common.mk文件又如下编译项:
DEVICE_SOURCES := device/mstar/avocado LOCAL_KERNEL := $(DEVICE_SOURCES)/kernel PRODUCT_PACKAGE_OVERLAYS := $(DEVICE_SOURCES)/overlay这里可以看出:MSTAR使用的Overlay选项为PRODUCT_PACKAGE_OVERLAYS,其优先级比DEVICE_PACKAGE_OVERLAYS高
验证Overlay是否有效
1. 修改overlay资源下文件下任意资源文件中的配置参数 2. mm局部编译framework下res资源文件 3. 拷贝出framework-res.apk查看其中配置文件是否改变
小结
通过以上两种方式的Overlay机制,我们可以方便的移植定制我们的系统,一方面保持源码的干净完整,另一方面达到我们定制系统UI功能。
无论是代码overlay还是资源文件overlay,都免不了我们修改编译脚本的过程,其原理也就是使用控制脚本,动态的将原来的编译文件从新用新的文件进行替换,以达到无需修改源码和结构酒客轻松定制出自己的系统。