diff options
author | John Spurlock <jspurlock@google.com> | 2015-04-09 12:50:04 -0400 |
---|---|---|
committer | John Spurlock <jspurlock@google.com> | 2015-04-09 20:56:16 -0400 |
commit | 45fa140b8c6846b4546fdeabebf989ae9102cebb (patch) | |
tree | ddebdae6ced30e4be858c4381c7c029e132dfa4a /src/com/android | |
parent | 342d08537fe316f0d046a3a3097c294e4b30e912 (diff) | |
download | packages_apps_Settings-45fa140b8c6846b4546fdeabebf989ae9102cebb.zip packages_apps_Settings-45fa140b8c6846b4546fdeabebf989ae9102cebb.tar.gz packages_apps_Settings-45fa140b8c6846b4546fdeabebf989ae9102cebb.tar.bz2 |
Settings: An update on Downtime.
- Migrate settings to the new zen mode state model.
- Remove downtime settings.
- Add automatic rule management page (add/remove)
- Bind new automatic schedule rules to detail editor.
- Clean up a few found miscapitalized string captions.
- Migrate zen switch to report the shared summary string.
Bug: 20064962
Change-Id: Ia561e7f77c90c962729240b4d51ba1915297f64a
Diffstat (limited to 'src/com/android')
-rw-r--r-- | src/com/android/settings/Settings.java | 1 | ||||
-rw-r--r-- | src/com/android/settings/SettingsActivity.java | 4 | ||||
-rw-r--r-- | src/com/android/settings/notification/ZenModeAutomaticConditionSelection.java | 157 | ||||
-rw-r--r-- | src/com/android/settings/notification/ZenModeAutomationSettings.java | 456 | ||||
-rw-r--r-- | src/com/android/settings/notification/ZenModeConditionSelection.java | 7 | ||||
-rw-r--r-- | src/com/android/settings/notification/ZenModeScheduleDaysSelection.java (renamed from src/com/android/settings/notification/ZenModeDowntimeDaysSelection.java) | 46 | ||||
-rw-r--r-- | src/com/android/settings/notification/ZenModeScheduleRuleSettings.java | 477 | ||||
-rw-r--r-- | src/com/android/settings/notification/ZenModeSettings.java | 47 | ||||
-rw-r--r-- | src/com/android/settings/notification/ZenModeSettingsBase.java | 39 | ||||
-rw-r--r-- | src/com/android/settings/notification/ZenRuleNameDialog.java | 93 | ||||
-rw-r--r-- | src/com/android/settings/search/SearchIndexableResources.java | 12 |
11 files changed, 706 insertions, 633 deletions
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java index 70455a4..b58159e 100644 --- a/src/com/android/settings/Settings.java +++ b/src/com/android/settings/Settings.java @@ -96,6 +96,7 @@ public class Settings extends SettingsActivity { public static class ZenModeSettingsActivity extends SettingsActivity { /* empty */ } public static class ZenModePrioritySettingsActivity extends SettingsActivity { /* empty */ } public static class ZenModeAutomationSettingsActivity extends SettingsActivity { /* empty */ } + public static class ZenModeScheduleRuleSettingsActivity 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 0973b14..24209b0 100644 --- a/src/com/android/settings/SettingsActivity.java +++ b/src/com/android/settings/SettingsActivity.java @@ -100,6 +100,7 @@ import com.android.settings.notification.NotificationSettings; import com.android.settings.notification.NotificationStation; import com.android.settings.notification.OtherSoundSettings; import com.android.settings.notification.ZenModeSettings; +import com.android.settings.notification.ZenModeScheduleRuleSettings; import com.android.settings.print.PrintJobSettingsFragment; import com.android.settings.print.PrintSettingsFragment; import com.android.settings.search.DynamicIndexableContentMonitor; @@ -332,7 +333,8 @@ public class SettingsActivity extends Activity AppNotificationSettings.class.getName(), OtherSoundSettings.class.getName(), ApnSettings.class.getName(), - WifiCallingSettings.class.getName() + WifiCallingSettings.class.getName(), + ZenModeScheduleRuleSettings.class.getName(), }; diff --git a/src/com/android/settings/notification/ZenModeAutomaticConditionSelection.java b/src/com/android/settings/notification/ZenModeAutomaticConditionSelection.java deleted file mode 100644 index 0e77632..0000000 --- a/src/com/android/settings/notification/ZenModeAutomaticConditionSelection.java +++ /dev/null @@ -1,157 +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.animation.LayoutTransition; -import android.app.INotificationManager; -import android.content.Context; -import android.net.Uri; -import android.os.Handler; -import android.os.Message; -import android.os.RemoteException; -import android.os.ServiceManager; -import android.service.notification.Condition; -import android.service.notification.IConditionListener; -import android.util.ArraySet; -import android.util.Log; -import android.widget.CheckBox; -import android.widget.CompoundButton; -import android.widget.LinearLayout; - -import com.android.settings.R; - -public class ZenModeAutomaticConditionSelection extends LinearLayout { - private static final String TAG = "ZenModeAutomaticConditionSelection"; - private static final boolean DEBUG = true; - - private final INotificationManager mNoMan; - private final H mHandler = new H(); - private final Context mContext; - private final ArraySet<Uri> mSelectedConditions = new ArraySet<Uri>(); - - public ZenModeAutomaticConditionSelection(Context context) { - super(context); - mContext = context; - setOrientation(VERTICAL); - setLayoutTransition(new LayoutTransition()); - final int p = mContext.getResources().getDimensionPixelSize(R.dimen.content_margin_left); - setPadding(p, p, p, 0); - mNoMan = INotificationManager.Stub.asInterface( - ServiceManager.getService(Context.NOTIFICATION_SERVICE)); - refreshSelectedConditions(); - } - - private void refreshSelectedConditions() { - try { - final Condition[] automatic = mNoMan.getAutomaticZenModeConditions(); - mSelectedConditions.clear(); - if (automatic != null) { - for (Condition c : automatic) { - mSelectedConditions.add(c.id); - } - } - } catch (RemoteException e) { - Log.w(TAG, "Error calling getAutomaticZenModeConditions", e); - } - } - - private CheckBox newCheckBox(Object tag) { - final CheckBox button = new CheckBox(mContext); - button.setTag(tag); - button.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { - @Override - public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - setSelectedCondition((Uri)button.getTag(), isChecked); - } - }); - addView(button); - return button; - } - - private void setSelectedCondition(Uri conditionId, boolean selected) { - if (DEBUG) Log.d(TAG, "setSelectedCondition conditionId=" + conditionId - + " selected=" + selected); - if (selected) { - mSelectedConditions.add(conditionId); - } else { - mSelectedConditions.remove(conditionId); - } - final Uri[] automatic = new Uri[mSelectedConditions.size()]; - for (int i = 0; i < automatic.length; i++) { - automatic[i] = mSelectedConditions.valueAt(i); - } - try { - mNoMan.setAutomaticZenModeConditions(automatic); - } catch (RemoteException e) { - Log.w(TAG, "Error calling setAutomaticZenModeConditions", e); - } - } - - @Override - protected void onAttachedToWindow() { - super.onAttachedToWindow(); - requestZenModeConditions(Condition.FLAG_RELEVANT_ALWAYS); - } - - @Override - protected void onDetachedFromWindow() { - super.onDetachedFromWindow(); - requestZenModeConditions(0 /*none*/); - } - - protected void requestZenModeConditions(int relevance) { - if (DEBUG) Log.d(TAG, "requestZenModeConditions " + Condition.relevanceToString(relevance)); - try { - mNoMan.requestZenModeConditions(mListener, relevance); - } catch (RemoteException e) { - Log.w(TAG, "Error calling requestZenModeConditions", e); - } - } - - protected void handleConditions(Condition[] conditions) { - for (final Condition c : conditions) { - CheckBox v = (CheckBox) findViewWithTag(c.id); - if (c.state != Condition.STATE_ERROR) { - if (v == null) { - v = newCheckBox(c.id); - } - } - if (v != null) { - v.setText(c.summary); - v.setEnabled(c.state != Condition.STATE_ERROR); - v.setChecked(mSelectedConditions.contains(c.id)); - } - } - } - - private final IConditionListener mListener = new IConditionListener.Stub() { - @Override - public void onConditionsReceived(Condition[] conditions) { - if (conditions == null || conditions.length == 0) return; - mHandler.obtainMessage(H.CONDITIONS, conditions).sendToTarget(); - } - }; - - private final class H extends Handler { - private static final int CONDITIONS = 1; - - @Override - public void handleMessage(Message msg) { - if (msg.what == CONDITIONS) handleConditions((Condition[])msg.obj); - } - } -} diff --git a/src/com/android/settings/notification/ZenModeAutomationSettings.java b/src/com/android/settings/notification/ZenModeAutomationSettings.java index 378643e..09de7d1 100644 --- a/src/com/android/settings/notification/ZenModeAutomationSettings.java +++ b/src/com/android/settings/notification/ZenModeAutomationSettings.java @@ -16,248 +16,76 @@ package com.android.settings.notification; -import static com.android.settings.notification.ZenModeDowntimeDaysSelection.DAYS; - -import android.app.AlertDialog; -import android.app.Dialog; -import android.app.DialogFragment; -import android.app.FragmentManager; -import android.app.INotificationManager; -import android.app.TimePickerDialog; -import android.content.Context; -import android.content.DialogInterface; -import android.content.DialogInterface.OnDismissListener; -import android.content.pm.PackageManager; -import android.content.res.Resources; +import android.content.Intent; import android.os.Bundle; -import android.os.ServiceManager; import android.preference.Preference; import android.preference.Preference.OnPreferenceClickListener; -import android.preference.PreferenceCategory; import android.preference.PreferenceScreen; -import android.service.notification.Condition; +import android.provider.Settings.Global; import android.service.notification.ZenModeConfig; -import android.text.format.DateFormat; +import android.service.notification.ZenModeConfig.ScheduleInfo; +import android.service.notification.ZenModeConfig.ZenRule; import android.util.Log; -import android.util.SparseArray; -import android.widget.TimePicker; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; import com.android.internal.logging.MetricsLogger; -import com.android.settings.DropDownPreference; import com.android.settings.R; -import com.android.settings.search.BaseSearchIndexProvider; -import com.android.settings.search.Indexable; -import com.android.settings.search.SearchIndexableRaw; - -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.List; -import java.util.Objects; - -public class ZenModeAutomationSettings extends ZenModeSettingsBase implements Indexable { - private static final String KEY_DOWNTIME = "downtime"; - 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_DOWNTIME_MODE = "downtime_mode"; - - private static final String KEY_AUTOMATION = "automation"; - private static final String KEY_ENTRY = "entry"; - private static final String KEY_CONDITION_PROVIDERS = "manage_condition_providers"; - - private static final SimpleDateFormat DAY_FORMAT = new SimpleDateFormat("EEE"); - - private PackageManager mPM; - private boolean mDisableListeners; - private boolean mDowntimeSupported; - private Preference mDays; - private TimePickerPreference mStart; - private TimePickerPreference mEnd; - private DropDownPreference mDowntimeMode; - private PreferenceCategory mAutomationCategory; - private Preference mEntry; - private Preference mConditionProviders; +public class ZenModeAutomationSettings extends ZenModeSettingsBase { @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); - mPM = mContext.getPackageManager(); + + setHasOptionsMenu(true); addPreferencesFromResource(R.xml.zen_mode_automation_settings); - final PreferenceScreen root = getPreferenceScreen(); + } - onCreateDowntimeSettings(root); + 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)); + } - mAutomationCategory = (PreferenceCategory) findPreference(KEY_AUTOMATION); - mEntry = findPreference(KEY_ENTRY); - mEntry.setOnPreferenceClickListener(new OnPreferenceClickListener() { - @Override - public boolean onPreferenceClick(Preference preference) { - new AlertDialog.Builder(mContext) - .setTitle(R.string.zen_mode_entry_conditions_title) - .setView(new ZenModeAutomaticConditionSelection(mContext)) - .setOnDismissListener(new OnDismissListener() { - @Override - public void onDismiss(DialogInterface dialog) { - refreshAutomationSection(); - } - }) - .setPositiveButton(R.string.dlg_ok, null) - .show(); - return true; - } - }); - mConditionProviders = findPreference(KEY_CONDITION_PROVIDERS); + @Override + public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + inflater.inflate(R.menu.zen_mode_automation, menu); } - private void onCreateDowntimeSettings(PreferenceScreen root) { - mDowntimeSupported = isDowntimeSupported(mContext); - if (!mDowntimeSupported) { - removePreference(KEY_DOWNTIME); - return; + @Override + public boolean onOptionsItemSelected(MenuItem item) { + if (item.getItemId() == R.id.add) { + showAddRuleDialog(); + return true; } - final PreferenceCategory downtime = (PreferenceCategory) findPreference(KEY_DOWNTIME); - mDays = downtime.findPreference(KEY_DAYS); - mDays.setOnPreferenceClickListener(new OnPreferenceClickListener() { - @Override - public boolean onPreferenceClick(Preference preference) { - new AlertDialog.Builder(mContext) - .setTitle(R.string.zen_mode_downtime_days) - .setView(new ZenModeDowntimeDaysSelection(mContext, mConfig.sleepMode) { - @Override - protected void onChanged(String mode) { - if (mDisableListeners) return; - if (Objects.equals(mode, mConfig.sleepMode)) return; - if (DEBUG) Log.d(TAG, "days.onChanged sleepMode=" + mode); - final ZenModeConfig newConfig = mConfig.copy(); - newConfig.sleepMode = mode; - setZenModeConfig(newConfig); - } - }) - .setOnDismissListener(new OnDismissListener() { - @Override - public void onDismiss(DialogInterface dialog) { - updateDays(); - } - }) - .setPositiveButton(R.string.done_button, null) - .show(); - return true; - } - }); - - final FragmentManager mgr = getFragmentManager(); - - mStart = new TimePickerPreference(mContext, mgr); - mStart.setKey(KEY_START_TIME); - mStart.setTitle(R.string.zen_mode_start_time); - mStart.setCallback(new TimePickerPreference.Callback() { - @Override - public boolean onSetTime(int hour, int minute) { - if (mDisableListeners) return true; - if (!ZenModeConfig.isValidHour(hour)) return false; - if (!ZenModeConfig.isValidMinute(minute)) return false; - if (hour == mConfig.sleepStartHour && minute == mConfig.sleepStartMinute) { - return true; - } - if (DEBUG) Log.d(TAG, "onPrefChange sleepStart h=" + hour + " m=" + minute); - final ZenModeConfig newConfig = mConfig.copy(); - newConfig.sleepStartHour = hour; - newConfig.sleepStartMinute = minute; - return setZenModeConfig(newConfig); - } - }); - downtime.addPreference(mStart); - mStart.setDependency(mDays.getKey()); - - mEnd = new TimePickerPreference(mContext, mgr); - mEnd.setKey(KEY_END_TIME); - mEnd.setTitle(R.string.zen_mode_end_time); - mEnd.setCallback(new TimePickerPreference.Callback() { - @Override - public boolean onSetTime(int hour, int minute) { - if (mDisableListeners) return true; - if (!ZenModeConfig.isValidHour(hour)) return false; - if (!ZenModeConfig.isValidMinute(minute)) return false; - if (hour == mConfig.sleepEndHour && minute == mConfig.sleepEndMinute) { - return true; - } - if (DEBUG) Log.d(TAG, "onPrefChange sleepEnd h=" + hour + " m=" + minute); - final ZenModeConfig newConfig = mConfig.copy(); - newConfig.sleepEndHour = hour; - newConfig.sleepEndMinute = minute; - return setZenModeConfig(newConfig); - } - }); - downtime.addPreference(mEnd); - mEnd.setDependency(mDays.getKey()); + return super.onOptionsItemSelected(item); + } - mDowntimeMode = (DropDownPreference) downtime.findPreference(KEY_DOWNTIME_MODE); - mDowntimeMode.addItem(R.string.zen_mode_downtime_mode_priority, false); - mDowntimeMode.addItem(R.string.zen_mode_downtime_mode_none, true); - mDowntimeMode.setCallback(new DropDownPreference.Callback() { + private void showAddRuleDialog() { + new ZenRuleNameDialog(mContext, "", mConfig.getAutomaticRuleNames()) { @Override - public boolean onItemSelected(int pos, Object value) { - if (mDisableListeners) return true; - final boolean sleepNone = value instanceof Boolean ? ((Boolean) value) : false; - if (mConfig == null || mConfig.sleepNone == sleepNone) return false; + public void onOk(String ruleName) { + final ScheduleInfo schedule = new ScheduleInfo(); + schedule.days = ZenModeConfig.ALL_DAYS; + schedule.startHour = 22; + schedule.endHour = 7; + final ZenRule rule = new ZenRule(); + rule.name = ruleName; + rule.enabled = true; + rule.zenMode = Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS; + rule.conditionId = ZenModeConfig.toScheduleConditionId(schedule); final ZenModeConfig newConfig = mConfig.copy(); - newConfig.sleepNone = sleepNone; - if (DEBUG) Log.d(TAG, "onPrefChange sleepNone=" + sleepNone); - return setZenModeConfig(newConfig); - } - }); - mDowntimeMode.setOrder(10); // sort at the bottom of the category - mDowntimeMode.setDependency(mDays.getKey()); - } - - private void updateDays() { - // Compute an ordered, delimited list of day names based on the persisted user config. - if (mConfig != null) { - final int[] days = ZenModeConfig.tryParseDays(mConfig.sleepMode); - if (days != null && days.length != 0) { - final StringBuilder sb = new StringBuilder(); - final Calendar c = Calendar.getInstance(); - for (int i = 0; i < DAYS.length; i++) { - final int day = DAYS[i]; - for (int j = 0; j < days.length; j++) { - if (day == days[j]) { - c.set(Calendar.DAY_OF_WEEK, day); - if (sb.length() > 0) { - sb.append(mContext.getString(R.string.summary_divider_text)); - } - sb.append(DAY_FORMAT.format(c.getTime())); - break; - } - } - } - if (sb.length() > 0) { - mDays.setSummary(sb); - mDays.notifyDependencyChange(false); - return; + final String ruleId = newConfig.newRuleId(); + newConfig.automaticRules.put(ruleId, rule); + if (setZenModeConfig(newConfig)) { + showRule(ruleId, rule.name); } } - } - mDays.setSummary(R.string.zen_mode_downtime_days_none); - mDays.notifyDependencyChange(true); - } - - private void updateEndSummary() { - if (!mDowntimeSupported) return; - final int startMin = 60 * mConfig.sleepStartHour + mConfig.sleepStartMinute; - final int endMin = 60 * mConfig.sleepEndHour + mConfig.sleepEndMinute; - final boolean nextDay = startMin >= endMin; - final int summaryFormat; - if (mConfig.sleepNone) { - summaryFormat = nextDay ? R.string.zen_mode_end_time_none_next_day_summary_format - : R.string.zen_mode_end_time_none_same_day_summary_format; - } else { - summaryFormat = nextDay ? R.string.zen_mode_end_time_priority_next_day_summary_format - : 0; - } - mEnd.setSummaryFormat(summaryFormat); + }.show(); } @Override @@ -277,188 +105,32 @@ public class ZenModeAutomationSettings extends ZenModeSettingsBase implements In } private void updateControls() { - mDisableListeners = true; - if (mDowntimeSupported) { - updateDays(); - mStart.setTime(mConfig.sleepStartHour, mConfig.sleepStartMinute); - mEnd.setTime(mConfig.sleepEndHour, mConfig.sleepEndMinute); - mDowntimeMode.setSelectedValue(mConfig.sleepNone); - } - mDisableListeners = false; - refreshAutomationSection(); - updateEndSummary(); - } - - @Override - protected int getMetricsCategory() { - return MetricsLogger.NOTIFICATION_ZEN_MODE_AUTOMATION; - } - - private void refreshAutomationSection() { - if (mConditionProviders != null) { - final int total = ConditionProviderSettings.getProviderCount(mPM); - if (total == 0) { - getPreferenceScreen().removePreference(mAutomationCategory); - } else { - final int n = ConditionProviderSettings.getEnabledProviderCount(mContext); - if (n == 0) { - mConditionProviders.setSummary(getResources().getString( - R.string.manage_condition_providers_summary_zero)); - } else { - mConditionProviders.setSummary(String.format(getResources().getQuantityString( - R.plurals.manage_condition_providers_summary_nonzero, - n, n))); - } - final String entrySummary = getEntryConditionSummary(); - if (n == 0 || entrySummary == null) { - mEntry.setSummary(R.string.zen_mode_entry_conditions_summary_none); - } else { - mEntry.setSummary(entrySummary); - } - } - } - } - - private String getEntryConditionSummary() { - final INotificationManager nm = INotificationManager.Stub.asInterface( - ServiceManager.getService(Context.NOTIFICATION_SERVICE)); - try { - final Condition[] automatic = nm.getAutomaticZenModeConditions(); - if (automatic == null || automatic.length == 0) { - return null; - } - final String divider = getString(R.string.summary_divider_text); - final StringBuilder sb = new StringBuilder(); - for (int i = 0; i < automatic.length; i++) { - if (i > 0) sb.append(divider); - sb.append(automatic[i].summary); - } - return sb.toString(); - } catch (Exception e) { - Log.w(TAG, "Error calling getAutomaticZenModeConditions", e); - return null; - } - } - - private static SparseArray<String> allKeyTitles(Context context) { - final SparseArray<String> rt = new SparseArray<String>(); - rt.put(R.string.zen_mode_downtime_category, KEY_DOWNTIME); - rt.put(R.string.zen_mode_downtime_days, KEY_DAYS); - rt.put(R.string.zen_mode_start_time, KEY_START_TIME); - rt.put(R.string.zen_mode_end_time, KEY_END_TIME); - rt.put(R.string.zen_mode_downtime_mode_title, KEY_DOWNTIME_MODE); - rt.put(R.string.zen_mode_automation_category, KEY_AUTOMATION); - rt.put(R.string.manage_condition_providers, KEY_CONDITION_PROVIDERS); - return rt; - } - - // Enable indexing of searchable data - public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = - new BaseSearchIndexProvider() { - - @Override - public List<SearchIndexableRaw> getRawDataToIndex(Context context, boolean enabled) { - final SparseArray<String> keyTitles = allKeyTitles(context); - final int N = keyTitles.size(); - final List<SearchIndexableRaw> result = new ArrayList<SearchIndexableRaw>(N); - final Resources res = context.getResources(); - for (int i = 0; i < N; i++) { - final SearchIndexableRaw data = new SearchIndexableRaw(context); - data.key = keyTitles.valueAt(i); - data.title = res.getString(keyTitles.keyAt(i)); - data.screenTitle = res.getString(R.string.zen_mode_automation_settings_title); - result.add(data); - } - return result; - } - - @Override - public List<String> getNonIndexableKeys(Context context) { - final ArrayList<String> rt = new ArrayList<String>(); - if (!isDowntimeSupported(context)) { - rt.add(KEY_DOWNTIME); - rt.add(KEY_DAYS); - rt.add(KEY_START_TIME); - rt.add(KEY_END_TIME); - rt.add(KEY_DOWNTIME_MODE); - } - return rt; - } - }; - - private static class TimePickerPreference extends Preference { - private final Context mContext; - - private int mSummaryFormat; - private int mHourOfDay; - private int mMinute; - private Callback mCallback; - - public TimePickerPreference(Context context, final FragmentManager mgr) { - super(context); - mContext = context; - setPersistent(false); - setOnPreferenceClickListener(new OnPreferenceClickListener(){ + 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 Preference p = new Preference(mContext); + p.setTitle(rule.name); + p.setSummary(rule.enabled ? R.string.switch_on_text : R.string.switch_off_text); + p.setPersistent(false); + p.setOnPreferenceClickListener(new OnPreferenceClickListener() { @Override public boolean onPreferenceClick(Preference preference) { - final TimePickerFragment frag = new TimePickerFragment(); - frag.pref = TimePickerPreference.this; - frag.show(mgr, TimePickerPreference.class.getName()); + showRule(id, rule.name); return true; } }); + root.addPreference(p); } + } - public void setCallback(Callback callback) { - mCallback = callback; - } - - public void setSummaryFormat(int resId) { - mSummaryFormat = resId; - updateSummary(); - } - - public void setTime(int hourOfDay, int minute) { - if (mCallback != null && !mCallback.onSetTime(hourOfDay, minute)) return; - mHourOfDay = hourOfDay; - mMinute = minute; - updateSummary(); - } - - private void updateSummary() { - final Calendar c = Calendar.getInstance(); - c.set(Calendar.HOUR_OF_DAY, mHourOfDay); - c.set(Calendar.MINUTE, mMinute); - String time = DateFormat.getTimeFormat(mContext).format(c.getTime()); - if (mSummaryFormat != 0) { - time = mContext.getResources().getString(mSummaryFormat, time); - } - setSummary(time); - } - - public static class TimePickerFragment extends DialogFragment implements - TimePickerDialog.OnTimeSetListener { - public TimePickerPreference pref; - - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - final boolean usePref = pref != null && pref.mHourOfDay >= 0 && pref.mMinute >= 0; - final Calendar c = Calendar.getInstance(); - final int hour = usePref ? pref.mHourOfDay : c.get(Calendar.HOUR_OF_DAY); - final int minute = usePref ? pref.mMinute : c.get(Calendar.MINUTE); - return new TimePickerDialog(getActivity(), this, hour, minute, - DateFormat.is24HourFormat(getActivity())); - } - - public void onTimeSet(TimePicker view, int hourOfDay, int minute) { - if (pref != null) { - pref.setTime(hourOfDay, minute); - } - } - } - - public interface Callback { - boolean onSetTime(int hour, int minute); - } + @Override + protected int getMetricsCategory() { + return MetricsLogger.NOTIFICATION_ZEN_MODE_AUTOMATION; } + } diff --git a/src/com/android/settings/notification/ZenModeConditionSelection.java b/src/com/android/settings/notification/ZenModeConditionSelection.java index 9beea0a..481bd88 100644 --- a/src/com/android/settings/notification/ZenModeConditionSelection.java +++ b/src/com/android/settings/notification/ZenModeConditionSelection.java @@ -45,11 +45,14 @@ public class ZenModeConditionSelection extends RadioGroup { private final H mHandler = new H(); private final Context mContext; private final List<Condition> mConditions; + private final int mZenMode; + private Condition mCondition; - public ZenModeConditionSelection(Context context) { + public ZenModeConditionSelection(Context context, int zenMode) { super(context); mContext = context; + mZenMode = zenMode; mConditions = new ArrayList<Condition>(); setLayoutTransition(new LayoutTransition()); final int p = mContext.getResources().getDimensionPixelSize(R.dimen.content_margin_left); @@ -130,7 +133,7 @@ public class ZenModeConditionSelection extends RadioGroup { public void confirmCondition() { if (DEBUG) Log.d(TAG, "confirmCondition " + mCondition); try { - mNoMan.setZenModeCondition(mCondition); + mNoMan.setZenMode(mZenMode, mCondition != null ? mCondition.id : null, TAG); } catch (RemoteException e) { // noop } diff --git a/src/com/android/settings/notification/ZenModeDowntimeDaysSelection.java b/src/com/android/settings/notification/ZenModeScheduleDaysSelection.java index 3361ad0..6d11ffb 100644 --- a/src/com/android/settings/notification/ZenModeDowntimeDaysSelection.java +++ b/src/com/android/settings/notification/ZenModeScheduleDaysSelection.java @@ -17,37 +17,42 @@ package com.android.settings.notification; import android.content.Context; -import android.service.notification.ZenModeConfig; import android.util.SparseBooleanArray; import android.view.LayoutInflater; import android.widget.CheckBox; import android.widget.CompoundButton; -import android.widget.ScrollView; import android.widget.CompoundButton.OnCheckedChangeListener; import android.widget.LinearLayout; +import android.widget.ScrollView; import com.android.settings.R; import java.text.SimpleDateFormat; +import java.util.Arrays; import java.util.Calendar; -public class ZenModeDowntimeDaysSelection extends ScrollView { +public class ZenModeScheduleDaysSelection extends ScrollView { public static final int[] DAYS = { - Calendar.MONDAY, Calendar.TUESDAY, Calendar.WEDNESDAY, Calendar.THURSDAY, Calendar.FRIDAY, - Calendar.SATURDAY, Calendar.SUNDAY + Calendar.SUNDAY, + Calendar.MONDAY, + Calendar.TUESDAY, + Calendar.WEDNESDAY, + Calendar.THURSDAY, + Calendar.FRIDAY, + Calendar.SATURDAY, }; private static final SimpleDateFormat DAY_FORMAT = new SimpleDateFormat("EEEE"); private final SparseBooleanArray mDays = new SparseBooleanArray(); private final LinearLayout mLayout; - public ZenModeDowntimeDaysSelection(Context context, String mode) { + public ZenModeScheduleDaysSelection(Context context, int[] days) { super(context); mLayout = new LinearLayout(mContext); - final int hPad = context.getResources().getDimensionPixelSize(R.dimen.zen_downtime_margin); + final int hPad = context.getResources() + .getDimensionPixelSize(R.dimen.zen_schedule_day_margin); mLayout.setPadding(hPad, 0, hPad, 0); addView(mLayout); - final int[] days = ZenModeConfig.tryParseDays(mode); if (days != null) { for (int i = 0; i < days.length; i++) { mDays.put(days[i], true); @@ -58,7 +63,7 @@ public class ZenModeDowntimeDaysSelection extends ScrollView { final LayoutInflater inflater = LayoutInflater.from(context); for (int i = 0; i < DAYS.length; i++) { final int day = DAYS[i]; - final CheckBox checkBox = (CheckBox) inflater.inflate(R.layout.zen_downtime_day, + final CheckBox checkBox = (CheckBox) inflater.inflate(R.layout.zen_schedule_rule_day, this, false); c.set(Calendar.DAY_OF_WEEK, day); checkBox.setText(DAY_FORMAT.format(c.getTime())); @@ -67,30 +72,29 @@ public class ZenModeDowntimeDaysSelection extends ScrollView { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { mDays.put(day, isChecked); - onChanged(getMode()); + onChanged(getDays()); } }); mLayout.addView(checkBox); } } - private String getMode() { - final StringBuilder sb = new StringBuilder(ZenModeConfig.SLEEP_MODE_DAYS_PREFIX); - boolean empty = true; + private int[] getDays() { + final SparseBooleanArray rt = new SparseBooleanArray(mDays.size()); for (int i = 0; i < mDays.size(); i++) { final int day = mDays.keyAt(i); if (!mDays.valueAt(i)) continue; - if (empty) { - empty = false; - } else { - sb.append(','); - } - sb.append(day); + rt.put(day, true); + } + final int[] rta = new int[rt.size()]; + for (int i = 0; i < rta.length; i++) { + rta[i] = rt.keyAt(i); } - return empty ? null : sb.toString(); + Arrays.sort(rta); + return rta; } - protected void onChanged(String mode) { + protected void onChanged(int[] days) { // event hook for subclasses } } diff --git a/src/com/android/settings/notification/ZenModeScheduleRuleSettings.java b/src/com/android/settings/notification/ZenModeScheduleRuleSettings.java new file mode 100644 index 0000000..7bec3c4 --- /dev/null +++ b/src/com/android/settings/notification/ZenModeScheduleRuleSettings.java @@ -0,0 +1,477 @@ +/* + * 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 static com.android.settings.notification.ZenModeScheduleDaysSelection.DAYS; + +import android.app.AlertDialog; +import android.app.Dialog; +import android.app.DialogFragment; +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"; + 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) + : null; + if (mSchedule == null) { + toastAndFinish(); + return true; + } + return false; + } + + @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); + } + + @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; + } + + 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 + public boolean onPreferenceClick(Preference preference) { + showDaysDialog(); + return true; + } + }); + + final FragmentManager mgr = getFragmentManager(); + + mStart = new TimePickerPreference(mContext, mgr); + mStart.setKey(KEY_START_TIME); + mStart.setTitle(R.string.zen_mode_start_time); + mStart.setCallback(new TimePickerPreference.Callback() { + @Override + public boolean onSetTime(final int hour, final int minute) { + if (mDisableListeners) return true; + if (!ZenModeConfig.isValidHour(hour)) return false; + if (!ZenModeConfig.isValidMinute(minute)) return false; + if (hour == mSchedule.startHour && minute == mSchedule.startMinute) { + return true; + } + 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); + return true; + } + }); + root.addPreference(mStart); + mStart.setDependency(mDays.getKey()); + + mEnd = new TimePickerPreference(mContext, mgr); + mEnd.setKey(KEY_END_TIME); + mEnd.setTitle(R.string.zen_mode_end_time); + mEnd.setCallback(new TimePickerPreference.Callback() { + @Override + public boolean onSetTime(final int hour, final int minute) { + if (mDisableListeners) return true; + if (!ZenModeConfig.isValidHour(hour)) return false; + if (!ZenModeConfig.isValidMinute(minute)) return false; + if (hour == mSchedule.endHour && minute == mSchedule.endMinute) { + return true; + } + if (DEBUG) Log.d(TAG, "onPrefChange end h=" + hour + " m=" + minute); + mSchedule.startHour = hour; + mSchedule.startMinute = minute; + mRule.conditionId = ZenModeConfig.toScheduleConditionId(mSchedule); + mRule.condition = null; + mRule.snoozing = false; + setZenModeConfig(mConfig); + 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() { + // Compute an ordered, delimited list of day names based on the persisted user config. + final int[] days = mSchedule.days; + if (days != null && days.length > 0) { + final StringBuilder sb = new StringBuilder(); + final Calendar c = Calendar.getInstance(); + for (int i = 0; i < DAYS.length; i++) { + final int day = DAYS[i]; + for (int j = 0; j < days.length; j++) { + if (day == days[j]) { + c.set(Calendar.DAY_OF_WEEK, day); + if (sb.length() > 0) { + sb.append(mContext.getString(R.string.summary_divider_text)); + } + sb.append(DAY_FORMAT.format(c.getTime())); + break; + } + } + } + if (sb.length() > 0) { + mDays.setSummary(sb); + mDays.notifyDependencyChange(false); + return; + } + } + mDays.setSummary(R.string.zen_mode_schedule_rule_days_none); + mDays.notifyDependencyChange(true); + } + + private void updateEndSummary() { + final int startMin = 60 * mSchedule.startHour + mSchedule.startMinute; + final int endMin = 60 * mSchedule.endHour + mSchedule.endMinute; + final boolean nextDay = startMin >= endMin; + final int summaryFormat = nextDay ? R.string.zen_mode_end_time_next_day_summary_format : 0; + mEnd.setSummaryFormat(summaryFormat); + } + + @Override + public void onResume() { + super.onResume(); + updateControls(); + } + + private void updateRuleName() { + getActivity().setTitle(mRule.name); + mRuleName.setSummary(mRule.name); + } + + private void updateControls() { + mDisableListeners = true; + updateRuleName(); + 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 + protected int getMetricsCategory() { + 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) + .setView(new ZenModeScheduleDaysSelection(mContext, mSchedule.days) { + @Override + protected void onChanged(final int[] days) { + if (mDisableListeners) return; + 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); + } + }) + .setOnDismissListener(new OnDismissListener() { + @Override + public void onDismiss(DialogInterface dialog) { + updateDays(); + } + }) + .setPositiveButton(R.string.done_button, null) + .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; + + private int mSummaryFormat; + private int mHourOfDay; + private int mMinute; + private Callback mCallback; + + public TimePickerPreference(Context context, final FragmentManager mgr) { + super(context); + mContext = context; + setPersistent(false); + setOnPreferenceClickListener(new OnPreferenceClickListener(){ + @Override + public boolean onPreferenceClick(Preference preference) { + final TimePickerFragment frag = new TimePickerFragment(); + frag.pref = TimePickerPreference.this; + frag.show(mgr, TimePickerPreference.class.getName()); + return true; + } + }); + } + + public void setCallback(Callback callback) { + mCallback = callback; + } + + public void setSummaryFormat(int resId) { + mSummaryFormat = resId; + updateSummary(); + } + + public void setTime(int hourOfDay, int minute) { + if (mCallback != null && !mCallback.onSetTime(hourOfDay, minute)) return; + mHourOfDay = hourOfDay; + mMinute = minute; + updateSummary(); + } + + private void updateSummary() { + final Calendar c = Calendar.getInstance(); + c.set(Calendar.HOUR_OF_DAY, mHourOfDay); + c.set(Calendar.MINUTE, mMinute); + String time = DateFormat.getTimeFormat(mContext).format(c.getTime()); + if (mSummaryFormat != 0) { + time = mContext.getResources().getString(mSummaryFormat, time); + } + setSummary(time); + } + + public static class TimePickerFragment extends DialogFragment implements + TimePickerDialog.OnTimeSetListener { + public TimePickerPreference pref; + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + final boolean usePref = pref != null && pref.mHourOfDay >= 0 && pref.mMinute >= 0; + final Calendar c = Calendar.getInstance(); + final int hour = usePref ? pref.mHourOfDay : c.get(Calendar.HOUR_OF_DAY); + final int minute = usePref ? pref.mMinute : c.get(Calendar.MINUTE); + return new TimePickerDialog(getActivity(), this, hour, minute, + DateFormat.is24HourFormat(getActivity())); + } + + public void onTimeSet(TimePicker view, int hourOfDay, int minute) { + if (pref != null) { + pref.setTime(hourOfDay, minute); + } + } + } + + public interface Callback { + boolean onSetTime(int hour, int minute); + } + } +} diff --git a/src/com/android/settings/notification/ZenModeSettings.java b/src/com/android/settings/notification/ZenModeSettings.java index f519796..4ff5e0f 100644 --- a/src/com/android/settings/notification/ZenModeSettings.java +++ b/src/com/android/settings/notification/ZenModeSettings.java @@ -21,10 +21,12 @@ import android.content.Context; import android.content.DialogInterface; import android.content.res.Resources; import android.os.Bundle; +import android.os.UserHandle; import android.preference.Preference; import android.preference.PreferenceScreen; import android.provider.Settings.Global; import android.service.notification.Condition; +import android.service.notification.ZenModeConfig; import android.text.TextUtils; import android.util.Log; import android.util.SparseArray; @@ -51,6 +53,7 @@ public class ZenModeSettings extends ZenModeSettingsBase private AlertDialog mDialog; private SwitchBar mSwitchBar; private boolean mShowing; + private boolean mUpdatingControls; @Override public void onCreate(Bundle savedInstanceState) { @@ -60,7 +63,7 @@ public class ZenModeSettings extends ZenModeSettingsBase final PreferenceScreen root = getPreferenceScreen(); mPrioritySettings = root.findPreference(KEY_PRIORITY_SETTINGS); - if (!isDowntimeSupported(mContext)) { + if (!isScheduleSupported(mContext)) { removePreference(KEY_AUTOMATION_SETTINGS); } } @@ -97,13 +100,14 @@ public class ZenModeSettings extends ZenModeSettingsBase @Override public void onSwitchChanged(Switch switchView, boolean isChecked) { - if (DEBUG) Log.d(TAG, "onSwitchChanged " + isChecked + " mShowing=" + mShowing); - if (!mShowing) return; // not from the user + if (DEBUG) Log.d(TAG, "onSwitchChanged " + isChecked + " mShowing=" + mShowing + + " mUpdatingControls=" + mUpdatingControls); + if (!mShowing || mUpdatingControls) return; // not from the user if (isChecked) { - setZenMode(Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS); + setZenMode(Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, null); showConditionSelection(Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS); } else { - setZenMode(Global.ZEN_MODE_OFF); + setZenMode(Global.ZEN_MODE_OFF, null); } } @@ -135,29 +139,20 @@ public class ZenModeSettings extends ZenModeSettingsBase } } - private String computeExitConditionText() { - return mConfig == null || mConfig.exitCondition == null - ? getString(com.android.internal.R.string.zen_mode_forever) - : computeConditionText(mConfig.exitCondition); - } - - public static String computeConditionText(Condition c) { - return !TextUtils.isEmpty(c.line1) ? c.line1 - : !TextUtils.isEmpty(c.summary) ? c.summary - : ""; - } - private String computeZenModeSummaryLine() { final String caption = computeZenModeCaption(mZenMode); - if (caption == null) return null; - final String conditionText = computeExitConditionText().toLowerCase(); + if (caption == null) return null; // zen mode off + final String conditionText = ZenModeConfig.getConditionLine1(mContext, mConfig, + UserHandle.myUserId()); return getString(R.string.zen_mode_summary_combination, caption, conditionText); } private void updateControls() { if (mSwitchBar != null) { final String summaryLine = computeZenModeSummaryLine(); + mUpdatingControls = true; mSwitchBar.setChecked(summaryLine != null); + mUpdatingControls = false; mSwitchBar.setSummary(summaryLine); } updatePrioritySettingsSummary(); @@ -184,7 +179,7 @@ public class ZenModeSettings extends ZenModeSettingsBase if (mDialog != null) return; final ZenModeConditionSelection zenModeConditionSelection = - new ZenModeConditionSelection(mContext); + new ZenModeConditionSelection(mContext, zenMode); DialogInterface.OnClickListener positiveListener = new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { @@ -198,7 +193,7 @@ public class ZenModeSettings extends ZenModeSettingsBase .setTitle(computeZenModeCaption(zenMode)) .setView(scrollView) .setPositiveButton(R.string.okay, positiveListener) - .setNegativeButton(R.string.cancel_all_caps, new DialogInterface.OnClickListener() { + .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { cancelDialog(); @@ -216,10 +211,16 @@ public class ZenModeSettings extends ZenModeSettingsBase private void cancelDialog() { if (DEBUG) Log.d(TAG, "cancelDialog"); // If not making a decision, reset zen to off. - setZenMode(Global.ZEN_MODE_OFF); + setZenMode(Global.ZEN_MODE_OFF, null); mDialog = null; } + public static String computeConditionText(Condition c) { + return !TextUtils.isEmpty(c.line1) ? c.line1 + : !TextUtils.isEmpty(c.summary) ? c.summary + : ""; + } + private static SparseArray<String> allKeyTitles(Context context) { final SparseArray<String> rt = new SparseArray<String>(); rt.put(R.string.zen_mode_priority_settings_title, KEY_PRIORITY_SETTINGS); @@ -250,7 +251,7 @@ public class ZenModeSettings extends ZenModeSettingsBase @Override public List<String> getNonIndexableKeys(Context context) { final ArrayList<String> rt = new ArrayList<String>(); - if (!isDowntimeSupported(context)) { + if (!isScheduleSupported(context)) { rt.add(KEY_AUTOMATION_SETTINGS); } return rt; diff --git a/src/com/android/settings/notification/ZenModeSettingsBase.java b/src/com/android/settings/notification/ZenModeSettingsBase.java index 5ef0da4..9824dc7 100644 --- a/src/com/android/settings/notification/ZenModeSettingsBase.java +++ b/src/com/android/settings/notification/ZenModeSettingsBase.java @@ -16,14 +16,12 @@ package com.android.settings.notification; -import android.app.INotificationManager; import android.app.NotificationManager; import android.content.Context; import android.database.ContentObserver; import android.net.Uri; import android.os.Bundle; import android.os.Handler; -import android.os.ServiceManager; import android.provider.Settings; import android.provider.Settings.Global; import android.service.notification.ZenModeConfig; @@ -91,40 +89,27 @@ abstract public class ZenModeSettingsBase extends SettingsPreferenceFragment { } protected boolean setZenModeConfig(ZenModeConfig config) { - final INotificationManager nm = INotificationManager.Stub.asInterface( - ServiceManager.getService(Context.NOTIFICATION_SERVICE)); - try { - final boolean success = nm.setZenModeConfig(config); - if (success) { - mConfig = config; - if (DEBUG) Log.d(TAG, "Saved mConfig=" + mConfig); - onZenModeConfigChanged(); - } - return success; - } catch (Exception e) { - Log.w(TAG, "Error calling NoMan", e); - return false; + final String reason = getClass().getSimpleName(); + final boolean success = NotificationManager.from(mContext).setZenModeConfig(config, reason); + if (success) { + mConfig = config; + if (DEBUG) Log.d(TAG, "Saved mConfig=" + mConfig); + onZenModeConfigChanged(); } + return success; } - protected void setZenMode(int zenMode) { - Global.putInt(getContentResolver(), Global.ZEN_MODE, zenMode); + protected void setZenMode(int zenMode, Uri conditionId) { + NotificationManager.from(mContext).setZenMode(zenMode, conditionId, TAG); } - protected static boolean isDowntimeSupported(Context context) { + protected static boolean isScheduleSupported(Context context) { return NotificationManager.from(context) - .isSystemConditionProviderEnabled(ZenModeConfig.DOWNTIME_PATH); + .isSystemConditionProviderEnabled(ZenModeConfig.SCHEDULE_PATH); } private ZenModeConfig getZenModeConfig() { - final INotificationManager nm = INotificationManager.Stub.asInterface( - ServiceManager.getService(Context.NOTIFICATION_SERVICE)); - try { - return nm.getZenModeConfig(); - } catch (Exception e) { - Log.w(TAG, "Error calling NoMan", e); - return new ZenModeConfig(); - } + return NotificationManager.from(mContext).getZenModeConfig(); } private final class SettingsObserver extends ContentObserver { diff --git a/src/com/android/settings/notification/ZenRuleNameDialog.java b/src/com/android/settings/notification/ZenRuleNameDialog.java new file mode 100644 index 0000000..b0eaaec --- /dev/null +++ b/src/com/android/settings/notification/ZenRuleNameDialog.java @@ -0,0 +1,93 @@ +/* + * 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.text.Editable; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.util.ArraySet; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.EditText; + +import com.android.settings.R; + +public abstract class ZenRuleNameDialog { + private final AlertDialog mDialog; + private final EditText mEditText; + private final ArraySet<String> mExistingNames; + + public ZenRuleNameDialog(Context context, String ruleName, ArraySet<String> existingNames) { + 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); + mEditText.setSelectAllOnFocus(true); + 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()); + } + }) + .setNegativeButton(R.string.cancel, null) + .create(); + mEditText.addTextChangedListener(new TextWatcher() { + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + // noop + } + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + // noop + } + + @Override + public void afterTextChanged(Editable s) { + updatePositiveButton(); + } + }); + mExistingNames = new ArraySet<String>(existingNames.size()); + for (String existingName : existingNames) { + mExistingNames.add(existingName.toLowerCase()); + } + } + + abstract public void onOk(String ruleName); + + private String trimmedText() { + return mEditText.getText() == null ? null : mEditText.getText().toString().trim(); + } + + public void show() { + mDialog.show(); + updatePositiveButton(); + } + + private void updatePositiveButton() { + final String name = trimmedText(); + final boolean validName = !TextUtils.isEmpty(name) + && !mExistingNames.contains(name.toLowerCase()); + mDialog.getButton(DialogInterface.BUTTON_POSITIVE).setEnabled(validName); + } + +}
\ No newline at end of file diff --git a/src/com/android/settings/search/SearchIndexableResources.java b/src/com/android/settings/search/SearchIndexableResources.java index 0ad9503..dae8860 100644 --- a/src/com/android/settings/search/SearchIndexableResources.java +++ b/src/com/android/settings/search/SearchIndexableResources.java @@ -24,11 +24,12 @@ import com.android.settings.DevelopmentSettings; import com.android.settings.DeviceInfoSettings; import com.android.settings.DisplaySettings; import com.android.settings.HomeSettings; -import com.android.settings.ScreenPinningSettings; import com.android.settings.PrivacySettings; import com.android.settings.R; +import com.android.settings.ScreenPinningSettings; import com.android.settings.SecuritySettings; import com.android.settings.WallpaperTypeSettings; +import com.android.settings.WifiCallingSettings; import com.android.settings.WirelessSettings; import com.android.settings.accessibility.AccessibilitySettings; import com.android.settings.applications.AdvancedAppSettings; @@ -43,7 +44,6 @@ import com.android.settings.location.ScanningSettings; import com.android.settings.net.DataUsageMeteredSettings; import com.android.settings.notification.NotificationSettings; import com.android.settings.notification.OtherSoundSettings; -import com.android.settings.notification.ZenModeAutomationSettings; import com.android.settings.notification.ZenModePrioritySettings; import com.android.settings.notification.ZenModeSettings; import com.android.settings.print.PrintSettingsFragment; @@ -53,7 +53,6 @@ import com.android.settings.voice.VoiceInputSettings; import com.android.settings.wifi.AdvancedWifiSettings; import com.android.settings.wifi.SavedAccessPointsWifiSettings; import com.android.settings.wifi.WifiSettings; -import com.android.settings.WifiCallingSettings; import java.util.Collection; import java.util.HashMap; @@ -171,13 +170,6 @@ public final class SearchIndexableResources { ZenModePrioritySettings.class.getName(), R.drawable.ic_settings_notifications)); - sResMap.put(ZenModeAutomationSettings.class.getName(), - new SearchIndexableResource( - Ranking.getRankForClassName(ZenModeAutomationSettings.class.getName()), - NO_DATA_RES_ID, - ZenModeAutomationSettings.class.getName(), - R.drawable.ic_settings_notifications)); - sResMap.put(Memory.class.getName(), new SearchIndexableResource( Ranking.getRankForClassName(Memory.class.getName()), |