Packages¶
Installed-app management on a connected device: listing (pm list
packages), installing (adb install), uninstalling (pm uninstall),
making an installed package available to another user (pm
install-existing), reading a package's APK paths and details, and enabling
or disabling a package or component (pm enable / pm disable). Options are
semantic rather than raw adb/pm flags — see each tool's Args for how they
map to Android's behavior.
get_package_info
¶
Curated snapshot of an installed package: adb shell dumpsys package <pkg>.
Parses the stable, automation-relevant fields out of dumpsys — version, UID, install/update times, code path, data dir, installer, flags, per-user enabled/installed state, and requested vs. granted permissions — instead of returning the (very large, version-variable) raw dump. Fields dumpsys doesn't report on a given Android version come back null / empty, never an error.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
serial
|
str
|
The target device's adb serial (see list_connected_devices). |
required |
package_name
|
str
|
The application id to inspect, e.g. "com.example.app". |
required |
Returns:
| Type | Description |
|---|---|
PackageInfo
|
A PackageInfo: package_name, uid, version_code / version_name, min_sdk / target_sdk, code_path, data_dir, installer_package_name, first_install_time / last_update_time, is_system, flags, users (per Android user: installed, enabled_state, stopped, hidden, suspended), requested_permissions, and granted_permissions (every permission with granted=true anywhere in the dump — install-time and runtime, across users). |
Error handling
An empty package_name raises INVALID_ARGUMENT before any adb call. An unknown serial raises DEVICE_NOT_FOUND; an unreachable adb binary raises ADB_UNAVAILABLE. A package dumpsys has no record of raises PACKAGE_NOT_FOUND (dumpsys says "Unable to find package" and still exits 0 — this tool turns that into the error).
Example
Called with serial="emulator-5554", package_name="com.example.thirdparty". A typical response:
{
"status": "success",
"message": "com.example.thirdparty 4.5.0 (user) on emulator-5554: 3 granted / 4 requested permissions, 1 user(s).",
"data": {
"serial": "emulator-5554",
"package_name": "com.example.thirdparty",
"uid": 10234,
"version_code": 4500,
"version_name": "4.5.0",
"min_sdk": 24,
"target_sdk": 34,
"code_path": "/data/app/~~kQ7d==/com.example.thirdparty-Ab3c==",
"data_dir": "/data/user/0/com.example.thirdparty",
"installer_package_name": "com.android.vending",
"first_install_time": "2026-09-01 12:00:00",
"last_update_time": "2026-09-03 08:30:00",
"is_system": false,
"flags": ["HAS_CODE", "ALLOW_CLEAR_USER_DATA", "ALLOW_BACKUP"],
"users": [
{"user_id": 0, "installed": true, "enabled_state": "enabled",
"stopped": false, "hidden": false, "suspended": false}
],
"requested_permissions": [
"android.permission.INTERNET", "android.permission.ACCESS_NETWORK_STATE",
"android.permission.CAMERA", "android.permission.ACCESS_FINE_LOCATION"
],
"granted_permissions": [
"android.permission.INTERNET", "android.permission.ACCESS_NETWORK_STATE",
"android.permission.CAMERA"
]
},
"error": null
}
get_package_path
¶
Resolve an installed package's on-device APK paths: adb shell pm path.
Use this before pulling or analyzing an app's APKs — it returns the base
APK plus any split APKs (split_config.*) for a split-installed app, so a
follow-up pull can fetch every piece.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
serial
|
str
|
The target device's adb serial (see list_connected_devices). |
required |
package_name
|
str
|
The application id to resolve, e.g. "com.example.app". |
required |
user_id
|
int | None
|
Resolve against one Android user's view ( |
None
|
Returns:
| Type | Description |
|---|---|
PackagePathInfo
|
The serial, package_name, user_id, and paths — every APK path pm reported, in its order. base_apk is the base APK (identified by a trailing "/base.apk", else the first path), and split_apks is the rest; for a monolithic install split_apks is empty and base_apk is the single path. |
Error handling
An empty package_name or negative user_id raises INVALID_ARGUMENT
before any adb call. An unknown serial raises DEVICE_NOT_FOUND; an
unreachable adb binary raises ADB_UNAVAILABLE. A package that isn't
installed (or isn't installed for the requested user) raises
PACKAGE_NOT_FOUND — pm path reports both the same way. A recognizably
bad user scope raises USER_NOT_FOUND where pm says so.
Example
Called with serial="emulator-5554", package_name="com.android.car.settings". A typical response:
{
"status": "success",
"message": "com.android.car.settings on emulator-5554: 1 APK.",
"data": {
"serial": "emulator-5554",
"package_name": "com.android.car.settings",
"user_id": null,
"paths": ["/system/priv-app/CarSettings/CarSettings.apk"],
"base_apk": "/system/priv-app/CarSettings/CarSettings.apk",
"split_apks": []
},
"error": null
}
install_apk
¶
Install an APK on a connected device (adb install).
Exposes semantic installation options rather than raw adb/pm flags. Android's Package Manager remains the final authority on whether a requested installation is legal — these options select supported installation behavior, they never bypass signature checks, Package Manager restrictions, or (absent the matching option) SDK/downgrade restrictions.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
serial
|
str
|
The target device's adb serial (see list_connected_devices). |
required |
apk_path
|
str
|
Path to the APK to install, resolved by adb itself (a host path when running against a real device/emulator). Must not be empty. |
required |
user_id
|
int | None
|
Install the APK for one Android user ( |
None
|
replace_existing
|
bool
|
Replace/reinstall an already-installed version of
this package ( |
False
|
allow_downgrade
|
bool
|
Allow installing a lower versionCode than what's
currently installed ( |
False
|
grant_runtime_permissions
|
bool
|
Grant all of the app's declared runtime
permissions automatically at install time ( |
False
|
allow_test_packages
|
bool
|
Allow installing an APK built with
|
False
|
force_sdk
|
bool
|
Ask the Package Manager to override its usual
minSdkVersion/targetSdkVersion compatibility check
( |
False
|
Returns:
| Type | Description |
|---|---|
InstallResult
|
Whether the install succeeded, the requested apk_path and user_id, and which semantic options were requested (not raw flags). |
Error handling
Raises DeviceNotFoundError if serial doesn't match a connected device. Raises AndroidRejectionError when adb install reports a "Failure [REASON]" outcome — e.g. a signature mismatch, a downgrade/SDK/test-package restriction the requested options didn't cover, or insufficient storage — REASON is included in the error details. Raises InvalidArgumentError for an empty apk_path or a negative user_id. Any other non-zero exit surfaces as BackendError.
Example
Called with serial="emulator-5554", apk_path="/tmp/app-debug.apk", replace_existing=True. A typical response:
{
"status": "success",
"message": "Installed /tmp/app-debug.apk on emulator-5554.",
"data": {
"serial": "emulator-5554",
"apk_path": "/tmp/app-debug.apk",
"user_id": null,
"replace_existing": true,
"allow_downgrade": false,
"grant_runtime_permissions": false,
"allow_test_packages": false,
"force_sdk": false,
"success": true,
"output": "Performing Streamed Install\nSuccess\n"
},
"error": null
}
install_existing_for_user
¶
Make an already-installed package available to another Android user
(adb shell pm install-existing --user USER_ID PACKAGE).
This is distinct from install_apk: it never touches an APK file, it only extends an app that's already present on the device to another user's view of it (e.g. a work profile or a secondary user on a multi-user/automotive build).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
serial
|
str
|
The target device's adb serial (see list_connected_devices). |
required |
package_name
|
str
|
The already-installed package to make available. Must not be empty. |
required |
user_id
|
int
|
The Android user to make the package available to (see list_users). |
required |
Returns:
| Type | Description |
|---|---|
InstallExistingResult
|
The package name, target user, and whether the operation succeeded. Requesting this for a user the package is already available to is not an error — pm install-existing is idempotent. |
Error handling
Raises DeviceNotFoundError if serial doesn't match a connected device. Raises PackageNotFoundError when package_name isn't installed on the device at all. Raises AndroidRejectionError for any other on-device Package Manager rejection. Raises InvalidArgumentError for an empty package_name or a negative user_id. Any other non-zero exit surfaces as BackendError.
Note: pm install-existing does NOT validate the target user —
verified live that a non-existent user_id (e.g. 42 on a
single-user device) still returns "Package
Example
Called with serial="emulator-5554", package_name="com.example.app", user_id=10. A typical response:
{
"status": "success",
"message": "Made com.example.app available for user 10 on emulator-5554.",
"data": {
"serial": "emulator-5554",
"package_name": "com.example.app",
"user_id": 10,
"success": true,
"output": "Package com.example.app installed for user: 10\n"
},
"error": null
}
list_packages
¶
List installed Android packages on a device: adb shell pm list packages.
Returns parsed package names only, not pm's raw text output.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
serial
|
str
|
The target device's adb serial (see list_connected_devices). |
required |
user_id
|
int | None
|
Restrict the listing to one Android user's package view
( |
None
|
package_filter
|
PackageFilter | None
|
Restrict to "system" packages ( |
None
|
Returns:
| Type | Description |
|---|---|
PackageList
|
The serial and every matching package name. An empty list is a normal result (e.g. no third-party apps installed), not an error. |
Error handling
Propagates the same way most tools do (unlike check_adb_available): if the adb binary itself can't be found or is unresponsive, or the serial doesn't match a connected device, that surfaces as an actual tool error.
Example
Called with serial="emulator-5554", package_filter="third_party". A typical response:
{
"status": "success",
"message": "2 packages on emulator-5554.",
"data": {
"serial": "emulator-5554",
"packages": ["com.example.app", "com.example.other"]
},
"error": null
}
set_package_enabled_state
¶
Enable or disable an app, or one of its components: adb shell pm enable|disable|....
Use this to turn a package (or a specific Activity / Service / Receiver / Provider) on or off for automation — e.g. disable a receiver, observe the behavior change, then set it back to "default". Reversible: "default" clears any override this tool (or anything else) set.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
serial
|
str
|
The target device's adb serial (see list_connected_devices). |
required |
package_name
|
str
|
The application id, e.g. "com.example.app". |
required |
state
|
PackageEnabledState
|
The state to set. One of "enabled", "disabled", "disabled_user" (disable only for the given/current user, the safe choice for an app package — plain "disabled" is often refused for system apps), or "default" (clear any override). |
required |
component
|
str | None
|
Optional class name of a single component to target instead of the whole package — either relative (".MyReceiver") or fully qualified ("com.example.app.MyReceiver"). No spaces or "/". |
None
|
user_id
|
int | None
|
Apply for one Android user ( |
None
|
Returns:
| Type | Description |
|---|---|
PackageEnabledStateResult
|
The serial, package_name, component (null for a whole-package change), the resolved target string ("pkg" or "pkg/component"), user_id, requested_state, and new_state — the state pm confirmed, normalized to the same names as the request ("disabled_user", not "disabled-user"). |
Error handling
An empty package_name, unknown state, negative user_id, or malformed component raises INVALID_ARGUMENT before any adb call. An unknown serial raises DEVICE_NOT_FOUND; an unreachable adb binary raises ADB_UNAVAILABLE. A package pm doesn't know raises PACKAGE_NOT_FOUND. pm refusing the change — a protected/system package, or a component the shell isn't allowed to touch (pm reports an absent component the same way) — raises PERMISSION_DENIED.
Example
Called with serial="emulator-5554", package_name="com.example.app", state="disabled_user". A typical response:
{
"status": "success",
"message": "com.example.app on emulator-5554 is now 'disabled_user'.",
"data": {
"serial": "emulator-5554",
"package_name": "com.example.app",
"component": null,
"target": "com.example.app",
"user_id": null,
"requested_state": "disabled_user",
"new_state": "disabled_user",
"success": true
},
"error": null
}
uninstall_package
¶
Uninstall a package on a connected device (adb shell pm uninstall).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
serial
|
str
|
The target device's adb serial (see list_connected_devices). |
required |
package_name
|
str
|
The package to uninstall. Must not be empty. |
required |
user_id
|
int | None
|
Uninstall the package for one Android user ( |
None
|
keep_data
|
bool
|
Request that Android preserve the package's data/cache
( |
False
|
version_code
|
int | None
|
Only uninstall if the installed package's version
code matches ( |
None
|
Returns:
| Type | Description |
|---|---|
UninstallResult
|
The package name, target user (if any), whether data retention was requested, and whether the uninstall succeeded. |
Error handling
Raises DeviceNotFoundError if serial doesn't match a connected device. Raises PackageNotFoundError when the package isn't installed at all, or isn't installed for the targeted user. Raises UserNotFoundError when user_id doesn't correspond to an Android user on the device. Raises AndroidRejectionError for any other on-device Package Manager rejection (e.g. a version_code that doesn't match the installed package). Raises InvalidArgumentError for an empty package_name, a negative user_id, or a non-positive version_code. Any other non-zero exit surfaces as BackendError.
Example
Called with serial="emulator-5554", package_name="com.example.app", user_id=10. A typical response:
{
"status": "success",
"message": "Uninstalled com.example.app on emulator-5554 for user 10.",
"data": {
"serial": "emulator-5554",
"package_name": "com.example.app",
"user_id": 10,
"keep_data": false,
"version_code": null,
"success": true,
"output": "Success\n"
},
"error": null
}