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.settings.applications; 18 19 import android.content.Context; 20 import android.content.pm.ApplicationInfo; 21 import android.content.pm.PackageInfo; 22 import android.content.pm.PackageManager; 23 import android.content.pm.PackageManager.NameNotFoundException; 24 import android.content.pm.PermissionInfo; 25 import android.os.Build; 26 import android.util.ArrayMap; 27 import android.util.Log; 28 29 import java.util.ArrayList; 30 import java.util.List; 31 32 /** 33 * Based off from 34 * packages/apps/PackageInstaller/src/com/android/packageinstaller/permission/AppPermissions.java 35 * Except we only care about the number rather than the details. 36 */ 37 public final class AppPermissions { 38 private static final String TAG = "AppPermissions"; 39 40 private final ArrayMap<String, PermissionGroup> mGroups = new ArrayMap<>(); 41 private final Context mContext; 42 private final PackageInfo mPackageInfo; 43 44 public AppPermissions(Context context, String packageName) { 45 mContext = context; 46 mPackageInfo = getPackageInfo(packageName); 47 refresh(); 48 } 49 50 private PackageInfo getPackageInfo(String packageName) { 51 try { 52 return mContext.getPackageManager().getPackageInfo(packageName, 53 PackageManager.GET_PERMISSIONS); 54 } catch (NameNotFoundException e) { 55 Log.e(TAG, "Unable to find " + packageName, e); 56 return null; 57 } 58 } 59 60 public void refresh() { 61 if (mPackageInfo != null) { 62 loadPermissionGroups(); 63 } 64 } 65 66 public int getPermissionCount() { 67 return mGroups.size(); 68 } 69 70 public int getGrantedPermissionsCount() { 71 int ct = 0; 72 for (int i = 0; i < mGroups.size(); i++) { 73 if (mGroups.valueAt(i).areRuntimePermissionsGranted()) { 74 ct++; 75 } 76 } 77 return ct; 78 } 79 80 private void loadPermissionGroups() { 81 mGroups.clear(); 82 if (mPackageInfo.requestedPermissions == null) { 83 return; 84 } 85 86 final boolean appSupportsRuntimePermissions = appSupportsRuntime( 87 mPackageInfo.applicationInfo); 88 89 for (int i = 0; i < mPackageInfo.requestedPermissions.length; i++) { 90 String requestedPerm = mPackageInfo.requestedPermissions[i]; 91 92 final PermissionInfo permInfo; 93 try { 94 permInfo = mContext.getPackageManager().getPermissionInfo(requestedPerm, 0); 95 } catch (NameNotFoundException e) { 96 Log.w(TAG, "Unknown permission: " + requestedPerm); 97 continue; 98 } 99 100 String permName = permInfo.name; 101 String groupName = permInfo.group != null ? permInfo.group : permName; 102 103 PermissionGroup group = mGroups.get(groupName); 104 if (group == null) { 105 group = new PermissionGroup(); 106 mGroups.put(groupName, group); 107 } 108 109 final boolean runtime = appSupportsRuntimePermissions 110 && permInfo.protectionLevel == PermissionInfo.PROTECTION_DANGEROUS; 111 final boolean granted = (mPackageInfo.requestedPermissionsFlags[i] 112 & PackageInfo.REQUESTED_PERMISSION_GRANTED) != 0; 113 114 Permission permission = new Permission(runtime, granted); 115 group.addPermission(permission, permName); 116 } 117 // Only care about runtime perms for now. 118 for (int i = mGroups.size() - 1; i >= 0; i--) { 119 if (!mGroups.valueAt(i).mHasRuntimePermissions) { 120 mGroups.removeAt(i); 121 } 122 } 123 } 124 125 public static boolean appSupportsRuntime(ApplicationInfo info) { 126 return info.targetSdkVersion > Build.VERSION_CODES.LOLLIPOP_MR1; 127 } 128 129 private static final class PermissionGroup { 130 private final ArrayMap<String, Permission> mPermissions = new ArrayMap<>(); 131 private boolean mHasRuntimePermissions; 132 133 public boolean hasRuntimePermissions() { 134 return mHasRuntimePermissions; 135 } 136 137 public boolean areRuntimePermissionsGranted() { 138 final int permissionCount = mPermissions.size(); 139 for (int i = 0; i < permissionCount; i++) { 140 Permission permission = mPermissions.valueAt(i); 141 if (permission.runtime && !permission.granted) { 142 return false; 143 } 144 } 145 return true; 146 } 147 148 public List<Permission> getPermissions() { 149 return new ArrayList<>(mPermissions.values()); 150 } 151 152 void addPermission(Permission permission, String permName) { 153 mPermissions.put(permName, permission); 154 if (permission.runtime) { 155 mHasRuntimePermissions = true; 156 } 157 } 158 } 159 160 private static final class Permission { 161 private final boolean runtime; 162 private boolean granted; 163 164 public Permission(boolean runtime, boolean granted) { 165 this.runtime = runtime; 166 this.granted = granted; 167 } 168 } 169 } 170