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