Android Thread Model

Process v.s Thread

Android OS is a kind of Linus system. Every time you launch an application on your device, it invokes a process to host this application and provides the necessary resources for the application. By default, all components that come from the same application would run in the same process and thread (called main thread or UI thread). By default, you would run all components, Activity, Service, Receiver, Provider, on the same process. But there’s a way for a specific need for developers who want to run these components on different processes. You can add android: process in the AndroidManifest.xml file in each component declaration. For example,

1
2
3
4
5
<activity 
android:launchMode="singleTop"
android:process="process_name"
...
/>

You might be interested in how the Android system manages the processes, for example, what if we run out of the system resources, let’s say the memory, which process is going to be closed? Here is how system weight each process:

  1. Foreground process
    There are three different scenarios for a foreground process.

    • It’s running an Activity which you are interacting with.
    • It’s running this method BroadcastReceiver.onReceive() in a broadcast receiver.
    • It’s running these methods, Service.onCreate(), Service.onStart(), Service.onDestroy() in a Service.
  2. Visible process
    How to define if this process is a visible process? Here are some criterias:

    • An Activity has been called onPause().
    • A Service has been launched by calling Service.startForeground().
  3. Service process
    A service process is a process that holds a service launched by startService().

  4. Cached process
    A process has been clarified as a cached process means this process is no longer interacting with the users. For example, an Activity has been called onStop() function. Android system would have a list for these processes and would delete them when the system resource is not enough.

You can check the AOSP source code in the ActivityManagerService.java to get more information about this. (services/core/java/com/android/server/am/ActivityManagerService.java - platform/frameworks/base)

We already have a picture of what the process is and how the Android system measures a process. Now, we need to dive into the process to see what a thread is and what main/UI thread means. When you launch an application, the Android system creates a thread of execution for this application called main. The main thread is responsible for dispatching events (included drawing events) to user interface widgets. Due to this reason, the main thread is sometimes called UIThread. The main thread is not always the UI thread. If you check the annotations, you can find two annotations called @MainThread and @UiThread. They are usually the same, but you can assign different threads as the UI thread too. If you check Activity.java in the AOSP project, you can see there are two variables that one is mUiThread and another one is mMainThread.

The Android system doesn’t create a specific thread to run different components that means, by default, all components run on MainThread. You are not allowed to do heavy work loading, such as network loading on the main thread. It would cause ANR - application not responding error. You would need to create another thread to handle these heavy-loading jobs. That comes to another problem. The Android UI toolkits are not thread-safe, so you can’t operate UIs in another thread, not in the main thread. You can send events back to the main thread to control the UI. For instance, you want to display a picture that comes from the internet,

1
2
3
4
5
6
7
Thread(Runnable {
// a potentially time consuming task
val bitmap = processBitMap("image.png")
imageView.post {
imageView.setImageBitmap(bitmap)
}
}).start()

You should post this update event to the main thread and update the image view.

Here is come high-level overview of the thread model in the Android system. I hope you find something useful in this article. Enjoy!

[Reference]

[1] Who lives and who dies? Process priorities on Android