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