Customizing Android Devices Using Runtime Resource Overlay

DZone 's Guide to

Customizing Android Devices Using Runtime Resource Overlay

With the new Runtime Resource Overlay framework, you can make customizations that weren't possible before.

· Mobile Zone ·
Free Resource

All Android phones have an “About phone” option in the device settings menu of the Android Settings app. Similarly, all Android tablets have an “About tablet” option. Wouldn’t it be great if different devices could show customized information while using the same Android system image? More importantly, such a mechanism could also be used to include information that is relevant to the countries the devices are sold. Regulatory information is just one example of this and could include FCC regulations for the US, CE regulations for Europe, and Telec regulations for Japan.

From a technical perspective, both the About Settings string and the regulatory info graphics asset are built-in resources of the Android Settings app. Though system developers are encouraged to create device overlays that mimic the file system path layout of the target Android package without modifying the actual source code, the resources are substituted at build time, it still ends up with diverse system images for each build targets, and the increasing maintenance effort as more devices need to be supported.

With the new Android Runtime Resource Overlay (RRO) framework, OEMs are able to share a single Android system image amongst several device models, as the RRO framework provide the ability to replace application resources at runtime. This article will walk the reader through a practical example showing how to customize the regulatory information screen shown by the Android Settings application on a MinnowBoard* MAX board running the Android-IA build.

RRO Introduction

In Android apps, resources are additional files that contain integers, strings, bitmaps, and layout definitions, etc. to be used by the Java code. Since resources are externalized from the application code, an Android app can change its look and feel dynamically depending on the device current configuration such as the user locale, screen size or orientation, because the app accesses its resources by referencing the resource IDs, and Android has implemented a resource lookup system that uses the current device configuration to map a resource ID to the compiled binary blob of the best-match resource amongst all alternative resources.

The Runtime Resource Overlay (RRO) framework was contributed by Sony [1] to extend the Android resource lookup system in order to shadow existing resources or add resources for new configurations while the application is running. The resource substitution is done at runtime without changing or recompiling the application source code, therefore there is no need to build different software packages for each product while customizing Android for multiple devices.

id resource lookup with RRO feature.png

Figure 1  Android resource lookup with RRO feature

Figure 1 shows the resource look up path in the original Android framework, and the path after RRO has introduced to the framework. As shown in Figure 1, the RRO framework accepts overlay packages which provide resource shadowing to the target package (e.g. Settings APK com.android.settings). An overlay package is a regular APK file with no code in it, it contains alternative versions of one or more application’s resources to be changed. When the system loads an application, the associated overlay packages are loaded automatically as well. However, during resource lookup Android will pick up the resource with the same symbolic name in the overlay packages as the best matching resource. Since overlay packages can be developed independently of the target application, device customizations can be achieved using a fixed target application while providing overlay packages with different resources for each device.

Note that in current RRO implementation, the resources of any applications can be shadowed by any overlay packages, which could lead to severe security consequences. To constrain any illegal attempts, only overlay packages pre-installed in /vendor/overlay folder are trusted to add resources for new configurations or shadow existing resources of a target package.

Add /oem support and redirect /vendor/overlay to it

Android creates a symbolic link redirecting the folder /vendor to /system/vendor by default, as packages included in the system image are considered trusted. However, to leverage RRO framework for customizing builds based on a single system image, overlay packages must be preloaded in /vendor/overlay folder. To that end, we could create a OEM partition named /oem to host all the customization assets and to create a symbolic link /system/vendor/overlay pointing to /oem/overlay to host the overlay packages. The following sections elaborate on the RRO experiments using the Android-IA build *1 on Minnowboard MAX hardware platform.

In the process of installing Android-IA images on the MinnowBoard MAX board, the host version of Fastboot executable communicates with the device version of the UserFastboot binary to provision the hardware device [2]. The following patches are example code to add the capability to flash or erase OEM partition from UserFastboot:

*1 The following AOSP patches are required to be applied to the Android-IA 5.1 MR1 reference code to fix the upstream bug and enable the RRO framework correctly.

diff --git a/groups/boot-arch/efi/fstab b/groups/boot-arch/efi/fstab
index ff5aebc..0fabb82 100644
--- a/groups/boot-arch/efi/fstab
+++ b/groups/boot-arch/efi/fstab
@@ -13,4 +13,5 @@
 /dev/block/by-name/android_bootloader2  /bootloader2    emmc    defaults                                   recoveryonly
 /dev/block/by-name/android_persistent   /persistent     emmc    defaults                                   defaults
 /dev/block/by-name/android_metadata     /metadata       emmc    defaults                                   defaults
+/dev/block/by-name/android_oem          /oem            ext4    ro,context=u:object_r:oemfs:s0   wait

  • device/intel/mixins/groups/boot-arch/efi/gpt.ini

diff --git a/groups/boot-arch/efi/gpt.ini b/groups/boot-arch/efi/gpt.ini
index 5569df8..715d49e 100644
--- a/groups/boot-arch/efi/gpt.ini
+++ b/groups/boot-arch/efi/gpt.ini
@@ -1,5 +1,5 @@
-partitions = bootloader bootloader2 boot recovery misc metadata system cache data persistent
+partitions = bootloader bootloader2 boot recovery misc metadata system cache data persistent oem
 device = {{{device}}}

@@ -65,3 +65,9 @@ len = 1
 type = linux
 guid = ebc597d0-2053-4b15-8b64-e0aac75f4db1

+label = android_oem
+len = 100
+type = linux
+guid = ac6d7924-eb71-4df8-b48d-e267b27148f 

To create a symbolic link to redirect /vendor/overlay to /oem/overlay in the new added OEM partition image, we have added the following build instructons to the AndroidBoard.mk of the minnow_max build target:

  • device/intel/baytrail/minnow_max/AndroidBoard.mk
diff --git a/minnow_max/AndroidBoard.mk b/minnow_max/AndroidBoard.mk
index d37eaa3..6e742e2 100644
--- a/minnow_max/AndroidBoard.mk
+++ b/minnow_max/AndroidBoard.mk
@@ -1,3 +1,13 @@
+# Create a symbolic link /system/vendor/overlay pointing to the overlay folder in OEM partition
+VENDOR_OVERLAY_DIR := $(PRODUCT_OUT)/system/vendor/overlay
+OEM_OVERLAY_DIR := /oem/overlay
+$(hide) mkdir -p $(dir $@)
+$(hide) ln -sf $(OEM_OVERLAY_DIR) $@

Device overlay setup for the Settings app

In this case study, we are going to customize the regulatory information of an Android device shown by the Settings application.

In the manifest file of the Android Settings app, whether or not to display the regulatory info is determined by the boolean resource config_show_regulatory_info, which is disabled by default. Instead of changing the boolean resource in the Android source code directly, the disciplined approach is to create a device overlay folder that mimics the file path of the modified resources of the target packages so that Android build system only incorporates the modified resources for specific device during the build time. Figure 2 depicts the resource file structure we have added to the overlay of the minnow_max build target in order to enable the regulatory info display.


Figure 2  Resource overlay file structure for the Android Settings app

After following the instructions in the OS Build Guide [3] to rebuild the Android image and flash the image on Minnowboard MAX board, you should observe the new added regulatory information from the Android Settings app as shown in Figure 3.


Figure 3  Screenshots of the device overlay result

Build the overlay package

It is easier to build overlay packages if you have installed Android Studio, otherwise you would need to install Android SDK tools and manually build the overlay package by using the Android packaging tool aapt [4]. The Android packaging tool compiles application resources, creates mapping to the generated binary blobs, and packages the binary blobs in an APK file.

First of all, create a folder that contains the modified resources and a manifest file AndroidManifest.xml which specifies the package name of the target application to be overlaid, and the priority order if the same resource will be shadowed by multiple overlay packages. Figures 4 depicts the RRO package folder used in this case study.


Figure 4  Example content of RRO overlay package folder

Then generate Java source code of the R class which contains IDs of all overlay resources, and create the initial APK package with the following commands:

$ cd regulatory_info  # where the source of overlay package build folder
$ mkdir -p gen/com/intel/irda/settings_overlay  # this must match the overlay package name
$ aapt package -m -J gen/ -M AndroidManifest.xml -S res/ -I <android_sdk_platform_API_folder>/android.jar
$ aapt package -f -M AndroidManifest.xml -S res/ -I <android_sdk_platform_API_folder>/android.jar -F regulatory_info.apk.unaligned

Sign the package with your key as Android requires all apps being signed before they can be installed. You might reference the Android SDK online document [5] to generate your own signing key.

$ jarsigner -keystore <keystore-filename> regulatory_info.apk.unaligned <key-name>

Finally, it’s recommended to align the APK to increase performance:

$ zipalign 4 regulatory_info.apk.unaligned regulatory_info.apk

Create OEM partition image and flash to the device

Once you have built the overlay package, setup a local directory (e.g. ./oem) with the overlay package, and generate the OEM partition image with the following commands:

$ mkdir -p oem/overlay
$ cp <overlay_build_folder>/regulatory_info.apk ./oem/overlay
$ genext2fs -b 8192 -m 0 -d oem/ oem.img

Use the fastboot command to flash the OEM partition image into the device, reboot the device after complete the following fastboot flash command, the updated regulatory logos should be shown (Figure 5) by the Settings app without re-building the system image.

$ fastboot -t <device_IP_address> flash oem oem.img
$ fastboot -t <device_IP_address> continue

Reboot the device and revisit the regulatory information page of the Android Settings app, the updated regulatory info will be shown as Figure 5.



Figure 5  Screenshots of the runtime overlay result


Android has been porting to a variety of devices, device builders used to customize the Android source code to meet each device’s specific requirements, including those device information which are irrelevant to the integrated hardware components or software features. With the new Runtime Resource Overlay framework, such customizations become less effort for programs such as Intel Reference Design for Android, which shares a single Android binary image amongst a number of supported Intel platforms.



  1. Sony contributes Runtime Resource Overlay framework to Android

  2. Android* 5.0 Lollipop Bring-up Guide on MinnowBoard MAX

  3. Android* 5.0 Lollipop OS Build Guide

  4. Building Android Application Bundles (APKs) by Hand

  5. Signing Your Applications


Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}