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