Fabricated RRO简单理解

随笔6个月前发布 挚居無啶鎍
67 0 0

从system_neutral1_50来切入,简单理解Fabricated RRO。
android.R.color.system_neutral1_50的颜色实际打印出来的是#FAEFE8

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ...
        String colorHex = getColorValueAsString(this, android.R.color.system_neutral1_50);
        Log.d("MainActivity", "Color value: " + colorHex);
    }

    public String getColorValueAsString(Context context, int resourceId) {
        int color = ContextCompat.getColor(context, resourceId);
        return String.format("#%06X", (0xFFFFFF & color));
    }

D/MainActivity: Color value: #FAEFE8

但是在framework下的xml中,定义的并不是这个数据。

frameworks/base/core/res/res/values/public.xml
    <public type="color" name="system_neutral1_50" id="0x0106001f" />


frameworks/base/core/res/res/values/colors.xml
    <color name="system_neutral1_50">#F0F0F3</color>

使用dumpsys overlay查看overlay,可以看到overlay path有2种类型文件,一种是apk文件,另一种是frro文件。SystemUIResOverlay中也没有定义该值,实际是/data/resource-cache/com.android.systemui-neutral-xx.frro中定义的。

com.android.internal.systemui.navbar.gestural_narrow_back:0 {
  mPackageName...........: com.android.internal.systemui.navbar.gestural_narrow_back
  mOverlayName...........: null
  mUserId................: 0
  mTargetPackageName.....: android
  mTargetOverlayableName.: null
  mBaseCodePath..........: /product/overlay/NavigationBarModeGesturalNarrowBack/NavigationBarModeGesturalOverlayNarrowBack.apk
  mState.................: STATE_DISABLED
  mIsEnabled.............: false
  mIsMutable.............: true
  mPriority..............: 2147483647
  mCategory..............: com.android.internal.navigation_bar_mode
  mIsFabricated..........: false
}
com.android.systemui:neutral:0 {
  mPackageName...........: com.android.systemui
  mOverlayName...........: neutral
  mUserId................: 0
  mTargetPackageName.....: android
  mTargetOverlayableName.: 
  mBaseCodePath..........: /data/resource-cache/com.android.systemui-neutral-xx.frro
  mState.................: STATE_ENABLED
  mIsEnabled.............: true
  mIsMutable.............: true
  mPriority..............: 2147483647
  mCategory..............: null
  mIsFabricated..........: true
}


IDMAP OF com.android.systemui:neutral
Paths:
    target path  : /system/framework/framework-res.apk
    overlay path : /data/resource-cache/com.android.systemui-neutral-xx.frro
Overlay name: neutral
Mapping:
    0x0106001e -> color 0xfffffbff (color/system_neutral1_10)
    0x0106001f -> color 0xfffaefe8 (color/system_neutral1_50)
    0x01060020 -> color 0xffece0da (color/system_neutral1_100)
    0x01060021 -> color 0xffcfc4be (color/system_neutral1_200)
    0x01060022 -> color 0xffb3a9a3 (color/system_neutral1_300)
    0x01060023 -> color 0xff988f89 (color/system_neutral1_400)
    0x01060024 -> color 0xff7d746f (color/system_neutral1_500)
    0x01060025 -> color 0xff655d58 (color/system_neutral1_600)
    0x01060026 -> color 0xff4c4541 (color/system_neutral1_700)
    0x01060027 -> color 0xff352f2b (color/system_neutral1_800)
    0x01060028 -> color 0xff201b17 (color/system_neutral1_900)
    0x01060029 -> color 0xff000000 (color/system_neutral1_1000)
    0x0106002b -> color 0xfffffbff (color/system_neutral2_10)
    0x0106002c -> color 0xffffeee2 (color/system_neutral2_50)
    0x0106002d -> color 0xfff2dfd1 (color/system_neutral2_100)
    0x0106002e -> color 0xffd6c3b6 (color/system_neutral2_200)
    0x0106002f -> color 0xffb9a89b (color/system_neutral2_300)
    0x01060030 -> color 0xff9e8e82 (color/system_neutral2_400)
    0x01060031 -> color 0xff827368 (color/system_neutral2_500)
    0x01060032 -> color 0xff6a5c51 (color/system_neutral2_600)
    0x01060033 -> color 0xff51443a (color/system_neutral2_700)
    0x01060034 -> color 0xff3a2e25 (color/system_neutral2_800)
    0x01060035 -> color 0xff231a11 (color/system_neutral2_900)
    0x01060036 -> color 0xff000000 (color/system_neutral2_1000)

frro的原理是什么?这里不做深入,大致应该是是跟OverlayManagerService和Idmap2Service相关,具体可以参考这2条提交:
https://cs.android.com/android/_/android/platform/frameworks/base/+/2ed8bfa7fda3c42280e0816c6cf1af852981723b?hl=zh-cn

https://cs.android.com/android/_/android/platform/frameworks/base/+/6a2ca782d497e6fdb616f6a273409786a0b81f99?hl=zh-cn

Add fabricated RRO generation to libidmap2

Fabricated Runtime Resource Overlays are overlays that are generated
at runtime and are stored in the data/ partition.

The system can fabricate RROs at runtime to dynamically theme the
device. Idmaps can now be created from APK RROs and fabricated RROs.

Rather than operating on ApkAssets, libidmap2 now operates on abstract
resource "containers" that supply resource values. Target resource
containers implement methods needed to query overlayable and target
overlay information. Currently only APKs can be loaded as target
resource containers. Overlay resource containers implement methods to
supply the mapping of target resource to overlay value and other
overlay information.

The format of a fabricated RRO is as follows:
0x00 - 0x04 : fabricated overlay magic (always FRRO)
0x04 - 0x08 : file format version
0x08 - 0x0c : crc of version + proto data
0x0c - EOF  : proto fabricated overlay data

The magic is used to quickly detect if the file is a fabricated overlay.
The version is incremented whenever backwards incompatible changes are
made to the proto file format. Idmap must always be able to upgrade
fabricated overlays from previous versions to new versions, so all
previous versions must be checked into the tree.

——————引用开始(由GPT生成)——————
这段话介绍了“Fabricated Runtime Resource Overlays”(制造的运行时资源覆盖,即 FRRO)的概念和生成机制,以及如何在 Android 系统的 libidmap2 库中实现对这些 FRRO 的处理。下面是对这段话的详细解释:

  1. FRRO 的定义和存储

    • FRRO 是在设备运行时生成的资源覆盖文件,存储在设备的 data/ 分区中。这允许系统动态地应用主题和样式变更,而不需要预先定义的资源文件。
  2. 动态生成与管理

    • 系统可以在运行时生成 FRRO 来动态地应用主题到设备上。这意味着 Android 设备可以根据需要修改其 UI 的外观,而不必重新启动或进行重大更新。
    • Idmap 工具现在可以从 APK 文件生成的 RRO 和动态生成的 FRRO 创建资源映射(idmaps)。这扩展了资源覆盖的灵活性和应用场景。
  3. libidmap2 的更新

    • libidmap2 是一个库,用于处理资源 ID 的映射。它已被更新,以便不仅仅操作 ApkAssets(来自 APK 文件的资源),而是操作抽象的资源“容器”。
    • 这些容器提供资源值,并实现了查询覆盖信息和目标资源信息所需的方法。
    • 目前,只有 APK 文件可以被加载作为目标资源容器。而覆盖资源容器则实现了提供目标资源到覆盖值映射的方法。
  4. FRRO 文件格式

    • FRRO 文件具有特定的二进制格式,以标识文件类型、版本和内容。格式包括:
      • 文件开始的几个字节定义了“魔术数字”(FRRO),用于快速识别文件是否为制造的覆盖文件。
      • 文件版本信息跟随魔术数字,用于标识文件格式的版本。每当文件格式发生向后不兼容的变化时,版本号会增加。
      • 文件还包含了一个 CRC 校验和,用于验证版本信息和协议数据的完整性。
      • 文件的剩余部分包含了实际的覆盖数据,采用 protobuf 格式。
  5. 版本兼容性和管理

    • Idmap 必须能够将旧版本的 FRRO 升级到新版本,这要求所有历史版本的信息都必须被检入到代码库中,以保证覆盖文件在系统更新后仍能被正确处理。

这种机制使 Android 系统能够更加动态和灵活地处理资源覆盖,支持更加丰富的用户定制和即时主题变更,而无需深入修改系统底层或进行重启。
——————引用结束(由GPT生成)——————

OverlayManager Fabricated RROs

Adds registering and unregistering of FabricatedOverlay to the OMS.
The process that creates the fabricated overlays owns it and is the
only process allowed to unregister it.

When a fabricated overlay is registered, overlay settings for it are
initialized in all users. When a fabricated overlay is unregistered,
it is disabled and removed from all users. When a new user is created,
it will be able to use the fabricated overlay as well.

On boot, fabricated overlays that are not referenced in overlay
settings will be deleted.

When the package that created the fabricated overlay is uninstalled,
its fabricated overlays are also unregistered.

——————引用开始(由GPT生成)——————
这段话描述了与 Android 系统中的“OverlayManager”(叠加层管理器)和“Fabricated RROs”(即时生成的运行时资源覆盖)的相关功能。以下是详细解释:

  1. 添加注册与注销功能:系统允许注册和注销“FabricatedOverlay”(即时生成的资源覆盖层)到 Overlay Manager Service(OMS,叠加层管理服务)。即时生成的覆盖层由创建它的进程拥有,并且只有该进程有权限注销它。

  2. 覆盖层的生命周期

    • 注册时:当一个即时生成的覆盖层被注册时,它的设置会为所有用户初始化。这意味着一旦注册,所有用户都可以使用这个覆盖层。
    • 注销时:当一个即时生成的覆盖层被注销时,它会被禁用并从所有用户中移除。
    • 新用户创建时:新用户也将能够使用已注册的即时生成的覆盖层。
  3. 系统启动时的处理:在系统启动时,任何在覆盖层设置中未被引用的即时生成的覆盖层将被删除。这是一种清理机制,确保不再需要的覆盖层不会继续占用资源。

  4. 关联包被卸载时的处理:当创建即时生成覆盖层的包(应用)被卸载时,其所创建的所有即时生成覆盖层也会被注销。

这一机制主要用于动态地管理和控制应用生成和使用的资源覆盖层,使得系统能够更灵活地处理主题或其他资源的动态变化,同时确保系统的整洁和资源的有效管理。
——————引用结束(由GPT生成)——————

apk文件是vendor/mediatek/proprietary/packages/overlay这种文件下定义的,那frro文件是怎么来的呢。关键是frameworks/base/packages/SystemUI/src/com/android/systemui/theme这个目录。
android13,使用FabricatedOverlay.Builder,使用FabricatedOverlayInternal.aidl等构建neutral.frro文件,然后使用ColorScheme去定义neutral.frro中的颜色。

//frameworks/base/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
    /**
     * Given a color candidate, return an overlay definition.
     */
    protected @Nullable FabricatedOverlay getOverlay(int color, int type) {
        boolean nightMode = (mContext.getResources().getConfiguration().uiMode
                & Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES;

        mColorScheme = new ColorScheme(color, nightMode);
        List<Integer> colorShades = type == ACCENT
                ? mColorScheme.getAllAccentColors() : mColorScheme.getAllNeutralColors();
        String name = type == ACCENT ? "accent" : "neutral";
        int paletteSize = mColorScheme.getAccent1().size();
        FabricatedOverlay.Builder overlay =
                new FabricatedOverlay.Builder("com.android.systemui", name, "android");
        for (int i = 0; i < colorShades.size(); i++) {
            int luminosity = i % paletteSize;
            int paletteIndex = i / paletteSize + 1;
            String resourceName;
            switch (luminosity) {
                case 0:
                    resourceName = "android:color/system_" + name + paletteIndex + "_10";
                    break;
                case 1:
                    resourceName = "android:color/system_" + name + paletteIndex + "_50";
                    break;
                default:
                    int l = luminosity - 1;
                    resourceName = "android:color/system_" + name + paletteIndex + "_" + l + "00";
            }
            overlay.setResourceValue(resourceName, TypedValue.TYPE_INT_COLOR_ARGB8,
                    ColorUtils.setAlphaComponent(colorShades.get(i), 0xFF));
        }

        return overlay.build();
    }

——————引用开始(由GPT生成)——————
这段代码定义了一个名为 getOverlay 的方法,该方法用于根据给定的颜色生成一个“fabricated overlay”(即在运行时生成的资源覆盖)。这个方法主要应用于 Android 系统界面(如 SystemUI)的主题定制中,用于动态调整颜色主题。下面是对这段代码的详细解释:

参数

  • color: 一个整数,表示用作生成颜色方案的基础颜色。
  • type: 一个整数,表示生成的是 “accent” 色彩方案还是 “neutral” 色彩方案。
  • style: 一个 Style 枚举,可能包含额外的风格定义,用于颜色方案的创建。

方法逻辑

  1. 夜间模式检测:

    • 通过检查系统配置(mResources.getConfiguration().uiMode),确定当前是否处于夜间模式。
  2. 颜色方案生成:

    • 使用给定的颜色、夜间模式标志和风格定义,创建一个 ColorScheme 对象。这个对象负责生成一系列基于基础颜色的调色板。
  3. 获取色调和颜色列表:

    • 根据 type 参数(ACCENT 或 NEUTRAL),从 ColorScheme 对象中获取对应的颜色列表。
  4. Overlay 名称设定:

    • 根据颜色类型确定 overlay 的名称(”accent” 或 “neutral”)。
  5. Fabricated Overlay 构建:

    • 使用 FabricatedOverlay.Builder,为 SystemUI 创建一个 overlay,目标包名为 “android”。
    • 遍历色调列表,为每种色调生成一个资源定义,资源名称格式为 “android:color/system_[name][paletteIndex]_[luminosity]”。其中,luminositypaletteIndex 由颜色列表中的位置决定,以确保不同深浅度和色系的颜色能被正确配置。
  6. 资源值设置:

    • 对每一个颜色资源,使用 overlay.setResourceValue 设置 ARGB 形式的颜色值,这里确保颜色的透明度始终为不透明(alpha 值为 0xFF)。

返回值

  • 方法返回构建好的 FabricatedOverlay 对象,这个对象包含了所有的资源修改定义,可以被应用于系统界面,以改变相应的颜色主题。

这个方法的设计允许在不同的用户界面环境下(如日间模式和夜间模式)动态调整系统主题的颜色,提高了 Android 系统界面的可定制性和适应性。
——————引用结束(由GPT生成)——————

参考链接:
Android两种查看overlay的方法
Android Overlay 机制解析
运行时资源叠加层 (RRO)
排查运行时资源叠加层问题

© 版权声明

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...