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