Let’s start with system_neutral1_50 and briefly understand Fabricated RRO.
android.R.color.system_neutral1_50
The colors actually printed are #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
But in the xml under the framework, this data is not defined.
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>
Using dumpsys overlay
View overlay
, you can see overlay path
that there are 2 types of files, one is apk
a file and the other is frro
a file. SystemUIResOverlay
This value is not defined in , but is actually /data/resource-cache/com.android.systemui-neutral-xx.frro
defined in .
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)
What is the principle of frro? I won’t go into details here. It should be roughly related to OverlayManagerService and Idmap2Service. For details, you can refer to these two submissions:https://cs.android.com/android/_/android/platform/frameworks/base/+/2ed8bfa7fda3c42280e0816c6cf1af852981723b
andhttps://cs.android.com/android/_/android/platform/frameworks/base/+/6a2ca782d497e6fdb616f6a273409786a0b81f99
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.
This paragraph introduces the concept and generation mechanism of “Fabricated Runtime Resource Overlays” (Fabricated Runtime Resource Overlays, or FRRO), and how to libidmap2
implement the processing of these FRROs in the Android system library. Here is a detailed explanation of this passage:
- Definition and storage of FRRO :
- FRRO is a resource overlay file generated when the device is running and stored in the device’s
data/
partition. This allows the system to apply theme and style changes dynamically without the need for pre-defined resource files.
- FRRO is a resource overlay file generated when the device is running and stored in the device’s
- Dynamic generation and management :
- The system can generate FRRO at runtime to dynamically apply themes to devices. This means that Android devices can modify the appearance of their UI as needed without having to reboot or perform a major update.
Idmap
Tools can now create resource maps (idmaps) from RROs generated from APK files and from dynamically generated FRROs. This expands the flexibility and application scenarios of resource coverage.
libidmap2
Updates :libidmap2
Is a library used to handle the mapping of resource IDs. It has been updated to operate not just onApkAssets
resources (from APK files), but on abstract “containers” of resources.- These containers provide resource values and implement the methods needed to query coverage information and target resource information.
- Currently, only APK files can be loaded as target resource containers. The coverage resource container implements a method of mapping target resources to coverage values.
- FRRO file format :
- FRRO files have a specific binary format that identifies the file type, version, and content. Format includes:
- The first few bytes of the file define a “magic number” (FRRO) that is used to quickly identify whether the file is a manufactured overlay file.
- File version information follows a magic number that identifies the version of the file format. Whenever a backward-incompatible change occurs to the file format, the version number is incremented.
- The file also contains a CRC checksum to verify the integrity of the version information and protocol data.
- The remainder of the file contains the actual coverage data, in protobuf format.
- FRRO files have a specific binary format that identifies the file type, version, and content. Format includes:
- Version compatibility and management :
Idmap
It must be possible to upgrade the old version of FRRO to the new version, which requires that all historical version information must be checked into the code base to ensure that the overwritten files can still be processed correctly after the system is updated.
This mechanism enables the Android system to handle resource coverage more dynamically and flexibly, supporting richer user customization and instant theme changes without the need to deeply modify the underlying system or restart.
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.
This paragraph describes the functionality related to the “OverlayManager” (overlay manager) and “Fabricated RROs” (instantly generated runtime resource overlays) in the Android system. Here is a detailed explanation:
- Added registration and deregistration functions : The system allows registration and deregistration of “FabricatedOverlay” (instantly generated resource overlay) to the Overlay Manager Service (OMS, overlay management service). An on-the-fly overlay is owned by the process that created it, and only that process has permission to unregister it.
- Overlay life cycle :
- On registration : When an instant-generated overlay is registered, its settings are initialized for all users. This means that once registered, this overlay is available to all users.
- On logout : When an instant-generated overlay is logged out, it is disabled and removed from all users.
- When a new user is created : New users will also be able to use registered on-the-fly overlays.
- System startup handling : On system startup, any on-the-fly generated overlays that are not referenced in the overlay settings will be deleted. This is a cleanup mechanism to ensure that overlays that are no longer needed do not continue to occupy resources.
- Handling when the associated package is uninstalled : When the package (application) that created the instant generation overlay is uninstalled, all the instant generation overlays it created will also be unregistered.
This mechanism is mainly used to dynamically manage and control the resource overlays generated and used by applications, so that the system can handle dynamic changes in themes or other resources more flexibly, while ensuring the cleanliness of the system and the effective management of resources.
The apk file is vendor/mediatek/proprietary/packages/overlay
defined under this kind of file, so frro
where does the file come from? The key is frameworks/base/packages/SystemUI/src/com/android/systemui/theme
this directory.
android13, use FabricatedOverlay.Builder, use FabricatedOverlayInternal.aidl, etc. to build the neutral.frro file, and then use ColorScheme to define the colors in 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();
}
This code defines a getOverlay
method called which is used to generate a “fabricated overlay” (i.e. a resource overlay generated at runtime) based on the given color. This method is mainly used in theme customization of Android system interfaces (such as SystemUI) to dynamically adjust color themes. Here is a detailed explanation of this code:
parameter
color
: An integer representing the base color used to generate the color scheme.type
: An integer indicating whether the “accent” color scheme or the “neutral” color scheme is generated.style
: AnStyle
enumeration that may contain additional style definitions for use in color scheme creation.
method logic
- Night mode detection :
- Determine whether you are currently in night mode by checking the system configuration (
mResources.getConfiguration().uiMode
).
- Determine whether you are currently in night mode by checking the system configuration (
- Color scheme generation :
ColorScheme
Creates an object using the given color, night mode flag, and style definition . This object is responsible for generating a palette of base colors.
- Get a list of shades and colors :
- According to
type
the parameter (ACCENT or NEUTRAL),ColorScheme
get the corresponding color list from the object.
- According to
- Overlay name setting :
- Determines the name of the overlay based on the color type (“accent” or “neutral”).
- Fabricated Overlay build :
- Using
FabricatedOverlay.Builder
, create an overlay for SystemUI with the target package name “android”. - Traverse the list of hues and generate a resource definition for each hue. The resource name is in the format “android:color/system_[name][paletteIndex]_[luminosity]”. Among them,
luminosity
andpaletteIndex
are determined by the position in the color list to ensure that colors of different shades and colors can be configured correctly.
- Using
- Resource value settings :
- For each color resource, use
overlay.setResourceValue
to set the color value in ARGB form, where the transparency of the color is always opaque (alpha value is 0xFF).
- For each color resource, use
return value
- The method returns the constructed
FabricatedOverlay
object. This object contains all resource modification definitions and can be applied to the system interface to change the corresponding color theme.
The design of this method allows the color of the system theme to be dynamically adjusted in different user interface environments (such as day mode and night mode), improving the customizability and adaptability of the Android system interface.