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.
Two components: the wake lock and the Doze whitelist.
# In start-pocketclaw.sh (boot script):
termux-wake-lock 2>/dev/nullThe 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# 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)termux-wake-lock is a Termux-specific command that calls Android's PowerManager PARTIAL_WAKE_LOCK API| Metric | Before | After |
|---|---|---|
| Message delay | 2-3 hours | 5-10 seconds |
| CPU state (screen off) | Suspended (Doze) | Active |
| GC interval | Erratic (hour gaps) | Regular (30s) |
| Battery on power | N/A | N/A (plugged in) |