From command line we can interact with system services. For example, we can print a list of available system services. On Android 10 Pixel emulator there are 165 services, which we can compare to only 65 on analogous Pixel 3 XL emulator but with Android 4.1. A lot has changed over the years.
Some system services that we can interact with are the ActivityManager and PackageManager service. We can even interact with the StatusBarService which has its own system service.
Through command-line we can trigger binder transactions. Binder is an IPC (Inter Process Communication) mechanism, which is used for communication between system services and app and user apps as well. And we can invoke the following commands to show and hide the status bar:
service call status bar 1 (show the status bar)
service call status bar 2 (hide the status bar)
We can interact this way with many different services.
If we are really curious about what’s going on our Android device, we can invoke Process Status and show All. An Interesting thing that we can find here is init
. As theory says, init
is the 1st process on an Android device, and indeed it is the 1st because it has process id 1. And zygote
, which is the root process for all Java apps, has a certain process id. And of the Java apps that are running have the parent process id of zygote
.
stop zygote
start zygote
To play a little bit with zygote
, we can start or stop it. This triggers the whole user space to reboot. It’s not a complete reboot of our device, because we are basically stopping the parent process and also stopping all the child processes, and all Java spaces get restarted. And because kernel has a special check for whether zygote
is running or not, it instantly restarts it.
System Services are organized in a way that they are exposed to something called System Server. And System Server exposes services like Activity Manager, Package Manager, etc.
We cannot find this, if we try to look at running processes and search for something related to Activity Manager or Package Manager - these return no results. But instead we find something called System Server, which has the same parent process as zygote
.
And these System Services are exposed through System Server. So they are all running in the same process.
The interesting thing is that if we look at threads, we might find out that System Server runs on 132 threads. So all the 165 system services are running on 132 threads.
Also when we take a closer look, Activity Manager tuns on 3 threads and Package Manager runs on 2 threads.
A simple hello_world app needs to run at least 13 threads. Why? First of all, it has the main
thread.
We are essentially busting a myth. Because there’s a myth that Android apps run on a single thread. Not true, they run on at least 13. We have threads related to debugger, garbage collection, finalizing and reclaiming memory. We have something called RenderThread which renders our UI. And we have some open Binder threads which are used for communication, for example, with Activity Manager. They have their own threads, on which if they receive a call to start another activity. Then this call is redirected to the main
thread, and then another activity is started on the main
thread of the given app.
Essentially, it’s not true that Android apps by default are single-threaded, they are 13-threaded at least.
And we can create a bunch of other threads, in this case 5 new threads.
We can see them in this listing as well.
It’s a common misconception that Java threads are somewhat different than Linux system threads. They are not, they are just some handy abstraction of system threads. But in fact what’s going on is that the system created all these threads, not Java Virtual Machine.
And we can also see all these threads in a tab that perhaps not too many people look at. When we debug our app, we can see all these threads when they are running. And we can stop/resume them one by one. I’ve discovered recently that we can change values of variables when we are debugging.