Evolution of Android Update System

Let’s review all the possible options for updating the firmware on Android devices, paying special attention to over-the-air updates (OTA), and looking back at its development stages.

Ivan Kuten
ProAndroidDev

--

Our fan art for Android Engineers who also like movies about Indiana Jones
Fan Art: Indiana Jones sets up a new “active section”, swapping a golden idol for a sandbag in an iconic scene from Raiders of the Lost Ark.

So, how can you update Android on mobile devices? While developing software for Smart TVs and Android-based set-top boxes, we’ve narrowed it down to four ways, discarding some very exotic options:

  1. Flashing the flash memory via the JTAG hardware interface (if available).
  2. Flashing the flash memory with the bootloader.
  3. Updating via Recovery Mode.
  4. OTA (over-the-air).

Let’s take a closer look at each of the options.

1. Updating Android via the JTAG interface

The option with JTAG allows you to update the device on the spot only and requires connecting the Android device to the host, for example, via the USB interface. Since we reflash a flash memory, a new Android version can be put on the firmware with other security keys. You can also choose almost any Android OS version, the assembled firmware, or reconfiguration of flash memory partitions.

However, the JTAG interface is usually available on dev kits only, significantly narrowing this update option’s scope.

2. Updating Android via the Recovery Mode

Usually, the bootloader is proprietary and developed by the chip manufacturer. The bootloader initializes the TEE (trusted execution environment) and checks the integrity of the boot and recovery partitions before transferring the execution to the Linux kernel. The bootloader itself is often composite, some of its levels may be open source (e.g., based on U-boot), and some may be proprietary.

The Android bootloader allows you to reflash the flash memory of your device with prepared partition images. This is done using the fastboot protocol or its analogue (in Amlogic’s case, the WorldCup Device protocol). Fastboot, like its counterpart WorldCup Device, is a protocol for communicating with the bootloader via the USB interface or local Ethernet network.

To reflash it, you need to connect your device via USB to the host (there is an option to use LAN Ethernet), put the bootloader into a special update mode, and in this mode, reflash the flash memory of the device.

This method’s advantages and disadvantages are the same as for JTAG: since the update takes place without the Android system’s participation, there are no restrictions related to the version of the system/build or security keys when reflashing.

But, as always, there is one nuance. :-) The bootloader must be unlocked, which means that you can reflash the bootloader itself or the device partitions. To lock/unlock your device, you need to launch the fastboot flashing lock/unlock command, but it may require a password set by someone who got to the device before you did (usually, the manufacturer).

3. Updating Android via Recovery Mode and OTA

If the first two updating options have remained unchanged throughout the evolution of Android, the next two options, such as updating via Recovery Mode and OTA, are implemented employing Android itself and have evolved with this OS.

It’s worth mentioning that Recovery Mode and OTA are two different options for calling the Android update engine.

3.1. Recovery Mode or non-A/B System Updates

Recovery and the updater engine (bootable/recovery/updater) are the things that started the Android update system (located in bootable/recovery in the AOSP source tree).

The Recovery or non-A/B System Updates involves a particular recovery partition containing a special OS based on the Linux kernel. This Linux-based OS contains software for unpacking the downloaded update image and applying it to other partitions. That’s how the Android update goes.

An example of flash memory partitioning on a device with Android 6.0:

Android 6.0.1, partition map:

[mmcblk0p01] bootloader offset 0x000000000000, size 0x000000400000
[mmcblk0p02] reserved offset 0x000002400000, size 0x000004000000
[mmcblk0p03] cache offset 0x000006c00000, size 0x000020000000
[mmcblk0p04] env offset 0x000027400000, size 0x000000800000
[mmcblk0p05] logo offset 0x000028400000, size 0x000002000000
[mmcblk0p06] recovery offset 0x00002ac00000, size 0x000002000000
[mmcblk0p07] rsv offset 0x00002d400000, size 0x000000800000
[mmcblk0p08] tee offset 0x00002e400000, size 0x000000800000
[mmcblk0p09] crypt offset 0x00002f400000, size 0x000002000000
[mmcblk0p10] misc offset 0x000031c00000, size 0x000002000000
[mmcblk0p11] instaboot offset 0x000034400000, size 0x000020000000
[mmcblk0p12] boot offset 0x000054c00000, size 0x000002000000
[mmcblk0p13] system offset 0x000057400000, size 0x000060000000
[mmcblk0p14] data offset 0x0000b7c00000, size 0x0002ec200000

The updating process involves two stages:

  1. After booting from the Recovery partition, all other Android partitions will be updated.
  2. And after rebooting and starting a new version of Android, the Recovery section will be updated.

When upgrading using the updater engine, the first step is to check the version and digital signature of the image, so you cannot roll back to an older version of the operating system.

With the Recovery system, you can run the updating process either locally, by selecting Recovery Mode in the bootloader and running the updater engine in the Recovery Mode menu, or remotely using OTA when the Android application calls the same updater from Java. And this remote start makes possible a mass update of a whole series of devices. This option is used by operators to update OS for their digital TV solutions on set-top boxes.

The Recovery partition within the non-A/B update scheme is actually a physical partition of the flash memory. With the advent of the A/B system, the Recovery partition was moved to the RAM disk in the device’s random access memory, but the ability to make it a separate physical partition remained.

There is no clear distinction between “old” and “new” in the Android system; it’s more like adding additional features in the Android build configuration while maintaining compatibility with older solutions where possible. However, not all configurations work.

A critical disadvantage of the Recovery or non-A/B System Updates is that with any failure during the update process or with any invalid firmware, a device will require recovery. We will not get a “brick” because you can still run the device in the Recovery Mode from the Recovery section, but the device will not be working properly.

Apparently, the Android developers decided to do something about this because the next step in the evolution of the update system was seamless updates or A/B-scheme updates.

3.2. Seamless update or A/B scheme

This feature appeared in Android 7.0; it is implemented in the new update_engine, located in the system/update_engine in the AOSP source tree.

The main feature of the A/B-scheme was that it is possible to boot from a previously working version of the Android system in case of failures during the update. The flash memory contains duplicate system partitions or slots (A and B); this is why it was named the A/B system updates (the eternal problem with the choice of names). The bootloader is responsible for selecting the slot to load (A or B) by analyzing both slots’ state.

Seamless Android A/B update scheme
Image: the principle of the seamless Android A/B update (an active partition is marked with a checkmark)

So, that is how the upgrade works:

  1. By booting from the A slots system, we download and flash updates to the B slots.
  2. After rebooting from the B slot, we check if the system is working correctly, and if everything is OK, we tell the bootloader that the upgrade was successful.

In case of any problems with the update, the bootloader will revert to the old firmware version after several unsuccessful attempts to boot from the new one.

On the official website for developers — Android Source — this process is described in more detail within 9 steps; it also explains how everything works after the reboot.

A feature of the seamless A/B update scheme is that it “eats up” more flash memory. How much more? This can be estimated from the partition maps for Android 9.0 (see below). As mentioned earlier, a software engineer can choose between the schemes to apply to the system configuration: A/B or non-A/B.

Android P partition map (recovery):

[mmcblk0p01] bootloader offset 0x000000000000, size 0x000000400000
[mmcblk0p02] reserved offset 0x000002400000, size 0x000004000000
[mmcblk0p03] cache offset 0x000006c00000, size 0x000046000000
[mmcblk0p04] env offset 0x00004d400000, size 0x000000800000
[mmcblk0p05] logo offset 0x00004e400000, size 0x000000800000
[mmcblk0p06] recovery offset 0x00004f400000, size 0x000001800000
[mmcblk0p07] misc offset 0x000051400000, size 0x000000800000
[mmcblk0p08] dtbo offset 0x000052400000, size 0x000000800000
[mmcblk0p09] cri_data offset 0x000053400000, size 0x000000800000
[mmcblk0p10] param offset 0x000054400000, size 0x000001000000
[mmcblk0p11] boot offset 0x000055c00000, size 0x000001000000
[mmcblk0p12] rsv offset 0x000057400000, size 0x000001000000
[mmcblk0p13] metadata offset 0x000058c00000, size 0x000001000000
[mmcblk0p14] vbmeta offset 0x00005a400000, size 0x000000200000
[mmcblk0p15] tee offset 0x00005ae00000, size 0x000002000000
[mmcblk0p16] vendor offset 0x00005d600000, size 0x000040000000
[mmcblk0p17] odm offset 0x00009de00000, size 0x000008000000
[mmcblk0p18] system offset 0x0000a6600000, size 0x000050000000
[mmcblk0p19] product offset 0x0000f6e00000, size 0x00000800000

Android P partition map (A/B scheme):

[mmcblk0p01] bootloader offset 0x000000000000, size 0x000000400000
[mmcblk0p02] reserved offset 0x000002400000, size 0x000004000000
[mmcblk0p03] cache offset 0x000006c00000, size 0x000000000000
[mmcblk0p04] env offset 0x000007400000, size 0x000000800000
[mmcblk0p05] logo offset 0x000008400000, size 0x000000800000
[mmcblk0p06] boot_a offset 0x000009400000, size 0x000001000000
[mmcblk0p07] misc offset 0x00000ac00000, size 0x000000800000
[mmcblk0p08] dtbo_a offset 0x00000bc00000, size 0x000000800000
[mmcblk0p09] dtbo_b offset 0x00000cc00000, size 0x000000800000
[mmcblk0p10] cri_data offset 0x00000dc00000, size 0x000000800000
[mmcblk0p11] param offset 0x00000ec00000, size 0x000001000000
[mmcblk0p12] boot_b offset 0x000010400000, size 0x000001000000
[mmcblk0p13] rsv offset 0x000011c00000, size 0x000001000000
[mmcblk0p14] metadata_a offset 0x000013400000, size 0x000001000000
[mmcblk0p15] metadata_b offset 0x000014c00000, size 0x000001000000
[mmcblk0p16] vbmeta_a offset 0x000016400000, size 0x000000200000
[mmcblk0p17] vbmeta_b offset 0x000016e00000, size 0x000000200000
[mmcblk0p18] tee offset 0x000017800000, size 0x000002000000
[mmcblk0p19] vendor_a offset 0x00001a000000, size 0x000040000000
[mmcblk0p20] vendor_b offset 0x00005a800000, size 0x000040000000
[mmcblk0p21] odm_a offset 0x00009b000000, size 0x000008000000
[mmcblk0p22] odm_b offset 0x0000a3800000, size 0x000008000000
[mmcblk0p23] system_a offset 0x0000ac000000, size 0x000050000000
[mmcblk0p24] system_b offset 0x0000fc800000, size 0x000050000000
[mmcblk0p25] product_a offset 0x00014d000000, size 0x000008000000
[mmcblk0p26] product_b offset 0x000155800000, size 0x000008000000
[mmcblk0p27] data offset 0x00015e000000, size 0x000245e00000

If to compare these two configurations, you will notice that the data partition in the A/B scheme is 1.6 GB smaller, and this is the price of duplicate system partitions. Whether this is a lot or not is up to everyone to decide, based on their device/project characteristics.

3.3. The Treble project

The next changes to the update system took place in Android 8.0. Starting with Android O (8.0) and continuing with Android P (9.0), Google has been implementing its Treble project. The idea of the project is to simplify the technological process of creating an update for Android devices. Google suggested separating parts of the firmware created by different companies with the help of unchangeable interfaces. The process of developing firmware for a particular device can be simplified into the following steps:

  1. The Android team creates a new version of their OS.
  2. A chip/SoC vendor (Silicon Manufacturer) creates hardware-dependent patches to run this version of Android on its board.
  3. A designer of the final device (Vendor) does its part in implementing all the functions of a particular product for the target electronics market.

The Treble project distinguishes between the Android OS with add-ons from Silicon Manufacturers and code added by Vendors so that the operating system can now receive updates without implementing changes from the device manufacturer.

The separation takes place both through the software interface (switching from Hardware Abstraction Layer 1.0 to HAL2.0) and by allocating separate partitions on the flash memory for Silicon Manufacturer and Vendor (you can see the odm, vendor, product partitions in the Android 9.0 partition map above).

The transition from HAL1.0 to HAL2.0 eliminates the direct linkage with system libraries. Instead, using the IPC Binder, you can connect to system services.

Comparison of vendor implementations before and after the Treble project

And one more small but useful change: starting from Android 8.0, update_engine added support for the A/B streaming updates, during which it writes directly to the B slot without the need for intermediate data storage in /data. These streaming updates require almost no temporary storage, just 100 kilobytes to store metadata.

This requires that the http server used to download the update should support HTTP range requests, or in other words, download resumption.

3.4. The Mainline project

The next major step in the development of the Android update system was the Mainline project. It began with Android 10.0 and continued with the current Android 11.0.

The Mainline project allows you to upgrade individual system components without upgrading the entire OS. The necessary data is downloaded via Google Play separately from the OTA firmware update from the manufacturer. It is expected that the direct delivery of updates, which is not tied to hardware parts of Android, will significantly reduce the time it takes to receive updates, increase the speed of vulnerability fixes and reduce dependence on device manufacturers to support the security of the OS.

For the implementation of the Mainline project, selected components of the Android system are converted into modules. Some of these modules have the old APK format, while others are converted to the new APEX format, which differs from APK in its ability to be used in an early system’s boot phase. In case of possible failures, there is a mode of changes rollback.

APEX packets are handled by the APEX manager system service (apexd). It is a native service that, after verification, unpacks the APEX package into the user’s disk space and adds a record of it to its database. On the next system boot, the APEX manager checks all packages from the database, creates the ext4 image for each APEX package and mounts it at /apex/name@ver.

Modules with updates will initially come with open source code; they will be immediately available in the AOSP repositories (Android Open Source Project) and can include improvements and fixes prepared by third parties.

The Mainline project added 13 updatable modules to Android 10, and 11 more modules to Android 11.

Android Framework with Mainline modules

3.5. The virtual A/B scheme

The Virtual A/B scheme has been added to the non-A/B and A/B schemes in Android 11. This new update mechanism combines the advantages of both predecessors, it provides a crash-proof update of the device while using a minimal amount of flash memory. This is made possible by creating snapshots of the file system using Dynamic Partitions and the Device-mapper technology (a subsystem of the Linux kernel that allows you to create virtual block devices).

Dynamic Partitions is a dynamic partitioning system for Android. You can use it to create, resize, or delete partitions within the over-the-air (OTA) update. With dynamic partitions, software developers no longer have to worry about the size of individual partitions such as system, vendor, and product. Instead, a super partition is allocated on the device, and subsections can be dynamically resized within it. You no longer need to leave free space for future OTA updates inside individual partition images. The remaining free space in the super partition is now available for all dynamic subsections.

One last thing. Rumors of the end of 2020 as a cherry on a cake. Google is converting the Android Runtime to a Mainline module. The Android Runtime or ART is an execution environment for Android applications that includes the compilation of the app bytecode into machine instructions. So there is a chance that in Android 12, you will be able to update ART via Google Play by installing the APEX package.

It is also likely that the Android update system will migrate to Fuchsia, a new OS by Google, which is currently under development. They traditionally copy successful solutions to their other software products. For example, the update_engine for the A/B-scheme, which is currently used in Android, is also used in Chrome, another OS designed by Google. Or one more example: Fuchsia offers the Machina library, which allows you to run Linux programs in a special isolated virtual machine, similar to the way Linux applications are run in Chrome OS.

So, may a successful update be with you and your Android devices!

P. S. Do you remember what they said about it in Indiana Jones?
Elsa: Dr. Jones? I knew it was you, you have your father’s eyes.
Indiana Jones: And my mother’s ears but the rest belongs to you.

About the author: Hi, I’m Ivan Kuten, a co-owner & CTO at Promwad, where we design new electronics and embedded software for smart TV, IoT, and other industries. My hobby is to solve engineering challenges, to study new technologies, and to share my experience with others. Feel free to add me on LinkedIn; I will be glad to connect with you.

--

--

Ivan is a co-owner & tech expert at Promwad Electronics Design House, where startups & mature companies transform their ideas into new devices & apps