Merge "Refactor ChooseLockGenericController" into sc-dev am: b3b59d6edd
Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/apps/Settings/+/14269154 Change-Id: Iaf50c89889b985c638211a9101fa9f8f664097ac
This commit is contained in:
@@ -1311,16 +1311,16 @@
|
|||||||
<!-- Title for security picker to choose the unlock method: None/Pattern/PIN/Password [CHAR LIMIT=22] -->
|
<!-- Title for security picker to choose the unlock method: None/Pattern/PIN/Password [CHAR LIMIT=22] -->
|
||||||
<string name="lock_settings_picker_title">Choose screen lock</string>
|
<string name="lock_settings_picker_title">Choose screen lock</string>
|
||||||
|
|
||||||
<!-- Screen title. This title is asking the user to choose a type of screen lock for their device, such as a pattern, PIN, or password. [CHAR LIMIT=27] -->
|
<!-- Screen title. This title is asking the user to choose a type of screen lock for their device, such as a pattern, PIN, or password. [CHAR LIMIT=55] -->
|
||||||
<string name="lock_settings_picker_new_lock_title">Choose a screen lock</string>
|
<string name="lock_settings_picker_new_lock_title">Choose a screen lock</string>
|
||||||
|
|
||||||
<!-- Screen title. This title is asking the user to choose a new screen lock for their device, such as a pattern, PIN, or password. [CHAR LIMIT=27] -->
|
<!-- Screen title. This title is asking the user to choose a new screen lock for their device, such as a pattern, PIN, or password. [CHAR LIMIT=55] -->
|
||||||
<string name="lock_settings_picker_update_lock_title">Choose a new screen lock</string>
|
<string name="lock_settings_picker_update_lock_title">Choose a new screen lock</string>
|
||||||
|
|
||||||
<!-- Screen title. This title is asking the user to choose a type of screen lock (such as a pattern, PIN, or password) that they need to enter to use their work apps. [CHAR LIMIT=27] -->
|
<!-- Screen title. This title is asking the user to choose a type of screen lock (such as a pattern, PIN, or password) that they need to enter to use their work apps. [CHAR LIMIT=56] -->
|
||||||
<string name="lock_settings_picker_new_profile_lock_title">Choose a lock for work apps</string>
|
<string name="lock_settings_picker_new_profile_lock_title">Choose a lock for work apps</string>
|
||||||
|
|
||||||
<!-- Screen title. This title is asking the user to choose a new screen lock (such as a pattern, PIN, or password) that they need to enter to use their work apps. [CHAR LIMIT=27] -->
|
<!-- Screen title. This title is asking the user to choose a new screen lock (such as a pattern, PIN, or password) that they need to enter to use their work apps. [CHAR LIMIT=55] -->
|
||||||
<string name="lock_settings_picker_update_profile_lock_title">Choose a new work lock</string>
|
<string name="lock_settings_picker_update_profile_lock_title">Choose a new work lock</string>
|
||||||
|
|
||||||
<!-- Title for security picker in setup wizard to choose the unlock method: None/Pattern/PIN/Password (tablet) [CHAR LIMIT=22] -->
|
<!-- Title for security picker in setup wizard to choose the unlock method: None/Pattern/PIN/Password (tablet) [CHAR LIMIT=22] -->
|
||||||
|
@@ -298,9 +298,7 @@ public class BiometricEnrollActivity extends InstrumentedActivity {
|
|||||||
private void launchChooseLock() {
|
private void launchChooseLock() {
|
||||||
Log.d(TAG, "launchChooseLock");
|
Log.d(TAG, "launchChooseLock");
|
||||||
Intent intent = BiometricUtils.getChooseLockIntent(this, getIntent());
|
Intent intent = BiometricUtils.getChooseLockIntent(this, getIntent());
|
||||||
intent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY,
|
intent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.HIDE_INSECURE_OPTIONS, true);
|
||||||
DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
|
|
||||||
intent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.HIDE_DISABLED_PREFS, true);
|
|
||||||
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW_HANDLE, true);
|
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW_HANDLE, true);
|
||||||
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_BIOMETRICS, true);
|
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_BIOMETRICS, true);
|
||||||
|
|
||||||
@@ -350,8 +348,7 @@ public class BiometricEnrollActivity extends InstrumentedActivity {
|
|||||||
final Intent intent;
|
final Intent intent;
|
||||||
// If only device credential was specified, ask the user to only set that up.
|
// If only device credential was specified, ask the user to only set that up.
|
||||||
intent = new Intent(this, ChooseLockGeneric.class);
|
intent = new Intent(this, ChooseLockGeneric.class);
|
||||||
intent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY,
|
intent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.HIDE_INSECURE_OPTIONS, true);
|
||||||
DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
|
|
||||||
launchEnrollActivity(intent);
|
launchEnrollActivity(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -222,9 +222,7 @@ public abstract class BiometricEnrollIntroduction extends BiometricEnrollBase
|
|||||||
|
|
||||||
private void launchChooseLock() {
|
private void launchChooseLock() {
|
||||||
Intent intent = BiometricUtils.getChooseLockIntent(this, getIntent());
|
Intent intent = BiometricUtils.getChooseLockIntent(this, getIntent());
|
||||||
intent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY,
|
intent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.HIDE_INSECURE_OPTIONS, true);
|
||||||
DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
|
|
||||||
intent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.HIDE_DISABLED_PREFS, true);
|
|
||||||
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW_HANDLE, true);
|
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW_HANDLE, true);
|
||||||
intent.putExtra(getExtraKeyForBiometric(), true);
|
intent.putExtra(getExtraKeyForBiometric(), true);
|
||||||
if (mUserId != UserHandle.USER_NULL) {
|
if (mUserId != UserHandle.USER_NULL) {
|
||||||
|
@@ -19,7 +19,6 @@ import static android.app.Activity.RESULT_OK;
|
|||||||
|
|
||||||
import static com.android.settings.password.ChooseLockPattern.RESULT_FINISHED;
|
import static com.android.settings.password.ChooseLockPattern.RESULT_FINISHED;
|
||||||
|
|
||||||
import android.app.admin.DevicePolicyManager;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.hardware.face.FaceManager;
|
import android.hardware.face.FaceManager;
|
||||||
@@ -193,9 +192,8 @@ public abstract class BiometricsSettingsBase extends DashboardFragment {
|
|||||||
|
|
||||||
if (!launched) {
|
if (!launched) {
|
||||||
Intent intent = BiometricUtils.getChooseLockIntent(getActivity(), getIntent());
|
Intent intent = BiometricUtils.getChooseLockIntent(getActivity(), getIntent());
|
||||||
intent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY,
|
intent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.HIDE_INSECURE_OPTIONS,
|
||||||
DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
|
true);
|
||||||
intent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.HIDE_DISABLED_PREFS, true);
|
|
||||||
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW_HANDLE, true);
|
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW_HANDLE, true);
|
||||||
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_BIOMETRICS, true);
|
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_BIOMETRICS, true);
|
||||||
|
|
||||||
|
@@ -685,9 +685,7 @@ public class FingerprintSettings extends SubSettings {
|
|||||||
// TODO: This should be cleaned up. ChooseLockGeneric should provide a way of
|
// TODO: This should be cleaned up. ChooseLockGeneric should provide a way of
|
||||||
// specifying arguments/requests, instead of relying on callers setting extras.
|
// specifying arguments/requests, instead of relying on callers setting extras.
|
||||||
intent.setClassName(SETTINGS_PACKAGE_NAME, ChooseLockGeneric.class.getName());
|
intent.setClassName(SETTINGS_PACKAGE_NAME, ChooseLockGeneric.class.getName());
|
||||||
intent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY,
|
intent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.HIDE_INSECURE_OPTIONS,
|
||||||
DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
|
|
||||||
intent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.HIDE_DISABLED_PREFS,
|
|
||||||
true);
|
true);
|
||||||
intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
|
intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
|
||||||
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW_HANDLE, true);
|
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW_HANDLE, true);
|
||||||
|
@@ -75,8 +75,6 @@ import com.android.settings.biometrics.BiometricEnrollBase;
|
|||||||
import com.android.settings.core.SubSettingLauncher;
|
import com.android.settings.core.SubSettingLauncher;
|
||||||
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
|
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
|
||||||
import com.android.settings.search.SearchFeatureProvider;
|
import com.android.settings.search.SearchFeatureProvider;
|
||||||
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
|
|
||||||
import com.android.settingslib.RestrictedLockUtilsInternal;
|
|
||||||
import com.android.settingslib.RestrictedPreference;
|
import com.android.settingslib.RestrictedPreference;
|
||||||
|
|
||||||
import com.google.android.setupcompat.util.WizardManagerHelper;
|
import com.google.android.setupcompat.util.WizardManagerHelper;
|
||||||
@@ -112,8 +110,7 @@ public class ChooseLockGeneric extends SettingsActivity {
|
|||||||
private static final String KEY_SKIP_BIOMETRICS = "unlock_skip_biometrics";
|
private static final String KEY_SKIP_BIOMETRICS = "unlock_skip_biometrics";
|
||||||
private static final String PASSWORD_CONFIRMED = "password_confirmed";
|
private static final String PASSWORD_CONFIRMED = "password_confirmed";
|
||||||
private static final String WAITING_FOR_CONFIRMATION = "waiting_for_confirmation";
|
private static final String WAITING_FOR_CONFIRMATION = "waiting_for_confirmation";
|
||||||
public static final String MINIMUM_QUALITY_KEY = "minimum_quality";
|
public static final String HIDE_INSECURE_OPTIONS = "hide_insecure_options";
|
||||||
public static final String HIDE_DISABLED_PREFS = "hide_disabled_prefs";
|
|
||||||
public static final String TAG_FRP_WARNING_DIALOG = "frp_warning_dialog";
|
public static final String TAG_FRP_WARNING_DIALOG = "frp_warning_dialog";
|
||||||
public static final String KEY_LOCK_SETTINGS_FOOTER ="lock_settings_footer";
|
public static final String KEY_LOCK_SETTINGS_FOOTER ="lock_settings_footer";
|
||||||
|
|
||||||
@@ -277,21 +274,20 @@ public class ChooseLockGeneric extends SettingsActivity {
|
|||||||
arguments,
|
arguments,
|
||||||
intent.getExtras()).getIdentifier();
|
intent.getExtras()).getIdentifier();
|
||||||
mIsManagedProfile = UserManager.get(getActivity()).isManagedProfile(mUserId);
|
mIsManagedProfile = UserManager.get(getActivity()).isManagedProfile(mUserId);
|
||||||
mController = new ChooseLockGenericController(
|
mController = new ChooseLockGenericController.Builder(
|
||||||
getContext(), mUserId, mRequestedMinComplexity,
|
getContext(), mUserId, mLockPatternUtils)
|
||||||
mOnlyEnforceDevicePasswordRequirement,
|
.setAppRequestedMinComplexity(mRequestedMinComplexity)
|
||||||
mLockPatternUtils);
|
.setEnforceDevicePasswordRequirementOnly(mOnlyEnforceDevicePasswordRequirement)
|
||||||
|
.setProfileToUnify(mUnificationProfileId)
|
||||||
final int aggregatedComplexity = mController.getAggregatedPasswordComplexity();
|
.setHideInsecureScreenLockTypes(alwaysHideInsecureScreenLockTypes()
|
||||||
final boolean isComplexityProvidedByAdmin =
|
|| intent.getBooleanExtra(HIDE_INSECURE_OPTIONS, false))
|
||||||
aggregatedComplexity > mRequestedMinComplexity
|
.build();
|
||||||
&& aggregatedComplexity > PASSWORD_COMPLEXITY_NONE;
|
|
||||||
|
|
||||||
// If the complexity is provided by the admin, do not get the caller app's name.
|
// If the complexity is provided by the admin, do not get the caller app's name.
|
||||||
// If the app requires, for example, low complexity, and the admin requires high
|
// If the app requires, for example, low complexity, and the admin requires high
|
||||||
// complexity, it does not make sense to show a footer telling the user it's the app
|
// complexity, it does not make sense to show a footer telling the user it's the app
|
||||||
// requesting a particular complexity because the admin-set complexity will override it.
|
// requesting a particular complexity because the admin-set complexity will override it.
|
||||||
mCallerAppName = isComplexityProvidedByAdmin ? null :
|
mCallerAppName = mController.isComplexityProvidedByAdmin() ? null :
|
||||||
intent.getStringExtra(EXTRA_KEY_CALLER_APP_NAME);
|
intent.getStringExtra(EXTRA_KEY_CALLER_APP_NAME);
|
||||||
|
|
||||||
mManagedPasswordProvider = ManagedLockPasswordProvider.get(activity, mUserId);
|
mManagedPasswordProvider = ManagedLockPasswordProvider.get(activity, mUserId);
|
||||||
@@ -330,6 +326,10 @@ public class ChooseLockGeneric extends SettingsActivity {
|
|||||||
return super.onCreateView(inflater, container, savedInstanceState);
|
return super.onCreateView(inflater, container, savedInstanceState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected boolean alwaysHideInsecureScreenLockTypes() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private void updateActivityTitle() {
|
private void updateActivityTitle() {
|
||||||
if (mLockPatternUtils == null) {
|
if (mLockPatternUtils == null) {
|
||||||
// mLockPatternUtils will be uninitialized if ChooseLockGenericFragment.onCreate()
|
// mLockPatternUtils will be uninitialized if ChooseLockGenericFragment.onCreate()
|
||||||
@@ -606,16 +606,12 @@ public class ChooseLockGeneric extends SettingsActivity {
|
|||||||
}
|
}
|
||||||
if (quality == -1) {
|
if (quality == -1) {
|
||||||
// If caller didn't specify password quality, show UI and allow the user to choose.
|
// If caller didn't specify password quality, show UI and allow the user to choose.
|
||||||
quality = intent.getIntExtra(MINIMUM_QUALITY_KEY, -1);
|
|
||||||
quality = mController.upgradeQuality(quality);
|
|
||||||
final boolean hideDisabledPrefs = intent.getBooleanExtra(
|
|
||||||
HIDE_DISABLED_PREFS, false);
|
|
||||||
final PreferenceScreen prefScreen = getPreferenceScreen();
|
final PreferenceScreen prefScreen = getPreferenceScreen();
|
||||||
if (prefScreen != null) {
|
if (prefScreen != null) {
|
||||||
prefScreen.removeAll();
|
prefScreen.removeAll();
|
||||||
}
|
}
|
||||||
addPreferences();
|
addPreferences();
|
||||||
disableUnusablePreferences(quality, hideDisabledPrefs);
|
disableUnusablePreferences();
|
||||||
updatePreferenceText();
|
updatePreferenceText();
|
||||||
updateCurrentPreference();
|
updateCurrentPreference();
|
||||||
updatePreferenceSummaryIfNeeded();
|
updatePreferenceSummaryIfNeeded();
|
||||||
@@ -746,71 +742,23 @@ public class ChooseLockGeneric extends SettingsActivity {
|
|||||||
return lock != null ? lock.preferenceKey : null;
|
return lock != null ? lock.preferenceKey : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***
|
|
||||||
* Disables preferences that are less secure than required quality. The actual
|
|
||||||
* implementation is in disableUnusablePreferenceImpl.
|
|
||||||
*
|
|
||||||
* @param quality the requested quality.
|
|
||||||
* @param hideDisabledPrefs if false preferences show why they were disabled; otherwise
|
|
||||||
* they're not shown at all.
|
|
||||||
*/
|
|
||||||
protected void disableUnusablePreferences(final int quality, boolean hideDisabledPrefs) {
|
|
||||||
disableUnusablePreferencesImpl(quality, hideDisabledPrefs);
|
|
||||||
}
|
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* Disables preferences that are less secure than required quality.
|
* Disables preferences that are less secure than required quality.
|
||||||
*
|
*
|
||||||
* @param quality the requested quality.
|
|
||||||
* @param hideDisabled whether to hide disable screen lock options.
|
|
||||||
*/
|
*/
|
||||||
protected void disableUnusablePreferencesImpl(final int quality,
|
private void disableUnusablePreferences() {
|
||||||
boolean hideDisabled) {
|
|
||||||
final PreferenceScreen entries = getPreferenceScreen();
|
final PreferenceScreen entries = getPreferenceScreen();
|
||||||
|
|
||||||
int adminEnforcedQuality = LockPatternUtils.credentialTypeToPasswordQuality(
|
|
||||||
mLockPatternUtils.getRequestedPasswordMetrics(
|
|
||||||
mUserId, mOnlyEnforceDevicePasswordRequirement).credType);
|
|
||||||
EnforcedAdmin enforcedAdmin =
|
|
||||||
RestrictedLockUtilsInternal.checkIfPasswordQualityIsSet(getActivity(),
|
|
||||||
mUserId);
|
|
||||||
// If we are to unify a work challenge at the end of the credential enrollment, manually
|
|
||||||
// merge any password policy from that profile here, so we are enrolling a compliant
|
|
||||||
// password. This is because once unified, the profile's password policy will
|
|
||||||
// be enforced on the new credential.
|
|
||||||
if (mUnificationProfileId != UserHandle.USER_NULL) {
|
|
||||||
int profileEnforceQuality = mDpm.getPasswordQuality(null, mUnificationProfileId);
|
|
||||||
if (profileEnforceQuality > adminEnforcedQuality) {
|
|
||||||
adminEnforcedQuality = profileEnforceQuality;
|
|
||||||
enforcedAdmin = EnforcedAdmin.combine(enforcedAdmin,
|
|
||||||
RestrictedLockUtilsInternal.checkIfPasswordQualityIsSet(
|
|
||||||
getActivity(), mUnificationProfileId));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (ScreenLockType lock : ScreenLockType.values()) {
|
for (ScreenLockType lock : ScreenLockType.values()) {
|
||||||
String key = lock.preferenceKey;
|
String key = lock.preferenceKey;
|
||||||
Preference pref = findPreference(key);
|
Preference pref = findPreference(key);
|
||||||
if (pref instanceof RestrictedPreference) {
|
if (pref instanceof RestrictedPreference) {
|
||||||
boolean visible = mController.isScreenLockVisible(lock);
|
boolean visible = mController.isScreenLockVisible(lock);
|
||||||
boolean enabled = mController.isScreenLockEnabled(lock, quality);
|
boolean enabled = mController.isScreenLockEnabled(lock);
|
||||||
boolean disabledByAdmin =
|
|
||||||
mController.isScreenLockDisabledByAdmin(lock, adminEnforcedQuality);
|
|
||||||
if (hideDisabled) {
|
|
||||||
visible = visible && enabled;
|
|
||||||
}
|
|
||||||
if (!visible) {
|
if (!visible) {
|
||||||
entries.removePreference(pref);
|
entries.removePreference(pref);
|
||||||
} else if (disabledByAdmin && enforcedAdmin != null) {
|
|
||||||
((RestrictedPreference) pref).setDisabledByAdmin(enforcedAdmin);
|
|
||||||
} else if (!enabled) {
|
} else if (!enabled) {
|
||||||
// we need to setDisabledByAdmin to null first to disable the padlock
|
|
||||||
// in case it was set earlier.
|
|
||||||
((RestrictedPreference) pref).setDisabledByAdmin(null);
|
|
||||||
pref.setSummary(R.string.unlock_set_unlock_disabled_summary);
|
|
||||||
pref.setEnabled(false);
|
pref.setEnabled(false);
|
||||||
} else {
|
|
||||||
((RestrictedPreference) pref).setDisabledByAdmin(null);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -17,6 +17,7 @@
|
|||||||
package com.android.settings.password;
|
package com.android.settings.password;
|
||||||
|
|
||||||
import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_NONE;
|
import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_NONE;
|
||||||
|
import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
|
||||||
|
|
||||||
import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_NONE;
|
import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_NONE;
|
||||||
|
|
||||||
@@ -24,6 +25,7 @@ import android.app.admin.DevicePolicyManager.PasswordComplexity;
|
|||||||
import android.app.admin.PasswordMetrics;
|
import android.app.admin.PasswordMetrics;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
|
import android.os.UserManager;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.VisibleForTesting;
|
import androidx.annotation.VisibleForTesting;
|
||||||
@@ -36,84 +38,140 @@ import java.util.List;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* A controller for ChooseLockGeneric, and other similar classes which shows a list of possible
|
* A controller for ChooseLockGeneric, and other similar classes which shows a list of possible
|
||||||
* screen locks for the user to choose from.
|
* screen lock types for the user to choose from. This is the main place where different
|
||||||
|
* restrictions on allowed screen lock types are aggregated in Settings.
|
||||||
|
*
|
||||||
|
* Each screen lock type has two states: whether it is visible and whether it is enabled.
|
||||||
|
* Visibility is affected by things like resource configs, whether it's for a managed profile,
|
||||||
|
* or whether the caller allows it or not. This is determined by
|
||||||
|
* {@link #isScreenLockVisible(ScreenLockType)}. For visible screen lock types, they can be disabled
|
||||||
|
* by a combination of admin policies and request from the calling app, which is determined by
|
||||||
|
* {@link #isScreenLockEnabled(ScreenLockType}.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class ChooseLockGenericController {
|
public class ChooseLockGenericController {
|
||||||
|
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
private final int mUserId;
|
private final int mUserId;
|
||||||
@PasswordComplexity private final int mRequestedMinComplexity;
|
private final boolean mHideInsecureScreenLockTypes;
|
||||||
|
@PasswordComplexity private final int mAppRequestedMinComplexity;
|
||||||
private final boolean mDevicePasswordRequirementOnly;
|
private final boolean mDevicePasswordRequirementOnly;
|
||||||
private ManagedLockPasswordProvider mManagedPasswordProvider;
|
private final int mUnificationProfileId;
|
||||||
|
private final ManagedLockPasswordProvider mManagedPasswordProvider;
|
||||||
private final LockPatternUtils mLockPatternUtils;
|
private final LockPatternUtils mLockPatternUtils;
|
||||||
|
|
||||||
public ChooseLockGenericController(Context context, int userId) {
|
|
||||||
this(
|
|
||||||
context,
|
|
||||||
userId,
|
|
||||||
PASSWORD_COMPLEXITY_NONE,
|
|
||||||
/* mOnlyEnforceDevicePasswordRequirement */ false,
|
|
||||||
new LockPatternUtils(context));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param requestedMinComplexity specifies the min password complexity to be taken into account
|
|
||||||
* when determining the available screen lock types
|
|
||||||
*/
|
|
||||||
public ChooseLockGenericController(Context context, int userId,
|
public ChooseLockGenericController(Context context, int userId,
|
||||||
@PasswordComplexity int requestedMinComplexity,
|
ManagedLockPasswordProvider managedPasswordProvider, LockPatternUtils lockPatternUtils,
|
||||||
boolean devicePasswordRequirementOnly,
|
boolean hideInsecureScreenLockTypes, int appRequestedMinComplexity,
|
||||||
LockPatternUtils lockPatternUtils) {
|
boolean devicePasswordRequirementOnly, int unificationProfileId) {
|
||||||
this(
|
|
||||||
context,
|
|
||||||
userId,
|
|
||||||
requestedMinComplexity,
|
|
||||||
devicePasswordRequirementOnly,
|
|
||||||
ManagedLockPasswordProvider.get(context, userId),
|
|
||||||
lockPatternUtils);
|
|
||||||
}
|
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
ChooseLockGenericController(
|
|
||||||
Context context,
|
|
||||||
int userId,
|
|
||||||
@PasswordComplexity int requestedMinComplexity,
|
|
||||||
boolean devicePasswordRequirementOnly,
|
|
||||||
ManagedLockPasswordProvider managedLockPasswordProvider,
|
|
||||||
LockPatternUtils lockPatternUtils) {
|
|
||||||
mContext = context;
|
mContext = context;
|
||||||
mUserId = userId;
|
mUserId = userId;
|
||||||
mRequestedMinComplexity = requestedMinComplexity;
|
mManagedPasswordProvider = managedPasswordProvider;
|
||||||
mDevicePasswordRequirementOnly = devicePasswordRequirementOnly;
|
|
||||||
mManagedPasswordProvider = managedLockPasswordProvider;
|
|
||||||
mLockPatternUtils = lockPatternUtils;
|
mLockPatternUtils = lockPatternUtils;
|
||||||
|
mHideInsecureScreenLockTypes = hideInsecureScreenLockTypes;
|
||||||
|
mAppRequestedMinComplexity = appRequestedMinComplexity;
|
||||||
|
mDevicePasswordRequirementOnly = devicePasswordRequirementOnly;
|
||||||
|
mUnificationProfileId = unificationProfileId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Builder class for {@link ChooseLockGenericController} */
|
||||||
|
public static class Builder {
|
||||||
|
private final Context mContext;
|
||||||
|
private final int mUserId;
|
||||||
|
private final ManagedLockPasswordProvider mManagedPasswordProvider;
|
||||||
|
private final LockPatternUtils mLockPatternUtils;
|
||||||
|
|
||||||
|
private boolean mHideInsecureScreenLockTypes = false;
|
||||||
|
@PasswordComplexity private int mAppRequestedMinComplexity = PASSWORD_COMPLEXITY_NONE;
|
||||||
|
private boolean mDevicePasswordRequirementOnly = false;
|
||||||
|
private int mUnificationProfileId = UserHandle.USER_NULL;
|
||||||
|
|
||||||
|
public Builder(Context context, int userId) {
|
||||||
|
this(context, userId, new LockPatternUtils(context));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder(Context context, int userId,
|
||||||
|
LockPatternUtils lockPatternUtils) {
|
||||||
|
this(
|
||||||
|
context,
|
||||||
|
userId,
|
||||||
|
ManagedLockPasswordProvider.get(context, userId),
|
||||||
|
lockPatternUtils);
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
Builder(
|
||||||
|
Context context,
|
||||||
|
int userId,
|
||||||
|
ManagedLockPasswordProvider managedLockPasswordProvider,
|
||||||
|
LockPatternUtils lockPatternUtils) {
|
||||||
|
mContext = context;
|
||||||
|
mUserId = userId;
|
||||||
|
mManagedPasswordProvider = managedLockPasswordProvider;
|
||||||
|
mLockPatternUtils = lockPatternUtils;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Sets the password complexity requested by the calling app via
|
||||||
|
* {@link android.app.admin.DevicePolicyManager#EXTRA_PASSWORD_COMPLEXITY}.
|
||||||
|
*/
|
||||||
|
public Builder setAppRequestedMinComplexity(int complexity) {
|
||||||
|
mAppRequestedMinComplexity = complexity;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether the enrolment flow should discard any password policies originating from the
|
||||||
|
* work profile, even if the work profile currently has unified challenge. This can be
|
||||||
|
* requested by the calling app via
|
||||||
|
* {@link android.app.admin.DevicePolicyManager#EXTRA_DEVICE_PASSWORD_REQUIREMENT_ONLY}.
|
||||||
|
*/
|
||||||
|
public Builder setEnforceDevicePasswordRequirementOnly(boolean deviceOnly) {
|
||||||
|
mDevicePasswordRequirementOnly = deviceOnly;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the user ID of any profile whose work challenge should be unified at the end of this
|
||||||
|
* enrolment flow. This will lead to all password policies from that profile to be taken
|
||||||
|
* into consideration by this class, so that we are enrolling a compliant password. This is
|
||||||
|
* because once unified, the profile's password policy will be enforced on the new
|
||||||
|
* credential.
|
||||||
|
*/
|
||||||
|
public Builder setProfileToUnify(int profileId) {
|
||||||
|
mUnificationProfileId = profileId;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether insecure screen lock types (NONE and SWIPE) should be hidden in the UI.
|
||||||
|
*/
|
||||||
|
public Builder setHideInsecureScreenLockTypes(boolean hide) {
|
||||||
|
mHideInsecureScreenLockTypes = hide;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Creates {@link ChooseLockGenericController} instance. */
|
||||||
|
public ChooseLockGenericController build() {
|
||||||
|
return new ChooseLockGenericController(mContext, mUserId, mManagedPasswordProvider,
|
||||||
|
mLockPatternUtils, mHideInsecureScreenLockTypes, mAppRequestedMinComplexity,
|
||||||
|
mDevicePasswordRequirementOnly, mUnificationProfileId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the highest quality among the specified {@code quality}, the password requirement
|
* Returns whether the given screen lock type should be visible in the given context.
|
||||||
* set by device admins (legacy password quality metrics and password complexity), and the
|
|
||||||
* min password complexity requested by the calling app.
|
|
||||||
*/
|
|
||||||
public int upgradeQuality(int quality) {
|
|
||||||
// Compare specified quality and dpm quality
|
|
||||||
// TODO(b/142781408): convert from quality to credential type once PIN is supported.
|
|
||||||
int dpmUpgradedQuality = Math.max(quality, LockPatternUtils.credentialTypeToPasswordQuality(
|
|
||||||
getAggregatedPasswordMetrics().credType));
|
|
||||||
return Math.max(dpmUpgradedQuality,
|
|
||||||
PasswordMetrics.complexityLevelToMinQuality(getAggregatedPasswordComplexity()));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether the given screen lock type should be visible in the given context.
|
|
||||||
*/
|
*/
|
||||||
public boolean isScreenLockVisible(ScreenLockType type) {
|
public boolean isScreenLockVisible(ScreenLockType type) {
|
||||||
final boolean managedProfile = mUserId != UserHandle.myUserId();
|
final boolean managedProfile = mContext.getSystemService(UserManager.class)
|
||||||
|
.isManagedProfile(mUserId);
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case NONE:
|
case NONE:
|
||||||
return !mContext.getResources().getBoolean(R.bool.config_hide_none_security_option)
|
return !mHideInsecureScreenLockTypes
|
||||||
|
&& !mContext.getResources().getBoolean(R.bool.config_hide_none_security_option)
|
||||||
&& !managedProfile; // Profiles should use unified challenge instead.
|
&& !managedProfile; // Profiles should use unified challenge instead.
|
||||||
case SWIPE:
|
case SWIPE:
|
||||||
return !mContext.getResources().getBoolean(R.bool.config_hide_swipe_security_option)
|
return !mHideInsecureScreenLockTypes
|
||||||
|
&& !mContext.getResources().getBoolean(R.bool.config_hide_swipe_security_option)
|
||||||
&& !managedProfile; // Swipe doesn't make sense for profiles.
|
&& !managedProfile; // Swipe doesn't make sense for profiles.
|
||||||
case MANAGED:
|
case MANAGED:
|
||||||
return mManagedPasswordProvider.isManagedPasswordChoosable();
|
return mManagedPasswordProvider.isManagedPasswordChoosable();
|
||||||
@@ -128,29 +186,27 @@ public class ChooseLockGenericController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether screen lock with {@code type} should be enabled.
|
* Whether screen lock with {@code type} should be enabled assuming all relevant password
|
||||||
*
|
* requirements. The lock's visibility ({@link #isScreenLockVisible}) is not considered here.
|
||||||
* @param type The screen lock type.
|
|
||||||
* @param quality The minimum required quality. This can either be requirement by device policy
|
|
||||||
* manager or because some flow only makes sense with secure lock screens.
|
|
||||||
*/
|
*/
|
||||||
public boolean isScreenLockEnabled(ScreenLockType type, int quality) {
|
public boolean isScreenLockEnabled(ScreenLockType type) {
|
||||||
return type.maxQuality >= quality;
|
return type.maxQuality >= upgradeQuality(PASSWORD_QUALITY_UNSPECIFIED);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether screen lock with {@code type} is disabled by device policy admin.
|
* Increases the given quality to be as high as the combined quality from all relevant
|
||||||
*
|
* password requirements.
|
||||||
* @param type The screen lock type.
|
|
||||||
* @param adminEnforcedQuality The minimum quality that the admin enforces.
|
|
||||||
*/
|
*/
|
||||||
public boolean isScreenLockDisabledByAdmin(ScreenLockType type, int adminEnforcedQuality) {
|
// TODO(b/142781408): convert from quality to credential type once PIN is supported.
|
||||||
boolean disabledByAdmin = type.maxQuality < adminEnforcedQuality;
|
public int upgradeQuality(int quality) {
|
||||||
if (type == ScreenLockType.MANAGED) {
|
return Math.max(quality,
|
||||||
disabledByAdmin = disabledByAdmin
|
Math.max(
|
||||||
|| !mManagedPasswordProvider.isManagedPasswordChoosable();
|
LockPatternUtils.credentialTypeToPasswordQuality(
|
||||||
}
|
getAggregatedPasswordMetrics().credType),
|
||||||
return disabledByAdmin;
|
PasswordMetrics.complexityLevelToMinQuality(
|
||||||
|
getAggregatedPasswordComplexity())
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -175,43 +231,72 @@ public class ChooseLockGenericController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a list of screen locks that should be visible for the given quality. The returned list
|
* Gets a list of screen lock types that should be visible for the given quality. The returned
|
||||||
* is ordered in the natural order of the enum (the order those enums were defined).
|
* list is ordered in the natural order of the enum (the order those enums were defined). Screen
|
||||||
*
|
* locks disabled by password policy will not be returned.
|
||||||
* @param quality The minimum quality required in the context of the current flow. This should
|
|
||||||
* be one of the constants defined in
|
|
||||||
* {@code DevicePolicyManager#PASSWORD_QUALITY_*}.
|
|
||||||
* @param includeDisabled Whether to include screen locks disabled by {@code quality}
|
|
||||||
* requirements in the returned list.
|
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public List<ScreenLockType> getVisibleScreenLockTypes(int quality, boolean includeDisabled) {
|
public List<ScreenLockType> getVisibleAndEnabledScreenLockTypes() {
|
||||||
int upgradedQuality = upgradeQuality(quality);
|
|
||||||
List<ScreenLockType> locks = new ArrayList<>();
|
List<ScreenLockType> locks = new ArrayList<>();
|
||||||
// EnumSet's iterator guarantees the natural order of the enums
|
// EnumSet's iterator guarantees the natural order of the enums
|
||||||
for (ScreenLockType lock : ScreenLockType.values()) {
|
for (ScreenLockType lock : ScreenLockType.values()) {
|
||||||
if (isScreenLockVisible(lock)) {
|
if (isScreenLockVisible(lock) && isScreenLockEnabled(lock)) {
|
||||||
if (includeDisabled || isScreenLockEnabled(lock, upgradedQuality)) {
|
locks.add(lock);
|
||||||
locks.add(lock);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return locks;
|
return locks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the combined password metrics from all relevant policies which affects the current
|
||||||
|
* user. Normally password policies set on the current user's work profile instance will be
|
||||||
|
* taken into consideration here iff the work profile doesn't have its own work challenge.
|
||||||
|
* By setting {@link #mUnificationProfileId}, the work profile's password policy will always
|
||||||
|
* be combined here. Alternatively, by setting {@link #mDevicePasswordRequirementOnly}, its
|
||||||
|
* password policy will always be disregarded here.
|
||||||
|
*/
|
||||||
public PasswordMetrics getAggregatedPasswordMetrics() {
|
public PasswordMetrics getAggregatedPasswordMetrics() {
|
||||||
return mLockPatternUtils.getRequestedPasswordMetrics(mUserId,
|
PasswordMetrics metrics = mLockPatternUtils.getRequestedPasswordMetrics(mUserId,
|
||||||
mDevicePasswordRequirementOnly);
|
mDevicePasswordRequirementOnly);
|
||||||
|
if (mUnificationProfileId != UserHandle.USER_NULL) {
|
||||||
|
metrics.maxWith(mLockPatternUtils.getRequestedPasswordMetrics(mUnificationProfileId));
|
||||||
|
}
|
||||||
|
return metrics;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the combined password complexity from all relevant policies which affects the current
|
||||||
|
* user. The same logic of handling work profile password policies as
|
||||||
|
* {@link #getAggregatedPasswordMetrics} applies here.
|
||||||
|
*/
|
||||||
public int getAggregatedPasswordComplexity() {
|
public int getAggregatedPasswordComplexity() {
|
||||||
return Math.max(mRequestedMinComplexity,
|
int complexity = Math.max(mAppRequestedMinComplexity,
|
||||||
mLockPatternUtils.getRequestedPasswordComplexity(
|
mLockPatternUtils.getRequestedPasswordComplexity(
|
||||||
mUserId, mDevicePasswordRequirementOnly));
|
mUserId, mDevicePasswordRequirementOnly));
|
||||||
|
if (mUnificationProfileId != UserHandle.USER_NULL) {
|
||||||
|
complexity = Math.max(complexity,
|
||||||
|
mLockPatternUtils.getRequestedPasswordComplexity(mUnificationProfileId));
|
||||||
|
}
|
||||||
|
return complexity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether any screen lock type has been disabled only due to password policy
|
||||||
|
* from the admin. Will return {@code false} if the restriction is purely due to calling
|
||||||
|
* app's request.
|
||||||
|
*/
|
||||||
public boolean isScreenLockRestrictedByAdmin() {
|
public boolean isScreenLockRestrictedByAdmin() {
|
||||||
return getAggregatedPasswordMetrics().credType != CREDENTIAL_TYPE_NONE
|
return getAggregatedPasswordMetrics().credType != CREDENTIAL_TYPE_NONE
|
||||||
|| getAggregatedPasswordComplexity() != PASSWORD_COMPLEXITY_NONE;
|
|| isComplexityProvidedByAdmin();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the aggregated password complexity is non-zero and comes from
|
||||||
|
* admin policy.
|
||||||
|
*/
|
||||||
|
public boolean isComplexityProvidedByAdmin() {
|
||||||
|
final int aggregatedComplexity = getAggregatedPasswordComplexity();
|
||||||
|
return aggregatedComplexity > mAppRequestedMinComplexity
|
||||||
|
&& aggregatedComplexity > PASSWORD_COMPLEXITY_NONE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -416,19 +416,6 @@ public class ChooseLockPassword extends SettingsActivity {
|
|||||||
mMinComplexity = intent.getIntExtra(EXTRA_KEY_MIN_COMPLEXITY, PASSWORD_COMPLEXITY_NONE);
|
mMinComplexity = intent.getIntExtra(EXTRA_KEY_MIN_COMPLEXITY, PASSWORD_COMPLEXITY_NONE);
|
||||||
mMinMetrics = intent.getParcelableExtra(EXTRA_KEY_MIN_METRICS);
|
mMinMetrics = intent.getParcelableExtra(EXTRA_KEY_MIN_METRICS);
|
||||||
if (mMinMetrics == null) mMinMetrics = new PasswordMetrics(CREDENTIAL_TYPE_NONE);
|
if (mMinMetrics == null) mMinMetrics = new PasswordMetrics(CREDENTIAL_TYPE_NONE);
|
||||||
// If we are to unify a work challenge at the end of the credential enrollment, manually
|
|
||||||
// merge any password policy from that profile here, so we are enrolling a compliant
|
|
||||||
// password. This is because once unified, the profile's password policy will
|
|
||||||
// be enforced on the new credential.
|
|
||||||
//TODO: Move this logic to ChooseLockGeneric; let ChooseLockGeneric be the only place
|
|
||||||
//where password requirement mixing happens. ChooseLockPassword simply enforces what's
|
|
||||||
//set via IntentBuilder.setPasswordRequirement()
|
|
||||||
if (mUnificationProfileId != UserHandle.USER_NULL) {
|
|
||||||
mMinMetrics.maxWith(
|
|
||||||
mLockPatternUtils.getRequestedPasswordMetrics(mUnificationProfileId));
|
|
||||||
mMinComplexity = Math.max(mMinComplexity,
|
|
||||||
mLockPatternUtils.getRequestedPasswordComplexity(mUnificationProfileId));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (intent.getBooleanExtra(
|
if (intent.getBooleanExtra(
|
||||||
ChooseLockSettingsHelper.EXTRA_KEY_FOR_CHANGE_CRED_REQUIRED_FOR_BOOT, false)) {
|
ChooseLockSettingsHelper.EXTRA_KEY_FOR_CHANGE_CRED_REQUIRED_FOR_BOOT, false)) {
|
||||||
|
@@ -18,7 +18,6 @@ package com.android.settings.password;
|
|||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
||||||
import android.app.admin.DevicePolicyManager;
|
|
||||||
import android.app.settings.SettingsEnums;
|
import android.app.settings.SettingsEnums;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
@@ -100,7 +99,9 @@ public class ChooseLockTypeDialogFragment extends InstrumentedDialogFragment
|
|||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
final int userId = getArguments().getInt(ARG_USER_ID);
|
final int userId = getArguments().getInt(ARG_USER_ID);
|
||||||
mController = new ChooseLockGenericController(getContext(), userId);
|
mController = new ChooseLockGenericController.Builder(getContext(), userId)
|
||||||
|
.setHideInsecureScreenLockTypes(true)
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -124,10 +125,7 @@ public class ChooseLockTypeDialogFragment extends InstrumentedDialogFragment
|
|||||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||||
Context context = getContext();
|
Context context = getContext();
|
||||||
Builder builder = new Builder(context);
|
Builder builder = new Builder(context);
|
||||||
List<ScreenLockType> locks =
|
List<ScreenLockType> locks = mController.getVisibleAndEnabledScreenLockTypes();
|
||||||
mController.getVisibleScreenLockTypes(
|
|
||||||
DevicePolicyManager.PASSWORD_QUALITY_SOMETHING,
|
|
||||||
false /* includeDisabled */);
|
|
||||||
mAdapter = new ScreenLockAdapter(context, locks, mController);
|
mAdapter = new ScreenLockAdapter(context, locks, mController);
|
||||||
builder.setAdapter(mAdapter, this);
|
builder.setAdapter(mAdapter, this);
|
||||||
builder.setTitle(R.string.setup_lock_settings_options_dialog_title);
|
builder.setTitle(R.string.setup_lock_settings_options_dialog_title);
|
||||||
|
@@ -19,7 +19,6 @@ package com.android.settings.password;
|
|||||||
import static android.app.admin.DevicePolicyManager.ACTION_SET_NEW_PASSWORD;
|
import static android.app.admin.DevicePolicyManager.ACTION_SET_NEW_PASSWORD;
|
||||||
import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_FACE;
|
import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_FACE;
|
||||||
import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT;
|
import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT;
|
||||||
import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
|
|
||||||
|
|
||||||
import static com.android.internal.util.Preconditions.checkNotNull;
|
import static com.android.internal.util.Preconditions.checkNotNull;
|
||||||
|
|
||||||
@@ -145,10 +144,8 @@ final class SetNewPasswordController {
|
|||||||
|
|
||||||
private Bundle getBiometricChooseLockExtras() {
|
private Bundle getBiometricChooseLockExtras() {
|
||||||
Bundle chooseLockExtras = new Bundle();
|
Bundle chooseLockExtras = new Bundle();
|
||||||
chooseLockExtras.putInt(ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY,
|
|
||||||
PASSWORD_QUALITY_SOMETHING);
|
|
||||||
chooseLockExtras.putBoolean(
|
chooseLockExtras.putBoolean(
|
||||||
ChooseLockGeneric.ChooseLockGenericFragment.HIDE_DISABLED_PREFS, true);
|
ChooseLockGeneric.ChooseLockGenericFragment.HIDE_INSECURE_OPTIONS, true);
|
||||||
chooseLockExtras.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW_HANDLE, true);
|
chooseLockExtras.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW_HANDLE, true);
|
||||||
chooseLockExtras.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_FOR_BIOMETRICS, true);
|
chooseLockExtras.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_FOR_BIOMETRICS, true);
|
||||||
return chooseLockExtras;
|
return chooseLockExtras;
|
||||||
@@ -156,10 +153,8 @@ final class SetNewPasswordController {
|
|||||||
|
|
||||||
private Bundle getFingerprintChooseLockExtras() {
|
private Bundle getFingerprintChooseLockExtras() {
|
||||||
Bundle chooseLockExtras = new Bundle();
|
Bundle chooseLockExtras = new Bundle();
|
||||||
chooseLockExtras.putInt(ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY,
|
|
||||||
PASSWORD_QUALITY_SOMETHING);
|
|
||||||
chooseLockExtras.putBoolean(
|
chooseLockExtras.putBoolean(
|
||||||
ChooseLockGeneric.ChooseLockGenericFragment.HIDE_DISABLED_PREFS, true);
|
ChooseLockGeneric.ChooseLockGenericFragment.HIDE_INSECURE_OPTIONS, true);
|
||||||
chooseLockExtras.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW_HANDLE, true);
|
chooseLockExtras.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW_HANDLE, true);
|
||||||
chooseLockExtras.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, true);
|
chooseLockExtras.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, true);
|
||||||
return chooseLockExtras;
|
return chooseLockExtras;
|
||||||
@@ -167,10 +162,8 @@ final class SetNewPasswordController {
|
|||||||
|
|
||||||
private Bundle getFaceChooseLockExtras() {
|
private Bundle getFaceChooseLockExtras() {
|
||||||
Bundle chooseLockExtras = new Bundle();
|
Bundle chooseLockExtras = new Bundle();
|
||||||
chooseLockExtras.putInt(ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY,
|
|
||||||
PASSWORD_QUALITY_SOMETHING);
|
|
||||||
chooseLockExtras.putBoolean(
|
chooseLockExtras.putBoolean(
|
||||||
ChooseLockGeneric.ChooseLockGenericFragment.HIDE_DISABLED_PREFS, true);
|
ChooseLockGeneric.ChooseLockGenericFragment.HIDE_INSECURE_OPTIONS, true);
|
||||||
chooseLockExtras.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW_HANDLE, true);
|
chooseLockExtras.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW_HANDLE, true);
|
||||||
chooseLockExtras.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FACE, true);
|
chooseLockExtras.putBoolean(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FACE, true);
|
||||||
return chooseLockExtras;
|
return chooseLockExtras;
|
||||||
|
@@ -21,7 +21,6 @@ import static android.app.admin.DevicePolicyManager.EXTRA_PASSWORD_COMPLEXITY;
|
|||||||
|
|
||||||
import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_REQUESTED_MIN_COMPLEXITY;
|
import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_REQUESTED_MIN_COMPLEXITY;
|
||||||
|
|
||||||
import android.app.admin.DevicePolicyManager;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
@@ -160,22 +159,12 @@ public class SetupChooseLockGeneric extends ChooseLockGeneric {
|
|||||||
return SetupChooseLockGeneric.InternalActivity.class;
|
return SetupChooseLockGeneric.InternalActivity.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***
|
|
||||||
* Disables preferences that are less secure than required quality and shows only secure
|
|
||||||
* screen lock options here.
|
|
||||||
*
|
|
||||||
* @param quality the requested quality.
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
protected void disableUnusablePreferences(final int quality, boolean hideDisabled) {
|
protected boolean alwaysHideInsecureScreenLockTypes() {
|
||||||
// At this part of the flow, the user has already indicated they want to add a pin,
|
// At this part of the flow, the user has already indicated they want to add a pin,
|
||||||
// pattern or password, so don't show "None" or "Slide". We disable them here and set
|
// pattern or password, so don't show "None" or "Slide". We disable them here.
|
||||||
// the HIDE_DISABLED flag to true to hide them. This only happens for setup wizard.
|
// This only happens for setup wizard.
|
||||||
// We do the following max check here since the device may already have a Device Admin
|
return true;
|
||||||
// installed with a policy we need to honor.
|
|
||||||
final int newQuality = Math.max(quality,
|
|
||||||
DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
|
|
||||||
super.disableUnusablePreferencesImpl(newQuality, true /* hideDisabled */);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@@ -17,7 +17,6 @@
|
|||||||
package com.android.settings.password;
|
package com.android.settings.password;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.admin.DevicePolicyManager;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
@@ -81,9 +80,11 @@ public class SetupChooseLockPassword extends ChooseLockPassword {
|
|||||||
super.onViewCreated(view, savedInstanceState);
|
super.onViewCreated(view, savedInstanceState);
|
||||||
final Activity activity = getActivity();
|
final Activity activity = getActivity();
|
||||||
ChooseLockGenericController chooseLockGenericController =
|
ChooseLockGenericController chooseLockGenericController =
|
||||||
new ChooseLockGenericController(activity, mUserId);
|
new ChooseLockGenericController.Builder(activity, mUserId)
|
||||||
boolean anyOptionsShown = chooseLockGenericController.getVisibleScreenLockTypes(
|
.setHideInsecureScreenLockTypes(true)
|
||||||
DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, false).size() > 0;
|
.build();
|
||||||
|
boolean anyOptionsShown = chooseLockGenericController
|
||||||
|
.getVisibleAndEnabledScreenLockTypes().size() > 0;
|
||||||
boolean showOptionsButton = activity.getIntent().getBooleanExtra(
|
boolean showOptionsButton = activity.getIntent().getBooleanExtra(
|
||||||
ChooseLockGeneric.ChooseLockGenericFragment.EXTRA_SHOW_OPTIONS_BUTTON, false);
|
ChooseLockGeneric.ChooseLockGenericFragment.EXTRA_SHOW_OPTIONS_BUTTON, false);
|
||||||
if (!anyOptionsShown) {
|
if (!anyOptionsShown) {
|
||||||
|
@@ -136,8 +136,8 @@ public class ScreenPinningSettings extends SettingsPreferenceFragment
|
|||||||
if (passwordQuality == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
|
if (passwordQuality == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
|
||||||
Intent chooseLockIntent = new Intent(DevicePolicyManager.ACTION_SET_NEW_PASSWORD);
|
Intent chooseLockIntent = new Intent(DevicePolicyManager.ACTION_SET_NEW_PASSWORD);
|
||||||
chooseLockIntent.putExtra(
|
chooseLockIntent.putExtra(
|
||||||
ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY,
|
ChooseLockGeneric.ChooseLockGenericFragment.HIDE_INSECURE_OPTIONS,
|
||||||
DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
|
true);
|
||||||
startActivityForResult(chooseLockIntent, CHANGE_LOCK_METHOD_REQUEST);
|
startActivityForResult(chooseLockIntent, CHANGE_LOCK_METHOD_REQUEST);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@@ -432,8 +432,8 @@ public class UserSettings extends SettingsPreferenceFragment
|
|||||||
|
|
||||||
private void launchChooseLockscreen() {
|
private void launchChooseLockscreen() {
|
||||||
Intent chooseLockIntent = new Intent(DevicePolicyManager.ACTION_SET_NEW_PASSWORD);
|
Intent chooseLockIntent = new Intent(DevicePolicyManager.ACTION_SET_NEW_PASSWORD);
|
||||||
chooseLockIntent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY,
|
chooseLockIntent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.HIDE_INSECURE_OPTIONS,
|
||||||
DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
|
true);
|
||||||
startActivityForResult(chooseLockIntent, REQUEST_CHOOSE_LOCK);
|
startActivityForResult(chooseLockIntent, REQUEST_CHOOSE_LOCK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -20,23 +20,31 @@ import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_HIGH;
|
|||||||
import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_LOW;
|
import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_LOW;
|
||||||
import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_MEDIUM;
|
import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_MEDIUM;
|
||||||
import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_NONE;
|
import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_NONE;
|
||||||
|
import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC;
|
||||||
|
import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
|
||||||
|
import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
|
||||||
|
import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX;
|
||||||
|
import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
|
||||||
|
import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
import static com.google.common.truth.Truth.assertWithMessage;
|
import static com.google.common.truth.Truth.assertWithMessage;
|
||||||
|
|
||||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||||
import static org.mockito.ArgumentMatchers.anyInt;
|
import static org.mockito.ArgumentMatchers.anyInt;
|
||||||
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
import static org.mockito.Mockito.doReturn;
|
import static org.mockito.Mockito.doReturn;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
import static org.robolectric.RuntimeEnvironment.application;
|
import static org.robolectric.RuntimeEnvironment.application;
|
||||||
|
|
||||||
import android.app.admin.DevicePolicyManager;
|
import android.app.admin.DevicePolicyManager;
|
||||||
import android.app.admin.DevicePolicyManager.PasswordComplexity;
|
|
||||||
import android.app.admin.PasswordPolicy;
|
import android.app.admin.PasswordPolicy;
|
||||||
|
import android.os.UserHandle;
|
||||||
|
|
||||||
import com.android.internal.widget.LockPatternUtils;
|
import com.android.internal.widget.LockPatternUtils;
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
import com.android.settings.testutils.shadow.SettingsShadowResources;
|
import com.android.settings.testutils.shadow.SettingsShadowResources;
|
||||||
|
import com.android.settings.testutils.shadow.ShadowUserManager;
|
||||||
|
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
@@ -48,10 +56,11 @@ import org.robolectric.RobolectricTestRunner;
|
|||||||
import org.robolectric.annotation.Config;
|
import org.robolectric.annotation.Config;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
@RunWith(RobolectricTestRunner.class)
|
@RunWith(RobolectricTestRunner.class)
|
||||||
@Config(shadows = SettingsShadowResources.class)
|
@Config(shadows = {ShadowUserManager.class, SettingsShadowResources.class})
|
||||||
public class ChooseLockGenericControllerTest {
|
public class ChooseLockGenericControllerTest {
|
||||||
|
|
||||||
private ChooseLockGenericController mController;
|
private ChooseLockGenericController mController;
|
||||||
@@ -68,7 +77,7 @@ public class ChooseLockGenericControllerTest {
|
|||||||
|
|
||||||
when(mLockPatternUtils.hasSecureLockScreen()).thenReturn(true);
|
when(mLockPatternUtils.hasSecureLockScreen()).thenReturn(true);
|
||||||
setDevicePolicyPasswordQuality(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED);
|
setDevicePolicyPasswordQuality(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED);
|
||||||
mController = createController(PASSWORD_COMPLEXITY_NONE);
|
mController = createBuilder().build();
|
||||||
SettingsShadowResources.overrideResource(R.bool.config_hide_none_security_option, false);
|
SettingsShadowResources.overrideResource(R.bool.config_hide_none_security_option, false);
|
||||||
SettingsShadowResources.overrideResource(R.bool.config_hide_swipe_security_option, false);
|
SettingsShadowResources.overrideResource(R.bool.config_hide_swipe_security_option, false);
|
||||||
}
|
}
|
||||||
@@ -95,8 +104,8 @@ public class ChooseLockGenericControllerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void isScreenLockVisible_notCurrentUser_shouldHideInsecure() {
|
public void isScreenLockVisible_ManagedProfile_shouldHideInsecure() {
|
||||||
mController = new ChooseLockGenericController(application, 1 /* userId */);
|
ShadowUserManager.getShadow().setManagedProfiles(Set.of(0));
|
||||||
assertWithMessage("SWIPE visible").that(
|
assertWithMessage("SWIPE visible").that(
|
||||||
mController.isScreenLockVisible(ScreenLockType.SWIPE)).isFalse();
|
mController.isScreenLockVisible(ScreenLockType.SWIPE)).isFalse();
|
||||||
assertWithMessage("NONE visible").that(mController.isScreenLockVisible(ScreenLockType.NONE))
|
assertWithMessage("NONE visible").that(mController.isScreenLockVisible(ScreenLockType.NONE))
|
||||||
@@ -112,62 +121,116 @@ public class ChooseLockGenericControllerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void isScreenLockEnabled_lowerQuality_shouldReturnFalse() {
|
public void isScreenLockEnabled_Default() {
|
||||||
for (ScreenLockType lock : ScreenLockType.values()) {
|
assertThat(mController.isScreenLockEnabled(ScreenLockType.NONE)).isTrue();
|
||||||
assertWithMessage(lock + " enabled").that(
|
assertThat(mController.isScreenLockEnabled(ScreenLockType.SWIPE)).isTrue();
|
||||||
mController.isScreenLockEnabled(lock, lock.maxQuality + 1)).isFalse();
|
assertThat(mController.isScreenLockEnabled(ScreenLockType.PATTERN)).isTrue();
|
||||||
}
|
assertThat(mController.isScreenLockEnabled(ScreenLockType.PIN)).isTrue();
|
||||||
|
assertThat(mController.isScreenLockEnabled(ScreenLockType.PASSWORD)).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void isScreenLockEnabled_equalQuality_shouldReturnTrue() {
|
public void isScreenLockEnabled_QualityUnspecified() {
|
||||||
for (ScreenLockType lock : ScreenLockType.values()) {
|
setDevicePolicyPasswordQuality(PASSWORD_QUALITY_UNSPECIFIED);
|
||||||
assertWithMessage(lock + " enabled").that(
|
assertThat(mController.isScreenLockEnabled(ScreenLockType.NONE)).isTrue();
|
||||||
mController.isScreenLockEnabled(lock, lock.defaultQuality)).isTrue();
|
assertThat(mController.isScreenLockEnabled(ScreenLockType.SWIPE)).isTrue();
|
||||||
}
|
assertThat(mController.isScreenLockEnabled(ScreenLockType.PATTERN)).isTrue();
|
||||||
|
assertThat(mController.isScreenLockEnabled(ScreenLockType.PIN)).isTrue();
|
||||||
|
assertThat(mController.isScreenLockEnabled(ScreenLockType.PASSWORD)).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void isScreenLockEnabled_higherQuality_shouldReturnTrue() {
|
public void isScreenLockEnabled_QualitySomething() {
|
||||||
for (ScreenLockType lock : ScreenLockType.values()) {
|
setDevicePolicyPasswordQuality(PASSWORD_QUALITY_SOMETHING);
|
||||||
assertWithMessage(lock + " enabled").that(
|
assertThat(mController.isScreenLockEnabled(ScreenLockType.NONE)).isFalse();
|
||||||
mController.isScreenLockEnabled(lock, lock.maxQuality - 1)).isTrue();
|
assertThat(mController.isScreenLockEnabled(ScreenLockType.SWIPE)).isFalse();
|
||||||
}
|
assertThat(mController.isScreenLockEnabled(ScreenLockType.PATTERN)).isTrue();
|
||||||
|
assertThat(mController.isScreenLockEnabled(ScreenLockType.PIN)).isTrue();
|
||||||
|
assertThat(mController.isScreenLockEnabled(ScreenLockType.PASSWORD)).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void isScreenLockDisabledByAdmin_lowerQuality_shouldReturnTrue() {
|
public void isScreenLockEnabled_QualityNumeric() {
|
||||||
doReturn(true).when(mManagedLockPasswordProvider).isManagedPasswordChoosable();
|
setDevicePolicyPasswordQuality(PASSWORD_QUALITY_NUMERIC);
|
||||||
for (ScreenLockType lock : ScreenLockType.values()) {
|
assertThat(mController.isScreenLockEnabled(ScreenLockType.NONE)).isFalse();
|
||||||
assertWithMessage(lock + " disabledByAdmin").that(
|
assertThat(mController.isScreenLockEnabled(ScreenLockType.SWIPE)).isFalse();
|
||||||
mController.isScreenLockDisabledByAdmin(lock, lock.maxQuality + 1)).isTrue();
|
assertThat(mController.isScreenLockEnabled(ScreenLockType.PATTERN)).isFalse();
|
||||||
}
|
assertThat(mController.isScreenLockEnabled(ScreenLockType.PIN)).isTrue();
|
||||||
|
assertThat(mController.isScreenLockEnabled(ScreenLockType.PASSWORD)).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void isScreenLockDisabledByAdmin_equalQuality_shouldReturnFalse() {
|
public void isScreenLockEnabled_QualityNumericComplex() {
|
||||||
doReturn(true).when(mManagedLockPasswordProvider).isManagedPasswordChoosable();
|
setDevicePolicyPasswordQuality(PASSWORD_QUALITY_NUMERIC_COMPLEX);
|
||||||
for (ScreenLockType lock : ScreenLockType.values()) {
|
assertThat(mController.isScreenLockEnabled(ScreenLockType.NONE)).isFalse();
|
||||||
assertWithMessage(lock + " disabledByAdmin").that(
|
assertThat(mController.isScreenLockEnabled(ScreenLockType.SWIPE)).isFalse();
|
||||||
mController.isScreenLockDisabledByAdmin(lock, lock.maxQuality)).isFalse();
|
assertThat(mController.isScreenLockEnabled(ScreenLockType.PATTERN)).isFalse();
|
||||||
}
|
assertThat(mController.isScreenLockEnabled(ScreenLockType.PIN)).isTrue();
|
||||||
|
assertThat(mController.isScreenLockEnabled(ScreenLockType.PASSWORD)).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void isScreenLockDisabledByAdmin_higherQuality_shouldReturnFalse() {
|
public void isScreenLockEnabled_QualityAlphabetic() {
|
||||||
doReturn(true).when(mManagedLockPasswordProvider).isManagedPasswordChoosable();
|
setDevicePolicyPasswordQuality(PASSWORD_QUALITY_ALPHABETIC);
|
||||||
for (ScreenLockType lock : ScreenLockType.values()) {
|
assertThat(mController.isScreenLockEnabled(ScreenLockType.NONE)).isFalse();
|
||||||
assertWithMessage(lock + " disabledByAdmin").that(
|
assertThat(mController.isScreenLockEnabled(ScreenLockType.SWIPE)).isFalse();
|
||||||
mController.isScreenLockDisabledByAdmin(lock, lock.maxQuality - 1)).isFalse();
|
assertThat(mController.isScreenLockEnabled(ScreenLockType.PATTERN)).isFalse();
|
||||||
}
|
assertThat(mController.isScreenLockEnabled(ScreenLockType.PIN)).isFalse();
|
||||||
|
assertThat(mController.isScreenLockEnabled(ScreenLockType.PASSWORD)).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void isScreenLockDisabledByAdmin_managedNotChoosable_shouldReturnTrue() {
|
public void isScreenLockEnabled_QualityComplex() {
|
||||||
doReturn(false).when(mManagedLockPasswordProvider).isManagedPasswordChoosable();
|
setDevicePolicyPasswordQuality(PASSWORD_QUALITY_COMPLEX);
|
||||||
assertWithMessage("MANANGED disabledByAdmin").that(mController.isScreenLockDisabledByAdmin(
|
assertThat(mController.isScreenLockEnabled(ScreenLockType.NONE)).isFalse();
|
||||||
ScreenLockType.MANAGED, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED))
|
assertThat(mController.isScreenLockEnabled(ScreenLockType.SWIPE)).isFalse();
|
||||||
.isTrue();
|
assertThat(mController.isScreenLockEnabled(ScreenLockType.PATTERN)).isFalse();
|
||||||
|
assertThat(mController.isScreenLockEnabled(ScreenLockType.PIN)).isFalse();
|
||||||
|
assertThat(mController.isScreenLockEnabled(ScreenLockType.PASSWORD)).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void isScreenLockEnabled_NoneComplexity() {
|
||||||
|
when(mLockPatternUtils.getRequestedPasswordComplexity(anyInt(), anyBoolean()))
|
||||||
|
.thenReturn(PASSWORD_COMPLEXITY_NONE);
|
||||||
|
assertThat(mController.isScreenLockEnabled(ScreenLockType.NONE)).isTrue();
|
||||||
|
assertThat(mController.isScreenLockEnabled(ScreenLockType.SWIPE)).isTrue();
|
||||||
|
assertThat(mController.isScreenLockEnabled(ScreenLockType.PATTERN)).isTrue();
|
||||||
|
assertThat(mController.isScreenLockEnabled(ScreenLockType.PIN)).isTrue();
|
||||||
|
assertThat(mController.isScreenLockEnabled(ScreenLockType.PASSWORD)).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void isScreenLockEnabled_lowComplexity() {
|
||||||
|
when(mLockPatternUtils.getRequestedPasswordComplexity(anyInt(), anyBoolean()))
|
||||||
|
.thenReturn(PASSWORD_COMPLEXITY_LOW);
|
||||||
|
assertThat(mController.isScreenLockEnabled(ScreenLockType.NONE)).isFalse();
|
||||||
|
assertThat(mController.isScreenLockEnabled(ScreenLockType.SWIPE)).isFalse();
|
||||||
|
assertThat(mController.isScreenLockEnabled(ScreenLockType.PATTERN)).isTrue();
|
||||||
|
assertThat(mController.isScreenLockEnabled(ScreenLockType.PIN)).isTrue();
|
||||||
|
assertThat(mController.isScreenLockEnabled(ScreenLockType.PASSWORD)).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void isScreenLockEnabled_mediumComplexity() {
|
||||||
|
when(mLockPatternUtils.getRequestedPasswordComplexity(anyInt(), anyBoolean()))
|
||||||
|
.thenReturn(PASSWORD_COMPLEXITY_MEDIUM);
|
||||||
|
assertThat(mController.isScreenLockEnabled(ScreenLockType.NONE)).isFalse();
|
||||||
|
assertThat(mController.isScreenLockEnabled(ScreenLockType.SWIPE)).isFalse();
|
||||||
|
assertThat(mController.isScreenLockEnabled(ScreenLockType.PATTERN)).isFalse();
|
||||||
|
assertThat(mController.isScreenLockEnabled(ScreenLockType.PIN)).isTrue();
|
||||||
|
assertThat(mController.isScreenLockEnabled(ScreenLockType.PASSWORD)).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void isScreenLockEnabled_highComplexity() {
|
||||||
|
when(mLockPatternUtils.getRequestedPasswordComplexity(anyInt(), anyBoolean()))
|
||||||
|
.thenReturn(PASSWORD_COMPLEXITY_HIGH);
|
||||||
|
assertThat(mController.isScreenLockEnabled(ScreenLockType.NONE)).isFalse();
|
||||||
|
assertThat(mController.isScreenLockEnabled(ScreenLockType.SWIPE)).isFalse();
|
||||||
|
assertThat(mController.isScreenLockEnabled(ScreenLockType.PATTERN)).isFalse();
|
||||||
|
assertThat(mController.isScreenLockEnabled(ScreenLockType.PIN)).isTrue();
|
||||||
|
assertThat(mController.isScreenLockEnabled(ScreenLockType.PASSWORD)).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -181,8 +244,8 @@ public class ChooseLockGenericControllerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getVisibleScreenLockTypes_qualitySomething_shouldReturnPatterPinPassword() {
|
public void getVisibleScreenLockTypes_qualitySomething_shouldReturnPatterPinPassword() {
|
||||||
assertThat(mController.getVisibleScreenLockTypes(
|
mController = createBuilder().setHideInsecureScreenLockTypes(true).build();
|
||||||
DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, false))
|
assertThat(mController.getVisibleAndEnabledScreenLockTypes())
|
||||||
.isEqualTo(Arrays.asList(
|
.isEqualTo(Arrays.asList(
|
||||||
ScreenLockType.PATTERN,
|
ScreenLockType.PATTERN,
|
||||||
ScreenLockType.PIN,
|
ScreenLockType.PIN,
|
||||||
@@ -191,8 +254,7 @@ public class ChooseLockGenericControllerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getVisibleScreenLockTypes_showDisabled_shouldReturnAllButManaged() {
|
public void getVisibleScreenLockTypes_showDisabled_shouldReturnAllButManaged() {
|
||||||
assertThat(mController.getVisibleScreenLockTypes(
|
assertThat(mController.getVisibleAndEnabledScreenLockTypes())
|
||||||
DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, true))
|
|
||||||
.isEqualTo(Arrays.asList(
|
.isEqualTo(Arrays.asList(
|
||||||
ScreenLockType.NONE,
|
ScreenLockType.NONE,
|
||||||
ScreenLockType.SWIPE,
|
ScreenLockType.SWIPE,
|
||||||
@@ -223,31 +285,68 @@ public class ChooseLockGenericControllerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void upgradeQuality_complexityHigh_minQualityNumericComplex() {
|
public void upgradeQuality_complexityHigh_minQualityNumericComplex() {
|
||||||
|
mController = createBuilder().setAppRequestedMinComplexity(PASSWORD_COMPLEXITY_HIGH)
|
||||||
|
.build();
|
||||||
setDevicePolicyPasswordQuality(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED);
|
setDevicePolicyPasswordQuality(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED);
|
||||||
ChooseLockGenericController controller = createController(PASSWORD_COMPLEXITY_HIGH);
|
|
||||||
|
|
||||||
assertThat(controller.upgradeQuality(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED))
|
assertThat(mController.upgradeQuality(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED))
|
||||||
.isEqualTo(DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX);
|
.isEqualTo(DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void upgradeQuality_complexityMedium_minQualityNumericComplex() {
|
public void upgradeQuality_complexityMedium_minQualityNumericComplex() {
|
||||||
|
mController = createBuilder().setAppRequestedMinComplexity(PASSWORD_COMPLEXITY_MEDIUM)
|
||||||
|
.build();
|
||||||
setDevicePolicyPasswordQuality(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED);
|
setDevicePolicyPasswordQuality(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED);
|
||||||
ChooseLockGenericController controller = createController(PASSWORD_COMPLEXITY_MEDIUM);
|
|
||||||
|
|
||||||
assertThat(controller.upgradeQuality(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED))
|
assertThat(mController.upgradeQuality(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED))
|
||||||
.isEqualTo(DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX);
|
.isEqualTo(DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void upgradeQuality_complexityLow_minQualitySomething() {
|
public void upgradeQuality_complexityLow_minQualitySomething() {
|
||||||
|
mController = createBuilder().setAppRequestedMinComplexity(PASSWORD_COMPLEXITY_LOW)
|
||||||
|
.build();
|
||||||
setDevicePolicyPasswordQuality(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED);
|
setDevicePolicyPasswordQuality(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED);
|
||||||
ChooseLockGenericController controller = createController(PASSWORD_COMPLEXITY_LOW);
|
|
||||||
|
|
||||||
assertThat(controller.upgradeQuality(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED))
|
assertThat(mController.upgradeQuality(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED))
|
||||||
.isEqualTo(DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
|
.isEqualTo(DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getAggregatedPasswordComplexity_AppRequest() {
|
||||||
|
mController = createBuilder().setAppRequestedMinComplexity(PASSWORD_COMPLEXITY_HIGH)
|
||||||
|
.build();
|
||||||
|
assertThat(mController.getAggregatedPasswordComplexity())
|
||||||
|
.isEqualTo(PASSWORD_COMPLEXITY_HIGH);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getAggregatedPasswordComplexity_DevicePolicy() {
|
||||||
|
mController = createBuilder().setAppRequestedMinComplexity(PASSWORD_COMPLEXITY_LOW)
|
||||||
|
.build();
|
||||||
|
when(mLockPatternUtils.getRequestedPasswordComplexity(eq(UserHandle.myUserId()), eq(false)))
|
||||||
|
.thenReturn(PASSWORD_COMPLEXITY_MEDIUM);
|
||||||
|
|
||||||
|
assertThat(mController.getAggregatedPasswordComplexity())
|
||||||
|
.isEqualTo(PASSWORD_COMPLEXITY_MEDIUM);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getAggregatedPasswordComplexity_ProfileUnification() {
|
||||||
|
mController = createBuilder()
|
||||||
|
.setProfileToUnify(123)
|
||||||
|
.setAppRequestedMinComplexity(PASSWORD_COMPLEXITY_LOW)
|
||||||
|
.build();
|
||||||
|
when(mLockPatternUtils.getRequestedPasswordComplexity(eq(UserHandle.myUserId()), eq(false)))
|
||||||
|
.thenReturn(PASSWORD_COMPLEXITY_MEDIUM);
|
||||||
|
when(mLockPatternUtils.getRequestedPasswordComplexity(eq(123)))
|
||||||
|
.thenReturn(PASSWORD_COMPLEXITY_HIGH);
|
||||||
|
|
||||||
|
assertThat(mController.getAggregatedPasswordComplexity())
|
||||||
|
.isEqualTo(PASSWORD_COMPLEXITY_HIGH);
|
||||||
|
}
|
||||||
|
|
||||||
private void setDevicePolicyPasswordQuality(int quality) {
|
private void setDevicePolicyPasswordQuality(int quality) {
|
||||||
PasswordPolicy policy = new PasswordPolicy();
|
PasswordPolicy policy = new PasswordPolicy();
|
||||||
policy.quality = quality;
|
policy.quality = quality;
|
||||||
@@ -256,13 +355,10 @@ public class ChooseLockGenericControllerTest {
|
|||||||
.thenReturn(policy.getMinMetrics());
|
.thenReturn(policy.getMinMetrics());
|
||||||
}
|
}
|
||||||
|
|
||||||
private ChooseLockGenericController createController(
|
private ChooseLockGenericController.Builder createBuilder() {
|
||||||
@PasswordComplexity int minPasswordComplexity) {
|
return new ChooseLockGenericController.Builder(
|
||||||
return new ChooseLockGenericController(
|
|
||||||
application,
|
application,
|
||||||
0 /* userId */,
|
0 /* userId */,
|
||||||
minPasswordComplexity,
|
|
||||||
false,
|
|
||||||
mManagedLockPasswordProvider,
|
mManagedLockPasswordProvider,
|
||||||
mLockPatternUtils);
|
mLockPatternUtils);
|
||||||
}
|
}
|
||||||
|
@@ -30,7 +30,6 @@ import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED
|
|||||||
|
|
||||||
import static com.android.internal.widget.LockPatternUtils.PASSWORD_TYPE_KEY;
|
import static com.android.internal.widget.LockPatternUtils.PASSWORD_TYPE_KEY;
|
||||||
import static com.android.settings.password.ChooseLockGeneric.CONFIRM_CREDENTIALS;
|
import static com.android.settings.password.ChooseLockGeneric.CONFIRM_CREDENTIALS;
|
||||||
import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_UNIFICATION_PROFILE_ID;
|
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
import static com.google.common.truth.Truth.assertWithMessage;
|
import static com.google.common.truth.Truth.assertWithMessage;
|
||||||
@@ -429,18 +428,6 @@ public class ChooseLockPasswordTest {
|
|||||||
"PIN must be at least 8 digits");
|
"PIN must be at least 8 digits");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void validateComplexityMergedFromUnificationUserOnCreate() {
|
|
||||||
ShadowLockPatternUtils.setRequiredPasswordComplexity(PASSWORD_COMPLEXITY_LOW);
|
|
||||||
ShadowLockPatternUtils.setRequiredPasswordComplexity(123, PASSWORD_COMPLEXITY_HIGH);
|
|
||||||
|
|
||||||
Intent intent = createIntentForPasswordValidation(null, PASSWORD_COMPLEXITY_NONE,
|
|
||||||
PASSWORD_QUALITY_NUMERIC);
|
|
||||||
intent.putExtra(EXTRA_KEY_UNIFICATION_PROFILE_ID, 123);
|
|
||||||
assertPasswordValidationResultForIntent(LockscreenCredential.createNone(), intent,
|
|
||||||
"PIN must be at least 8 digits");
|
|
||||||
}
|
|
||||||
|
|
||||||
private ChooseLockPassword buildChooseLockPasswordActivity(Intent intent) {
|
private ChooseLockPassword buildChooseLockPasswordActivity(Intent intent) {
|
||||||
return Robolectric.buildActivity(ChooseLockPassword.class, intent).setup().get();
|
return Robolectric.buildActivity(ChooseLockPassword.class, intent).setup().get();
|
||||||
}
|
}
|
||||||
|
@@ -19,8 +19,7 @@ package com.android.settings.password;
|
|||||||
import static android.content.pm.PackageManager.FEATURE_FACE;
|
import static android.content.pm.PackageManager.FEATURE_FACE;
|
||||||
import static android.content.pm.PackageManager.FEATURE_FINGERPRINT;
|
import static android.content.pm.PackageManager.FEATURE_FINGERPRINT;
|
||||||
|
|
||||||
import static com.android.settings.password.ChooseLockGeneric.ChooseLockGenericFragment.HIDE_DISABLED_PREFS;
|
import static com.android.settings.password.ChooseLockGeneric.ChooseLockGenericFragment.HIDE_INSECURE_OPTIONS;
|
||||||
import static com.android.settings.password.ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY;
|
|
||||||
import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_FOR_FACE;
|
import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_FOR_FACE;
|
||||||
import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT;
|
import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT;
|
||||||
import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW_HANDLE;
|
import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW_HANDLE;
|
||||||
@@ -262,12 +261,9 @@ public final class SetNewPasswordControllerTest {
|
|||||||
|
|
||||||
private void compareFingerprintExtras(Bundle actualBundle) {
|
private void compareFingerprintExtras(Bundle actualBundle) {
|
||||||
assertEquals(
|
assertEquals(
|
||||||
"Password quality must be something in order to config fingerprint.",
|
"Insecure options must be disabled in order to config fingerprint.",
|
||||||
DevicePolicyManager.PASSWORD_QUALITY_SOMETHING,
|
true,
|
||||||
actualBundle.getInt(MINIMUM_QUALITY_KEY));
|
actualBundle.getBoolean(HIDE_INSECURE_OPTIONS));
|
||||||
assertTrue(
|
|
||||||
"All disabled preference should be removed.",
|
|
||||||
actualBundle.getBoolean(HIDE_DISABLED_PREFS));
|
|
||||||
assertTrue(
|
assertTrue(
|
||||||
"Fingerprint enroll must request Gatekeeper Password.",
|
"Fingerprint enroll must request Gatekeeper Password.",
|
||||||
actualBundle.getBoolean(EXTRA_KEY_REQUEST_GK_PW_HANDLE));
|
actualBundle.getBoolean(EXTRA_KEY_REQUEST_GK_PW_HANDLE));
|
||||||
@@ -282,12 +278,9 @@ public final class SetNewPasswordControllerTest {
|
|||||||
|
|
||||||
private void compareFaceExtras(Bundle actualBundle) {
|
private void compareFaceExtras(Bundle actualBundle) {
|
||||||
assertEquals(
|
assertEquals(
|
||||||
"Password quality must be something in order to config face.",
|
"Insecure options must be disabled in order to config face.",
|
||||||
DevicePolicyManager.PASSWORD_QUALITY_SOMETHING,
|
true,
|
||||||
actualBundle.getInt(MINIMUM_QUALITY_KEY));
|
actualBundle.getBoolean(HIDE_INSECURE_OPTIONS));
|
||||||
assertTrue(
|
|
||||||
"All disabled preference should be removed.",
|
|
||||||
actualBundle.getBoolean(HIDE_DISABLED_PREFS));
|
|
||||||
assertTrue(
|
assertTrue(
|
||||||
"Face enroll must request Gatekeeper Password",
|
"Face enroll must request Gatekeeper Password",
|
||||||
actualBundle.getBoolean(EXTRA_KEY_REQUEST_GK_PW_HANDLE));
|
actualBundle.getBoolean(EXTRA_KEY_REQUEST_GK_PW_HANDLE));
|
||||||
|
@@ -198,8 +198,7 @@ public class SetupChooseLockPasswordTest {
|
|||||||
@Implements(ChooseLockGenericController.class)
|
@Implements(ChooseLockGenericController.class)
|
||||||
public static class ShadowChooseLockGenericController {
|
public static class ShadowChooseLockGenericController {
|
||||||
@Implementation
|
@Implementation
|
||||||
protected List<ScreenLockType> getVisibleScreenLockTypes(int quality,
|
protected List<ScreenLockType> getVisibleScreenLockTypes() {
|
||||||
boolean includeDisabled) {
|
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user