In this post we’ll look at Android Application architecture.
Here is the official Google introduction in the topic. Frankly, I find it not very helpful. It dives immediately in details of “how” without ever explaining “what” and “why”. So here is my version and I hope it may bring you a bit more clarity. However I strongly encourage you to read the Google article since it contains a lot of useful data which I’m not going to repeat in my blog.
Android OS architecture – a bit of history
As often in IT many things could not be explained unless one knows history of particular software. That’s why we need to take a brief look at Android OS history.
Initial development of Android OS has been started in 2003 by a startup company called Android Inc. The company was bought by Google in 2005. My guess is that main features on Android architecture were defined in that timeframe. And they were not just result of Android Inc work; Google architectural philosophy and financial resources definitely influenced Android architecture. I will give several examples later on.
Also if you remember 2003-2005 were years on AJAX applications boom. I think this had a substantial influence on Android application architecture: in many aspects it is closer to a typical AJAX application architecture than to any sort of desktop GUI application architecture based on Java or C# or C++ or VB etc.
I don’t know why it happened. My guess is it was brought by somebody from Google since Google folks at that time apparently thought that Rich Internet Applications would be a solution to all problems – think of Google docs or Gmail. Also I think it was neither particularly good or bad idea. Just keep in mind that it is very different from what you are used to if your background is desktop applications.
Also influence of Eclipse architectural philosophy is visible in choice of GUI implementation approach. It is closer to SWT than to Swing.
Interestingly, somebody with a decision making power came from Windows world as well J You can see it in Android code convention using fabulous MS-born “Hungarian notation”.
Android architectural layers
Android operational system has three distinctively different and very much separated architectural layers:
- Underneath it has a somewhat modified and stripped down version of Linux as I mentioned in one of my previous posts.
- On top of the Linux layer it has application infrastructure layer which consists of Dalvik Java virtual machine, web browser, SQLite database, certain infrastructure “plumbing” and Java APIs
- And, finally, a layer of Google-made Android applications. In a certain sense they are an extension to the application infrastructure layer since a developer working on Android application can use them or parts of them as building blocks for her own application
Let’s look at those layers one by one.
Imagine you are an architect of a startup company. You have to develop OS for a new type of devices. What would you do?
You have basically two choices: start from scratch and implement your own ideas or use some existing OS and adopt it for your device.
Implementing everything from scratch always sounds compelling for software developers. Somehow we all believe that this time we can do better than others did or ourselves did in the past.
However this is not always a very practical idea. For example, Linux kernel replacement cost estimate (probably somewhat inflated) suggests that if somebody decided to build a thing similar to Linux kernel as it is now, they would need several billion dollars to do this.
If you run Android Inc, you definitely don’t have such money. If you run Google, you have such money, but you would probably think twice before spending them on building custom OS nuts and bolts. Also you would need to spend several years until you get where e.g. Linux already is; several years of delay may make you critically late to the market.
In a similar situation Apple decided to build their Mac OS and iOS on Free BSD code base. Android Inc decided to use Linux as a base for Android. Both Free BSD and Linux codes are available free of charge and provide a robust foundation for building whatever Apple or Google needed.
However one could not just run a standard Linux on mobile devices at the time (although now it is possible). The devices had very little RAM and very little persistent memory. CPUs were very weak in comparison to CPUs available on computers where Linux was normally used. As a result Android developers had to minimize Linux footprint before using it.
If you look at Linux from a high level, it is a combination of Linux kernel (which is a“must have” part) and many other parts that are optional. Actually one can run Linux kernel on its own without anything else. So Google had to have Linux kernel as a part of Android anyway. Besides this they looked at other optional parts available and added those that they considered desirable. For example, they added IPTables (network firewall) and Ash shell. Noteworthy they added Ash shell and not Bash despite the latter is much more powerful; apparently the decision was made based on smaller Ash footprint.
Also Android developers have had to modify Linux kernel so that to add support for hardware that is used by mobile devices and which is not typically available on computers. You can find more about this here.
Overall, choosing Linux as a foundation for Android made a huge impact on all aspects of Android OS. Its build is essentially a version of Linux build process. Its code is managed by git (a tool developed for managing Linux code). And so on.
While all this is interesting, if your goal is just to develop Android application, you probably won’t even touch all this Linux stuff ever (with exception of browsing Android filesystem with Ash commands). Most you need to know about Android while developing an application is Android application infrastructure layer.
You may ask what if you want to develop a native application for Android anyway. This is strictly discouraged by Google. Technically you can do this, but you won’t be able to distribute your code through normal channels. So think twice before you start doing native development on Android unless you are working on Android Open Source Project (AOSP), i.e. Android OS itself.
Application infrastructure layer
While there is a lot of similarity between how foundational parts of Apple iOS and Android OS were created, there is a striking difference between architectural decisions on Application infrastructure layer made by architects of both OS.
Apple decided to use Objective C as a programming language and a runtime for iOS applications. Objective C looks like more or less natural choice for OS built on Free BSD foundation. One can think of Objective C as a generic C++ with a custom preprocessor that adds certain linguistical constructs. Somebody may wonder why they didn’t use just straight C which Free BSD is written in? I guess this is because Apple tends to do everything in their special”Apple” way. You can read more about this here.
The bottom line is that iOS applications are written more or less in the same language as the underlying OS.
Android applications are strikingly different in this aspect. They are written in Java which is very different technology than C++ (although with its syntax derived from C++).
Why it is so? Why e.g. Android applications are not written in C++? I could not find Google explanation on this, so I can just offer my own guess.
I think the main reason was a need to make the same application binaries working without changes across multitude of hardware. This is a special problem that Android OS architects had to deal with; Apple folks did not have this problem at all. iOS runs only on Apple-built hardware and Apple is in a complete control of it. For Android opposite is true: Google does not control hardware manufacturers. For example Android OS has to run on CPUs with x86, ARM and Atom architectures. Those architectures are incompatible at binary level.
If Android OS architects had chosen the same approach as Apple architects, Android application developers would need to build and distribute their apps in several binary versions simultaneously. This could be a huge problem which potentially could make the whole Android OS project a failure.
To make the same application binaries working across different hardware Google had to use a container-based architecture for their applications. In container-based architecture binaries are executed by a software container which isolates them from details of particular hardware the binaries are running on. Examples are Java and C#. In both languages binaries do not depend on a particular hardware and they are executed by virtual machines.
Well, there are other ways to achieve independence from hardware at binary level. For example one can use a hardware emulator e.g. well known QEMU. It allows emulating e.g. a device with ARM CPU on x86 platform and so on. Google could use C++ as an application development language and run those applications inside hardware emulators. Actually, Google uses such approach in their Android emulator which is built on top of QEMU.
The most likely they did not take hardware emulator route since in this case one has to run OS on the emulator as well which makes emulation scope much bigger and as the result the execution becomes much slower. To achieve faster execution one has to limit emulation to only parts where it could not be avoided, which in our case is Android application.
Whatever Google thinking process was they decided to use Java as a primary application development language and runtime.
I think this was a critical architectural decision which made Android standing out of a bunch of other competing Linux-derived mobile OSs that have been evolving at the time. Neither of them as far as I know offers binary portability at application level. Look e.g. at MeeGo. It uses C++ and QT framework; although QT framework is multi-platform one still has to have separate binaries built for each platform.
After deciding on Java they had to decide what Java virtual machine (JVM) to use. They could not use a standard JVM due to resource constrains. One possible choice was to use Java ME JVM developed for mobile devices. However Google was not completely happy with Java ME and they decided to develop their own version of JVM, so-called Dalvik JVM.
Dalvik JVM differs from other JVMs in following aspects:
- It uses special DEX format for storing applications binaries vs. JAR and Pack200 formats used by standard Java virtual machines. Google claims that DEX results in smaller binaries than JAR. I think they could use Pack200 with the same success, but they decided to go their own way in this aspect
- Dalvik JVM was optimized for running multiple JVM processes simultaneously
- Dalvik JVM uses refister-based architecture vs. stack based architecture of other JVMs with intent to speed up the execution and to reduce binaries size
- It uses its own instructions set (not a standard JVM bytecode)
- One can run (if needed) several independent Android applications within a single JVM process
- Application execution can span across several Dalvik JVM processes “naturally”(we’ll discuss what this means later). To support this it adds:
- Special object serialization mechanism based on Parcel and Parcelable classes. Functionally it serves the same purpose as standard Java Serializable, but results in smaller data footprint and potentially it is more lenient towards differences in versions of classes
- Special Android way to execute inter process calls (IPC) based on Android Interface Definition Language (AIDL)
- Until Android 2.2 Dalvik JVM did not support JIT compilation which adversely impacted Android application performance. Adding it in 2.2 improves markedly execution speed for often used applications
Google folks revised standard Java JDK API packages as well. They removed some of the packages (e.g. everything related to Swing) and added a number of their own packages with names starting from “android”.
They also added certain open source packages that are not a part of a standard JDK. For example they added Bouncy Castle crypto API, HTTPClient which supports client-side portion of HTTP/HTTPS protocol.
This is all for today. We’ll look at Android application architecture proper in the next posts.