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     @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      */
isSameUser(int uid1, int uid2)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      */
isSameApp(int uid1, int uid2)110     public static boolean isSameApp(int uid1, int uid2) {
111         return getAppId(uid1) == getAppId(uid2);
112     }
113 
114     /** @hide */
isIsolated(int uid)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 */
isApp(int uid)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      */
getUserHandleForUid(int uid)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      */
getUserId(int uid)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 */
getCallingUserId()156     public static @UserIdInt int getCallingUserId() {
157         return getUserId(Binder.getCallingUid());
158     }
159 
160     /** @hide */
161     @SystemApi
of(@serIdInt int userId)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      */
getUid(@serIdInt int userId, @AppIdInt int appId)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
getAppId(int uid)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      */
getUserGid(@serIdInt int userId)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      */
getSharedAppGid(int id)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      */
getAppIdFromSharedAppGid(int gid)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      */
getCacheAppGid(int id)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      */
formatUid(StringBuilder sb, int uid)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      */
formatUid(int uid)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      */
formatUid(PrintWriter pw, int uid)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 */
parseUserArg(String arg)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
myUserId()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
isOwner()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
isSystem()333     public boolean isSystem() {
334         return this.equals(SYSTEM);
335     }
336 
337     /** @hide */
UserHandle(int h)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
getIdentifier()348     public @UserIdInt int getIdentifier() {
349         return mHandle;
350     }
351 
352     @Override
toString()353     public String toString() {
354         return "UserHandle{" + mHandle + "}";
355     }
356 
357     @Override
equals(Object obj)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
hashCode()370     public int hashCode() {
371         return mHandle;
372     }
373 
describeContents()374     public int describeContents() {
375         return 0;
376     }
377 
writeToParcel(Parcel out, int flags)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      */
writeToParcel(UserHandle h, Parcel out)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      */
readFromParcel(Parcel in)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      */
UserHandle(Parcel in)436     public UserHandle(Parcel in) {
437         mHandle = in.readInt();
438     }
439 }
440