源码编译之系统代码资源Overlay机制

代码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文件

代码添加完成,接下来就需要对其编译脚本进行修改。

  1. 添加原文件到编译系统中

    # 为当前目录层级添加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)
    
  2. 删除编译系统重复的原文件

    # 定义空变量用来字串替换
    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等文件名操作函数见下链接
    
  3. 编译验证

    初始编译环境
    跳转到当前文件下
    mm -B 
    拷贝生成的services.jar,替换文件system/framework/services.jar
    提权,重启查看logcat
    
  4. 参考及扩展链接

    代码overlay机制

    Linux文件名操作函数相关

资源文件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的层级结构

  1. 目录层级如下:

    Overlay层级如下:
    device/mstar/avocado/overlay/frameworks/base/core/res/res/*
    
    原文件目录层级:
    frameworks/base/core/res/res/*
    
  2. 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高

  3. 验证Overlay是否有效

    1. 修改overlay资源下文件下任意资源文件中的配置参数
    2. mm局部编译framework下res资源文件
    3. 拷贝出framework-res.apk查看其中配置文件是否改变
    

小结

通过以上两种方式的Overlay机制,我们可以方便的移植定制我们的系统,一方面保持源码的干净完整,另一方面达到我们定制系统UI功能。

无论是代码overlay还是资源文件overlay,都免不了我们修改编译脚本的过程,其原理也就是使用控制脚本,动态的将原来的编译文件从新用新的文件进行替换,以达到无需修改源码和结构酒客轻松定制出自己的系统。

坚持原创技术分享,您的支持将鼓励我继续创作!