• 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.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 */
getCallingAppId()161     public static @AppIdInt int getCallingAppId() {
162         return getAppId(Binder.getCallingUid());
163     }
164 
165     /** @hide */
166     @SystemApi
of(@serIdInt int userId)167     public static UserHandle of(@UserIdInt int userId) {
168         return userId == USER_SYSTEM ? SYSTEM : new UserHandle(userId);
169     }
170 
171     /**
172      * Returns the uid that is composed from the userId and the appId.
173      * @hide
174      */
getUid(@serIdInt int userId, @AppIdInt int appId)175     public static int getUid(@UserIdInt int userId, @AppIdInt int appId) {
176         if (MU_ENABLED) {
177             return userId * PER_USER_RANGE + (appId % PER_USER_RANGE);
178         } else {
179             return appId;
180         }
181     }
182 
183     /**
184      * Returns the app id (or base uid) for a given uid, stripping out the user id from it.
185      * @hide
186      */
187     @TestApi
getAppId(int uid)188     public static @AppIdInt int getAppId(int uid) {
189         return uid % PER_USER_RANGE;
190     }
191 
192     /**
193      * Returns the gid shared between all apps with this userId.
194      * @hide
195      */
getUserGid(@serIdInt int userId)196     public static int getUserGid(@UserIdInt int userId) {
197         return getUid(userId, Process.SHARED_USER_GID);
198     }
199 
200     /**
201      * Returns the shared app gid for a given uid or appId.
202      * @hide
203      */
getSharedAppGid(int id)204     public static int getSharedAppGid(int id) {
205         return Process.FIRST_SHARED_APPLICATION_GID + (id % PER_USER_RANGE)
206                 - Process.FIRST_APPLICATION_UID;
207     }
208 
209     /**
210      * Returns the app id for a given shared app gid. Returns -1 if the ID is invalid.
211      * @hide
212      */
getAppIdFromSharedAppGid(int gid)213     public static @AppIdInt int getAppIdFromSharedAppGid(int gid) {
214         final int appId = getAppId(gid) + Process.FIRST_APPLICATION_UID
215                 - Process.FIRST_SHARED_APPLICATION_GID;
216         if (appId < 0 || appId >= Process.FIRST_SHARED_APPLICATION_GID) {
217             return -1;
218         }
219         return appId;
220     }
221 
222     /**
223      * Returns the cache GID for a given UID or appId.
224      * @hide
225      */
getCacheAppGid(int id)226     public static int getCacheAppGid(int id) {
227         return Process.FIRST_APPLICATION_CACHE_GID + (id % PER_USER_RANGE)
228                 - Process.FIRST_APPLICATION_UID;
229     }
230 
231     /**
232      * Generate a text representation of the uid, breaking out its individual
233      * components -- user, app, isolated, etc.
234      * @hide
235      */
formatUid(StringBuilder sb, int uid)236     public static void formatUid(StringBuilder sb, int uid) {
237         if (uid < Process.FIRST_APPLICATION_UID) {
238             sb.append(uid);
239         } else {
240             sb.append('u');
241             sb.append(getUserId(uid));
242             final int appId = getAppId(uid);
243             if (appId >= Process.FIRST_ISOLATED_UID && appId <= Process.LAST_ISOLATED_UID) {
244                 sb.append('i');
245                 sb.append(appId - Process.FIRST_ISOLATED_UID);
246             } else if (appId >= Process.FIRST_APPLICATION_UID) {
247                 sb.append('a');
248                 sb.append(appId - Process.FIRST_APPLICATION_UID);
249             } else {
250                 sb.append('s');
251                 sb.append(appId);
252             }
253         }
254     }
255 
256     /**
257      * Generate a text representation of the uid, breaking out its individual
258      * components -- user, app, isolated, etc.
259      * @hide
260      */
formatUid(int uid)261     public static String formatUid(int uid) {
262         StringBuilder sb = new StringBuilder();
263         formatUid(sb, uid);
264         return sb.toString();
265     }
266 
267     /**
268      * Generate a text representation of the uid, breaking out its individual
269      * components -- user, app, isolated, etc.
270      * @hide
271      */
formatUid(PrintWriter pw, int uid)272     public static void formatUid(PrintWriter pw, int uid) {
273         if (uid < Process.FIRST_APPLICATION_UID) {
274             pw.print(uid);
275         } else {
276             pw.print('u');
277             pw.print(getUserId(uid));
278             final int appId = getAppId(uid);
279             if (appId >= Process.FIRST_ISOLATED_UID && appId <= Process.LAST_ISOLATED_UID) {
280                 pw.print('i');
281                 pw.print(appId - Process.FIRST_ISOLATED_UID);
282             } else if (appId >= Process.FIRST_APPLICATION_UID) {
283                 pw.print('a');
284                 pw.print(appId - Process.FIRST_APPLICATION_UID);
285             } else {
286                 pw.print('s');
287                 pw.print(appId);
288             }
289         }
290     }
291 
292     /** @hide */
parseUserArg(String arg)293     public static @UserIdInt int parseUserArg(String arg) {
294         int userId;
295         if ("all".equals(arg)) {
296             userId = UserHandle.USER_ALL;
297         } else if ("current".equals(arg) || "cur".equals(arg)) {
298             userId = UserHandle.USER_CURRENT;
299         } else {
300             try {
301                 userId = Integer.parseInt(arg);
302             } catch (NumberFormatException e) {
303                 throw new IllegalArgumentException("Bad user number: " + arg);
304             }
305         }
306         return userId;
307     }
308 
309     /**
310      * Returns the user id of the current process
311      * @return user id of the current process
312      * @hide
313      */
314     @SystemApi
myUserId()315     public static @UserIdInt int myUserId() {
316         return getUserId(Process.myUid());
317     }
318 
319     /**
320      * Returns true if this UserHandle refers to the owner user; false otherwise.
321      * @return true if this UserHandle refers to the owner user; false otherwise.
322      * @hide
323      * @deprecated please use {@link #isSystem()} or check for
324      * {@link android.content.pm.UserInfo#isPrimary()}
325      * {@link android.content.pm.UserInfo#isAdmin()} based on your particular use case.
326      */
327     @Deprecated
328     @SystemApi
isOwner()329     public boolean isOwner() {
330         return this.equals(OWNER);
331     }
332 
333     /**
334      * @return true if this UserHandle refers to the system user; false otherwise.
335      * @hide
336      */
337     @SystemApi
isSystem()338     public boolean isSystem() {
339         return this.equals(SYSTEM);
340     }
341 
342     /** @hide */
UserHandle(int h)343     public UserHandle(int h) {
344         mHandle = h;
345     }
346 
347     /**
348      * Returns the userId stored in this UserHandle.
349      * @hide
350      */
351     @SystemApi
352     @TestApi
getIdentifier()353     public @UserIdInt int getIdentifier() {
354         return mHandle;
355     }
356 
357     @Override
toString()358     public String toString() {
359         return "UserHandle{" + mHandle + "}";
360     }
361 
362     @Override
equals(Object obj)363     public boolean equals(Object obj) {
364         try {
365             if (obj != null) {
366                 UserHandle other = (UserHandle)obj;
367                 return mHandle == other.mHandle;
368             }
369         } catch (ClassCastException e) {
370         }
371         return false;
372     }
373 
374     @Override
hashCode()375     public int hashCode() {
376         return mHandle;
377     }
378 
describeContents()379     public int describeContents() {
380         return 0;
381     }
382 
writeToParcel(Parcel out, int flags)383     public void writeToParcel(Parcel out, int flags) {
384         out.writeInt(mHandle);
385     }
386 
387     /**
388      * Write a UserHandle to a Parcel, handling null pointers.  Must be
389      * read with {@link #readFromParcel(Parcel)}.
390      *
391      * @param h The UserHandle to be written.
392      * @param out The Parcel in which the UserHandle will be placed.
393      *
394      * @see #readFromParcel(Parcel)
395      */
writeToParcel(UserHandle h, Parcel out)396     public static void writeToParcel(UserHandle h, Parcel out) {
397         if (h != null) {
398             h.writeToParcel(out, 0);
399         } else {
400             out.writeInt(USER_NULL);
401         }
402     }
403 
404     /**
405      * Read a UserHandle from a Parcel that was previously written
406      * with {@link #writeToParcel(UserHandle, Parcel)}, returning either
407      * a null or new object as appropriate.
408      *
409      * @param in The Parcel from which to read the UserHandle
410      * @return Returns a new UserHandle matching the previously written
411      * object, or null if a null had been written.
412      *
413      * @see #writeToParcel(UserHandle, Parcel)
414      */
readFromParcel(Parcel in)415     public static UserHandle readFromParcel(Parcel in) {
416         int h = in.readInt();
417         return h != USER_NULL ? new UserHandle(h) : null;
418     }
419 
420     public static final Parcelable.Creator<UserHandle> CREATOR
421             = new Parcelable.Creator<UserHandle>() {
422         public UserHandle createFromParcel(Parcel in) {
423             return new UserHandle(in);
424         }
425 
426         public UserHandle[] newArray(int size) {
427             return new UserHandle[size];
428         }
429     };
430 
431     /**
432      * Instantiate a new UserHandle from the data in a Parcel that was
433      * previously written with {@link #writeToParcel(Parcel, int)}.  Note that you
434      * must not use this with data written by
435      * {@link #writeToParcel(UserHandle, Parcel)} since it is not possible
436      * to handle a null UserHandle here.
437      *
438      * @param in The Parcel containing the previously written UserHandle,
439      * positioned at the location in the buffer where it was written.
440      */
UserHandle(Parcel in)441     public UserHandle(Parcel in) {
442         mHandle = in.readInt();
443     }
444 }
445