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 getIntent()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 isValidFragment(String fragmentName)72 protected boolean isValidFragment(String fragmentName) { 73 if (ChooseLockGenericFragment.class.getName().equals(fragmentName)) return true; 74 return false; 75 } 76 getFragmentClass()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 getMetricsCategory()126 protected int getMetricsCategory() { 127 return MetricsEvent.CHOOSE_LOCK_GENERIC; 128 } 129 130 @Override onCreate(Bundle savedInstanceState)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 addHeaderView()216 protected void addHeaderView() { 217 if (mForFingerprint) { 218 setHeaderView(R.layout.choose_lock_generic_fingerprint_header); 219 } 220 } 221 222 @Override onPreferenceTreeClick(Preference preference)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 maybeEnableEncryption(int quality, boolean disabled)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 onActivityResult(int requestCode, int resultCode, Intent data)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 onSaveInstanceState(Bundle outState)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 updatePreferencesOrFinish()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 addPreferences()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 updatePreferenceText()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 updateCurrentPreference()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 getKeyForCurrent()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 */ upgradeQuality(int quality)409 private int upgradeQuality(int quality) { 410 quality = upgradeQualityForDPM(quality); 411 return quality; 412 } 413 upgradeQualityForDPM(int quality)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 */ disableUnusablePreferences(final int quality, boolean hideDisabledPrefs)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 */ disableUnusablePreferencesImpl(final int quality, boolean hideDisabled)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 updatePreferenceSummaryIfNeeded()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 getLockManagedPasswordIntent(boolean requirePassword, String password)542 protected Intent getLockManagedPasswordIntent(boolean requirePassword, String password) { 543 return mManagedPasswordProvider.createIntent(requirePassword, password); 544 } 545 getLockPasswordIntent(Context context, int quality, int minLength, final int maxLength, boolean requirePasswordToDecrypt, boolean confirmCredentials, int userId)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 getLockPasswordIntent(Context context, int quality, int minLength, final int maxLength, boolean requirePasswordToDecrypt, long challenge, int userId)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 getLockPasswordIntent(Context context, int quality, int minLength, int maxLength, boolean requirePasswordToDecrypt, String password, int userId)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 getLockPatternIntent(Context context, final boolean requirePassword, final boolean confirmCredentials, int userId)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 getLockPatternIntent(Context context, final boolean requirePassword, long challenge, int userId)572 protected Intent getLockPatternIntent(Context context, final boolean requirePassword, 573 long challenge, int userId) { 574 return ChooseLockPattern.createIntent(context, requirePassword, challenge, userId); 575 } 576 getLockPatternIntent(Context context, final boolean requirePassword, final String pattern, int userId)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 getEncryptionInterstitialIntent(Context context, int quality, boolean required, Intent unlockMethodIntent)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 */ updateUnlockMethodAndFinish(int quality, boolean disabled)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 getIntentForUnlockMethod(int quality, boolean disabled)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 removeAllFingerprintForUserAndFinish(final int userId)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 removeManagedProfileFingerprintsAndFinishIfNecessary(final int parentUserId)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 onDestroy()717 public void onDestroy() { 718 super.onDestroy(); 719 } 720 721 @Override getHelpResource()722 protected int getHelpResource() { 723 return R.string.help_url_choose_lockscreen; 724 } 725 getResIdForFactoryResetProtectionWarningTitle()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 getResIdForFactoryResetProtectionWarningMessage()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 isUnlockMethodSecure(String unlockMethod)786 private boolean isUnlockMethodSecure(String unlockMethod) { 787 return !(KEY_UNLOCK_SET_OFF.equals(unlockMethod) || 788 KEY_UNLOCK_SET_NONE.equals(unlockMethod)); 789 } 790 setUnlockMethod(String unlockMethod)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 showFactoryResetProtectionWarningDialog(String unlockMethodToSet)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 newInstance( int titleRes, int messageRes, String unlockMethodToSet)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 show(FragmentManager manager, String tag)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 onCreateDialog(Bundle savedInstanceState)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