Note: Read the first part before proceeding.
Part II : Deep Dive into Android Internals (You are here)
Merry Christmas and a Happy New Year (in advance) !!!
As promised I’m gonna reveal in this post about rooting and all that stuff. But before that we’ll look into
init . We are also look into how two apps communicate with each other and not compromising the security of the operating system (Even though Android is the least secure mobile OS 😜).
init is what starts the daemons and other pre-defined settings in Android.
init is something that Android borrowed from Linux Kernel. As the name suggests,
init in layman’s terms initialises the world of Android for users. In terms of developers
init does the following things:
- First user space process
- The root of all other processes
- Spawns everything else
Some processes that
init starts are
zygote etc. All the of the said processes are
A daemon is a type of program on Unix-like operating systems that runs unobtrusively in the background, rather than under the direct control of a user, waiting to be activated by the occurrence of a specific event or condition.
Stands for Android Device Bridge Daemon. The developer docs define
adb as following:
Android Debug Bridge (adb) is a versatile command-line tool that lets you communicate with a device. The adb command facilitates a variety of device actions, such as installing and debugging apps, and it provides access to a Unix shell that you can use to run a variety of commands on a device.
ADBD on the other hand is a daemon which runs in background(obvious). The role of
adbd is to run commands on the device according to the client.
As said above
zygote is also a daemon. The reason there is a bigger circle around zygote is because its the most important daemon for developers. In fact sometimes if you carefully read the logcat you will notice that it contains zygote. Anyway the question is what is zygote and why do we need it?
To understand this, we’re gonna look into how a Unix process actually forms. In a traditional Unix Desktop each process is
fork() ed from the Kernel. (FYI thats where the the GitHub fork comes from). Forking is nothing but an operation whereby a process replicates itself. The most important thing to note that in Unix/Linux this happens from the kernel itself. This is a rather slow process but with the processing power of a PC its fast. This is where the requirement of
zygote comes from. To speed up the process of opening up apps Android Developers have created a
zygote from which each process is forked.
So instead of forking up all away from kernel it forks from something that specifically designed to launch apps. In summary, Zygote is a shortcut process that is sitting and waiting to run our Java/Kotlin code.
Don’t worry about
Dalvik/ART . They are process virtual machines, i.e they are designed to execute computer programs in a platform-independent environment.
Now as an Android Developer you might have used Content providers system or custom to share data between apps. Ever wondered why use Content Providers? Thats because Android won’t allow apps to directly exchange data or memory like Linux. In a typical Linux system each app is running under a user/admin so apps, so if you notice by typing
ps aux in terminal most of the apps have root or some other
uid. But in Android in order to implement security and robustness each process is treated as a different user. Thus each process has a different
How do apps communicate with each other?
As we talked earlier apps can’t communicate with each other in Android. But then we(developers) see that apps do communicate with each other. How is this possible?
Enter Android Binder IPC.
What is Binder? The short answer is binder is like a clock pulse in a flip-flop. It keeps your system in sync by communicating between various processes and services.
Before that what is IPC?
IPC stands for Inter-Process Communication. It is a framework for exchange of data and signals across multiple processes. Used for message passing, synchronisation, shared memory, and remote procedure calls (RPC).
There’re many IPC options. Some of them include:
- Sockets (UNIX)
- Intents, Content Providers
and many others!!
There’re many reasons why Android uses Binder. Some of them are thread migration, simple Android Interface Definition Language(AIDL) etc. Most of the important apps and core system services work on Binder. Activity life-cycle callbacks like
onDestroy() are invoked by
ActivityManagerService via binder. Turn off the binder and entire system gets halted.
Intents and Content Providers
Perhaps the most simple Binders in Android are
Intent messaging is a framework for asynchronous communication among Android components. Those components may run in the same or across different apps (i.e. processes).
ContentResolvers communicate synchronously with ContentProviders (typically running in separate apps) via a fixed (CRUD) API.
All communication happens on the Looper i.e the Main Thread( by default).
For example :
Funny enough right? You have been using Binders without knowing it. There’re many more like Messenger IPC etc. which I leave it you for exploring.
Managers in Android/ System Server
System Server is also initialised by
init and forked from
zygote . The
System Server is the heart of Android Application Management. It manages things like location, Wi-Fi, Battery etc. It is modular in nature which means there are several managers to handle different things. Some of them are listed below:
WindowManager: This is responsible for managing all windows in our phones. This might include transition between apps or opening of menus etc. It also includes system gestures like drawing a curve to open an app or something.
PackageManager: This is responsible for looking into our
manifest.xmlfile. It also resolves the correct activity to be opened when the app is launched.
Activities Manager: This is the most important of the managers. It manages lifecycles, applications (activities, services, content providers) etc. It manages excessive power usage and configuration changes. The
ActivityManageris also responsible for giving
oom_adjscores to processes. (Refer to Part 1).
Activities Manager manage applications?
Enter Data Structures!!!! The manager creates one or more stacks inside which it stores tasks which correlates to a process(≥1). The task can be one more activity.
How does a process relate to activity?
Alright. Up until now we were talking about processes. But how does a process relate to activity? Let’s find out.
Above is the diagram case of a Single Activity App. The
ActivityManager creates a record which identifies an activity and stores it as a task in stack. This task has a process which consists of the
Above is the diagram for multiple activities in a single app. Here two records are created in one task. This task associated with
MyApp process creates another activity inside it.
Now what if another app is opened by the user?
As we can see another task is created with a new record inside in it. This task has a corresponding process called
NewApp process. This was fairly simple. But what if we want to open another app from
NewApp . This may arise when I want to share something or click a photo using camera etc.
As we see above, the record gets migrated to another task but the process remains same. So whenever you open an app through another app you migrate the task but the process remains the same. This is to increase the security as if the process is same then sharing resources becomes easy.
What do you mean by rooting?
This is where the fun stuff starts. All the pre-knowledge that you got from reading Part I and II can be applied here. Note that I am not telling you to root your phone or neither is this a tutorial on it.
Warning: Enterring sudo mode
Now, as we said before Android uses Linux based Kernel, which means it uses a permission based system. Every file, every folder and every partition has a set of permissions. These permissions decide who can read a file (look at or access the contents without changing them), write to a file (be able to change the contents of that file, or create a new file inside a folder or partition) and execute a file (run the file if it’s a type that can run, like an app).
When you first set up your phone and turn it on for the first time, you are assigned a user ID. If another user logs in via Google, they are assigned a different user ID. When an app is installed on your phone, it’s also assigned a user ID of its own. The system itself is a user and other processes that need to run on your phone may have their own user ID. Everything that can do anything to any files on your Android is a user.
While it’s technically possibly to change the way your phone boots up and the files it uses to start the running system and assign your user ID elevated permissions, that’s neither safe nor practical. But Android (and most Unix or Linux based systems) have what’s called a root user, and support the
SubstituteUser binary (think of a binary as a small app) to change user IDs. Those are used to administrate the system at the core level.
No surprise, that Android phone manufacturers for better or worse don’t include the
SubstituteUser binary. The core system files i.e bootloader are even modified so that you don’t switch user ID’s.
Assuming you have done all this, you get the
root access. Funny thing about Android, when you type
su in the terminal you directly get the
root access instead of typing your password. This is because
root is an unused user in Android.
root/superuser access you can literally do anything in Android. You can delete bloatware, you can change the CPU frequency, you can insert custom ROM and many more things. Remember with great power comes great responsibility. Getting
root access is a door to many options including ruining your phone forever.
That’s it. Hope you enjoyed the series. Clap and Follow me to get more articles related to Android. As usual suggestions are welcomed through comments below.