Understanding Multi-User Mode on Android Devices When Using UAD-ng: Key Implications

UAD-ng detects and respects Android's multi-user architecture by checking SDK version 21+, enumerating user profiles, skipping protected users, and warning about cross-user package restoration side effects.

The Universal Android Debloater Next Generation (UAD-ng) is designed to handle Android's multi-user system safely and transparently. When managing packages across devices with multiple profiles, the tool adapts its debloating logic to prevent accidental modifications to secondary users or protected accounts. This awareness is crucial for maintaining system stability on shared devices, work profiles, or restricted user environments.

How UAD-ng Detects Multi-User Capability

UAD-ng determines whether a device supports multiple users through SDK version verification before attempting any package modifications.

SDK Version Verification

In crates/uad-core/src/sync.rs, the supports_multi_user function checks the device's SDK version against the constant MULTI_USER_SDK (Lollipop 5.0, API 21). Devices running API level 21 or higher are flagged as potentially supporting multiple users, while older devices are treated as single-user systems.

use uad_core::{Phone, sync};

// Check if device supports multi-user mode
let phone: Phone = /* obtain from ADB discovery */;
if sync::supports_multi_user(&phone) {
    println!("Device supports multi-user mode (SDK ≥ {})", sync::MULTI_USER_SDK);
}

This detection serves as a best-effort gate: a true value indicates the SDK is sufficient, but actual multi-user support may still be absent on heavily customized OEM builds.

Enumerating and Managing User Profiles

Once multi-user capability is confirmed, UAD-ng enumerates all user accounts to determine which profiles can be safely modified.

Listing Device Users

The list_users_idx_prot function in crates/uad-core/src/sync.rs executes the ADB command pm list-users and constructs a vector of User structs. Each struct contains the user ID, index, and a protected flag indicating whether the profile restricts modifications.

let users = sync::list_users_idx_prot(&phone.serial);
for user in users {
    println!(
        "User {} (index {}): {}",
        user.id,
        user.index,
        if user.protected { "protected - read only" } else { "modifiable" }
    );
}

Identifying Protected Accounts

UAD-ng identifies protected users through the is_protected_user helper function. This utility attempts to list packages for a given user ID; if the operation returns an error, the user is marked as protected and excluded from debloating operations.

// Check if user 10 is protected before attempting modifications
let is_prot = sync::is_protected_user(10, &phone.serial);
if is_prot {
    println!("Skipping protected user 10");
}

Protected profiles typically include the device owner or restricted work profiles that require root access to modify.

Cross-User Package Restoration Warnings

Android OEMs sometimes implement cross-user package restoration, where enabling or disabling a package for one user inadvertently affects other users who previously did not have that package installed.

Detecting OEM Side Effects

The detect_cross_user_change function in crates/uad-core/src/sync.rs (lines 350-388) monitors for this behavior. When UAD-ng enables or disables a package for a target user, the algorithm checks whether the same package appears on other users that previously lacked it. If detected, the tool generates a warning string alerting the operator to the potential side effect.

This safety mechanism prevents situations where debloating a secondary profile causes system apps to reappear or disappear from the primary user account unexpectedly.

Multi-User Safety Features in Practice

UAD-ng implements several safeguards to respect Android's multi-user model:

  • Default Scope: By default, UAD-ng operates only on the current user unless explicitly instructed otherwise via the --user flag.
  • Protected User Skipping: The tool automatically bypasses any package changes for protected users to avoid permission errors.
  • Isolation: UAD-ng never alters packages belonging to other users unless explicitly targeted, preventing accidental removal of apps required by secondary profiles.
  • CLI Awareness: The command-line interface explicitly marks the tool as "Multi-user aware" in crates/uad-cli/README.md (lines 229-230), reminding operators of these architectural constraints.

Summary

  • UAD-ng checks for multi-user support via supports_multi_user by verifying SDK version ≥ 21 in crates/uad-core/src/sync.rs.
  • The tool enumerates all device users with list_users_idx_prot, parsing ADB output to identify user IDs and protection status.
  • Protected users are detected via is_protected_user and automatically excluded from modification attempts.
  • Cross-user package restoration is monitored through detect_cross_user_change, with warnings generated when OEM behavior may cause unintended propagation across profiles.
  • By default, UAD-ng targets only the current user profile, requiring explicit flags to modify secondary users.

Frequently Asked Questions

What Android versions support multi-user mode in UAD-ng?

UAD-ng identifies multi-user capability on devices running Android 5.0 (Lollipop) or higher, corresponding to API level 21. The tool uses the MULTI_USER_SDK constant to perform this check. However, some OEM customizations may disable multi-user functionality even on supported SDK versions, in which case UAD-ng treats the device as single-user.

Does UAD-ng modify packages across all user profiles by default?

No. UAD-ng operates exclusively on the current user profile unless you explicitly specify a different target using the --user flag. This design prevents accidental debloating of secondary profiles, work accounts, or restricted user environments that may depend on specific system packages.

What happens if I try to debloat a protected user profile?

UAD-ng will skip the operation entirely. The is_protected_user function detects protected status by attempting to list packages for the specified user ID. If the check fails (indicating insufficient permissions or restrictions), UAD-ng marks the user as protected and excludes it from all package modification operations to prevent permission errors.

How does UAD-ng handle OEM-specific cross-user package restoration?

When enabling or disabling packages, UAD-ng runs the detect_cross_user_change logic to monitor for OEM-specific behavior where changes propagate across user boundaries. If the tool detects that a package modification for one user has caused the same package to appear on other users who previously lacked it, it generates a warning message. This allows operators to review the implications before proceeding with additional changes.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →