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.os;
18
19import android.annotation.AppIdInt;
20import android.annotation.SystemApi;
21import android.annotation.TestApi;
22import android.annotation.UserIdInt;
23
24import java.io.PrintWriter;
25
26/**
27 * Representation of a user on the device.
28 */
29public final class UserHandle implements Parcelable {
30    /**
31     * @hide Range of uids allocated for a user.
32     */
33    public static final int PER_USER_RANGE = 100000;
34
35    /** @hide A user id to indicate all users on the device */
36    public static final @UserIdInt int USER_ALL = -1;
37
38    /** @hide A user handle to indicate all users on the device */
39    public static final UserHandle ALL = new UserHandle(USER_ALL);
40
41    /** @hide A user id to indicate the currently active user */
42    public static final @UserIdInt int USER_CURRENT = -2;
43
44    /** @hide A user handle to indicate the current user of the device */
45    public static final UserHandle CURRENT = new UserHandle(USER_CURRENT);
46
47    /** @hide A user id to indicate that we would like to send to the current
48     *  user, but if this is calling from a user process then we will send it
49     *  to the caller's user instead of failing with a security exception */
50    public static final @UserIdInt int USER_CURRENT_OR_SELF = -3;
51
52    /** @hide A user handle to indicate that we would like to send to the current
53     *  user, but if this is calling from a user process then we will send it
54     *  to the caller's user instead of failing with a security exception */
55    public static final UserHandle CURRENT_OR_SELF = new UserHandle(USER_CURRENT_OR_SELF);
56
57    /** @hide An undefined user id */
58    public static final @UserIdInt int USER_NULL = -10000;
59
60    /**
61     * @hide A user id constant to indicate the "owner" user of the device
62     * @deprecated Consider using either {@link UserHandle#USER_SYSTEM} constant or
63     * check the target user's flag {@link android.content.pm.UserInfo#isAdmin}.
64     */
65    @Deprecated
66    public static final @UserIdInt int USER_OWNER = 0;
67
68    /**
69     * @hide A user handle to indicate the primary/owner user of the device
70     * @deprecated Consider using either {@link UserHandle#SYSTEM} constant or
71     * check the target user's flag {@link android.content.pm.UserInfo#isAdmin}.
72     */
73    @Deprecated
74    public static final UserHandle OWNER = new UserHandle(USER_OWNER);
75
76    /** @hide A user id constant to indicate the "system" user of the device */
77    public static final @UserIdInt int USER_SYSTEM = 0;
78
79    /** @hide A user serial constant to indicate the "system" user of the device */
80    public static final int USER_SERIAL_SYSTEM = 0;
81
82    /** @hide A user handle to indicate the "system" user of the device */
83    public static final UserHandle SYSTEM = new UserHandle(USER_SYSTEM);
84
85    /**
86     * @hide Enable multi-user related side effects. Set this to false if
87     * there are problems with single user use-cases.
88     */
89    public static final boolean MU_ENABLED = true;
90
91    final int mHandle;
92
93    /**
94     * Checks to see if the user id is the same for the two uids, i.e., they belong to the same
95     * user.
96     * @hide
97     */
98    public static boolean isSameUser(int uid1, int uid2) {
99        return getUserId(uid1) == getUserId(uid2);
100    }
101
102    /**
103     * Checks to see if both uids are referring to the same app id, ignoring the user id part of the
104     * uids.
105     * @param uid1 uid to compare
106     * @param uid2 other uid to compare
107     * @return whether the appId is the same for both uids
108     * @hide
109     */
110    public static boolean isSameApp(int uid1, int uid2) {
111        return getAppId(uid1) == getAppId(uid2);
112    }
113
114    /** @hide */
115    public static boolean isIsolated(int uid) {
116        if (uid > 0) {
117            final int appId = getAppId(uid);
118            return appId >= Process.FIRST_ISOLATED_UID && appId <= Process.LAST_ISOLATED_UID;
119        } else {
120            return false;
121        }
122    }
123
124    /** @hide */
125    public static boolean isApp(int uid) {
126        if (uid > 0) {
127            final int appId = getAppId(uid);
128            return appId >= Process.FIRST_APPLICATION_UID && appId <= Process.LAST_APPLICATION_UID;
129        } else {
130            return false;
131        }
132    }
133
134    /**
135     * Returns the user for a given uid.
136     * @param uid A uid for an application running in a particular user.
137     * @return A {@link UserHandle} for that user.
138     */
139    public static UserHandle getUserHandleForUid(int uid) {
140        return of(getUserId(uid));
141    }
142
143    /**
144     * Returns the user id for a given uid.
145     * @hide
146     */
147    public static @UserIdInt int getUserId(int uid) {
148        if (MU_ENABLED) {
149            return uid / PER_USER_RANGE;
150        } else {
151            return UserHandle.USER_SYSTEM;
152        }
153    }
154
155    /** @hide */
156    public static @UserIdInt int getCallingUserId() {
157        return getUserId(Binder.getCallingUid());
158    }
159
160    /** @hide */
161    @SystemApi
162    public static UserHandle of(@UserIdInt int userId) {
163        return userId == USER_SYSTEM ? SYSTEM : new UserHandle(userId);
164    }
165
166    /**
167     * Returns the uid that is composed from the userId and the appId.
168     * @hide
169     */
170    public static int getUid(@UserIdInt int userId, @AppIdInt int appId) {
171        if (MU_ENABLED) {
172            return userId * PER_USER_RANGE + (appId % PER_USER_RANGE);
173        } else {
174            return appId;
175        }
176    }
177
178    /**
179     * Returns the app id (or base uid) for a given uid, stripping out the user id from it.
180     * @hide
181     */
182    @TestApi
183    public static @AppIdInt int getAppId(int uid) {
184        return uid % PER_USER_RANGE;
185    }
186
187    /**
188     * Returns the gid shared between all apps with this userId.
189     * @hide
190     */
191    public static int getUserGid(@UserIdInt int userId) {
192        return getUid(userId, Process.SHARED_USER_GID);
193    }
194
195    /**
196     * Returns the shared app gid for a given uid or appId.
197     * @hide
198     */
199    public static int getSharedAppGid(int id) {
200        return Process.FIRST_SHARED_APPLICATION_GID + (id % PER_USER_RANGE)
201                - Process.FIRST_APPLICATION_UID;
202    }
203
204    /**
205     * Returns the app id for a given shared app gid. Returns -1 if the ID is invalid.
206     * @hide
207     */
208    public static @AppIdInt int getAppIdFromSharedAppGid(int gid) {
209        final int appId = getAppId(gid) + Process.FIRST_APPLICATION_UID
210                - Process.FIRST_SHARED_APPLICATION_GID;
211        if (appId < 0 || appId >= Process.FIRST_SHARED_APPLICATION_GID) {
212            return -1;
213        }
214        return appId;
215    }
216
217    /**
218     * Returns the cache GID for a given UID or appId.
219     * @hide
220     */
221    public static int getCacheAppGid(int id) {
222        return Process.FIRST_APPLICATION_CACHE_GID + (id % PER_USER_RANGE)
223                - Process.FIRST_APPLICATION_UID;
224    }
225
226    /**
227     * Generate a text representation of the uid, breaking out its individual
228     * components -- user, app, isolated, etc.
229     * @hide
230     */
231    public static void formatUid(StringBuilder sb, int uid) {
232        if (uid < Process.FIRST_APPLICATION_UID) {
233            sb.append(uid);
234        } else {
235            sb.append('u');
236            sb.append(getUserId(uid));
237            final int appId = getAppId(uid);
238            if (appId >= Process.FIRST_ISOLATED_UID && appId <= Process.LAST_ISOLATED_UID) {
239                sb.append('i');
240                sb.append(appId - Process.FIRST_ISOLATED_UID);
241            } else if (appId >= Process.FIRST_APPLICATION_UID) {
242                sb.append('a');
243                sb.append(appId - Process.FIRST_APPLICATION_UID);
244            } else {
245                sb.append('s');
246                sb.append(appId);
247            }
248        }
249    }
250
251    /**
252     * Generate a text representation of the uid, breaking out its individual
253     * components -- user, app, isolated, etc.
254     * @hide
255     */
256    public static String formatUid(int uid) {
257        StringBuilder sb = new StringBuilder();
258        formatUid(sb, uid);
259        return sb.toString();
260    }
261
262    /**
263     * Generate a text representation of the uid, breaking out its individual
264     * components -- user, app, isolated, etc.
265     * @hide
266     */
267    public static void formatUid(PrintWriter pw, int uid) {
268        if (uid < Process.FIRST_APPLICATION_UID) {
269            pw.print(uid);
270        } else {
271            pw.print('u');
272            pw.print(getUserId(uid));
273            final int appId = getAppId(uid);
274            if (appId >= Process.FIRST_ISOLATED_UID && appId <= Process.LAST_ISOLATED_UID) {
275                pw.print('i');
276                pw.print(appId - Process.FIRST_ISOLATED_UID);
277            } else if (appId >= Process.FIRST_APPLICATION_UID) {
278                pw.print('a');
279                pw.print(appId - Process.FIRST_APPLICATION_UID);
280            } else {
281                pw.print('s');
282                pw.print(appId);
283            }
284        }
285    }
286
287    /** @hide */
288    public static @UserIdInt int parseUserArg(String arg) {
289        int userId;
290        if ("all".equals(arg)) {
291            userId = UserHandle.USER_ALL;
292        } else if ("current".equals(arg) || "cur".equals(arg)) {
293            userId = UserHandle.USER_CURRENT;
294        } else {
295            try {
296                userId = Integer.parseInt(arg);
297            } catch (NumberFormatException e) {
298                throw new IllegalArgumentException("Bad user number: " + arg);
299            }
300        }
301        return userId;
302    }
303
304    /**
305     * Returns the user id of the current process
306     * @return user id of the current process
307     * @hide
308     */
309    @SystemApi
310    public static @UserIdInt int myUserId() {
311        return getUserId(Process.myUid());
312    }
313
314    /**
315     * Returns true if this UserHandle refers to the owner user; false otherwise.
316     * @return true if this UserHandle refers to the owner user; false otherwise.
317     * @hide
318     * @deprecated please use {@link #isSystem()} or check for
319     * {@link android.content.pm.UserInfo#isPrimary()}
320     * {@link android.content.pm.UserInfo#isAdmin()} based on your particular use case.
321     */
322    @Deprecated
323    @SystemApi
324    public boolean isOwner() {
325        return this.equals(OWNER);
326    }
327
328    /**
329     * @return true if this UserHandle refers to the system user; false otherwise.
330     * @hide
331     */
332    @SystemApi
333    public boolean isSystem() {
334        return this.equals(SYSTEM);
335    }
336
337    /** @hide */
338    public UserHandle(int h) {
339        mHandle = h;
340    }
341
342    /**
343     * Returns the userId stored in this UserHandle.
344     * @hide
345     */
346    @SystemApi
347    @TestApi
348    public @UserIdInt int getIdentifier() {
349        return mHandle;
350    }
351
352    @Override
353    public String toString() {
354        return "UserHandle{" + mHandle + "}";
355    }
356
357    @Override
358    public boolean equals(Object obj) {
359        try {
360            if (obj != null) {
361                UserHandle other = (UserHandle)obj;
362                return mHandle == other.mHandle;
363            }
364        } catch (ClassCastException e) {
365        }
366        return false;
367    }
368
369    @Override
370    public int hashCode() {
371        return mHandle;
372    }
373
374    public int describeContents() {
375        return 0;
376    }
377
378    public void writeToParcel(Parcel out, int flags) {
379        out.writeInt(mHandle);
380    }
381
382    /**
383     * Write a UserHandle to a Parcel, handling null pointers.  Must be
384     * read with {@link #readFromParcel(Parcel)}.
385     *
386     * @param h The UserHandle to be written.
387     * @param out The Parcel in which the UserHandle will be placed.
388     *
389     * @see #readFromParcel(Parcel)
390     */
391    public static void writeToParcel(UserHandle h, Parcel out) {
392        if (h != null) {
393            h.writeToParcel(out, 0);
394        } else {
395            out.writeInt(USER_NULL);
396        }
397    }
398
399    /**
400     * Read a UserHandle from a Parcel that was previously written
401     * with {@link #writeToParcel(UserHandle, Parcel)}, returning either
402     * a null or new object as appropriate.
403     *
404     * @param in The Parcel from which to read the UserHandle
405     * @return Returns a new UserHandle matching the previously written
406     * object, or null if a null had been written.
407     *
408     * @see #writeToParcel(UserHandle, Parcel)
409     */
410    public static UserHandle readFromParcel(Parcel in) {
411        int h = in.readInt();
412        return h != USER_NULL ? new UserHandle(h) : null;
413    }
414
415    public static final Parcelable.Creator<UserHandle> CREATOR
416            = new Parcelable.Creator<UserHandle>() {
417        public UserHandle createFromParcel(Parcel in) {
418            return new UserHandle(in);
419        }
420
421        public UserHandle[] newArray(int size) {
422            return new UserHandle[size];
423        }
424    };
425
426    /**
427     * Instantiate a new UserHandle from the data in a Parcel that was
428     * previously written with {@link #writeToParcel(Parcel, int)}.  Note that you
429     * must not use this with data written by
430     * {@link #writeToParcel(UserHandle, Parcel)} since it is not possible
431     * to handle a null UserHandle here.
432     *
433     * @param in The Parcel containing the previously written UserHandle,
434     * positioned at the location in the buffer where it was written.
435     */
436    public UserHandle(Parcel in) {
437        mHandle = in.readInt();
438    }
439}
440