A dive into the depths of Android customization architecture
Author: Martin Becker, Fraunhofer Institute for Experimental Software Engineering (IESE)
Contribution – Embedded Software Engineering Congress 2017
The Android operating system has been used in a wide variety of embedded systems for years. It can be highly and extensively adapted to specific use cases. This is achieved through a sophisticated interplay of different mechanisms at various system levels. This configuration and customization architecture provides excellent inspiration for efficiently implementing and managing necessary customizations within one's own system landscape. Unfortunately, gaining a comprehensive overview is not always easy. This article therefore examines which types of customization are supported in Android and how they are implemented in the Android architecture.
motivation
The demand for software solutions precisely tailored to customer needs is growing unabated. In everyday development, the question often arises as to how to effectively support the necessary customizations. In previous articles, we examined typical mechanisms and architectures for this purpose. In this article, we explore how the necessary customizations are supported in the open-source operating system Android.
Android has been used very successfully in a wide variety of embedded systems for several years. Besides mobile consumer electronics, applications can also be found in the automotive and healthcare sectors [1]. The Android codebase is very large and includes a significant proportion of other open-source projects. The widespread use of Android suggests that it can be highly adapted to specific application contexts.
In addition to supporting a wide range of hardware platforms, Android also supports extensive customization of its functionality. This is achieved through a sophisticated interplay of different mechanisms at various levels. This configuration and customization architecture provides valuable insights into how to efficiently implement and manage necessary customizations within your own system landscape. Unfortunately, gaining a comprehensive overview is not always straightforward. To address this, we have conducted an in-depth analysis of the Android build system. This article briefly presents the analysis results from [2][3]. It highlights the types of customizations supported in Android and how these are implemented in the Android customization architecture.
Android Code Repository
Our analysis is based on the Android 6 code repository [4]. Although Android uses a variety of other open-source projects, we analyzed the entire code repository. The repository content is as shown in Fig. 1 (see below). PDFThe file structure is very large and quite heterogeneous in terms of the file types used. It's clear that a number of programming languages are employed, including Java, C, C++, Python, Go, and JavaScript, although the majority of Android is programmed in C/C++. The build process is controlled by 4475 Makefiles – a considerable number that isn't easy to keep track of.
The code is roughly distributed across three levels (see below). PDF, Fig. 2).
The Android configuration level includes product and board configurations. The latter are mainly located in the folder Device. Some generic product configurations can be found in /build/target/product. The corresponding configuration items are defined in Makefiles, which are typically located in device/ / This allows them to be used in the build system and source code. Product configurations include general product information, such as product name and manufacturer, as well as a list of modules required for a device. Board configurations are always stored in a Makefile called `boardconfig`. BoardConfig.mk These parameters define a variety of settings related to peripheral devices on the board. These parameters are then used in the code modules.
The Android build system consists of two parts: i) global build files, which define the overall build process, and ii) local build files, which build individual modules. As shown in Figure 2, the global build files are located in the build Folder. The Makefile main.mk This represents the entry point into the build process. The Makefile product.mk defines helper functions, e.g., to resolve product dependencies. Each code module contains a Makefile called Android.mk, which builds the module. Makefiles of the build system can use configuration variables defined in the configuration files.
Android source code is structured into modules, which are located in separate folders. These folders are nested hierarchically. Some belong to the Android core infrastructure (e.g., the Linux kernel), others to application support (e.g., Phone). Some modules are manufacturer-specific and are therefore located in the root directory. device Folder.
Configuration level adjustments
Configurations are defined via Makefile variables that specify software and hardware settings. The corresponding Makefiles are located in the device Folder. In total, we found 206 configuration variables using a custom-built parser. Most variables follow the naming convention. PRODUCT_* or BOARD_*. Our analysis showed that most product variables are used for descriptive purposes only. In contrast, board variables are used to control the build process. A relatively small number of variables are frequently referenced, while the majority are used only a few times. This gives the build system a fairly clean and organized appearance. An overview can be found in Table 1. References are made in the global build Folders, in manufacturer-specific modules in device Folders and other modules are distinguished. Among the most frequently used configuration variables are: TARGET_ARCH and TARGET_BOARD_PLATFORM, which was ultimately to be expected.
|
# Config References |
1 |
2~3 |
4~50 |
51~246 |
Sum |
|
# Configs in Global |
19 |
23 |
41 |
3 |
86 |
|
# Configs in Device |
6 |
6 |
4 |
0 |
16 |
|
# Configs in Others |
38 |
28 |
25 |
3 |
94 |
Table 1: References to configuration variables in the build system
Fig. 3 (see. PDFThe image shows a typical use of configuration variables in the Makefiles. Here, dependencies around dex-preoptimization are discussed. This is implemented. Depending on the value of higher-level variables, the value of other variables is set.
A type of inheritance is supported between product configurations. A Makefile can inherit settings from multiple parent Makefiles. This is achieved through the helper function. inherit-product in product.mk This enables the easier reuse of common settings. Settings in the higher-level Makefiles are considered default values, which can be overridden in more specific product configurations. The inheritance graph between the product configuration files is shown in Figure 4 (see...). PDFHe can be connected with make product graph Create. As you can see, multiple inheritance is used in several places. It's important to ensure that the assignments are correctly superimposed.
Adjustments at the build system level
Unlike other Make-based build systems, Android does not call Makefiles recursively. Global Makefiles initially contain all Android.mk Files within the codebase are grouped together, their contents are included, and then the make instructions are executed. Why is this done? It allows for easy analysis and optimization of the build process. More on that later.
The module Makefiles then include the selection of the files from which the module is built. Fig. 5 (see below). PDFThis is shown in the example below. It involves a type of file-level polymorphism. Files that are optional or alternative to the build process can thus be easily identified. The preprocessor (#ifdefs) is likely deliberately avoided in favor of module replacement, thereby improving the readability of the source code files.
To better understand the customization architecture, we analyzed the selection constructs and the variables used in more detail. For this purpose, we modified the Kati tool [5] slightly and then used it in the analysis. Kati is an open-source tool from Google that parses Makefiles and converts them into Ninja files. Android can then be built using these Ninja files in an optimized way, which significantly speeds up the build process – a very interesting approach. We found 682 build variables, which can be divided into four categories: product configuration, board configuration, build OS, and build details. Fig. 7 (see below). PDF) provides an overview of whether these variables are used in the build system or in the source code.
Code-level adjustments
Since Android's configuration variables are defined in Makefiles and not in header files, they are not directly available to the preprocessor when processing the source code files, but must be explicitly passed. A corresponding example is shown in Fig. 8 (see below). PDFAs illustrated: Depending on higher-level configuration variables, lower-level configuration variables are first set. Then, in the build system, compiler flags are set based on these lower-level configuration variables, and the values of these variables are passed to the preprocessor/compiler. This may initially seem somewhat cumbersome.
Upon closer inspection, however, a clear configuration architecture emerges, which clearly separates the application configuration from the technical configuration of the modules. Since the relevant relationships are only expressed via the Makefiles, the customization architecture can be analyzed, optimized, and further developed quite effectively using tools. There is certainly something to be learned from Android for large projects in this regard. If needed, the Kati tool [5] is certainly a good starting point. We have extended it somewhat to access additional information available during the analysis of the build system within the tool.
Summary
Android developers have successfully supported a wide range of customizations based on a heterogeneous codebase that evolves concurrently. This suggests that Android's customization and configuration architecture is a valuable source of inspiration for developers struggling with managing variant implementations in their daily work. Since gaining a comprehensive overview is not always straightforward, we conducted a thorough analysis, which we have documented in detail in [2][3].
Our analysis led to the following findings: Customization support in Android is significantly simpler than we had anticipated. Instead of sophisticated configuration models, techniques, and tools, as well as clear coding standards, the usual suspects are used. It's noticeable that the three-tier configuration and customization architecture is very clear and essentially relies on Makefiles. The user-side configuration is strictly separated from the technical configuration of the modules—a pattern we've encountered elsewhere. The dependencies between application configuration, build system, and source code are contained in the Makefiles and can be extracted using the Kati tool. In future Android releases, Make will be replaced by Kati/Ninja. This example also demonstrates how the transition between different build systems can succeed, even in complex systems.
thanksgiving
The analyses presented here were carried out by Nicolas Fußbender at Fraunhofer IESE as part of a student project at the Technical University of Kaiserslautern. Vasil Tenev and Dr. Bo Zhang provided significant support for the project.
Bibliography and list of sources
[2] Nicolas Fußberger: „Analyzing the Variability Realization in Androidd“, TU Kaiserslautern
[3] Nicolas Fußberger, Bo Zhang, and Martin Becker: „A Deep Dive into Android's Variability Realizations„", in Proceedings of the 21st International Systems and Software Product Line Conference (SPLC '17). DOI
[5] Kati Tool
author
Dr. Martin Becker is a computer scientist and heads the Embedded Systems Engineering department at Fraunhofer IESE. Over the past 17 years, he has gained extensive experience in variant management across various application areas through numerous research and industry projects, and has also developed new methods, techniques, and tools in this field.
Open Source – our training & coaching
Do you want to bring yourself up to date with the latest technology?
Then find out more here MircoConsult offers training courses/seminars/workshops and individual coaching on the topic of Open Source / Embedded Software Engineering.
Training & coaching on the other topics in our portfolio can be found here. here.
Open Source – Expertise
Valuable expertise in the field of Open Source / Embedded Software Engineering is available. here Available for you to download free of charge.
You can find expertise on other topics in our portfolio here. here.
