Exploring Android Processes

A few weeks ago I was fixing a bug in Android Studio and came across the “android:process” tag. (I work at Google on the Android Studio team.) I knew the tag allows you to specify the process the android component will run on. However a lot of the finer details and reasoning behind Android processes was unknown to me. So I read up on it and wrote this article to share what I learned.

As always, I’m happy to be corrected on anything I’m misinformed about.

An overview on Android Processes

Android is based on linux so “the Android system starts a new Linux process for the application with a single thread of execution. By default, all components of the same application run in the same process and thread (called the “main” thread).” (from: Process and Threads Overview)

Generally the “main” thread is also the “UI” thread or the “event” thread, as any UI modification or event handling occurs on this thread. (exception: y̵o̵u̵ ̵c̵a̵n̵ ̵c̵h̵a̵n̵g̵e̵ ̵t̵h̵i̵s̵ ̵b̵y̵ ̵u̵s̵i̵n̵g̵ ̵T̵h̵r̵e̵a̵d̵ ̵A̵n̵n̵o̵t̵a̵t̵i̵o̵n̵s̵.̵ I was wrong, it’s only possible for systems apps to have different MainThread and UIThread: “The build tools treat the @MainThread and @UiThread annotations as interchangeable, so you can call @UiThread methods from @MainThread methods, and vice versa. However, it's possible for a UI thread to be different from the main thread in the case of system apps with multiple views on different threads.”)

By default the main process (and the main thread it starts) runs with a process name that is the same as applicationId of the application (declared in your app’s build.gradle). So if you were to create a default project with Android Studio, you’d get an Android app that will run on thread: com.example.<username>.myapplication and the matching default package for your code.

What the “android:process” tag does

By default an Android app will only have a single process. All components will run on the same process. When declaring new components in your application’s manifest, you can use the “android:process” tag to declare a new process for this component. Like so:

<activity
android:name=".SettingsActivity"
android:process=":setting"
android:label="@string/title_activity_settings">
</activity>

In the snippet above I declare a SettingActivity that will run on the local com.example.kelvinma.myapplication:setting process. (more on local vs global later in this article)

The “android:process” tag can be applied on the 4 android components:

  • Activity
  • Service
  • Receiver
  • Provider

and also on the Application tag. When applied on the Application tag, any components of the application also inherits the android:process unless overridden by their own android:process tag.

I’m not sure what the use case is for using this tag on your application declaration when you can just change your applicationId instead. If you know of one, please tell me.

A short visual example

To illustrate a multi-process app, suppose I start the default activity on my Pomodoro application then using the snippet above, I change my SettingsActivity to run on another process. Then after starting my app and the starting the SettingsActivity, my application will have 2 processes:

$ ./adb shell ps | grep kelvin
u0_a61 32175 1669 1292180 47600 SyS_epoll_ b738f2b5 S com.example.kelvinhanma.pomodoro
u0_a61 32223 1669 1284796 43736 SyS_epoll_ b738f2b5 S com.example.kelvinhanma.pomodoro:setting

However, all components implicitly run on the default process unless otherwise specified by the process tag. So if you add android:process=":setting"to your default activity and then start another activity, your app will have 2 processes:

com.example.kelvinhanma.pomodoro:setting
com.example.kelvinhanma.pomodoro

Because the started activity will start on the default process as it does not have an process tag set.

When do I make my app multi-process?

There are 2 reasons I know of to create a multi-process app:

  1. Your app has separate actions that needs to be run independently, the common example is a music playing app would have the default process handle UI and another process to handle music playing.
  2. Your app is hitting memory constraints. Android limits the RAM usage on a per process basis. So you can increase your app’s total RAM limit by running multiple processes. However since processes do not share memory, you cannot share Singleton’s between processes.

Local vs Global process

The type of the process is dependent on the value you enter in the process tag. If you start with a colon (“:”) then the process is a local one that is private to your application (full process name would be applicationId:processName). If you start with a lowercase letter then it is a global process.

A global process can be shared between applications. Often a library will run on a global process so multiple applications can share the process to reduce memory usage.

android:process quiz

Let’s end with a few scenarios, see if you can predict the answer.

Q: What happens if you use a global process to set your process to your package id? android:process="com.example.kelvinhanma.pomodoro"

A: Your process remains unchanged and this is allowed. Although it’s a pointless and silly thing to do.

Q: What if you use it to set your process to another app’s package? Suppose I have a com.example.kelvinhanma.pomodoro running on my device. I set the global process of another app to the same name and deploy it.

I’d end up with 2 processes with the same name!

./adb shell ps | grep kelvin
u0_a181 28008 630 4324212 66060 SyS_epoll_wait 0 S com.example.kelvinhanma.pomodoro
u0_a179 28287 630 4327384 66200 SyS_epoll_wait 0 S com.example.kelvinhanma.pomodoro

But that’s fine. Process names don’t have to be unique. Notice the users are different (u0_a181, u0_a179) and the process ids are unique.

Hope you enjoyed the article and learned something. Feel free to let me know if something is incorrect!

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.