OSDN Git Service

am 3f3f390b: am a6daa21d: (-s ours) am 015788ca: Merge "Import translations for cherr...
[android-x86/packages-apps-Settings.git] / src / com / android / settings / SecuritySettings.java
1 /*
2  * Copyright (C) 2007 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
20 import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
21
22 import com.android.internal.widget.LockPatternUtils;
23
24 import android.app.admin.DevicePolicyManager;
25 import android.content.ContentQueryMap;
26 import android.content.ContentResolver;
27 import android.content.Context;
28 import android.content.Intent;
29 import android.database.Cursor;
30 import android.location.LocationManager;
31 import android.os.Bundle;
32 import android.os.Vibrator;
33 import android.preference.CheckBoxPreference;
34 import android.preference.ListPreference;
35 import android.preference.Preference;
36 import android.preference.Preference.OnPreferenceChangeListener;
37 import android.preference.PreferenceGroup;
38 import android.preference.PreferenceScreen;
39 import android.provider.Settings;
40 import android.security.KeyStore;
41 import android.telephony.TelephonyManager;
42 import android.util.Log;
43
44 import java.util.ArrayList;
45 import java.util.Observable;
46 import java.util.Observer;
47
48 /**
49  * Gesture lock pattern settings.
50  */
51 public class SecuritySettings extends SettingsPreferenceFragment
52         implements OnPreferenceChangeListener {
53
54     // Lock Settings
55     private static final String KEY_UNLOCK_SET_OR_CHANGE = "unlock_set_or_change";
56     private static final String KEY_LOCK_ENABLED = "lockenabled";
57     private static final String KEY_VISIBLE_PATTERN = "visiblepattern";
58     private static final String KEY_TACTILE_FEEDBACK_ENABLED = "unlock_tactile_feedback";
59     private static final String KEY_SECURITY_CATEGORY = "security_category";
60     private static final String KEY_LOCK_AFTER_TIMEOUT = "lock_after_timeout";
61     private static final int SET_OR_CHANGE_LOCK_METHOD_REQUEST = 123;
62
63     // Location Settings
64     private static final String KEY_LOCATION_CATEGORY = "location_category";
65     private static final String KEY_LOCATION_NETWORK = "location_network";
66     private static final String KEY_LOCATION_GPS = "location_gps";
67     private static final String KEY_ASSISTED_GPS = "assisted_gps";
68     private static final String KEY_USE_LOCATION = "location_use_for_services";
69
70     // Misc Settings
71     private static final String KEY_SIM_LOCK = "sim_lock";
72     private static final String KEY_SHOW_PASSWORD = "show_password";
73     private static final String KEY_RESET_CREDENTIALS = "reset_credentials";
74
75     private static final String TAG = "SecuritySettings";
76
77     private CheckBoxPreference mNetwork;
78     private CheckBoxPreference mGps;
79     private CheckBoxPreference mAssistedGps;
80     private CheckBoxPreference mUseLocation;
81
82     DevicePolicyManager mDPM;
83
84     // These provide support for receiving notification when Location Manager settings change.
85     // This is necessary because the Network Location Provider can change settings
86     // if the user does not confirm enabling the provider.
87     private ContentQueryMap mContentQueryMap;
88
89     private ChooseLockSettingsHelper mChooseLockSettingsHelper;
90     private LockPatternUtils mLockPatternUtils;
91     private ListPreference mLockAfter;
92
93     private Observer mSettingsObserver;
94
95     private CheckBoxPreference mVisiblePattern;
96     private CheckBoxPreference mTactileFeedback;
97
98     private CheckBoxPreference mShowPassword;
99
100     private Preference mResetCredentials;
101
102     @Override
103     public void onCreate(Bundle savedInstanceState) {
104         super.onCreate(savedInstanceState);
105
106         mLockPatternUtils = new LockPatternUtils(getActivity());
107
108         mDPM = (DevicePolicyManager)getSystemService(Context.DEVICE_POLICY_SERVICE);
109
110         mChooseLockSettingsHelper = new ChooseLockSettingsHelper(getActivity());
111     }
112
113     @Override
114     public void onStart() {
115         super.onStart();
116         // listen for Location Manager settings changes
117         Cursor settingsCursor = getContentResolver().query(Settings.Secure.CONTENT_URI, null,
118                 "(" + Settings.System.NAME + "=?)",
119                 new String[]{Settings.Secure.LOCATION_PROVIDERS_ALLOWED},
120                 null);
121         mContentQueryMap = new ContentQueryMap(settingsCursor, Settings.System.NAME, true, null);
122     }
123
124     @Override
125     public void onStop() {
126         super.onStop();
127         if (mSettingsObserver != null) {
128             mContentQueryMap.deleteObserver(mSettingsObserver);
129         }
130     }
131
132     private PreferenceScreen createPreferenceHierarchy() {
133         PreferenceScreen root = getPreferenceScreen();
134         if (root != null) {
135             root.removeAll();
136         }
137         addPreferencesFromResource(R.xml.security_settings);
138         root = getPreferenceScreen();
139
140         mNetwork = (CheckBoxPreference) root.findPreference(KEY_LOCATION_NETWORK);
141         mGps = (CheckBoxPreference) root.findPreference(KEY_LOCATION_GPS);
142         mAssistedGps = (CheckBoxPreference) root.findPreference(KEY_ASSISTED_GPS);
143         if (GoogleLocationSettingHelper.isAvailable(getActivity())) {
144             // GSF present, Add setting for 'Use My Location'
145             PreferenceGroup locationCat =
146                     (PreferenceGroup) root.findPreference(KEY_LOCATION_CATEGORY);
147             CheckBoxPreference useLocation = new CheckBoxPreference(getActivity());
148             useLocation.setKey(KEY_USE_LOCATION);
149             useLocation.setTitle(R.string.use_location_title);
150             useLocation.setSummaryOn(R.string.use_location_summary_enabled);
151             useLocation.setSummaryOff(R.string.use_location_summary_disabled);
152             useLocation.setChecked(
153                     GoogleLocationSettingHelper.getUseLocationForServices(getActivity())
154                     == GoogleLocationSettingHelper.USE_LOCATION_FOR_SERVICES_ON);
155             useLocation.setPersistent(false);
156             useLocation.setOnPreferenceChangeListener(this);
157             locationCat.addPreference(useLocation);
158             mUseLocation = useLocation;
159         }
160
161         // Change the summary for wifi-only devices
162         if (Utils.isWifiOnly()) {
163             mNetwork.setSummaryOn(R.string.location_neighborhood_level_wifi);
164         }
165
166         // Add options for lock/unlock screen
167         int resid = 0;
168         if (!mLockPatternUtils.isSecure()) {
169             if (mLockPatternUtils.isLockScreenDisabled()) {
170                 resid = R.xml.security_settings_lockscreen;
171             } else {
172                 resid = R.xml.security_settings_chooser;
173             }
174         } else {
175             switch (mLockPatternUtils.getKeyguardStoredPasswordQuality()) {
176                 case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
177                     resid = R.xml.security_settings_pattern;
178                     break;
179                 case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
180                     resid = R.xml.security_settings_pin;
181                     break;
182                 case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
183                 case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
184                 case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
185                     resid = R.xml.security_settings_password;
186                     break;
187             }
188         }
189         addPreferencesFromResource(resid);
190
191
192         // Add options for device encryption
193         DevicePolicyManager dpm =
194                 (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
195
196         switch (dpm.getStorageEncryptionStatus()) {
197         case DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE:
198             // The device is currently encrypted.
199             addPreferencesFromResource(R.xml.security_settings_encrypted);
200             break;
201         case DevicePolicyManager.ENCRYPTION_STATUS_INACTIVE:
202             // This device supports encryption but isn't encrypted.
203             addPreferencesFromResource(R.xml.security_settings_unencrypted);
204             break;
205         }
206
207         // lock after preference
208         mLockAfter = (ListPreference) root.findPreference(KEY_LOCK_AFTER_TIMEOUT);
209         if (mLockAfter != null) {
210             setupLockAfterPreference();
211             updateLockAfterPreferenceSummary();
212         }
213
214         // visible pattern
215         mVisiblePattern = (CheckBoxPreference) root.findPreference(KEY_VISIBLE_PATTERN);
216
217         // tactile feedback. Should be common to all unlock preference screens.
218         mTactileFeedback = (CheckBoxPreference) root.findPreference(KEY_TACTILE_FEEDBACK_ENABLED);
219         if (!((Vibrator) getSystemService(Context.VIBRATOR_SERVICE)).hasVibrator()) {
220             PreferenceGroup securityCategory = (PreferenceGroup)
221                     root.findPreference(KEY_SECURITY_CATEGORY);
222             if (securityCategory != null && mTactileFeedback != null) {
223                 securityCategory.removePreference(mTactileFeedback);
224             }
225         }
226
227         // Append the rest of the settings
228         addPreferencesFromResource(R.xml.security_settings_misc);
229
230         // Do not display SIM lock for CDMA phone
231         if (TelephonyManager.PHONE_TYPE_CDMA ==
232                 TelephonyManager.getDefault().getCurrentPhoneType()) {
233             root.removePreference(root.findPreference(KEY_SIM_LOCK));
234         }
235
236         // Show password
237         mShowPassword = (CheckBoxPreference) root.findPreference(KEY_SHOW_PASSWORD);
238
239         // Credential storage
240         mResetCredentials = root.findPreference(KEY_RESET_CREDENTIALS);
241
242         return root;
243     }
244
245     private void setupLockAfterPreference() {
246         // Compatible with pre-Froyo
247         long currentTimeout = Settings.Secure.getLong(getContentResolver(),
248                 Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT, 5000);
249         mLockAfter.setValue(String.valueOf(currentTimeout));
250         mLockAfter.setOnPreferenceChangeListener(this);
251         final long adminTimeout = (mDPM != null ? mDPM.getMaximumTimeToLock(null) : 0);
252         final long displayTimeout = Math.max(0,
253                 Settings.System.getInt(getContentResolver(), SCREEN_OFF_TIMEOUT, 0));
254         if (adminTimeout > 0) {
255             // This setting is a slave to display timeout when a device policy is enforced.
256             // As such, maxLockTimeout = adminTimeout - displayTimeout.
257             // If there isn't enough time, shows "immediately" setting.
258             disableUnusableTimeouts(Math.max(0, adminTimeout - displayTimeout));
259         }
260     }
261
262     private void updateLockAfterPreferenceSummary() {
263         // Update summary message with current value
264         long currentTimeout = Settings.Secure.getLong(getContentResolver(),
265                 Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT, 0);
266         final CharSequence[] entries = mLockAfter.getEntries();
267         final CharSequence[] values = mLockAfter.getEntryValues();
268         int best = 0;
269         for (int i = 0; i < values.length; i++) {
270             long timeout = Long.valueOf(values[i].toString());
271             if (currentTimeout >= timeout) {
272                 best = i;
273             }
274         }
275         mLockAfter.setSummary(getString(R.string.lock_after_timeout_summary, entries[best]));
276     }
277
278     private void disableUnusableTimeouts(long maxTimeout) {
279         final CharSequence[] entries = mLockAfter.getEntries();
280         final CharSequence[] values = mLockAfter.getEntryValues();
281         ArrayList<CharSequence> revisedEntries = new ArrayList<CharSequence>();
282         ArrayList<CharSequence> revisedValues = new ArrayList<CharSequence>();
283         for (int i = 0; i < values.length; i++) {
284             long timeout = Long.valueOf(values[i].toString());
285             if (timeout <= maxTimeout) {
286                 revisedEntries.add(entries[i]);
287                 revisedValues.add(values[i]);
288             }
289         }
290         if (revisedEntries.size() != entries.length || revisedValues.size() != values.length) {
291             mLockAfter.setEntries(
292                     revisedEntries.toArray(new CharSequence[revisedEntries.size()]));
293             mLockAfter.setEntryValues(
294                     revisedValues.toArray(new CharSequence[revisedValues.size()]));
295             final int userPreference = Integer.valueOf(mLockAfter.getValue());
296             if (userPreference <= maxTimeout) {
297                 mLockAfter.setValue(String.valueOf(userPreference));
298             } else {
299                 // There will be no highlighted selection since nothing in the list matches
300                 // maxTimeout. The user can still select anything less than maxTimeout.
301                 // TODO: maybe append maxTimeout to the list and mark selected.
302             }
303         }
304         mLockAfter.setEnabled(revisedEntries.size() > 0);
305     }
306
307     @Override
308     public void onResume() {
309         super.onResume();
310
311         // Make sure we reload the preference hierarchy since some of these settings
312         // depend on others...
313         createPreferenceHierarchy();
314         updateLocationToggles();
315
316         if (mSettingsObserver == null) {
317             mSettingsObserver = new Observer() {
318                 public void update(Observable o, Object arg) {
319                     updateLocationToggles();
320                 }
321             };
322             mContentQueryMap.addObserver(mSettingsObserver);
323         }
324
325         final LockPatternUtils lockPatternUtils = mChooseLockSettingsHelper.utils();
326         if (mVisiblePattern != null) {
327             mVisiblePattern.setChecked(lockPatternUtils.isVisiblePatternEnabled());
328         }
329         if (mTactileFeedback != null) {
330             mTactileFeedback.setChecked(lockPatternUtils.isTactileFeedbackEnabled());
331         }
332
333         mShowPassword.setChecked(Settings.System.getInt(getContentResolver(),
334                 Settings.System.TEXT_SHOW_PASSWORD, 1) != 0);
335
336         KeyStore.State state = KeyStore.getInstance().state();
337         mResetCredentials.setEnabled(state != KeyStore.State.UNINITIALIZED);
338     }
339
340     @Override
341     public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen,
342             Preference preference) {
343         final String key = preference.getKey();
344
345         final LockPatternUtils lockPatternUtils = mChooseLockSettingsHelper.utils();
346         if (KEY_UNLOCK_SET_OR_CHANGE.equals(key)) {
347             startFragment(this, "com.android.settings.ChooseLockGeneric$ChooseLockGenericFragment",
348                     SET_OR_CHANGE_LOCK_METHOD_REQUEST, null);
349         } else if (KEY_LOCK_ENABLED.equals(key)) {
350             lockPatternUtils.setLockPatternEnabled(isToggled(preference));
351         } else if (KEY_VISIBLE_PATTERN.equals(key)) {
352             lockPatternUtils.setVisiblePatternEnabled(isToggled(preference));
353         } else if (KEY_TACTILE_FEEDBACK_ENABLED.equals(key)) {
354             lockPatternUtils.setTactileFeedbackEnabled(isToggled(preference));
355         } else if (preference == mShowPassword) {
356             Settings.System.putInt(getContentResolver(), Settings.System.TEXT_SHOW_PASSWORD,
357                     mShowPassword.isChecked() ? 1 : 0);
358         } else if (preference == mNetwork) {
359             Settings.Secure.setLocationProviderEnabled(getContentResolver(),
360                     LocationManager.NETWORK_PROVIDER, mNetwork.isChecked());
361         } else if (preference == mGps) {
362             boolean enabled = mGps.isChecked();
363             Settings.Secure.setLocationProviderEnabled(getContentResolver(),
364                     LocationManager.GPS_PROVIDER, enabled);
365             if (mAssistedGps != null) {
366                 mAssistedGps.setEnabled(enabled);
367             }
368         } else if (preference == mAssistedGps) {
369             Settings.Secure.putInt(getContentResolver(), Settings.Secure.ASSISTED_GPS_ENABLED,
370                     mAssistedGps.isChecked() ? 1 : 0);
371         } else {
372             // If we didn't handle it, let preferences handle it.
373             return super.onPreferenceTreeClick(preferenceScreen, preference);
374         }
375
376         return true;
377     }
378
379     /*
380      * Creates toggles for each available location provider
381      */
382     private void updateLocationToggles() {
383         ContentResolver res = getContentResolver();
384         boolean gpsEnabled = Settings.Secure.isLocationProviderEnabled(
385                 res, LocationManager.GPS_PROVIDER);
386         mNetwork.setChecked(Settings.Secure.isLocationProviderEnabled(
387                 res, LocationManager.NETWORK_PROVIDER));
388         mGps.setChecked(gpsEnabled);
389         if (mAssistedGps != null) {
390             mAssistedGps.setChecked(Settings.Secure.getInt(res,
391                     Settings.Secure.ASSISTED_GPS_ENABLED, 2) == 1);
392             mAssistedGps.setEnabled(gpsEnabled);
393         }
394     }
395
396     private boolean isToggled(Preference pref) {
397         return ((CheckBoxPreference) pref).isChecked();
398     }
399
400     /**
401      * @see #confirmPatternThenDisableAndClear
402      */
403     @Override
404     public void onActivityResult(int requestCode, int resultCode, Intent data) {
405         super.onActivityResult(requestCode, resultCode, data);
406         createPreferenceHierarchy();
407     }
408
409     public boolean onPreferenceChange(Preference preference, Object value) {
410         if (preference == mLockAfter) {
411             int timeout = Integer.parseInt((String) value);
412             try {
413                 Settings.Secure.putInt(getContentResolver(),
414                         Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT, timeout);
415             } catch (NumberFormatException e) {
416                 Log.e("SecuritySettings", "could not persist lockAfter timeout setting", e);
417             }
418             updateLockAfterPreferenceSummary();
419         } else if (preference == mUseLocation) {
420             boolean newValue = (value == null ? false : (Boolean) value);
421             GoogleLocationSettingHelper.setUseLocationForServices(getActivity(), newValue);
422             // We don't want to change the value immediately here, since the user may click
423             // disagree in the dialog that pops up. When the activity we just launched exits, this
424             // activity will be restated and the new value re-read, so the checkbox will get its
425             // new value then.
426             return false;
427         }
428         return true;
429     }
430 }