Fun with GSIs: A retrospective on Project Treble’s impact on custom ROMs
In last week’s edition of Android Dessert Bites, I talked about how Google plans to standardize virtualization on Android in order to combat fragmentation. Fragmentation is a term you’ll see a lot in this column, but when I use it, it’ll usually be when I’m talking about the distribution of Android OS versions — last week was an exception. Android fragmentation is not a problem that Google can solve overnight considering there are over 3 billion active Android devices made by over 140 different brands, but to Google’s credit, it made huge strides in reducing fragmentation.
With the architecture introduced by Project Treble in 2018, which Google frequently cites as the reason new OS versions are being adopted more quickly, the system image on Android devices can be genericized, resulting in what’s called a generic system image (GSI). The GSI contains the unmodified OS framework from AOSP and is intended to be used to speed up compatibility testing of hardware components during the bring up of a new OS version. However, members of the Android community had another idea in mind for the GSI: to use it as a base for developing custom ROMs that can boot on any Treble-supporting hardware. It’s been nearly four years since the first proof-of-concept, so for this week’s Android Dessert Bites, I’ll provide a broad overview of Project Treble and showcase some of the work on GSIs done by community developers.
How Google rearchitected Android with Project Treble
How exactly did Project Treble change the way Android is architected? Put simply, it began the process of separating vendor-specific software code from the Android OS framework contained within the system image. This vendor-specific software code consists mostly of hardware abstraction layers (HALs) that interact with the device’s specific hardware components. In order for the OS framework to communicate with HALs, Google worked with its OEM and silicon vendor partners to define a vendor interface (VINTF) with standardized code written in an interface definition language like HIDL (pre-Android 10) or AIDL (post-Android 10). Thus, by reducing the system image down to the OS framework, moving all HALs to a new vendor partition, standardizing the communication between the OS and HALs, and mandating new compliance tests, Project Treble succeeded in rearchitecting Android to make it more modular and updatable.
If that doesn’t make sense to you, here’s an analogy that might clear things up. Think of a car and its basic components, like the steering wheel and brakes. The steering wheel and brakes are HALs in this analogy, since they control the movement of the car without the driver needing to understand how the car’s hardware works. Continuing with this analogy, the driver of the car is the operating system since they send the commands to the HALs (by turning the wheel or pressing the brakes) to make the car move. As for the vendor interface, that’d be the driving school where the driver learned the standard way to operate the steering wheel and brakes. Put together, Project Treble defines the way for a driver (Android) to drive a car (the device) through standardized actions learned in driving school (the vendor interface) to control the steering wheel and brakes (HALs).
Things get a bit more complicated when discussing how Treble handles compatibility between different versions of the OS and vendor implementation, as we then need to talk about the VNDK and interface versioning. These complexities affect how vendors support Treble, though, and they’ve been made moot by Google allowing vendors to “freeze” the vendor implementation with the launch of a new silicon platform. But you don’t need to think too hard about that, as all you really need to know is that AOSP maintains backward compatibility with older vendor implementations, which means that GSIs based on newer versions of Android should boot on devices without needing an accompanying update to the vendor image.
🧑🚀Wait, it’s a developer tool? 🔫🧑🚀Always has been
When Google first announced Project Treble back in 2017, I was led to believe that devices launching with Android 8.0 Oreo would be fully compatible with Project Treble. After all, that is what Google basically said when they stated that “Project Treble will be coming to all new devices launched with Android O and beyond.” So you’d assume that all Android 8.0 launch devices would be able to boot a GSI based on AOSP Android 8.0 Oreo or later without any trouble.
For some devices, that was indeed the case. For many other devices, however, GSIs were either unable to boot at all or were barely functional after booting. The reason is that these devices weren’t fully “Treblized”, a term that Google uses to describe software builds that meet Project Treble requirements. So despite what you read about Project Treble being introduced alongside Android 8.0 Oreo, it wasn’t until the launch of Android 9 Pie that the first fully Treble-compliant devices became available.
It may seem like Google quietly moved the goalposts on when Project Treble really came into play, but looking back, it was obvious that they were never going to be able to guarantee Treble compliance on newly launched devices after just a single OS release. Google can’t make major architectural changes to Android without feedback and support from its OEM and silicon vendor partners. Together, Google and its partners worked to define the vendor interface and validate the implementation using the GSI. But because Google never intended for the GSI to be used by consumers, validating Treble compliance means ensuring that the GSI boots and not much else.
For instance, the two automated tests that all device makers must run to validate Treble compliance — VTS and CTS-on-GSI — weren’t designed to enforce full compatibility with all hardware components. Second, AOSP did not include generic abstraction layers or implementations of some common hardware components, most notably the popular optical under-display fingerprint scanner. Google did finally add support for under-display fingerprint scanners in Android 12, but only because the Pixel 6 shipped with this hardware. A generic HAL for the Pixel 6 Pro’s ultra-wideband (UWB) radio, meanwhile, won’t be included until next year’s Android 13 release. Third, neither Google nor its partners bothered to fix some common bugs with GSIs, such as the lack of in-call audio and buggy Bluetooth audio on devices with Qualcomm chipsets.
Thus, a GSI you build from AOSP probably won’t be suitable for use on your daily driver device. Google even explicitly warns against installing a GSI on your personal device, as they state it’s only intended for system developers to test Treble compliance (as previously mentioned) and for app developers to test how their app behaves on real hardware running AOSP. Even if Google only sees the GSI as a developer tool and nothing more, that hasn’t stopped the custom ROM community from taking full advantage of it.
Fun with GSIs
Custom GSI development all started when a developer named phhusson decided to try his hand at validating the claim that Project Treble enables booting a genericized system image. After dozens of hours of researching, developing, and debugging, phhusson built the first community GSI that booted on phones from multiple different OEMs and had different SoCs. This development led to the creation of a Project Treble community on the XDA-Developers forums, but that was only the beginning.
Over the past few years, phhusson has led the development of a GSI that fixes many of the issues found in Google’s build, fixes quirks with specific devices, and extends Treble with additional hardware support. His GSI fixes the in-call audio and Bluetooth A2DP bugs that still affect Google’s own builds, for example. It also adds overlays to make things like the adaptive brightness slider work and bundles a settings app with a plethora of toggles to address device-specific issues like the refresh rate being fixed at the maximum on devices with displays that have high refresh rates. Just take a look at the release notes of his GSI to see how many device-specific quirks he’s addressed. It’s not an exaggeration to say that the entire community GSI development effort wouldn’t exist without phhusson.
Phhusson’s efforts are focused on fixing bugs with the AOSP GSI and not in making a custom ROM that’s daily driver ready, though, so his work is often underappreciated. However, it’s thanks to his patches and build scripts that other independent developers have been able to create their own GSIs with added features. A community maintained GSI list shows just how many projects rely on phhusson’s GSI, and it’s thanks to that list that I’ve been able to indulge in a lengthy session of custom ROM flashing this week.
To test some of the GSIs on that list, I grabbed my Lenovo Tab K10, a budget tablet with a MediaTek Helio P22T chipset and Android 11 out of the box. It’s a decent target to test GSIs on because its hardware is simple and it runs a newer version of Android. Because the Lenovo Tab K10 supports seamless updates through the virtual A/B partition scheme and features the userspace fastboot implementation, I couldn’t exactly follow the old method of installing GSIs. Fortunately, Google’s instructions for flashing a GSI onto a Pixel phone worked almost perfectly on my Tab K10 because they have a similar setup, though I did have to manually reboot to recovery to wipe the data partition because the ‘fastboot -w’ command was inexplicably not working.
One of the downsides of Google changing the partition layout seemingly every release is that picking and choosing which GSI to flash has become a bit complicated. Fortunately, there are apps that can help you decide, and the community maintained FAQ does a great job at breaking down the various acronyms you’ll see in build names. Based on the particular setup of the Tab K10, I downloaded and installed the following GSIs onto:
- Descendant 11.5 GSI based on Android 11 (descendant_gsi_arm64ab-11.5-20210912-Official.img)
- dotOS 5.2 GSI based on Android 11 (dotOS-R-v5.2-arm64-ab-VANILLA-OFFICIAL.img)
- LineageOS 18.1 GSI based on Android 11 (lineage-18.1-20211214-UNOFFICIAL-treble_arm64_bvS.img)
- Phh’s “Roar” GSI based on Android 11 (system-roar-arm64-ab-vanilla.img)
- Phh’s “Squeak” GSI based on Android 12 (system-squeak-arm64-ab-gapps.img)
- ProtonAOSP 12.1.0 GSI based on Android 12 (proton-12.1.0-a1-arm64_bvN.img)
For good measure, I also tested Google’s latest official GSI based on Android 12L Beta 1.
Here is a screenshot gallery showing these 7 different GSIs running on my Lenovo Tab K10 (for more screenshots, click on the links above to load the album):
Given the simplicity of the hardware in the Lenovo Tab K10, I wasn’t surprised that all of these GSIs worked. The tablet didn’t have multiple cameras or niche hardware components that a generic build of Android might not be able to interface with. Still, the Tab K10 is not the kind of device that a large developer community would organically grow around, so these GSIs are the only way an ordinary user would be able to experience these alternative software experiences.
I’d expect to lose out on some or many features if I tried these GSIs on more complicated hardware, which is why my recommendation is to use a GSI on less expensive hardware. If you have a spare phone lying around, try flashing a GSI to see what custom ROM developers are up to these days. Since installing a GSI only requires overwriting the system partition, it’s easy to revert the installation if you have a backup of the system partition from a factory image or firmware dump.
You do still need to unlock the bootloader of the device to enable flashing the system partition, though, which means your device will likely fail to pass SafetyNet Attestation (you can check using this app) without tamper detection bypasses enabled. Unlocking the bootloader also means your device’s Widevine L1 keys may be wiped (you can check the Widevine status using this app), which means you won’t be able to access higher quality streams from services that use Widevine DRM. Lastly, you’ll also need to disable verified boot by flashing an empty vbmeta image, because most GSIs aren’t signed with keys recognized by the bootloader.
These three issues are problems that most custom ROM users face, though, so they aren’t unique to GSIs. There are custom ROMs that don’t break Android’s security model (eg. GrapheneOS, CalyxOS, and DivestOS), but they aren’t offered as a GSI. If you’re concerned about security, then it’s probably best that you don’t unlock the bootloader to install custom software (or if you do, it’s to install one of the three aforementioned custom ROMs on a device that supports flashing custom AVB keys). If you have a spare device and just want to play around with the software, or you have an old device that you want to keep running for as long as possible, then give one of these community GSIs a shot rather than throwing them out — the world could use less electronic waste.
Thanks for reading this week’s edition of Android Dessert Bites. The GSI is a topic near and dear to me, because I was heavily involved in testing the first community GSI and promoting the GSI as a boon to custom ROM development. If you’re interested in learning more about the community GSI project, I recommend reading this wiki page. If you have any questions for me, you can contact me at email@example.com.