DisplaySettings.java revision 333efe90978beeed36a45df6b45a7d7119140bb4
1/* 2 * Copyright (C) 2010 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 17package com.android.settings; 18 19import com.android.settings.search.BaseSearchIndexProvider; 20import com.android.settings.search.Indexable; 21 22import static android.provider.Settings.Secure.WAKE_GESTURE_ENABLED; 23import static android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE; 24import static android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC; 25import static android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL; 26import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT; 27 28import android.app.ActivityManagerNative; 29import android.app.Dialog; 30import android.app.admin.DevicePolicyManager; 31import android.content.ContentResolver; 32import android.content.Context; 33import android.content.res.Configuration; 34import android.content.res.Resources; 35import android.hardware.Sensor; 36import android.hardware.SensorManager; 37import android.os.Bundle; 38import android.os.RemoteException; 39import android.preference.ListPreference; 40import android.preference.Preference; 41import android.preference.Preference.OnPreferenceClickListener; 42import android.preference.PreferenceScreen; 43import android.preference.SwitchPreference; 44import android.provider.SearchIndexableResource; 45import android.provider.Settings; 46import android.util.Log; 47 48import java.util.ArrayList; 49import java.util.List; 50 51public class DisplaySettings extends SettingsPreferenceFragment implements 52 Preference.OnPreferenceChangeListener, OnPreferenceClickListener, Indexable { 53 private static final String TAG = "DisplaySettings"; 54 55 /** If there is no setting in the provider, use this. */ 56 private static final int FALLBACK_SCREEN_TIMEOUT_VALUE = 30000; 57 58 private static final String KEY_SCREEN_TIMEOUT = "screen_timeout"; 59 private static final String KEY_FONT_SIZE = "font_size"; 60 private static final String KEY_SCREEN_SAVER = "screensaver"; 61 private static final String KEY_LIFT_TO_WAKE = "lift_to_wake"; 62 private static final String KEY_AUTO_BRIGHTNESS = "auto_brightness"; 63 64 private static final int DLG_GLOBAL_CHANGE_WARNING = 1; 65 66 private WarnedListPreference mFontSizePref; 67 68 private final Configuration mCurConfig = new Configuration(); 69 70 private ListPreference mScreenTimeoutPreference; 71 private Preference mScreenSaverPreference; 72 private SwitchPreference mLiftToWakePreference; 73 private SwitchPreference mAutoBrightnessPreference; 74 75 @Override 76 public void onCreate(Bundle savedInstanceState) { 77 super.onCreate(savedInstanceState); 78 final ContentResolver resolver = getActivity().getContentResolver(); 79 80 addPreferencesFromResource(R.xml.display_settings); 81 82 mScreenSaverPreference = findPreference(KEY_SCREEN_SAVER); 83 if (mScreenSaverPreference != null 84 && getResources().getBoolean( 85 com.android.internal.R.bool.config_dreamsSupported) == false) { 86 getPreferenceScreen().removePreference(mScreenSaverPreference); 87 } 88 89 mScreenTimeoutPreference = (ListPreference) findPreference(KEY_SCREEN_TIMEOUT); 90 final long currentTimeout = Settings.System.getLong(resolver, SCREEN_OFF_TIMEOUT, 91 FALLBACK_SCREEN_TIMEOUT_VALUE); 92 mScreenTimeoutPreference.setValue(String.valueOf(currentTimeout)); 93 mScreenTimeoutPreference.setOnPreferenceChangeListener(this); 94 disableUnusableTimeouts(mScreenTimeoutPreference); 95 updateTimeoutPreferenceDescription(currentTimeout); 96 97 mFontSizePref = (WarnedListPreference) findPreference(KEY_FONT_SIZE); 98 mFontSizePref.setOnPreferenceChangeListener(this); 99 mFontSizePref.setOnPreferenceClickListener(this); 100 101 if (isAutomaticBrightnessAvailable(getResources())) { 102 mAutoBrightnessPreference = (SwitchPreference) findPreference(KEY_AUTO_BRIGHTNESS); 103 mAutoBrightnessPreference.setOnPreferenceChangeListener(this); 104 } else { 105 removePreference(KEY_AUTO_BRIGHTNESS); 106 } 107 108 if (isLiftToWakeAvailable(getActivity())) { 109 mLiftToWakePreference = (SwitchPreference) findPreference(KEY_LIFT_TO_WAKE); 110 mLiftToWakePreference.setOnPreferenceChangeListener(this); 111 } else { 112 removePreference(KEY_LIFT_TO_WAKE); 113 } 114 } 115 116 private static boolean isLiftToWakeAvailable(Context context) { 117 SensorManager sensors = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE); 118 return sensors != null && sensors.getDefaultSensor(Sensor.TYPE_WAKE_GESTURE) != null; 119 } 120 121 private static boolean isAutomaticBrightnessAvailable(Resources res) { 122 return res.getBoolean(com.android.internal.R.bool.config_automatic_brightness_available); 123 } 124 125 private void updateTimeoutPreferenceDescription(long currentTimeout) { 126 ListPreference preference = mScreenTimeoutPreference; 127 String summary; 128 if (currentTimeout < 0) { 129 // Unsupported value 130 summary = ""; 131 } else { 132 final CharSequence[] entries = preference.getEntries(); 133 final CharSequence[] values = preference.getEntryValues(); 134 if (entries == null || entries.length == 0) { 135 summary = ""; 136 } else { 137 int best = 0; 138 for (int i = 0; i < values.length; i++) { 139 long timeout = Long.parseLong(values[i].toString()); 140 if (currentTimeout >= timeout) { 141 best = i; 142 } 143 } 144 summary = preference.getContext().getString(R.string.screen_timeout_summary, 145 entries[best]); 146 } 147 } 148 preference.setSummary(summary); 149 } 150 151 private void disableUnusableTimeouts(ListPreference screenTimeoutPreference) { 152 final DevicePolicyManager dpm = 153 (DevicePolicyManager) getActivity().getSystemService( 154 Context.DEVICE_POLICY_SERVICE); 155 final long maxTimeout = dpm != null ? dpm.getMaximumTimeToLock(null) : 0; 156 if (maxTimeout == 0) { 157 return; // policy not enforced 158 } 159 final CharSequence[] entries = screenTimeoutPreference.getEntries(); 160 final CharSequence[] values = screenTimeoutPreference.getEntryValues(); 161 ArrayList<CharSequence> revisedEntries = new ArrayList<CharSequence>(); 162 ArrayList<CharSequence> revisedValues = new ArrayList<CharSequence>(); 163 for (int i = 0; i < values.length; i++) { 164 long timeout = Long.parseLong(values[i].toString()); 165 if (timeout <= maxTimeout) { 166 revisedEntries.add(entries[i]); 167 revisedValues.add(values[i]); 168 } 169 } 170 if (revisedEntries.size() != entries.length || revisedValues.size() != values.length) { 171 final int userPreference = Integer.parseInt(screenTimeoutPreference.getValue()); 172 screenTimeoutPreference.setEntries( 173 revisedEntries.toArray(new CharSequence[revisedEntries.size()])); 174 screenTimeoutPreference.setEntryValues( 175 revisedValues.toArray(new CharSequence[revisedValues.size()])); 176 if (userPreference <= maxTimeout) { 177 screenTimeoutPreference.setValue(String.valueOf(userPreference)); 178 } else if (revisedValues.size() > 0 179 && Long.parseLong(revisedValues.get(revisedValues.size() - 1).toString()) 180 == maxTimeout) { 181 // If the last one happens to be the same as the max timeout, select that 182 screenTimeoutPreference.setValue(String.valueOf(maxTimeout)); 183 } else { 184 // There will be no highlighted selection since nothing in the list matches 185 // maxTimeout. The user can still select anything less than maxTimeout. 186 // TODO: maybe append maxTimeout to the list and mark selected. 187 } 188 } 189 screenTimeoutPreference.setEnabled(revisedEntries.size() > 0); 190 } 191 192 int floatToIndex(float val) { 193 String[] indices = getResources().getStringArray(R.array.entryvalues_font_size); 194 float lastVal = Float.parseFloat(indices[0]); 195 for (int i=1; i<indices.length; i++) { 196 float thisVal = Float.parseFloat(indices[i]); 197 if (val < (lastVal + (thisVal-lastVal)*.5f)) { 198 return i-1; 199 } 200 lastVal = thisVal; 201 } 202 return indices.length-1; 203 } 204 205 public void readFontSizePreference(ListPreference pref) { 206 try { 207 mCurConfig.updateFrom(ActivityManagerNative.getDefault().getConfiguration()); 208 } catch (RemoteException e) { 209 Log.w(TAG, "Unable to retrieve font size"); 210 } 211 212 // mark the appropriate item in the preferences list 213 int index = floatToIndex(mCurConfig.fontScale); 214 pref.setValueIndex(index); 215 216 // report the current size in the summary text 217 final Resources res = getResources(); 218 String[] fontSizeNames = res.getStringArray(R.array.entries_font_size); 219 pref.setSummary(String.format(res.getString(R.string.summary_font_size), 220 fontSizeNames[index])); 221 } 222 223 @Override 224 public void onResume() { 225 super.onResume(); 226 updateState(); 227 } 228 229 @Override 230 public Dialog onCreateDialog(int dialogId) { 231 if (dialogId == DLG_GLOBAL_CHANGE_WARNING) { 232 return Utils.buildGlobalChangeWarningDialog(getActivity(), 233 R.string.global_font_change_title, 234 new Runnable() { 235 public void run() { 236 mFontSizePref.click(); 237 } 238 }); 239 } 240 return null; 241 } 242 243 private void updateState() { 244 readFontSizePreference(mFontSizePref); 245 updateScreenSaverSummary(); 246 247 // Update auto brightness if it is available. 248 if (mAutoBrightnessPreference != null) { 249 int brightnessMode = Settings.System.getInt(getContentResolver(), 250 SCREEN_BRIGHTNESS_MODE, SCREEN_BRIGHTNESS_MODE_MANUAL); 251 mAutoBrightnessPreference.setChecked(brightnessMode != SCREEN_BRIGHTNESS_MODE_MANUAL); 252 } 253 254 // Update lift-to-wake if it is available. 255 if (mLiftToWakePreference != null) { 256 int value = Settings.Secure.getInt(getContentResolver(), WAKE_GESTURE_ENABLED, 0); 257 mLiftToWakePreference.setChecked(value != 0); 258 } 259 } 260 261 private void updateScreenSaverSummary() { 262 if (mScreenSaverPreference != null) { 263 mScreenSaverPreference.setSummary( 264 DreamSettings.getSummaryTextWithDreamName(getActivity())); 265 } 266 } 267 268 public void writeFontSizePreference(Object objValue) { 269 try { 270 mCurConfig.fontScale = Float.parseFloat(objValue.toString()); 271 ActivityManagerNative.getDefault().updatePersistentConfiguration(mCurConfig); 272 } catch (RemoteException e) { 273 Log.w(TAG, "Unable to save font size"); 274 } 275 } 276 277 @Override 278 public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) { 279 return super.onPreferenceTreeClick(preferenceScreen, preference); 280 } 281 282 @Override 283 public boolean onPreferenceChange(Preference preference, Object objValue) { 284 final String key = preference.getKey(); 285 if (KEY_SCREEN_TIMEOUT.equals(key)) { 286 try { 287 int value = Integer.parseInt((String) objValue); 288 Settings.System.putInt(getContentResolver(), SCREEN_OFF_TIMEOUT, value); 289 updateTimeoutPreferenceDescription(value); 290 } catch (NumberFormatException e) { 291 Log.e(TAG, "could not persist screen timeout setting", e); 292 } 293 } 294 if (KEY_FONT_SIZE.equals(key)) { 295 writeFontSizePreference(objValue); 296 } 297 if (preference == mAutoBrightnessPreference) { 298 boolean auto = (Boolean) objValue; 299 Settings.System.putInt(getContentResolver(), SCREEN_BRIGHTNESS_MODE, 300 auto ? SCREEN_BRIGHTNESS_MODE_AUTOMATIC : SCREEN_BRIGHTNESS_MODE_MANUAL); 301 } 302 if (preference == mLiftToWakePreference) { 303 boolean value = (Boolean) objValue; 304 Settings.Secure.putInt(getContentResolver(), WAKE_GESTURE_ENABLED, value ? 1 : 0); 305 } 306 return true; 307 } 308 309 @Override 310 public boolean onPreferenceClick(Preference preference) { 311 if (preference == mFontSizePref) { 312 if (Utils.hasMultipleUsers(getActivity())) { 313 showDialog(DLG_GLOBAL_CHANGE_WARNING); 314 return true; 315 } else { 316 mFontSizePref.click(); 317 } 318 } 319 return false; 320 } 321 322 public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = 323 new BaseSearchIndexProvider() { 324 @Override 325 public List<SearchIndexableResource> getXmlResourcesToIndex(Context context, 326 boolean enabled) { 327 ArrayList<SearchIndexableResource> result = 328 new ArrayList<SearchIndexableResource>(); 329 330 SearchIndexableResource sir = new SearchIndexableResource(context); 331 sir.xmlResId = R.xml.display_settings; 332 result.add(sir); 333 334 return result; 335 } 336 337 @Override 338 public List<String> getNonIndexableKeys(Context context) { 339 ArrayList<String> result = new ArrayList<String>(); 340 if (!context.getResources().getBoolean( 341 com.android.internal.R.bool.config_dreamsSupported)) { 342 result.add(KEY_SCREEN_SAVER); 343 } 344 if (!isAutomaticBrightnessAvailable(context.getResources())) { 345 result.add(KEY_AUTO_BRIGHTNESS); 346 } 347 if (!isLiftToWakeAvailable(context)) { 348 result.add(KEY_LIFT_TO_WAKE); 349 } 350 return result; 351 } 352 }; 353} 354