IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    Android12编译配置Overlay实现机制

    FranzKafka95发表于 2023-10-14 10:59:35
    love 0
    Read Time:2 Minute, 10 Second

    在Android Framework层有很多配置是通过XML的形式进行设置的,以CarService为例,其原生配置位于packages/services/Car/service/res/values/config.xml文件内,里面通常包含了各个子manager的相关配置信息,这里摘录部分:

    <string name="config_evsRearviewCameraId" translatable="false">/dev/video0</string>
    <string name="config_template_activity_class_name">
            androidx.car.app.activity.CarAppActivity
    </string>

    在这个配置中,name指代具体的配置名称,string指代其数据类型,而标签内的内容即为该配置对应的值;在这里我们可以看到,默认的config_evsRearviewCameraId配置为/dev/video0;在CarEvsManager内会通过读取该配置信息,从而打开相应的Camera设备,其相关源码如下所示:

    //packages/services/Car/service/src/com/android/car/evs/CarEvsService.java
    String cameraId;
    if (mUseCameraIdOverride) {
          cameraId = mCameraIdOverride;
    } else {
          cameraId = mContext.getString(R.string.config_evsRearviewCameraId);
       }
    
    if (!nativeOpenCamera(mNativeEvsServiceObj, cameraId)) {
          Slog.e(TAG_EVS, "Failed to open a target camera device");
          return false;
    }

    在我们实际开发时,与硬件相关的配置往往是多样的,依据硬件设计而变化,此时我们就需要来对这些差异项进行管理,使其能够满足我们多样化的需求。而Google其实也早就考虑到了这一点,并在其编译系统内为我们提供了相关了工具,本篇文章将从实践出发,聊聊其Overlay配置的实现机制。

    在面对上面场景时,我们大致要通过以下几个步骤来实现配置管理。

    第一步,我们需要在合适的位置创建overlay文件夹,并递归创建与我们需要overlay配置所同名的文件夹,在此示例中为packages/services/Car/service/res/values/,并创建同名的配置文件config.xml 。故此,完整路径为${SELF_DEFINED_DIR}/overlay/packages/services/Car/service/res/values/config.xml;一般我们为自己的board在device目录下创建属于自己平台的文件夹,并将需要overlay的配置放置到该文件夹内。

    第二步,编辑config.xml,将我们需要进行替换的配置项写入,比如这里我们将config_evsRearviewCameraId配置值由默认的/dev/video0变为/dev/video12:

    <string name="config_evsRearviewCameraId" translatable="false">/dev/video12</string>

    第三步,新建Makefile,一般会与overlay文件夹同级,在该Makefile内,通过PRODUCT_PACKAGE_OVERLAYS或DEVICE_PACKAGE_OVERLAYS关键字来完成替换:

    DEVICE_PACKAGE_OVERLAYS += ${SELF_DEFINED_DIR}/overlay

    完成上述配置之后,我们再进行编译,编译之后得到具体的CarService.apk文件,我们单纯解压该apk文件是无法得到其配置信息的,此时我们可以借助aapt工具来获取apk内的配置信息:

    aapt  dump strings CarService.apk  | grep “evsRearviewCameraId”

    通过这样的方式我们可以直接检验Overlay的配置是否生效;同时我们还会发现,未被替换的配置内容仍旧保持原样,这可以说明overlay并非是简单的文件替换,更像是字段替换,具体的逻辑是如何实现的呢。这里有两个关键的Makefile:

    //build/make/core/package_internal.mk:
    $(wildcard $(foreach dir, $(PRODUCT_PACKAGE_OVERLAYS), \
          $(addprefix $(dir)/, $(LOCAL_RESOURCE_DIR)))))
    device_package_overlays := $(strip \
    $(wildcard $(foreach dir, $(DEVICE_PACKAGE_OVERLAYS), \
          $(addprefix $(dir)/, $(LOCAL_RESOURCE_DIR)))))
    //build/make/core/aapt2.mk:
    my_overlay_resources_flat := \
      $(foreach r, $(my_overlay_resources),\
        $(eval o := $(call aapt2-compiled-resource-out-file,$(r),$(my_compiled_res_base_dir)))\
        $(eval $(call aapt2-compile-one-resource-file-rule,$(r),$(o)))\
        $(o))

    这里面涉及到两个自定义的函数:aapt2-compiled-resource-out-file、aapt2-compile-one-resource-file-rule,者两个自定义的函数我们可以在definitions.mk中找到:

    //build/make/core/definitions.mk
    # Convert input resource file path to output file path.
    # values-[config]/<file>.xml -> values-[config]_<file>.arsc.flat;
    # For other resource file, just replace the last "/" with "_" and
    # add .flat extension.
    #
    # $(1): the input resource file path
    # $(2): the base dir of the output file path
    # Returns: the compiled output file path
    define aapt2-compiled-resource-out-file
    $(strip \
      $(eval _p_w := $(strip $(subst /,$(space),$(dir $(call clean-path,$(1))))))
      $(2)/$(subst $(space),/,$(_p_w))_$(if $(filter values%,$(lastword $(_p_w))),$(patsubst %.xml,%.arsc,$(notdir $(1))),$(notdir $(1))).flat)
    endef
    
    # Set up rule to compile one resource file with aapt2.
    # Must be called with $(eval).
    # $(1): the source file
    # $(2): the output file
    define aapt2-compile-one-resource-file-rule
    $(2) : $(1) $(AAPT2)
    	@echo "AAPT2 compile $$@ <- $$<"
    	$$(call aapt2-compile-one-resource-file)
    endef
    
    define aapt2-compile-one-resource-file
    @mkdir -p $(dir $@)
    $(hide) $(AAPT2) compile -o $(dir $@) $(PRIVATE_AAPT2_CFLAGS) $<
    endef

    Happy
    Happy
    0 0 %
    Sad
    Sad
    0 0 %
    Excited
    Excited
    0 0 %
    Sleepy
    Sleepy
    0 0 %
    Angry
    Angry
    0 0 %
    Surprise
    Surprise
    0 0 %

    The post Android12编译配置Overlay实现机制 first appeared on FranzKafka Blog.



沪ICP备19023445号-2号
友情链接