Thursday, March 23, 2017

Android Internals : just what application developers needs to know

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. 

Source Tree : kernel

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

Source Tree: libcore ,  dalvik , system 

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,


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

1 comment :

  1. You actually make it seem so easy with your presentation
    but I find this matter to be actually something that I think I
    would never understand. It seems too complicated and extremely broad for me.
    I am looking forward for your next post, I will try to get the hang of it!


    Also visit my page; postcards ()

    ReplyDelete