debugging¶
Debugging aids for a connected device.
get_process_exit_history—adb shell dumpsys activity exit-info <pkg>: ActivityManager's boundedApplicationExitInforing, parsed into typed records (reason, timestamp, pid, importance, pss/rss, trace availability).set_debug_app/clear_debug_app—adb shell am set-debug-app [-w] [--persistent] <pkg>/am clear-debug-app. Marks (or clears) ActivityManager's debug app; does not attach a debugger.list_jdwp_processes—adb jdwp: PIDs of processes currently exposing a JDWP transport (a snapshot, sinceadb jdwpstreams and never exits).capture_native_backtrace—adb shell debuggerd -b <pid>: native thread backtraces for a running process, parsed to a per-thread summary plus the capped full text. Privileged on production builds.capture_native_tombstone—adb shell debuggerd <pid>: a full native tombstone written intoADB_AUTOMATION_LOCAL_ROOT/tombstones/; returns path + parsed header metadata, not contents.
adb_automation_mcp.modules.debugging.tools
¶
Module-level, statically-introspectable tool functions for the debugging module.
Kept as plain top-level functions, never closures, so that documentation tooling and the registry meta-test can both introspect them directly.
capture_native_backtrace(ctx: Context, serial: str, pid: int) -> NativeBacktrace
async
¶
Capture native thread backtraces for a running process: adb shell
debuggerd -b <pid>.
Dumps every thread's native call stack without stopping the process. Returns the parsed header (process name, ABI), a per-thread summary (name / tid / frame count), and the full backtrace text (capped). This is a privileged operation on production builds — a device that isn't rooted/userdebug rejects it.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
serial
|
str
|
The target device's adb serial (see list_connected_devices). |
required |
pid
|
int
|
The process id to backtrace (a positive integer — see processes.get_process_id / list_processes). |
required |
Returns:
| Type | Description |
|---|---|
NativeBacktrace
|
The serial and pid; process_name and abi from the dump header; thread_count and threads (name / sys_tid / frame_count per thread); and text (the full dump, truncated if very large). |
Error handling
A non-positive pid raises INVALID_ARGUMENT before anything runs. An unknown serial raises DEVICE_NOT_FOUND. A device that requires root for debuggerd, or otherwise refuses it, raises PERMISSION_DENIED. A dead or invalid pid (debuggerd produced no backtrace) raises BACKEND_ERROR.
Example
Called with serial="emulator-5554", pid=1224. A typical (trimmed) response:
{
"status": "success",
"message": "capture_native_backtrace completed successfully.",
"data": {
"serial": "emulator-5554",
"pid": 1224,
"process_name": "com.android.systemui",
"abi": "x86_64",
"thread_count": 2,
"threads": [
{"name": "ndroid.systemui", "sys_tid": 1224, "frame_count": 17}
],
"text": "----- pid 1224 at ... -----\nCmd line: com.android.systemui\n..."
},
"error": null
}
Source code in src/adb_automation_mcp/modules/debugging/tools.py
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 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 | |
capture_native_tombstone(ctx: Context, serial: str, pid: int, local_path: str) -> NativeTombstone
async
¶
Request a full native tombstone for a process and save it to the
host: adb shell debuggerd <pid>.
Triggers a full crash-style dump (registers, memory map, all thread
backtraces) for a running process and writes the human-readable
tombstone text into <ADB_AUTOMATION_LOCAL_ROOT>/tombstones/.
Categorized write because it's a high-impact diagnostic that briefly
pauses the target's threads, and is privileged on production builds. The
tombstone bytes are not embedded in the response — only the saved path
and parsed metadata.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
serial
|
str
|
The target device's adb serial (see list_connected_devices). |
required |
pid
|
int
|
The process id to dump (a positive integer). |
required |
local_path
|
str
|
Destination path relative to the server's local_root
|
required |
Returns:
| Type | Description |
|---|---|
NativeTombstone
|
The serial and pid; process_name / abi / signal from the header;
frame_count (the "N total frames" value); device_tombstone_ref (the
|
Error handling
A non-positive pid raises INVALID_ARGUMENT. No configured local_root, or a local_path escaping it, raises POLICY_DENIED. An unknown serial raises DEVICE_NOT_FOUND. A device that requires root for debuggerd, or refuses it, raises PERMISSION_DENIED. A dead or invalid pid raises BACKEND_ERROR.
Example
Called with serial="emulator-5554", pid=1224, local_path="sysui.txt". A typical response:
{
"status": "success",
"message": "Saved native tombstone for pid 1224 on emulator-5554 to /data/out/tombstones/sysui.txt.",
"data": {
"serial": "emulator-5554",
"pid": 1224,
"process_name": "com.android.systemui",
"abi": "x86_64",
"signal": "35 (<debuggerd signal>), code -1 (SI_QUEUE from pid 7338, uid 0), fault addr --------",
"frame_count": 24,
"device_tombstone_ref": "tombstone_27.pb",
"local_path": "/data/out/tombstones/sysui.txt",
"size_bytes": 18244,
"success": true
},
"error": null
}
Source code in src/adb_automation_mcp/modules/debugging/tools.py
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 | |
clear_debug_app(ctx: Context, serial: str) -> ClearDebugAppResult
async
¶
Clear ActivityManager's configured debug app: adb shell am
clear-debug-app.
Undoes a previous set_debug_app. Idempotent — calling it when no debug
app is set is a successful no-op, and cleared being true does not
imply one had been configured.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
serial
|
str
|
The target device's adb serial (see list_connected_devices). |
required |
Returns:
| Type | Description |
|---|---|
ClearDebugAppResult
|
The serial and cleared (always true on success). |
Error handling
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.
Example
Called with serial="emulator-5554". A typical response:
{
"status": "success",
"message": "Cleared the debug app on emulator-5554.",
"data": {"serial": "emulator-5554", "cleared": true},
"error": null
}
Source code in src/adb_automation_mcp/modules/debugging/tools.py
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 | |
get_process_exit_history(ctx: Context, serial: str, package: str) -> ProcessExitHistory
async
¶
Get a package's recent process-exit records: adb shell dumpsys
activity exit-info <package>.
ActivityManager keeps a bounded ApplicationExitInfo ring per package.
This parses it into typed records — reason (crash / ANR / low-memory
kill / self-exit / signalled), timestamp, pid, importance, pss/rss, and
whether a trace was captured — so an agent can explain why an app died.
Reading only. A package with no retained history returns an empty list,
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 |
Returns:
| Type | Description |
|---|---|
ProcessExitHistory
|
The serial / package / count, and records (newest first). Each record has timestamp, pid, real_uid, user, process, reason_code + reason label, subreason_code + subreason label, status, importance, pss and rss (the raw strings the dump reports), state, description, trace_available (bool), and has_anr_info (bool). Fields the record didn't carry are null. |
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 non-zero exit raises BACKEND_ERROR. An unknown package or one with no history is an empty result, not an error.
Example
Called with serial="emulator-5554", package="com.example.app". A typical response:
{
"status": "success",
"message": "2 exit records for com.example.app on emulator-5554 (newest: APP CRASH(EXCEPTION) at 2026-09-06 22:39:39.266).",
"data": {
"serial": "emulator-5554",
"package": "com.example.app",
"count": 2,
"records": [
{
"timestamp": "2026-09-06 22:39:39.266",
"pid": 5486,
"real_uid": 10234,
"user": 0,
"process": "com.example.app",
"reason_code": 4,
"reason": "APP CRASH(EXCEPTION)",
"subreason_code": 0,
"subreason": "UNKNOWN",
"status": 0,
"importance": 400,
"pss": "0.00",
"rss": "167MB",
"state": "empty",
"description": "crash",
"trace_available": false,
"has_anr_info": false
}
]
},
"error": null
}
Source code in src/adb_automation_mcp/modules/debugging/tools.py
25 26 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 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | |
list_jdwp_processes(ctx: Context, serial: str) -> JdwpProcessList
async
¶
List processes exposing a JDWP transport: adb jdwp.
Returns the PIDs of the device's debuggable processes that currently
have a Java Debug Wire Protocol endpoint open — the candidates you can
attach a debugger or jdb to. adb jdwp streams and never exits on its
own, so this returns a snapshot taken after a short settle window.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
serial
|
str
|
The target device's adb serial (see list_connected_devices). |
required |
Returns:
| Type | Description |
|---|---|
JdwpProcessList
|
The serial, count, and pids (a list of integers, in first-seen order, deduplicated). An empty list is a normal result. |
Error handling
An unknown/offline serial raises DEVICE_NOT_FOUND; the adb binary being unreachable raises ADB_UNAVAILABLE. Any other non-zero exit raises BACKEND_ERROR. Non-numeric lines in the output are ignored.
Example
Called with serial="emulator-5554". A typical response:
{
"status": "success",
"message": "3 JDWP-debuggable process(es) on emulator-5554: [1224, 1568, 2411].",
"data": {"serial": "emulator-5554", "count": 3, "pids": [1224, 1568, 2411]},
"error": null
}
Source code in src/adb_automation_mcp/modules/debugging/tools.py
198 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 | |
set_debug_app(ctx: Context, serial: str, package: str, wait_for_debugger: bool = False, persistent: bool = False) -> SetDebugAppResult
async
¶
Mark an app as ActivityManager's debug app: adb shell am set-debug-app.
Records package as the debug app so its next launch is
debugger-friendly. This does NOT attach a debugger — it only sets the
marker. With wait_for_debugger the next launch of the app blocks until a
debugger connects (-w); with persistent the setting survives reboot
(--persistent). Pair with clear_debug_app when done.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
serial
|
str
|
The target device's adb serial (see list_connected_devices). |
required |
package
|
str
|
The package to mark, e.g. "com.example.app". |
required |
wait_for_debugger
|
bool
|
Block the app's next launch until a debugger
attaches ( |
False
|
persistent
|
bool
|
Keep the setting across reboots ( |
False
|
Returns:
| Type | Description |
|---|---|
SetDebugAppResult
|
The serial, package, and the wait_for_debugger / persistent flags that were applied. |
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 non-zero exit raises BACKEND_ERROR. An
unknown package is NOT an error — am doesn't validate it.
Example
Called with serial="emulator-5554", package="com.example.app", wait_for_debugger=true. A typical response:
{
"status": "success",
"message": "Set com.example.app as the debug app on emulator-5554 (waits for debugger on next launch).",
"data": {
"serial": "emulator-5554",
"package": "com.example.app",
"wait_for_debugger": true,
"persistent": false
},
"error": null
}
Source code in src/adb_automation_mcp/modules/debugging/tools.py
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 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 | |