• 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.SystemApi;
20 import android.util.SparseArray;
21 
22 import java.io.PrintWriter;
23 import java.util.HashMap;
24 
25 /**
26  * Representation of a user on the device.
27  */
28 public final class UserHandle implements Parcelable {
29     /**
30      * @hide Range of uids allocated for a user.
31      */
32     public static final int PER_USER_RANGE = 100000;
33 
34     /** @hide A user id to indicate all users on the device */
35     public static final int USER_ALL = -1;
36 
37     /** @hide A user handle to indicate all users on the device */
38     public static final UserHandle ALL = new UserHandle(USER_ALL);
39 
40     /** @hide A user id to indicate the currently active user */
41     public static final int USER_CURRENT = -2;
42 
43     /** @hide A user handle to indicate the current user of the device */
44     public static final UserHandle CURRENT = new UserHandle(USER_CURRENT);
45 
46     /** @hide A user id to indicate that we would like to send to the current
47      *  user, but if this is calling from a user process then we will send it
48      *  to the caller's user instead of failing with a security exception */
49     public static final int USER_CURRENT_OR_SELF = -3;
50 
51     /** @hide A user handle to indicate that we would like to send to the current
52      *  user, but if this is calling from a user process then we will send it
53      *  to the caller's user instead of failing with a security exception */
54     public static final UserHandle CURRENT_OR_SELF = new UserHandle(USER_CURRENT_OR_SELF);
55 
56     /** @hide An undefined user id */
57     public static final int USER_NULL = -10000;
58 
59     /** @hide A user id constant to indicate the "owner" user of the device */
60     public static final int USER_OWNER = 0;
61 
62     /** @hide A user handle to indicate the primary/owner user of the device */
63     public static final UserHandle OWNER = new UserHandle(USER_OWNER);
64 
65     /**
66      * @hide Enable multi-user related side effects. Set this to false if
67      * there are problems with single user use-cases.
68      */
69     public static final boolean MU_ENABLED = true;
70 
71     final int mHandle;
72 
73     private static final SparseArray<UserHandle> userHandles = new SparseArray<UserHandle>();
74 
75     /**
76      * Checks to see if the user id is the same for the two uids, i.e., they belong to the same
77      * user.
78      * @hide
79      */
isSameUser(int uid1, int uid2)80     public static final boolean isSameUser(int uid1, int uid2) {
81         return getUserId(uid1) == getUserId(uid2);
82     }
83 
84     /**
85      * Checks to see if both uids are referring to the same app id, ignoring the user id part of the
86      * uids.
87      * @param uid1 uid to compare
88      * @param uid2 other uid to compare
89      * @return whether the appId is the same for both uids
90      * @hide
91      */
isSameApp(int uid1, int uid2)92     public static final boolean isSameApp(int uid1, int uid2) {
93         return getAppId(uid1) == getAppId(uid2);
94     }
95 
96     /** @hide */
isIsolated(int uid)97     public static final boolean isIsolated(int uid) {
98         if (uid > 0) {
99             final int appId = getAppId(uid);
100             return appId >= Process.FIRST_ISOLATED_UID && appId <= Process.LAST_ISOLATED_UID;
101         } else {
102             return false;
103         }
104     }
105 
106     /** @hide */
isApp(int uid)107     public static boolean isApp(int uid) {
108         if (uid > 0) {
109             final int appId = getAppId(uid);
110             return appId >= Process.FIRST_APPLICATION_UID && appId <= Process.LAST_APPLICATION_UID;
111         } else {
112             return false;
113         }
114     }
115 
116     /**
117      * Returns the user id for a given uid.
118      * @hide
119      */
getUserId(int uid)120     public static final int getUserId(int uid) {
121         if (MU_ENABLED) {
122             return uid / PER_USER_RANGE;
123         } else {
124             return 0;
125         }
126     }
127 
128     /** @hide */
getCallingUserId()129     public static final int getCallingUserId() {
130         return getUserId(Binder.getCallingUid());
131     }
132 
133     /** @hide */
getCallingUserHandle()134     public static final UserHandle getCallingUserHandle() {
135         int userId = getUserId(Binder.getCallingUid());
136         UserHandle userHandle = userHandles.get(userId);
137         // Intentionally not synchronized to save time
138         if (userHandle == null) {
139             userHandle = new UserHandle(userId);
140             userHandles.put(userId, userHandle);
141         }
142         return userHandle;
143     }
144 
145     /**
146      * Returns the uid that is composed from the userId and the appId.
147      * @hide
148      */
getUid(int userId, int appId)149     public static final int getUid(int userId, int appId) {
150         if (MU_ENABLED) {
151             return userId * PER_USER_RANGE + (appId % PER_USER_RANGE);
152         } else {
153             return appId;
154         }
155     }
156 
157     /**
158      * Returns the app id (or base uid) for a given uid, stripping out the user id from it.
159      * @hide
160      */
getAppId(int uid)161     public static final int getAppId(int uid) {
162         return uid % PER_USER_RANGE;
163     }
164 
165     /**
166      * Returns the gid shared between all apps with this userId.
167      * @hide
168      */
getUserGid(int userId)169     public static final int getUserGid(int userId) {
170         return getUid(userId, Process.SHARED_USER_GID);
171     }
172 
173     /**
174      * Returns the shared app gid for a given uid or appId.
175      * @hide
176      */
getSharedAppGid(int id)177     public static final int getSharedAppGid(int id) {
178         return Process.FIRST_SHARED_APPLICATION_GID + (id % PER_USER_RANGE)
179                 - Process.FIRST_APPLICATION_UID;
180     }
181 
182     /**
183      * Generate a text representation of the uid, breaking out its individual
184      * components -- user, app, isolated, etc.
185      * @hide
186      */
formatUid(StringBuilder sb, int uid)187     public static void formatUid(StringBuilder sb, int uid) {
188         if (uid < Process.FIRST_APPLICATION_UID) {
189             sb.append(uid);
190         } else {
191             sb.append('u');
192             sb.append(getUserId(uid));
193             final int appId = getAppId(uid);
194             if (appId >= Process.FIRST_ISOLATED_UID && appId <= Process.LAST_ISOLATED_UID) {
195                 sb.append('i');
196                 sb.append(appId - Process.FIRST_ISOLATED_UID);
197             } else if (appId >= Process.FIRST_APPLICATION_UID) {
198                 sb.append('a');
199                 sb.append(appId - Process.FIRST_APPLICATION_UID);
200             } else {
201                 sb.append('s');
202                 sb.append(appId);
203             }
204         }
205     }
206 
207     /**
208      * Generate a text representation of the uid, breaking out its individual
209      * components -- user, app, isolated, etc.
210      * @hide
211      */
formatUid(PrintWriter pw, int uid)212     public static void formatUid(PrintWriter pw, int uid) {
213         if (uid < Process.FIRST_APPLICATION_UID) {
214             pw.print(uid);
215         } else {
216             pw.print('u');
217             pw.print(getUserId(uid));
218             final int appId = getAppId(uid);
219             if (appId >= Process.FIRST_ISOLATED_UID && appId <= Process.LAST_ISOLATED_UID) {
220                 pw.print('i');
221                 pw.print(appId - Process.FIRST_ISOLATED_UID);
222             } else if (appId >= Process.FIRST_APPLICATION_UID) {
223                 pw.print('a');
224                 pw.print(appId - Process.FIRST_APPLICATION_UID);
225             } else {
226                 pw.print('s');
227                 pw.print(appId);
228             }
229         }
230     }
231 
232     /**
233      * Returns the user id of the current process
234      * @return user id of the current process
235      * @hide
236      */
237     @SystemApi
myUserId()238     public static final int myUserId() {
239         return getUserId(Process.myUid());
240     }
241 
242     /**
243      * Returns true if this UserHandle refers to the owner user; false otherwise.
244      * @return true if this UserHandle refers to the owner user; false otherwise.
245      * @hide
246      */
247     @SystemApi
isOwner()248     public final boolean isOwner() {
249         return this.equals(OWNER);
250     }
251 
252     /** @hide */
UserHandle(int h)253     public UserHandle(int h) {
254         mHandle = h;
255     }
256 
257     /**
258      * Returns the userId stored in this UserHandle.
259      * @hide
260      */
261     @SystemApi
getIdentifier()262     public int getIdentifier() {
263         return mHandle;
264     }
265 
266     @Override
toString()267     public String toString() {
268         return "UserHandle{" + mHandle + "}";
269     }
270 
271     @Override
equals(Object obj)272     public boolean equals(Object obj) {
273         try {
274             if (obj != null) {
275                 UserHandle other = (UserHandle)obj;
276                 return mHandle == other.mHandle;
277             }
278         } catch (ClassCastException e) {
279         }
280         return false;
281     }
282 
283     @Override
hashCode()284     public int hashCode() {
285         return mHandle;
286     }
287 
describeContents()288     public int describeContents() {
289         return 0;
290     }
291 
writeToParcel(Parcel out, int flags)292     public void writeToParcel(Parcel out, int flags) {
293         out.writeInt(mHandle);
294     }
295 
296     /**
297      * Write a UserHandle to a Parcel, handling null pointers.  Must be
298      * read with {@link #readFromParcel(Parcel)}.
299      *
300      * @param h The UserHandle to be written.
301      * @param out The Parcel in which the UserHandle will be placed.
302      *
303      * @see #readFromParcel(Parcel)
304      */
writeToParcel(UserHandle h, Parcel out)305     public static void writeToParcel(UserHandle h, Parcel out) {
306         if (h != null) {
307             h.writeToParcel(out, 0);
308         } else {
309             out.writeInt(USER_NULL);
310         }
311     }
312 
313     /**
314      * Read a UserHandle from a Parcel that was previously written
315      * with {@link #writeToParcel(UserHandle, Parcel)}, returning either
316      * a null or new object as appropriate.
317      *
318      * @param in The Parcel from which to read the UserHandle
319      * @return Returns a new UserHandle matching the previously written
320      * object, or null if a null had been written.
321      *
322      * @see #writeToParcel(UserHandle, Parcel)
323      */
readFromParcel(Parcel in)324     public static UserHandle readFromParcel(Parcel in) {
325         int h = in.readInt();
326         return h != USER_NULL ? new UserHandle(h) : null;
327     }
328 
329     public static final Parcelable.Creator<UserHandle> CREATOR
330             = new Parcelable.Creator<UserHandle>() {
331         public UserHandle createFromParcel(Parcel in) {
332             return new UserHandle(in);
333         }
334 
335         public UserHandle[] newArray(int size) {
336             return new UserHandle[size];
337         }
338     };
339 
340     /**
341      * Instantiate a new UserHandle from the data in a Parcel that was
342      * previously written with {@link #writeToParcel(Parcel, int)}.  Note that you
343      * must not use this with data written by
344      * {@link #writeToParcel(UserHandle, Parcel)} since it is not possible
345      * to handle a null UserHandle here.
346      *
347      * @param in The Parcel containing the previously written UserHandle,
348      * positioned at the location in the buffer where it was written.
349      */
UserHandle(Parcel in)350     public UserHandle(Parcel in) {
351         mHandle = in.readInt();
352     }
353 }
354