Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 57a4f5b4 authored by Felipe Leme's avatar Felipe Leme
Browse files

Improved cmd user list to show unresolved name.

When the user name is not explicitly set, UserManager uses a
"user-friendly" name for them, like "Owner" or "Guest", and
`cmd user` only displays that name, not the unresolved one (null).

Similarly, `dumpsys user` only shows the unresolved name, although it
also shows the "Owner name" in a separate section.

This CL includes the raw name on `cmd user` and the guest name on
`dumpsys user`.

Test: adb shell dumpsys user |grep "Guest name"
Test: adb shell cmd user list -v --all | grep unresolvedName
Bug: 407597096
Flag: EXEMPT changes debugging behavior only

Change-Id: I502f0b037e2d44ec6c90e7736a2950bc0dbfa220
parent 2b5a8e70
Loading
Loading
Loading
Loading
+40 −6
Original line number Diff line number Diff line
@@ -1554,11 +1554,20 @@ public class UserManagerService extends IUserManager.Stub {
    public @NonNull List<UserInfo> getUsers(boolean excludePartial, boolean excludeDying,
            boolean excludePreCreated) {
        checkCreateUsersPermission("query users");
        return getUsersInternal(excludePartial, excludeDying, excludePreCreated);
        return getUsersInternal(excludePartial, excludeDying, excludePreCreated,
                /* resolveNullNames= */ true);
    }

    // Used by cmd users
    @NonNull List<UserInfo> getUsersWithUnresolvedNames(boolean excludePartial,
            boolean excludeDying, boolean excludePreCreated) {
        checkCreateUsersPermission("get users with unresolved names");
        return getUsersInternal(excludePartial, excludeDying, excludePreCreated,
                /* resolveNullNames= */ false);
    }

    private @NonNull List<UserInfo> getUsersInternal(boolean excludePartial, boolean excludeDying,
            boolean excludePreCreated) {
            boolean excludePreCreated, boolean resolveNullNames) {
        synchronized (mUsersLock) {
            ArrayList<UserInfo> users = new ArrayList<>(mUsers.size());
            final int userSize = mUsers.size();
@@ -1569,7 +1578,8 @@ public class UserManagerService extends IUserManager.Stub {
                        || (excludePreCreated && ui.preCreated)) {
                    continue;
                }
                users.add(userWithName(ui));
                var user = resolveNullNames ? userWithName(ui) : ui;
                users.add(user);
            }
            return users;
        }
@@ -2380,6 +2390,7 @@ public class UserManagerService extends IUserManager.Stub {
    private UserInfo userWithName(UserInfo orig) {
        if (orig != null && orig.name == null) {
            String name = null;
            // TODO(b/407597096): refactor to use getName() instead
            if (orig.id == UserHandle.USER_SYSTEM) {
                if (DBG_ALLOCATION) {
                    final int number = mUser0Allocations.incrementAndGet();
@@ -2400,6 +2411,20 @@ public class UserManagerService extends IUserManager.Stub {
        return orig;
    }

    @Nullable
    String getName(UserInfo user) {
        if (user.name != null) {
            return user.name;
        }
        if (user.id == UserHandle.USER_SYSTEM || user.isMain()) {
            return getOwnerName();
        }
        if (user.isGuest()) {
            return getGuestName();
        }
        return null;
    }

    /** Returns whether the given user type is one of the FULL user types. */
    boolean isUserTypeSubtypeOfFull(String userType) {
        UserTypeDetails userTypeDetails = mUserTypes.get(userType);
@@ -4985,7 +5010,11 @@ public class UserManagerService extends IUserManager.Stub {

    /** Returns the oldest Full Admin user, or null is if there none. */
    private @Nullable UserInfo getEarliestCreatedFullUser() {
        final List<UserInfo> users = getUsersInternal(true, true, true);
        // TODO(b/407597096): it could call with resolveNullNames=false, but that method was added
        // in a "pure refactoring" CL
        final List<UserInfo> users = getUsersInternal(/* excludePartial= */ true,
                /* excludeDying= */ true, /* excludePreCreated= */ true,
                /* resolveNullNames= */ true);
        UserInfo earliestUser = null;
        long earliestCreationTime = Long.MAX_VALUE;
        for (int i = 0; i < users.size(); i++) {
@@ -6259,7 +6288,11 @@ public class UserManagerService extends IUserManager.Stub {
    /** Writes a UserInfo pulled atom for each user on the device. */
    private int onPullAtom(int atomTag, List<StatsEvent> data) {
        if (atomTag == FrameworkStatsLog.USER_INFO) {
            final List<UserInfo> users = getUsersInternal(true, true, true);
            // TODO(b/407597096): it could call with resolveNullNames=false, but that method was
            // added in a "pure refactoring" CL
            final List<UserInfo> users = getUsersInternal(/* excludePartial= */ true,
                    /* excludeDying= */ true, /* excludePreCreated= */ true,
                    /* resolveNullNames= */ true);
            final int size = users.size();
            if (size > 1) {
                for (int idx = 0; idx < size; idx++) {
@@ -7615,6 +7648,7 @@ public class UserManagerService extends IUserManager.Stub {
        }
        pw.println("  User version: " + mUserVersion);
        pw.println("  Owner name: " + getOwnerName());
        pw.println("  Guest name: " + getGuestName());
        if (DBG_ALLOCATION) {
            pw.println("  System user allocations: " + mUser0Allocations.get());
        }
@@ -8030,7 +8064,7 @@ public class UserManagerService extends IUserManager.Stub {
        public @NonNull List<UserInfo> getUsers(boolean excludePartial, boolean excludeDying,
                boolean excludePreCreated) {
            return UserManagerService.this.getUsersInternal(excludePartial, excludeDying,
                    excludePreCreated);
                    excludePreCreated, /* resolveNullNames= */ true);
        }

        @Override
+10 −4
Original line number Diff line number Diff line
@@ -183,8 +183,9 @@ public class UserManagerServiceShellCommand extends ShellCommand {
            }
        }
        final IActivityManager am = ActivityManager.getService();
        final List<UserInfo> users = mService.getUsers(/* excludePartial= */ !all,
                /* excludeDying= */ false, /* excludePreCreated= */ !all);
        final List<UserInfo> users = mService.getUsersWithUnresolvedNames(
                /* excludePartial= */ !all, /* excludeDying= */ false,
                /* excludePreCreated= */ !all);
        if (users == null) {
            pw.println("Error: couldn't get users");
            return 1;
@@ -226,10 +227,15 @@ public class UserManagerServiceShellCommand extends ShellCommand {
                    final boolean hasParent = user.profileGroupId != user.id
                            && user.profileGroupId != UserInfo.NO_PROFILE_GROUP_ID;
                    final boolean visible = mService.isUserVisible(user.id);
                    pw.printf("%d: id=%d, name=%s, type=%s, flags=%s%s%s%s%s%s%s%s%s%s\n",
                    final String unresolvedName = user.name;
                    // If name is null, use the default (owner / guest)
                    final String name = user.name != null ? user.name : mService.getName(user);
                    pw.printf("%d: id=%d, name=%s, unresolvedName=%s, type=%s, "
                            + "flags=%s%s%s%s%s%s%s%s%s%s\n",
                            i,
                            user.id,
                            user.name,
                            name,
                            unresolvedName,
                            user.userType.replace("android.os.usertype.", ""),
                            UserInfo.flagsToString(user.flags),
                            hasParent ? " (parentId=" + user.profileGroupId + ")" : "",