Home | History | Annotate | Download | only in notification
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.settings.notification;
     18 
     19 import android.app.AlertDialog;
     20 import android.app.AutomaticZenRule;
     21 import android.app.Dialog;
     22 import android.app.DialogFragment;
     23 import android.app.FragmentManager;
     24 import android.app.TimePickerDialog;
     25 import android.content.Context;
     26 import android.content.DialogInterface;
     27 import android.content.DialogInterface.OnDismissListener;
     28 import android.os.Bundle;
     29 import android.provider.Settings;
     30 import android.service.notification.ZenModeConfig;
     31 import android.service.notification.ZenModeConfig.ScheduleInfo;
     32 import android.support.v14.preference.SwitchPreference;
     33 import android.support.v7.preference.Preference;
     34 import android.support.v7.preference.Preference.OnPreferenceClickListener;
     35 import android.support.v7.preference.PreferenceScreen;
     36 import android.text.format.DateFormat;
     37 import android.util.Log;
     38 import android.widget.TimePicker;
     39 
     40 import com.android.internal.logging.MetricsProto.MetricsEvent;
     41 import com.android.settings.R;
     42 
     43 import java.text.SimpleDateFormat;
     44 import java.util.Arrays;
     45 import java.util.Calendar;
     46 
     47 public class ZenModeScheduleRuleSettings extends ZenModeRuleSettingsBase {
     48     private static final String KEY_DAYS = "days";
     49     private static final String KEY_START_TIME = "start_time";
     50     private static final String KEY_END_TIME = "end_time";
     51     private static final String KEY_EXIT_AT_ALARM = "exit_at_alarm";
     52 
     53     public static final String ACTION = Settings.ACTION_ZEN_MODE_SCHEDULE_RULE_SETTINGS;
     54 
     55     // per-instance to ensure we're always using the current locale
     56     private final SimpleDateFormat mDayFormat = new SimpleDateFormat("EEE");
     57 
     58     private Preference mDays;
     59     private TimePickerPreference mStart;
     60     private TimePickerPreference mEnd;
     61     private SwitchPreference mExitAtAlarm;
     62 
     63     private ScheduleInfo mSchedule;
     64 
     65     @Override
     66     protected boolean setRule(AutomaticZenRule rule) {
     67         mSchedule = rule != null ? ZenModeConfig.tryParseScheduleConditionId(rule.getConditionId())
     68                 : null;
     69         return mSchedule != null;
     70     }
     71 
     72     @Override
     73     protected String getZenModeDependency() {
     74         return mDays.getKey();
     75     }
     76 
     77     @Override
     78     protected int getEnabledToastText() {
     79         return R.string.zen_schedule_rule_enabled_toast;
     80     }
     81 
     82     @Override
     83     protected void onCreateInternal() {
     84         addPreferencesFromResource(R.xml.zen_mode_schedule_rule_settings);
     85         final PreferenceScreen root = getPreferenceScreen();
     86 
     87         mDays = root.findPreference(KEY_DAYS);
     88         mDays.setOnPreferenceClickListener(new OnPreferenceClickListener() {
     89             @Override
     90             public boolean onPreferenceClick(Preference preference) {
     91                 showDaysDialog();
     92                 return true;
     93             }
     94         });
     95 
     96         final FragmentManager mgr = getFragmentManager();
     97 
     98         mStart = new TimePickerPreference(getPrefContext(), mgr);
     99         mStart.setKey(KEY_START_TIME);
    100         mStart.setTitle(R.string.zen_mode_start_time);
    101         mStart.setCallback(new TimePickerPreference.Callback() {
    102             @Override
    103             public boolean onSetTime(final int hour, final int minute) {
    104                 if (mDisableListeners) return true;
    105                 if (!ZenModeConfig.isValidHour(hour)) return false;
    106                 if (!ZenModeConfig.isValidMinute(minute)) return false;
    107                 if (hour == mSchedule.startHour && minute == mSchedule.startMinute) {
    108                     return true;
    109                 }
    110                 if (DEBUG) Log.d(TAG, "onPrefChange start h=" + hour + " m=" + minute);
    111                 mSchedule.startHour = hour;
    112                 mSchedule.startMinute = minute;
    113                 updateRule(ZenModeConfig.toScheduleConditionId(mSchedule));
    114                 return true;
    115             }
    116         });
    117         root.addPreference(mStart);
    118         mStart.setDependency(mDays.getKey());
    119 
    120         mEnd = new TimePickerPreference(getPrefContext(), mgr);
    121         mEnd.setKey(KEY_END_TIME);
    122         mEnd.setTitle(R.string.zen_mode_end_time);
    123         mEnd.setCallback(new TimePickerPreference.Callback() {
    124             @Override
    125             public boolean onSetTime(final int hour, final int minute) {
    126                 if (mDisableListeners) return true;
    127                 if (!ZenModeConfig.isValidHour(hour)) return false;
    128                 if (!ZenModeConfig.isValidMinute(minute)) return false;
    129                 if (hour == mSchedule.endHour && minute == mSchedule.endMinute) {
    130                     return true;
    131                 }
    132                 if (DEBUG) Log.d(TAG, "onPrefChange end h=" + hour + " m=" + minute);
    133                 mSchedule.endHour = hour;
    134                 mSchedule.endMinute = minute;
    135                 updateRule(ZenModeConfig.toScheduleConditionId(mSchedule));
    136                 return true;
    137             }
    138         });
    139         root.addPreference(mEnd);
    140         mEnd.setDependency(mDays.getKey());
    141 
    142         mExitAtAlarm = (SwitchPreference) root.findPreference(KEY_EXIT_AT_ALARM);
    143         mExitAtAlarm.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
    144             @Override
    145             public boolean onPreferenceChange(Preference preference, Object o) {
    146                 mSchedule.exitAtAlarm = (Boolean) o;
    147                 updateRule(ZenModeConfig.toScheduleConditionId(mSchedule));
    148                 return true;
    149             }
    150         });
    151     }
    152 
    153     private void updateDays() {
    154         // Compute an ordered, delimited list of day names based on the persisted user config.
    155         final int[] days = mSchedule.days;
    156         if (days != null && days.length > 0) {
    157             final StringBuilder sb = new StringBuilder();
    158             final Calendar c = Calendar.getInstance();
    159             int[] daysOfWeek = ZenModeScheduleDaysSelection.getDaysOfWeekForLocale(c);
    160             for (int i = 0; i < daysOfWeek.length; i++) {
    161                 final int day = daysOfWeek[i];
    162                 for (int j = 0; j < days.length; j++) {
    163                     if (day == days[j]) {
    164                         c.set(Calendar.DAY_OF_WEEK, day);
    165                         if (sb.length() > 0) {
    166                             sb.append(mContext.getString(R.string.summary_divider_text));
    167                         }
    168                         sb.append(mDayFormat.format(c.getTime()));
    169                         break;
    170                     }
    171                 }
    172             }
    173             if (sb.length() > 0) {
    174                 mDays.setSummary(sb);
    175                 mDays.notifyDependencyChange(false);
    176                 return;
    177             }
    178         }
    179         mDays.setSummary(R.string.zen_mode_schedule_rule_days_none);
    180         mDays.notifyDependencyChange(true);
    181     }
    182 
    183     private void updateEndSummary() {
    184         final int startMin = 60 * mSchedule.startHour + mSchedule.startMinute;
    185         final int endMin = 60 * mSchedule.endHour + mSchedule.endMinute;
    186         final boolean nextDay = startMin >= endMin;
    187         final int summaryFormat = nextDay ? R.string.zen_mode_end_time_next_day_summary_format : 0;
    188         mEnd.setSummaryFormat(summaryFormat);
    189     }
    190 
    191     @Override
    192     protected void updateControlsInternal() {
    193         updateDays();
    194         mStart.setTime(mSchedule.startHour, mSchedule.startMinute);
    195         mEnd.setTime(mSchedule.endHour, mSchedule.endMinute);
    196         mExitAtAlarm.setChecked(mSchedule.exitAtAlarm);
    197         updateEndSummary();
    198     }
    199 
    200     @Override
    201     protected int getMetricsCategory() {
    202         return MetricsEvent.NOTIFICATION_ZEN_MODE_SCHEDULE_RULE;
    203     }
    204 
    205     private void showDaysDialog() {
    206         new AlertDialog.Builder(mContext)
    207                 .setTitle(R.string.zen_mode_schedule_rule_days)
    208                 .setView(new ZenModeScheduleDaysSelection(mContext, mSchedule.days) {
    209                       @Override
    210                       protected void onChanged(final int[] days) {
    211                           if (mDisableListeners) return;
    212                           if (Arrays.equals(days, mSchedule.days)) return;
    213                           if (DEBUG) Log.d(TAG, "days.onChanged days=" + Arrays.asList(days));
    214                           mSchedule.days = days;
    215                           updateRule(ZenModeConfig.toScheduleConditionId(mSchedule));
    216                       }
    217                 })
    218                 .setOnDismissListener(new OnDismissListener() {
    219                     @Override
    220                     public void onDismiss(DialogInterface dialog) {
    221                         updateDays();
    222                     }
    223                 })
    224                 .setPositiveButton(R.string.done_button, null)
    225                 .show();
    226     }
    227 
    228     private static class TimePickerPreference extends Preference {
    229         private final Context mContext;
    230 
    231         private int mSummaryFormat;
    232         private int mHourOfDay;
    233         private int mMinute;
    234         private Callback mCallback;
    235 
    236         public TimePickerPreference(Context context, final FragmentManager mgr) {
    237             super(context);
    238             mContext = context;
    239             setPersistent(false);
    240             setOnPreferenceClickListener(new OnPreferenceClickListener(){
    241                 @Override
    242                 public boolean onPreferenceClick(Preference preference) {
    243                     final TimePickerFragment frag = new TimePickerFragment();
    244                     frag.pref = TimePickerPreference.this;
    245                     frag.show(mgr, TimePickerPreference.class.getName());
    246                     return true;
    247                 }
    248             });
    249         }
    250 
    251         public void setCallback(Callback callback) {
    252             mCallback = callback;
    253         }
    254 
    255         public void setSummaryFormat(int resId) {
    256             mSummaryFormat = resId;
    257             updateSummary();
    258         }
    259 
    260         public void setTime(int hourOfDay, int minute) {
    261             if (mCallback != null && !mCallback.onSetTime(hourOfDay, minute)) return;
    262             mHourOfDay = hourOfDay;
    263             mMinute = minute;
    264             updateSummary();
    265         }
    266 
    267         private void updateSummary() {
    268             final Calendar c = Calendar.getInstance();
    269             c.set(Calendar.HOUR_OF_DAY, mHourOfDay);
    270             c.set(Calendar.MINUTE, mMinute);
    271             String time = DateFormat.getTimeFormat(mContext).format(c.getTime());
    272             if (mSummaryFormat != 0) {
    273                 time = mContext.getResources().getString(mSummaryFormat, time);
    274             }
    275             setSummary(time);
    276         }
    277 
    278         public static class TimePickerFragment extends DialogFragment implements
    279                 TimePickerDialog.OnTimeSetListener {
    280             public TimePickerPreference pref;
    281 
    282             @Override
    283             public Dialog onCreateDialog(Bundle savedInstanceState) {
    284                 final boolean usePref = pref != null && pref.mHourOfDay >= 0 && pref.mMinute >= 0;
    285                 final Calendar c = Calendar.getInstance();
    286                 final int hour = usePref ? pref.mHourOfDay : c.get(Calendar.HOUR_OF_DAY);
    287                 final int minute = usePref ? pref.mMinute : c.get(Calendar.MINUTE);
    288                 return new TimePickerDialog(getActivity(), this, hour, minute,
    289                         DateFormat.is24HourFormat(getActivity()));
    290             }
    291 
    292             public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
    293                 if (pref != null) {
    294                     pref.setTime(hourOfDay, minute);
    295                 }
    296             }
    297         }
    298 
    299         public interface Callback {
    300             boolean onSetTime(int hour, int minute);
    301         }
    302     }
    303 
    304 }
    305