android_services¶
Starting Android services (adb shell am start-service) on a connected device.
Named android_services, not services, to avoid colliding with this
project's own "services" concept (the per-module domain service instances the
registry builds). Foreground-service starts and stopping/querying a service's
status aren't implemented yet.
adb_automation_mcp.modules.android_services.tools
¶
Module-level, statically-introspectable tool functions for the android_services module.
Kept as plain top-level functions, never closures, so that documentation tooling and the registry meta-test can both introspect them directly.
get_service_status(ctx: Context, serial: str, component: str) -> ServiceStatus
async
¶
Status snapshot for one Android Service: adb shell dumpsys activity services <component>.
The way to verify what start_service / start_foreground_service actually did — process/PID, foreground state, start bookkeeping — without parsing dumpsys yourself. A Service can be active for more than one Android user at once, so instances is a list.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
serial
|
str
|
The target device's adb serial (see list_connected_devices). |
required |
component
|
str
|
The service to inspect, in "package/class" form, e.g. "com.example.app/.MyService" (relative ".Class" is resolved against the package). |
required |
Returns:
| Type | Description |
|---|---|
ServiceStatus
|
running (False with an empty instances list when the service isn't active anywhere — a normal result, not an error), and one entry per active instance: user_id, pid, process_name, package_name, is_foreground / foreground_id, start_requested / last_start_id, created_from_fg, and start_foreground_count. Fields this Android version's dump omits come back null. |
Error handling
An empty component raises INVALID_ARGUMENT before any adb call. An
unknown serial raises DEVICE_NOT_FOUND; an unreachable adb binary
raises ADB_UNAVAILABLE. dumpsys activity services can't tell a
stopped service from an unknown or malformed component — all report
"no services match" — so none of those raise; they come back as
running=false.
Example
Called with serial="emulator-5554", component="com.example.app/.MyFgService". A typical response:
{
"status": "success",
"message": "com.example.app/.MyFgService is running on emulator-5554: 2 instance(s), 1 foreground.",
"data": {
"serial": "emulator-5554",
"component": "com.example.app/.MyFgService",
"running": true,
"instances": [
{
"user_id": 0,
"pid": 1884,
"process_name": "com.example.app",
"package_name": "com.example.app",
"is_foreground": true,
"foreground_id": 1,
"start_requested": true,
"last_start_id": 2,
"created_from_fg": false,
"start_foreground_count": 1
}
]
},
"error": null
}
Source code in src/adb_automation_mcp/modules/android_services/tools.py
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 269 270 271 | |
start_foreground_service(ctx: Context, serial: str, component: str, user_id: int | None = None) -> StartForegroundServiceResult
async
¶
Start an Android foreground service: adb shell am start-foreground-service.
Separate from start_service because Android's background-execution rules differ: a plain start-service from the background is refused on Android 8+, while start-foreground-service is allowed but the app must then call startForeground() within a few seconds or the system kills it. This tool reports only that ActivityManager accepted and dispatched the start — not the later startForeground() call.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
serial
|
str
|
The target device's adb serial (see list_connected_devices). |
required |
component
|
str
|
The service to start, in "package/class" form, e.g.
"com.example.app/.MyFgService" ( |
required |
user_id
|
int | None
|
Start the service as one specific Android user ( |
None
|
Returns:
| Type | Description |
|---|---|
StartForegroundServiceResult
|
The serial, component, and user_id the service was started with, plus the raw am output. Only returned on success. |
Error handling
An empty component or negative user_id raises INVALID_ARGUMENT before any adb call. A malformed component string, or a well-formed component that matches no declared service, raises COMPONENT_NOT_FOUND. A service requiring a permission the caller doesn't hold raises PERMISSION_DENIED. A foreground-service-start restriction raises BACKGROUND_SERVICE_RESTRICTED. An unknown serial raises DEVICE_NOT_FOUND; an unreachable adb binary raises ADB_UNAVAILABLE; any other ActivityManager/adb failure raises BACKEND_ERROR.
Example
Called with serial="emulator-5554", component="com.example.app/.MyFgService". A typical response:
{
"status": "success",
"message": "Started foreground service com.example.app/.MyFgService on emulator-5554.",
"data": {
"serial": "emulator-5554",
"component": "com.example.app/.MyFgService",
"user_id": null,
"output": "Starting service: Intent { cmp=com.example.app/.MyFgService }\n"
},
"error": null
}
Source code in src/adb_automation_mcp/modules/android_services/tools.py
87 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 | |
start_service(ctx: Context, serial: str, component: str, user_id: int | None = None) -> StartServiceResult
async
¶
Start an Android service on a device: adb shell am start-service.
Models the target semantically (an explicit component) rather than
accepting a raw am command string — see the module docs for why this
server never exposes arbitrary shell arguments. Only a plain
(non-foreground) service start is supported so far — foreground-service
starts, and stopping/querying a service's status, aren't implemented
yet (see the activities/broadcasts modules for launching activities or
sending broadcasts instead).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
serial
|
str
|
The target device's adb serial (see list_connected_devices). |
required |
component
|
str
|
The service to start, in "package/class" form, e.g.
"com.example.app/.MyService" ( |
required |
user_id
|
int | None
|
Start the service as one specific Android user ( |
None
|
Returns:
| Type | Description |
|---|---|
StartServiceResult
|
The serial, component, and user_id the service was started with, plus the raw am output. Only returned on success — see Error handling below for how each failure kind is distinguished. |
Error handling
Unlike most tools here, am start-service resolves synchronously to
one of several distinct outcomes, each raised as its own tool error
rather than returned as success:false data: a malformed component
string (not "package/class" shape) or a well-formed component that
doesn't match any declared service both raise COMPONENT_NOT_FOUND; a
service requiring a permission the caller doesn't hold raises
PERMISSION_DENIED; Android 8+'s background-service-start limits (the
caller tried to start a service while the app is in the background)
raise BACKGROUND_SERVICE_RESTRICTED; an unresponsive adb binary or
unknown serial raises DEVICE_NOT_FOUND/ADB_UNAVAILABLE; any other
ActivityManager/adb failure raises a generic BACKEND_ERROR.
Example
Called with serial="emulator-5554", component="com.example.app/.MyService". A typical response:
{
"status": "success",
"message": "Started service com.example.app/.MyService on emulator-5554.",
"data": {
"serial": "emulator-5554",
"component": "com.example.app/.MyService",
"user_id": null,
"output": "Starting service: Intent { cmp=com.example.app/.MyService }\n"
},
"error": null
}
Source code in src/adb_automation_mcp/modules/android_services/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 | |
stop_service(ctx: Context, serial: str, component: str, user_id: int | None = None) -> StopServiceResult
async
¶
Stop a started Android service: adb shell am stop-service.
The counterpart to start_service — stops a service that was started via
am (or startService()). Not an error if the service isn't running; that
comes back as stopped=false / was_running=false, since the intended end
state is reached either way.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
serial
|
str
|
The target device's adb serial (see list_connected_devices). |
required |
component
|
str
|
The service to stop, in "package/class" form, e.g.
"com.example.app/.MyService" ( |
required |
user_id
|
int | None
|
Stop the service for one specific Android user ( |
None
|
Returns:
| Type | Description |
|---|---|
StopServiceResult
|
The serial, component, user_id, and: stopped (True only when am reported "Service stopped"), was_running (False when am reported "was not running", None if the outcome wasn't recognized), plus the raw am output. |
Error handling
An empty component or negative user_id raises INVALID_ARGUMENT before
any adb call. A malformed component string raises COMPONENT_NOT_FOUND —
but note am stop-service does NOT distinguish an unknown service
component from a known-but-not-running one, so an unknown component
comes back as was_running=false, not an error. An unknown serial raises
DEVICE_NOT_FOUND; an unreachable adb binary raises ADB_UNAVAILABLE; a
permission denial raises PERMISSION_DENIED; any other am failure raises
BACKEND_ERROR.
Example
Called with serial="emulator-5554", component="com.example.app/.MyService". A typical response:
{
"status": "success",
"message": "Stopped service com.example.app/.MyService on emulator-5554.",
"data": {
"serial": "emulator-5554",
"component": "com.example.app/.MyService",
"user_id": null,
"stopped": true,
"was_running": true,
"output": "Stopping service: Intent { cmp=com.example.app/.MyService }\nService stopped\n"
},
"error": null
}
Source code in src/adb_automation_mcp/modules/android_services/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 197 198 199 200 201 202 | |