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