VTS Testing with Debug Ramdisk

In Android 10, the generic system image (GSI) used to run CTS-on-GSI/VTS compliance testing changes from userdebug to user build type, because GSI is release signed. However, the adb root command that gives a host root permissions to the Android device under test isn't available in a user build. This is a problem because VTS requires adb root to run.

The debug ramdisk is introduced in Android 10 to make adb root possible, if the device is unlocked. This simplifies the testing flow by reusing the same user build GSI system.img. For STS setup, using another userdebug OEM system.img is still required. The following table shows images and build types for the compliance tests in Android 10.

Test suite Test with Build Debug ramdisk adb root? Android 9 -> 10 build variant change
CTS OEM’s system user N N No change
CTS-on-GSI GSI user N N

userdebug -> user GSI

release signed

STS OEM’s system userdebug N Y New in Q
VTS GSI user Y Y

userdebug -> user GSI

release signed

AOSP changes

The debug ramdisk changes in AOSP are identified by the debug_ramdisk hashtag.

These additional image files are generated under the build folder out/target/product/$(TARGET_DEVICE):

  • ramdisk-debug.img
  • boot-debug.img

When boot-debug.img is flashed onto the /boot partition of the device, the userdebug version of the system sepolicy file and an additional property file, adb_debug.prop, are loaded. This allows adb root with the user build system.img (either GSI’s or the OEM’s).

This also applies to devices with a vendor_boot-debug.img flashed onto the vendor_boot partition. i.e., the debug files can be loaded from either the /boot or the /vendor_boot partition.

Vendor boot debug ramdisk

Starting from Android 11, vendor_boot-debug.img should be flashed onto the /vendor_boot partition in VTS for devices supporting the Generic Kernel Image (GKI) architecture. And a signed GKI boot-${KERNEL_VERSION}.img should be flashed onto the /boot partition instead of a boot-with-debug-ramdisk-${KERNEL_VERSION}.img.

Prerequisites for using a debug ramdisk

The debug ramdisk is provided by the OEM running the compliance tests. It shouldn't be release signed, and it can only be used if the device is unlocked.

The debug ramdisk won't be generated or used for upgrading devices with:

  • BOARD_BUILD_SYSTEM_ROOT_IMAGE true
  • skip_initramfs in kernel command line

Updating sepolicy in the Debug Ramdisk is required for Android 11 GSI

When you use boot-debug.img, system sepolicy gets loaded from the file userdebug_plat_sepolicy.cil in a boot-debug.img. Please always incorporate new sepolicy changes from android{N}-gsi branches to rebuild boot-debug.img, for example, android11-gsi. Otherwise, the device might not be able to boot a new GSI image. This also applies to vendor_boot-debug.img for devices having a /vendor_boot partition.

Updating sepolicy in the Debug Ramdisk is NOT required for Android 12 GSI

Starting 09/29/2021, debug ramdisks no longer require updating with the repack_bootimg tool when using an Android 12 GSI starting from the following build.

  • Android 12: SGR1.210929.001 (7777720)

Because an Android 12 GSI incorporates the up-to-date userdebug_plat_sepolicy.cil and ignores userdebug_plat_sepolicy.cil from the debug ramdisk. See the CLs for details.

Repacking a debug ramdisk

Instead of incorporating sepolicy changes to rebuild boot-debug.img, partners can use repack_bootimg to update the sepolicy file into boot-debug.img (or vendor_boot-debug.img if the device uses a generic boot.img).

The steps are as follows:

  1. Download otatools.zip from https://ci.android.com. For example, download it from aosp_arm64-userdebug build artifacts.

  2. Run the following command to check repack_bootimg is available.

    $ unzip otatools.zip -d otatools
    $ export PATH="$PWD"/otatools/bin:"$PATH"
    $ repack_bootimg
    
  3. Download a generic boot-with-debug-ramdisk.img from GSI builds. For example, if you're using a generic system.img from RJR1.210927.001_7770257, then download the generic boot-with-debug-ramdisk-${KERNEL_VERSION}.img from the same version RJR1.210927.001_7770257.

  4. Run the following command to extract the userdebug sepolicy file from boot-with-debug-ramdisk-${KERNEL_VERSION}.img and update it into the device-specific boot-debug.img (or vendor_boot-debug.img).

    $ repack_bootimg --src_bootimg boot-with-debug-ramdisk-5.4.img --dst_bootimg boot-debug.img
    $ repack_bootimg --src_bootimg boot-with-debug-ramdisk-5.4.img --dst_bootimg vendor_boot-debug.img
    

The path of the userdebug sepolicy

The above repack_bootimg copies file /userdebug_plat_sepolicy.cil from the ramdisk of --src_bootimg to the ramdisk of --dst_bootimg. However, the path within a debug ramdisk might be different in different Android versions. In Android 10 and 11, the path is /first_stage_ramdisk/userdebug_plat_sepolicy.cil for devices with androidboot.force_normal_boot=1 in the kernel command line. Otherwise, the path is /userdebug_plat_sepolicy.

Run the following command to check if there is androidboot.force_normal_boot in the kernel command line:

$ adb root
$ adb shell cat /proc/cmdline | grep force_normal_boot

Starting from Android 12, the path within a debug ramdisk is always/userdebug_plat_sepolicy, regardless of the existence of androidboot.force_normal_boot=1 in the kernel command line. The following table shows the paths within a debug ramdisk in different Android versions.

Debug image Android 10 Android 11 Android 12
GKI boot-with-debug-ramdisk-${KERNEL_VERSION}.img N/A /first_stage_ramdisk/userdebug_plat_sepolicy.cil /userdebug_plat_sepolicy.cil
Device-specific boot-debug.img Depends on force_normal_boot Depends on force_normal_boot /userdebug_plat_sepolicy.cil
Device-specific vendor_boot-debug.img N/A Depends on force_normal_boot /userdebug_plat_sepolicy.cil

You can specify --ramdisk_add to copy files from and to different locations, with a list of src_path:dst_path pairs. For example, the following command copies file /userdebug_plat_sepolicy from a Android 12 boot-with-debug-ramdisk-5.4.img to /first_stage_ramdisk/userdebug_plat_sepolicy.cil within a Android 11 vendor_boot-debug.img.

$ repack_bootimg \
    --src_bootimg boot-with-debug-ramdisk-5.4.img \
    --dst_bootimg vendor_boot-debug.img \
    --ramdisk_add userdebug_plat_sepolicy.cil:first_stage_ramdisk/userdebug_plat_sepolicy.cil

If there is no androidboot.force_normal_boot=1 in the kernel command line, then the command should be adjusted as below to change the destination path to /userdebug_plat_sepolicy.

$ repack_bootimg \
    --src_bootimg boot-with-debug-ramdisk-5.4.img \
    --dst_bootimg vendor_boot-debug.img \
    --ramdisk_add userdebug_plat_sepolicy.cil:userdebug_plat_sepolicy.cil

The --help option also gives more examples.

$ repack_bootimg --help

If the image passed to --dst_bootimg is configured as a AVB-chained partition, a AVB footer needs to be added after running the repack_bootimg command.

For example, before running repack_bootimg, run the following command to check if a vendor_boot-debug.img has a chained AVB footer.

$ avbtool info_image --image vendor_boot-debug.img

If it originally has a chained AVB footer, a AVB footer needs to be added after running the repack_bootimg command. Using any test key to sign the vendor_boot-debug.img works because the debug ramdisk can only be used when a device is unlocked, which allows non-release key signed images on the /boot or /vendor_boot partition.

$ avbtool add_hash_footer --partition_name vendor_boot \
    --partition_size 100663296 \
    --algorithm SHA256_RSA4096 \
    --key otatools/external/avb/test/data/testkey_rsa4096.pem \
    --image vendor_boot-debug.img