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     // NOTE: keep logic in sync with system/core/libcutils/multiuser.c
     31 
     32     /**
     33      * @hide Range of uids allocated for a user.
     34      */
     35     public static final int PER_USER_RANGE = 100000;
     36 
     37     /** @hide A user id to indicate all users on the device */
     38     public static final @UserIdInt int USER_ALL = -1;
     39 
     40     /** @hide A user handle to indicate all users on the device */
     41     public static final UserHandle ALL = new UserHandle(USER_ALL);
     42 
     43     /** @hide A user id to indicate the currently active user */
     44     public static final @UserIdInt int USER_CURRENT = -2;
     45 
     46     /** @hide A user handle to indicate the current user of the device */
     47     public static final UserHandle CURRENT = new UserHandle(USER_CURRENT);
     48 
     49     /** @hide A user id to indicate that we would like to send to the current
     50      *  user, but if this is calling from a user process then we will send it
     51      *  to the caller's user instead of failing with a security exception */
     52     public static final @UserIdInt int USER_CURRENT_OR_SELF = -3;
     53 
     54     /** @hide A user handle to indicate that we would like to send to the current
     55      *  user, but if this is calling from a user process then we will send it
     56      *  to the caller's user instead of failing with a security exception */
     57     public static final UserHandle CURRENT_OR_SELF = new UserHandle(USER_CURRENT_OR_SELF);
     58 
     59     /** @hide An undefined user id */
     60     public static final @UserIdInt int USER_NULL = -10000;
     61 
     62     /**
     63      * @hide A user id constant to indicate the "owner" user of the device
     64      * @deprecated Consider using either {@link UserHandle#USER_SYSTEM} constant or
     65      * check the target user's flag {@link android.content.pm.UserInfo#isAdmin}.
     66      */
     67     @Deprecated
     68     public static final @UserIdInt int USER_OWNER = 0;
     69 
     70     /**
     71      * @hide A user handle to indicate the primary/owner user of the device
     72      * @deprecated Consider using either {@link UserHandle#SYSTEM} constant or
     73      * check the target user's flag {@link android.content.pm.UserInfo#isAdmin}.
     74      */
     75     @Deprecated
     76     public static final UserHandle OWNER = new UserHandle(USER_OWNER);
     77 
     78     /** @hide A user id constant to indicate the "system" user of the device */
     79     public static final @UserIdInt int USER_SYSTEM = 0;
     80 
     81     /** @hide A user serial constant to indicate the "system" user of the device */
     82     public static final int USER_SERIAL_SYSTEM = 0;
     83 
     84     /** @hide A user handle to indicate the "system" user of the device */
     85     @TestApi
     86     public static final UserHandle SYSTEM = new UserHandle(USER_SYSTEM);
     87 
     88     /**
     89      * @hide Enable multi-user related side effects. Set this to false if
     90      * there are problems with single user use-cases.
     91      */
     92     public static final boolean MU_ENABLED = true;
     93 
     94     /** @hide */
     95     public static final int ERR_GID = -1;
     96     /** @hide */
     97     public static final int AID_ROOT = android.os.Process.ROOT_UID;
     98     /** @hide */
     99     public static final int AID_APP_START = android.os.Process.FIRST_APPLICATION_UID;
    100     /** @hide */
    101     public static final int AID_APP_END = android.os.Process.LAST_APPLICATION_UID;
    102     /** @hide */
    103     public static final int AID_SHARED_GID_START = android.os.Process.FIRST_SHARED_APPLICATION_GID;
    104     /** @hide */
    105     public static final int AID_CACHE_GID_START = android.os.Process.FIRST_APPLICATION_CACHE_GID;
    106 
    107     final int mHandle;
    108 
    109     /**
    110      * Checks to see if the user id is the same for the two uids, i.e., they belong to the same
    111      * user.
    112      * @hide
    113      */
    114     public static boolean isSameUser(int uid1, int uid2) {
    115         return getUserId(uid1) == getUserId(uid2);
    116     }
    117 
    118     /**
    119      * Checks to see if both uids are referring to the same app id, ignoring the user id part of the
    120      * uids.
    121      * @param uid1 uid to compare
    122      * @param uid2 other uid to compare
    123      * @return whether the appId is the same for both uids
    124      * @hide
    125      */
    126     public static boolean isSameApp(int uid1, int uid2) {
    127         return getAppId(uid1) == getAppId(uid2);
    128     }
    129 
    130     /**
    131      * Whether a UID is an "isolated" UID.
    132      * @hide
    133      */
    134     public static boolean isIsolated(int uid) {
    135         if (uid > 0) {
    136             final int appId = getAppId(uid);
    137             return appId >= Process.FIRST_ISOLATED_UID && appId <= Process.LAST_ISOLATED_UID;
    138         } else {
    139             return false;
    140         }
    141     }
    142 
    143     /**
    144      * Whether a UID belongs to a regular app. *Note* "Not a regular app" does not mean
    145      * "it's system", because of isolated UIDs. Use {@link #isCore} for that.
    146      * @hide
    147      */
    148     public static boolean isApp(int uid) {
    149         if (uid > 0) {
    150             final int appId = getAppId(uid);
    151             return appId >= Process.FIRST_APPLICATION_UID && appId <= Process.LAST_APPLICATION_UID;
    152         } else {
    153             return false;
    154         }
    155     }
    156 
    157     /**
    158      * Whether a UID belongs to a system core component or not.
    159      * @hide
    160      */
    161     public static boolean isCore(int uid) {
    162         if (uid >= 0) {
    163             final int appId = getAppId(uid);
    164             return appId < Process.FIRST_APPLICATION_UID;
    165         } else {
    166             return false;
    167         }
    168     }
    169 
    170     /**
    171      * Returns the user for a given uid.
    172      * @param uid A uid for an application running in a particular user.
    173      * @return A {@link UserHandle} for that user.
    174      */
    175     public static UserHandle getUserHandleForUid(int uid) {
    176         return of(getUserId(uid));
    177     }
    178 
    179     /**
    180      * Returns the user id for a given uid.
    181      * @hide
    182      */
    183     public static @UserIdInt int getUserId(int uid) {
    184         if (MU_ENABLED) {
    185             return uid / PER_USER_RANGE;
    186         } else {
    187             return UserHandle.USER_SYSTEM;
    188         }
    189     }
    190 
    191     /** @hide */
    192     public static @UserIdInt int getCallingUserId() {
    193         return getUserId(Binder.getCallingUid());
    194     }
    195 
    196     /** @hide */
    197     public static @AppIdInt int getCallingAppId() {
    198         return getAppId(Binder.getCallingUid());
    199     }
    200 
    201     /** @hide */
    202     @SystemApi
    203     public static UserHandle of(@UserIdInt int userId) {
    204         return userId == USER_SYSTEM ? SYSTEM : new UserHandle(userId);
    205     }
    206 
    207     /**
    208      * Returns the uid that is composed from the userId and the appId.
    209      * @hide
    210      */
    211     public static int getUid(@UserIdInt int userId, @AppIdInt int appId) {
    212         if (MU_ENABLED) {
    213             return userId * PER_USER_RANGE + (appId % PER_USER_RANGE);
    214         } else {
    215             return appId;
    216         }
    217     }
    218 
    219     /**
    220      * Returns the app id (or base uid) for a given uid, stripping out the user id from it.
    221      * @hide
    222      */
    223     @TestApi
    224     public static @AppIdInt int getAppId(int uid) {
    225         return uid % PER_USER_RANGE;
    226     }
    227 
    228     /**
    229      * Returns the gid shared between all apps with this userId.
    230      * @hide
    231      */
    232     public static int getUserGid(@UserIdInt int userId) {
    233         return getUid(userId, Process.SHARED_USER_GID);
    234     }
    235 
    236     /** @hide */
    237     public static int getSharedAppGid(int uid) {
    238         return getSharedAppGid(getUserId(uid), getAppId(uid));
    239     }
    240 
    241     /** @hide */
    242     public static int getSharedAppGid(int userId, int appId) {
    243         if (appId >= AID_APP_START && appId <= AID_APP_END) {
    244             return (appId - AID_APP_START) + AID_SHARED_GID_START;
    245         } else if (appId >= AID_ROOT && appId <= AID_APP_START) {
    246             return appId;
    247         } else {
    248             return -1;
    249         }
    250     }
    251 
    252     /**
    253      * Returns the app id for a given shared app gid. Returns -1 if the ID is invalid.
    254      * @hide
    255      */
    256     public static @AppIdInt int getAppIdFromSharedAppGid(int gid) {
    257         final int appId = getAppId(gid) + Process.FIRST_APPLICATION_UID
    258                 - Process.FIRST_SHARED_APPLICATION_GID;
    259         if (appId < 0 || appId >= Process.FIRST_SHARED_APPLICATION_GID) {
    260             return -1;
    261         }
    262         return appId;
    263     }
    264 
    265     /** @hide */
    266     public static int getCacheAppGid(int uid) {
    267         return getCacheAppGid(getUserId(uid), getAppId(uid));
    268     }
    269 
    270     /** @hide */
    271     public static int getCacheAppGid(int userId, int appId) {
    272         if (appId >= AID_APP_START && appId <= AID_APP_END) {
    273             return getUid(userId, (appId - AID_APP_START) + AID_CACHE_GID_START);
    274         } else {
    275             return -1;
    276         }
    277     }
    278 
    279     /**
    280      * Generate a text representation of the uid, breaking out its individual
    281      * components -- user, app, isolated, etc.
    282      * @hide
    283      */
    284     public static void formatUid(StringBuilder sb, int uid) {
    285         if (uid < Process.FIRST_APPLICATION_UID) {
    286             sb.append(uid);
    287         } else {
    288             sb.append('u');
    289             sb.append(getUserId(uid));
    290             final int appId = getAppId(uid);
    291             if (appId >= Process.FIRST_ISOLATED_UID && appId <= Process.LAST_ISOLATED_UID) {
    292                 sb.append('i');
    293                 sb.append(appId - Process.FIRST_ISOLATED_UID);
    294             } else if (appId >= Process.FIRST_APPLICATION_UID) {
    295                 sb.append('a');
    296                 sb.append(appId - Process.FIRST_APPLICATION_UID);
    297             } else {
    298                 sb.append('s');
    299                 sb.append(appId);
    300             }
    301         }
    302     }
    303 
    304     /**
    305      * Generate a text representation of the uid, breaking out its individual
    306      * components -- user, app, isolated, etc.
    307      * @hide
    308      */
    309     public static String formatUid(int uid) {
    310         StringBuilder sb = new StringBuilder();
    311         formatUid(sb, uid);
    312         return sb.toString();
    313     }
    314 
    315     /**
    316      * Generate a text representation of the uid, breaking out its individual
    317      * components -- user, app, isolated, etc.
    318      * @hide
    319      */
    320     public static void formatUid(PrintWriter pw, int uid) {
    321         if (uid < Process.FIRST_APPLICATION_UID) {
    322             pw.print(uid);
    323         } else {
    324             pw.print('u');
    325             pw.print(getUserId(uid));
    326             final int appId = getAppId(uid);
    327             if (appId >= Process.FIRST_ISOLATED_UID && appId <= Process.LAST_ISOLATED_UID) {
    328                 pw.print('i');
    329                 pw.print(appId - Process.FIRST_ISOLATED_UID);
    330             } else if (appId >= Process.FIRST_APPLICATION_UID) {
    331                 pw.print('a');
    332                 pw.print(appId - Process.FIRST_APPLICATION_UID);
    333             } else {
    334                 pw.print('s');
    335                 pw.print(appId);
    336             }
    337         }
    338     }
    339 
    340     /** @hide */
    341     public static @UserIdInt int parseUserArg(String arg) {
    342         int userId;
    343         if ("all".equals(arg)) {
    344             userId = UserHandle.USER_ALL;
    345         } else if ("current".equals(arg) || "cur".equals(arg)) {
    346             userId = UserHandle.USER_CURRENT;
    347         } else {
    348             try {
    349                 userId = Integer.parseInt(arg);
    350             } catch (NumberFormatException e) {
    351                 throw new IllegalArgumentException("Bad user number: " + arg);
    352             }
    353         }
    354         return userId;
    355     }
    356 
    357     /**
    358      * Returns the user id of the current process
    359      * @return user id of the current process
    360      * @hide
    361      */
    362     @SystemApi
    363     public static @UserIdInt int myUserId() {
    364         return getUserId(Process.myUid());
    365     }
    366 
    367     /**
    368      * Returns true if this UserHandle refers to the owner user; false otherwise.
    369      * @return true if this UserHandle refers to the owner user; false otherwise.
    370      * @hide
    371      * @deprecated please use {@link #isSystem()} or check for
    372      * {@link android.content.pm.UserInfo#isPrimary()}
    373      * {@link android.content.pm.UserInfo#isAdmin()} based on your particular use case.
    374      */
    375     @Deprecated
    376     @SystemApi
    377     public boolean isOwner() {
    378         return this.equals(OWNER);
    379     }
    380 
    381     /**
    382      * @return true if this UserHandle refers to the system user; false otherwise.
    383      * @hide
    384      */
    385     @SystemApi
    386     public boolean isSystem() {
    387         return this.equals(SYSTEM);
    388     }
    389 
    390     /** @hide */
    391     public UserHandle(int h) {
    392         mHandle = h;
    393     }
    394 
    395     /**
    396      * Returns the userId stored in this UserHandle.
    397      * @hide
    398      */
    399     @SystemApi
    400     @TestApi
    401     public @UserIdInt int getIdentifier() {
    402         return mHandle;
    403     }
    404 
    405     @Override
    406     public String toString() {
    407         return "UserHandle{" + mHandle + "}";
    408     }
    409 
    410     @Override
    411     public boolean equals(Object obj) {
    412         try {
    413             if (obj != null) {
    414                 UserHandle other = (UserHandle)obj;
    415                 return mHandle == other.mHandle;
    416             }
    417         } catch (ClassCastException e) {
    418         }
    419         return false;
    420     }
    421 
    422     @Override
    423     public int hashCode() {
    424         return mHandle;
    425     }
    426 
    427     public int describeContents() {
    428         return 0;
    429     }
    430 
    431     public void writeToParcel(Parcel out, int flags) {
    432         out.writeInt(mHandle);
    433     }
    434 
    435     /**
    436      * Write a UserHandle to a Parcel, handling null pointers.  Must be
    437      * read with {@link #readFromParcel(Parcel)}.
    438      *
    439      * @param h The UserHandle to be written.
    440      * @param out The Parcel in which the UserHandle will be placed.
    441      *
    442      * @see #readFromParcel(Parcel)
    443      */
    444     public static void writeToParcel(UserHandle h, Parcel out) {
    445         if (h != null) {
    446             h.writeToParcel(out, 0);
    447         } else {
    448             out.writeInt(USER_NULL);
    449         }
    450     }
    451 
    452     /**
    453      * Read a UserHandle from a Parcel that was previously written
    454      * with {@link #writeToParcel(UserHandle, Parcel)}, returning either
    455      * a null or new object as appropriate.
    456      *
    457      * @param in The Parcel from which to read the UserHandle
    458      * @return Returns a new UserHandle matching the previously written
    459      * object, or null if a null had been written.
    460      *
    461      * @see #writeToParcel(UserHandle, Parcel)
    462      */
    463     public static UserHandle readFromParcel(Parcel in) {
    464         int h = in.readInt();
    465         return h != USER_NULL ? new UserHandle(h) : null;
    466     }
    467 
    468     public static final Parcelable.Creator<UserHandle> CREATOR
    469             = new Parcelable.Creator<UserHandle>() {
    470         public UserHandle createFromParcel(Parcel in) {
    471             return new UserHandle(in);
    472         }
    473 
    474         public UserHandle[] newArray(int size) {
    475             return new UserHandle[size];
    476         }
    477     };
    478 
    479     /**
    480      * Instantiate a new UserHandle from the data in a Parcel that was
    481      * previously written with {@link #writeToParcel(Parcel, int)}.  Note that you
    482      * must not use this with data written by
    483      * {@link #writeToParcel(UserHandle, Parcel)} since it is not possible
    484      * to handle a null UserHandle here.
    485      *
    486      * @param in The Parcel containing the previously written UserHandle,
    487      * positioned at the location in the buffer where it was written.
    488      */
    489     public UserHandle(Parcel in) {
    490         mHandle = in.readInt();
    491     }
    492 }
    493