This page presents several mechanisms that Android device OEMs can use to have their own shared system image (SSI) across product lines. It also proposes a procedure for basing an OEM-owned SSI on an AOSP-built generic system image (GSI).
With Project Treble, monolithic Android was split into two parts: the hardware-specific part (the vendor implementation) and the generic OS part (the Android OS framework). The software for each is installed in a separate partition: the vendor partition for the hardware-specific software, and the system partition for the generic OS software. A versioned interface, called the vendor interface (VINTF), is defined and enforced across the two partitions. By using this partitioning system, you can modify the system partition without modifying the vendor partition, and vice versa.
The framework code released in AOSP has been compliant with the Treble architecture and has maintained backward compatibility with older vendor implementations. For example, a generic system image built from Android 10 AOSP sources can run on any Treble-compliant device that’s running on Android 8 or higher. The version of Android that’s shipped on consumer devices is modified by SoC vendors and OEMs. (See Life of an Android Release.) These changes and extensions that were made to the framework weren't written for maintaining backward compatibility, which translated to increased complexity and higher cost in an OS upgrade. Device-specific changes and modifications add to the cost and complexity of upgrading an Android OS version.
Before Android 11 there was no clear architecture that enabled partners to build modular extensions to the Android OS framework. This document describes the steps that SoC vendors and OEMs can take to create an SSI. This means one image, built from the Android OS framework sources for reuse across multiple devices, for maintaining backward compatibility with vendor implementations, and for providing a significant reduction in the complexity and cost of Android OS upgrades. For the specific steps you need to create an SSI, see the Suggested steps for GSI-based SSI section, and note that you don’t have to use all four steps. Which steps you choose (only Step 1, for example) depends on your implementation.
With SSI, product-specific software components and OEM extensions are placed in
/product partition. The components in the
/product partition use a
well-defined, stable interface to interact with components in the
partition. OEMs can either choose to build one SSI, or to have a small number of
SSIs for use across multiple device SKUs. When a new version of the Android OS
is released, OEMs invest only once in updating their SSIs to the latest
Android release. They can reuse the SSIs to update multiple devices without
Note that OEMs and SoC vendors build SSIs that include all the custom features and modifications that an OEM needs. The mechanisms and best practices provided on this page are intended for OEMs to use to reach these key goals:
- Reuse the SSI across multiple device SKUs.
- Update the Android system with the modular extensions to make OS upgrades easier.
The core idea of separating product-specific components into the product partition is similar to the Treble idea of separating SoC-specific components into the vendor partition. A product interface (similar to VINTF) allows communication between SSI and the product partition. Note that with respect to SSI, the term “components” describes all the resources, binaries, texts, libraries, and so on that are installed to images, which essentially become partitions.
Partitions around SSI
Figure 1 shows partitions around SSI, and the versioned interfaces across the partitions and policies on the interfaces. This section explains each of the partitions and interfaces in detail.
Figure 1. Partitions and interfaces around SSI
Images and partitions
The information in this section distinguishes between the terms image and partition.
- An image is a conceptual piece of software that can be updated independently.
- A partition is a physical storage location that can be updated independently.
The sections in Figure 1 are defined as follows:
SSI: The SSI is the image that’s common to an OEM, and can exist across multiple devices. It doesn't have any hardware-specific or product-specific components. Everything in a given SSI is, by definition, shared among all devices using that SSI. The SSI is composed of either a single
/systemimage, or a
/system_extpartitions, as seen in Figure 1.
/systempartition contains AOSP-based components, while
/system_ext, when implemented, contains OEM and SoC vendor extensions and components that are tightly coupled with AOSP components. For example, an OEM Java framework library that provides custom APIs for the OEM’s own apps fits better in the
/system_extthan in the
/systempartition. Content for both the
/system_extpartitions is built from OEM-modified Android sources.
/system_extpartition is optional, but it’s beneficial to use it for any custom features and extensions that are tightly coupled with AOSP- based components. This distinction helps you identify changes you need to make, to move such components from the
/system_extpartition to the
/productpartition over a period of time.
Product: A collection of product- or device-specific components that represent OEM customizations and extensions to the Android OS. Put SoC-specific components in the
/vendorpartition. SoC vendors can also use the
/productpartition for appropriate components, such as SoC-independent ones. For example, if an SoC vendor provides an SoC-independent component to their OEM customers (that’s optional to ship with the product), the SoC vendor can place that component in the product image. The location of a component isn’t determined by its ownership, it’s dictated by its purpose.
Vendor: A collection of SoC-specific components.
ODM: A collection of board-specific components that aren’t provided by the SoC. Typically the SoC vendor owns the vendor image, while the device maker owns the ODM image. When there is no separate
/odmpartition, both the SoC vendor and ODM images are merged together in the
Interfaces between images
Two main interfaces for vendor and product images exist around SSI:
Vendor Interface (VINTF): VINTF is the interface to the components that reside in the vendor and the ODM images. Components in the product and system images can only interact with the vendor and ODM images through this interface. For example, a vendor image can’t depend on a private part of the system image, and vice versa. This is originally defined in Project Treble, which split the images into system and vendor partitions. The interface is described using the following mechanisms:
- HIDL (Passthrough HAL is only available for
- Stable AIDL
- System properties API
- Config file schema API
- Android SDK APIs
- Java SDK library
- HIDL (Passthrough HAL is only available for
Product Interfaces: The product interface is the interface between SSI and the product image. Defining a stable interface decouples the product components from the system components in an SSI. The product Interface requires the same stable interfaces as VINTF. However, only the VNDK and Android SDK APIs are enforced for devices launching with Android 11 (and higher).
Enabling SSI in Android 11
This section explains how to use the new features in place to support SSI in Android 11.
The /system_ext partition
/system_ext partition was introduced in Android 11 as an optional
partition. (It’s the place for non-AOSP components that have tight coupling with
the AOSP-defined components in the
/system partition.) The
partition is assumed to be the OEM-specific extension to the
partition, without an interface defined across the two partitions. Components in
/system_ext partition can make private API calls into the
partition, and components in the
/systempartition can make private API calls
Because the two partitions are tightly coupled, both partitions are upgraded
together when a new Android version is released. A
created for the previous release of Android doesn’t need to be compatible with
/system partition in the next Android release.
To install a module to the
/system_ext partition, add
Android.bp file. For devices that don't have a
partition, install such modules to the
./system_ext subdirectory in the
Here is some history about the
/system_ext partition. The design goal was to
place all OEM-specific components, regardless of whether they're common, in the
/product partition. However, moving them all at once wasn’t feasible,
especially when some components had a tight coupling with the
partition. To move a tightly coupled component to the
/product partition, the
product interface must be extended. This often required the component itself to
be extensively refactored, which consumes a lot of time and effort. The
/system_ext partition started as a place to temporarily host those components
that aren’t ready to be moved to the
/product partition. The goal of the SSI
was to eventually eliminate the
/system_ext partition is useful for keeping the
partition as close to AOSP as possible. With SSI, most of the upgrade effort is
spent on the components in the
/system and the
When the system image is built from sources that are as similar as possible to
those in AOSP, you can focus the upgrade effort on the
Unbundling components from
/system_ext partitions into the
Android 9 introduced a
that’s coupled with the
/system partition. The modules in the
/product partition use the system resources without any restriction, and vice
versa. To make SSI possible in Android 10, the product components are split into
/product partitions. The
/system_ext partition doesn’t
have to adhere to the restrictions on using system components that the
/product partition did in Android 9. Starting in Android 10, the
partition must be unbundled from the
/system partition and must use stable
interfaces from the
/system_ext partition's primary purpose is to extend system features,
rather than to install bundled product modules, as described in the
/system_ext partition section. To do this, unbundle
the product-specific modules and move them into the
Unbundling the product-specific modules makes
/system_ext common to the
devices. (For more detail, see Making the /system_ext partition common.)
To unbundle the
/product partition from the system components, the
partition must have the same enforcement policy as the
/vendor partition that
was already unbundled with Project Treble.
Starting in Android 11, native and Java interfaces for the
are enforced as described below. For more information, see
Enforcing Product Partition Interfaces.
- Native interfaces: The native modules in the
/productpartition must be unbundled from the other partitions. The only allowed dependencies from the product modules are some VNDK libraries (including LLNDK) from the
/systempartition. JNI libraries that the product apps depend on must be NDK libraries.
- Java interfaces: The Java (app) modules in the
/productpartition can’t use hidden APIs, because they’re unstable. These modules must only use public APIs and system APIs from the
/systempartition, and Java SDK libraries in the
/system_extpartition. You can define Java SDK libraries for custom APIs.
Suggested steps for GSI-based SSI
Figure 2. Suggested partitions for GSI-based SSI
A generic system image (GSI) is the system image that’s built directly from AOSP. It’s used for the Treble compliance tests (for example, CTS-on-GSI) and as a reference platform that app developers can use to test the compatibility of their apps when they don’t have a real device running the required version of Android.
OEMs can also use GSI to make their SSI. As explained in Images and partitions,
SSI consists of the system image for the AOSP-defined components
system_ext image for the OEM-defined components. When GSI is used as
system image, the OEM can focus on the
system_ext image for the upgrade.
This section provides a guide to OEMs who want to modularize their
customizations into the
/product partitions while using an
AOSP or near-AOSP system image. If OEMs build the system image from AOSP
sources, then they can substitute the system image that they build with the GSI
provided by AOSP. However, OEMs don’t need to reach the final step (using GSI as
it is) all at once.
Step 1. Inheriting generic_system.mk for OEM’s system image (OEM GSI)
(which was named
mainline_system.mk in Android 11, and renamed to
AOSP), the system image (OEM GSI) includes all the files that the AOSP GSI has.
These files can be modified by OEMs, so that the OEM GSI can contain the OEM
proprietary files in addition to the AOSP GSI files. However, OEMs aren't
allowed to modify the
generic_system.mk file itself.
Figure 3. Inheriting
generic_system.mk for OEM’s system image
Step 2. Making the OEM GSI have the same list of files with the AOSP GSI
The OEM GSI can’t have additional files at this stage. The OEM’s proprietary
files must be moved out to the
Figure 4. Moving added files out of the OEM GSI
Step 3. Defining an allowlist to limit the modified files in the OEM GSI
To check the modified files, OEMs can use the
tool, and compare the AOSP GSI with the OEM GSI. Obtain the AOSP GSI from the
AOSP lunch target
By running the
compare_images tool periodically with the
parameter, you can monitor the differences outside the allowed list. This prevents
needing additional modifications to the OEM GSI.
Figure 5. Define an allowlist to reduce the modified files list in the OEM GSI
Step 4. Making the OEM GSI have the same binaries as the AOSP GSI
Cleaning up the allowlist allows OEMs to use the AOSP GSI as the system image for their own products. To clean up the allowlist, OEMs can either abandon their changes in the OEM GSI, or upstream their changes to AOSP so that the AOSP GSI includes their changes.
Figure 6. Making the OEM GSI have the same binaries as the AOSP GSI
Defining SSI for OEMs
Protect the /system partition at build time
To avoid any product-specific changes in the
/system partition and define the
OEM GSI, OEMs can use a makefile macro called
to prevent any declaration of system modules after the macro is called. See
the Create makefile and enable artifact path check example.
OEMs can define a list to allow product-specific modules to be installed in the
/system partition temporarily. However, the list must be empty to make the OEM
GSI common to all of the OEM’s products. This process is for defining the OEM
GSI and can be independent from the steps for the AOSP GSI.
Enforce product interfaces
To guarantee that the
/product partition is unbundled, OEMs can ensure their
devices enforce the product interfaces by setting
for native modules, and
for Java modules. These variables are automatically set if the
PRODUCT_SHIPPING_API_LEVEL of the device is greater than or equal to
detailed information, see Enforcing Product Partition Interfaces.
/system_ext partition common
/system_ext partition might differ between devices, because it can have
device-specific, system-bundled modules. Because the SSI consists of
/system_ext partitions, the differences in the
hinder OEMs from defining an SSI. OEMs can have their own SSI and can share that
SSI among multiple devices by removing any differences and making the
/system_ext partition common.
This section gives recommendations for making the
/system_ext partition common.
Expose hidden APIs in the system partition
Many product specific-applications can’t be installed in the product partition because they use hidden APIs, which are prohibited in the product partition. To move device-specific applications to the product partition, remove the use of hidden APIs.
The preferred way to remove hidden APIs from the applications is to find the alternative public or system APIs to replace them. If there are no APIs to replace the hidden APIs, OEMs can contribute to AOSP to define the new system APIs for their devices.
Alternatively, OEMs can define custom APIs by creating their own Java SDK library
/system_ext partition. It can use hidden APIs in the system partition,
and can provide the APIs to the applications in the product or vendor partition.
OEMs must freeze the product-facing APIs
for backward compatibility.
Include the superset of all APKs and skip some packages installs for each device
Certain packages that are bundled with the system aren’t common across devices.
Unbundling these APK modules to move them to the product or the vendor partition
can be difficult. As an interim solution, OEMs can make the SSI include all the
modules, then filter unwanted ones out by using a SKU property
ro.boot.hardware.sku). To use the filter, OEMs overlay the framework
For more precise settings, declare a broadcast receiver that disables
unnecessary packages. The broadcast receiver calls
to disable the package when it receives the
Define RRO instead of using static resource overlay
A static resource overlay manipulates the overlaid packages. However, it can impede defining an SSI, so ensure that properties for RRO are turned on and set properly. By setting the properties as follows, OEMs can have all auto-generated overlays as RROs.
PRODUCT_ENFORCE_RRO_TARGETS := * PRODUCT_ENFORCE_RRO_EXCLUDED_OVERLAYS := # leave it empty
If a detailed configuration is required, define an RRO manually instead of
relying on an auto-generated one. For detailed information, see Runtime Resource Overlays (RROs).
OEMs also can define conditional RROs that depend on the system properties by
Frequently asked questions (FAQ)
Can I define multiple SSIs?
It depends on the commonality and characteristics of devices (or device group).
OEMs can try to make the
system_ext partition common, as described in
Making the system_ext partition common. If a device
group has many differences, then it’s better to define multiple SSIs.
Can I modify
mainline_system.mk) for an OEM GSI?
No. But OEMs may define a new makefile for an OEM GSI that inherits the
generic_system.mk file and use the new makefile instead. For an example, see
Enforcing Product Partition Interfaces.
Can I remove modules from
generic_system.mk that conflict with my implementation?
No. GSI has a minimum set of bootable and testable modules. If you think a
module isn't essential, please file a bug to update the