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