The ActivityManagerService
class is probably one of the most important of all services that exist in an Android system. In this recipe, we will go through its major functions and highlight peculiarities of the service.
ActivityManagerService.java
is the source file and is located at ANDROID_SRC/frameworks/base/services/java/com/android/server/am
.
Open this file in a code editor of your choice. We will move through the
ActivityManagerService
file and understand its various components.The Activity Manager extends a class known as
ActivityManagerNative
, which implements the binder protocol for remote invocation. This code is written manually like we've written in the recipe on using IPC with our system service code. This was done as the AIDL compiler did not exist the time the Activity Manager code was written by Google employees.In the beginning of the file, there are various control variables for different aspects related to activities. One such variable is:
static final int MAX_ACTIVITIES = 20;
This defines the maximum number of activities that can be in the stack. It means the maximum number of activities that could be running at a time.
Another interesting variable is the duration the system waits for a process to be launched.
static final int PROC_START_TIMEOUT = 10*1000;
SDK developers will know that when using a broadcast receiver, the
onReceive()
method should finish fast. The timeout is governed by:static final int BROADCAST_TIMEOUT = 10*1000;
which is around
10
seconds.Scroll down in the file, there is a handler which does the majority of the work that does not require immediate return. As you may know, Android has the concept of a handler, which basically is a mechanism to execute code in a separate thread and have it return results later. The handler is defined as:
final Handler mHandler = new Handler() {
Some example tasks performed are the ANR dialogs, indicated by case
SHOW_NOT_RESPONDING_MSG
and the sending of broadcasts to registered receivers.Other functionality is implemented as methods that return synchronously. An asynchronous return means that the results of a request are returned to the caller at a later time, and not immediately, like a synchronous call.
There is a separate section in the sources for permissions manipulation and verification. The only public entry point for permissions checking is the method:
public int checkPermission(String permission, int pid, int uid)
All permission checks that are executed in the system go through this one method. Hence it serves as a reliable checkpoint to understand what processes are doing with respect to protected data and operations.
Following this, the Activity Manager has a group of methods that manage tasks by manipulating the activity stack. The stack is a data structure defined in the
ActivityStack.java
file in the same directory as the activity manager service.The following method is executed when the system has completely booted and is ready to start launching user processes:
public void systemReady(final Runnable goingCallback)
There are separate sections managing services, content providers, and broadcasts. At the start of each section, a comment indicates what type of methods follow. Various API methods such as
registerReceiver
,startActivity
, andstartService
are implemented by theActivityManagerService
class in the same file.
The Activity Manager service is started early during the bootup process. At the end, when all the initialization tasks are complete, the systemReady
method is executed and the system boot complete broadcast is fired. This method is called by the SystemServer
service. It is used to notify the ActivityManagerService
that the system is at a point where it is possible to start running third-party code. While the ActivityManagerService
does not immediately do this, it gets itself ready when it receives the systemReady
call.
Whenever you make changes to the ActivityManagerService
class, make sure that you don't introduce code paths that make the service vulnerable or leak sensitive data to malicious applications. Always follow the principles of secure coding and protect your methods by permission checks. If you don't want third-party developers to access your functionality, assign a signature permission to that method. The keen reader will have noticed that the ActivityManagerService
class is like any other system service and executes in the context of the SystemServer
service. Hence, now you realize that your custom system service executes alongside such important services. Any bugs in your system service have the potential to bring down the whole framework. So be careful when writing such code!