Android is a software stack for mobile platforms. What this means is that it is Android delivers a complete set of software for mobile devices: an operating system, middleware and key mobile applications. In last few years it has gained a lot of popularity. Android was built from the ground-up to enable developers to create crossplatform mobile applications that take full advantage of all a handset has to offer without worrying about the hardware too much. Due to its open nature the developer can use as little or as more as he wants, i.e. developers can only concentrate on building highlevel apps or games etc. If they want they can use the native level to gain more power. Android is built on linux kernel, this allows the OS to get all the goodness of linux, a lot of user/developer base who already know linux. It also features development through Java language which is awsome. Being opensource it gets the benefit of being ported to new platforms, get new drivers of hardwares. It provides access to web so developers can now tap into the power of web and even harness the data of the handset to build custom apps. It also provides a nice and open tool chain for development. It is managed by Open Handset Alliance which has a lot of major players as members. Due to its open nature now a lot of other devices are adapting android.
Note: I have tried to keep the history as true as possible to my knowledge. Let me know if there is any mistakes.
I will be giving the history just for the completion of the article. There is a nice article which gives a good picture of the rise of the operating system. It was basically started by Andy Rubin when he left Danger Inc. his former company and started used a domain he previously had Android.com for his new company Android Inc. He was joined by Rich Miner, Nick Sears, and Chris White to develop a user centric operating system. Their aim was to develop a mobile OS which was highly customizable, lightweight and responsive and free with open source operating system. Though the company ended its funds the same year it got a gift of 10000$ from sSteve Perlman who was a friend of Andy to continue his dreams. The real turning poing for Android came when in 2005 Google bought the whole company. With a boost from such a company there was no looking back for android. From this time the real work began on the customizing the linux kernel. In November 7th 2007 Open Handset Alliance was launched which included other world leaders in mobile telecom to define openstandards and free software for the android ecosystem. After 5 days in 12th November 2007 the first version of android SDK was launched. This is how the new era of android devices began.
Android Building Blocks
The android architecture diagram clearly states the different elements that make the building blocks.
Now lets discuss briefly the different layers in android.
- Kernel - Android should work on some device. The most portable OS that can really scale to any device is the linux OS. By taking linux as the base we get a plethora of existing experienced people who can work on the linux os. Its easy to port to new hardware and its robust. Also we get existing people who can write drivers for new devices. So this was a good descision. This is the core of the android ecosystem. This serves as the hardware abstraction layer (HAL).
- Libraries - Above the HAL lies the C/C++ libraries that takes the services of HAL and give a more general user centric service. These are the libraries that a user can consume to build applocations. It has the OpenGL, Sqlite Database, FreeType font rendering engine, SSL, libc etc.
- Android Runtime - This consists of the Dalvik Virtual Machine and the java core libraries. Dalvik is a VM that consumes the java class files and converts them into Dex files, which is a more compact and less resource starving than JVM. As android runs on mobile devices which has limited memory and battery resourses the Dalvik VM was needed. So why convert class files and not produce dex files from source? Well Java compiler already does a classic job of generating the class files, so by taking them we dont need to rewrite the entire compiler framework. Secondly not only java but other languages also produce class files like the JPython, Scala. So by taking the class files only we do not need to write or modify complier for other current or future languages. The android runtime exports the functionalities ofthe Android libraries to the user. So the user can write everything in java langauge.
- Application framework - The framework is a highlevel framework for developers. Its built around the android runtime and libraries to give the user a feature rich environment for android development. The main Android API's are UI (User Interface), telephony, resources, locations, Content Providers (data) and package managers. The most important component of the framework is the Activity Manager, which manages the life cycle of applications and a common "back-stack" for user navigation. This is the layer that makes an android lively. This layer helps a lot of developers tap into the power of the OS and provide rich user experience.
- Applications - Finally, the top layer is the Applications layer. Most of your code will live here, along side built-in applications such as the Phone and Web Browser.
One of the unique and powerful qualities of Android is that all applications have the same access to resources. What I mean is that the applications Google writes have to go through the same public API that you use. There is nothing that Google can do and you cant do. You can even tell Android to make your application replace the standard applications if you like.
Next we will take a deeper look at the different important components of the OS.
Inherently android is a Linux varient. This means it can all those thing that a regular Linux OS can do. We only have to deal with the constraints of the mobile limited resources. So as any regular OS it also has bootup sequence. Lets see the bootup.
When we switch on the system at that instant CPU will be in a state where no initializations have been done. The CPU will invoke the reset vector to start initialization. Internal clocks are not set up and the only memory available is the internal RAM. When power supplies are stable the execution will start with the Boot ROM code. This is a small piece of code that is hardwired in the CPU ASIC. The CPU will read the code from the known location in the ROM and start reading.
The ROM code will perform some clock, memory and peripheral configuration at a very basic level. Then it will load and execute the bootloader. Technically the bootloader is not part of the android ecosystem. Its just an external system used to bring up android. Usually its the responsibility of the device manifacturer to supply this as they will be more knowledgable in the internals of the device. They can use any of the popular bootloaders such as redboot,uboot, qi bootloader. They can also decide to rollup their own bootloader. As long as it works nothing to worry.
OEMs and Carriers put there locks and restrictions in the bootloader. If you are feeling too eager you can check this location for the boot loader. The two important files here are
- init.S - This initializes stacks, zeros the BSS segments, call _main() in main.c
- main.c - This initializes hardware (clocks, board, keypad, console), creates Linux tags.
Then it will search the 'booting device' for a boot image of the OS. The boot loader sets up boot arguments and passess control to the kernel image. Then the kernel is decompressed and loaded into the flash drive. It will then start up peripheral devices such as USB, SD card, audio etc.
The bootloader can also detect certain keypresses, which can be used to make it load a 'recovery' kernel, or put the phone into a mode where the developer can perform development tasks such as re-writing flash images, and directly downloading and executing an alternate kernel image, etc.
The Linux kernel starts up in a similar way on Android as on other systems. It will set up everything that is needed for the system to run. The following things are done:
- 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)
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 desktop or embedded distributions, Android uses its own set of initialization program. The Android 'init' program processes two files called 'init.rc' and 'init.<machine_name>.rc'. Here the machine name is appended with the file name. Mostly this will be a code word. The rc files will hold the instructions in a language called the 'Init Language'.
- init.rc - Contains the generic initializations for any kind of android system and hardware.
- init.<machine_name>.rc - Contains instructions particular to that hardware.
So if some one wants to have their own service which will startup at the boot time needs to put it in one of these files. Generally this is not for general users. But still if you want to know this is how it can be done. Lets say we have the below code that we want to be executed in the bootup. This will wake up every 3 seconds and log the time elapsed to the system log.
#include < utils/log.h >
#include < unistd.h >
int main(int argc, char **argv)
LOGI("Brainless Service started");
int elapsed = 0;
elapsed += 3;
LOGI("Service elapsed time is %d", elapsed);
Now say we somehow manage to compile it into the executable '/system/bin/brainlessservice'. Once this is done we need to add the following to the init.rc file
service brainlessservice /system/bin/brainlessservice
Now this will start on the service 'brainlessservice' at 'init' phase.
Following is a lost of activities that is done by Init:
- Init process starts daemons such as rild (radio interface link daemon) and vold (volume daemon for media volumes, as in file systems - nothing to do with audio volume).
- Dalvik daemon (Zygote) is started
- 'system_server' starts, and initializes several core services. The system server is the core of the Android system and it is started as soon as Dalvik is initialized and running. The other system services will be running in the context of the System Server process. The first thing that happens is that the server will load a native library called android_servers that provides interfaces to native functionality. Initalization is done in 2 steps:
- a library is loaded to initialize interfaces to native services,
- java-based core services are initialized in ServerThread::run() in SystemServer.java
- The 'activity manager' starts core applications (which are themselves dalvik applications) [Example com.android.phone - phone application or android.process.acore - home (desktop)]
- ther processes like adb, mediaserver, dbus-daemon, etc are also started by 'init'
Zygote (Dalvik VM Launcher)
Zygote is a daemon whose only goal is to launch Apps. It is started by app_process. Here is the sequence used to start such special process
Lets see the init.rc file for the start of Zygote:
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
socket zygote stream 660 root system
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart media
onrestart restart netd
When app_process launches Zygote, it creates the first 'Dalvik VM' and calls Zygote’s main () method. Once Zygote starts, it preloads all necessary Java classes and resources, starts System Server (system_server) as mentioned in the previous section and opens a socket '/dev/socket/zygote' to listen for requests for starting applications. System Server is a complete detached process from it’s parent.
How a New App is started?
Zygote receives a request to launch an App through '/dev/socket/zygote'. Zygote then trigger a fork() creating a clone of it self in another memory space. Now in the main Zygote all the initialization (Loading Dalvik and loading java classess) is done so this clone is effecient and fast. This makes the process of creating a VM and load resources pretty efficiently. Actually during the fork or clone call linux implements Copy on Write principle. So in reality no different memory is actually copied to the other memory space. The memory is shared and marked Copy on Write. When there is a write request to the memory only then the memory is copied. So this process is fast. Now can you see the benefit of using Linux kernel? We get all these implements by default.
Zygote will launch an application when it is requested. Like when we tap an application then it launches it on the onClick() event. At this point the application launcher contacts the Activity Manager. This is done through a Remote Procedure Call (RPC) mechanism called 'Binder' and calles startActivity(). On request for startActivity() the Activity Manager request the Zygote to fork itself and start the new VM as we discussed in the last section. This is done via startViaZygote() method which will open a connection to the Zygote socket (/dev/socket/zygote).
Apart from this activity manager is responsible for other tasks as intent broadcasting, launching the "Application Not Responding" message box.
To know more about the activity manager you can refer the code.
Now that we know briefly about the android internals we will talk about the important aspect of android. This is the Dalvik VM.
Dalvik is Android’s Java virtual machine. It allows Android to run the byte-code generated from Java-based apps and exports android components and jni hooks to native libraries and the rest of the native user-space. Dalvik was design for embedded systems. Those systems would have a small amount of RAM, slow CPU and run an OS without swap space and limited battery. As we discussed earlier Dalvik translates the 'class' files to 'dex' files and executes. These 'dex' files can be upto half the size of the corresponding jar files.
There is also difference in the internal structure of the dalvik vm from the JVM. JVM is a stakc based VM but Dalvik is a register based VM. Memory footprint in Dalvik is saved via few techniques as minimal repetition, implicit typing and implicit labeling. The Dalvik VM relies on the Linux kernel for underlying functionality such as threading and low-level memory management. As of android 2.2 Dalvik also has a Just in Time compiler.
Dalvik VM internels in a more involving topic. We will discuss it in a different article later
In this article we have gone through a lot of internals and details of the android internal process. I will try to improve this article as and when I feel more content can enhance this. If you have any suggestion please let me know.