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