< Back to all hacks

#55 termux-wake-lock + Doze Bypass

Boot
Problem
Doze mode suspends CPU after 30 min screen off. Telegram messages delayed 2-3 hours.
Solution
termux-wake-lock (PARTIAL_WAKE_LOCK) + deviceidle whitelist for Termux. CPU stays on, screen off.
Lesson
Wake lock requires com.termux Dalvik alive (48 MB). Killing it releases the lock AND cascade-kills the gateway.

Context

Android 6.0 introduced Doze mode: after 30 minutes of screen-off inactivity, the CPU is suspended to save battery. Periodic maintenance windows (increasing intervals: 15 min, 30 min, 1 hour, 2 hours) allow brief processing bursts. For a phone plugged into power running as a server, Doze is counterproductive — Telegram messages arrive 2-3 hours late because the CPU is suspended.

The solution is a PARTIAL_WAKE_LOCK via Termux's wake lock API, combined with Doze whitelist exemption.

Implementation

Two components: the wake lock and the Doze whitelist.

# In start-pocketclaw.sh (boot script):
termux-wake-lock 2>/dev/null

The Doze whitelist exemption is set once from ADB (persists across reboots):

# From ADB shell (one-time setup):
adb shell dumpsys deviceidle whitelist +com.termux
# Expected: Added: com.termux

# Verify whitelist:
adb shell dumpsys deviceidle whitelist
# Expected: system,com.termux,...

The GC logs prove the difference:

# Without wake lock — CPU suspended, gaps in GC:
# 14:00:00 [gc] freed 15 MB
# 16:30:00 [gc] freed 15 MB  (2.5 hour gap!)
# 18:45:00 [gc] freed 15 MB  (2.25 hour gap!)

# With wake lock — CPU active, regular GC:
# 14:00:00 [gc] freed 15 MB
# 14:00:30 [gc] freed 15 MB  (30s interval as configured)
# 14:01:00 [gc] freed 15 MB

Verification

# Check wake lock is held:
adb shell dumpsys power | grep "Wake Locks"
# Expected: shows Termux wake lock

# Check Doze whitelist:
adb shell dumpsys deviceidle whitelist | grep termux
# Expected: com.termux

# Check Doze state:
adb shell dumpsys deviceidle
# Expected: mState=ACTIVE (not IDLE)

# Verify Telegram responds promptly:
# Send a message to @pocketclawbot
# Expected: response within 5-10 seconds (not hours)

Gotchas

  • Wake lock requires the com.termux Dalvik VM to remain alive (48 MB RSS). Killing it releases the lock AND triggers a cgroup cascade that kills the gateway
  • On a plugged-in phone, battery impact is irrelevant. But if running on battery, wake lock will drain it in 4-6 hours
  • termux-wake-lock is a Termux-specific command that calls Android's PowerManager PARTIAL_WAKE_LOCK API
  • The Doze whitelist exemption persists across reboots. You only need to set it once
  • Some ROMs override Doze settings. If messages are still delayed, check manufacturer-specific battery optimization settings

Result

MetricBeforeAfter
Message delay2-3 hours5-10 seconds
CPU state (screen off)Suspended (Doze)Active
GC intervalErratic (hour gaps)Regular (30s)
Battery on powerN/AN/A (plugged in)