Advanced AOSP Subsystems
3 min read

Wakelocks in Framework

Understanding Wakelocks in Android

In Android, the default state of the device is asleep. To perform work when the screen is off, an application or system service must explicitly request the system to stay awake. This is achieved using Wakelocks, a power management API exposed through the PowerManager system service.

The PowerManager.WakeLock API

The PowerManager.WakeLock class is the primary mechanism for controlling device power states from the application framework.

To acquire a wakelock, an app must first request the android.permission.WAKE_LOCK permission in its manifest.

// Example: Acquiring a basic partial wakelock
PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wakeLock = powerManager.newWakeLock(
        PowerManager.PARTIAL_WAKE_LOCK, "MyApp::MyBackgroundService");

// Acquire the lock for a maximum of 10 minutes (timeout is highly recommended)
wakeLock.acquire(10 * 60 * 1000L); 

try {
    // Perform background work
    doCriticalBackgroundWork();
} finally {
    // ALWAYS release the wakelock in a finally block
    if (wakeLock.isHeld()) {
        wakeLock.release();
    }
}

Types of Wakelocks

The framework defines several levels of wakelocks, each affecting different hardware components.

PARTIAL_WAKE_LOCK

This is the most common type of wakelock used by background services.

  • Effect: Ensures the CPU remains running. The screen and keyboard backlight will be allowed to turn off.
  • Use Case: Background downloads, audio playback, or processing push notifications.

Deprecated Screen Wakelocks

Historically, developers used FULL_WAKE_LOCK, SCREEN_DIM_WAKE_LOCK, and SCREEN_BRIGHT_WAKE_LOCK to control the display. These are now deprecated.

  • Modern Alternative: Apps should use WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON in their Activity's window. This approach is managed by the WindowManager and automatically handles the lifecycle (e.g., turning off the screen when the app goes to the background).

PROXIMITY_SCREEN_OFF_WAKE_LOCK

Used exclusively during phone calls.

  • Effect: Turns off the screen and disables touch input when the proximity sensor detects an object (like the user's face) near the screen.

Lifecycle and Reference Counting

Wakelocks are reference-counted by default. If acquire() is called three times, release() must be called exactly three times before the system is actually permitted to sleep.

This behavior can be disabled by calling wakeLock.setReferenceCounted(false). In this mode, a single release() call will free the wakelock regardless of how many times it was acquired.

Timed Wakelocks

It is a best practice to always use a timeout when acquiring a wakelock: wakeLock.acquire(timeoutMillis). If the app crashes or fails to call release(), the system will automatically release the lock after the timeout expires, preventing a permanent battery drain.

Debugging Wake Lock Abusers

A single rogue app holding a PARTIAL_WAKE_LOCK can drain a device's battery in hours. Android provides tools to identify these abusers.

Using Dumpsys

The dumpsys power command reveals detailed information about current power state and held wakelocks.

# View all currently held wakelocks
adb shell dumpsys power | grep -i wake_lock

The output identifies the holding process, the type of lock, and the tag provided during creation.

// Sample dumpsys output
Wake Locks: size=2
  PARTIAL_WAKE_LOCK              'MyApp::AudioPlayback' ACQ=-1s234ms (uid=10123 pid=4567)
  PARTIAL_WAKE_LOCK              '*job*/com.example.app/.SyncJob' ACQ=-5s10ms (uid=10050 pid=4500)

Battery Historian

For deeper analysis, developers should use Battery Historian. By capturing a bugreport (adb shell bugreport), Battery Historian can visualize exactly when wakelocks were acquired, how long they were held, and correlate them with CPU usage and battery drops over time.