This post is targeted for Software Engineers wanting to dive deep into Android’s Internals and its workings. We’ll take a look at what happens when your Android Phone boots up but specifically what is Zygote in Android and its role in firing up an application.
We’ll see how an Activity is fired up in Android using ActivityManager and who’s responsible for initializing that Activity Manager. What happens in the init.rc file which starts various daemons in Android. And more such interesting questions.
A knowledge of Android Internals is necessary if you want to build a career as an Android Engineer. Knowledge of Android internals will make you aware of all the optimisations that can be used in your regular development tasks. You’ll be more cautious while allocating objects and creating new activities. Apart from that, it’ll also help you in interviews!
Let’s get started.
There are some prerequisites to this article. You must be familiar with concepts such as:
Here’s the cycle of the bootup process in Android:
This is how it goes: Boot ROM -> Bootloader -> Kernel -> Init -> Dalvik VM -> Zygote -> System Server -> Managers.
Boot ROM contains the initial code that’s run as soon as the device wakes up. It is a mask ROM or write protected flash drive. Embedded in the CPU chip, Boot ROM loads the Bootloader into RAM for execution.
Here are some examples of Bootrom I found on StackOverflow:
Bootloader is a piece of code that runs before any operating system. It is responsible for loading an operating system from the device, setting up a minimal environment in which OS can run and beginning the startup process. Hence, bootloader is not specific to Android.
In the context of Android (pun intended!) you might’ve heard of OEM manufacturers placing certain limitations on the operating system (eg: limited background processes). This is where those rules are stored.
One of the major tasks of bootloader involves setting up memory management, security options. This is essential for the Kernel.Bootloader contains two important files: init.s and main.c
Init.s is responsible for initializing stacks, and BSS segments. It eventually calls main.c which is responsible for initializing hardware such as keyboard, system clock, console etc.
Most importantly, the bootloader verifies the integrity of the boot and recovery partitions before moving execution to the kernel and displays the warnings specified in the section Boot state.
Once kernel boots up, it starts setup cache, loads drivers, mounts file system, starts kernel daemons etc. Once it finishes system setup, it looks for init process in the system files and launch the root/first process.
Without Kernel, your software won’t have a chance to communicate with the hardware.
This is a very crucial process. It is where the directories such as /dev, /sys, /proc are mounted. This is also the place where init.rc script is executed.
Init process also starts the daemons such as bluetooth daemon, adb daemon etc. These handle low level hardware interface including radio interface.
If you take a look at init.rc script you’ll find that it includes commands such as “start vold” for file system, “trigger zygote” for starting the Zygote process in Android.
One of the most important things that happens during this init process is a call to start the Zygote. The app_process command starts the ART or Dalvik VM and also give a call to Zygote’s main() method.
When the command app_process launches the Zygote, first a VM instance is created and then a call to Zygote’s main() function happens.
According to dictionary definition: Zygote is the first cell that’s formed during fertilisation. Similarly, Zygote is the first Android specific process when Android OS boots up!”
Zygote preloads all the system resources and classes used by the Android framework thus achieving fast app launches.
The Zygote forks itself to start a “system-server”. The system-server starts services such as ActivityManagerService, Hardware services etc.
It starts listening on a socket interface for future requests to spawn off new virtual machines (VM) for managing new application processes. On receiving a new request, it forks itself to create a new process which gets a pre-initialized VM instance.
This forking is available due to copy-on-write resource management technique. It doesn’t copy anything actually, just points to the pages of the parent process. The actual copying happens when there is a new write to the process’ pages.
The forking happens very efficiently. A new Dalvik VM is created, process gets its own thread and resources to work with. This enables code sharing among VMs thus resulting in minimal startup time.
System Server is the first service started by the Zygote. The first thing system server does is starts the native library called android_servers that provides interfaces to native functionalities.
It starts initializing each system service and and registering them with the previously started Service Manager. Each service runs in a separate Dalvik thread in system server.
ActivityManager is responsible for starting the Launcher App and registering click listeners to it. It also manages the activity lifecycle, maintains activity stack etc.
System Server also starts other services beginning with com.android such as com.android.phone, com.android.email. It also starts other managers such as Location Manager, Bluetooth Manager etc.
It is responsible for activity thread process creation, activity stack management and activity lifecycle management. At the end, it launches an intent to start Home Launcher and registers on click listeners to it. Whenever a click is detected, it launches new apps from icons on home screen.
The click events are transferred to AcitivityManagerService via Binder IPC. AMS performs multiple steps:
This article will help you host CloudAnchors using Google Cloud Anchors API. Let me know if you’ll face any problems and I’ll be happy to help :)