Home | History | Annotate | Download | only in notification
      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.Fragment;
     22 import android.app.NotificationManager;
     23 import android.content.ComponentName;
     24 import android.content.Context;
     25 import android.content.DialogInterface;
     26 import android.os.AsyncTask;
     27 import android.os.Bundle;
     28 import android.provider.Settings;
     29 import android.service.notification.NotificationListenerService;
     30 import android.util.Log;
     31 
     32 import com.android.internal.annotations.VisibleForTesting;
     33 import com.android.internal.logging.MetricsLogger;
     34 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
     35 import com.android.settings.R;
     36 import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
     37 import com.android.settings.overlay.FeatureFactory;
     38 import com.android.settings.utils.ManagedServiceSettings;
     39 
     40 public class NotificationAccessSettings extends ManagedServiceSettings {
     41     private static final String TAG = NotificationAccessSettings.class.getSimpleName();
     42     private static final Config CONFIG = getNotificationListenerConfig();
     43 
     44 
     45     @Override
     46     public void onCreate(Bundle icicle) {
     47         super.onCreate(icicle);
     48     }
     49 
     50     private static Config getNotificationListenerConfig() {
     51         final Config c = new Config();
     52         c.tag = TAG;
     53         c.setting = Settings.Secure.ENABLED_NOTIFICATION_LISTENERS;
     54         c.intentAction = NotificationListenerService.SERVICE_INTERFACE;
     55         c.permission = android.Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE;
     56         c.noun = "notification listener";
     57         c.warningDialogTitle = R.string.notification_listener_security_warning_title;
     58         c.warningDialogSummary = R.string.notification_listener_security_warning_summary;
     59         c.emptyText = R.string.no_notification_listeners;
     60         return c;
     61     }
     62 
     63     @Override
     64     public int getMetricsCategory() {
     65         return MetricsEvent.NOTIFICATION_ACCESS;
     66     }
     67 
     68     @Override
     69     protected Config getConfig() {
     70         return CONFIG;
     71     }
     72 
     73     protected boolean setEnabled(ComponentName service, String title, boolean enable) {
     74         logSpecialPermissionChange(enable, service.getPackageName());
     75         if (!enable) {
     76             if (!mServiceListing.isEnabled(service)) {
     77                 return true; // already disabled
     78             }
     79             // show a friendly dialog
     80             new FriendlyWarningDialogFragment()
     81                     .setServiceInfo(service, title, this)
     82                     .show(getFragmentManager(), "friendlydialog");
     83             return false;
     84         } else {
     85             return super.setEnabled(service, title, enable);
     86         }
     87     }
     88 
     89     @VisibleForTesting
     90     void logSpecialPermissionChange(boolean enable, String packageName) {
     91         int logCategory = enable ? MetricsEvent.APP_SPECIAL_PERMISSION_NOTIVIEW_ALLOW
     92                 : MetricsEvent.APP_SPECIAL_PERMISSION_NOTIVIEW_DENY;
     93         FeatureFactory.getFactory(getContext()).getMetricsFeatureProvider().action(getContext(),
     94                 logCategory, packageName);
     95     }
     96 
     97     private static void disable(final Context context, final NotificationAccessSettings parent,
     98             final ComponentName cn) {
     99         parent.mServiceListing.setEnabled(cn, false);
    100         AsyncTask.execute(new Runnable() {
    101             @Override
    102             public void run() {
    103                 final NotificationManager mgr = context.getSystemService(NotificationManager.class);
    104 
    105                 if (!mgr.isNotificationPolicyAccessGrantedForPackage(
    106                         cn.getPackageName())) {
    107                     mgr.removeAutomaticZenRules(cn.getPackageName());
    108                 }
    109             }
    110         });
    111     }
    112 
    113     public static class FriendlyWarningDialogFragment extends InstrumentedDialogFragment {
    114         static final String KEY_COMPONENT = "c";
    115         static final String KEY_LABEL = "l";
    116 
    117         public FriendlyWarningDialogFragment setServiceInfo(ComponentName cn, String label,
    118                 Fragment target) {
    119             Bundle args = new Bundle();
    120             args.putString(KEY_COMPONENT, cn.flattenToString());
    121             args.putString(KEY_LABEL, label);
    122             setArguments(args);
    123             setTargetFragment(target, 0);
    124             return this;
    125         }
    126 
    127         @Override
    128         public int getMetricsCategory() {
    129             return MetricsEvent.DIALOG_DISABLE_NOTIFICATION_ACCESS;
    130         }
    131 
    132         @Override
    133         public Dialog onCreateDialog(Bundle savedInstanceState) {
    134             final Bundle args = getArguments();
    135             final String label = args.getString(KEY_LABEL);
    136             final ComponentName cn = ComponentName.unflattenFromString(args
    137                     .getString(KEY_COMPONENT));
    138             NotificationAccessSettings parent = (NotificationAccessSettings) getTargetFragment();
    139 
    140             final String summary = getResources().getString(
    141                     R.string.notification_listener_disable_warning_summary, label);
    142             return new AlertDialog.Builder(getContext())
    143                     .setMessage(summary)
    144                     .setCancelable(true)
    145                     .setPositiveButton(R.string.notification_listener_disable_warning_confirm,
    146                             new DialogInterface.OnClickListener() {
    147                                 public void onClick(DialogInterface dialog, int id) {
    148                                     disable(getContext(), parent, cn);
    149                                 }
    150                             })
    151                     .setNegativeButton(R.string.notification_listener_disable_warning_cancel,
    152                             new DialogInterface.OnClickListener() {
    153                                 public void onClick(DialogInterface dialog, int id) {
    154                                     // pass
    155                                 }
    156                             })
    157                     .create();
    158         }
    159     }
    160 }
    161