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  */
14 package com.android.settings.applications;
15 
16 import android.content.Context;
17 import android.content.pm.PackageInfo;
18 import android.content.pm.PackageManager;
19 import android.icu.text.ListFormatter;
20 import android.util.ArraySet;
21 
22 import androidx.annotation.VisibleForTesting;
23 import androidx.preference.Preference;
24 
25 import com.android.settings.R;
26 import com.android.settings.core.BasePreferenceController;
27 import com.android.settingslib.applications.PermissionsSummaryHelper;
28 
29 import java.util.List;
30 import java.util.Set;
31 import java.util.stream.Collectors;
32 
33 public class AppPermissionsPreferenceController extends BasePreferenceController {
34 
35     private static final String TAG = "AppPermissionPrefCtrl";
36     private static final int NUM_PACKAGE_TO_CHECK = 4;
37 
38     @VisibleForTesting
39     static int NUM_PERMISSIONS_TO_SHOW = 3;
40 
41     private final PackageManager mPackageManager;
42     private final Set<CharSequence> mPermissionGroups;
43 
44     private final PermissionsSummaryHelper.PermissionsResultCallback mPermissionsCallback =
45             new PermissionsSummaryHelper.PermissionsResultCallback() {
46                 @Override
47                 public void onPermissionSummaryResult(int standardGrantedPermissionCount,
48                         int requestedPermissionCount, int additionalGrantedPermissionCount,
49                         List<CharSequence> grantedGroupLabels) {
50                     updateSummary(grantedGroupLabels);
51                 }
52             };
53 
54     @VisibleForTesting
55     int mNumPackageChecked;
56 
57     private Preference mPreference;
58 
AppPermissionsPreferenceController(Context context, String preferenceKey)59     public AppPermissionsPreferenceController(Context context, String preferenceKey) {
60         super(context, preferenceKey);
61         mPackageManager = context.getPackageManager();
62         mPermissionGroups = new ArraySet<>();
63     }
64 
65     @Override
getAvailabilityStatus()66     public int getAvailabilityStatus() {
67         return AVAILABLE;
68     }
69 
70     @Override
updateState(Preference preference)71     public void updateState(Preference preference) {
72         mPreference = preference;
73         mNumPackageChecked = 0;
74         queryPermissionSummary();
75     }
76 
77     @VisibleForTesting
queryPermissionSummary()78     void queryPermissionSummary() {
79         final List<PackageInfo> installedPackages =
80                 mPackageManager.getInstalledPackages(PackageManager.GET_PERMISSIONS);
81         // Here we only get the first four apps and check their permissions.
82         final List<PackageInfo> packagesWithPermission = installedPackages.stream()
83                 .filter(pInfo -> pInfo.permissions != null)
84                 .limit(NUM_PACKAGE_TO_CHECK)
85                 .collect(Collectors.toList());
86 
87         for (PackageInfo installedPackage : packagesWithPermission) {
88             PermissionsSummaryHelper.getPermissionSummary(mContext,
89                     installedPackage.packageName, mPermissionsCallback);
90         }
91     }
92 
93     @VisibleForTesting
updateSummary(List<CharSequence> grantedGroupLabels)94     void updateSummary(List<CharSequence> grantedGroupLabels) {
95         mPermissionGroups.addAll(grantedGroupLabels);
96         mNumPackageChecked++;
97 
98         if (mNumPackageChecked < NUM_PACKAGE_TO_CHECK) {
99             return;
100         }
101 
102         final List<CharSequence> permissionsToShow = mPermissionGroups.stream()
103                 .limit(NUM_PERMISSIONS_TO_SHOW)
104                 .collect(Collectors.toList());
105         final boolean isMoreShowed = mPermissionGroups.size() > NUM_PERMISSIONS_TO_SHOW;
106         CharSequence summary;
107 
108         if (!permissionsToShow.isEmpty()) {
109             if (isMoreShowed) {
110                 summary = mContext.getString(R.string.app_permissions_summary_more,
111                         ListFormatter.getInstance().format(permissionsToShow).toLowerCase());
112             } else {
113                 summary = mContext.getString(R.string.app_permissions_summary,
114                         ListFormatter.getInstance().format(permissionsToShow).toLowerCase());
115             }
116         } else {
117             summary = mContext.getString(
118                     R.string.runtime_permissions_summary_no_permissions_granted);
119         }
120         mPreference.setSummary(summary);
121     }
122 }