2016年3月24日木曜日

Android Booting

The bootup of an Android system consists of several phases, which are outlined here.

Contents
1 Key bootup components
1.1 Bootloader
1.2 'init'
1.2.1 'init' resources
2 Sequence of boot steps on ADP1
2.1 firmware
2.2 kernel
2.3 user space
3 Tools for analyzing Android Bootup
4 Notes on the Android startup procedure
4.1 Overview
4.2 strace
4.3 Interaction of different processes on application initialization
4.4 Improving Bootup Time presentation
5 News
5.1 1-second boot of Android
Key bootup components
Bootloader
The first program which runs on any Android system is the bootloader. Technically, the bootloader is outside the realm of Android itself, and is used to do very low-level system initialization, before loading the Linux kernel. The kernel then does the bulk of hardware, driver and file system initialization, before starting up the user-space programs and applications that make up Android.

Often, the first-stage bootloader will provide support for loading recovery images to the system flash, or performing other recovery, update, or debugging tasks.

The bootloader on the ADP1 detects certain keypresses, which can be used to make it load a 'recovery' image (second instance of the kernel and system), or put the phone into a mode where the developer can perform development tasks ('fastboot' mode), such as re-writing flash images, directly downloading and executing an alternate kernel image, etc.

'init'
A key component of the Android bootup sequence is the program 'init', which is a specialized program for initializing elements of the Android system. Unlike other Linux systems (embedded or otherwise), Android uses its own initialization program. (Linux desktop systems have historically used some combination of /etc/inittab and sysV init levels - e.g. /etc/rc.d/init.d with symlinks in /etc/rc.d/rc.[2345]). Some embedded Linux systems use simplified forms of these -- such as the init program included in busybox, which processes a limited form of /etc/inittab, or a direct invocation of a shell script or small program to do fixed initialization steps.

The Android 'init' program processes two files, executing the commands it finds in them, called 'init.rc' and 'init.<machine_name>.rc', where <machine_name> is the name of the hardware that Android is running on. (Usually, this is a code word. The name of the HTC1 hardware for the ADP1 is 'trout', and the name of the emulator is 'goldfish'.

The 'init.rc' file is intended to provide the generic initialization instructions, while the 'init.<machine_name>.rc' file is intended to provide the machine-specific initialization instructions.

'init' resources
The syntax for these .rc files is documented in a readme file in the source tree. See the Android init language reference

Or, see also: kandroid copy of old Android PDK

Note that the old PDK has been retracted from where it used to found below http://source.android.com/porting
You may be able to reconstruct it though:
You need a local copy of the AOSP sourcetree, and run the usual build/envsetup.sh preparation
Use repo init -b to check out the AOSP sourcetree with a tag around 2.3, then make sdk sdk_all
This worked for me, though I used some tag around 4.0.4. Some links had to be fixed in the resulting html output
See also http://www.androidenea.com/2009/08/init-process-and-initrc.html

Sequence of boot steps on ADP1
firmware
first-stage bootloader runs
it detects if a special key is held, and can launch the recovery image, or the 'fastboot' bootloader
eventually, a kernel is loaded into RAM (usually with an initrd)
normally, this will be the kernel from the 'boot' flash partition.
kernel
the kernel boots
core kernel initialization
memory and I/O areas are initialized
interrupts are started, and the process table is initialized
driver initialization
kernel daemons (threads) are started
root file system is mounted
the first user-space process is started
usually /init (note that other Linux systems usually start /sbin/init)
user space
the kernel runs /init
/init processes /init.rc and /init.<machine_name>.rc
dalvik VM is started (zygote). See Android Zygote Startup
several daemons are started:
rild - radio interface link daemon
vold - volume daemon (media volumes, as in file systems - nothing to do with audio volume)
the system_server starts, and initializes several core services
See http://www.androidenea.com/2009/07/system-server-in-android.html
initalization is done in 2 steps:
1) a library is loaded to initialize interfaces to native services, then
2) java-based core services are initialized in ServerThread::run() in SystemServer.java
the activity manager starts core applications (which are themselves dalvik applications)
com.android.phone - phone application
android.process.acore - home (desktop) and a few core apps.
other processes are also started by /init, somewhere in there:
adb
mediaserver
dbus-daemon
akmd
Tools for analyzing Android Bootup
logcat - see Android Logging System
try this command: 'adb logcat -d -b events | grep "boot"
01-01 00:00:08.396 I/boot_progress_start( 754): 12559
01-01 00:00:13.716 I/boot_progress_preload_start( 754): 17879
01-01 00:00:24.380 I/boot_progress_preload_end( 754): 28546
01-01 00:00:25.068 I/boot_progress_system_run( 768): 29230
01-01 00:00:25.536 I/boot_progress_pms_start( 768): 29697
01-01 00:00:25.958 I/boot_progress_pms_system_scan_start( 768): 30117
01-01 00:00:40.005 I/boot_progress_pms_data_scan_start( 768): 44171
01-01 00:00:45.841 I/boot_progress_pms_scan_end( 768): 50006
01-01 00:00:46.341 I/boot_progress_pms_ready( 768): 50505
01-01 00:00:49.005 I/boot_progress_ams_ready( 768): 53166
01-01 00:00:52.630 I/boot_progress_enable_screen( 768): 56793
or this: 'adb logcat -d | grep preload'
10-15 00:00:17.748 I/Zygote ( 535): ...preloaded 1873 classes in 2438ms.
10-15 00:00:17.764 I/Zygote ( 535): ...preloaded 0 resources in 0ms.
10-15 00:00:17.772 I/Zygote ( 535): ...preloaded 15 resources in 7ms.
Bootchart - see Using Bootchart on Android
strace is pretty handy also, to see the timings for system calls from a process as it runs
You can use strace as a wrapper for a program in init.rc, and save the results to a file
Use -f to follow sub-processes
Use -tt to get detailed timestamps for syscalls
Use -o to output the data to a file
Here is an example of using strace to follow the startup of zygote, and the apps that are forked from it.

Replace:

service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
with

service zygote /system/xbin/strace -f -tt -o /cache/debug/boot.strace /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
Here is some sample data:

$ head boot.strace
571 00:00:11.389939 execve("/system/bin/app_process", ["/system/bin/app_process", "-Xzygote", "/system/bin", "--zygote", "--start-system-server"], [/* 15 vars */]) = 0
571 00:00:11.658878 brk(0) = 0x804b000
571 00:00:11.659048 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x77f9a000
571 00:00:11.659169 readlink("/proc/self/exe", "/system/bin/app_process", 4096) = 23
571 00:00:11.659339 access("/etc/ld.so.preload", R_OK) = 0
571 00:00:11.659440 open("/etc/ld.so.preload", O_RDONLY) = 3
571 00:00:11.659548 fstat64(0x3, 0x7fa76650) = 0
571 00:00:11.659887 mmap2(NULL, 36, PROT_READ|PROT_WRITE, MAP_PRIVATE, 3, 0) = 0x77f99000
571 00:00:11.659970 close(3) = 0
571 00:00:11.660071 open("/lib/libc_sse.so", O_RDONLY) = 3
Please note that writing the strace data takes extra time. For long sequences of very fast syscalls (such as when the timezone file is being read) the overhead of strace itself exaggerates the timings in the trace. Use the timing information with caution.

Notes on the Android startup procedure
Overview
See "Android Initialization Process" at: http://blog.chinaunix.net/u2/85805/showart_1421736.html (this address is not work), using http://blog.chinaunix.net/space.php?uid=7788581&do=blog&id=2558375 instead.

strace
http://benno.id.au/blog/2007/11/18/android-runtime-strace

Interaction of different processes on application initialization
Talking about Android Process - http://blog.csdn.net/mawl2002/archive/2009/06/24/4295905.aspx

Improving Bootup Time presentation
See Improving Android Boot Time - notes and material for a talk at LinuxCon North America, 2010 by Tim Bird

News
1-second boot of Android
Ubiquitous Corporation has announced boot of ARM-based Android system in 1 second. Actually, it's more like a suspend and resume than a boot. See http://www.linuxfordevices.com/c/a/News/Ubiquitous-QuickBoot/?kc=LNXDEVNL032410 [March, 2010]

The Android Booting process

Some questions arise when we think about the Android boot sequence. What is the Zygote, init.rc, what is the difference between the linux kernel and the android linux kernel?.

This document is intended to explain how the booting process runs.

 

Consider the following graph:

 

 

Step 1: Power On and System Startup

 

When we press the power button, the Boot ROM code starts executing from a pre-defined location which is hardwired in ROM. It loads the Bootloader into RAM and starts executing.

 

Step 2: Bootloader

 

The bootloader is a small program which runs before Android does. This is NOT part of the Android operating system. The bootloader is the place where manufacturer puts their locks and restrictions.

The bootloader executes in two stages. In the first stage it detects external RAM and loads a program which helps in the second stage.

In the second stage, the bootloader setups the network, memory, etc, which requires to run kernel. The bootloader is able to provide configuration parameters or inputs to the kernel for specific purposes.

 

The bootloader can be found at:

 

<android source>/bootable/bootloader/legacy/usbloader

 

This legacy loader contains 2 important files:

1.      1- Init.s :: Initializes stacks, zeros the BSS segments and  call_main() in main.c

2.      2- Main.c :: Initializes hardware (clocks, board, keyboard, console) and creates linux tags.

 

Step 3: Kernel

 

The Android kernel starts in a similar way as the linux kernel.  As the kernel launches, is starts to setup cache, protected memory, scheduling and loads drivers. When the kernel finishes the system setup, it looks for "init" in the system files.

 

What is the difference between the linux and android kernels?, here's a list of changes/addons that the Android Project made to the Linux kernel:

 

·         Binder: It is an Android specific interprocess communication mechanism and remote method invocation system.

·         ashmem:  "Android Shared Memory". It is a new shared memory allocator, similar to POSIX SHM but with a different behavior and sporting a simpler file-based API.

·         pmem: "Process memory allocator": It is used to manage large (1-16+ MB) physically contigous regions of memory shared between userspace and kernel drivers.

·         logger:  This is the kernel support for the logcat command.

·         wakelocks: It is used for power management files. It holds the machine awake on a per-event basis until wakelock is released.

·         oom handling: It kills processes as available memory becomes low.

·         alarm manager: It lets user space tell the kernel when it would like to wake up.

·         RAM_CONSOLE: Allows to save kernel printk messages to a buffer in RAM, so that after a kernel panic they can be viewed in the next kernel invocation.

·         USB gadget driver for ADB

·         yaffs2 flash filesystem

 

Step 4: init process

Init is the very first process, we can say it is a root process, or the grandfather of all processes. The init process has two responsibilities.

 

     1- Mounts directories like /sys , /dev    or /proc

     2- Runs init.rc script

 

·         - The init process can be found at /init :: <android source>/system/core/init

·         - Init.rc file can be found at :: <android source>/system/core/rootdir/

 

Android has specific format and rules for init.rc files. More information about this rules can be found in: What is inside the init.rc and what is it used for.

At  this stage, you can finally see the Android logo in your screen.

 

Step 5: Zygote and Dalvik

 

In Java, we know that a separate Virtual Machine instance will popup in memory for separate per app, but in the case of Android, the VM should run as quick as possible for an app. But what happens if you have several apps thus launching several instances of the Dalvik (VM)?, it would consume an immense amount of memory.

To overcome this problem, the Android OS has a system called "Zygote".  The Zygote enables code sharing across the Dalvik VM, achieving a lower memory footprint and minimal startup time.  Zygote is a virtual machine process that starts at system boot. The Zygote preloads and initializes core library classes.

 

The Zygote loading process:

 

1.      Load Zygote Init class: 
<android source>/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

2.      registerZygoteSocket() :: It registers a server socket for zygote command connections.

3.      preloadClasses() :: Is a simple text file that contains a list of classes that need to be preloaded, you can find the file at <android source>/framework/base

4.      preloadResources()  :: Everything that is included in the android.R file will be loaded with this method (themes and layouts).

 

At this time, you can see the boot animation.

 

Step 6: System service

 

After the above steps are completed,  Zygote launches the system services.  The Zygote forks a new process to launch the system services.

Core services:

·         Starting power manager

·         Creating the Activity Manager

·         Starting telephony registry

·         Starting package manager

·         Set activity manager service as system process

·         Starting context manager

·         Starting system contact providers

·         Starting battery service

·         Starting alarm manager

·         Starting sensor service

·         Starting window manager

·         Starting Bluetooth service

·         Starting mount service

 

Other services:

 

·         Starting status bar service

·         Starting hardware service

·         Starting NetStat service

·         Starting connectivity service

·         Starting Notification Manager

·         Starting DeviceStorageMonitor service

·         Starting Location Manager

·         Starting Search Service

·         Starting Clipboard Service

·         Starting checkin service

·         Starting Wallpaper service

·         Starting Audio Service

·         Starting HeadsetObserver

·         Starting AdbSettingsObserver

 

Now we have finally completed the booting process (system service are up and running in memory).

Need to analyze the Android Bootup?

 

The logcat ::  Use adb to get the booting process events from the logcat.

 

'adb logcat –d –b events | grep "boot"

'adb logcat –d | grep preload'

 

 

Important to understand is the fact that "Android" alone is not entirely an Operating System, it is rather the User Space of Linux Kernel. Android is based on the Linux Operating System, the GNU Linux kernel.

 

Boot Process is Architecture dependent i.e. X86 and ARM (e.g A8 Cortex) have differences, ARM requires a signed first stage loader so there is a two stage boot process as the article says but does not clearly say its for ARM, Android now runs on x86 as well. If you are interested reading upon the x86 boot process see my white paper: "https://sites.google.com/site/weqaar/Home/files/bootSector_code.pdf?attredirects=0&d=1"

 

On ARM the boot process looks like:

1) X Loader (ARM specific)

2) Boot strapper (i.e. uBoot) - jumps to kernel entry point (head.s)

3) Kernel loads init (i.e. /sbin/init)

4) /sbin/init then reads /etc/inittab, then "si::sysinit:/etc/init.d/rcS" (systemV init)

5) rcS creates device files (i.e. using mtab, mounts important fs i.e. /sys), forks daemons or demons whatever

6) getty is then attached to virt terminals, bash is then executed on user login by getty

 

Dalvik is a Register VM, a user space process for most of the part, JAVA eh.

 

I forked an embedded Linux distro, that is not based on any other distro i.e. Debian, its a good starting point for anybody wanting to learn boot stuff (for ARM specially), runs in QEMU, here is the doc:

"https://sites.google.com/site/weqaar/Home/files/DaaS-Embedded-Linux-v1.03.pdf?attredirects=0&d=1"