Home | History | Annotate | Download | only in settings
      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 
     17 package com.android.settings;
     18 
     19 import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
     20 
     21 import android.app.ActivityManagerNative;
     22 import android.app.Dialog;
     23 import android.app.admin.DevicePolicyManager;
     24 import android.content.BroadcastReceiver;
     25 import android.content.ContentResolver;
     26 import android.content.Context;
     27 import android.content.Intent;
     28 import android.content.IntentFilter;
     29 import android.content.res.Configuration;
     30 import android.content.res.Resources;
     31 import android.hardware.display.DisplayManager;
     32 import android.hardware.display.WifiDisplay;
     33 import android.hardware.display.WifiDisplayStatus;
     34 import android.os.Bundle;
     35 import android.os.RemoteException;
     36 import android.preference.CheckBoxPreference;
     37 import android.preference.ListPreference;
     38 import android.preference.Preference;
     39 import android.preference.Preference.OnPreferenceClickListener;
     40 import android.preference.PreferenceScreen;
     41 import android.provider.Settings;
     42 import android.provider.Settings.SettingNotFoundException;
     43 import android.util.AttributeSet;
     44 import android.util.Log;
     45 
     46 import com.android.internal.view.RotationPolicy;
     47 import com.android.settings.DreamSettings;
     48 
     49 import java.util.ArrayList;
     50 
     51 public class DisplaySettings extends SettingsPreferenceFragment implements
     52         Preference.OnPreferenceChangeListener, OnPreferenceClickListener {
     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_ACCELEROMETER = "accelerometer";
     60     private static final String KEY_FONT_SIZE = "font_size";
     61     private static final String KEY_NOTIFICATION_PULSE = "notification_pulse";
     62     private static final String KEY_SCREEN_SAVER = "screensaver";
     63     private static final String KEY_WIFI_DISPLAY = "wifi_display";
     64 
     65     private static final int DLG_GLOBAL_CHANGE_WARNING = 1;
     66 
     67     private DisplayManager mDisplayManager;
     68 
     69     private CheckBoxPreference mAccelerometer;
     70     private WarnedListPreference mFontSizePref;
     71     private CheckBoxPreference mNotificationPulse;
     72 
     73     private final Configuration mCurConfig = new Configuration();
     74 
     75     private ListPreference mScreenTimeoutPreference;
     76     private Preference mScreenSaverPreference;
     77 
     78     private WifiDisplayStatus mWifiDisplayStatus;
     79     private Preference mWifiDisplayPreference;
     80 
     81     private final RotationPolicy.RotationPolicyListener mRotationPolicyListener =
     82             new RotationPolicy.RotationPolicyListener() {
     83         @Override
     84         public void onChange() {
     85             updateAccelerometerRotationCheckbox();
     86         }
     87     };
     88 
     89     @Override
     90     public void onCreate(Bundle savedInstanceState) {
     91         super.onCreate(savedInstanceState);
     92         ContentResolver resolver = getActivity().getContentResolver();
     93 
     94         addPreferencesFromResource(R.xml.display_settings);
     95 
     96         mAccelerometer = (CheckBoxPreference) findPreference(KEY_ACCELEROMETER);
     97         mAccelerometer.setPersistent(false);
     98         if (RotationPolicy.isRotationLockToggleSupported(getActivity())) {
     99             // If rotation lock is supported, then we do not provide this option in
    100             // Display settings.  However, is still available in Accessibility settings.
    101             getPreferenceScreen().removePreference(mAccelerometer);
    102         }
    103 
    104         mScreenSaverPreference = findPreference(KEY_SCREEN_SAVER);
    105         if (mScreenSaverPreference != null
    106                 && getResources().getBoolean(
    107                         com.android.internal.R.bool.config_dreamsSupported) == false) {
    108             getPreferenceScreen().removePreference(mScreenSaverPreference);
    109         }
    110 
    111         mScreenTimeoutPreference = (ListPreference) findPreference(KEY_SCREEN_TIMEOUT);
    112         final long currentTimeout = Settings.System.getLong(resolver, SCREEN_OFF_TIMEOUT,
    113                 FALLBACK_SCREEN_TIMEOUT_VALUE);
    114         mScreenTimeoutPreference.setValue(String.valueOf(currentTimeout));
    115         mScreenTimeoutPreference.setOnPreferenceChangeListener(this);
    116         disableUnusableTimeouts(mScreenTimeoutPreference);
    117         updateTimeoutPreferenceDescription(currentTimeout);
    118 
    119         mFontSizePref = (WarnedListPreference) findPreference(KEY_FONT_SIZE);
    120         mFontSizePref.setOnPreferenceChangeListener(this);
    121         mFontSizePref.setOnPreferenceClickListener(this);
    122         mNotificationPulse = (CheckBoxPreference) findPreference(KEY_NOTIFICATION_PULSE);
    123         if (mNotificationPulse != null
    124                 && getResources().getBoolean(
    125                         com.android.internal.R.bool.config_intrusiveNotificationLed) == false) {
    126             getPreferenceScreen().removePreference(mNotificationPulse);
    127         } else {
    128             try {
    129                 mNotificationPulse.setChecked(Settings.System.getInt(resolver,
    130                         Settings.System.NOTIFICATION_LIGHT_PULSE) == 1);
    131                 mNotificationPulse.setOnPreferenceChangeListener(this);
    132             } catch (SettingNotFoundException snfe) {
    133                 Log.e(TAG, Settings.System.NOTIFICATION_LIGHT_PULSE + " not found");
    134             }
    135         }
    136 
    137         mDisplayManager = (DisplayManager)getActivity().getSystemService(
    138                 Context.DISPLAY_SERVICE);
    139         mWifiDisplayStatus = mDisplayManager.getWifiDisplayStatus();
    140         mWifiDisplayPreference = (Preference)findPreference(KEY_WIFI_DISPLAY);
    141         if (mWifiDisplayStatus.getFeatureState()
    142                 == WifiDisplayStatus.FEATURE_STATE_UNAVAILABLE) {
    143             getPreferenceScreen().removePreference(mWifiDisplayPreference);
    144             mWifiDisplayPreference = null;
    145         }
    146     }
    147 
    148     private void updateTimeoutPreferenceDescription(long currentTimeout) {
    149         ListPreference preference = mScreenTimeoutPreference;
    150         String summary;
    151         if (currentTimeout < 0) {
    152             // Unsupported value
    153             summary = "";
    154         } else {
    155             final CharSequence[] entries = preference.getEntries();
    156             final CharSequence[] values = preference.getEntryValues();
    157             if (entries == null || entries.length == 0) {
    158                 summary = "";
    159             } else {
    160                 int best = 0;
    161                 for (int i = 0; i < values.length; i++) {
    162                     long timeout = Long.parseLong(values[i].toString());
    163                     if (currentTimeout >= timeout) {
    164                         best = i;
    165                     }
    166                 }
    167                 summary = preference.getContext().getString(R.string.screen_timeout_summary,
    168                         entries[best]);
    169             }
    170         }
    171         preference.setSummary(summary);
    172     }
    173 
    174     private void disableUnusableTimeouts(ListPreference screenTimeoutPreference) {
    175         final DevicePolicyManager dpm =
    176                 (DevicePolicyManager) getActivity().getSystemService(
    177                 Context.DEVICE_POLICY_SERVICE);
    178         final long maxTimeout = dpm != null ? dpm.getMaximumTimeToLock(null) : 0;
    179         if (maxTimeout == 0) {
    180             return; // policy not enforced
    181         }
    182         final CharSequence[] entries = screenTimeoutPreference.getEntries();
    183         final CharSequence[] values = screenTimeoutPreference.getEntryValues();
    184         ArrayList<CharSequence> revisedEntries = new ArrayList<CharSequence>();
    185         ArrayList<CharSequence> revisedValues = new ArrayList<CharSequence>();
    186         for (int i = 0; i < values.length; i++) {
    187             long timeout = Long.parseLong(values[i].toString());
    188             if (timeout <= maxTimeout) {
    189                 revisedEntries.add(entries[i]);
    190                 revisedValues.add(values[i]);
    191             }
    192         }
    193         if (revisedEntries.size() != entries.length || revisedValues.size() != values.length) {
    194             screenTimeoutPreference.setEntries(
    195                     revisedEntries.toArray(new CharSequence[revisedEntries.size()]));
    196             screenTimeoutPreference.setEntryValues(
    197                     revisedValues.toArray(new CharSequence[revisedValues.size()]));
    198             final int userPreference = Integer.parseInt(screenTimeoutPreference.getValue());
    199             if (userPreference <= maxTimeout) {
    200                 screenTimeoutPreference.setValue(String.valueOf(userPreference));
    201             } else {
    202                 // There will be no highlighted selection since nothing in the list matches
    203                 // maxTimeout. The user can still select anything less than maxTimeout.
    204                 // TODO: maybe append maxTimeout to the list and mark selected.
    205             }
    206         }
    207         screenTimeoutPreference.setEnabled(revisedEntries.size() > 0);
    208     }
    209 
    210     int floatToIndex(float val) {
    211         String[] indices = getResources().getStringArray(R.array.entryvalues_font_size);
    212         float lastVal = Float.parseFloat(indices[0]);
    213         for (int i=1; i<indices.length; i++) {
    214             float thisVal = Float.parseFloat(indices[i]);
    215             if (val < (lastVal + (thisVal-lastVal)*.5f)) {
    216                 return i-1;
    217             }
    218             lastVal = thisVal;
    219         }
    220         return indices.length-1;
    221     }
    222 
    223     public void readFontSizePreference(ListPreference pref) {
    224         try {
    225             mCurConfig.updateFrom(ActivityManagerNative.getDefault().getConfiguration());
    226         } catch (RemoteException e) {
    227             Log.w(TAG, "Unable to retrieve font size");
    228         }
    229 
    230         // mark the appropriate item in the preferences list
    231         int index = floatToIndex(mCurConfig.fontScale);
    232         pref.setValueIndex(index);
    233 
    234         // report the current size in the summary text
    235         final Resources res = getResources();
    236         String[] fontSizeNames = res.getStringArray(R.array.entries_font_size);
    237         pref.setSummary(String.format(res.getString(R.string.summary_font_size),
    238                 fontSizeNames[index]));
    239     }
    240 
    241     @Override
    242     public void onResume() {
    243         super.onResume();
    244 
    245         RotationPolicy.registerRotationPolicyListener(getActivity(),
    246                 mRotationPolicyListener);
    247 
    248         if (mWifiDisplayPreference != null) {
    249             getActivity().registerReceiver(mReceiver, new IntentFilter(
    250                     DisplayManager.ACTION_WIFI_DISPLAY_STATUS_CHANGED));
    251             mWifiDisplayStatus = mDisplayManager.getWifiDisplayStatus();
    252         }
    253 
    254         updateState();
    255     }
    256 
    257     @Override
    258     public void onPause() {
    259         super.onPause();
    260 
    261         RotationPolicy.unregisterRotationPolicyListener(getActivity(),
    262                 mRotationPolicyListener);
    263 
    264         if (mWifiDisplayPreference != null) {
    265             getActivity().unregisterReceiver(mReceiver);
    266         }
    267     }
    268 
    269     @Override
    270     public Dialog onCreateDialog(int dialogId) {
    271         if (dialogId == DLG_GLOBAL_CHANGE_WARNING) {
    272             return Utils.buildGlobalChangeWarningDialog(getActivity(),
    273                     R.string.global_font_change_title,
    274                     new Runnable() {
    275                         public void run() {
    276                             mFontSizePref.click();
    277                         }
    278                     });
    279         }
    280         return null;
    281     }
    282 
    283     private void updateState() {
    284         updateAccelerometerRotationCheckbox();
    285         readFontSizePreference(mFontSizePref);
    286         updateScreenSaverSummary();
    287         updateWifiDisplaySummary();
    288     }
    289 
    290     private void updateScreenSaverSummary() {
    291         if (mScreenSaverPreference != null) {
    292             mScreenSaverPreference.setSummary(
    293                     DreamSettings.getSummaryTextWithDreamName(getActivity()));
    294         }
    295     }
    296 
    297     private void updateWifiDisplaySummary() {
    298         if (mWifiDisplayPreference != null) {
    299             switch (mWifiDisplayStatus.getFeatureState()) {
    300                 case WifiDisplayStatus.FEATURE_STATE_OFF:
    301                     mWifiDisplayPreference.setSummary(R.string.wifi_display_summary_off);
    302                     break;
    303                 case WifiDisplayStatus.FEATURE_STATE_ON:
    304                     mWifiDisplayPreference.setSummary(R.string.wifi_display_summary_on);
    305                     break;
    306                 case WifiDisplayStatus.FEATURE_STATE_DISABLED:
    307                 default:
    308                     mWifiDisplayPreference.setSummary(R.string.wifi_display_summary_disabled);
    309                     break;
    310             }
    311         }
    312     }
    313 
    314     private void updateAccelerometerRotationCheckbox() {
    315         if (getActivity() == null) return;
    316 
    317         mAccelerometer.setChecked(!RotationPolicy.isRotationLocked(getActivity()));
    318     }
    319 
    320     public void writeFontSizePreference(Object objValue) {
    321         try {
    322             mCurConfig.fontScale = Float.parseFloat(objValue.toString());
    323             ActivityManagerNative.getDefault().updatePersistentConfiguration(mCurConfig);
    324         } catch (RemoteException e) {
    325             Log.w(TAG, "Unable to save font size");
    326         }
    327     }
    328 
    329     @Override
    330     public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
    331         if (preference == mAccelerometer) {
    332             RotationPolicy.setRotationLockForAccessibility(
    333                     getActivity(), !mAccelerometer.isChecked());
    334         } else if (preference == mNotificationPulse) {
    335             boolean value = mNotificationPulse.isChecked();
    336             Settings.System.putInt(getContentResolver(), Settings.System.NOTIFICATION_LIGHT_PULSE,
    337                     value ? 1 : 0);
    338             return true;
    339         }
    340         return super.onPreferenceTreeClick(preferenceScreen, preference);
    341     }
    342 
    343     public boolean onPreferenceChange(Preference preference, Object objValue) {
    344         final String key = preference.getKey();
    345         if (KEY_SCREEN_TIMEOUT.equals(key)) {
    346             int value = Integer.parseInt((String) objValue);
    347             try {
    348                 Settings.System.putInt(getContentResolver(), SCREEN_OFF_TIMEOUT, value);
    349                 updateTimeoutPreferenceDescription(value);
    350             } catch (NumberFormatException e) {
    351                 Log.e(TAG, "could not persist screen timeout setting", e);
    352             }
    353         }
    354         if (KEY_FONT_SIZE.equals(key)) {
    355             writeFontSizePreference(objValue);
    356         }
    357 
    358         return true;
    359     }
    360 
    361     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
    362         @Override
    363         public void onReceive(Context context, Intent intent) {
    364             if (intent.getAction().equals(DisplayManager.ACTION_WIFI_DISPLAY_STATUS_CHANGED)) {
    365                 mWifiDisplayStatus = (WifiDisplayStatus)intent.getParcelableExtra(
    366                         DisplayManager.EXTRA_WIFI_DISPLAY_STATUS);
    367                 updateWifiDisplaySummary();
    368             }
    369         }
    370     };
    371 
    372     @Override
    373     public boolean onPreferenceClick(Preference preference) {
    374         if (preference == mFontSizePref) {
    375             if (Utils.hasMultipleUsers(getActivity())) {
    376                 showDialog(DLG_GLOBAL_CHANGE_WARNING);
    377                 return true;
    378             } else {
    379                 mFontSizePref.click();
    380             }
    381         }
    382         return false;
    383     }
    384 }
    385