How Android OS Works Internally
📖 Concept
Understanding Android OS internals separates senior engineers from mid-level ones. At Google, you're expected to reason about framework-level behavior when debugging complex issues.
Boot sequence:
1. Bootloader → Linux Kernel
2. Kernel starts init process (PID 1)
3. init starts system daemons:
- servicemanager (Binder registry)
- surfaceflinger (compositing)
- zygote (app process factory)
4. Zygote preloads Android classes & resources
5. Zygote forks system_server
6. system_server starts all Android services:
- ActivityManagerService (AMS)
- WindowManagerService (WMS)
- PackageManagerService (PMS)
- InputManagerService
7. AMS starts the Launcher app
Key system services:
- AMS (ActivityManagerService): Manages Activity lifecycle, processes, tasks, and back stacks
- WMS (WindowManagerService): Manages windows, input dispatch, screen layout
- PMS (PackageManagerService): Manages installed packages, permissions, IntentFilters
- SurfaceFlinger: Composites all window surfaces into the final display frame
Rendering pipeline:
App Process:
UI Thread: measure → layout → draw (record display list)
RenderThread: execute display list → OpenGL/Vulkan commands
System Process:
SurfaceFlinger: composite all surfaces → display
16.6ms per frame (60 FPS). If UI Thread + RenderThread exceed this budget → dropped frame (jank).
Threading model:
- Main/UI Thread: All UI operations, lifecycle callbacks. Blocking = ANR after 5 seconds.
- RenderThread: Executes GPU commands. Introduced in Android 5.0 to offload GPU work from UI thread.
- Binder threads: Handle IPC calls (pool of 15-16 threads per process).
- Worker threads: Your coroutines, AsyncTask (deprecated), executors.
💻 Code Example
1// Understanding the rendering pipeline2// The Choreographer coordinates frame rendering at VSYNC boundaries34// Check for jank using Choreographer5class JankDetector {6 private var lastFrameTime = 0L78 fun start() {9 Choreographer.getInstance().postFrameCallback(object : Choreographer.FrameCallback {10 override fun doFrame(frameTimeNanos: Long) {11 if (lastFrameTime > 0) {12 val frameMs = (frameTimeNanos - lastFrameTime) / 1_000_00013 if (frameMs > 16) {14 Log.w("Jank", "Frame took ${frameMs}ms (budget: 16ms)")15 }16 }17 lastFrameTime = frameTimeNanos18 Choreographer.getInstance().postFrameCallback(this)19 }20 })21 }22}2324// StrictMode — detect main thread violations during development25class MyApplication : Application() {26 override fun onCreate() {27 super.onCreate()28 if (BuildConfig.DEBUG) {29 StrictMode.setThreadPolicy(30 StrictMode.ThreadPolicy.Builder()31 .detectDiskReads()32 .detectDiskWrites()33 .detectNetwork()34 .penaltyLog() // Log violations35 .penaltyFlashScreen() // Flash screen on violation36 .build()37 )38 StrictMode.setVmPolicy(39 StrictMode.VmPolicy.Builder()40 .detectLeakedSqlLiteObjects()41 .detectLeakedClosableObjects()42 .detectActivityLeaks()43 .penaltyLog()44 .build()45 )46 }47 }48}4950// Understanding Looper/Handler/MessageQueue51// Main thread runs a Looper that processes Messages from a MessageQueue52// Every lifecycle callback, touch event, and invalidate() is a Message5354// How ANR happens:55// 1. System sends an input event message to your app's MessageQueue56// 2. If the current message is blocking (heavy computation, disk I/O)57// 3. The input event waits in the queue58// 4. After 5 seconds, AMS triggers ANR dialog
🏋️ Practice Exercise
Practice:
- Trace the Android boot sequence from bootloader to Launcher
- Explain what happens at the OS level when you rotate your device
- Use
adb shell dumpsys activity activitiesto inspect the Activity stack - Enable StrictMode and identify main thread violations in your app
- Explain the role of SurfaceFlinger in the rendering pipeline
- What's the maximum number of Binder threads per process? Why does it matter?
⚠️ Common Mistakes
Assuming the UI thread is only for drawing — it also handles lifecycle callbacks, input events, and Binder calls
Not understanding that each VSYNC signal triggers a frame render — if your frame isn't ready, it's a dropped frame
Ignoring Binder thread limits — if all 15-16 threads are busy with IPC calls, new IPC calls will block
Thinking Android services run in separate threads — Services run on the main thread by default
💼 Interview Questions
🎤 Mock Interview
Mock interview is powered by AI for How Android OS Works Internally. Login to unlock this feature.