framework-res.apk覆盖编译方式由RRO替换为SRO

本文深入解析了Android系统中资源替换的两种机制:运行时Overlay(RRO)与静态Overlay(SRO),并探讨了它们之间的关键区别。通过具体实例,展示了如何在Android O版本中解决资源覆盖问题,包括修改编译策略以实现资源的定制替换。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、问题描述:

android O版本,默认指定了framework-res编译时使用RRO的形式加载资源覆盖,这就导致一些 reference resource 类型的文件,如layout、anim、xml目录中的xml文件,在overlay目录不能进行覆盖,编译时会出现很多类似于

device/bbkedu/H6000/overlay/frameworks/base/core/res/res/layout/safe_mode.xml:17: error: Error: No resource found that matches the given name (at 'background' with value '@drawable/safe_mode_background').

但是我们的systemUI需要定制这些reference resource,所以需要将RRO编译更改为SRO。

二、SRO,RRO相关定义与区别。

1.SRO

即静态Overlay,发生在编译时,需要在Android系统源码环境中进行配置。

2.RRO

即运行时Overlay,该机制的资源替换发生在运行时。

3.区别:

(1)RRO能直接定制替换第三方APK的资源,而不需要其源码。SRO如上节所述,则需要对应APK的源码才能完成,一般而言,第三方是不会提供项目源码的。
(2)RRO的编译结果会得到一个xxx_overlay.apk,加上原项目的apk,总共会有2个apk,而SRO最终只会得到一个已经完成资源替换的apk。得到的overlay.apk可以视为一个正常的apk,因为它能被安装,含有自己的AndroidManifest.xml文件,当然正常下,overlay.apk是不含有执行代码的。
(3)RRO不能替换AndroidManifest.xml文件及reference resource 类型的文件,如layout、anim、xml目录中的xml文件。虽然RRO具有自己的AndroidManifest.xml文件,但它却不能替换源项目中的AndroidManifest.xml文件。关于layout目录中的xml文件,SRO是可以替换的。
以上来源于GrayMonkey:Android Overlay机制


三、RRO是如何引入的

直接看一下几个mk文件:
**device/mediatek/common/device.mk
build/core/definitions.mk
build/core/package_internal.mk**
详细改动如下:

1.device/mediatek/common/device.mk
PRODUCT_ENFORCE_RRO_TARGETS += framework-res

2.build/core/definitions.mk
###########################################################
# Append the information to generate a RRO package for the
# source module.
#
#  $(1): Source module name.
#  $(2): Whether $(3) is a manifest package name or not.
#  $(3): Manifest package name if $(2) is true.
#        Otherwise, android manifest file path of the
#        source module.
#  $(4): Whether LOCAL_EXPORT_PACKAGE_RESOURCES is set or
#        not for the source module.
#  $(5): Resource overlay list.
###########################################################
define append_enforce_rro_sources
  $(eval ENFORCE_RRO_SOURCES += \
      $(strip $(1))||$(strip $(2))||$(strip $(3))||$(strip $(4))||$(call normalize-path-list, $(strip $(5))))
endef

3.build/core/package_internal.mk
enforce_rro_enabled :=
ifneq ($(PRODUCT_ENFORCE_RRO_TARGETS),)
  ifneq ($(package_resource_overlays),)
    ifeq ($(PRODUCT_ENFORCE_RRO_TARGETS),*)
      enforce_rro_enabled := true
    else ifneq (,$(filter $(LOCAL_PACKAGE_NAME), $(PRODUCT_ENFORCE_RRO_TARGETS)))
      enforce_rro_enabled := true
    endif
  endif
  ifdef enforce_rro_enabled
    ifeq (,$(LOCAL_MODULE_PATH))
      ifeq (true,$(LOCAL_PROPRIETARY_MODULE))
        enforce_rro_enabled :=
      else ifeq (true,$(LOCAL_OEM_MODULE))
        enforce_rro_enabled :=
      else ifeq (true,$(LOCAL_ODM_MODULE))
        enforce_rro_enabled :=
      endif
    else ifeq ($(filter $(TARGET_OUT)/%,$(LOCAL_MODULE_PATH)),)
      enforce_rro_enabled :=
    endif
  endif
endif
ifdef enforce_rro_enabled
  ifneq ($(PRODUCT_ENFORCE_RRO_EXCLUDED_OVERLAYS),)
    static_only_resource_overlays := $(filter $(addsuffix %,$(PRODUCT_ENFORCE_RRO_EXCLUDED_OVERLAYS)),$(package_resource_overlays))
    ifneq ($(static_only_resource_overlays),)
      package_resource_overlays := $(filter-out $(static_only_resource_overlays),$(package_resource_overlays))
      LOCAL_RESOURCE_DIR := $(static_only_resource_overlays) $(LOCAL_RESOURCE_DIR)
      ifeq ($(package_resource_overlays),)
        enforce_rro_enabled :=
      endif
    endif
  endif
else
LOCAL_RESOURCE_DIR := $(package_resource_overlays) $(LOCAL_RESOURCE_DIR)
endif
ifdef enforce_rro_enabled
  ifdef LOCAL_EXPORT_PACKAGE_RESOURCES
    enforce_rro_use_res_lib := true
  else
    enforce_rro_use_res_lib := false
  endif
  ifdef LOCAL_MANIFEST_PACKAGE_NAME
    enforce_rro_is_manifest_package_name := true
    enforce_rro_manifest_package_info := $(LOCAL_MANIFEST_PACKAGE_NAME)
  else
    enforce_rro_is_manifest_package_name := false
    enforce_rro_manifest_package_info := $(full_android_manifest)
  endif
$(call append_enforce_rro_sources, \
    $(my_register_name), \
    $(enforce_rro_is_manifest_package_name), \
    $(enforce_rro_manifest_package_info), \
    $(enforce_rro_use_res_lib), \
    $(package_resource_overlays) \
    )
endif  # enforce_rro_enabled

四、修改策略

1.移除 PRODUCT_ENFORCE_RRO_TARGETS += framework-res,仍然使用SRO进行编译,移除后出现报错

out/target/product/H6000/obj/APPS/framework-res_intermediates/flat-res/device/mediatek/common/overlay/telephony/frameworks/base/core/res/res/values-mcc310-mnc260_strings.arsc.flat: error: resource array/wfcOperatorErrorCodes does not override an existing resource.
out/target/product/H6000/obj/APPS/framework-res_intermediates/flat-res/device/mediatek/common/overlay/telephony/frameworks/base/core/res/res/values-mcc310-mnc260_strings.arsc.flat: note: define an <add-resource> tag or use --auto-add-overlay.
error: failed parsing overlays.

从报错信息可以知道,缺少了–auto-add-overlay,于是加上,这时候又一次出错。
这里写图片描述
于是查看了下N版本上framework-res的Android.mk配置,对比发现缺少 -x 这个aapt flag
这里写图片描述


五、最后修改如下:

diff --git a/device/mediatek/common/device.mk b/device/mediatek/common/device.mk
index 8fb4086..d3ad649 100644
--- a/device/mediatek/common/device.mk
+++ b/device/mediatek/common/device.mk
@@ -3347,7 +3347,7 @@ ifneq ($(strip $(MTK_BASIC_PACKAGE)), yes)
DEVICE_PACKAGE_OVERLAYS += device/mediatek/common/overlay/wifitethering_channel
endif

-PRODUCT_ENFORCE_RRO_TARGETS += framework-res
+#PRODUCT_ENFORCE_RRO_TARGETS += framework-res

# Add vendor minijail policy for mediacodec service for Android O
PRODUCT_COPY_FILES += device/mediatek/common/seccomp_policy/mediacodec.policy:$(TARGET_COPY_OUT_VENDOR)/etc/seccomp_policy/mediacodec.policy:mtk
diff --git a/frameworks/base/core/res/Android.mk b/frameworks/base/core/res/Android.mk
index b066929..43c7f96 100644
--- a/frameworks/base/core/res/Android.mk
+++ b/frameworks/base/core/res/Android.mk
@@ -28,7 +28,8 @@ LOCAL_AAPT_FLAGS += --private-symbols com.android.internal

# Framework doesn't need versioning since it IS the platform.
LOCAL_AAPT_FLAGS += --no-auto-version
-
+LOCAL_AAPT_FLAGS += --auto-add-overlay
+LOCAL_AAPT_FLAGS += -x
# Install this alongside the libraries.
LOCAL_MODULE_PATH := $(TARGET_OUT_JAVA_LIBRARIES)
<think>好的,我现在需要帮助用户理解Android中的RRO(运行时资源覆盖)的原理和实现。首先,我需要回忆一下自己对RRO的了解,确保信息的准确性。根据用户提供的引用内容,RRO允许在不修改原应用代码的情况下覆盖其资源,这对于主题定制和品牌化非常有用。 首先,我应该解释RRO的基本概念。根据引用[^1],RRO是Android提供的一种运行时资源覆盖机制,通过叠加层(OverlayAPK替换目标应用的资源。接下来,我需要详细说明其工作原理,可能需要涉及资源查找机制和叠加包的应用顺序。 然后,需要描述实现RRO的具体步骤。根据引用[^2]中的例子,创建一个叠加包APK需要特定的目录结构和AndroidManifest配置。用户可能需要知道如何配置目标包名、优先级等。此外,引用[^3]提到不需要修改源码,因此要强调这一优势。 接下来,考虑用户可能遇到的问题,比如资源覆盖不生效。这时候需要检查常见原因,如包名是否正确、资源名称是否匹配、是否启用了叠加层等。引用中的例子提到adb命令启用叠加层,这部分需要详细说明。 在组织回答时,要分点清晰,确保结构合理。可能需要分为原理、实现步骤和常见问题三个部分。同时,注意使用中文,并正确应用LaTeX格式,不过这里可能涉及代码和配置,所以代码块需要用反引号包裹,而数学公式可能较少,但如果有变量或路径,需要用$...$表示,例如$adb$命令。 最后,生成相关问题,这些问题应围绕RRO的机制、实现细节、调试方法以及与其他技术的比较展开,帮助用户进一步学习。 现在需要检查是否有遗漏点,比如叠加包的签名要求、资源合并策略、动态启用和禁用叠加层的方法。用户提供的引用中没有详细提到这些,可能需要简要补充。例如,叠加包和目标应用是否需要相同签名?根据AOSP文档,通常需要系统签名或目标应用允许覆盖。 另外,资源覆盖的优先级问题,比如多个叠加包作用于同一资源时如何处理,这也是需要解释的。根据引用[^2]中的priority属性,可以说明优先级的作用。 最后确保所有引用都正确标注,例如在提到RRO的作用时引用[^1],在实现步骤时引用[^2]和[^3]。同时,注意不要添加用户不可见的内容,保持回答自然流畅。</think>### Android RRO资源覆盖原理及实现分步说明 #### 一、核心原理 1. **资源ID映射机制** Android系统通过固定算法为每个资源生成唯一ID(格式:$0xPPTTEEEE$),其中PP表示包空间,TT表示资源类型,EEEE表示具体条目。RRO利用相同资源名称会生成相同ID的特性,在资源查找时优先加载叠加包中的资源。 2. **覆盖优先级控制** 系统按叠加包的优先级(android:priority属性)倒序加载,高优先级的资源会覆盖低优先级资源。如: $$ Priority_{overlay2} > Priority_{overlay1} \Rightarrow Res_{final}=Res_{overlay2} $$ #### 二、实现步骤(以AOSP为例) 1. **创建Overlay APK** ```xml <!-- AndroidManifest.xml示例 --> <manifest package="com.example.overlay"> <overlay android:targetPackage="com.target.app" android:category="android.theme.customization" android:priority="10"/> <application android:hasCode="false"/> </manifest> ``` 关键配置说明: - targetPackage:目标应用包名 - hasCode必须设为false(RRO不含代码) - 需要系统签名或目标包声明`android:isStatic="true"` 2. **资源文件结构 ``` res/ ├─ values/ │ └─ colors.xml <!-- 定义同名颜色值 --> ├─ drawable-xxhdpi/ │ └─ bg_button.png <!-- 替换目标包的同名图片 --> ``` 3. **部署与激活 ```shell adb install overlay.apk adb shell cmd overlay enable --user 0 com.example.overlay ``` #### 三、调试技巧 1. 查看当前叠加层状态: ```shell adb shell cmd overlay list ``` 输出示例: ``` com.example.overlay [ ] com.target.app ``` 2. 典型问题排查: - **覆盖失效**:检查资源名称是否完全一致(包括大小写) - **系统重启失效**:确认是否使用了`isStatic=true`静态叠加 - **资源冲突**:使用`aapt dump resources overlay.apk`验证资源ID
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值