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

Commit b9a57da9 authored by Adam Bookatz's avatar Adam Bookatz Committed by Android (Google) Code Review
Browse files

Merge "Introduce user types"

parents 77c54b3a 029832a9
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -516,7 +516,7 @@ public class UserLifecycleTests {
    /** Creates a managed (work) profile under the current user, returning its userId. */
    private int createManagedProfile() {
        final UserInfo userInfo = mUm.createProfileForUser("TestProfile",
                UserInfo.FLAG_MANAGED_PROFILE, mAm.getCurrentUser());
                UserManager.USER_TYPE_PROFILE_MANAGED, /* flags */ 0, mAm.getCurrentUser());
        if (userInfo == null) {
            throw new IllegalStateException("Creating managed profile failed. Most likely there is "
                    + "already a pre-existing profile on the device.");
+14 −25
Original line number Diff line number Diff line
@@ -92,7 +92,6 @@ import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.DebugUtils;
import android.util.IconDrawableFactory;
import android.util.LauncherIcons;
import android.util.Log;
import android.view.Display;
@@ -1474,11 +1473,11 @@ public class ApplicationPackageManager extends PackageManager {

    @Override
    public Drawable getUserBadgedIcon(Drawable icon, UserHandle user) {
        if (!isManagedProfile(user.getIdentifier())) {
        if (!hasUserBadge(user.getIdentifier())) {
            return icon;
        }
        Drawable badge = new LauncherIcons(mContext).getBadgeDrawable(
                com.android.internal.R.drawable.ic_corp_icon_badge_case,
                getUserManager().getUserIconBadgeResId(user.getIdentifier()),
                getUserBadgeColor(user));
        return getBadgedDrawable(icon, badge, null, true);
    }
@@ -1493,26 +1492,21 @@ public class ApplicationPackageManager extends PackageManager {
        return getBadgedDrawable(drawable, badgeDrawable, badgeLocation, true);
    }

    @VisibleForTesting
    public static final int[] CORP_BADGE_LABEL_RES_ID = new int[] {
        com.android.internal.R.string.managed_profile_label_badge,
        com.android.internal.R.string.managed_profile_label_badge_2,
        com.android.internal.R.string.managed_profile_label_badge_3
    };

    /** Returns the color of the user's actual badge (not the badge's shadow). */
    private int getUserBadgeColor(UserHandle user) {
        return IconDrawableFactory.getUserBadgeColor(getUserManager(), user.getIdentifier());
        return getUserManager().getUserBadgeColor(user.getIdentifier());
    }

    @Override
    public Drawable getUserBadgeForDensity(UserHandle user, int density) {
        Drawable badgeColor = getManagedProfileIconForDensity(user,
        // This is part of the shadow, not the main color, and is not actually corp-specific.
        Drawable badgeColor = getProfileIconForDensity(user,
                com.android.internal.R.drawable.ic_corp_badge_color, density);
        if (badgeColor == null) {
            return null;
        }
        Drawable badgeForeground = getDrawableForDensity(
                com.android.internal.R.drawable.ic_corp_badge_case, density);
                getUserManager().getUserBadgeResId(user.getIdentifier()), density);
        badgeForeground.setTint(getUserBadgeColor(user));
        Drawable badge = new LayerDrawable(new Drawable[] {badgeColor, badgeForeground });
        return badge;
@@ -1520,8 +1514,8 @@ public class ApplicationPackageManager extends PackageManager {

    @Override
    public Drawable getUserBadgeForDensityNoBackground(UserHandle user, int density) {
        Drawable badge = getManagedProfileIconForDensity(user,
                com.android.internal.R.drawable.ic_corp_badge_no_background, density);
        Drawable badge = getProfileIconForDensity(user,
                getUserManager().getUserBadgeNoBackgroundResId(user.getIdentifier()), density);
        if (badge != null) {
            badge.setTint(getUserBadgeColor(user));
        }
@@ -1535,8 +1529,8 @@ public class ApplicationPackageManager extends PackageManager {
        return mContext.getResources().getDrawableForDensity(drawableId, density);
    }

    private Drawable getManagedProfileIconForDensity(UserHandle user, int drawableId, int density) {
        if (isManagedProfile(user.getIdentifier())) {
    private Drawable getProfileIconForDensity(UserHandle user, int drawableId, int density) {
        if (hasUserBadge(user.getIdentifier())) {
            return getDrawableForDensity(drawableId, density);
        }
        return null;
@@ -1544,12 +1538,7 @@ public class ApplicationPackageManager extends PackageManager {

    @Override
    public CharSequence getUserBadgedLabel(CharSequence label, UserHandle user) {
        if (isManagedProfile(user.getIdentifier())) {
            int badge = getUserManager().getManagedProfileBadge(user.getIdentifier());
            int resourceId = CORP_BADGE_LABEL_RES_ID[badge % CORP_BADGE_LABEL_RES_ID.length];
            return Resources.getSystem().getString(resourceId, label);
        }
        return label;
        return getUserManager().getBadgedLabelForUser(label, user);
    }

    @Override
@@ -2865,8 +2854,8 @@ public class ApplicationPackageManager extends PackageManager {
        return drawable;
    }

    private boolean isManagedProfile(int userId) {
        return getUserManager().isManagedProfile(userId);
    private boolean hasUserBadge(int userId) {
        return getUserManager().hasBadge(userId);
    }

    /**
+95 −29
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package android.content.pm;

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.UnsupportedAppUsage;
import android.annotation.UserIdInt;
import android.os.Parcel;
@@ -25,6 +26,8 @@ import android.os.UserHandle;
import android.os.UserManager;
import android.util.DebugUtils;

import com.android.server.pm.UserTypeDetails;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@@ -32,13 +35,13 @@ import java.lang.annotation.RetentionPolicy;
 * Per-user information.
 *
 * <p>There are 3 base properties of users: {@link #FLAG_SYSTEM}, {@link #FLAG_FULL}, and
 * {@link #FLAG_MANAGED_PROFILE}. Every user must have one of the following combination of these
 * {@link #FLAG_PROFILE}. Every user must have one of the following combination of these
 * flags:
 * <ul>
 *    <li>FLAG_SYSTEM (user {@link UserHandle#USER_SYSTEM} on a headless-user-0 device)</li>
 *    <li>FLAG_SYSTEM and FLAG_FULL (user {@link UserHandle#USER_SYSTEM} on a regular device)</li>
 *    <li>FLAG_FULL (non-profile secondary user)</li>
 *    <li>FLAG_MANAGED_PROFILE (profile users)</li>
 *    <li>FLAG_PROFILE (profile users)</li>
 * </ul>
 * Users can have also have additional flags (such as FLAG_GUEST) as appropriate.
 *
@@ -70,13 +73,17 @@ public class UserInfo implements Parcelable {

    /**
     * Indicates a guest user that may be transient.
     * @deprecated Use {@link UserManager#USER_TYPE_FULL_GUEST} instead.
     */
    @Deprecated
    public static final int FLAG_GUEST   = 0x00000004;

    /**
     * Indicates the user has restrictions in privileges, in addition to those for normal users.
     * Exact meaning TBD. For instance, maybe they can't install apps or administer WiFi access pts.
     * @deprecated Use {@link UserManager#USER_TYPE_FULL_RESTRICTED} instead.
     */
    @Deprecated
    public static final int FLAG_RESTRICTED = 0x00000008;

    /**
@@ -87,7 +94,9 @@ public class UserInfo implements Parcelable {
    /**
     * Indicates that this user is a profile of another user, for example holding a users
     * corporate data.
     * @deprecated Use {@link UserManager#USER_TYPE_PROFILE_MANAGED} instead.
     */
    @Deprecated
    public static final int FLAG_MANAGED_PROFILE = 0x00000020;

    /**
@@ -108,14 +117,16 @@ public class UserInfo implements Parcelable {

    /**
     * User is for demo purposes only and can be removed at any time.
     * @deprecated Use {@link UserManager#USER_TYPE_FULL_DEMO} instead.
     */
    @Deprecated
    public static final int FLAG_DEMO = 0x00000200;

    /**
     * Indicates that this user is a non-profile human user.
     *
     * <p>When creating a new (non-system) user, this flag will always be forced true unless the
     * user is a {@link #FLAG_MANAGED_PROFILE}. If user {@link UserHandle#USER_SYSTEM} is also a
     * user is a {@link #FLAG_PROFILE}. If user {@link UserHandle#USER_SYSTEM} is also a
     * human user, it must also be flagged as FULL.
     */
    public static final int FLAG_FULL = 0x00000400;
@@ -126,11 +137,10 @@ public class UserInfo implements Parcelable {
    public static final int FLAG_SYSTEM = 0x00000800;

    /**
     * Indicates that this user is some sort of profile. Right now, the only profile type is
     * {@link #FLAG_MANAGED_PROFILE}, but this can include other types of profiles too if any
     * are created in the future. This is therefore not a flag, but an OR of several flags.
     * Indicates that this user is a profile human user, such as a managed profile.
     * Mutually exclusive with {@link #FLAG_FULL}.
     */
    public static final int PROFILE_FLAGS_MASK = FLAG_MANAGED_PROFILE;
    public static final int FLAG_PROFILE = 0x00001000;

    /**
     * @hide
@@ -147,7 +157,8 @@ public class UserInfo implements Parcelable {
            FLAG_EPHEMERAL,
            FLAG_DEMO,
            FLAG_FULL,
            FLAG_SYSTEM
            FLAG_SYSTEM,
            FLAG_PROFILE
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface UserInfoFlag {
@@ -170,6 +181,13 @@ public class UserInfo implements Parcelable {
    @UnsupportedAppUsage
    public long lastLoggedInTime;
    public String lastLoggedInFingerprint;

    /**
     * Type of user, such as {@link UserManager#USER_TYPE_PROFILE_MANAGED}, corresponding to
     * {@link UserTypeDetails#getName()}.
     */
    public String userType;

    /**
     * If this user is a parent user, it would be its own user id.
     * If this user is a child user, it would be its parent user id.
@@ -178,7 +196,12 @@ public class UserInfo implements Parcelable {
    @UnsupportedAppUsage
    public int profileGroupId;
    public int restrictedProfileParentId;
    /** Which profile badge color/label to use. */

    /**
     * Which badge color/label to use within a particular {@link UserTypeDetails}, i.e.
     * the badgeIndex.
     * This is an index for distinguishing different profiles with the same parent and user type.
     */
    public int profileBadge;

    /** User is only partially created. */
@@ -199,21 +222,68 @@ public class UserInfo implements Parcelable {
     */
    public boolean preCreated;

    /**
     * Creates a UserInfo whose user type is determined automatically by the flags according to
     * {@link #getDefaultUserType}; can only be used for user types handled there.
     */
    @UnsupportedAppUsage
    public UserInfo(int id, String name, int flags) {
        this(id, name, null, flags);
    }

    /**
     * Creates a UserInfo whose user type is determined automatically by the flags according to
     * {@link #getDefaultUserType}; can only be used for user types handled there.
     */
    @UnsupportedAppUsage
    public UserInfo(int id, String name, String iconPath, int flags) {
        this(id, name, iconPath, flags, getDefaultUserType(flags));
    }

    public UserInfo(int id, String name, String iconPath, int flags, String userType) {
        this.id = id;
        this.name = name;
        this.flags = flags;
        this.userType = userType;
        this.iconPath = iconPath;
        this.profileGroupId = NO_PROFILE_GROUP_ID;
        this.restrictedProfileParentId = NO_PROFILE_GROUP_ID;
    }

    /**
     * Get the user type (such as {@link UserManager#USER_TYPE_PROFILE_MANAGED}) that corresponds to
     * the given {@link UserInfoFlag}s.

     * <p>The userInfoFlag can contain GUEST, RESTRICTED, MANAGED_PROFILE, DEMO, or else be
     * interpreted as a regular "secondary" user. It cannot contain more than one of these.
     * It can contain other UserInfoFlag properties (like EPHEMERAL), which will be ignored here.
     *
     * @throws IllegalArgumentException if userInfoFlag is more than one type of user or if it
     *                                  is a SYSTEM user.
     *
     * @hide
     */
    public static @NonNull String getDefaultUserType(@UserInfoFlag int userInfoFlag) {
        if ((userInfoFlag & FLAG_SYSTEM) != 0) {
            throw new IllegalArgumentException("Cannot getDefaultUserType for flags "
                    + Integer.toHexString(userInfoFlag) + " because it corresponds to a "
                    + "SYSTEM user type.");
        }
        final int supportedFlagTypes =
                FLAG_GUEST | FLAG_RESTRICTED | FLAG_MANAGED_PROFILE | FLAG_DEMO;
        switch (userInfoFlag & supportedFlagTypes) {
            case 0 :                   return UserManager.USER_TYPE_FULL_SECONDARY;
            case FLAG_GUEST:           return UserManager.USER_TYPE_FULL_GUEST;
            case FLAG_RESTRICTED:      return UserManager.USER_TYPE_FULL_RESTRICTED;
            case FLAG_MANAGED_PROFILE: return UserManager.USER_TYPE_PROFILE_MANAGED;
            case FLAG_DEMO:            return UserManager.USER_TYPE_FULL_DEMO;
            default:
                throw new IllegalArgumentException("Cannot getDefaultUserType for flags "
                        + Integer.toHexString(userInfoFlag) + " because it doesn't correspond to a "
                        + "valid user type.");
        }
    }

    @UnsupportedAppUsage
    public boolean isPrimary() {
        return (flags & FLAG_PRIMARY) == FLAG_PRIMARY;
@@ -226,31 +296,21 @@ public class UserInfo implements Parcelable {

    @UnsupportedAppUsage
    public boolean isGuest() {
        return isGuest(flags);
    }

    /**
     * Checks if the flag denotes a guest user.
     */
    public static boolean isGuest(@UserInfoFlag int flags) {
        return (flags & FLAG_GUEST) == FLAG_GUEST;
        return UserManager.isUserTypeGuest(userType);
    }

    @UnsupportedAppUsage
    public boolean isRestricted() {
        return (flags & FLAG_RESTRICTED) == FLAG_RESTRICTED;
        return UserManager.isUserTypeRestricted(userType);
    }

    @UnsupportedAppUsage
    public boolean isManagedProfile() {
        return isManagedProfile(flags);
    public boolean isProfile() {
        return (flags & FLAG_PROFILE) != 0;
    }

    /**
     * Checks if the flag denotes a managed profile.
     */
    public static boolean isManagedProfile(@UserInfoFlag int flags) {
        return (flags & FLAG_MANAGED_PROFILE) == FLAG_MANAGED_PROFILE;
    @UnsupportedAppUsage
    public boolean isManagedProfile() {
        return UserManager.isUserTypeManagedProfile(userType);
    }

    @UnsupportedAppUsage
@@ -271,7 +331,7 @@ public class UserInfo implements Parcelable {
    }

    public boolean isDemo() {
        return (flags & FLAG_DEMO) == FLAG_DEMO;
        return UserManager.isUserTypeDemo(userType);
    }

    public boolean isFull() {
@@ -304,7 +364,7 @@ public class UserInfo implements Parcelable {
            // Don't support switching to an ephemeral user with removal in progress.
            return false;
        }
        return !isManagedProfile();
        return !isProfile();
    }

    /**
@@ -316,9 +376,10 @@ public class UserInfo implements Parcelable {
        return (!hideSystemUser || id != UserHandle.USER_SYSTEM) && supportsSwitchTo();
    }

    // TODO(b/142482943): Make this logic more specific and customizable. (canHaveProfile(userType))
    /* @hide */
    public boolean canHaveProfile() {
        if (isManagedProfile() || isGuest() || isRestricted()) {
        if (isProfile() || isGuest() || isRestricted()) {
            return false;
        }
        if (UserManager.isSplitSystemUser() || UserManager.isHeadlessSystemUserMode()) {
@@ -336,6 +397,7 @@ public class UserInfo implements Parcelable {
        iconPath = orig.iconPath;
        id = orig.id;
        flags = orig.flags;
        userType = orig.userType;
        serialNumber = orig.serialNumber;
        creationTime = orig.creationTime;
        lastLoggedInTime = orig.lastLoggedInTime;
@@ -353,6 +415,7 @@ public class UserInfo implements Parcelable {
        return UserHandle.of(id);
    }

    // TODO(b/142482943): Probably include mUserType here, which means updating TestDevice, etc.
    @Override
    public String toString() {
        // NOTE:  do not change this string, it's used by 'pm list users', which in turn is
@@ -365,6 +428,7 @@ public class UserInfo implements Parcelable {
    public String toFullString() {
        return "UserInfo[id=" + id
                + ", name=" + name
                + ", type=" + userType
                + ", flags=" + flagsToString(flags)
                + (preCreated ? " (pre-created)" : "")
                + (partial ? " (partial)" : "")
@@ -387,6 +451,7 @@ public class UserInfo implements Parcelable {
        dest.writeString(name);
        dest.writeString(iconPath);
        dest.writeInt(flags);
        dest.writeString(userType);
        dest.writeInt(serialNumber);
        dest.writeLong(creationTime);
        dest.writeLong(lastLoggedInTime);
@@ -415,6 +480,7 @@ public class UserInfo implements Parcelable {
        name = source.readString();
        iconPath = source.readString();
        flags = source.readInt();
        userType = source.readString();
        serialNumber = source.readInt();
        creationTime = source.readLong();
        lastLoggedInTime = source.readLong();
+46 −39
Original line number Diff line number Diff line
@@ -35,77 +35,84 @@ interface IUserManager {
    /*
     * DO NOT MOVE - UserManager.h depends on the ordering of this function.
     */
    int getCredentialOwnerProfile(int userHandle);
    int getProfileParentId(int userHandle);
    int getCredentialOwnerProfile(int userId);
    int getProfileParentId(int userId);
    /*
     * END OF DO NOT MOVE
     */

    UserInfo createUser(in String name, int flags);
    UserInfo preCreateUser(int flags);
    UserInfo createProfileForUser(in String name, int flags, int userHandle,
    UserInfo createUser(in String name, in String userType, int flags);
    UserInfo preCreateUser(in String userType);
    UserInfo createProfileForUser(in String name, in String userType, int flags, int userId,
            in String[] disallowedPackages);
    UserInfo createRestrictedProfile(String name, int parentUserHandle);
    void setUserEnabled(int userHandle);
    void setUserEnabled(int userId);
    void setUserAdmin(int userId);
    void evictCredentialEncryptionKey(int userHandle);
    boolean removeUser(int userHandle);
    boolean removeUserEvenWhenDisallowed(int userHandle);
    void setUserName(int userHandle, String name);
    void setUserIcon(int userHandle, in Bitmap icon);
    ParcelFileDescriptor getUserIcon(int userHandle);
    void evictCredentialEncryptionKey(int userId);
    boolean removeUser(int userId);
    boolean removeUserEvenWhenDisallowed(int userId);
    void setUserName(int userId, String name);
    void setUserIcon(int userId, in Bitmap icon);
    ParcelFileDescriptor getUserIcon(int userId);
    UserInfo getPrimaryUser();
    List<UserInfo> getUsers(boolean excludePartial, boolean excludeDying, boolean excludePreCreated);
    List<UserInfo> getProfiles(int userHandle, boolean enabledOnly);
    List<UserInfo> getProfiles(int userId, boolean enabledOnly);
    int[] getProfileIds(int userId, boolean enabledOnly);
    boolean canAddMoreManagedProfiles(int userHandle, boolean allowedToRemoveOne);
    UserInfo getProfileParent(int userHandle);
    boolean isSameProfileGroup(int userHandle, int otherUserHandle);
    boolean canAddMoreProfilesToUser(in String userType, int userId, boolean allowedToRemoveOne);
    boolean canAddMoreManagedProfiles(int userId, boolean allowedToRemoveOne);
    UserInfo getProfileParent(int userId);
    boolean isSameProfileGroup(int userId, int otherUserHandle);
    String getUserTypeForUser(int userId);
    @UnsupportedAppUsage
    UserInfo getUserInfo(int userHandle);
    String getUserAccount(int userHandle);
    void setUserAccount(int userHandle, String accountName);
    long getUserCreationTime(int userHandle);
    UserInfo getUserInfo(int userId);
    String getUserAccount(int userId);
    void setUserAccount(int userId, String accountName);
    long getUserCreationTime(int userId);
    boolean isRestricted();
    boolean canHaveRestrictedProfile(int userHandle);
    int getUserSerialNumber(int userHandle);
    boolean canHaveRestrictedProfile(int userId);
    int getUserSerialNumber(int userId);
    int getUserHandle(int userSerialNumber);
    int getUserRestrictionSource(String restrictionKey, int userHandle);
    List<UserManager.EnforcingUser> getUserRestrictionSources(String restrictionKey, int userHandle);
    Bundle getUserRestrictions(int userHandle);
    boolean hasBaseUserRestriction(String restrictionKey, int userHandle);
    boolean hasUserRestriction(in String restrictionKey, int userHandle);
    int getUserRestrictionSource(String restrictionKey, int userId);
    List<UserManager.EnforcingUser> getUserRestrictionSources(String restrictionKey, int userId);
    Bundle getUserRestrictions(int userId);
    boolean hasBaseUserRestriction(String restrictionKey, int userId);
    boolean hasUserRestriction(in String restrictionKey, int userId);
    boolean hasUserRestrictionOnAnyUser(in String restrictionKey);
    boolean isSettingRestrictedForUser(in String setting, int userId, in String value, int callingUid);
    void addUserRestrictionsListener(IUserRestrictionsListener listener);
    void setUserRestriction(String key, boolean value, int userHandle);
    void setApplicationRestrictions(in String packageName, in Bundle restrictions,
            int userHandle);
    void setUserRestriction(String key, boolean value, int userId);
    void setApplicationRestrictions(in String packageName, in Bundle restrictions, int userId);
    Bundle getApplicationRestrictions(in String packageName);
    Bundle getApplicationRestrictionsForUser(in String packageName, int userHandle);
    Bundle getApplicationRestrictionsForUser(in String packageName, int userId);
    void setDefaultGuestRestrictions(in Bundle restrictions);
    Bundle getDefaultGuestRestrictions();
    boolean markGuestForDeletion(int userHandle);
    boolean isQuietModeEnabled(int userHandle);
    void setSeedAccountData(int userHandle, in String accountName,
    boolean markGuestForDeletion(int userId);
    boolean isQuietModeEnabled(int userId);
    void setSeedAccountData(int userId, in String accountName,
            in String accountType, in PersistableBundle accountOptions, boolean persist);
    String getSeedAccountName();
    String getSeedAccountType();
    PersistableBundle getSeedAccountOptions();
    void clearSeedAccountData();
    boolean someUserHasSeedAccount(in String accountName, in String accountType);
    boolean isProfile(int userId);
    boolean isManagedProfile(int userId);
    boolean isDemoUser(int userId);
    boolean isPreCreated(int userId);
    UserInfo createProfileForUserEvenWhenDisallowed(in String name, int flags, int userHandle,
            in String[] disallowedPackages);
    UserInfo createProfileForUserEvenWhenDisallowed(in String name, in String userType, int flags,
            int userId, in String[] disallowedPackages);
    boolean isUserUnlockingOrUnlocked(int userId);
    int getManagedProfileBadge(int userId);
    int getUserIconBadgeResId(int userId);
    int getUserBadgeResId(int userId);
    int getUserBadgeNoBackgroundResId(int userId);
    int getUserBadgeLabelResId(int userId);
    int getUserBadgeColorResId(int userId);
    boolean hasBadge(int userId);
    boolean isUserUnlocked(int userId);
    boolean isUserRunning(int userId);
    boolean isUserNameSet(int userHandle);
    boolean isUserNameSet(int userId);
    boolean hasRestrictedProfiles();
    boolean requestQuietModeEnabled(String callingPackage, boolean enableQuietMode, int userHandle, in IntentSender target);
    boolean requestQuietModeEnabled(String callingPackage, boolean enableQuietMode, int userId, in IntentSender target);
    String getUserName();
    long getUserStartRealtime();
    long getUserUnlockRealtime();
+383 −51

File changed.

Preview size limit exceeded, changes collapsed.

Loading