memory¶
Structured memory diagnostics for a connected device.
get_app_memory_summary/get_app_memory_details—dumpsys meminfo -s|-a <target>, parsed via the sharedadb_automation_mcp.meminfohelpers.get_system_memory_summary— baredumpsys meminfo: RAM totals + top PSS consumers.get_memory_history—dumpsys procstats --hours <h> <package>: the "Process summary" min/avg/max PSS/USS/RSS bands.capture_heap_dump—am dumpheap+adb pullintoADB_AUTOMATION_LOCAL_ROOT/heapdumps/, device temp file cleaned.set_heap_watch/clear_heap_watch—am set-watch-heap <pkg> <bytes>/am clear-watch-heap <pkg>: auto-collect a heap dump when a process's PSS crosses a threshold.get_memory_maps—cat /proc/<pid>/smaps_rollup: the kernel's per-process Rss/Pss + clean/dirty split + swap aggregates (a fixed compact model, not a generic /proc reader).
adb_automation_mcp.modules.memory.tools
¶
Module-level, statically-introspectable tool functions for the memory module.
Kept as plain top-level functions, never closures, so that documentation tooling and the registry meta-test can both introspect them directly.
capture_heap_dump(ctx: Context, serial: str, package: str, local_path: str, force_gc: bool = False, native: bool = False, user_id: int | None = None, timeout_s: float = 120.0) -> HeapDumpResult
async
¶
Capture a heap dump and save it to the host: adb shell am dumpheap
then adb pull.
Dumps the managed heap (or the native heap with native=true) of a
running process to a device temp file, pulls it into
<ADB_AUTOMATION_LOCAL_ROOT>/heapdumps/, and deletes the temp file
(on success and on failure). Categorized write because it forces the
target process to pause and serialize its heap. The .hprof is not
embedded in the response — only its path and size.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
serial
|
str
|
The target device's adb serial (see list_connected_devices). |
required |
package
|
str
|
The process to dump — a package name or a numeric PID as a string. Must be running and debuggable/profileable. |
required |
local_path
|
str
|
Destination path relative to the server's local_root
|
required |
force_gc
|
bool
|
Pass |
False
|
native
|
bool
|
Pass |
False
|
user_id
|
int | None
|
Dump the process for a specific Android user ( |
None
|
timeout_s
|
float
|
How long to wait for the dump to finish, 5-600 seconds (default 120). A large heap on a slow device can take a while. |
120.0
|
Returns:
| Type | Description |
|---|---|
HeapDumpResult
|
The serial and package; local_path (the absolute host path the .hprof was written to); native / force_gc / user_id echoed; and size_bytes (the saved file size, or null if it couldn't be stat'd). |
Error handling
A blank package, a negative user_id, or an out-of-range timeout_s raises INVALID_ARGUMENT. No configured local_root, or a local_path escaping it, raises POLICY_DENIED. An unknown serial raises DEVICE_NOT_FOUND. A package that isn't running raises PACKAGE_NOT_RUNNING; one that can't be dumped (not debuggable/ profileable) raises PERMISSION_DENIED. A failed pull raises REMOTE_FILE_NOT_FOUND / BACKEND_ERROR. The device temp file is cleaned up in every case.
Example
Called with serial="emulator-5554", package="com.android.systemui", local_path="systemui.hprof", force_gc=true. A typical response:
{
"status": "success",
"message": "Captured managed heap dump of com.android.systemui from emulator-5554 to /data/out/heapdumps/systemui.hprof.",
"data": {
"serial": "emulator-5554",
"package": "com.android.systemui",
"local_path": "/data/out/heapdumps/systemui.hprof",
"native": false,
"force_gc": true,
"user_id": null,
"size_bytes": 64329246,
"success": true
},
"error": null
}
Source code in src/adb_automation_mcp/modules/memory/tools.py
271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 | |
clear_heap_watch(ctx: Context, serial: str, package: str) -> ClearHeapWatchResult
async
¶
Clear a previously configured heap watch: adb shell am
clear-watch-heap.
Undoes set_heap_watch for a package. Idempotent — clearing when nothing is watched is a successful no-op.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
serial
|
str
|
The target device's adb serial (see list_connected_devices). |
required |
package
|
str
|
The package whose heap watch to clear, e.g. "com.example.app". |
required |
Returns:
| Type | Description |
|---|---|
ClearHeapWatchResult
|
The serial, package, and cleared (always true on success). |
Error handling
A blank package raises INVALID_ARGUMENT before anything runs. An unknown serial or unresponsive adb binary raises DEVICE_NOT_FOUND/ADB_UNAVAILABLE. A permission rejection raises PERMISSION_DENIED; any other failure raises BACKEND_ERROR.
Example
Called with serial="emulator-5554", package="com.example.app". A typical response:
{
"status": "success",
"message": "Cleared the heap watch for com.example.app on emulator-5554.",
"data": {"serial": "emulator-5554", "package": "com.example.app", "cleared": true},
"error": null
}
Source code in src/adb_automation_mcp/modules/memory/tools.py
410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 | |
get_app_memory_details(ctx: Context, serial: str, target: str) -> AppMemoryDetails
async
¶
Detailed memory breakdown for one app: adb shell dumpsys meminfo -a.
Returns the App Summary totals plus the per-mapping table (categories: "Native Heap", "Dalvik Heap", ".so mmap", ... "TOTAL"), the "Objects" section (view / binder / parcel / WebView counts) and the "SQL" section. Sections vary by Android version, so objects and sql come back as maps and are empty when absent. The raw dump text is never exposed.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
serial
|
str
|
The target device's adb serial (see list_connected_devices). |
required |
target
|
str
|
A package name or a numeric PID as a string. |
required |
Returns:
| Type | Description |
|---|---|
AppMemoryDetails
|
The serial / target / pid / process_name; the App Summary total fields; categories (a list of per-mapping rows with pss/private/ shared/rss/heap columns in KB, columns a build omits are null); objects (name -> count); and sql (name -> value). |
Error handling
Same as get_app_memory_summary: INVALID_ARGUMENT for a blank target, PACKAGE_NOT_RUNNING when nothing is running, and MEMORY_INFO_UNAVAILABLE when no memory sections are recognizable; DEVICE_NOT_FOUND / PERMISSION_DENIED / BACKEND_ERROR otherwise.
Example
Called with serial="emulator-5554", target="com.android.systemui". A typical (trimmed) response:
{
"status": "success",
"message": "com.android.systemui on emulator-5554: 16 memory categories, 12 object counts.",
"data": {
"serial": "emulator-5554",
"target": "com.android.systemui",
"pid": 1224,
"process_name": "com.android.systemui",
"total_pss_kb": 104328,
"total_rss_kb": 264948,
"total_swap_kb": 8,
"categories": [
{"name": "Native Heap", "pss_total_kb": 21824, "private_dirty_kb": 21748, "rss_total_kb": 25540}
],
"objects": {"views": 855, "activities": 0, "local_binders": 374},
"sql": {"memory_used": 0, "malloc_size": 0}
},
"error": null
}
Source code in src/adb_automation_mcp/modules/memory/tools.py
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 | |
get_app_memory_summary(ctx: Context, serial: str, target: str) -> AppMemorySummary
async
¶
Compact memory snapshot for one app/process: adb shell dumpsys meminfo -s.
Parses only the stable "App Summary" totals (Java/Native heap, Code, Stack, Graphics, Private Other, System, and TOTAL PSS/RSS/SWAP), all in kilobytes. For the full per-mapping / object / SQL breakdown use get_app_memory_details.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
serial
|
str
|
The target device's adb serial (see list_connected_devices). |
required |
target
|
str
|
A package name (e.g. "com.android.systemui") or a numeric PID as a string. |
required |
Returns:
| Type | Description |
|---|---|
AppMemorySummary
|
The serial and target queried; pid / process_name from meminfo's header; and the App Summary Pss category fields plus total_pss_kb / total_rss_kb / total_swap_kb. Any field the build didn't emit is null. |
Error handling
A blank target raises INVALID_ARGUMENT before anything runs. An unknown serial or unresponsive adb binary raises DEVICE_NOT_FOUND/ADB_UNAVAILABLE. A target with no running process ("No process found for: ...") raises PACKAGE_NOT_RUNNING. Output with no recognizable header or TOTAL line raises MEMORY_INFO_UNAVAILABLE. A permission rejection raises PERMISSION_DENIED; any other non-zero exit raises BACKEND_ERROR.
Example
Called with serial="emulator-5554", target="com.android.systemui". A typical response:
{
"status": "success",
"message": "com.android.systemui on emulator-5554: 104328 KB total PSS.",
"data": {
"serial": "emulator-5554",
"target": "com.android.systemui",
"pid": 1224,
"process_name": "com.android.systemui",
"java_heap_pss_kb": 25324,
"native_heap_pss_kb": 21748,
"code_pss_kb": 37816,
"stack_pss_kb": 1656,
"graphics_pss_kb": 0,
"private_other_pss_kb": 4280,
"system_pss_kb": 13504,
"total_pss_kb": 104328,
"total_rss_kb": 264948,
"total_swap_kb": 8
},
"error": null
}
Source code in src/adb_automation_mcp/modules/memory/tools.py
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | |
get_memory_history(ctx: Context, serial: str, package: str, hours: int = 3) -> MemoryHistory
async
¶
Historical memory bands for a package: adb shell dumpsys procstats
--hours <hours> <package>.
Reads procstats' "Process summary" min/avg/max PSS/USS/RSS bands per process state ("TOTAL", "Top", "Persistent", ...) accumulated over the requested window. procstats samples lazily, so a package that hasn't been sampled in the window returns has_history=false — a normal result, not an error.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
serial
|
str
|
The target device's adb serial (see list_connected_devices). |
required |
package
|
str
|
The package to look up, e.g. "com.example.app". |
required |
hours
|
int
|
The look-back window, 1-72 hours (default 3). |
3
|
Returns:
| Type | Description |
|---|---|
MemoryHistory
|
The serial / package / hours; has_history; window_start (procstats' aggregation start time); and bands — one entry per process state, each with percent, samples, and pss/uss/rss min/avg/max in kilobytes (fields procstats didn't report are null). |
Error handling
A blank package or an hours value outside 1-72 raises INVALID_ARGUMENT before anything runs. An unknown serial or unresponsive adb binary raises DEVICE_NOT_FOUND/ADB_UNAVAILABLE. A permission rejection raises PERMISSION_DENIED; any other non-zero exit raises BACKEND_ERROR. No accumulated history is has_history=false, not an error.
Example
Called with serial="emulator-5554", package="com.android.systemui", hours=3. A typical response:
{
"status": "success",
"message": "com.android.systemui on emulator-5554: 2 memory band(s) over the last 3h.",
"data": {
"serial": "emulator-5554",
"package": "com.android.systemui",
"hours": 3,
"has_history": true,
"window_start": "2026-09-07 07:48:12",
"bands": [
{
"state": "TOTAL",
"percent": 100.0,
"samples": 8,
"pss_min_kb": 0,
"pss_avg_kb": 63488,
"pss_max_kb": 105472,
"uss_min_kb": 0,
"uss_avg_kb": 55296,
"uss_max_kb": 92160,
"rss_min_kb": 268288,
"rss_avg_kb": 264192,
"rss_max_kb": 268288
}
]
},
"error": null
}
Source code in src/adb_automation_mcp/modules/memory/tools.py
199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 | |
get_memory_maps(ctx: Context, serial: str, pid: int) -> MemoryMaps
async
¶
Get a process's memory-map aggregates: adb shell cat
/proc/<pid>/smaps_rollup.
Returns the kernel's own rollup totals for a process — Rss/Pss, the shared/private clean/dirty split, and swap — all in kilobytes. This is a fixed compact model, not a generic /proc reader. Access may be restricted to root by SELinux on some builds.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
serial
|
str
|
The target device's adb serial (see list_connected_devices). |
required |
pid
|
int
|
The process id to inspect (a positive integer — see processes.get_process_id / list_processes). |
required |
Returns:
| Type | Description |
|---|---|
MemoryMaps
|
The serial and pid, plus rss_kb / pss_kb / pss_dirty_kb / pss_anon_kb / pss_file_kb / pss_shmem_kb / shared_clean_kb / shared_dirty_kb / private_clean_kb / private_dirty_kb / referenced_kb / anonymous_kb / swap_kb / swap_pss_kb / locked_kb. Any field the kernel didn't emit is null. |
Error handling
A non-positive pid raises INVALID_ARGUMENT. An unknown serial or unresponsive adb binary raises DEVICE_NOT_FOUND/ADB_UNAVAILABLE. smaps_rollup being unreadable (SELinux/root) raises PERMISSION_DENIED; the pid not being a running process raises REMOTE_FILE_NOT_FOUND; output with no recognizable fields raises MEMORY_INFO_UNAVAILABLE.
Example
Called with serial="emulator-5554", pid=1224. A typical (trimmed) response:
{
"status": "success",
"message": "pid 1224 on emulator-5554: 127651 KB PSS.",
"data": {
"serial": "emulator-5554",
"pid": 1224,
"rss_kb": 290988,
"pss_kb": 127651,
"private_dirty_kb": 69252,
"shared_clean_kb": 143216,
"swap_kb": 8
},
"error": null
}
Source code in src/adb_automation_mcp/modules/memory/tools.py
450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 | |
get_system_memory_summary(ctx: Context, serial: str) -> SystemMemorySummary
async
¶
System-wide memory totals and top consumers: adb shell dumpsys meminfo.
Reads the RAM totals block (Total / Free / Used / Lost RAM, ZRAM / swap) and the "Total PSS by process" list, bounded to the top entries. Everything else in the (large) dump is ignored.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
serial
|
str
|
The target device's adb serial (see list_connected_devices). |
required |
Returns:
| Type | Description |
|---|---|
SystemMemorySummary
|
The serial; total_ram_kb / free_ram_kb / used_ram_kb / lost_ram_kb; zram_physical_used_kb / zram_in_swap_kb / zram_total_swap_kb; status (the "(status normal)" word); and top_processes (name, pid, user, pss_kb), newest-heaviest first, capped. Fields the dump didn't carry are null. |
Error handling
An unknown serial or unresponsive adb binary raises DEVICE_NOT_FOUND/ADB_UNAVAILABLE. Output with no recognizable RAM totals raises MEMORY_INFO_UNAVAILABLE. A permission rejection raises PERMISSION_DENIED; any other non-zero exit raises BACKEND_ERROR.
Example
Called with serial="emulator-5554". A typical (trimmed) response:
{
"status": "success",
"message": "emulator-5554: 4007632 KB total RAM, 2516255 KB free, 15 top procs.",
"data": {
"serial": "emulator-5554",
"total_ram_kb": 4007632,
"free_ram_kb": 2516255,
"used_ram_kb": 1406266,
"lost_ram_kb": 95527,
"zram_physical_used_kb": 15404,
"zram_in_swap_kb": 19880,
"zram_total_swap_kb": 3005720,
"status": "status normal",
"top_processes": [
{"name": "system", "pid": 729, "user": null, "pss_kb": 266973}
]
},
"error": null
}
Source code in src/adb_automation_mcp/modules/memory/tools.py
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 | |
set_heap_watch(ctx: Context, serial: str, package: str, threshold_bytes: int) -> HeapWatchResult
async
¶
Auto-collect a heap dump when a process gets large: adb shell am
set-watch-heap.
Tells ActivityManager to watch package's PSS and, once it reaches
threshold_bytes, collect a heap dump on the device for later
retrieval. Use clear_heap_watch to stop watching. am doesn't validate
the package, so an unknown one isn't an error. Support varies by
Android version.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
serial
|
str
|
The target device's adb serial (see list_connected_devices). |
required |
package
|
str
|
The package/process to watch, e.g. "com.example.app". |
required |
threshold_bytes
|
int
|
PSS threshold in bytes (must be positive), e.g. 268435456 for 256 MB. |
required |
Returns:
| Type | Description |
|---|---|
HeapWatchResult
|
The serial, package, threshold_bytes, and watching (always true on success). |
Error handling
A blank package or a non-positive threshold_bytes raises INVALID_ARGUMENT before anything runs. An unknown serial or unresponsive adb binary raises DEVICE_NOT_FOUND/ADB_UNAVAILABLE. A permission rejection raises PERMISSION_DENIED; a build that doesn't support the command raises BACKEND_ERROR.
Example
Called with serial="emulator-5554", package="com.example.app", threshold_bytes=268435456. A typical response:
{
"status": "success",
"message": "Watching com.example.app on emulator-5554; a heap dump triggers at 268435456 bytes PSS.",
"data": {
"serial": "emulator-5554",
"package": "com.example.app",
"threshold_bytes": 268435456,
"watching": true
},
"error": null
}
Source code in src/adb_automation_mcp/modules/memory/tools.py
357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 | |