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.tv.settings.device.display.daydream; 18 19 import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT; 20 21 import static com.android.tv.settings.overlay.FlavorUtils.FLAVOR_CLASSIC; 22 import static com.android.tv.settings.overlay.FlavorUtils.FLAVOR_TWO_PANEL; 23 import static com.android.tv.settings.overlay.FlavorUtils.FLAVOR_VENDOR; 24 import static com.android.tv.settings.overlay.FlavorUtils.FLAVOR_X; 25 import static com.android.tv.settings.util.InstrumentationUtils.logEntrySelected; 26 27 import android.app.tvsettings.TvSettingsEnums; 28 import android.content.BroadcastReceiver; 29 import android.content.ComponentName; 30 import android.content.Context; 31 import android.content.Intent; 32 import android.content.IntentFilter; 33 import android.os.Bundle; 34 import android.os.UserManager; 35 import android.provider.Settings; 36 import android.text.format.DateUtils; 37 import android.util.ArrayMap; 38 import android.util.Log; 39 40 import androidx.annotation.Keep; 41 import androidx.preference.ListPreference; 42 import androidx.preference.Preference; 43 44 import com.android.settingslib.dream.DreamBackend; 45 import com.android.tv.settings.R; 46 import com.android.tv.settings.RestrictedPreferenceAdapter; 47 import com.android.tv.settings.SettingsPreferenceFragment; 48 import com.android.tv.settings.overlay.FlavorUtils; 49 50 import java.util.List; 51 import java.util.Map; 52 import java.util.Objects; 53 54 /** 55 * The screen saver screen in TV settings. 56 */ 57 @Keep 58 public class DaydreamFragment extends SettingsPreferenceFragment 59 implements Preference.OnPreferenceChangeListener { 60 61 private static final String TAG = "DaydreamFragment"; 62 63 private static final String KEY_ACTIVE_DREAM = "activeDream"; 64 private static final String KEY_DREAM_TIME = "dreamTime"; 65 private static final String KEY_DREAM_NOW = "dreamNow"; 66 67 private static final String DREAM_COMPONENT_NONE = "NONE"; 68 private static final String PACKAGE_SCHEME = "package"; 69 70 private static final int DEFAULT_DREAM_TIME_MS = (int) (30 * DateUtils.MINUTE_IN_MILLIS); 71 72 private final PackageReceiver mPackageReceiver = new PackageReceiver(); 73 74 private DreamBackend mBackend; 75 private final Map<String, DreamBackend.DreamInfo> mDreamInfos = new ArrayMap<>(); 76 77 private RestrictedPreferenceAdapter<ListPreference> mActiveDreamPref; 78 private RestrictedPreferenceAdapter<ListPreference> mDreamTimePref; 79 newInstance()80 public static DaydreamFragment newInstance() { 81 return new DaydreamFragment(); 82 } 83 84 @Override onCreate(Bundle savedInstanceState)85 public void onCreate(Bundle savedInstanceState) { 86 mBackend = new DreamBackend(getActivity()); 87 super.onCreate(savedInstanceState); 88 } 89 90 @Override onResume()91 public void onResume() { 92 super.onResume(); 93 refreshFromBackend(); 94 95 // listen for package changes 96 IntentFilter filter = new IntentFilter(); 97 filter.addAction(Intent.ACTION_PACKAGE_ADDED); 98 filter.addAction(Intent.ACTION_PACKAGE_CHANGED); 99 filter.addAction(Intent.ACTION_PACKAGE_REMOVED); 100 filter.addAction(Intent.ACTION_PACKAGE_REPLACED); 101 filter.addDataScheme(PACKAGE_SCHEME); 102 getActivity().registerReceiver(mPackageReceiver, filter); 103 } 104 105 @Override onPause()106 public void onPause() { 107 super.onPause(); 108 109 getActivity().unregisterReceiver(mPackageReceiver); 110 } 111 112 getPreferenceScreenResId()113 private int getPreferenceScreenResId() { 114 switch (FlavorUtils.getFlavor(getContext())) { 115 case FLAVOR_CLASSIC: 116 case FLAVOR_TWO_PANEL: 117 return R.xml.daydream; 118 case FLAVOR_X: 119 case FLAVOR_VENDOR: 120 return R.xml.daydream_x; 121 default: 122 return R.xml.daydream; 123 } 124 } 125 126 @Override onCreatePreferences(Bundle savedInstanceState, String rootKey)127 public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { 128 setPreferencesFromResource(getPreferenceScreenResId(), null); 129 final String userRestriction = UserManager.DISALLOW_CONFIG_SCREEN_TIMEOUT; 130 131 final ListPreference activeDreamPref = (ListPreference) findPreference(KEY_ACTIVE_DREAM); 132 refreshActiveDreamPref(); 133 if (activeDreamPref != null) { 134 activeDreamPref.setOnPreferenceChangeListener(this); 135 mActiveDreamPref = RestrictedPreferenceAdapter.adapt(activeDreamPref, userRestriction); 136 } 137 138 final ListPreference dreamTimePref = (ListPreference) findPreference(KEY_DREAM_TIME); 139 if (dreamTimePref != null) { 140 dreamTimePref.setValue(Integer.toString(getDreamTime())); 141 dreamTimePref.setOnPreferenceChangeListener(this); 142 mDreamTimePref = RestrictedPreferenceAdapter.adapt(dreamTimePref, userRestriction); 143 } 144 145 final Preference dreamNowPref = findPreference(KEY_DREAM_NOW); 146 dreamNowPref.setEnabled(mBackend.isEnabled()); 147 } 148 refreshActiveDreamPref()149 private void refreshActiveDreamPref() { 150 if (mActiveDreamPref == null) { 151 return; 152 } 153 154 final List<DreamBackend.DreamInfo> infos = mBackend.getDreamInfos(); 155 final CharSequence[] dreamEntries = new CharSequence[infos.size() + 1]; 156 final CharSequence[] dreamEntryValues = new CharSequence[infos.size() + 1]; 157 refreshDreamInfoMap(infos, dreamEntries, dreamEntryValues); 158 final ComponentName currentDreamComponent = mBackend.getActiveDream(); 159 160 mActiveDreamPref.updatePreference(activeDreamPref -> { 161 activeDreamPref.setEntries(dreamEntries); 162 activeDreamPref.setEntryValues(dreamEntryValues); 163 activeDreamPref.setValue(mBackend.isEnabled() && currentDreamComponent != null 164 ? currentDreamComponent.toShortString() : DREAM_COMPONENT_NONE); 165 }); 166 } 167 refreshDreamInfoMap(List<DreamBackend.DreamInfo> infos, CharSequence[] listEntries, CharSequence[] listEntryValues)168 private void refreshDreamInfoMap(List<DreamBackend.DreamInfo> infos, 169 CharSequence[] listEntries, CharSequence[] listEntryValues) { 170 mDreamInfos.clear(); 171 listEntries[0] = getString(R.string.device_daydreams_none); 172 listEntryValues[0] = DREAM_COMPONENT_NONE; 173 int index = 1; 174 for (final DreamBackend.DreamInfo info : infos) { 175 final String componentNameString = info.componentName.toShortString(); 176 mDreamInfos.put(componentNameString, info); 177 listEntries[index] = info.caption; 178 listEntryValues[index] = componentNameString; 179 index++; 180 } 181 } 182 183 @Override onPreferenceChange(Preference preference, Object newValue)184 public boolean onPreferenceChange(Preference preference, Object newValue) { 185 switch (preference.getKey()) { 186 case KEY_ACTIVE_DREAM: 187 logEntrySelected(TvSettingsEnums.PREFERENCES_SCREENSAVER_CHOOSER); 188 setActiveDream((String) newValue); 189 break; 190 case KEY_DREAM_TIME: 191 final int sleepTimeout = Integer.parseInt((String) newValue); 192 if (getSleepTimeoutEntryId(sleepTimeout) != -1) { 193 logEntrySelected(getSleepTimeoutEntryId(sleepTimeout)); 194 } 195 setDreamTime(sleepTimeout); 196 break; 197 } 198 return true; 199 } 200 setActiveDream(String componentNameString)201 private void setActiveDream(String componentNameString) { 202 final DreamBackend.DreamInfo dreamInfo = mDreamInfos.get(componentNameString); 203 if (dreamInfo != null) { 204 if (dreamInfo.settingsComponentName != null) { 205 startActivity(new Intent().setComponent(dreamInfo.settingsComponentName)); 206 } 207 if (!mBackend.isEnabled()) { 208 mBackend.setEnabled(true); 209 } 210 if (!Objects.equals(mBackend.getActiveDream(), dreamInfo.componentName)) { 211 mBackend.setActiveDream(dreamInfo.componentName); 212 } 213 } else { 214 if (mBackend.isEnabled()) { 215 mBackend.setActiveDream(null); 216 mBackend.setEnabled(false); 217 } 218 } 219 } 220 getDreamTime()221 private int getDreamTime() { 222 return Settings.System.getInt(getActivity().getContentResolver(), SCREEN_OFF_TIMEOUT, 223 DEFAULT_DREAM_TIME_MS); 224 } 225 setDreamTime(int ms)226 private void setDreamTime(int ms) { 227 Settings.System.putInt(getActivity().getContentResolver(), SCREEN_OFF_TIMEOUT, ms); 228 } 229 230 @Override onPreferenceTreeClick(Preference preference)231 public boolean onPreferenceTreeClick(Preference preference) { 232 switch (preference.getKey()) { 233 case KEY_DREAM_NOW: 234 logEntrySelected(TvSettingsEnums.PREFERENCES_SCREENSAVER_START_NOW); 235 mBackend.startDreaming(); 236 return true; 237 default: 238 return super.onPreferenceTreeClick(preference); 239 } 240 } 241 refreshFromBackend()242 private void refreshFromBackend() { 243 if (getActivity() == null) { 244 Log.d(TAG, "No activity, not refreshing"); 245 return; 246 } 247 248 refreshActiveDreamPref(); 249 if (mDreamTimePref != null) { 250 mDreamTimePref.updatePreference( 251 dreamTimePref -> dreamTimePref.setValue(Integer.toString(getDreamTime()))); 252 } 253 254 final Preference dreamNowPref = findPreference(KEY_DREAM_NOW); 255 if (dreamNowPref != null) { 256 dreamNowPref.setEnabled(mBackend.isEnabled()); 257 } 258 } 259 260 private class PackageReceiver extends BroadcastReceiver { 261 @Override onReceive(Context context, Intent intent)262 public void onReceive(Context context, Intent intent) { 263 refreshFromBackend(); 264 } 265 } 266 267 // Map @array/sleep_timeout_entries to defined log enum getSleepTimeoutEntryId(int sleepTimeout)268 private int getSleepTimeoutEntryId(int sleepTimeout) { 269 switch(sleepTimeout) { 270 case 300000: 271 return TvSettingsEnums.PREFERENCES_SCREENSAVER_START_DELAY_5M; 272 case 900000: 273 return TvSettingsEnums.PREFERENCES_SCREENSAVER_START_DELAY_15M; 274 case 1800000: 275 return TvSettingsEnums.PREFERENCES_SCREENSAVER_START_DELAY_30M; 276 case 3600000: 277 return TvSettingsEnums.PREFERENCES_SCREENSAVER_START_DELAY_1H; 278 case 7200000: 279 return TvSettingsEnums.PREFERENCES_SCREENSAVER_START_DELAY_2H; 280 default: 281 return -1; 282 } 283 } 284 285 @Override getPageId()286 protected int getPageId() { 287 return TvSettingsEnums.PREFERENCES_SCREENSAVER; 288 } 289 } 290