Home | History | Annotate | Download | only in permission
      1 /*
      2  * Copyright (C) 2017 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.permission;
     18 
     19 import android.annotation.NonNull;
     20 import android.annotation.Nullable;
     21 import android.content.Context;
     22 import android.content.pm.PackageParser;
     23 import android.util.ArrayMap;
     24 import android.util.ArraySet;
     25 import android.util.Log;
     26 
     27 import com.android.internal.R;
     28 import com.android.internal.annotations.GuardedBy;
     29 import com.android.internal.util.XmlUtils;
     30 import com.android.server.pm.DumpState;
     31 import com.android.server.pm.PackageManagerService;
     32 
     33 import org.xmlpull.v1.XmlPullParser;
     34 import org.xmlpull.v1.XmlPullParserException;
     35 import org.xmlpull.v1.XmlSerializer;
     36 
     37 import java.io.IOException;
     38 import java.io.PrintWriter;
     39 import java.util.Collection;
     40 import java.util.Set;
     41 
     42 /**
     43  * Permissions and other related data. This class is not meant for
     44  * direct access outside of the permission package with the sole exception
     45  * of package settings. Instead, it should be reference either from the
     46  * permission manager or package settings.
     47  */
     48 public class PermissionSettings {
     49 
     50     public final boolean mPermissionReviewRequired;
     51 
     52     /**
     53      * All of the permissions known to the system. The mapping is from permission
     54      * name to permission object.
     55      */
     56     @GuardedBy("mLock")
     57     final ArrayMap<String, BasePermission> mPermissions =
     58             new ArrayMap<String, BasePermission>();
     59 
     60     /**
     61      * All permission trees known to the system. The mapping is from permission tree
     62      * name to permission object.
     63      */
     64     @GuardedBy("mLock")
     65     final ArrayMap<String, BasePermission> mPermissionTrees =
     66             new ArrayMap<String, BasePermission>();
     67 
     68     /**
     69      * All permisson groups know to the system. The mapping is from permission group
     70      * name to permission group object.
     71      */
     72     @GuardedBy("mLock")
     73     final ArrayMap<String, PackageParser.PermissionGroup> mPermissionGroups =
     74             new ArrayMap<String, PackageParser.PermissionGroup>();
     75 
     76     /**
     77      * Set of packages that request a particular app op. The mapping is from permission
     78      * name to package names.
     79      */
     80     @GuardedBy("mLock")
     81     final ArrayMap<String, ArraySet<String>> mAppOpPermissionPackages = new ArrayMap<>();
     82 
     83     private final Object mLock;
     84 
     85     PermissionSettings(@NonNull Context context, @NonNull Object lock) {
     86         mPermissionReviewRequired =
     87                 context.getResources().getBoolean(R.bool.config_permissionReviewRequired);
     88         mLock = lock;
     89     }
     90 
     91     public @Nullable BasePermission getPermission(@NonNull String permName) {
     92         synchronized (mLock) {
     93             return getPermissionLocked(permName);
     94         }
     95     }
     96 
     97     public void addAppOpPackage(String permName, String packageName) {
     98         ArraySet<String> pkgs = mAppOpPermissionPackages.get(permName);
     99         if (pkgs == null) {
    100             pkgs = new ArraySet<>();
    101             mAppOpPermissionPackages.put(permName, pkgs);
    102         }
    103         pkgs.add(packageName);
    104     }
    105 
    106     /**
    107      * Transfers ownership of permissions from one package to another.
    108      */
    109     public void transferPermissions(String origPackageName, String newPackageName) {
    110         synchronized (mLock) {
    111             for (int i=0; i<2; i++) {
    112                 ArrayMap<String, BasePermission> permissions =
    113                         i == 0 ? mPermissionTrees : mPermissions;
    114                 for (BasePermission bp : permissions.values()) {
    115                     bp.transfer(origPackageName, newPackageName);
    116                 }
    117             }
    118         }
    119     }
    120 
    121     public boolean canPropagatePermissionToInstantApp(String permName) {
    122         synchronized (mLock) {
    123             final BasePermission bp = mPermissions.get(permName);
    124             return (bp != null && (bp.isRuntime() || bp.isDevelopment()) && bp.isInstant());
    125         }
    126     }
    127 
    128     public void readPermissions(XmlPullParser parser) throws IOException, XmlPullParserException {
    129         synchronized (mLock) {
    130             readPermissions(mPermissions, parser);
    131         }
    132     }
    133 
    134     public void readPermissionTrees(XmlPullParser parser)
    135             throws IOException, XmlPullParserException {
    136         synchronized (mLock) {
    137             readPermissions(mPermissionTrees, parser);
    138         }
    139     }
    140 
    141     public void writePermissions(XmlSerializer serializer) throws IOException {
    142         synchronized (mLock) {
    143             for (BasePermission bp : mPermissions.values()) {
    144                 bp.writeLPr(serializer);
    145             }
    146         }
    147     }
    148 
    149     public void writePermissionTrees(XmlSerializer serializer) throws IOException {
    150         synchronized (mLock) {
    151             for (BasePermission bp : mPermissionTrees.values()) {
    152                 bp.writeLPr(serializer);
    153             }
    154         }
    155     }
    156 
    157     public static void readPermissions(ArrayMap<String, BasePermission> out, XmlPullParser parser)
    158             throws IOException, XmlPullParserException {
    159         int outerDepth = parser.getDepth();
    160         int type;
    161         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
    162                 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
    163             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
    164                 continue;
    165             }
    166 
    167             if (!BasePermission.readLPw(out, parser)) {
    168                 PackageManagerService.reportSettingsProblem(Log.WARN,
    169                         "Unknown element reading permissions: " + parser.getName() + " at "
    170                                 + parser.getPositionDescription());
    171             }
    172             XmlUtils.skipCurrentTag(parser);
    173         }
    174     }
    175 
    176     public void dumpPermissions(PrintWriter pw, String packageName,
    177             ArraySet<String> permissionNames, boolean externalStorageEnforced,
    178             DumpState dumpState) {
    179         synchronized (mLock) {
    180             boolean printedSomething = false;
    181             for (BasePermission bp : mPermissions.values()) {
    182                 printedSomething = bp.dumpPermissionsLPr(pw, packageName, permissionNames,
    183                         externalStorageEnforced, printedSomething, dumpState);
    184             }
    185             if (packageName == null && permissionNames == null) {
    186                 for (int iperm = 0; iperm<mAppOpPermissionPackages.size(); iperm++) {
    187                     if (iperm == 0) {
    188                         if (dumpState.onTitlePrinted())
    189                             pw.println();
    190                         pw.println("AppOp Permissions:");
    191                     }
    192                     pw.print("  AppOp Permission ");
    193                     pw.print(mAppOpPermissionPackages.keyAt(iperm));
    194                     pw.println(":");
    195                     ArraySet<String> pkgs = mAppOpPermissionPackages.valueAt(iperm);
    196                     for (int ipkg=0; ipkg<pkgs.size(); ipkg++) {
    197                         pw.print("    "); pw.println(pkgs.valueAt(ipkg));
    198                     }
    199                 }
    200             }
    201         }
    202     }
    203 
    204     @GuardedBy("mLock")
    205     @Nullable BasePermission getPermissionLocked(@NonNull String permName) {
    206         return mPermissions.get(permName);
    207     }
    208 
    209     @GuardedBy("mLock")
    210     @Nullable BasePermission getPermissionTreeLocked(@NonNull String permName) {
    211         return mPermissionTrees.get(permName);
    212     }
    213 
    214     @GuardedBy("mLock")
    215     void putPermissionLocked(@NonNull String permName, @NonNull BasePermission permission) {
    216         mPermissions.put(permName, permission);
    217     }
    218 
    219     @GuardedBy("mLock")
    220     void putPermissionTreeLocked(@NonNull String permName, @NonNull BasePermission permission) {
    221         mPermissionTrees.put(permName, permission);
    222     }
    223 
    224     @GuardedBy("mLock")
    225     void removePermissionLocked(@NonNull String permName) {
    226         mPermissions.remove(permName);
    227     }
    228 
    229     @GuardedBy("mLock")
    230     void removePermissionTreeLocked(@NonNull String permName) {
    231         mPermissionTrees.remove(permName);
    232     }
    233 
    234     @GuardedBy("mLock")
    235     @NonNull Collection<BasePermission> getAllPermissionsLocked() {
    236         return mPermissions.values();
    237     }
    238 
    239     @GuardedBy("mLock")
    240     @NonNull Collection<BasePermission> getAllPermissionTreesLocked() {
    241         return mPermissionTrees.values();
    242     }
    243 
    244     /**
    245      * Returns the permission tree for the given permission.
    246      * @throws SecurityException If the calling UID is not allowed to add permissions to the
    247      * found permission tree.
    248      */
    249     @Nullable BasePermission enforcePermissionTree(@NonNull String permName, int callingUid) {
    250         synchronized (mLock) {
    251             return BasePermission.enforcePermissionTree(
    252                     mPermissionTrees.values(), permName, callingUid);
    253         }
    254     }
    255 
    256     public boolean isPermissionInstant(String permName) {
    257         synchronized (mLock) {
    258             final BasePermission bp = mPermissions.get(permName);
    259             return (bp != null && bp.isInstant());
    260         }
    261     }
    262 
    263     boolean isPermissionAppOp(String permName) {
    264         synchronized (mLock) {
    265             final BasePermission bp = mPermissions.get(permName);
    266             return (bp != null && bp.isAppOp());
    267         }
    268     }
    269 
    270 }
    271