193568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk/* 293568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk * Copyright (C) 2015 The Android Open Source Project 393568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk * 493568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk * Licensed under the Apache License, Version 2.0 (the "License"); 593568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk * you may not use this file except in compliance with the License. 693568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk * You may obtain a copy of the License at 793568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk * 893568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk * http://www.apache.org/licenses/LICENSE-2.0 993568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk * 1093568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk * Unless required by applicable law or agreed to in writing, software 1193568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk * distributed under the License is distributed on an "AS IS" BASIS, 1293568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1393568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk * See the License for the specific language governing permissions and 1493568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk * limitations under the License. 1593568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk */ 1693568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monkpackage com.android.packageinstaller.permission.model; 1793568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk 1893568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monkimport android.content.BroadcastReceiver; 1993568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monkimport android.content.Context; 2093568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monkimport android.content.Intent; 2193568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monkimport android.content.pm.PackageInfo; 2293568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monkimport android.content.pm.PackageManager; 2393568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monkimport android.content.pm.PackageManager.NameNotFoundException; 247445ca7255d491bbc41f7532af758f96f55e0602Svet Ganovimport android.util.ArrayMap; 259f0442cdfc055cc3aed19770f48f516b052f6e60Jason Monkimport android.util.ArraySet; 2693568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk 2793568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monkimport com.android.packageinstaller.permission.model.PermissionApps.PermissionApp; 2893568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monkimport com.android.packageinstaller.permission.utils.Utils; 2993568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk 30bf3e576881748a1420fabc9c7ecc55cbadcc8136Makoto Onukiimport java.text.Collator; 31bf3e576881748a1420fabc9c7ecc55cbadcc8136Makoto Onukiimport java.util.ArrayList; 32bf3e576881748a1420fabc9c7ecc55cbadcc8136Makoto Onukiimport java.util.Collections; 3393568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk 34bf3e576881748a1420fabc9c7ecc55cbadcc8136Makoto Onukipublic class PermissionStatusReceiver extends BroadcastReceiver { 3593568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk @Override 3693568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk public void onReceive(Context context, Intent intent) { 37bf3e576881748a1420fabc9c7ecc55cbadcc8136Makoto Onuki int[] counts = new int[3]; 38bf3e576881748a1420fabc9c7ecc55cbadcc8136Makoto Onuki ArrayList<CharSequence> grantedGroups = new ArrayList<>(); 3993568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk boolean succeeded = false; 40bf3e576881748a1420fabc9c7ecc55cbadcc8136Makoto Onuki 41bf3e576881748a1420fabc9c7ecc55cbadcc8136Makoto Onuki boolean isForPackage = intent.hasExtra(Intent.EXTRA_PACKAGE_NAME); 42bf3e576881748a1420fabc9c7ecc55cbadcc8136Makoto Onuki 4393568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk Intent responseIntent = new Intent(intent.getStringExtra( 4493568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk Intent.EXTRA_GET_PERMISSIONS_RESPONSE_INTENT)); 4593568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk responseIntent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND); 46bf3e576881748a1420fabc9c7ecc55cbadcc8136Makoto Onuki 47bf3e576881748a1420fabc9c7ecc55cbadcc8136Makoto Onuki 48bf3e576881748a1420fabc9c7ecc55cbadcc8136Makoto Onuki if (isForPackage) { 4993568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk String pkg = intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME); 50bf3e576881748a1420fabc9c7ecc55cbadcc8136Makoto Onuki succeeded = getPermissionsCount(context, pkg, counts, grantedGroups); 5193568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk } else { 52bf3e576881748a1420fabc9c7ecc55cbadcc8136Makoto Onuki succeeded = getAppsWithPermissionsCount(context, counts); 5393568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk } 54bf3e576881748a1420fabc9c7ecc55cbadcc8136Makoto Onuki if (succeeded) { 55bf3e576881748a1420fabc9c7ecc55cbadcc8136Makoto Onuki responseIntent.putExtra(Intent.EXTRA_GET_PERMISSIONS_COUNT_RESULT, counts); 56bf3e576881748a1420fabc9c7ecc55cbadcc8136Makoto Onuki 57bf3e576881748a1420fabc9c7ecc55cbadcc8136Makoto Onuki if (isForPackage) { 58bf3e576881748a1420fabc9c7ecc55cbadcc8136Makoto Onuki responseIntent.putExtra(Intent.EXTRA_GET_PERMISSIONS_GROUP_LIST_RESULT, 59bf3e576881748a1420fabc9c7ecc55cbadcc8136Makoto Onuki grantedGroups.toArray(new CharSequence[grantedGroups.size()])); 60bf3e576881748a1420fabc9c7ecc55cbadcc8136Makoto Onuki } 61bf3e576881748a1420fabc9c7ecc55cbadcc8136Makoto Onuki } 62bf3e576881748a1420fabc9c7ecc55cbadcc8136Makoto Onuki 6393568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk context.sendBroadcast(responseIntent); 6493568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk } 6593568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk 66bf3e576881748a1420fabc9c7ecc55cbadcc8136Makoto Onuki public boolean getPermissionsCount(Context context, String pkg, int[] counts, 67bf3e576881748a1420fabc9c7ecc55cbadcc8136Makoto Onuki ArrayList<CharSequence> grantedGroups) { 6893568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk try { 6993568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk PackageInfo packageInfo = 7093568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk context.getPackageManager().getPackageInfo(pkg, PackageManager.GET_PERMISSIONS); 7193568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk AppPermissions appPermissions = 7248f67a93bfec31dc8bf0f89290056e5f36434fa2Svetoslav new AppPermissions(context, packageInfo, null, false, null); 7393568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk int grantedCount = 0; 7493568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk int totalCount = 0; 75bf3e576881748a1420fabc9c7ecc55cbadcc8136Makoto Onuki int additionalCount = 0; 76bf3e576881748a1420fabc9c7ecc55cbadcc8136Makoto Onuki 7793568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk for (AppPermissionGroup group : appPermissions.getPermissionGroups()) { 78c83c08a579316c432c6d0c009aba0fdc3b6cdb12Svetoslav if (Utils.shouldShowPermission(group, pkg)) { 7993568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk totalCount++; 8095560c737ad280d1582c4e0bd66dc76a89b6cdc0Ian Pedowitz if (group.areRuntimePermissionsGranted()) { 8193568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk grantedCount++; 82bf3e576881748a1420fabc9c7ecc55cbadcc8136Makoto Onuki 83bf3e576881748a1420fabc9c7ecc55cbadcc8136Makoto Onuki if (Utils.OS_PKG.equals(group.getDeclaringPackage())) { 84bf3e576881748a1420fabc9c7ecc55cbadcc8136Makoto Onuki grantedGroups.add(group.getLabel()); 85bf3e576881748a1420fabc9c7ecc55cbadcc8136Makoto Onuki } else { 86bf3e576881748a1420fabc9c7ecc55cbadcc8136Makoto Onuki additionalCount++; 87bf3e576881748a1420fabc9c7ecc55cbadcc8136Makoto Onuki } 8893568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk } 8993568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk } 9093568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk } 91bf3e576881748a1420fabc9c7ecc55cbadcc8136Makoto Onuki 92bf3e576881748a1420fabc9c7ecc55cbadcc8136Makoto Onuki // Sort 93bf3e576881748a1420fabc9c7ecc55cbadcc8136Makoto Onuki Collator coll = Collator.getInstance(); 94bf3e576881748a1420fabc9c7ecc55cbadcc8136Makoto Onuki coll.setStrength(Collator.PRIMARY); 95bf3e576881748a1420fabc9c7ecc55cbadcc8136Makoto Onuki Collections.sort(grantedGroups, coll); 96bf3e576881748a1420fabc9c7ecc55cbadcc8136Makoto Onuki 97bf3e576881748a1420fabc9c7ecc55cbadcc8136Makoto Onuki // Set results 9893568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk counts[0] = grantedCount; 9993568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk counts[1] = totalCount; 100bf3e576881748a1420fabc9c7ecc55cbadcc8136Makoto Onuki counts[2] = additionalCount; 101bf3e576881748a1420fabc9c7ecc55cbadcc8136Makoto Onuki 10293568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk return true; 10393568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk } catch (NameNotFoundException e) { 10493568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk return false; 10593568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk } 10693568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk } 10793568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk 10893568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk public boolean getAppsWithPermissionsCount(Context context, int[] counts) { 1099f0442cdfc055cc3aed19770f48f516b052f6e60Jason Monk ArraySet<String> launcherPkgs = Utils.getLauncherPackages(context); 11093568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk // Indexed by uid. 1117445ca7255d491bbc41f7532af758f96f55e0602Svet Ganov ArrayMap<String, Boolean> grantedApps = new ArrayMap<>(); 1127445ca7255d491bbc41f7532af758f96f55e0602Svet Ganov ArrayMap<String, Boolean> allApps = new ArrayMap<>(); 11393568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk for (String group : Utils.MODERN_PERMISSION_GROUPS) { 11493568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk PermissionApps permissionApps = new PermissionApps(context, 11593568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk group, null); 11693568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk permissionApps.loadNowWithoutUi(); 11793568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk for (PermissionApp app : permissionApps.getApps()) { 1187445ca7255d491bbc41f7532af758f96f55e0602Svet Ganov String key = app.getKey(); 1199f0442cdfc055cc3aed19770f48f516b052f6e60Jason Monk if (Utils.isSystem(app, launcherPkgs)) { 120ae2ceca3c7ac2c3420541f552a2dc47f261ec199Jason Monk // We default to not showing system apps, so hide them from count. 121ae2ceca3c7ac2c3420541f552a2dc47f261ec199Jason Monk continue; 122ae2ceca3c7ac2c3420541f552a2dc47f261ec199Jason Monk } 12393568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk if (app.areRuntimePermissionsGranted()) { 1247445ca7255d491bbc41f7532af758f96f55e0602Svet Ganov grantedApps.put(key, true); 12593568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk } 1267445ca7255d491bbc41f7532af758f96f55e0602Svet Ganov allApps.put(key, true); 12793568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk } 12893568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk } 12993568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk counts[0] = grantedApps.size(); 13093568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk counts[1] = allApps.size(); 13193568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk return true; 13293568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk } 13393568c580d730911a6e2734e79fbe6dc27c1bca1Jason Monk} 134