pm disable-user
changes the deviceSwitches a package off for one Android user without removing it — the reversible alternative to uninstalling.
- Command
- adb shell pm disable-user
- Commands
- Packages (pm)
- Risk
- changes the device
Syntax
pm disable-user [--user <id>] <package>
pm enable [--user <id>] <package>Flags and arguments
| Token | Meaning |
|---|---|
| --user <id> | Which Android user to change. Worth passing explicitly, because the state is per user and so is the command that undoes it. |
Examples
pm disable-user --user 0 com.manufacturer.bloatSwitch a preinstalled app off for the primary user.
pm enable --user 0 com.manufacturer.bloatSwitch it back on.
pm list packages -d --user 0Confirm what is disabled, from the platform rather than from memory.
Reading the output
Sample output
Package com.manufacturer.bloat new state: disabled-userThe command prints the state it read back, which is not always the state you asked for — and that is the whole reason to read this line rather than to check for the absence of the word "error". `pm enable` on a package the platform will not re-enable prints `new state: disabled-user` and exits zero. Compare the state to what you wanted.
Output fields
| Field | Meaning |
|---|---|
| disabled-user | Off because a user (or this command) switched it off. |
| disabled | Off because the app or the framework switched it off. |
| disabled-until-used | Off until something needs it. |
| enabled | Explicitly on. |
| default | No override: whatever the app's manifest declares, which is normally on. |
What access it needs
An authorised `adb` connection; no root and no `su`. That is the whole reason this command is the standard answer for a preinstalled app you cannot delete — the enabled state is a per-user override the shell is allowed to set, so nothing is written to the read-only system partition and nothing has to be unlocked first. Two access details shape how the reply should be read. `--user <id>` names whose override is being changed, and a build unwilling to let the shell touch another user's state refuses rather than quietly editing your own. And the platform reserves the right to decline a re-enable: `pm enable` on a package it will not switch back on prints a state line and exits zero, so the exit status is not the signal here. The state named in the line is. `parseEnabledStateLine` also checks that the package in the answer is the package in the question, because a device that replied about something else replied to a different question.
Failure messages, decoded
| Message | Meaning |
|---|---|
| Package com.example new state: disabled-user | Printed by `pm enable`, this is a refusal wearing a success line's clothes: the command ran, exited zero, and left the app switched off. `classifyPmEnabledChange` therefore compares the state that came back against the state that was asked for instead of scanning for the word error, which is the difference between a restore button that works and one that only claims to. |
| Warning: Unknown option | The option loop did not recognise a flag — in practice `--user` on a build too old for it. `isFailureLine` counts this as a failure despite the milder word, because a run that did not understand your flag did not do what you asked, whatever it did instead. |
| Exception occurred while executing 'disable-user': | The wrapper caught a `Throwable` and the following line names it. `IllegalArgumentException` and `NameNotFoundException` both arrive this way and both point at a misspelt or absent package; no state line is printed at all, which is how the classifier separates this from a state it simply did not want. |
What it changes, and the way back
The app stops running, stops receiving broadcasts and disappears from the launcher for that user; nothing is deleted. `pm enable --user <id> <pkg>` switches it back on. Disabling a system service other apps depend on can break them in ways that only show up later, so change one package at a time and watch what stops working.
Version and vendor notes
- `disable-user` sets the state that this command reports back, so a package somebody else had already disabled answers `disabled` or `disabled-until-used`. All three mean it is not running.
- A success line naming a state other than the one you asked for is a failure with a calm voice. Reading the line is the difference between an honest restore button and a broken one.
We have a UI for this
Android Debloat Tool runs this command over USB and parses what comes back — a Chromium browser, no SDK, nothing uploaded.
Related commands
Commands that turn up in the same session as pm disable-user.
| Command | What it does |
|---|---|
| pm uninstall | Removes a package, or removes it for one Android user only — which is how a preinstalled app is disposed of without root. |
| pm list packages | Lists installed packages, optionally with the APK path, uid, version code and installer. |
| dumpsys package | Everything the package manager knows about one app: version, paths, flags, install source and per-user state. |
More Packages (pm) commands
| Command | What it does |
|---|---|
| pm path | Prints the absolute paths of the APK files that make up an installed package. |
| pm clear | Wipes an app's data — or, on Android 13 and later, only its cache. |
| pm trim-caches | Asks the system to drop cached files until the given amount of free space exists. |
| pm install | Installs one APK that is already on the device, which is what `adb install` does under the hood. |
| pm install-create | Opens an install session so several APKs — a base plus its splits — are installed as one atomic unit. |
Checked against AOSP, toybox and kernel sources while writing the parsers behind our Web ADB tools. Where a behaviour genuinely varies by Android version or manufacturer, this page says so instead of giving a number that would be wrong on half the phones out there.