1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.content.pm;
18
19import android.os.Parcel;
20import android.os.Parcelable;
21import android.os.SystemProperties;
22import android.os.UserHandle;
23import android.os.UserManager;
24
25/**
26 * Per-user information.
27 * @hide
28 */
29public class UserInfo implements Parcelable {
30
31    /** 16 bits for user type */
32    public static final int FLAG_MASK_USER_TYPE = 0x0000FFFF;
33
34    /**
35     * *************************** NOTE ***************************
36     * These flag values CAN NOT CHANGE because they are written
37     * directly to storage.
38     */
39
40    /**
41     * Primary user. Only one user can have this flag set. It identifies the first human user
42     * on a device.
43     */
44    public static final int FLAG_PRIMARY = 0x00000001;
45
46    /**
47     * User with administrative privileges. Such a user can create and
48     * delete users.
49     */
50    public static final int FLAG_ADMIN   = 0x00000002;
51
52    /**
53     * Indicates a guest user that may be transient.
54     */
55    public static final int FLAG_GUEST   = 0x00000004;
56
57    /**
58     * Indicates the user has restrictions in privileges, in addition to those for normal users.
59     * Exact meaning TBD. For instance, maybe they can't install apps or administer WiFi access pts.
60     */
61    public static final int FLAG_RESTRICTED = 0x00000008;
62
63    /**
64     * Indicates that this user has gone through its first-time initialization.
65     */
66    public static final int FLAG_INITIALIZED = 0x00000010;
67
68    /**
69     * Indicates that this user is a profile of another user, for example holding a users
70     * corporate data.
71     */
72    public static final int FLAG_MANAGED_PROFILE = 0x00000020;
73
74    /**
75     * Indicates that this user is disabled.
76     *
77     * <p>Note: If an ephemeral user is disabled, it shouldn't be later re-enabled. Ephemeral users
78     * are disabled as their removal is in progress to indicate that they shouldn't be re-entered.
79     */
80    public static final int FLAG_DISABLED = 0x00000040;
81
82    public static final int FLAG_QUIET_MODE = 0x00000080;
83
84    /**
85     * Indicates that this user is ephemeral. I.e. the user will be removed after leaving
86     * the foreground.
87     */
88    public static final int FLAG_EPHEMERAL = 0x00000100;
89
90    /**
91     * User is for demo purposes only and can be removed at any time.
92     */
93    public static final int FLAG_DEMO = 0x00000200;
94
95    public static final int NO_PROFILE_GROUP_ID = UserHandle.USER_NULL;
96
97    public int id;
98    public int serialNumber;
99    public String name;
100    public String iconPath;
101    public int flags;
102    public long creationTime;
103    public long lastLoggedInTime;
104    public String lastLoggedInFingerprint;
105    /**
106     * If this user is a parent user, it would be its own user id.
107     * If this user is a child user, it would be its parent user id.
108     * Otherwise, it would be {@link #NO_PROFILE_GROUP_ID}.
109     */
110    public int profileGroupId;
111    public int restrictedProfileParentId;
112    /** Which profile badge color/label to use. */
113    public int profileBadge;
114
115    /** User is only partially created. */
116    public boolean partial;
117    public boolean guestToRemove;
118
119    public UserInfo(int id, String name, int flags) {
120        this(id, name, null, flags);
121    }
122
123    public UserInfo(int id, String name, String iconPath, int flags) {
124        this.id = id;
125        this.name = name;
126        this.flags = flags;
127        this.iconPath = iconPath;
128        this.profileGroupId = NO_PROFILE_GROUP_ID;
129        this.restrictedProfileParentId = NO_PROFILE_GROUP_ID;
130    }
131
132    public boolean isPrimary() {
133        return (flags & FLAG_PRIMARY) == FLAG_PRIMARY;
134    }
135
136    public boolean isAdmin() {
137        return (flags & FLAG_ADMIN) == FLAG_ADMIN;
138    }
139
140    public boolean isGuest() {
141        return (flags & FLAG_GUEST) == FLAG_GUEST;
142    }
143
144    public boolean isRestricted() {
145        return (flags & FLAG_RESTRICTED) == FLAG_RESTRICTED;
146    }
147
148    public boolean isManagedProfile() {
149        return (flags & FLAG_MANAGED_PROFILE) == FLAG_MANAGED_PROFILE;
150    }
151
152    public boolean isEnabled() {
153        return (flags & FLAG_DISABLED) != FLAG_DISABLED;
154    }
155
156    public boolean isQuietModeEnabled() {
157        return (flags & FLAG_QUIET_MODE) == FLAG_QUIET_MODE;
158    }
159
160    public boolean isEphemeral() {
161        return (flags & FLAG_EPHEMERAL) == FLAG_EPHEMERAL;
162    }
163
164    public boolean isInitialized() {
165        return (flags & FLAG_INITIALIZED) == FLAG_INITIALIZED;
166    }
167
168    public boolean isDemo() {
169        return (flags & FLAG_DEMO) == FLAG_DEMO;
170    }
171
172    /**
173     * Returns true if the user is a split system user.
174     * <p>If {@link UserManager#isSplitSystemUser split system user mode} is not enabled,
175     * the method always returns false.
176     */
177    public boolean isSystemOnly() {
178        return isSystemOnly(id);
179    }
180
181    /**
182     * Returns true if the given user is a split system user.
183     * <p>If {@link UserManager#isSplitSystemUser split system user mode} is not enabled,
184     * the method always returns false.
185     */
186    public static boolean isSystemOnly(int userId) {
187        return userId == UserHandle.USER_SYSTEM && UserManager.isSplitSystemUser();
188    }
189
190    /**
191     * @return true if this user can be switched to.
192     **/
193    public boolean supportsSwitchTo() {
194        if (isEphemeral() && !isEnabled()) {
195            // Don't support switching to an ephemeral user with removal in progress.
196            return false;
197        }
198        return !isManagedProfile();
199    }
200
201    /**
202     * @return true if this user can be switched to by end user through UI.
203     */
204    public boolean supportsSwitchToByUser() {
205        // Hide the system user when it does not represent a human user.
206        boolean hideSystemUser = UserManager.isSplitSystemUser();
207        return (!hideSystemUser || id != UserHandle.USER_SYSTEM) && supportsSwitchTo();
208    }
209
210    /* @hide */
211    public boolean canHaveProfile() {
212        if (isManagedProfile() || isGuest() || isRestricted()) {
213            return false;
214        }
215        if (UserManager.isSplitSystemUser()) {
216            return id != UserHandle.USER_SYSTEM;
217        } else {
218            return id == UserHandle.USER_SYSTEM;
219        }
220    }
221
222    public UserInfo() {
223    }
224
225    public UserInfo(UserInfo orig) {
226        name = orig.name;
227        iconPath = orig.iconPath;
228        id = orig.id;
229        flags = orig.flags;
230        serialNumber = orig.serialNumber;
231        creationTime = orig.creationTime;
232        lastLoggedInTime = orig.lastLoggedInTime;
233        lastLoggedInFingerprint = orig.lastLoggedInFingerprint;
234        partial = orig.partial;
235        profileGroupId = orig.profileGroupId;
236        restrictedProfileParentId = orig.restrictedProfileParentId;
237        guestToRemove = orig.guestToRemove;
238        profileBadge = orig.profileBadge;
239    }
240
241    public UserHandle getUserHandle() {
242        return new UserHandle(id);
243    }
244
245    @Override
246    public String toString() {
247        return "UserInfo{" + id + ":" + name + ":" + Integer.toHexString(flags) + "}";
248    }
249
250    public int describeContents() {
251        return 0;
252    }
253
254    public void writeToParcel(Parcel dest, int parcelableFlags) {
255        dest.writeInt(id);
256        dest.writeString(name);
257        dest.writeString(iconPath);
258        dest.writeInt(flags);
259        dest.writeInt(serialNumber);
260        dest.writeLong(creationTime);
261        dest.writeLong(lastLoggedInTime);
262        dest.writeString(lastLoggedInFingerprint);
263        dest.writeInt(partial ? 1 : 0);
264        dest.writeInt(profileGroupId);
265        dest.writeInt(guestToRemove ? 1 : 0);
266        dest.writeInt(restrictedProfileParentId);
267        dest.writeInt(profileBadge);
268    }
269
270    public static final Parcelable.Creator<UserInfo> CREATOR
271            = new Parcelable.Creator<UserInfo>() {
272        public UserInfo createFromParcel(Parcel source) {
273            return new UserInfo(source);
274        }
275        public UserInfo[] newArray(int size) {
276            return new UserInfo[size];
277        }
278    };
279
280    private UserInfo(Parcel source) {
281        id = source.readInt();
282        name = source.readString();
283        iconPath = source.readString();
284        flags = source.readInt();
285        serialNumber = source.readInt();
286        creationTime = source.readLong();
287        lastLoggedInTime = source.readLong();
288        lastLoggedInFingerprint = source.readString();
289        partial = source.readInt() != 0;
290        profileGroupId = source.readInt();
291        guestToRemove = source.readInt() != 0;
292        restrictedProfileParentId = source.readInt();
293        profileBadge = source.readInt();
294    }
295}
296