Well, this sure enough confirmed my hypothesis of "if no one on stackexchange knows the answer, you're going to have to figure it out yourself".
So I did.
The answer to this question is twofold. There's the window manager and the activity manager, and both play a certain role in this.
While it was tempting to write a TL;DR at the top here, I didn't, because especially with the second part, you have to be very careful with what you're doing, at least for now.
Window Manager/Recent Tasks
Let's start with the window manager, as this will also be interesting for people without large amounts of RAM. Also, it's quite a bit simpler.
It works with a number of variables:
config_activeTaskDurationHours as well as a number of
config_activeTaskDurationHours determines, as the name suggests, how long a task is considered active, that is, relevant to the user. On my device, this was set to 6. After those 6 hours, the "task" no longer appears in the recent apps list, with one exception: the number of open apps would be lower than, in my case,
config_minNumVisibleRecentTasks, launcher included. In that case, the app is not discarded. If the number of open apps is the same as
config_minNumVisibleRecentTasks, though, then as soon as you open an app that isn't opened yet, the oldest open app that hasn't been used for more than 6 hours is discarded.
There are also a couple of other related settings that weren't relevant in my case:
config_minNumVisibleRecentTasks_grid: This is for when apps are displayed in a grid. This view is not available on many builds of Android, though.
config_minNumVisibleRecentTasks_lowRam: The same setting for low RAM devices.
config_maxNumVisibleRecentTasks_lowRam: these are upper limits for the numbers of recent tasks. In my case
config_maxNumVisibleRecentTasks was set to -1, which means there is no maximum limit.
These are all grabbed from resources, and can be modified with GravityBox (root and XPosed/EdExposed/LSPosed required), under the Advanced tuning section, in the Framework section. They require a restart to activate the changes.
In my case, I set both
config_minNumVisibleRecentTasks to a ridiculous level: 5000. That way, it takes over a half a year for a task to have a chance to be removed, and that only if there are more than 5000 apps open, which I suspect will never happen.
This was a bit of a tougher nut to crack for me, and took a good amount of searching through the source code to find the answer - although the answer may not have really required it. Oh, well.
I first tried writing an XPosed module to override
updateMaxCachedProcesses. Unfortunately, I couldn't get it to hook the method properly, I don't know why. Mind you, I've never tried writing an XPosed module before, and I did this with AIDE - maybe sometime I'll unpack Android Studio again and try it in there. But if anyone wants finer control, this should offer an avenue to do that.
At the end, my original suspicion that you might be able to use the background process limit unoficially to increase the limit ended up being true. Sure enough, if you go into developer settings and change the background process limit to, say, 4, the output of
su -c dumpsys activity settings looks like this at the end:
Note that the trim levels aren't changed, and IMO it doesn't make sense to change those levels even if the device has a high amount of RAM. Essentially, if the process numbers are below the trim levels, the system doesn't even bother trimming memory.
So, how can we assign a higher value? This is where things get complicated. I tried to call
ActivityManager.setProcessLimit() with the permission
android.permission.SET_PROCESS_LIMIT (which is only available to system apps but can also be granted via ADB) as defined in the IActivityManager Interface, but I couldn't get it to work (again, I was working with AIDE, so that may be the problem, I may try it again on Android Studio later).
However, there is a little known android shell command,
service call, which essentially lets you call a whole bunch of methods from different service interfaces, see Where to find info on Android's "service call" shell command?. What you're looking for is the activity service, which is defined in
android.app.IActivityManager.aidl, and you're looking for the method
setProcessLimit(int max). Using the terminal, we can do
service list to get a list of the services that can be called here. In my case, the service name I'm looking for was activity. Then, we look up the
setProcessLimit(int max) command in the source code. Since I'm reasonably close to AOSP, I can look it up in there. In my case, it's the 40th command.
WARNING: Before I show what I needed for my device, don't just blindly follow this. This is different for just about every version of Android, and if you mess it up, it could cause problems. Read the link from the paragraph beforehand to be sure, at the very least be sure to understand my explanation in the previous paragraph.
In my case, I decided to set it to something ridiculous, so I took the tenfold of the original value, 600. That turned it into:
service call activity 40 i32 600 (be sure to run
su before that as this needs root privileges). Now, when I call
su -c dumpsys activity settings, the section looks like this:
Halleluja! We did it! Mind you, AFAIK, you'll have to repeat the
service call command on every restart, and if you mess around with the background process limit setting in developer settings, you'll also lose what you just set.
Maybe someday I'll try the approach with a root/adb app or an XPosed module again, and If I do, I'll update this answer. But for now, I'm happy with the results. RAM usage is now more between 5.5 and 6GB, as opposed to 4GB. Apps seem to be restarting less. Life is better.