• 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.NonNull;
21 import android.annotation.Nullable;
22 import android.annotation.SystemApi;
23 import android.annotation.TestApi;
24 import android.annotation.UserIdInt;
25 import android.compat.annotation.UnsupportedAppUsage;
26 import android.util.SparseArray;
27 
28 import com.android.internal.annotations.GuardedBy;
29 import com.android.internal.annotations.VisibleForTesting;
30 
31 import java.io.PrintWriter;
32 import java.util.ArrayList;
33 import java.util.List;
34 import java.util.Random;
35 
36 /**
37  * Representation of a user on the device.
38  */
39 public final class UserHandle implements Parcelable {
40     // NOTE: keep logic in sync with system/core/libcutils/multiuser.c
41 
42     /**
43      * @hide Range of uids allocated for a user.
44      */
45     @UnsupportedAppUsage
46     public static final int PER_USER_RANGE = 100000;
47 
48     /** @hide A user id to indicate all users on the device */
49     @UnsupportedAppUsage
50     @TestApi
51     public static final @UserIdInt int USER_ALL = -1;
52 
53     /** @hide A user handle to indicate all users on the device */
54     @SystemApi
55     public static final @NonNull UserHandle ALL = new UserHandle(USER_ALL);
56 
57     /** @hide A user id to indicate the currently active user */
58     @UnsupportedAppUsage
59     @TestApi
60     public static final @UserIdInt int USER_CURRENT = -2;
61 
62     /** @hide A user handle to indicate the current user of the device */
63     @SystemApi
64     public static final @NonNull UserHandle CURRENT = new UserHandle(USER_CURRENT);
65 
66     /** @hide A user id to indicate that we would like to send to the current
67      *  user, but if this is calling from a user process then we will send it
68      *  to the caller's user instead of failing with a security exception */
69     @UnsupportedAppUsage
70     public static final @UserIdInt int USER_CURRENT_OR_SELF = -3;
71 
72     /** @hide A user handle to indicate that we would like to send to the current
73      *  user, but if this is calling from a user process then we will send it
74      *  to the caller's user instead of failing with a security exception */
75     @UnsupportedAppUsage
76     public static final @NonNull UserHandle CURRENT_OR_SELF = new UserHandle(USER_CURRENT_OR_SELF);
77 
78     /** @hide An undefined user id */
79     @UnsupportedAppUsage
80     @TestApi
81     public static final @UserIdInt int USER_NULL = -10000;
82 
83     private static final @NonNull UserHandle NULL = new UserHandle(USER_NULL);
84 
85     /**
86      * @hide A user id constant to indicate the "owner" user of the device
87      * @deprecated Consider using either {@link UserHandle#USER_SYSTEM} constant or
88      * check the target user's flag {@link android.content.pm.UserInfo#isAdmin}.
89      */
90     @UnsupportedAppUsage
91     @Deprecated
92     public static final @UserIdInt int USER_OWNER = 0;
93 
94     /**
95      * @hide A user handle to indicate the primary/owner user of the device
96      * @deprecated Consider using either {@link UserHandle#SYSTEM} constant or
97      * check the target user's flag {@link android.content.pm.UserInfo#isAdmin}.
98      */
99     @UnsupportedAppUsage
100     @Deprecated
101     public static final @NonNull UserHandle OWNER = new UserHandle(USER_OWNER);
102 
103     /** @hide A user id constant to indicate the "system" user of the device */
104     @UnsupportedAppUsage
105     @TestApi
106     public static final @UserIdInt int USER_SYSTEM = 0;
107 
108     /** @hide A user serial constant to indicate the "system" user of the device */
109     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
110     public static final int USER_SERIAL_SYSTEM = 0;
111 
112     /** @hide A user handle to indicate the "system" user of the device */
113     @SystemApi
114     public static final @NonNull UserHandle SYSTEM = new UserHandle(USER_SYSTEM);
115 
116     /**
117      * @hide Enable multi-user related side effects. Set this to false if
118      * there are problems with single user use-cases.
119      */
120     @UnsupportedAppUsage
121     public static final boolean MU_ENABLED = true;
122 
123     /** @hide */
124     @TestApi
125     public static final int MIN_SECONDARY_USER_ID = 10;
126 
127     /** @hide */
128     public static final int MAX_SECONDARY_USER_ID = Integer.MAX_VALUE / UserHandle.PER_USER_RANGE;
129 
130     /**
131      * (Arbitrary) user handle cache size.
132      * {@link #CACHED_USER_HANDLES} caches user handles in the range of
133      * [{@link #MIN_SECONDARY_USER_ID}, {@link #MIN_SECONDARY_USER_ID} + {@link #NUM_CACHED_USERS}).
134      *
135      * For other users, we cache UserHandles in {link #sExtraUserHandleCache}.
136      *
137      * Normally, {@link #CACHED_USER_HANDLES} should cover all existing users, but use
138      * {link #sExtraUserHandleCache} to ensure {@link UserHandle#of} will not cause too many
139      * object allocations even if the device happens to have a secondary user with a large number
140      * (e.g. the user kept creating and removing the guest user?).
141      */
142     private static final int NUM_CACHED_USERS = MU_ENABLED ? 8 : 0;
143 
144     /** @see #NUM_CACHED_USERS} */
145     private static final UserHandle[] CACHED_USER_HANDLES = new UserHandle[NUM_CACHED_USERS];
146 
147     /**
148      * Extra cache for users beyond CACHED_USER_HANDLES.
149      *
150      * @see #NUM_CACHED_USERS
151      * @hide
152      */
153     @GuardedBy("sExtraUserHandleCache")
154     @VisibleForTesting
155     public static final SparseArray<UserHandle> sExtraUserHandleCache = new SparseArray<>(0);
156 
157     /**
158      * Max size of {@link #sExtraUserHandleCache}. Once it reaches this size, we select
159      * an element to remove at random.
160      *
161      * @hide
162      */
163     @VisibleForTesting
164     public static final int MAX_EXTRA_USER_HANDLE_CACHE_SIZE = 32;
165 
166     static {
167         // Not lazily initializing the cache, so that we can share them across processes.
168         // (We'll create them in zygote.)
169         for (int i = 0; i < CACHED_USER_HANDLES.length; i++) {
170             CACHED_USER_HANDLES[i] = new UserHandle(MIN_SECONDARY_USER_ID + i);
171         }
172     }
173 
174     /** @hide */
175     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
176     public static final int ERR_GID = -1;
177     /** @hide */
178     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
179     public static final int AID_ROOT = android.os.Process.ROOT_UID;
180     /** @hide */
181     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
182     public static final int AID_APP_START = android.os.Process.FIRST_APPLICATION_UID;
183     /** @hide */
184     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
185     public static final int AID_APP_END = android.os.Process.LAST_APPLICATION_UID;
186     /** @hide */
187     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
188     public static final int AID_SHARED_GID_START = android.os.Process.FIRST_SHARED_APPLICATION_GID;
189     /** @hide */
190     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
191     public static final int AID_CACHE_GID_START = android.os.Process.FIRST_APPLICATION_CACHE_GID;
192 
193     /** The userId represented by this UserHandle. */
194     @UnsupportedAppUsage
195     final @UserIdInt int mHandle;
196 
197     /**
198      * Checks to see if the user id is the same for the two uids, i.e., they belong to the same
199      * user.
200      * @hide
201      */
isSameUser(int uid1, int uid2)202     public static boolean isSameUser(int uid1, int uid2) {
203         return getUserId(uid1) == getUserId(uid2);
204     }
205 
206     /**
207      * Checks to see if both uids are referring to the same app id, ignoring the user id part of the
208      * uids.
209      * @param uid1 uid to compare
210      * @param uid2 other uid to compare
211      * @return whether the appId is the same for both uids
212      * @hide
213      */
214     @UnsupportedAppUsage
isSameApp(int uid1, int uid2)215     public static boolean isSameApp(int uid1, int uid2) {
216         return getAppId(uid1) == getAppId(uid2);
217     }
218 
219     /**
220      * Whether a UID is an "isolated" UID.
221      * @hide
222      */
223     @UnsupportedAppUsage
isIsolated(int uid)224     public static boolean isIsolated(int uid) {
225         if (uid > 0) {
226             return Process.isIsolated(uid);
227         } else {
228             return false;
229         }
230     }
231 
232     /**
233      * Whether a UID belongs to a regular app. *Note* "Not a regular app" does not mean
234      * "it's system", because of isolated UIDs. Use {@link #isCore} for that.
235      * @hide
236      */
237     @UnsupportedAppUsage
238     @TestApi
isApp(int uid)239     public static boolean isApp(int uid) {
240         if (uid > 0) {
241             final int appId = getAppId(uid);
242             return appId >= Process.FIRST_APPLICATION_UID && appId <= Process.LAST_APPLICATION_UID;
243         } else {
244             return false;
245         }
246     }
247 
248     /**
249      * Whether a UID belongs to a system core component or not.
250      * @hide
251      */
isCore(int uid)252     public static boolean isCore(int uid) {
253         if (uid >= 0) {
254             final int appId = getAppId(uid);
255             return appId < Process.FIRST_APPLICATION_UID;
256         } else {
257             return false;
258         }
259     }
260 
261     /**
262      * Whether a UID belongs to a shared app gid.
263      * @hide
264      */
isSharedAppGid(int uid)265     public static boolean isSharedAppGid(int uid) {
266         return getAppIdFromSharedAppGid(uid) != -1;
267     }
268 
269     /**
270      * Returns the user for a given uid.
271      * @param uid A uid for an application running in a particular user.
272      * @return A {@link UserHandle} for that user.
273      */
getUserHandleForUid(int uid)274     public static UserHandle getUserHandleForUid(int uid) {
275         return of(getUserId(uid));
276     }
277 
278     /**
279      * Returns the user id for a given uid.
280      * @hide
281      */
282     @UnsupportedAppUsage
283     @TestApi
getUserId(int uid)284     public static @UserIdInt int getUserId(int uid) {
285         if (MU_ENABLED) {
286             return uid / PER_USER_RANGE;
287         } else {
288             return UserHandle.USER_SYSTEM;
289         }
290     }
291 
292     /** @hide */
293     @UnsupportedAppUsage
getCallingUserId()294     public static @UserIdInt int getCallingUserId() {
295         return getUserId(Binder.getCallingUid());
296     }
297 
298     /** @hide */
getCallingAppId()299     public static @AppIdInt int getCallingAppId() {
300         return getAppId(Binder.getCallingUid());
301     }
302 
303     /** @hide */
304     @NonNull
fromUserHandles(@onNull List<UserHandle> users)305     public static int[] fromUserHandles(@NonNull List<UserHandle> users) {
306         int[] userIds = new int[users.size()];
307         for (int i = 0; i < userIds.length; ++i) {
308             userIds[i] = users.get(i).getIdentifier();
309         }
310         return userIds;
311     }
312 
313     /** @hide */
314     @NonNull
toUserHandles(@onNull int[] userIds)315     public static List<UserHandle> toUserHandles(@NonNull int[] userIds) {
316         List<UserHandle> users = new ArrayList<>(userIds.length);
317         for (int i = 0; i < userIds.length; ++i) {
318             users.add(UserHandle.of(userIds[i]));
319         }
320         return users;
321     }
322 
323     /** @hide */
324     @SystemApi
of(@serIdInt int userId)325     public static UserHandle of(@UserIdInt int userId) {
326         if (userId == USER_SYSTEM) {
327             return SYSTEM; // Most common.
328         }
329         // These are sequential; so use a switch. Maybe they'll be optimized to a table lookup.
330         switch (userId) {
331             case USER_ALL:
332                 return ALL;
333 
334             case USER_CURRENT:
335                 return CURRENT;
336 
337             case USER_CURRENT_OR_SELF:
338                 return CURRENT_OR_SELF;
339         }
340         if (userId >= MIN_SECONDARY_USER_ID
341                 && userId < (MIN_SECONDARY_USER_ID + CACHED_USER_HANDLES.length)) {
342             return CACHED_USER_HANDLES[userId - MIN_SECONDARY_USER_ID];
343         }
344         if (userId == USER_NULL) { // Not common.
345             return NULL;
346         }
347         return getUserHandleFromExtraCache(userId);
348     }
349 
350     /** @hide */
351     @VisibleForTesting
getUserHandleFromExtraCache(@serIdInt int userId)352     public static UserHandle getUserHandleFromExtraCache(@UserIdInt int userId) {
353         synchronized (sExtraUserHandleCache) {
354             final UserHandle extraCached = sExtraUserHandleCache.get(userId);
355             if (extraCached != null) {
356                 return extraCached;
357             }
358             if (sExtraUserHandleCache.size() >= MAX_EXTRA_USER_HANDLE_CACHE_SIZE) {
359                 sExtraUserHandleCache.removeAt(
360                         (new Random()).nextInt(MAX_EXTRA_USER_HANDLE_CACHE_SIZE));
361             }
362             final UserHandle newHandle = new UserHandle(userId);
363             sExtraUserHandleCache.put(userId, newHandle);
364             return newHandle;
365         }
366     }
367 
368     /**
369      * Returns the uid that is composed from the userId and the appId.
370      * @hide
371      */
372     @UnsupportedAppUsage
373     @TestApi
getUid(@serIdInt int userId, @AppIdInt int appId)374     public static int getUid(@UserIdInt int userId, @AppIdInt int appId) {
375         if (MU_ENABLED && appId >= 0) {
376             return userId * PER_USER_RANGE + (appId % PER_USER_RANGE);
377         } else {
378             return appId;
379         }
380     }
381 
382     /**
383      * Returns the uid representing the given appId for this UserHandle.
384      *
385      * @param appId the AppId to compose the uid
386      * @return the uid representing the given appId for this UserHandle
387      * @hide
388      */
389     @SystemApi
getUid(@ppIdInt int appId)390     public int getUid(@AppIdInt int appId) {
391         return getUid(getIdentifier(), appId);
392     }
393 
394     /**
395      * Returns the app id (or base uid) for a given uid, stripping out the user id from it.
396      * @hide
397      */
398     @SystemApi
getAppId(int uid)399     public static @AppIdInt int getAppId(int uid) {
400         return uid % PER_USER_RANGE;
401     }
402 
403     /**
404      * Returns the gid shared between all apps with this userId.
405      * @hide
406      */
getUserGid(@serIdInt int userId)407     public static int getUserGid(@UserIdInt int userId) {
408         return getUid(userId, Process.SHARED_USER_GID);
409     }
410 
411     /**
412      * Returns the gid shared between all users with the app that this uid represents, or -1 if the
413      * uid is invalid.
414      * @hide
415      */
416     @SystemApi
getSharedAppGid(int uid)417     public static int getSharedAppGid(int uid) {
418         return getSharedAppGid(getUserId(uid), getAppId(uid));
419     }
420 
421     /** @hide */
getSharedAppGid(@serIdInt int userId, @AppIdInt int appId)422     public static int getSharedAppGid(@UserIdInt int userId, @AppIdInt int appId) {
423         if (appId >= AID_APP_START && appId <= AID_APP_END) {
424             return (appId - AID_APP_START) + AID_SHARED_GID_START;
425         } else if (appId >= AID_ROOT && appId <= AID_APP_START) {
426             return appId;
427         } else {
428             return -1;
429         }
430     }
431 
432     /**
433      * Returns the app id for a given shared app gid. Returns -1 if the ID is invalid.
434      * @hide
435      */
436     @UnsupportedAppUsage
getAppIdFromSharedAppGid(int gid)437     public static @AppIdInt int getAppIdFromSharedAppGid(int gid) {
438         final int appId = getAppId(gid) + Process.FIRST_APPLICATION_UID
439                 - Process.FIRST_SHARED_APPLICATION_GID;
440         if (appId < 0 || appId >= Process.FIRST_SHARED_APPLICATION_GID) {
441             return -1;
442         }
443         return appId;
444     }
445 
446     /** @hide */
getCacheAppGid(int uid)447     public static int getCacheAppGid(int uid) {
448         return getCacheAppGid(getUserId(uid), getAppId(uid));
449     }
450 
451     /** @hide */
getCacheAppGid(@serIdInt int userId, @AppIdInt int appId)452     public static int getCacheAppGid(@UserIdInt int userId, @AppIdInt int appId) {
453         if (appId >= AID_APP_START && appId <= AID_APP_END) {
454             return getUid(userId, (appId - AID_APP_START) + AID_CACHE_GID_START);
455         } else {
456             return -1;
457         }
458     }
459 
460     /**
461      * Generate a text representation of the uid, breaking out its individual
462      * components -- user, app, isolated, etc.
463      * @hide
464      */
formatUid(StringBuilder sb, int uid)465     public static void formatUid(StringBuilder sb, int uid) {
466         if (uid < Process.FIRST_APPLICATION_UID) {
467             sb.append(uid);
468         } else {
469             sb.append('u');
470             sb.append(getUserId(uid));
471             final int appId = getAppId(uid);
472             if (isIsolated(appId)) {
473                 if (appId > Process.FIRST_ISOLATED_UID) {
474                     sb.append('i');
475                     sb.append(appId - Process.FIRST_ISOLATED_UID);
476                 } else {
477                     sb.append("ai");
478                     sb.append(appId - Process.FIRST_APP_ZYGOTE_ISOLATED_UID);
479                 }
480             } else if (appId >= Process.FIRST_APPLICATION_UID) {
481                 sb.append('a');
482                 sb.append(appId - Process.FIRST_APPLICATION_UID);
483             } else {
484                 sb.append('s');
485                 sb.append(appId);
486             }
487         }
488     }
489 
490     /**
491      * Generate a text representation of the uid, breaking out its individual
492      * components -- user, app, isolated, etc.
493      *
494      * @param uid The uid to format
495      * @return A string representing the UID with its individual components broken out
496      * @hide
497      */
498     @SystemApi
499     @NonNull
formatUid(int uid)500     public static String formatUid(int uid) {
501         StringBuilder sb = new StringBuilder();
502         formatUid(sb, uid);
503         return sb.toString();
504     }
505 
506     /**
507      * Generate a text representation of the uid, breaking out its individual
508      * components -- user, app, isolated, etc.
509      * @hide
510      */
511     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
formatUid(PrintWriter pw, int uid)512     public static void formatUid(PrintWriter pw, int uid) {
513         if (uid < Process.FIRST_APPLICATION_UID) {
514             pw.print(uid);
515         } else {
516             pw.print('u');
517             pw.print(getUserId(uid));
518             final int appId = getAppId(uid);
519             if (isIsolated(appId)) {
520                 if (appId > Process.FIRST_ISOLATED_UID) {
521                     pw.print('i');
522                     pw.print(appId - Process.FIRST_ISOLATED_UID);
523                 } else {
524                     pw.print("ai");
525                     pw.print(appId - Process.FIRST_APP_ZYGOTE_ISOLATED_UID);
526                 }
527             } else if (appId >= Process.FIRST_APPLICATION_UID) {
528                 pw.print('a');
529                 pw.print(appId - Process.FIRST_APPLICATION_UID);
530             } else {
531                 pw.print('s');
532                 pw.print(appId);
533             }
534         }
535     }
536 
537     /** @hide */
parseUserArg(String arg)538     public static @UserIdInt int parseUserArg(String arg) {
539         int userId;
540         if ("all".equals(arg)) {
541             userId = UserHandle.USER_ALL;
542         } else if ("current".equals(arg) || "cur".equals(arg)) {
543             userId = UserHandle.USER_CURRENT;
544         } else {
545             try {
546                 userId = Integer.parseInt(arg);
547             } catch (NumberFormatException e) {
548                 throw new IllegalArgumentException("Bad user number: " + arg);
549             }
550         }
551         return userId;
552     }
553 
554     /**
555      * Returns the user id of the current process
556      * @return user id of the current process
557      * @hide
558      */
559     @SystemApi
myUserId()560     public static @UserIdInt int myUserId() {
561         return getUserId(Process.myUid());
562     }
563 
564     /**
565      * Returns true if this UserHandle refers to the owner user; false otherwise.
566      * @return true if this UserHandle refers to the owner user; false otherwise.
567      * @hide
568      * @deprecated please use {@link #isSystem()} or check for
569      * {@link android.content.pm.UserInfo#isPrimary()}
570      * {@link android.content.pm.UserInfo#isAdmin()} based on your particular use case.
571      */
572     @Deprecated
573     @SystemApi
isOwner()574     public boolean isOwner() {
575         return this.equals(OWNER);
576     }
577 
578     /**
579      * @return true if this UserHandle refers to the system user; false otherwise.
580      * @hide
581      */
582     @SystemApi
isSystem()583     public boolean isSystem() {
584         return this.equals(SYSTEM);
585     }
586 
587     /** @hide */
588     @UnsupportedAppUsage
UserHandle(@serIdInt int userId)589     public UserHandle(@UserIdInt int userId) {
590         mHandle = userId;
591     }
592 
593     /**
594      * Returns the userId stored in this UserHandle.
595      * @hide
596      */
597     @SystemApi
getIdentifier()598     public @UserIdInt int getIdentifier() {
599         return mHandle;
600     }
601 
602     @Override
toString()603     public String toString() {
604         return "UserHandle{" + mHandle + "}";
605     }
606 
607     @Override
equals(@ullable Object obj)608     public boolean equals(@Nullable Object obj) {
609         try {
610             if (obj != null) {
611                 UserHandle other = (UserHandle)obj;
612                 return mHandle == other.mHandle;
613             }
614         } catch (ClassCastException ignore) {
615         }
616         return false;
617     }
618 
619     @Override
hashCode()620     public int hashCode() {
621         return mHandle;
622     }
623 
describeContents()624     public int describeContents() {
625         return 0;
626     }
627 
writeToParcel(Parcel out, int flags)628     public void writeToParcel(Parcel out, int flags) {
629         out.writeInt(mHandle);
630     }
631 
632     /**
633      * Write a UserHandle to a Parcel, handling null pointers.  Must be
634      * read with {@link #readFromParcel(Parcel)}.
635      *
636      * @param h The UserHandle to be written.
637      * @param out The Parcel in which the UserHandle will be placed.
638      *
639      * @see #readFromParcel(Parcel)
640      */
writeToParcel(UserHandle h, Parcel out)641     public static void writeToParcel(UserHandle h, Parcel out) {
642         if (h != null) {
643             h.writeToParcel(out, 0);
644         } else {
645             out.writeInt(USER_NULL);
646         }
647     }
648 
649     /**
650      * Read a UserHandle from a Parcel that was previously written
651      * with {@link #writeToParcel(UserHandle, Parcel)}, returning either
652      * a null or new object as appropriate.
653      *
654      * @param in The Parcel from which to read the UserHandle
655      * @return Returns a new UserHandle matching the previously written
656      * object, or null if a null had been written.
657      *
658      * @see #writeToParcel(UserHandle, Parcel)
659      */
readFromParcel(Parcel in)660     public static UserHandle readFromParcel(Parcel in) {
661         int h = in.readInt();
662         return h != USER_NULL ? new UserHandle(h) : null;
663     }
664 
665     public static final @android.annotation.NonNull Parcelable.Creator<UserHandle> CREATOR
666             = new Parcelable.Creator<UserHandle>() {
667         public UserHandle createFromParcel(Parcel in) {
668             // Try to avoid allocation; use of() here. Keep this and the constructor below
669             // in sync.
670             return UserHandle.of(in.readInt());
671         }
672 
673         public UserHandle[] newArray(int size) {
674             return new UserHandle[size];
675         }
676     };
677 
678     /**
679      * Instantiate a new UserHandle from the data in a Parcel that was
680      * previously written with {@link #writeToParcel(Parcel, int)}.  Note that you
681      * must not use this with data written by
682      * {@link #writeToParcel(UserHandle, Parcel)} since it is not possible
683      * to handle a null UserHandle here.
684      *
685      * @param in The Parcel containing the previously written UserHandle,
686      * positioned at the location in the buffer where it was written.
687      */
UserHandle(Parcel in)688     public UserHandle(Parcel in) {
689         mHandle = in.readInt(); // Keep this and createFromParcel() in sync.
690     }
691 }
692