DisplaySettings.java revision cbf312ec2984dcc42bc39b01f4b126b0901740cf
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 static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
20
21import android.app.ActivityManagerNative;
22import android.app.admin.DevicePolicyManager;
23import android.content.ContentResolver;
24import android.content.Context;
25import android.content.res.Configuration;
26import android.content.res.Resources;
27import android.database.ContentObserver;
28import android.os.Bundle;
29import android.os.Handler;
30import android.os.RemoteException;
31import android.os.ServiceManager;
32import android.preference.CheckBoxPreference;
33import android.preference.ListPreference;
34import android.preference.Preference;
35import android.preference.PreferenceScreen;
36import android.provider.Settings;
37import android.provider.Settings.SettingNotFoundException;
38import android.util.Log;
39import android.view.IWindowManager;
40import android.view.Surface;
41
42import java.util.ArrayList;
43
44public class DisplaySettings extends SettingsPreferenceFragment implements
45        Preference.OnPreferenceChangeListener {
46    private static final String TAG = "DisplaySettings";
47
48    /** If there is no setting in the provider, use this. */
49    private static final int FALLBACK_SCREEN_TIMEOUT_VALUE = 30000;
50
51    private static final String KEY_SCREEN_TIMEOUT = "screen_timeout";
52    private static final String KEY_ACCELEROMETER = "accelerometer";
53    private static final String KEY_FONT_SIZE = "font_size";
54    private static final String KEY_NOTIFICATION_PULSE = "notification_pulse";
55
56    private CheckBoxPreference mAccelerometer;
57    private ListPreference mFontSizePref;
58    private CheckBoxPreference mNotificationPulse;
59
60    private final Configuration mCurConfig = new Configuration();
61
62    private ListPreference mScreenTimeoutPreference;
63
64    private ContentObserver mAccelerometerRotationObserver = new ContentObserver(new Handler()) {
65        @Override
66        public void onChange(boolean selfChange) {
67            updateAccelerometerRotationCheckbox();
68        }
69    };
70
71    @Override
72    public void onCreate(Bundle savedInstanceState) {
73        super.onCreate(savedInstanceState);
74        ContentResolver resolver = getActivity().getContentResolver();
75
76        addPreferencesFromResource(R.xml.display_settings);
77
78        mAccelerometer = (CheckBoxPreference) findPreference(KEY_ACCELEROMETER);
79        mAccelerometer.setPersistent(false);
80
81        mScreenTimeoutPreference = (ListPreference) findPreference(KEY_SCREEN_TIMEOUT);
82        final long currentTimeout = Settings.System.getLong(resolver, SCREEN_OFF_TIMEOUT,
83                FALLBACK_SCREEN_TIMEOUT_VALUE);
84        mScreenTimeoutPreference.setValue(String.valueOf(currentTimeout));
85        mScreenTimeoutPreference.setOnPreferenceChangeListener(this);
86        disableUnusableTimeouts(mScreenTimeoutPreference);
87        updateTimeoutPreferenceDescription(currentTimeout);
88
89        mFontSizePref = (ListPreference) findPreference(KEY_FONT_SIZE);
90        mFontSizePref.setOnPreferenceChangeListener(this);
91        mNotificationPulse = (CheckBoxPreference) findPreference(KEY_NOTIFICATION_PULSE);
92        if (mNotificationPulse != null
93                && getResources().getBoolean(
94                        com.android.internal.R.bool.config_intrusiveNotificationLed) == false) {
95            getPreferenceScreen().removePreference(mNotificationPulse);
96        } else {
97            try {
98                mNotificationPulse.setChecked(Settings.System.getInt(resolver,
99                        Settings.System.NOTIFICATION_LIGHT_PULSE) == 1);
100                mNotificationPulse.setOnPreferenceChangeListener(this);
101            } catch (SettingNotFoundException snfe) {
102                Log.e(TAG, Settings.System.NOTIFICATION_LIGHT_PULSE + " not found");
103            }
104        }
105    }
106
107    private void updateTimeoutPreferenceDescription(long currentTimeout) {
108        ListPreference preference = mScreenTimeoutPreference;
109        String summary;
110        if (currentTimeout < 0) {
111            // Unsupported value
112            summary = "";
113        } else {
114            final CharSequence[] entries = preference.getEntries();
115            final CharSequence[] values = preference.getEntryValues();
116            int best = 0;
117            for (int i = 0; i < values.length; i++) {
118                long timeout = Long.parseLong(values[i].toString());
119                if (currentTimeout >= timeout) {
120                    best = i;
121                }
122            }
123            summary = preference.getContext().getString(R.string.screen_timeout_summary,
124                    entries[best]);
125        }
126        preference.setSummary(summary);
127    }
128
129    private void disableUnusableTimeouts(ListPreference screenTimeoutPreference) {
130        final DevicePolicyManager dpm =
131                (DevicePolicyManager) getActivity().getSystemService(
132                Context.DEVICE_POLICY_SERVICE);
133        final long maxTimeout = dpm != null ? dpm.getMaximumTimeToLock(null) : 0;
134        if (maxTimeout == 0) {
135            return; // policy not enforced
136        }
137        final CharSequence[] entries = screenTimeoutPreference.getEntries();
138        final CharSequence[] values = screenTimeoutPreference.getEntryValues();
139        ArrayList<CharSequence> revisedEntries = new ArrayList<CharSequence>();
140        ArrayList<CharSequence> revisedValues = new ArrayList<CharSequence>();
141        for (int i = 0; i < values.length; i++) {
142            long timeout = Long.parseLong(values[i].toString());
143            if (timeout <= maxTimeout) {
144                revisedEntries.add(entries[i]);
145                revisedValues.add(values[i]);
146            }
147        }
148        if (revisedEntries.size() != entries.length || revisedValues.size() != values.length) {
149            screenTimeoutPreference.setEntries(
150                    revisedEntries.toArray(new CharSequence[revisedEntries.size()]));
151            screenTimeoutPreference.setEntryValues(
152                    revisedValues.toArray(new CharSequence[revisedValues.size()]));
153            final int userPreference = Integer.parseInt(screenTimeoutPreference.getValue());
154            if (userPreference <= maxTimeout) {
155                screenTimeoutPreference.setValue(String.valueOf(userPreference));
156            } else {
157                // There will be no highlighted selection since nothing in the list matches
158                // maxTimeout. The user can still select anything less than maxTimeout.
159                // TODO: maybe append maxTimeout to the list and mark selected.
160            }
161        }
162        screenTimeoutPreference.setEnabled(revisedEntries.size() > 0);
163    }
164
165    int floatToIndex(float val) {
166        String[] indices = getResources().getStringArray(R.array.entryvalues_font_size);
167        float lastVal = Float.parseFloat(indices[0]);
168        for (int i=1; i<indices.length; i++) {
169            float thisVal = Float.parseFloat(indices[i]);
170            if (val < (lastVal + (thisVal-lastVal)*.5f)) {
171                return i-1;
172            }
173            lastVal = thisVal;
174        }
175        return indices.length-1;
176    }
177
178    public void readFontSizePreference(ListPreference pref) {
179        try {
180            mCurConfig.updateFrom(ActivityManagerNative.getDefault().getConfiguration());
181        } catch (RemoteException e) {
182            Log.w(TAG, "Unable to retrieve font size");
183        }
184
185        // mark the appropriate item in the preferences list
186        int index = floatToIndex(mCurConfig.fontScale);
187        pref.setValueIndex(index);
188
189        // report the current size in the summary text
190        final Resources res = getResources();
191        String[] fontSizeNames = res.getStringArray(R.array.entries_font_size);
192        pref.setSummary(String.format(res.getString(R.string.summary_font_size),
193                fontSizeNames[index]));
194    }
195
196    @Override
197    public void onResume() {
198        super.onResume();
199
200        updateState();
201        getContentResolver().registerContentObserver(
202                Settings.System.getUriFor(Settings.System.ACCELEROMETER_ROTATION), true,
203                mAccelerometerRotationObserver);
204    }
205
206    @Override
207    public void onPause() {
208        super.onPause();
209
210        getContentResolver().unregisterContentObserver(mAccelerometerRotationObserver);
211    }
212
213    private void updateState() {
214        updateAccelerometerRotationCheckbox();
215        readFontSizePreference(mFontSizePref);
216    }
217
218    private void updateAccelerometerRotationCheckbox() {
219        mAccelerometer.setChecked(Settings.System.getInt(
220                getContentResolver(),
221                Settings.System.ACCELEROMETER_ROTATION, 0) != 0);
222    }
223
224    public void writeFontSizePreference(Object objValue) {
225        try {
226            mCurConfig.fontScale = Float.parseFloat(objValue.toString());
227            ActivityManagerNative.getDefault().updatePersistentConfiguration(mCurConfig);
228        } catch (RemoteException e) {
229            Log.w(TAG, "Unable to save font size");
230        }
231    }
232
233    @Override
234    public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
235        if (preference == mAccelerometer) {
236            try {
237                IWindowManager wm = IWindowManager.Stub.asInterface(
238                        ServiceManager.getService(Context.WINDOW_SERVICE));
239                if (mAccelerometer.isChecked()) {
240                    wm.thawRotation();
241                } else {
242                    wm.freezeRotation(Surface.ROTATION_0);
243                }
244            } catch (RemoteException exc) {
245                Log.w(TAG, "Unable to save auto-rotate setting");
246            }
247        } else if (preference == mNotificationPulse) {
248            boolean value = mNotificationPulse.isChecked();
249            Settings.System.putInt(getContentResolver(), Settings.System.NOTIFICATION_LIGHT_PULSE,
250                    value ? 1 : 0);
251            return true;
252        }
253        return super.onPreferenceTreeClick(preferenceScreen, preference);
254    }
255
256    public boolean onPreferenceChange(Preference preference, Object objValue) {
257        final String key = preference.getKey();
258        if (KEY_SCREEN_TIMEOUT.equals(key)) {
259            int value = Integer.parseInt((String) objValue);
260            try {
261                Settings.System.putInt(getContentResolver(), SCREEN_OFF_TIMEOUT, value);
262                updateTimeoutPreferenceDescription(value);
263            } catch (NumberFormatException e) {
264                Log.e(TAG, "could not persist screen timeout setting", e);
265            }
266        }
267        if (KEY_FONT_SIZE.equals(key)) {
268            writeFontSizePreference(objValue);
269        }
270
271        return true;
272    }
273}
274