Contrary to the traditional computing world, where programs won't quit without the user asking for it, in the mobile world (and Android in particular), it's generally considered up to the system to decide which app to quit and when, to the point where many if not most apps don't even have a quit option.
Up to some extent, it's justified due to :
- The limited amount of RAM available (contrary to the PC/Mac world where we've gone too far in the other direction, and the system by default considers a program can ask for as much virtual memory as it wants, which is a security problem, but that's another subject)
- The devices being for the general public, in a context where people don't necessarily have the knowledge/will/time to manage their phone usage on an app by app basis
- The apps are often designed to be used for short periods of time (which is linked to the previous point somehow)
However, there are cases where one doesn't want a given app to quit unless it's asked to explicitly by the end user. The reality of that need seems to have been taken into account by some mobile phone manufacturers (if I'm not mistaken, Samsung has been providing such an option for some time now).
So my question is : how shall I tell the system to not kill a given app ? I know there are apps that pretend to achieve this, but how shall I do that myself, without resorting to third party tools, only the stock Android command line tools and APIs ?
Afaik, there seem to be three criteria to decide to kill an app :
- Memory usage (the LMK daemon being in charge, unless a specific driver is present, in my case I have lmkd running)
- A limit on the number of running processes
- Battery optimisation, but there's already an option to disable that per-app, so I don't consider it a problem
So basically, only points 1 and 2 remain to be solved. You advices are welcome !
For what it's worth, I run Android x86 9.0 on an emulator (qemu).
EDIT : I checked the code of a program that's called App Settings, that's part of the Xposed framework. The program pretends to be able to set a program to stay resident in memory. After checking the code, it seems it modifies some application process attributes that are defined in the ProcessRecord class, namely maxAdj, curRawAdj, setRawAdj, curAdj and setAdj, setting those to the value of -12.
I wasn't able to test the program since my x86_64 Android 9.0 doesn't seem compatible with the framework, but I found this page, explaining in more detail how the activity manager service updates OOM values according to the app status, and communicates with LMK. It explains what the OOM values can be and what they mean. So clearly, trying to change the OOM values in /proc is useless, as the activity manager will change them, and probably LMK doesn't even read them anyway, and only takes what the activity manager transmits.
Is there any way to hint the Activity Manager into giving chosen OOM values to an app ? I could for example set the value to NATIVE_ADJ, or even no more than FOREGROUND_APP_ADJ at all times. Or maybe passing those parameters through a specially crafted intent ?
REEDIT : for those interested, the stop lmkd command should stop the LMK daemon until next reboot at least, which leaves only the OOM killer from Linux in charge. I didn't test it so I can't say for sure, but that should do it for some people. Beware of the consequences, however, if you continue using many apps at the same time, as a performance hit can be expected.
system_serverwhen making decisions. – Irfan Latif Apr 16 '20 at 16:27initservice) in background and that won't be killed (do take care ofcgroupsthough). Exactly the same behavior as on a Linux PC. Android's decision to not let apps run in background is not only to free RAM but mainly to preserve battery. And also to provide user somewhat control on privacy i.e. what's happening in background without being noticed. Phones are 24/7 partners and hence perfect spying tools, PCs aren't. Btw I don't think there's a reliable way to prevent an app (which doesn't run a FG service) from being killed, even using 3rd party tools – Irfan Latif Apr 16 '20 at 16:39onPausestate and may be killed. Programming related questions should be directed to https://stackoverflow.com/questions/tagged/android – Morrison Chang Apr 17 '20 at 00:15stop lmkd, that's better than nothing after all. – NovHak Apr 25 '20 at 14:17stop lmkdwould definitely break Activity Manager as there would be no way for AM to communicate with kernel for memory management. So the device may get into bootloop or at leastzygotewould keep on restarting. // I agree with your concerns that at least there should be a way to whitelist some apps from being killed in background (and in fact there should be if your device is configured to use memory cgroup on per UID basis (checkro.config.per_app_memcg)). But my point is that comparing to standard Linux distros, Android's memory management is no way worse. Actually it ... – Irfan Latif Apr 25 '20 at 17:59vmpressureandcgroupsto limitize the allocated memory to apps before the killing stage comes. Linux kernel alone (OOM killer) may kill anything (including critical native service e.g. HALs and frameowork apps) on memory pressure events (if there is no dirty data to flush out and no SWAP memory). It relies onoom_adjandoom_score_adjvalues (if set from userspace). Android at least controls what should be killed first to avoid any crash situation. Also LMKD is added in Android 9, on older deviceslowmemorykillerwas an ... – Irfan Latif Apr 25 '20 at 17:59oom_score_adjvalues of processes but with a more fine grained control. That's why the problem you are highlighting is there since ever: https://android.stackexchange.com/questions/89544 // Now that said, what I have talked about above and what you are talking about IS NOT YOUR ACTUAL PROBLEM at all. Your problem is that the Android's Java framework (which runs insystem_servernative process and) which has a core component name Activity Manager puts your favorite app in a list of *cached processes* (to be killed if needed) as soon as ... – Irfan Latif Apr 25 '20 at 18:00ps) and is *NOT KILLED BY LMKD* immediately (if there's not a shortage of RAM). So to keep your app running even in background (and not to get into cached processes list) the app must be in foreground or it must run a service (in Java framework, not native) or a broadcast receiver etc. Or the other way again, what I stated in my previous comments: modify Android source to change the behavior how Activity Manager puts apps in cached processes list, which is not exactly killing ... – Irfan Latif Apr 25 '20 at 18:11kill <pid>from CLI. This is not what LMKD does. – Irfan Latif Apr 28 '20 at 18:00