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.UserIdInt;
24 import android.compat.annotation.UnsupportedAppUsage;
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     @UnsupportedAppUsage
175     @TestApi
isApp(int uid)176     public static boolean isApp(int uid) {
177         if (uid > 0) {
178             final int appId = getAppId(uid);
179             return appId >= Process.FIRST_APPLICATION_UID && appId <= Process.LAST_APPLICATION_UID;
180         } else {
181             return false;
182         }
183     }
184 
185     /**
186      * Whether a UID belongs to a system core component or not.
187      * @hide
188      */
isCore(int uid)189     public static boolean isCore(int uid) {
190         if (uid >= 0) {
191             final int appId = getAppId(uid);
192             return appId < Process.FIRST_APPLICATION_UID;
193         } else {
194             return false;
195         }
196     }
197 
198     /**
199      * Returns the user for a given uid.
200      * @param uid A uid for an application running in a particular user.
201      * @return A {@link UserHandle} for that user.
202      */
getUserHandleForUid(int uid)203     public static UserHandle getUserHandleForUid(int uid) {
204         return of(getUserId(uid));
205     }
206 
207     /**
208      * Returns the user id for a given uid.
209      * @hide
210      */
211     @UnsupportedAppUsage
getUserId(int uid)212     public static @UserIdInt int getUserId(int uid) {
213         if (MU_ENABLED) {
214             return uid / PER_USER_RANGE;
215         } else {
216             return UserHandle.USER_SYSTEM;
217         }
218     }
219 
220     /** @hide */
221     @UnsupportedAppUsage
getCallingUserId()222     public static @UserIdInt int getCallingUserId() {
223         return getUserId(Binder.getCallingUid());
224     }
225 
226     /** @hide */
getCallingAppId()227     public static @AppIdInt int getCallingAppId() {
228         return getAppId(Binder.getCallingUid());
229     }
230 
231     /** @hide */
232     @SystemApi
of(@serIdInt int userId)233     public static UserHandle of(@UserIdInt int userId) {
234         return userId == USER_SYSTEM ? SYSTEM : new UserHandle(userId);
235     }
236 
237     /**
238      * Returns the uid that is composed from the userId and the appId.
239      * @hide
240      */
241     @UnsupportedAppUsage
getUid(@serIdInt int userId, @AppIdInt int appId)242     public static int getUid(@UserIdInt int userId, @AppIdInt int appId) {
243         if (MU_ENABLED) {
244             return userId * PER_USER_RANGE + (appId % PER_USER_RANGE);
245         } else {
246             return appId;
247         }
248     }
249 
250     /**
251      * Returns the app id (or base uid) for a given uid, stripping out the user id from it.
252      * @hide
253      */
254     @TestApi
255     @SystemApi
getAppId(int uid)256     public static @AppIdInt int getAppId(int uid) {
257         return uid % PER_USER_RANGE;
258     }
259 
260     /**
261      * Returns the gid shared between all apps with this userId.
262      * @hide
263      */
getUserGid(@serIdInt int userId)264     public static int getUserGid(@UserIdInt int userId) {
265         return getUid(userId, Process.SHARED_USER_GID);
266     }
267 
268     /** @hide */
getSharedAppGid(int uid)269     public static int getSharedAppGid(int uid) {
270         return getSharedAppGid(getUserId(uid), getAppId(uid));
271     }
272 
273     /** @hide */
getSharedAppGid(int userId, int appId)274     public static int getSharedAppGid(int userId, int appId) {
275         if (appId >= AID_APP_START && appId <= AID_APP_END) {
276             return (appId - AID_APP_START) + AID_SHARED_GID_START;
277         } else if (appId >= AID_ROOT && appId <= AID_APP_START) {
278             return appId;
279         } else {
280             return -1;
281         }
282     }
283 
284     /**
285      * Returns the app id for a given shared app gid. Returns -1 if the ID is invalid.
286      * @hide
287      */
288     @UnsupportedAppUsage
getAppIdFromSharedAppGid(int gid)289     public static @AppIdInt int getAppIdFromSharedAppGid(int gid) {
290         final int appId = getAppId(gid) + Process.FIRST_APPLICATION_UID
291                 - Process.FIRST_SHARED_APPLICATION_GID;
292         if (appId < 0 || appId >= Process.FIRST_SHARED_APPLICATION_GID) {
293             return -1;
294         }
295         return appId;
296     }
297 
298     /** @hide */
getCacheAppGid(int uid)299     public static int getCacheAppGid(int uid) {
300         return getCacheAppGid(getUserId(uid), getAppId(uid));
301     }
302 
303     /** @hide */
getCacheAppGid(int userId, int appId)304     public static int getCacheAppGid(int userId, int appId) {
305         if (appId >= AID_APP_START && appId <= AID_APP_END) {
306             return getUid(userId, (appId - AID_APP_START) + AID_CACHE_GID_START);
307         } else {
308             return -1;
309         }
310     }
311 
312     /**
313      * Generate a text representation of the uid, breaking out its individual
314      * components -- user, app, isolated, etc.
315      * @hide
316      */
formatUid(StringBuilder sb, int uid)317     public static void formatUid(StringBuilder sb, int uid) {
318         if (uid < Process.FIRST_APPLICATION_UID) {
319             sb.append(uid);
320         } else {
321             sb.append('u');
322             sb.append(getUserId(uid));
323             final int appId = getAppId(uid);
324             if (isIsolated(appId)) {
325                 if (appId > Process.FIRST_ISOLATED_UID) {
326                     sb.append('i');
327                     sb.append(appId - Process.FIRST_ISOLATED_UID);
328                 } else {
329                     sb.append("ai");
330                     sb.append(appId - Process.FIRST_APP_ZYGOTE_ISOLATED_UID);
331                 }
332             } else if (appId >= Process.FIRST_APPLICATION_UID) {
333                 sb.append('a');
334                 sb.append(appId - Process.FIRST_APPLICATION_UID);
335             } else {
336                 sb.append('s');
337                 sb.append(appId);
338             }
339         }
340     }
341 
342     /**
343      * Generate a text representation of the uid, breaking out its individual
344      * components -- user, app, isolated, etc.
345      * @hide
346      */
formatUid(int uid)347     public static String formatUid(int uid) {
348         StringBuilder sb = new StringBuilder();
349         formatUid(sb, uid);
350         return sb.toString();
351     }
352 
353     /**
354      * Generate a text representation of the uid, breaking out its individual
355      * components -- user, app, isolated, etc.
356      * @hide
357      */
358     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
formatUid(PrintWriter pw, int uid)359     public static void formatUid(PrintWriter pw, int uid) {
360         if (uid < Process.FIRST_APPLICATION_UID) {
361             pw.print(uid);
362         } else {
363             pw.print('u');
364             pw.print(getUserId(uid));
365             final int appId = getAppId(uid);
366             if (isIsolated(appId)) {
367                 if (appId > Process.FIRST_ISOLATED_UID) {
368                     pw.print('i');
369                     pw.print(appId - Process.FIRST_ISOLATED_UID);
370                 } else {
371                     pw.print("ai");
372                     pw.print(appId - Process.FIRST_APP_ZYGOTE_ISOLATED_UID);
373                 }
374             } else if (appId >= Process.FIRST_APPLICATION_UID) {
375                 pw.print('a');
376                 pw.print(appId - Process.FIRST_APPLICATION_UID);
377             } else {
378                 pw.print('s');
379                 pw.print(appId);
380             }
381         }
382     }
383 
384     /** @hide */
parseUserArg(String arg)385     public static @UserIdInt int parseUserArg(String arg) {
386         int userId;
387         if ("all".equals(arg)) {
388             userId = UserHandle.USER_ALL;
389         } else if ("current".equals(arg) || "cur".equals(arg)) {
390             userId = UserHandle.USER_CURRENT;
391         } else {
392             try {
393                 userId = Integer.parseInt(arg);
394             } catch (NumberFormatException e) {
395                 throw new IllegalArgumentException("Bad user number: " + arg);
396             }
397         }
398         return userId;
399     }
400 
401     /**
402      * Returns the user id of the current process
403      * @return user id of the current process
404      * @hide
405      */
406     @SystemApi
myUserId()407     public static @UserIdInt int myUserId() {
408         return getUserId(Process.myUid());
409     }
410 
411     /**
412      * Returns true if this UserHandle refers to the owner user; false otherwise.
413      * @return true if this UserHandle refers to the owner user; false otherwise.
414      * @hide
415      * @deprecated please use {@link #isSystem()} or check for
416      * {@link android.content.pm.UserInfo#isPrimary()}
417      * {@link android.content.pm.UserInfo#isAdmin()} based on your particular use case.
418      */
419     @Deprecated
420     @SystemApi
isOwner()421     public boolean isOwner() {
422         return this.equals(OWNER);
423     }
424 
425     /**
426      * @return true if this UserHandle refers to the system user; false otherwise.
427      * @hide
428      */
429     @SystemApi
isSystem()430     public boolean isSystem() {
431         return this.equals(SYSTEM);
432     }
433 
434     /** @hide */
435     @UnsupportedAppUsage
UserHandle(int h)436     public UserHandle(int h) {
437         mHandle = h;
438     }
439 
440     /**
441      * Returns the userId stored in this UserHandle.
442      * @hide
443      */
444     @SystemApi
445     @TestApi
getIdentifier()446     public @UserIdInt int getIdentifier() {
447         return mHandle;
448     }
449 
450     @Override
toString()451     public String toString() {
452         return "UserHandle{" + mHandle + "}";
453     }
454 
455     @Override
equals(Object obj)456     public boolean equals(Object obj) {
457         try {
458             if (obj != null) {
459                 UserHandle other = (UserHandle)obj;
460                 return mHandle == other.mHandle;
461             }
462         } catch (ClassCastException e) {
463         }
464         return false;
465     }
466 
467     @Override
hashCode()468     public int hashCode() {
469         return mHandle;
470     }
471 
describeContents()472     public int describeContents() {
473         return 0;
474     }
475 
writeToParcel(Parcel out, int flags)476     public void writeToParcel(Parcel out, int flags) {
477         out.writeInt(mHandle);
478     }
479 
480     /**
481      * Write a UserHandle to a Parcel, handling null pointers.  Must be
482      * read with {@link #readFromParcel(Parcel)}.
483      *
484      * @param h The UserHandle to be written.
485      * @param out The Parcel in which the UserHandle will be placed.
486      *
487      * @see #readFromParcel(Parcel)
488      */
writeToParcel(UserHandle h, Parcel out)489     public static void writeToParcel(UserHandle h, Parcel out) {
490         if (h != null) {
491             h.writeToParcel(out, 0);
492         } else {
493             out.writeInt(USER_NULL);
494         }
495     }
496 
497     /**
498      * Read a UserHandle from a Parcel that was previously written
499      * with {@link #writeToParcel(UserHandle, Parcel)}, returning either
500      * a null or new object as appropriate.
501      *
502      * @param in The Parcel from which to read the UserHandle
503      * @return Returns a new UserHandle matching the previously written
504      * object, or null if a null had been written.
505      *
506      * @see #writeToParcel(UserHandle, Parcel)
507      */
readFromParcel(Parcel in)508     public static UserHandle readFromParcel(Parcel in) {
509         int h = in.readInt();
510         return h != USER_NULL ? new UserHandle(h) : null;
511     }
512 
513     public static final @android.annotation.NonNull Parcelable.Creator<UserHandle> CREATOR
514             = new Parcelable.Creator<UserHandle>() {
515         public UserHandle createFromParcel(Parcel in) {
516             return new UserHandle(in);
517         }
518 
519         public UserHandle[] newArray(int size) {
520             return new UserHandle[size];
521         }
522     };
523 
524     /**
525      * Instantiate a new UserHandle from the data in a Parcel that was
526      * previously written with {@link #writeToParcel(Parcel, int)}.  Note that you
527      * must not use this with data written by
528      * {@link #writeToParcel(UserHandle, Parcel)} since it is not possible
529      * to handle a null UserHandle here.
530      *
531      * @param in The Parcel containing the previously written UserHandle,
532      * positioned at the location in the buffer where it was written.
533      */
UserHandle(Parcel in)534     public UserHandle(Parcel in) {
535         mHandle = in.readInt();
536     }
537 }
538