Skip to content

Axion SPSM v3.0.6 (RMX3430) — why nothing was being saved

Choose a tag to compare

@arena-ai-coding-agent arena-ai-coding-agent released this 13 Sep 06:08
· 112 commits to Rewrite since this release

The mode was not saving anything, and this is why

Your report — all cores active, schedutil, every app still running, no drain at all, an empty drain.log — turned out to have one cause, and it is a bug in the module, not a setting you missed.

The screen state is read from the backlight node, which is right. But a rule sat on top of it: on a dark reading the app's own marker file was allowed to override the panel, and that marker was trusted for 24 hours.

The app writes on every time you open it and every time the screen wakes. It writes off when the screen turns off — but only while its process is alive, and Android reclaims a cached app routinely, even more so while a power saving mode is running. So the ordinary sequence is:

  1. you open the app (it writes on),
  2. Android reclaims the process,
  3. the screen goes off, and nobody writes off,
  4. the marker still says on, still "fresh" as far as the old rule was concerned, and it outranks the dark panel.

From that moment the daemon is certain the screen is always on. It never logs a screen-off transition, never enters the deep phase, never caps a core, never freezes Google, never restricts background work — and drain.log stays empty. Meanwhile the session knobs (home swap, Wi-Fi, Bluetooth, brightness, timeouts) all work, which is exactly why it looked like the mode was doing something while saving nothing.

That also explains FKM: everything looked normal because, as far as the module was concerned, the idle phase never happened — not because the caps were released too quickly.

The fix is a bound, not a removal: the app's marker may outrank a dark panel only while it is seconds old (the window in which its write can genuinely arrive before the backlight node lights). Anything older is stale evidence and the panel decides. screen_mark_grace defaults to 10 s and is configurable.

The mode can now prove it is working — and prove it is alive

A mode that saves nothing and a mode that is not running looked identical from the outside, which is how this went unnoticed for two releases. Now:

daemon: screen is off (panel=0 via panel marker=on@10800s)
screen on -> off (panel=0 via panel)
daemon alive: panel=0 state=off deep=applied caps_little=1100000 ticks=60
  • every decision says what decided it (panel, app marker, or dumpsys),
  • a heartbeat every few minutes says the screen is off, the caps are in place and the process saying so is still alive,
  • and on demand:
sh /data/adb/spsm/scripts/engine.sh status
screen=off
screen_source=panel
panel=0
deep=little_max=1100000 big_max=1300000 governor=schedutil doze=forced
daemon=2341

The daemon also runs in its own session now (setsid where available) and writes its own pid file, so a force-stop of the app can no longer take the screen watcher down with it.

What to do

Flash Axion-SPSM-v3.0.6-RMX3430.zip, reboot, turn the mode on, and check that status shows daemon=<pid>. Then the test that matters: screen off for 30–60 minutes, wake it, and look for the heartbeat and a drain: line.

Also in this zip, from your previous report (v3.0.5)

  • Block other apps — a new option: apps you have not allowed are suspended and stopped, so they cannot be opened from Settings ▸ Apps ▸ Open while the mode is on. Never the dialer, messages, alarms, system UI, Settings, your keyboard, your launcher, or your root manager. Defaults to on; one switch turns it off.
  • Your root apps are in the picker now. The list was asking the launcher which activities answer MAIN/LAUNCHER — not "what is installed" — so a hidden root manager, or any app with its launcher entry disabled, was never offered. It is built from installed apps now. ResukiSU was also missing from the module's own "never restrict" list, which meant the app you would rescue the phone with was being treated as an ordinary background app.
  • Deep-phase report, so the caps are on record at the moment they exist rather than invisible afterwards.

Tests

tests/run.sh: 43 cases / 194 assertions, passing (was 184), plus run-install.sh 21/21. Case 31 fails on the old rule, and case 41 reproduces your exact scenario end to end: a stale on marker, the screen goes off, and the CPU cap must still land.