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 android.app.Activity; 21 import android.app.AlertDialog; 22 import android.app.admin.DevicePolicyManager; 23 import android.content.ComponentName; 24 import android.content.Context; 25 import android.content.DialogInterface; 26 import android.content.Intent; 27 import android.content.pm.PackageManager; 28 import android.content.pm.ResolveInfo; 29 import android.content.pm.UserInfo; 30 import android.content.res.Resources; 31 import android.os.Bundle; 32 import android.os.UserHandle; 33 import android.os.UserManager; 34 import android.preference.SwitchPreference; 35 import android.preference.ListPreference; 36 import android.preference.Preference; 37 import android.preference.Preference.OnPreferenceChangeListener; 38 import android.preference.PreferenceGroup; 39 import android.preference.PreferenceScreen; 40 import android.provider.SearchIndexableResource; 41 import android.provider.Settings; 42 import android.provider.Settings.SettingNotFoundException; 43 import android.security.KeyStore; 44 import android.service.trust.TrustAgentService; 45 import android.telephony.TelephonyManager; 46 import android.telephony.SubscriptionManager; 47 import android.telephony.SubscriptionInfo; 48 import android.text.TextUtils; 49 import android.util.Log; 50 51 import com.android.internal.widget.LockPatternUtils; 52 import com.android.settings.TrustAgentUtils.TrustAgentComponentInfo; 53 import com.android.settings.search.BaseSearchIndexProvider; 54 import com.android.settings.search.Index; 55 import com.android.settings.search.Indexable; 56 import com.android.settings.search.SearchIndexableRaw; 57 58 import java.util.ArrayList; 59 import java.util.List; 60 61 import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT; 62 63 /** 64 * Gesture lock pattern settings. 65 */ 66 public class SecuritySettings extends SettingsPreferenceFragment 67 implements OnPreferenceChangeListener, DialogInterface.OnClickListener, Indexable { 68 private static final String TRUST_AGENT_CLICK_INTENT = "trust_agent_click_intent"; 69 static final String TAG = "SecuritySettings"; 70 private static final Intent TRUST_AGENT_INTENT = 71 new Intent(TrustAgentService.SERVICE_INTERFACE); 72 73 // Lock Settings 74 private static final String KEY_UNLOCK_SET_OR_CHANGE = "unlock_set_or_change"; 75 private static final String KEY_BIOMETRIC_WEAK_IMPROVE_MATCHING = 76 "biometric_weak_improve_matching"; 77 private static final String KEY_BIOMETRIC_WEAK_LIVELINESS = "biometric_weak_liveliness"; 78 private static final String KEY_LOCK_ENABLED = "lockenabled"; 79 private static final String KEY_VISIBLE_PATTERN = "visiblepattern"; 80 private static final String KEY_SECURITY_CATEGORY = "security_category"; 81 private static final String KEY_DEVICE_ADMIN_CATEGORY = "device_admin_category"; 82 private static final String KEY_LOCK_AFTER_TIMEOUT = "lock_after_timeout"; 83 private static final String KEY_OWNER_INFO_SETTINGS = "owner_info_settings"; 84 private static final String KEY_ADVANCED_SECURITY = "advanced_security"; 85 private static final String KEY_MANAGE_TRUST_AGENTS = "manage_trust_agents"; 86 87 private static final int SET_OR_CHANGE_LOCK_METHOD_REQUEST = 123; 88 private static final int CONFIRM_EXISTING_FOR_BIOMETRIC_WEAK_IMPROVE_REQUEST = 124; 89 private static final int CONFIRM_EXISTING_FOR_BIOMETRIC_WEAK_LIVELINESS_OFF = 125; 90 private static final int CHANGE_TRUST_AGENT_SETTINGS = 126; 91 92 // Misc Settings 93 private static final String KEY_SIM_LOCK = "sim_lock"; 94 private static final String KEY_SHOW_PASSWORD = "show_password"; 95 private static final String KEY_CREDENTIAL_STORAGE_TYPE = "credential_storage_type"; 96 private static final String KEY_RESET_CREDENTIALS = "credentials_reset"; 97 private static final String KEY_CREDENTIALS_INSTALL = "credentials_install"; 98 private static final String KEY_TOGGLE_INSTALL_APPLICATIONS = "toggle_install_applications"; 99 private static final String KEY_POWER_INSTANTLY_LOCKS = "power_button_instantly_locks"; 100 private static final String KEY_CREDENTIALS_MANAGER = "credentials_management"; 101 private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive"; 102 private static final String KEY_TRUST_AGENT = "trust_agent"; 103 private static final String KEY_SCREEN_PINNING = "screen_pinning_settings"; 104 105 // These switch preferences need special handling since they're not all stored in Settings. 106 private static final String SWITCH_PREFERENCE_KEYS[] = { KEY_LOCK_AFTER_TIMEOUT, 107 KEY_LOCK_ENABLED, KEY_VISIBLE_PATTERN, KEY_BIOMETRIC_WEAK_LIVELINESS, 108 KEY_POWER_INSTANTLY_LOCKS, KEY_SHOW_PASSWORD, KEY_TOGGLE_INSTALL_APPLICATIONS }; 109 110 // Only allow one trust agent on the platform. 111 private static final boolean ONLY_ONE_TRUST_AGENT = true; 112 113 private DevicePolicyManager mDPM; 114 private SubscriptionManager mSubscriptionManager; 115 116 private ChooseLockSettingsHelper mChooseLockSettingsHelper; 117 private LockPatternUtils mLockPatternUtils; 118 private ListPreference mLockAfter; 119 120 private SwitchPreference mBiometricWeakLiveliness; 121 private SwitchPreference mVisiblePattern; 122 123 private SwitchPreference mShowPassword; 124 125 private KeyStore mKeyStore; 126 private Preference mResetCredentials; 127 128 private SwitchPreference mToggleAppInstallation; 129 private DialogInterface mWarnInstallApps; 130 private SwitchPreference mPowerButtonInstantlyLocks; 131 132 private boolean mIsPrimary; 133 134 private Intent mTrustAgentClickIntent; 135 136 @Override 137 public void onCreate(Bundle savedInstanceState) { 138 super.onCreate(savedInstanceState); 139 140 mSubscriptionManager = SubscriptionManager.from(getActivity()); 141 142 mLockPatternUtils = new LockPatternUtils(getActivity()); 143 144 mDPM = (DevicePolicyManager)getSystemService(Context.DEVICE_POLICY_SERVICE); 145 146 mChooseLockSettingsHelper = new ChooseLockSettingsHelper(getActivity()); 147 148 if (savedInstanceState != null 149 && savedInstanceState.containsKey(TRUST_AGENT_CLICK_INTENT)) { 150 mTrustAgentClickIntent = savedInstanceState.getParcelable(TRUST_AGENT_CLICK_INTENT); 151 } 152 } 153 154 private static int getResIdForLockUnlockScreen(Context context, 155 LockPatternUtils lockPatternUtils) { 156 int resid = 0; 157 if (!lockPatternUtils.isSecure()) { 158 // if there are multiple users, disable "None" setting 159 UserManager mUm = (UserManager) context. getSystemService(Context.USER_SERVICE); 160 List<UserInfo> users = mUm.getUsers(true); 161 final boolean singleUser = users.size() == 1; 162 163 if (singleUser && lockPatternUtils.isLockScreenDisabled()) { 164 resid = R.xml.security_settings_lockscreen; 165 } else { 166 resid = R.xml.security_settings_chooser; 167 } 168 } else if (lockPatternUtils.usingBiometricWeak() && 169 lockPatternUtils.isBiometricWeakInstalled()) { 170 resid = R.xml.security_settings_biometric_weak; 171 } else { 172 switch (lockPatternUtils.getKeyguardStoredPasswordQuality()) { 173 case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING: 174 resid = R.xml.security_settings_pattern; 175 break; 176 case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC: 177 case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX: 178 resid = R.xml.security_settings_pin; 179 break; 180 case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC: 181 case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC: 182 case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX: 183 resid = R.xml.security_settings_password; 184 break; 185 } 186 } 187 return resid; 188 } 189 190 /** 191 * Important! 192 * 193 * Don't forget to update the SecuritySearchIndexProvider if you are doing any change in the 194 * logic or adding/removing preferences here. 195 */ 196 private PreferenceScreen createPreferenceHierarchy() { 197 PreferenceScreen root = getPreferenceScreen(); 198 if (root != null) { 199 root.removeAll(); 200 } 201 addPreferencesFromResource(R.xml.security_settings); 202 root = getPreferenceScreen(); 203 204 // Add options for lock/unlock screen 205 final int resid = getResIdForLockUnlockScreen(getActivity(), mLockPatternUtils); 206 addPreferencesFromResource(resid); 207 208 // Add options for device encryption 209 mIsPrimary = UserHandle.myUserId() == UserHandle.USER_OWNER; 210 211 if (!mIsPrimary) { 212 // Rename owner info settings 213 Preference ownerInfoPref = findPreference(KEY_OWNER_INFO_SETTINGS); 214 if (ownerInfoPref != null) { 215 if (UserManager.get(getActivity()).isLinkedUser()) { 216 ownerInfoPref.setTitle(R.string.profile_info_settings_title); 217 } else { 218 ownerInfoPref.setTitle(R.string.user_info_settings_title); 219 } 220 } 221 } 222 223 if (mIsPrimary) { 224 if (LockPatternUtils.isDeviceEncryptionEnabled()) { 225 // The device is currently encrypted. 226 addPreferencesFromResource(R.xml.security_settings_encrypted); 227 } else { 228 // This device supports encryption but isn't encrypted. 229 addPreferencesFromResource(R.xml.security_settings_unencrypted); 230 } 231 } 232 233 // Trust Agent preferences 234 PreferenceGroup securityCategory = (PreferenceGroup) 235 root.findPreference(KEY_SECURITY_CATEGORY); 236 if (securityCategory != null) { 237 final boolean hasSecurity = mLockPatternUtils.isSecure(); 238 ArrayList<TrustAgentComponentInfo> agents = 239 getActiveTrustAgents(getPackageManager(), mLockPatternUtils); 240 for (int i = 0; i < agents.size(); i++) { 241 final TrustAgentComponentInfo agent = agents.get(i); 242 Preference trustAgentPreference = 243 new Preference(securityCategory.getContext()); 244 trustAgentPreference.setKey(KEY_TRUST_AGENT); 245 trustAgentPreference.setTitle(agent.title); 246 trustAgentPreference.setSummary(agent.summary); 247 // Create intent for this preference. 248 Intent intent = new Intent(); 249 intent.setComponent(agent.componentName); 250 intent.setAction(Intent.ACTION_MAIN); 251 trustAgentPreference.setIntent(intent); 252 // Add preference to the settings menu. 253 securityCategory.addPreference(trustAgentPreference); 254 if (!hasSecurity) { 255 trustAgentPreference.setEnabled(false); 256 trustAgentPreference.setSummary(R.string.disabled_because_no_backup_security); 257 } 258 } 259 } 260 261 // lock after preference 262 mLockAfter = (ListPreference) root.findPreference(KEY_LOCK_AFTER_TIMEOUT); 263 if (mLockAfter != null) { 264 setupLockAfterPreference(); 265 updateLockAfterPreferenceSummary(); 266 } 267 268 // biometric weak liveliness 269 mBiometricWeakLiveliness = 270 (SwitchPreference) root.findPreference(KEY_BIOMETRIC_WEAK_LIVELINESS); 271 272 // visible pattern 273 mVisiblePattern = (SwitchPreference) root.findPreference(KEY_VISIBLE_PATTERN); 274 275 // lock instantly on power key press 276 mPowerButtonInstantlyLocks = (SwitchPreference) root.findPreference( 277 KEY_POWER_INSTANTLY_LOCKS); 278 Preference trustAgentPreference = root.findPreference(KEY_TRUST_AGENT); 279 if (mPowerButtonInstantlyLocks != null && 280 trustAgentPreference != null && 281 trustAgentPreference.getTitle().length() > 0) { 282 mPowerButtonInstantlyLocks.setSummary(getString( 283 R.string.lockpattern_settings_power_button_instantly_locks_summary, 284 trustAgentPreference.getTitle())); 285 } 286 287 // don't display visible pattern if biometric and backup is not pattern 288 if (resid == R.xml.security_settings_biometric_weak && 289 mLockPatternUtils.getKeyguardStoredPasswordQuality() != 290 DevicePolicyManager.PASSWORD_QUALITY_SOMETHING) { 291 if (securityCategory != null && mVisiblePattern != null) { 292 securityCategory.removePreference(root.findPreference(KEY_VISIBLE_PATTERN)); 293 } 294 } 295 296 // Append the rest of the settings 297 addPreferencesFromResource(R.xml.security_settings_misc); 298 299 // Do not display SIM lock for devices without an Icc card 300 TelephonyManager tm = TelephonyManager.getDefault(); 301 if (!mIsPrimary || !isSimIccReady()) { 302 root.removePreference(root.findPreference(KEY_SIM_LOCK)); 303 } else { 304 // Disable SIM lock if there is no ready SIM card. 305 root.findPreference(KEY_SIM_LOCK).setEnabled(isSimReady()); 306 } 307 if (Settings.System.getInt(getContentResolver(), 308 Settings.System.LOCK_TO_APP_ENABLED, 0) != 0) { 309 root.findPreference(KEY_SCREEN_PINNING).setSummary( 310 getResources().getString(R.string.switch_on_text)); 311 } 312 313 // Show password 314 mShowPassword = (SwitchPreference) root.findPreference(KEY_SHOW_PASSWORD); 315 mResetCredentials = root.findPreference(KEY_RESET_CREDENTIALS); 316 317 // Credential storage 318 final UserManager um = (UserManager) getActivity().getSystemService(Context.USER_SERVICE); 319 mKeyStore = KeyStore.getInstance(); // needs to be initialized for onResume() 320 if (!um.hasUserRestriction(UserManager.DISALLOW_CONFIG_CREDENTIALS)) { 321 Preference credentialStorageType = root.findPreference(KEY_CREDENTIAL_STORAGE_TYPE); 322 323 final int storageSummaryRes = 324 mKeyStore.isHardwareBacked() ? R.string.credential_storage_type_hardware 325 : R.string.credential_storage_type_software; 326 credentialStorageType.setSummary(storageSummaryRes); 327 } else { 328 PreferenceGroup credentialsManager = (PreferenceGroup) 329 root.findPreference(KEY_CREDENTIALS_MANAGER); 330 credentialsManager.removePreference(root.findPreference(KEY_RESET_CREDENTIALS)); 331 credentialsManager.removePreference(root.findPreference(KEY_CREDENTIALS_INSTALL)); 332 credentialsManager.removePreference(root.findPreference(KEY_CREDENTIAL_STORAGE_TYPE)); 333 } 334 335 // Application install 336 PreferenceGroup deviceAdminCategory = (PreferenceGroup) 337 root.findPreference(KEY_DEVICE_ADMIN_CATEGORY); 338 mToggleAppInstallation = (SwitchPreference) findPreference( 339 KEY_TOGGLE_INSTALL_APPLICATIONS); 340 mToggleAppInstallation.setChecked(isNonMarketAppsAllowed()); 341 // Side loading of apps. 342 // Disable for restricted profiles. For others, check if policy disallows it. 343 mToggleAppInstallation.setEnabled(!um.getUserInfo(UserHandle.myUserId()).isRestricted()); 344 if (um.hasUserRestriction(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES) 345 || um.hasUserRestriction(UserManager.DISALLOW_INSTALL_APPS)) { 346 mToggleAppInstallation.setEnabled(false); 347 } 348 349 // Advanced Security features 350 PreferenceGroup advancedCategory = 351 (PreferenceGroup)root.findPreference(KEY_ADVANCED_SECURITY); 352 if (advancedCategory != null) { 353 Preference manageAgents = advancedCategory.findPreference(KEY_MANAGE_TRUST_AGENTS); 354 if (manageAgents != null && !mLockPatternUtils.isSecure()) { 355 manageAgents.setEnabled(false); 356 manageAgents.setSummary(R.string.disabled_because_no_backup_security); 357 } 358 } 359 360 // The above preferences come and go based on security state, so we need to update 361 // the index. This call is expected to be fairly cheap, but we may want to do something 362 // smarter in the future. 363 Index.getInstance(getActivity()) 364 .updateFromClassNameResource(SecuritySettings.class.getName(), true, true); 365 366 for (int i = 0; i < SWITCH_PREFERENCE_KEYS.length; i++) { 367 final Preference pref = findPreference(SWITCH_PREFERENCE_KEYS[i]); 368 if (pref != null) pref.setOnPreferenceChangeListener(this); 369 } 370 return root; 371 } 372 373 /* Return true if a there is a Slot that has Icc. 374 */ 375 private boolean isSimIccReady() { 376 TelephonyManager tm = TelephonyManager.getDefault(); 377 final List<SubscriptionInfo> subInfoList = 378 mSubscriptionManager.getActiveSubscriptionInfoList(); 379 380 if (subInfoList != null) { 381 for (SubscriptionInfo subInfo : subInfoList) { 382 if (tm.hasIccCard(subInfo.getSimSlotIndex())) { 383 return true; 384 } 385 } 386 } 387 388 return false; 389 } 390 391 /* Return true if a SIM is ready for locking. 392 * TODO: consider adding to TelephonyManager or SubscritpionManasger. 393 */ 394 private boolean isSimReady() { 395 int simState = TelephonyManager.SIM_STATE_UNKNOWN; 396 final List<SubscriptionInfo> subInfoList = 397 mSubscriptionManager.getActiveSubscriptionInfoList(); 398 if (subInfoList != null) { 399 for (SubscriptionInfo subInfo : subInfoList) { 400 simState = TelephonyManager.getDefault().getSimState(subInfo.getSimSlotIndex()); 401 if((simState != TelephonyManager.SIM_STATE_ABSENT) && 402 (simState != TelephonyManager.SIM_STATE_UNKNOWN)){ 403 return true; 404 } 405 } 406 } 407 return false; 408 } 409 410 private static ArrayList<TrustAgentComponentInfo> getActiveTrustAgents( 411 PackageManager pm, LockPatternUtils utils) { 412 ArrayList<TrustAgentComponentInfo> result = new ArrayList<TrustAgentComponentInfo>(); 413 List<ResolveInfo> resolveInfos = pm.queryIntentServices(TRUST_AGENT_INTENT, 414 PackageManager.GET_META_DATA); 415 List<ComponentName> enabledTrustAgents = utils.getEnabledTrustAgents(); 416 if (enabledTrustAgents != null && !enabledTrustAgents.isEmpty()) { 417 for (int i = 0; i < resolveInfos.size(); i++) { 418 ResolveInfo resolveInfo = resolveInfos.get(i); 419 if (resolveInfo.serviceInfo == null) continue; 420 if (!TrustAgentUtils.checkProvidePermission(resolveInfo, pm)) continue; 421 TrustAgentComponentInfo trustAgentComponentInfo = 422 TrustAgentUtils.getSettingsComponent(pm, resolveInfo); 423 if (trustAgentComponentInfo.componentName == null || 424 !enabledTrustAgents.contains( 425 TrustAgentUtils.getComponentName(resolveInfo)) || 426 TextUtils.isEmpty(trustAgentComponentInfo.title)) continue; 427 result.add(trustAgentComponentInfo); 428 if (ONLY_ONE_TRUST_AGENT) break; 429 } 430 } 431 return result; 432 } 433 434 private boolean isNonMarketAppsAllowed() { 435 return Settings.Global.getInt(getContentResolver(), 436 Settings.Global.INSTALL_NON_MARKET_APPS, 0) > 0; 437 } 438 439 private void setNonMarketAppsAllowed(boolean enabled) { 440 final UserManager um = (UserManager) getActivity().getSystemService(Context.USER_SERVICE); 441 if (um.hasUserRestriction(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES)) { 442 return; 443 } 444 // Change the system setting 445 Settings.Global.putInt(getContentResolver(), Settings.Global.INSTALL_NON_MARKET_APPS, 446 enabled ? 1 : 0); 447 } 448 449 private void warnAppInstallation() { 450 // TODO: DialogFragment? 451 mWarnInstallApps = new AlertDialog.Builder(getActivity()).setTitle( 452 getResources().getString(R.string.error_title)) 453 .setIcon(com.android.internal.R.drawable.ic_dialog_alert) 454 .setMessage(getResources().getString(R.string.install_all_warning)) 455 .setPositiveButton(android.R.string.yes, this) 456 .setNegativeButton(android.R.string.no, this) 457 .show(); 458 } 459 460 @Override 461 public void onClick(DialogInterface dialog, int which) { 462 if (dialog == mWarnInstallApps) { 463 boolean turnOn = which == DialogInterface.BUTTON_POSITIVE; 464 setNonMarketAppsAllowed(turnOn); 465 if (mToggleAppInstallation != null) { 466 mToggleAppInstallation.setChecked(turnOn); 467 } 468 } 469 } 470 471 @Override 472 public void onDestroy() { 473 super.onDestroy(); 474 if (mWarnInstallApps != null) { 475 mWarnInstallApps.dismiss(); 476 } 477 } 478 479 private void setupLockAfterPreference() { 480 // Compatible with pre-Froyo 481 long currentTimeout = Settings.Secure.getLong(getContentResolver(), 482 Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT, 5000); 483 mLockAfter.setValue(String.valueOf(currentTimeout)); 484 mLockAfter.setOnPreferenceChangeListener(this); 485 final long adminTimeout = (mDPM != null ? mDPM.getMaximumTimeToLock(null) : 0); 486 final long displayTimeout = Math.max(0, 487 Settings.System.getInt(getContentResolver(), SCREEN_OFF_TIMEOUT, 0)); 488 if (adminTimeout > 0) { 489 // This setting is a slave to display timeout when a device policy is enforced. 490 // As such, maxLockTimeout = adminTimeout - displayTimeout. 491 // If there isn't enough time, shows "immediately" setting. 492 disableUnusableTimeouts(Math.max(0, adminTimeout - displayTimeout)); 493 } 494 } 495 496 private void updateLockAfterPreferenceSummary() { 497 // Update summary message with current value 498 long currentTimeout = Settings.Secure.getLong(getContentResolver(), 499 Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT, 5000); 500 final CharSequence[] entries = mLockAfter.getEntries(); 501 final CharSequence[] values = mLockAfter.getEntryValues(); 502 int best = 0; 503 for (int i = 0; i < values.length; i++) { 504 long timeout = Long.valueOf(values[i].toString()); 505 if (currentTimeout >= timeout) { 506 best = i; 507 } 508 } 509 510 Preference preference = getPreferenceScreen().findPreference(KEY_TRUST_AGENT); 511 if (preference != null && preference.getTitle().length() > 0) { 512 mLockAfter.setSummary(getString(R.string.lock_after_timeout_summary_with_exception, 513 entries[best], preference.getTitle())); 514 } else { 515 mLockAfter.setSummary(getString(R.string.lock_after_timeout_summary, entries[best])); 516 } 517 } 518 519 private void disableUnusableTimeouts(long maxTimeout) { 520 final CharSequence[] entries = mLockAfter.getEntries(); 521 final CharSequence[] values = mLockAfter.getEntryValues(); 522 ArrayList<CharSequence> revisedEntries = new ArrayList<CharSequence>(); 523 ArrayList<CharSequence> revisedValues = new ArrayList<CharSequence>(); 524 for (int i = 0; i < values.length; i++) { 525 long timeout = Long.valueOf(values[i].toString()); 526 if (timeout <= maxTimeout) { 527 revisedEntries.add(entries[i]); 528 revisedValues.add(values[i]); 529 } 530 } 531 if (revisedEntries.size() != entries.length || revisedValues.size() != values.length) { 532 mLockAfter.setEntries( 533 revisedEntries.toArray(new CharSequence[revisedEntries.size()])); 534 mLockAfter.setEntryValues( 535 revisedValues.toArray(new CharSequence[revisedValues.size()])); 536 final int userPreference = Integer.valueOf(mLockAfter.getValue()); 537 if (userPreference <= maxTimeout) { 538 mLockAfter.setValue(String.valueOf(userPreference)); 539 } else { 540 // There will be no highlighted selection since nothing in the list matches 541 // maxTimeout. The user can still select anything less than maxTimeout. 542 // TODO: maybe append maxTimeout to the list and mark selected. 543 } 544 } 545 mLockAfter.setEnabled(revisedEntries.size() > 0); 546 } 547 548 @Override 549 public void onSaveInstanceState(Bundle outState) { 550 super.onSaveInstanceState(outState); 551 if (mTrustAgentClickIntent != null) { 552 outState.putParcelable(TRUST_AGENT_CLICK_INTENT, mTrustAgentClickIntent); 553 } 554 } 555 556 @Override 557 public void onResume() { 558 super.onResume(); 559 560 // Make sure we reload the preference hierarchy since some of these settings 561 // depend on others... 562 createPreferenceHierarchy(); 563 564 final LockPatternUtils lockPatternUtils = mChooseLockSettingsHelper.utils(); 565 if (mBiometricWeakLiveliness != null) { 566 mBiometricWeakLiveliness.setChecked( 567 lockPatternUtils.isBiometricWeakLivelinessEnabled()); 568 } 569 if (mVisiblePattern != null) { 570 mVisiblePattern.setChecked(lockPatternUtils.isVisiblePatternEnabled()); 571 } 572 if (mPowerButtonInstantlyLocks != null) { 573 mPowerButtonInstantlyLocks.setChecked(lockPatternUtils.getPowerButtonInstantlyLocks()); 574 } 575 576 if (mShowPassword != null) { 577 mShowPassword.setChecked(Settings.System.getInt(getContentResolver(), 578 Settings.System.TEXT_SHOW_PASSWORD, 1) != 0); 579 } 580 581 if (mResetCredentials != null) { 582 mResetCredentials.setEnabled(!mKeyStore.isEmpty()); 583 } 584 } 585 586 @Override 587 public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) { 588 final String key = preference.getKey(); 589 if (KEY_UNLOCK_SET_OR_CHANGE.equals(key)) { 590 startFragment(this, "com.android.settings.ChooseLockGeneric$ChooseLockGenericFragment", 591 R.string.lock_settings_picker_title, SET_OR_CHANGE_LOCK_METHOD_REQUEST, null); 592 } else if (KEY_BIOMETRIC_WEAK_IMPROVE_MATCHING.equals(key)) { 593 ChooseLockSettingsHelper helper = 594 new ChooseLockSettingsHelper(this.getActivity(), this); 595 if (!helper.launchConfirmationActivity( 596 CONFIRM_EXISTING_FOR_BIOMETRIC_WEAK_IMPROVE_REQUEST, null, null)) { 597 // If this returns false, it means no password confirmation is required, so 598 // go ahead and start improve. 599 // Note: currently a backup is required for biometric_weak so this code path 600 // can't be reached, but is here in case things change in the future 601 startBiometricWeakImprove(); 602 } 603 } else if (KEY_TRUST_AGENT.equals(key)) { 604 ChooseLockSettingsHelper helper = 605 new ChooseLockSettingsHelper(this.getActivity(), this); 606 mTrustAgentClickIntent = preference.getIntent(); 607 if (!helper.launchConfirmationActivity(CHANGE_TRUST_AGENT_SETTINGS, null, null) && 608 mTrustAgentClickIntent != null) { 609 // If this returns false, it means no password confirmation is required. 610 startActivity(mTrustAgentClickIntent); 611 mTrustAgentClickIntent = null; 612 } 613 } else { 614 // If we didn't handle it, let preferences handle it. 615 return super.onPreferenceTreeClick(preferenceScreen, preference); 616 } 617 return true; 618 } 619 620 /** 621 * see confirmPatternThenDisableAndClear 622 */ 623 @Override 624 public void onActivityResult(int requestCode, int resultCode, Intent data) { 625 super.onActivityResult(requestCode, resultCode, data); 626 if (requestCode == CONFIRM_EXISTING_FOR_BIOMETRIC_WEAK_IMPROVE_REQUEST && 627 resultCode == Activity.RESULT_OK) { 628 startBiometricWeakImprove(); 629 return; 630 } else if (requestCode == CONFIRM_EXISTING_FOR_BIOMETRIC_WEAK_LIVELINESS_OFF && 631 resultCode == Activity.RESULT_OK) { 632 final LockPatternUtils lockPatternUtils = mChooseLockSettingsHelper.utils(); 633 lockPatternUtils.setBiometricWeakLivelinessEnabled(false); 634 // Setting the mBiometricWeakLiveliness checked value to false is handled when onResume 635 // is called by grabbing the value from lockPatternUtils. We can't set it here 636 // because mBiometricWeakLiveliness could be null 637 return; 638 } else if (requestCode == CHANGE_TRUST_AGENT_SETTINGS && resultCode == Activity.RESULT_OK) { 639 if (mTrustAgentClickIntent != null) { 640 startActivity(mTrustAgentClickIntent); 641 mTrustAgentClickIntent = null; 642 } 643 return; 644 } 645 createPreferenceHierarchy(); 646 } 647 648 @Override 649 public boolean onPreferenceChange(Preference preference, Object value) { 650 boolean result = true; 651 final String key = preference.getKey(); 652 final LockPatternUtils lockPatternUtils = mChooseLockSettingsHelper.utils(); 653 if (KEY_LOCK_AFTER_TIMEOUT.equals(key)) { 654 int timeout = Integer.parseInt((String) value); 655 try { 656 Settings.Secure.putInt(getContentResolver(), 657 Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT, timeout); 658 } catch (NumberFormatException e) { 659 Log.e("SecuritySettings", "could not persist lockAfter timeout setting", e); 660 } 661 updateLockAfterPreferenceSummary(); 662 } else if (KEY_LOCK_ENABLED.equals(key)) { 663 lockPatternUtils.setLockPatternEnabled((Boolean) value); 664 } else if (KEY_VISIBLE_PATTERN.equals(key)) { 665 lockPatternUtils.setVisiblePatternEnabled((Boolean) value); 666 } else if (KEY_BIOMETRIC_WEAK_LIVELINESS.equals(key)) { 667 if ((Boolean) value) { 668 lockPatternUtils.setBiometricWeakLivelinessEnabled(true); 669 } else { 670 // In this case the user has just unchecked the checkbox, but this action requires 671 // them to confirm their password. We need to re-check the checkbox until 672 // they've confirmed their password 673 mBiometricWeakLiveliness.setChecked(true); 674 ChooseLockSettingsHelper helper = 675 new ChooseLockSettingsHelper(this.getActivity(), this); 676 if (!helper.launchConfirmationActivity( 677 CONFIRM_EXISTING_FOR_BIOMETRIC_WEAK_LIVELINESS_OFF, null, null)) { 678 // If this returns false, it means no password confirmation is required, so 679 // go ahead and uncheck it here. 680 // Note: currently a backup is required for biometric_weak so this code path 681 // can't be reached, but is here in case things change in the future 682 lockPatternUtils.setBiometricWeakLivelinessEnabled(false); 683 mBiometricWeakLiveliness.setChecked(false); 684 } 685 } 686 } else if (KEY_POWER_INSTANTLY_LOCKS.equals(key)) { 687 mLockPatternUtils.setPowerButtonInstantlyLocks((Boolean) value); 688 } else if (KEY_SHOW_PASSWORD.equals(key)) { 689 Settings.System.putInt(getContentResolver(), Settings.System.TEXT_SHOW_PASSWORD, 690 ((Boolean) value) ? 1 : 0); 691 } else if (KEY_TOGGLE_INSTALL_APPLICATIONS.equals(key)) { 692 if ((Boolean) value) { 693 mToggleAppInstallation.setChecked(false); 694 warnAppInstallation(); 695 // Don't change Switch status until user makes choice in dialog, so return false. 696 result = false; 697 } else { 698 setNonMarketAppsAllowed(false); 699 } 700 } 701 return result; 702 } 703 704 @Override 705 protected int getHelpResource() { 706 return R.string.help_url_security; 707 } 708 709 public void startBiometricWeakImprove(){ 710 Intent intent = new Intent(); 711 intent.setClassName("com.android.facelock", "com.android.facelock.AddToSetup"); 712 startActivity(intent); 713 } 714 715 /** 716 * For Search. Please keep it in sync when updating "createPreferenceHierarchy()" 717 */ 718 public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = 719 new SecuritySearchIndexProvider(); 720 721 private static class SecuritySearchIndexProvider extends BaseSearchIndexProvider { 722 723 boolean mIsPrimary; 724 725 public SecuritySearchIndexProvider() { 726 super(); 727 728 mIsPrimary = UserHandle.myUserId() == UserHandle.USER_OWNER; 729 } 730 731 @Override 732 public List<SearchIndexableResource> getXmlResourcesToIndex( 733 Context context, boolean enabled) { 734 735 List<SearchIndexableResource> result = new ArrayList<SearchIndexableResource>(); 736 737 LockPatternUtils lockPatternUtils = new LockPatternUtils(context); 738 // Add options for lock/unlock screen 739 int resId = getResIdForLockUnlockScreen(context, lockPatternUtils); 740 741 SearchIndexableResource sir = new SearchIndexableResource(context); 742 sir.xmlResId = resId; 743 result.add(sir); 744 745 if (mIsPrimary) { 746 DevicePolicyManager dpm = (DevicePolicyManager) 747 context.getSystemService(Context.DEVICE_POLICY_SERVICE); 748 749 switch (dpm.getStorageEncryptionStatus()) { 750 case DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE: 751 // The device is currently encrypted. 752 resId = R.xml.security_settings_encrypted; 753 break; 754 case DevicePolicyManager.ENCRYPTION_STATUS_INACTIVE: 755 // This device supports encryption but isn't encrypted. 756 resId = R.xml.security_settings_unencrypted; 757 break; 758 } 759 760 sir = new SearchIndexableResource(context); 761 sir.xmlResId = resId; 762 result.add(sir); 763 } 764 765 // Append the rest of the settings 766 sir = new SearchIndexableResource(context); 767 sir.xmlResId = R.xml.security_settings_misc; 768 result.add(sir); 769 770 return result; 771 } 772 773 @Override 774 public List<SearchIndexableRaw> getRawDataToIndex(Context context, boolean enabled) { 775 final List<SearchIndexableRaw> result = new ArrayList<SearchIndexableRaw>(); 776 final Resources res = context.getResources(); 777 778 final String screenTitle = res.getString(R.string.security_settings_title); 779 780 SearchIndexableRaw data = new SearchIndexableRaw(context); 781 data.title = screenTitle; 782 data.screenTitle = screenTitle; 783 result.add(data); 784 785 if (!mIsPrimary) { 786 int resId = (UserManager.get(context).isLinkedUser()) ? 787 R.string.profile_info_settings_title : R.string.user_info_settings_title; 788 789 data = new SearchIndexableRaw(context); 790 data.title = res.getString(resId); 791 data.screenTitle = screenTitle; 792 result.add(data); 793 } 794 795 // Credential storage 796 final UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE); 797 798 if (!um.hasUserRestriction(UserManager.DISALLOW_CONFIG_CREDENTIALS)) { 799 KeyStore keyStore = KeyStore.getInstance(); 800 801 final int storageSummaryRes = keyStore.isHardwareBacked() ? 802 R.string.credential_storage_type_hardware : 803 R.string.credential_storage_type_software; 804 805 data = new SearchIndexableRaw(context); 806 data.title = res.getString(storageSummaryRes); 807 data.screenTitle = screenTitle; 808 result.add(data); 809 } 810 811 // Advanced 812 final LockPatternUtils lockPatternUtils = new LockPatternUtils(context); 813 if (lockPatternUtils.isSecure()) { 814 ArrayList<TrustAgentComponentInfo> agents = 815 getActiveTrustAgents(context.getPackageManager(), lockPatternUtils); 816 for (int i = 0; i < agents.size(); i++) { 817 final TrustAgentComponentInfo agent = agents.get(i); 818 data = new SearchIndexableRaw(context); 819 data.title = agent.title; 820 data.screenTitle = screenTitle; 821 result.add(data); 822 } 823 } 824 return result; 825 } 826 827 @Override 828 public List<String> getNonIndexableKeys(Context context) { 829 final List<String> keys = new ArrayList<String>(); 830 831 LockPatternUtils lockPatternUtils = new LockPatternUtils(context); 832 // Add options for lock/unlock screen 833 int resId = getResIdForLockUnlockScreen(context, lockPatternUtils); 834 835 // don't display visible pattern if biometric and backup is not pattern 836 if (resId == R.xml.security_settings_biometric_weak && 837 lockPatternUtils.getKeyguardStoredPasswordQuality() != 838 DevicePolicyManager.PASSWORD_QUALITY_SOMETHING) { 839 keys.add(KEY_VISIBLE_PATTERN); 840 } 841 842 // Do not display SIM lock for devices without an Icc card 843 TelephonyManager tm = TelephonyManager.getDefault(); 844 if (!mIsPrimary || !tm.hasIccCard()) { 845 keys.add(KEY_SIM_LOCK); 846 } 847 848 final UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE); 849 if (um.hasUserRestriction(UserManager.DISALLOW_CONFIG_CREDENTIALS)) { 850 keys.add(KEY_CREDENTIALS_MANAGER); 851 } 852 853 // TrustAgent settings disappear when the user has no primary security. 854 if (!lockPatternUtils.isSecure()) { 855 keys.add(KEY_TRUST_AGENT); 856 keys.add(KEY_MANAGE_TRUST_AGENTS); 857 } 858 859 return keys; 860 } 861 } 862 863 } 864