It is always good (not a must) to know the internals of a software platform, to be an efficient developer. After having exposed to the internals, many facts will make more sense to during the development, further you will get the clear picture of how each components connect and interact with each other.
Its been a while since the inception of the Android Mobile platform. Since then, there has been higher demand for android developers, not to mention how it made easy for existing Java developers to migrate. Statistics show, most mobile and embedded devices will default to Android soon or later.Learning this platform would be worth the time spend.
This article, will explain only necessary internal details just enough for user-space developer. Once complete we will have a clear picture of entire android stack starting from the source tree organisation, architecture component interaction, start up sequence, to how an application is launched.
1. Architecture
Fig 1 Conceptual Architecture |
1.1 Kernel
A the bottom most level, the host operating system, is the Linux kernel.
Theoretically it could be any host kernel, practically, however it is a difficult task to achieve. Though, Linux kernel is being used, there were many kernel specific patches those were added to support various user level android policies and drivers.
Kernel patches (Details are skipped)
- Wake Locks
- Binder
- Klogger
- Anonymous Share Memory
- Alarm Timers
- Low Memory Killer
- Network Security policy
Other than the patches above, one has to keep in mind, the device manufactures do add custom patches to support their hardware, what is mentioned above are core kernel patches for a android system to work.
1.2 Android Runtime
Consist of the Dalvik virtual machine, which is just like JVM on tbe desktop, that executes the android applications we run, Java runtime, that comes from the Apache Harmony project, system daemons, the init binary and various supporting binaries. Dalvik virtual machine executes dex files instead of class files. dex files are generated by post processing class files with dx utility.
Oracle Java = Java Language + class file + JVM + JRE libs
Android Java = Java Language + dex file + DVM + Apache Harmony Project
Most of the java.* , org.w3c.* junit.* org.json.* in the android API comes from here, including the sql jdbc driver
1.3 Libraries
This is where, the 3rd party native libraries (C/C++) are hosted, they act as a support layer for low level access from the java libraries, it consist of google developed C library called Bionic, it is stripped down library from BSD standard C library. Bionic isn't compliance with POSIX, so native (non java) application and library porting from POSIX system is a hurdle. Though only few libraries have been mentioned in the diagram, it consist of more, starting from libusb to webRTC, kindly see the source tree.
The Application frame work access these libraries via JNI , one such example to site would be sqlite, we will see a source relation, check the links
So, in nutshell, these libraries are accessed by the application frame work via JNI.
Source Tree: external
1.4 Application Framework
Ah, finally we are at the top, the android.* APIs you see in the Android API reference sprouts from here, this is what we mostly use while developing an android applications. Framework don't just consist of developer apis, but, various services and interfaces to communicate with them. Services are not directly accessible via framework , however, via kernel supported mechanism called Binder. In short andorid.* APIs connected to service / system server via binder.
Source Tree: framework
1.5 Applications
There is were we have all the fun, we use the SDKs to access these framework APIs to develop the applications. Most of the application developers play here. There are other species of developers who hack the frameworks , android services and even the kernel subsystem to build custom roms, one such community is the CyanaogenMOD, we should say they are the first class android developers and us to be economy developers. ;-). Most android devices have set of default applications like dialers, mms, browsers you can find its source tree over here.
2. Android Hardware Abstraction Layer
Kernel does provide HAL , however Google engineers felt it wasn't enough, one reason could be GPL license that the kernel has. So, in order to make device manufacturers implement non GPLed drivers in the user space, this may be a favorable choice.
Libhardware provides interface for various devices and sensors, the device manufacturers can develop drivers in closed source environment, complying to these interfaces. Few of the interfaces are listed here.
- Audio (libaudio.so)
- Graphics (gralloc.so, copybit.so, libhgl.so)
- Camera (libcamera.so)
- GPS (libgps.so)
- Sensors (libsensors.so)
- Radio Interface (libril-vendor-version.so)
All that the manufacturer has to do is to put their library into /system/libs/hw/
Case Study : If you like to know how RIL is used for receiving calls, sending sms, receving sms etc take a look into this answer.
3. Android File System
Android though is Linux based doesn't strictly abide to the FHS , instead has a custom hierarchy
/system Immutable directory coming from the original build.
It contains native binaries and libraries, framework jar files,
configuration files, standard apps, etc.
/system/app All the pre-installed apps
/system/bin Binaries installed on the system (toolbox, vold, surfaceflinger)
/system/etc Configuration files
/system/fonts Fonts installed on the system
/system/framework Jar fi les for the framework
/system/lib Shared objects for the system libraries
/system/modules Kernel modules
/system/xbin External binaries
/data changing content of the system are put:
apps, data added by the user, data generated by all the apps at runtime, etc.
/etc Symbolic link to /system/etc
/dev Mount point for tmpfs filesystem
/proc Mount point for procfs filesystem which provide access to kernel data structures
/sbin Contains various daemons
/root As usual the root home directory
/mnt Mount point for external and internal filesystems
and some security related filessytem
/sys Mount point for sysfs filesystem which has information on
kernel's device objects
/sdcard Symbolic link to /mnt/sdcard
/cache Used by application to save data temporarily like Google Play Store download etc
/d Symbolic link to /sys/kernel/debug
/acct Mount point for the acct cgroup (control group),
which provides for user accounting.
/vendor Symbolic link to /system/vendor
4. Source Code Organisation Overview
bionic/ is where Android's standard C library is stored
bootable/ contains code samples regarding the boot of an Android device. In this folder,
you will find the protocol used by all Android bootloaders and a recovery image
build/ holds the core components of the build system
cts/ The Compatibility Test Suite
dalvik/ contains the source code of the Dalvik virtual machine
development/ holds the development tools, debug applications, API samples, etc
device/ contains the device-speci c components
external/ is one of the largest folders in the source code, it contains all the external
projects used in the Android code
frameworks/ holds the source code of the various parts of the framework
hardware/ contains all the hardware abstraction layers
libcore/ is the Java core library
ndk/ is the place where you will nd the Native Development Kit, which allows to build native
applications for Android
packages/ contains the standard Android applications
prebuilt/ holds all the prebuilt binaries, most notably the toolchains
sdk/ is where you will nd the Software Development Kit
system/ contains all the basic pieces of the Android system: init, shell, the volume manager, etc.
5. System Startup
Fig 2. start up sequence
Start up sequence till init is quite straight forward, this is similar usual x86 boot process, finally calling Init , however Android system differs starting from the init sequence. The init itself was written from scratch and not same as the one seen on Linux distribution.
Once the kernel start /init process, it reads the file name /init.rc and /init.(machine-name).rc , these rc script, first of all sets the environment variables, mounts various file system to its respective mount points, starts various daemons like rild (radio interface layer daemon), adb , vold, netd etc. Init become mother of all the process created subsequently. The next core job of init is to start up the Zygote, which is the mother of all the android applications.
Lets take a deeper view into Zygote start up,
The entry above from ./init.rc that start the app_process to startup the zygote.
As seen in the source line 188 of app_main.cpp
It start up the java implementation of Zygote , and 'start-system-server' flag is passed as the parameter. This is exactly what we had passed in the entry from the init.rc. The line 189 does many other tasks under the hood, the runtine.start() at line 839 start up up the Dalvik virtual machine, see line 443 of AndroidRuntime.cpp for more information.Ahead of zygote invocation, Dalvik runtime was setup and Dalvik virtual machine was initialized. ZygoteInit::main() get called at line 888 of AndroidRuntime.cpp , which start up the System Server this can be seen at line 544 of ZygoteInit.java, finally it runs runSelectLoopMode() and waits for future request to fork() new zygote instances which specialize into the android application.The System server is started in a two sequence process , first a libary is called to initialize the native services, which can be seen at line 1064 of SystemServer.java , then java based core services are run by ServerThread::run() which is seen at like 1067 of SystemServer.java. Check the source to find out the sequence of the services started, core services line the PowerManager, ActivityManager, Sensor Service etc and other non critical services are started this way. The main being the AcitivityManager, which handles the our Andorid Application.
Once the kernel start /init process, it reads the file name /init.rc and /init.(machine-name)
Lets take a deeper view into Zygote start up,
Init runs the /system/bin/app_process and name it zygote.
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
The entry above from ./init.rc that start the app_process to startup the zygote.
As seen in the source line 188 of app_main.cpp
188 if (zygote) {
189 runtime.start("com.android.internal.os.ZygoteInit",
190 startSystemServer ? "start-system-server" : "");
191 }
It start up the java implementation of Zygote , and 'start-system-server' flag is passed as the parameter. This is exactly what we had passed in the entry from the init.rc. The line 189 does many other tasks under the hood, the runtine.start() at line 839 start up up the Dalvik virtual machine, see line 443 of AndroidRuntime.cpp for more information.Ahead of zygote invocation, Dalvik runtime was setup and Dalvik virtual machine was initialized. ZygoteInit::main() get called at line 888 of AndroidRuntime.cpp , which start up the System Server this can be seen at line 544 of ZygoteInit.java, finally it runs runSelectLoopMode() and waits for future request to fork() new zygote instances which specialize into the android application.The System server is started in a two sequence process , first a libary is called to initialize the native services, which can be seen at line 1064 of SystemServer.java , then java based core services are run by ServerThread::run() which is seen at like 1067 of SystemServer.java. Check the source to find out the sequence of the services started, core services line the PowerManager, ActivityManager, Sensor Service etc and other non critical services are started this way. The main being the AcitivityManager, which handles the our Andorid Application.
501 /* Request to fork the system server process */
502 pid = Zygote.forkSystemServer(
503 parsedArgs.uid, parsedArgs.gid,
504 parsedArgs.gids,
505 parsedArgs.debugFlags,
506 null,
507 parsedArgs.permittedCapabilities,
508 parsedArgs.effectiveCapabilities);
509 } catch (IllegalArgumentException ex) {
510 throw new RuntimeException(ex);
511 }
512
544 if (argv[1].equals("start-system-server")) {
545 startSystemServer();
546 } else if (!argv[1].equals("")) {
547 throw new RuntimeException(argv[0] + USAGE_STRING);
548 }
Code Snippet Showing How System Server is started
Conclusion
Ah finally we have reached the end, though this was quick introduction into the android internals, it is my humble opinion that , information above would be sufficient enough to get you started with griping the Android APIs. This introduction will hopefully help you understand the relations and component interaction, which would make android application programming more exiting. Where go from here ? Now you can start reading Application Fundamentals from the android main resource, trust me, many things will make more sense now.
Reference
[3] Elinux Android
No comments :
Post a Comment