Android Upgrades, Custom ROMs (LineageOS), & Kernels

Porting A/B Seamless Updates to Custom ROMs (LineageOS): A Developer’s Guide

Google AdSense Native Placement - Horizontal Top-Post banner

Introduction to A/B Seamless Updates

Android’s A/B (Seamless) System Updates, introduced with Android 7.0 Nougat, revolutionized the update process by providing a safer, more robust, and user-friendly experience. Unlike traditional updates that require a dedicated recovery partition and significant downtime, A/B updates allow a device to update in the background while still operational. If an update fails, the device can simply roll back to the previously working system. For custom ROM developers, particularly those maintaining LineageOS for various devices, integrating and properly configuring A/B updates can be a complex but highly rewarding endeavor, significantly enhancing the user experience.

This guide delves into the technical specifics of Android’s A/B update mechanism and provides a comprehensive, expert-level walkthrough for porting this functionality to custom ROMs, using LineageOS as a primary example. We’ll cover the necessary device tree modifications, kernel considerations, and build system adjustments to achieve seamless updates on your custom builds.

The Android A/B Update Mechanism Explained

At its core, A/B updating works by maintaining two complete sets of system partitions, typically referred to as ‘slot A’ and ‘slot B’. Only one slot is active at any given time. When an update is released:

  • The update is downloaded and installed onto the *inactive* slot.
  • The device continues to run normally from the *active* slot.
  • Upon the next reboot, the device attempts to boot from the newly updated, previously inactive slot.
  • If the boot is successful, the new slot becomes active. If it fails, the device automatically reverts to the previous, working slot (the one that was active before the update attempt).

Key Components of A/B Updates

  • Dual Partition System: Critical partitions like `system`, `vendor`, `product`, `odm`, and `system_ext` are duplicated (e.g., `system_a`, `system_b`).

  • `update_engine`: A userspace daemon responsible for managing the update process. It downloads, verifies, and applies updates to the inactive slot.

  • `boot_control` HAL: An interface that allows the system to communicate with the bootloader to determine the active slot, mark a slot as successfully booted, or switch slots.

  • `dm-verity` (Device Mapper Verity): Ensures the integrity of system partitions by cryptographically verifying blocks as they are read. Essential for A/B to prevent tampering and enable rollback to a known good state.

  • Dynamic Partitions (`super` partition): On newer Android devices (Android 10+), logical partitions like `system`, `vendor`, `product` reside within a single `super` partition, allowing for more flexible partition sizing and management. This is often leveraged with ‘Virtual A/B’ for space efficiency.

Prerequisites for A/B Custom ROM Porting

Before diving into the code, ensure your device meets these foundational requirements:

Device Tree Configuration (`BoardConfig.mk`)

Your device’s `BoardConfig.mk` file must explicitly enable A/B support and properly define dynamic partition groups if your device uses them. Key flags include:

  • `BOARD_AVB_ENABLE := true`: Enables Android Verified Boot (AVB) and A/B updates.
  • `BOARD_USES_VIRTUAL_AB := true`: For devices utilizing dynamic partitions and Virtual A/B. This optimizes storage by not requiring fully duplicated `system_a`/`system_b` physical partitions but rather logical slots within the `super` partition.
  • `BOARD_SUPER_PARTITION_SIZE`: The total size of your `super` partition (e.g., `8589934592` for 8GB).
  • `BOARD_SUPER_PARTITION_GROUPS`: Defines logical groups within the `super` partition. For A/B, you’ll typically have an `android_system` group containing `system`, `vendor`, etc.

Kernel Requirements

The kernel running on your device must have specific device-mapper features enabled to support A/B and `dm-verity`. Check your kernel configuration (`/proc/config.gz` on a running device or your kernel source tree’s `.config` file) for:

  • `CONFIG_DM_VERITY=y`
  • `CONFIG_DM_LINEAR=y`
  • `CONFIG_DM_ZERO=y` (sometimes required)
  • `CONFIG_ANDROID_OEM_PARTITION=y` (if applicable for `product`/`odm`)

Without these, `dm-verity` will fail, leading to boot loops or update failures.

Step-by-Step Porting A/B to LineageOS

This section provides a practical guide to modifying your LineageOS device tree.

Step 1: Initialize Your Device Tree and Manifest

Ensure you have a working LineageOS build environment and a device tree for your target device. If starting fresh:

repo init -u https://github.com/LineageOS/android.git -b lineage-20.0 # Or your desired branchrepo sync

Navigate to your device’s tree: `device//`.

Step 2: Configure `BoardConfig.mk` for A/B and Dynamic Partitions

Open `BoardConfig.mk` and add or modify the following lines. The exact values for partition sizes and groups will depend on your device’s original partition layout.

# A/B UpdatesBOARD_AVB_ENABLE := trueAB_OTA_UPDATER := trueBOARD_USES_VIRTUAL_AB := true # Use true for dynamic partitionsBOARD_SUPER_PARTITION_SIZE := 8589934592 # Example: 8GBBOARD_SUPER_PARTITION_GROUPS := android_systemBOARD_ANDROID_SYSTEM_PARTITION_SIZE := 0 # Auto-sized by dynamic partitionsBOARD_ANDROID_SYSTEM_EXT_PARTITION_SIZE := 0BOARD_ANDROID_PRODUCT_PARTITION_SIZE := 0BOARD_ANDROID_VENDOR_PARTITION_SIZE := 0BOARD_ANDROID_ODM_PARTITION_SIZE := 0# Define dynamic partitions in the super partition groupTARGET_COPY_OUT_PRODUCT := system/productTARGET_COPY_OUT_SYSTEM_EXT := system_extTARGET_COPY_OUT_ODM := odmTARGET_COPY_OUT_VENDOR := vendor# Enable build of super.imgPRODUCT_BUILD_SUPER_PARTITION := truePRODUCT_USE_DYNAMIC_PARTITIONS := true# Optional: If you use a separate recovery, ensure it supports A/B recovery# TARGET_NO_RECOVERY := true (if recovery is part of boot.img)# TARGET_RECOVERY_FSTAB := $(LOCAL_PATH)/recovery/root/fstab.qcom (example)

Step 3: Verify Kernel Configuration

Ensure your kernel sources (found in `kernel//` or `device///kernel`) have the necessary `dm-verity` and device-mapper options enabled. If not, you’ll need to enable them via `make menuconfig` or by directly editing your kernel `.config` file. Rebuild your kernel after changes.

Step 4: Adjust `fstab` and `init.rc`

Ensure your `fstab.` file (`device///rootdir/fstab.`) properly handles the `super` partition and mounting of dynamic partitions. For A/B, the `fstab` typically references logical partition names (`/dev/block/mapper/system`) rather than `_a` or `_b` suffixes. The bootloader and `init` handle slot selection.

Verify that `update_engine` related services are not explicitly disabled in your device’s `init.rc` or `init.target.rc` files. These are typically handled by the generic Android `init` system, but custom modifications might interfere.

Step 5: Build and Test Your A/B ROM

With the configurations in place, build your LineageOS ROM:

source build/envsetup.shlunch lineage_<device_codename>-userdebugmka bacon # This builds the ROM and generates the OTA package

Initial Flash: For the first flash on an A/B device, you’ll typically flash a full factory image or use `fastboot update `. Ensure your `super` partition is correctly formatted. If coming from a non-A/B setup, a full erase and format might be required.

Testing OTA Updates:

  1. Flash your newly built ROM to your device.
  2. Make a small, trivial change in your device tree (e.g., modify `BUILD_NUMBER` or add a dummy file).
  3. Rebuild your ROM to generate a new `ota_update.zip`.
  4. Push the OTA ZIP to your device or sideload it: `adb sideload lineage_*.zip`
  5. Monitor the update process.
  6. After the update completes, reboot the device.
  7. Verify the active slot: `adb shell bootctl get-current-slot` and `adb shell bootctl get-active-slot`. They should both point to the newly updated slot (e.g., `_b` if you started on `_a`).
  8. To test rollback, deliberately cause a boot failure on the new slot (e.g., corrupt a system partition via `fastboot`). Upon reboot, the device should automatically revert to the previous working slot.

Troubleshooting Common A/B Porting Issues

  • `update_engine` Failures: Check `logcat | grep update_engine` for detailed errors. Common issues include insufficient space, `dm-verity` failures, or incorrect partition layouts.

  • Bootloops After Update: This often points to `dm-verity` issues or incorrect `fstab` entries. Ensure all required kernel modules are loaded and partitions are correctly defined and mounted.

  • Insufficient Super Partition Size: If you’re using dynamic partitions, ensure `BOARD_SUPER_PARTITION_SIZE` is large enough to accommodate all logical partitions for both slots, even if using Virtual A/B. The build system will report errors if space is insufficient.

  • AVB Verification Failures: If you see

    Android Mobile Specs & Compare Directory

    Are you researching mobile hardware properties, processor SoCs, GPU chipsets, or RAM configurations? Access our complete specs catalog to compare up to 5 devices side-by-side!

    Compare Devices Specs →
Google AdSense Inline Placement - Content Footer banner