Skip to content
Lifestyle & Learning

Android Source Overview: Architecture, Source Tree Structure, and Platform Build Systems

In this article

The Android Open Source Project (AOSP) source code comprises the complete operating system stack for Android devices, ranging from the low-level Linux kernel and native hardware abstraction interfaces to the core Java application framework and platform utilities. Developers interact with the Android source tree to construct custom firmware, port operating systems to new hardware platforms, perform security audits, and build specialized embedded systems. Managing this extensive code base requires a clear understanding of its directory hierarchy, multi-repository management tools, and specialized build infrastructure.

Architectural Layers of the Android Source Code

To navigate the Android source code effectively, platform engineers must understand how its software components are layered. Android uses a modular architecture where higher-level framework services interact with physical hardware through abstraction layers and native daemons, eliminating direct hardware dependencies within application-level code.

  1. System Applications (Launcher, Settings, Dialer, Camera, etc.)
  2. Java Application Framework (ActivityManager, PackageManager, WindowManager, etc.)
  3. Android Runtime (ART) & Native C/C++ Libraries (Bionic libc, SurfaceFlinger, MediaCodec, LibCore)
  4. Hardware Abstraction Layer (AIDL / HIDL Hardware Interfaces)
  5. Linux Kernel & GKI (Core Drivers, Binder IPC, Power Management)

1. Linux Kernel and Core Drivers

At the foundation of the Android architecture sits a customized Linux kernel. Android relies on the kernel for core system services such as memory management, process scheduling, network protocol stacks, driver support, and hardware security enforcement.

Android platform builds utilize the Generic Kernel Image (GKI) architecture to unify core kernel features across diverse SoC (System-on-Chip) vendors. In addition to standard Linux drivers, the Android kernel source includes Android-specific extensions:

  • Binder IPC: A lightweight inter-process communication mechanism optimized for mobile resources and secure process isolation.
  • Ashmem / dm-abyssal: Shared memory allocation subsystems designed for low-memory environments.
  • Low Memory Killer (LMK / psi-lmkd): Memory management mechanisms that monitor system memory pressure and terminate background tasks based on strict priority heuristics.

2. Hardware Abstraction Layer (HAL)

The Hardware Abstraction Layer defines standardized interfaces that allow high-level Java frameworks to interact with physical hardware drivers without direct knowledge of vendor-specific driver implementations.

Historically implemented via C/C++ struct pointers (libhardware) and subsequently HAL Interface Definition Language (HIDL), modern Android releases rely predominantly on Android Interface Definition Language (AIDL) for HAL implementations. The HAL decouples the core operating system framework—housed in system images—from vendor-specific driver blobs, enabling independent system updates (Project Treble).

3. Android Runtime (ART) and Native C/C++ Libraries

Above the HAL sit the core native C/C++ daemons, libraries, and execution runtimes:

  • Android Runtime (ART): The managed execution environment for Android applications. ART utilizes Ahead-Of-Time (AOT) and Just-In-Time (JIT) compilation, profile-guided optimization, and concurrent garbage collection to execute Android DEX bytecode efficiently.
  • Bionic C Library: Android's custom, lightweight implementation of the standard C library (libc), tailored specifically for small memory footprints, fast execution paths, and integration with Android's thread and permission models.
  • Native Daemons and Services: Essential system utilities, including SurfaceFlinger (display composition and frame management), AudioFlinger (audio rendering and routing), vold (volume management and storage encryption), and netd (network interface management).

4. Java Application Framework

Written primarily in Java and Kotlin, the Application Framework exposes the underlying capabilities of the Android OS to software applications via structured APIs. Core architectural services include:

  • Activity Manager (ActivityManagerService): Manages process lifecycles, activity backstacks, and task switching.
  • Window Manager (WindowManagerService): Manages window display hierarchies, z-ordering, surface allocation, and input event routing.
  • Package Manager (PackageManagerService): Handles application installation, verification, permission resolution, and APK parsing.
  • Content Providers & Notification Managers: Enables secure structured data sharing across applications and manages system status bar alerts.

5. System Applications

The top layer of the source tree contains the default system applications shipped with base AOSP builds. These include the default home screen launcher, system settings app, telephony dialer, camera app, and media providers. System applications run within the managed runtime environment and interact with the platform exclusively through published framework APIs and system-privileged permissions.

Navigating the AOSP Source Tree Structure

When checked out locally, the Android source code is organized into a top-level directory structure containing hundreds of individual modules. Each top-level folder serves a distinct functional role within the OS build pipeline.

  • aosp-root/
    • art/
    • bionic/
    • bootloader/
    • build/
    • cts/
    • developers/
    • development/
    • device/
    • external/
    • frameworks/
    • hardware/
    • kernel/
    • libcore/
    • packages/
    • platform_testing/
    • prebuilts/
    • system/
    • toolchain/
    • tools/
    • vendor/

Key Directories Explained

  • art/ Contains the source code for the Android Runtime, including the DEX bytecode interpreter, compiler toolchains (dex2oat), garbage collector implementations, and core runtime libraries.

  • bionic/ Houses Android’s custom C library (libc), math library (libm), dynamic linker (linker), and thread library (libdl). It replaces GNU glibc to preserve memory and respect Android's licensing requirements.

  • build/ Contains the central build system infrastructure. This directory holds the logic for the Soong build system, Blueprint files, Ninja build file generators, environment setup scripts (envsetup.sh), and global build target rules.

  • cts/ Houses the Compatibility Test Suite (CTS). CTS comprises thousands of automated unit, integration, and security tests designed to verify that custom device builds comply with official Android compatibility standards.

  • device/ Contains device-specific build rules, product definitions, board configurations, kernel compilation parameters, and display setups for target hardware (such as Google Pixel devices or reference emulator targets).

  • external/ Holds third-party open-source projects imported into Android without modification to their original codebase upstream structure (e.g., OpenSSL/BoringSSL, SQLite, WebKit, protobuf, and FFmpeg).

  • frameworks/ Contains the core implementation of the Android Java APIs and native framework services.

    • frameworks/base/: Contains the bulk of Java APIs, system service implementations, resources (res/), and core UI widgets.
    • frameworks/av/: Audio and video media framework services, including mediaserver and codec abstraction frameworks.
    • frameworks/native/: Native C++ framework implementations, including SurfaceFlinger, input subsystems, and graphics pipelines.
  • hardware/ Contains open-source HAL definitions and reference implementations (hardware/interfaces for AIDL/HIDL files) for common platform components such as audio, camera, Bluetooth, sensors, and GPS.

  • packages/ Contains system applications, input method editors (IMEs), content providers, wallpaper engines, and services. Subdirectories include packages/apps/ (standard UI apps), packages/providers/ (database providers), and packages/services/ (background services).

  • prebuilts/ Stores pre-compiled toolchains, build tools, compiler toolsets (such as Clang/LLVM), and static binaries required across different host operating systems to establish reproducible build conditions.

  • system/ Contains low-level C++ system daemons, core execution utilities, security policies, and base runtime initialization scripts. Critical subdirectories include:

    • system/core/: Houses the init process (init), logging framework (logd), and basic shell utilities.
    • system/sepolicy/: Security-Enhanced Linux (SELinux) mandatory access control policy rules.
    • system/vold/: Volume daemon for block storage encryption, mounting, and access control.
  • vendor/ Stores proprietary hardware drivers, board support packages (BSPs), binary blobs, and proprietary HAL implementations supplied by hardware manufacturers (e.g., Qualcomm, MediaTek, Samsung).

Ludo Classic - Android Source Code Source Code - SellAnyCode
Ludo Classic - Android Source Code Source Code - SellAnyCode

The Modern AOSP Build System: Soong, Blueprint, and Ninja

The build architecture of AOSP has evolved from traditional GNU Make scripts to a modern, parallelized build toolchain designed to process millions of lines of code cleanly and quickly.

1. From Make to Soong

Historically, modules were defined using Android.mk files interpreted by GNU Make. However, as the source code grew, GNU Make suffered performance bottlenecks and complex scope-bleeding issues.

Modern AOSP uses the Soong build system, which reads declarative Android.bp (Blueprint) build specifications. Soong converts these build definitions into configuration files executed by Ninja, a low-level build system designed for high speed and parallel execution.

  1. Android.bp (interpreted by Soong / Blueprint)
  2. Soong / Blueprint emits build.ninja
  3. build.ninja executes to produce Platform Images (system, vendor)

2. Module Definition via Android.bp

Android.bp files use a JSON-like syntax to define software build targets. Unlike standard Makefiles, Blueprint files are non-imperative; they do not allow complex control flows, inline conditional branching, or direct execution of external shell commands.

A typical Android.bp entry defining a native shared C++ library looks like this:

cc_library_shared { name: "libexample_driver", srcs: [ "src/driver_main.cpp", "src/hardware_interface.cpp", ], cflags: [ "-Wall", "-Werror", ], shared_libs: [ "liblog", "libutils", "libcutils", ], vendor: true, }

3. Build Target Variants

When configuring an AOSP compilation run, developers specify a target build variant using the lunch selection tool. Target choices combine target device definitions with one of three build variants:

  • user: The final production configuration intended for consumer release. Debugging features are disabled, root access is restricted, SELinux is set to Enforcing, and operational logs are limited.
  • userdebug: Identical to the user build, but retains elevated root access (adb root), debugging utilities, performance profiling flags, and operational logging.
  • eng: Engineering build profile optimized for system developers. Turns off compiler optimizations for fast compile times, enables extensive logging, exposes root shells, and installs extra debugging tools.

Repository Management using the Repo Tool

Because the Android source code consists of hundreds of separate Git repositories organized across distinct platform subcomponents, standard Git commands cannot easily manage the entire source tree concurrently. Google developed Repo, a Python-based wrapper tool built on top of Git.

1. The Manifest File

Repo reads a central configuration file known as the XML Manifest (default.xml), hosted in a dedicated manifest repository. The manifest declares:

  • The remote code repositories hosting each component.
  • The local file path mapping for every repository within the unified source directory.
  • The specific Git commit, branch name, or tag assigned to each repository.

2. Essential Repo Workflow Commands

Platform developers interact with the global source tree using primary Repo commands:

  • Initialize workspace:repo init -u https://android.googlesource.com/platform/manifest -b android-14.0.0_r1Configures the local checkout workspace to point to a specific manifest repository branch or release tag.

  • Synchronize source tree:repo sync -j8Downloads and updates all sub-repositories declared in the manifest concurrently across multiple thread connections.

  • Create local branches across modules:repo start feature-branch-name --allCreates a new local Git development branch across all individual managed sub-repositories simultaneously.

  • Inspect workspace status:repo statusScans all sub-repositories and summarizes uncommitted local changes, untracked files, and modified files in a unified console output.

Comparison Matrix: Architectural Layers and Directory Roles

Architecture Layer Key Source Directory Key Languages & Tools Main Operational Responsibility Output Artifact
Linux Kernel kernel/, device/ C, Assembly, Kbuild Hardware initialization, memory protection, task scheduling, driver interfaces boot.img, kernel binary
Hardware Abstraction (HAL) hardware/interfaces/ C++, AIDL, C Standardizes component access (Camera, Sensors, Audio) across vendors Vendor HAL shared objects (.so)
Native Libraries & ART bionic/, art/, system/core C++, Assembly, DEX Manages process execution, memory management, and system daemons system.img, libart.so, libc.so
Application Framework frameworks/base/ Java, Kotlin, C++ Provides system APIs, Windowing, Activity Lifecycles, and permissions framework.jar, services.jar
System Applications packages/apps/ Java, Kotlin, XML Default user interface applications (Launcher, Settings, Phone) System APKs / APEX modules
Build Infrastructure build/, tools/ Go, Python, Ninja Converts blueprint modules into compiled flashable disk partition images system.img, vendor.img, userdata.img

Environment Prerequisites and Initializing a Local Build

Building the Android Open Source Project requires a dedicated Linux Workstation. Due to the scale of the source codebase, system hardware must meet robust operational specifications.

Minimum Recommended System Specifications

  • Operating System: Ubuntu LTS (64-bit) or compatible Linux distribution.
  • Disk Space: Minimum 300 GB free disk space for source checkout; 400 GB+ recommended to account for build cache files (out/ directory output). SSD storage is highly recommended.
  • Processor: Multi-core x86_64 CPU (16+ cores recommended to accelerate build parallelism).
  • System RAM: Minimum 32 GB RAM (64 GB+ recommended to prevent Out-Of-Memory exceptions during Ninja compilation phases).

Step-by-Step Build Initialization Sequence

Step 1: Install Required Build Dependencies

Install host compiler tools, Python utilities, Git libraries, and build tools via the package manager:

sudo apt-get update sudo apt-get install -y git-core gnupg flex bison build-essential zip curl zlib1g-dev \ libc6-dev-i386 x11proto-core-dev libx11-dev libgl1-mesa-dev libxml2-utils \ xsltproc unzip fontconfig python3

Step 2: Download and Install the Repo Tool

Fetch the Repo executable from official Google storage mirrors, make it executable, and place it within your local executable binary execution path:

mkdir -p ~/.bin PATH=~/.bin:$PATH curl https://storage.googleapis.com/git-repo-downloads/repo > ~/.bin/repo chmod a+rx ~/.bin/repo

Step 3: Initialize and Synchronize the Source Tree

Create a working project directory, initialize the Repo tool against the target tag release branch, and execute a multi-threaded code download synchronization:

mkdir ~/aosp-source && cd ~/aosp-source repo init -u https://android.googlesource.com/platform/manifest -b android-14.0.0_r1 repo sync -c -j8 --no-clone-bundle

Step 4: Environment Initialization, Target Selection, and Compilation

Source the environment setup script to import execution macros, select the build target profile using lunch, and initiate system image assembly using the m command wrapper:

source build/envsetup.sh lunch aosp_cf_x86_64_phone-userdebug m -j$(nproc)

The resulting build artifacts will reside in the out/target/product// path, yielding flashable image files including system.img, vendor.img, boot.img, and userdata.img.

Security Frameworks and Hardware Isolation Boundaries

Modern Android source code is designed to maintain strict privilege boundaries across software layers, preventing compromised applications or low-level components from taking over the device.

1. SELinux Rules (system/sepolicy)

Android enforces mandatory access control (MAC) via Security-Enhanced Linux (SELinux). Every file, process, socket, and device node is labeled with a specific security domain context. Access permissions between domains are denied by default and explicitly declared within text policy files (.te).

SELinux configurations are strictly partitioned:

  • System Policy (system/sepolicy): Maintained by platform developers; defines core domains, application sandboxes, and immutable security guarantees.
  • Vendor Policy (device///sepolicy): Maintained by hardware OEMs; defines access policies for custom hardware drivers and vendor daemons without overriding system-level core policies.
  1. System Partition
    • System Apps
    • Framework APIs
    • Android Runtime
    • System Policies (system/sepolicy)
  2. Treble Interface (AIDL HALs)
  3. Vendor Partition
    • Hardware Drivers
    • Proprietary Blobs
    • Vendor Daemons
    • Vendor Policies (vendor/sepolicy)

2. Project Treble and the Vendor Interface

Introduced to prevent fragmentation and accelerate OS updates, Project Treble cleanly separates system framework code from hardware-specific vendor code.

The vendor partition (/vendor) contains hardware drivers, configuration binaries, and vendor HAL implementations, while the system partition (/system) houses pure OS framework code. Communication between system and vendor components occurs strictly across versioned AIDL interface sockets, enabling developers to update the OS framework partition without recompiling or modifying underlying vendor board support drivers.

Frequently Asked Questions

What is the difference between AOSP and commercial Android distributions?

AOSP is the core, fully open-source foundation of the Android operating system managed by Google. Commercial Android distributions (such as those shipped on consumer smartphones) build upon AOSP by integrating proprietary vendor device drivers, hardware-specific board support packages, custom user interfaces, and Google Mobile Services (GMS)—which includes proprietary components like the Google Play Store, Google Maps, and Play Services frameworks.

Why does AOSP use the Repo tool instead of standard Git submodules?

AOSP consists of hundreds of distinct Git repositories. Standard Git submodules lock sub-projects to rigid commit hashes and struggle to handle parallel commits across multiple repositories smoothly. The Repo tool uses XML manifest files to manage branch synchronization, bulk cherry-picking, status reporting, and distributed branch tracking across these repositories, simplifying multi-repository maintenance without locking the source tree into rigid submodule states.

How do Android.bp files differ from traditional Android.mk files?

Android.mk files rely on GNU Make syntax, which permits runtime logic execution, dynamic variable modification, shell command invocation, and complex procedural rules. This procedural nature caused slow build times and tracking errors. Android.bp files are declarative, non-imperative JSON-like specifications parsed by the Soong build engine into static Ninja files. They prevent inline execution side effects, guarantee reproducible dependency graphs, and significantly speed up incremental compilation.

What is the Generic Kernel Image (GKI) in the Android source tree?

The Generic Kernel Image (GKI) addresses Android kernel fragmentation by unifying core Linux kernel development. Under the GKI model, Google provides pre-built, unified core kernel binaries built directly from common Android kernel branches. Hardware vendors deliver SoC-specific drivers and board logic strictly as dynamically loaded kernel modules (.ko files) rather than applying invasive modifications directly to core kernel tree source files.

Can Android source code be built natively on Windows or macOS?

While limited parts of AOSP (such as native SDK host utilities or ADB drivers) can be compiled under macOS or Windows environments, building the full operating system target images (system.img, boot.img) requires a 64-bit Linux host operating system (typically Ubuntu LTS). Developers on non-Linux platforms routinely use dedicated Linux Virtual Machines (VMs), Docker containers, or remote cloud-hosted Linux build slaves to compile the complete platform.

Practical Recommendations for Platform Engineers

When working with the Android source tree, follow these established platform development standards:

  1. Leverage Sparse Checkouts for Targeted Framework Edits: If working exclusively on Java framework logic or applications, avoid full tree builds when possible. Utilize component-specific build commands (such as m FrameworksServicesTests or m Settings) to save hours of compilation time.
  2. Isolate Proprietary Hardware Changes: Place hardware-specific extensions inside dedicated subdirectories under device// or vendor//. Never modify core files inside frameworks/base/ or system/core/ to implement vendor-specific hardware hacks.
  3. Verify SELinux Rules Early: Always test new native platform daemons with SELinux set to Permissive mode initially (adb shell setenforce 0) to log denial events using dmesg | grep audit. Write precise explicit access policy rules inside your custom device sepolicy subdirectories before switching SELinux back to strict Enforcing mode.
  4. Enforce CTS Compliance Checks: When porting AOSP to custom target hardware, execute the Android Compatibility Test Suite (cts-tradefed) early in the board-bringup cycle. Validating API surface compliance prevents breaking core application behavior downstream.