Android 12’s new background app limitations could be a major headache for power users

Android 12’s new background app limitations could be a major headache for power users

Android 12 has introduced a lot of changes, though not all of them are really user-facing. Features like the massive Material You redesign are obviously shoved in your face and hard to miss, but something like Digital Car Key support might be easier to miss. However, one change that might even be entirely undocumented will wreak havoc on apps like Termux, and that’s the introduction of a pretty aggressive background process killer.

For context, Termux is a Linux terminal emulator that you can get on Android, and Termux’s package management system is much like Debian’s Advanced Package Tool (APT) in that you can search, install, and uninstall with the command apt. Termux installs just a few basic packages out of the box, to reduce APK size on the Play Store, but allows you to install any extra packages that you desire. People will often make use of Termux to turn older smartphones into mini servers, or use it to run other programs that are typically not aimed at smartphones. A common usage is even natively setting up youtube-dl, as you can execute Python scripts using Termux on your smartphone.

In Android 12, though, it was discovered that a mechanism to monitor forked child processes started by apps and kills them if they consume too much CPU if the app is in the background (via Mishaal Rahman) was introduced. It also limits the number of child processes that parent processes can spawn to 32, which greatly limits the number of operations an app can complete in the background. This 32 child process limit is actually across the entire system, not just per app, meaning that other apps with child processes will contribute to that limit as well. I tested on the Google Pixel 6 Pro, and I can confirm that the PhantomProcessKiller exists and can potentially wreak havoc on Termux.

Android 12’s Phantom Process Killer kills background processes

Android 12 introduced a couple of restrictions on background processes; the first is that child processes of apps consuming too much CPU in the background will be killed if the parent process is also in the background. The second restriction introduced is a limit on the number of child processes that can be active at any given time. From the commit history, it would appear that Google was trying to clamp down on rogue background processes.

“Apps could use Runtime.exec() to spawn child process and framework will have no idea about its lifecycle. Now track those processes whenever we find them – currently during the cpu stats sampling they could be spotted. If it’s consuming too much CPU while its parent app process are also in the background, kill it. By default we allow up to 32 such processes; the process with the worst oom adj score of their parents will be killed if there are too many of them.”

Of course, Android smartphones are already notorious for background app killing. Pretty much all major OEMs engage in it in some way, shape, or form, and companies like OnePlus, Samsung, and Xiaomi are considered amongst the worst. While AOSP has some background app restrictions, it’s typical of manufacturers to build their own restrictions on top of AOSP. However, these are pretty strict limitations for power users and encourage behaviors that power users have been vocally against for a long time. Maybe it will increase battery life in the long run, but there’s seemingly no way of disabling it either.

Triggering the Android 12 Phantom Process Killer

As the commit says, 32 such processes are allowed, and I verified this on my Google Pixel 6 Pro with the following command.

adb shell "/system/bin/dumpsys activity settings"

In the output of this command, there’s a constant called “max_phantom_processes” with a value of 32. In this context, a “phantom process” is judged by the Android system to be a child process running in the background. If you have an Android 12 device, you can use Termux to spawn more than 32 child processes by creating a bash script somewhere on your storage containing the following code and executing it (credits to agnostic-apollo on GitHub, a developer involved with Termux):

for i in $(seq 40); do
sha256sum /dev/zero &
done

To execute it, in Termux navigate to the folder you saved the script in and type the following:

sh filename.sh

If your phone starts to feel laggy, then that means it’s working. The above code spawns 40 sha256sum operations in the background (denoted by the ampersand) taking the /dev/zero file as an input. sha256sum will give the SHA-256 hash of whatever file is given as an input. The reason /dev/zero is used is that it’s an infinite-length file that contains null values for as long as it’s read, meaning that the sha256sum operation will never reach the end of the file, serving as a good stress test to ensure continuous background operations.

After a few seconds to a minute, you may get the following to appear:

Termux Android 12 bash killed

“signal 9” is a signal sent to the process forcing it to shut down, and this signal is sent by the Linux scheduler. The reason the message appears is that the bash terminal is technically a child process of Termux too, and Android 12 ends up killing the bash terminal in the above demonstration. In the logcat output, you can see see the following:

11-02 13:01:52.507  1444  1762 I ActivityManager: Killing PhantomProcessRecord {623260a 7362:7284:nightwatch.txt/u0a227}: Trimming phantom processes
11-02 13:01:52.507  1444  1762 I ActivityManager: Killing PhantomProcessRecord {bf3d88c 24220:24040:nightwatch.txt/u0a237}: Trimming phantom processes
11-02 13:01:52.507  1444  1762 I ActivityManager: Killing PhantomProcessRecord {b160bd5 27316:27269:bash/u0a340}: Trimming phantom processes
11-02 13:01:52.507  1444  1762 I ActivityManager: Killing PhantomProcessRecord {bbc1fea 27371:27269:sha256sum/u0a340}: Trimming phantom processes
11-02 13:01:52.507  1444  1762 I ActivityManager: Killing PhantomProcessRecord {9cf12db 27372:27269:sha256sum/u0a340}: Trimming phantom processes
11-02 13:01:52.507  1444  1762 I ActivityManager: Killing PhantomProcessRecord {54bf178 27373:27269:sha256sum/u0a340}: Trimming phantom processes
11-02 13:01:52.507  1444  1762 I ActivityManager: Killing PhantomProcessRecord {fb89051 27374:27269:sha256sum/u0a340}: Trimming phantom processes
11-02 13:01:52.507  1444  1762 I ActivityManager: Killing PhantomProcessRecord {d3450b6 27375:27269:sha256sum/u0a340}: Trimming phantom processes
11-02 13:01:52.507  1444  1762 I ActivityManager: Killing PhantomProcessRecord {2a201b7 27376:27269:sha256sum/u0a340}: Trimming phantom processes
11-02 13:01:52.507  1444  1762 I ActivityManager: Killing PhantomProcessRecord {60aad24 27377:27269:sha256sum/u0a340}: Trimming phantom processes
11-02 13:01:52.507  1444  1762 I ActivityManager: Killing PhantomProcessRecord {124e08d 27378:27269:sha256sum/u0a340}: Trimming phantom processes
11-02 13:01:52.507  1444  1762 I ActivityManager: Killing PhantomProcessRecord {32cc242 27379:27269:sha256sum/u0a340}: Trimming phantom processes
11-02 13:01:52.511  1444  1764 I ActivityManager: Process PhantomProcessRecord {b160bd5 27316:27269:bash/u0a340} died
11-02 13:01:52.511  1444  1764 I ActivityManager: Process PhantomProcessRecord {9cf12db 27372:27269:sha256sum/u0a340} died
11-02 13:01:52.511  1444  1764 I ActivityManager: Process PhantomProcessRecord {414579a 27434:27269:top/u0a340} died
11-02 13:01:52.511  1444  1764 I ActivityManager: Process PhantomProcessRecord {32cc242 27379:27269:sha256sum/u0a340} died
11-02 13:01:52.511  1444  1764 I ActivityManager: Process PhantomProcessRecord {bbc1fea 27371:27269:sha256sum/u0a340} died
11-02 13:01:52.511  1444  1764 I ActivityManager: Process PhantomProcessRecord {bf3d88c 24220:24040:nightwatch.txt/u0a237} died
11-02 13:01:52.512  1444  1764 I ActivityManager: Process PhantomProcessRecord {60aad24 27377:27269:sha256sum/u0a340} died
11-02 13:01:52.516  1444  1764 I ActivityManager: Process PhantomProcessRecord {623260a 7362:7284:nightwatch.txt/u0a227} died
11-02 13:01:52.516  1444  1764 I ActivityManager: Process PhantomProcessRecord {124e08d 27378:27269:sha256sum/u0a340} died
11-02 13:01:52.517  1444  1764 I ActivityManager: Process PhantomProcessRecord {fb89051 27374:27269:sha256sum/u0a340} died
11-02 13:01:52.519  1444  1764 I ActivityManager: Process PhantomProcessRecord {54bf178 27373:27269:sha256sum/u0a340} died
11-02 13:01:52.532  1444  1764 I ActivityManager: Process PhantomProcessRecord {2a201b7 27376:27269:sha256sum/u0a340} died
11-02 13:01:52.545  1444  1764 I ActivityManager: Process PhantomProcessRecord {d3450b6 27375:27269:sha256sum/u0a340} died

The important line is the one that mentions that the “bash” process was trimmed and then died, and that’s why Termux stops working. While I’m unsure what “nightwatch.txt” is, a cursory Google search appears to suggest that it’s related to Facebook and Facebook Messenger, two apps that I do have installed. I tested this with adaptive battery off and made sure that there were no battery optimizations being applied to Termux, either.

After you’re finished testing, it’s likely some of the sha256sum operations will continue in the background still (and pressing enter will force close Termux), so re-open Termux and type the following:

killall sha256sum

While such a limitation makes sense for some apps, apps that power users might be more inclined to use (such as Termux) will suffer. This may also have an effect on other apps that power users use too, such as Tasker. It’s a limitation that doesn’t seem possible to overcome just yet and introduces even more limitations on background apps on top of all of the other proprietary restrictions that manufacturers impose. In the ongoing GitHub issue thread, the following is mentioned by agnostic-apollo regarding a logcat that was emailed to them:

“All the 32 tracked logcat PhantomProcessRecord belong to com.wsandroid.suite and termux’s bash was one of the processes that got killed. So as mentioned above, the 32 process limit is for all apps combined”

Amusingly, I ran the same tests on a Xiaomi 11T Pro running Android 11 and confirmed that the behavior doesn’t exist on that particular device in that configuration, even though Xiaomi devices are notorious for background app limitations. This is, oddly, one of the strictest background application management policies introduced on any Android smartphone, as there’s no way around it. Even on Xiaomi devices and OnePlus devices, it’s possible to disable most of it, and for some people, disabling all the battery optimizations on those devices is enough for them to be happy. The phantom process killer, in contrast, can’t even be disabled.

If you rely on Termux for a lot of on-device operations that are intensive with many background processes, it might be worth holding off upgrading for now until there’s more information. If you’re not a power user, then this likely isn’t something that you really need to worry about.

About author

Adam Conway
Adam Conway

I'm a senior editor at XDA-Developers. I have a BSc in Computer Science from University College Dublin, and I'm a lover of smartphones, cybersecurity, and Counter-Strike. You can contact me at [email protected] My Twitter is @AdamConwayIE and my Instagram is adamc.99.