Android Architecture
Overview
Android is a Linux-based mobile operating system developed by Android Inc. (acquired by Google in 2005) and released as open source under Apache 2.0 (with some GPL components). It is the world's most widely deployed operating system by active device count — approximately 3.5 billion active Android devices as of 2024, spanning smartphones, tablets, wearables, TVs, automotive systems, and embedded devices.
Android is not simply Linux with a mobile UI. It is a fundamentally restructured software stack that replaces standard GNU userspace with a purpose-built Android runtime, a custom IPC mechanism (Binder), a Java/Kotlin application model, and a deep security architecture built around per-application Linux process isolation. Understanding Android means understanding both the Linux kernel it builds on and the Android-specific layers above it.
Prerequisites
- Linux kernel fundamentals: processes, IPC, memory management, device drivers
- Java/Kotlin programming (for framework-level understanding)
- C/C++ systems programming (for HAL and native layer)
- Basic operating systems concepts: scheduling, virtual memory, IPC
Historical Context
Android Timeline:
2003 Andy Rubin, Rich Miner, Nick Sears, Chris White found Android Inc.
Original concept: OS for digital cameras
2005 Google acquires Android Inc. for ~$50M
Project pivots to mobile phones
2007 OHA (Open Handset Alliance) announced: Google + carriers + OEMs
Apple announces iPhone (December — first shipped January 2007)
2008 Android 1.0 on HTC Dream (T-Mobile G1)
Dalvik VM, Linux 2.6 kernel, limited API
2010 Android 2.2 (Froyo): JIT compiler in Dalvik, significant performance jump
Android market share begins growing rapidly
2011 Android 4.0 (Ice Cream Sandwich): unified phone/tablet UI, Holo design
Project Butter (4.1 Jelly Bean 2012): 60fps rendering, vsync
2014 Android 5.0 (Lollipop): ART replaces Dalvik, Material Design
SELinux enforcing mode becomes mandatory
64-bit AArch64 support
2017 Android 8.0 (Oreo): Project Treble — decouples vendor from framework
Background execution limits, new notification system
2019 Android 10: mandatory Project Mainline, scoped storage, foldables
Background location restrictions
2021 Android 12: Material You, Privacy Dashboard, approximate location
Hardware-backed attestation requirements tightened
2023 Android 14: partial photo/video access, predictive back gesture
First-class 64-bit only support (dropped 32-bit system support)
Android Layer Stack
+-------------------------------------------------------------+
| APPLICATIONS |
| (Java/Kotlin — run in ART, isolated per-app process) |
| Phone Maps Browser Camera 3rd-party apps |
+-------------------------------------------------------------+
| APPLICATION FRAMEWORK |
| Activity Manager Window Manager Notification Manager |
| Package Manager Power Manager Content Providers |
| Telephony Manager Location Manager View System |
+-------------------------------------------------------------+
| ANDROID RUNTIME (ART) |
| DEX bytecode AOT compilation GC (Concurrent mark- |
| JNI bridge Profile-guided sweep + generational) |
| Core libraries optimization Stack maps for GC |
+-------------------------------------------------------------+
| NATIVE C/C++ LIBRARIES | HARDWARE ABSTRACTION LAYER|
| libc (bionic) libz | Camera HAL Audio HAL |
| libssl/crypto libsqlite | Bluetooth GPS HAL |
| Skia (2D) WebKit | Sensor HAL Wifi HAL |
| OpenGL ES Vulkan | Power HAL Keymaster |
+-------------------------------------------------------------+
| LINUX KERNEL |
| Binder IPC driver Ion memory allocator |
| Android wakelocks Ashmem (anonymous shared memory) |
| Paranoid networking USBGadget Low memory killer |
| cpusets / cpufreq Incremental FS (INCFS) |
+-------------------------------------------------------------+
| HARDWARE |
| SoC: Snapdragon / Exynos / Dimensity / Tensor |
| Secure Enclave Camera ISP DSP GPU Modem |
+-------------------------------------------------------------+
Linux Kernel: Android Extensions
Android uses a modified Linux kernel with several Android-specific additions. Since Project Mainline and AOSP's "Generic Kernel Image" (GKI) initiative (Android 11+), the goal is to minimize the delta between Android kernel and mainline Linux.
Binder IPC Driver
The most important Android-specific kernel component. /dev/binder implements Android's high-performance, secure IPC (covered in depth in 02-binder-ipc.md).
ION Memory Allocator
ION (replaced by DMA-BUF Heaps in Android 12+) provides shared memory between processes and hardware components (GPU, camera, DSP) without intermediate copies. A camera frame can be allocated in ION, written by the camera ISP, read by the GPU for rendering, and read by the encoder for H.264 compression — all without any CPU copy.
Android Wakelocks
Standard Linux power management was insufficient for mobile. Android added wakelocks: a process holds a wakelock to prevent the system from suspending. The framework's PowerManager.WakeLock in Java maps to kernel wakelocks.
Wakelock lifecycle:
App acquires wakelock -> kernel prevents suspend
App does work (music playback, GPS fix)
App releases wakelock -> system can suspend
If app crashes while holding wakelock -> wakelock leaked
-> Battery drain (device never sleeps)
-> Detected by BatteryStats: "wakelocks held" metric
Android 6.0 introduced Doze mode — the framework overrides wakelocks when the screen is off and the device is stationary, periodically batching network and sync operations.
Low Memory Killer (LMK)
Android has no swap partition on most devices. When memory pressure mounts, the kernel's LMK kills background processes. Each process has an OOM score adjusted by the Android framework based on its visibility and importance:
OOM Score Adj -> Process State:
-1000: System-critical (init, system_server) — never killed
-900: Persistent services
0: Foreground app (screen visible, user interacting)
100: Visible (partially obscured)
200: Service (started service)
500: Cached (background, recently used)
900: Background (background, not recently used)
1000: Empty (no active components) — killed first
LMK kills in order from highest oom_score_adj first.
The userspace LMKD daemon (replacing the in-kernel LMK since Android 10) uses pressure stall information (PSI) from the kernel to make kill decisions based on memory pressure levels rather than just free page count.
Hardware Abstraction Layer (HAL)
HAL is a C interface layer between Android's Java/native framework and hardware-specific kernel drivers. Its purpose: allow Android framework code to work across different hardware without recompilation, while letting OEMs implement hardware features without modifying the framework.
HAL Architecture (Project Treble)
Before Android 8.0 (Oreo), HAL modules were loaded directly into the framework process as .so shared libraries. This meant the framework had direct access to vendor code running in the same process. Framework updates required OEM cooperation to update their HAL code simultaneously.
Project Treble (Android 8.0) separated HAL into its own process:
Before Treble: After Treble:
system_server system_server
+-------------------+ +------------------+
| Framework code | Binder | Framework code |
| HAL .so loaded |---------> | HIDL / AIDL |
| in same process | | interface client |
+-------------------+ +------------------+
|
Binder IPC
|
+------------------+
| HAL service |
| (separate process|
| in vendor |
| partition) |
| camera.so |
| audio.default.so |
+------------------+
HIDL (HAL Interface Definition Language, Android 8-11) and then AIDL (Android 12+) define stable interfaces between framework and HAL. This means Google can update the Android framework (system partition) independently of the OEM HAL (vendor partition) — enabling faster security updates without OEM participation.
Android Runtime (ART)
ART replaced the Dalvik VM in Android 5.0 (Lollipop). The transition was the most significant performance improvement in Android history.
Dalvik vs. ART
Dalvik (pre-5.0):
.java source -> javac -> .class (JVM bytecode)
-> dx -> .dex (Dalvik bytecode)
On device: JIT compilation + interpreter
- JIT compiles hot methods on first execution
- Cold start = slow (interpreter until JIT kicks in)
- JIT-compiled code is temporary, regenerated on reboot
ART (5.0+):
.java source -> javac -> .class
-> d8/r8 -> .dex
On device at install time:
- dex2oat: Ahead-Of-Time compilation: .dex -> .oat (native code)
ART 7.0+: Hybrid AOT + JIT + Profile-Guided Optimization (PGO)
- App first run: interpreted + JIT profiling
- Background dex2oat: AOT compile hot paths from profile
- Result: fast startup, optimal steady-state performance
ART Garbage Collection
ART's GC is generational, concurrent, and compacting:
- Young generation: Small objects, collected frequently. Bump-pointer allocation.
- Old generation: Long-lived objects, collected less often. Compaction reduces fragmentation.
- Concurrent: GC runs concurrently with application threads — short stop-the-world pauses only for root scanning and final reference processing.
- Low-pause target: GC pause < 10ms for foreground apps (via
GcCause::kGcCauseForegroundpriority elevation).
ART uses read barriers (with CC — Concurrent Copying collector) to allow object relocation while the app continues running. Objects can be moved in memory while live references to them remain valid because reads are intercepted to look up the forwarding address.
Android App Model
Android applications are composed of four component types:
Activity: Single screen with UI
- Has lifecycle: onCreate -> onStart -> onResume -> [running]
-> onPause -> onStop -> onDestroy
- Back stack management: TaskStack
Service: Background work, no UI
- Started service: runs until stopSelf() or stopService()
- Bound service: IPC endpoint, stays alive while clients bound
- Foreground service: requires persistent notification,
survives memory pressure better than background
BroadcastReceiver: Event handler for system/app broadcasts
- Intent-based message bus
- Manifest-declared: launched for events even if app not running
- Dynamic: registered in code while component is running
ContentProvider: Structured data sharing between apps
- URI-based access model
- Enforces permissions per URI
- Contacts, MediaStore, Settings are system ContentProviders
Components are loosely coupled — Activities can launch Activities in other apps, Services can be bound from other packages. The Intent system is the glue.
Intent System
Intents are the mechanism for component invocation:
- Explicit intent: Named target component (
new Intent(context, MyActivity.class)) - Implicit intent: Describes an action + data (
ACTION_VIEW + content://...). Android resolves to the best matching component (or shows a chooser)
The Android framework's Activity Manager validates intent routing, enforces permissions, and manages task stacks.
Zygote: Warm App Start
Cold starting every app from scratch would mean loading the Android framework classes (hundreds of MB) each time. Zygote solves this:
Boot sequence:
init (PID 1)
-> Zygote (/system/bin/app_process)
- Loads and initializes ART runtime
- Pre-loads ~800 framework Java classes
- Pre-loads common resources (themes, drawables)
- Opens /dev/binder
- Listens for spawn requests on /dev/socket/zygote
-> Forks for each app launch request:
fork() -> new process inherits:
- ART runtime (initialized)
- Pre-loaded classes (shared, copy-on-write pages)
- /dev/binder FD
child process:
- Drops privileges to app's UID
- Loads app-specific code
- Calls Application.onCreate() -> Activity.onCreate()
Performance benefit:
Cold start without Zygote: ~500ms (load ART + framework classes)
Warm start from Zygote fork: ~50-100ms (fork is fast, pages are CoW)
The pre-loaded framework classes share physical pages across all apps (copy-on-write semantics). On a device running 50 apps, the ~300MB of pre-loaded ART data appears once in physical RAM, not 50 times.
Android Permissions Model
Android's permission system enforces what data and capabilities each app can access.
Install-Time Permissions (Protection Level: Normal)
Low-risk permissions, automatically granted at install. Example: INTERNET, BLUETOOTH, VIBRATE. The user is not prompted; they appear in the Play Store listing.
Runtime Permissions (Protection Level: Dangerous)
Introduced in Android 6.0. High-risk permissions require runtime user confirmation. Granted per-permission, not per-app. Can be revoked at any time:
Runtime permission categories:
CAMERA - Physical camera hardware
MICROPHONE - Microphone input
LOCATION - GPS / network location (fine / coarse)
CONTACTS - Contact database
STORAGE - Read/write external storage (pre-Android 10)
PHONE - Make calls, read call log
CALENDAR - Calendar database
BODY_SENSORS - Heart rate, etc.
Android 12+ partial permissions:
BLUETOOTH_SCAN (separated from legacy BLUETOOTH)
READ_MEDIA_IMAGES / READ_MEDIA_VIDEO (instead of READ_EXTERNAL_STORAGE)
APPROXIMATE_LOCATION (new — coarse only, without fine)
Android Sandbox
Each app has a unique Linux UID assigned at install time. This is the foundation of Android's security model:
App isolation via Linux UIDs:
com.google.android.maps -> UID 10052
com.instagram.android -> UID 10083
com.example.myapp -> UID 10104
Each app's data directory:
/data/data/com.example.myapp/ owned by UID 10104
Other apps cannot read this directory — standard Linux DAC.
Even root is not normally accessible to apps (SELinux).
SELinux on Android
Android enforces SELinux in enforcing mode since Android 5.0. Every process, file, socket, and device has a type label. Policy defines which types can interact. The policy ships as a compiled binary in the system image:
u:r:untrusted_app:s0— third-party app domainu:r:system_server:s0— system_server domainu:r:servicemanager:s0— Binder ServiceManager
An app exploiting a memory corruption vulnerability cannot escape its SELinux domain to access other apps' data or kernel interfaces without also exploiting an SELinux policy bypass.
Production Examples
Google Pixel 8 (2023): Tensor G3 SoC (2 Cortex-X3 + 2 Cortex-A715 + 4 Cortex-A510), 8GB LPDDR5 RAM, 128/256GB UFS 3.1 storage. Android 14. Tensor Security Core (dedicated security chip for Titan M2). Protected Computing for on-device ML. Android 14 requires ARMv8.0 minimum — drops old 32-bit-only SoCs.
Samsung Galaxy S24 Ultra: Snapdragon 8 Gen 3 (in US/Korea) or Exynos 2400. One UI 6.1 over Android 14. Samsung's hardware HAL layers implement camera tuning, S Pen digitizer, and Samsung-specific features as HAL extensions above standard Android HAL interfaces.
Android in Automotive (Android Auto / AAOS): Android Automotive OS runs natively on the vehicle's head unit. Distinct from Android Auto (phone projection). AAOS provides car-specific system services (CarHvacManager, CarSensorManager, VehicleHAL for CAN bus data). Used in Volvo, Polestar, BMW, Renault, and GM vehicles.
Debugging Notes
- adb shell dumpsys: Most powerful Android debugging command.
dumpsys activityshows task stacks and Activity states.dumpsys meminfoshows per-app memory usage.dumpsys batterystatsreveals wakelock abuse. - Android Profiler in Android Studio: CPU profiler (sampling + tracing), memory profiler (heap dumps, allocation tracking), network profiler. Attach to running process or profile from launch.
- strace on Android:
adb shell strace -p <pid>requires root or profiling permissions. Reveals unexpected file access, IPC activity, or system call failures. - systrace / Perfetto:
adb shell perfettorecords kernel scheduler events, Binder transactions, frame rendering timeline. Essential for diagnosing jank (missed 16ms vsync deadlines). Replaced the oldersystracein Android 10+. - ANR (Application Not Responding): Triggered when the main thread does not handle an input event within 5 seconds (foreground), or a broadcast handler exceeds 10 seconds. Check
/data/anr/traces.txtfor the main thread stack trace at time of ANR. Common cause: disk I/O or Binder call blocking the main thread.
Security Implications
- Permissions granularity creep: The permission system has hundreds of permissions; many are confusingly named or overlap. Users cannot make informed decisions. Android 12+ Privacy Dashboard shows which apps accessed camera/mic/location in the last 24 hours.
- One-time permissions (Android 11+): Camera, microphone, and location can be granted for "only this time" — revoked when app moves to background.
- Sideloading risk: Apps installed outside Play Store bypass Google Play Protect scanning. Android requires explicit user opt-in, but social engineering attacks exploit this. Enterprise MDM (Mobile Device Management) can disable sideloading.
- Kernel attack surface: Despite SELinux, kernel vulnerabilities are the most impactful Android attack vector — they can escape all userspace sandboxes. The annual Android Security Bulletin patches kernel vulnerabilities under CVEs. Project Zero's research has repeatedly shown Binder driver bugs as high-severity.
- Spectre/Meltdown on Android: ARM CPUs in Android devices were affected. Android's mitigations: KPTI (Kernel Page Table Isolation) enabled by default on AArch64, swpf instruction flushing, and compiler-based mitigations in ART.
Performance Implications
- Cold vs. warm vs. hot start: Cold start (process not running): ~500ms-2s. Warm start (process running, Activity recreated): ~200-500ms. Hot start (Activity in back stack, just brought forward): ~100-200ms. Zygote enables warm over cold. Retained process state enables hot.
- Binder call overhead on main thread: Every bound service call goes through Binder IPC. Synchronous Binder calls block the calling thread. Main thread Binder calls to slow services cause jank. Use async Binder (AIDL
onewaykeyword) or coroutines to avoid blocking. - ART Ahead-of-Time vs. Just-in-Time: Profile-guided compilation (introduced Android 7) produces the best performance. The first run is slower (JIT profiling); subsequent runs benefit from AOT compilation of hot paths. Cloud-based profile delivery allows new installs to benefit from other users' profiles.
- GC pause: Despite concurrent GC, stop-the-world pauses can cause dropped frames. Applications should minimize allocation rate in rendering loops.
Allocation Trackerin Android Studio identifies hot allocation sites. - Memory pressure and app process death: When the system kills background processes, restoring state requires a cold start. Activity
onSaveInstanceStateand ViewModel survive process death. Design apps to restore state gracefully.
Failure Modes
- Wakelock leak: App acquires
PARTIAL_WAKE_LOCKand crashes before releasing. Device never sleeps; battery drains in hours instead of days. Detected byadb shell dumpsys power | grep "Wake Locks"and battery stats. - Content Provider crash loop: A ContentProvider that crashes causes all apps depending on it to die. Can cascade into system instability. ContentProvider crashes are surfaced in
logcatandadb bugreport. - Implicit broadcast abuse: Pre-Android 8, apps received many system broadcasts (battery changed, network state changed) even when not running. This caused millions of apps to wake up for every battery status change. Android 8+ restricts background implicit broadcasts.
- Doze mode interfering with RT tasks: Background services in Doze mode (screen off, stationary) are deferred for up to hours. Apps requiring periodic background work must use
WorkManagerwith constraints,JobScheduler, or foreground services.
Modern Usage
- Android 14 Health Connect: Centralized health data platform with unified permissions for fitness, nutrition, sleep. Apps share data through the Health Connect ContentProvider rather than direct API access.
- Android 15 predictive back gesture: Framework-level API for previewing the back destination before committing. Requires application opt-in via manifest.
- Google Play Integrity API (replacing SafetyNet): Stronger device integrity checking for banking and payment apps. Backed by hardware attestation via the Secure Enclave.
- Android for Cars: Android Automotive OS in production vehicles from Volvo, BMW, Renault. Full Android stack running on the vehicle's IVI unit with Vehicle HAL integration.
Future Directions
- Mainline (Project Mainline): Google-updateable system modules delivered outside of full OTA. 30+ modules including Media codecs, DNS resolver, TLS, Wi-Fi. Allows security patches without waiting for OEM OTA cycle.
- Generic Kernel Image (GKI): Standardized Android kernel that all Android 11+ devices run. Vendor-specific code moves to loadable kernel modules (GKI modules). Enables Google to ship kernel security updates independently of OEM.
- Android Virtualization Framework (AVF): Protected VMs using ARM virtualization. pKVM (protected KVM) hypervisor. Used for Protected Compute — isolated environments where even the host OS cannot read the VM's memory. Enables confidential ML model inference.
- RISC-V Android: Google has announced first-class RISC-V support in Android. AOSP RISC-V builds are functional. First commercial Android RISC-V hardware expected in 2025-2026.
Exercises
- Use
adb shell dumpsys activityto observe the Activity back stack of a running app. Navigate through multiple screens and observe how the stack grows. Then use the back button and watch it shrink. Identify any Activities with unusual flags in the record. - Write a simple Android app that deliberately leaks a
PARTIAL_WAKE_LOCK. Confirm the leak withadb shell dumpsys power. Then fix the leak. UseBatteryHistorianto visualize battery impact. - Use Android Studio's Memory Profiler to capture a heap dump of your app after navigating through several screens. Identify whether any Activities are being retained after their
onDestroyis called (memory leak). Common cause: anonymous inner class holding Activity reference. - Examine the SELinux policy on an Android device with
adb shell cat /sys/fs/selinux/policy | audit2allow. Find the domain for a third-party app process and list what file types and Binder services it is allowed to access. - Build AOSP from source for a supported target (or use an Android Emulator build). Modify the
ActivityManagerto log the OOM score adjustment of each process on every adjustment event. Observe the priority adjustments during app lifecycle transitions.
References
- Android Open Source Project Documentation: https://source.android.com/docs/
- Reto Meier and Ian Lake, Professional Android (4th ed., Wrox, 2018)
- Android Architecture Components Documentation: https://developer.android.com/topic/architecture
- Google Android Security Team, "Android Security Bulletin": https://source.android.com/docs/security/bulletin
- Eran Messeri, "Android ART Explained" (Google I/O 2014)
- Android's SELinux Policy: https://source.android.com/docs/security/features/selinux
- Project Treble Overview: https://android-developers.googleblog.com/2017/05/here-comes-treble-modular-base-for.html
- Jeff Vander Stoep, "SEAndroid: Bringing flexible mandatory access control to Android" (USENIX LISA 2013)
- Brendan Gregg, "Android Performance Profiling" — perf and Perfetto on Android
- Android Compatibility Definition Document (CDD): https://source.android.com/docs/compatibility/cdd