October 20, 2026
Part 2: Android Architecture 101
To understand the Android operating system completely, it is best to walk through it in logical and chronological order.
By Shambhukapadi
7 min read
Here is the complete breakdown structured into four sequential phases:
- Code Compilation & Execution Engines (JVM β DVM β ART)
- The 5 Structural Architecture Layers (Bottom to Top)
- The Complete System Boot Sequence & App Launch Flow
- Inter-Process Communication (IPC via Binder & AIDL)
Phase 1: Code Compilation & Runtime Engines (JVM β DVM β ART)
Before code can run on hardware, high-level Java or Kotlin code must be compiled into machine instructions that the phone's CPU understands.
[Kotlin / Java Source Code]
β (javac / kotlinc)
βΌ
[.class Java Bytecode]
β (D8 / R8 Compiler)
βΌ
[.dex Dalvik Bytecode]
β
ββββ> [Dalvik VM (Legacy)]: Trace-based JIT Compiler
ββββ> [Android Runtime (Modern ART)]: Hybrid Profile-Guided JIT + AOT[Kotlin / Java Source Code]
β (javac / kotlinc)
βΌ
[.class Java Bytecode]
β (D8 / R8 Compiler)
βΌ
[.dex Dalvik Bytecode]
β
ββββ> [Dalvik VM (Legacy)]: Trace-based JIT Compiler
ββββ> [Android Runtime (Modern ART)]: Hybrid Profile-Guided JIT + AOTJava Virtual Machine (JVM) (Standard Desktop):
- Compiles
.javafiles into.classfiles containing platform-independent Java Bytecode. - Uses a stack-based virtual machine architecture.
- Standard JVM was not suitable for early mobile devices due to high RAM and CPU overhead.
Dalvik Virtual Machine (DVM) (Legacy Android 1.0β4.4):
- Android build tools translate
.classbytecode files into a single.dex(Dalvik Executable) file, which deduplicates shared string constants to save storage. - DVM is a register-based virtual machine, executing instructions in fewer total CPU cycles than stack-based VMs.
- Trace-Based JIT: Android 2.2 introduced a Just-In-Time (JIT) compiler that continually profiled running apps and dynamically compiled "hot code" loops into native machine instructions.
- Garbage Collection (GC): Dalvik used a single-threaded "Stop-The-World" Garbage Collector that paused all app threads during memory cleanups, causing visible UI stutters ("jank").
Android Runtime (ART) (Modern Android 5.0+):
- Early ART (Android 5.0β6.0 β Pure AOT): Replaced Dalvik with Ahead-Of-Time (AOT) compilation using an on-device utility called
dex2oat. During app installation,dex2oatcompiled the entire.dexfile into a native ELF executable (.oatbinary). This eliminated runtime translation overhead but caused long installation times and increased storage usage. - Hybrid ART (Android 7.0+ β Profile-Guided JIT + AOT): Apps install instantly and execute via an interpreter and JIT compiler. As you use the app, ART profiles "hot code" (frequently executed methods and UI thread code). When the device is idle and charging, a background daemon uses
dex2oatto compile only those hot methods into native code. - Garbage Collection Evolution: ART introduced Concurrent Copying (CC) GC to compact heap memory in parallel with app execution. In Android 13, ART introduced a Concurrent Mark-Compact (CMC) collector using the Linux
userfaultfdsystem call to compact heap memory concurrently without pausing app threads.
Phase 2: The 5 Structural Architecture Layers
Android's software stack is organized into five distinct horizontal layers from the physical hardware up to the user UI.
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Layer 5: Applications β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Layer 4: Application Framework β
ββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββ€
β Layer 3: Native Libraries β Android Runtime (ART) β
ββββββββββββββββββββββββββββββ΄βββββββββββββββββββββββββββββ€
β Layer 2: Hardware Abstraction Layer (HAL) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Layer 1: Linux Kernel β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Layer 5: Applications β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Layer 4: Application Framework β
ββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββ€
β Layer 3: Native Libraries β Android Runtime (ART) β
ββββββββββββββββββββββββββββββ΄βββββββββββββββββββββββββββββ€
β Layer 2: Hardware Abstraction Layer (HAL) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Layer 1: Linux Kernel β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββLayer 1: Linux Kernel (The Foundation):
- Acts as the core abstraction layer between physical hardware and the software stack.
- Built on modified Long Term Supported (LTS) Linux kernels known as Android Common Kernels (ACKs) integrated into a Generic Kernel Image (GKI).
- Key Enhancements: Includes device drivers (display, camera, Wi-Fi, audio), the custom Binder driver (
/dev/binder), SELinux mandatory access control, Ashmem /memfdshared memory, and adaptive memory management viakswapd(RAM swapping into zRAM) and LMKD (Low Memory Killer Daemon).
Layer 2: Hardware Abstraction Layer (HAL):
- Standardizes the interface between the open-source framework and hardware drivers implemented by silicon vendors (e.g., Qualcomm, MediaTek).
- Project Treble (Android 8.0): Separated OS code from vendor hardware code using HIDL (Hardware Interface Definition Language) and process isolation.
- Stable AIDL for HALs: Modern Android unifies OS and vendor IPC under Stable AIDL, verified at boot time via VINTF manifests.
Layer 3: Native C/C++ Libraries & Android Runtime (ART):
- Bionic
libc: A lightweight, BSD-licensed implementation of the standard C library custom-built for mobile efficiency. - SurfaceFlinger: Composites visual graphics layers from multiple windows and outputs them to the display screen.
- Graphics & Media: Includes Skia (2D graphics engine), OpenGL ES / Vulkan (3D APIs), Stagefright (media playback), and SQLite (embedded database).
- ART: Runs directly alongside these native libraries to execute DEX bytecode.
Layer 4: Application Framework:
- High-level Java/Kotlin APIs used by developers.
- Most core services reside inside a single privileged process called
system_server: - ActivityTaskManagerService (ATMS): Directs Activity lifecycles and task back-stacks.
- ActivityManagerService (AMS): Oversees background services, broadcasts, process importance, and
oom_score_adjRAM priorities. - WindowManagerService (WMS): Controls screen window placement, depth layering, and input event dispatching.
- PackageManagerService (PKMS): Inspects
AndroidManifest.xmlfiles and enforces permissions.
Layer 5: Application Layer & Security Sandboxing:
- Contains pre-installed system apps (Launcher, Phone, Settings) and third-party downloaded apps.
- Security Sandbox: Android assigns a unique Linux User ID (UID) to each app upon installation. The kernel enforces process boundary isolation so one app cannot read another app's memory or private storage files.
Phase 3: Complete Boot Sequence & App Execution Flow
When you press the power button, the operating system initializes step-by-step:
[Power On] ββ> [Boot ROM] ββ> [Bootloader] ββ> [Linux Kernel]
β
ββββββββββββββββββββββββββββββββββββββββββββββββββββ
βΌ
[init (PID 1)] ββ> Starts [servicemanager] (Context Manager - Handle 0)
β
βββ> Starts [Zygote]
β
ββββ> Preloads ART Runtime, Framework Classes & Resources
β
ββββ> Forks [system_server] (ATMS, AMS, WMS, PKMS)
β
ββββ> App Launch: fork() + Copy-On-Write (COW) ββ> ActivityThread.main()[Power On] ββ> [Boot ROM] ββ> [Bootloader] ββ> [Linux Kernel]
β
ββββββββββββββββββββββββββββββββββββββββββββββββββββ
βΌ
[init (PID 1)] ββ> Starts [servicemanager] (Context Manager - Handle 0)
β
βββ> Starts [Zygote]
β
ββββ> Preloads ART Runtime, Framework Classes & Resources
β
ββββ> Forks [system_server] (ATMS, AMS, WMS, PKMS)
β
ββββ> App Launch: fork() + Copy-On-Write (COW) ββ> ActivityThread.main()- Boot ROM & Bootloader: Hardware executes code embedded in Boot ROM, initializes system RAM, and executes the Bootloader (IPL and SPL stages).
- Kernel Startup: The Linux Kernel initializes memory caches, scheduling, drivers, and SELinux, mounts the root file system, and spawns the first user-space process:
init(PID 1). servicemanagerStartup:initparses initialization scripts (init.rc) and startsservicemanager.servicemanagerissuesBINDER_SET_CONTEXT_MGRto become the global Context Manager at Handle 0.- Zygote Initialization:
initstarts the Zygote process. Zygote initializes ART and pre-loads thousands of shared Java framework classes, C/C++ native libraries, and system resources into memory. system_serverSpawning: Zygote executes afork()call to create its first child process,system_server.system_serverstarts core framework services (ATMS, AMS, WMS, PKMS) and registers them withservicemanager.- Launcher Display: ATMS commands the launch of the default Home screen (Launcher) app.
- App Launch & Copy-On-Write (COW):
- Tapping an app icon sends an launch intent to ATMS/AMS.
- AMS contacts Zygote over a socket requesting a process for the target app.
- Zygote calls
fork()to create a child process (or draws from a pre-forked Unspecialized App Process / USAP pool introduced in Android 10). - Copy-On-Write (COW): Thanks to Linux COW memory mapping, no physical RAM bytes are duplicated up-front. The new app process shares the read-only framework pages directly with Zygote, keeping RAM usage low and startup fast.
- The child process specializes its UID/GID, calls
ActivityThread.main(), sets up the main UI threadLooper, instantiates aContextImpl, and executes app lifecycle callbacks (onCreate(),onStart(),onResume()).
Phase 4: Inter-Process Communication (IPC via Binder & AIDL)
Inter-Process Communication (IPC) via Binder and AIDL is the nervous system of the Android platform. It allows separate software processes to talk to each other safely and rapidly.
1. The Big Picture: Why Do We Need Binder IPC?
In Android, every application and system service runs in its own isolated process sandbox. The Linux kernel assigns each app a unique Linux User ID (UID), meaning App A (e.g., UID 10001) cannot read or write data in App B's (e.g., UID 10002) memory.
Because processes cannot share memory directly, Android needs a secure way for them to communicate. For instance, when your app needs coordinates from the system Location Service, it must make a cross-process request. Binder IPC makes this cross-process call feel like calling a local method inside the same application.
2. The 4 Main Components of the Binder Framework
The Binder mechanism consists of four key building blocks across the kernel and user space:
[Client App Process] [Server Service Process]
βββββββββββββββββ βββββββββββββββββ
β Proxy Object β β Stub Object β
β (BpBinder) β β (BnBinder) β
βββββββββ¬ββββββββ βββββββββ²ββββββββ
β (Marshal into Parcel) β (Unmarshal & Execute)
βΌ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ΄ββββββββββ
β Binder Kernel Driver (/dev/binder) β
β * Verifies UID/PID Credentials * 1-Copy Scatter-Gather Copy β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ[Client App Process] [Server Service Process]
βββββββββββββββββ βββββββββββββββββ
β Proxy Object β β Stub Object β
β (BpBinder) β β (BnBinder) β
βββββββββ¬ββββββββ βββββββββ²ββββββββ
β (Marshal into Parcel) β (Unmarshal & Execute)
βΌ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ΄ββββββββββ
β Binder Kernel Driver (/dev/binder) β
β * Verifies UID/PID Credentials * 1-Copy Scatter-Gather Copy β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ- The Binder Kernel Driver (
/dev/binder): A character driver in the Linux kernel that acts as the central router. It handles message routing, thread allocation, security checks, and memory mapping. - ServiceManager (Context Manager β Handle 0): The central registry directory where system services register their names and handles. To solve the "chicken-and-egg" problem of how processes discover ServiceManager itself, it is hard-coded to Handle 0.
- Proxies & Stubs (
BpBinderandBnBinder):
- Proxy (
BpBinder): Resides in the client process. It acts as a local representative of the remote service. - Stub (
BnBinder): Resides in the server process. It unmarshals incoming requests and executes the actual service method.
- Parcels: High-performance binary serialization containers used to pack (marshal) parameters on the client side and unpack (unmarshal) them on the server side.
3. What is AIDL and How Does It Fit In?
AIDL (Android Interface Definition Language) is the interface contract language.
- The Problem: Writing low-level C++ or Java code to manually pack data into
Parcelobjects and issue kernel commands for every method is tedious and error-prone. - The Solution: You define your interface in a simple
.aidlfile. The Android build tools compile this.aidlfile into the necessary Proxy (BpBinder) and Stub (BnBinder) glue code automatically.
Key Distinction: Binder is the underlying IPC transport mechanism in the kernel, while AIDL is the programming language used to generate the typed RPC code layered on top.
4. Step-by-Step Workflow of a Binder Call
When an app calls a remote service method, the transaction executes through these steps:
- Service Registration: During boot, a system service registers its human-readable name (e.g.,
"location") and Binder reference withServiceManagerat Handle 0. - Client Lookup: A client app queries
ServiceManagerfor"location"to retrieve a handle to the service's proxy. - Marshalling: The client calls a method on its local Proxy. The Proxy serializes the method ID and parameters into a
Parcel. - Kernel Traversal: The Proxy makes an
ioctl()call to/dev/binderusing theBINDER_WRITE_READcommand. - Identity & Scatter-Gather: The Binder kernel driver attaches the caller's verified Linux UID and PID for security. Using scatter-gather memory mapping, the driver copies the payload directly into the target server process's address space in a single copy.
- Execution & Reply: The driver notifies a thread in the server process's Binder thread pool. The Stub (
BnBinder) unmarshals theParceland executes the real function. The return value is packed into a replyParceland sent back through the driver (BC_REPLY) to the client.
5. Core Performance and Security Features
- Kernel-Enforced Security: Because the kernel attaches caller credentials (UID/PID) directly during driver traversal, client processes cannot forge or spoof their identity.
- 1-Copy Data Transfer: Older IPC systems required three data copies. Modern Binder uses scatter-gather memory mapping to copy data from the client buffer directly to the target process in one single copy.
- Death Notifications: A client can ask Binder to notify it (
BC_REQUEST_DEATH_NOTIFICATION) if the remote server process crashes, allowing the app to handle failures gracefully. - Isolated Binder Domains: Modern Android splits Binder traffic into isolated device nodes β
/dev/binder(apps/framework),/dev/hwbinder(HAL hardware), and/dev/vndbinder(vendor processes)βpreventing cross-domain interference.
Part 3: The Android Security Model: Sandboxing & Permissions