Skip to content

How Android manages background processes?

mingyuan-xia edited this page Dec 18, 2014 · 1 revision

##Overview The Android system assigns importance to every process, i.e., visible process, hidden process, empty, etc. Each process has a oom_adj value according to its importance. The activity manger server (in Java, running as a system-wise service) updates the oom_adj value for all processes dynamically. Then the kernel low memory killer will kill processes with regards to its oom_adj. A process with higher oom_adj value is more likely to get killed. The low memory killer is configured with several threshold pairs: (<t1, oom_adj1>, <t2, oom_adj2>... ). These parameters mean that the killer will starts to kill processes with oom_adj larger than oom_adj1 when the RAM drops below t1. The low memory killer is implemented in Linux kernel as a driver and the activity manager service runs at android runtime level in user space. In short, the AM service updates oom_adj and low memory killer picks and kills bad processes.

These system-wise thresholds yield the tradeoff between keeping background processes and reserving free memory, which greatly affects the system performance.

Linux Out-Of-Memory Killer (OOM)

Android deprives its Linux kernel of page swapping capability, and instead relies totally on the Out-Of-Memory Killer (OOM) to keep system stable. In short, the OOM killer allows the Android to assign '''oom_adj''', a kind of priority, to all processes and kills the one with lowest priority when the system is running out of memory. Notice that Android has its only OOM killer implemented in its kernel and thus behaves slightly differently from the standard Linux's version. But they share the same nature.

The LWN article gives a finer-grained description of the OOM killer in standard Linux.

Android runtime part

Using Linux OOM

http://forum.xda-developers.com/showthread.php?t=622666

  • Every process has a oom_adj value, visible at /proc/<pid>/oom_adj. Higher values of oom_adj are more likely to be killed by the kernel's oom killer. The current foreground app has a oom_adj of 0.
  • There are oom_adj values associated with process classes such as "foreground app", "visible app", "secondary server", "hidden app", etc.
  • The low memory killer uses configurable rules based on free memory and oom_adj thresholds. ie, rules state "if free memory < X1, kill processes with oom_adj > Y1"
  • There is often one rule for each process class. However, it appears there is a limit of 6 rules in total, so sometimes there is one rule for 2 or more process classes.
  • The rules are configured succinctly using two parameters:
/sys/module/lowmemorykiller/parameters/adj=<list of oom_adj thresholds>
/sys/module/lowmemorykiller/parameters/minfree=<parallel list of memory thresholds, in 4K pages>

From my Samsung Galaxy S' /init.rc:

# Define the oom_adj values for the classes of processes that can be
# killed by the kernel.  These are used in ActivityManagerService.
    setprop ro.FOREGROUND_APP_ADJ 0
    setprop ro.VISIBLE_APP_ADJ 1
    setprop ro.SECONDARY_SERVER_ADJ 2
    setprop ro.BACKUP_APP_ADJ 2
    setprop ro.HOME_APP_ADJ 4
    setprop ro.HIDDEN_APP_MIN_ADJ 7
    setprop ro.CONTENT_PROVIDER_ADJ 14
    setprop ro.EMPTY_APP_ADJ 15

# Define the memory thresholds at which the above process classes will
# be killed.  These numbers are in pages (4k).
    setprop ro.FOREGROUND_APP_MEM 2560
    setprop ro.VISIBLE_APP_MEM 4096
    setprop ro.SECONDARY_SERVER_MEM 6144
    setprop ro.BACKUP_APP_MEM 6144
    setprop ro.HOME_APP_MEM 6144
    setprop ro.HIDDEN_APP_MEM 7168
    setprop ro.CONTENT_PROVIDER_MEM 8192
    setprop ro.EMPTY_APP_MEM 9216

# Write value must be consistent with the above properties.
# Note that the driver only supports 6 slots, so we have HOME_APP at the
# same memory level as services.
    write /sys/module/lowmemorykiller/parameters/adj 0,1,2,7,14,15                             
    write /sys/module/lowmemorykiller/parameters/minfree 2560,4096,6144,7168,8192,9216                       

I read this as:

  • if free memory goes below 9216x4K, kill EMPTY_APP processes;
  • if free memory goes below 8192x4K, kill CONTENT_PROVIDER and EMPTY_APPs.
  • if free memory goes below 7168x4K, kill HIDDEN_APP, CONTENT_PROVIDER and EMPTY_APPs
  • ... etc.

Higher level policy

The system component that assigns oom_adj to processes is the ActivityManager (source: frameworks/base/services/java/com/android/server/am/ActivityManagerService.java). The updating function concerned is updateOomAdjLocked(void). This function is called from multiple places, meaning that every time such as a new process is created, the ActivityManager will update the oom_adj value system-wise. In the function name, "Locked" means that this function is called in synchronized(this) {...} block. Since the ActivityManager is a singleton, this means that updateOomAdjLocked can only run serially for the entire system.