Write a process/service under Android that will never be killed

Source: Internet
Author: User

Write a process/service under Android that will never be killed

The Android system has its own method for memory management. In order to ensure the orderly and stable operation of the system, the system automatically allocates memory to control the memory usage of the program. When the system feels that the current resources are very limited, in order to ensure that some of the higher-priority programs can run, it will kill some programs or services that he thinks are not important to release the memory. This ensures that the programs that are truly useful to users are still running. If your Service encounters this situation, it will probably be killed first. However, if you increase the Service priority, you can leave it for a while. We can use setForeground (true) to set the Service priority.

 

Why is it foreground? By default, the started Service is marked as background, and the currently running Activity is usually marked as foreground, that is to say, if you set foreground for the Service, the priority of the running Activity will be improved. This does not guarantee that your Service will never be killed, but increases the priority of your Service.

 

There is a way to give you a clearer demonstration, go to $ SDK/tools to run the command

 

Copy code

# Adb shell dumpsys activity | grep oom_adj

Running Norm Proc #6: oom_adj = 0 ProcessRecord {43635cf0 12689: com. roiding. netraffic/10028}

Running Norm Proc #5: oom_adj = 7 ProcessRecord {436feda0 12729: com. android. browser/10006}

Running Norm Proc #4: oom_adj = 8 ProcessRecord {4367e838 12761: android. process. acore/10016}

Running Norm Proc #3: oom_adj = 8 ProcessRecord {43691cd8 12754: com. google. process. gapps/10000}

Running PERS Proc #1: oom_adj =-12 ProcessRecord {43506750 5941: com. android. phone/1001}

Running PERS Proc #0: oom_adj =-100 ProcessRecord {4348fde0 5908: system/1000}

Copy code

When a large number of items are returned, observe the oom_adj value. If the value is greater than 8, it is generally the backgroud which may be killed at any time. The smaller the value, the higher the priority, and the later the killing time. The phone program is-12, indicating that the phone number is the phone number. If everything else is done, you can answer the phone, right. There is another one-100, which is even worse because if the system is finished, the system will crash.

 

I am the dividing line of tiantiao

 

Starting from Android 1.5, A started service can call startForeground (int, Notification) to set the service to the foreground state, and call stopForeground (boolean) to set the service to the background state.

 

We will call startForeground (int, Notification) to pass in the parameter notification, which will display the ongoing foreground service in the status bar. The background service is not displayed in the status bar.

 

In Android 1.0, set a service to the foreground status:

 

SetForeground (true );

MNM. Y (id, notification );

Set a service to the background status:

 

MNM. cancel (id );

SetForeground (false );

The comparison shows that calling setForeground (boolean) in the 1.0 API simply changes the service status and the user will not be aware of it. The new API forcibly binds the notification and action that changes the service status. The foreground service is displayed in the status bar, but the background service is not.

 

I am the dividing line of tiantiao

 

By adding the android: persistent = "true" attribute to the application tag in androidmanifest. xml, the process where the application is located will not be killed by LMK. However, the premise is that the application must be a system application, that is, the application cannot be installed normally. You must put the apk package of the application directly in the/system/app directory. It takes effect only after the system is restarted.

 

In addition to several general priorities, coreserver also exists. A priority like system will never be reclaimed by LMK. The Telephone Application in the system is the coreserver priority.

 

You can see from the source code that only when the flag of the application is FLAG_SYSTEM and FLAG_PERSISTENT at the same time will the application be set to coreserver priority.

 

If (info. flags & (ApplicationInfo. FLAG_SYSTEM | ApplicationInfo. FLAG_PERSISTENT ))

==( ApplicationInfo. FLAG_SYSTEM | ApplicationInfo. FLAG_PERSISTENT )){

App. persistent = true;

App. maxAdj = CORE_SERVER_ADJ;

}

FLAG_SYSTEM is set when the application apk is placed under/system/app. Therefore, only setting android: persistent = "true" will still be killed.

 

During the test, it is found that the application is still recognized as a common process without restarting the system after it is placed in the/system/app. When the system restarts, the process is started from the beginning and its priority is set to coreserver.

 

The dumpsys activity command clearly shows the difference.

 

Copy code

Running processes (most recent first ):

App #3: adj = 2/1 ProcessRecord {30858c20 1877: com. android. email/10014} (started-services)

PERS #2: adj =-100/0 ProcessRecord {308fb390 1713: system/1000} (fixed)

App #1: adj = 0/0 ProcessRecord {30908198 1794: android. process. acore/10005} (top-activity)

PERS #0: adj =-12/0 ProcessRecord {3090d488 1789: xiao. xiong. test/10026} (fixed)

Copy code

In addition, the process is started immediately after manual stop through ddms when it is set to-12.

 

I am the dividing line of tiantiao

 

Method

For a service, you can first set it to run on the foreground:

 

Copy code

Public void MyService. onCreate (){

Super. onCreate ();

Notification notification = new Notification (android. R. drawable. my_service_icon, "my_service_name", System. currentTimeMillis ());

PendingIntent p_intent = PendingIntent. getActivity (this, 0,

New Intent (this, MyMainActivity. class), 0 );

Notification. setLatestEventInfo (this, "MyServiceNotification," MyServiceNotification is Running! ", P_intent );

Log. d (TAG, String. format ("notification = % s", notification ));

StartForeground (0x1982, notification); // notification ID: 0x1982, you can name it as you will.

}

Copy code

Compared with applications under/data/app, applications placed under/system/app enjoy more privileges, such. if the persistent attribute is set to true in the xml file, it can be protected from the influence of out-of-memory killer.

 

For example, the AndroidManifest. xml file of the 'phone' application:

 

<Application android: name = "PhoneApp"

Android: persistent = "true"

Android: label = "@ string/dialerIconLabel"

Android: icon = "@ drawable/ic_launcher_phone">

...

</Application>

After setting, the app is upgraded to the system core level and will not be killed in any case. The stop operation will also be blocked in settings-> applications.

 

Copy code

The preceding log is set as follows:

Proc #19: adj = svc/B 4067b028 255: com. xxx. xxx/10001 (started-services)

# Cat/proc/255/oom_adj

4

Configured log:

PERS #19: adj = core/F 406291f0 155: com. xxx. xxx/10001 (fixed)

# Cat/proc/155/oom_adj

-12 # This is CORE_SERVER_ADJ

Note: The oom_adj of the init process is-16 (SYSTEM_ADJ): cat/proc/1/oom_adj

Copy code

Android-Related Analysis

The following code is available in the file frameworks/base/services/java/com/android/server/am/ActivityManagerService. java:

 

Copy code

Final ProcessRecord addAppLocked (ApplicationInfo info ){

ProcessRecord app = getProcessRecordLocked (info. processName, info. uid );

 

If (app = null ){

App = newProcessRecordLocked (null, info, null );

MProcessNames. put (info. processName, info. uid, app );

UpdateLruProcessLocked (app, true, true );

}

 

If (info. flags & (ApplicationInfo. FLAG_SYSTEM | ApplicationInfo. FLAG_PERSISTENT ))

==( ApplicationInfo. FLAG_SYSTEM | ApplicationInfo. FLAG_PERSISTENT )){

App. persistent = true;

App. maxAdj = CORE_SERVER_ADJ; // This constant value is-12.

}

If (app. thread = null & mPersistentStartingProcesses. indexOf (app) <0 ){

MPersistentStartingProcesses. add (app );

StartProcessLocked (app, "added application", app. processName );

}

 

Return app;

}

Copy code

It can be seen that you want to become a core service (that is, app. maxAdj = CORE_SERVER_ADJ (-12). The application requires FLAG_SYSTEM and FLAG_PERSISTENT. FLAG_SYSTEM indicates that the application is located under/system/app, and FLAG_PERSISTENT indicates the persistent attribute.

 

For frameworks/base/services/java/com/android/server/SystemServer. java, ActivityManagerService. setSystemProcess () is called ();

 

Set your app. maxAdj to SYSTEM_ADJ, that is,-16.

 

I am the dividing line of tiantiao

 

Processes in Android are hosted. When the system process space is insufficient, the process is automatically reclaimed based on the priority. This brings about three problems:

 

Recycling rules: When to recycle and which one?

Avoid mistaken kill: how to prevent being recycled?

Data Recovery and storage: What should I do if it is recycled?

Android divides processes into six levels. The order of priority is from high to low:

 

Foreground process (FOREGROUND_APP)

Visualized process (VISIBLE_APP)

Secondary service process (SECONDARY_SERVER)

Background process (HIDDEN_APP)

Content supply node (CONTENT_PROVIDER)

Empty Process (EMPTY_APP)

Features:

 

If a process contains both service and visible activity, the process should be classified as a visible process rather than a service process.

In addition, if other processes depend on it, the level of a process can be increased. For example, if A service in process A is bound to A component in process B, process A is considered at least as important as process B.

The phone service in the system is divided into foreground processes rather than secondary service processes.

In android, The oom_adj value of a process represents its priority. The higher the oom_adj value, the lower the priority of the process. The file/init. rc has the following attribute settings:

 

Setprop ro. FOREGROUND_APP_ADJ 0

Setprop ro. VISIBLE_APP_ADJ 1

Setprop ro. SECONDARY_SERVER_ADJ 2

Setprop ro. HIDDEN_APP_MIN_ADJ 7

Setprop ro. CONTENT_PROVIDER_ADJ 14

Setprop ro. EMPTY_APP_ADJ 15

In/init. rc, set oom_adj of the process whose PID is 1 (init process) to SYSTEM_ADJ (-16 ):

 

# Set init its forked children's oom_adj.

Write/proc/1/oom_adj-16

View local settings:

 

Cat/sys/module/lowmemorykiller/parameters/adj

File/init. rc:

 

Setprop ro. FOREGROUND_APP_MEM 1536 // 6 M

Setprop ro. VISIBLE_APP_MEM 2048 // 8 M

Setprop ro. SECONDARY_SERVER_MEM 4096 // 16 M

Setprop ro. HIDDEN_APP_MEM 5120 // 20 M

Setprop ro. CONTENT_PROVIDER_MEM 5632 // 22.4 M

Setprop ro. EMPTY_APP_MEM 6144 // 24 M

These numbers are the corresponding memory threshold. Once they are lower than this value, Android begins to close the process of the corresponding level in order.

Note that the unit of these numbers is page: 1 page = 4 kB. So the above six numbers correspond to (MB): 6, 8, 16, 20.

 

View the current memory threshold settings:

 

Cat/sys/module/lowmemorykiller/parameters/minfree

To reset this value (corresponding to different requirements ):

 

Echo "1536,2048, 4096,5120, 15360,23040">/sys/module/lowmemorykiller/parameters/minfree

In this way, when the available memory is less than 90 MB, the "Empty Process" will be killed, and when the available memory is less than 60 MB, the "content supply node" process will be killed.

 

The specific recycling function trimApplications () in ActivityManagerService. java ():

 

First, Remove useless processes that have been uninstalled from the package;

Update the oom_adj value based on the current process status, and then perform the following operations:

1) Remove the processes without activity running;

2) If the AP has saved all activity states, terminate the AP.

Finally, if there are still many activities running, remove the activity that has been saved.

Update oom_adj value:

 

In the ComputeOomAdjLocked () file of the ActivityManagerService. java file, calculate the oom_adj of the process, for example:

 

If (app = TOP_APP ){

// The last app on the list is the foreground app.

Adj = FOREGROUND_APP_ADJ;

App. adjType = "top-activity ";

}

I am the dividing line of tiantiao

 

Low memory killer in Android kernel

 

Android Low Memory Killer kills the process to release its Memory as needed (when the system Memory is insufficient). The source code is in kernel/drivers/misc/lowmemorykiller. c. Simply put, it is to find the most suitable process to kill and release the memory it occupies.

 

The most suitable process is:

 

More oom_adj

The more physical memory occupied

Once a process is selected, the kernel sends a SIGKILL signal to kill it:

 

Copy code

For_each_process (p ){

......

If (selected = NULL | p-> oomkilladj> selected-> oomkilladj |

(P-> oomkilladj = selected-> oomkilladj & tasksize> selected_tasksize ))

{

Selected = p;

}

}

If (selected! = NULL ){

Force_sig (SIGKILL, selected );

}

Copy code

View LRU list: adb shell dumpsys activity

 

When activitydemo is on the frontend:

 

Processes that contain services have a high priority. In computeOomAdjLocked, they are divided into two classes:

 

Copy code

Static final int MAX_SERVICE_INACTIVITY = 30*60*1000;

If (now <(s. lastActivity + MAX_SERVICE_INACTIVITY )){

If (adj> SECONDARY_SERVER_ADJ ){

Adj = SECONDARY_SERVER_ADJ;

App. adjType = "started-services ";

App. hidden = false;

}

}

If (adj> SECONDARY_SERVER_ADJ ){

App. adjType = "started-bg-services ";

}

Copy code

It is impossible to completely prevent the process from being killed. We can perform some operations to reduce the chance of the process being killed:

 

Increase the priority of a process:

* Background operations run on the front-end Service because a process running the service has a higher level than a background activity;

* Press the back key to run the activity in the process in the background rather than destory. You need to reload the back button (no activity is killed first in the running process ).

* Dependent on other high-priority processes;

Force modify process attributes:

* Set in the process: setPersistent (true );

* Set in the Manifest file (as shown above ).

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.