If a manufacturer is building three different smartphones (e.g., a base model, a "Pro" model, and an "Ultra" model), they do not want to write three massive, identical device.mk files.
To solve this, AOSP Product Makefiles heavily utilize Inheritance. Inheritance allows a device configuration to absorb the apps, settings, and hardware definitions from a "base" configuration, and then layer its own specific modifications on top.
The inherit-product Macro
Inheritance in AOSP is achieved using a specialized Makefile macro called inherit-product.
# device.mk for a custom smartphone
# 1. Inherit the core AOSP framework and default apps
$(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_base.mk)
# 2. Inherit the chipset vendor's specific drivers (e.g., Qualcomm)
$(call inherit-product, vendor/qualcomm/sm8450/board.mk)
# 3. Add our custom device-specific apps
PRODUCT_PACKAGES += \
MyCustomCamera \
MyCustomLauncher
When the build system parses this file, it will recursively evaluate the inherited files first. It will pull in the standard Android apps (like the default Settings app) from aosp_base.mk, merge them with the Qualcomm drivers, and finally append the custom camera app.
Layered Architecture
A well-architected AOSP device tree utilizes strict layering to maximize code reuse:
- AOSP Level: The absolute core Google framework (
aosp_base.mk). Every standard Android device inherits this. - SoC Level: The hardware definitions provided by the silicon vendor (e.g., Qualcomm or MediaTek). This defines the CPU, GPU, and modem configurations.
- Board Level: The definitions for the physical motherboard. Sometimes a manufacturer will use the exact same motherboard for a phone and a tablet.
- Device Level: The final
device.mkfor the specific consumer product. This defines the final screen resolution, brand name, and pre-installed OEM apps.
Overriding Inherited Variables
Inheritance is processed sequentially. This allows a device-level Makefile to override a setting inherited from a lower-level AOSP Makefile.
For example, aosp_base.mk might include the default Android keyboard:
# Inside aosp_base.mk (Google's code)
PRODUCT_PACKAGES += LatinIME
If your company wants to use a proprietary keyboard instead, you can explicitly override or remove the inherited package later in your specific device.mk:
# Inside your device.mk
$(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_base.mk)
# Replace the default keyboard by redefining the list or adding an override
PRODUCT_PACKAGES += MyCompanyKeyboard
By mastering inherit-product, you can maintain dozens of different Android devices using a clean, modular configuration architecture without duplicating thousands of lines of makefile code.