Android is not “Linux with a touchscreen.” It is a five-layer software stack. A modified Linux kernel sits at the bottom, a hardware abstraction layer above it, native libraries and the Android Runtime (ART) in the middle, a Java/Kotlin framework above that, and apps on top. Every tap you make travels through all of them. This guide walks the stack bottom to top, shows commands to inspect each layer with adb, and covers boot sequence, security, and troubleshooting.
Quick Takeaways
- Kernel: Android uses a Linux kernel (GKI, Generic Kernel Image, since Android 12) plus Android-specific drivers such as Binder, ashmem/memfd, and lowmemorykiller/LMKD integration.
- HAL: Hardware Abstraction Layer modules (HIDL/AIDL) isolate vendor drivers from the framework, so one OS image can run on many SoCs.
- ART: The Android Runtime compiles DEX bytecode with AOT, JIT, and profile-guided compilation.
- Framework:
system_serverhosts services like ActivityManagerService and PackageManagerService. Apps reach them through Binder IPC.
| Layer | Primary Component | Language | Role |
|---|---|---|---|
| 5. Apps | System and user apps | Kotlin/Java | UI and business logic |
| 4. Framework | system_server, Android APIs |
Java/Kotlin | Services and app lifecycle |
| 3. Runtime and Native Libs | ART, Bionic, libc++, SurfaceFlinger | C/C++/Java | Execution and graphics |
| 2. HAL | Vendor HAL implementations | C/C++ | Hardware abstraction |
| 1. Kernel | Linux (GKI) + Android patches | C/Rust | Scheduling, memory, drivers, security |
Prerequisites
Set up a debugging environment before running the commands below.
- Install Android SDK Platform-Tools (
adb) on Linux, Windows, or macOS. - On the device, enable Developer Options and USB debugging.
- Connect and verify:
adb devices
adb devices lists attached devices. You should see a serial number with the state device.
adb shell getprop ro.build.version.release
adb shell getprop ro.build.version.sdk
getprop reads system properties. These return the Android version and API level.
Layer 1: The Linux Kernel
Android’s foundation is the Linux kernel. It handles process scheduling, memory management, the network stack, and device drivers. Google maintains Android Common Kernels (ACKs) with Android-specific features that were once out-of-tree and are now largely upstream.
Android-Specific Kernel Features
- Binder: The IPC driver at
/dev/binder(plus/dev/hwbinderand/dev/vndbinder). Nearly all framework communication flows through it. - Low Memory Killer Daemon (
lmkd): A userspace daemon that uses kernel PSI (Pressure Stall Information) to kill background processes before the system thrashes. - Wakelocks / Suspend control: Prevents the device from sleeping while work is active.
- SELinux: Mandatory access control, enforcing since Android 5.0.
- Control groups (cgroups): Used for CPU, memory, and freezer policies, including the app freezer for cached apps.
Generic Kernel Image (GKI)
Since Android 12, GKI separates the core kernel from vendor code. Vendors ship hardware support as loadable modules against a stable Kernel Module Interface (KMI). Google can then update the core kernel without rewriting each vendor’s fork.
Inspect the Kernel
adb shell uname -a
adb shell cat /proc/version
adb shell cat /proc/pressure/memory
adb shell ls -l /dev/binder /dev/hwbinder /dev/vndbinder
uname -aprints kernel version and build info./proc/pressure/memoryshows PSI stall metrics thatlmkdconsumes.- The
lscommand confirms the three Binder device nodes exist.
Android Kernel vs. Mainline Desktop Linux
| Feature | Android Kernel | Typical Desktop Linux |
|---|---|---|
| IPC | Binder (primary) | D-Bus over sockets |
| Memory pressure handling | lmkd + PSI |
OOM killer / systemd-oomd |
| libc | Bionic | glibc / musl |
| Init system | Android init |
systemd |
| Security model | App UID sandbox + SELinux | DAC + optional SELinux/AppArmor |
| Driver packaging | GKI + vendor modules | Distro kernel modules |
Layer 2: Hardware Abstraction Layer (HAL)
The HAL defines standard interfaces for camera, audio, sensors, Bluetooth, and graphics. The framework calls the interface. The vendor supplies the implementation.
HAL Evolution: HIDL to AIDL
| Aspect | Legacy HAL | HIDL | Stable AIDL |
|---|---|---|---|
| Introduced | Android 7 and earlier | Android 8 (Project Treble) | Android 11+, preferred since 13 |
| Process model | In-process .so |
Separate process via hwbinder |
Separate process via Binder |
| Versioning | None | Package versions | Per-interface versioning |
| Status | Deprecated | Deprecated | Recommended |
Project Treble (Android 8.0) split the OS into the system partition and the vendor partition. A Vendor Interface (VINTF) manifest declares what each side provides. This is why Google can ship OS updates without waiting on every driver rewrite.
Inspect HALs
adb shell lshal
adb shell service list
adb shell ls /vendor/lib64/hw/
lshallists registered HIDL services (on newer builds, much of the AIDL list shows inservice list)./vendor/lib64/hw/holds HAL shared libraries on many devices.
Layer 3: Native Libraries and Android Runtime (ART)
Native Libraries
| Library | Purpose |
|---|---|
| Bionic | Android’s libc, libm, and dynamic linker (/system/bin/linker64) |
| SurfaceFlinger | Composites app surfaces into the display |
| libhwui / Skia | Hardware-accelerated 2D rendering |
| Media stack (Codec2, NDK Media) | Audio/video codecs |
| SQLite | Embedded database used across the platform |
| Vulkan / OpenGL ES | GPU APIs |
Android Runtime (ART)
ART replaced Dalvik in Android 5.0. Apps compile to DEX (classes.dex) bytecode. ART then executes it using a hybrid strategy:
- Install time: Minimal or no compilation (since Android 7).
- First runs: The JIT compiles hot methods and records a profile.
- Idle and charging:
dex2oatperforms profile-guided AOT compilation, producing.odex,.vdex, and.artfiles. - Cloud profiles: Play Store can ship aggregated profiles so new installs start optimized.
Control and Inspect Compilation
adb shell dumpsys package dexopt | head -n 40
adb shell cmd package compile -m speed-profile -f com.example.app
adb shell cmd package compile -m everything -f com.example.app
dumpsys package dexoptreports compilation state.-m speed-profilecompiles using the recorded profile.-m everythingcompiles all methods (larger storage footprint, longer compile).-fforces recompilation.
Layer 4: The Java/Kotlin API Framework
The framework is the set of APIs developers call. Most run inside one process: system_server.
Core System Services
| Service | Responsibility |
|---|---|
| ActivityManagerService (AMS) | Process lifecycle, task stacks, broadcasts |
| WindowManagerService (WMS) | Window layout and input dispatch |
| PackageManagerService (PMS) | Install, permissions, intent resolution |
| PowerManagerService | Wakelocks, doze, screen state |
| NotificationManagerService | Notification posting and ranking |
| ConnectivityService | Network selection and VPN |
How Binder IPC Works
An app calls a method on a proxy object. The proxy marshals the arguments into a Parcel and sends it via ioctl() on /dev/binder. The kernel driver copies data once into the target process’s memory and wakes a thread in the service. The service executes the call and returns a reply the same way. Binder also carries the caller’s UID and PID, which the receiver uses for permission checks.
Inspect Services
adb shell dumpsys activity processes | head -n 30
adb shell dumpsys meminfo com.android.systemui
adb shell dumpsys window displays
adb shell ps -A | grep system_server
dumpsys <service>prints a system service’s internal state.meminfobreaks down a process’s PSS memory by category.
Layer 5: Applications
Every app runs in its own Linux process under a unique UID, with its own private directory at /data/data/<package> (and /data/user/0/<package>). This is the application sandbox, enforced by Linux DAC and SELinux domains (untrusted_app).
Application Components
| Component | Purpose |
|---|---|
| Activity | A single UI screen |
| Service | Background or foreground work |
| BroadcastReceiver | Responds to system or app events |
| ContentProvider | Structured data sharing across apps |
The AndroidManifest.xml declares these components and the permissions the app requests. After install, the APK lives under /data/app/.
adb shell pm list packages -3
adb shell pm path com.android.chrome
adb shell dumpsys package com.android.chrome | grep -A 20 "granted=true"
pm list packages -3lists third-party apps.pm pathshows the APK location.- The
dumpsys packagegrep shows granted permissions.
The Boot Sequence: Power Button to Home Screen
- Boot ROM loads the bootloader from fixed storage.
- Bootloader verifies and loads the kernel and ramdisk. Android Verified Boot (AVB) checks partition integrity.
- Kernel initializes hardware, mounts the ramdisk, and starts
/init. initparses*.rcfiles, mounts partitions, applies SELinux policy, and starts native daemons (servicemanager,vold,lmkd,logd).zygotestarts. It preloads framework classes and common resources, then waits on a socket.system_serveris forked from Zygote and starts the core services.- Launcher activity starts, and
BOOT_COMPLETEDbroadcasts.
Zygote is the key optimization. Every app process is a fork of Zygote, so apps share preloaded memory pages via copy-on-write. This is why cold-starting an app is faster than loading a full runtime from scratch.
adb shell ps -A | grep -E "zygote|system_server|init"
adb shell getprop init.svc.zygote
adb logcat -b events | grep boot_progress
adb shell getprop sys.boot_completed
boot_progressevents in the events buffer mark boot stages.sys.boot_completedreturns1once boot finishes.
Security Architecture
| Mechanism | What It Does | Introduced |
|---|---|---|
| App Sandbox (UID) | Isolates app data and processes | Android 1.0 |
| SELinux | Mandatory access control for all processes | 4.3 (enforcing in 5.0) |
| Verified Boot (AVB) | Cryptographic check of boot chain | 4.4 / AVB 2.0 in 8.0 |
| File-Based Encryption (FBE) | Per-user, per-file encryption keys | 7.0 |
| Runtime permissions | User grants at use time | 6.0 |
| Scoped storage | Restricts broad file access | 10 / enforced 11 |
| Hardware-backed Keystore / StrongBox | Keys in TEE or secure element | 6.0+ |
| Memory tagging (MTE) | Detects memory-safety bugs on supported hardware | 12+ |
Check SELinux mode and security patch level:
adb shell getenforce
adb shell getprop ro.build.version.security_patch
adb shell getprop ro.boot.verifiedbootstate
getenforceshould returnEnforcing.verifiedbootstatereturnsgreenon a locked, verified device.
Android vs. Other Mobile and Linux Platforms
| Attribute | Android | iOS | Desktop Linux |
|---|---|---|---|
| Kernel | Linux (GKI) | XNU (Mach + BSD) | Linux |
| App runtime | ART (DEX) + native | Native ARM binaries | Native / interpreters |
| IPC | Binder | XPC / Mach ports | D-Bus / sockets |
| Primary languages | Kotlin, Java, C++ | Swift, Objective-C | Any |
| Update model | Treble / Mainline modules + OTA | Monolithic OTA | Package manager |
| Customization | High (OEM skins, AOSP) | Low | Very high |
Project Mainline and Modular Updates
Since Android 10, Project Mainline delivers updates to core components, such as the media codecs, ART, and networking modules, as APEX packages through Google Play. These modules live under /apex/.
adb shell pm list packages --apex-only --show-versioncode
adb shell ls /apex/
--apex-onlylists Mainline modules and their version codes.
Troubleshooting and Real-World Scenarios
Scenario 1: Device Stuck in a Boot Loop
Symptoms: The boot animation repeats. system_server or zygote crashes.
adb logcat -b all -d > bootlog.txt
adb shell dmesg > dmesg.txt
adb shell cat /proc/last_kmsg
-b allcaptures every log buffer.-ddumps and exits.- On newer devices use
/sys/fs/pstore/for the last kernel panic log (requires root or recovery access).
Search for FATAL EXCEPTION, avc: denied (SELinux), or Zygote crash traces. A common cause is a corrupted /data partition or an incompatible module. Boot into recovery and choose a cache or data wipe only after backing up.
Scenario 2: App Killed in the Background
Symptoms: Background apps reload constantly on low-memory devices.
adb shell dumpsys meminfo | head -n 30
adb logcat -b events | grep -i lmk
adb shell cat /proc/pressure/memory
High some/full PSI values indicate memory pressure. The lmk events show which processes lmkd killed and why. Reduce background services, trim app memory, or check for leaks.
Scenario 3: Binder Transaction Failures
Symptoms: TransactionTooLargeException or DeadObjectException.
adb shell cat /sys/kernel/debug/binder/failed_transaction_log
adb shell cat /sys/kernel/debug/binder/state
Binder’s per-process transaction buffer is about 1 MB, shared across all in-flight transactions. Keep Intent extras and Parcel payloads small. Pass large data through files, ContentProvider, or shared memory. Debugfs may need root or a userdebug build.
Scenario 4: App Slow After Install or Update
adb shell cmd package compile -m speed-profile -f <package>
adb shell cmd package bg-dexopt-job
bg-dexopt-jobtriggers the background optimization job immediately instead of waiting for idle and charging.
Scenario 5: Performance Profiling
adb shell dumpsys gfxinfo <package> framestats
adb shell am start -W <package>/<activity>
adb shell perfetto -o /data/misc/perfetto-traces/trace -t 10s sched freq idle am wm gfx view
am start -Wwaits for launch and printsTotalTime.- Perfetto is the system-wide tracing tool replacing
systrace. Open the output at the Perfetto UI.
Developer Checklist
- Test on multiple API levels. Behavior changes across versions are documented per release.
- Use
adb shell dumpsysas the first diagnostic. - Ship Baseline Profiles to cut cold-start time.
- Respect scoped storage and runtime permissions.
- Use
StrictModein debug builds to catch main-thread I/O.
FAQ
What kernel does Android use?
Android uses a modified Linux kernel, delivered as a Generic Kernel Image (GKI) since Android 12. It adds Android-specific features such as the Binder IPC driver and integration with lmkd. Check yours with adb shell uname -a.
What is the difference between Dalvik and ART?
Dalvik was the original JIT-only VM. ART, the default since Android 5.0, uses ahead-of-time compilation and, since Android 7, a hybrid of JIT, profile-guided AOT, and cloud profiles. ART gives faster startup and better battery life.
What is Zygote in Android?
Zygote is a process started by init that preloads framework classes and resources. Every app and system_server is forked from it, so they share memory pages through copy-on-write. This speeds up app launch and reduces RAM usage.
Is Android the same as Linux?
No. Android uses the Linux kernel but replaces the userspace. It uses Bionic instead of glibc, Android init instead of systemd, and Binder instead of D-Bus. Standard GNU tools and X11/Wayland desktop stacks are not included.




