1 /*
2  * Copyright (C) 2021 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  */
16 
17 package com.android.car.settingslib.applications;
18 
19 import android.app.admin.DevicePolicyManager;
20 import android.content.Context;
21 import android.content.pm.ApplicationInfo;
22 import android.content.pm.IPackageManager;
23 import android.content.pm.PackageManager;
24 import android.os.Build;
25 import android.os.RemoteException;
26 import android.os.UserHandle;
27 
28 /**
29  * Counts installed apps across all users that have been granted one or more specific permissions by
30  * the admin.
31  */
32 // TODO(b/208511815): copied from Settings "as-is"; ideally should be move to SettingsLib, but if
33 // not, we should copy the unit tests as well.
34 public abstract class AppWithAdminGrantedPermissionsCounter extends AppCounter {
35 
36     private final String[] mPermissions;
37     private final IPackageManager mPackageManagerService;
38     private final DevicePolicyManager mDevicePolicyManager;
39 
AppWithAdminGrantedPermissionsCounter(Context context, String[] permissions, PackageManager packageManager, IPackageManager packageManagerService, DevicePolicyManager devicePolicyManager)40     public AppWithAdminGrantedPermissionsCounter(Context context, String[] permissions,
41             PackageManager packageManager, IPackageManager packageManagerService,
42             DevicePolicyManager devicePolicyManager) {
43         super(context, packageManager);
44         mPermissions = permissions;
45         mPackageManagerService = packageManagerService;
46         mDevicePolicyManager = devicePolicyManager;
47     }
48 
49     @Override
includeInCount(ApplicationInfo info)50     protected boolean includeInCount(ApplicationInfo info) {
51         return includeInCount(mPermissions, mDevicePolicyManager, mPm, mPackageManagerService,
52                 info);
53     }
54 
55     /**
56      * TODO(b/208511815): add javadoc if it's not moved to SettingsLib.
57      */
includeInCount(String[] permissions, DevicePolicyManager devicePolicyManager, PackageManager packageManager, IPackageManager packageManagerService, ApplicationInfo info)58     public static boolean includeInCount(String[] permissions,
59             DevicePolicyManager devicePolicyManager, PackageManager packageManager,
60             IPackageManager packageManagerService, ApplicationInfo info) {
61         if (info.targetSdkVersion >= Build.VERSION_CODES.M) {
62             // The app uses run-time permissions. Check whether one or more of the permissions were
63             // granted by enterprise policy.
64             for (final String permission : permissions) {
65                 if (devicePolicyManager.getPermissionGrantState(null /* admin */, info.packageName,
66                         permission) == DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED) {
67                     return true;
68                 }
69             }
70             return false;
71         }
72 
73         // The app uses install-time permissions. Check whether the app requested one or more of the
74         // permissions and was installed by enterprise policy, implicitly granting permissions.
75         if (packageManager.getInstallReason(info.packageName,
76                 new UserHandle(UserHandle.getUserId(info.uid)))
77                 != PackageManager.INSTALL_REASON_POLICY) {
78             return false;
79         }
80         try {
81             for (final String permission : permissions) {
82                 if (packageManagerService.checkUidPermission(permission, info.uid)
83                         == PackageManager.PERMISSION_GRANTED) {
84                     return true;
85                 }
86             }
87         } catch (RemoteException exception) {
88         }
89         return false;
90     }
91 }
92