[Treble-Enabled Device Guides, News, & Discussion] ssjgoku:
Recently I figured out how to flash GSIs on the emulator in Android Studio, and I'll share the process.

My device is MacBook Pro 14-inch M2 Pro, with MacOS 13.6.3 and Android Studio 2023.3.1.

Firstly, create a Virtual Device in Android Studio. In my case, I choose Android 14 as the image, the path of which is ~/Library/Android/sdk/system-images/android-34/default/arm64-v8a/. There is a "system.img" inside this directory. At first I thought it is an ext4 image, but actually it is a QEMU Raw disk image, which contains two partitions, vbmeta and super.

Inside the super partition, there are 5 partitions: system, system_ext, system_dlkm, product, vendor. Similar to what we do on Android devices, we need to replace the system partition with a GSI. The steps are as follows:

0. Preparations

1. Unpack the super partition to get the images of the 5 partitions mentioned above

2. Replace the system.img (from step 1) with a GSI and generate a new super.img

3. Extend the size of the QEMU image (optional)

4. Write the new super.img into the super partition

These steps are done under Linux.​

0. Preparations​

Download cvd-host_package.tar.gz from https://ci.android.com/builds/submitted/11997608/aosp_cf_arm64_phone-userdebug/latest , we need to use lpunpack and lpmake inside it to unpack the super partition and generate a new super.img respectively.

Prepare a GSI, I use Miku UI GSI (https://github.com/xiaoleGun/treble_build_miku/releases/tag/Udon_v2-0.9.0) in my case.

1. Unpack the super partiton​

Run losetup -f to get an available loop, in my case it is /dev/loop7. Then run the following commands to unpack the super partition:

losetup /dev/loop7 system.img && kpartx -a /dev/loop7
lpunpack /dev/mapper/loop7p2 lpunpack_out/
kpartx -d /dev/loop7 && losetup -d /dev/loop7

In the commands above, "system.img" is the QEMU Raw image, "lpunpack_out" is the directory where the extracted images are.

Now we should find 5 img files in the output directory: system.img, system_ext.img, system_dlkm.img, product.img, vendor.img.

2. Replace system.img and generate a new super.img​

Many GSIs contains product and system_ext as well, in this case, we do not need to pack the product.img and system_ext.img.

Run the following command to generate a new super.img:

lpmake --metadata-size 65536 --super-name super --metadata-slots 1 --device super:4294967296 --group main:4012691456 \
--partition system:none:3914780672:main --image system=gsi.img \
--partition vendor:none:93540352:main --image vendor=vendor.img \
--partition system_dlkm:none:4370432:main --image system_dlkm=system_dlkm.img \
--output super.img

Explanations of the command:

* --device super:4294967296

The size of generated super.img, it must be divisible by 512.

* --group main:4012691456

The sum of the sizes of the 3 img files (3914780672+93540352+4370432).

* --partition system:none:3914780672:main --image system=gsi.img

The filename of GSI is gsi.img, its size is 3914780672, and it is written into the system partition.

The other 2 lines are similar, where vendor.img and system_dlkm.img are extracted from the super partition in step 1.

3. Extend the size of the QEMU image (optional)​

If the generated super.img is larger than the original super partition, we need to resize system.img (the QEMU image, not the extracted system.img).

This can be done under Linux or MacOS. For example, this command extends 3G for system.img:

qemu-img resize -f raw system.img +3G

Delete the original super partition, and create a larger one:

sgdisk -e system.img
gdisk system.img

View attachment 6118097

4. Write the new super.img into the super partition

This can be done under Linux or MacOS.

Linux:

losetup /dev/loop7 system.img && kpartx -a /dev/loop7
cat super.img > /dev/mapper/loop7p2
kpartx -d /dev/loop7 && losetup -d /dev/loop7

MacOS:

hdiutil attach -imagekey diskimage-class=CRawDiskImage -nomount system.img
cat super.img > /dev/disk4s2
hdiutil detach /dev/disk4

As mentioned before, "loop7" or "disk4" varies by your environment.

Put the system.img back to the original path (~/Library/Android/sdk/system-images/android-34/default/arm64-v8a/ in my case), now we can boot the emulator (with permissive SELinux):

emulator -avd AVD_NAME -no-snapshot-save -no-snapshot-load -show-kernel -verbose -selinux permissive

Where AVD_NAME is the name of the AVD created at the beginning, it can be found via running "emulator -list-avds".

View attachment 6118103View attachment 6118104View attachment 6118105

If failed unfortunately, check the logs and search for appropriate solutions.