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