Home | History | Annotate | Download | only in os
      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      */
     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      */
    110     public static boolean isSameApp(int uid1, int uid2) {
    111         return getAppId(uid1) == getAppId(uid2);
    112     }
    113 
    114     /** @hide */
    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 */
    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      */
    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      */
    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 */
    156     public static @UserIdInt int getCallingUserId() {
    157         return getUserId(Binder.getCallingUid());
    158     }
    159 
    160     /** @hide */
    161     @SystemApi
    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      */
    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
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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 */
    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
    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
    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
    333     public boolean isSystem() {
    334         return this.equals(SYSTEM);
    335     }
    336 
    337     /** @hide */
    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
    348     public @UserIdInt int getIdentifier() {
    349         return mHandle;
    350     }
    351 
    352     @Override
    353     public String toString() {
    354         return "UserHandle{" + mHandle + "}";
    355     }
    356 
    357     @Override
    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
    370     public int hashCode() {
    371         return mHandle;
    372     }
    373 
    374     public int describeContents() {
    375         return 0;
    376     }
    377 
    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      */
    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      */
    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      */
    436     public UserHandle(Parcel in) {
    437         mHandle = in.readInt();
    438     }
    439 }
    440