diff --git a/proguard.flags b/proguard.flags index f3c218a54df..040fa6c9cf5 100644 --- a/proguard.flags +++ b/proguard.flags @@ -20,6 +20,7 @@ -keep class com.android.settings.overlay.FeatureFactoryImpl -keep class com.android.settings.accessibility.*FragmentForSetupWizard -keep class com.android.settings.display.*FragmentForSetupWizard +-keep class com.android.settings.display.NightDisplaySettings # Keep click responders -keepclassmembers class com.android.settings.inputmethod.UserDictionaryAddWordActivity { diff --git a/res/values/strings.xml b/res/values/strings.xml index 369210fb9aa..b35ef5be8bb 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -2133,6 +2133,39 @@ Optimize brightness level for available light + + Night display + + Night display tints your screen red at night. This makes it easier to look at your screen in dim light and may help you fall asleep more easily. + + Turn on automatically + + Never + + Custom schedule + + Sunset to sunrise + + Start time + + End time + + Off / %1$s + + Never turn on automatically + + Turn on automatically at %1$s + + Turn on automatically at sunset + + On / %1$s + + Never turn off automatically + + Turn off automatically at %1$s + + Turn off automatically at sunrise + Sleep @@ -5825,6 +5858,7 @@ screen, touchscreen dim screen, touchscreen, battery dim screen, touchscreen, battery + dim screen, night, tint background, personalize, customize display text size project, cast diff --git a/res/xml/display_settings.xml b/res/xml/display_settings.xml index b540c8fecdf..e96a0506d83 100644 --- a/res/xml/display_settings.xml +++ b/res/xml/display_settings.xml @@ -32,6 +32,12 @@ settings:keywords="@string/keywords_display_auto_brightness" android:summary="@string/auto_brightness_summary" /> + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/com/android/settings/DisplaySettings.java b/src/com/android/settings/DisplaySettings.java index bb10570daab..2821eb24f92 100644 --- a/src/com/android/settings/DisplaySettings.java +++ b/src/com/android/settings/DisplaySettings.java @@ -44,6 +44,7 @@ import android.support.v7.preference.Preference.OnPreferenceChangeListener; import android.text.TextUtils; import android.util.Log; +import com.android.internal.app.NightDisplayController; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.MetricsProto.MetricsEvent; import com.android.internal.view.RotationPolicy; @@ -83,6 +84,7 @@ public class DisplaySettings extends SettingsPreferenceFragment implements private static final String KEY_TAP_TO_WAKE = "tap_to_wake"; private static final String KEY_AUTO_BRIGHTNESS = "auto_brightness"; private static final String KEY_AUTO_ROTATE = "auto_rotate"; + private static final String KEY_NIGHT_DISPLAY = "night_display"; private static final String KEY_NIGHT_MODE = "night_mode"; private static final String KEY_CAMERA_GESTURE = "camera_gesture"; private static final String KEY_WALLPAPER = "wallpaper"; @@ -129,6 +131,10 @@ public class DisplaySettings extends SettingsPreferenceFragment implements removePreference(KEY_AUTO_BRIGHTNESS); } + if (!NightDisplayController.isAvailable(activity)) { + removePreference(KEY_NIGHT_DISPLAY); + } + if (isLiftToWakeAvailable(activity)) { mLiftToWakePreference = (SwitchPreference) findPreference(KEY_LIFT_TO_WAKE); mLiftToWakePreference.setOnPreferenceChangeListener(this); @@ -496,6 +502,9 @@ public class DisplaySettings extends SettingsPreferenceFragment implements if (!isAutomaticBrightnessAvailable(context.getResources())) { result.add(KEY_AUTO_BRIGHTNESS); } + if (!NightDisplayController.isAvailable(context)) { + result.add(KEY_NIGHT_DISPLAY); + } if (!isLiftToWakeAvailable(context)) { result.add(KEY_LIFT_TO_WAKE); } diff --git a/src/com/android/settings/display/NightDisplayPreference.java b/src/com/android/settings/display/NightDisplayPreference.java new file mode 100644 index 00000000000..73ecf493073 --- /dev/null +++ b/src/com/android/settings/display/NightDisplayPreference.java @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2016 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.display; + +import android.content.Context; +import android.support.v7.preference.Preference; +import android.util.AttributeSet; + +import com.android.internal.app.NightDisplayController; +import com.android.settings.R; + +import java.text.DateFormat; +import java.util.Calendar; +import java.util.TimeZone; + +public class NightDisplayPreference extends Preference implements NightDisplayController.Callback { + + private NightDisplayController mController; + private DateFormat mTimeFormatter; + + public NightDisplayPreference(Context context, AttributeSet attrs) { + super(context, attrs); + + mController = new NightDisplayController(context); + mTimeFormatter = android.text.format.DateFormat.getTimeFormat(context); + mTimeFormatter.setTimeZone(TimeZone.getTimeZone("UTC")); + } + + @Override + public void onAttached() { + super.onAttached(); + + // Listen for changes only while attached. + mController.setListener(this); + + // Update the summary since the state may have changed while not attached. + updateSummary(); + } + + @Override + public void onDetached() { + super.onDetached(); + + // Stop listening for state changes. + mController.setListener(null); + } + + private String getFormattedTimeString(NightDisplayController.LocalTime localTime) { + final Calendar c = Calendar.getInstance(); + c.setTimeZone(mTimeFormatter.getTimeZone()); + c.set(Calendar.HOUR_OF_DAY, localTime.hourOfDay); + c.set(Calendar.MINUTE, localTime.minute); + c.set(Calendar.SECOND, 0); + c.set(Calendar.MILLISECOND, 0); + return mTimeFormatter.format(c.getTime()); + } + + private void updateSummary() { + final Context context = getContext(); + + final boolean isActivated = mController.isActivated(); + final int autoMode = mController.getAutoMode(); + + final String autoModeSummary; + switch (autoMode) { + default: + case NightDisplayController.AUTO_MODE_DISABLED: + autoModeSummary = context.getString(isActivated + ? R.string.night_display_summary_on_auto_mode_never + : R.string.night_display_summary_off_auto_mode_never); + break; + case NightDisplayController.AUTO_MODE_CUSTOM: + if (isActivated) { + autoModeSummary = context.getString( + R.string.night_display_summary_on_auto_mode_custom, + getFormattedTimeString(mController.getCustomEndTime())); + } else { + autoModeSummary = context.getString( + R.string.night_display_summary_off_auto_mode_custom, + getFormattedTimeString(mController.getCustomStartTime())); + } + break; + case NightDisplayController.AUTO_MODE_TWILIGHT: + autoModeSummary = context.getString(isActivated + ? R.string.night_display_summary_on_auto_mode_twilight + : R.string.night_display_summary_off_auto_mode_twilight); + break; + } + + final int summaryFormatResId = isActivated ? R.string.night_display_summary_on + : R.string.night_display_summary_off; + setSummary(context.getString(summaryFormatResId, autoModeSummary)); + } + + @Override + public void onActivated(boolean activated) { + updateSummary(); + } + + @Override + public void onAutoModeChanged(int autoMode) { + updateSummary(); + } + + @Override + public void onCustomStartTimeChanged(NightDisplayController.LocalTime startTime) { + updateSummary(); + } + + @Override + public void onCustomEndTimeChanged(NightDisplayController.LocalTime endTime) { + updateSummary(); + } +} diff --git a/src/com/android/settings/display/NightDisplaySettings.java b/src/com/android/settings/display/NightDisplaySettings.java new file mode 100644 index 00000000000..ecba527efce --- /dev/null +++ b/src/com/android/settings/display/NightDisplaySettings.java @@ -0,0 +1,226 @@ +/** + * Copyright (C) 2016 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.display; + +import android.app.Dialog; +import android.app.TimePickerDialog; +import android.content.Context; +import android.os.Bundle; +import android.support.v7.preference.DropDownPreference; +import android.support.v7.preference.Preference; +import android.widget.Switch; +import android.widget.TimePicker; + +import com.android.internal.app.NightDisplayController; +import com.android.internal.logging.MetricsProto.MetricsEvent; +import com.android.settings.R; +import com.android.settings.SettingsActivity; +import com.android.settings.SettingsPreferenceFragment; +import com.android.settings.widget.SwitchBar; + +import java.text.DateFormat; +import java.util.Calendar; +import java.util.TimeZone; + +/** + * Settings screen for Night display. + */ +public class NightDisplaySettings extends SettingsPreferenceFragment implements + NightDisplayController.Callback, + Preference.OnPreferenceChangeListener, + SwitchBar.OnSwitchChangeListener { + + private static final String KEY_NIGHT_DISPLAY_AUTO_MODE = "night_display_auto_mode"; + private static final String KEY_NIGHT_DISPLAY_START_TIME = "night_display_start_time"; + private static final String KEY_NIGHT_DISPLAY_END_TIME = "night_display_end_time"; + + private static final int DIALOG_START_TIME = 0; + private static final int DIALOG_END_TIME = 1; + + private NightDisplayController mController; + private DateFormat mTimeFormatter; + + private DropDownPreference mAutoModePreference; + private Preference mStartTimePreference; + private Preference mEndTimePreference; + + private SwitchBar mSwitchBar; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + final Context context = getContext(); + mController = new NightDisplayController(context); + + mTimeFormatter = android.text.format.DateFormat.getTimeFormat(context); + mTimeFormatter.setTimeZone(TimeZone.getTimeZone("UTC")); + } + + @Override + public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { + super.onCreatePreferences(savedInstanceState, rootKey); + + // Load the preferences from xml. + addPreferencesFromResource(R.xml.night_display_settings); + + mAutoModePreference = (DropDownPreference) findPreference(KEY_NIGHT_DISPLAY_AUTO_MODE); + mStartTimePreference = findPreference(KEY_NIGHT_DISPLAY_START_TIME); + mEndTimePreference = findPreference(KEY_NIGHT_DISPLAY_END_TIME); + + mAutoModePreference.setEntries(new CharSequence[] { + getString(R.string.night_display_auto_mode_never), + getString(R.string.night_display_auto_mode_custom), + getString(R.string.night_display_auto_mode_twilight) + }); + mAutoModePreference.setEntryValues(new CharSequence[] { + String.valueOf(NightDisplayController.AUTO_MODE_DISABLED), + String.valueOf(NightDisplayController.AUTO_MODE_CUSTOM), + String.valueOf(NightDisplayController.AUTO_MODE_TWILIGHT) + }); + mAutoModePreference.setOnPreferenceChangeListener(this); + } + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + + mSwitchBar = ((SettingsActivity) getActivity()).getSwitchBar(); + mSwitchBar.addOnSwitchChangeListener(this); + mSwitchBar.show(); + } + + @Override + public void onStart() { + super.onStart(); + + // Listen for changes only while visible. + mController.setListener(this); + + // Update the current state since it have changed while not visible. + onActivated(mController.isActivated()); + onAutoModeChanged(mController.getAutoMode()); + onCustomStartTimeChanged(mController.getCustomStartTime()); + onCustomEndTimeChanged(mController.getCustomEndTime()); + } + + @Override + public void onStop() { + super.onStop(); + + // Stop listening for state changes. + mController.setListener(null); + } + + @Override + public boolean onPreferenceTreeClick(Preference preference) { + if (preference == mStartTimePreference) { + showDialog(DIALOG_START_TIME); + return true; + } else if (preference == mEndTimePreference) { + showDialog(DIALOG_END_TIME); + return true; + } + return super.onPreferenceTreeClick(preference); + } + + @Override + public Dialog onCreateDialog(final int dialogId) { + if (dialogId == DIALOG_START_TIME || dialogId == DIALOG_END_TIME) { + final NightDisplayController.LocalTime initialTime; + if (dialogId == DIALOG_START_TIME) { + initialTime = mController.getCustomStartTime(); + } else { + initialTime = mController.getCustomEndTime(); + } + + final Context context = getContext(); + final boolean use24HourFormat = android.text.format.DateFormat.is24HourFormat(context); + return new TimePickerDialog(context, new TimePickerDialog.OnTimeSetListener() { + @Override + public void onTimeSet(TimePicker view, int hourOfDay, int minute) { + final NightDisplayController.LocalTime time = + new NightDisplayController.LocalTime(hourOfDay, minute); + if (dialogId == DIALOG_START_TIME) { + mController.setCustomStartTime(time); + } else { + mController.setCustomEndTime(time); + } + } + }, initialTime.hourOfDay, initialTime.minute, use24HourFormat); + } + return super.onCreateDialog(dialogId); + } + + @Override + public void onActivated(boolean activated) { + mSwitchBar.setChecked(activated); + } + + @Override + public void onAutoModeChanged(int autoMode) { + mAutoModePreference.setValue(String.valueOf(autoMode)); + + final boolean showCustomSchedule = autoMode == NightDisplayController.AUTO_MODE_CUSTOM; + mStartTimePreference.setVisible(showCustomSchedule); + mEndTimePreference.setVisible(showCustomSchedule); + } + + private String getFormattedTimeString(NightDisplayController.LocalTime localTime) { + final Calendar c = Calendar.getInstance(); + c.setTimeZone(mTimeFormatter.getTimeZone()); + c.set(Calendar.HOUR_OF_DAY, localTime.hourOfDay); + c.set(Calendar.MINUTE, localTime.minute); + c.set(Calendar.SECOND, 0); + c.set(Calendar.MILLISECOND, 0); + return mTimeFormatter.format(c.getTime()); + } + + @Override + public void onCustomStartTimeChanged(NightDisplayController.LocalTime startTime) { + mStartTimePreference.setSummary(getFormattedTimeString(startTime)); + } + + @Override + public void onCustomEndTimeChanged(NightDisplayController.LocalTime endTime) { + mEndTimePreference.setSummary(getFormattedTimeString(endTime)); + } + + @Override + public void onSwitchChanged(Switch switchView, boolean isChecked) { + // Attempt to update the NIGHT_DISPLAY_ACTIVATED setting if necessary. + final boolean isActivated = mController.isActivated(); + if (isActivated != isChecked) { + if (mController.setActivated(isChecked)) { + switchView.setChecked(isActivated); + } + } + } + + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + if (preference == mAutoModePreference) { + return mController.setAutoMode(Integer.parseInt((String) newValue)); + } + return false; + } + + @Override + protected int getMetricsCategory() { + return MetricsEvent.NIGHT_DISPLAY_SETTINGS; + } +}