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