Android Overlay 机制解析

2024-06-04 2176阅读

Android Overlay机制

Android Overlay 是一种资源替换机制,它能在不修改原资源文件的情况下,覆盖替换 res/ 下的字符和图片等资源。

主要分为 静态Overlay (Static Resource Overlay) 和 运行时 Overlay (Runtime Resource Overlay) 。

静态Overlay (SRO):发生在编译时,需要在 Aosp 源码中配置。

运行时Overlay (RRO):发生在运行时,可以直接覆盖替换其他 apk 的资源而不需要其源码。

静态Overlay (SRO)

可以替换 string.xml 、图片、layout、anim、xml目录中的 xml 文件 。

常用场景:覆盖替换 frameworks/ 、packages/ 目录下的资源文件。如改翻译词条、图片、改默认值等。

frameworks/base/core/res/res/drawable-xxxhdpi/
frameworks/base/core/res/res/layout-xxxhdpi/
frameworks/base/core/res/res/values/
frameworks/base/packages/SettingsProvider/res/values/defaults.xml
packages/apps/Bluetooth/res/values/

1.配置 overlay 目录

在 AOSP 源码下下找到 PRODUCT_PACKAGE_OVERLAYS 的宏定义,一般都配置在 device 目录下,如 device/xxx/yyy/device.mk

# overlay
PRODUCT_PACKAGE_OVERLAYS := \
    device/xxx/yyy/overlay

2.替换资源文件

在 device/xxx/yyy/overlay (其他目录也可以,主要对应上上面定义的PRODUCT_PACKAGE_OVERLAYS即可)下按照 frameworks 目录新建对应的文件夹,放入要替换的文件即可。

device/xxx/yyy/overlay/frameworks/
device/xxx/yyy/overlay/packages/

这种会在编译版本的时候根据设置的路径和配置的res文件直接将对应修改编译到目标apk中,相对于静态Overlay,运行时Overlay更灵活

运行时Overlay (RRO)

https://source.android.google.cn/docs/core/architecture/rros?hl=zh-cn

可以替换 string.xml 、图片,不能替换 layout、anim、xml 目录中的 xml 文件 。

举个栗子:

frameworks/base/packages/overlays/NavigationBarMode3ButtonOverlay/Android.bp

26 runtime_resource_overlay {
27     name: "NavigationBarMode3ButtonOverlay",
28     theme: "NavigationBarMode3Button",
29     product_specific: true,
30 }

frameworks/base/packages/overlays/NavigationBarMode3ButtonOverlay/AndroidManifest.xml

18 
22     
25 
26     
27 

frameworks/base/packages/overlays/NavigationBarMode3ButtonOverlay/res/values/config.xml

19 
20     
24     0
25 

我们先来解释一下:

1.NavigationBarMode2ButtonOverlay是编译出来的overlay APK的名字,product_specific表示这个应用会在product目录下

2.NavigationBarMode3ButtonOverlay是一个没有Java代码的APK,com.android.internal.systemui.navbar.threebutton表示这个overlay的包名,android:targetPackage="android"表示目标应用是framework-res.apk,会替换这个应用的res资源,android:priority="1"表示优先级,越大越高

3.需要留意,即使只是想替换 values-xx/strings.xml 里的字符串,values/strings.xml 里也要加上对应的字符串,要不然会替换不成功

4.因为NavigationBarMode3ButtonOverlay是一个应用,所以这个也是必须的

PRODUCT_PACKAGES +=

NavigationBarMode3ButtonOverlay \

AOSP源码中像这样overlay还有很多。一般都是为了方便不同机型机器配置不同属性的,我们照着这个写就行了

如何知道系统中有哪些Overlay呢?

我们可以通过命令adb shell dumpsys overlay或者adb shell cmd overlay命令

这里我们着重介绍下cmd overlay,这个命令允许我们动态的对系统中的overlay进行修改:

adb shell cmd overlay

Overlay manager (overlay) commands:
  help
    Print this help text.
  dump [--verbose] [--user USER_ID] [[FIELD] PACKAGE[:NAME]]
    Print debugging information about the overlay manager.
    With optional parameters PACKAGE and NAME, limit output to the specified
    overlay or target. With optional parameter FIELD, limit output to
    the corresponding SettingsItem field. Field names are all lower case
    and omit the m prefix, i.e. 'userid' for SettingsItem.mUserId.
  list [--user USER_ID] [PACKAGE[:NAME]]
    Print information about target and overlay packages.
    Overlay packages are printed in priority order. With optional
    parameters PACKAGE and NAME, limit output to the specified overlay or
    target.
  enable [--user USER_ID] PACKAGE[:NAME]
    Enable overlay within or owned by PACKAGE with optional unique NAME.
  disable [--user USER_ID] PACKAGE[:NAME]
    Disable overlay within or owned by PACKAGE with optional unique NAME.
  enable-exclusive [--user USER_ID] [--category] PACKAGE
    Enable overlay within or owned by PACKAGE and disable all other overlays
    for its target package. If the --category option is given, only disables
    other overlays in the same category.
  set-priority [--user USER_ID] PACKAGE PARENT|lowest|highest
    Change the priority of the overlay to be just higher than
    the priority of PARENT If PARENT is the special keyword
    'lowest', change priority of PACKAGE to the lowest priority.
    If PARENT is the special keyword 'highest', change priority of
    PACKAGE to the highest priority.
  lookup [--user USER_ID] [--verbose] PACKAGE-TO-LOAD PACKAGE:TYPE/NAME
    Load a package and print the value of a given resource
    applying the current configuration and enabled overlays.
    For a more fine-grained alternative, use 'idmap2 lookup'.
  fabricate [--user USER_ID] [--target-name OVERLAYABLE] --target PACKAGE
            --name NAME [--file FILE]
            PACKAGE:TYPE/NAME ENCODED-TYPE-ID/TYPE-NAME ENCODED-VALUE
    Create an overlay from a single resource. Caller must be root. Example:
      fabricate --target android --name LighterGray \
                android:color/lighter_gray 0x1c 0xffeeeeee

我们挑几个常用的

1.dump出当前系统中所有target为android的overlay以及mapping信息:

adb shell cmd overlay dump android

...
IDMAP OF com.google.android.overlay.gmsconfig.personalsafety
Paths:
    target path  : /system/framework/framework-res.apk
    overlay path : /product/overlay/GmsConfigOverlayPersonalSafety.apk
Mapping:
    0x01040241 -> 0x7f010000 (string/config_emergency_dialer_package -> string/config_emergency_dialer_package)

2.list出当前系统中所有target为android的overlay,其中[x]表示已启用的Overlay

adb shell cmd overlay list android

android
[x] com.google.android.overlay.gmsconfig.common
[x] com.google.android.overlay.gmsconfig.gsa
[x] com.google.android.overlay.gmsconfig.geotz
[ ] com.android.internal.display.cutout.emulation.corner
[ ] com.android.internal.display.cutout.emulation.double
[ ] com.android.internal.systemui.navbar.gestural_wide_back
  1. enable/disable某个Overlay(配置了isStatic=true的是无法disable的)

    adb shell cmd overlay disable com.android.systemui:neutral

[x] com.android.systemui:accent
[x] com.android.systemui:dynamic
[ ] com.android.systemui:neutral

adb shell cmd overlay enable com.android.systemui:neutral

[x] com.android.systemui:accent
[x] com.android.systemui:dynamic
[x] com.android.systemui:neutral
  1. enable-exclusive disable除指定overlay之外其他的所有overlay

  2. lookup 查看某个overlay实际覆盖的属性,比如上文的三指导航就可以用这个命令查看

adb shell cmd overlay lookup

com.android.internal.systemui.navbar.threebutton

android:integer/config_navBarInteractionMode

6.添加一个overlay

adb shell cmd overlay fabricate --target android --name com.android.internal.systemui.navbar.twobutton android:integer/config_navBarInteractionMode 0x010 0x1

此时我们通过命令可以看到我们刚添加的twobutton

IDMAP OF com.android.shell:com.android.internal.systemui.navbar.twobutton
Paths:
    target path  : /system/framework/framework-res.apk
    overlay path : /data/resource-cache/com.android.shell-com.android.internal.systemui.navbar.twobutton-rfZe.frro
Overlay name: com.android.internal.systemui.navbar.twobutton
Mapping:
    0x010e00b5 -> integer 0x00000001 (integer/config_navBarInteractionMode)

用enable使这个生效:adb shell cmd overlay enable com.android.shell:com.android.internal.systemui.navbar.twobutton

此时你会发现导航栏变成了两个按钮模式了

idmap2

OverlayManagerService 使用 idmap2 将目标软件包中的资源 ID 映射到叠加层软件包中的资源 ID。生成的 ID 映射存储在 /data/resource-cache/ 中。如果叠加层无法正常运行,请在 /data/resource-cache/ 中查找叠加层的相应 idmap 文件,然后运行以下命令。

adb shell idmap2 dump --idmap-path [file]


    免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

    目录[+]