1 /* 2 * Copyright (C) 2006 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.IntDef; 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.content.pm.PermissionInfo; 23 import android.util.Log; 24 25 import com.android.modules.utils.TypedXmlPullParser; 26 import com.android.modules.utils.TypedXmlSerializer; 27 import com.android.server.pm.DumpState; 28 import com.android.server.pm.PackageManagerService; 29 30 import libcore.util.EmptyArray; 31 32 import java.io.IOException; 33 import java.io.PrintWriter; 34 import java.lang.annotation.Retention; 35 import java.lang.annotation.RetentionPolicy; 36 import java.util.Arrays; 37 import java.util.Map; 38 import java.util.Objects; 39 import java.util.Set; 40 41 /** 42 * Legacy permission definition. 43 */ 44 //@SystemApi(client = SystemApi.Client.SYSTEM_SERVER) 45 public final class LegacyPermission { 46 /** 47 * The permission is defined in a manifest. 48 */ 49 public static final int TYPE_MANIFEST = 0; 50 51 /** 52 * The permission is defined in a system config. 53 */ 54 public static final int TYPE_CONFIG = 1; 55 56 /** 57 * The permission is defined dynamically. 58 */ 59 public static final int TYPE_DYNAMIC = 2; 60 61 /** 62 * @hide 63 */ 64 @IntDef({ 65 TYPE_MANIFEST, 66 TYPE_CONFIG, 67 TYPE_DYNAMIC, 68 }) 69 @Retention(RetentionPolicy.SOURCE) 70 public @interface PermissionType {} 71 72 private static final String ATTR_NAME = "name"; 73 private static final String ATTR_PACKAGE = "package"; 74 private static final String TAG_ITEM = "item"; 75 76 @NonNull 77 private final PermissionInfo mPermissionInfo; 78 @PermissionType 79 private final int mType; 80 private final int mUid; 81 @NonNull 82 private final int[] mGids; 83 84 /** 85 * Create a new instance of this class. 86 * 87 * @param permissionInfo the {@link PermissionInfo} for the permission 88 * @param type the type of the permission 89 * @param uid the UID defining the permission 90 * @param gids the GIDs associated with the permission 91 */ LegacyPermission(@onNull PermissionInfo permissionInfo, @PermissionType int type, int uid, @NonNull int[] gids)92 public LegacyPermission(@NonNull PermissionInfo permissionInfo, @PermissionType int type, 93 int uid, @NonNull int[] gids) { 94 mPermissionInfo = permissionInfo; 95 mType = type; 96 mUid = uid; 97 mGids = gids; 98 } 99 LegacyPermission(@onNull String name, @NonNull String packageName, @PermissionType int type)100 private LegacyPermission(@NonNull String name, @NonNull String packageName, 101 @PermissionType int type) { 102 mPermissionInfo = new PermissionInfo(); 103 mPermissionInfo.name = name; 104 mPermissionInfo.packageName = packageName; 105 // Default to most conservative protection level. 106 mPermissionInfo.protectionLevel = PermissionInfo.PROTECTION_SIGNATURE; 107 mType = type; 108 mUid = 0; 109 mGids = EmptyArray.INT; 110 } 111 112 /** 113 * Get the {@link PermissionInfo} for this mission. 114 * 115 * @return the {@link PermissionInfo} 116 */ 117 @NonNull getPermissionInfo()118 public PermissionInfo getPermissionInfo() { 119 return mPermissionInfo; 120 } 121 122 /** 123 * Get the type of this mission. 124 * 125 * @return the type 126 */ getType()127 public int getType() { 128 return mType; 129 } 130 131 /** 132 * @hide 133 */ read(@onNull Map<String, LegacyPermission> out, @NonNull TypedXmlPullParser parser)134 public static boolean read(@NonNull Map<String, LegacyPermission> out, 135 @NonNull TypedXmlPullParser parser) { 136 final String tagName = parser.getName(); 137 if (!tagName.equals(TAG_ITEM)) { 138 return false; 139 } 140 final String name = parser.getAttributeValue(null, ATTR_NAME); 141 final String packageName = parser.getAttributeValue(null, ATTR_PACKAGE); 142 final String ptype = parser.getAttributeValue(null, "type"); 143 if (name == null || packageName == null) { 144 PackageManagerService.reportSettingsProblem(Log.WARN, 145 "Error in package manager settings: permissions has" + " no name at " 146 + parser.getPositionDescription()); 147 return false; 148 } 149 final boolean dynamic = "dynamic".equals(ptype); 150 LegacyPermission bp = out.get(name); 151 // If the permission is builtin, do not clobber it. 152 if (bp == null || bp.mType != TYPE_CONFIG) { 153 bp = new LegacyPermission(name.intern(), packageName, 154 dynamic ? TYPE_DYNAMIC : TYPE_MANIFEST); 155 } 156 bp.mPermissionInfo.protectionLevel = readInt(parser, null, "protection", 157 PermissionInfo.PROTECTION_NORMAL); 158 bp.mPermissionInfo.protectionLevel = PermissionInfo.fixProtectionLevel( 159 bp.mPermissionInfo.protectionLevel); 160 if (dynamic) { 161 bp.mPermissionInfo.icon = readInt(parser, null, "icon", 0); 162 bp.mPermissionInfo.nonLocalizedLabel = parser.getAttributeValue(null, "label"); 163 } 164 out.put(bp.mPermissionInfo.name, bp); 165 return true; 166 } 167 readInt(@onNull TypedXmlPullParser parser, @Nullable String namespace, @NonNull String name, int defaultValue)168 private static int readInt(@NonNull TypedXmlPullParser parser, @Nullable String namespace, 169 @NonNull String name, int defaultValue) { 170 return parser.getAttributeInt(namespace, name, defaultValue); 171 } 172 173 /** 174 * @hide 175 */ write(@onNull TypedXmlSerializer serializer)176 public void write(@NonNull TypedXmlSerializer serializer) throws IOException { 177 if (mPermissionInfo.packageName == null) { 178 return; 179 } 180 serializer.startTag(null, TAG_ITEM); 181 serializer.attribute(null, ATTR_NAME, mPermissionInfo.name); 182 serializer.attribute(null, ATTR_PACKAGE, mPermissionInfo.packageName); 183 if (mPermissionInfo.protectionLevel != PermissionInfo.PROTECTION_NORMAL) { 184 serializer.attributeInt(null, "protection", mPermissionInfo.protectionLevel); 185 } 186 if (mType == TYPE_DYNAMIC) { 187 serializer.attribute(null, "type", "dynamic"); 188 if (mPermissionInfo.icon != 0) { 189 serializer.attributeInt(null, "icon", mPermissionInfo.icon); 190 } 191 if (mPermissionInfo.nonLocalizedLabel != null) { 192 serializer.attribute(null, "label", mPermissionInfo.nonLocalizedLabel.toString()); 193 } 194 } 195 serializer.endTag(null, TAG_ITEM); 196 } 197 198 /** 199 * @hide 200 */ dump(@onNull PrintWriter pw, @NonNull String packageName, @NonNull Set<String> permissionNames, boolean readEnforced, boolean printedSomething, @NonNull DumpState dumpState)201 public boolean dump(@NonNull PrintWriter pw, @NonNull String packageName, 202 @NonNull Set<String> permissionNames, boolean readEnforced, boolean printedSomething, 203 @NonNull DumpState dumpState) { 204 if (packageName != null && !packageName.equals(mPermissionInfo.packageName)) { 205 return false; 206 } 207 if (permissionNames != null && !permissionNames.contains(mPermissionInfo.name)) { 208 return false; 209 } 210 if (!printedSomething) { 211 if (dumpState.onTitlePrinted()) { 212 pw.println(); 213 } 214 pw.println("Permissions:"); 215 } 216 pw.print(" Permission ["); pw.print(mPermissionInfo.name); pw.print("] ("); 217 pw.print(Integer.toHexString(System.identityHashCode(this))); 218 pw.println("):"); 219 pw.print(" sourcePackage="); pw.println(mPermissionInfo.packageName); 220 pw.print(" uid="); pw.print(mUid); 221 pw.print(" gids="); pw.print(Arrays.toString(mGids)); 222 pw.print(" type="); pw.print(mType); 223 pw.print(" prot="); 224 pw.println(PermissionInfo.protectionToString(mPermissionInfo.protectionLevel)); 225 if (mPermissionInfo != null) { 226 pw.print(" perm="); pw.println(mPermissionInfo); 227 if ((mPermissionInfo.flags & PermissionInfo.FLAG_INSTALLED) == 0 228 || (mPermissionInfo.flags & PermissionInfo.FLAG_REMOVED) != 0) { 229 pw.print(" flags=0x"); pw.println(Integer.toHexString(mPermissionInfo.flags)); 230 } 231 } 232 if (Objects.equals(mPermissionInfo.name, 233 android.Manifest.permission.READ_EXTERNAL_STORAGE)) { 234 pw.print(" enforced="); 235 pw.println(readEnforced); 236 } 237 return true; 238 } 239 } 240