AOSP.dev — 1: What lies beyond the app?
The Developer Experience
We have become so accustomed to looking at our smartphones as ‘containers for apps’, that we tend to forget (and take for granted) the underlying complexity of this little shiny box. Even as app developers, we usually don’t tend to think beyond the Android SDK. Not because we don’t want to, but rather because there is a brilliant team behind the AOSP that does so much thinking for us that we don’t have to.
All of this factors into the Android vision of the developer experience. The common app developer will have no need to interact with elements other than the ones provided by the SDK (and maybe even NDK). He just needs a guarantee, a contract with the system if you will, that the functionality provided by the SDK will do exactly what it’s designed to do, and will take care of all background operations for him.
So how can the system guarantee this contract amongst the fragmentation of API’s, platforms, architectures & chipsets? One of the main contributors to this is the Compatibility Test Suite (better known under its abbreviation as CTS). CTS is a test suite compromised of several unit tests that will run these tests on a live device or emulator, targeting areas such as: platform API’s, API signatures, permissions, etc. just to name a few. Aside from CTS, there are also frameworks such as the Trade Federation which contains packages such as the Vendor Test Suite.
Fragmentation is far too big of a topic to handle in this article alone, and will be saved for a later one.
The Android Core
As most of you probably already know, Android contains a Linux kernel at its very core. This was a pragmatic design choice made mainly due to the maturity and familiarity of the Linux kernel, which would allow the Android software stack to make use of its key security features and facilitate writing device drivers.
Note that I said software stack and not operating system previously, as it is mentioned this way in the main article. This StackOverflow answer explains the difference between both pretty well, but software stack seems to be such a niche term that it might cause more confusion instead of clarity as opposed to OS.
One of the things you might not know, is that Android is actually not considered fully POSIX-compliant due to it’s use of Bionic as a replacement for glibc. This choice was mainly political/commercial in nature to avoid the GPL/LGPL license, as well as pragmatic in the sense of Bionic being both smaller and a better fit for slower CPU’s.
Hardware Abstraction Layer (HAL)
A HAL module is a driver-agnostic implementation of a standard interface defined by Android. This allows Android to abstract away from device-specific details and use the same interface across different devices. Due to this uniform interface, Android can be equipped with a high-level Java API to access hardware capabilities (audio, camera, …). This usually happens by implementing a JNI-interface.
Every Android image contains several HAL modules residing either within /system/lib/hw/ for default (and sometimes device specific) ones, and usually /vendor/lib/hw/ for device specific ones. These come in the shape of C/C++ shared libraries (.so). Note that 64-bit devices (also) have modules in lib64 instead of lib.
ART & Dalvik
ART is the Android runtime that’s been implemented since Lollipop (5.0) and is the successor to the Dalvik runtime. It provides some new features such as Ahead-of-Time (AOT) compilation, which will basically compile the bytecode that’s normally executed on a virtual machine, into native machine code for the target device. This will of course result in (much) better performance & less power consumption. The process happens using the dex2oat utility which will convert the original dex file into an ELF executable. Other mentioned improvements are improved garbage collection & more debugging features.
A separate instance of ART/Dalvik (virtual machine) will be ran per app, and these instances are called Application Sandboxes. This means enhanced security considering apps won’t be able to access each others memory and upon crashing, only that particular instance will be killed. From a Linux point-of-view, this means that every application will have it’s own UID along with a restricted set of permissions.
From Android 7.0 onwards, there’s been a complementary Just-in-Time (JIT) compiler added to the AOT compiler. The JIT will do run-time profiling and optimisations of the app while you use it, which results in further improved performance and faster updates.
The native libraries are sometimes also better known as the Native Development Kit (NDK). These are the libraries that can be used either when developing native applications (C/C++) on Android, and sometimes they’re also accessed through a Java wrapper (f.e. OpenGL ES, Camera2, …).
Despite that Android advises to use Java as much as possible (and you should try to do so!), there are some cases when Java just doesn’t cut it (yet). One example are applications which have real-time requirements (low latency audio for example) where Java can’t compare in terms of performance. In this case you could resort to using the available OpenSL ES implementation within the NDK, or if I may advise, take a look at the SuperPowered SDK which has built a feature rich high-performance wrapper around it.
The NDK also features several C++ runtime libraries from different vendors, such as GNU, LLVM, STLport, … By default, a static version of the GNU STL will be used unless specified differently. Important to note is that there is an exclusion in the GPL license for statically linking the GNU STL, so there is no need to apply the GPL license for proprietary builds linked with this runtime.
Android Java API Framework
This part of the Android OS is probably the part you’ve come in touch with the most, and they form the basic building blocks when you’re making an app. The frameworks can also change depending on the Android API version you’re on, as they are a part of the Android SDK.
The Android documentation regards these 5 elements to be the most important ones:
A rich and extensible View System you can use to build an app’s UI, including lists, grids, text boxes, buttons, and even an embeddable web browser
A Resource Manager, providing access to non-code resources such as localized strings, graphics, and layout files
A Notification Manager that enables all apps to display custom alerts in the status bar
Content Providers that enable apps to access data from other apps, such as the Contacts app, or to share their own data
Android Core / System Apps
Last but not least, we’ll discuss the apps which are embedded into the OS, and are the first (and likely only) layer of interaction with end users. As opposed to what many people believe, the Google Mobile Services (GMS) is not a stock part of Android but can be attained by contacting Google through a form on the Android website.
This means that once you build an image for a device using the available AOSP, it will not contain any of the apps which are a part of GMS (Youtube, Play Store, Google Music, Google Maps, …).
There is not a lot of clarity on how the procedure to acquire GMS looks like and what the potential hidden cost is (the GMS is marketed as being “free” though), but you might find more information in regards to this procedure here. An alternative to the GMS (for personal use!) can be found in the form of Open GApps. Do take note of the following:
Take note that Open GApps does not provide you with any license for Google’s APKs included in the package. The Open GApps packages merely provide a convenient way to sideload APKs to your device. It is your own responsibility to obtain the proper permissions by e.g. buying an OHA-licensed device with pre-installed Google Apps and/or acquiring the applications from Google’s Play Store.
The apps that you do get on your device image from the AOSP, are the Android Core apps. These are apps such as: Calculator, Camera, Gallery, Phone, Settings, … There is no guarantee / steady maintenance track that the apps will work out-of-the-box. For example, while building the 7.1.1_r10 branch for Nexus 6P, I noticed that the Music app crashes upon launch.
One of the main things about System Apps is that they’re embedded into the image and you can’t remove them from the device. This is a very interesting feature when making your own device images from both a security as a commercial perspective. They also have access to certain areas in the file system as well as some protected native API’s.
This wraps up our Android OS crash course. If you’re still hungry for more knowledge, your best starting point would be the Android Source website. Should you have any questions left in regards to what is discussed here, feel free to leave a comment below.