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.permissionutils;
18 
19 import static android.os.Process.myUserHandle;
20 
21 import android.content.Context;
22 import android.content.pm.PackageInfo;
23 import android.content.pm.PackageManager;
24 import android.content.pm.PackageManager.NameNotFoundException;
25 import android.content.pm.PermissionInfo;
26 import android.util.Log;
27 import java.util.ArrayList;
28 import java.util.List;
29 
30 /**
31  * A utility to dump or grant all revoked runtime permissions
32  */
33 public class GrantPermissionUtil {
34     private static final String LOG_TAG = GrantPermissionUtil.class.getSimpleName();
35 
grantAllPermissions(Context context)36     public static void grantAllPermissions (Context context) {
37         PackageManager pm = context.getPackageManager();
38         for (PackageInfo pkgInfo : getPackageInfos(context)) {
39             List<String> missingPermissions = getMissingPermissions(context, pkgInfo);
40             if (!missingPermissions.isEmpty()) {
41                 for (String permission : missingPermissions) {
42                     pm.grantRuntimePermission(pkgInfo.packageName, permission, myUserHandle());
43                 }
44             }
45         }
46     }
47 
dumpMissingPermissions(Context context)48     public static void dumpMissingPermissions (Context context) {
49         for (PackageInfo pkgInfo : getPackageInfos(context)) {
50             List<String> missingPermissions = getMissingPermissions(context, pkgInfo);
51             if (!missingPermissions.isEmpty()) {
52                 Log.e(LOG_TAG, String.format("Missing permissions for %s", pkgInfo.packageName));
53                 for (String permission : missingPermissions) {
54                     Log.e(LOG_TAG, "    " + permission);
55                 }
56             }
57         }
58     }
59 
getPackageInfos(Context context)60     private static List<PackageInfo> getPackageInfos(Context context) {
61         return context.getPackageManager().getInstalledPackages(PackageManager.GET_PERMISSIONS);
62     }
63 
getMissingPermissions(Context context, PackageInfo info)64     private static List<String> getMissingPermissions(Context context, PackageInfo info) {
65         // No requested permissions
66         if (info.requestedPermissions == null) {
67             return new ArrayList<>();
68         }
69         List<String> result = new ArrayList<>();
70         PackageManager pm = context.getPackageManager();
71         // Iterate through requested permissions for denied ones
72         for (String permission : info.requestedPermissions) {
73             PermissionInfo pi = null;
74             try {
75                 pi = pm.getPermissionInfo(permission, 0);
76             } catch (NameNotFoundException nnfe) {
77                 // ignore
78             }
79             if (pi == null) {
80                 continue;
81             }
82             if (!isRuntime(pi)) {
83                 continue;
84             }
85             int flag = pm.checkPermission(permission, info.packageName);
86             if (flag == PackageManager.PERMISSION_DENIED) {
87                 result.add(permission);
88             }
89         }
90         return result;
91     }
92 
isRuntime(PermissionInfo pi)93     private static boolean isRuntime(PermissionInfo pi) {
94         return (pi.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE)
95                 == PermissionInfo.PROTECTION_DANGEROUS;
96     }
97 }
98