Default setup wizard to use PIN
- Added "Screen lock options" button in PIN screen, controlled by extra EXTRA_SHOW_OPTIONS_BUTTON, which will create a dialog to ask the user to choose another screen lock type. - Extracted ScreenLockType enum and ChooseLockGenericController that can be shared by ChooseLockGeneric and the dialog ChooseLockTypeDialogFragment. - The intent extra EXTRA_SHOW_OPTIONS_BUTTON will be set if ChooseLockGeneric screen starts ChooseLockPassword / ChooseLockPattern without asking the user. (Although the extra is ignored by ChooseLockPattern currently) - Fix layout alignment for the password entry field to remove the extra 4dp padding on the sides. Test: cd tests/robotests && mma Bug: 35442933 Bug: 38002299 Change-Id: I877fbe08a0c05bb97175e1cbf0260ea6dbda22e2
This commit is contained in:
@@ -43,11 +43,13 @@
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"/>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/password_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
android:orientation="vertical"
|
||||
android:layoutMode="opticalBounds"
|
||||
android:paddingBottom="8dp">
|
||||
|
||||
<!-- Password entry field -->
|
||||
@@ -68,6 +70,15 @@
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<Button
|
||||
android:id="@+id/screen_lock_options"
|
||||
style="@style/SuwGlifButton.Tertiary"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/setup_lock_settings_options_button_label"
|
||||
android:visibility="gone" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</com.android.setupwizardlib.GlifLayout>
|
||||
|
@@ -18,5 +18,4 @@
|
||||
android:id="@+id/description_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="4dp"
|
||||
android:textSize="14sp"/>
|
@@ -1088,6 +1088,9 @@
|
||||
<!-- Message shown in screen lock picker while setting up the backup/fallback screen lock method for fingerprint. Users can choose to use this method to unlock the screen instead of fingerprint, or when fingerprint is not accepted. [CHAR LIMIT=80] [BACKUP_MESSAGE_ID=2799884038398627882] -->
|
||||
<string name="lock_settings_picker_fingerprint_message">Choose your backup screen lock method</string>
|
||||
|
||||
<!-- Label for button in screen lock settings, allowing users to choose other types of screen locks. [CHAR LIMIT=40] -->
|
||||
<string name="setup_lock_settings_options_button_label">Screen lock options</string>
|
||||
|
||||
<!-- Main Security lock settings --><skip />
|
||||
<!-- Title for PreferenceScreen to launch picker for security method when there is none [CHAR LIMIT=22] -->
|
||||
<string name="unlock_set_unlock_launch_picker_title">Screen lock</string>
|
||||
|
@@ -17,6 +17,7 @@
|
||||
package com.android.settings.fingerprint;
|
||||
|
||||
import android.app.KeyguardManager;
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Resources;
|
||||
import android.os.UserHandle;
|
||||
@@ -27,13 +28,19 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SetupWizardUtils;
|
||||
import com.android.settings.password.ChooseLockGeneric;
|
||||
import com.android.settings.password.ChooseLockGeneric.ChooseLockGenericFragment;
|
||||
import com.android.settings.password.SetupChooseLockGeneric;
|
||||
|
||||
public class SetupFingerprintEnrollIntroduction extends FingerprintEnrollIntroduction {
|
||||
|
||||
@Override
|
||||
protected Intent getChooseLockIntent() {
|
||||
Intent intent = new Intent(this, SetupChooseLockGeneric.class);
|
||||
Intent intent = new Intent(this, SetupChooseLockGeneric.class)
|
||||
.putExtra(
|
||||
LockPatternUtils.PASSWORD_TYPE_KEY,
|
||||
DevicePolicyManager.PASSWORD_QUALITY_NUMERIC);
|
||||
intent.putExtra(ChooseLockGenericFragment.EXTRA_SHOW_OPTIONS_BUTTON, true);
|
||||
SetupWizardUtils.copySetupExtras(getIntent(), intent);
|
||||
return intent;
|
||||
}
|
||||
|
@@ -29,7 +29,6 @@ import android.app.Fragment;
|
||||
import android.app.FragmentManager;
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.hardware.fingerprint.Fingerprint;
|
||||
@@ -40,6 +39,7 @@ import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.os.storage.StorageManager;
|
||||
import android.security.KeyStore;
|
||||
import android.support.annotation.StringRes;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.support.v7.preference.PreferenceScreen;
|
||||
import android.text.TextUtils;
|
||||
@@ -95,14 +95,9 @@ public class ChooseLockGeneric extends SettingsActivity {
|
||||
}
|
||||
|
||||
public static class ChooseLockGenericFragment extends SettingsPreferenceFragment {
|
||||
|
||||
private static final String TAG = "ChooseLockGenericFragment";
|
||||
private static final int MIN_PASSWORD_LENGTH = 4;
|
||||
private static final String KEY_UNLOCK_SET_OFF = "unlock_set_off";
|
||||
private static final String KEY_UNLOCK_SET_NONE = "unlock_set_none";
|
||||
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 KEY_SKIP_FINGERPRINT = "unlock_skip_fingerprint";
|
||||
private static final String PASSWORD_CONFIRMED = "password_confirmed";
|
||||
private static final String WAITING_FOR_CONFIRMATION = "waiting_for_confirmation";
|
||||
@@ -112,6 +107,27 @@ public class ChooseLockGeneric extends SettingsActivity {
|
||||
public static final String ENCRYPT_REQUESTED_DISABLED = "encrypt_requested_disabled";
|
||||
public static final String TAG_FRP_WARNING_DIALOG = "frp_warning_dialog";
|
||||
|
||||
/**
|
||||
* Boolean extra determining whether a "screen lock options" button should be shown. This
|
||||
* extra is both sent and received by ChooseLockGeneric.
|
||||
*
|
||||
* When this extra is false, nothing will be done.
|
||||
* When ChooseLockGeneric receives this extra set as true, and if ChooseLockGeneric is
|
||||
* starting ChooseLockPassword or ChooseLockPattern automatically without user interaction,
|
||||
* ChooseLockGeneric will set this extra to true when starting ChooseLockPassword/Pattern.
|
||||
*
|
||||
* This gives the user the choice to select a different screen lock type, even if
|
||||
* ChooseLockGeneric selected a default.
|
||||
*/
|
||||
public static final String EXTRA_SHOW_OPTIONS_BUTTON = "show_options_button";
|
||||
|
||||
/**
|
||||
* Original intent extras used to start this activity. This is passed to ChooseLockPassword
|
||||
* when the "screen lock options" button is shown, so that when that button is clicked,
|
||||
* ChooseLockGeneric can be relaunched with the same extras.
|
||||
*/
|
||||
public static final String EXTRA_CHOOSE_LOCK_GENERIC_EXTRAS = "choose_lock_generic_extras";
|
||||
|
||||
private static final int CONFIRM_EXISTING_REQUEST = 100;
|
||||
private static final int ENABLE_ENCRYPTION_REQUEST = 101;
|
||||
private static final int CHOOSE_LOCK_REQUEST = 102;
|
||||
@@ -136,6 +152,7 @@ public class ChooseLockGeneric extends SettingsActivity {
|
||||
private ManagedLockPasswordProvider mManagedPasswordProvider;
|
||||
private boolean mIsSetNewPassword = false;
|
||||
private UserManager mUserManager;
|
||||
private ChooseLockGenericController mController;
|
||||
|
||||
protected boolean mForFingerprint = false;
|
||||
|
||||
@@ -192,6 +209,7 @@ public class ChooseLockGeneric extends SettingsActivity {
|
||||
UserManager.get(getActivity()),
|
||||
getArguments(),
|
||||
getActivity().getIntent().getExtras()).getIdentifier();
|
||||
mController = new ChooseLockGenericController(getContext(), mUserId);
|
||||
if (ACTION_SET_NEW_PASSWORD.equals(chooseLockAction)
|
||||
&& UserManager.get(getActivity()).isManagedProfile(mUserId)
|
||||
&& mLockPatternUtils.isSeparateProfileChallengeEnabled(mUserId)) {
|
||||
@@ -303,7 +321,7 @@ public class ChooseLockGeneric extends SettingsActivity {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
updateUnlockMethodAndFinish(quality, disabled);
|
||||
updateUnlockMethodAndFinish(quality, disabled, false /* chooseLockSkipped */);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -328,6 +346,15 @@ public class ChooseLockGeneric extends SettingsActivity {
|
||||
if (resultCode != RESULT_CANCELED || mForChangeCredRequiredForBoot) {
|
||||
getActivity().setResult(resultCode, data);
|
||||
finish();
|
||||
} else {
|
||||
// If PASSWORD_TYPE_KEY is set, this activity is used as a trampoline to start
|
||||
// the actual password enrollment. If the result is canceled, which means the
|
||||
// user pressed back, finish the activity with result canceled.
|
||||
int quality = getIntent().getIntExtra(LockPatternUtils.PASSWORD_TYPE_KEY, -1);
|
||||
if (quality != -1) {
|
||||
getActivity().setResult(RESULT_CANCELED, data);
|
||||
finish();
|
||||
}
|
||||
}
|
||||
} else if (requestCode == CHOOSE_LOCK_BEFORE_FINGERPRINT_REQUEST
|
||||
&& resultCode == FingerprintEnrollBase.RESULT_FINISHED) {
|
||||
@@ -374,7 +401,7 @@ public class ChooseLockGeneric extends SettingsActivity {
|
||||
if (quality == -1) {
|
||||
// If caller didn't specify password quality, show UI and allow the user to choose.
|
||||
quality = intent.getIntExtra(MINIMUM_QUALITY_KEY, -1);
|
||||
quality = upgradeQuality(quality);
|
||||
quality = mController.upgradeQuality(quality);
|
||||
final boolean hideDisabledPrefs = intent.getBooleanExtra(
|
||||
HIDE_DISABLED_PREFS, false);
|
||||
final PreferenceScreen prefScreen = getPreferenceScreen();
|
||||
@@ -387,7 +414,7 @@ public class ChooseLockGeneric extends SettingsActivity {
|
||||
updateCurrentPreference();
|
||||
updatePreferenceSummaryIfNeeded();
|
||||
} else {
|
||||
updateUnlockMethodAndFinish(quality, false);
|
||||
updateUnlockMethodAndFinish(quality, false, true /* chooseLockSkipped */);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -395,33 +422,26 @@ public class ChooseLockGeneric extends SettingsActivity {
|
||||
addPreferencesFromResource(R.xml.security_settings_picker);
|
||||
|
||||
// Used for testing purposes
|
||||
findPreference(KEY_UNLOCK_SET_NONE).setViewId(R.id.lock_none);
|
||||
findPreference(ScreenLockType.NONE.preferenceKey).setViewId(R.id.lock_none);
|
||||
findPreference(KEY_SKIP_FINGERPRINT).setViewId(R.id.lock_none);
|
||||
findPreference(KEY_UNLOCK_SET_PIN).setViewId(R.id.lock_pin);
|
||||
findPreference(KEY_UNLOCK_SET_PASSWORD).setViewId(R.id.lock_password);
|
||||
findPreference(ScreenLockType.PIN.preferenceKey).setViewId(R.id.lock_pin);
|
||||
findPreference(ScreenLockType.PASSWORD.preferenceKey).setViewId(R.id.lock_password);
|
||||
}
|
||||
|
||||
private void updatePreferenceText() {
|
||||
if (mForFingerprint) {
|
||||
final String key[] = { KEY_UNLOCK_SET_PATTERN,
|
||||
KEY_UNLOCK_SET_PIN,
|
||||
KEY_UNLOCK_SET_PASSWORD };
|
||||
final int res[] = { R.string.fingerprint_unlock_set_unlock_pattern,
|
||||
R.string.fingerprint_unlock_set_unlock_pin,
|
||||
R.string.fingerprint_unlock_set_unlock_password };
|
||||
for (int i = 0; i < key.length; i++) {
|
||||
Preference pref = findPreference(key[i]);
|
||||
if (pref != null) { // can be removed by device admin
|
||||
pref.setTitle(res[i]);
|
||||
}
|
||||
}
|
||||
setPreferenceTitle(ScreenLockType.PATTERN,
|
||||
R.string.fingerprint_unlock_set_unlock_pattern);
|
||||
setPreferenceTitle(ScreenLockType.PIN, R.string.fingerprint_unlock_set_unlock_pin);
|
||||
setPreferenceTitle(ScreenLockType.PASSWORD,
|
||||
R.string.fingerprint_unlock_set_unlock_password);
|
||||
}
|
||||
|
||||
if (mManagedPasswordProvider.isSettingManagedPasswordSupported()) {
|
||||
Preference managed = findPreference(KEY_UNLOCK_SET_MANAGED);
|
||||
managed.setTitle(mManagedPasswordProvider.getPickerOptionTitle(mForFingerprint));
|
||||
setPreferenceTitle(ScreenLockType.MANAGED,
|
||||
mManagedPasswordProvider.getPickerOptionTitle(mForFingerprint));
|
||||
} else {
|
||||
removePreference(KEY_UNLOCK_SET_MANAGED);
|
||||
removePreference(ScreenLockType.MANAGED.preferenceKey);
|
||||
}
|
||||
|
||||
if (!(mForFingerprint && mIsSetNewPassword)) {
|
||||
@@ -429,6 +449,27 @@ public class ChooseLockGeneric extends SettingsActivity {
|
||||
}
|
||||
}
|
||||
|
||||
private void setPreferenceTitle(ScreenLockType lock, @StringRes int title) {
|
||||
Preference preference = findPreference(lock.preferenceKey);
|
||||
if (preference != null) {
|
||||
preference.setTitle(title);
|
||||
}
|
||||
}
|
||||
|
||||
private void setPreferenceTitle(ScreenLockType lock, CharSequence title) {
|
||||
Preference preference = findPreference(lock.preferenceKey);
|
||||
if (preference != null) {
|
||||
preference.setTitle(title);
|
||||
}
|
||||
}
|
||||
|
||||
private void setPreferenceSummary(ScreenLockType lock, @StringRes int summary) {
|
||||
Preference preference = findPreference(lock.preferenceKey);
|
||||
if (preference != null) {
|
||||
preference.setSummary(summary);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateCurrentPreference() {
|
||||
String currentKey = getKeyForCurrent();
|
||||
Preference preference = findPreference(currentKey);
|
||||
@@ -441,39 +482,12 @@ public class ChooseLockGeneric extends SettingsActivity {
|
||||
final int credentialOwner = UserManager.get(getContext())
|
||||
.getCredentialOwnerProfile(mUserId);
|
||||
if (mLockPatternUtils.isLockScreenDisabled(credentialOwner)) {
|
||||
return KEY_UNLOCK_SET_OFF;
|
||||
return ScreenLockType.NONE.preferenceKey;
|
||||
}
|
||||
switch (mLockPatternUtils.getKeyguardStoredPasswordQuality(credentialOwner)) {
|
||||
case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
|
||||
return KEY_UNLOCK_SET_PATTERN;
|
||||
case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
|
||||
case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
|
||||
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;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/** increases the quality if necessary */
|
||||
private int upgradeQuality(int quality) {
|
||||
quality = upgradeQualityForDPM(quality);
|
||||
return quality;
|
||||
}
|
||||
|
||||
private int upgradeQualityForDPM(int quality) {
|
||||
// Compare min allowed password quality
|
||||
int minQuality = mDPM.getPasswordQuality(null, mUserId);
|
||||
if (quality < minQuality) {
|
||||
quality = minQuality;
|
||||
}
|
||||
return quality;
|
||||
ScreenLockType lock =
|
||||
ScreenLockType.fromQuality(
|
||||
mLockPatternUtils.getKeyguardStoredPasswordQuality(credentialOwner));
|
||||
return lock != null ? lock.preferenceKey : null;
|
||||
}
|
||||
|
||||
/***
|
||||
@@ -501,54 +515,17 @@ public class ChooseLockGeneric extends SettingsActivity {
|
||||
int adminEnforcedQuality = mDPM.getPasswordQuality(null, mUserId);
|
||||
EnforcedAdmin enforcedAdmin = RestrictedLockUtils.checkIfPasswordQualityIsSet(
|
||||
getActivity(), mUserId);
|
||||
for (int i = entries.getPreferenceCount() - 1; i >= 0; --i) {
|
||||
Preference pref = entries.getPreference(i);
|
||||
|
||||
for (ScreenLockType lock : ScreenLockType.values()) {
|
||||
String key = lock.preferenceKey;
|
||||
Preference pref = findPreference(key);
|
||||
if (pref instanceof RestrictedPreference) {
|
||||
final String key = pref.getKey();
|
||||
boolean enabled = true;
|
||||
boolean visible = true;
|
||||
boolean disabledByAdmin = false;
|
||||
if (KEY_UNLOCK_SET_OFF.equals(key)) {
|
||||
enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
|
||||
if (getResources().getBoolean(R.bool.config_hide_none_security_option)) {
|
||||
enabled = false;
|
||||
visible = false;
|
||||
}
|
||||
disabledByAdmin = adminEnforcedQuality
|
||||
> DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
|
||||
} else if (KEY_UNLOCK_SET_NONE.equals(key)) {
|
||||
if (getResources().getBoolean(R.bool.config_hide_swipe_security_option)) {
|
||||
enabled = false;
|
||||
visible = false;
|
||||
} else {
|
||||
if (mUserId != UserHandle.myUserId()) {
|
||||
// Swipe doesn't make sense for profiles.
|
||||
visible = false;
|
||||
}
|
||||
enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
|
||||
}
|
||||
disabledByAdmin = adminEnforcedQuality
|
||||
> DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
|
||||
} else if (KEY_UNLOCK_SET_PATTERN.equals(key)) {
|
||||
enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
|
||||
disabledByAdmin = adminEnforcedQuality
|
||||
> DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
|
||||
} else if (KEY_UNLOCK_SET_PIN.equals(key)) {
|
||||
enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX;
|
||||
disabledByAdmin = adminEnforcedQuality
|
||||
> DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX;
|
||||
} else if (KEY_UNLOCK_SET_PASSWORD.equals(key)) {
|
||||
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;
|
||||
}
|
||||
boolean visible = mController.isScreenLockVisible(lock);
|
||||
boolean enabled = mController.isScreenLockEnabled(lock, quality);
|
||||
boolean disabledByAdmin =
|
||||
mController.isScreenLockDisabledByAdmin(lock, adminEnforcedQuality);
|
||||
if (hideDisabled) {
|
||||
visible = enabled;
|
||||
visible = visible && enabled;
|
||||
}
|
||||
if (!visible) {
|
||||
entries.removePreference(pref);
|
||||
@@ -583,21 +560,10 @@ public class ChooseLockGeneric extends SettingsActivity {
|
||||
return;
|
||||
}
|
||||
|
||||
CharSequence summary = getString(R.string.secure_lock_encryption_warning);
|
||||
|
||||
PreferenceScreen screen = getPreferenceScreen();
|
||||
final int preferenceCount = screen.getPreferenceCount();
|
||||
for (int i = 0; i < preferenceCount; i++) {
|
||||
Preference preference = screen.getPreference(i);
|
||||
switch (preference.getKey()) {
|
||||
case KEY_UNLOCK_SET_PATTERN:
|
||||
case KEY_UNLOCK_SET_PIN:
|
||||
case KEY_UNLOCK_SET_PASSWORD:
|
||||
case KEY_UNLOCK_SET_MANAGED: {
|
||||
preference.setSummary(summary);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
setPreferenceSummary(ScreenLockType.PATTERN, R.string.secure_lock_encryption_warning);
|
||||
setPreferenceSummary(ScreenLockType.PIN, R.string.secure_lock_encryption_warning);
|
||||
setPreferenceSummary(ScreenLockType.PASSWORD, R.string.secure_lock_encryption_warning);
|
||||
setPreferenceSummary(ScreenLockType.MANAGED, R.string.secure_lock_encryption_warning);
|
||||
}
|
||||
|
||||
protected Intent getLockManagedPasswordIntent(String password) {
|
||||
@@ -643,17 +609,24 @@ public class ChooseLockGeneric extends SettingsActivity {
|
||||
*
|
||||
* @param quality the desired quality. Ignored if DevicePolicyManager requires more security
|
||||
* @param disabled whether or not to show LockScreen at all. Only meaningful when quality is
|
||||
* @param chooseLockSkipped whether or not this activity is skipped. This is true when this
|
||||
* activity was not shown to the user at all, instead automatically proceeding based on
|
||||
* the given intent extras, typically {@link LockPatternUtils#PASSWORD_TYPE_KEY}.
|
||||
* {@link DevicePolicyManager#PASSWORD_QUALITY_UNSPECIFIED}
|
||||
*/
|
||||
void updateUnlockMethodAndFinish(int quality, boolean disabled) {
|
||||
void updateUnlockMethodAndFinish(int quality, boolean disabled, boolean chooseLockSkipped) {
|
||||
// Sanity check. We should never get here without confirming user's existing password.
|
||||
if (!mPasswordConfirmed) {
|
||||
throw new IllegalStateException("Tried to update password without confirming it");
|
||||
}
|
||||
|
||||
quality = upgradeQuality(quality);
|
||||
quality = mController.upgradeQuality(quality);
|
||||
Intent intent = getIntentForUnlockMethod(quality);
|
||||
if (intent != null) {
|
||||
if (getIntent().getBooleanExtra(EXTRA_SHOW_OPTIONS_BUTTON, false)) {
|
||||
intent.putExtra(EXTRA_SHOW_OPTIONS_BUTTON, chooseLockSkipped);
|
||||
}
|
||||
intent.putExtra(EXTRA_CHOOSE_LOCK_GENERIC_EXTRAS, getIntent().getExtras());
|
||||
startActivityForResult(intent,
|
||||
mIsSetNewPassword && mHasChallenge
|
||||
? CHOOSE_LOCK_BEFORE_FINGERPRINT_REQUEST
|
||||
@@ -831,36 +804,34 @@ public class ChooseLockGeneric extends SettingsActivity {
|
||||
}
|
||||
|
||||
private boolean isUnlockMethodSecure(String unlockMethod) {
|
||||
return !(KEY_UNLOCK_SET_OFF.equals(unlockMethod) ||
|
||||
KEY_UNLOCK_SET_NONE.equals(unlockMethod));
|
||||
return !(ScreenLockType.SWIPE.preferenceKey.equals(unlockMethod) ||
|
||||
ScreenLockType.NONE.preferenceKey.equals(unlockMethod));
|
||||
}
|
||||
|
||||
private boolean setUnlockMethod(String unlockMethod) {
|
||||
EventLog.writeEvent(EventLogTags.LOCK_SCREEN_TYPE, unlockMethod);
|
||||
|
||||
if (KEY_UNLOCK_SET_OFF.equals(unlockMethod)) {
|
||||
ScreenLockType lock = ScreenLockType.fromKey(unlockMethod);
|
||||
if (lock != null) {
|
||||
switch (lock) {
|
||||
case NONE:
|
||||
case SWIPE:
|
||||
updateUnlockMethodAndFinish(
|
||||
DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, true /* disabled */ );
|
||||
} 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);
|
||||
} else if (KEY_UNLOCK_SET_PIN.equals(unlockMethod)) {
|
||||
maybeEnableEncryption(
|
||||
DevicePolicyManager.PASSWORD_QUALITY_NUMERIC, false);
|
||||
} else if (KEY_UNLOCK_SET_PASSWORD.equals(unlockMethod)) {
|
||||
maybeEnableEncryption(
|
||||
DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC, false);
|
||||
} else {
|
||||
lock.defaultQuality,
|
||||
lock == ScreenLockType.NONE,
|
||||
false /* chooseLockSkipped */);
|
||||
return true;
|
||||
case PATTERN:
|
||||
case PIN:
|
||||
case PASSWORD:
|
||||
case MANAGED:
|
||||
maybeEnableEncryption(lock.defaultQuality, false);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Log.e(TAG, "Encountered unknown unlock method to set: " + unlockMethod);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void showFactoryResetProtectionWarningDialog(String unlockMethodToSet) {
|
||||
int title = getResIdForFactoryResetProtectionWarningTitle();
|
||||
@@ -905,23 +876,12 @@ public class ChooseLockGeneric extends SettingsActivity {
|
||||
.setTitle(args.getInt(ARG_TITLE_RES))
|
||||
.setMessage(args.getInt(ARG_MESSAGE_RES))
|
||||
.setPositiveButton(R.string.unlock_disable_frp_warning_ok,
|
||||
new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int whichButton) {
|
||||
(dialog, whichButton) -> {
|
||||
String unlockMethod = args.getString(ARG_UNLOCK_METHOD_TO_SET);
|
||||
((ChooseLockGenericFragment) getParentFragment())
|
||||
.setUnlockMethod(
|
||||
args.getString(ARG_UNLOCK_METHOD_TO_SET));
|
||||
}
|
||||
}
|
||||
)
|
||||
.setNegativeButton(R.string.cancel,
|
||||
new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int whichButton) {
|
||||
dismiss();
|
||||
}
|
||||
}
|
||||
)
|
||||
.setUnlockMethod(unlockMethod);
|
||||
})
|
||||
.setNegativeButton(R.string.cancel, (dialog, whichButton) -> dismiss())
|
||||
.create();
|
||||
}
|
||||
|
||||
|
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.password;
|
||||
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
import android.content.Context;
|
||||
import android.os.UserHandle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
|
||||
import com.android.settings.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A controller for ChooseLockGeneric, and other similar classes which shows a list of possible
|
||||
* screen locks for the user to choose from.
|
||||
*/
|
||||
public class ChooseLockGenericController {
|
||||
|
||||
private final Context mContext;
|
||||
private final int mUserId;
|
||||
private ManagedLockPasswordProvider mManagedPasswordProvider;
|
||||
private DevicePolicyManager mDpm;
|
||||
|
||||
public ChooseLockGenericController(Context context, int userId) {
|
||||
this(
|
||||
context,
|
||||
userId,
|
||||
context.getSystemService(DevicePolicyManager.class),
|
||||
ManagedLockPasswordProvider.get(context, userId));
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
ChooseLockGenericController(
|
||||
Context context,
|
||||
int userId,
|
||||
DevicePolicyManager dpm,
|
||||
ManagedLockPasswordProvider managedLockPasswordProvider) {
|
||||
mContext = context;
|
||||
mUserId = userId;
|
||||
mManagedPasswordProvider = managedLockPasswordProvider;
|
||||
mDpm = dpm;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The higher quality of either the specified {@code quality} or the quality required
|
||||
* by {@link DevicePolicyManager#getPasswordQuality}.
|
||||
*/
|
||||
public int upgradeQuality(int quality) {
|
||||
// Compare min allowed password quality
|
||||
return Math.max(quality, mDpm.getPasswordQuality(null, mUserId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the given screen lock type should be visible in the given context.
|
||||
*/
|
||||
public boolean isScreenLockVisible(ScreenLockType type) {
|
||||
switch (type) {
|
||||
case NONE:
|
||||
return !mContext.getResources().getBoolean(R.bool.config_hide_none_security_option);
|
||||
case SWIPE:
|
||||
return !mContext.getResources().getBoolean(R.bool.config_hide_swipe_security_option)
|
||||
// Swipe doesn't make sense for profiles.
|
||||
&& mUserId == UserHandle.myUserId();
|
||||
case MANAGED:
|
||||
return mManagedPasswordProvider.isManagedPasswordChoosable();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether screen lock with {@code type} should be enabled.
|
||||
*
|
||||
* @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) {
|
||||
return type.maxQuality >= quality;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether screen lock with {@code type} is disabled by device policy admin.
|
||||
*
|
||||
* @param type The screen lock type.
|
||||
* @param adminEnforcedQuality The minimum quality that the admin enforces.
|
||||
*/
|
||||
public boolean isScreenLockDisabledByAdmin(ScreenLockType type, int adminEnforcedQuality) {
|
||||
boolean disabledByAdmin = type.maxQuality < adminEnforcedQuality;
|
||||
if (type == ScreenLockType.MANAGED) {
|
||||
disabledByAdmin = disabledByAdmin
|
||||
|| !mManagedPasswordProvider.isManagedPasswordChoosable();
|
||||
}
|
||||
return disabledByAdmin;
|
||||
}
|
||||
|
||||
/**
|
||||
* User friendly title for the given screen lock type.
|
||||
*/
|
||||
public CharSequence getTitle(ScreenLockType type) {
|
||||
switch (type) {
|
||||
case NONE:
|
||||
return mContext.getText(R.string.unlock_set_unlock_off_title);
|
||||
case SWIPE:
|
||||
return mContext.getText(R.string.unlock_set_unlock_none_title);
|
||||
case PATTERN:
|
||||
return mContext.getText(R.string.unlock_set_unlock_pattern_title);
|
||||
case PIN:
|
||||
return mContext.getText(R.string.unlock_set_unlock_pin_title);
|
||||
case PASSWORD:
|
||||
return mContext.getText(R.string.unlock_set_unlock_password_title);
|
||||
case MANAGED:
|
||||
return mManagedPasswordProvider.getPickerOptionTitle(false);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of screen locks that should be visible for the given quality. The returned list
|
||||
* is ordered in the natural order of the enum (the order those enums were defined).
|
||||
*
|
||||
* @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
|
||||
public List<ScreenLockType> getVisibleScreenLockTypes(int quality, boolean includeDisabled) {
|
||||
int upgradedQuality = upgradeQuality(quality);
|
||||
List<ScreenLockType> locks = new ArrayList<>();
|
||||
// EnumSet's iterator guarantees the natural order of the enums
|
||||
for (ScreenLockType lock : ScreenLockType.values()) {
|
||||
if (isScreenLockVisible(lock)) {
|
||||
if (includeDisabled || isScreenLockEnabled(lock, upgradedQuality)) {
|
||||
locks.add(lock);
|
||||
}
|
||||
}
|
||||
}
|
||||
return locks;
|
||||
}
|
||||
}
|
@@ -28,6 +28,7 @@ import android.app.admin.DevicePolicyManager;
|
||||
import android.app.admin.PasswordMetrics;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Insets;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
@@ -171,7 +172,7 @@ public class ChooseLockPassword extends SettingsActivity {
|
||||
private int mPasswordMinNumeric = 0;
|
||||
private int mPasswordMinNonLetter = 0;
|
||||
private int mPasswordMinLengthToFulfillAllPolicies = 0;
|
||||
private int mUserId;
|
||||
protected int mUserId;
|
||||
private boolean mHideDrawer = false;
|
||||
/**
|
||||
* Password requirements that we need to verify.
|
||||
@@ -188,7 +189,7 @@ public class ChooseLockPassword extends SettingsActivity {
|
||||
private TextView mHeaderText;
|
||||
private String mFirstPin;
|
||||
private RecyclerView mPasswordRestrictionView;
|
||||
private boolean mIsAlphaMode;
|
||||
protected boolean mIsAlphaMode;
|
||||
private Button mCancelButton;
|
||||
private Button mNextButton;
|
||||
|
||||
@@ -291,6 +292,11 @@ public class ChooseLockPassword extends SettingsActivity {
|
||||
public void onViewCreated(View view, Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
// Make the password container consume the optical insets so the edit text is aligned
|
||||
// with the sides of the parent visually.
|
||||
ViewGroup container = view.findViewById(R.id.password_container);
|
||||
container.setOpticalInsets(Insets.NONE);
|
||||
|
||||
mCancelButton = (Button) view.findViewById(R.id.cancel_button);
|
||||
mCancelButton.setOnClickListener(this);
|
||||
mNextButton = (Button) view.findViewById(R.id.next_button);
|
||||
|
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.password;
|
||||
|
||||
import android.app.AlertDialog.Builder;
|
||||
import android.app.Dialog;
|
||||
import android.app.Fragment;
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.DialogInterface.OnClickListener;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A dialog fragment similar to {@link ChooseLockGeneric} where the user can select from a few
|
||||
* lock screen types.
|
||||
*/
|
||||
public class ChooseLockTypeDialogFragment extends InstrumentedDialogFragment
|
||||
implements OnClickListener {
|
||||
|
||||
private static final String ARG_USER_ID = "userId";
|
||||
private static final String ARG_EXCLUDE_LOCK = "excludeLock";
|
||||
|
||||
private ScreenLockAdapter mAdapter;
|
||||
private ChooseLockGenericController mController;
|
||||
|
||||
public static ChooseLockTypeDialogFragment newInstance(int userId, String excludeLock) {
|
||||
Bundle args = new Bundle();
|
||||
args.putInt(ARG_USER_ID, userId);
|
||||
args.putString(ARG_EXCLUDE_LOCK, excludeLock);
|
||||
ChooseLockTypeDialogFragment fragment = new ChooseLockTypeDialogFragment();
|
||||
fragment.setArguments(args);
|
||||
return fragment;
|
||||
}
|
||||
|
||||
public interface OnLockTypeSelectedListener {
|
||||
void onLockTypeSelected(ScreenLockType lock);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
final int userId = getArguments().getInt(ARG_USER_ID);
|
||||
mController = new ChooseLockGenericController(getContext(), userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(DialogInterface dialogInterface, int i) {
|
||||
OnLockTypeSelectedListener listener = null;
|
||||
Fragment parentFragment = getParentFragment();
|
||||
if (parentFragment instanceof OnLockTypeSelectedListener) {
|
||||
listener = (OnLockTypeSelectedListener) parentFragment;
|
||||
} else {
|
||||
Context context = getContext();
|
||||
if (context instanceof OnLockTypeSelectedListener) {
|
||||
listener = (OnLockTypeSelectedListener) context;
|
||||
}
|
||||
}
|
||||
if (listener != null) {
|
||||
listener.onLockTypeSelected(mAdapter.getItem(i));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
Context context = getContext();
|
||||
Builder builder = new Builder(context);
|
||||
List<ScreenLockType> locks =
|
||||
mController.getVisibleScreenLockTypes(
|
||||
DevicePolicyManager.PASSWORD_QUALITY_SOMETHING,
|
||||
false /* includeDisabled */);
|
||||
String excludeLockName = getArguments().getString(ARG_EXCLUDE_LOCK);
|
||||
if (excludeLockName != null) {
|
||||
locks.remove(ScreenLockType.valueOf(excludeLockName));
|
||||
}
|
||||
mAdapter = new ScreenLockAdapter(context, locks, mController);
|
||||
builder.setAdapter(mAdapter, this);
|
||||
return builder.create();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return MetricsEvent.SETTINGS_CHOOSE_LOCK_DIALOG;
|
||||
}
|
||||
|
||||
private static class ScreenLockAdapter extends ArrayAdapter<ScreenLockType> {
|
||||
|
||||
private final ChooseLockGenericController mController;
|
||||
|
||||
ScreenLockAdapter(
|
||||
Context context,
|
||||
List<ScreenLockType> locks,
|
||||
ChooseLockGenericController controller) {
|
||||
super(context, android.R.layout.simple_list_item_1, locks);
|
||||
mController = controller;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View view, ViewGroup parent) {
|
||||
if (view == null) {
|
||||
view = LayoutInflater.from(parent.getContext())
|
||||
.inflate(android.R.layout.simple_list_item_1, parent, false);
|
||||
}
|
||||
((TextView) view).setText(mController.getTitle(getItem(position)));
|
||||
return view;
|
||||
}
|
||||
}
|
||||
}
|
@@ -52,7 +52,7 @@ public class ManagedLockPasswordProvider {
|
||||
* Should be overridden if {@link #isManagedPasswordSupported()} returns true.
|
||||
* @param forFingerprint Whether fingerprint unlock is enabled.
|
||||
*/
|
||||
String getPickerOptionTitle(boolean forFingerprint) { return ""; }
|
||||
CharSequence getPickerOptionTitle(boolean forFingerprint) { return ""; }
|
||||
|
||||
/**
|
||||
* Gets resource id of the lock screen preference that should be displayed in security settings
|
||||
|
110
src/com/android/settings/password/ScreenLockType.java
Normal file
110
src/com/android/settings/password/ScreenLockType.java
Normal file
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.password;
|
||||
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
|
||||
/**
|
||||
* List of screen lock type options that are available in ChooseLockGeneric. Provides the key and
|
||||
* the associated quality, and also some helper functions to translate between them.
|
||||
*/
|
||||
public enum ScreenLockType {
|
||||
|
||||
NONE(
|
||||
DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED,
|
||||
"unlock_set_off"),
|
||||
SWIPE(
|
||||
DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED,
|
||||
"unlock_set_none"),
|
||||
PATTERN(
|
||||
DevicePolicyManager.PASSWORD_QUALITY_SOMETHING,
|
||||
"unlock_set_pattern"),
|
||||
PIN(
|
||||
DevicePolicyManager.PASSWORD_QUALITY_NUMERIC,
|
||||
DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX,
|
||||
"unlock_set_pin"),
|
||||
PASSWORD(
|
||||
DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC,
|
||||
DevicePolicyManager.PASSWORD_QUALITY_COMPLEX,
|
||||
"unlock_set_password"),
|
||||
MANAGED(
|
||||
DevicePolicyManager.PASSWORD_QUALITY_MANAGED,
|
||||
"unlock_set_managed");
|
||||
|
||||
private static final ScreenLockType MIN_QUALITY = ScreenLockType.NONE;
|
||||
private static final ScreenLockType MAX_QUALITY = ScreenLockType.MANAGED;
|
||||
|
||||
/**
|
||||
* The default quality of the type of lock used. For example, in the case of PIN, the default
|
||||
* quality if PASSWORD_QUALITY_NUMERIC, while the highest quality is
|
||||
* PASSWORD_QUALITY_NUMERIC_COMPLEX.
|
||||
*/
|
||||
public final int defaultQuality;
|
||||
|
||||
/**
|
||||
* The highest quality for the given type of lock. For example, in the case of password, the
|
||||
* default quality is PASSWORD_QUALITY_ALPHABETIC, but the highest possible quality is
|
||||
* PASSWORD_QUALITY_COMPLEX.
|
||||
*/
|
||||
public final int maxQuality;
|
||||
|
||||
public final String preferenceKey;
|
||||
|
||||
ScreenLockType(int quality, String preferenceKey) {
|
||||
this(quality, quality, preferenceKey);
|
||||
}
|
||||
|
||||
ScreenLockType(int defaultQuality, int maxQuality, String preferenceKey) {
|
||||
this.defaultQuality = defaultQuality;
|
||||
this.maxQuality = maxQuality;
|
||||
this.preferenceKey = preferenceKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the screen lock type for the given quality. Note that this method assumes that a screen
|
||||
* lock is enabled, which means if the quality is
|
||||
* {@link DevicePolicyManager#PASSWORD_QUALITY_UNSPECIFIED}, the returned type will be
|
||||
* {@link #SWIPE} and not {@link #NONE}.
|
||||
*/
|
||||
public static ScreenLockType fromQuality(int quality) {
|
||||
switch (quality) {
|
||||
case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
|
||||
return ScreenLockType.PATTERN;
|
||||
case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
|
||||
case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
|
||||
return ScreenLockType.PIN;
|
||||
case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
|
||||
case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
|
||||
case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
|
||||
return ScreenLockType.PASSWORD;
|
||||
case DevicePolicyManager.PASSWORD_QUALITY_MANAGED:
|
||||
return ScreenLockType.MANAGED;
|
||||
case DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED:
|
||||
return ScreenLockType.SWIPE;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static ScreenLockType fromKey(String key) {
|
||||
for (ScreenLockType lock : ScreenLockType.values()) {
|
||||
if (lock.preferenceKey.equals(key)) {
|
||||
return lock;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@@ -111,7 +111,6 @@ public class SetupChooseLockGeneric extends ChooseLockGeneric {
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
if (resultCode != RESULT_CANCELED) {
|
||||
if (data == null) {
|
||||
data = new Intent();
|
||||
}
|
||||
@@ -123,9 +122,6 @@ public class SetupChooseLockGeneric extends ChooseLockGeneric {
|
||||
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
// If the started activity was cancelled (e.g. the user presses back), then this
|
||||
// activity will be resumed to foreground.
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecyclerView onCreateRecyclerView(LayoutInflater inflater, ViewGroup parent,
|
||||
|
@@ -16,16 +16,24 @@
|
||||
|
||||
package com.android.settings.password;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Fragment;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Resources;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SetupRedactionInterstitial;
|
||||
import com.android.settings.SetupWizardUtils;
|
||||
import com.android.settings.password.ChooseLockGeneric.ChooseLockGenericFragment;
|
||||
import com.android.settings.password.ChooseLockTypeDialogFragment.OnLockTypeSelectedListener;
|
||||
import com.android.setupwizardlib.util.WizardManagerHelper;
|
||||
|
||||
/**
|
||||
* Setup Wizard's version of ChooseLockPassword screen. It inherits the logic and basic structure
|
||||
@@ -67,7 +75,41 @@ public class SetupChooseLockPassword extends ChooseLockPassword {
|
||||
super.onApplyThemeResource(theme, resid, first);
|
||||
}
|
||||
|
||||
public static class SetupChooseLockPasswordFragment extends ChooseLockPasswordFragment {
|
||||
public static class SetupChooseLockPasswordFragment extends ChooseLockPasswordFragment
|
||||
implements OnLockTypeSelectedListener {
|
||||
|
||||
@VisibleForTesting
|
||||
static final int REQUEST_SCREEN_LOCK_OPTIONS = 1;
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View view, Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
boolean showOptionsButton = getActivity().getIntent().getBooleanExtra(
|
||||
ChooseLockGenericFragment.EXTRA_SHOW_OPTIONS_BUTTON, false);
|
||||
if (showOptionsButton) {
|
||||
Button optionsButton = view.findViewById(R.id.screen_lock_options);
|
||||
optionsButton.setVisibility(View.VISIBLE);
|
||||
optionsButton.setOnClickListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
switch (v.getId()) {
|
||||
case R.id.screen_lock_options:
|
||||
launchChooseLockGeneric();
|
||||
break;
|
||||
default:
|
||||
super.onClick(v);
|
||||
}
|
||||
}
|
||||
|
||||
private void launchChooseLockGeneric() {
|
||||
ScreenLockType currentLock = mIsAlphaMode
|
||||
? ScreenLockType.PASSWORD : ScreenLockType.PIN;
|
||||
ChooseLockTypeDialogFragment.newInstance(mUserId, currentLock.toString())
|
||||
.show(getChildFragmentManager(), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Intent getRedactionInterstitialIntent(Context context) {
|
||||
@@ -76,5 +118,46 @@ public class SetupChooseLockPassword extends ChooseLockPassword {
|
||||
SetupRedactionInterstitial.setEnabled(context, true);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLockTypeSelected(ScreenLockType lock) {
|
||||
Intent activityIntent = getActivity().getIntent();
|
||||
Intent intent = new Intent(getContext(), SetupChooseLockGeneric.class);
|
||||
|
||||
// Copy the original extras into the new intent
|
||||
if (activityIntent
|
||||
.hasExtra(ChooseLockGenericFragment.EXTRA_CHOOSE_LOCK_GENERIC_EXTRAS)) {
|
||||
intent.putExtras(activityIntent.getBundleExtra(
|
||||
ChooseLockGenericFragment.EXTRA_CHOOSE_LOCK_GENERIC_EXTRAS));
|
||||
}
|
||||
intent.putExtra(LockPatternUtils.PASSWORD_TYPE_KEY, lock.defaultQuality);
|
||||
|
||||
// Propagate the fingerprint challenge
|
||||
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE,
|
||||
activityIntent.getBooleanExtra(ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE,
|
||||
false));
|
||||
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE,
|
||||
activityIntent.getLongExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, 0));
|
||||
|
||||
// The user is already given the choice of the what screen lock to set up. No need to
|
||||
// show this button again.
|
||||
intent.putExtra(ChooseLockGenericFragment.EXTRA_SHOW_OPTIONS_BUTTON, false);
|
||||
|
||||
WizardManagerHelper.copyWizardManagerExtras(activityIntent, intent);
|
||||
|
||||
startActivityForResult(intent, REQUEST_SCREEN_LOCK_OPTIONS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
if (requestCode == REQUEST_SCREEN_LOCK_OPTIONS) {
|
||||
if (resultCode != Activity.RESULT_CANCELED) {
|
||||
Activity activity = getActivity();
|
||||
activity.setResult(resultCode, data);
|
||||
activity.finish();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
49
tests/robotests/src/android/app/admin/PasswordMetrics.java
Normal file
49
tests/robotests/src/android/app/admin/PasswordMetrics.java
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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 android.app.admin;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
|
||||
/**
|
||||
* Stub implementation of framework's PasswordMetrics for Robolectric tests. Otherwise Robolectric
|
||||
* is throwing ClassNotFoundError.
|
||||
*
|
||||
* TODO: Remove this class when Robolectric supports O
|
||||
*/
|
||||
public class PasswordMetrics {
|
||||
|
||||
// Maximum allowed number of repeated or ordered characters in a sequence before we'll
|
||||
// consider it a complex PIN/password.
|
||||
public static final int MAX_ALLOWED_SEQUENCE = 3;
|
||||
|
||||
public int length = 0;
|
||||
public int letters = 0;
|
||||
public int upperCase = 0;
|
||||
public int lowerCase = 0;
|
||||
public int numeric = 0;
|
||||
public int symbols = 0;
|
||||
public int nonLetter = 0;
|
||||
|
||||
public static int maxLengthSequence(@NonNull String string) {
|
||||
// Stub implementation
|
||||
return 1;
|
||||
}
|
||||
|
||||
public static PasswordMetrics computeForPassword(@NonNull String password) {
|
||||
return new PasswordMetrics();
|
||||
}
|
||||
}
|
@@ -0,0 +1,230 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.password;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.anyBoolean;
|
||||
import static org.mockito.Matchers.anyInt;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.robolectric.RuntimeEnvironment.application;
|
||||
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
import android.content.ComponentName;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SettingsRobolectricTestRunner;
|
||||
import com.android.settings.TestConfig;
|
||||
import com.android.settings.testutils.shadow.SettingsShadowResources;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
@Config(
|
||||
manifest = TestConfig.MANIFEST_PATH,
|
||||
sdk = TestConfig.SDK_VERSION,
|
||||
shadows = {
|
||||
SettingsShadowResources.class
|
||||
})
|
||||
public class ChooseLockGenericControllerTest {
|
||||
|
||||
private ChooseLockGenericController mController;
|
||||
|
||||
@Mock
|
||||
private ManagedLockPasswordProvider mManagedLockPasswordProvider;
|
||||
|
||||
@Mock
|
||||
private DevicePolicyManager mDevicePolicyManager;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
mController = new ChooseLockGenericController(
|
||||
application,
|
||||
0 /* userId */,
|
||||
mDevicePolicyManager,
|
||||
mManagedLockPasswordProvider);
|
||||
SettingsShadowResources.overrideResource(R.bool.config_hide_none_security_option, false);
|
||||
SettingsShadowResources.overrideResource(R.bool.config_hide_swipe_security_option, false);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
SettingsShadowResources.reset();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isScreenLockVisible_shouldRespectResourceConfig() {
|
||||
for (ScreenLockType lock : ScreenLockType.values()) {
|
||||
// All locks except managed defaults to visible
|
||||
assertThat(mController.isScreenLockVisible(lock)).named(lock + " visible")
|
||||
.isEqualTo(lock != ScreenLockType.MANAGED);
|
||||
}
|
||||
|
||||
SettingsShadowResources.overrideResource(R.bool.config_hide_none_security_option, true);
|
||||
SettingsShadowResources.overrideResource(R.bool.config_hide_swipe_security_option, true);
|
||||
assertThat(mController.isScreenLockVisible(ScreenLockType.NONE)).named("NONE visible")
|
||||
.isFalse();
|
||||
assertThat(mController.isScreenLockVisible(ScreenLockType.SWIPE)).named("SWIPE visible")
|
||||
.isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isScreenLockVisible_notCurrentUser_shouldHideSwipe() {
|
||||
mController = new ChooseLockGenericController(application, 1 /* userId */);
|
||||
assertThat(mController.isScreenLockVisible(ScreenLockType.SWIPE)).named("SWIPE visible")
|
||||
.isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isScreenLockVisible_managedPasswordChoosable_shouldShowManaged() {
|
||||
doReturn(true).when(mManagedLockPasswordProvider).isManagedPasswordChoosable();
|
||||
|
||||
assertThat(mController.isScreenLockVisible(ScreenLockType.MANAGED)).named("MANAGED visible")
|
||||
.isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isScreenLockEnabled_lowerQuality_shouldReturnFalse() {
|
||||
for (ScreenLockType lock : ScreenLockType.values()) {
|
||||
assertThat(mController.isScreenLockEnabled(lock, lock.maxQuality + 1))
|
||||
.named(lock + " enabled")
|
||||
.isFalse();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isScreenLockEnabled_equalQuality_shouldReturnTrue() {
|
||||
for (ScreenLockType lock : ScreenLockType.values()) {
|
||||
assertThat(mController.isScreenLockEnabled(lock, lock.defaultQuality))
|
||||
.named(lock + " enabled")
|
||||
.isTrue();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isScreenLockEnabled_higherQuality_shouldReturnTrue() {
|
||||
for (ScreenLockType lock : ScreenLockType.values()) {
|
||||
assertThat(mController.isScreenLockEnabled(lock, lock.maxQuality - 1))
|
||||
.named(lock + " enabled")
|
||||
.isTrue();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isScreenLockDisabledByAdmin_lowerQuality_shouldReturnTrue() {
|
||||
doReturn(true).when(mManagedLockPasswordProvider).isManagedPasswordChoosable();
|
||||
for (ScreenLockType lock : ScreenLockType.values()) {
|
||||
assertThat(mController.isScreenLockDisabledByAdmin(lock, lock.maxQuality + 1))
|
||||
.named(lock + " disabledByAdmin")
|
||||
.isTrue();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isScreenLockDisabledByAdmin_equalQuality_shouldReturnFalse() {
|
||||
doReturn(true).when(mManagedLockPasswordProvider).isManagedPasswordChoosable();
|
||||
for (ScreenLockType lock : ScreenLockType.values()) {
|
||||
assertThat(mController.isScreenLockDisabledByAdmin(lock, lock.maxQuality))
|
||||
.named(lock + " disabledByAdmin")
|
||||
.isFalse();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isScreenLockDisabledByAdmin_higherQuality_shouldReturnFalse() {
|
||||
doReturn(true).when(mManagedLockPasswordProvider).isManagedPasswordChoosable();
|
||||
for (ScreenLockType lock : ScreenLockType.values()) {
|
||||
assertThat(mController.isScreenLockDisabledByAdmin(lock, lock.maxQuality - 1))
|
||||
.named(lock + " disabledByAdmin")
|
||||
.isFalse();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isScreenLockDisabledByAdmin_managedNotChoosable_shouldReturnTrue() {
|
||||
doReturn(false).when(mManagedLockPasswordProvider).isManagedPasswordChoosable();
|
||||
assertThat(mController.isScreenLockDisabledByAdmin(
|
||||
ScreenLockType.MANAGED, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED))
|
||||
.named("MANANGED disabledByAdmin")
|
||||
.isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getTitle_shouldContainEnumName() {
|
||||
doReturn("MANAGED").when(mManagedLockPasswordProvider).getPickerOptionTitle(anyBoolean());
|
||||
for (ScreenLockType lock : ScreenLockType.values()) {
|
||||
assertThat(mController.getTitle(lock).toString())
|
||||
.containsMatch(Pattern.compile(lock.toString(), Pattern.CASE_INSENSITIVE));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getVisibleScreenLockTypes_qualitySomething_shouldReturnPatterPinPassword() {
|
||||
assertThat(mController.getVisibleScreenLockTypes(
|
||||
DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, false))
|
||||
.isEqualTo(Arrays.asList(
|
||||
ScreenLockType.PATTERN,
|
||||
ScreenLockType.PIN,
|
||||
ScreenLockType.PASSWORD));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getVisibleScreenLockTypes_showDisabled_shouldReturnAllButManaged() {
|
||||
assertThat(mController.getVisibleScreenLockTypes(
|
||||
DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, true))
|
||||
.isEqualTo(Arrays.asList(
|
||||
ScreenLockType.NONE,
|
||||
ScreenLockType.SWIPE,
|
||||
ScreenLockType.PATTERN,
|
||||
ScreenLockType.PIN,
|
||||
ScreenLockType.PASSWORD));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void upgradeQuality_noDpmRequirement_shouldReturnQuality() {
|
||||
doReturn(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED)
|
||||
.when(mDevicePolicyManager).getPasswordQuality(any(ComponentName.class), anyInt());
|
||||
|
||||
int upgradedQuality = mController.upgradeQuality(
|
||||
DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC);
|
||||
assertThat(upgradedQuality).named("upgradedQuality")
|
||||
.isEqualTo(DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void upgradeQuality_dpmRequirement_shouldReturnRequiredQuality() {
|
||||
doReturn(DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC)
|
||||
.when(mDevicePolicyManager).getPasswordQuality(any(ComponentName.class), anyInt());
|
||||
|
||||
int upgradedQuality = mController.upgradeQuality(
|
||||
DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
|
||||
assertThat(upgradedQuality).named("upgradedQuality")
|
||||
.isEqualTo(DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC);
|
||||
}
|
||||
}
|
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.password;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
|
||||
import com.android.settings.SettingsRobolectricTestRunner;
|
||||
import com.android.settings.TestConfig;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
@Config(
|
||||
manifest = TestConfig.MANIFEST_PATH,
|
||||
sdk = TestConfig.SDK_VERSION)
|
||||
public class ScreenLockTypeTest {
|
||||
|
||||
@Test
|
||||
public void fromQuality_shouldReturnLockWithAssociatedQuality() {
|
||||
assertThat(ScreenLockType.fromQuality(DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC))
|
||||
.isEqualTo(ScreenLockType.PASSWORD);
|
||||
assertThat(ScreenLockType.fromQuality(DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC))
|
||||
.isEqualTo(ScreenLockType.PASSWORD);
|
||||
assertThat(ScreenLockType.fromQuality(DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK))
|
||||
.isNull();
|
||||
assertThat(ScreenLockType.fromQuality(DevicePolicyManager.PASSWORD_QUALITY_COMPLEX))
|
||||
.isEqualTo(ScreenLockType.PASSWORD);
|
||||
assertThat(ScreenLockType.fromQuality(DevicePolicyManager.PASSWORD_QUALITY_MANAGED))
|
||||
.isEqualTo(ScreenLockType.MANAGED);
|
||||
assertThat(ScreenLockType.fromQuality(DevicePolicyManager.PASSWORD_QUALITY_NUMERIC))
|
||||
.isEqualTo(ScreenLockType.PIN);
|
||||
assertThat(ScreenLockType.fromQuality(DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX))
|
||||
.isEqualTo(ScreenLockType.PIN);
|
||||
assertThat(ScreenLockType.fromQuality(DevicePolicyManager.PASSWORD_QUALITY_SOMETHING))
|
||||
.isEqualTo(ScreenLockType.PATTERN);
|
||||
assertThat(ScreenLockType.fromQuality(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED))
|
||||
.isEqualTo(ScreenLockType.SWIPE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fromKey_shouldReturnLockWithGivenKey() {
|
||||
for (ScreenLockType lock : ScreenLockType.values()) {
|
||||
assertThat(ScreenLockType.fromKey(lock.preferenceKey)).isEqualTo(lock);
|
||||
}
|
||||
assertThat(ScreenLockType.fromKey("nonexistent")).isNull();
|
||||
}
|
||||
}
|
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.password;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.robolectric.RuntimeEnvironment.application;
|
||||
import static org.robolectric.Shadows.shadowOf;
|
||||
|
||||
import android.app.Fragment;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.widget.Button;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SettingsRobolectricTestRunner;
|
||||
import com.android.settings.TestConfig;
|
||||
import com.android.settings.password.ChooseLockGeneric.ChooseLockGenericFragment;
|
||||
import com.android.settings.password.ChooseLockPassword.IntentBuilder;
|
||||
import com.android.settings.password.SetupChooseLockPassword.SetupChooseLockPasswordFragment;
|
||||
import com.android.settings.testutils.shadow.SettingsShadowResources;
|
||||
import com.android.settings.testutils.shadow.ShadowDynamicIndexableContentMonitor;
|
||||
import com.android.settings.testutils.shadow.ShadowEventLogWriter;
|
||||
import com.android.settings.testutils.shadow.ShadowUtils;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.Robolectric;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.shadows.ShadowActivity;
|
||||
import org.robolectric.shadows.ShadowActivity.IntentForResult;
|
||||
import org.robolectric.shadows.ShadowDialog;
|
||||
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
@Config(
|
||||
manifest = TestConfig.MANIFEST_PATH,
|
||||
sdk = TestConfig.SDK_VERSION,
|
||||
shadows = {
|
||||
SettingsShadowResources.class,
|
||||
SettingsShadowResources.SettingsShadowTheme.class,
|
||||
ShadowDynamicIndexableContentMonitor.class,
|
||||
ShadowEventLogWriter.class,
|
||||
ShadowUtils.class
|
||||
})
|
||||
public class SetupChooseLockPasswordTest {
|
||||
|
||||
@Test
|
||||
public void createActivity_shouldNotCrash() {
|
||||
// Basic sanity test for activity created without crashing
|
||||
Robolectric.buildActivity(SetupChooseLockPassword.class,
|
||||
SetupChooseLockPassword.modifyIntentForSetup(
|
||||
application,
|
||||
new IntentBuilder(application).build()))
|
||||
.setup().get();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createActivity_withShowOptionsButtonExtra_shouldShowButton() {
|
||||
Intent intent = SetupChooseLockPassword.modifyIntentForSetup(
|
||||
application,
|
||||
new IntentBuilder(application).build());
|
||||
intent.putExtra(ChooseLockGenericFragment.EXTRA_SHOW_OPTIONS_BUTTON, true);
|
||||
SetupChooseLockPassword activity =
|
||||
Robolectric.buildActivity(SetupChooseLockPassword.class, intent).setup().get();
|
||||
|
||||
Button optionsButton = activity.findViewById(R.id.screen_lock_options);
|
||||
assertThat(optionsButton).isNotNull();
|
||||
|
||||
ShadowActivity shadowActivity = shadowOf(activity);
|
||||
optionsButton.performClick();
|
||||
|
||||
assertThat(ShadowDialog.getLatestDialog()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createActivity_clickDifferentOption_extrasShouldBePropagated() {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString("foo", "bar");
|
||||
|
||||
Intent intent = new IntentBuilder(application).build();
|
||||
intent.putExtra(ChooseLockGenericFragment.EXTRA_CHOOSE_LOCK_GENERIC_EXTRAS, bundle);
|
||||
intent = SetupChooseLockPassword.modifyIntentForSetup(application, intent);
|
||||
intent.putExtra(ChooseLockGenericFragment.EXTRA_SHOW_OPTIONS_BUTTON, true);
|
||||
|
||||
SetupChooseLockPassword activity =
|
||||
Robolectric.buildActivity(SetupChooseLockPassword.class, intent).setup().get();
|
||||
|
||||
SetupChooseLockPasswordFragment fragment =
|
||||
(SetupChooseLockPasswordFragment) activity.getFragmentManager()
|
||||
.findFragmentById(R.id.main_content);
|
||||
fragment.onLockTypeSelected(ScreenLockType.PATTERN);
|
||||
|
||||
ShadowActivity shadowActivity = shadowOf(activity);
|
||||
IntentForResult chooseLockIntent = shadowActivity.getNextStartedActivityForResult();
|
||||
assertThat(chooseLockIntent).isNotNull();
|
||||
assertThat(chooseLockIntent.requestCode)
|
||||
.isEqualTo(SetupChooseLockPasswordFragment.REQUEST_SCREEN_LOCK_OPTIONS);
|
||||
assertThat(chooseLockIntent.intent.getStringExtra("foo")).named("Foo extra")
|
||||
.isEqualTo("bar");
|
||||
}
|
||||
}
|
@@ -137,6 +137,16 @@ public class SettingsShadowResources extends ShadowResources {
|
||||
realResources, Resources.class, "getInteger", ClassParameter.from(int.class, id));
|
||||
}
|
||||
|
||||
@Implementation
|
||||
public boolean getBoolean(int id) {
|
||||
final Object override = sResourceOverrides.get(id);
|
||||
if (override instanceof Boolean) {
|
||||
return (boolean) override;
|
||||
}
|
||||
return Shadow.directlyOn(realResources, Resources.class, "getBoolean",
|
||||
ClassParameter.from(int.class, id));
|
||||
}
|
||||
|
||||
@Implements(Theme.class)
|
||||
public static class SettingsShadowTheme extends ShadowTheme {
|
||||
|
||||
|
Reference in New Issue
Block a user