1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
5  * except in compliance with the License. You may obtain a copy of the License at
6  *
7  *      http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software distributed under the
10  * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
11  * KIND, either express or implied. See the License for the specific language governing
12  * permissions and limitations under the License.
13  */
14 package com.android.car.developeroptions.applications;
15 
16 import android.content.Context;
17 import android.content.pm.PackageInfo;
18 import android.content.pm.PackageManager;
19 import android.content.pm.PackageManager.NameNotFoundException;
20 import android.content.pm.PermissionGroupInfo;
21 import android.content.pm.PermissionInfo;
22 import android.icu.text.ListFormatter;
23 import android.util.ArraySet;
24 import android.util.Log;
25 
26 import com.android.car.developeroptions.R;
27 import com.android.car.developeroptions.core.BasePreferenceController;
28 
29 import java.util.ArrayList;
30 import java.util.List;
31 import java.util.Set;
32 
33 public class AppPermissionsPreferenceController extends BasePreferenceController {
34 
35     private static final String TAG = "AppPermissionPrefCtrl";
36     private static final String[] PERMISSION_GROUPS = new String[]{
37             "android.permission-group.LOCATION",
38             "android.permission-group.MICROPHONE",
39             "android.permission-group.CAMERA",
40             "android.permission-group.SMS",
41             "android.permission-group.CONTACTS",
42             "android.permission-group.PHONE"};
43 
44     private static final int NUM_PERMISSION_TO_USE = 3;
45 
46     private final PackageManager mPackageManager;
47 
AppPermissionsPreferenceController(Context context, String preferenceKey)48     public AppPermissionsPreferenceController(Context context, String preferenceKey) {
49         super(context, preferenceKey);
50         mPackageManager = context.getPackageManager();
51     }
52 
53     @Override
getAvailabilityStatus()54     public int getAvailabilityStatus() {
55         return AVAILABLE;
56     }
57 
58     /*
59        Summary text looks like: Apps using Permission1, Permission2, Permission3
60        The 3 permissions are the first three from the list which any app has granted:
61        Location, Microphone, Camera, Sms, Contacts, and Phone
62      */
63     @Override
getSummary()64     public CharSequence getSummary() {
65         final Set<String> permissions = getAllPermissionsInGroups();
66         Set<String> grantedPermissionGroups = getGrantedPermissionGroups(permissions);
67         int count = 0;
68         final List<String> summaries = new ArrayList<>();
69 
70         for (String group : PERMISSION_GROUPS) {
71             if (!grantedPermissionGroups.contains(group)) {
72                 continue;
73             }
74             summaries.add(getPermissionGroupLabel(group).toString().toLowerCase());
75             if (++count >= NUM_PERMISSION_TO_USE) {
76                 break;
77             }
78         }
79         return count > 0 ? mContext.getString(R.string.app_permissions_summary,
80                 ListFormatter.getInstance().format(summaries)) : null;
81     }
82 
getGrantedPermissionGroups(Set<String> permissions)83     private Set<String> getGrantedPermissionGroups(Set<String> permissions) {
84         ArraySet<String> grantedPermissionGroups = new ArraySet<>();
85         List<PackageInfo> installedPackages =
86                 mPackageManager.getInstalledPackages(PackageManager.GET_PERMISSIONS);
87         for (PackageInfo installedPackage : installedPackages) {
88             if (installedPackage.permissions == null) {
89                 continue;
90             }
91             for (PermissionInfo permissionInfo : installedPackage.permissions) {
92                 if (permissions.contains(permissionInfo.name)
93                         && !grantedPermissionGroups.contains(permissionInfo.group)) {
94                     grantedPermissionGroups.add(permissionInfo.group);
95                 }
96             }
97         }
98         return grantedPermissionGroups;
99     }
100 
getPermissionGroupLabel(String group)101     private CharSequence getPermissionGroupLabel(String group) {
102         try {
103             final PermissionGroupInfo groupInfo = mPackageManager.getPermissionGroupInfo(group, 0);
104             return groupInfo.loadLabel(mPackageManager);
105         } catch (NameNotFoundException e) {
106             Log.e(TAG, "Error getting permissions label.", e);
107         }
108         return group;
109     }
110 
getAllPermissionsInGroups()111     private Set<String> getAllPermissionsInGroups() {
112         ArraySet<String> result = new ArraySet<>();
113         for (String group : PERMISSION_GROUPS) {
114             try {
115                 final List<PermissionInfo> permissions =
116                         mPackageManager.queryPermissionsByGroup(group, 0);
117                 for (PermissionInfo permissionInfo : permissions) {
118                     result.add(permissionInfo.name);
119                 }
120             } catch (NameNotFoundException e) {
121                 Log.e(TAG, "Error getting permissions in group " + group, e);
122             }
123         }
124         return result;
125     }
126 }
127