Android WakeLock

ID

kotlin.android_wakelock

Severity

high

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Reliability

Language

Kotlin

Tags

CWE:400, android, efficiency, reliability

Description

Reports a local WakeLock binding obtained via PowerManager.newWakeLock(…​) that is never released within the same function body. An unreleased WakeLock keeps the CPU (or screen) on indefinitely and drains the device battery.

Rationale

fun bad(pm: PowerManager) {
    val wl = pm.newWakeLock(PARTIAL_WAKE_LOCK, "tag")   // FLAW
    wl.acquire()
    doSomething()
}

fun good(pm: PowerManager) {
    val wl = pm.newWakeLock(PARTIAL_WAKE_LOCK, "tag")
    wl.acquire()
    try {
        doSomething()
    } finally {
        wl.release()                                     // OK
    }
}

Once acquired, a WakeLock blocks the device from entering deep sleep until it is released. If the holding code throws before reaching release(), or simply forgets to call it, the lock leaks. The user sees rapid battery drain with no obvious cause.

Remediation

  • Wrap the work in try/finally and call release() in the finally block.

  • Prefer acquire(timeoutMs) so the OS reclaims the lock if your code crashes.

  • Where possible, migrate to WorkManager constraints (setRequiresDeviceIdle(false)) that manage wake state automatically.