1 /* 2 * Copyright (C) 2019 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.tv.settings.device.display.daydream; 18 19 import static android.provider.Settings.Secure.ATTENTIVE_TIMEOUT; 20 import static android.provider.Settings.Secure.SLEEP_TIMEOUT; 21 22 import static com.android.tv.settings.util.InstrumentationUtils.logEntrySelected; 23 24 import android.app.AlertDialog; 25 import android.app.tvsettings.TvSettingsEnums; 26 import android.os.Bundle; 27 import android.os.UserManager; 28 import android.provider.Settings; 29 import android.text.format.DateUtils; 30 31 import androidx.annotation.Keep; 32 import androidx.preference.ListPreference; 33 import androidx.preference.Preference; 34 35 import com.android.settingslib.RestrictedSwitchPreference; 36 import com.android.tv.settings.R; 37 import com.android.tv.settings.RestrictedPreferenceAdapter; 38 import com.android.tv.settings.SettingsPreferenceFragment; 39 import com.android.tv.twopanelsettings.TwoPanelSettingsFragment; 40 41 /** 42 * The energy saver screen in TV settings. 43 */ 44 @Keep 45 public class EnergySaverFragment extends SettingsPreferenceFragment implements 46 Preference.OnPreferenceChangeListener { 47 private static final String TAG = "EnergySaverFragment"; 48 private static final String KEY_SLEEP_TIME = "sleepTime"; 49 private static final String KEY_ALLOW_TURN_SCREEN_OFF = "allowTurnScreenOff"; 50 private static final int DEFAULT_SLEEP_TIME_MS = (int) (24 * DateUtils.HOUR_IN_MILLIS); 51 private static final int WARNING_THRESHOLD_SLEEP_TIME_MS = (int) (4 * DateUtils.HOUR_IN_MILLIS); 52 private RestrictedSwitchPreference mAllowTurnScreenOffWithWakeLockPref; 53 private ListPreference mSleepTimePref; 54 private RestrictedPreferenceAdapter<ListPreference> mRestrictedSleepTime; 55 56 @Override onCreatePreferences(Bundle bundle, String s)57 public void onCreatePreferences(Bundle bundle, String s) { 58 setPreferencesFromResource(R.xml.energy_saver, null); 59 mAllowTurnScreenOffWithWakeLockPref = findPreference(KEY_ALLOW_TURN_SCREEN_OFF); 60 mAllowTurnScreenOffWithWakeLockPref.setOnPreferenceChangeListener(this); 61 mAllowTurnScreenOffWithWakeLockPref.setVisible(showStandbyTimeout()); 62 UserManager userManager = UserManager.get(getContext()); 63 if (userManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_SCREEN_TIMEOUT) 64 && !mAllowTurnScreenOffWithWakeLockPref.isDisabledByAdmin()) { 65 mAllowTurnScreenOffWithWakeLockPref.setEnabled(false); 66 } 67 68 updateAllowTurnScreenOffWithWakeLockPref(); 69 mSleepTimePref = findPreference(KEY_SLEEP_TIME); 70 if (allowTurnOffWithWakeLock()) { 71 int validatedAttentiveSleepTime = getValidatedTimeout(getAttentiveSleepTime()); 72 mSleepTimePref.setValue(String.valueOf(validatedAttentiveSleepTime)); 73 if (getAttentiveSleepTime() != validatedAttentiveSleepTime) { 74 setAttentiveSleepTime(validatedAttentiveSleepTime); 75 } 76 } else { 77 int validatedSleepTime = getValidatedTimeout(getSleepTime()); 78 mSleepTimePref.setValue(String.valueOf(validatedSleepTime)); 79 if (getSleepTime() != validatedSleepTime) { 80 setSleepTime(validatedSleepTime); 81 } 82 } 83 mSleepTimePref.setOnPreferenceChangeListener(this); 84 mSleepTimePref.setOnPreferenceClickListener( 85 preference -> { 86 logEntrySelected(TvSettingsEnums.SYSTEM_ENERGYSAVER_START_DELAY); 87 return false; 88 }); 89 90 mRestrictedSleepTime = RestrictedPreferenceAdapter.adapt( 91 mSleepTimePref, UserManager.DISALLOW_CONFIG_SCREEN_TIMEOUT); 92 } 93 showStandbyTimeout()94 private boolean showStandbyTimeout() { 95 return getResources().getBoolean(R.bool.config_show_standby_timeout); 96 } 97 allowTurnOffWithWakeLock()98 private boolean allowTurnOffWithWakeLock() { 99 return showStandbyTimeout() && mAllowTurnScreenOffWithWakeLockPref.isChecked(); 100 } 101 updateAllowTurnScreenOffWithWakeLockPref()102 private void updateAllowTurnScreenOffWithWakeLockPref() { 103 if (!mAllowTurnScreenOffWithWakeLockPref.isVisible()) { 104 return; 105 } 106 107 UserManager userManager = UserManager.get(getContext()); 108 boolean canChangeEnabled = !userManager 109 .hasUserRestriction(UserManager.DISALLOW_CONFIG_SCREEN_TIMEOUT); 110 111 if (getSleepTime() == -1) { 112 mAllowTurnScreenOffWithWakeLockPref.setChecked(false); 113 if (canChangeEnabled) { 114 mAllowTurnScreenOffWithWakeLockPref.setEnabled(false); 115 } 116 } else if (getAttentiveSleepTime() == -1) { 117 mAllowTurnScreenOffWithWakeLockPref.setChecked(false); 118 if (canChangeEnabled) { 119 mAllowTurnScreenOffWithWakeLockPref.setEnabled(true); 120 } 121 } else { 122 mAllowTurnScreenOffWithWakeLockPref.setChecked(true); 123 if (canChangeEnabled) { 124 mAllowTurnScreenOffWithWakeLockPref.setEnabled(true); 125 } 126 } 127 } 128 129 @Override onPreferenceChange(Preference preference, Object newValue)130 public boolean onPreferenceChange(Preference preference, Object newValue) { 131 switch (preference.getKey()) { 132 case KEY_SLEEP_TIME: 133 final int newSleepTime = Integer.parseInt((String) newValue); 134 if (getSleepTimeEntryId(newSleepTime) != -1) { 135 logEntrySelected(getSleepTimeEntryId(newSleepTime)); 136 } 137 if (showStandbyTimeout() 138 && (newSleepTime > WARNING_THRESHOLD_SLEEP_TIME_MS || newSleepTime == -1)) { 139 // Some regions require a warning to be presented. 140 new AlertDialog.Builder(getContext()) 141 .setTitle(R.string.device_energy_saver_confirmation_title) 142 .setMessage(getConfirmationDialogDescription(newSleepTime)) 143 .setPositiveButton(R.string.settings_confirm, 144 (dialog, which) -> confirmNewSleepTime(newSleepTime)) 145 .setNegativeButton(R.string.settings_cancel, 146 (dialog, which) -> dialog.dismiss()) 147 .create() 148 .show(); 149 return false; 150 } else { 151 updateTimeOut(allowTurnOffWithWakeLock(), newSleepTime); 152 return true; 153 } 154 case KEY_ALLOW_TURN_SCREEN_OFF: 155 updateTimeOut((boolean) newValue, Integer.parseInt(mSleepTimePref.getValue())); 156 return true; 157 default: 158 return false; 159 } 160 } 161 updateTimeOut(boolean allowTurnScreenOffWithWakeLock, int value)162 private void updateTimeOut(boolean allowTurnScreenOffWithWakeLock, int value) { 163 if (allowTurnScreenOffWithWakeLock) { 164 setSleepTime(value); 165 if (showStandbyTimeout()) { 166 setAttentiveSleepTime(value); 167 } 168 } else { 169 setSleepTime(value); 170 if (showStandbyTimeout()) { 171 setAttentiveSleepTime(-1); 172 } 173 } 174 updateAllowTurnScreenOffWithWakeLockPref(); 175 } 176 getSleepTime()177 private int getSleepTime() { 178 return Settings.Secure.getInt(getActivity().getContentResolver(), SLEEP_TIMEOUT, 179 DEFAULT_SLEEP_TIME_MS); 180 } 181 getAttentiveSleepTime()182 private int getAttentiveSleepTime() { 183 return Settings.Secure.getInt(getActivity().getContentResolver(), ATTENTIVE_TIMEOUT, 184 DEFAULT_SLEEP_TIME_MS); 185 } 186 setSleepTime(int ms)187 private void setSleepTime(int ms) { 188 Settings.Secure.putInt(getActivity().getContentResolver(), SLEEP_TIMEOUT, ms); 189 } 190 setAttentiveSleepTime(int ms)191 private void setAttentiveSleepTime(int ms) { 192 Settings.Secure.putInt(getActivity().getContentResolver(), ATTENTIVE_TIMEOUT, ms); 193 } 194 195 // The SLEEP_TIMEOUT and ATTENTIVE_TIMEOUT could be defined in overlay by OEMs. We validate the 196 // value to make sure that we select from the predefined options. If the value from overlay is 197 // not one of the predefined options, we round it to the closest predefined value, except -1. getValidatedTimeout(int purposedTimeout)198 private int getValidatedTimeout(int purposedTimeout) { 199 int validatedTimeout = DEFAULT_SLEEP_TIME_MS; 200 if (purposedTimeout < 0) { 201 return -1; 202 } 203 String[] optionsString = getResources().getStringArray(R.array.screen_off_timeout_values); 204 // Find the value from the predefined values that is closest to the proposed value except -1 205 int diff = Integer.MAX_VALUE; 206 for (String option : optionsString) { 207 if (Integer.parseInt(option) != -1) { 208 int currentDiff = Math.abs(purposedTimeout - Integer.parseInt(option)); 209 if (currentDiff < diff) { 210 diff = currentDiff; 211 validatedTimeout = Integer.parseInt(option); 212 } 213 } 214 } 215 return validatedTimeout; 216 } 217 getConfirmationDialogDescription(int newSleepTime)218 private String getConfirmationDialogDescription(int newSleepTime) { 219 String sleepTimeText = null; 220 String[] optionsValues = getResources().getStringArray(R.array.screen_off_timeout_values); 221 String[] optionsStrings = getResources().getStringArray(R.array.screen_off_timeout_entries); 222 for (int i = 0; i < optionsValues.length; i++) { 223 if (newSleepTime == Integer.parseInt(optionsValues[i])) { 224 sleepTimeText = optionsStrings[i]; 225 } 226 } 227 return getString(R.string.device_energy_saver_confirmation_text, sleepTimeText); 228 } 229 confirmNewSleepTime(int newSleepTime)230 private void confirmNewSleepTime(int newSleepTime) { 231 if (mSleepTimePref != null) { 232 updateTimeOut(allowTurnOffWithWakeLock(), newSleepTime); 233 mSleepTimePref.setValue(String.valueOf(newSleepTime)); 234 mRestrictedSleepTime.updatePreference(); 235 if (getCallbackFragment() instanceof TwoPanelSettingsFragment) { 236 ((TwoPanelSettingsFragment) getCallbackFragment()).refocusPreference(this); 237 } 238 } 239 } 240 241 // TODO(b/158783050): update logging for new options 4H, 8H, 24H. 242 // Map @array/screen_off_timeout_entries to defined log enum getSleepTimeEntryId(int sleepTimeValue)243 private int getSleepTimeEntryId(int sleepTimeValue) { 244 switch(sleepTimeValue) { 245 case -1: 246 return TvSettingsEnums.SYSTEM_ENERGYSAVER_START_DELAY_NEVER; 247 case 900000: 248 return TvSettingsEnums.SYSTEM_ENERGYSAVER_START_DELAY_15M; 249 case 1800000: 250 return TvSettingsEnums.SYSTEM_ENERGYSAVER_START_DELAY_30M; 251 case 3600000: 252 return TvSettingsEnums.SYSTEM_ENERGYSAVER_START_DELAY_1H; 253 case 43200000: 254 return TvSettingsEnums.SYSTEM_ENERGYSAVER_START_DELAY_12H; 255 default: 256 return -1; 257 } 258 } 259 260 @Override getPageId()261 protected int getPageId() { 262 return TvSettingsEnums.SYSTEM_ENERGYSAVER; 263 } 264 } 265