summaryrefslogtreecommitdiffstats
path: root/src/com/android
diff options
context:
space:
mode:
authorJohn Spurlock <jspurlock@google.com>2015-04-10 11:59:54 -0400
committerJohn Spurlock <jspurlock@google.com>2015-04-13 12:19:55 -0400
commitc96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceaf (patch)
treef705752a83dc3bcabcea1d9ac69e0682d13251dd /src/com/android
parent3b1a4c6cc2afe590407819fc66c30e9361862950 (diff)
downloadpackages_apps_Settings-c96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceaf.zip
packages_apps_Settings-c96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceaf.tar.gz
packages_apps_Settings-c96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceaf.tar.bz2
Settings: External automatic rule settings.
- Add external automatic rule settings page with the common settings for all rules (enabled, name, zen mode). - Pull common rule-instance settings into settings base class, share with existing schedule rule settings. - New page not searchable since it is at the rule-instance level. - Obtain external rule information from existing conditions provider metadata. Includes rule type caption, sub-configuration activity, and default condition id. - If external condition providers exist with the appropriate metadata, display the external rule types as options in the new rule dialog. (max of 3 external types) - Pull common managed service listing code out of common settings base class and into a more reusable helper class. Bug: 20064962 Change-Id: Ibc13607490b7312a7d9f7f3bd61c3cfcf71a2794
Diffstat (limited to 'src/com/android')
-rw-r--r--src/com/android/settings/Settings.java1
-rw-r--r--src/com/android/settings/SettingsActivity.java4
-rw-r--r--src/com/android/settings/notification/ConditionProviderSettings.java50
-rw-r--r--src/com/android/settings/notification/ManagedServiceSettings.java233
-rw-r--r--src/com/android/settings/notification/NotificationAccessSettings.java4
-rw-r--r--src/com/android/settings/notification/ServiceListing.java206
-rw-r--r--src/com/android/settings/notification/ZenModeAutomationSettings.java124
-rw-r--r--src/com/android/settings/notification/ZenModeExternalRuleSettings.java133
-rw-r--r--src/com/android/settings/notification/ZenModeRuleSettingsBase.java256
-rw-r--r--src/com/android/settings/notification/ZenModeScheduleRuleSettings.java216
-rw-r--r--src/com/android/settings/notification/ZenRuleNameDialog.java119
11 files changed, 870 insertions, 476 deletions
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index fe0df59..ba08036 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -98,6 +98,7 @@ public class Settings extends SettingsActivity {
public static class ZenModePrioritySettingsActivity extends SettingsActivity { /* empty */ }
public static class ZenModeAutomationSettingsActivity extends SettingsActivity { /* empty */ }
public static class ZenModeScheduleRuleSettingsActivity extends SettingsActivity { /* empty */ }
+ public static class ZenModeExternalRuleSettingsActivity extends SettingsActivity { /* empty */ }
public static class NotificationSettingsActivity extends SettingsActivity { /* empty */ }
public static class NotificationAppListActivity extends SettingsActivity { /* empty */ }
public static class AppNotificationSettingsActivity extends SettingsActivity { /* empty */ }
diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java
index 7bfd249..0fdf04b 100644
--- a/src/com/android/settings/SettingsActivity.java
+++ b/src/com/android/settings/SettingsActivity.java
@@ -95,11 +95,11 @@ import com.android.settings.location.LocationSettings;
import com.android.settings.nfc.AndroidBeam;
import com.android.settings.nfc.PaymentSettings;
import com.android.settings.notification.AppNotificationSettings;
-import com.android.settings.notification.ConditionProviderSettings;
import com.android.settings.notification.NotificationAccessSettings;
import com.android.settings.notification.NotificationSettings;
import com.android.settings.notification.NotificationStation;
import com.android.settings.notification.OtherSoundSettings;
+import com.android.settings.notification.ZenModeExternalRuleSettings;
import com.android.settings.notification.ZenModeSettings;
import com.android.settings.notification.ZenModeScheduleRuleSettings;
import com.android.settings.print.PrintJobSettingsFragment;
@@ -320,7 +320,6 @@ public class SettingsActivity extends Activity
DreamSettings.class.getName(),
UserSettings.class.getName(),
NotificationAccessSettings.class.getName(),
- ConditionProviderSettings.class.getName(),
PrintSettingsFragment.class.getName(),
PrintJobSettingsFragment.class.getName(),
TrustedCredentialsSettings.class.getName(),
@@ -337,6 +336,7 @@ public class SettingsActivity extends Activity
ApnSettings.class.getName(),
WifiCallingSettings.class.getName(),
ZenModeScheduleRuleSettings.class.getName(),
+ ZenModeExternalRuleSettings.class.getName(),
};
diff --git a/src/com/android/settings/notification/ConditionProviderSettings.java b/src/com/android/settings/notification/ConditionProviderSettings.java
deleted file mode 100644
index 76576ab..0000000
--- a/src/com/android/settings/notification/ConditionProviderSettings.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.notification;
-
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.provider.Settings;
-import android.service.notification.ConditionProviderService;
-
-public class ConditionProviderSettings extends ManagedServiceSettings {
- private static final String TAG = ConditionProviderSettings.class.getSimpleName();
- private static final Config CONFIG = getConditionProviderConfig();
-
- private static Config getConditionProviderConfig() {
- final Config c = new Config();
- c.tag = TAG;
- c.setting = Settings.Secure.ENABLED_CONDITION_PROVIDERS;
- c.intentAction = ConditionProviderService.SERVICE_INTERFACE;
- c.permission = android.Manifest.permission.BIND_CONDITION_PROVIDER_SERVICE;
- c.noun = "condition provider";
- return c;
- }
-
- @Override
- protected Config getConfig() {
- return CONFIG;
- }
-
- public static int getProviderCount(PackageManager pm) {
- return getServicesCount(CONFIG, pm);
- }
-
- public static int getEnabledProviderCount(Context context) {
- return getEnabledServicesCount(CONFIG, context);
- }
-}
diff --git a/src/com/android/settings/notification/ManagedServiceSettings.java b/src/com/android/settings/notification/ManagedServiceSettings.java
index 7be644e..cc9e734 100644
--- a/src/com/android/settings/notification/ManagedServiceSettings.java
+++ b/src/com/android/settings/notification/ManagedServiceSettings.java
@@ -16,28 +16,17 @@
package com.android.settings.notification;
-import android.app.ActivityManager;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.app.ListFragment;
-import android.content.BroadcastReceiver;
import android.content.ComponentName;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.IntentFilter;
import android.content.pm.PackageItemInfo;
import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
-import android.database.ContentObserver;
-import android.net.Uri;
import android.os.Bundle;
-import android.os.Handler;
-import android.provider.Settings;
-import android.util.Slog;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -49,17 +38,15 @@ import android.widget.TextView;
import com.android.settings.R;
-import java.util.HashSet;
import java.util.List;
public abstract class ManagedServiceSettings extends ListFragment {
private static final boolean SHOW_PACKAGE_NAME = false;
private final Config mConfig;
- private PackageManager mPM;
- private ContentResolver mCR;
- private final HashSet<ComponentName> mEnabledServices = new HashSet<ComponentName>();
+ private PackageManager mPM;
+ private ServiceListing mServiceListing;
private ServiceListAdapter mListAdapter;
abstract protected Config getConfig();
@@ -68,68 +55,18 @@ public abstract class ManagedServiceSettings extends ListFragment {
mConfig = getConfig();
}
- private final ContentObserver mSettingsObserver = new ContentObserver(new Handler()) {
- @Override
- public void onChange(boolean selfChange, Uri uri) {
- updateList();
- }
- };
-
- private final BroadcastReceiver mPackageReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- updateList();
- }
- };
-
- public class ScaryWarningDialogFragment extends DialogFragment {
- static final String KEY_COMPONENT = "c";
- static final String KEY_LABEL = "l";
-
- public ScaryWarningDialogFragment setServiceInfo(ComponentName cn, String label) {
- Bundle args = new Bundle();
- args.putString(KEY_COMPONENT, cn.flattenToString());
- args.putString(KEY_LABEL, label);
- setArguments(args);
- return this;
- }
-
- @Override
- public Dialog onCreateDialog(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- final Bundle args = getArguments();
- final String label = args.getString(KEY_LABEL);
- final ComponentName cn = ComponentName.unflattenFromString(args.getString(KEY_COMPONENT));
-
- final String title = getResources().getString(mConfig.warningDialogTitle, label);
- final String summary = getResources().getString(mConfig.warningDialogSummary, label);
- return new AlertDialog.Builder(getActivity())
- .setMessage(summary)
- .setTitle(title)
- .setCancelable(true)
- .setPositiveButton(android.R.string.ok,
- new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int id) {
- mEnabledServices.add(cn);
- saveEnabledServices();
- }
- })
- .setNegativeButton(android.R.string.cancel,
- new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int id) {
- // pass
- }
- })
- .create();
- }
- }
-
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
mPM = getActivity().getPackageManager();
- mCR = getActivity().getContentResolver();
+ mServiceListing = new ServiceListing(getActivity(), mConfig);
+ mServiceListing.addCallback(new ServiceListing.Callback() {
+ @Override
+ public void onServicesReloaded(List<ServiceInfo> services) {
+ updateList(services);
+ }
+ });
mListAdapter = new ServiceListAdapter(getActivity());
}
@@ -145,122 +82,31 @@ public abstract class ManagedServiceSettings extends ListFragment {
@Override
public void onResume() {
super.onResume();
- updateList();
-
- // listen for package changes
- IntentFilter filter = new IntentFilter();
- filter.addAction(Intent.ACTION_PACKAGE_ADDED);
- filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
- filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
- filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
- filter.addDataScheme("package");
- getActivity().registerReceiver(mPackageReceiver, filter);
-
- mCR.registerContentObserver(Settings.Secure.getUriFor(mConfig.setting),
- false, mSettingsObserver);
+ mServiceListing.reload();
+ mServiceListing.setListening(true);
}
@Override
public void onPause() {
super.onPause();
-
- getActivity().unregisterReceiver(mPackageReceiver);
- mCR.unregisterContentObserver(mSettingsObserver);
- }
-
- private void loadEnabledServices() {
- mEnabledServices.clear();
- final String flat = Settings.Secure.getString(mCR, mConfig.setting);
- if (flat != null && !"".equals(flat)) {
- final String[] names = flat.split(":");
- for (int i = 0; i < names.length; i++) {
- final ComponentName cn = ComponentName.unflattenFromString(names[i]);
- if (cn != null) {
- mEnabledServices.add(cn);
- }
- }
- }
- }
-
- private void saveEnabledServices() {
- StringBuilder sb = null;
- for (ComponentName cn : mEnabledServices) {
- if (sb == null) {
- sb = new StringBuilder();
- } else {
- sb.append(':');
- }
- sb.append(cn.flattenToString());
- }
- Settings.Secure.putString(mCR,
- mConfig.setting,
- sb != null ? sb.toString() : "");
+ mServiceListing.setListening(false);
}
- private void updateList() {
- loadEnabledServices();
-
- getServices(mConfig, mListAdapter, mPM);
+ private void updateList(List<ServiceInfo> services) {
+ mListAdapter.clear();
+ mListAdapter.addAll(services);
mListAdapter.sort(new PackageItemInfo.DisplayNameComparator(mPM));
getListView().setAdapter(mListAdapter);
}
- protected static int getEnabledServicesCount(Config config, Context context) {
- final String flat = Settings.Secure.getString(context.getContentResolver(), config.setting);
- if (flat == null || "".equals(flat)) return 0;
- final String[] components = flat.split(":");
- return components.length;
- }
-
- protected static int getServicesCount(Config c, PackageManager pm) {
- return getServices(c, null, pm);
- }
-
- private static int getServices(Config c, ArrayAdapter<ServiceInfo> adapter, PackageManager pm) {
- int services = 0;
- if (adapter != null) {
- adapter.clear();
- }
- final int user = ActivityManager.getCurrentUser();
-
- List<ResolveInfo> installedServices = pm.queryIntentServicesAsUser(
- new Intent(c.intentAction),
- PackageManager.GET_SERVICES | PackageManager.GET_META_DATA,
- user);
-
- for (int i = 0, count = installedServices.size(); i < count; i++) {
- ResolveInfo resolveInfo = installedServices.get(i);
- ServiceInfo info = resolveInfo.serviceInfo;
-
- if (!c.permission.equals(info.permission)) {
- Slog.w(c.tag, "Skipping " + c.noun + " service "
- + info.packageName + "/" + info.name
- + ": it does not require the permission "
- + c.permission);
- continue;
- }
- if (adapter != null) {
- adapter.add(info);
- }
- services++;
- }
- return services;
- }
-
- private boolean isServiceEnabled(ServiceInfo info) {
- final ComponentName cn = new ComponentName(info.packageName, info.name);
- return mEnabledServices.contains(cn);
- }
-
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
ServiceInfo info = mListAdapter.getItem(position);
final ComponentName cn = new ComponentName(info.packageName, info.name);
- if (mEnabledServices.contains(cn)) {
+ if (mServiceListing.isEnabled(cn)) {
// the simple version: disabling
- mEnabledServices.remove(cn);
- saveEnabledServices();
+ mServiceListing.setEnabled(cn, false);
} else {
// show a scary dialog
new ScaryWarningDialogFragment()
@@ -269,6 +115,48 @@ public abstract class ManagedServiceSettings extends ListFragment {
}
}
+ public class ScaryWarningDialogFragment extends DialogFragment {
+ static final String KEY_COMPONENT = "c";
+ static final String KEY_LABEL = "l";
+
+ public ScaryWarningDialogFragment setServiceInfo(ComponentName cn, String label) {
+ Bundle args = new Bundle();
+ args.putString(KEY_COMPONENT, cn.flattenToString());
+ args.putString(KEY_LABEL, label);
+ setArguments(args);
+ return this;
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ final Bundle args = getArguments();
+ final String label = args.getString(KEY_LABEL);
+ final ComponentName cn = ComponentName.unflattenFromString(args
+ .getString(KEY_COMPONENT));
+
+ final String title = getResources().getString(mConfig.warningDialogTitle, label);
+ final String summary = getResources().getString(mConfig.warningDialogSummary, label);
+ return new AlertDialog.Builder(getActivity())
+ .setMessage(summary)
+ .setTitle(title)
+ .setCancelable(true)
+ .setPositiveButton(android.R.string.ok,
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ mServiceListing.setEnabled(cn, true);
+ }
+ })
+ .setNegativeButton(android.R.string.cancel,
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ // pass
+ }
+ })
+ .create();
+ }
+ }
+
private static class ViewHolder {
ImageView icon;
TextView name;
@@ -327,7 +215,8 @@ public abstract class ManagedServiceSettings extends ListFragment {
} else {
vh.description.setVisibility(View.GONE);
}
- vh.checkbox.setChecked(isServiceEnabled(info));
+ final ComponentName cn = new ComponentName(info.packageName, info.name);
+ vh.checkbox.setChecked(mServiceListing.isEnabled(cn));
}
}
diff --git a/src/com/android/settings/notification/NotificationAccessSettings.java b/src/com/android/settings/notification/NotificationAccessSettings.java
index ced71a4..5104d4a 100644
--- a/src/com/android/settings/notification/NotificationAccessSettings.java
+++ b/src/com/android/settings/notification/NotificationAccessSettings.java
@@ -46,10 +46,10 @@ public class NotificationAccessSettings extends ManagedServiceSettings {
}
public static int getListenersCount(PackageManager pm) {
- return getServicesCount(CONFIG, pm);
+ return ServiceListing.getServicesCount(CONFIG, pm);
}
public static int getEnabledListenersCount(Context context) {
- return getEnabledServicesCount(CONFIG, context);
+ return ServiceListing.getEnabledServicesCount(CONFIG, context);
}
}
diff --git a/src/com/android/settings/notification/ServiceListing.java b/src/com/android/settings/notification/ServiceListing.java
new file mode 100644
index 0000000..d296139
--- /dev/null
+++ b/src/com/android/settings/notification/ServiceListing.java
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.notification;
+
+import android.app.ActivityManager;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.provider.Settings;
+import android.util.Slog;
+
+import com.android.settings.notification.ManagedServiceSettings.Config;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+
+public class ServiceListing {
+ private final ContentResolver mContentResolver;
+ private final Context mContext;
+ private final Config mConfig;
+ private final HashSet<ComponentName> mEnabledServices = new HashSet<ComponentName>();
+ private final List<ServiceInfo> mServices = new ArrayList<ServiceInfo>();
+ private final List<Callback> mCallbacks = new ArrayList<Callback>();
+
+ private boolean mListening;
+
+ public ServiceListing(Context context, Config config) {
+ mContext = context;
+ mConfig = config;
+ mContentResolver = context.getContentResolver();
+ }
+
+ public void addCallback(Callback callback) {
+ mCallbacks.add(callback);
+ }
+
+ public void removeCallback(Callback callback) {
+ mCallbacks.remove(callback);
+ }
+
+ public void setListening(boolean listening) {
+ if (mListening == listening) return;
+ mListening = listening;
+ if (mListening) {
+ // listen for package changes
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_PACKAGE_ADDED);
+ filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
+ filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+ filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
+ filter.addDataScheme("package");
+ mContext.registerReceiver(mPackageReceiver, filter);
+ mContentResolver.registerContentObserver(Settings.Secure.getUriFor(mConfig.setting),
+ false, mSettingsObserver);
+ } else {
+ mContext.unregisterReceiver(mPackageReceiver);
+ mContentResolver.unregisterContentObserver(mSettingsObserver);
+ }
+ }
+
+ public static int getEnabledServicesCount(Config config, Context context) {
+ final String flat = Settings.Secure.getString(context.getContentResolver(), config.setting);
+ if (flat == null || "".equals(flat)) return 0;
+ final String[] components = flat.split(":");
+ return components.length;
+ }
+
+ public static int getServicesCount(Config c, PackageManager pm) {
+ return getServices(c, null, pm);
+ }
+
+ public static ServiceInfo findService(Context context, Config config, final ComponentName cn) {
+ final ServiceListing listing = new ServiceListing(context, config);
+ final List<ServiceInfo> services = listing.reload();
+ for (ServiceInfo service : services) {
+ final ComponentName serviceCN = new ComponentName(service.packageName, service.name);
+ if (serviceCN.equals(cn)) {
+ return service;
+ }
+ }
+ return null;
+ }
+
+ private static int getServices(Config c, List<ServiceInfo> list, PackageManager pm) {
+ int services = 0;
+ if (list != null) {
+ list.clear();
+ }
+ final int user = ActivityManager.getCurrentUser();
+
+ List<ResolveInfo> installedServices = pm.queryIntentServicesAsUser(
+ new Intent(c.intentAction),
+ PackageManager.GET_SERVICES | PackageManager.GET_META_DATA,
+ user);
+
+ for (int i = 0, count = installedServices.size(); i < count; i++) {
+ ResolveInfo resolveInfo = installedServices.get(i);
+ ServiceInfo info = resolveInfo.serviceInfo;
+
+ if (!c.permission.equals(info.permission)) {
+ Slog.w(c.tag, "Skipping " + c.noun + " service "
+ + info.packageName + "/" + info.name
+ + ": it does not require the permission "
+ + c.permission);
+ continue;
+ }
+ if (list != null) {
+ list.add(info);
+ }
+ services++;
+ }
+ return services;
+ }
+
+ private void saveEnabledServices() {
+ StringBuilder sb = null;
+ for (ComponentName cn : mEnabledServices) {
+ if (sb == null) {
+ sb = new StringBuilder();
+ } else {
+ sb.append(':');
+ }
+ sb.append(cn.flattenToString());
+ }
+ Settings.Secure.putString(mContentResolver, mConfig.setting,
+ sb != null ? sb.toString() : "");
+ }
+
+ private void loadEnabledServices() {
+ mEnabledServices.clear();
+ final String flat = Settings.Secure.getString(mContentResolver, mConfig.setting);
+ if (flat != null && !"".equals(flat)) {
+ final String[] names = flat.split(":");
+ for (int i = 0; i < names.length; i++) {
+ final ComponentName cn = ComponentName.unflattenFromString(names[i]);
+ if (cn != null) {
+ mEnabledServices.add(cn);
+ }
+ }
+ }
+ }
+
+ public List<ServiceInfo> reload() {
+ loadEnabledServices();
+ getServices(mConfig, mServices, mContext.getPackageManager());
+ for (Callback callback : mCallbacks) {
+ callback.onServicesReloaded(mServices);
+ }
+ return mServices;
+ }
+
+ public boolean isEnabled(ComponentName cn) {
+ return mEnabledServices.contains(cn);
+ }
+
+ public void setEnabled(ComponentName cn, boolean enabled) {
+ if (enabled) {
+ mEnabledServices.add(cn);
+ } else {
+ mEnabledServices.remove(cn);
+ }
+ saveEnabledServices();
+ }
+
+ private final ContentObserver mSettingsObserver = new ContentObserver(new Handler()) {
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ reload();
+ }
+ };
+
+ private final BroadcastReceiver mPackageReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ reload();
+ }
+ };
+
+ public interface Callback {
+ void onServicesReloaded(List<ServiceInfo> services);
+ }
+}
diff --git a/src/com/android/settings/notification/ZenModeAutomationSettings.java b/src/com/android/settings/notification/ZenModeAutomationSettings.java
index c43d99e..f2ee71d 100644
--- a/src/com/android/settings/notification/ZenModeAutomationSettings.java
+++ b/src/com/android/settings/notification/ZenModeAutomationSettings.java
@@ -18,12 +18,16 @@ package com.android.settings.notification;
import static android.service.notification.ZenModeConfig.ALL_DAYS;
+import android.content.ComponentName;
import android.content.Intent;
+import android.content.pm.ServiceInfo;
import android.os.Bundle;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceClickListener;
import android.preference.PreferenceScreen;
+import android.provider.Settings;
import android.provider.Settings.Global;
+import android.service.notification.ConditionProviderService;
import android.service.notification.ZenModeConfig;
import android.service.notification.ZenModeConfig.ScheduleInfo;
import android.service.notification.ZenModeConfig.ZenRule;
@@ -35,30 +39,39 @@ import android.view.MenuItem;
import com.android.internal.logging.MetricsLogger;
import com.android.settings.R;
+import com.android.settings.notification.ManagedServiceSettings.Config;
+import com.android.settings.notification.ZenRuleNameDialog.RuleInfo;
import java.text.SimpleDateFormat;
import java.util.Calendar;
+import java.util.List;
import java.util.TreeSet;
public class ZenModeAutomationSettings extends ZenModeSettingsBase {
private static final SimpleDateFormat DAY_FORMAT = new SimpleDateFormat("EEE");
+ static final Config CONFIG = getConditionProviderConfig();
+
private final Calendar mCalendar = Calendar.getInstance();
+ private ServiceListing mServiceListing;
+
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
-
setHasOptionsMenu(true);
-
addPreferencesFromResource(R.xml.zen_mode_automation_settings);
+ mServiceListing = new ServiceListing(mContext, CONFIG);
+ mServiceListing.addCallback(mServiceListingCallback);
+ mServiceListing.reload();
+ mServiceListing.setListening(true);
}
- private void showRule(String ruleId, String ruleName) {
- if (DEBUG) Log.d(TAG, "showRule " + ruleId + " name=" + ruleName);
- mContext.startActivity(new Intent(ZenModeScheduleRuleSettings.ACTION)
- .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
- .putExtra(ZenModeScheduleRuleSettings.EXTRA_RULE_ID, ruleId));
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ mServiceListing.setListening(false);
+ mServiceListing.removeCallback(mServiceListingCallback);
}
@Override
@@ -75,54 +88,58 @@ public class ZenModeAutomationSettings extends ZenModeSettingsBase {
return super.onOptionsItemSelected(item);
}
+ @Override
+ protected void onZenModeChanged() {
+ // don't care
+ }
+
+ @Override
+ protected void onZenModeConfigChanged() {
+ updateControls();
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ updateControls();
+ }
+
private void showAddRuleDialog() {
- new ZenRuleNameDialog(mContext, "", mConfig.getAutomaticRuleNames()) {
+ new ZenRuleNameDialog(mContext, mServiceListing, null, mConfig.getAutomaticRuleNames()) {
@Override
- public void onOk(String ruleName) {
- final ScheduleInfo schedule = new ScheduleInfo();
- schedule.days = ZenModeConfig.ALL_DAYS;
- schedule.startHour = 22;
- schedule.endHour = 7;
+ public void onOk(String ruleName, RuleInfo ri) {
final ZenRule rule = new ZenRule();
rule.name = ruleName;
rule.enabled = true;
rule.zenMode = Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
- rule.conditionId = ZenModeConfig.toScheduleConditionId(schedule);
+ rule.conditionId = ri.defaultConditionId;
+ rule.component = ri.serviceComponent;
final ZenModeConfig newConfig = mConfig.copy();
final String ruleId = newConfig.newRuleId();
newConfig.automaticRules.put(ruleId, rule);
if (setZenModeConfig(newConfig)) {
- showRule(ruleId, rule.name);
+ showRule(ri.settingsAction, ri.configurationActivity, ruleId, rule.name);
}
}
}.show();
}
- @Override
- protected void onZenModeChanged() {
- // don't care
- }
-
- @Override
- protected void onZenModeConfigChanged() {
- updateControls();
- }
-
- @Override
- public void onResume() {
- super.onResume();
- updateControls();
+ private void showRule(String settingsAction, ComponentName configurationActivity,
+ String ruleId, String ruleName) {
+ if (DEBUG) Log.d(TAG, "showRule " + ruleId + " name=" + ruleName);
+ mContext.startActivity(new Intent(settingsAction)
+ .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
+ .putExtra(ZenModeRuleSettingsBase.EXTRA_RULE_ID, ruleId));
}
private void updateControls() {
final PreferenceScreen root = getPreferenceScreen();
root.removeAll();
-
if (mConfig == null) return;
for (int i = 0; i < mConfig.automaticRules.size(); i++) {
final String id = mConfig.automaticRules.keyAt(i);
final ZenRule rule = mConfig.automaticRules.valueAt(i);
- if (!ZenModeConfig.isValidScheduleConditionId(rule.conditionId)) continue;
+ final boolean isSchedule = ZenModeConfig.isValidScheduleConditionId(rule.conditionId);
final Preference p = new Preference(mContext);
p.setTitle(rule.name);
p.setSummary(computeRuleSummary(rule));
@@ -130,7 +147,9 @@ public class ZenModeAutomationSettings extends ZenModeSettingsBase {
p.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
- showRule(id, rule.name);
+ final String action = isSchedule ? ZenModeScheduleRuleSettings.ACTION
+ : ZenModeExternalRuleSettings.ACTION;
+ showRule(action, null, id, rule.name);
return true;
}
});
@@ -146,13 +165,16 @@ public class ZenModeAutomationSettings extends ZenModeSettingsBase {
private String computeRuleSummary(ZenRule rule) {
if (rule == null || !rule.enabled) return getString(R.string.switch_off_text);
final ScheduleInfo schedule = ZenModeConfig.tryParseScheduleConditionId(rule.conditionId);
- if (schedule == null) return getString(R.string.switch_on_text);
- final String days = computeContiguousDayRanges(schedule.days);
- final String start = getTime(schedule.startHour, schedule.startMinute);
- final String end = getTime(schedule.endHour, schedule.endMinute);
- final String time = getString(R.string.summary_range_verbal_combination, start, end);
final String mode = ZenModeSettings.computeZenModeCaption(getResources(), rule.zenMode);
- return getString(R.string.zen_mode_rule_summary_template, days, time, mode);
+ String summary = getString(R.string.switch_on_text);
+ if (schedule != null) {
+ final String days = computeContiguousDayRanges(schedule.days);
+ final String start = getTime(schedule.startHour, schedule.startMinute);
+ final String end = getTime(schedule.endHour, schedule.endMinute);
+ final String time = getString(R.string.summary_range_verbal_combination, start, end);
+ summary = getString(R.string.zen_mode_rule_summary_combination, days, time);
+ }
+ return getString(R.string.zen_mode_rule_summary_combination, summary, mode);
}
private String getTime(int hour, int minute) {
@@ -199,4 +221,30 @@ public class ZenModeAutomationSettings extends ZenModeSettingsBase {
return DAY_FORMAT.format(mCalendar.getTime());
}
+ private static Config getConditionProviderConfig() {
+ final Config c = new Config();
+ c.tag = TAG;
+ c.setting = Settings.Secure.ENABLED_CONDITION_PROVIDERS;
+ c.intentAction = ConditionProviderService.SERVICE_INTERFACE;
+ c.permission = android.Manifest.permission.BIND_CONDITION_PROVIDER_SERVICE;
+ c.noun = "condition provider";
+ return c;
+ }
+
+ private final ServiceListing.Callback mServiceListingCallback = new ServiceListing.Callback() {
+ @Override
+ public void onServicesReloaded(List<ServiceInfo> services) {
+ for (ServiceInfo service : services) {
+ final RuleInfo ri = ZenModeExternalRuleSettings.getRuleInfo(service);
+ if (ri != null && ri.serviceComponent != null
+ && ri.settingsAction == ZenModeExternalRuleSettings.ACTION) {
+ if (!mServiceListing.isEnabled(ri.serviceComponent)) {
+ Log.i(TAG, "Enabling external condition provider: " + ri.serviceComponent);
+ mServiceListing.setEnabled(ri.serviceComponent, true);
+ }
+ }
+ }
+ }
+ };
+
}
diff --git a/src/com/android/settings/notification/ZenModeExternalRuleSettings.java b/src/com/android/settings/notification/ZenModeExternalRuleSettings.java
new file mode 100644
index 0000000..9f9dc8a
--- /dev/null
+++ b/src/com/android/settings/notification/ZenModeExternalRuleSettings.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.notification;
+
+import android.app.Activity;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.pm.ServiceInfo;
+import android.net.Uri;
+import android.preference.Preference;
+import android.preference.Preference.OnPreferenceClickListener;
+import android.preference.PreferenceScreen;
+import android.provider.Settings;
+import android.service.notification.ZenModeConfig.ZenRule;
+import android.util.Log;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.settings.R;
+import com.android.settings.notification.ZenRuleNameDialog.RuleInfo;
+
+public class ZenModeExternalRuleSettings extends ZenModeRuleSettingsBase {
+ private static final String KEY_TYPE = "type";
+ private static final String KEY_CONFIGURE = "configure";
+
+ public static final String ACTION = Settings.ACTION_ZEN_MODE_EXTERNAL_RULE_SETTINGS;
+ private static final int REQUEST_CODE_CONFIGURE = 1;
+
+ private static final String MD_RULE_TYPE = "automatic.ruleType";
+ private static final String MD_DEFAULT_CONDITION_ID = "automatic.defaultConditionId";
+ private static final String MD_CONFIGURATION_ACTIVITY = "automatic.configurationActivity";
+ private static final String EXTRA_CONDITION_ID = "automatic.conditionId";
+
+ private Preference mType;
+ private Preference mConfigure;
+
+ @Override
+ protected boolean setRule(ZenRule rule) {
+ return rule != null;
+ }
+
+ @Override
+ protected String getZenModeDependency() {
+ return null;
+ }
+
+ @Override
+ protected void onCreateInternal() {
+ addPreferencesFromResource(R.xml.zen_mode_external_rule_settings);
+ final PreferenceScreen root = getPreferenceScreen();
+ final ServiceInfo si = ServiceListing.findService(mContext,
+ ZenModeAutomationSettings.CONFIG, mRule.component);
+ if (DEBUG) Log.d(TAG, "ServiceInfo: " + si);
+ final RuleInfo ri = getRuleInfo(si);
+ if (DEBUG) Log.d(TAG, "RuleInfo: " + ri);
+ mType = root.findPreference(KEY_TYPE);
+ if (ri == null) {
+ mType.setSummary(R.string.zen_mode_rule_type_unknown);
+ } else {
+ mType.setSummary(ri.caption);
+ }
+
+ mConfigure = root.findPreference(KEY_CONFIGURE);
+ if (ri == null || ri.configurationActivity == null) {
+ mConfigure.setEnabled(false);
+ } else {
+ mConfigure.setOnPreferenceClickListener(new OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ startActivityForResult(new Intent().setComponent(ri.configurationActivity),
+ REQUEST_CODE_CONFIGURE);
+ return true;
+ }
+ });
+ }
+ }
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+ if (requestCode == REQUEST_CODE_CONFIGURE) {
+ if (resultCode == Activity.RESULT_OK && data != null) {
+ final Uri conditionId = data.getParcelableExtra(EXTRA_CONDITION_ID);
+ if (conditionId != null && !conditionId.equals(mRule.conditionId)) {
+ updateRule(conditionId);
+ }
+ }
+ }
+ }
+
+ public static RuleInfo getRuleInfo(ServiceInfo si) {
+ if (si == null || si.metaData == null) return null;
+ final String ruleType = si.metaData.getString(MD_RULE_TYPE);
+ final String defaultConditionId = si.metaData.getString(MD_DEFAULT_CONDITION_ID);
+ final String configurationActivity = si.metaData.getString(MD_CONFIGURATION_ACTIVITY);
+ if (ruleType != null && !ruleType.trim().isEmpty() && defaultConditionId != null) {
+ final RuleInfo ri = new RuleInfo();
+ ri.serviceComponent = new ComponentName(si.packageName, si.name);
+ ri.settingsAction = ZenModeExternalRuleSettings.ACTION;
+ ri.caption = ruleType;
+ ri.defaultConditionId = Uri.parse(defaultConditionId);
+ if (configurationActivity != null) {
+ ri.configurationActivity = ComponentName.unflattenFromString(configurationActivity);
+ }
+ return ri;
+ }
+ return null;
+ }
+
+ @Override
+ protected void updateControlsInternal() {
+ // everything done up front
+ }
+
+ @Override
+ protected int getMetricsCategory() {
+ return MetricsLogger.NOTIFICATION_ZEN_MODE_EXTERNAL_RULE;
+ }
+
+}
diff --git a/src/com/android/settings/notification/ZenModeRuleSettingsBase.java b/src/com/android/settings/notification/ZenModeRuleSettingsBase.java
new file mode 100644
index 0000000..f6bc75f
--- /dev/null
+++ b/src/com/android/settings/notification/ZenModeRuleSettingsBase.java
@@ -0,0 +1,256 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.notification;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnClickListener;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.preference.Preference;
+import android.preference.Preference.OnPreferenceClickListener;
+import android.preference.PreferenceScreen;
+import android.provider.Settings.Global;
+import android.service.notification.ZenModeConfig;
+import android.service.notification.ZenModeConfig.ZenRule;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.widget.Switch;
+import android.widget.Toast;
+
+import com.android.settings.DropDownPreference;
+import com.android.settings.R;
+import com.android.settings.SettingsActivity;
+import com.android.settings.widget.SwitchBar;
+
+public abstract class ZenModeRuleSettingsBase extends ZenModeSettingsBase
+ implements SwitchBar.OnSwitchChangeListener {
+ protected static final String TAG = ZenModeSettingsBase.TAG;
+ protected static final boolean DEBUG = ZenModeSettingsBase.DEBUG;
+
+ public static final String EXTRA_RULE_ID = "rule_id";
+ private static final String KEY_RULE_NAME = "rule_name";
+ private static final String KEY_ZEN_MODE = "zen_mode";
+
+ protected Context mContext;
+ protected boolean mDisableListeners;
+ protected ZenRule mRule;
+
+ private String mRuleId;
+ private boolean mDeleting;
+ private Preference mRuleName;
+ private SwitchBar mSwitchBar;
+ private DropDownPreference mZenMode;
+
+ abstract protected void onCreateInternal();
+ abstract protected boolean setRule(ZenRule rule);
+ abstract protected String getZenModeDependency();
+ abstract protected void updateControlsInternal();
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+
+ mContext = getActivity();
+
+ final Intent intent = getActivity().getIntent();
+ if (DEBUG) Log.d(TAG, "onCreate getIntent()=" + intent);
+ if (intent == null) {
+ Log.w(TAG, "No intent");
+ toastAndFinish();
+ return;
+ }
+
+ mRuleId = intent.getStringExtra(EXTRA_RULE_ID);
+ if (DEBUG) Log.d(TAG, "mRuleId=" + mRuleId);
+ if (refreshRuleOrFinish()) {
+ return;
+ }
+
+ setHasOptionsMenu(true);
+
+ onCreateInternal();
+
+ final PreferenceScreen root = getPreferenceScreen();
+ mRuleName = root.findPreference(KEY_RULE_NAME);
+ mRuleName.setOnPreferenceClickListener(new OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ showRuleNameDialog();
+ return true;
+ }
+ });
+
+ mZenMode = (DropDownPreference) root.findPreference(KEY_ZEN_MODE);
+ mZenMode.addItem(R.string.zen_mode_option_important_interruptions,
+ Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS);
+ mZenMode.addItem(R.string.zen_mode_option_alarms, Global.ZEN_MODE_ALARMS);
+ mZenMode.addItem(R.string.zen_mode_option_no_interruptions,
+ Global.ZEN_MODE_NO_INTERRUPTIONS);
+ mZenMode.setCallback(new DropDownPreference.Callback() {
+ @Override
+ public boolean onItemSelected(int pos, Object value) {
+ if (mDisableListeners) return true;
+ final int zenMode = (Integer) value;
+ if (zenMode == mRule.zenMode) return true;
+ if (DEBUG) Log.d(TAG, "onPrefChange zenMode=" + zenMode);
+ mRule.zenMode = zenMode;
+ setZenModeConfig(mConfig);
+ return true;
+ }
+ });
+ mZenMode.setOrder(10); // sort at the bottom of the category
+ mZenMode.setDependency(getZenModeDependency());
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ updateControls();
+ }
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+
+ final SettingsActivity activity = (SettingsActivity) getActivity();
+ mSwitchBar = activity.getSwitchBar();
+ mSwitchBar.addOnSwitchChangeListener(this);
+ mSwitchBar.show();
+ }
+
+ @Override
+ public void onDestroyView() {
+ super.onDestroyView();
+ mSwitchBar.removeOnSwitchChangeListener(this);
+ mSwitchBar.hide();
+ }
+
+ @Override
+ public void onSwitchChanged(Switch switchView, boolean isChecked) {
+ if (DEBUG) Log.d(TAG, "onSwitchChanged " + isChecked);
+ if (mDisableListeners) return;
+ final boolean enabled = isChecked;
+ if (enabled == mRule.enabled) return;
+ if (DEBUG) Log.d(TAG, "onSwitchChanged enabled=" + enabled);
+ mRule.enabled = enabled;
+ mRule.snoozing = false;
+ setZenModeConfig(mConfig);
+ }
+
+ protected void updateRule(Uri newConditionId) {
+ mRule.conditionId = newConditionId;
+ mRule.condition = null;
+ mRule.snoozing = false;
+ setZenModeConfig(mConfig);
+ }
+
+ @Override
+ protected void onZenModeChanged() {
+ // noop
+ }
+
+ @Override
+ protected void onZenModeConfigChanged() {
+ if (!refreshRuleOrFinish()) {
+ updateControls();
+ }
+ }
+
+ @Override
+ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ if (DEBUG) Log.d(TAG, "onCreateOptionsMenu");
+ inflater.inflate(R.menu.zen_mode_rule, menu);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ if (DEBUG) Log.d(TAG, "onOptionsItemSelected " + item.getItemId());
+ if (item.getItemId() == R.id.delete) {
+ showDeleteRuleDialog();
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ private void showRuleNameDialog() {
+ new ZenRuleNameDialog(mContext, null, mRule.name, mConfig.getAutomaticRuleNames()) {
+ @Override
+ public void onOk(String ruleName, RuleInfo type) {
+ final ZenModeConfig newConfig = mConfig.copy();
+ final ZenRule rule = newConfig.automaticRules.get(mRuleId);
+ if (rule == null) return;
+ rule.name = ruleName;
+ setZenModeConfig(newConfig);
+ }
+ }.show();
+ }
+
+ private boolean refreshRuleOrFinish() {
+ mRule = mConfig.automaticRules.get(mRuleId);
+ if (DEBUG) Log.d(TAG, "mRule=" + mRule);
+ if (!setRule(mRule)) {
+ toastAndFinish();
+ return true;
+ }
+ return false;
+ }
+
+ private void showDeleteRuleDialog() {
+ new AlertDialog.Builder(mContext)
+ .setMessage(getString(R.string.zen_mode_delete_rule_confirmation, mRule.name))
+ .setNegativeButton(R.string.cancel, null)
+ .setPositiveButton(R.string.zen_mode_delete_rule_button, new OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ mDeleting = true;
+ mConfig.automaticRules.remove(mRuleId);
+ setZenModeConfig(mConfig);
+ }
+ })
+ .show();
+ }
+
+ private void toastAndFinish() {
+ if (!mDeleting) {
+ Toast.makeText(mContext, R.string.zen_mode_rule_not_found_text, Toast.LENGTH_SHORT)
+ .show();
+ }
+ getActivity().finish();
+ }
+
+ private void updateRuleName() {
+ getActivity().setTitle(mRule.name);
+ mRuleName.setSummary(mRule.name);
+ }
+
+ private void updateControls() {
+ mDisableListeners = true;
+ updateRuleName();
+ updateControlsInternal();
+ mZenMode.setSelectedValue(mRule.zenMode);
+ mDisableListeners = false;
+ if (mSwitchBar != null) {
+ mSwitchBar.setChecked(mRule.enabled);
+ }
+ }
+
+}
diff --git a/src/com/android/settings/notification/ZenModeScheduleRuleSettings.java b/src/com/android/settings/notification/ZenModeScheduleRuleSettings.java
index f0f0294..f7015d3 100644
--- a/src/com/android/settings/notification/ZenModeScheduleRuleSettings.java
+++ b/src/com/android/settings/notification/ZenModeScheduleRuleSettings.java
@@ -25,141 +25,58 @@ import android.app.FragmentManager;
import android.app.TimePickerDialog;
import android.content.Context;
import android.content.DialogInterface;
-import android.content.DialogInterface.OnClickListener;
import android.content.DialogInterface.OnDismissListener;
-import android.content.Intent;
import android.os.Bundle;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceClickListener;
import android.preference.PreferenceScreen;
import android.provider.Settings;
-import android.provider.Settings.Global;
import android.service.notification.ZenModeConfig;
import android.service.notification.ZenModeConfig.ScheduleInfo;
import android.service.notification.ZenModeConfig.ZenRule;
import android.text.format.DateFormat;
import android.util.Log;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
-import android.widget.Switch;
import android.widget.TimePicker;
-import android.widget.Toast;
import com.android.internal.logging.MetricsLogger;
-import com.android.settings.DropDownPreference;
import com.android.settings.R;
-import com.android.settings.SettingsActivity;
-import com.android.settings.widget.SwitchBar;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
-public class ZenModeScheduleRuleSettings extends ZenModeSettingsBase
- implements SwitchBar.OnSwitchChangeListener {
- private static final String TAG = ZenModeSettingsBase.TAG;
- private static final boolean DEBUG = ZenModeSettingsBase.DEBUG;
-
- private static final String KEY_RULE_NAME = "rule_name";
+public class ZenModeScheduleRuleSettings extends ZenModeRuleSettingsBase {
private static final String KEY_DAYS = "days";
private static final String KEY_START_TIME = "start_time";
private static final String KEY_END_TIME = "end_time";
- private static final String KEY_ZEN_MODE = "zen_mode";
private static final SimpleDateFormat DAY_FORMAT = new SimpleDateFormat("EEE");
public static final String ACTION = Settings.ACTION_ZEN_MODE_SCHEDULE_RULE_SETTINGS;
- public static final String EXTRA_RULE_ID = "rule_id";
- private Context mContext;
- private boolean mDisableListeners;
- private SwitchBar mSwitchBar;
- private Preference mRuleName;
private Preference mDays;
private TimePickerPreference mStart;
private TimePickerPreference mEnd;
- private DropDownPreference mZenMode;
- private String mRuleId;
- private ZenRule mRule;
private ScheduleInfo mSchedule;
- private boolean mDeleting;
-
- @Override
- protected void onZenModeChanged() {
- // noop
- }
@Override
- protected void onZenModeConfigChanged() {
- if (!refreshRuleOrFinish()) {
- updateControls();
- }
- }
-
- private boolean refreshRuleOrFinish() {
- mRule = mConfig.automaticRules.get(mRuleId);
- if (DEBUG) Log.d(TAG, "mRule=" + mRule);
- mSchedule = mRule != null ? ZenModeConfig.tryParseScheduleConditionId(mRule.conditionId)
+ protected boolean setRule(ZenRule rule) {
+ mSchedule = rule != null ? ZenModeConfig.tryParseScheduleConditionId(rule.conditionId)
: null;
- if (mSchedule == null) {
- toastAndFinish();
- return true;
- }
- return false;
+ return mSchedule != null;
}
@Override
- public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
- if (DEBUG) Log.d(TAG, "onCreateOptionsMenu");
- inflater.inflate(R.menu.zen_mode_rule, menu);
+ protected String getZenModeDependency() {
+ return mDays.getKey();
}
@Override
- public boolean onOptionsItemSelected(MenuItem item) {
- if (DEBUG) Log.d(TAG, "onOptionsItemSelected " + item.getItemId());
- if (item.getItemId() == R.id.delete) {
- showDeleteRuleDialog();
- return true;
- }
- return super.onOptionsItemSelected(item);
- }
-
- @Override
- public void onCreate(Bundle icicle) {
- super.onCreate(icicle);
-
- mContext = getActivity();
-
- final Intent intent = getActivity().getIntent();
- if (DEBUG) Log.d(TAG, "onCreate getIntent()=" + intent);
- if (intent == null) {
- Log.w(TAG, "No intent");
- toastAndFinish();
- return;
- }
-
- mRuleId = intent.getStringExtra(EXTRA_RULE_ID);
- if (DEBUG) Log.d(TAG, "mRuleId=" + mRuleId);
- if (refreshRuleOrFinish()) {
- return;
- }
-
+ protected void onCreateInternal() {
addPreferencesFromResource(R.xml.zen_mode_schedule_rule_settings);
final PreferenceScreen root = getPreferenceScreen();
- setHasOptionsMenu(true);
-
- mRuleName = root.findPreference(KEY_RULE_NAME);
- mRuleName.setOnPreferenceClickListener(new OnPreferenceClickListener() {
- @Override
- public boolean onPreferenceClick(Preference preference) {
- showRuleNameDialog();
- return true;
- }
- });
-
mDays = root.findPreference(KEY_DAYS);
mDays.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
@@ -186,10 +103,7 @@ public class ZenModeScheduleRuleSettings extends ZenModeSettingsBase
if (DEBUG) Log.d(TAG, "onPrefChange start h=" + hour + " m=" + minute);
mSchedule.startHour = hour;
mSchedule.startMinute = minute;
- mRule.conditionId = ZenModeConfig.toScheduleConditionId(mSchedule);
- mRule.condition = null;
- mRule.snoozing = false;
- setZenModeConfig(mConfig);
+ updateRule(ZenModeConfig.toScheduleConditionId(mSchedule));
return true;
}
});
@@ -211,63 +125,12 @@ public class ZenModeScheduleRuleSettings extends ZenModeSettingsBase
if (DEBUG) Log.d(TAG, "onPrefChange end h=" + hour + " m=" + minute);
mSchedule.endHour = hour;
mSchedule.endMinute = minute;
- mRule.conditionId = ZenModeConfig.toScheduleConditionId(mSchedule);
- mRule.condition = null;
- mRule.snoozing = false;
- setZenModeConfig(mConfig);
+ updateRule(ZenModeConfig.toScheduleConditionId(mSchedule));
return true;
}
});
root.addPreference(mEnd);
mEnd.setDependency(mDays.getKey());
-
- mZenMode = (DropDownPreference) root.findPreference(KEY_ZEN_MODE);
- mZenMode.addItem(R.string.zen_mode_option_important_interruptions, Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS);
- mZenMode.addItem(R.string.zen_mode_option_alarms, Global.ZEN_MODE_ALARMS);
- mZenMode.addItem(R.string.zen_mode_option_no_interruptions, Global.ZEN_MODE_NO_INTERRUPTIONS);
- mZenMode.setCallback(new DropDownPreference.Callback() {
- @Override
- public boolean onItemSelected(int pos, Object value) {
- if (mDisableListeners) return true;
- final int zenMode = (Integer) value;
- if (zenMode == mRule.zenMode) return true;
- if (DEBUG) Log.d(TAG, "onPrefChange zenMode=" + zenMode);
- mRule.zenMode = zenMode;
- setZenModeConfig(mConfig);
- return true;
- }
- });
- mZenMode.setOrder(10); // sort at the bottom of the category
- mZenMode.setDependency(mDays.getKey());
- }
-
- @Override
- public void onActivityCreated(Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
-
- final SettingsActivity activity = (SettingsActivity) getActivity();
- mSwitchBar = activity.getSwitchBar();
- mSwitchBar.addOnSwitchChangeListener(this);
- mSwitchBar.show();
- }
-
- @Override
- public void onDestroyView() {
- super.onDestroyView();
- mSwitchBar.removeOnSwitchChangeListener(this);
- mSwitchBar.hide();
- }
-
- @Override
- public void onSwitchChanged(Switch switchView, boolean isChecked) {
- if (DEBUG) Log.d(TAG, "onSwitchChanged " + isChecked);
- if (mDisableListeners) return;
- final boolean enabled = isChecked;
- if (enabled == mRule.enabled) return;
- if (DEBUG) Log.d(TAG, "onSwitchChanged enabled=" + enabled);
- mRule.enabled = enabled;
- mRule.snoozing = false;
- setZenModeConfig(mConfig);
}
private void updateDays() {
@@ -308,28 +171,11 @@ public class ZenModeScheduleRuleSettings extends ZenModeSettingsBase
}
@Override
- public void onResume() {
- super.onResume();
- updateControls();
- }
-
- private void updateRuleName() {
- getActivity().setTitle(mRule.name);
- mRuleName.setSummary(mRule.name);
- }
-
- private void updateControls() {
- mDisableListeners = true;
- updateRuleName();
+ protected void updateControlsInternal() {
updateDays();
mStart.setTime(mSchedule.startHour, mSchedule.startMinute);
mEnd.setTime(mSchedule.endHour, mSchedule.endMinute);
- mZenMode.setSelectedValue(mRule.zenMode);
- mDisableListeners = false;
updateEndSummary();
- if (mSwitchBar != null) {
- mSwitchBar.setChecked(mRule.enabled);
- }
}
@Override
@@ -337,34 +183,6 @@ public class ZenModeScheduleRuleSettings extends ZenModeSettingsBase
return MetricsLogger.NOTIFICATION_ZEN_MODE_SCHEDULE_RULE;
}
- private void showDeleteRuleDialog() {
- new AlertDialog.Builder(mContext)
- .setMessage(getString(R.string.zen_mode_delete_rule_confirmation, mRule.name))
- .setNegativeButton(R.string.cancel, null)
- .setPositiveButton(R.string.zen_mode_delete_rule_button, new OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- mDeleting = true;
- mConfig.automaticRules.remove(mRuleId);
- setZenModeConfig(mConfig);
- }
- })
- .show();
- }
-
- private void showRuleNameDialog() {
- new ZenRuleNameDialog(mContext, mRule.name, mConfig.getAutomaticRuleNames()) {
- @Override
- public void onOk(String ruleName) {
- final ZenModeConfig newConfig = mConfig.copy();
- final ZenRule rule = newConfig.automaticRules.get(mRuleId);
- if (rule == null) return;
- rule.name = ruleName;
- setZenModeConfig(newConfig);
- }
- }.show();
- }
-
private void showDaysDialog() {
new AlertDialog.Builder(mContext)
.setTitle(R.string.zen_mode_schedule_rule_days)
@@ -375,10 +193,7 @@ public class ZenModeScheduleRuleSettings extends ZenModeSettingsBase
if (Arrays.equals(days, mSchedule.days)) return;
if (DEBUG) Log.d(TAG, "days.onChanged days=" + Arrays.asList(days));
mSchedule.days = days;
- mRule.conditionId = ZenModeConfig.toScheduleConditionId(mSchedule);
- mRule.condition = null;
- mRule.snoozing = false;
- setZenModeConfig(mConfig);
+ updateRule(ZenModeConfig.toScheduleConditionId(mSchedule));
}
})
.setOnDismissListener(new OnDismissListener() {
@@ -391,14 +206,6 @@ public class ZenModeScheduleRuleSettings extends ZenModeSettingsBase
.show();
}
- private void toastAndFinish() {
- if (!mDeleting) {
- Toast.makeText(mContext, R.string.zen_mode_rule_not_found_text, Toast.LENGTH_SHORT)
- .show();
- }
- getActivity().finish();
- }
-
private static class TimePickerPreference extends Preference {
private final Context mContext;
@@ -474,4 +281,5 @@ public class ZenModeScheduleRuleSettings extends ZenModeSettingsBase
boolean onSetTime(int hour, int minute);
}
}
+
}
diff --git a/src/com/android/settings/notification/ZenRuleNameDialog.java b/src/com/android/settings/notification/ZenRuleNameDialog.java
index b0eaaec..8b44e46 100644
--- a/src/com/android/settings/notification/ZenRuleNameDialog.java
+++ b/src/com/android/settings/notification/ZenRuleNameDialog.java
@@ -17,35 +17,71 @@
package com.android.settings.notification;
import android.app.AlertDialog;
+import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
+import android.content.DialogInterface.OnDismissListener;
+import android.content.pm.ServiceInfo;
+import android.net.Uri;
+import android.service.notification.ZenModeConfig;
+import android.service.notification.ZenModeConfig.ScheduleInfo;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.ArraySet;
+import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.EditText;
+import android.widget.RadioButton;
+import android.widget.RadioGroup;
import com.android.settings.R;
+import java.util.List;
+
public abstract class ZenRuleNameDialog {
+ private static final String TAG = ZenModeSettings.TAG;
+ private static final boolean DEBUG = ZenModeSettings.DEBUG;
+
private final AlertDialog mDialog;
private final EditText mEditText;
+ private final RadioGroup mTypes;
private final ArraySet<String> mExistingNames;
+ private final ServiceListing mServiceListing;
+ private final RuleInfo[] mExternalRules = new RuleInfo[3];
- public ZenRuleNameDialog(Context context, String ruleName, ArraySet<String> existingNames) {
+ public ZenRuleNameDialog(Context context, ServiceListing serviceListing, String ruleName,
+ ArraySet<String> existingNames) {
+ mServiceListing = serviceListing;
final View v = LayoutInflater.from(context).inflate(R.layout.zen_rule_name, null, false);
mEditText = (EditText) v.findViewById(R.id.rule_name);
- mEditText.setText(ruleName);
+ if (ruleName != null) {
+ mEditText.setText(ruleName);
+ }
mEditText.setSelectAllOnFocus(true);
+ mTypes = (RadioGroup) v.findViewById(R.id.rule_types);
+ if (mServiceListing != null) {
+ bindType(R.id.rule_type_schedule, defaultNewSchedule());
+ bindExternalRules();
+ mServiceListing.addCallback(mServiceListingCallback);
+ mServiceListing.reload();
+ }
mDialog = new AlertDialog.Builder(context)
.setTitle(R.string.zen_mode_rule_name)
.setView(v)
.setPositiveButton(R.string.okay, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
- onOk(trimmedText());
+ onOk(trimmedText(), selectedRuleInfo());
+ }
+ })
+ .setOnDismissListener(new OnDismissListener() {
+ @Override
+ public void onDismiss(DialogInterface dialog) {
+ if (mServiceListing != null) {
+ mServiceListing.removeCallback(mServiceListingCallback);
+ }
}
})
.setNegativeButton(R.string.cancel, null)
@@ -72,17 +108,37 @@ public abstract class ZenRuleNameDialog {
}
}
- abstract public void onOk(String ruleName);
-
- private String trimmedText() {
- return mEditText.getText() == null ? null : mEditText.getText().toString().trim();
- }
+ abstract public void onOk(String ruleName, RuleInfo ruleInfo);
public void show() {
mDialog.show();
updatePositiveButton();
}
+ private void bindType(int id, RuleInfo ri) {
+ final RadioButton rb = (RadioButton) mTypes.findViewById(id);
+ if (ri == null) {
+ rb.setVisibility(View.GONE);
+ return;
+ }
+ rb.setVisibility(View.VISIBLE);
+ if (ri.caption != null) {
+ rb.setText(ri.caption);
+ }
+ rb.setTag(ri);
+ }
+
+ private RuleInfo selectedRuleInfo() {
+ final int id = mTypes.getCheckedRadioButtonId();
+ if (id == -1) return null;
+ final RadioButton rb = (RadioButton) mTypes.findViewById(id);
+ return (RuleInfo) rb.getTag();
+ }
+
+ private String trimmedText() {
+ return mEditText.getText() == null ? null : mEditText.getText().toString().trim();
+ }
+
private void updatePositiveButton() {
final String name = trimmedText();
final boolean validName = !TextUtils.isEmpty(name)
@@ -90,4 +146,51 @@ public abstract class ZenRuleNameDialog {
mDialog.getButton(DialogInterface.BUTTON_POSITIVE).setEnabled(validName);
}
+ private static RuleInfo defaultNewSchedule() {
+ final ScheduleInfo schedule = new ScheduleInfo();
+ schedule.days = ZenModeConfig.ALL_DAYS;
+ schedule.startHour = 22;
+ schedule.endHour = 7;
+ final RuleInfo rt = new RuleInfo();
+ rt.settingsAction = ZenModeScheduleRuleSettings.ACTION;
+ rt.defaultConditionId = ZenModeConfig.toScheduleConditionId(schedule);
+ return rt;
+ }
+
+ private void bindExternalRules() {
+ bindType(R.id.rule_type_2, mExternalRules[0]);
+ bindType(R.id.rule_type_3, mExternalRules[1]);
+ bindType(R.id.rule_type_4, mExternalRules[2]);
+ // show radio group if we have at least one external rule type
+ mTypes.setVisibility(mExternalRules[0] != null ? View.VISIBLE : View.GONE);
+ }
+
+ private final ServiceListing.Callback mServiceListingCallback = new ServiceListing.Callback() {
+ @Override
+ public void onServicesReloaded(List<ServiceInfo> services) {
+ if (DEBUG) Log.d(TAG, "Services reloaded: count=" + services.size());
+ mExternalRules[0] = mExternalRules[1] = mExternalRules[2] = null;
+ int i = 0;
+ for (ServiceInfo si : services) {
+ final RuleInfo ri = ZenModeExternalRuleSettings.getRuleInfo(si);
+ if (ri != null) {
+ mExternalRules[i] = ri;
+ i++;
+ if (i == mExternalRules.length) {
+ break;
+ }
+ }
+ }
+ bindExternalRules();
+ }
+ };
+
+ public static class RuleInfo {
+ public String caption;
+ public String settingsAction;
+ public Uri defaultConditionId;
+ public ComponentName serviceComponent;
+ public ComponentName configurationActivity;
+ }
+
} \ No newline at end of file