Skip to content

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 (--user ID, see list_users). Omit to use pm's default user.

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 (--user ID, see list_users) instead of adb's default target.

None
replace_existing bool

Replace/reinstall an already-installed version of this package (-r) instead of failing when one is present.

False
allow_downgrade bool

Allow installing a lower versionCode than what's currently installed (-d), where Android's Package Manager permits it (documented as debuggable-package behavior — this does not override a build's own downgrade restrictions).

False
grant_runtime_permissions bool

Grant all of the app's declared runtime permissions automatically at install time (-g).

False
allow_test_packages bool

Allow installing an APK built with android:testOnly="true" (-t), which a plain install rejects.

False
force_sdk bool

Ask the Package Manager to override its usual minSdkVersion/targetSdkVersion compatibility check (--force-sdk). Android still enforces every other install check normally.

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 installed for user: 42" and exit 0. This tool reports that as success; it cannot surface a bogus user_id as an error because pm itself doesn't. Use list_users first if the id must be known-good.

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 (--user ID, see list_users). Omit to use pm's default user.

None
package_filter PackageFilter | None

Restrict to "system" packages (-s) or "third_party" packages (-3) — pm's own mutually exclusive filter flags. Omit to list every package regardless of origin.

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 (--user ID, see list_users). Omit for pm's default/current 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 (--user ID, see list_users) rather than the device's normal (unscoped) uninstall behavior. Removing it for one user never removes it for every user — omit user_id for that instead.

None
keep_data bool

Request that Android preserve the package's data/cache (-k) rather than wiping it. This is what pm's -k provides, not a stronger guarantee beyond what Package Manager itself does.

False
version_code int | None

Only uninstall if the installed package's version code matches (--versionCode CODE). Omit to uninstall regardless of version.

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
}