Zygote
Hands-on labsintermediate

Lab 5 — Memory and power

Read a meminfo table without panicking, find the processes holding memory, read battery stats and wakelock history, and understand why 'free RAM' is the wrong question.

6 minAPI 1–37 · 17verified 2026-10-27

Memory and power are the two resources Android manages most aggressively, and the two where folklore is most common. Both have good instrumentation. This lab reads it.

TL;DR#

  • dumpsys meminfo reports total, free, used and lost RAM, plus a per-process PSS summary. A healthy device has a large cached category, not a large free one.
  • PSS counts shared pages proportionally, which is why it is the right number for "how much does this app cost" and why the totals do not simply add up.
  • dumpsys batterystats is a historical record, not a live meter. --charged filters to the last charge cycle.
  • Wakelocks, alarms and jobs are the three mechanisms that keep a device awake. Each has a dump.
  • Doze and App Standby are visible in the dumps as states, and they explain why a background app may not run when you expect.

Mental model#

Think of a hotel with a fixed number of rooms.

Free rooms are unused RAM. Occupied rooms are running processes. Rooms being cleaned are cached pages that can be reused.

A hotel with many free rooms is not healthy; it is empty. A well-run hotel has its rooms occupied and a fast turnaround process for when a guest needs one. Android's "turnaround" is the low-memory killer, and its signal is memory pressure, not free-room count.

Where the analogy breaks#

A hotel guest leaves when they check out. An Android process can be evicted without warning, and it is expected to save its state before that happens. The system's willingness to evict is a feature, not a failure, which is the opposite of the hotel metaphor.

Deep dive#

meminfo#

adb shell dumpsys meminfo

The top section reports total, free, used and lost RAM. The categories below are the ones that matter:

CategoryWhat it is
CachedPages backing cached processes and file cache; reclaimable
FreeTruly unused
UsedAnonymous and kernel memory in active use
LostMemory the kernel cannot account for

A device with a low Free and a high Cached is healthy. A device with a low Free and a low Cached is under pressure.

Per-process:

adb shell dumpsys meminfo <package>
adb shell dumpsys meminfo <pid>

The output includes PSS Total, Private Dirty, Private Clean, and a breakdown by category (Java heap, native heap, code, stack, graphics). PSS is proportional: a page shared by four processes contributes a quarter to each, which is why summing PSS across processes can exceed physical RAM.

Finding the holders#

adb shell dumpsys meminfo

The default output ends with a summary of total PSS by process, which is the fastest answer to "what is using my memory". The flags are worth knowing:1

FlagEffect
-sA short summary of memory categories, per process
-dInclude the Dalvik/ART detail rows
-cCompact, machine-parseable output
-aAll available information for each process
--oomOrganise the processes by OOM adjustment

-d adds detail for Dalvik/ART; --oom is the view you want when the question is "what would the killer evict first".

The framework also tracks process state:

adb shell dumpsys activity processes | grep -E "ProcessRecord|oom adj"

Between the memory numbers and the process states, you can usually tell the difference between "an app is using a lot of memory" and "an app is being kept alive when it should not be".

Battery stats#

adb shell dumpsys batterystats --charged

--charged restricts the output to the period since the last full charge, which is the relevant window for "why did my battery drain today". Without it, the output covers the device's whole recorded history and is much harder to read.

The sections worth knowing:

  • Per-UID battery usage — which apps used what.
  • Wakelocks — what held the device awake.
  • Alarms — what scheduled wakeups.
  • Jobs — what background work ran.
  • Doze and standby state — when the device was idle.

Doze and standby#

Doze is the system's low-power state for an idle, stationary device. App Standby is the per-app version: an app that has not been used is moved into a bucket with fewer privileges.

Both are visible:

adb shell dumpsys deviceidle
adb shell am get-standby-bucket <package>

The standby bucket is the practical thing to check when a background task does not run. An app in a restricted bucket gets fewer job and alarm slots, and no amount of code changes that; the bucket is the platform's decision based on usage.

Foreground services#

A foreground service is the supported way to keep work running, and it shows a notification. The dumpsys activity services output lists running services and whether they are foreground.

A foreground service is not a licence to run forever: since Android 14, foreground service types are mandatory, and some types have timeouts. The dump shows the type.

Walkthrough#

  1. Read the memory summary

    adb shell dumpsys meminfo | head -30

    You should seeTotal, free, used, lost, and a large cached category.
  2. Find the top memory consumers

    adb shell dumpsys meminfo | grep -A 30 "Total PSS by process"

    You should seeA per-process list with PSS totals.
  3. Read one app's breakdown

    adb shell dumpsys meminfo com.android.settings

    You should seePSS, private dirty/clean, and category breakdown.
  4. Read the battery history

    adb shell dumpsys batterystats --charged | head -60

    You should seePer-UID usage and wakelock sections.
  5. Check an app's standby bucket

    adb shell am get-standby-bucket com.android.settings}

    You should seeA bucket number or name.
Memory and power
adb shell dumpsys meminfo | head -30
adb shell dumpsys meminfo | grep -A 30 "Total PSS by process"
adb shell dumpsys meminfo com.android.settings
adb shell dumpsys batterystats --charged | head -60
adb shell am get-standby-bucket com.android.settings
adb shell dumpsys deviceidle
Example output
Illustrative output — values differ per device and over time.

Challenges#

Challenge 1 — Explain the cached number#

Why is a large cached category a sign of health rather than a problem?

Reveal the answer

Cached pages are reclaimable: they hold recently used code and data that the system can drop when memory is needed. Keeping them costs nothing and makes the next access faster. A device with a large cached category has been used and is reusing its memory well; a device with a large free category has been idle or has had its caches cleared, and will be slower on the next action.

Challenge 2 — Attribute memory to an app#

Pick an app and report its PSS and private dirty memory. Explain the difference.

Reveal the answer
adb shell dumpsys meminfo <package> | grep -E "PSS|Private"

PSS is the app's proportional share of all pages it maps, including shared libraries and shared memory. Private dirty is memory that is exclusively the app's and has been modified, so it cannot be reclaimed without swapping or killing the app. Private dirty is the best single number for "what would be freed if this app died".

Challenge 3 — Find what wakes the device#

Use the battery stats to find an alarm or wakelock that is causing wakeups.

Reveal the answer
adb shell dumpsys batterystats --charged | grep -i -A 3 "wakelock"
adb shell dumpsys alarm | head -40

The wakelock section lists holders and durations; the alarm dump lists scheduled alarms with their owners and windows. An app with many short wakeups is usually more expensive than one with a few long ones, because each wakeup costs a transition.

What you learned#

You can read the memory and power instrumentation well enough to tell a healthy device from a pressured one, and to attribute cost to a process or an app. That is the foundation for the tracing labs, which replace these counters with a timeline.

Next#

Lab 6 — Permissions and AppOps looks at the other resource the system rations.

Sources#

Sources

Every version number, API level, class name and date on this page is traced to one of these. Pages are re-verified against them; last_verified above says when.

  1. docsdumpsysdeveloper.android.comaccessed 2026-10-27↩
  2. docsManage your app's memory overviewdeveloper.android.comaccessed 2026-10-27↩
  3. docsManage your app's memorydeveloper.android.comaccessed 2026-10-27↩
  4. docsOptimize power usedeveloper.android.comaccessed 2026-10-27↩
  5. docsOptimize for Doze and App Standbydeveloper.android.comaccessed 2026-10-27↩
  6. docsStandby bucketsdeveloper.android.comaccessed 2026-10-27↩
  7. docsLow-memory killer daemon (lmkd)source.android.comaccessed 2026-10-27↩