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.settings.applications.specialaccess.notificationaccess;
18 
19 import android.app.NotificationManager;
20 import android.app.settings.SettingsEnums;
21 import android.content.ComponentName;
22 import android.content.Context;
23 import android.content.pm.PackageInfo;
24 import android.content.pm.PackageManager;
25 import android.os.AsyncTask;
26 
27 import androidx.annotation.VisibleForTesting;
28 import androidx.preference.Preference;
29 import androidx.preference.PreferenceFragmentCompat;
30 import androidx.preference.SwitchPreference;
31 
32 import com.android.settings.core.BasePreferenceController;
33 import com.android.settings.overlay.FeatureFactory;
34 
35 public class ApprovalPreferenceController extends BasePreferenceController {
36 
37     private static final String TAG = "ApprovalPrefController";
38 
39     private PackageInfo mPkgInfo;
40     private ComponentName mCn;
41     private PreferenceFragmentCompat mParent;
42     private NotificationManager mNm;
43     private PackageManager mPm;
44 
ApprovalPreferenceController(Context context, String key)45     public ApprovalPreferenceController(Context context, String key) {
46         super(context, key);
47     }
48 
setPkgInfo(PackageInfo pkgInfo)49     public ApprovalPreferenceController setPkgInfo(PackageInfo pkgInfo) {
50         mPkgInfo = pkgInfo;
51         return this;
52     }
53 
setCn(ComponentName cn)54     public ApprovalPreferenceController setCn(ComponentName cn) {
55         mCn = cn;
56         return this;
57     }
58 
setParent(PreferenceFragmentCompat parent)59     public ApprovalPreferenceController setParent(PreferenceFragmentCompat parent) {
60         mParent = parent;
61         return this;
62     }
63 
setNm(NotificationManager nm)64     public ApprovalPreferenceController setNm(NotificationManager nm) {
65         mNm = nm;
66         return this;
67     }
68 
setPm(PackageManager pm)69     public ApprovalPreferenceController setPm(PackageManager pm) {
70         mPm = pm;
71         return this;
72     }
73 
74     @Override
getAvailabilityStatus()75     public int getAvailabilityStatus() {
76         return AVAILABLE;
77     }
78 
79     @Override
updateState(Preference pref)80     public void updateState(Preference pref) {
81         final SwitchPreference preference = (SwitchPreference) pref;
82         final CharSequence label = mPkgInfo.applicationInfo.loadLabel(mPm);
83         preference.setChecked(isServiceEnabled(mCn));
84         preference.setOnPreferenceChangeListener((p, newValue) -> {
85             final boolean access = (Boolean) newValue;
86             if (!access) {
87                 if (!isServiceEnabled(mCn)) {
88                     return true; // already disabled
89                 }
90                 // show a friendly dialog
91                 new FriendlyWarningDialogFragment()
92                         .setServiceInfo(mCn, label, mParent)
93                         .show(mParent.getFragmentManager(), "friendlydialog");
94                 return false;
95             } else {
96                 if (isServiceEnabled(mCn)) {
97                     return true; // already enabled
98                 }
99                 // show a scary dialog
100                 new ScaryWarningDialogFragment()
101                         .setServiceInfo(mCn, label, mParent)
102                         .show(mParent.getFragmentManager(), "dialog");
103                 return false;
104             }
105         });
106     }
107 
disable(final ComponentName cn)108     public void disable(final ComponentName cn) {
109         logSpecialPermissionChange(true, cn.getPackageName());
110         mNm.setNotificationListenerAccessGranted(cn, false);
111         AsyncTask.execute(() -> {
112             if (!mNm.isNotificationPolicyAccessGrantedForPackage(
113                     cn.getPackageName())) {
114                 mNm.removeAutomaticZenRules(cn.getPackageName());
115             }
116         });
117     }
118 
enable(ComponentName cn)119     protected void enable(ComponentName cn) {
120         logSpecialPermissionChange(true, cn.getPackageName());
121         mNm.setNotificationListenerAccessGranted(cn, true);
122     }
123 
isServiceEnabled(ComponentName cn)124     protected boolean isServiceEnabled(ComponentName cn) {
125         return mNm.isNotificationListenerAccessGranted(cn);
126     }
127 
128     @VisibleForTesting
logSpecialPermissionChange(boolean enable, String packageName)129     void logSpecialPermissionChange(boolean enable, String packageName) {
130         final int logCategory = enable ? SettingsEnums.APP_SPECIAL_PERMISSION_NOTIVIEW_ALLOW
131                 : SettingsEnums.APP_SPECIAL_PERMISSION_NOTIVIEW_DENY;
132         FeatureFactory.getFactory(mContext).getMetricsFeatureProvider().action(mContext,
133                 logCategory, packageName);
134     }
135 }