Home | History | Annotate | Download | only in applications
      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