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 static android.app.admin.DevicePolicyManager.ACTION_SET_NEW_PARENT_PROFILE_PASSWORD; 20 import static android.app.admin.DevicePolicyManager.ACTION_SET_NEW_PASSWORD; 21 import static com.android.settings.ChooseLockPassword.ChooseLockPasswordFragment.RESULT_FINISHED; 22 import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; 23 24 import android.accessibilityservice.AccessibilityServiceInfo; 25 import android.app.Activity; 26 import android.app.AlertDialog; 27 import android.app.Dialog; 28 import android.app.Fragment; 29 import android.app.FragmentManager; 30 import android.app.admin.DevicePolicyManager; 31 import android.content.Context; 32 import android.content.DialogInterface; 33 import android.content.Intent; 34 import android.content.pm.UserInfo; 35 import android.hardware.fingerprint.Fingerprint; 36 import android.hardware.fingerprint.FingerprintManager; 37 import android.hardware.fingerprint.FingerprintManager.RemovalCallback; 38 import android.os.Bundle; 39 import android.os.UserHandle; 40 import android.os.UserManager; 41 import android.os.storage.StorageManager; 42 import android.security.KeyStore; 43 import android.support.v7.preference.Preference; 44 import android.support.v7.preference.PreferenceScreen; 45 import android.text.TextUtils; 46 import android.util.EventLog; 47 import android.util.Log; 48 import android.view.accessibility.AccessibilityManager; 49 import android.widget.TextView; 50 51 import com.android.internal.logging.nano.MetricsProto.MetricsEvent; 52 import com.android.internal.widget.LockPatternUtils; 53 import com.android.settings.core.instrumentation.InstrumentedDialogFragment; 54 import com.android.settings.fingerprint.FingerprintEnrollBase; 55 import com.android.settings.fingerprint.FingerprintEnrollFindSensor; 56 import com.android.settingslib.RestrictedLockUtils; 57 import com.android.settingslib.RestrictedPreference; 58 59 import java.util.List; 60 61 public class ChooseLockGeneric extends SettingsActivity { 62 public static final String CONFIRM_CREDENTIALS = "confirm_credentials"; 63 64 @Override getIntent()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 isValidFragment(String fragmentName)78 protected boolean isValidFragment(String fragmentName) { 79 if (ChooseLockGenericFragment.class.getName().equals(fragmentName)) return true; 80 return false; 81 } 82 getFragmentClass()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 getMetricsCategory()137 public int getMetricsCategory() { 138 return MetricsEvent.CHOOSE_LOCK_GENERIC; 139 } 140 141 @Override onCreate(Bundle savedInstanceState)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 addHeaderView()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 onPreferenceTreeClick(Preference preference)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 maybeEnableEncryption(int quality, boolean disabled)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 onActivityResult(int requestCode, int resultCode, Intent data)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 getFindSensorIntent(Context context)352 protected Intent getFindSensorIntent(Context context) { 353 return new Intent(context, FingerprintEnrollFindSensor.class); 354 } 355 356 @Override onSaveInstanceState(Bundle outState)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 updatePreferencesOrFinish()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 addPreferences()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 updatePreferenceText()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 updateCurrentPreference()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 getKeyForCurrent()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 */ upgradeQuality(int quality)460 private int upgradeQuality(int quality) { 461 quality = upgradeQualityForDPM(quality); 462 return quality; 463 } 464 upgradeQualityForDPM(int quality)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 */ disableUnusablePreferences(final int quality, boolean hideDisabledPrefs)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 */ disableUnusablePreferencesImpl(final int quality, boolean hideDisabled)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 updatePreferenceSummaryIfNeeded()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 getLockManagedPasswordIntent(boolean requirePassword, String password)598 protected Intent getLockManagedPasswordIntent(boolean requirePassword, String password) { 599 return mManagedPasswordProvider.createIntent(requirePassword, password); 600 } 601 getLockPasswordIntent(Context context, int quality, int minLength, final int maxLength, boolean requirePasswordToDecrypt, boolean confirmCredentials, int userId)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 getLockPasswordIntent(Context context, int quality, int minLength, final int maxLength, boolean requirePasswordToDecrypt, long challenge, int userId)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 getLockPasswordIntent(Context context, int quality, int minLength, int maxLength, boolean requirePasswordToDecrypt, String password, int userId)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 getLockPatternIntent(Context context, final boolean requirePassword, final boolean confirmCredentials, int userId)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 getLockPatternIntent(Context context, final boolean requirePassword, long challenge, int userId)628 protected Intent getLockPatternIntent(Context context, final boolean requirePassword, 629 long challenge, int userId) { 630 return ChooseLockPattern.createIntent(context, requirePassword, challenge, userId); 631 } 632 getLockPatternIntent(Context context, final boolean requirePassword, final String pattern, int userId)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 getEncryptionInterstitialIntent(Context context, int quality, boolean required, Intent unlockMethodIntent)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 */ updateUnlockMethodAndFinish(int quality, boolean disabled)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 getIntentForUnlockMethod(int quality, boolean disabled)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 removeAllFingerprintForUserAndFinish(final int userId)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 removeManagedProfileFingerprintsAndFinishIfNecessary(final int parentUserId)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 onDestroy()778 public void onDestroy() { 779 super.onDestroy(); 780 } 781 782 @Override getHelpResource()783 protected int getHelpResource() { 784 return R.string.help_url_choose_lockscreen; 785 } 786 getResIdForFactoryResetProtectionWarningTitle()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 getResIdForFactoryResetProtectionWarningMessage()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 isUnlockMethodSecure(String unlockMethod)852 private boolean isUnlockMethodSecure(String unlockMethod) { 853 return !(KEY_UNLOCK_SET_OFF.equals(unlockMethod) || 854 KEY_UNLOCK_SET_NONE.equals(unlockMethod)); 855 } 856 setUnlockMethod(String unlockMethod)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 showFactoryResetProtectionWarningDialog(String unlockMethodToSet)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 newInstance( int titleRes, int messageRes, String unlockMethodToSet)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 show(FragmentManager manager, String tag)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 onCreateDialog(Bundle savedInstanceState)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 getMetricsCategory()948 public int getMetricsCategory() { 949 return MetricsEvent.DIALOG_FRP; 950 } 951 } 952 } 953 } 954