1 /*
2  * Copyright (C) 2010 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.notification;
18 
19 import android.app.AlertDialog;
20 import android.app.Dialog;
21 import android.app.DialogFragment;
22 import android.app.NotificationManager;
23 import android.content.ComponentName;
24 import android.content.Context;
25 import android.content.DialogInterface;
26 import android.content.pm.PackageManager;
27 import android.os.AsyncTask;
28 import android.os.Bundle;
29 import android.provider.Settings;
30 import android.service.notification.NotificationListenerService;
31 
32 import com.android.internal.logging.MetricsProto.MetricsEvent;
33 import com.android.settings.R;
34 import com.android.settings.utils.ManagedServiceSettings;
35 import com.android.settings.utils.ServiceListing;
36 
37 public class NotificationAccessSettings extends ManagedServiceSettings {
38     private static final String TAG = NotificationAccessSettings.class.getSimpleName();
39     private static final Config CONFIG = getNotificationListenerConfig();
40 
41     private NotificationManager mNm;
42 
43     @Override
onCreate(Bundle icicle)44     public void onCreate(Bundle icicle) {
45         super.onCreate(icicle);
46         mNm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
47     }
48 
getNotificationListenerConfig()49     private static Config getNotificationListenerConfig() {
50         final Config c = new Config();
51         c.tag = TAG;
52         c.setting = Settings.Secure.ENABLED_NOTIFICATION_LISTENERS;
53         c.intentAction = NotificationListenerService.SERVICE_INTERFACE;
54         c.permission = android.Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE;
55         c.noun = "notification listener";
56         c.warningDialogTitle = R.string.notification_listener_security_warning_title;
57         c.warningDialogSummary = R.string.notification_listener_security_warning_summary;
58         c.emptyText = R.string.no_notification_listeners;
59         return c;
60     }
61 
62     @Override
getMetricsCategory()63     protected int getMetricsCategory() {
64         return MetricsEvent.NOTIFICATION_ACCESS;
65     }
66 
67     @Override
getConfig()68     protected Config getConfig() {
69         return CONFIG;
70     }
71 
getListenersCount(PackageManager pm)72     public static int getListenersCount(PackageManager pm) {
73         return ServiceListing.getServicesCount(CONFIG, pm);
74     }
75 
getEnabledListenersCount(Context context)76     public static int getEnabledListenersCount(Context context) {
77         return ServiceListing.getEnabledServicesCount(CONFIG, context);
78     }
79 
setEnabled(ComponentName service, String title, boolean enable)80     protected boolean setEnabled(ComponentName service, String title, boolean enable) {
81         if (!enable) {
82             if (!mServiceListing.isEnabled(service)) {
83                 return true; // already disabled
84             }
85             // show a friendly dialog
86             new FriendlyWarningDialogFragment()
87                     .setServiceInfo(service, title)
88                     .show(getFragmentManager(), "friendlydialog");
89             return false;
90         } else {
91             return super.setEnabled(service, title, enable);
92         }
93     }
94 
deleteRules(final Context context, final String pkg)95     private static void deleteRules(final Context context, final String pkg) {
96         AsyncTask.execute(new Runnable() {
97             @Override
98             public void run() {
99                 final NotificationManager mgr = context.getSystemService(NotificationManager.class);
100                 mgr.removeAutomaticZenRules(pkg);
101             }
102         });
103     }
104 
105     public class FriendlyWarningDialogFragment extends DialogFragment {
106         static final String KEY_COMPONENT = "c";
107         static final String KEY_LABEL = "l";
108 
setServiceInfo(ComponentName cn, String label)109         public FriendlyWarningDialogFragment setServiceInfo(ComponentName cn, String label) {
110             Bundle args = new Bundle();
111             args.putString(KEY_COMPONENT, cn.flattenToString());
112             args.putString(KEY_LABEL, label);
113             setArguments(args);
114             return this;
115         }
116 
117         @Override
onCreateDialog(Bundle savedInstanceState)118         public Dialog onCreateDialog(Bundle savedInstanceState) {
119             super.onCreate(savedInstanceState);
120             final Bundle args = getArguments();
121             final String label = args.getString(KEY_LABEL);
122             final ComponentName cn = ComponentName.unflattenFromString(args
123                     .getString(KEY_COMPONENT));
124 
125             final String summary = getResources().getString(
126                     R.string.notification_listener_disable_warning_summary, label);
127             return new AlertDialog.Builder(mContext)
128                     .setMessage(summary)
129                     .setCancelable(true)
130                     .setPositiveButton(R.string.notification_listener_disable_warning_confirm,
131                             new DialogInterface.OnClickListener() {
132                                 public void onClick(DialogInterface dialog, int id) {
133                                     mServiceListing.setEnabled(cn, false);
134                                     if (!mNm.isNotificationPolicyAccessGrantedForPackage(
135                                             cn.getPackageName())) {
136                                         deleteRules(mContext, cn.getPackageName());
137                                     }
138                                 }
139                             })
140                     .setNegativeButton(R.string.notification_listener_disable_warning_cancel,
141                             new DialogInterface.OnClickListener() {
142                                 public void onClick(DialogInterface dialog, int id) {
143                                     // pass
144                                 }
145                             })
146                     .create();
147         }
148     }
149 }
150