Asynchronous programming has become an important topic of discussion in the past few years, especially when using the concurrent processing capabilities available on the most recent mobile hardware.
In recent years, the number of independent processing units (cores) available on the CPU have increased, so to benefit from this new processing power, a new programming model called asynchronous programming has appeared to orchestrate the work between the several independent hardware-processing units available on the device. Asynchronous programming comes to the rescue to solve the problems that could arise from this new processing paradigm.
Android applications, since they mostly run on devices with multiple units of processing, should take advantage of asynchronous programming to scale and improve the application performance when blocking operations, and when CPU-intensive tasks are required.
Android is an open source operating system (OS) based on Linux kernel that was devised in 2003 by Andy Rubin, Nick Sears, Chris White, and Rick Miner, and then acquired by Google in July, 2005.
The Android OS, actually maintained by Google and the Open Handset Alliance, was created to provide an open mobile-device platform for devices with limited resources of computation, memory, and energy.
The platform has been incorporating advanced mobile devices standards, such as NFC and Bluetooth LE, and its scope has grown from a pure smartphone platform to a broader software platform for smart watches, TVs, tablets, and consoles.
The maintainers have been regularly updating the platform with great features and some improvements over minor and major releases since the first release.
The following diagram displays the Android versions over time:

Android software stack (C libraries and Java frameworks), orchestrated by the Android runtime (Dalvik VM, and most recently, ART) was created around the Linux kernel to provide highly interactive user experiences over a well-proven group of technologies.
In each new OS version, a well-defined application interface (API) is provided to the developer in order to create applications around the new features and standards introduced with the release.
The Android application compiled code (bytecode), typically a Java compiled code, runs on a virtual machine based on Dalvik or ART.
The Dalvik VM (DVM) runtime, created by Dan Borstein, was the first runtime for the platform and is a register-based virtual machine that was created to run the Java code efficiently in a constrained runtime with a limited amount of power processing, RAM, and electric power.
Dalvik's creators claim that the DVM is, on an average, around 30% more efficient than the standard Java VM (Oracle). According to Bornstein, it requires 30% less instructions and 35 % less coding units.
Clearly, Google has gone to great lengths to squeeze every drop of performance out of each mobile device to help developers build responsive applications.
The virtual machine, which runs the Java code compiled and transformed to the dex format over the dx tool, runs on a Linux process with its own memory space and file descriptors. It also manages its own group of threads.
In more advanced architectures, an Android application might run a service in a separate process and communicate over the IPC mechanism, but most of the time, it runs on a single self-contained process.
The dex file and application resources are packed in an Android application package (APK) by the AAPT and installed over Google Play in the end user devices.
Note
The application store distribution model has become extremely popular on the mobile platforms since the launch of the Apple iPhone in 2007.
Since Android 2.2 the DVM comes with a trace-based Just-In-Time (JIT) compilation feature that actively optimizes every time the application runs some short segments of frequently used bytecode called traces.
The generated machine code provides significant performance improvements in the application execution and on the time spent on some intensive CPU tasks, and thereafter, decreases the battery power used.
The ART runtime is a new version of the DVM and was introduced to improve the runtime performance and memory consumption. The new runtime was introduced in Android 4.4 KitKat as an experimental runtime, and since the Android 5.0 Lollipop, it has become the main Android runtime.
This new runtime, making use of the ahead-of-time (AOT) compilation, brings new app-performance optimizations on startup time and application execution. The AOT, as opposed to DVM JIT (Just in Time), compiles the dex files during the installation time using the device dex2oat tool. The compiled code generated from the dex2oat tool generates system-dependent code for the target device and removes the delay introduced by the JIT compilation during each application execution.
The AOT compiler also reduces the number of processor cycles used by the application as it removes the time spent by the JIT compiler to convert the code into machine code, and then uses less battery power to run the application.
One of the drawbacks of the AOT compilation is the larger memory footprint in comparison with the JIT used by DVM.
With the new runtime, some improvements were also introduced in the memory allocation and on Garbage Collection (GC), resulting in a more responsive UI and better application experience.
Basically, the platform runs an instance of DVM/ART for each application, but large optimization of the platform is brought about by the way a new DVM instance is created and managed.
A special process called the Zygote (first life cell in an animal's reproduction)—the process that all the Android applications are based on—is launched when an Android device initially boots.
The Zygote starts up a virtual machine, preloads the core libraries, and initializes various shared structures. It then waits for instructions by listening on a socket.
When a new Android application is launched, the Zygote receives a command to create a virtual machine to run the application on. It does this by forking its pre-warmed VM process and creating a new child process that shares some memory portions with the parent, using a technique called copy-on-write (COW).
The COW technique, available on most Unix systems, only allocates new memory on the child process when the process tries to change the memory cloned from the parent process.
This technique has some fantastic benefits, as listed in the following:
First, the virtual machine and core libraries are already loaded into the memory. Not having to read this significant chunk of data from the filesystem to initialize the virtual machine drastically reduces the startup overhead.
Second, the memory in which these core libraries and common structures reside is shared by the Zygote with all other applications, resulting in saving a lot of memory when the user is running multiple apps.
Android is a multiuser, multitasking system that can run multiple applications in parallel, where all the applications attempt to acquire CPU time to execute its job.
Each application runs independently on an isolated Linux process cloned from the Zygote process, and by default, all the Android components run within the same process with the same name as the application package specified in Android Application Manifest (AAM).
The Linux kernel will fairly allocate small amounts of CPU time for application execution called CPU time slices. This time-slicing approach means that even a single-processor device can appear to be actively working in more than one application at the same time, when in fact, each application is taking very short turns on the CPU.
The Android operating system tries to maintain the application running for as long as possible, but when the available memory is low, it will try to free resources in the system by killing the processes with lower importance first.
This is when process ranking comes into the picture; the Android processes are ranked in the next five categories from the higher priority to the lower priorities:
Foreground process: This is a process that hosts an activity or service that the user is currently interacting with: a service started in the foreground or service running its life cycle callbacks
Visible process: This is a process that hosts a paused activity or service bounded to a visible activity
Service process: This is a process that hosts a service not bound to a visible activity
Background process: This is a process that hosts a non-visible activity; all background processes are sorted over a Least-Recently-Used (LRU) list, therefore, the most recently used processes are the last killed processes when they have the same rank
Empty process: This is a process used to cache inactive Android components and to improve any component startup time
When the system reaches a point that it needs to release resources, the processes available to be killed will be sorted, taking into account the process rank, last used processes, and components running.
The Android application always runs under a unique Linux user ID (UID) assigned to the application during the application installation so that the process runs on a sandboxed environment, which by default, isolates your data and code execution from other apps.
In some cases, a user could explicitly be required to share the UID with another application to have access to their data:
The preceding table that results from running the adb shell ps
command in the computer with Android SDK Table is a list of Android running processes.
The first column shows the user identifier (UID) assigned at the time of installation, the second column is the process ID (PID), the third column shows the parent process ID (PPID) that for Android applications is the Zygote process, and the last column shows the application package.
From this list, we can assure that the WhatsApp application is running under the user ID u0_a221
with the process ID 5993
and the parent process is the Zygote process with the PID 319
.