Author: Tencent — Zhang Xinghua

At present, the applications on the market, except wechat and Q, seem to be more worried about being killed by users or systems (manufacturers). This article summarizes the Android process pull live.

Android process pull consists of two layers:

A. Provide process priority to reduce the probability of process killing

B. Pull the process after it is killed

The following is a summary from these two aspects.

1. Process priority

The Android system will hold on to application processes for as long as possible, but in order to create new processes or run more important ones, the old processes will eventually need to be cleared to reclaim memory. To determine which processes to keep or kill, each process is placed in an “importance hierarchy” based on the components that are running in the process and the state of those components. If necessary, the system will first eliminate the least important processes, then purge the less important processes, and so on, to reclaim system resources.

The importance of the process, divided into 5 levels:

  1. Foreground Process

  2. Visible Process

  3. Service Process

  4. Background Processes

  5. Empty Processes

Foreground processes have the highest, decreasing importance, and empty processes have the lowest importance. Each level of process is described below

1.1. Foreground Process — Foreground Process

Processes that are necessary for the user’s current operation. There are usually not many foreground processes at any given time. The system terminates them only when it is absolutely necessary that there is not enough memory to support them while still running.

A. Have an Activity that the user is interacting with (onResume() has been called)

B. Have a Service that is bound to the Activity the user is interacting with

C. “foreground” Service (Service is called startForeground())

D. have a Service (onCreate(), onStart(), or onDestroy()) that is performing a lifecycle callback

E. Have BroadcastReceiver that is executing its onReceive() method

1.2. Visible processes — Visible processes

A process that does not have any foreground components but still affects what the user sees on the screen. Visible processes are considered extremely important and will not be terminated unless necessary to keep all foreground processes running at the same time.

A. Have an Activity that is not in the foreground but is still visible to the user (onPause() has been called).

B. Have a Service bound to a visible (or foreground) Activity

1.3. A Service process

Although server processes are not directly related to what the user sees, they are usually performing some action that the user cares about (for example, playing music in the background or downloading data from the network). Therefore, unless there is not enough memory to keep all foreground and visible processes running at the same time, the system will leave the server processes running.

A. The service that is being started by the startService() method and does not belong to the above two higher categories of processes.

1.4. Background processes

Background processes have no direct impact on the user experience, and the system may terminate them at any time to reclaim memory for foreground, visible, or server processes. There are usually many background processes running, so they are saved in the LRU list to ensure that the process containing the Activity the user recently viewed is the last to terminate. If an Activity implements the lifecycle method correctly and saves its current state, terminating its process does not have a significant impact on the user experience, because the Activity resumes all its visible states when the user navigates back to the Activity.

A. The process of an Activity that is not visible to the user (the Activity onStop() method has been called)

1.5. Empty Process — Empty Process

The sole purpose of keeping such processes is to be used as a cache to reduce the startup time needed to run components in it the next time. To balance overall system resources between the process cache and the underlying kernel cache, systems often kill these processes.

A. Processes that do not contain any active application components

See: developer.android.com/intl/zh-cn/…

2. Reclaiming Android processes

Lowmemorykiller is a mechanism that triggers memory reclamation based on the OOM_ADJ threshold level.

The description of OOM_ADJ is as follows:

The red part represents the Android process that is easy to kill (OOM_ADJ>=4), the green part represents the Android process that is not easy to kill, and the other part represents non-Android process (pure Linux process). Lowmemorykiller reclaims memory and kills processes with higher OOM_ADJ based on their priority level, and processes with the same priority are further affected by memory usage and process lifetime.

The following conditions may occur when a process is killed on an Android phone:

To sum up, it can be concluded that reducing the probability of process being killed is nothing more than trying to improve the priority of process and reduce the probability of process being killed in the case of insufficient memory.

3. Solutions to improve process priorities

3.1. Use Activity to promote permissions

3.1.1. Scheme design idea

Monitor the mobile phone lock screen unlock event, start the Activity with 1 pixel when the screen is locked, and destroy the Activity when the user unlocks. Note that the Activity should be designed to be insensitive to the user.

This solution increases the process priority from 4 to 1 during the screen lock period.

3.1.2. Scope of application

Application scenario: This solution solves the problem that third-party applications and system management tools will kill background processes within a period of time (usually less than 5 minutes) after detecting a screen lock event, saving power.

Available versions: Works with all Android versions.

3.1.3. Concrete implementation of the scheme

First define the Activity and set the size of the Activity to 1 pixel:

Second, exclude Activity display in RecentTask from AndroidManifest via the following attributes:

Finally, make the Activity transparent:

Control the timing of Activity startup and destruction:

3.2. Use Notification to promote permissions

3.2.1. Scheme design idea

The priority of Service in Android is 4. Through the setForeground interface, the background Service can be set to foreground Service, so that the process’s priority is raised from 4 to 2, so that the process’s priority is only lower than the process that the user is currently interacting with. Consistent with the visible process priority, the probability of the process being killed is greatly reduced.

3.2.2. Implementation challenges

When setForeground Service is set to foreground Service by calling setForeground Service from Android2.3, a notice must be sent in the notification bar of the system, that is, foreground Service is bound with a visible notice.

This is great for apps that don’t need a permanent notification bar, but it’s user-aware and not directly usable.

3.2.3. Program challenge response measures

By implementing an internal Service, a Notification with the same ID is sent in both the LiveService and its internal Service, and the internal Service is terminated. As the internal Service ends, the Notification disappears, but the system priority remains 2.

3.2.4. Scope of application

Works with all versions known so far.

3.2.5. Concrete implementation of the scheme

4. Pull-alive scheme for process after death

4.1. Pull live by system broadcast

#####4.1.1. Scheme design idea

When a specific system event occurs, the system will issue a response broadcast. By “statically” registering the corresponding broadcast listener in the AndroidManifest, the response event can be pulled alive.

Common broadcast events used to pull include:

4.1.2. Scope of application

Available on all Android platforms. However, there are several disadvantages as follows:

1) When the broadcast receiver is disabled by the management software or system software through “self-start Management” or other functions, the broadcast receiver cannot receive the broadcast, and therefore cannot self-start.

2) The event broadcast by the system is uncontrollable, so the process can only be pulled alive when the event occurs, but cannot be pulled alive immediately after the process hangs up.

The programme is therefore primarily used as a backup.

4.2. Broadcast live via third-party applications

4.2.1. Scheme design idea

The overall design idea of the scheme is similar to that of receiving system broadcast, but the difference is that the scheme is receiving third-party Top application broadcast.

By decomcompiling third-party Top applications, such as mobile QQ, wechat, Alipay, UC browser, etc., as well as SDK such as Youmeng, Singe, Getui, etc., to find out their external broadcast and monitor in the application, so that when these applications broadcast, our application will be activated.

4.2.2. Scope of application

In addition to the same factors as system broadcast, the effectiveness of the scheme is mainly limited by the following factors:

1) How many third party applications decompiled and analyzed

2) Broadcasts of third-party applications are proprietary to the application. Broadcasts that are valid in the current version may be removed or changed to non-outgoing at any time in the subsequent version.

All these factors affect the effect of pulling.

4.3. Activate the system Service mechanism

4.3.1. Scheme design idea

If a Service is set to START_STICKY, the system will automatically activate the Service if the Service fails:

4.3.2. Scope of application

The following two conditions cannot be pulled:

  1. The system restarts within 5 seconds after the Service is killed for the first time, within 10 seconds after the Service is killed for the second time, and within 20 seconds after the Service is killed for the third time. Once the Service is killed for five times in a short period of time, the system does not restart.

  2. The process is stopped by the management tool or system tool that has the Root permission through forestop and cannot be restarted.

4.4. Pull with Native process

#####4.4.1. Scheme design idea

** Main idea: ** Uses the fork mechanism in Linux to create Native process, monitors the survival of the main process in the Native process, and immediately pulls the main process alive in the Native process when the main process dies.

** The lifecycle of all processes and system components in Android is centrally managed by ActivityManagerService. Also, processes created through Linux’s fork mechanism are pure Linux processes and their life cycles are not managed by Android.

#####4.4.2. Solution implementation challenges

Challenge 1: How to sense the death of the main process in Native.

There are two ways to sense whether the main process is alive or not in a Native process:

  1. In Native process, through the dead-loop or timer, rotation training to judge whether the main process is alive, and pull alive when the main process is not alive. The great disadvantage of this scheme is that the judgment logic is executed constantly in polling, which is very power consuming.

  2. Create a monitor file in the main process and hold the file lock in the main process. The file lock application will be blocked after the pull process starts. Once the lock is successfully obtained, it indicates that the main process is down and the pull process can be started. Because Android applications run on virtual machines, the file lock of the Java layer is different from that of the Linux layer. To implement this function, the file lock of the Linux layer needs to be encapsulated for upper-layer invocation.

The code to encapsulate a Linux file lock is as follows:

Native layer block application file lock part of the code:

Challenge 2: How to activate the main process in Native.

Part of the code for pulling the main process through Native process is as follows, that is, pulling the main process through am command. Pull the master process in the forestop state by specifying the “-include-stopped -packages” parameter.

Challenge 3: How to make Native processes unique.

Considering from the aspects of scalability and process uniqueness, the C/S structure mode of Native process design layer is adopted. The main process communicates with Native process through Localsocket. In the Native process, Localsocket is used to ensure the uniqueness of the Native process, so as not to create multiple Native processes or turn the Native process into zombie process.

4.4.3. Scope of application

The solution is mainly applicable to phones with Android5.0 or lower versions.

Forcestop is not affected by forcestop, and apps that have been forced to stop can still be pulled, which works very well on Android5.0 and below.

For Android5.0 or above, although the system will kill all the processes in the native process, here is actually the system “sequence” killing process time and the execution time of pull live logic race, if you can run faster than the system logic, still can effectively pull up. I remember that some people have done experiments online, the conclusion is valid, in some Android 5.0 or above models.

4.5. Use the JobScheduler mechanism to pull work

4.5.1. Scheme design idea

Android5.0 after the system to strengthen the management of Native process, Native pull mode failure. The system provides the JobScheduler interface in Android5.0 and above. The system will periodically call this process to make the application perform some logical operations.

In this project, I further encapsulate JobScheduler, which is compatible with Android5.0 and below. The encapsulated JobScheduler interface is used as follows:

4.5.2. Scope of application

The solution is mainly applicable to Android5.0 and above.

This solution is not affected by forcestop in Android5.0 and above. The application that is forced to stop can still be pulled, which works very well in Android5.0 and above.

Xiaomi phones alone may sometimes fail to pull live issues.

4.6. Activate the account synchronization mechanism

#####4.6.1. Scheme design idea

The Account synchronization mechanism of the Android system periodically synchronizes accounts. This solution uses the synchronization mechanism to pull and live processes. The code for adding an account and setting the synchronization period is as follows:

This solution requires the account authorization and synchronization service to be defined in AndroidManifest.

####4.6.2. Scope of application

The solution works on all Android versions, including the ability to pull processes that have been stopped by Forestop.

In the latest version of Android (Android N), the system seems to have made a change to account synchronization. This method no longer works.

5. Other effective pulling schemes

It is found that there are other system pulling measures that can be used, but user authorization is required when using, and user perception is strong.

These programmes include:

  1. Use the system notification management rights to pull

  2. Add an application to the whitelist of the vendor or management software by using auxiliary functions.

These solutions need to be combined with specific product characteristics.

All of the above explains that these scenarios are considered for the root-free case.

There are other non-technical measures, such as the option of an in-app Push channel:

  1. Foreign version application: Access Google’S GCM.

  2. Domestic application: according to different terminals, xiaomi mobile phones (including MIUI) can access Xiaomi Push, and Huawei mobile phones can access Huawei push; Other mobile phones can consider access to Tencent carrier pigeon or Aurora push and Xiaomi push to do A/B Test.