Skip to content

tracing

Perfetto system traces and ActivityManager Binder/IPC transaction traces.

  • capture_system_traceadb shell perfetto ... + adb pull. Semantic presets (cpu, scheduling, graphics, app_startup, memory, binder), bounded duration 1–120s, optional package scope. Pulled into ADB_AUTOMATION_LOCAL_ROOT/traces/; device file removed afterwards.
  • start_ipc_trace / stop_ipc_traceadb shell am trace-ipc start / am trace-ipc stop --dump-file <dev> + adb pull. start returns session state only; stop dumps the Binder transaction log into ADB_AUTOMATION_LOCAL_ROOT/ipc_traces/ and cleans up the device file.

All three return artifact path/size, never the trace contents.

adb_automation_mcp.modules.tracing.tools

Module-level, statically-introspectable tool functions for the tracing module.

Kept as plain top-level functions, never closures, so that documentation tooling and the registry meta-test can both introspect them directly.

capture_system_trace(ctx: Context, serial: str, preset: TracePreset, local_path: str, duration_seconds: int = 10, package: str | None = None) -> SystemTraceResult async

Capture a bounded Perfetto system trace: adb shell perfetto ... + adb pull.

v1 exposes semantic presets rather than a raw Perfetto config. Each preset maps to a curated set of scheduler / atrace categories: cpu, scheduling, graphics, app_startup, memory, binder. The trace runs for duration_seconds (1-120), is pulled into <ADB_AUTOMATION_LOCAL_ROOT>/traces/, and the device-side file is deleted afterwards (on success and on failure). The trace bytes are not embedded in the response — only the saved path and sizes.

Parameters:

Name Type Description Default
serial str

The target device's adb serial (see list_connected_devices).

required
preset TracePreset

The trace preset — one of "cpu", "scheduling", "graphics", "app_startup", "memory", "binder".

required
local_path str

Destination path relative to the server's local_root traces/ directory, e.g. "startup.perfetto-trace" or "run1/cpu.perfetto-trace". Must resolve inside local_root.

required
duration_seconds int

How long to trace, 1-120 seconds (default 10).

10
package str | None

Optional app package to scope app-level (atrace) events to. Omit for a system-wide trace.

None

Returns:

Type Description
SystemTraceResult

The serial; the preset / duration_seconds / package requested; local_path (the absolute host path the trace was written to); device_bytes (what perfetto reported writing on the device, or null); and size_bytes (the pulled file size, or null).

Error handling

An unknown preset, a duration outside 1-120, or a blank package raises INVALID_ARGUMENT before anything runs. No configured local_root, or a local_path escaping it, raises POLICY_DENIED. An unknown serial raises DEVICE_NOT_FOUND. A device without perfetto raises TRACING_UNAVAILABLE. A perfetto permission rejection raises PERMISSION_DENIED; a failed pull raises REMOTE_FILE_NOT_FOUND / BACKEND_ERROR. The device trace file is cleaned up in every case.

Example

Called with serial="emulator-5554", preset="app_startup", duration_seconds=10, package="com.example.app", local_path="startup.perfetto-trace". A typical response:

{
  "status": "success",
  "message": "Captured a 10s 'app_startup' trace (com.example.app) from emulator-5554 to /data/out/traces/startup.perfetto-trace.",
  "data": {
    "serial": "emulator-5554",
    "preset": "app_startup",
    "duration_seconds": 10,
    "package": "com.example.app",
    "local_path": "/data/out/traces/startup.perfetto-trace",
    "device_bytes": 84260,
    "size_bytes": 84260,
    "success": true
  },
  "error": null
}
Source code in src/adb_automation_mcp/modules/tracing/tools.py
24
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
@category("write")
async def capture_system_trace(
    ctx: Context,
    serial: str,
    preset: TracePreset,
    local_path: str,
    duration_seconds: int = 10,
    package: str | None = None,
) -> SystemTraceResult:
    """Capture a bounded Perfetto system trace: `adb shell perfetto ...` +
    `adb pull`.

    v1 exposes semantic presets rather than a raw Perfetto config. Each
    preset maps to a curated set of scheduler / atrace categories:
    `cpu`, `scheduling`, `graphics`, `app_startup`, `memory`, `binder`.
    The trace runs for duration_seconds (1-120), is pulled into
    `<ADB_AUTOMATION_LOCAL_ROOT>/traces/`, and the device-side file is
    deleted afterwards (on success and on failure). The trace bytes are not
    embedded in the response — only the saved path and sizes.

    Args:
        serial: The target device's adb serial (see list_connected_devices).
        preset: The trace preset — one of "cpu", "scheduling", "graphics",
            "app_startup", "memory", "binder".
        local_path: Destination path relative to the server's local_root
            `traces/` directory, e.g. "startup.perfetto-trace" or
            "run1/cpu.perfetto-trace". Must resolve inside local_root.
        duration_seconds: How long to trace, 1-120 seconds (default 10).
        package: Optional app package to scope app-level (atrace) events to.
            Omit for a system-wide trace.

    Returns:
        The serial; the preset / duration_seconds / package requested;
        local_path (the absolute host path the trace was written to);
        device_bytes (what perfetto reported writing on the device, or
        null); and size_bytes (the pulled file size, or null).

    Error handling:
        An unknown preset, a duration outside 1-120, or a blank package
        raises INVALID_ARGUMENT before anything runs. No configured
        local_root, or a local_path escaping it, raises POLICY_DENIED. An
        unknown serial raises DEVICE_NOT_FOUND. A device without perfetto
        raises TRACING_UNAVAILABLE. A perfetto permission rejection raises
        PERMISSION_DENIED; a failed pull raises
        REMOTE_FILE_NOT_FOUND / BACKEND_ERROR. The device trace file is
        cleaned up in every case.

    Example:
        Called with serial="emulator-5554", preset="app_startup",
        duration_seconds=10, package="com.example.app",
        local_path="startup.perfetto-trace". A typical response:

        ```json
        {
          "status": "success",
          "message": "Captured a 10s 'app_startup' trace (com.example.app) from emulator-5554 to /data/out/traces/startup.perfetto-trace.",
          "data": {
            "serial": "emulator-5554",
            "preset": "app_startup",
            "duration_seconds": 10,
            "package": "com.example.app",
            "local_path": "/data/out/traces/startup.perfetto-trace",
            "device_bytes": 84260,
            "size_bytes": 84260,
            "success": true
          },
          "error": null
        }
        ```
    """
    services = cast("dict[str, object]", ctx.lifespan_context["services"])
    tracing = cast(TracingService, services["tracing"])
    return await tracing.capture_system_trace(
        serial, preset, local_path, duration_seconds=duration_seconds, package=package
    )

start_ipc_trace(ctx: Context, serial: str) -> IpcTraceSession async

Start ActivityManager Binder/IPC transaction tracing: adb shell am trace-ipc start.

Begins recording Binder transactions system-wide. This produces no artifact on its own — call stop_ipc_trace to dump the collected transactions and pull them to the host. Starting when a session is already running is harmless; am doesn't report that case, so this always reports tracing=true on success.

Parameters:

Name Type Description Default
serial str

The target device's adb serial (see list_connected_devices).

required

Returns:

Type Description
IpcTraceSession

The serial and tracing (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 failure (including a build without IPC tracing) raises BACKEND_ERROR.

Example

Called with serial="emulator-5554". A typical response:

{
  "status": "success",
  "message": "Started IPC transaction tracing on emulator-5554.",
  "data": {"serial": "emulator-5554", "tracing": true},
  "error": null
}
Source code in src/adb_automation_mcp/modules/tracing/tools.py
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
@category("write")
async def start_ipc_trace(ctx: Context, serial: str) -> IpcTraceSession:
    """Start ActivityManager Binder/IPC transaction tracing: `adb shell am
    trace-ipc start`.

    Begins recording Binder transactions system-wide. This produces no
    artifact on its own — call stop_ipc_trace to dump the collected
    transactions and pull them to the host. Starting when a session is
    already running is harmless; `am` doesn't report that case, so this
    always reports tracing=true on success.

    Args:
        serial: The target device's adb serial (see list_connected_devices).

    Returns:
        The serial and tracing (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 failure (including a build without IPC
        tracing) raises BACKEND_ERROR.

    Example:
        Called with serial="emulator-5554". A typical response:

        ```json
        {
          "status": "success",
          "message": "Started IPC transaction tracing on emulator-5554.",
          "data": {"serial": "emulator-5554", "tracing": true},
          "error": null
        }
        ```
    """
    services = cast("dict[str, object]", ctx.lifespan_context["services"])
    tracing = cast(TracingService, services["tracing"])
    return await tracing.start_ipc_trace(serial)

stop_ipc_trace(ctx: Context, serial: str, local_path: str) -> IpcTraceResult async

Stop IPC tracing, dump it, and save it to the host: adb shell am trace-ipc stop --dump-file <dev> + adb pull.

Stops the session started by start_ipc_trace, writes the Binder transaction dump to a device temp file, pulls it into <ADB_AUTOMATION_LOCAL_ROOT>/ipc_traces/, and deletes the device file (on success and on failure). The trace text is not embedded in the response — only the saved path and size.

Parameters:

Name Type Description Default
serial str

The target device's adb serial (see list_connected_devices).

required
local_path str

Destination path relative to the server's local_root ipc_traces/ directory, e.g. "ipc.txt" or "run1/ipc.txt". Must resolve inside local_root.

required

Returns:

Type Description
IpcTraceResult

The serial, local_path (the absolute host path the trace was written to), and size_bytes.

Error handling

No configured local_root, or a local_path escaping it, raises POLICY_DENIED. An unknown serial raises DEVICE_NOT_FOUND. Stopping with no active trace, or a failed dump/pull, raises REMOTE_FILE_NOT_FOUND / BACKEND_ERROR. The device temp file is cleaned up in every case.

Example

Called with serial="emulator-5554", local_path="ipc.txt". A typical response:

{
  "status": "success",
  "message": "Saved IPC transaction trace from emulator-5554 to /data/out/ipc_traces/ipc.txt.",
  "data": {
    "serial": "emulator-5554",
    "local_path": "/data/out/ipc_traces/ipc.txt",
    "size_bytes": 6570,
    "success": true
  },
  "error": null
}
Source code in src/adb_automation_mcp/modules/tracing/tools.py
141
142
143
144
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
@category("write")
async def stop_ipc_trace(ctx: Context, serial: str, local_path: str) -> IpcTraceResult:
    """Stop IPC tracing, dump it, and save it to the host: `adb shell am
    trace-ipc stop --dump-file <dev>` + `adb pull`.

    Stops the session started by start_ipc_trace, writes the Binder
    transaction dump to a device temp file, pulls it into
    `<ADB_AUTOMATION_LOCAL_ROOT>/ipc_traces/`, and deletes the device file
    (on success and on failure). The trace text is not embedded in the
    response — only the saved path and size.

    Args:
        serial: The target device's adb serial (see list_connected_devices).
        local_path: Destination path relative to the server's local_root
            `ipc_traces/` directory, e.g. "ipc.txt" or "run1/ipc.txt". Must
            resolve inside local_root.

    Returns:
        The serial, local_path (the absolute host path the trace was written
        to), and size_bytes.

    Error handling:
        No configured local_root, or a local_path escaping it, raises
        POLICY_DENIED. An unknown serial raises DEVICE_NOT_FOUND. Stopping
        with no active trace, or a failed dump/pull, raises
        REMOTE_FILE_NOT_FOUND / BACKEND_ERROR. The device temp file is
        cleaned up in every case.

    Example:
        Called with serial="emulator-5554", local_path="ipc.txt". A typical
        response:

        ```json
        {
          "status": "success",
          "message": "Saved IPC transaction trace from emulator-5554 to /data/out/ipc_traces/ipc.txt.",
          "data": {
            "serial": "emulator-5554",
            "local_path": "/data/out/ipc_traces/ipc.txt",
            "size_bytes": 6570,
            "success": true
          },
          "error": null
        }
        ```
    """
    services = cast("dict[str, object]", ctx.lifespan_context["services"])
    tracing = cast(TracingService, services["tracing"])
    return await tracing.stop_ipc_trace(serial, local_path)