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