Android Architecture Overview
Android is not a monolithic operating system; it is a layered software stack. From the moment the hardware powers on to the launch of a sophisticated application, the system traverses four distinct architectural layers. Understanding this "Onion Model" is the prerequisite for mastering any advanced Android internal logic.
1. The Four-Layer Stack
Android's architecture spans from high-level Java/Kotlin code down to low-level hardware communication:
- Application Layer: The user-facing tier containing system apps (Phone, Browser, SMS) and the third-party apps developed by the community.
- Application Framework Layer: Acts as the API surface for developers. It houses critical system services like
ActivityManagerService(AMS),WindowManagerService(WMS), andPackageManagerService(PMS). - Libraries & Android Runtime (ART): Contains the native C/C++ libraries (SQLite, OpenGL ES, libc) that power the OS and the ART virtual machine that executes mobile bytecode.
- Linux Kernel Layer: The bedrock of the system. It handles hardware abstraction (HAL), memory management, process scheduling, and the Binder IPC driver.
2. The Custom Linux Kernel
At its core, Android is a specialized distribution of the Linux kernel. Its primary responsibilities include:
- Process Isolation: Every Android application runs in its own isolated Linux process with a dedicated User ID (UID). This ensures that a crash or security breach in one app does not affect others.
- Low Memory Killer (LMK): Unlike standard desktop Linux, Android aggressively reclaims RAM by killing background processes based on their OOM adj score (priority level), ensuring the foreground app remains responsive under pressure.
- Binder Driver: The most critical innovation in the Android stack. Implemented as a kernel character driver (
/dev/binder), it provides a high-performance, secure, and low-overhead communication channel between different processes.
3. The Evolution of Android Runtime (ART)
The container that executes your code has evolved significantly to optimize for mobile hardware:
I. Dalvik & JIT (The Legacy Model)
In the early days, Android relied on the Dalvik VM, an interpreter-based system. It later added JIT (Just-In-Time) compilation, which identified "hot code" during runtime and compiled it into machine code in memory.
- Trade-off: JIT consumed significant CPU and battery while the app was running, causing sporadic stutters (jank).
II. ART & AOT (The Ahead-of-Time Model)
Android 5.0 introduced ART with a primary focus on AOT (Ahead-Of-Time) compilation.
- Mechanism: During app installation, the system translated all
.dexbytecode into native machine code (.oatfiles). - Result: Apps executed exactly like native binary code—fast and smooth. However, it led to massive installation times and high storage consumption.
III. The Hybrid PGO Model (Android 7.0+)
Modern Android uses a sophisticated mix of Interpreter + JIT + AOT guided by PGO (Profile-Guided Optimization).
- Install: Fast installation with zero compilation.
- Initial Usage: Uses a JIT/Interpreter and logs "Hot Code" locations into a profile.
- Maintenance: When the device is idle and charging, a background system task consumes the profile to perform deep AOT compilation on only the most critical code paths. This achieves native speed for user-facing logic without wasting storage on unused code.
4. Zygote: The Process Template
Zygote is the architectural shortcut for App startup. It serves as a pre-loaded "Blueprint" for all Android applications.
- Preparation: During system boot, Zygote pre-loads over 4,000 common Framework classes and shared UI resources into its own memory space.
- Process Spawn: When you launch an app, the system does not create a process from scratch. Instead, it
forks()the Zygote process. - Copy-on-Write (CoW): Thanks to Linux's CoW mechanism, the newly spawned app process shares the identical physical memory pages as Zygote. They only become independent when the app Attempt to write or modify its own framework state.
This design enables near-instantaneous startup times by delegating the heavy lifting of class loading to the system boot sequence rather than the app launch sequence.