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 android.app.Activity; 23 import android.app.AlertDialog; 24 import android.app.admin.DevicePolicyManager; 25 import android.content.Context; 26 import android.content.DialogInterface; 27 import android.content.Intent; 28 import android.content.pm.PackageManager; 29 import android.content.pm.ResolveInfo; 30 import android.content.pm.UserInfo; 31 import android.os.Bundle; 32 import android.os.UserHandle; 33 import android.os.UserManager; 34 import android.preference.CheckBoxPreference; 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.Settings; 41 import android.security.KeyStore; 42 import android.telephony.TelephonyManager; 43 import android.util.Log; 44 45 import com.android.internal.widget.LockPatternUtils; 46 47 import java.util.ArrayList; 48 import java.util.List; 49 50 /** 51 * Gesture lock pattern settings. 52 */ 53 public class SecuritySettings extends SettingsPreferenceFragment 54 implements OnPreferenceChangeListener, DialogInterface.OnClickListener { 55 56 static final String TAG = "SecuritySettings"; 57 58 // Lock Settings 59 private static final String KEY_UNLOCK_SET_OR_CHANGE = "unlock_set_or_change"; 60 private static final String KEY_BIOMETRIC_WEAK_IMPROVE_MATCHING = 61 "biometric_weak_improve_matching"; 62 private static final String KEY_BIOMETRIC_WEAK_LIVELINESS = "biometric_weak_liveliness"; 63 private static final String KEY_LOCK_ENABLED = "lockenabled"; 64 private static final String KEY_VISIBLE_PATTERN = "visiblepattern"; 65 private static final String KEY_SECURITY_CATEGORY = "security_category"; 66 private static final String KEY_DEVICE_ADMIN_CATEGORY = "device_admin_category"; 67 private static final String KEY_LOCK_AFTER_TIMEOUT = "lock_after_timeout"; 68 private static final String KEY_OWNER_INFO_SETTINGS = "owner_info_settings"; 69 private static final int SET_OR_CHANGE_LOCK_METHOD_REQUEST = 123; 70 private static final int CONFIRM_EXISTING_FOR_BIOMETRIC_WEAK_IMPROVE_REQUEST = 124; 71 private static final int CONFIRM_EXISTING_FOR_BIOMETRIC_WEAK_LIVELINESS_OFF = 125; 72 73 // Misc Settings 74 private static final String KEY_SIM_LOCK = "sim_lock"; 75 private static final String KEY_SHOW_PASSWORD = "show_password"; 76 private static final String KEY_CREDENTIAL_STORAGE_TYPE = "credential_storage_type"; 77 private static final String KEY_RESET_CREDENTIALS = "reset_credentials"; 78 private static final String KEY_TOGGLE_INSTALL_APPLICATIONS = "toggle_install_applications"; 79 private static final String KEY_TOGGLE_VERIFY_APPLICATIONS = "toggle_verify_applications"; 80 private static final String KEY_POWER_INSTANTLY_LOCKS = "power_button_instantly_locks"; 81 private static final String KEY_CREDENTIALS_MANAGER = "credentials_management"; 82 private static final String KEY_NOTIFICATION_ACCESS = "manage_notification_access"; 83 private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive"; 84 85 private PackageManager mPM; 86 DevicePolicyManager mDPM; 87 88 private ChooseLockSettingsHelper mChooseLockSettingsHelper; 89 private LockPatternUtils mLockPatternUtils; 90 private ListPreference mLockAfter; 91 92 private CheckBoxPreference mBiometricWeakLiveliness; 93 private CheckBoxPreference mVisiblePattern; 94 95 private CheckBoxPreference mShowPassword; 96 97 private KeyStore mKeyStore; 98 private Preference mResetCredentials; 99 100 private CheckBoxPreference mToggleAppInstallation; 101 private DialogInterface mWarnInstallApps; 102 private CheckBoxPreference mToggleVerifyApps; 103 private CheckBoxPreference mPowerButtonInstantlyLocks; 104 105 private Preference mNotificationAccess; 106 107 private boolean mIsPrimary; 108 109 @Override 110 public void onCreate(Bundle savedInstanceState) { 111 super.onCreate(savedInstanceState); 112 113 mLockPatternUtils = new LockPatternUtils(getActivity()); 114 115 mPM = getActivity().getPackageManager(); 116 mDPM = (DevicePolicyManager)getSystemService(Context.DEVICE_POLICY_SERVICE); 117 118 mChooseLockSettingsHelper = new ChooseLockSettingsHelper(getActivity()); 119 } 120 121 private PreferenceScreen createPreferenceHierarchy() { 122 PreferenceScreen root = getPreferenceScreen(); 123 if (root != null) { 124 root.removeAll(); 125 } 126 addPreferencesFromResource(R.xml.security_settings); 127 root = getPreferenceScreen(); 128 129 // Add options for lock/unlock screen 130 int resid = 0; 131 if (!mLockPatternUtils.isSecure()) { 132 // if there are multiple users, disable "None" setting 133 UserManager mUm = (UserManager) getSystemService(Context.USER_SERVICE); 134 List<UserInfo> users = mUm.getUsers(true); 135 final boolean singleUser = users.size() == 1; 136 137 if (singleUser && mLockPatternUtils.isLockScreenDisabled()) { 138 resid = R.xml.security_settings_lockscreen; 139 } else { 140 resid = R.xml.security_settings_chooser; 141 } 142 } else if (mLockPatternUtils.usingBiometricWeak() && 143 mLockPatternUtils.isBiometricWeakInstalled()) { 144 resid = R.xml.security_settings_biometric_weak; 145 } else { 146 switch (mLockPatternUtils.getKeyguardStoredPasswordQuality()) { 147 case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING: 148 resid = R.xml.security_settings_pattern; 149 break; 150 case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC: 151 resid = R.xml.security_settings_pin; 152 break; 153 case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC: 154 case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC: 155 case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX: 156 resid = R.xml.security_settings_password; 157 break; 158 } 159 } 160 addPreferencesFromResource(resid); 161 162 163 // Add options for device encryption 164 DevicePolicyManager dpm = 165 (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE); 166 167 mIsPrimary = UserHandle.myUserId() == UserHandle.USER_OWNER; 168 169 if (!mIsPrimary) { 170 // Rename owner info settings 171 Preference ownerInfoPref = findPreference(KEY_OWNER_INFO_SETTINGS); 172 if (ownerInfoPref != null) { 173 if (UserManager.get(getActivity()).isLinkedUser()) { 174 ownerInfoPref.setTitle(R.string.profile_info_settings_title); 175 } else { 176 ownerInfoPref.setTitle(R.string.user_info_settings_title); 177 } 178 } 179 } 180 181 if (mIsPrimary) { 182 switch (dpm.getStorageEncryptionStatus()) { 183 case DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE: 184 // The device is currently encrypted. 185 addPreferencesFromResource(R.xml.security_settings_encrypted); 186 break; 187 case DevicePolicyManager.ENCRYPTION_STATUS_INACTIVE: 188 // This device supports encryption but isn't encrypted. 189 addPreferencesFromResource(R.xml.security_settings_unencrypted); 190 break; 191 } 192 } 193 194 // lock after preference 195 mLockAfter = (ListPreference) root.findPreference(KEY_LOCK_AFTER_TIMEOUT); 196 if (mLockAfter != null) { 197 setupLockAfterPreference(); 198 updateLockAfterPreferenceSummary(); 199 } 200 201 // biometric weak liveliness 202 mBiometricWeakLiveliness = 203 (CheckBoxPreference) root.findPreference(KEY_BIOMETRIC_WEAK_LIVELINESS); 204 205 // visible pattern 206 mVisiblePattern = (CheckBoxPreference) root.findPreference(KEY_VISIBLE_PATTERN); 207 208 // lock instantly on power key press 209 mPowerButtonInstantlyLocks = (CheckBoxPreference) root.findPreference( 210 KEY_POWER_INSTANTLY_LOCKS); 211 212 // don't display visible pattern if biometric and backup is not pattern 213 if (resid == R.xml.security_settings_biometric_weak && 214 mLockPatternUtils.getKeyguardStoredPasswordQuality() != 215 DevicePolicyManager.PASSWORD_QUALITY_SOMETHING) { 216 PreferenceGroup securityCategory = (PreferenceGroup) 217 root.findPreference(KEY_SECURITY_CATEGORY); 218 if (securityCategory != null && mVisiblePattern != null) { 219 securityCategory.removePreference(root.findPreference(KEY_VISIBLE_PATTERN)); 220 } 221 } 222 223 // Append the rest of the settings 224 addPreferencesFromResource(R.xml.security_settings_misc); 225 226 // Do not display SIM lock for devices without an Icc card 227 TelephonyManager tm = TelephonyManager.getDefault(); 228 if (!mIsPrimary || !tm.hasIccCard()) { 229 root.removePreference(root.findPreference(KEY_SIM_LOCK)); 230 } else { 231 // Disable SIM lock if sim card is missing or unknown 232 if ((TelephonyManager.getDefault().getSimState() == 233 TelephonyManager.SIM_STATE_ABSENT) || 234 (TelephonyManager.getDefault().getSimState() == 235 TelephonyManager.SIM_STATE_UNKNOWN)) { 236 root.findPreference(KEY_SIM_LOCK).setEnabled(false); 237 } 238 } 239 240 // Show password 241 mShowPassword = (CheckBoxPreference) root.findPreference(KEY_SHOW_PASSWORD); 242 243 // Credential storage 244 final UserManager um = (UserManager) getActivity().getSystemService(Context.USER_SERVICE); 245 if (!um.hasUserRestriction(UserManager.DISALLOW_CONFIG_CREDENTIALS)) { 246 mKeyStore = KeyStore.getInstance(); 247 Preference credentialStorageType = root.findPreference(KEY_CREDENTIAL_STORAGE_TYPE); 248 249 final int storageSummaryRes = 250 mKeyStore.isHardwareBacked() ? R.string.credential_storage_type_hardware 251 : R.string.credential_storage_type_software; 252 credentialStorageType.setSummary(storageSummaryRes); 253 254 mResetCredentials = root.findPreference(KEY_RESET_CREDENTIALS); 255 } else { 256 removePreference(KEY_CREDENTIALS_MANAGER); 257 } 258 259 // Application install 260 PreferenceGroup deviceAdminCategory= (PreferenceGroup) 261 root.findPreference(KEY_DEVICE_ADMIN_CATEGORY); 262 mToggleAppInstallation = (CheckBoxPreference) findPreference( 263 KEY_TOGGLE_INSTALL_APPLICATIONS); 264 mToggleAppInstallation.setChecked(isNonMarketAppsAllowed()); 265 266 // Side loading of apps. 267 mToggleAppInstallation.setEnabled(mIsPrimary); 268 269 // Package verification, only visible to primary user and if enabled 270 mToggleVerifyApps = (CheckBoxPreference) findPreference(KEY_TOGGLE_VERIFY_APPLICATIONS); 271 if (mIsPrimary && showVerifierSetting()) { 272 if (isVerifierInstalled()) { 273 mToggleVerifyApps.setChecked(isVerifyAppsEnabled()); 274 } else { 275 mToggleVerifyApps.setChecked(false); 276 mToggleVerifyApps.setEnabled(false); 277 } 278 } else { 279 if (deviceAdminCategory != null) { 280 deviceAdminCategory.removePreference(mToggleVerifyApps); 281 } else { 282 mToggleVerifyApps.setEnabled(false); 283 } 284 } 285 286 mNotificationAccess = findPreference(KEY_NOTIFICATION_ACCESS); 287 if (mNotificationAccess != null) { 288 final int total = NotificationAccessSettings.getListenersCount(mPM); 289 if (total == 0) { 290 if (deviceAdminCategory != null) { 291 deviceAdminCategory.removePreference(mNotificationAccess); 292 } 293 } else { 294 final int n = getNumEnabledNotificationListeners(); 295 if (n == 0) { 296 mNotificationAccess.setSummary(getResources().getString( 297 R.string.manage_notification_access_summary_zero)); 298 } else { 299 mNotificationAccess.setSummary(String.format(getResources().getQuantityString( 300 R.plurals.manage_notification_access_summary_nonzero, 301 n, n))); 302 } 303 } 304 } 305 306 return root; 307 } 308 309 private int getNumEnabledNotificationListeners() { 310 final String flat = Settings.Secure.getString(getContentResolver(), 311 Settings.Secure.ENABLED_NOTIFICATION_LISTENERS); 312 if (flat == null || "".equals(flat)) return 0; 313 final String[] components = flat.split(":"); 314 return components.length; 315 } 316 317 private boolean isNonMarketAppsAllowed() { 318 return Settings.Global.getInt(getContentResolver(), 319 Settings.Global.INSTALL_NON_MARKET_APPS, 0) > 0; 320 } 321 322 private void setNonMarketAppsAllowed(boolean enabled) { 323 final UserManager um = (UserManager) getActivity().getSystemService(Context.USER_SERVICE); 324 if (um.hasUserRestriction(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES)) { 325 return; 326 } 327 // Change the system setting 328 Settings.Global.putInt(getContentResolver(), Settings.Global.INSTALL_NON_MARKET_APPS, 329 enabled ? 1 : 0); 330 } 331 332 private boolean isVerifyAppsEnabled() { 333 return Settings.Global.getInt(getContentResolver(), 334 Settings.Global.PACKAGE_VERIFIER_ENABLE, 1) > 0; 335 } 336 337 private boolean isVerifierInstalled() { 338 final PackageManager pm = getPackageManager(); 339 final Intent verification = new Intent(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION); 340 verification.setType(PACKAGE_MIME_TYPE); 341 verification.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); 342 final List<ResolveInfo> receivers = pm.queryBroadcastReceivers(verification, 0); 343 return (receivers.size() > 0) ? true : false; 344 } 345 346 private boolean showVerifierSetting() { 347 return Settings.Global.getInt(getContentResolver(), 348 Settings.Global.PACKAGE_VERIFIER_SETTING_VISIBLE, 1) > 0; 349 } 350 351 private void warnAppInstallation() { 352 // TODO: DialogFragment? 353 mWarnInstallApps = new AlertDialog.Builder(getActivity()).setTitle( 354 getResources().getString(R.string.error_title)) 355 .setIcon(com.android.internal.R.drawable.ic_dialog_alert) 356 .setMessage(getResources().getString(R.string.install_all_warning)) 357 .setPositiveButton(android.R.string.yes, this) 358 .setNegativeButton(android.R.string.no, null) 359 .show(); 360 } 361 362 @Override 363 public void onClick(DialogInterface dialog, int which) { 364 if (dialog == mWarnInstallApps && which == DialogInterface.BUTTON_POSITIVE) { 365 setNonMarketAppsAllowed(true); 366 if (mToggleAppInstallation != null) { 367 mToggleAppInstallation.setChecked(true); 368 } 369 } 370 } 371 372 @Override 373 public void onDestroy() { 374 super.onDestroy(); 375 if (mWarnInstallApps != null) { 376 mWarnInstallApps.dismiss(); 377 } 378 } 379 380 private void setupLockAfterPreference() { 381 // Compatible with pre-Froyo 382 long currentTimeout = Settings.Secure.getLong(getContentResolver(), 383 Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT, 5000); 384 mLockAfter.setValue(String.valueOf(currentTimeout)); 385 mLockAfter.setOnPreferenceChangeListener(this); 386 final long adminTimeout = (mDPM != null ? mDPM.getMaximumTimeToLock(null) : 0); 387 final long displayTimeout = Math.max(0, 388 Settings.System.getInt(getContentResolver(), SCREEN_OFF_TIMEOUT, 0)); 389 if (adminTimeout > 0) { 390 // This setting is a slave to display timeout when a device policy is enforced. 391 // As such, maxLockTimeout = adminTimeout - displayTimeout. 392 // If there isn't enough time, shows "immediately" setting. 393 disableUnusableTimeouts(Math.max(0, adminTimeout - displayTimeout)); 394 } 395 } 396 397 private void updateLockAfterPreferenceSummary() { 398 // Update summary message with current value 399 long currentTimeout = Settings.Secure.getLong(getContentResolver(), 400 Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT, 5000); 401 final CharSequence[] entries = mLockAfter.getEntries(); 402 final CharSequence[] values = mLockAfter.getEntryValues(); 403 int best = 0; 404 for (int i = 0; i < values.length; i++) { 405 long timeout = Long.valueOf(values[i].toString()); 406 if (currentTimeout >= timeout) { 407 best = i; 408 } 409 } 410 mLockAfter.setSummary(getString(R.string.lock_after_timeout_summary, entries[best])); 411 } 412 413 private void disableUnusableTimeouts(long maxTimeout) { 414 final CharSequence[] entries = mLockAfter.getEntries(); 415 final CharSequence[] values = mLockAfter.getEntryValues(); 416 ArrayList<CharSequence> revisedEntries = new ArrayList<CharSequence>(); 417 ArrayList<CharSequence> revisedValues = new ArrayList<CharSequence>(); 418 for (int i = 0; i < values.length; i++) { 419 long timeout = Long.valueOf(values[i].toString()); 420 if (timeout <= maxTimeout) { 421 revisedEntries.add(entries[i]); 422 revisedValues.add(values[i]); 423 } 424 } 425 if (revisedEntries.size() != entries.length || revisedValues.size() != values.length) { 426 mLockAfter.setEntries( 427 revisedEntries.toArray(new CharSequence[revisedEntries.size()])); 428 mLockAfter.setEntryValues( 429 revisedValues.toArray(new CharSequence[revisedValues.size()])); 430 final int userPreference = Integer.valueOf(mLockAfter.getValue()); 431 if (userPreference <= maxTimeout) { 432 mLockAfter.setValue(String.valueOf(userPreference)); 433 } else { 434 // There will be no highlighted selection since nothing in the list matches 435 // maxTimeout. The user can still select anything less than maxTimeout. 436 // TODO: maybe append maxTimeout to the list and mark selected. 437 } 438 } 439 mLockAfter.setEnabled(revisedEntries.size() > 0); 440 } 441 442 @Override 443 public void onResume() { 444 super.onResume(); 445 446 // Make sure we reload the preference hierarchy since some of these settings 447 // depend on others... 448 createPreferenceHierarchy(); 449 450 final LockPatternUtils lockPatternUtils = mChooseLockSettingsHelper.utils(); 451 if (mBiometricWeakLiveliness != null) { 452 mBiometricWeakLiveliness.setChecked( 453 lockPatternUtils.isBiometricWeakLivelinessEnabled()); 454 } 455 if (mVisiblePattern != null) { 456 mVisiblePattern.setChecked(lockPatternUtils.isVisiblePatternEnabled()); 457 } 458 if (mPowerButtonInstantlyLocks != null) { 459 mPowerButtonInstantlyLocks.setChecked(lockPatternUtils.getPowerButtonInstantlyLocks()); 460 } 461 462 if (mShowPassword != null) { 463 mShowPassword.setChecked(Settings.System.getInt(getContentResolver(), 464 Settings.System.TEXT_SHOW_PASSWORD, 1) != 0); 465 } 466 467 if (mResetCredentials != null) { 468 mResetCredentials.setEnabled(!mKeyStore.isEmpty()); 469 } 470 } 471 472 @Override 473 public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) { 474 final String key = preference.getKey(); 475 476 final LockPatternUtils lockPatternUtils = mChooseLockSettingsHelper.utils(); 477 if (KEY_UNLOCK_SET_OR_CHANGE.equals(key)) { 478 startFragment(this, "com.android.settings.ChooseLockGeneric$ChooseLockGenericFragment", 479 SET_OR_CHANGE_LOCK_METHOD_REQUEST, null); 480 } else if (KEY_BIOMETRIC_WEAK_IMPROVE_MATCHING.equals(key)) { 481 ChooseLockSettingsHelper helper = 482 new ChooseLockSettingsHelper(this.getActivity(), this); 483 if (!helper.launchConfirmationActivity( 484 CONFIRM_EXISTING_FOR_BIOMETRIC_WEAK_IMPROVE_REQUEST, null, null)) { 485 // If this returns false, it means no password confirmation is required, so 486 // go ahead and start improve. 487 // Note: currently a backup is required for biometric_weak so this code path 488 // can't be reached, but is here in case things change in the future 489 startBiometricWeakImprove(); 490 } 491 } else if (KEY_BIOMETRIC_WEAK_LIVELINESS.equals(key)) { 492 if (isToggled(preference)) { 493 lockPatternUtils.setBiometricWeakLivelinessEnabled(true); 494 } else { 495 // In this case the user has just unchecked the checkbox, but this action requires 496 // them to confirm their password. We need to re-check the checkbox until 497 // they've confirmed their password 498 mBiometricWeakLiveliness.setChecked(true); 499 ChooseLockSettingsHelper helper = 500 new ChooseLockSettingsHelper(this.getActivity(), this); 501 if (!helper.launchConfirmationActivity( 502 CONFIRM_EXISTING_FOR_BIOMETRIC_WEAK_LIVELINESS_OFF, null, null)) { 503 // If this returns false, it means no password confirmation is required, so 504 // go ahead and uncheck it here. 505 // Note: currently a backup is required for biometric_weak so this code path 506 // can't be reached, but is here in case things change in the future 507 lockPatternUtils.setBiometricWeakLivelinessEnabled(false); 508 mBiometricWeakLiveliness.setChecked(false); 509 } 510 } 511 } else if (KEY_LOCK_ENABLED.equals(key)) { 512 lockPatternUtils.setLockPatternEnabled(isToggled(preference)); 513 } else if (KEY_VISIBLE_PATTERN.equals(key)) { 514 lockPatternUtils.setVisiblePatternEnabled(isToggled(preference)); 515 } else if (KEY_POWER_INSTANTLY_LOCKS.equals(key)) { 516 lockPatternUtils.setPowerButtonInstantlyLocks(isToggled(preference)); 517 } else if (preference == mShowPassword) { 518 Settings.System.putInt(getContentResolver(), Settings.System.TEXT_SHOW_PASSWORD, 519 mShowPassword.isChecked() ? 1 : 0); 520 } else if (preference == mToggleAppInstallation) { 521 if (mToggleAppInstallation.isChecked()) { 522 mToggleAppInstallation.setChecked(false); 523 warnAppInstallation(); 524 } else { 525 setNonMarketAppsAllowed(false); 526 } 527 } else if (KEY_TOGGLE_VERIFY_APPLICATIONS.equals(key)) { 528 Settings.Global.putInt(getContentResolver(), Settings.Global.PACKAGE_VERIFIER_ENABLE, 529 mToggleVerifyApps.isChecked() ? 1 : 0); 530 } else { 531 // If we didn't handle it, let preferences handle it. 532 return super.onPreferenceTreeClick(preferenceScreen, preference); 533 } 534 535 return true; 536 } 537 538 private boolean isToggled(Preference pref) { 539 return ((CheckBoxPreference) pref).isChecked(); 540 } 541 542 /** 543 * see confirmPatternThenDisableAndClear 544 */ 545 @Override 546 public void onActivityResult(int requestCode, int resultCode, Intent data) { 547 super.onActivityResult(requestCode, resultCode, data); 548 if (requestCode == CONFIRM_EXISTING_FOR_BIOMETRIC_WEAK_IMPROVE_REQUEST && 549 resultCode == Activity.RESULT_OK) { 550 startBiometricWeakImprove(); 551 return; 552 } else if (requestCode == CONFIRM_EXISTING_FOR_BIOMETRIC_WEAK_LIVELINESS_OFF && 553 resultCode == Activity.RESULT_OK) { 554 final LockPatternUtils lockPatternUtils = mChooseLockSettingsHelper.utils(); 555 lockPatternUtils.setBiometricWeakLivelinessEnabled(false); 556 // Setting the mBiometricWeakLiveliness checked value to false is handled when onResume 557 // is called by grabbing the value from lockPatternUtils. We can't set it here 558 // because mBiometricWeakLiveliness could be null 559 return; 560 } 561 createPreferenceHierarchy(); 562 } 563 564 @Override 565 public boolean onPreferenceChange(Preference preference, Object value) { 566 if (preference == mLockAfter) { 567 int timeout = Integer.parseInt((String) value); 568 try { 569 Settings.Secure.putInt(getContentResolver(), 570 Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT, timeout); 571 } catch (NumberFormatException e) { 572 Log.e("SecuritySettings", "could not persist lockAfter timeout setting", e); 573 } 574 updateLockAfterPreferenceSummary(); 575 } 576 return true; 577 } 578 579 @Override 580 protected int getHelpResource() { 581 return R.string.help_url_security; 582 } 583 584 public void startBiometricWeakImprove(){ 585 Intent intent = new Intent(); 586 intent.setClassName("com.android.facelock", "com.android.facelock.AddToSetup"); 587 startActivity(intent); 588 } 589 } 590