How Android Boots Up
The first program that runs on any Android system is the bootloader. Technically, the bootloader is present in any UNIX system. What you need to know is, that bootloader is used to do a low-level system initialization, before loading Linux Kernel.
Often, the first-stage bootloader will provide support for loading recovery images to the system flash.
The bootloader detects certain key presses which can be used to load a recovery image 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.

Eventually, a kernel is loaded into RAM (normally this will be the kernel from the /boot flash partition)
Linux Kernel

Before starting up the user-space programs and applications that make up Android. The Kernel does the bulk of hardware, driver and file system initialization.
- Core kernel initialization (Memory and I/O areas are initialized, Interrupts are started, and the process table is initialized)
- Driver initialization
- /root file system is mounted
- The first user-space process init is started

At startup, Android loads the Linux Kernel and starts the first process called init with PID 1, this is similar to how any Linux system starts up.

init program is a key component of the Android bootup sequence, it initializes main elements of Android System.
The Android init program process two files, executing the commands which it finds in them.
First one is generic init.rc, common for all Android Devices. The the second one init.<machine_name>.rc is device-specific initialization (example init.flo.rc for Nexus 7).

In those files, we can find commands that are responsible for starting processes called daemons. They sit on top of the hardware abstraction layer and listen on sockets for things like
- Android Debug Bridge Daemon (adbd) to manage ADB connections
- Debugger Daemon (debuggerd) to manage debug processes requests (dump memory, etc.)
- Radio Interface Layer Daemon (rild) to sit on top of the radio baseband interface with basement modem to manage communication with the radio
Here we also start ServiceManager which will act as a registry for all system services.

We can also find the line responsible for launching the boot animation.
Did you know that we can start these programs anytime on-demand?
$ adb shell bootanimation

After starting up the Linux daemons, the init process starts up a really neat process called Zygote. It’s just the beginning of all of the rest of the Android platform. Zygote process is basically a warmed-up ART/Dalvik VM with loaded all standard core packages (like java.util.HashMap etc). When it’s loaded it goes to sleep. When new Application is required to start, the system sends an Intent to that process (with a message similar to “execute com.example.MainActivity”). Zygote process wakes up, fork and then go back to sleep. The child process, create a new VM instance and load the component that was requested eg. com.example.MainActivity)
Every application is going to run its own process and we don’t want to do a cold start on the VM to start those up.
Zygote is the reason why Android apps start so fast.
At this point we have a bunch of subprocesses started

Init starts Runtime process
Runtime is an instance of class AppRuntime, which is sub-classed from AndroidRuntime
Runtime process does one very important thing.
It starts the Service Manager and this is really the Context manager for Binder, that handles service registration and lookup (like DNS)
It registers Service Manager as default context manager for Binder services.

Next, Zygote forks a new ART/Dalvik VM instance and starts the System Server.
System Server starts system servers like Surface Flinger, Audio Flinder and System Services like:
- Entropy Service
- Power Manager
- Activity Manager
- Telephony Registry
- Package Manager
- Battery Service
- Lights Service
- Vibrator Service
- Alarm Manager
- Window Manager
- Bluetooth Service
- and many more...
All of those services register themselves to the ServiceManager

so you as an application developer can access them by simply calling
val powerManager = context.getSystemService(Context.POWER_SERVICE)
Cool, huh?
System is ready
At this point, we are ready to launch the Home Application.
Activity Manager will send a request to Zygote and say “I want to start an activity that subscribes to the Intent.ACTION_MAIN
and Intent.CATEGORY_HOME
. That will cause Zygote to fork off, and load this new process with the Home Activity and new ART/Dalvik VM.

And now your system is ready.

Let’s do one more inspection, and track how does your.app.MainActivity really starts?

- You press on your app icon. Home application calls
val launchIntent = packageManager.launchIntentForPackage("your.app.MainActivity")
startActivity(launchIntent)
2. which in cooperation of PackageManager and ActivityManager call Zygote with your package name your.app and an entry point which is your.app.MainActivity
Similar to standard java world
java -cp your.app your.app.Main
3. The zygote then forks off with new ART/Dalvik VM and loads the activity component your.app.MainActivity
