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