How to Speed Up Android Boot: Deep Dive into the Boot Process and Practical Optimizations
This article explains the Android boot sequence from the boot ROM to the SystemServer, shows how to analyze boot time using logs, bootchart and boottrace, and provides practical optimization steps to reduce the startup delay, especially focusing on the Zygote and AudioService bottlenecks.
Optimizing boot time is critical for any operating system because long wait times after powering on lead to a poor user experience.
This article, based on Android 12, explains Android boot optimization in three parts:
Android boot process
Boot time analysis
Boot speed optimization practice
1. Android Boot Process
The boot process starts when the CPU is powered on and ends when the lock screen is displayed. The following diagram shows a simplified boot flow.
Another detailed diagram follows.
The boot process consists of six main sub‑processes.
1.1 Boot ROM
Boot ROM is a hard‑coded ROM inside the CPU (or an external Boot ROM on older systems) provided by the CPU manufacturer. When the power key is pressed or the system restarts, the CPU powers up, hardware is not yet initialized, but the ROM is already readable. The CPU first executes the Primary Boot Loader (PBL) stored in ROM.
After necessary hardware initialization, Boot ROM loads the bootloader into RAM and jumps to it. The PBL can also verify the bootloader; if verification fails, the boot stops.
A. When the CPU is first powered, it is uninitialized, the internal clock is not set, and only internal RAM is available. After power stabilizes, the Boot ROM code runs.
Boot ROM maps to a physical region in the ASIC to find the boot media and then loads the bootloader.
B. After the boot media is identified, Boot ROM loads the bootloader into internal RAM and jumps to it.
1.2 Bootloader
The bootloader is a special program independent of the kernel that runs after the CPU reset and before the operating system starts. It provides the basic runtime environment, such as initializing the CPU, clocks, stack, and memory system.
Bootloader functionality is similar to a PC BIOS; its code depends on the CPU architecture, chip model, system configuration, and OS, so there is no universal bootloader. In embedded Linux, common bootloaders include armboot, redboot, blob, U‑Boot, Bios‑lt, and Bootldr. U‑Boot is widely used and powerful but relatively complex.
After hardware initialization, the bootloader copies boot.img (kernel + ramdisk) from flash to RAM and then executes the kernel.
// system/core/init/init.cpp
int main(int argc, char** argv) { ... }The bootloader also mounts necessary filesystems, creates directories, and sets permissions.
tmpfs – a virtual memory filesystem stored in RAM (non‑persistent).
devpts – provides a standard interface for pseudo‑terminals.
proc – a virtual filesystem exposing kernel data structures.
sysfs – another virtual filesystem similar to proc.
During the first stage, the kernel logging system is initialized via /dev/kmsg.
1.3 Kernel
Android’s kernel is based on the upstream Linux LTS kernel. Google adds Android‑specific patches to create the Android Common Kernel (ACK). Newer ACK (5.4+) is also called GKI (Generic Kernel Image), which separates SoC‑specific code into loadable modules, solving kernel fragmentation.
GKI characteristics:
Built from ACK sources.
Single binary per architecture and LTS version (e.g., arm64 for Android 11‑5.4 and Android 12‑5.4).
Tested on all Android platform versions supported by the associated ACK.
Provides a stable Kernel Module Interface (KMI) for drivers.
Contains no SoC‑specific or board‑specific code.
When the kernel finishes its initialization, it looks for the init file, starts the first user‑space process, and continues with the rest of the boot sequence.
1.4 init Process
The first user‑space process is init (PID 1). After system startup, init runs as a daemon monitoring other processes. In Linux, all processes are forked from init.
During init startup, it launches servicemanager, Zygote, and other core services.
// system/core/init/init.cpp
static void LoadBootScripts(ActionManager& am, ServiceList& sl) { ... }Key init.rc directives include imports, early‑init actions, and service definitions for ueventd, logd, console, adbd, and servicemanager.
1.5 Zygote
Zygote is the parent process of all Android Java processes. It is started as a service during the init phase. The init.zygote64.rc file defines the Zygote service:
// system/core/rootdir/init.zygote64.rc
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
class main
priority -20
user root
group root readproc reserved_disk
socket zygote stream 660 root system
...The Zygote process loads the VM, registers JNI methods, preloads classes and resources, forks the system_server, and then waits for further process creation requests.
1.6 SystemServer
SystemServer is forked from Zygote and is the first Java process that starts the Android framework. It initializes AMS, WMS, PMS, and many other core services.
// frameworks/base/services/java/com/android/server/SystemServer.java
public static void main(String[] args) { new SystemServer().run(); }
private void run() {
Looper.prepareMainLooper();
System.loadLibrary("android_servers");
createSystemContext();
mSystemServiceManager = new SystemServiceManager(mSystemContext);
SystemServerInitThreadPool.get();
traceEnd(); // InitBeforeStartServices
try {
traceBeginAndSlog("StartServices");
startBootstrapServices();
startCoreServices();
startOtherServices();
SystemServerInitThreadPool.shutdown();
} catch (Throwable ex) { ... }
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}Service startup is divided into three phases:
Bootstrap services (e.g., Installer, ActivityManagerService, PowerManagerService, PackageManagerService).
Core services (e.g., LightsService, BatteryService, UsageStatsService).
Other services (all remaining services, including SystemUI).
When SystemServer notifies AMS that the system is ready, AMS launches the home activity and sends the BOOT_COMPLETED broadcast, completing the system‑level boot.
2. Boot Time Analysis
To optimize boot speed, first analyze the distribution of boot time to locate abnormal delays.
2.1 Analyzing Boot Logs
Android logcat categorizes logs into main, events, radio, and system. The events buffer contains boot progress events. Use the following command to filter boot progress entries:
adb logcat -d -v time -b "events" | grep "boot_progress"The output shows timestamps (in milliseconds since boot) for each key stage, such as boot_progress_start, boot_progress_preload_start, boot_progress_system_run, boot_progress_pms_start, boot_progress_ams_ready, boot_progress_enable_screen, sf_stop_bootanim, and wm_boot_animation_done.
Stage
Description
boot_progress_start
Kernel has finished and user space starts.
boot_progress_preload_start
Zygote starts.
boot_progress_preload_end
Zygote finishes.
boot_progress_system_run
SystemServer is ready and begins starting Android services.
boot_progress_pms_start
PackageManagerService begins scanning installed apps.
boot_progress_pms_system_scan_start
PMS scans /system packages.
boot_progress_pms_data_scan_start
PMS scans /data packages.
boot_progress_pms_scan_end
PMS scanning ends.
boot_progress_pms_ready
PMS is ready.
boot_progress_ams_ready
ActivityManagerService is ready.
boot_progress_enable_screen
Screen is enabled after AMS is ready.
sf_stop_bootanim
SurfaceFlinger signals the end of the boot animation.
wm_boot_animation_done
WindowManager reports boot animation finished.
Each line’s trailing number indicates the elapsed time since boot. By comparing logs from a fast device and a slow device, you can create a chart to visualize where the delay occurs.
2.2 Using bootchart
Bootchart collects CPU usage, disk I/O, and process activity during boot and generates a visual chart.
To enable bootchart on Android, create the file /data/bootchart/enabled and reboot:
adb shell touch /data/bootchart/enabled
adb rebootAfter boot, pull the data: adb pull /data/bootchart Compress the directory and generate the chart with the bootchart Java tool:
tar -czf bootchart.tgz *
java -jar bootchart.jar bootchart.tgzThe resulting PNG shows per‑process CPU and I/O usage, making it easy to spot long‑running processes.
2.3 Capturing boottrace
Boottrace records a detailed trace of the boot sequence. Enable it by editing /system/etc/init/atrace.rc and adding:
on property:persist.debug.atrace.boottrace=1
start boottrace
service boottrace /system/bin/atrace --async_start -b 30720 gfx input view webview wm am sm audio video binder_lock binder_driver camera hal res dalvik rs bionic power pm ss database network adb vibrator aidl sched
disabled
oneshotPush the modified file back, enable the property, reboot, wait a few seconds, then disable the property:
adb shell setprop persist.debug.atrace.boottrace 1
adb reboot
# after boot
adb shell setprop persist.debug.atrace.boottrace 0Stop tracing and pull the trace file:
adb shell atrace --async_stop -z -c -o /data/local/tmp/boot_trace
adb pull /data/local/tmp/boot_traceAnalyze the boot_trace file with Android’s trace viewer to pinpoint slow stages.
3. Practical Boot Speed Optimizations
During an upgrade from Android S to Android T, a device showed an 18‑second increase in boot time. Log analysis revealed a large gap (≈20 s) between boot_progress_pms_ready and boot_progress_ams_ready. Boottrace indicated that the delay was caused by the AudioService startup.
Further instrumentation inside AudioService confirmed that a driver issue on Android T caused a 15.5‑second stall. After reporting the problem to the audio team and fixing the driver, the boot time returned to normal.
Author: Nubia Technical Team Link: https://www.jianshu.com/p/3f23e027b591
21CTO
21CTO (21CTO.com) offers developers community, training, and services, making it your go‑to learning and service platform.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
