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