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 */
16package com.android.packageinstaller.permission.model;
17
18import android.content.BroadcastReceiver;
19import android.content.Context;
20import android.content.Intent;
21import android.content.pm.PackageInfo;
22import android.content.pm.PackageManager;
23import android.content.pm.PackageManager.NameNotFoundException;
24import android.util.ArrayMap;
25import android.util.ArraySet;
26
27import com.android.packageinstaller.permission.model.PermissionApps.PermissionApp;
28import com.android.packageinstaller.permission.utils.Utils;
29
30import java.text.Collator;
31import java.util.ArrayList;
32import java.util.Collections;
33
34public class PermissionStatusReceiver extends BroadcastReceiver {
35    @Override
36    public void onReceive(Context context, Intent intent) {
37        int[] counts = new int[3];
38        ArrayList<CharSequence> grantedGroups = new ArrayList<>();
39        boolean succeeded = false;
40
41        boolean isForPackage = intent.hasExtra(Intent.EXTRA_PACKAGE_NAME);
42
43        Intent responseIntent = new Intent(intent.getStringExtra(
44                Intent.EXTRA_GET_PERMISSIONS_RESPONSE_INTENT));
45        responseIntent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
46
47
48        if (isForPackage) {
49            String pkg = intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME);
50            succeeded = getPermissionsCount(context, pkg, counts, grantedGroups);
51        } else {
52            succeeded = getAppsWithPermissionsCount(context, counts);
53        }
54        if (succeeded) {
55            responseIntent.putExtra(Intent.EXTRA_GET_PERMISSIONS_COUNT_RESULT, counts);
56
57            if (isForPackage) {
58                responseIntent.putExtra(Intent.EXTRA_GET_PERMISSIONS_GROUP_LIST_RESULT,
59                        grantedGroups.toArray(new CharSequence[grantedGroups.size()]));
60            }
61        }
62
63        context.sendBroadcast(responseIntent);
64    }
65
66    public boolean getPermissionsCount(Context context, String pkg, int[] counts,
67            ArrayList<CharSequence> grantedGroups) {
68        try {
69            PackageInfo packageInfo =
70                    context.getPackageManager().getPackageInfo(pkg, PackageManager.GET_PERMISSIONS);
71            AppPermissions appPermissions =
72                    new AppPermissions(context, packageInfo, null, false, null);
73            int grantedCount = 0;
74            int totalCount = 0;
75            int additionalCount = 0;
76
77            for (AppPermissionGroup group : appPermissions.getPermissionGroups()) {
78                if (Utils.shouldShowPermission(group, pkg)) {
79                    totalCount++;
80                    if (group.areRuntimePermissionsGranted()) {
81                        grantedCount++;
82
83                        if (Utils.OS_PKG.equals(group.getDeclaringPackage())) {
84                            grantedGroups.add(group.getLabel());
85                        } else {
86                            additionalCount++;
87                        }
88                    }
89                }
90            }
91
92            // Sort
93            Collator coll = Collator.getInstance();
94            coll.setStrength(Collator.PRIMARY);
95            Collections.sort(grantedGroups, coll);
96
97            // Set results
98            counts[0] = grantedCount;
99            counts[1] = totalCount;
100            counts[2] = additionalCount;
101
102            return true;
103        } catch (NameNotFoundException e) {
104            return false;
105        }
106    }
107
108    public boolean getAppsWithPermissionsCount(Context context, int[] counts) {
109        ArraySet<String> launcherPkgs = Utils.getLauncherPackages(context);
110        // Indexed by uid.
111        ArrayMap<String, Boolean> grantedApps = new ArrayMap<>();
112        ArrayMap<String, Boolean> allApps = new ArrayMap<>();
113        for (String group : Utils.MODERN_PERMISSION_GROUPS) {
114            PermissionApps permissionApps = new PermissionApps(context,
115                    group, null);
116            permissionApps.loadNowWithoutUi();
117            for (PermissionApp app : permissionApps.getApps()) {
118                String key = app.getKey();
119                if (Utils.isSystem(app, launcherPkgs)) {
120                    // We default to not showing system apps, so hide them from count.
121                    continue;
122                }
123                if (app.areRuntimePermissionsGranted()) {
124                    grantedApps.put(key, true);
125                }
126                allApps.put(key, true);
127            }
128        }
129        counts[0] = grantedApps.size();
130        counts[1] = allApps.size();
131        return true;
132    }
133}
134