diff --git a/res/xml/security_settings_picker.xml b/res/xml/security_settings_picker.xml index 3a456973de3..7b6069d3360 100644 --- a/res/xml/security_settings_picker.xml +++ b/res/xml/security_settings_picker.xml @@ -43,4 +43,8 @@ android:title="@string/unlock_set_unlock_password_title" android:persistent="false"/> + + diff --git a/src/com/android/settings/ChooseLockGeneric.java b/src/com/android/settings/ChooseLockGeneric.java index 775cf77c37c..1182ed51682 100644 --- a/src/com/android/settings/ChooseLockGeneric.java +++ b/src/com/android/settings/ChooseLockGeneric.java @@ -92,6 +92,7 @@ public class ChooseLockGeneric extends SettingsActivity { private static final String KEY_UNLOCK_SET_PIN = "unlock_set_pin"; private static final String KEY_UNLOCK_SET_PASSWORD = "unlock_set_password"; private static final String KEY_UNLOCK_SET_PATTERN = "unlock_set_pattern"; + private static final String KEY_UNLOCK_SET_MANAGED = "unlock_set_managed"; private static final String PASSWORD_CONFIRMED = "password_confirmed"; private static final String WAITING_FOR_CONFIRMATION = "waiting_for_confirmation"; public static final String MINIMUM_QUALITY_KEY = "minimum_quality"; @@ -120,6 +121,7 @@ public class ChooseLockGeneric extends SettingsActivity { private FingerprintManager mFingerprintManager; private int mUserId; private boolean mHideDrawer = false; + private ManagedLockPasswordProvider mManagedPasswordProvider; protected boolean mForFingerprint = false; @@ -181,6 +183,8 @@ public class ChooseLockGeneric extends SettingsActivity { mUserId = targetUser; } + mManagedPasswordProvider = ManagedLockPasswordProvider.get(getActivity(), mUserId); + if (mPasswordConfirmed) { updatePreferencesOrFinish(); if (mForChangeCredRequiredForBoot) { @@ -356,6 +360,13 @@ public class ChooseLockGeneric extends SettingsActivity { Preference password = findPreference(KEY_UNLOCK_SET_PASSWORD); password.setTitle(R.string.fingerprint_unlock_set_unlock_password); } + + if (mManagedPasswordProvider.isSettingManagedPasswordSupported()) { + Preference managed = findPreference(KEY_UNLOCK_SET_MANAGED); + managed.setTitle(mManagedPasswordProvider.getPickerOptionTitle(mForFingerprint)); + } else { + removePreference(KEY_UNLOCK_SET_MANAGED); + } } private void updateCurrentPreference() { @@ -380,7 +391,10 @@ public class ChooseLockGeneric extends SettingsActivity { return KEY_UNLOCK_SET_PIN; case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC: case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC: + case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX: return KEY_UNLOCK_SET_PASSWORD; + case DevicePolicyManager.PASSWORD_QUALITY_MANAGED: + return KEY_UNLOCK_SET_MANAGED; case DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED: return KEY_UNLOCK_SET_NONE; } @@ -462,6 +476,11 @@ public class ChooseLockGeneric extends SettingsActivity { enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_COMPLEX; disabledByAdmin = adminEnforcedQuality > DevicePolicyManager.PASSWORD_QUALITY_COMPLEX; + } else if (KEY_UNLOCK_SET_MANAGED.equals(key)) { + enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_MANAGED + && mManagedPasswordProvider.isManagedPasswordChoosable(); + disabledByAdmin = adminEnforcedQuality + > DevicePolicyManager.PASSWORD_QUALITY_MANAGED; } if (hideDisabled) { visible = enabled; @@ -508,13 +527,18 @@ public class ChooseLockGeneric extends SettingsActivity { switch (preference.getKey()) { case KEY_UNLOCK_SET_PATTERN: case KEY_UNLOCK_SET_PIN: - case KEY_UNLOCK_SET_PASSWORD: { + case KEY_UNLOCK_SET_PASSWORD: + case KEY_UNLOCK_SET_MANAGED: { preference.setSummary(summary); } break; } } } + protected Intent getLockManagedPasswordIntent(boolean requirePassword, String password) { + return mManagedPasswordProvider.createIntent(requirePassword, password); + } + protected Intent getLockPasswordIntent(Context context, int quality, int minLength, final int maxLength, boolean requirePasswordToDecrypt, boolean confirmCredentials, int userId) { @@ -593,7 +617,9 @@ public class ChooseLockGeneric extends SettingsActivity { private Intent getIntentForUnlockMethod(int quality, boolean disabled) { Intent intent = null; final Context context = getActivity(); - if (quality >= DevicePolicyManager.PASSWORD_QUALITY_NUMERIC) { + if (quality >= DevicePolicyManager.PASSWORD_QUALITY_MANAGED) { + intent = getLockManagedPasswordIntent(mRequirePassword, mUserPassword); + } else if (quality >= DevicePolicyManager.PASSWORD_QUALITY_NUMERIC) { int minLength = mDPM.getPasswordMinimumLength(null, mUserId); if (minLength < MIN_PASSWORD_LENGTH) { minLength = MIN_PASSWORD_LENGTH; @@ -721,6 +747,7 @@ public class ChooseLockGeneric extends SettingsActivity { case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC: case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC: case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX: + case DevicePolicyManager.PASSWORD_QUALITY_MANAGED: if (hasFingerprints && isProfile) { return R.string .unlock_disable_frp_warning_content_password_fingerprint_profile; @@ -759,6 +786,8 @@ public class ChooseLockGeneric extends SettingsActivity { } else if (KEY_UNLOCK_SET_NONE.equals(unlockMethod)) { updateUnlockMethodAndFinish( DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, false /* disabled */ ); + } else if (KEY_UNLOCK_SET_MANAGED.equals(unlockMethod)) { + maybeEnableEncryption(DevicePolicyManager.PASSWORD_QUALITY_MANAGED, false); } else if (KEY_UNLOCK_SET_PATTERN.equals(unlockMethod)) { maybeEnableEncryption( DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, false); diff --git a/src/com/android/settings/ChooseLockSettingsHelper.java b/src/com/android/settings/ChooseLockSettingsHelper.java index c25503d4ff9..ec7aa330ea6 100644 --- a/src/com/android/settings/ChooseLockSettingsHelper.java +++ b/src/com/android/settings/ChooseLockSettingsHelper.java @@ -189,6 +189,7 @@ public final class ChooseLockSettingsHelper { case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC: case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC: case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX: + case DevicePolicyManager.PASSWORD_QUALITY_MANAGED: launched = launchConfirmationActivity(request, title, header, description, returnCredentials || hasChallenge ? ConfirmLockPassword.InternalActivity.class diff --git a/src/com/android/settings/ConfirmLockPassword.java b/src/com/android/settings/ConfirmLockPassword.java index 87e710bf873..d7bdb8b1342 100644 --- a/src/com/android/settings/ConfirmLockPassword.java +++ b/src/com/android/settings/ConfirmLockPassword.java @@ -121,7 +121,8 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity { mErrorTextView = (TextView) view.findViewById(R.id.errorText); mIsAlpha = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC == storedQuality || DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC == storedQuality - || DevicePolicyManager.PASSWORD_QUALITY_COMPLEX == storedQuality; + || DevicePolicyManager.PASSWORD_QUALITY_COMPLEX == storedQuality + || DevicePolicyManager.PASSWORD_QUALITY_MANAGED == storedQuality; mImm = (InputMethodManager) getActivity().getSystemService( Context.INPUT_METHOD_SERVICE); diff --git a/src/com/android/settings/ManagedLockPasswordProvider.java b/src/com/android/settings/ManagedLockPasswordProvider.java new file mode 100644 index 00000000000..b9725d706cb --- /dev/null +++ b/src/com/android/settings/ManagedLockPasswordProvider.java @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.settings; + +import android.content.Context; +import android.content.Intent; + +/** + * Helper for handling managed passwords in security settings UI. + * It provides resources that should be shown in settings UI when lock password quality is set to + * {@link android.app.admin.DevicePolicyManager#PASSWORD_QUALITY_MANAGED} and hooks for implementing + * an option for setting the password quality to + * {@link android.app.admin.DevicePolicyManager#PASSWORD_QUALITY_MANAGED}. + */ +public class ManagedLockPasswordProvider { + /** Factory method to make it easier to inject extended ManagedLockPasswordProviders. */ + static ManagedLockPasswordProvider get(Context context, int userId) { + return new ManagedLockPasswordProvider(); + } + + protected ManagedLockPasswordProvider() {} + + /** + * Whether choosing/setting a managed lock password is supported for the user. + * Please update {@link #getPickerOptionTitle(boolean)} if overridden to return true. + */ + boolean isSettingManagedPasswordSupported() { return false; } + + /** + * Whether the user should be able to choose managed lock password. + */ + boolean isManagedPasswordChoosable() { return false; } + + /** + * Returns title for managed password preference in security (lock) setting picker. + * Should be overridden if {@link #isManagedPasswordSupported()} returns true. + * @param forFingerprint Whether fingerprint unlock is enabled. + */ + String getPickerOptionTitle(boolean forFingerprint) { return ""; } + + /** + * Gets resource id of the lock screen preference that should be displayed in security settings + * if the current password quality is set to + * {@link android.app.admin.DevicePolicyManager#PASSWORD_QUALITY_MANAGED}. + * @param forProfile Whether the settings are shown for a user profile rather than a user. + */ + int getResIdForLockUnlockScreen(boolean forProfile) { + return forProfile ? R.xml.security_settings_password_profile + : R.xml.security_settings_password; + } + + /** + * Gets resource id of the subscreen that should be shown after clicking gear icon for lock + * screen preference in security settings if the current password quality is set to + * {@link android.app.admin.DevicePolicyManager#PASSWORD_QUALITY_MANAGED}. + */ + int getResIdForLockUnlockSubScreen() { + return R.xml.security_settings_password_sub; + } + + /** + * Creates intent that should be launched when user chooses managed password in the lock + * settings picker. + * @param requirePasswordToDecrypt Whether a password is needed to decrypt the user. + * @param password Current lock password. + * @return Intent that should update lock password to a managed password. + */ + Intent createIntent(boolean requirePasswordToDecrypt, String password) { + return null; + } +} diff --git a/src/com/android/settings/ScreenPinningSettings.java b/src/com/android/settings/ScreenPinningSettings.java index d8e821c8400..5b5b9efa919 100644 --- a/src/com/android/settings/ScreenPinningSettings.java +++ b/src/com/android/settings/ScreenPinningSettings.java @@ -150,6 +150,7 @@ public class ScreenPinningSettings extends SettingsPreferenceFragment case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC: case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC: case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX: + case DevicePolicyManager.PASSWORD_QUALITY_MANAGED: return R.string.screen_pinning_unlock_password; case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING: if (mLockPatternUtils.isLockPatternEnabled(UserHandle.myUserId())) { diff --git a/src/com/android/settings/SecuritySettings.java b/src/com/android/settings/SecuritySettings.java index 5699874c1cd..0c3260f012d 100644 --- a/src/com/android/settings/SecuritySettings.java +++ b/src/com/android/settings/SecuritySettings.java @@ -130,6 +130,7 @@ public class SecuritySettings extends SettingsPreferenceFragment private ChooseLockSettingsHelper mChooseLockSettingsHelper; private LockPatternUtils mLockPatternUtils; + private ManagedLockPasswordProvider mManagedPasswordProvider; private SwitchPreference mVisiblePatternProfile; private SwitchPreference mUnifyProfile; @@ -164,6 +165,8 @@ public class SecuritySettings extends SettingsPreferenceFragment mLockPatternUtils = new LockPatternUtils(getActivity()); + mManagedPasswordProvider = ManagedLockPasswordProvider.get(getActivity(), MY_USER_ID); + mDPM = (DevicePolicyManager)getSystemService(Context.DEVICE_POLICY_SERVICE); mUm = UserManager.get(getActivity()); @@ -177,7 +180,8 @@ public class SecuritySettings extends SettingsPreferenceFragment } private static int getResIdForLockUnlockScreen(Context context, - LockPatternUtils lockPatternUtils, int userId) { + LockPatternUtils lockPatternUtils, ManagedLockPasswordProvider managedPasswordProvider, + int userId) { final boolean isMyUser = userId == MY_USER_ID; int resid = 0; if (!lockPatternUtils.isSecure(userId)) { @@ -205,6 +209,9 @@ public class SecuritySettings extends SettingsPreferenceFragment resid = isMyUser ? R.xml.security_settings_password : R.xml.security_settings_password_profile; break; + case DevicePolicyManager.PASSWORD_QUALITY_MANAGED: + resid = managedPasswordProvider.getResIdForLockUnlockScreen(!isMyUser); + break; } } return resid; @@ -225,7 +232,8 @@ public class SecuritySettings extends SettingsPreferenceFragment root = getPreferenceScreen(); // Add options for lock/unlock screen - final int resid = getResIdForLockUnlockScreen(getActivity(), mLockPatternUtils, MY_USER_ID); + final int resid = getResIdForLockUnlockScreen(getActivity(), mLockPatternUtils, + mManagedPasswordProvider, MY_USER_ID); addPreferencesFromResource(resid); // DO or PO installed in the user may disallow to change password. @@ -237,7 +245,8 @@ public class SecuritySettings extends SettingsPreferenceFragment addPreferencesFromResource(R.xml.security_settings_profile); addPreferencesFromResource(R.xml.security_settings_unification); final int profileResid = getResIdForLockUnlockScreen( - getActivity(), mLockPatternUtils, mProfileChallengeUserId); + getActivity(), mLockPatternUtils, mManagedPasswordProvider, + mProfileChallengeUserId); addPreferencesFromResource(profileResid); maybeAddFingerprintPreference(root, mProfileChallengeUserId); if (!mLockPatternUtils.isSeparateProfileChallengeEnabled(mProfileChallengeUserId)) { @@ -794,6 +803,8 @@ public class SecuritySettings extends SettingsPreferenceFragment final List index = new ArrayList(); final LockPatternUtils lockPatternUtils = new LockPatternUtils(context); + final ManagedLockPasswordProvider managedPasswordProvider = + ManagedLockPasswordProvider.get(context, MY_USER_ID); final DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE); final UserManager um = UserManager.get(context); @@ -807,7 +818,7 @@ public class SecuritySettings extends SettingsPreferenceFragment || !isPasswordManaged(profileUserId, context, dpm))) { // Add options for lock/unlock screen final int resId = getResIdForLockUnlockScreen(context, lockPatternUtils, - MY_USER_ID); + managedPasswordProvider, MY_USER_ID); index.add(getSearchResource(context, resId)); } @@ -815,7 +826,7 @@ public class SecuritySettings extends SettingsPreferenceFragment && lockPatternUtils.isSeparateProfileChallengeAllowed(profileUserId) && !isPasswordManaged(profileUserId, context, dpm)) { index.add(getSearchResource(context, getResIdForLockUnlockScreen(context, - lockPatternUtils, profileUserId))); + lockPatternUtils, managedPasswordProvider, profileUserId))); } if (um.isAdminUser()) { @@ -832,7 +843,8 @@ public class SecuritySettings extends SettingsPreferenceFragment } final SearchIndexableResource sir = getSearchResource(context, - SecuritySubSettings.getResIdForLockUnlockSubScreen(context, lockPatternUtils)); + SecuritySubSettings.getResIdForLockUnlockSubScreen(context, lockPatternUtils, + managedPasswordProvider)); sir.className = SecuritySubSettings.class.getName(); index.add(sir); @@ -1038,7 +1050,8 @@ public class SecuritySettings extends SettingsPreferenceFragment root = null; final int resid = getResIdForLockUnlockSubScreen(getActivity(), - new LockPatternUtils(getContext())); + new LockPatternUtils(getContext()), + ManagedLockPasswordProvider.get(getContext(), MY_USER_ID)); addPreferencesFromResource(resid); // lock after preference @@ -1176,7 +1189,8 @@ public class SecuritySettings extends SettingsPreferenceFragment } private static int getResIdForLockUnlockSubScreen(Context context, - LockPatternUtils lockPatternUtils) { + LockPatternUtils lockPatternUtils, + ManagedLockPasswordProvider managedPasswordProvider) { if (lockPatternUtils.isSecure(MY_USER_ID)) { switch (lockPatternUtils.getKeyguardStoredPasswordQuality(MY_USER_ID)) { case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING: @@ -1188,6 +1202,8 @@ public class SecuritySettings extends SettingsPreferenceFragment case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC: case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX: return R.xml.security_settings_password_sub; + case DevicePolicyManager.PASSWORD_QUALITY_MANAGED: + return managedPasswordProvider.getResIdForLockUnlockSubScreen(); } } else if (!lockPatternUtils.isLockScreenDisabled(MY_USER_ID)) { return R.xml.security_settings_slide_sub;