1 /*
2  * Copyright (C) 2020 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.permissioncontroller.role.model;
18 
19 import android.app.AppOpsManager;
20 import android.content.Context;
21 import android.content.pm.PackageInfo;
22 import android.content.pm.PackageManager;
23 
24 import androidx.annotation.NonNull;
25 
26 import com.android.modules.utils.build.SdkLevel;
27 import com.android.permissioncontroller.permission.utils.ArrayUtils;
28 import com.android.permissioncontroller.role.utils.PackageUtils;
29 
30 /**
31  * App op permissions to be granted or revoke by a {@link Role}.
32  */
33 public class AppOpPermissions {
34 
AppOpPermissions()35     private AppOpPermissions() {}
36 
37     /**
38      * Grant the app op of an app op permission to an application.
39      *
40      * @param packageName the package name of the application
41      * @param appOpPermission the name of the app op permission
42      * @param context the {@code Context} to retrieve system services
43      *
44      * @return whether any app op mode has changed
45      */
grant(@onNull String packageName, @NonNull String appOpPermission, @NonNull Context context)46     public static boolean grant(@NonNull String packageName, @NonNull String appOpPermission,
47             @NonNull Context context) {
48         PackageInfo packageInfo = PackageUtils.getPackageInfo(packageName,
49                 PackageManager.GET_PERMISSIONS, context);
50         if (packageInfo == null) {
51             return false;
52         }
53         if (!ArrayUtils.contains(packageInfo.requestedPermissions, appOpPermission)) {
54             return false;
55         }
56         String appOp = AppOpsManager.permissionToOp(appOpPermission);
57         return setAppOpMode(packageName, appOp, AppOpsManager.MODE_ALLOWED, context);
58     }
59 
60     /**
61      * Revoke the app op of an app op permission from an application.
62      *
63      * @param packageName the package name of the application
64      * @param appOpPermission the name of the app op permission
65      * @param context the {@code Context} to retrieve system services
66      *
67      * @return whether any app op mode has changed
68      */
revoke(@onNull String packageName, @NonNull String appOpPermission, @NonNull Context context)69     public static boolean revoke(@NonNull String packageName, @NonNull String appOpPermission,
70             @NonNull Context context) {
71         String appOp = AppOpsManager.permissionToOp(appOpPermission);
72         int defaultMode = Permissions.getDefaultAppOpMode(appOp);
73         return setAppOpMode(packageName, appOp, defaultMode, context);
74     }
75 
setAppOpMode(@onNull String packageName, @NonNull String appOp, int mode, @NonNull Context context)76     private static boolean setAppOpMode(@NonNull String packageName, @NonNull String appOp,
77             int mode, @NonNull Context context) {
78         switch (appOp) {
79             case AppOpsManager.OPSTR_ACCESS_NOTIFICATIONS:
80             case AppOpsManager.OPSTR_SYSTEM_ALERT_WINDOW:
81             case AppOpsManager.OPSTR_WRITE_SETTINGS:
82             case AppOpsManager.OPSTR_REQUEST_INSTALL_PACKAGES:
83             case AppOpsManager.OPSTR_START_FOREGROUND:
84             // This isn't an API but we are deprecating it soon anyway.
85             //case AppOpsManager.OPSTR_SMS_FINANCIAL_TRANSACTIONS:
86             case AppOpsManager.OPSTR_MANAGE_IPSEC_TUNNELS:
87             case AppOpsManager.OPSTR_INSTANT_APP_START_FOREGROUND:
88             case AppOpsManager.OPSTR_LOADER_USAGE_STATS:
89                 return Permissions.setAppOpPackageMode(packageName, appOp, mode, context);
90             case AppOpsManager.OPSTR_INTERACT_ACROSS_PROFILES:
91                 // We fixed OP_INTERACT_ACROSS_PROFILES to use UID mode on S.
92                 if (SdkLevel.isAtLeastS()) {
93                     return Permissions.setAppOpUidMode(packageName, appOp, mode, context);
94                 } else {
95                     return Permissions.setAppOpPackageMode(packageName, appOp, mode, context);
96                 }
97             default:
98                 return Permissions.setAppOpUidMode(packageName, appOp, mode, context);
99         }
100     }
101 }
102