• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 import android.os.Build;
24 
25 import androidx.annotation.NonNull;
26 
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 overrideNonDefaultMode whether to override the app opp mode if it isn't in the default
43      *        mode
44      * @param context the {@code Context} to retrieve system services
45      *
46      * @return whether any app op mode has changed
47      */
grant(@onNull String packageName, @NonNull String appOpPermission, boolean overrideNonDefaultMode, @NonNull Context context)48     public static boolean grant(@NonNull String packageName, @NonNull String appOpPermission,
49             boolean overrideNonDefaultMode, @NonNull Context context) {
50         PackageInfo packageInfo = PackageUtils.getPackageInfo(packageName,
51                 PackageManager.GET_PERMISSIONS, context);
52         if (packageInfo == null) {
53             return false;
54         }
55         if (!ArrayUtils.contains(packageInfo.requestedPermissions, appOpPermission)) {
56             return false;
57         }
58         String appOp = AppOpsManager.permissionToOp(appOpPermission);
59         if (!overrideNonDefaultMode) {
60             Integer currentMode = Permissions.getAppOpMode(packageName, appOp, context);
61             if (currentMode != null && currentMode != Permissions.getDefaultAppOpMode(appOp)) {
62                 return false;
63             }
64         }
65         boolean changed = setAppOpMode(packageName, appOp, AppOpsManager.MODE_ALLOWED, context);
66         if (changed) {
67             Permissions.setPermissionGrantedByRole(packageName, appOpPermission, true, context);
68         }
69         return changed;
70     }
71 
72     /**
73      * Revoke the app op of an app op permission from an application.
74      *
75      * @param packageName the package name of the application
76      * @param appOpPermission the name of the app op permission
77      * @param context the {@code Context} to retrieve system services
78      *
79      * @return whether any app op mode has changed
80      */
revoke(@onNull String packageName, @NonNull String appOpPermission, @NonNull Context context)81     public static boolean revoke(@NonNull String packageName, @NonNull String appOpPermission,
82             @NonNull Context context) {
83         if (!Permissions.isPermissionGrantedByRole(packageName, appOpPermission, context)) {
84             return false;
85         }
86         String appOp = AppOpsManager.permissionToOp(appOpPermission);
87         int defaultMode = Permissions.getDefaultAppOpMode(appOp);
88         boolean changed = setAppOpMode(packageName, appOp, defaultMode, context);
89         Permissions.setPermissionGrantedByRole(packageName, appOpPermission, false, context);
90         return changed;
91     }
92 
setAppOpMode(@onNull String packageName, @NonNull String appOp, int mode, @NonNull Context context)93     private static boolean setAppOpMode(@NonNull String packageName, @NonNull String appOp,
94             int mode, @NonNull Context context) {
95         switch (appOp) {
96             case AppOpsManager.OPSTR_ACCESS_NOTIFICATIONS:
97             case AppOpsManager.OPSTR_SYSTEM_ALERT_WINDOW:
98             case AppOpsManager.OPSTR_WRITE_SETTINGS:
99             case AppOpsManager.OPSTR_REQUEST_INSTALL_PACKAGES:
100             case AppOpsManager.OPSTR_START_FOREGROUND:
101             // This isn't an API but we are deprecating it soon anyway.
102             //case AppOpsManager.OPSTR_SMS_FINANCIAL_TRANSACTIONS:
103             case AppOpsManager.OPSTR_MANAGE_IPSEC_TUNNELS:
104             case AppOpsManager.OPSTR_INSTANT_APP_START_FOREGROUND:
105             case AppOpsManager.OPSTR_LOADER_USAGE_STATS:
106                 return Permissions.setAppOpPackageMode(packageName, appOp, mode, context);
107             case AppOpsManager.OPSTR_INTERACT_ACROSS_PROFILES:
108                 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
109                     // We fixed OP_INTERACT_ACROSS_PROFILES to use UID mode on S and backported it
110                     // to R, but still, we might have an out-of-date platform or an upgraded
111                     // platform with old state.
112                     boolean changed = false;
113                     changed |= Permissions.setAppOpUidMode(packageName, appOp, mode, context);
114                     changed |= Permissions.setAppOpPackageMode(packageName, appOp,
115                             Permissions.getDefaultAppOpMode(appOp), context);
116                     return changed;
117                 } else {
118                     return Permissions.setAppOpPackageMode(packageName, appOp, mode, context);
119                 }
120             default:
121                 return Permissions.setAppOpUidMode(packageName, appOp, mode, context);
122         }
123     }
124 }
125