Overview of Android Architecture and Development
Overview of Android Architecture and Development
Android is a platform for mobile devices (phones, PDAs, netbooks, tablets, etc.). It is
composed of an operating system, middleware libraries, and a set of applications: a
client email, a browser, a calendar, etc.
Android is based on a Linux kernel. The middleware libraries that compose it are written in C/C++.
The framework is written in Java.
OHA
Android is developed by the OHA (Open Handset Alliance), an international alliance of companies. This
alliance consists of companies that are not part of the same sector.
Thus it is composed:
History
In July 2005, Google acquired Android, Inc., a small startup that was developing applications for
mobile phones. It was at that time that rumors about Google's entry into the sector began.
Mobile had begun. But no one knew which markets they were going to position themselves in.
After this acquisition, at Google, a team led by Andy Rubin, a former member of Android Inc, began to
work on a mobile operating system based on Linux. For 2 years, before the OHA
officially created, a number of rumors have circulated about Google. It has been said that
Google was developing mobile applications for its search engine, which they were developing a
new mobile phone, etc.
1- General overview:
Android is based on a Linux [Link] kernel, above the kernel is the hardware abstraction layer.
which allows separating the logical platform from the hardware.
Above this layer of abstraction, we find the C/C++ libraries used by a certain
name of components of the Android system.
Above the libraries, we find the Android Runtime; this layer includes the core libraries of
Framework as well as the virtual machine running the applications.
Above the 'Android Runtime' layer and the core libraries, we find the Framework that allows
to the developer to create applications. Finally, above the Framework, there are the applications.
2- Linux Kernel :
Android is based on a Linux 2.6 kernel but it is not Linux. It does not have a system of
native windowing (X window system), glibc is not supported, Android uses a custom libc
called Bionic libc.
Finally, Android uses a kernel with different patches for power management, sharing
memory, etc. allowing for better management of these characteristics for mobile devices.
The Linux kernel has a memory and process management system recognized for its
stability and its performance.
The security model used by Linux, based on a permission system, known for
to be robust and efficient. It has not changed since the 1970s.
The Linux kernel provides a driver system allowing an abstraction with the
material. It also allows for the sharing of libraries between different processes, the
loading and unloading of hot modules.
the Linux kernel is completely open source and there is a community of
developers who improved it and added drivers.
It is for the points mentioned above that the team in charge of the core decided to use a
Linux kernel.
Alarm
This patch provides a number of timers that allow, for example, to 'wake the device when it
is in sleep mode
Ashmem
Interprocess communication (IPC) can lead to security holes, which is why Android has
its own IPC, the Binder, and that interprocess communication is not left to developers
of the application. Moreover, having a centralized IPC system allows for easier maintenance and a
correction of general security issues.
In Android, each application runs in a different process. These different processes have
Need to communicate together, to share data. This IPC is possible with the Binder.
It allows multiple processes to share data, to communicate with each other using the
memory sharing (ashmem driver). This technique allows for improved performance compared to
copy data into memory, or serialization.
Concurrency issues, when multiple processes try to access at the same time to a
Same memory zone (on the same java object) is managed by the Binder. All calls are synchronized.
between the processes.
Operation
IPC
With its emphasis on isolating apps and services in process boundaries, it is clear that Android
requires a lightweight IPC. The IPC mechanism in Android is called Binder and is based on
shared memory. Recall that when a process starts it registers itself with the Service Manager.
This happens behind the scenes, and upon registration, each process gets what is called
aContextobject – a reference to the Service manager. Now let's say app A needs to
communicate with service B, and the two are running in two separate processes. To do this, app
A asks the Context for Service B by passing the well known name of the service. The Context
returns a reference to the service to A, on which A can call a method–say foo. This method call
is intercepted by the Binder driver. The driver marshals the object and passes a reference of it to
the receiver–B. Note that this is passing by reference, not passing by value, in which the object
is serialized. On the side of the service B, the Binder maintains a thread-pool (transparent to the
service). One of the threads in this pool receives the incoming call, locates the actual object in the
service B and make the call. The return value is then similarly passed back to the caller.
following diagram (from[Link]
illustrates this:
Application A retrieves a reference to Service B using the Context Manager. The Context Manager
can be compared to a DNS. It allows retrieving a reference to a Java object using a name.
For those who know RMI (Remote Method Invocation), it is the registry. If we want to share some
objects must first be registered in the Context Manager.
Once the reference to service B is retrieved, the foo() method of service B is called by
the application A. The binder intercepts this call, and with the help of one of the free threads present in its thread
pool (thread pool or thread reservoir), it will execute the method on service B.
Food management:
Issue:
Mobile devices depend on battery power and batteries have a limited capacity.
Android supports its own Power Management (based on the standard Linux Power Management),
designed on the principle that the CPU should not consume energy if none of the applications or
services require a power supply.
Android requires applications and services to request CPU resources with 'Wake Locks' at
through the Android Application Framework and the native Linux libraries.
If there are no active 'Wake Locks', Android will stop the CPU.
FULL_WAKE_LOCK Wake lock that ensures the screen and keyboard are fully on
brightness.
ON_AFTER_RELEASE When this wake lock is released, reset the activity timer.
the user so that the screen stays on for a little longer.
PARTIAL_WAKE_LOCK Wake lock that ensures the CPU is on. The screen may not
to be on the move.
3- The Bookstores
Above the kernel are the native libraries. These libraries are written in C/C++. They provide the
low-level features of Android.
Bionic Libc
Android does not support glibc, which is why we developed a C library (libc) called Bionic libc. It is
optimized for mobile devices and was developed especially for Android.
The Android platform needs its own libc because it needed a lightweight libc (the libc will be loaded
in each process) and fast (mobile devices do not have powerful CPUs).
The Bionic libc was written to support ARM CPUs, although x86 support is present. There is no
support for other CPU architectures such as PowerPC or MIPS. Nevertheless, for the market of
mobile devices, only the ARM architecture is important.
The ARM architectures, developed byARM Ltd are 32-bit RISC architectures.
Equipped with a relatively simpler architecture than other families of processors, and benefiting from a
low power consumption, ARM processors have become dominant in the field of computing
onboard, particularly mobile telephony and tablets.
Features:
It has a size of about 200KB, which is half of glibc.
The implementation of pthreads (POSIX thread) has been completely rewritten to support threads.
from the Dalvik virtual machine. As a result, the Bionic libc does not support POSIX threads
WebKit supports CSS, Javascript, AJAX. The version of WebKit present in Android has been
slightly modified to adapt to mobile devices.
Media framework
The Media Framework library is based on OpenCore from PacketVideo. It enables support for
audio/video/images standards.
Android Media Framework is built on top of a set of libraries of
media, including OpenCore, vorbis, and SONiVOX. So, one of the objectives of Android Media
The framework is to provide a consistent interface for all services provided by the
underlying libraries and make them transparent for users.
The figure below shows the dependency relationships between the media libraries.
framework.
In this figure, the green components are the media libraries, the internal Android libraries are
yellow components, the gray components are the external libraries, and the class of
light blue is the Java consumer of the media framework. Except for the class
[Link], all components are implemented in C or C++.
The core of the Media Framework is composed of libmedia, libmediaplayerservice, and libmedia_jni.
libmedia defines the inheritance hierarchy and the base interfaces. It is the core library.
libmedia_jni is the intermediary between the Java application and the native library. First, it
implement the JNI specification (The JNI (Java Native Interface) is a framework that allows for
Java code running inside the JVM to call and be called by applications
natives (that is to say specific programs to the hardware and operating system of the
platform concerned), or with software libraries based on other languages (C,
C++, assembler, etc.) so that it can be used by a Java application. Secondly, it
implement the facade model for the convenience of the caller.
libmediaplayerservice concretely implements certain Media Players and services
media that will manage the instances of these readers.
What is interesting to note in Android is that the application that intends to display the
Media content and the player that actually displays this content (audio, video...) function
in different processes. The red line in the sequence diagram below shows the
limit of two processes.
The figure shows the three most common operations: creating a new Reader, updating
DataSource and Reading. The last object MediaPlayerBase is the interface which object
MediaPlayerService::client is used to refer to the instance of the concrete player. The player
concrete can be VorbisPlayer, pvPlayer, or any other Player, depending on the type of
average you.
Having the above knowledge, it is not difficult to understand why MediaPlayer does not
does not provide an API to use as a memory stream source. Because the memory manipulated
by the flow is in the application's address space, and it is not directly accessible by
the media server process.
The diagram below describes all the features provided by this library:
Media libraries – based on OpenCore's PacketVideo; the libraries enabling playback and
audio and video recording, as well as image file management, including MPEG4, H.264,
The diagram below describes all the elements of the architecture of these media libraries:
SURFACE FLINGER :
The Surface Flinger allows for the construction of graphical rendering; it manipulates all the surfaces to be displayed.
coming from the frame buffer. It can combine 2D and 3D from different applications.
The surfaces to be displayed have passed through buffers via the Binder.
The surface flinger uses a double buffer allowing for quick switching from one surface to another.
This double buffer also ensures that incomplete surfaces are never displayed, as the second
The buffer is only displayed when it is full. The two buffers are used alternately.
It can use OpenGL ES and hardware acceleration for 2D rendering using the Khronos API.
Audio Flinger
The audio flinger manages all audio devices. It processes audio streams and routes them to the devices.
output (speaker, Bluetooth, headset).
The Hardware Abstraction Layer
This layer is situated between the libraries and the Linux kernel, it provides the interfaces that must
implement the kernel drivers. This layer separates the logical platform from the hardware interfaces. The
The purpose of this layer is to facilitate the portability of libraries across different hardware.
Dalvik
The Dalvik virtual machine is based on a register architecture like many machines.
virtual and the Java virtual machine that has a stack architecture.
Using a stack or register architecture depends on the strategies of compilation and interpretation.
choose. Generally, machines based on a stack architecture must use instructions
to load the data onto the stack and manipulate this data. This adds instructions into the
code machine, and therefore there is more code than for a machine based on a register architecture.
Java applications developed for Android must be compiled in the Dalvik executable (.dex) format.
with the dx tool. This tool compiles .java files into .class files and then converts these .class files into .dex. A .dex can
containing multiple classes. The duplicated strings and other constants used in multiple classes
are grouped in a .dex. The bytecode used in .dex is Dalvik bytecode and not Java.
Bytecode.
For comparison, a decompressed .dex is a bit smaller in size than a compressed .jar derived from
same .class files.
Being optimized to use minimal memory, the Dalvik VM has a few characteristics
specific compared to other VMs:
The Core libraries provide the Java language available for applications. The Java language comes with
Android largely takes over the JSE 1.5 API. There are things that have been set aside because they were not
of meaning for Android (like printers, swing, etc.) and others because of specific APIs
are required for Android.
JSE 1.5 packages supported by Android Packages JSE 1.5 unsupported by Android
[Link] [Link]
[Link] (except [Link]) [Link]
support [Link]
[Link] [Link]
[Link] [Link]
[Link] [Link]
[Link] [Link]
[Link] [Link]
[Link] [Link]
[Link] [Link]
[Link] [Link]
[Link] [Link]
[Link] (except [Link]
[Link]
[Link]
[Link] and
[Link] [Link]
[Link] [Link]
[Link] (except [Link]) [Link]
[Link] [Link] (except [Link])
[Link] [Link].*
[Link] [Link].*
[Link].*
[Link]
[Link]
[Link]
[Link]
The Application Framework:
The framework is located above the Android Runtime and libraries. It provides APIs that allow for
developers to create rich applications.
Android introduces the concept of services. A service is an application that has no interaction with
the user and runs in the background for an indefinite time.
The core services of the platform (Core Platform Services) provide essential services to
functioning of the platform:
Activity Manager: manages the application lifecycle and maintains a 'navigation stack'
(navigation backstack) allowing you to go from one application to another and return to the
previous when the last opened application is closed.
Package Manager: used by the Activity Manager to load information from the
APK files (Android Package Files)
Window Manager: just above the Surface Flinger (link), it manages the windows of applications:
Which window should be displayed in front of another on the screen?
Resource Manage: Manages everything that is not code, all resources --> images, files
audio, etc.
Content Provider: manages the sharing of data between applications, such as the database
contact data, which can be accessed by other applications besides the Contact app.
Data can be shared through a database (SQLite), files, the network, etc.
View System: provides all the graphical components: lists, grid, textbox, buttons, and even a
embedded web browser.
Hardware Services
A-Like any Linux system, at startup the bootloader loads the kernel and starts the
init process. The father of all processes.
B-Then a certain number of daemons are launched by the init process:
Thereafter, the init process launches the Zygote process. At startup, an instance
special Java virtual machine is launched, called zygote. This process loads a
basic Java classes and perform their initial processing, making it possible
to avoid this step for each app launch. Once the initial work is
Indeed, the process is waiting for requests by listening on a socket.
Then the initialization process starts the Runtime process which will in turn launch the Service Manager.
("DNS" providing a way to communicate with a service by its name, responsible for
the management of the IPC allowing to record and retrieve references to Android services
and register this Service Manager as the default Context Manager.
C-Once all of this is done, the Runtime process sends a request to the zygote process itself.
requesting to launch the System Server. Zygote will fork a new instance of Dalvik VM
for the System Server process and start the service. This is the first process (after
Zygote) which executes an instance of Dalvik VM.
The D-Le System Server will launch the Audio Flinger and the Surface Flinger, which will then ...
register with the Service Manager.
The E-Le System Server then launches the Android services (window manager, manager
telephony, Power Manager, activity manager, etc...). These services once launched
will register with the Service Manager.
Once all services are loaded, the system is ready. User applications can be
launched.
At this stage, we have the following processes in place:
1. Init - the original initialization process began with the boot program
4. Zygote - the original zygote that will endlessly create forks for new applications.
be launched
5. System Server - the first managed process that contains all the services and components of the
base platform.
After that, the home screen or screensaver is launched - essentially the task manager.
(which is inside the server system) sends a message to Zygote to launch the 'Home' activity, this
which causes Zygote to fork into a new process of a Dalvik VM for the activity
"Home." Now, depending on the action taken by the user, the appropriate application would be
launched with the Zygote fork each time to create a new VM instance in a new
process. Thus, for example, if the user launches the Contacts application, the apt process would be
installed
Each new application receives a unique user ID that is unknown to the application, and the
system defines permissions for all files in the application so that only the ID
the user assigned to the application can access these files. this makes the system secure since
It is the only application that has access to the components it needs to do its job and nothing else.
other. However, applications may need to communicate with each other and with the
system services, which are all executed in separate processes. This is accomplished through the
Binder IPC
Applications
An Android application is a collection of components. There are four types of components:
Content provider: A content provider is an element that stores and retrieves the
data and makes it available to all applications. There are different types of
content providers: audio, video, contacts, etc. and you can create your own
content provider as well.
As mentioned earlier, each application runs in its own process. By default, all components used
by that app also run in the same process, and on the main thread. However, it is possible to make
a component of your app runs in a separate process through the manifest file. Thus, an application in
Android may span multiple processes.
Starting an Application
Android is quite a unique model in that there is no single entry point for a
application - there is no main() function.
On the other hand, a component in an Android application can start another in another
application. This communication between applications happens through the IPC mechanism
described previously. Thus, while the activity is held by an application, it is possible for
another application of the launcher (if the proprietary application allows it).
1. In the event that the application is not already launched, the Android system would bring the application to the
lives in a new process by forking the zygote.
Note that in the case where the application is already running, the new component will be instantiated by
defect in the same process.
As mentioned above, the IPC goes through a 'Context' object. So, when a component
"A" inside an application must activate another component "B" in an application
different, or give him something new to do, he essentially uses the object
« Context » to send a message to the other component. In the case of an activity, service or
A BroadcastReceiver takes the form of what is called an 'Intent.'
It is a passive data structure that defines the operation to be performed for an activity and a
service, and for a BroadcastReceiver, it is a definition of the ongoing broadcast declaration.
Content providers are not activated by Intentions, however. Instead, the activation
occurs at the request of a ContentResolver, which acts as a mediator between the component
requester and the content provider.
The Back-Stack
Let's consider the following scenario:
2. You click on the Mail application icon, which activates the main activity in the Mail application.
which appears in the foreground. It is activity 2
3. You now click on Compose, which activates the composing activity in the application.
Mail. This is activity 3
4. You decide to cancel composing a new message and press the back button.
You are returning to activity 2
Here is what is happening in the background:
When one activity starts another, it stops and its state is saved. So, when
Activity 1 starts Activity 2, activity 1 is stopped, its state saved and so on.
The system maintains a stack (called a Back-Stack) with the latest activity on top and the
older activity at the base.
When the user presses the back button on the device, activity 3 is removed from the stack and
Activity 2 has started from its saved state.
The Tasks
In the scenario described above, it is assumed that when the user has been in the application
New Mail (Activity 3), he decided to call someone and pressed the Home button. It's not going to
do not unstack theback-stackbut start a new stack. To do this, the collection of activities
in the first stack needs to move to the background. This is achieved through the concept of 'task'
A task is a coherent unit of Activities. When a task moves to the background, all the
activities in this task are stopped, but theback-stackthe task remains intact, so that
when the user returns to the task, it can resume where it left off. However, for
save memory, theback-stacka background task is not retained for a very long time
period and if the user does not return to the task, theback-stackis erased, with the exception of the activity
root.
Life cycle of an activity
The life cycle of an activity is influenced by its association with other activities, its
mission and its back stack. There are three states in which an activity can exist:
• Replay / In execution: The activity is at the forefront and has user focus. Such
activity is never killed by the system.
• On Pause: The activity is visible, but another activity is in the foreground and has the focus
user. This could happen if the other activity is at its peak, but it is translucent, or
because it does not cover the entire screen. In the pause state, the activity is preserved in
memory, maintains all state information and remains attached to the window manager.
However, it can be killed under extremely low memory conditions.
• Stopped: the activity is not visible to the user. While the activity is retained in
memory, keeps all state information, it does not remain attached to the manager of
windows. The activity can be killed by the system to recover memory if
necessary.
State of activity recording
In order to recover memory, note that it is quite possible that the system can
to destroy an activity, or even the process in which the activity was underway. However,
when the user returns to the activity (via the back stack), we resume from the point where the user
left. To do this, an activity must record its state. This happens through the method
onSaveInstanceState ().
Process life cycle
The Android system may need to kill a process in order to recover from
memory. In order to ensure that this creates minimal impact on the user experience,
Android organizes processes in a priority order:
•Foreground process: A process that is required for what the user is in.
such a process is only killed as a last resort
• Visible processes: This process is not at the forefront, but it can affect what
the user sees on the screen. For example, it can host a paused activity. Such
the process is not killed unless it is necessary to maintain all the processes of the
first plan, in execution
• Processus Service: A process that executes a service and is not one of the two types mentioned.
on top. For example, the service can play music or download
something. The system can keep such a process running as long as there is enough
memory to keep the foreground processes running and visible.
Background process: A process that manages an activity that is not currently
visible to the user (the activity is stopped). Such a process has no impact on the experience
user (if the activity lifecycle is correctly implemented and the activity status
is correctly saved and restored). The system can kill such a process at any
Usually, there are several background processes and the system maintains
a LRU list that is used to kill these processes.
• Empty processes: an empty process holds no active components. The only reason for
that such a process be kept alive, first of all, is for caching and
the improvement of startup time. The system often kills these processes in order to
maintain the balance between process caches and the underlying kernel caches.
Of course, it can happen that a high-priority process is dependent on a process of
low priority. In such a case, the ranking of the serving processes increases to the same level as
that of the dependent process.
Your application needs to download something large that may take time and
The user is likely to move away from the application's activity to something else.
If you create a thread for this task and the user moves, the process becomes a
background process.
However, if you create a service instead, the process would be a service process and will be
less likely to be killed
Main / UI Thread
When an application is launched and a new process is created to host it, the application
receives a single thread called the main thread or the interface thread since this thread is
responsible for the user interface service.
Basically, the user interface thread runs an infinite loop that checks a queue.
waiting to see if there are any ongoing user interface events. In the case of Android, this
The concept is formalized in the form of a looper.
Le looper traite une MessageQueue (file de messages) qui contient les messages à être expédiés. La
The actual task of queue management is carried out by a manager who is responsible for the
manipulation (adding, removing, dispatching) of messages in the message queue.
For the main thread, a Looper is set up by the system. However, you can also
associate a Looper with your own thread.
Note that the Looper can be associated with a single thread and that the association cannot be
changée.
The way Android ensures this (the association cannot be changed) is by using the looper.
on the thread local storage of the thread and not expose a constructor for the Looper.
The Services
As mentioned earlier, a service is a type of component that is used to achieve
a background operation, and does not provide a user interface. A component of a
the application can start a service, and even if the user switches from the application, the service
continues to operate.
A typical use case is to play music and download a file. Android ensures for
a process of executing a service so that it is not killed as much as possible (see lifecycle of
above process).
Note that by default, a service runs on the main UI thread in the same process. This
means that if we perform a blocking operation, your interface will no longer respond, because the
thread would not be available to execute the activity. To work around this, you must start a
work thread within the service.