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
17package com.android.settings.notification;
18
19import android.app.AlertDialog;
20import android.app.Dialog;
21import android.app.DialogFragment;
22import android.app.NotificationManager;
23import android.content.ComponentName;
24import android.content.Context;
25import android.content.DialogInterface;
26import android.content.pm.PackageManager;
27import android.os.AsyncTask;
28import android.os.Bundle;
29import android.provider.Settings;
30import android.service.notification.NotificationListenerService;
31
32import com.android.internal.logging.MetricsProto.MetricsEvent;
33import com.android.settings.R;
34import com.android.settings.utils.ManagedServiceSettings;
35import com.android.settings.utils.ServiceListing;
36
37public 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
44    public void onCreate(Bundle icicle) {
45        super.onCreate(icicle);
46        mNm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
47    }
48
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
63    protected int getMetricsCategory() {
64        return MetricsEvent.NOTIFICATION_ACCESS;
65    }
66
67    @Override
68    protected Config getConfig() {
69        return CONFIG;
70    }
71
72    public static int getListenersCount(PackageManager pm) {
73        return ServiceListing.getServicesCount(CONFIG, pm);
74    }
75
76    public static int getEnabledListenersCount(Context context) {
77        return ServiceListing.getEnabledServicesCount(CONFIG, context);
78    }
79
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
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
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
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