Home | History | Annotate | Download | only in pm
      1 /*
      2  * Copyright (C) 2015 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 com.android.server.pm;
     18 
     19 import android.content.pm.PackageManager;
     20 import android.os.UserHandle;
     21 import android.util.ArrayMap;
     22 import android.util.ArraySet;
     23 
     24 import android.util.SparseArray;
     25 import android.util.SparseBooleanArray;
     26 import com.android.internal.util.ArrayUtils;
     27 
     28 import java.util.ArrayList;
     29 import java.util.Arrays;
     30 import java.util.Collections;
     31 import java.util.List;
     32 import java.util.Set;
     33 
     34 /**
     35  * This class encapsulates the permissions for a package or a shared user.
     36  * <p>
     37  * There are two types of permissions: install (granted at installation)
     38  * and runtime (granted at runtime). Install permissions are granted to
     39  * all device users while runtime permissions are granted explicitly to
     40  * specific users.
     41  * </p>
     42  * <p>
     43  * The permissions are kept on a per device user basis. For example, an
     44  * application may have some runtime permissions granted under the device
     45  * owner but not granted under the secondary user.
     46  * <p>
     47  * This class is also responsible for keeping track of the Linux gids per
     48  * user for a package or a shared user. The gids are computed as a set of
     49  * the gids for all granted permissions' gids on a per user basis.
     50  * </p>
     51  */
     52 public final class PermissionsState {
     53 
     54     /** The permission operation failed. */
     55     public static final int PERMISSION_OPERATION_FAILURE = -1;
     56 
     57     /** The permission operation succeeded and no gids changed. */
     58     public static final int PERMISSION_OPERATION_SUCCESS = 0;
     59 
     60     /** The permission operation succeeded and gids changed. */
     61     public static final int PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED = 1;
     62 
     63     private static final int[] NO_GIDS = {};
     64 
     65     private ArrayMap<String, PermissionData> mPermissions;
     66 
     67     private int[] mGlobalGids = NO_GIDS;
     68 
     69     private SparseBooleanArray mPermissionReviewRequired;
     70 
     71     public PermissionsState() {
     72         /* do nothing */
     73     }
     74 
     75     public PermissionsState(PermissionsState prototype) {
     76         copyFrom(prototype);
     77     }
     78 
     79     /**
     80      * Sets the global gids, applicable to all users.
     81      *
     82      * @param globalGids The global gids.
     83      */
     84     public void setGlobalGids(int[] globalGids) {
     85         if (!ArrayUtils.isEmpty(globalGids)) {
     86             mGlobalGids = Arrays.copyOf(globalGids, globalGids.length);
     87         }
     88     }
     89 
     90     /**
     91      * Initialized this instance from another one.
     92      *
     93      * @param other The other instance.
     94      */
     95     public void copyFrom(PermissionsState other) {
     96         if (other == this) {
     97             return;
     98         }
     99         if (mPermissions != null) {
    100             if (other.mPermissions == null) {
    101                 mPermissions = null;
    102             } else {
    103                 mPermissions.clear();
    104             }
    105         }
    106         if (other.mPermissions != null) {
    107             if (mPermissions == null) {
    108                 mPermissions = new ArrayMap<>();
    109             }
    110             final int permissionCount = other.mPermissions.size();
    111             for (int i = 0; i < permissionCount; i++) {
    112                 String name = other.mPermissions.keyAt(i);
    113                 PermissionData permissionData = other.mPermissions.valueAt(i);
    114                 mPermissions.put(name, new PermissionData(permissionData));
    115             }
    116         }
    117 
    118         mGlobalGids = NO_GIDS;
    119         if (other.mGlobalGids != NO_GIDS) {
    120             mGlobalGids = Arrays.copyOf(other.mGlobalGids,
    121                     other.mGlobalGids.length);
    122         }
    123 
    124         if (mPermissionReviewRequired != null) {
    125             if (other.mPermissionReviewRequired == null) {
    126                 mPermissionReviewRequired = null;
    127             } else {
    128                 mPermissionReviewRequired.clear();
    129             }
    130         }
    131         if (other.mPermissionReviewRequired != null) {
    132             if (mPermissionReviewRequired == null) {
    133                 mPermissionReviewRequired = new SparseBooleanArray();
    134             }
    135             final int userCount = other.mPermissionReviewRequired.size();
    136             for (int i = 0; i < userCount; i++) {
    137                 final boolean reviewRequired = other.mPermissionReviewRequired.valueAt(i);
    138                 mPermissionReviewRequired.put(i, reviewRequired);
    139             }
    140         }
    141     }
    142 
    143     public boolean isPermissionReviewRequired(int userId) {
    144         return mPermissionReviewRequired != null && mPermissionReviewRequired.get(userId);
    145     }
    146 
    147     /**
    148      * Grant an install permission.
    149      *
    150      * @param permission The permission to grant.
    151      * @return The operation result which is either {@link #PERMISSION_OPERATION_SUCCESS},
    152      *     or {@link #PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED}, or {@link
    153      *     #PERMISSION_OPERATION_FAILURE}.
    154      */
    155     public int grantInstallPermission(BasePermission permission) {
    156         return grantPermission(permission, UserHandle.USER_ALL);
    157     }
    158 
    159     /**
    160      * Revoke an install permission.
    161      *
    162      * @param permission The permission to revoke.
    163      * @return The operation result which is either {@link #PERMISSION_OPERATION_SUCCESS},
    164      *     or {@link #PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED}, or {@link
    165      *     #PERMISSION_OPERATION_FAILURE}.
    166      */
    167     public int revokeInstallPermission(BasePermission permission) {
    168         return revokePermission(permission, UserHandle.USER_ALL);
    169     }
    170 
    171     /**
    172      * Grant a runtime permission for a given device user.
    173      *
    174      * @param permission The permission to grant.
    175      * @param userId The device user id.
    176      * @return The operation result which is either {@link #PERMISSION_OPERATION_SUCCESS},
    177      *     or {@link #PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED}, or {@link
    178      *     #PERMISSION_OPERATION_FAILURE}.
    179      */
    180     public int grantRuntimePermission(BasePermission permission, int userId) {
    181         enforceValidUserId(userId);
    182         if (userId == UserHandle.USER_ALL) {
    183             return PERMISSION_OPERATION_FAILURE;
    184         }
    185         return grantPermission(permission, userId);
    186     }
    187 
    188     /**
    189      *  Revoke a runtime permission for a given device user.
    190      *
    191      * @param permission The permission to revoke.
    192      * @param userId The device user id.
    193      * @return The operation result which is either {@link #PERMISSION_OPERATION_SUCCESS},
    194      *     or {@link #PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED}, or {@link
    195      *     #PERMISSION_OPERATION_FAILURE}.
    196      */
    197     public int revokeRuntimePermission(BasePermission permission, int userId) {
    198         enforceValidUserId(userId);
    199         if (userId == UserHandle.USER_ALL) {
    200             return PERMISSION_OPERATION_FAILURE;
    201         }
    202         return revokePermission(permission, userId);
    203     }
    204 
    205     /**
    206      * Gets whether this state has a given runtime permission for a
    207      * given device user id.
    208      *
    209      * @param name The permission name.
    210      * @param userId The device user id.
    211      * @return Whether this state has the permission.
    212      */
    213     public boolean hasRuntimePermission(String name, int userId) {
    214         enforceValidUserId(userId);
    215         return !hasInstallPermission(name) && hasPermission(name, userId);
    216     }
    217 
    218     /**
    219      * Gets whether this state has a given install permission.
    220      *
    221      * @param name The permission name.
    222      * @return Whether this state has the permission.
    223      */
    224     public boolean hasInstallPermission(String name) {
    225         return hasPermission(name, UserHandle.USER_ALL);
    226     }
    227 
    228     /**
    229      * Gets whether the state has a given permission for the specified
    230      * user, regardless if this is an install or a runtime permission.
    231      *
    232      * @param name The permission name.
    233      * @param userId The device user id.
    234      * @return Whether the user has the permission.
    235      */
    236     public boolean hasPermission(String name, int userId) {
    237         enforceValidUserId(userId);
    238 
    239         if (mPermissions == null) {
    240             return false;
    241         }
    242 
    243         PermissionData permissionData = mPermissions.get(name);
    244         return permissionData != null && permissionData.isGranted(userId);
    245     }
    246 
    247     /**
    248      * Returns whether the state has any known request for the given permission name,
    249      * whether or not it has been granted.
    250      */
    251     public boolean hasRequestedPermission(ArraySet<String> names) {
    252         if (mPermissions == null) {
    253             return false;
    254         }
    255         for (int i=names.size()-1; i>=0; i--) {
    256             if (mPermissions.get(names.valueAt(i)) != null) {
    257                 return true;
    258             }
    259         }
    260         return false;
    261     }
    262 
    263     /**
    264      * Gets all permissions for a given device user id regardless if they
    265      * are install time or runtime permissions.
    266      *
    267      * @param userId The device user id.
    268      * @return The permissions or an empty set.
    269      */
    270     public Set<String> getPermissions(int userId) {
    271         enforceValidUserId(userId);
    272 
    273         if (mPermissions == null) {
    274             return Collections.emptySet();
    275         }
    276 
    277         Set<String> permissions = new ArraySet<>(mPermissions.size());
    278 
    279         final int permissionCount = mPermissions.size();
    280         for (int i = 0; i < permissionCount; i++) {
    281             String permission = mPermissions.keyAt(i);
    282 
    283             if (hasInstallPermission(permission)) {
    284                 permissions.add(permission);
    285                 continue;
    286             }
    287 
    288             if (userId != UserHandle.USER_ALL) {
    289                 if (hasRuntimePermission(permission, userId)) {
    290                     permissions.add(permission);
    291                 }
    292             }
    293         }
    294 
    295         return permissions;
    296     }
    297 
    298     /**
    299      * Gets the state for an install permission or null if no such.
    300      *
    301      * @param name The permission name.
    302      * @return The permission state.
    303      */
    304     public PermissionState getInstallPermissionState(String name) {
    305         return getPermissionState(name, UserHandle.USER_ALL);
    306     }
    307 
    308     /**
    309      * Gets the state for a runtime permission or null if no such.
    310      *
    311      * @param name The permission name.
    312      * @param userId The device user id.
    313      * @return The permission state.
    314      */
    315     public PermissionState getRuntimePermissionState(String name, int userId) {
    316         enforceValidUserId(userId);
    317         return getPermissionState(name, userId);
    318     }
    319 
    320     /**
    321      * Gets all install permission states.
    322      *
    323      * @return The permission states or an empty set.
    324      */
    325     public List<PermissionState> getInstallPermissionStates() {
    326         return getPermissionStatesInternal(UserHandle.USER_ALL);
    327     }
    328 
    329     /**
    330      * Gets all runtime permission states.
    331      *
    332      * @return The permission states or an empty set.
    333      */
    334     public List<PermissionState> getRuntimePermissionStates(int userId) {
    335         enforceValidUserId(userId);
    336         return getPermissionStatesInternal(userId);
    337     }
    338 
    339     /**
    340      * Gets the flags for a permission regardless if it is install or
    341      * runtime permission.
    342      *
    343      * @param name The permission name.
    344      * @return The permission state or null if no such.
    345      */
    346     public int getPermissionFlags(String name, int userId) {
    347         PermissionState installPermState = getInstallPermissionState(name);
    348         if (installPermState != null) {
    349             return installPermState.getFlags();
    350         }
    351         PermissionState runtimePermState = getRuntimePermissionState(name, userId);
    352         if (runtimePermState != null) {
    353             return runtimePermState.getFlags();
    354         }
    355         return 0;
    356     }
    357 
    358     /**
    359      * Update the flags associated with a given permission.
    360      * @param permission The permission whose flags to update.
    361      * @param userId The user for which to update.
    362      * @param flagMask Mask for which flags to change.
    363      * @param flagValues New values for the mask flags.
    364      * @return Whether the permission flags changed.
    365      */
    366     public boolean updatePermissionFlags(BasePermission permission, int userId,
    367             int flagMask, int flagValues) {
    368         enforceValidUserId(userId);
    369 
    370         final boolean mayChangeFlags = flagValues != 0 || flagMask != 0;
    371 
    372         if (mPermissions == null) {
    373             if (!mayChangeFlags) {
    374                 return false;
    375             }
    376             ensurePermissionData(permission);
    377         }
    378 
    379         PermissionData permissionData = mPermissions.get(permission.name);
    380         if (permissionData == null) {
    381             if (!mayChangeFlags) {
    382                 return false;
    383             }
    384             permissionData = ensurePermissionData(permission);
    385         }
    386 
    387         final int oldFlags = permissionData.getFlags(userId);
    388 
    389         final boolean updated = permissionData.updateFlags(userId, flagMask, flagValues);
    390         if (updated) {
    391             final int newFlags = permissionData.getFlags(userId);
    392             if ((oldFlags & PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED) == 0
    393                     && (newFlags & PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED) != 0) {
    394                 if (mPermissionReviewRequired == null) {
    395                     mPermissionReviewRequired = new SparseBooleanArray();
    396                 }
    397                 mPermissionReviewRequired.put(userId, true);
    398             } else if ((oldFlags & PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED) != 0
    399                     && (newFlags & PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED) == 0) {
    400                 if (mPermissionReviewRequired != null) {
    401                     mPermissionReviewRequired.delete(userId);
    402                     if (mPermissionReviewRequired.size() <= 0) {
    403                         mPermissionReviewRequired = null;
    404                     }
    405                 }
    406             }
    407         }
    408         return updated;
    409     }
    410 
    411     public boolean updatePermissionFlagsForAllPermissions(
    412             int userId, int flagMask, int flagValues) {
    413         enforceValidUserId(userId);
    414 
    415         if (mPermissions == null) {
    416             return false;
    417         }
    418         boolean changed = false;
    419         final int permissionCount = mPermissions.size();
    420         for (int i = 0; i < permissionCount; i++) {
    421             PermissionData permissionData = mPermissions.valueAt(i);
    422             changed |= permissionData.updateFlags(userId, flagMask, flagValues);
    423         }
    424         return changed;
    425     }
    426 
    427     /**
    428      * Compute the Linux gids for a given device user from the permissions
    429      * granted to this user. Note that these are computed to avoid additional
    430      * state as they are rarely accessed.
    431      *
    432      * @param userId The device user id.
    433      * @return The gids for the device user.
    434      */
    435     public int[] computeGids(int userId) {
    436         enforceValidUserId(userId);
    437 
    438         int[] gids = mGlobalGids;
    439 
    440         if (mPermissions != null) {
    441             final int permissionCount = mPermissions.size();
    442             for (int i = 0; i < permissionCount; i++) {
    443                 String permission = mPermissions.keyAt(i);
    444                 if (!hasPermission(permission, userId)) {
    445                     continue;
    446                 }
    447                 PermissionData permissionData = mPermissions.valueAt(i);
    448                 final int[] permGids = permissionData.computeGids(userId);
    449                 if (permGids != NO_GIDS) {
    450                     gids = appendInts(gids, permGids);
    451                 }
    452             }
    453         }
    454 
    455         return gids;
    456     }
    457 
    458     /**
    459      * Compute the Linux gids for all device users from the permissions
    460      * granted to these users.
    461      *
    462      * @return The gids for all device users.
    463      */
    464     public int[] computeGids(int[] userIds) {
    465         int[] gids = mGlobalGids;
    466 
    467         for (int userId : userIds) {
    468             final int[] userGids = computeGids(userId);
    469             gids = appendInts(gids, userGids);
    470         }
    471 
    472         return gids;
    473     }
    474 
    475     /**
    476      * Resets the internal state of this object.
    477      */
    478     public void reset() {
    479         mGlobalGids = NO_GIDS;
    480         mPermissions = null;
    481         mPermissionReviewRequired = null;
    482     }
    483 
    484     private PermissionState getPermissionState(String name, int userId) {
    485         if (mPermissions == null) {
    486             return null;
    487         }
    488         PermissionData permissionData = mPermissions.get(name);
    489         if (permissionData == null) {
    490             return null;
    491         }
    492         return permissionData.getPermissionState(userId);
    493     }
    494 
    495     private List<PermissionState> getPermissionStatesInternal(int userId) {
    496         enforceValidUserId(userId);
    497 
    498         if (mPermissions == null) {
    499             return Collections.emptyList();
    500         }
    501 
    502         List<PermissionState> permissionStates = new ArrayList<>();
    503 
    504         final int permissionCount = mPermissions.size();
    505         for (int i = 0; i < permissionCount; i++) {
    506             PermissionData permissionData = mPermissions.valueAt(i);
    507 
    508             PermissionState permissionState = permissionData.getPermissionState(userId);
    509             if (permissionState != null) {
    510                 permissionStates.add(permissionState);
    511             }
    512         }
    513 
    514         return permissionStates;
    515     }
    516 
    517     private int grantPermission(BasePermission permission, int userId) {
    518         if (hasPermission(permission.name, userId)) {
    519             return PERMISSION_OPERATION_FAILURE;
    520         }
    521 
    522         final boolean hasGids = !ArrayUtils.isEmpty(permission.computeGids(userId));
    523         final int[] oldGids = hasGids ? computeGids(userId) : NO_GIDS;
    524 
    525         PermissionData permissionData = ensurePermissionData(permission);
    526 
    527         if (!permissionData.grant(userId)) {
    528             return PERMISSION_OPERATION_FAILURE;
    529         }
    530 
    531         if (hasGids) {
    532             final int[] newGids = computeGids(userId);
    533             if (oldGids.length != newGids.length) {
    534                 return PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED;
    535             }
    536         }
    537 
    538         return PERMISSION_OPERATION_SUCCESS;
    539     }
    540 
    541     private int revokePermission(BasePermission permission, int userId) {
    542         if (!hasPermission(permission.name, userId)) {
    543             return PERMISSION_OPERATION_FAILURE;
    544         }
    545 
    546         final boolean hasGids = !ArrayUtils.isEmpty(permission.computeGids(userId));
    547         final int[] oldGids = hasGids ? computeGids(userId) : NO_GIDS;
    548 
    549         PermissionData permissionData = mPermissions.get(permission.name);
    550 
    551         if (!permissionData.revoke(userId)) {
    552             return PERMISSION_OPERATION_FAILURE;
    553         }
    554 
    555         if (permissionData.isDefault()) {
    556             ensureNoPermissionData(permission.name);
    557         }
    558 
    559         if (hasGids) {
    560             final int[] newGids = computeGids(userId);
    561             if (oldGids.length != newGids.length) {
    562                 return PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED;
    563             }
    564         }
    565 
    566         return PERMISSION_OPERATION_SUCCESS;
    567     }
    568 
    569     private static int[] appendInts(int[] current, int[] added) {
    570         if (current != null && added != null) {
    571             for (int guid : added) {
    572                 current = ArrayUtils.appendInt(current, guid);
    573             }
    574         }
    575         return current;
    576     }
    577 
    578     private static void enforceValidUserId(int userId) {
    579         if (userId != UserHandle.USER_ALL && userId < 0) {
    580             throw new IllegalArgumentException("Invalid userId:" + userId);
    581         }
    582     }
    583 
    584     private PermissionData ensurePermissionData(BasePermission permission) {
    585         if (mPermissions == null) {
    586             mPermissions = new ArrayMap<>();
    587         }
    588         PermissionData permissionData = mPermissions.get(permission.name);
    589         if (permissionData == null) {
    590             permissionData = new PermissionData(permission);
    591             mPermissions.put(permission.name, permissionData);
    592         }
    593         return permissionData;
    594     }
    595 
    596     private void ensureNoPermissionData(String name) {
    597         if (mPermissions == null) {
    598             return;
    599         }
    600         mPermissions.remove(name);
    601         if (mPermissions.isEmpty()) {
    602             mPermissions = null;
    603         }
    604     }
    605 
    606     private static final class PermissionData {
    607         private final BasePermission mPerm;
    608         private SparseArray<PermissionState> mUserStates = new SparseArray<>();
    609 
    610         public PermissionData(BasePermission perm) {
    611             mPerm = perm;
    612         }
    613 
    614         public PermissionData(PermissionData other) {
    615             this(other.mPerm);
    616             final int otherStateCount = other.mUserStates.size();
    617             for (int i = 0; i < otherStateCount; i++) {
    618                 final int otherUserId = other.mUserStates.keyAt(i);
    619                 PermissionState otherState = other.mUserStates.valueAt(i);
    620                 mUserStates.put(otherUserId, new PermissionState(otherState));
    621             }
    622         }
    623 
    624         public int[] computeGids(int userId) {
    625             return mPerm.computeGids(userId);
    626         }
    627 
    628         public boolean isGranted(int userId) {
    629             if (isInstallPermission()) {
    630                 userId = UserHandle.USER_ALL;
    631             }
    632 
    633             PermissionState userState = mUserStates.get(userId);
    634             if (userState == null) {
    635                 return false;
    636             }
    637 
    638             return userState.mGranted;
    639         }
    640 
    641         public boolean grant(int userId) {
    642             if (!isCompatibleUserId(userId)) {
    643                 return false;
    644             }
    645 
    646             if (isGranted(userId)) {
    647                 return false;
    648             }
    649 
    650             PermissionState userState = mUserStates.get(userId);
    651             if (userState == null) {
    652                 userState = new PermissionState(mPerm.name);
    653                 mUserStates.put(userId, userState);
    654             }
    655 
    656             userState.mGranted = true;
    657 
    658             return true;
    659         }
    660 
    661         public boolean revoke(int userId) {
    662             if (!isCompatibleUserId(userId)) {
    663                 return false;
    664             }
    665 
    666             if (!isGranted(userId)) {
    667                 return false;
    668             }
    669 
    670             PermissionState userState = mUserStates.get(userId);
    671             userState.mGranted = false;
    672 
    673             if (userState.isDefault()) {
    674                 mUserStates.remove(userId);
    675             }
    676 
    677             return true;
    678         }
    679 
    680         public PermissionState getPermissionState(int userId) {
    681             return mUserStates.get(userId);
    682         }
    683 
    684         public int getFlags(int userId) {
    685             PermissionState userState = mUserStates.get(userId);
    686             if (userState != null) {
    687                 return userState.mFlags;
    688             }
    689             return 0;
    690         }
    691 
    692         public boolean isDefault() {
    693             return mUserStates.size() <= 0;
    694         }
    695 
    696         public static boolean isInstallPermissionKey(int userId) {
    697             return userId == UserHandle.USER_ALL;
    698         }
    699 
    700         public boolean updateFlags(int userId, int flagMask, int flagValues) {
    701             if (isInstallPermission()) {
    702                 userId = UserHandle.USER_ALL;
    703             }
    704 
    705             if (!isCompatibleUserId(userId)) {
    706                 return false;
    707             }
    708 
    709             final int newFlags = flagValues & flagMask;
    710 
    711             PermissionState userState = mUserStates.get(userId);
    712             if (userState != null) {
    713                 final int oldFlags = userState.mFlags;
    714                 userState.mFlags = (userState.mFlags & ~flagMask) | newFlags;
    715                 if (userState.isDefault()) {
    716                     mUserStates.remove(userId);
    717                 }
    718                 return userState.mFlags != oldFlags;
    719             } else if (newFlags != 0) {
    720                 userState = new PermissionState(mPerm.name);
    721                 userState.mFlags = newFlags;
    722                 mUserStates.put(userId, userState);
    723                 return true;
    724             }
    725 
    726             return false;
    727         }
    728 
    729         private boolean isCompatibleUserId(int userId) {
    730             return isDefault() || !(isInstallPermission() ^ isInstallPermissionKey(userId));
    731         }
    732 
    733         private boolean isInstallPermission() {
    734             return mUserStates.size() == 1
    735                     && mUserStates.get(UserHandle.USER_ALL) != null;
    736         }
    737     }
    738 
    739     public static final class PermissionState {
    740         private final String mName;
    741         private boolean mGranted;
    742         private int mFlags;
    743 
    744         public PermissionState(String name) {
    745             mName = name;
    746         }
    747 
    748         public PermissionState(PermissionState other) {
    749             mName = other.mName;
    750             mGranted = other.mGranted;
    751             mFlags = other.mFlags;
    752         }
    753 
    754         public boolean isDefault() {
    755             return !mGranted && mFlags == 0;
    756         }
    757 
    758         public String getName() {
    759             return mName;
    760         }
    761 
    762         public boolean isGranted() {
    763             return mGranted;
    764         }
    765 
    766         public int getFlags() {
    767             return mFlags;
    768         }
    769     }
    770 }
    771