How Android works, Part 1
In this series of articles, I'll talk about the internal Android device - about the boot process, about the contents of the file system, about Binder and Android Runtime, about what they consist of, how the applications are installed, running, interacting with each other, about the Android Framework, and on how Android provides security.
How Android works, Part 1
How Android works, part 2
Few factsAndroid is the most popular operating system and application platform, with more than two billion active users. It runs a completely different device, from the "Internet of things" and smart hours to televisions, laptops and cars, but most often Android is used on smartphones and tablets.
Android is a free and open project. Most of the source code (which can be found at https://source.android.com ) is distributed under the free Apache 2.0 license.
Android Inc. was founded in 2003 and in 2005 was bought by Google. The public beta of Android was released in 2007, and the first stable version - in 2008, since then the major releases come out about once a year. The latest at the time of writing, the stable version of Android is 7.1.2 Nougat.
Android is LinuxThere was a lot of controversy about this formulation, so I will immediately explain what I mean by this phrase: Android is based on the Linux kernel, but it differs significantly from most other Linux systems.
Among the original developers of Android was Robert Love, one of the most famous developers of the Linux kernel, and now Google remains one of the most active contributors to the core, so it's no surprise that Android is built on Linux.
As with other Linux systems, the Linux kernel provides such low-level things as memory management, data protection, support for multiprocessing and multithreading. But - with a few exceptions - you will not find other familiar GNU / Linux components in Android: there is nothing from the GNU project, no use of X.Org, or even systemd. All these components are replaced by analogs that are more suitable for use in low-memory, low-speed processor and minimal power consumption - thus, Android is more like an embedded Linux system than on GNU / Linux.
Another reason that Android does not use the GNU software is the well-known "no GPL in userspace" policy:
We are sometimes asked why Apache Software License 2.0 is the preferred license for Android. For userspace (that is, non-kernel) software, we do in fact prefer ASL 2.0 (and similar licenses like BSD, MIT, etc.) over other licenses such as LGPL.To implement such a system, it is necessary that applications have the ability to communicate with each other and with system services - in other words, a very advanced and fast IPC mechanism is needed.
Android is about freedom and choice. The purpose of Android is to promote openness in the mobile world, and we do not believe it's possible to predict or dictate. So, while we are promoting everyone to make devices that are open and modifiable, we do not believe it is our place to force them to do so. The Linux kernel itself in Android was also slightly modified: several small components were added, including ashmem (anonymous shared memory), Binder driver (part of the large and important Binder framework, which I will discuss below), wakelocks (sleep mode control) and low memory killer. Initially they were patches to the kernel, but their code was quickly added back to the upstream kernel. However, you will not find them in "normal Linux": most other distributions disable these components during assembly.
As libc (the standard C language library), Android does not use the GNU C library ( glibc ), but its own minimalistic implementation for the name bionic , optimized for embedded systems - it is much faster, less and less demanding on memory than glibc, which is overgrown with many layers of compatibility.
In Android, there is a command-line shell (shell) and many standard for Unix-like command / program systems. Embedded systems usually use the Busybox package, which implements the functionality of many commands in a single executable; Android uses its analogue under the name Toybox . As with "regular" Linux distributions (and unlike embedded systems), the main way to interact with the system is the graphical interface, not the command line. Nevertheless, it's very easy to "get" to the command line - just run the terminal emulator application. By default, it is usually not installed, but it's easy, for example, to download from the Play Store ( Terminal Emulator for Android , Material Terminal , Termux ). In many "advanced" distributions of Android - such as LineageOS (formerly CyanogenMod) - the terminal emulator is preinstalled.
The second option is to connect to your Android device from your computer via the Android Debug Bridge (adb). This is very similar to connecting via SSH:
[email protected]$ adb shellOther familiar components in Android use the FreeType library (for displaying text), graphic APIs OpenGL ES , EGL and Vulkan , as well as a lightweight database SQLite .
In addition, before the WebView implementation was used the browser engine WebKit , but starting with version 7.0 Instead, it uses the installed Chrome application (or another; list of applications that are allowed to act as a WebView provider, is configured at the compilation stage of the system). Inside Chrome, too, uses the WebKit-based engine Blink , but unlike the system library, Chrome is updated via the Play Store - so all applications that use WebView automatically receive the latest vulnerability improvements and fixes.
It's all about appsAs you can easily notice, the use of Android is fundamentally different from using "regular Linux" - you do not need to open and close applications, you just switch between them, as if all applications are always running. Indeed, one of the unique features of Android is that applications do not directly control the process in which they are running. Let's talk about this in more detail.
The basic unit in Unix-like systems is the process. Both low-level system services, and individual commands in the shell, and graphical applications are processes. In most cases, the process is a black box for the rest of the system - other components of the system do not know and do not care about its state. The process begins with the call to the function main () (actually_start), and then it implements some kind of its logic, interacting with the rest of the system through system calls and the simplest interprocess communication (IPC).
Because Android is also Unix-like, all this is true for it, but while low-level parts - at the Unix level - operate with the concept of the process, at a higher level - the Android Framework level - the basic unit is the application. The application is not a black box: it consists of individual components well known to the rest of the system.
Android applications do not have the function main (), there is no single entry point. Generally, Android as much as possible abstracts the concept of the application launched from both the user and the developer. Of course, the application process needs to be started and stopped, but Android does this automatically (for more details I'll talk about this in the next articles). The developer is invited to implement several separate components, each of which has its own life cycle.
<blockquote> In Android, however, we explicitly decided we were not going to have a main () function, because we needed more control over how an app runs. In particular, we wanted to build a system where the user would need to think about and stopping apps, but rather the system took care of this for them ... so the system had to have some more information about what is going on inside of each
This mechanism is Binder.
BinderBinder is a platform for fast, convenient and object-oriented interprocess communication.
The development of Binder began in Be Inc. (for BeOS), then it was ported to Linux and opened. The main developer of Binder, Dianne Hackborn, was and remains one of the main Android developers. During the development of Android Binder was completely rewritten.
Binder does not work on top of System V IPC (which is not even supported in bionic), but uses its small core module, which interacts with userspace through system calls (basicallyioctl) on the "virtual device" / dev / binder. On the userspace side, low-level work with Binder, including interaction with / dev / binder and marshalling / unmarshalling data, is implemented in the libbinder .
Low-level parts of the Binder operate in terms of objects that can be sent between processes. In this case, reference-counting is used to automatically release unused shared resources and a notification about the completion of a remote process (link-to-death) for releasing resources within the process.
The high-level parts of the Binder work in terms of interfaces, services and proxy objects. A description of the interface provided by the program to other programs is recorded in the special language AIDL (Android Interface Definition Language), externally very similar to the declaration of interfaces in Java. This description automatically generates a real Java-interface, which can then be used by both clients and the service itself. In addition, two special classes are automatically generated on the .aidl-file: Proxy (for use by the client) and Stub (from the service side) that implement this interface.
For Java code in the client process, the proxy object looks like a regular Java object that implements our interface, and this code can simply call its methods. In this case, the generated proxy object implementation automatically serializes the passed arguments, communicates with the process service via libbinder, deserializes the returned result of the call and returns it from the Java method.
Stub works the other way: it accepts incoming calls via libbinder, deserializes arguments, calls an abstract implementation of the method, serializes the return value, and passes it to the client process. Accordingly, to implement the service, the programmer should implement the abstract methods in the class inherited from the Stub.
Such a Java-level implementation of Binder allows most code to use a proxy object, without even thinking about the fact that its functionality is implemented in another process. To ensure full transparency, Binder supports nested and recursive interprocess calls. Moreover, the use of the Binder from the client side looks exactly the same, regardless of whether the implementation of the service in question is located in the same or in a separate process.
In order for different processes to "find" each other's services, Android has a special ServiceManager service that stores, registers and issues tokens of all other services.
Binder is widely used in Android to implement system services (for example, the packet manager and the clipboard), but the details of this are hidden from the application developer by the high-level classes in the Android Framework, such as Activity , Intent and Context . Applications can also use Binder to provide each other with their own services - for example, the Google Play Services application does not have its own graphical user interface , but it gives developers of other applications the ability to use Google Play services.
More information about Binder can be found on these links:
Android Binder - Embedded Linux Wiki
Android Interface Definition Language, IBinder
Deep Dive into Android IPC/Binder Framework
Android Binder - Android Interprocess Communication
An Overview of Android Binder Framework
Binders & Window Tokens
|Vote for this post
Bring it to the Main Page