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