2 * Copyright (C) 2010 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.android.settings.password;
19 import static android.app.admin.DevicePolicyManager.ACTION_SET_NEW_PARENT_PROFILE_PASSWORD;
20 import static android.app.admin.DevicePolicyManager.ACTION_SET_NEW_PASSWORD;
22 import static com.android.settings.password.ChooseLockPassword.ChooseLockPasswordFragment.RESULT_FINISHED;
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;
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;
66 import java.util.List;
68 public class ChooseLockGeneric extends SettingsActivity {
69 public static final String CONFIRM_CREDENTIALS = "confirm_credentials";
72 public Intent getIntent() {
73 Intent modIntent = new Intent(super.getIntent());
74 modIntent.putExtra(EXTRA_SHOW_FRAGMENT, getFragmentClass().getName());
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);
85 protected boolean isValidFragment(String fragmentName) {
86 if (ChooseLockGenericFragment.class.getName().equals(fragmentName)) return true;
90 /* package */ Class<? extends Fragment> getFragmentClass() {
91 return ChooseLockGenericFragment.class;
94 public static class InternalActivity extends ChooseLockGeneric {
97 public static class ChooseLockGenericFragment extends SettingsPreferenceFragment {
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";
111 * Boolean extra determining whether a "screen lock options" button should be shown. This
112 * extra is both sent and received by ChooseLockGeneric.
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.
119 * This gives the user the choice to select a different screen lock type, even if
120 * ChooseLockGeneric selected a default.
122 public static final String EXTRA_SHOW_OPTIONS_BUTTON = "show_options_button";
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.
129 public static final String EXTRA_CHOOSE_LOCK_GENERIC_EXTRAS = "choose_lock_generic_extras";
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;
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;
151 private boolean mHideDrawer = false;
152 private ManagedLockPasswordProvider mManagedPasswordProvider;
153 private boolean mIsSetNewPassword = false;
154 private UserManager mUserManager;
155 private ChooseLockGenericController mController;
157 protected boolean mForFingerprint = false;
160 public int getMetricsCategory() {
161 return MetricsEvent.CHOOSE_LOCK_GENERIC;
165 public void onCreate(Bundle savedInstanceState) {
166 super.onCreate(savedInstanceState);
167 final Activity activity = getActivity();
168 if (!Utils.isDeviceProvisioned(activity) && !canRunBeforeDeviceProvisioned()) {
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);
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);
190 mHideDrawer = getActivity().getIntent().getBooleanExtra(EXTRA_HIDE_DRAWER, false);
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());
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);
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()),
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);
230 mManagedPasswordProvider = ManagedLockPasswordProvider.get(getActivity(), mUserId);
232 if (mPasswordConfirmed) {
233 updatePreferencesOrFinish(savedInstanceState != null);
234 if (mForChangeCredRequiredForBoot) {
235 maybeEnableEncryption(mLockPatternUtils.getKeyguardStoredPasswordQuality(
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;
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);
251 mWaitingForConfirmation = true;
257 protected boolean canRunBeforeDeviceProvisioned() {
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);
272 public boolean onPreferenceTreeClick(Preference preference) {
273 final String key = preference.getKey();
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);
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,
291 startActivityForResult(chooseLockGenericIntent, SKIP_FINGERPRINT_REQUEST);
294 return setUnlockMethod(key);
299 * If the device has encryption already enabled, then ask the user if they
300 * also want to encrypt the phone with this password.
305 // TODO: why does this take disabled, its always called with a quality higher than
306 // what makes sense with disabled == true
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,
330 intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT,
332 intent.putExtra(EXTRA_HIDE_DRAWER, mHideDrawer);
333 startActivityForResult(
335 mIsSetNewPassword && mHasChallenge
336 ? CHOOSE_LOCK_BEFORE_FINGERPRINT_REQUEST
337 : ENABLE_ENCRYPTION_REQUEST);
339 if (mForChangeCredRequiredForBoot) {
340 // Welp, couldn't change it. Oh well.
344 updateUnlockMethodAndFinish(quality, disabled, false /* chooseLockSkipped */);
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);
364 } else if (requestCode == CHOOSE_LOCK_REQUEST
365 || requestCode == ENABLE_ENCRYPTION_REQUEST) {
366 if (resultCode != RESULT_CANCELED || mForChangeCredRequiredForBoot) {
367 getActivity().setResult(resultCode, data);
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);
375 getActivity().setResult(RESULT_CANCELED, data);
379 } else if (requestCode == CHOOSE_LOCK_BEFORE_FINGERPRINT_REQUEST
380 && resultCode == FingerprintEnrollBase.RESULT_FINISHED) {
381 Intent intent = getFindSensorIntent(getActivity());
383 intent.putExtras(data.getExtras());
385 // Forward the target user id to fingerprint setup page.
386 intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
387 startActivity(intent);
389 } else if (requestCode == SKIP_FINGERPRINT_REQUEST) {
390 if (resultCode != RESULT_CANCELED) {
391 getActivity().setResult(
392 resultCode == RESULT_FINISHED ? RESULT_OK : resultCode, data);
396 getActivity().setResult(Activity.RESULT_CANCELED);
399 if (requestCode == Activity.RESULT_CANCELED && mForChangeCredRequiredForBoot) {
404 protected Intent getFindSensorIntent(Context context) {
405 return new Intent(context, FingerprintEnrollFindSensor.class);
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);
421 private void updatePreferencesOrFinish(boolean isRecreatingActivity) {
422 Intent intent = getActivity().getIntent();
423 int quality = intent.getIntExtra(LockPatternUtils.PASSWORD_TYPE_KEY, -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();
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 */);
445 protected void addPreferences() {
446 addPreferencesFromResource(R.xml.security_settings_picker);
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);
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);
464 if (mManagedPasswordProvider.isSettingManagedPasswordSupported()) {
465 setPreferenceTitle(ScreenLockType.MANAGED,
466 mManagedPasswordProvider.getPickerOptionTitle(mForFingerprint));
468 removePreference(ScreenLockType.MANAGED.preferenceKey);
471 if (!(mForFingerprint && mIsSetNewPassword)) {
472 removePreference(KEY_SKIP_FINGERPRINT);
476 private void setPreferenceTitle(ScreenLockType lock, @StringRes int title) {
477 Preference preference = findPreference(lock.preferenceKey);
478 if (preference != null) {
479 preference.setTitle(title);
483 private void setPreferenceTitle(ScreenLockType lock, CharSequence title) {
484 Preference preference = findPreference(lock.preferenceKey);
485 if (preference != null) {
486 preference.setTitle(title);
490 private void setPreferenceSummary(ScreenLockType lock, @StringRes int summary) {
491 Preference preference = findPreference(lock.preferenceKey);
492 if (preference != null) {
493 preference.setSummary(summary);
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);
505 private String getKeyForCurrent() {
506 final int credentialOwner = UserManager.get(getContext())
507 .getCredentialOwnerProfile(mUserId);
508 if (mLockPatternUtils.isLockScreenDisabled(credentialOwner)) {
509 return ScreenLockType.NONE.preferenceKey;
511 ScreenLockType lock =
512 ScreenLockType.fromQuality(
513 mLockPatternUtils.getKeyguardStoredPasswordQuality(credentialOwner));
514 return lock != null ? lock.preferenceKey : null;
518 * Disables preferences that are less secure than required quality. The actual
519 * implementation is in disableUnusablePreferenceImpl.
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.
525 protected void disableUnusablePreferences(final int quality, boolean hideDisabledPrefs) {
526 disableUnusablePreferencesImpl(quality, hideDisabledPrefs);
530 * Disables preferences that are less secure than required quality.
532 * @param quality the requested quality.
533 * @param hideDisabled whether to hide disable screen lock options.
535 protected void disableUnusablePreferencesImpl(final int quality,
536 boolean hideDisabled) {
537 final PreferenceScreen entries = getPreferenceScreen();
539 int adminEnforcedQuality = mDPM.getPasswordQuality(null, mUserId);
540 EnforcedAdmin enforcedAdmin = RestrictedLockUtils.checkIfPasswordQualityIsSet(
541 getActivity(), mUserId);
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);
552 visible = visible && enabled;
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);
565 ((RestrictedPreference) pref).setDisabledByAdmin(null);
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()) {
578 if (StorageManager.isNonDefaultBlockEncrypted()) {
582 if (AccessibilityManager.getInstance(getActivity()).getEnabledAccessibilityServiceList(
583 AccessibilityServiceInfo.FEEDBACK_ALL_MASK).isEmpty()) {
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);
593 protected Intent getLockManagedPasswordIntent(String password) {
594 return mManagedPasswordProvider.createIntent(false, password);
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)
605 builder.setChallenge(mChallenge);
607 if (mUserPassword != null) {
608 builder.setPassword(mUserPassword);
610 return builder.build();
613 protected Intent getLockPatternIntent() {
614 ChooseLockPattern.IntentBuilder builder =
615 new ChooseLockPattern.IntentBuilder(getContext())
616 .setForFingerprint(mForFingerprint)
619 builder.setChallenge(mChallenge);
621 if (mUserPassword != null) {
622 builder.setPattern(mUserPassword);
624 return builder.build();
627 protected Intent getEncryptionInterstitialIntent(Context context, int quality,
628 boolean required, Intent unlockMethodIntent) {
629 return EncryptionInterstitial.createStartIntent(context, quality, required,
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.
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}
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");
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);
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);
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);
671 removeAllFingerprintForUserAndFinish(mUserId);
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;
684 final int maxLength = mDPM.getPasswordMaximumLength(quality);
685 intent = getLockPasswordIntent(quality, minLength, maxLength);
686 } else if (quality == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING) {
687 intent = getLockPatternIntent();
689 if (intent != null) {
690 intent.putExtra(EXTRA_HIDE_DRAWER, mHideDrawer);
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() {
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.
715 public void onRemovalSucceeded(Fingerprint fp, int remaining) {
716 if (remaining == 0) {
717 removeManagedProfileFingerprintsAndFinishIfNecessary(userId);
722 // No fingerprints in this user, we may also want to delete managed profile
724 removeManagedProfileFingerprintsAndFinishIfNecessary(userId);
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.
735 private void removeManagedProfileFingerprintsAndFinishIfNecessary(final int parentUserId) {
736 if (mFingerprintManager != null && mFingerprintManager.isHardwareDetected()) {
737 mFingerprintManager.setActiveUser(UserHandle.myUserId());
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;
754 if (!hasChildProfile) {
760 public void onDestroy() {
765 public int getHelpResource() {
766 return R.string.help_url_choose_lockscreen;
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;
775 private int getResIdForFactoryResetProtectionWarningMessage() {
776 final boolean hasFingerprints;
777 if (mFingerprintManager != null && mFingerprintManager.isHardwareDetected()) {
778 hasFingerprints = mFingerprintManager.hasEnrolledFingerprints(mUserId);
780 hasFingerprints = false;
782 boolean isProfile = UserManager.get(getActivity()).isManagedProfile(mUserId);
783 switch (mLockPatternUtils.getKeyguardStoredPasswordQuality(mUserId)) {
784 case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
785 if (hasFingerprints && isProfile) {
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;
793 return R.string.unlock_disable_frp_warning_content_pattern;
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;
804 return R.string.unlock_disable_frp_warning_content_pin;
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) {
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;
818 return R.string.unlock_disable_frp_warning_content_password;
821 if (hasFingerprints && isProfile) {
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;
829 return R.string.unlock_disable_frp_warning_content_unknown;
834 private boolean isUnlockMethodSecure(String unlockMethod) {
835 return !(ScreenLockType.SWIPE.preferenceKey.equals(unlockMethod) ||
836 ScreenLockType.NONE.preferenceKey.equals(unlockMethod));
839 private boolean setUnlockMethod(String unlockMethod) {
840 EventLog.writeEvent(EventLogTags.LOCK_SCREEN_TYPE, unlockMethod);
842 ScreenLockType lock = ScreenLockType.fromKey(unlockMethod);
847 updateUnlockMethodAndFinish(
849 lock == ScreenLockType.NONE,
850 false /* chooseLockSkipped */);
856 maybeEnableEncryption(lock.defaultQuality, false);
860 Log.e(TAG, "Encountered unknown unlock method to set: " + unlockMethod);
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);
873 public static class FactoryResetProtectionWarningDialog extends InstrumentedDialogFragment {
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";
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);
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);
900 public Dialog onCreateDialog(Bundle savedInstanceState) {
901 final Bundle args = getArguments();
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);
912 .setNegativeButton(R.string.cancel, (dialog, whichButton) -> dismiss())
917 public int getMetricsCategory() {
918 return MetricsEvent.DIALOG_FRP;