7

I'd like a browser app (FireFox) not to be killed every now and then by the system's task killer since I'd like to use certain single page applications that hold some data and are not loaded very quickly. Is there any way to deal with this, even if root is required?

Some time ago, I've updated my device from a 1 GB RAM to another one, 3 GB RAM and everything went well (browser stopped to get killed at all). But after a system update in Jan 2016, things got even worse, now FireFox usually gets killed even after an alarm clock rang or I opened a camera app. This is a major issue for me so I appreciate any help about this.

PS yeap, I've tried Settings→Battery→Battery Optimization where I both added FF to exceptions (didn't help) and turned Battery Optimization at all (didn't help as well).

8
+100

Tl;dr

It's possible with root, you can tweak oom_adj values to prevent apps from being killed, alternatively force the target app to stay in memory by "locking" it or change some related settings responsible for killing apps in low memory condition.


Background: Android RAM Management

Android uses a different way of handling processes. Instead of killing every process after its activity ended, processes are kept until the system needs more memory. The idea is to give speed improvements if you start that activity again. But how/when does Android kill a process if it needs more memory and which process to kill first?

This is managed by the LMK (Low Memory Killer) driver of Android. You may already know that every app/process in Android is assigned an oom_adj value, which indicates the likelihood of it being killed when an out of memory (OOM) situation occurs. More higher it's value, the higher likelihood of it getting killed. Valid range is -17 to +15. (if in the -17 range means it won't get killed). According to that, there are six groups (OOM groups), into which apps/processes are categorised:

  1. Foreground app
  2. Visible app
  3. Secondary server
  4. Hidden app
  5. Content provider
  6. Empty app

Basically these could be described as:

FOREGROUND_APP: This is the process running the current foreground app. We'd really rather not kill it!

VISIBLE_APP: This is a process only hosting activities that are visible to the user, so we'd prefer they don't disappear.

SECONDARY_SERVER: This is a process holding a secondary server -- killing it will not have much of an impact as far as the user is concerned.

HIDDEN_APP: This is a process only hosting activities that are not visible, so it can be killed without any disruption.

CONTENT_PROVIDER: This is a process with a content provider that does not have any clients attached to it. If it did have any clients, its adjustment would be the one for the highest-priority of those processes.

EMPTY_APP: This is a process without anything currently running in it. Definitely the first to go.

These groups are defined by oom_adj value limits, and apps would fall into one of those groups according to the oom_adj value assigned to that particular app. "Foreground apps" usually have an oom_adj value of 0 or less (so they are the least killable; i.e High priority).

"Empty apps" have a higher oom_adj (they are killed early; i.e Low priority). Also, oom_adj value changes according to the state of the user app; it's 0 when the app is active in the foreground and assigned a higher value when the app goes to the background.

Why their "killability" differ? Apps belonging to these different groups (that have different oom_adj's), start to get killed at different levels of free RAM. These triggering RAM limits are defined by the LMK minfree values. Above 6 categories correspond with 6 RAM limits which are set in the LMK minfree. eg: Stock Android 4.3 in my device comes with the minfree values of 48,60,72,84,96,120. (these are in MB).

enter image description here

Practically what it means is, Empty apps will get killed when ram goes below 120mb, Content providers when it goes below 96mb, Hidden apps when it goes below 84mb and so on.. lastly starts killing Foreground apps when ram goes below 48mb. (You may notice that this last value (48mb) is not desirable when using memory intensive apps like heavy games).

NB:

  1. In newer kernel, oom_ score _adj is used instead of old oom_adj. (oom_score_adj valid range is -1000 to 1000). But oom_adj is also maintained for perhaps compatibility.

  2. It is said that there are many OOM process categories that are assigned different oom_adj priorities by the ActivityManagerService, but eventually all of those would be considered under above six slots/groups (according to oom_limits), for the purpose of killing by the LMK minfree triggers. Therefore, those six are the important ones for normal users.

    • We can check the minfree values (also change them) and see the OOM groupings of apps/processes with this Memory Manager app easily.
  3. Not every device has the same OOM configuration.


Improving RAM Management

Nowadays there is much user friendly implementation of RAM management mechanism with UI in system settings (such as App optimisation in Battery settings, Protected apps in some ROMS e.g Huawei’s EMUI etc) and can have the same effect as described above:

enter image description here

Having said that we can now explore ways in which, RAM can be utilised without killing foreground applications too often. The target areas will include:

1.Adjusting minifree values to suit one’s needs

2.Locking apps in memory to prevent them from being killed

3.Overridding the hidden app limit of android


  1. Adjusting minifree values

    • You can change the minfree values with memory manager and tap apply. (Additionally there is an option “apply at boot” and tick to preserve settings across boots). Several apps can achieve this e.g Memory manager, Minfree manager etc

    • Alternatively use terminal/adb using pages:

      #!/system/bin/sh echo “values” > /sys/module
      
  2. Locking apps to stay in memory (making it resident)

a) Using App Settings (Xposed)

  • One simple method is used Xposed module, App settings (you need Xposed framework installed)
  • After installing the framework, then download the 'App Settings' module through Xposed installer.
  • Open App Settings and allow the applications to load, selected the target app (in this case firefox browser)
  • In the settings page, enable the toggle and activate editing mode, tick the “Resident” option and save. (Making apps resident, causes apps to staying memory without being killed and it is advised to use exit button in target application if it’s no longer needed otherwise it will deprive other apps memory)

enter image description here

b) Using memory locker

Another implementation of this concept is locking the target application in memory by controlling the system files for setting oom_adj for all running processes.

How the application works:

Memory locker controls files in the /data directory and also controls sytem files in root for setting oom_adj for running processes.

All locked applications are automatically locked after each reboot. Apps are classified as downloaded/system apps, to unlock select target app and click on the lock on right side. (You can optionally set oom_adj priority)

  1. Overriding the hidden app limit

    • In addition the low memory killing mechanism, there is another parameter that controls killing of hidden and empty apps. Apps are killed when they go beyond specified limits.

    • There is a build.prop setting that which can control this (default is usually a low number less than 25, and modifying this can increase this value to a much larger value like 80)

    • Add this line to build.prop file in /system and leave another blank line below that (be sure to make back up first)

ro.sys.fw.bg_apps_limit=80


References and Credits

  1. Android RAM Management (Special credits: mrhnet)
  2. Memory Locker
  3. Xposed - General info, versions & changelog
  • Thanks for this very detailed explanation. This most likely deserves the bounty, but let me think this over and ask some questions first. By the way, the first question is: so without rooting, there's no way to handle the problem, except for deleting many apps and hoping that the memory is loaded less? – YakovL Sep 24 '17 at 14:13
  • Another question is: which values can I see without rooting? I've made a simple test where I switched from FF to a photo app and couple others and moved back to FF and it got unloaded and loaded back. According to plots by Simple System Monitor, there were at least 300 MB of free RAM at each moment (much > than 120 MB) and FF still got unloaded... – YakovL Sep 24 '17 at 14:14
  • 1. I don't think it is possible to do it manually without root since you have to tweak a lot of system files, whilst adjusting the values and such messing requires elevated privileges or root. – xavier_fakerat Sep 24 '17 at 16:50
  • 2. What Android calls "Free RAM" is not necessarily free because a large part of it is cached memory (useful for fast execution of apps when relaunching them) such that the actual free memory is even less than the minifree value of say 120MB in this case. Good news most developers are now hardcoding the settings in their ROM ti allow non root users to accomplish this easily – xavier_fakerat Sep 24 '17 at 16:54
  • Don't worry about bounty, first try to get as much answers (even better answers) from others users , this will allow you to find the most helpful solution :) – xavier_fakerat Sep 24 '17 at 16:56
1

This app, RAM Manager claims to be able to lock certain apps from Android's RAM management mechanics.

Alternatively, go to Settings→Battery→Battery Optimization and set Firefox to Don't optimize can help a bit.

  • Yeah, I've tried the second option and also tried turning off optimization at all, that doesn't help. Could you point where exactly RAM Manager claims that? As far as I can see, it only allows to avoid its own optimization for certain apps (for launchers, to be specific). But the good point is – I should look into apps that try to control LMK and may be ask those who develop them – they probably have some extra knowledge. – YakovL Sep 24 '17 at 11:56
1

The post above is very thorough, but I will add instructions for a few specific models (stolen from ASM app page). Note that for apps that use more memory (eg Firefox), the system will likely eventually kill the app anyway when other apps request memory space. If the cached ram is needed, the largest and oldest apps go first regardless of battery saving settings, and Firefox is a big spender.


How to deal with (known) Battery savers?

Samsung In Android settings > Device Maintenance > Battery, add app to the list of Unmonitored apps

Huawei (depending on models) In Android settings > Advanced settings > Battery Manager, add app to the list of Protected Apps or: Battery > Close apps after screen lock, uncheck app from the Lock screen clean up

Xiaomi In your Security app: Battery % > App battery saver, select app then No restrictions and: In your Security app: Permissions > Autostart then allow app to be started.

Asus (Zenfone) Open your Auto-start Manager and allow app to be started.

OnePlus In Android settings > Battery > Menu > Aggressive Doze & App Hibernation, check app to exclude it from the optimised apps.

Infinix Open your Xmanager app, Auto-start manager and allow app to be started.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.