This book is about Android system programming. In this chapter, we will start with a discussion on system programming and the scope of Android system programming (to give a high-level view of this book). After that, we will look at the Android system architecture. From the architecture, we can see the layers that we will focus on in this book. We will also talk about the virtual hardware platforms and third-party open source projects that we will use in this book. In summary, we will cover the following topics in this chapter:
- Introduction to Android system programming
- Overview of the Android system architecture
- Introduction to the third-party projects used in this book
- Introduction to virtual hardware platforms
When we talk about what system programming is, we can start with the definition of system programming in Wikipedia:
"System programming (or systems programming) is the activity of programming system software. The primary distinguishing characteristic of systems programming when compared to application programming is that application programming aims to produce software which provides services to the user (e.g. word processor), whereas systems programming aims to produce software and software platforms which provide services to other software, are performance constrained, or both (e.g. operating systems, computational science applications, game engines and AAA video games, industrial automation, and software as a service applications). "
From the preceding definition, we can see that when we talk about system programming we actually deal with the building blocks of the computer system itself. We may depict the system architecture and how it looks like inside the system. As an example, we can refer to system programming books for Windows or Linux. The book Linux System Programming published by O'Reilly Media, Inc. includes topics about file I/O, process management, memory management, interrupt handling, and so on. There is another book called Windows System Programming published by Addison-Wesley Professional that includes very similar topics to its Linux counterpart.
You may expect similar content in this book for Android, but you will find that the topics in this book are quite different from the classic system programming book. First of all, it doesn't really make sense to have a system programming book for Android talk about file I/O, process management, or memory management, because the Linux System Programming book can cover almost the same topics for Android (Android uses Linux kernels and device driver models).
When you want to explore kernel space system programming, you can read books such as Linux Device Drivers by O'Reilly or Essential Linux Device Drivers from Prentice Hall. When you want to explore user space system programming, you can read the book that I mentioned before, Linux System Programming by O'Reilly. Then you may wonder, Do we need an Android System Programming book in this case? To answer this question, it depends on how we look at system programming for Android. Or in other words, it depends on which angle we look at Android System Programming from. We can tell people different things about the same world from different perspectives. In that sense, we may need more than one book to talk about Android system programming.
To talk about Android system programming, we can talk about it theoretically or practically. In this book, we will do it practically with a few actual projects and hands-on examples. Our focus will be how to customize the Android system and how to port it to a new platform.
As we know, there are two kinds of programming for Android: application programming and system programming.
Usually, it is hard to draw a line between system programming and application programming, especially for C language-based operating systems, such as Linux and all kinds of Unix system. With the Android framework, the application layer is separated nicely from the rest of the system. You may know that Android application programming uses the Java language and Android system programming using Java, C/C++, or assembly languages. To make it simple, we can treat everything other than application programming in the Android world as the scope of system programming. In this sense, the Android framework is also in the scope of system programming.
From the perspective of the audiences of this book, they may want to learn more about the layers they may touch on in their project work. The Android framework is a layer that will be changed by Google only in most cases. From this point of view, we won't spend too much time talking about the framework itself. Instead, we will focus on how to port the system including the Android framework from the standard platforms in Android Open Source Project (AOSP) to other platforms. We will focus on the layers that need to be changed during the porting process in this book.
After we have done the porting work, a new Android system will be available. One thing that we need to do for the new system is deliver the changes for the new system to the end users from time to time. It could be a major system update or bug fixing. This is supported by over-the-air (OTA) updates in Android. This is also one of the topics in this book.
Traditionally, all Unix programming was system-level programming. Unix or Linux programming is built around three cornerstones, which are system calls, the C library, and the C compiler. This is true for Android system programming as well. On top of the system calls and C library, Android has an additional layer of abstraction for the Android application level. This is the Android framework and Java virtual machine.
In that sense, most Android applications are built using Android SDK and Java language. You may be wondering whether it is possible to do Android application development using C/C++ or even do system level programming using Java. Yes, all these are possible. Besides Android SDK, we can also develop native applications using Android NDK. There are also a lot of Android framework components developed using the Java language. We can even develop Android applications using C# with Visual Studio (Xamarin). However, we won't go to that kind of complexity in this book. We will focus on the layers below the application framework. Again, the focus will be on customizing and extending the existing system or porting the entire system to a new hardware platform.
The reason why we will focus on the porting of Android systems and the customization of Android systems is because these are what most people working on the Android system level will do. After Google releases a new version of Android, silicon vendors need to port the new version to their reference platform. When OEM/ODM companies get the reference platform, they have to customize the reference platform to their products. The customization includes the build of the initial system itself and the deployment of the updates to the deployed system. In the first part of this book, we will discuss the porting of Android systems. In the second part of this book, we will discuss how to update the existing system.
If we consider the architecture of Android in the right-hand side of the following figure, we can see that most porting work will focus on the Kernel and Hardware Abstraction Layer (HAL) in the Android system architecture. This is true for other Android derivatives as well. The knowledge and concepts in this book can apply to Android wearables and Brillo as well. The left-hand side of the following figure, it shows the architecture diagram of Brillo. Brillo is the IoT operating system from Google for IoT devices. It is a simpler and smaller version of Android for IoT devices. However, the porting layer is still the same as Android.
Comparison of Android and Brillo system architecture
As we can see from the architecture diagram, the architecture layers of Android include Application Framework, Android System Services, HAL, and Kernel. Binder IPC is used as a mechanism for inter-process communication. We will cover each of them in this section. Since recovery is also part of the system programming scope, we will also give an overview of recovery in this section.
You can find more information about key porting layers and system architecture internals at the following Google website:http://source.android.com/devices/index.html
As we know, Android uses the Linux kernel. Linux was developed by Linus Torvalds in 1991. The current Linux kernel is maintained by the Linux Kernel Organization Inc. The latest mainline kernel releases can be found at https://www.kernel.org.
Android uses a slightly customized Linux kernel. The following is a concise list of the changes to the Linux kernel:
- ashmem (Android Shared Memory): A file-based shared memory system to user space
- Binder: An interprocess communication (IPC) and remote procedure call (RPC) system
- logger: A high-speed in-kernel logging mechanism optimized for writes
- paranoid networking: A mechanism to restrict network I/O to certain processes
- pmem (physical memory): A driver for mapping large chunks of physical memory into user space
- Viking Killer: A replacement OOM killer that implements Android's "kill least recently used process" logic under low-memory conditions
- wakelocks: Android's unique power management solution, in which the default state of the device is sleep and explicit action is required (via a wakelock) to prevent that
Most of the changes were implemented as device drivers with little or no changes necessary to the core kernel code. The only significant subsystem-spanning change is wakelocks.
There are many Android patches accepted by the mainline Linux kernel today. The mainline kernel can even boot up Android directly. There is a blog from Linaro about how to boot Nexus 7 running a mainline kernel. If you want to try it, you can find the instructions at https://wiki.linaro.org/LMG/Kernel/FormFactorEnablement.
If a Linux device driver is available for a hardware device, it usually can work on Android as well. The development of device drivers is the same as the development of a typical Linux device driver. If you want to find out the merges on the mainline kernel related to Android, you can check the kernel release notes at https://kernelnewbies.org/LinuxVersions.
The Android kernel source code is usually provided by SoC vendors, such as Qualcomm or MTK. The kernel source code for Google devices can be found at https://android.googlesource.com/kernel/.
Google devices use SoC from various vendors so that you can find kernel source code from different vendors here. For example, the kernel source of QualComm SoC is under
kernel/msm and the kernel source of Mediatek is under
kernel/mediatek. The general Android kernel source code is in the folder
kernel/common, which looks much like the Vanilla kernel.
The default build of AOSP is for various devices from Google, such as Nexus or Pixel. It started to include some reference boards from silicon vendors as well recently, such as
hikey-linaro, and so on. If you need a vendor-specific Android kernel for your reference platform, you should get the kernel source code from your platform vendors.
There are also open source communities maintaining Android kernels. For example, the kernel for the ARM architecture can be found at Linaro for many reference boards. For Intel x86 architecture, you can find various versions of kernels in the Android-x86 project. As you can see from the following Linaro Linux Kernel status website, the
linaro-android tree is a forward port of the out-of-tree AOSP patches. It provides a preview of what Google's next AOSP
kernel/common.git tree "might" look like.
The Linaro Android kernel tree can be found at https://android.git.linaro.org/gitweb/kernel/linaro-android.git.The status of this kernel tree can be seen at https://wiki.linaro.org/LMG/Kernel/Upstreaming.
HAL defines a standard interface for hardware vendors to implement and allows Android to be agnostic about lower-level driver implementations. HAL allows you to implement functionality without affecting or modifying the higher level system. HAL implementations are packaged into module (
.so) files and loaded by the Android system at the appropriate time. This is one of the focuses for porting Android systems to a new platform. We will discover more about HAL in Chapter 3, Discovering Kernel, HAL, and Virtual Hardware. Throughout this book, I will give a very detailed analysis of the HAL layer for various hardware interfaces.
Functionality exposed by application framework APIs communicates with system services to access the underlying hardware. There are two groups of services that application developers may interact mostly with. They are system (services such as window manager and notification manager) and media (services involved in playing and recording media). These are the services that provide application interfaces as part of the Android framework.
Besides these services, there are also native services supporting these system services, such as SurfaceFlinger, netd, logcatd, rild, and so on. Many of them are very similar to Linux daemons that you may find in a Linux distribution. In a complicated hardware module, such as graphic, both system services and native services need to access HAL in order to provide the framework API to the application layer. We will talk about system services when we debug the init process in Chapter 6, Enabling Wi-Fi on the Android Emulator to Chapter 9, Booting Up x86vbox Using PXE/NFS.
The Binder IPC mechanism allows the application framework to cross process boundaries and call into the Android system services code. This enables high-level framework APIs to interact with Android system services. An Android application usually runs in its own process space. It doesn't have the ability to access system resources or the underlying hardware directly. It has to talk to system services through Binder IPC to access the system resource. Since applications and system services run in different processes, the Binder IPC provides a mechanism for this purpose.
The Binder IPC proxies are the channel by which the application framework can access system services in different process spaces. It does not mean it is a layer between the application framework and system services. Binder IPC is the inter-process communication mechanism that can be used by any process that wants to talk to another process. For example, system services can use Binder IPC to talk to each other as well.
The application framework provides APIs to the applications. It is used most often by application developers. After an interface is invoked by the applications, application frameworks talk to the system services through the Binder IPC mechanism. An Android application framework is not just a set of libraries for the application developers to use. It provides much more than that.
The break-through technology that the Android application framework brought to the developer community is a very nice separation between application layers and system layers. As we know Android application development uses the Java language and Android applications run in an environment similar to the Java virtual machine. In this kind of setup, the application layer is separated from the system layer very clearly.
The Android application framework also provides a unique programming model together with a tight integration with the integrated development environment (IDE) from Google. With this programming model and related tools, Android developers can work on application development with great efficiency and productivity. All these are key reasons why Android has gained so much traction in the mobile device world.
I have given an overall introduction to all the layers in the previous Android system architecture diagram. As I mentioned about the scope of Android system programming before, we can consider all programming in Android systems as within the scope of system programming other than application programming. With this concept in mind, we actually missed one piece in the previous architecture diagram, which is recovery.
In this chapter, we want to have a brief look at recovery as well, since we have three chapters about it in the second part of this book.
Recovery is a tool that can be used to upgrade or reinstall Android systems. It is part of the AOSP source code. The source code for recovery can be found at
The unique point about recovery compared to the other parts of Android is that it is a self-contained system by itself. We can look at recovery using the following diagram, and compare it to the Android and Brillo architectures that we talked about before:
Recovery is a separate system from Android that shares the same kernel with the Android system that it supports. We can treat it as a mini operating system or an embedded application that we can find in many embedded devices. It is a dedicated application running on top of the same Linux kernel as Android and it performs a single task, which is to update the current Android system.
When the system boots to recovery mode, it boots from a dedicated partition in the flash. This partition includes the recovery image that includes a Linux kernel and a special ramdisk image. If we look at Nexus 5 partitions, we will see the following list:
# parted /dev/block/mmcblk0 parted /dev/block/mmcblk0 GNU Parted 22.214.171.124.179-aef3 Using /dev/block/mmcblk0 Welcome to GNU Parted! Type 'help' to view a list of commands. (parted) print print print Model: MMC SEM32G (sd/mmc) Disk /dev/block/mmcblk0: 31.3GB Sector size (logical/physical): 512B/512B Partition Table: gpt Number Start End Size File system Name Flags 1 524kB 67.6MB 67.1MB fat16 modem 2 67.6MB 68.7MB 1049kB sbl1 3 68.7MB 69.2MB 524kB rpm 4 69.2MB 69.7MB 524kB tz 5 69.7MB 70.3MB 524kB sdi 6 70.3MB 70.8MB 524kB aboot 7 70.8MB 72.9MB 2097kB pad 8 72.9MB 73.9MB 1049kB sbl1b 9 73.9MB 74.4MB 524kB tzb 10 74.4MB 75.0MB 524kB rpmb 11 75.0MB 75.5MB 524kB abootb 12 75.5MB 78.6MB 3146kB modemst1 13 78.6MB 81.8MB 3146kB modemst2 14 81.8MB 82.3MB 524kB metadata 15 82.3MB 99.1MB 16.8MB misc 16 99.1MB 116MB 16.8MB ext4 persist 17 116MB 119MB 3146kB imgdata 18 119MB 142MB 23.1MB laf 19 142MB 165MB 23.1MB boot 20 165MB 188MB 23.1MB recovery 21 188MB 191MB 3146kB fsg 22 191MB 192MB 524kB fsc 23 192MB 192MB 524kB ssd 24 192MB 193MB 524kB DDR 25 193MB 1267MB 1074MB ext4 system 26 1267MB 1298MB 31.5MB crypto 27 1298MB 2032MB 734MB ext4 cache 28 2032MB 31.3GB 29.2GB ext4 userdata 29 31.3GB 31.3GB 5632B grow
The list includes 29 partitions and recovery partition is one of them. The recovery ramdisk of recovery, it has a similar directory structure to the normal ramdisk. In the init script of recovery ramdisk, init starts the recovery program and it is the main process of the recovery mode. The recovery itself is the same as other native daemons in the Android system. The programming for recovery is part of the scope of Android system programming. The programming language and debug method for recovery is also the same as native Android applications. We will discuss this in more depth in the second part of this book.
As we know, AOSP source code is the major source that we can start to work with in system-level programming. Various silicon vendors usually work with Google to enable their reference platforms. This is a huge effort and they won't publish everything to the world except for their customers. This brings a limitation to the open source world. Since the AOSP source code is mainly for Google devices, such as emulator, Nexus, or Pixel series, there is no problem for developers who use Nexus devices as hardware reference platforms. How about other devices? Manufacturers may release the kernel source code for their devices, but nothing else. In the open source world, several third-party organizations provide solutions for this situation. We will have a brief look at the ones that we used in this book in the following sections.
LineageOS is a community providing aftermarket firmware distribution for many popular Android devices. It is the successor to the highly popular CyanogenMod. If you cannot build the ROM for your devices from AOSP source code, you may look at LineageOS source code. Because there are many devices supported by LineageOS, many major third-party ROM images are built on top of its predecessor CyanogenMod. From the famous MIUI in China to the latest OnePlus device, they all use CyanogenMod source code as the base start from. The major contributions of LineageOS/CyanogenMod to the open source world are the adaptation of the Linux kernel and HAL to various Android devices.
The source code of LineageOS is maintained in GitHub and you can find it at https://github.com/LineageOS.
To build LineageOS source code for your device, the overall build process is similar to the AOSP build. The key difference is the large number of devices supported by LineageOS. For each device, there is a web page to give information about how to build for a device. We use Nexus 5 as an example. You can go to the following page for detailed information:
In the information page, you can find information about how to download the ROM image, how to install the image, and how to build the image. There is a build guide for devices and we can find the build guide for Nexus 5 at https://wiki.lineageos.org/devices/hammerhead/build.
To build LineageOS for Nexus 5, the two key elements are Kernel and Device. The Kernel includes the Linux kernel and Nexus 5-specific device drivers, while the Device includes the major part of the device-specific HAL code. The naming convention for both the Kernel and Device folder is
The code name for Nexus 5 is hammerhead and the manufacturer is lge, which is LG.
We can find the following two Git repositories for Kernel and Device:https://github.com/LineageOS/android_kernel_lge_hammerheadhttps://github.com/LineageOS/android_device_lge_hammerhead
Other than the Kernel and Device, other important information is the LineageOS version. You may find it on the same device information page. For Nexus 5, the versions that can be used are 11, 12, 12.1, 13, and 14.1. You may be wondering how to match LineageOS versions to AOSP versions.
The information can be found at the following two pages at Wikipedia about CyanogenMod and LineageOS:https://en.wikipedia.org/wiki/CyanogenMod#Version_historyhttps://en.wikipedia.org/wiki/LineageOS#Version_history
The LineageOS/CyanogenMod and AOSP versions supported for Nexus 5 are CM11 (Android 4.4), CM 12 (Android 5.0), CM 12.1 (Android 5.1), CM 13 (Android 6.0), and CM 14.1 (Android 7.1.1).
You will not be able to access the links related to CyanogenMod while you read this book, since the infrastructure behind CyanogenMod has been shut down recently. You can read the following post to find out more:https://plus.google.com/+CyanogenMod/posts/RYBfQ9rTjEH
Nevertheless, the idea from the preceding configuration is that the key pieces of code to differentiate one device from another are the Kernel and Device. It is possible to share the rest of the code across devices. This is one of the goals for the projects in this book. We try to keep the changes for different hardware platforms within the Kernel and the Device, while keeping the rest of the AOSP source code untouched. This is not 100% possible, but we can try to do it as much as possible. The benefit is that we can keep our code separated from AOSP code and it is much easier to update to a new AOSP version.
While LineageOS/CyanogenMod provides excellent support for a large number of Android devices, many of these devices are ARM-based devices from various silicon vendors, such as Qualcomm, Samsung, MTK, and so on. Similarly, there is an open source community for Intel-based Android devices as well. This is another famous open source project, Android-x86. Even though the number of Intel x86-based Android devices on the market cannot compare to the number of ARM-based devices, there is another market using the Intel x86 Android build extensively. This is the Android emulator market. For commercial Android emulator products, you can find AMI DuOS, Genymotion, Andy, and so on.
The project Android-x86 uses a very different approach to support various Intel x86-based devices compared to LineageOS/CyanogenMod. Its goal is to provide Board Support Package (BSP) for any Intel x86 devices. It is similar to how you install Microsoft Windows or Linux on your PC. You have only one copy of the release and you can install it on any Intel PCs. There is no special build of Windows or Linux for each different PC or laptop.
To achieve this goal on Android, Android-x86 customized the Android boot up process significantly. There are two stages of boot up process in Android-x86. The first stage is booting up a minimal Linux environment using a special ramdisk--
initrd.img. After the system can boot up to this Linux environment, it starts the second stage through the
switch_root command. In this stage, it will boot up the actual Android system.
This is a very smart way to resolve the new challenge using existing technology. Essentially, we try to resolve the problem in two steps. In the first stage of the boot up process, since both Windows and Linux can boot on Intel x86 PCs without a dedicated build, you should be able to boot Linux on an Intel device without too much effort. This is exactly what the first stage of Android-x86 boot up does. After the minimal Linux system can run properly, this means the minimum set of hardware devices is initialized and you are able to debug or boot the rest of the system using this minimal Linux environment. In the second stage, a common Android image for Intel x86 can be started with limited hardware initialization. This approach can be used in the debugging of hardware devices as well. We will show how we can do the same thing on the Android emulator in this book.
The official website of the Android-x86 project is http://www.android-x86.org/. You can find the information about the Android-x86 project there. To build Android-x86, it is a little tricky to get the source code. The original source code was hosted at
http://git.android-x86.org and it was maintained by volunteers from Taiwan Linux User Group (TLUG). It was valid for several years. However, it ceased to work from April 2015.
You can always find the latest status from the Google discussion group at https://groups.google.com/forum/#!forum/android-x86. There is an official announcement about the issue of
git.android-x86.org at the discussion group from the maintainer Chih-Wei Huang. Later, the hosting was moved to SourceForge for a short period. However, issues retrieving source code from SourceForge have been reported again since July 2016. Currently, the source code is hosted at OSDN and you can search the announcement from Chih-Wei Huang on September 8, 2016 at the Android-x86 discussion group. Since most open source projects are maintained by volunteers, they may be up and down from time to time. It is always good to keep your own mirror of the projects that you work on. We will discuss this issue in this book as well so that you can have full control of your own work.
We know that many open source projects are related to each other and this is true for both Android-x86 and LineageOS/CyanogenMod as well. Starting from January 2016, Jaap Jan Meijer did the initial porting of CyanogenMod to Android-x86 and this makes CyanogenMod available on most Intel devices. If you are interested in this topic, you can search for
CM porting plan in the Android-x86 discussion group.
As a part of system-level programming, we introduced recovery in the previous section. The original recovery from AOSP only supports very limited functionalities so there are many third-party recovery projects.
ClockworkMod recovery (CWM) is one of the famous open source recovery projects, written by Koushik Dutta. Even though many people still use ClockworkMod recovery now, this project ceased development some time ago.
Another recovery project is CyanogenMod recovery (CMR). CMR is maintained by the CyanogenMod team and it is quite similar to ClockworkMod recovery.
TWRP or TeamWin Recovery Project is another very widely used custom recovery. It is fully touch-driven and has one of the most complete feature sets available. TWRP is the default recovery of OmniROM and its source code is hosted in GitHub as part of OmniROM at https://github.com/omnirom/android_bootable_recovery/.
In the preceding sections, we talked about Android architecture, AOSP, and third-party open source projects for Android. The software industry has been there for decades. There are so many existing source codes that can be reused and the need to create something from scratch is very rare. The porting and customization for a new platform is basically art of integration.
In this book, we will use the AOSP source code as the foundation and try to build everything on top of it. However, we may not be able to rely on AOSP source code only. In fact, we want to demonstrate how to support a platform that is not supported by AOSP. How are we going to do this? Do we create something from scratch? The answer is no. We will demonstrate how we can integrate all existing projects together to create a new platform. That's the reason why we discuss third-party open source projects.
In our case, VirtualBox is not supported by AOSP and we are going to enable it using AOSP and Android-x86. We need to use projects from both AOSP and Android-x86 to build a system for VirtualBox. However, our goal is to create a new build system for VirtualBox with minimal changes to the AOSP source code tree. This is also the goal of many other projects based on AOSP.
Based on the previous understanding, we have four categories of projects in our integration process:
- The original unmodified AOSP projects: In these kinds of projects, we will use AOSP projects without any changes.
- The third-party projects: In this category, the projects are added by the third-party projects and are not part of AOSP, so there are no changes involved as well.
- Projects modified by both AOSP and one of the third-party projects: This is complicated. We need to review the third-party changes and decide whether we want to include them in our system or not.
- Projects modified by multiple open source projects and AOSP: This is the most complicated case that we should avoid to integrate or change.
It is very easy to understand that we should try to reuse projects in category 1 and 2 as much as possible. The challenges and major work will be in category 3, while we should try to avoid category 4 whenever possible.
The new Android releases usually come with two reference platforms. Developers can test the new Android releases on Android emulator first. This can be very useful in the preview stages. After the official release, the Google hardware platforms, such as Nexus or Pixel, usually become the devices for developers. The emulator and Nexus/Pixel builds are the earliest builds available in AOSP.
In this book, we will use Android emulator as the virtual hardware reference platform for our topics. Since the Android emulator build is already available in AOSP, you may wonder what we can do with it. Actually, we can customize an existing platform by adding new features to it. This is what OEM/ODM companies usually do using a reference platform from a silicon vendor. With Android emulator, we will demonstrate how to create a new device so that we can customize it. If you know any commercial emulator products, such as Genymotion and AMI DuOS, then you may know what features these products added to the emulator. We will extend Android emulator in a very similar way.
After we explore the topics about the customization of a new device, we will explore more advanced topics about porting. The major work with porting is the changes to the kernel and HAL. To discuss advanced topics about porting and debugging, we will also use VirtualBox as another virtual hardware reference platform. Even though VirtualBox has been used by many commercial emulator products, such as Genymotion, AMI DuOS, Leapdroid, and so on, it is not supported by AOSP directly. Most Android emulators for the PC are based on VirtualBox and they are designed for gamers to run Android games. In this book, we will learn how to create a similar build using various open source resources.
Android emulator has been changed dramatically as well in Android 4, 5, 6, and 7. Before Android 5, Android emulator was built on a virtual hardware reference board called goldfish.
The hardware specification of the goldfish virtual hardware platform can be found in the AOSP source tree at
$AOSP/platform/external/qemu/docs/GOLDFISH-VIRTUAL-HARDWARE.TXT. In this book, we will refer to the AOSP root directory as
The goldfish virtual hardware platform was built on QEMU 1.x to emulate ARM devices on the x86 environment. The x86 host environments could be a Windows, Linux, or macOS X computer. Since the target device architecture is emulated using QEMU, the performance is poor. The emulator is very slow and difficult to use for application developers. However, QEMU is actively developed on the x86 architecture and widely used together with various virtualization technologies, such as VT-x, AMD-V, and so on.
Since Android 4.x, Intel developed an x86-based Android emulator using KVM on Linux and Intel HAXM for Windows and macOS X. With the introduction of virtualization technology to the emulator, the Intel x86-based emulator is much faster than the emulated one for the ARM or MIPS architecture. For the sake of Android application developers, Google officially integrated the Intel x86-based Android emulator to Android SDK. The Intel x86-based Android emulator has become the recommended choice for developers to test their Android applications.
With the introduction of Android 5 (Lollipop), the 64-bit hardware architecture is available for both ARM and Intel platforms. However, 64-bit hardware devices for Android were still under development at that time. The only choice for developers was to get a hardware reference platform from silicon vendors.
To help developers test their applications on 64-bit architecture, the engineers at Linaro did an excellent job enabling a virtual hardware platform on QEMU to test ARMv8-A 64-bit architecture. They gave this virtual hardware platform a code name, ranchu. You may refer to the blog at Linaro by Alex Bennée at https://www.linaro.org/blog/core-dump/running-64bit-android-l-qemu/.
This change was adopted by Google later and was used as the hardware reference platform for the next generation of Android emulators. If you install the Android SDK images, you can see two kernel images starting from Android 5. The kernel image
kernel-qemu is the image to be used with the goldfish virtual hardware platform and the image
kernel-ranchu is the image to be used with the ranchu virtual hardware platform.
To respond to this change, both Intel and MIPS worked on their architectures to support their 64-bit hardware emulation in ranchu. You can refer to the group discussions at https://groups.google.com/forum/#!topic/android-emulator-dev/dltBnUW_HzU.
The ranchu hardware platform is based on a newer QEMU version and the architecture is changed to have less dependency on Google modification and goldfish-specific devices. For example, it uses virtio-block devices to emulate the NAND and SD card. This has the potential of providing much better performance and also makes it possible to utilize the features provided by the latest QEMU code base. The ranchu kernel is built on a new version in the
android-goldfish-3.10 branch, while the latest goldfish kernel is in the
android-goldfish-3.4 branch. You can notice this difference by running your Android virtual device using different kernels from Android SDK.
With the ever evolving nature of virtualization technology, there are many commercial Android emulator products developed on the market as well. You may have heard of some of them such as Genymotion, AMIDuOS, Andy, BlueStacks, and so on. Many of them are built using VirtualBox from Oracle, such as Genymotion, AMIDuOS, and Andy. The reason that VirtualBox is used instead of other solutions such as VMware is because VirtualBox is an open source solution.
To achieve the best performance and user experience, both host and target need to be customized in the commercial emulator products. Besides Android emulator, we will also use VirtualBox as the virtual hardware platform to demonstrate how to port Android to a new platform. The reason that we need another virtual hardware platform in this book is because Android emulator is already supported in AOSP. We will use Android emulator as a platform to teach how to extend and customize an existing platform. While VirtualBox is not supported in AOSP, it can be used as a target platform to teach how to port Android to a new platform. Even though Android has been ported to VirtualBox by Genymotion, AMI, and others, none of them are open source products.
In this chapter, we discussed what Android system programming is and the scope involved in system-level programming in this book. After that, we took an overview of the Android system architecture and talked about the layers that we will focus on in this book. We also discussed the virtual hardware platforms that we use in this book. In this book, we use the code from various third-party projects, so we also took a brief overview of each of them in this chapter. In the next chapter, we will start to learn about the development environment setup for Android system programming. This includes both development tools and the source code repository setup.