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