AppPermissionsPreferenceController.java revision 906572b127e57aac01bfe1a45ddcc7f053883f47
1/*
2 * Copyright (C) 2017 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 */
14package com.android.settings.applications;
15
16import android.content.Context;
17import android.content.pm.PackageInfo;
18import android.content.pm.PackageManager;
19import android.content.pm.PackageManager.NameNotFoundException;
20import android.content.pm.PermissionGroupInfo;
21import android.content.pm.PermissionInfo;
22import android.support.v7.preference.Preference;
23import android.text.TextUtils;
24import android.util.ArraySet;
25import android.util.Log;
26import com.android.settings.R;
27import com.android.settings.core.PreferenceControllerMixin;
28import com.android.settingslib.core.AbstractPreferenceController;
29
30import java.util.List;
31import java.util.Set;
32
33public class AppPermissionsPreferenceController extends AbstractPreferenceController
34        implements PreferenceControllerMixin {
35
36    private static final String TAG = "AppPermissionPrefCtrl";
37    private static final String KEY_APP_PERMISSION_GROUPS = "manage_perms";
38    private static final String[] PERMISSION_GROUPS = new String[] {
39        "android.permission-group.LOCATION",
40        "android.permission-group.MICROPHONE",
41        "android.permission-group.CAMERA",
42        "android.permission-group.SMS",
43        "android.permission-group.CONTACTS",
44        "android.permission-group.PHONE"};
45
46    private static final int NUM_PERMISSION_TO_USE = 3;
47
48    private final PackageManager mPackageManager;
49
50    public AppPermissionsPreferenceController(Context context) {
51        super(context);
52        mPackageManager = context.getPackageManager();
53    }
54
55    @Override
56    public boolean isAvailable() {
57        return true;
58    }
59
60    @Override
61    public String getPreferenceKey() {
62        return KEY_APP_PERMISSION_GROUPS;
63    }
64
65    @Override
66    public void updateState(Preference preference) {
67        final CharSequence summary = getSummary();
68        if (summary != null) {
69            preference.setSummary(summary);
70        }
71    }
72
73    /*
74       Summary text looks like: Apps using Permission1, Permission2, Permission3
75       The 3 permissions are the first three from the list which any app has granted:
76       Location, Microphone, Camera, Sms, Contacts, and Phone
77     */
78    @Override
79    public CharSequence getSummary() {
80        final Set<String> permissions = getAllPermissionsInGroups();
81        Set<String> grantedPermissionGroups = getGrantedPermissionGroups(permissions);
82        CharSequence summary = null;
83        int count = 0;
84        for (String group : PERMISSION_GROUPS) {
85            if (!grantedPermissionGroups.contains(group)) {
86                continue;
87            }
88            summary = concatSummaryText(summary, group);
89            if (++count >= NUM_PERMISSION_TO_USE) {
90                break;
91            }
92        }
93        return count > 0 ? mContext.getString(R.string.app_permissions_summary, summary) : null;
94    }
95
96    private Set<String> getGrantedPermissionGroups(Set<String> permissions) {
97        ArraySet<String> grantedPermissionGroups = new ArraySet<>();
98        List<PackageInfo> installedPackages =
99            mPackageManager.getInstalledPackages(PackageManager.GET_PERMISSIONS);
100        for (PackageInfo installedPackage : installedPackages) {
101            if (installedPackage.permissions == null) {
102                continue;
103            }
104            for (PermissionInfo permissionInfo : installedPackage.permissions) {
105                if (permissions.contains(permissionInfo.name)
106                        && !grantedPermissionGroups.contains(permissionInfo.group)) {
107                    grantedPermissionGroups.add(permissionInfo.group);
108                }
109            }
110        }
111        return grantedPermissionGroups;
112    }
113
114    private CharSequence concatSummaryText(CharSequence currentSummary, String permission) {
115        final String label = getPermissionGroupLabel(permission).toString().toLowerCase();
116        if (TextUtils.isEmpty(currentSummary)) {
117            return label;
118        }
119        return mContext.getString(R.string.join_many_items_middle, currentSummary, label);
120    }
121
122    private CharSequence getPermissionGroupLabel(String group) {
123        try {
124            final PermissionGroupInfo groupInfo = mPackageManager.getPermissionGroupInfo(group, 0);
125            return groupInfo.loadLabel(mPackageManager);
126        } catch (NameNotFoundException e) {
127            Log.e(TAG, "Error getting permissions label.", e);
128        }
129        return group;
130    }
131
132    private Set<String> getAllPermissionsInGroups() {
133        ArraySet<String> result = new ArraySet<>();
134        for (String group : PERMISSION_GROUPS) {
135            try {
136                final List<PermissionInfo> permissions =
137                    mPackageManager.queryPermissionsByGroup(group, 0);
138                for (PermissionInfo permissionInfo : permissions) {
139                    result.add(permissionInfo.name);
140                }
141            } catch (NameNotFoundException e) {
142                Log.e(TAG, "Error getting permissions in group "+group, e);
143            }
144        }
145        return result;
146    }
147}
148