安卓多用户管理之Userinfo

目录

  • 前言
  • Userinfo----用户信息
    • [1.1 属性](#1.1 属性)
    • [1.2 构造器](#1.2 构造器)
    • [1.3 信息的判断及获取方法](#1.3 信息的判断及获取方法)
        • [1.3.1 获取默认用户类型](#1.3.1 获取默认用户类型)
        • [1.3.2 基础信息判断](#1.3.2 基础信息判断)
    • [1.4 序列化部分](#1.4 序列化部分)
  • 总结

前言

UserManagerService内部类UserData中有一个Userinfo类型的info参数,在UserData中并未有所体现,但在后续的UserManagerService里会有对info参数的各种操作,需要看下Userinfo类的基本属性和方法


Userinfo----用户信息

源码有500行左右,复制在一块略显臃肿,对其分类解读。

源码结构大致如下:

java 复制代码
public class UserInfo implements Parcelable {
...............
属性
...............
构造器
................
信息的判断及获取方法
................
序列化部分的方法
.................
}

1.1 属性

java 复制代码
    /**
     * Primary user. Only one user can have this flag set. It identifies the first human user
     * on a device. This flag is not supported in headless system user mode.
     * 主要用户。只有一个用户可以设置此标志。它识别第一个人类用户
     * 在设备上。无头系统用户模式不支持此标志。
     */
    @UnsupportedAppUsage
    public static final int FLAG_PRIMARY = 0x00000001;

    /**
     * User with administrative privileges. Such a user can create and
     * delete users.
     * 具有管理权限的用户。这样的用户可以创建
     * 删除用户。
     */
    public static final int FLAG_ADMIN   = 0x00000002;

    /**
     * Indicates a guest user that may be transient.
     * @deprecated Use {@link UserManager#USER_TYPE_FULL_GUEST} instead.
     * 表示可能是临时的访客用户。
     * @不推荐使用{@link UserManager#USER_TYPE_FULL_GUEST}。
     */
    @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.
     * 表示除普通用户的权限外,用户还具有权限限制。
     * 确切含义待定。例如,他们可能无法安装应用程序或管理WiFi接入点。
     * @不推荐使用{@link UserManager#USER_TYPE_FULL_RESTRICTED}。
     */
    @Deprecated
    public static final int FLAG_RESTRICTED = 0x00000008;

    /**
     * Indicates that this user has gone through its first-time initialization.
     * 指示此用户已完成首次初始化。
     */
    public static final int FLAG_INITIALIZED = 0x00000010;

    /**
     * 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.
 	 * 指示此用户是另一个用户的配置文件,例如持有用户的公司数据。
	 * @不推荐使用{@link UserManager#USER_TYPE_PROFILE_MANAGED}。
     */
    @Deprecated
    public static final int FLAG_MANAGED_PROFILE = 0x00000020;

    /**
     * Indicates that this user is disabled.
     *
     * <p>Note: If an ephemeral user is disabled, it shouldn't be later re-enabled. Ephemeral users
     * are disabled as their removal is in progress to indicate that they shouldn't be re-entered.
	 *指示此用户已被禁用。
	 *<p>注意:如果临时用户被禁用,以后就不应该重新启用它。短暂用户在删除过程中被禁用,表示不应重新输入。
     */
    public static final int FLAG_DISABLED = 0x00000040;

    public static final int FLAG_QUIET_MODE = 0x00000080;

    /**
     * Indicates that this user is ephemeral. I.e. the user will be removed after leaving
     * the foreground.
     * 
	 *指示此用户是临时用户。即用户离开前台后将被删除。
     */
    public static final int FLAG_EPHEMERAL = 0x00000100;

    /**
     * User is for demo purposes only and can be removed at any time.
     * @deprecated Use {@link UserManager#USER_TYPE_FULL_DEMO} instead.
     * 
	 *用户仅用于演示目的,可以随时删除。
     *@不推荐使用{@link UserManager#USER_TYPE_FULL_DEMO}。
     */
    @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_PROFILE}. If user {@link UserHandle#USER_SYSTEM} is also a
     * human user, it must also be flagged as FULL.
     * /**
	 *指示此用户是非配置文件的人类用户。
	 *<p>当创建新的(非系统)用户时,除非该用户标志了flag_PROFILE,否则此标志将始终强制为true。
	 *如果用户标志了UserHandle#user_SYSTEM也是人类用户,则还必须将其标记为FULL。 
     */
    public static final int FLAG_FULL = 0x00000400;

    /**
     * Indicates that this user is {@link UserHandle#USER_SYSTEM}. Not applicable to created users.
     * 
	 *表示此用户是{@link UserHandle#user_SYSTEM}。不适用于创建的用户。
     */
    public static final int FLAG_SYSTEM = 0x00000800;

    /**
     * Indicates that this user is a profile human user, such as a managed profile.
     * Mutually exclusive with {@link #FLAG_FULL}.
     *
	 *指示此用户是配置文件的人工用户,例如托管配置文件。
	 *与{@link#FLAG_FULL}互斥。
     */
    public static final int FLAG_PROFILE = 0x00001000;

    /**
     * @hide
     */
    @IntDef(flag = true, prefix = "FLAG_", value = {
            FLAG_PRIMARY,
            FLAG_ADMIN,
            FLAG_GUEST,
            FLAG_RESTRICTED,
            FLAG_INITIALIZED,
            FLAG_MANAGED_PROFILE,
            FLAG_DISABLED,
            FLAG_QUIET_MODE,
            FLAG_EPHEMERAL,
            FLAG_DEMO,
            FLAG_FULL,
            FLAG_SYSTEM,
            FLAG_PROFILE
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface UserInfoFlag {
    }

    /**
    *将"NO_PROFILE_GROUP_ID"设置为一个表示无效用户ID的常量。
    */
    public static final int NO_PROFILE_GROUP_ID = UserHandle.USER_NULL;

    @UnsupportedAppUsage
    public @UserIdInt int id;
    @UnsupportedAppUsage
    public int serialNumber;
    @UnsupportedAppUsage
    public String name;
    @UnsupportedAppUsage
    public String iconPath;
    @UnsupportedAppUsage
    public @UserInfoFlag int flags;
    @UnsupportedAppUsage
    public long creationTime;
    @UnsupportedAppUsage
    public long lastLoggedInTime;
    public String lastLoggedInFingerprint;

    /**
     * Type of user, such as {@link UserManager#USER_TYPE_PROFILE_MANAGED}, corresponding to
     * {@link com.android.server.pm.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.
     * Otherwise, it would be {@link #NO_PROFILE_GROUP_ID}.
     */
    @UnsupportedAppUsage
    public int profileGroupId;
    public int restrictedProfileParentId;

    /**
     * Index for distinguishing different profiles with the same parent and user type for the
     * purpose of badging.
     * It is used for determining which badge color/label to use (if applicable) from
     * the options available for a particular user type.
	 * 用于区分具有相同父级和用户类型的不同配置文件以进行标记的索引。
	 * 它用于从特定用户类型的可用选项中确定使用哪种徽章颜色/标签(如果适用)。
     */
    public int profileBadge;

    /** User is only partially created. */
    @UnsupportedAppUsage
    public boolean partial;

	/**
	*代一个待移除的访客用户或者访客配置文件。这个变量的作用可能是用于跟踪需要移除的访客用户或者配置文件的信息,
	*以便在系统操作中进行相应的处理。
	*/
    @UnsupportedAppUsage
    public boolean guestToRemove;

    /**
     * This is used to optimize the creation of an user, i.e. OEMs might choose to pre-create a
     * number of users at the first boot, so the actual creation later is faster.
     *
     * <p>A {@code preCreated} user is not a real user yet, so it should not show up on regular
     * user operations (other than user creation per se).
     *
     * <p>Once the pre-created is used to create a "real" user later on, {@code preCreate} is set to
     * {@code false}.
 	 *这用于优化用户的创建,即原始设备制造商可能会选择在第一次启动时预先创建多个用户,因此以后的实际创建速度更快。
 	 *<p>{@code preCreated}用户还不是真正的用户,因此它不应该出现在常规用户操作中(而不是用户创建本身)。
	 *<p>一旦预先创建的用于稍后创建"真正"用户,{@code preCreate}将设置为{@code false}。
     */
    public boolean preCreated;

    /**
     * When {@code true}, it indicates this user was created by converting a {@link #preCreated}
     * user.
     *
     * <p><b>NOTE: </b>only used for debugging purposes, it's not set when marshalled to a parcel.
	 *当{@code true}时,表示该用户是通过转换{@link#preCreated}创建的用户。
	 *<p><b>注意:</b>仅用于调试目的,当它被整理到一个包裹时没有设置。
     */
    public boolean convertedFromPreCreated;
属性 类型 含义
FLAG_PRIMARY int 主要用户标志
FLAG_ADMIN int 具有管理权限的用户标志
FLAG_GUEST int 临时的访客用户标志
FLAG_RESTRICTED int 受限制的标志
FLAG_INITIALIZED int 完成首次初始化标志
FLAG_MANAGED_PROFILE int 被管理用户标志
FLAG_DISABLED int 被禁用标志
FLAG_QUIET_MODE int 安静模式标志
FLAG_EPHEMERAL int 临时用户标志
FLAG_DEMO int demo标志,可以随时删除
FLAG_FULL int 非配置文件的人类用户标志
FLAG_SYSTEM int 系统用户标志
FLAG_PROFILE int 配置文件的人类用户标志
NO_PROFILE_GROUP_ID int 字面翻译没有配置文件组ID,值为无效用户ID的常量
id int 用户id
serialNumber int 序列号
name String 名字
iconPath String 图标路径
flags int 标志
creationTime long 创造时间
lastLoggedInTime long 上次登录时间
lastLoggedInFingerprint String 上次登录的指纹
userType String 用户类型
profileGroupId int 配置文件组ID
restrictedProfileParentId int 受限制配置文件的父级ID
profileBadge int 配置文件徽章
partial boolean 偏好
guestToRemove boolean 待移除的访客
preCreated boolean 提前创建
convertedFromPreCreated boolean 通过提前创建转变的

1.2 构造器

四个构造器如下:

java 复制代码
      /**
     * 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.
     * 创建UserInfo,其用户类型由根据{@link#getDefaultUserType}的标志自动确定;只能用于在那里处理的用户类型
     */
    @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.
     * 创建UserInfo,其用户类型由根据{@link#getDefaultUserType}的标志自动确定;只能用于在那里处理的用户类型
     */
    @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;
    }
   public UserInfo(UserInfo orig) {
        name = orig.name;
        iconPath = orig.iconPath;
        id = orig.id;
        flags = orig.flags;
        userType = orig.userType;
        serialNumber = orig.serialNumber;
        creationTime = orig.creationTime;
        lastLoggedInTime = orig.lastLoggedInTime;
        lastLoggedInFingerprint = orig.lastLoggedInFingerprint;
        partial = orig.partial;
        preCreated = orig.preCreated;
        convertedFromPreCreated = orig.convertedFromPreCreated;
        profileGroupId = orig.profileGroupId;
        restrictedProfileParentId = orig.restrictedProfileParentId;
        guestToRemove = orig.guestToRemove;
        profileBadge = orig.profileBadge;
    }

1.3 信息的判断及获取方法

1.3.1 获取默认用户类型
java 复制代码
    /**
     * 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.
     *
	 *获取对应于的用户类型(例如{@link UserManager#user_type_PROFILE_MANAGED})
	 *给定的{@link UserInfoFlag}s。
	 *<p>userInfoFlag可以包含GUEST、RESTRICTED、MANAGED_PROFILE、DEMO,或者被解释为常规的"次要"用户。其中不能包含多个。
	 *它可以包含其他UserInfoFlag属性(如EPHEMERAL),此处将忽略这些属性。
	 *如果userInfoFlag是多种类型的用户,或者如果是SYSTEM用户。
     * @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.");
        }
    }

首先将userInfoFlagFLAG_SYSTEM进行位与操作,如果结果不等于0就会抛出异常表示当前用户类型相当于系统用户。
FLAG_SYSTEM即0x00000800 是一个十六进制数,转换成二进制为 0000 0000 0000 0000 0000 1000 0000 0000。在这里,只有自己&自己情况下才会抛出异常。

然后定义了一个supportedFlagTypes变量,它包含了一系列支持的用户类型标志位,包含了FLAG_GUESTFLAG_RESTRICTEDFLAG_MANAGED_PROFILEFLAG_DEMO

如果是0,表示userInfoFlag不包含任何支持的用户类型标志位,因此返回UserManager.USER_TYPE_FULL_SECONDARY

如果按位与的结果匹配到了FLAG_GUESTFLAG_RESTRICTEDFLAG_MANAGED_PROFILE或者FLAG_DEMO,那么分别返回对应的用户类型。

最后,如果userInfoFlag不匹配任何已知的用户类型标志位,那么抛出一个IllegalArgumentException异常,说明userInfoFlag不对应任何有效的用户类型。

1.3.2 基础信息判断

该部分些许无聊,flags 位与标志再判断是否相等就不作更多说明。通过UserManagerAPI再判断相关状态暂不做更多说明...后续看情况再写一篇UserManager的文章,这部分真的太碎了...

java 复制代码
    @UnsupportedAppUsage
    public boolean isPrimary() {
        return (flags & FLAG_PRIMARY) == FLAG_PRIMARY;
    }

    @UnsupportedAppUsage
    public boolean isAdmin() {
        return (flags & FLAG_ADMIN) == FLAG_ADMIN;
    }

    @UnsupportedAppUsage
    public boolean isGuest() {
        return UserManager.isUserTypeGuest(userType);
    }

    @UnsupportedAppUsage
    public boolean isRestricted() {
        return UserManager.isUserTypeRestricted(userType);
    }

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

    @UnsupportedAppUsage
    public boolean isManagedProfile() {
        return UserManager.isUserTypeManagedProfile(userType);
    }

    @UnsupportedAppUsage
    public boolean isEnabled() {
        return (flags & FLAG_DISABLED) != FLAG_DISABLED;
    }

    public boolean isQuietModeEnabled() {
        return (flags & FLAG_QUIET_MODE) == FLAG_QUIET_MODE;
    }

    public boolean isEphemeral() {
        return (flags & FLAG_EPHEMERAL) == FLAG_EPHEMERAL;
    }

    public boolean isInitialized() {
        return (flags & FLAG_INITIALIZED) == FLAG_INITIALIZED;
    }

    public boolean isDemo() {
        return UserManager.isUserTypeDemo(userType);
    }

    public boolean isFull() {
        return (flags & FLAG_FULL) == FLAG_FULL;
    }

    /**
     * Returns true if the user is a split system user.
     * <p>If {@link UserManager#isSplitSystemUser split system user mode} is not enabled,
     * the method always returns false.
     *
	 *如果用户是拆分系统用户,则返回true。
	 *<p>如果没有启用{@link UserManager#isSplitSystemUser拆分系统用户模式},
	 *该方法总是返回false。
     */
    public boolean isSystemOnly() {
        return isSystemOnly(id);
    }

    /**
     * Returns true if the given user is a split system user.
     * <p>If {@link UserManager#isSplitSystemUser split system user mode} is not enabled,
     * the method always returns false.
     *如果给定用户是拆分系统用户,则返回true。
	 *<p>如果没有启用{@link UserManager#isSplitSystemUser拆分系统用户模式},
	 *该方法总是返回false。
     */
    public static boolean isSystemOnly(int userId) {
        return userId == UserHandle.USER_SYSTEM && UserManager.isSplitSystemUser();
    }

    /**
     * @return true if this user can be switched to.
     * @如果此用户可以切换到,则返回true。
     **/
    public boolean supportsSwitchTo() {
        if (isEphemeral() && !isEnabled()) {
            // Don't support switching to an ephemeral user with removal in progress.
            //不支持在删除过程中切换到临时用户。
            return false;
        }
        if (preCreated) {
            // Don't support switching to pre-created users until they become "real" users.
            //在用户成为"真实"用户之前,不支持切换到预先创建的用户。
            return false;
        }
        return !isProfile();
    }

    /**
     * @return true if this user can be switched to by end user through UI.
     * *@return true如果最终用户可以通过UI切换到此用户。
     */
    public boolean supportsSwitchToByUser() {
        // Hide the system user when it does not represent a human user.
        // 当系统用户不代表人类用户时,隐藏系统用户。
        boolean hideSystemUser = UserManager.isHeadlessSystemUserMode();
        return (!hideSystemUser || id != UserHandle.USER_SYSTEM) && supportsSwitchTo();
    }

    // TODO(b/142482943): Make this logic more specific and customizable. (canHaveProfile(userType))
    //都产生todo了,可知该部分还不是完善,暂不做解读
    /* @hide */
    public boolean canHaveProfile() {
        if (isProfile() || isGuest() || isRestricted()) {
            return false;
        }
        if (UserManager.isSplitSystemUser() || UserManager.isHeadlessSystemUserMode()) {
            return id != UserHandle.USER_SYSTEM;
        } else {
            return id == UserHandle.USER_SYSTEM;
        }
    }

1.4 序列化部分

java 复制代码
	//describeContents方法: 这个方法返回一个标志位,用于描述Parcelable对象特殊对象的对象类型。
	//通常情况下,如果对象中存在文件描述符,那么返回1,否则返回0。在这个例子中,返回0表示不包含文件描述符。
    @Override
    public int describeContents() {
        return 0;
    }

	/**
	*writeToParcel方法: 这个方法用于将对象的数据写入Parcel对象中,以便进行传输。在这个例子中,通过调用Parcel对象的
	*不同写入方法,将id、name、iconPath、flags、userType、serialNumber、creationTime、lastLoggedInTime、
    *lastLoggedInFingerprint、partial、preCreated、profileGroupId、guestToRemove、restrictedProfileParentId
    *和profileBadge等变量的值写入Parcel对象中。
	*/
    @Override
    public void writeToParcel(Parcel dest, int parcelableFlags) {
        dest.writeInt(id);
        dest.writeString8(name);
        dest.writeString8(iconPath);
        dest.writeInt(flags);
        dest.writeString8(userType);
        dest.writeInt(serialNumber);
        dest.writeLong(creationTime);
        dest.writeLong(lastLoggedInTime);
        dest.writeString8(lastLoggedInFingerprint);
        dest.writeBoolean(partial);
        dest.writeBoolean(preCreated);
        dest.writeInt(profileGroupId);
        dest.writeBoolean(guestToRemove);
        dest.writeInt(restrictedProfileParentId);
        dest.writeInt(profileBadge);
    }

    @UnsupportedAppUsage
    public static final @android.annotation.NonNull Parcelable.Creator<UserInfo> CREATOR
            = new Parcelable.Creator<UserInfo>() {
        //createFromParcel方法: 这个方法接收一个Parcel对象作为参数,用于从Parcel中反序列化出一个UserInfo对象。
        //在这个例子中,这个方法返回一个新的UserInfo对象,通过读取Parcel对象中的数据来初始化UserInfo对象的各个字段。
        public UserInfo createFromParcel(Parcel source) {
            return new UserInfo(source);
        }
        //newArray方法: 这个方法接收一个整型参数size,用于创建一个指定大小的UserInfo数组。在这个例子中,
        //这个方法返回一个UserInfo类型的数组,其大小由传入的size参数决定。
        public UserInfo[] newArray(int size) {
            return new UserInfo[size];
        }
    };

    //这个构造函数通常用于在反序列化过程中创建UserInfo对象
    private UserInfo(Parcel source) {
        id = source.readInt();
        name = source.readString8();
        iconPath = source.readString8();
        flags = source.readInt();
        userType = source.readString8();
        serialNumber = source.readInt();
        creationTime = source.readLong();
        lastLoggedInTime = source.readLong();
        lastLoggedInFingerprint = source.readString8();
        partial = source.readBoolean();
        preCreated = source.readBoolean();
        profileGroupId = source.readInt();
        guestToRemove = source.readBoolean();
        restrictedProfileParentId = source.readInt();
        profileBadge = source.readInt();
    }

总结

Userinfo主要内容还是看它的属性,方法主要是通过属性标志位的与或操作判断结果,以及常见的序列化传输方法。

相关推荐
Good_tea_h2 小时前
Android中的单例模式
android·单例模式
计算机源码社7 小时前
分享一个基于微信小程序的居家养老服务小程序 养老服务预约安卓app uniapp(源码、调试、LW、开题、PPT)
android·微信小程序·uni-app·毕业设计项目·毕业设计源码·计算机课程设计·计算机毕业设计开题
丶白泽8 小时前
重修设计模式-结构型-门面模式
android
晨春计9 小时前
【git】
android·linux·git
标标大人10 小时前
c语言中的局部跳转以及全局跳转
android·c语言·开发语言
竹林海中敲代码10 小时前
Qt安卓开发连接手机调试(红米K60为例)
android·qt·智能手机
木鬼与槐11 小时前
MySQL高阶1783-大满贯数量
android·数据库·mysql
iofomo11 小时前
【Abyss】Android 平台应用级系统调用拦截框架
android·开发工具·移动端
AirDroid_cn13 小时前
在家找不到手机?除了语音助手,还可以用远程控制!
android·智能手机·远程控制·手机使用技巧·远程控制手机
Good_tea_h21 小时前
Android中如何处理运行时权限?
android