1 /*
2  * Copyright (C) 2016 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.display;
18 
19 import android.app.Dialog;
20 import android.app.TimePickerDialog;
21 import android.content.Context;
22 import android.os.Bundle;
23 import android.support.v7.preference.DropDownPreference;
24 import android.support.v7.preference.Preference;
25 import android.support.v7.preference.TwoStatePreference;
26 import android.widget.TimePicker;
27 
28 import com.android.internal.app.NightDisplayController;
29 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
30 import com.android.settings.R;
31 import com.android.settings.SeekBarPreference;
32 import com.android.settings.SettingsPreferenceFragment;
33 
34 import java.text.DateFormat;
35 import java.util.Calendar;
36 import java.util.TimeZone;
37 
38 /**
39  * Settings screen for Night display.
40  */
41 public class NightDisplaySettings extends SettingsPreferenceFragment
42         implements NightDisplayController.Callback, Preference.OnPreferenceChangeListener {
43 
44     private static final String KEY_NIGHT_DISPLAY_AUTO_MODE = "night_display_auto_mode";
45     private static final String KEY_NIGHT_DISPLAY_START_TIME = "night_display_start_time";
46     private static final String KEY_NIGHT_DISPLAY_END_TIME = "night_display_end_time";
47     private static final String KEY_NIGHT_DISPLAY_ACTIVATED = "night_display_activated";
48     private static final String KEY_NIGHT_DISPLAY_TEMPERATURE = "night_display_temperature";
49 
50     private static final int DIALOG_START_TIME = 0;
51     private static final int DIALOG_END_TIME = 1;
52 
53     private NightDisplayController mController;
54     private DateFormat mTimeFormatter;
55 
56     private DropDownPreference mAutoModePreference;
57     private Preference mStartTimePreference;
58     private Preference mEndTimePreference;
59     private TwoStatePreference mActivatedPreference;
60     private SeekBarPreference mTemperaturePreference;
61 
62     @Override
onCreate(Bundle savedInstanceState)63     public void onCreate(Bundle savedInstanceState) {
64         super.onCreate(savedInstanceState);
65 
66         final Context context = getContext();
67         mController = new NightDisplayController(context);
68 
69         mTimeFormatter = android.text.format.DateFormat.getTimeFormat(context);
70         mTimeFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));
71 
72         mTemperaturePreference.setMax(convertTemperature(mController.getMinimumColorTemperature()));
73         mTemperaturePreference.setContinuousUpdates(true);
74     }
75 
76     @Override
onCreatePreferences(Bundle savedInstanceState, String rootKey)77     public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
78         super.onCreatePreferences(savedInstanceState, rootKey);
79 
80         // Load the preferences from xml.
81         addPreferencesFromResource(R.xml.night_display_settings);
82         mFooterPreferenceMixin.createFooterPreference().setTitle(R.string.night_display_text);
83         mAutoModePreference = (DropDownPreference) findPreference(KEY_NIGHT_DISPLAY_AUTO_MODE);
84         mStartTimePreference = findPreference(KEY_NIGHT_DISPLAY_START_TIME);
85         mEndTimePreference = findPreference(KEY_NIGHT_DISPLAY_END_TIME);
86         mActivatedPreference = (TwoStatePreference) findPreference(KEY_NIGHT_DISPLAY_ACTIVATED);
87         mTemperaturePreference = (SeekBarPreference) findPreference(KEY_NIGHT_DISPLAY_TEMPERATURE);
88 
89         mAutoModePreference.setEntries(new CharSequence[] {
90                 getString(R.string.night_display_auto_mode_never),
91                 getString(R.string.night_display_auto_mode_custom),
92                 getString(R.string.night_display_auto_mode_twilight)
93         });
94         mAutoModePreference.setEntryValues(new CharSequence[] {
95                 String.valueOf(NightDisplayController.AUTO_MODE_DISABLED),
96                 String.valueOf(NightDisplayController.AUTO_MODE_CUSTOM),
97                 String.valueOf(NightDisplayController.AUTO_MODE_TWILIGHT)
98         });
99         mAutoModePreference.setOnPreferenceChangeListener(this);
100         mActivatedPreference.setOnPreferenceChangeListener(this);
101         mTemperaturePreference.setOnPreferenceChangeListener(this);
102     }
103 
104     @Override
onStart()105     public void onStart() {
106         super.onStart();
107 
108         // Listen for changes only while visible.
109         mController.setListener(this);
110 
111         // Update the current state since it have changed while not visible.
112         onActivated(mController.isActivated());
113         onAutoModeChanged(mController.getAutoMode());
114         onCustomStartTimeChanged(mController.getCustomStartTime());
115         onCustomEndTimeChanged(mController.getCustomEndTime());
116         onColorTemperatureChanged(mController.getColorTemperature());
117     }
118 
119     @Override
onStop()120     public void onStop() {
121         super.onStop();
122 
123         // Stop listening for state changes.
124         mController.setListener(null);
125     }
126 
127     @Override
onPreferenceTreeClick(Preference preference)128     public boolean onPreferenceTreeClick(Preference preference) {
129         if (preference == mStartTimePreference) {
130             showDialog(DIALOG_START_TIME);
131             return true;
132         } else if (preference == mEndTimePreference) {
133             showDialog(DIALOG_END_TIME);
134             return true;
135         }
136         return super.onPreferenceTreeClick(preference);
137     }
138 
139     @Override
onCreateDialog(final int dialogId)140     public Dialog onCreateDialog(final int dialogId) {
141         if (dialogId == DIALOG_START_TIME || dialogId == DIALOG_END_TIME) {
142             final NightDisplayController.LocalTime initialTime;
143             if (dialogId == DIALOG_START_TIME) {
144                 initialTime = mController.getCustomStartTime();
145             } else {
146                 initialTime = mController.getCustomEndTime();
147             }
148 
149             final Context context = getContext();
150             final boolean use24HourFormat = android.text.format.DateFormat.is24HourFormat(context);
151             return new TimePickerDialog(context, new TimePickerDialog.OnTimeSetListener() {
152                 @Override
153                 public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
154                     final NightDisplayController.LocalTime time =
155                             new NightDisplayController.LocalTime(hourOfDay, minute);
156                     if (dialogId == DIALOG_START_TIME) {
157                         mController.setCustomStartTime(time);
158                     } else {
159                         mController.setCustomEndTime(time);
160                     }
161                 }
162             }, initialTime.hourOfDay, initialTime.minute, use24HourFormat);
163         }
164         return super.onCreateDialog(dialogId);
165     }
166 
167     @Override
168     public int getDialogMetricsCategory(int dialogId) {
169         switch (dialogId) {
170             case DIALOG_START_TIME:
171                 return MetricsEvent.DIALOG_NIGHT_DISPLAY_SET_START_TIME;
172             case DIALOG_END_TIME:
173                 return MetricsEvent.DIALOG_NIGHT_DISPLAY_SET_END_TIME;
174             default:
175                 return 0;
176         }
177     }
178 
179     @Override
180     public void onActivated(boolean activated) {
181         mActivatedPreference.setChecked(activated);
182         mTemperaturePreference.setEnabled(activated);
183     }
184 
185     @Override
186     public void onAutoModeChanged(int autoMode) {
187         mAutoModePreference.setValue(String.valueOf(autoMode));
188 
189         final boolean showCustomSchedule = autoMode == NightDisplayController.AUTO_MODE_CUSTOM;
190         mStartTimePreference.setVisible(showCustomSchedule);
191         mEndTimePreference.setVisible(showCustomSchedule);
192     }
193 
194     @Override
195     public void onColorTemperatureChanged(int colorTemperature) {
196         mTemperaturePreference.setProgress(convertTemperature(colorTemperature));
197     }
198 
199     private String getFormattedTimeString(NightDisplayController.LocalTime localTime) {
200         final Calendar c = Calendar.getInstance();
201         c.setTimeZone(mTimeFormatter.getTimeZone());
202         c.set(Calendar.HOUR_OF_DAY, localTime.hourOfDay);
203         c.set(Calendar.MINUTE, localTime.minute);
204         c.set(Calendar.SECOND, 0);
205         c.set(Calendar.MILLISECOND, 0);
206         return mTimeFormatter.format(c.getTime());
207     }
208 
209     /**
210      * Inverts and range-adjusts a raw value from the SeekBar (i.e. [0, maxTemp-minTemp]), or
211      * converts an inverted and range-adjusted value to the raw SeekBar value, depending on the
212      * adjustment status of the input.
213      */
214     private int convertTemperature(int temperature) {
215         return mController.getMaximumColorTemperature() - temperature;
216     }
217 
218     @Override
219     public void onCustomStartTimeChanged(NightDisplayController.LocalTime startTime) {
220         mStartTimePreference.setSummary(getFormattedTimeString(startTime));
221     }
222 
223     @Override
224     public void onCustomEndTimeChanged(NightDisplayController.LocalTime endTime) {
225         mEndTimePreference.setSummary(getFormattedTimeString(endTime));
226     }
227 
228     @Override
229     public boolean onPreferenceChange(Preference preference, Object newValue) {
230         if (preference == mAutoModePreference) {
231             return mController.setAutoMode(Integer.parseInt((String) newValue));
232         } else if (preference == mActivatedPreference) {
233             return mController.setActivated((Boolean) newValue);
234         } else if (preference == mTemperaturePreference) {
235             return mController.setColorTemperature(convertTemperature((Integer) newValue));
236         }
237         return false;
238     }
239 
240     @Override
241     public int getMetricsCategory() {
242         return MetricsEvent.NIGHT_DISPLAY_SETTINGS;
243     }
244 }
245