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 17 package com.android.settings; 18 19 import static android.app.admin.DevicePolicyManager.ACTION_SET_NEW_PARENT_PROFILE_PASSWORD; 20 import static android.app.admin.DevicePolicyManager.ACTION_SET_NEW_PASSWORD; 21 import static com.android.settings.ChooseLockPassword.ChooseLockPasswordFragment.RESULT_FINISHED; 22 import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; 23 24 import android.accessibilityservice.AccessibilityServiceInfo; 25 import android.app.Activity; 26 import android.app.AlertDialog; 27 import android.app.Dialog; 28 import android.app.DialogFragment; 29 import android.app.Fragment; 30 import android.app.FragmentManager; 31 import android.app.admin.DevicePolicyManager; 32 import android.content.Context; 33 import android.content.DialogInterface; 34 import android.content.Intent; 35 import android.content.pm.UserInfo; 36 import android.hardware.fingerprint.Fingerprint; 37 import android.hardware.fingerprint.FingerprintManager; 38 import android.hardware.fingerprint.FingerprintManager.RemovalCallback; 39 import android.os.Bundle; 40 import android.os.UserHandle; 41 import android.os.UserManager; 42 import android.os.storage.StorageManager; 43 import android.security.KeyStore; 44 import android.support.v7.preference.Preference; 45 import android.support.v7.preference.PreferenceScreen; 46 import android.text.TextUtils; 47 import android.util.EventLog; 48 import android.util.Log; 49 import android.view.accessibility.AccessibilityManager; 50 import android.widget.TextView; 51 52 import com.android.internal.logging.MetricsProto.MetricsEvent; 53 import com.android.internal.widget.LockPatternUtils; 54 import com.android.settings.fingerprint.FingerprintEnrollBase; 55 import com.android.settings.fingerprint.FingerprintEnrollFindSensor; 56 import com.android.settingslib.RestrictedLockUtils; 57 import com.android.settingslib.RestrictedPreference; 58 59 import java.util.List; 60 61 public class ChooseLockGeneric extends SettingsActivity { 62 public static final String CONFIRM_CREDENTIALS = "confirm_credentials"; 63 64 @Override 65 public Intent getIntent() { 66 Intent modIntent = new Intent(super.getIntent()); 67 modIntent.putExtra(EXTRA_SHOW_FRAGMENT, getFragmentClass().getName()); 68 69 String action = modIntent.getAction(); 70 if (ACTION_SET_NEW_PASSWORD.equals(action) 71 || ACTION_SET_NEW_PARENT_PROFILE_PASSWORD.equals(action)) { 72 modIntent.putExtra(EXTRA_HIDE_DRAWER, true); 73 } 74 return modIntent; 75 } 76 77 @Override 78 protected boolean isValidFragment(String fragmentName) { 79 if (ChooseLockGenericFragment.class.getName().equals(fragmentName)) return true; 80 return false; 81 } 82 83 /* package */ Class<? extends Fragment> getFragmentClass() { 84 return ChooseLockGenericFragment.class; 85 } 86 87 public static class InternalActivity extends ChooseLockGeneric { 88 } 89 90 public static class ChooseLockGenericFragment extends SettingsPreferenceFragment { 91 private static final String TAG = "ChooseLockGenericFragment"; 92 private static final int MIN_PASSWORD_LENGTH = 4; 93 private static final String KEY_UNLOCK_SET_OFF = "unlock_set_off"; 94 private static final String KEY_UNLOCK_SET_NONE = "unlock_set_none"; 95 private static final String KEY_UNLOCK_SET_PIN = "unlock_set_pin"; 96 private static final String KEY_UNLOCK_SET_PASSWORD = "unlock_set_password"; 97 private static final String KEY_UNLOCK_SET_PATTERN = "unlock_set_pattern"; 98 private static final String KEY_UNLOCK_SET_MANAGED = "unlock_set_managed"; 99 private static final String KEY_SKIP_FINGERPRINT = "unlock_skip_fingerprint"; 100 private static final String PASSWORD_CONFIRMED = "password_confirmed"; 101 private static final String WAITING_FOR_CONFIRMATION = "waiting_for_confirmation"; 102 public static final String MINIMUM_QUALITY_KEY = "minimum_quality"; 103 public static final String HIDE_DISABLED_PREFS = "hide_disabled_prefs"; 104 public static final String ENCRYPT_REQUESTED_QUALITY = "encrypt_requested_quality"; 105 public static final String ENCRYPT_REQUESTED_DISABLED = "encrypt_requested_disabled"; 106 public static final String TAG_FRP_WARNING_DIALOG = "frp_warning_dialog"; 107 108 private static final int CONFIRM_EXISTING_REQUEST = 100; 109 private static final int ENABLE_ENCRYPTION_REQUEST = 101; 110 private static final int CHOOSE_LOCK_REQUEST = 102; 111 private static final int CHOOSE_LOCK_BEFORE_FINGERPRINT_REQUEST = 103; 112 private static final int SKIP_FINGERPRINT_REQUEST = 104; 113 114 private ChooseLockSettingsHelper mChooseLockSettingsHelper; 115 private DevicePolicyManager mDPM; 116 private KeyStore mKeyStore; 117 private boolean mHasChallenge = false; 118 private long mChallenge; 119 private boolean mPasswordConfirmed = false; 120 private boolean mWaitingForConfirmation = false; 121 private int mEncryptionRequestQuality; 122 private boolean mEncryptionRequestDisabled; 123 private boolean mRequirePassword; 124 private boolean mForChangeCredRequiredForBoot = false; 125 private String mUserPassword; 126 private LockPatternUtils mLockPatternUtils; 127 private FingerprintManager mFingerprintManager; 128 private int mUserId; 129 private boolean mHideDrawer = false; 130 private ManagedLockPasswordProvider mManagedPasswordProvider; 131 private boolean mIsSetNewPassword = false; 132 133 protected boolean mForFingerprint = false; 134 135 @Override 136 protected int getMetricsCategory() { 137 return MetricsEvent.CHOOSE_LOCK_GENERIC; 138 } 139 140 @Override 141 public void onCreate(Bundle savedInstanceState) { 142 super.onCreate(savedInstanceState); 143 144 String chooseLockAction = getActivity().getIntent().getAction(); 145 mFingerprintManager = 146 (FingerprintManager) getActivity().getSystemService(Context.FINGERPRINT_SERVICE); 147 mDPM = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE); 148 mKeyStore = KeyStore.getInstance(); 149 mChooseLockSettingsHelper = new ChooseLockSettingsHelper(this.getActivity()); 150 mLockPatternUtils = new LockPatternUtils(getActivity()); 151 mIsSetNewPassword = ACTION_SET_NEW_PARENT_PROFILE_PASSWORD.equals(chooseLockAction) 152 || ACTION_SET_NEW_PASSWORD.equals(chooseLockAction); 153 154 // Defaults to needing to confirm credentials 155 final boolean confirmCredentials = getActivity().getIntent() 156 .getBooleanExtra(CONFIRM_CREDENTIALS, true); 157 if (getActivity() instanceof ChooseLockGeneric.InternalActivity) { 158 mPasswordConfirmed = !confirmCredentials; 159 } 160 mHideDrawer = getActivity().getIntent().getBooleanExtra(EXTRA_HIDE_DRAWER, false); 161 162 mHasChallenge = getActivity().getIntent().getBooleanExtra( 163 ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, false); 164 mChallenge = getActivity().getIntent().getLongExtra( 165 ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, 0); 166 mForFingerprint = getActivity().getIntent().getBooleanExtra( 167 ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, false); 168 mForChangeCredRequiredForBoot = getArguments() != null && getArguments().getBoolean( 169 ChooseLockSettingsHelper.EXTRA_KEY_FOR_CHANGE_CRED_REQUIRED_FOR_BOOT); 170 if (mIsSetNewPassword) { 171 // In ACTION_SET_NEW_PARENT_PROFILE_PASSWORD or ACTION_SET_NEW_PASSWORD, the user 172 // will be asked to confirm the password if one has been set. 173 // On fingerprint supported device, fingerprint options are represented in the 174 // options. If the user chooses to skip fingerprint setup, ChooseLockGeneric is 175 // relaunched to only show options without fingerprint. In this case, we shouldn't 176 // ask the user to confirm the password again. 177 mPasswordConfirmed = getActivity().getIntent().getBooleanExtra( 178 PASSWORD_CONFIRMED, false); 179 } 180 181 if (savedInstanceState != null) { 182 mPasswordConfirmed = savedInstanceState.getBoolean(PASSWORD_CONFIRMED); 183 mWaitingForConfirmation = savedInstanceState.getBoolean(WAITING_FOR_CONFIRMATION); 184 mEncryptionRequestQuality = savedInstanceState.getInt(ENCRYPT_REQUESTED_QUALITY); 185 mEncryptionRequestDisabled = savedInstanceState.getBoolean( 186 ENCRYPT_REQUESTED_DISABLED); 187 } 188 189 int targetUser = Utils.getSecureTargetUser( 190 getActivity().getActivityToken(), 191 UserManager.get(getActivity()), 192 null, 193 getActivity().getIntent().getExtras()).getIdentifier(); 194 if (ACTION_SET_NEW_PARENT_PROFILE_PASSWORD.equals(chooseLockAction) 195 || !mLockPatternUtils.isSeparateProfileChallengeAllowed(targetUser)) { 196 // Always use parent if explicitely requested or if profile challenge is not 197 // supported 198 Bundle arguments = getArguments(); 199 mUserId = Utils.getUserIdFromBundle(getContext(), arguments != null ? arguments 200 : getActivity().getIntent().getExtras()); 201 } else { 202 mUserId = targetUser; 203 } 204 205 if (ACTION_SET_NEW_PASSWORD.equals(chooseLockAction) 206 && Utils.isManagedProfile(UserManager.get(getActivity()), mUserId) 207 && mLockPatternUtils.isSeparateProfileChallengeEnabled(mUserId)) { 208 getActivity().setTitle(R.string.lock_settings_picker_title_profile); 209 } 210 211 mManagedPasswordProvider = ManagedLockPasswordProvider.get(getActivity(), mUserId); 212 213 if (mPasswordConfirmed) { 214 updatePreferencesOrFinish(); 215 if (mForChangeCredRequiredForBoot) { 216 maybeEnableEncryption(mLockPatternUtils.getKeyguardStoredPasswordQuality( 217 mUserId), false); 218 } 219 } else if (!mWaitingForConfirmation) { 220 ChooseLockSettingsHelper helper = 221 new ChooseLockSettingsHelper(this.getActivity(), this); 222 boolean managedProfileWithUnifiedLock = Utils 223 .isManagedProfile(UserManager.get(getActivity()), mUserId) 224 && !mLockPatternUtils.isSeparateProfileChallengeEnabled(mUserId); 225 if (managedProfileWithUnifiedLock 226 || !helper.launchConfirmationActivity(CONFIRM_EXISTING_REQUEST, 227 getString(R.string.unlock_set_unlock_launch_picker_title), true, mUserId)) { 228 mPasswordConfirmed = true; // no password set, so no need to confirm 229 updatePreferencesOrFinish(); 230 } else { 231 mWaitingForConfirmation = true; 232 } 233 } 234 addHeaderView(); 235 } 236 237 protected void addHeaderView() { 238 if (mForFingerprint) { 239 setHeaderView(R.layout.choose_lock_generic_fingerprint_header); 240 if (mIsSetNewPassword) { 241 ((TextView) getHeaderView().findViewById(R.id.fingerprint_header_description)) 242 .setText(R.string.fingerprint_unlock_title); 243 } 244 } 245 } 246 247 @Override 248 public boolean onPreferenceTreeClick(Preference preference) { 249 final String key = preference.getKey(); 250 251 if (!isUnlockMethodSecure(key) && mLockPatternUtils.isSecure(mUserId)) { 252 // Show the disabling FRP warning only when the user is switching from a secure 253 // unlock method to an insecure one 254 showFactoryResetProtectionWarningDialog(key); 255 return true; 256 } else if (KEY_SKIP_FINGERPRINT.equals(key)) { 257 Intent chooseLockGenericIntent = new Intent(getActivity(), ChooseLockGeneric.class); 258 chooseLockGenericIntent.setAction(getIntent().getAction()); 259 chooseLockGenericIntent.putExtra(PASSWORD_CONFIRMED, mPasswordConfirmed); 260 startActivityForResult(chooseLockGenericIntent, SKIP_FINGERPRINT_REQUEST); 261 return true; 262 } else { 263 return setUnlockMethod(key); 264 } 265 } 266 267 /** 268 * If the device has encryption already enabled, then ask the user if they 269 * also want to encrypt the phone with this password. 270 * 271 * @param quality 272 * @param disabled 273 */ 274 // TODO: why does this take disabled, its always called with a quality higher than 275 // what makes sense with disabled == true 276 private void maybeEnableEncryption(int quality, boolean disabled) { 277 DevicePolicyManager dpm = (DevicePolicyManager) getSystemService(DEVICE_POLICY_SERVICE); 278 if (UserManager.get(getActivity()).isAdminUser() 279 && mUserId == UserHandle.myUserId() 280 && LockPatternUtils.isDeviceEncryptionEnabled() 281 && !LockPatternUtils.isFileEncryptionEnabled() 282 && !dpm.getDoNotAskCredentialsOnBoot()) { 283 mEncryptionRequestQuality = quality; 284 mEncryptionRequestDisabled = disabled; 285 // Get the intent that the encryption interstitial should start for creating 286 // the new unlock method. 287 Intent unlockMethodIntent = getIntentForUnlockMethod(quality, disabled); 288 unlockMethodIntent.putExtra( 289 ChooseLockSettingsHelper.EXTRA_KEY_FOR_CHANGE_CRED_REQUIRED_FOR_BOOT, 290 mForChangeCredRequiredForBoot); 291 final Context context = getActivity(); 292 // If accessibility is enabled and the user hasn't seen this dialog before, set the 293 // default state to agree with that which is compatible with accessibility 294 // (password not required). 295 final boolean accEn = AccessibilityManager.getInstance(context).isEnabled(); 296 final boolean required = mLockPatternUtils.isCredentialRequiredToDecrypt(!accEn); 297 Intent intent = getEncryptionInterstitialIntent(context, quality, required, 298 unlockMethodIntent); 299 intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, 300 mForFingerprint); 301 intent.putExtra(EXTRA_HIDE_DRAWER, mHideDrawer); 302 startActivityForResult( 303 intent, 304 mIsSetNewPassword && mHasChallenge 305 ? CHOOSE_LOCK_BEFORE_FINGERPRINT_REQUEST 306 : ENABLE_ENCRYPTION_REQUEST); 307 } else { 308 if (mForChangeCredRequiredForBoot) { 309 // Welp, couldn't change it. Oh well. 310 finish(); 311 return; 312 } 313 mRequirePassword = false; // device encryption not enabled or not device owner. 314 updateUnlockMethodAndFinish(quality, disabled); 315 } 316 } 317 318 @Override 319 public void onActivityResult(int requestCode, int resultCode, Intent data) { 320 super.onActivityResult(requestCode, resultCode, data); 321 mWaitingForConfirmation = false; 322 if (requestCode == CONFIRM_EXISTING_REQUEST && resultCode == Activity.RESULT_OK) { 323 mPasswordConfirmed = true; 324 mUserPassword = data.getStringExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD); 325 updatePreferencesOrFinish(); 326 if (mForChangeCredRequiredForBoot) { 327 if (!TextUtils.isEmpty(mUserPassword)) { 328 maybeEnableEncryption( 329 mLockPatternUtils.getKeyguardStoredPasswordQuality(mUserId), false); 330 } else { 331 finish(); 332 } 333 } 334 } else if (requestCode == CHOOSE_LOCK_REQUEST 335 || requestCode == ENABLE_ENCRYPTION_REQUEST) { 336 if (resultCode != RESULT_CANCELED || mForChangeCredRequiredForBoot) { 337 getActivity().setResult(resultCode, data); 338 finish(); 339 } 340 } else if (requestCode == CHOOSE_LOCK_BEFORE_FINGERPRINT_REQUEST 341 && resultCode == FingerprintEnrollBase.RESULT_FINISHED) { 342 Intent intent = new Intent(getActivity(), FingerprintEnrollFindSensor.class); 343 if (data != null) { 344 intent.putExtras(data.getExtras()); 345 } 346 startActivity(intent); 347 finish(); 348 } else if (requestCode == SKIP_FINGERPRINT_REQUEST) { 349 if (resultCode != RESULT_CANCELED) { 350 getActivity().setResult( 351 resultCode == RESULT_FINISHED ? RESULT_OK : resultCode, data); 352 finish(); 353 } 354 } else { 355 getActivity().setResult(Activity.RESULT_CANCELED); 356 finish(); 357 } 358 if (requestCode == Activity.RESULT_CANCELED && mForChangeCredRequiredForBoot) { 359 finish(); 360 } 361 } 362 363 @Override 364 public void onSaveInstanceState(Bundle outState) { 365 super.onSaveInstanceState(outState); 366 // Saved so we don't force user to re-enter their password if configuration changes 367 outState.putBoolean(PASSWORD_CONFIRMED, mPasswordConfirmed); 368 outState.putBoolean(WAITING_FOR_CONFIRMATION, mWaitingForConfirmation); 369 outState.putInt(ENCRYPT_REQUESTED_QUALITY, mEncryptionRequestQuality); 370 outState.putBoolean(ENCRYPT_REQUESTED_DISABLED, mEncryptionRequestDisabled); 371 } 372 373 private void updatePreferencesOrFinish() { 374 Intent intent = getActivity().getIntent(); 375 int quality = intent.getIntExtra(LockPatternUtils.PASSWORD_TYPE_KEY, -1); 376 if (quality == -1) { 377 // If caller didn't specify password quality, show UI and allow the user to choose. 378 quality = intent.getIntExtra(MINIMUM_QUALITY_KEY, -1); 379 quality = upgradeQuality(quality); 380 final boolean hideDisabledPrefs = intent.getBooleanExtra( 381 HIDE_DISABLED_PREFS, false); 382 final PreferenceScreen prefScreen = getPreferenceScreen(); 383 if (prefScreen != null) { 384 prefScreen.removeAll(); 385 } 386 addPreferences(); 387 disableUnusablePreferences(quality, hideDisabledPrefs); 388 updatePreferenceText(); 389 updateCurrentPreference(); 390 updatePreferenceSummaryIfNeeded(); 391 } else { 392 updateUnlockMethodAndFinish(quality, false); 393 } 394 } 395 396 protected void addPreferences() { 397 addPreferencesFromResource(R.xml.security_settings_picker); 398 399 // Used for testing purposes 400 findPreference(KEY_UNLOCK_SET_NONE).setViewId(R.id.lock_none); 401 findPreference(KEY_SKIP_FINGERPRINT).setViewId(R.id.lock_none); 402 findPreference(KEY_UNLOCK_SET_PIN).setViewId(R.id.lock_pin); 403 findPreference(KEY_UNLOCK_SET_PASSWORD).setViewId(R.id.lock_password); 404 } 405 406 private void updatePreferenceText() { 407 if (mForFingerprint) { 408 final String key[] = { KEY_UNLOCK_SET_PATTERN, 409 KEY_UNLOCK_SET_PIN, 410 KEY_UNLOCK_SET_PASSWORD }; 411 final int res[] = { R.string.fingerprint_unlock_set_unlock_pattern, 412 R.string.fingerprint_unlock_set_unlock_pin, 413 R.string.fingerprint_unlock_set_unlock_password }; 414 for (int i = 0; i < key.length; i++) { 415 Preference pref = findPreference(key[i]); 416 if (pref != null) { // can be removed by device admin 417 pref.setTitle(res[i]); 418 } 419 } 420 } 421 422 if (mManagedPasswordProvider.isSettingManagedPasswordSupported()) { 423 Preference managed = findPreference(KEY_UNLOCK_SET_MANAGED); 424 managed.setTitle(mManagedPasswordProvider.getPickerOptionTitle(mForFingerprint)); 425 } else { 426 removePreference(KEY_UNLOCK_SET_MANAGED); 427 } 428 429 if (!(mForFingerprint && mIsSetNewPassword)) { 430 removePreference(KEY_SKIP_FINGERPRINT); 431 } 432 } 433 434 private void updateCurrentPreference() { 435 String currentKey = getKeyForCurrent(); 436 Preference preference = findPreference(currentKey); 437 if (preference != null) { 438 preference.setSummary(R.string.current_screen_lock); 439 } 440 } 441 442 private String getKeyForCurrent() { 443 final int credentialOwner = UserManager.get(getContext()) 444 .getCredentialOwnerProfile(mUserId); 445 if (mLockPatternUtils.isLockScreenDisabled(credentialOwner)) { 446 return KEY_UNLOCK_SET_OFF; 447 } 448 switch (mLockPatternUtils.getKeyguardStoredPasswordQuality(credentialOwner)) { 449 case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING: 450 return KEY_UNLOCK_SET_PATTERN; 451 case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC: 452 case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX: 453 return KEY_UNLOCK_SET_PIN; 454 case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC: 455 case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC: 456 case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX: 457 return KEY_UNLOCK_SET_PASSWORD; 458 case DevicePolicyManager.PASSWORD_QUALITY_MANAGED: 459 return KEY_UNLOCK_SET_MANAGED; 460 case DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED: 461 return KEY_UNLOCK_SET_NONE; 462 } 463 return null; 464 } 465 466 /** increases the quality if necessary */ 467 private int upgradeQuality(int quality) { 468 quality = upgradeQualityForDPM(quality); 469 return quality; 470 } 471 472 private int upgradeQualityForDPM(int quality) { 473 // Compare min allowed password quality 474 int minQuality = mDPM.getPasswordQuality(null, mUserId); 475 if (quality < minQuality) { 476 quality = minQuality; 477 } 478 return quality; 479 } 480 481 /*** 482 * Disables preferences that are less secure than required quality. The actual 483 * implementation is in disableUnusablePreferenceImpl. 484 * 485 * @param quality the requested quality. 486 * @param hideDisabledPrefs if false preferences show why they were disabled; otherwise 487 * they're not shown at all. 488 */ 489 protected void disableUnusablePreferences(final int quality, boolean hideDisabledPrefs) { 490 disableUnusablePreferencesImpl(quality, hideDisabledPrefs); 491 } 492 493 /*** 494 * Disables preferences that are less secure than required quality. 495 * 496 * @param quality the requested quality. 497 * @param hideDisabled whether to hide disable screen lock options. 498 */ 499 protected void disableUnusablePreferencesImpl(final int quality, 500 boolean hideDisabled) { 501 final PreferenceScreen entries = getPreferenceScreen(); 502 503 int adminEnforcedQuality = mDPM.getPasswordQuality(null, mUserId); 504 EnforcedAdmin enforcedAdmin = RestrictedLockUtils.checkIfPasswordQualityIsSet( 505 getActivity(), mUserId); 506 for (int i = entries.getPreferenceCount() - 1; i >= 0; --i) { 507 Preference pref = entries.getPreference(i); 508 if (pref instanceof RestrictedPreference) { 509 final String key = pref.getKey(); 510 boolean enabled = true; 511 boolean visible = true; 512 boolean disabledByAdmin = false; 513 if (KEY_UNLOCK_SET_OFF.equals(key)) { 514 enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED; 515 if (getResources().getBoolean(R.bool.config_hide_none_security_option)) { 516 enabled = false; 517 visible = false; 518 } 519 disabledByAdmin = adminEnforcedQuality 520 > DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED; 521 } else if (KEY_UNLOCK_SET_NONE.equals(key)) { 522 if (mUserId != UserHandle.myUserId()) { 523 // Swipe doesn't make sense for profiles. 524 visible = false; 525 } 526 enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED; 527 disabledByAdmin = adminEnforcedQuality 528 > DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED; 529 } else if (KEY_UNLOCK_SET_PATTERN.equals(key)) { 530 enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_SOMETHING; 531 disabledByAdmin = adminEnforcedQuality 532 > DevicePolicyManager.PASSWORD_QUALITY_SOMETHING; 533 } else if (KEY_UNLOCK_SET_PIN.equals(key)) { 534 enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX; 535 disabledByAdmin = adminEnforcedQuality 536 > DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX; 537 } else if (KEY_UNLOCK_SET_PASSWORD.equals(key)) { 538 enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_COMPLEX; 539 disabledByAdmin = adminEnforcedQuality 540 > DevicePolicyManager.PASSWORD_QUALITY_COMPLEX; 541 } else if (KEY_UNLOCK_SET_MANAGED.equals(key)) { 542 enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_MANAGED 543 && mManagedPasswordProvider.isManagedPasswordChoosable(); 544 disabledByAdmin = adminEnforcedQuality 545 > DevicePolicyManager.PASSWORD_QUALITY_MANAGED; 546 } 547 if (hideDisabled) { 548 visible = enabled; 549 } 550 if (!visible) { 551 entries.removePreference(pref); 552 } else if (disabledByAdmin && enforcedAdmin != null) { 553 ((RestrictedPreference) pref).setDisabledByAdmin(enforcedAdmin); 554 } else if (!enabled) { 555 // we need to setDisabledByAdmin to null first to disable the padlock 556 // in case it was set earlier. 557 ((RestrictedPreference) pref).setDisabledByAdmin(null); 558 pref.setSummary(R.string.unlock_set_unlock_disabled_summary); 559 pref.setEnabled(false); 560 } else { 561 ((RestrictedPreference) pref).setDisabledByAdmin(null); 562 } 563 } 564 } 565 } 566 567 private void updatePreferenceSummaryIfNeeded() { 568 // On a default block encrypted device with accessibility, add a warning 569 // that your data is not credential encrypted 570 if (!StorageManager.isBlockEncrypted()) { 571 return; 572 } 573 574 if (StorageManager.isNonDefaultBlockEncrypted()) { 575 return; 576 } 577 578 if (AccessibilityManager.getInstance(getActivity()).getEnabledAccessibilityServiceList( 579 AccessibilityServiceInfo.FEEDBACK_ALL_MASK).isEmpty()) { 580 return; 581 } 582 583 CharSequence summary = getString(R.string.secure_lock_encryption_warning); 584 585 PreferenceScreen screen = getPreferenceScreen(); 586 final int preferenceCount = screen.getPreferenceCount(); 587 for (int i = 0; i < preferenceCount; i++) { 588 Preference preference = screen.getPreference(i); 589 switch (preference.getKey()) { 590 case KEY_UNLOCK_SET_PATTERN: 591 case KEY_UNLOCK_SET_PIN: 592 case KEY_UNLOCK_SET_PASSWORD: 593 case KEY_UNLOCK_SET_MANAGED: { 594 preference.setSummary(summary); 595 } break; 596 } 597 } 598 } 599 600 protected Intent getLockManagedPasswordIntent(boolean requirePassword, String password) { 601 return mManagedPasswordProvider.createIntent(requirePassword, password); 602 } 603 604 protected Intent getLockPasswordIntent(Context context, int quality, 605 int minLength, final int maxLength, 606 boolean requirePasswordToDecrypt, boolean confirmCredentials, int userId) { 607 return ChooseLockPassword.createIntent(context, quality, minLength, 608 maxLength, requirePasswordToDecrypt, confirmCredentials, userId); 609 } 610 611 protected Intent getLockPasswordIntent(Context context, int quality, 612 int minLength, final int maxLength, 613 boolean requirePasswordToDecrypt, long challenge, int userId) { 614 return ChooseLockPassword.createIntent(context, quality, minLength, 615 maxLength, requirePasswordToDecrypt, challenge, userId); 616 } 617 618 protected Intent getLockPasswordIntent(Context context, int quality, int minLength, 619 int maxLength, boolean requirePasswordToDecrypt, String password, int userId) { 620 return ChooseLockPassword.createIntent(context, quality, minLength, maxLength, 621 requirePasswordToDecrypt, password, userId); 622 } 623 624 protected Intent getLockPatternIntent(Context context, final boolean requirePassword, 625 final boolean confirmCredentials, int userId) { 626 return ChooseLockPattern.createIntent(context, requirePassword, 627 confirmCredentials, userId); 628 } 629 630 protected Intent getLockPatternIntent(Context context, final boolean requirePassword, 631 long challenge, int userId) { 632 return ChooseLockPattern.createIntent(context, requirePassword, challenge, userId); 633 } 634 635 protected Intent getLockPatternIntent(Context context, final boolean requirePassword, 636 final String pattern, int userId) { 637 return ChooseLockPattern.createIntent(context, requirePassword, pattern, userId); 638 } 639 640 protected Intent getEncryptionInterstitialIntent(Context context, int quality, 641 boolean required, Intent unlockMethodIntent) { 642 return EncryptionInterstitial.createStartIntent(context, quality, required, 643 unlockMethodIntent); 644 } 645 646 /** 647 * Invokes an activity to change the user's pattern, password or PIN based on given quality 648 * and minimum quality specified by DevicePolicyManager. If quality is 649 * {@link DevicePolicyManager#PASSWORD_QUALITY_UNSPECIFIED}, password is cleared. 650 * 651 * @param quality the desired quality. Ignored if DevicePolicyManager requires more security 652 * @param disabled whether or not to show LockScreen at all. Only meaningful when quality is 653 * {@link DevicePolicyManager#PASSWORD_QUALITY_UNSPECIFIED} 654 */ 655 void updateUnlockMethodAndFinish(int quality, boolean disabled) { 656 // Sanity check. We should never get here without confirming user's existing password. 657 if (!mPasswordConfirmed) { 658 throw new IllegalStateException("Tried to update password without confirming it"); 659 } 660 661 quality = upgradeQuality(quality); 662 Intent intent = getIntentForUnlockMethod(quality, disabled); 663 if (intent != null) { 664 startActivityForResult(intent, 665 mIsSetNewPassword && mHasChallenge 666 ? CHOOSE_LOCK_BEFORE_FINGERPRINT_REQUEST 667 : CHOOSE_LOCK_REQUEST); 668 return; 669 } 670 671 if (quality == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) { 672 mLockPatternUtils.setSeparateProfileChallengeEnabled(mUserId, true, mUserPassword); 673 mChooseLockSettingsHelper.utils().clearLock(mUserId); 674 mChooseLockSettingsHelper.utils().setLockScreenDisabled(disabled, mUserId); 675 getActivity().setResult(Activity.RESULT_OK); 676 removeAllFingerprintForUserAndFinish(mUserId); 677 } else { 678 removeAllFingerprintForUserAndFinish(mUserId); 679 } 680 } 681 682 private Intent getIntentForUnlockMethod(int quality, boolean disabled) { 683 Intent intent = null; 684 final Context context = getActivity(); 685 if (quality >= DevicePolicyManager.PASSWORD_QUALITY_MANAGED) { 686 intent = getLockManagedPasswordIntent(mRequirePassword, mUserPassword); 687 } else if (quality >= DevicePolicyManager.PASSWORD_QUALITY_NUMERIC) { 688 int minLength = mDPM.getPasswordMinimumLength(null, mUserId); 689 if (minLength < MIN_PASSWORD_LENGTH) { 690 minLength = MIN_PASSWORD_LENGTH; 691 } 692 final int maxLength = mDPM.getPasswordMaximumLength(quality); 693 if (mHasChallenge) { 694 intent = getLockPasswordIntent(context, quality, minLength, 695 maxLength, mRequirePassword, mChallenge, mUserId); 696 } else { 697 intent = getLockPasswordIntent(context, quality, minLength, 698 maxLength, mRequirePassword, mUserPassword, mUserId); 699 } 700 } else if (quality == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING) { 701 if (mHasChallenge) { 702 intent = getLockPatternIntent(context, mRequirePassword, 703 mChallenge, mUserId); 704 } else { 705 intent = getLockPatternIntent(context, mRequirePassword, 706 mUserPassword, mUserId); 707 } 708 } 709 if (intent != null) { 710 intent.putExtra(EXTRA_HIDE_DRAWER, mHideDrawer); 711 } 712 return intent; 713 } 714 715 private void removeAllFingerprintForUserAndFinish(final int userId) { 716 if (mFingerprintManager != null && mFingerprintManager.isHardwareDetected()) { 717 if (mFingerprintManager.hasEnrolledFingerprints(userId)) { 718 mFingerprintManager.setActiveUser(userId); 719 // For the purposes of M and N, groupId is the same as userId. 720 final int groupId = userId; 721 Fingerprint finger = new Fingerprint(null, groupId, 0, 0); 722 mFingerprintManager.remove(finger, userId, 723 new RemovalCallback() { 724 @Override 725 public void onRemovalError(Fingerprint fp, int errMsgId, 726 CharSequence errString) { 727 Log.v(TAG, "Fingerprint removed: " + fp.getFingerId()); 728 if (fp.getFingerId() == 0) { 729 removeManagedProfileFingerprintsAndFinishIfNecessary(userId); 730 } 731 } 732 733 @Override 734 public void onRemovalSucceeded(Fingerprint fingerprint) { 735 if (fingerprint.getFingerId() == 0) { 736 removeManagedProfileFingerprintsAndFinishIfNecessary(userId); 737 } 738 } 739 }); 740 } else { 741 // No fingerprints in this user, we may also want to delete managed profile 742 // fingerprints 743 removeManagedProfileFingerprintsAndFinishIfNecessary(userId); 744 } 745 } else { 746 // The removal callback will call finish, once all fingerprints are removed. 747 // We need to wait for that to occur, otherwise, the UI will still show that 748 // fingerprints exist even though they are (about to) be removed depending on 749 // the race condition. 750 finish(); 751 } 752 } 753 754 private void removeManagedProfileFingerprintsAndFinishIfNecessary(final int parentUserId) { 755 mFingerprintManager.setActiveUser(UserHandle.myUserId()); 756 final UserManager um = UserManager.get(getActivity()); 757 boolean hasChildProfile = false; 758 if (!um.getUserInfo(parentUserId).isManagedProfile()) { 759 // Current user is primary profile, remove work profile fingerprints if necessary 760 final List<UserInfo> profiles = um.getProfiles(parentUserId); 761 final int profilesSize = profiles.size(); 762 for (int i = 0; i < profilesSize; i++) { 763 final UserInfo userInfo = profiles.get(i); 764 if (userInfo.isManagedProfile() && !mLockPatternUtils 765 .isSeparateProfileChallengeEnabled(userInfo.id)) { 766 removeAllFingerprintForUserAndFinish(userInfo.id); 767 hasChildProfile = true; 768 break; 769 } 770 } 771 } 772 if (!hasChildProfile) { 773 finish(); 774 } 775 } 776 777 @Override 778 public void onDestroy() { 779 super.onDestroy(); 780 } 781 782 @Override 783 protected int getHelpResource() { 784 return R.string.help_url_choose_lockscreen; 785 } 786 787 private int getResIdForFactoryResetProtectionWarningTitle() { 788 boolean isProfile = Utils.isManagedProfile(UserManager.get(getActivity()), mUserId); 789 return isProfile ? R.string.unlock_disable_frp_warning_title_profile 790 : R.string.unlock_disable_frp_warning_title; 791 } 792 793 private int getResIdForFactoryResetProtectionWarningMessage() { 794 boolean hasFingerprints = mFingerprintManager.hasEnrolledFingerprints(mUserId); 795 boolean isProfile = Utils.isManagedProfile(UserManager.get(getActivity()), mUserId); 796 switch (mLockPatternUtils.getKeyguardStoredPasswordQuality(mUserId)) { 797 case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING: 798 if (hasFingerprints && isProfile) { 799 return R.string 800 .unlock_disable_frp_warning_content_pattern_fingerprint_profile; 801 } else if (hasFingerprints && !isProfile) { 802 return R.string.unlock_disable_frp_warning_content_pattern_fingerprint; 803 } else if (isProfile) { 804 return R.string.unlock_disable_frp_warning_content_pattern_profile; 805 } else { 806 return R.string.unlock_disable_frp_warning_content_pattern; 807 } 808 case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC: 809 case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX: 810 if (hasFingerprints && isProfile) { 811 return R.string.unlock_disable_frp_warning_content_pin_fingerprint_profile; 812 } else if (hasFingerprints && !isProfile) { 813 return R.string.unlock_disable_frp_warning_content_pin_fingerprint; 814 } else if (isProfile) { 815 return R.string.unlock_disable_frp_warning_content_pin_profile; 816 } else { 817 return R.string.unlock_disable_frp_warning_content_pin; 818 } 819 case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC: 820 case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC: 821 case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX: 822 case DevicePolicyManager.PASSWORD_QUALITY_MANAGED: 823 if (hasFingerprints && isProfile) { 824 return R.string 825 .unlock_disable_frp_warning_content_password_fingerprint_profile; 826 } else if (hasFingerprints && !isProfile) { 827 return R.string.unlock_disable_frp_warning_content_password_fingerprint; 828 } else if (isProfile) { 829 return R.string.unlock_disable_frp_warning_content_password_profile; 830 } else { 831 return R.string.unlock_disable_frp_warning_content_password; 832 } 833 default: 834 if (hasFingerprints && isProfile) { 835 return R.string 836 .unlock_disable_frp_warning_content_unknown_fingerprint_profile; 837 } else if (hasFingerprints && !isProfile) { 838 return R.string.unlock_disable_frp_warning_content_unknown_fingerprint; 839 } else if (isProfile) { 840 return R.string.unlock_disable_frp_warning_content_unknown_profile; 841 } else { 842 return R.string.unlock_disable_frp_warning_content_unknown; 843 } 844 } 845 } 846 847 private boolean isUnlockMethodSecure(String unlockMethod) { 848 return !(KEY_UNLOCK_SET_OFF.equals(unlockMethod) || 849 KEY_UNLOCK_SET_NONE.equals(unlockMethod)); 850 } 851 852 private boolean setUnlockMethod(String unlockMethod) { 853 EventLog.writeEvent(EventLogTags.LOCK_SCREEN_TYPE, unlockMethod); 854 855 if (KEY_UNLOCK_SET_OFF.equals(unlockMethod)) { 856 updateUnlockMethodAndFinish( 857 DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, true /* disabled */ ); 858 } else if (KEY_UNLOCK_SET_NONE.equals(unlockMethod)) { 859 updateUnlockMethodAndFinish( 860 DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, false /* disabled */ ); 861 } else if (KEY_UNLOCK_SET_MANAGED.equals(unlockMethod)) { 862 maybeEnableEncryption(DevicePolicyManager.PASSWORD_QUALITY_MANAGED, false); 863 } else if (KEY_UNLOCK_SET_PATTERN.equals(unlockMethod)) { 864 maybeEnableEncryption( 865 DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, false); 866 } else if (KEY_UNLOCK_SET_PIN.equals(unlockMethod)) { 867 maybeEnableEncryption( 868 DevicePolicyManager.PASSWORD_QUALITY_NUMERIC, false); 869 } else if (KEY_UNLOCK_SET_PASSWORD.equals(unlockMethod)) { 870 maybeEnableEncryption( 871 DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC, false); 872 } else { 873 Log.e(TAG, "Encountered unknown unlock method to set: " + unlockMethod); 874 return false; 875 } 876 return true; 877 } 878 879 private void showFactoryResetProtectionWarningDialog(String unlockMethodToSet) { 880 int title = getResIdForFactoryResetProtectionWarningTitle(); 881 int message = getResIdForFactoryResetProtectionWarningMessage(); 882 FactoryResetProtectionWarningDialog dialog = 883 FactoryResetProtectionWarningDialog.newInstance( 884 title, message, unlockMethodToSet); 885 dialog.show(getChildFragmentManager(), TAG_FRP_WARNING_DIALOG); 886 } 887 888 public static class FactoryResetProtectionWarningDialog extends DialogFragment { 889 890 private static final String ARG_TITLE_RES = "titleRes"; 891 private static final String ARG_MESSAGE_RES = "messageRes"; 892 private static final String ARG_UNLOCK_METHOD_TO_SET = "unlockMethodToSet"; 893 894 public static FactoryResetProtectionWarningDialog newInstance( 895 int titleRes, int messageRes, String unlockMethodToSet) { 896 FactoryResetProtectionWarningDialog frag = 897 new FactoryResetProtectionWarningDialog(); 898 Bundle args = new Bundle(); 899 args.putInt(ARG_TITLE_RES, titleRes); 900 args.putInt(ARG_MESSAGE_RES, messageRes); 901 args.putString(ARG_UNLOCK_METHOD_TO_SET, unlockMethodToSet); 902 frag.setArguments(args); 903 return frag; 904 } 905 906 @Override 907 public void show(FragmentManager manager, String tag) { 908 if (manager.findFragmentByTag(tag) == null) { 909 // Prevent opening multiple dialogs if tapped on button quickly 910 super.show(manager, tag); 911 } 912 } 913 914 @Override 915 public Dialog onCreateDialog(Bundle savedInstanceState) { 916 final Bundle args = getArguments(); 917 918 return new AlertDialog.Builder(getActivity()) 919 .setTitle(args.getInt(ARG_TITLE_RES)) 920 .setMessage(args.getInt(ARG_MESSAGE_RES)) 921 .setPositiveButton(R.string.unlock_disable_frp_warning_ok, 922 new DialogInterface.OnClickListener() { 923 @Override 924 public void onClick(DialogInterface dialog, int whichButton) { 925 ((ChooseLockGenericFragment) getParentFragment()) 926 .setUnlockMethod( 927 args.getString(ARG_UNLOCK_METHOD_TO_SET)); 928 } 929 } 930 ) 931 .setNegativeButton(R.string.cancel, 932 new DialogInterface.OnClickListener() { 933 @Override 934 public void onClick(DialogInterface dialog, int whichButton) { 935 dismiss(); 936 } 937 } 938 ) 939 .create(); 940 } 941 } 942 } 943 } 944