Deep Dive: RRO Architecture
Runtime Resource Overlays (RRO) evolved from static overlays to allow resources to be modified dynamically while the device is running. This architecture fundamentally changed how OEMs implement dark mode, dynamic themes, and user-selectable skins.
OverlayManagerService Internals
The core of the RRO system is the OverlayManagerService (OMS), a system service responsible for managing the lifecycle, state, and priority of all overlay packages installed on the device.
When the system boots, OMS scans specific directories (like /vendor/overlay and /product/overlay) for installed overlay packages. It parses their manifests to determine their targetPackage and initial state. OMS then communicates with the PackageManagerService to ensure the overlay APKs are valid and properly signed.
OMS maintains an internal state map for every user on the device, tracking which overlays are enabled, disabled, or missing.
Enabling and Disabling Overlays at Runtime
Unlike static overlays which are permanently merged during the build, RROs can be toggled via the OverlayManagerService APIs.
System apps with the android.permission.CHANGE_OVERLAY_PACKAGES permission can call the OMS API to enable or disable an overlay. Alternatively, developers can use the cmd overlay command via adb:
# List all overlays and their state
adb shell cmd overlay list
# Enable a specific overlay
adb shell cmd overlay enable com.android.theme.color.purple
When an overlay state changes, OMS broadcasts an intent. The framework then triggers a configuration change, forcing affected apps to recreate their Activities and reload their resources, instantly applying the new theme.
Overlays and idmap2
A critical performance challenge with RROs is resolving resource IDs quickly. A target package (e.g., Settings) expects its background color to be at ID 0x7f050001, but the overlay package might store its replacement color at ID 0x7f020005.
To solve this without incurring runtime lookup penalties, Android uses idmap2. The idmap2d daemon runs in the background and generates .idmap files. An idmap file is a highly optimized, pre-compiled lookup table that maps the resource IDs of the target package directly to the corresponding resource IDs in the overlay package.
When an app loads its resources, the AssetManager loads these .idmap files into memory. This allows the system to seamlessly and instantly swap the requested resource ID with the overlay's resource ID at the native level.