This chapter is an overview that provides context for the rest of the book. It will present three different, high-level views of the Android system. It is divided into two parts, a conceptual section followed by a practical section.
The conceptual half of the chapter explores Android, metaphorically, from the side. This section models Android as a geologist might, as a stack of strata. Each layer in the model has its own significance, and each supports the layer above it. The exploration will reveal most of the major components of the Android system as well as several key architectural structures.
The second half of the chapter—the practical half—explores the AOSP source. It addresses acquiring the code, its organization, its customization, and some of the tools used to maintain it.
You have almost certainly seen one of the many illustrations of Android as a layer cake before. Figure 3.1 is another version.
Figure 3.1 shows the Android system in its context. The left half of the figure could be a generic Linux distribution such as Ubuntu or Mint. The right half illustrates the components specific to Android.
In the model, the system is divided into four major layers, each based on the one underneath it. Starting at the bottom, they are:
Hardware: This is the physical device; a piece of metal you can hold in your hand.
Linux Kernel: The kernel is software that creates the process and memory environments in which all applications run. As noted in Chapter 1, Android uses the very popular Linux kernel.
System Libraries: System libraries are software libraries, frequently supplied as opaque binaries by third-party providers that implement services used by multiple applications.
Applications and System Services: Applications use the environment provided by the lower layers to do work useful to the user. A set of special, long-running applications, called system services or sometimes “daemons,” perform periodic tasks and manage system state.
In this model, most Android developers work predominantly in the block labeled “Android Applications” at the top right of the figure. They develop the applications that run in the Android environment. These developers spend their time learning and using the environment provided by the surrounding Android system.
The rest of this book is about customizing Android itself to adapt it to new hardware. Its focus is the shaded areas outlined with the bold border, most of which is in the System Services layer of Figure 3.1. Before launching into the discussion of the Android-specific components, though, reviewing the rest of the environment in which those components run will be useful.
In this model, the bottom of the stack is the hardware. The hardware is the motivation: some device with cool new features. It is the part that you, the reader, bring to the party. The purpose of the entire software stack above the hardware is to enable the creation of applications that provide a human user with appropriate and intuitive control of some new, innovative hardware features.
Designing and bringing up hardware are dark arts that are well outside the scope of this book. Roger Ye’s book, Embedded Programming with Android (Ye, 2016), part of the Android Deep Dive Series, is an excellent introduction to “bare-metal” programming and the process of bringing up a device from scratch.
As noted in Chapter 1, Android’s kernel is a variant of the Linux kernel. Linux is wildly popular, especially in embedded devices because it is open source and fairly easy to adapt to new hardware. Chapter 4 discusses it again in more detail.
The kernel is the Android system’s primary porting layer. The process of porting Android to a new device consists in large part of getting an Android variant of the Linux kernel running on the target device and then pulling the rest of the Android stack over on top of it.
Although a kernel is a key part of Android, building a kernel is not normally part of building an Android system. Instead, the Android build tools treat the kernel as a black box: a pre-built, third-party binary. As Chapter 4 will illustrate, it is a device developer’s responsibility to assemble the working kernel and to provide it for inclusion into the device-installable file system image that the Android build system creates.
You might be surprised to hear that the kernel is Android’s primary porting layer. Much of Android programming is done in the Java programming language, whose motto was “write once, run anywhere.” For Android, however, Java source code is compiled into instructions for Dalvik and ART, not instructions for the Java Virtual Machine (JVM). The purpose of the Android VM is to make applications portable across Android devices. Unlike the JVM, multi-platform and OS portability was not a goal at all in the design of Android’s virtual machine.
There are common capabilities and functions that are used by multiple applications. Some of these capabilities—cryptography, video and audio rendering, a web browser—are large and complex. Implementing them as libraries that can be used by multiple applications makes sense.
Most system libraries are included in the Android system, as is the kernel, as third-party, black box binaries. They are essential to Android but are neither built nor maintained as part of the Android source tree.
This is an important area of customization for the developer of a new device. If software already exists—and that definitely includes software written in a language other than Java—that can be used as part of the interface to a new device, it can be included as part of this layer.
Enterprises that already have extensive investments in software may be, quite understandably, reluctant to abandon that investment simply to move to the Android platform. Including the proprietary code as a system library and then plumbing it into the Android framework with Java bindings may preserve the investment at a reasonable cost.
One of the system libraries that is part of a standard Android system and that deserves particular attention is Bionic. Bionic is Android’s equivalent of the standard C library.
Most applications do not request kernel services directly. Instead, they use a standard library, the C library, to request them. The standard C library interface was specified originally as part of the ANSI C standard and subsequently accepted by ISO. The widely established POSIX C library standard is an incremental superset.
The C library standards are expressed as C header files (.h) against which applications are compiled. These header files define symbols that allow a compiler to emit code for macros, constants, variables, and functions in the application source code. Building an application requires only the header files. The actual implementations of the C library are not included in the compiled application.
Instead, at run time, a linker binds the compiled application dynamically to the implementation of the C library that is present on the system on which the application is running. Because the API definitions against which the application was compiled are (with luck!) identical to those actually implemented by the host system library, everything works. Usually, this just means that the C library is compiled using the exact same header files that the library clients use when they are compiled. A given piece of code can be binary compatible across multiple, similar platforms, as long as all the platforms have C libraries that implement the exact
same API.
Bionic is Android’s version of the standard C library. As part of Android’s ongoing battle for frugality, it has been pruned relentlessly and is dramatically smaller than its BSD ancestors. It is so small, in fact, that it does not meet even the ANSI standard, let alone the ubiquitous POSIX standard. Applications that run perfectly well on other platforms may not run at all on Android, because Bionic does not support the functionality they require.
The implication that Bionic has its roots in BSD may come as a surprise. Most operating systems based on a Linux kernel use a version of the GNU C library, glibc
. Instead, Bionic is derived from the BSD UNIX, libc
. There are several reasons for this but the most obvious is that libc
is licensed under the BSD license and is thus free of the constraints that its LGPL licensing imposes on glibc
. One of the goals in Android’s design was to eliminate any possible impediment to its acceptance. That goal absolutely implies removing any possible licensing constraints.
Many existing applications, libraries, and utilities may be used on Android as long as they are recompiled against the Android platform. Obviously, some limits exist because of the extent of the pruning in Bionic. For example, existing code that uses System V IPC or certain functions in the kernel concurrency feature, pthreads, cannot be built or run on Android. Additionally, as this chapter will make clearer, the Android software stack is fundamentally different than a typical Linux stack, which sometimes makes the use of existing Linux programs difficult or impossible.
Augmenting an Android system by adding one of the standard C-library implementations is entirely feasible. This simple and very common augmentation makes it possible to run many standard Unix applications and libraries on an Android system.
System services are those special applications, typically with minimal user interfaces, that maintain various subsystems: indexing files for search, locating and connecting to Wi-Fi networks, mounting and unmounting removable media, and so on. One special system service, init
, is the first application run on system startup. It is responsible for much of the system startup process, including bringing up the other system services. It is discussed in more detail in Chapter 6.
The Android system service environment is not the same as that on typical Linux systems. On a Linux system, running the command:
ps -ef
produces a list of currently running applications. On one of these systems, running this command will typically result in tens of lines of output describing many processes. Even if the system has just been finished booting and is not yet running many user applications, there are still likely to be quite a few applications running. These are the system services: the long running “daemons.”
Comparing the list of system services for a generic Linux system with a similar list from an Android system is instructive. Although the 30 to 40 system services that run as part of most common Linux distributions are fairly similar, the overlap with those running on an Android system is relatively small. The Android system has unfamiliar system services such as installd
, rild
, surfaceflinger
, and vold
instead of more common services such as udevd
and syslogd
. Although Chapter 6 addresses some of these daemons in a bit more detail, in-depth discussion of the differences between the daemons in the Android universe and those in the standard Linux universe are not the focus of this book. Linux daemons are well documented elsewhere. Although slightly dated, Karim Yaghmour’s excellent book Embedded Android (Yaghmour, 2013) is a fantastic resource for work in this area.
Figure 3.1 illustrates some of the Android-specific components of an Android system and their positions within the broader model of a working Linux system. The right side of the figure shows the Android framework in relation to the larger OS. Android has components that operate within each of the layers of the system model. From the bottom up, the components of the Android system are
Binder and other kernel plug-ins: Android requires several non-standard kernel
capabilities to function. These extensions are implemented as standard kernel extension modules. Chief among these extensions is Binder. Binder is an Interprocess Communi-cations service and is, perhaps, the heart of Android.
HAL: The Hardware Abstraction Layer (HAL) is a system library that supports binary compatibility for the Android system across multiple hardware/driver platforms. The HAL, actually a group of libraries, serves as the interface between Android and certain generic types of hardware devices. Like the C library, the HAL is, essentially, a set of header (.h) files that define an API for each of several common categories of hardware. The HAL abstracts an interface between the underlying hardware and Android almost exactly as the C library abstracts the interface to the kernel and other common functionality. The HAL has evolved over Android’s lifetime. Newer versions of Android combine a library and a daemon/service to push the abstraction even farther. Most HAL code is written in C or C++ and compiled to device native binaries. Chapters 8 and 10 cover this in greater detail.
Dalvik, ART, and the Native Libraries: These are the special system libraries that comprise the virtual machine and runtime environment in which Android applications execute. ART (and Dalvik, which it replaced) are Android’s analog of the Java virtual machine and the libraries it provides. Both the runtime and many of the libraries that support it are written in C/C++ and compiled to native code for the device. Above this layer, however, nearly all source code is written in Java and compiled to virtual instructions. Chapter 7 discusses ART and Dalvik.
Android API Libraries: These are system libraries written in Java, compiled to dex virtual machine code, and translated to near-machine code (.oat files) during installation. They are bound to Android applications at runtime, almost exactly as the C Library is bound to native applications. The code they contain, though, cannot be executed without the help of the virtual machine and its runtime environment. These libraries are the APIs to Android services.
Android Services: The Android analog of a system service, these privileged Android applications written in Java provide essential Android functionality. The Zygote service, especially, plays a key role in an Android system. Zygote is covered in Chapter 6. The Android service model is covered in the next section and seen again in Chapters 10 and 11 as part of the binderized HAL.
Android Applications: These applications are developed for Android, compiled against the Android API, and run within the runtime environment. Building an Android application is unlike developing applications either for other varieties of Linux or for other mobile platforms. Many other resources are available to a developer building an application. Application building is discussed only peripherally in this book.
A second, side-on view of the Android system gives a more functional perspective. Shown in Figure 3.2, it illustrates the basic structure of Android’s service model.
This diagram is key. It illustrates two applications in two separate processes, one on the right and one on the left. The application in the process on the left side of the diagram needs access to the scarce resource at the bottom of the diagram. The arrow from the application to the scarce resource represents its request.
In the diagram the scarce resource is shown as hardware because it often is. Examples of scarce hardware resources might include a phone’s screen, status lights, or a buzzer. Allowing all applications unrestricted access to these things wouldn’t make sense. At best, applications would have to coordinate access among themselves. At worst, a malicious application could make a device unusable by seizing one or more of the essential resources and refusing to release them.
Hardware resources, of course, are not the only things that can be scarce or that need protection. A list of accounts or a database of acquaintances might require similar protection. Android uses the same mechanism to protect non-hardware resources.
In Figure 3.2, the arrow illustrating the application’s intended request for the scarce resource is marked with an “X.” The “X” indicates that application is blocked by the system from making the request directly.
The portal through which an application interacts with hardware—its driver—is almost certainly catalogued as a file in the /dev
directory. Recall that as the creator of the file system abstraction, the kernel is able to represent nearly anything as a file. The driver is a special kind of file but still a file. To interact with the resource directly, the application must open the driver file and read and write from it.
Like all files in the Linux file system, the driver file is catalogued with permissions. These permissions determine which processes the kernel will allow to open the file.
Listing 3.1 shows excerpts from the listing of the contents of the /dev
directory from a typical Android device. Most of these files are drivers for one device or another. In most cases, the file’s permissions (the first column) limit access to the file’s owner (second column) or owning group (third column). Only a couple of the files in this example allow unrestricted access (crw-rw-rw
).
The others are accessible only by processes with specific UIDs.
crw------- root root 233, 0 1970-07-29 16:48 adsprpc-smd crw-rw-r-- system radio 10, 56 1970-07-29 16:48 alarm ... crw-rw---- system audio 10, 40 1970-07-29 16:48 audio_slimslave crw-rw---- nfc nfc 10, 70 1970-07-29 16:48 bcm2079x-i2c crw-rw-rw- root root 10, 62 1970-07-29 16:48 binder crw-r----- radio radio 230, 0 1970-07-29 16:48 hsicctl0 crw-r----- radio radio 230, 1 1970-07-29 16:48 hsicctl1 crw-r----- radio radio 230, 10 1970-07-29 16:48 hsicctl10 ... cr--r----- root system 10, 183 1970-07-29 16:48 hw_random crw------- root root 89, 0 1970-07-29 16:48 i2c-0 ... crw-rw---- system camera 239, 0 1970-07-29 16:48 jpeg0 ... crw-rw---- system camera 251, 0 1970-07-29 16:48 media0 ... crw-rw---- root mtp 10, 43 1970-07-29 16:48 mtp_usb ... crw-rw---- radio vpn 108, 0 1970-07-29 16:48 ppp ... crw-rw---- system drmrpc 244, 0 1970-07-29 16:48 qseecom crw------- root root 10, 92 1970-07-29 16:48 ramdump_adsp ... crw------- root root 232, 3 1970-07-29 16:48 smd3 crw------- root root 232, 36 1970-07-29 16:48 smd36 crw-rw---- system system 232, 4 1970-07-29 16:48 smd4 crw-rw---- system system 232, 5 1970-07-29 16:48 smd5 crw-rw---- system system 232, 6 1970-07-29 16:48 smd6 crw-rw---- bluetooth bluetooth 232, 7 1970-07-29 16:48 smd7 crw------- root root 232, 8 1970-07-29 16:48 smd8 crw-r----- radio radio 231, 25 1970-07-29 16:48 smd_cxm_qmi crw-rw---- bluetooth net_bt_stack 248, 0 2017-01-22 12:16 ttyHS0 crw------- media media 248, 3 2017-01-22 12:16 ttyHS3 crw------- root root 247, 0 1970-07-29 16:48 ttyHSL0 crw-rw---- system vpn 10, 200 1970-07-29 16:48 tun crw-rw---- system net_bt_stack 10, 239 1970-07-29 16:48 uhid ... crw-rw-rw- root root 1, 9 1970-07-29 16:48 urandom crw-rw---- root usb 10, 41 1970-07-29 16:48 usb_accessory
When Linux was first developed in the 1990s, it was designed for computers that were shared by many users. At that time, security in an operating system meant, exactly, protecting users of the same computer from each other. Although attacks from across a network were not unknown, it was far more likely that one of the users of a system would compromise another’s resources on a single system than it was that an attack would originate externally. Over years of use, the ability of the Linux system to protect individual user accounts from one another has been tested, retested, and tested again. It is quite secure.
The permissions system is what prevents the request for the scarce resource shown in Figure 3.2
from succeeding. The application’s process is not running with the user and group IDs that protect the resource and, therefore, the application does not have read or write permission on the driver. It does not have any way to obtain direct access to the resource.
Starting with KitKat, Android included an adaptation of SE Linux that further enhanced access controls. The original discretionary access control (DAC) model of permissions was not enough to prevent a system from being compromised. For example, using only DAC, a highly privileged system service (such as init
), 43if compromised, might allow unfettered access to the system. SE Linux for Android introduced mandatory access control (MAC). It allows each running process to be further constrained from a security standpoint. All applications, including system processes, are assigned SE context that is enforced by the kernel. This limits the damage any one process can do, if compromised.
As Chapter 5 will demonstrate, writing and extending SE policies is a non-trivial task. Unless absolutely necessary, not altering the SE policies that are provided in the AOSP tree is best because they are CDD/CTS compliant. This is particularly important if the device is to be certified as an Android device.
The series of unblocked arrows in Figure 3.2 show how Android applications actually do get access to scarce resources when they need them. Instead of requesting the access directly, they use an interprocess communication (IPC) mechanism, Binder, to make a request to a system service. Normally, the IPC request is completely hidden from the caller because it is wrapped in in the Android API libraries. The client app sees only a call to a local method.
When the client app wants to obtain access to a scarce resource, it simply calls one of the methods in the Android API. The method call actually initiates an IPC conversation with Android service applications in one or more remote processes. These service processes, unlike the client, have the necessary security privileges that do permit them to access the scarce resource. The service can coordinate the requests as appropriate and manage access and control client use of the resource. Services provide fine-grained control over application access to the scarce resources they manage by declaring permissions. A permission is nothing more than a unique string that is recognized by the Android system. Android strictly manages permissions: Applications that want to use them must declare their intentions in their manifests and must get explicit approval from the application user before the permissions are granted. When an application requests access to a scarce resource from a service, the service can provide access in the firm knowledge that the application is acting on behalf of an informed user.
This mechanism, access to resources through a proxy service, is the key to hardware access in Android.
The last of this chapter’s high-level views of Android is, as promised, much more practical. It’s time to look at the AOSP code-base.
The primary source for Android code is the Android Open Source Project (AOSP) site at https://source.android.com/. Android system developers should be familiar with this site whether it is the source of the code for their project or not. Android originates here, and documentation and update information are available here before being available anywhere else.
In particular, the Overview section of the AOSP website contains important information about source branching and tagging strategies and the legal constraints on the use of the Android name, logos, and so on. Anyone working with Android code should read this documentation and be, at the least, generally familiar with it.
Several other sources for forks of the AOSP code exist, each with its own advantages and disadvantages. Among these forks, perhaps the best known are AOKP and MIUI. Sadly, one of the most important forks, CyanogenMod, has disappeared from the scene. The support community has rebranded it as LineageOS, and it may return to viability in the future.
The remaining sections of this chapter assume that the developer/build machine has been set up as described in Chapter 2. Let’s take a quick walk through the source, just to get the lay of the land. Listing 3.2 shows the top-level directory structure.
lrwxr-xr-x 1 aosp staff 19 Oct 13 09:26 Android.bp -r--r--r-- 1 aosp staff 92 Oct 13 09:26 Makefile drwxr-xr-x 35 aosp staff 1564 Oct 13 09:26 art drwxr-xr-x 14 aosp staff 816 Oct 13 09:26 bionic drwxr-xr-x 3 aosp staff 102 Oct 13 09:26 bootable lrwxr-xr-x 1 aosp staff 26 Oct 13 09:26 bootstrap.bash drwxr-xr-x 5 aosp staff 374 Oct 13 09:26 build drwxr-xr-x 3 aosp staff 102 Oct 13 09:26 compatibility drwxr-xr-x 12 aosp staff 748 Oct 13 09:26 cts drwxr-xr-x 8 aosp staff 476 Oct 13 09:26 dalvik drwxr-xr-x 5 aosp staff 170 Oct 13 09:26 developers drwxr-xr-x 20 aosp staff 748 Oct 13 09:26 development drwxr-xr-x 10 aosp staff 340 Oct 13 09:27 device drwxr-xr-x 310 aosp staff 10540 Oct 13 09:30 external drwxr-xr-x 15 aosp staff 510 Oct 13 09:31 frameworks drwxr-xr-x 12 aosp staff 408 Oct 13 09:31 hardware drwxr-xr-x 5 aosp staff 170 Oct 13 09:31 kernel drwxr-xr-x 20 aosp staff 1258 Oct 13 09:31 libcore drwxr-xr-x 8 aosp staff 680 Oct 13 09:31 libnativehelper drwxr-xr-x 9 aosp staff 306 Oct 13 09:32 packages drwxr-xr-x 6 aosp staff 272 Oct 13 09:32 pdk drwxr-xr-x 10 aosp staff 374 Oct 13 09:32 platform_testing drwxr-xr-x 30 aosp staff 1020 Oct 13 09:36 prebuilts drwxr-xr-x 24 aosp staff 1054 Oct 13 09:36 sdk drwxr-xr-x 37 aosp staff 1258 Oct 13 09:36 system drwxr-xr-x 10 aosp staff 340 Oct 13 09:36 test drwxr-xr-x 4 aosp staff 136 Oct 13 09:36 toolchain drwxr-xr-x 21 aosp staff 714 Oct 13 09:37 tools
The build system for Android is in transition. Up through the Marshmallow release, Android used an extension of GNU make
as the underlying build system. The system used build files named Android.mk
dispersed throughout the build tree, selected using a configuration describing the particular device being built. The process resulted in a large in-memory makefile to do the build. While powerful, this approach had limitations and never scaled well, especially noticeable as the Android source tree grew in size.
Nougat introduced a new build system, Soong, which is inspired by Bazel and uses a Go syntax. With Soong, the Android.mk
files are replaced with Android.bp
(blue print) files. As announced in late 2020, Google will be further transitioning the build system to Bazel in the near future.
Makefile is the top-level makefile used in the legacy GNU make
build system. It is copied here from the build
directory when repo sync
is executed.
The art
directory contains the code for the Android Runtime (ART), an ahead-of-time compiled runtime that replaces the original Android virtual machine, Dalvik.
The bionic
directory contains the code for the Android Standard-C-like library, Bionic. The earlier section of this chapter, “System Libraries,” describes Bionic.
The bootable
directory contains the source for the recovery executable. Recovery is used to apply OTA updates, write new firmware, and perform a factory data wipe.
The bootstrap.bash
script is part of the new build system, Soong.
The build
directory contains the both the old and the new build systems. In particular, it contains the shell script envsetup.sh
, used to configure the build environment. In addition to setting up required environment variables, this script introduces helper aliases and shell functions, such as lunch
, which are used to configure and execute the build, as discussed in detail in Chapter 2.
The cts
directory contains the Android Compatibility Test Suite tests. Passing these tests is the minimum requirement for certification as an Android device.
The dalvik
directory contains the source for Android’s original VM, Dalvik.
The developers
directory contains three different repositories of mostly legacy example code. The example Gradle plug-ins may be of interest.
The development
directory contains odds and ends that may be useful to developers. It contains things such as tools for editing Android source using one of the popular IDEs, Eclipse or IntelliJ; more example code; developer debug applications; configurations for checkstyle, the emulator; and other tools.
device
is an extremely important directory for a device developer. The Android source and build system are designed with the intention that all device-specific code—device-specific configuration of the build system, toolchain customizations, kernel selection, and even specialized versions of applications—go here. Although most device developers will find that very constraining, it is a smart strategy to keep as much device-specific code as possible in this directory. Only broader, more generic cross-platform changes should be made outside of the device-specific directory. Much of the work in the rest of this book will happen in this directory.
external
contains all the buildable packages that are used, but not maintained, as part of Android. It contains things like bouncycastle
, the Android cryptography library; expat
, an XML parser; junit
, a standard testing framework; and so on. All of these things are essential components of a running Android system but are obtained from external providers. Placing the code for these components in this directory makes the dependency explicit and makes Android less susceptible to versioning issues.
The frameworks
directory is the heart of Android. The public Android API is located here, in the directory frameworks/base/core/java
. Core system services such as the ActivityManagerService
and PackageManagerService
are in frameworks/base/services/core/java
. Input event management and sensors code can be found under frameworks/base/native
. You can usually find native implementation code next to java
directories in sibling jni
directories and static resources in directories named res
.
The hardware
directory contains the HAL. This is the abstraction layer code for common devices: Wi-Fi, Bluetooth, and baseband radios; sensors; cameras; and so on. Although this directory contains shim code for many common devices, it is the device
directory that contains customizations for a specific board and any one-off hardware on that board.
The most interesting things that live in the libcore
directory are the sources for the Apache Harmony base implementations of the Java API. For example, the file
libcore/ojluni/src/main/java/java/lang/Class.java
is the source for Android’s implementation of the Java type Class
.
As the name implies, the libnativehelper
directory contains native helper functions. It is sort of a “commons” directory for HAL code that leverages Java Native Interface (JNI) to bridge the gap between the runtime code and backing native code.
The packages
directory contains applications that will be included as part of the system. The directory packages/apps
, for instance, contains the standard DeskClock, Phone, and Camera apps that are pre-installed (and not uninstallable) on a typical Android device.
The pdk
directory contains the platform development toolkit (PDK). It is given to original device manufacturers (ODMs) so that they can develop HAL and other specialization software for their devices. The PDK is a subset of the full Android source, so this directory doesn’t contain much that is useful as part of the Android source tree.
The platform-testing
directory contains odds and ends of tools for testing device functionality.
The large prebuilts
directory is very similar to the external
directory, except that the things that it contains are not built as part of the system build process. For instance, it contains the binaries for the clang
and gcc
, C compilers; the Python and Go language SDKs; and the kernel for the QEMU-based Android emulator.
sdk
, a mostly historical directory, contains source for some of the Android development tools as they were just before Android Studio was introduced. Since Android Studio, the SDK tools have their own, partially overlapping, repo
-maintained build tree (see http://tools.android.com/build). Most of the code here is obsolete.
Another very important directory, system
contains the native daemons, system libraries, and data essential to an Android system. In here are the sources for vold
, the SE Linux policies, and the system trusted certificates. These are the parts of the Android system that are illustrated in the top-left of Figure 3.1 and discussed in Chapter 7.
The toolchain
directory contains a set of automated tests that can be executed to gather benchmarking data. Building and running these tests require patching the source tree.
The tools
directory contains a number of helper tools, such as ones to ease the creation of Android AVDs and to analyze atrace
data captures.
The out
directory is not part of the build environment maintained by repo
. It is, however, the default scratchpad for the build system. None of the previously mentioned directories should be affected in any way by a system build. From the build’s point of view, they are all read only. Restoring a build environment to its pristine state should always be possible by simply deleting this directory. All intermediates as well as the final build artifacts are put here.
This chapter has been a very high-level tour of the Android system. It inspects Android from three very broad points of view: as a series of layers of abstraction, starting at the hardware and ending with user applications; as a client-server architecture in which servers regulate access to scarce resources; and as a build environment, with source and tools for generating the running system.
Subsequent chapters walk up the stack illustrated in Figure 3.1, illustrating the relation between the source code and the running system and demonstrating at each layer how to customize behavior.
3.224.147.211