37
CARNEGIE MELLON UNIVERSITY, PITTSBURGH Android architecture Copyright © Karan Khanna 7/28/2010 We try to explore the architectural drivers that shaped Android, its architecture at a high level, and then try to relate each architectural driver with various tactics that satisfy it.

Android Architecture

Embed Size (px)

Citation preview

CARNEGIE MELLON UNIVERSITY, PITTSBURGH

Android architecture

Copyright © Karan Khanna

7/28/2010

We try to explore the architectural drivers that shaped Android, its architecture at a high level, and then try to relate each architectural

driver with various tactics that satisfy it.

Copyright © Karan Khanna, Carnegie Mellon University, 2010 Page 2

CONTENTS 1. Introduction .............................................................................................................................................................................................................................................. 3

2. Architectural drivers ............................................................................................................................................................................................................................. 4

Functional goals ........................................................................................................................................................................................................................................... 4

Quality attributes: ....................................................................................................................................................................................................................................... 5

Constraints: .................................................................................................................................................................................................................................................... 7

3. Android mobile stack architecture [Dynamic view, 1st level decomposition]: ............................................................................................................. 9

4. Android mobile stack architecture [Dynamic view, 2nd level decomposition, Linux process and Android application]: ........................ 15

5. Android mobile stack architecture [Dynamic view, 3rd level decomposition, Android component: Activity]: ............................................ 22

6. Android mobile stack architecture [Dynamic view, 2nd level decomposition, application framework components]: .............................. 23

7. Android mobile stack architecture [Dynamic view, 2nd level decomposition, application framework start-up sequence]: .................. 30

8. Strategies and tactics to accomplish various architectural drivers:................................................................................................................................ 31

Security: ........................................................................................................................................................................................................................................................ 31

Time Performance: .................................................................................................................................................................................................................................. 32

Extensibility: ............................................................................................................................................................................................................................................... 34

Be open source but keep GPL out of user space: .......................................................................................................................................................................... 35

Long battery life: ....................................................................................................................................................................................................................................... 35

Fitting short memory (RAM): .............................................................................................................................................................................................................. 36

9. References .............................................................................................................................................................................................................................................. 37

Copyright © Karan Khanna, Carnegie Mellon University, 2010 Page 3

1. INTRODUCTION

Recent years have seen rapid evolution of mobile phones as computation platforms [beyond the basic voice telephony], which

could soon rival traditional desktop computing in many respects – Internet seems incipient. This has shifted focus of major

players in the area of general purpose desktop computing – Microsoft, Apple, and so on towards mobile computing, and we

have seen some very fine offerings like the iPhones, Andriod phones and Windows-mobile phones.

From my recent but brief introduction to Android and iPhone OS, I like to believe that in creating mobile software platforms,

existing expertise and knowledge in the area of desktop computing has been re-applied and desktop software systems have

been re-factored. It therefore becomes intriguing to explore what drives the architecture of a modern world mobile software

platform, and how these forces reshape the architecture of traditional desktop software platform to that of mobile software

platform.

There were several motivating factors to take this Independent study. Android is young, exciting product, and I wanted to

learn more about it. I also wanted to augment my architectural thinking on the lines advocated in the Architectures for software

systems course at Carnegie Mellon University. Also, there is not a comprehensive documentation yet available publicly, as far

as the architecture and design of Android is concerned. There is a set of videos from Google which give a high level insight, and

then there is an API reference plus the sample applications. While it may not be easy to search specific information from

within videos, API reference is sometimes hard to comprehend.

I hope to add more information, and make corrections to this initial draft, as my understanding of the architecture grows.

Copyright © Karan Khanna, Carnegie Mellon University, 2010 Page 4

2. ARCHITECTURAL DRIVERS

FUNCTIONAL GOALS

Android has been designed to meet amongst others, following larger functional goals:

• Ability to provide the basic Telephony service of making and receiving calls, along with a possibility of being

configurable for non-telephony usage, quite like the iPods and so forth.

• To serve as a robust network stack and Internet client

• To provide a comprehensive coding environment for mobile devices, giving application programmers freedom to take

advantage by developing using:

o Native code

o Managed code

o Web-browser based applications (so that applications can run on multiple phones)

[R1] Google I/O 2009 – How do I code Thee? Let me count the ways

http://developer.android.com/videos/index.html#v=GARMe7Km_gk

Copyright © Karan Khanna, Carnegie Mellon University, 2010 Page 5

QUALITY ATTRIBUTES:

Security

As in case of Desktops, and other mobile platforms, security against malicious code that may

cause bad user experience by bringing down the system is important. Additionally, in case of

mobile, also important is to guard against any malicious code that may cause bad user

experience by consuming unreasonable amount of battery, by making uncontrolled calls, and

accessing private user data like contacts.

Time performance [R2]

The platform should provide a pleasing user experience by having short application launch

and switching times. Switching context becomes even more important in case of mobile

because of the limited display/screen real-estate, where a single user-interaction almost

always takes-up the entire screen. Consequently, moving from one step to another within a

single user task might mean rendering complete screen several times in a short period of

time. More specifically, Android sets guidelines such as:

• Browser should launch in < 1300 ms

• MMS/SMS should launch in < 700 ms

• Alarm clock should launch in < 650 ms

• When more than one application has been launched, re-launching an already-running

application must take les that the original launch time

Complete system software

upgrade [R2]

It should be possible to upgrade entire system software (Restart OK), without wiping out

user data. Any of the following is allowed:

• Over the air downloads with offline update via reboot

• Tethered updates via USB from a host PC

• Offline updates via reboot and update from a file on a removable storage

Copyright © Karan Khanna, Carnegie Mellon University, 2010 Page 6

Extensibility

• One of the fundamental requirements of Android application framework is the re-use

and replacement of components. If your application likes to integrate the ‘Google

Maps’ feature, it should be able to do so. On the other hand, if you like to make a

device version with custom home application, it should be possible to do so.

• Backward compatibility of the framework, as the platform stack is revised over time.

• It should be easy for the OEMs to port the stack to their hardware

Battery[R3]

• The goal is to maximize the time before the phone battery must be recharged before it

can be used again. A minimum target cannot be specified here since how long the

battery lasts largely depends upon how the device gets used. However, there are some

statistics which can give a qualitative idea of the same:

HTC Dream has: 1150 mAh battery

Macbook PRO has: 5600 mAh battery

A 500 MHz CPU used at 100% clock-rate consumes around 100 mA

Using 3G at full rate consumes 150 mAh

Using WiFi at full rate consumes 275 mAh

Watching Youtube consumes 240 mAh

Typical usage: The phone on an average is used for 10 min/Hour, and the remaining

time phone is in the pocket.

Handling background tasks can be crucial to optimal usage of battery.

[R2] Android Compatibility Definition Document

http://static.googleusercontent.com/external_content/untrusted_dlcp/source.android.com/en/us/compatibility/android-2.1-

cdd.pdf

[R3] Google I/O 2009 – Coding for life, Battery life, That Is

http://developer.android.com/videos/index.html#v=OUemfrKe65c

Copyright © Karan Khanna, Carnegie Mellon University, 2010 Page 7

CONSTRAINTS:

Memory and storage[R2][R4]

As of Android 2.1: The minimum main memory (RAM) specified for Android compatibility is:

92 MB for kernel and user space applications, which is in addition to any memory dedicated

to hardware components such as radio, and so on.

In addition to this, the device must provide a non-volatile memory of 150 MB for user data

Further, there must be at-least 2GB of shared storage for applications

However, the original design also considers low end devices with 32-MB RAM, 32-MB non-

volatile storage, and 200 MHz online processor.

Open source, and keep

General Public Licence out of

user-space

Being open-source is one of the primary reasons for creating the Android Platform in first

place. Stakeholders believe that by exposing the complete software at source level, the

platform will evolve with inputs from entire community.

However, OEMs that build Android devices sometimes might have software components

added to Android, which they would like not to open-source. Consequently, there do not have

to be any part of the Android framework in user-space, which is distributed under GPL. This

is because, anything software that uses another software distributed under GPL must itself

also be distributed under GPL.

Other hardware[R2]

Android 2.1 compatibility mandates the following amongst others:

• 3-Axis accelerometer (with events at 50 Hz or more)

• 3-Axis compass (with events at 10 Hz or greater)

• GPS, and preferably assisted GPS

• Home, menu, and Back navigation keys to support Android’s navigation paradigm

• Dedicated search key

Copyright © Karan Khanna, Carnegie Mellon University, 2010 Page 8

[R4] Andy Rubin’s interview snippet:

http://www.talkandroid.com/android-forums/android-hardware/2-android-minimum-hardware-requirements.html

Copyright © Karan Khanna, Carnegie Mellon University, 2010 Page 9

3. ANDROID MOBILE STACK ARCHITECTURE [DYNAMIC VIEW, 1ST LEVEL DECOMPOSITION]:

Binder

Application framework

Power manager

Low memory killer

Linux kernel

LegendLinux

processLinux

kernel

Linux kernel

module

Group of

processes

Alarm

AShMem

Kernel debugger

Logger

AProcess A requests

some kernel/kernel

module service

Kernel calls driver

services on behalf of

some user space

process

Init

BA A creates B

PM LMK BINDER ALARM ASHMEM KD LOGGER

Copyright © Karan Khanna, Carnegie Mellon University, 2010 Page 10

Component & item catalogue: Android mobile stack architecture [Dynamic view, 1st level decomposition]

Linux kernel Android is a complete system stack and uses standard Linux kernel version 2.6.24 as its kernel. A set of kernel drivers is added as patch to Linux kernel to be able to meet some special requirements of Android as a whole.

Linux kernel is open source and provides:

• Memory and process management

• Permission based security model

• Proven driver model

Drivers/Linux kernel modules*

These driver modules are the main part of the Android specific kernel patch, and include amongst others:

1. Power management driver: This driver uses the existing power management capabilities, built within the Linux kernel, and specialises them so that they are more suitable for an embedded usage. Essentially, it implements a more aggressive policy that unless a user application specifically requests CPU or any other hardware resources, they shall be turned off.

2. Binder IPC driver: This driver is a character driver, and all forms of IPC available to user applications on Android are routed through, and facilitated by this driver module. It has been optimized for embedded use in that it does not use the general purpose Java serialization for marshalling objects but instead uses a more simplified protocol that is sufficient for system level IPC. It also keeps track of what requests come from what processes, and when the requests are between the objects of same process, no actual marshalling takes place, and objects are shared via shared memory. How this exactly works is not completely clear.

Copyright © Karan Khanna, Carnegie Mellon University, 2010 Page 11

3. Low memory killer driver: It registers a couple of functions with the kernel, which get called whenever kernel thinks that the RAM memory is low. These functions provided by this driver scan a list of running processes, and kill one based on a heuristic approach, that decides the least important process for the current circumstances. The default implementation of the Linux kernel’s OOM (out of memory) killer has a process selection algorithm that seemingly may choose any application to be killed under OOM condition, when there is no swap space. Android, like many other embedded devices, does not use a swap space. Further, typical smart-phone usage is characterised by frequent moves between applications, and this can quickly lead the system to OOM condition. Android implementation of the algorithm meets the needs of a smart-phone usage better, by giving preference to applications with which the user interacted more recently.

* What kind of structure is a Linux kernel Module: It is essentially a collection of C-functions, built into a special format object file, whose code can be linked to and unlinked from the kernel at run-time. The module does not run as a specific process. Instead, it is executed in kernel mode on behalf of the current process, like any other statically linked kernel function.

** It must be noted that these are not the only kernel modules that the framework will depend upon, and we have selected to show only those that were explicitly created to support the needs of Android.

Init process This is the first user space process that gets created after the kernel boots. Its role is similar to what it is on all Desktop distributions: to launch the rest of the system, which may include things like launching various background services and shell, etc. Linux kernel simply looks for an executable named Init at a designated place in the root file system. Android uses a custom version of Init, that interprets a file called Init.rc and

Copyright © Karan Khanna, Carnegie Mellon University, 2010 Page 12

launches rest of the framework services, applications, defines global environment variables, and so forth.

Android Init Language [/system/core/init/readme.txt]

Application framework

This is the part where a lot of engineering effort has been spent to design a rich application framework aptly suitable for mobile usage. We treat application framework as a collection of processes at this point, and we will get into its details subsequently. Some interesting aspects about the framework are as follows:

• It is primarily supports development in Java language, but defines an essentially new run-time environment and therefore much of the API differs from standard JDK.

• Native development is supported via Java Native Interface

• It is designed to promote synergy and collaboration amongst applications

This connector represents the user-space side interface for some operating system service, or some driver service. Each such interface is a set of system-calls. Each time a request is made by a user-space process to the kernel, it is done via a system call, which has semantics of call-return, and additionally, execution transitions from user-mode into kernel-mode, executing within the context of the same process, and returning back a result. Green symbolises that this is native/un-managed.

* While there are numerous interaction points between the application framework and the kernel, we only show those corresponding to the driver modules that have been newly added to keep it simple. We also distinguish between different instances of this type of connector by qualifying them with appropriate names. Each such instance may differ from another because of the exact set of system-calls/API it exposes.

This connector represents the kernel-side interface for driver modules, which may be used to extend kernel’s core functionality. This interface is a set of call-backs that are implemented by the driver, and are

Copyright © Karan Khanna, Carnegie Mellon University, 2010 Page 13

called by the kernel, when required.

Once again, different instances are uniquely identified by the qualifying name. Each driver implements a different functionality and therefore may implement a character driver interface or a block driver interface. Further, there can be variations such as the number of IOCTLS implemented by each driver.

Entity A creates entity B. Although we show here that process A creates process B, we use this same connector to also indicate entities other than processes, such as kernel, and assume that the semantics remain same, unless explicitly noted.

Colors We have borrowed one thing in particular from Google’s diagrams as noted in their documentation: they use red color for components that are part of kernel, green for all the user-space native code, and blue for managed code very consistently across the board. Yellow is used for Dalvik virtual machine, and Zygote. We try to incorporate the same color theme in our representations as strictly as possible, but there may be points where it might not be clearly obvious what color an item must be shown. For e.g., when we show application framework as one unified component in the diagram above, we shown it in blue indicating that it is managed component. While it is true that essentially Android’s application framework is largely about managed code, we also have native components within application framework. Consequently, wherever there is such a situation, we try to make it explicitly clear in text.

Before we breakdown further into the application framework, it will be helpful to understand how Android uses a Linux process. We will also introduce four elementary components that will form building-blocks for the complete framework, and for applications that you as developers write for Android. And even before that, it will make sense to know the larger picture of what the fundamental concept of applications on Android is. Here is the opening statement from developer’s page that aptly describes it:

Copyright © Karan Khanna, Carnegie Mellon University, 2010 Page 14

“A central feature of Android is that one application can make use of elements of other applications (provided those applications permit it). For example, if your application needs to display a scrolling list of images and another application has developed a suitable scroller and made it available to others, you can call upon that scroller to do the work, rather than develop your own. Your application doesn't incorporate the code of the other application or link to it. Rather, it simply starts up that piece of the other application when the need arises.

For this to work, the system must be able to start an application process when any part of it is needed, and instantiate the Java objects for that part. Therefore, unlike applications on most other systems, Android applications don't have a single entry point for everything in the application (no main() function, for example). Rather, they have essential components that the system can instantiate and run as needed.”

http://developer.android.com/guide/topics/fundamentals.html

Assuming that there is some structural manifestation of what we will call as an Android component, let us see how a Linux process relates to an Android application. We will have more to talk on Android components in subsequent sections.

Copyright © Karan Khanna, Carnegie Mellon University, 2010 Page 15

4. ANDROID MOBILE STACK ARCHITECTURE [DYNAMIC VIEW, 2ND LEVEL DECOMPOSITION, LINUX PROCESS AND ANDROID APPLICATION]:

Copyright © Karan Khanna, Carnegie Mellon University, 2010 Page 16

Component & item catalogue: Android mobile stack architecture [Dynamic view, 2nd level decomposition, Process organization]

The APK file When you as a developer develop an Android application, you end up creating the Android APK file which is capable of being installed and executed on Android. If you are familiar with other mobile development environments, this is pretty much analogous to sisx files on Symbian platform for example. It bundles execution-components, resources, meta-information describing application capabilities amongst other things.

Android application Build Process:

http://www.alittlemadness.com/2010/06/07/understanding-the-android-build-process/

Classes.dex This file is analogus to what you get as a JAR file in standard Java world. It is a collection of all the Java classes, compiled to appropriate byte-code, understandable by Dalvik-virtual machine, which will eventually run this code. Note that the byte-code is not compatible with Java’s JVM. So let us say you code defines two classes, A and B. Then Classes.dex will contain all the code spanning both the classes.

Resources.arsc If you are familiar with any development environments, be it desktop or mobile, you probably know how internationalization is achieved in an application. You export all your strings as a separate resource. This file is the binary that carries all your string resources. You define your string resources as an xml file using an Android specific structure, and the build tools translate them into a binary for memory efficiency purposes.

Copyright © Karan Khanna, Carnegie Mellon University, 2010 Page 17

res This directory is a collection of other resources such as icons, etc.

AndroidManifest.xml

As the name indicates, this is application’s Manifesto:

• It specifies what services the application is going to be using on Android – network, user-data, blue-tooth and so on.

• It also specifies what activities and services, the application provides, along with special information that allows Android to decide when to launch and run one or more components of your application.

• It determines which processes will host each of these components

• Permissions that others are required to have in order to communication with this application

Default APK process

By default, every APK is associated with one Linux process. All components included in that APK are executed in that one process, as and when required. In addition to the components that you develop and provide for you application, the process also gets the entire execution machinery required to execute those components. When discussing from a process perspective, we can think of all these components as run-time objects loaded in the memory of the process. The diagram above shows a minimal set of components, loaded into a process representing an Android application. We will discuss more about some of these next.

Bionic libc Bionic libc plays exactly the same role as any other version of libc on another platform – providing the basic C-runtime. C-runtime is often used to refer to a collection of library routines providing common system operations such as input and output, support to create environment for a C program to run, support to provide arithmetic operations that may be missing in the underlying hardware, but required by the code generated by the compiler and so forth.

Copyright © Karan Khanna, Carnegie Mellon University, 2010 Page 18

Android provides its own version of libc, which is not compatible with GNU libc, and also does not implement all the POSIX features. Consequently all native code must be compiled against this version of libc. There are several reasons for not using the standard libc on Android:

• Bionic libc is optimised for embedded use: faster and smaller (every process will have a copy of it).

• In case of Android, to best serve its business model, it was important to keep GPL out of user-space. Any software that uses GPL must also be available under GPL. GLIBC is available under GPL. Using a custom libc keeps the GPL out, and allows various OEMs that build Android devices to integrate their proprietary technology within the stack without necessarily having to make it public. For e.g., some OEM may want to use their graphics acceleration technology without making the code public.

• Adds support specific to Android such as some logging capabilities.

There are other important native libraries that may become part of your process, depending upon whether or not, your application needs them. Just to highlight the capabilities of Android, here is a listing of some of the more important native libraries:

• Media Framework

• SQLite

• WebKit

• OpenGLES

• SSL

Copyright © Karan Khanna, Carnegie Mellon University, 2010 Page 19

The reason to have these as native libraries is again to not to impede time performance because of the inherent disadvantages of executing in a higher level environment within a VM.

Dalvik Virtual Machine

DVM seems to be the real power-house that has made it possible to use Java programming language and the virtual machine model feasible on an embedded device such as smart phone. There are several aspects if the DVM design that are worth noting:

• To conserve memory: the DVM is compatible with a new executable file format called the DEX file, analogous to Java’s JAR file. An uncompressed DEX file as per Google’s benchmark data is about 50% of the corresponding JAR file for the same set of JAVA classes. Small DEX files mean that each process now occupies less RAM (as it loads its set of classes), and we maximize the number of processes that can be launched given a small amount of RAM that is available for processes after high level start-up (20-30 MB). Shared System libraries that are part of the managed code also then occupy 50% less memory, leaving more room for processes to execute. This becomes even more important as there is no swap-space.

• To improve execution speed: At install time, the dex file is subject to optimization, where-in, if possible, symbolic references are replaced by simple vtable offsets, and empty methods are removed

• Completely new byte-code format: The new byte-code is based on a register-machine model, which closely resembles the RISC architecture such as that of ARM, which is a popular platform in the Mobile segment. Closely mapping the execution model of VM to that of the actual underlying processor gives an execution speed benefit.

Android component

Up-to this point we’ve learnt that Android breaks the traditional single entry point paradigm, and introduces the notion of components, which the frame-work calls into, as and when required. These components are essentially Java objects, which provide implementations of the functions, that the Android application framework expects. Having said that, there are essentially four categories of such components:

Copyright © Karan Khanna, Carnegie Mellon University, 2010 Page 20

• Activities

• Services

• Broadcast receivers

• Content provider

ActivityThread object

This object basically manages execution of the main thread of an application’s process, scheduling and executing components of that application, based on requests sent by the activity manager service (this is a service provided by the framework, and we will visit is separately). These requests take the form of messages called Intents, which are again Java objects. The activity thread implements a message queue and an infinite loop that keeps reading messages from the queue as and when they are received. Each message is interpreted, and in-turn an appropriate action is taken – typically, a method implemented by one of the components of the application is executed. If the required component is not already loaded/ instantiated in the application process’s memory, it is loaded. Some peeking into the framework code reveals the following sequence of steps:

• Application process is created

• ActivityThread.Main() is called

• Some mysterious application registration with run-time environment takes place

• Main thread of the new process (represented as a Thread object) is registered with ActivityManager service.

• So that activity manager service can now run activities for this process

Copyright © Karan Khanna, Carnegie Mellon University, 2010 Page 21

• gets into infinite loop listening on a message queue, for messages from activity manager

• Calls component life-cycle methods on components that you define in your application

Communication between different components of same application, or across process boundaries is achieved essentially through asynchronous messages [again Java objects] called Intents. Often, Intents might be accompanied with additional data called Bundle [another Java object provided by the framework]. Both Intents and Bundles implement an Interface called Parcelable, because of which they are able to translate and save their state into something called a Parcel. A Parcel is essentially a C-Structure representation of the protocol, which is understood by the Binder driver. Binder driver is then able to forward this parcel to the destination process. Our green connector here represents the lowest level interaction with the binder, of sending and receiving parcels.

The next diagram explicitly shows interactions between an Android activity and the ActivityThread as already described above. The diagram only shows some of the lifecycle methods that are implemented by the activities.

Copyright © Karan Khanna, Carnegie Mellon University, 2010 Page 22

5. ANDROID MOBILE STACK ARCHITECTURE [DYNAMIC VIEW, 3RD LEVEL DECOMPOSITION, ANDROID COMPONENT: ACTIVITY]:

Copyright © Karan Khanna, Carnegie Mellon University, 2010 Page 23

6. ANDROID MOBILE STACK ARCHITECTURE [DYNAMIC VIEW, 2ND LEVEL DECOMPOSITION, APPLICATION FRAMEWORK COMPONENTS]:

Copyright © Karan Khanna, Carnegie Mellon University, 2010 Page 24

Component & item catalogue: Android mobile stack architecture [Dynamic view, 2nd level decomposition, Application framework processes]

Daemons

If you are familiar with Linux, you probably know what Linux daemons are. They are basically processes that run in background [do not typically have a front-end] and typically listen on a socket for incoming connections to the type of hardware service they are abstracting. In case of Android, after the kernel has started-up, the first thing Init process does is to launch these daemon processes that provide initial low-level access to things like USB connections, Radio Interface Layer, and so forth.

- usbd daemon manages USB connections, and keeps listening for incoming USB connections on a socket

- adbd manages Android Debug Bridge connections. Android Debug Bridge is a debugging facility provided to Android developers, which amongst other things, provides a remote shell log-in into the system.

- rild daemon manages all communications with Radio Interface Layer. This would include your 3G connections, Bluetooth connections and so on.

[/hardware/ril/rild/rild.c]

Zygote

This process is very specific to the design of Android application framework, and plays an important role. Zygote is a pre-warmed copy of Dalvik virtual machine – meaning, that in addition to Dalvik Virtual Machine, it also loads into its process memory a set of classes that is anticipated to be used more frequently by other applications and service. As of Android 1.5, this list includes around 1150 classes. After it is up and running, it sits on a socket listening for incoming requests to fork new processes. Whenever a new process/application request is received, a Linux fork is done, and a new process is

Copyright © Karan Khanna, Carnegie Mellon University, 2010 Page 25

created. This process keeps sharing all of its memory with the parent Zygote process, as long as it does not do a write on any of the shared data [copy-on-write]. This way, the memory footprint of the complete system is minimum at any given point in time. Typically, the new process will only have to load the new classes specific to the APK that it is associated with, and any non-shared data that it may allocate.

Another benefit is that now we do not do a cold start, and launch time for applications is also minimized.

List of classes loaded: [/frameworks/base/preloaded-classes]

Zygote: [???]

runtime process

This is the next process started-up after the Zygote is launched. Run-time process executes a C-program called ServiceManager. As we discover that Android application framework is essentially service oriented architecture, ServiceManager will essentially provide us the DNS-lookup kind of services. All services are registered with the service manager. Any application that may need to obtain services of a particular service must request a handle (also the proxy) to that service from the ServiceManager.

Once the run-time process has started the ServiceManager operations successfully, it sends a message [over socket] to Zygote to create the SystemServer process.

ServiceManager [/frameworks/base/cmds/servicemanager]

This is the first managed process in the system, and all of the core services of the Android platform live

Copyright © Karan Khanna, Carnegie Mellon University, 2010 Page 26

SystemServer

in this process. Each service that is started is also registered with the ServiceManger. Some of the services started are indicated in the diagram, and others have been omitted for simplicity.

[/frameworks/base/services/java/com/android/server/SystemServer.java]

ActivityManagerService

Amongst various other services, ActivityManagerService is an interesting one. It is responsible for managing each Android component’s life-cycle. The one interesting thing that it implements is the ‘back-stacks’ for user tasks. You will find a huge stress on the term “Task” being preferred over “application” at various points in Android’s documentation. They insist, that a Task is what an end user experiences as an application, and as far as application as a process/APK installed in system is concerned, a Task may span more than one application. Consider for e.g. that the user selects the browser in the home view. ActivityManager registers this as a new Task, and creates a stack for it. It creates and pushes the Browser activity into this stack. The while browsing, user clicks on an address which causes the maps activity to be launched and presented to the user. Activity manager pushes this activity on that same task stack. When the user hits back key on the phone, the maps activity is closed, and the next in the stack is launched at the same state where the user left it. All the activities live in the memory as long as there is no memory crunch. Where there is one, activities from a stack that was used last by the user may be removed from the memory.

[/frameworks/base/services/java/com/android/server/am/]

PowerManagerService

PowerManager service allows applications to participate in a more aggressive power management policy that is implemented using Android’s Power manager kernel module that we say earlier. The policy

Copyright © Karan Khanna, Carnegie Mellon University, 2010 Page 27

is that unless explicitly requested, various hardware modules including the CPU shall be put to sleep mode. Consequently, if an application such as Navigator requires that the LCD be run at its full brightness even if there is no touch activity from user, it must explicitly ask for it. PowerManagerService lets applications do this by introducing the concept of wakelocks. The relevant hardware module does not go into sleep mode between the time you acquire a wake lock and when you release it.

/frameworks/base/services/java/com/android/server/PowerManagerService.java

PackageManagerService

User applications typically do not use this service, but this service is important from the point of view of operation of the system. It is used by the activity manager to obtain information about the APK files installed on the system. Package manager maintains information about all the applications that are installed on the device, and what their capabilities are.

We had discussed a little about Intents earlier. Intent will typically be a constant saying something like: “start activity”, and a bundle that may have information on what activity to start. This information part can be very precise, and can be loose. For example, a precise version could say “Activity in XYZ.APK with MAIN intent”. When someone would have installed XYZ.APK, they would have indicated in its AndroidMainfest.xml that activity ABC is the MAIN activity that should be launched when user presses this APKs icon in the home view screen. A more loose version of an intent starting an activity could say start an activity that has an Intent QRS. The packageManagerService would then try to find if there is an activity that specifies such an Intent, and if found, ActivityManager would launch it.

/frameworks/base/services/java/com/android/server/PackageManagerService.java

Copyright © Karan Khanna, Carnegie Mellon University, 2010 Page 28

Other services

There are other services like WindowManager and so on, but we will not discuss them.

This connector as we already know represents user-space side interface for an operating system call. This specific instance represents that our process communicates with other processes via sockets API as provided by the operating system.

We have the Daemon processes listening on specific sockets for incoming connections/requests. We have Zygote process listening on incoming requests to fork new processes. System server is on the other end of this communication, with its components like the ActivityManager asking Zygote to launch a new process when they need to launch an activity whose process is not already running. Similarly, each time a new service is started-up in the SystemServer process, it gets registered with ServiceManager running in the runtime process.

The binder connector represents the relevant binder API used to negotiate IPC between processes. Here we are only concerned with native API, and any managed components access it indirectly via virtual machine’s native interface [JNI].

Applications almost always communicate with rest of the system through binder IPC. They use it to obtain handles to various services from the ServiceManager object. Then they make remote calls to services running in the SystemServer Process using Proxy objects.

Copyright © Karan Khanna, Carnegie Mellon University, 2010 Page 29

This connector represents the interface to power management API as provided by the Power manager module via kernel. PowerManagerService would interact with this API indirectly via JNI to accomplish wakelock requests.

Still exploring the real function of this component:

Here are some of the references:

Low memory killer:

[Why Linux default behavior might not be the best thing on a smart phone]

http://www.linuxjournal.com/article/8502

[Memory management approaches for swapless embedded systems]

http://delivery.acm.org/10.1145/1110000/1103152/8502.html?key1=1103152&key2=9699189721&coll

=GUIDE&dl=GUIDE&CFID=95698085&CFTOKEN=25750772

[What and why of a Linux OOM killer]

http://ubuntuforums.org/archive/index.php/t-617256.html

Copyright © Karan Khanna, Carnegie Mellon University, 2010 Page 30

7. ANDROID MOBILE STACK ARCHITECTURE [DYNAMIC VIEW, 2ND LEVEL DECOMPOSITION, APPLICATION FRAMEWORK START-UP SEQUENCE]:

Copyright © Karan Khanna, Carnegie Mellon University, 2010 Page 31

8. STRATEGIES AND TACTICS TO ACCOMPLISH VARIOUS ARCHITECTURAL DRIVERS:

SECURITY:

- Android application sand-box model: Android uses the process separation provided by Linux kernel as the primary means of achieving isolation amongst mutually suspicious applications. Each application runs in its own Linux process. Further, each managed piece of code executes under a virtual machine (DVM). As a result each application is sand-boxed from the other applications running at any given time. All IPC is routed via the mechanisms provided by Binder.

- A second level of isolation builds upon the capability of underlying Linux to strongly isolate data/files of one user from the other. This is achieved by allocating a unique user-id to each installed application on a particular system, and setting-up user permissions such that data created by one is not seen by others.

- There are additional access permissions defined for various hardware and software resources. E.g., access to GPS,

access to BATTERY, access to shared data like the Contacts list, etc. Applications are required to explicitly seek these permissions via their manifest files. This allows for the Application Installer (a tool that lets you install applications on the system) to create a list of resources the application intends to make use of, and show it to user, and have their consent to install it on system.

- Signed applications: All applications run by the Android application framework must be signed [self signing is enough].

The only reason self signing of applications exist is to establish mutual trust amongst application. Since Linux enforces security at a process level, code from two different packages cannot normally run in same process [since they are two different Linux users]. However, to have code from two applications run in same process, they are allowed to share the same user ID, by making an explicit indication in the manifest file, and the system entertains this request only when the two participating applications are signed by the same signature.

- Applications decide permissions for their data: An application can explicitly declare to have its data/files appropriate

global read/write permissions.

- Applications can create custom permissions: Custom permissions (applications can issue permissions for using their components, data etc.)

- Binder IPC driver: This is the only means of achieving IPC, and tries to address security holes in the conventional IPC.

<Probably need to dig through the source code to explore what this exactly means>

Copyright © Karan Khanna, Carnegie Mellon University, 2010 Page 32

- Native code subject to same security policy: Any native code that gets integrated via JNI is subject to same security paradigm as the managed code. This is because native code fits into the complete application paradigm via Dalvik virtual machine itself. So your application is still a Java application following the same model, but uses JNI to make calls to native code that you may want to embed into your application.

TIME PERFORMANCE:

- Most of the core libraries are native libraries: Most of the CPU intensive work of the framework is accomplished using native C/C++ libraries. Some of these are shown in the picture below:

- Native libraries for applications: As of the initial release, public libraries provided for application development are: o Bionic libc o libm

By public, it is meant that Android team is committed to preserve the public API between versions of Android. Native development has been used for example in the standard distribution for suggestive text-input, and Android features a really fine text input methods.

o A step further: these libraries have been custom written for an optimal embedded use: E.g., fast pthread implementation using 4-byte mutex rather than the 12-byte mutex [since not as many total threads are expect as are typical on a desktop environment]. There is no support for wide characters [Rely on UNICODE], and so forth.

- Activity manager: As we know Activity manager manages application and component life cycle. It tries to keep a launched application for as long as possible in memory, so in the event that the user may return to it, it is launched with minimal time overhead. Activity manager seems to work in conjunction with low memory killer, at-least on this regard.

Copyright © Karan Khanna, Carnegie Mellon University, 2010 Page 33

- Package manager: Maintains listing of various packages installed on the system, and their capabilities, so activity manager’s task of identifying the right component to launch is simplified and faster as compared to each time doing a scan on all installed APKs.

- Binder IPC driver: Since Android application framework is all about distributed components living in different

processes, it is crucial to be able to pass data back and forth between these components in a very time-efficient manner. Binder driver is the main facilitator of IPC and is claimed to perform highly optimized (for memory and time both) data transfers across process boundaries.

o It supports synchronous calls (with the semantics of call-return) across process boundaries. o It uses a very scaled down version of something like Java serialization for marshalling data, which is just good

enough for system level (processes running on the same system) IPC.

- DVM: A completely new virtual machine for optimal performance with typical ARM based mobile hardware. o Implemented as register based machine rather that a stack based machine for best performance on a RISC

architecture (ARM core). o Optimised bytecode o Uses fixed-width data structures so that parsing time is less

- Zygote: As we know, Zygote is a parent process with virtual machine and a set of libraries/classes that are expected to

be used by most applications, launch time of a new application that is not already in the memory is considerably reduced.

Copyright © Karan Khanna, Carnegie Mellon University, 2010 Page 34

EXTENSIBILITY:

- Application framework design: o We’ve already seen that the application framework on android is essentially about distributed components,

which mean a lot of flexibility in terms of how the framework can be configured and how new components can build on strengths of existing ones.

- Easy porting: Most mobile OEMs have the basic drivers to control their audio, video etc. Android defines a second hardware abstraction layer on top of kernel, and standardises Android’s interface to which the OEMs can implement their drivers to. This hardware abstraction layer exists as a user-space C/C++ library. This probably means that Android implements a standard interface for Audio, irrespective of the technology supported by the underlying hardware, just asking implementations of features that it needs from the particular hardware.

- Core system applications and services allow replacement of default core system applications by third party/ custom implementations.

- Codec extensions for audio and video: The media framework within the application framework supports a standard OpenMax IO Interface which supports codec plug-in. This allows adding any unsupported codec and replacing software codec implementation with hardware codec implementation.

- Possibility of using hardware acceleration, Open GL ES etc. for screen rendering

Copyright © Karan Khanna, Carnegie Mellon University, 2010 Page 35

BE OPEN SOURCE BUT KEEP GPL OUT OF USER SPACE:

- libc has been customized picking from various BSD versions and g-libc which comes with GPL licence has not been used.

- Standard codec are distributed under the Apache-2 licence. - User space drivers for OEMs (facilitated by the additional HAL layer that sits above the kernel) so that they can keep

them closed source if they want to.

LONG BATTERY LIFE:

- Power management policy with the concept of wake-locks, which is available to the applications through the PowerManagerService component introduced earlier, and which works in tandem with the power manager kernel module.

- Default service behaviour: By default, services that need to perform some intermittent activities like checking the network connectivity are only run when the system is already awake. This means, that even if that service is due for running and system is sleeping, it will keep doing so unless another activity or condition in the system wakes it up. Once the system is awake, the service takes the chance to execute. This is a good strategy, because it clubs together several services running on a system to cause a single system wake-up rather than all of them causing the system to wake up at random and asynchronous times, keeping it practically up at all times.

- Low battery notifications: Services can register for this notification, and can voluntarily decide to shut-down if the battery is low. For example, it would make sense to shut down email checking every 10 minutes, if the battery is running low, and be able to live to take calls until the phone dies!

- Battery meter: At-least with the 2.0 release and onwards, end users can see which applications cost the maximum

battery on their phone and can decide if they want those applications or not.

Copyright © Karan Khanna, Carnegie Mellon University, 2010 Page 36

FITTING SHORT MEMORY (RAM):

- Bionic libc: Has a small size: Approximately 200K, which is half the size of the glibc.

- Low memory killer: This is a special kernel module that kills the oldest application when no memory is left for an incoming application, based on a carefully designed heuristic.

- Zygote: Zygote uses a copy-on-write strategy to allocate memory to new applications. Until a write occurs, the data structures are shared with Zygote.

Copyright © Karan Khanna, Carnegie Mellon University, 2010 Page 37

9. REFERENCES

[R1] Google I/O 2009 – How do I code Thee? Let me count the ways

http://developer.android.com/videos/index.html#v=GARMe7Km_gk

[R2] Android Compatibility Definition Document

http://static.googleusercontent.com/external_content/untrusted_dlcp/source.android.com/en/us/compatibility/android-2.1-

cdd.pdf

[R3] Google I/O 2009 – Coding for life, Battery life, That Is

http://developer.android.com/videos/index.html#v=OUemfrKe65c

[R4] Andy Rubin’s interview snippet:

http://www.talkandroid.com/android-forums/android-hardware/2-android-minimum-hardware-requirements.html

[R5] Sample code, API reference, Introduction on application framework, and lot more:

http://developer.android.com

[R5] Very helpful insights into the application framework:

http://mylifewithandroid.blogspot.com

[R6] OpenBinder IPC mechanism:

http://www.angryredplanet.com/~hackbod/openbinder/docs/html/BinderIPCMechanism.html

[R7] Android applications build process:

http://www.alittlemadness.com/2010/06/07/understanding-the-android-build-process/