In Android (and Linux) philosophy, free RAM is wasted RAM. The Operating System will try to utilize all the amount of RAM available to it to increase its throughput. By design, Android tends to keep activities in RAM after the user exits them. This way it can speed up opening them again if needed. This behavior though can easily get the system in a low free memory state.
Android manages low memory states using a Kernel module known as Low Memory Killer (LMK). LMK is a process killer, which is designed to work in cooperation with the Android Framework. Each process is assigned a special value by the Framework when started, the oom_adj value(oom_score_adj on newer kernels). This value defines how important the process is for the system(its priority), and thus how easily it can be killed. Values vary between -17 and +15(0 to 1000 for oom_score_adj). Higher values are given to less important processes which are killed first. Moreover, LMK defines 5 different categories for processes, each one containing processes with oom_adj/oom_score_adj in a specific range of values:
- Foreground Applications
The application currently shown on the screen and running.
- Visible Applications
Applications that might not be shown on the screen currently, but are still running. They might be hidden behind an overlay or have a transparent window.
- Secondary Server
Services running in the background and needed for Apps to function properly. This category includes Google Play Services for example.
- Hidden Applications
Applications that are hidden from the user, but are running in the background.
- Content Providers
These are the services providing content to the system like contacts provider, location provider etc.
- Empty Applications
This category contains Applications that the user exited, but Android still keeps in RAM. They do not steal any CPU time or cause any power drain.
Don’t miss: Do things Faster with These 7 Android Shortcuts
Empty Applications category contains processes with the highest oom_adj/oom_score_adj values while Foreground Applications category Apps with the lowest values. Also, each of the categories above has its own memory threshold and when free RAM falls below this threshold, LMK will start killing processes inside this category, starting with processes with lower priorities.
Android Activity Manager is responsible for assigning oom_adj/oom_score_adj values for each process at run-time. Moreover, the system assigns memory thresholds to each process category at boot time. However, category thresholds can be changed directly through the kernel SysFS after boot. This makes room for configuring the Android Memory Management Subsystem according to personal needs.
Tuning the LMK parameters will have a greater impact on lower-end devices with 1 GB RAM or less since these devices are really stressed with multitasking on Android. To change LMK parameters, the device needs to have root support.
Changing LMK parameters can be done through the console by directly modifying the SysFS entry /sys/module/lowmemorykiller/parameters/minfree. This needs the data to be given in the form x1, x2, x3, x4, x5, x6, where each (x) is a memory threshold and x1 represents Foreground Applications, x2 Visible Applications, x3 Secondary Server, x4 Hidden Applications, x5 Content Providers and x6 Empty Applications. So, registering a new set of thresholds to the LMK is as simple as entering a Terminal App and writing the following commands:
su echo x1,x2,x3,x4,x5,x6 > /sys/module/lowmemorykiller/parameters/minfree
replacing each x in the last command with the needed values. LMK needs the parameters to be given in terms of memory pages. On Android, a memory page is 4 KB in size. So, to put a memory threshold of 50 MB to a category, the value (x) assigned to it should be 12800 [(50*1024)/4=12800].
Fortunately, changing LMK parameters can also be done quite easily using a kernel-tuning App that supports changing LMK parameters, like the open source Kernel Adiutor App:
Tips on LMK parameters configuration
- Assigning very high values to Foreground and Visible categories can make the system unstable.
- There should be no danger of killing critical system processes by any configuration. Processes that must not be killed are given a special oomj_adj value, which registers them as not killable to LMK.
- Values assigned to LMK are lost on reboot, so they need to be reassigned each time the device boots. Some kernel-tuning Apps can automatically re-apply changes on boot.
- Most Android modders only change the thresholds of the Empty and Hidden Applications categories, since these have the most impact on device responsiveness and multitasking capabilities.
- Memory thresholds should be registered in increasing order from Foreground Applications to Empty Applications category. So, memory threshold of Foreground Applications < Visible Applications < System Server < Hidden Applications < Content Providers < Empty Applications.
- Finding the right configuration for LMK is a procedure of trial and error. Each user has different usage needs and should configure LMK according to them. For example, a gamer should not increase the memory threshold of Foreground and Visible Applications a lot. Games are memory demanding Applications and would easily get killed (even while playing) in this situation. Instead, a gamer could set the Foreground threshold to around 10 MB, ensuring that the game App won’t get killed that easily.
- Although some universal profiles are listed below, there is a great variability of their effectiveness on different devices.
- To get real results from any tweak on LMK, any other Task Killers should be disabled beforehand, since they interfere with it. Essentially, LMK is a kernel-based solution that does exactly the same job as Task Killer Apps (and can replace them completely when configured correctly), without any additional overhead.
Example Universal LMK Profiles
As an LMK profile is considered a set of memory thresholds for each process category of LMK. Following is a list of some profiles, known to be effective on most of the devices. These should be considered as a starting point for more tweaking. All the values are given in memory pages.
Foreground Applications : 6400 Visible Applications : 7680 Secondary Server : 11520 Hidden Applications : 25600 Content Providers : 35840 Empty Applications : 38400
This profile will aggressively start killing processes at 150 MB of free RAM. At 100 MB it will start killing Hidden Applications.
Foreground Applications : 2560 Visible Applications : 5120 Secondary Server : 11520 Hidden Applications : 25600 Content Providers : 35840 Empty Applications : 38400
This profile is acting just like Aggressive Profile, except on Foreground and Visible Applications categories. It makes sure that, if a game makes use of big amounts of memory, it will not get killed by the LMK while it is running on screen.
Foreground Applications : 2560 Visible Applications : 5120 Secondary Server : 7680 Hidden Applications : 8960 Content Providers : 10240 Empty Applications : 12800
Light profile should be ideal for users not doing heavy multitasking. On devices with a small number of applications installed, this profile will kick LMK less frequently, saving some CPU cycles and reducing battery drain.