Home | History | Annotate | Download | only in utils
      1 /*
      2  * Copyright (C) 2014 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.utils;
     18 
     19 import android.annotation.Nullable;
     20 import android.app.AlertDialog;
     21 import android.app.Dialog;
     22 import android.app.Fragment;
     23 import android.app.admin.DevicePolicyManager;
     24 import android.content.ComponentName;
     25 import android.content.Context;
     26 import android.content.DialogInterface;
     27 import android.content.pm.PackageItemInfo;
     28 import android.content.pm.PackageManager;
     29 import android.content.pm.ServiceInfo;
     30 import android.os.Bundle;
     31 import android.os.UserHandle;
     32 import android.os.UserManager;
     33 import android.support.v14.preference.SwitchPreference;
     34 import android.support.v7.preference.Preference;
     35 import android.support.v7.preference.Preference.OnPreferenceChangeListener;
     36 import android.support.v7.preference.PreferenceScreen;
     37 import android.view.View;
     38 
     39 import com.android.internal.logging.nano.MetricsProto;
     40 import com.android.settings.R;
     41 import com.android.settings.Utils;
     42 import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
     43 import com.android.settings.notification.EmptyTextSettings;
     44 
     45 import java.util.Collections;
     46 import java.util.List;
     47 
     48 public abstract class ManagedServiceSettings extends EmptyTextSettings {
     49     private final Config mConfig;
     50 
     51     protected Context mContext;
     52     private PackageManager mPM;
     53     private DevicePolicyManager mDpm;
     54     protected ServiceListing mServiceListing;
     55 
     56     abstract protected Config getConfig();
     57 
     58     public ManagedServiceSettings() {
     59         mConfig = getConfig();
     60     }
     61 
     62     @Override
     63     public void onCreate(Bundle icicle) {
     64         super.onCreate(icicle);
     65 
     66         mContext = getActivity();
     67         mPM = mContext.getPackageManager();
     68         mDpm = (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
     69         mServiceListing = new ServiceListing(mContext, mConfig);
     70         mServiceListing.addCallback(new ServiceListing.Callback() {
     71             @Override
     72             public void onServicesReloaded(List<ServiceInfo> services) {
     73                 updateList(services);
     74             }
     75         });
     76         setPreferenceScreen(getPreferenceManager().createPreferenceScreen(mContext));
     77     }
     78 
     79     @Override
     80     public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
     81         super.onViewCreated(view, savedInstanceState);
     82         setEmptyText(mConfig.emptyText);
     83     }
     84 
     85     @Override
     86     public void onResume() {
     87         super.onResume();
     88         mServiceListing.reload();
     89         mServiceListing.setListening(true);
     90     }
     91 
     92     @Override
     93     public void onPause() {
     94         super.onPause();
     95         mServiceListing.setListening(false);
     96     }
     97 
     98     private void updateList(List<ServiceInfo> services) {
     99         UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
    100         final int managedProfileId = Utils.getManagedProfileId(um, UserHandle.myUserId());
    101 
    102         final PreferenceScreen screen = getPreferenceScreen();
    103         screen.removeAll();
    104         Collections.sort(services, new PackageItemInfo.DisplayNameComparator(mPM));
    105         for (ServiceInfo service : services) {
    106             final ComponentName cn = new ComponentName(service.packageName, service.name);
    107             final String title = service.loadLabel(mPM).toString();
    108             final SwitchPreference pref = new SwitchPreference(getPrefContext());
    109             pref.setPersistent(false);
    110             pref.setIcon(service.loadIcon(mPM));
    111             pref.setTitle(title);
    112             pref.setChecked(mServiceListing.isEnabled(cn));
    113             if (managedProfileId != UserHandle.USER_NULL
    114                     && !mDpm.isNotificationListenerServicePermitted(
    115                             service.packageName, managedProfileId)) {
    116                 pref.setSummary(R.string.work_profile_notification_access_blocked_summary);
    117             }
    118             pref.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
    119                 @Override
    120                 public boolean onPreferenceChange(Preference preference, Object newValue) {
    121                     final boolean enable = (boolean) newValue;
    122                     return setEnabled(cn, title, enable);
    123                 }
    124             });
    125             screen.addPreference(pref);
    126         }
    127     }
    128 
    129     protected boolean setEnabled(ComponentName service, String title, boolean enable) {
    130         if (!enable) {
    131             // the simple version: disabling
    132             mServiceListing.setEnabled(service, false);
    133             return true;
    134         } else {
    135             if (mServiceListing.isEnabled(service)) {
    136                 return true; // already enabled
    137             }
    138             // show a scary dialog
    139             new ScaryWarningDialogFragment()
    140                     .setServiceInfo(service, title, this)
    141                     .show(getFragmentManager(), "dialog");
    142             return false;
    143         }
    144     }
    145 
    146     public static class ScaryWarningDialogFragment extends InstrumentedDialogFragment {
    147         static final String KEY_COMPONENT = "c";
    148         static final String KEY_LABEL = "l";
    149 
    150         @Override
    151         public int getMetricsCategory() {
    152             return MetricsProto.MetricsEvent.DIALOG_SERVICE_ACCESS_WARNING;
    153         }
    154 
    155         public ScaryWarningDialogFragment setServiceInfo(ComponentName cn, String label,
    156                 Fragment target) {
    157             Bundle args = new Bundle();
    158             args.putString(KEY_COMPONENT, cn.flattenToString());
    159             args.putString(KEY_LABEL, label);
    160             setArguments(args);
    161             setTargetFragment(target, 0);
    162             return this;
    163         }
    164 
    165         @Override
    166         public Dialog onCreateDialog(Bundle savedInstanceState) {
    167             final Bundle args = getArguments();
    168             final String label = args.getString(KEY_LABEL);
    169             final ComponentName cn = ComponentName.unflattenFromString(args
    170                     .getString(KEY_COMPONENT));
    171             ManagedServiceSettings parent = (ManagedServiceSettings) getTargetFragment();
    172 
    173             final String title = getResources().getString(parent.mConfig.warningDialogTitle, label);
    174             final String summary = getResources().getString(parent.mConfig.warningDialogSummary,
    175                     label);
    176             return new AlertDialog.Builder(getContext())
    177                     .setMessage(summary)
    178                     .setTitle(title)
    179                     .setCancelable(true)
    180                     .setPositiveButton(R.string.allow,
    181                             new DialogInterface.OnClickListener() {
    182                                 public void onClick(DialogInterface dialog, int id) {
    183                                     parent.mServiceListing.setEnabled(cn, true);
    184                                 }
    185                             })
    186                     .setNegativeButton(R.string.deny,
    187                             new DialogInterface.OnClickListener() {
    188                                 public void onClick(DialogInterface dialog, int id) {
    189                                     // pass
    190                                 }
    191                             })
    192                     .create();
    193         }
    194     }
    195 
    196     public static class Config {
    197         public String tag;
    198         public String setting;
    199         public String secondarySetting;
    200         public String intentAction;
    201         public String permission;
    202         public String noun;
    203         public int warningDialogTitle;
    204         public int warningDialogSummary;
    205         public int emptyText;
    206     }
    207 }
    208