Twitter Android
The Background Ghost
Twitter appeared in every user's top battery consumers — even when they hadn't opened the app in days.
The Incident
In late 2022, Twitter's Android app was flagged widely as one of the top battery drainers on the platform. Users reported significant battery depletion overnight, even after force-stopping the app. Battery Historian logs showed constant background wakeups. The system had become a ghost that refused to sleep.
Evidence from the Scene
- Battery drain continued overnight with the screen off and app in background
- Battery Historian showed CPU wakeups every 15–30 seconds
- Force-stopping the app temporarily halted the drain — until the next launch
- The drain persisted even with all notifications disabled in Android settings
- Android 12+ automatically applied battery restriction to the app after repeated offenses
The Suspects
3 of these are the real root causes. The others are plausible-sounding distractors.
WakeLock acquired on network response but never released on the failure path
Background service polling the timeline API every 30 seconds
AlarmManager using ELAPSED_REALTIME_WAKEUP bypassing Doze mode entirely
Bitmap cache holding references to all decoded tweet images
Room database writes running without transaction blocks
RecyclerView not recycling ViewHolders on large timeline lists
The Verdict
Real Root Causes
WakeLock acquired on network response but never released on the failure path
A WakeLock not released in every code path (including exception handlers) keeps the CPU alive indefinitely. Battery Historian exposes this as a continuous partial wakelock — the most common cause of the drain pattern described.
Background service polling the timeline API every 30 seconds
Polling instead of FCM push is battery-hostile by design. Each poll wakes the radio, runs the full network stack, and prevents Doze mode from engaging — even when there is nothing new to fetch.
AlarmManager using ELAPSED_REALTIME_WAKEUP bypassing Doze mode entirely
ELAPSED_REALTIME_WAKEUP fires even during Doze. Combined with a network request on each alarm, it defeats Android's entire power-saving system. The correct approach is WorkManager with battery and network constraints.
Plausible But Wrong
Bitmap cache holding references to all decoded tweet images
Holding Bitmaps in memory affects RAM usage, not battery. The drain described is CPU and radio wakeups during screen-off — not memory pressure.
Room database writes running without transaction blocks
Unbatched Room writes add disk I/O overhead but would not produce the continuous overnight battery drain visible in Battery Historian.
RecyclerView not recycling ViewHolders on large timeline lists
RecyclerView pool exhaustion causes jank and memory pressure during active scrolling — not background battery drain on a device with the screen off.
Summary
Twitter's background work had been implemented with direct AlarmManager wakeups and a persistent background service — patterns that predate Android's Doze mode introduced in Android 6. When Doze arrived, these patterns began fighting the OS. The app kept winning: acquiring WakeLocks, firing alarms, polling the API every 30 seconds — draining batteries across millions of devices silently. The modern fix is WorkManager with network and battery constraints for non-urgent work, and FCM high-priority messages for anything time-sensitive.
The Real Decision That Caused This
“Using pre-Doze background patterns (WakeLock + AlarmManager + polling) that were never updated to respect Android's power management system introduced in API 23.”
Lesson Hint
Chapter 4 (Networking & Real-Time) covers FCM vs polling trade-offs. Chapter 7 (Platform & Performance) covers WorkManager constraints and Doze-safe background work patterns.
Want to test yourself before reading the verdict?
Open Interactive Case in Autopsy Lab