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"/>
|
android:textAppearance="?android:attr/textAppearanceMedium"/>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
android:id="@+id/password_container"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:clipChildren="false"
|
android:clipChildren="false"
|
||||||
android:clipToPadding="false"
|
android:clipToPadding="false"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
|
android:layoutMode="opticalBounds"
|
||||||
android:paddingBottom="8dp">
|
android:paddingBottom="8dp">
|
||||||
|
|
||||||
<!-- Password entry field -->
|
<!-- Password entry field -->
|
||||||
@@ -68,6 +70,15 @@
|
|||||||
android:layout_height="wrap_content"/>
|
android:layout_height="wrap_content"/>
|
||||||
|
|
||||||
</LinearLayout>
|
</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>
|
</LinearLayout>
|
||||||
|
|
||||||
</com.android.setupwizardlib.GlifLayout>
|
</com.android.setupwizardlib.GlifLayout>
|
||||||
|
@@ -18,5 +18,4 @@
|
|||||||
android:id="@+id/description_text"
|
android:id="@+id/description_text"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:paddingStart="4dp"
|
android:textSize="14sp"/>
|
||||||
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] -->
|
<!-- 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>
|
<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 />
|
<!-- Main Security lock settings --><skip />
|
||||||
<!-- Title for PreferenceScreen to launch picker for security method when there is none [CHAR LIMIT=22] -->
|
<!-- 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>
|
<string name="unlock_set_unlock_launch_picker_title">Screen lock</string>
|
||||||
|
@@ -17,6 +17,7 @@
|
|||||||
package com.android.settings.fingerprint;
|
package com.android.settings.fingerprint;
|
||||||
|
|
||||||
import android.app.KeyguardManager;
|
import android.app.KeyguardManager;
|
||||||
|
import android.app.admin.DevicePolicyManager;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.os.UserHandle;
|
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.internal.widget.LockPatternUtils;
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
import com.android.settings.SetupWizardUtils;
|
import com.android.settings.SetupWizardUtils;
|
||||||
|
import com.android.settings.password.ChooseLockGeneric;
|
||||||
|
import com.android.settings.password.ChooseLockGeneric.ChooseLockGenericFragment;
|
||||||
import com.android.settings.password.SetupChooseLockGeneric;
|
import com.android.settings.password.SetupChooseLockGeneric;
|
||||||
|
|
||||||
public class SetupFingerprintEnrollIntroduction extends FingerprintEnrollIntroduction {
|
public class SetupFingerprintEnrollIntroduction extends FingerprintEnrollIntroduction {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Intent getChooseLockIntent() {
|
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);
|
SetupWizardUtils.copySetupExtras(getIntent(), intent);
|
||||||
return intent;
|
return intent;
|
||||||
}
|
}
|
||||||
|
@@ -29,7 +29,6 @@ import android.app.Fragment;
|
|||||||
import android.app.FragmentManager;
|
import android.app.FragmentManager;
|
||||||
import android.app.admin.DevicePolicyManager;
|
import android.app.admin.DevicePolicyManager;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.UserInfo;
|
import android.content.pm.UserInfo;
|
||||||
import android.hardware.fingerprint.Fingerprint;
|
import android.hardware.fingerprint.Fingerprint;
|
||||||
@@ -40,6 +39,7 @@ import android.os.UserHandle;
|
|||||||
import android.os.UserManager;
|
import android.os.UserManager;
|
||||||
import android.os.storage.StorageManager;
|
import android.os.storage.StorageManager;
|
||||||
import android.security.KeyStore;
|
import android.security.KeyStore;
|
||||||
|
import android.support.annotation.StringRes;
|
||||||
import android.support.v7.preference.Preference;
|
import android.support.v7.preference.Preference;
|
||||||
import android.support.v7.preference.PreferenceScreen;
|
import android.support.v7.preference.PreferenceScreen;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
@@ -95,14 +95,9 @@ public class ChooseLockGeneric extends SettingsActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static class ChooseLockGenericFragment extends SettingsPreferenceFragment {
|
public static class ChooseLockGenericFragment extends SettingsPreferenceFragment {
|
||||||
|
|
||||||
private static final String TAG = "ChooseLockGenericFragment";
|
private static final String TAG = "ChooseLockGenericFragment";
|
||||||
private static final int MIN_PASSWORD_LENGTH = 4;
|
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 KEY_SKIP_FINGERPRINT = "unlock_skip_fingerprint";
|
||||||
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";
|
||||||
@@ -112,6 +107,27 @@ public class ChooseLockGeneric extends SettingsActivity {
|
|||||||
public static final String ENCRYPT_REQUESTED_DISABLED = "encrypt_requested_disabled";
|
public static final String ENCRYPT_REQUESTED_DISABLED = "encrypt_requested_disabled";
|
||||||
public static final String TAG_FRP_WARNING_DIALOG = "frp_warning_dialog";
|
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 CONFIRM_EXISTING_REQUEST = 100;
|
||||||
private static final int ENABLE_ENCRYPTION_REQUEST = 101;
|
private static final int ENABLE_ENCRYPTION_REQUEST = 101;
|
||||||
private static final int CHOOSE_LOCK_REQUEST = 102;
|
private static final int CHOOSE_LOCK_REQUEST = 102;
|
||||||
@@ -136,6 +152,7 @@ public class ChooseLockGeneric extends SettingsActivity {
|
|||||||
private ManagedLockPasswordProvider mManagedPasswordProvider;
|
private ManagedLockPasswordProvider mManagedPasswordProvider;
|
||||||
private boolean mIsSetNewPassword = false;
|
private boolean mIsSetNewPassword = false;
|
||||||
private UserManager mUserManager;
|
private UserManager mUserManager;
|
||||||
|
private ChooseLockGenericController mController;
|
||||||
|
|
||||||
protected boolean mForFingerprint = false;
|
protected boolean mForFingerprint = false;
|
||||||
|
|
||||||
@@ -192,6 +209,7 @@ public class ChooseLockGeneric extends SettingsActivity {
|
|||||||
UserManager.get(getActivity()),
|
UserManager.get(getActivity()),
|
||||||
getArguments(),
|
getArguments(),
|
||||||
getActivity().getIntent().getExtras()).getIdentifier();
|
getActivity().getIntent().getExtras()).getIdentifier();
|
||||||
|
mController = new ChooseLockGenericController(getContext(), mUserId);
|
||||||
if (ACTION_SET_NEW_PASSWORD.equals(chooseLockAction)
|
if (ACTION_SET_NEW_PASSWORD.equals(chooseLockAction)
|
||||||
&& UserManager.get(getActivity()).isManagedProfile(mUserId)
|
&& UserManager.get(getActivity()).isManagedProfile(mUserId)
|
||||||
&& mLockPatternUtils.isSeparateProfileChallengeEnabled(mUserId)) {
|
&& mLockPatternUtils.isSeparateProfileChallengeEnabled(mUserId)) {
|
||||||
@@ -303,7 +321,7 @@ public class ChooseLockGeneric extends SettingsActivity {
|
|||||||
finish();
|
finish();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
updateUnlockMethodAndFinish(quality, disabled);
|
updateUnlockMethodAndFinish(quality, disabled, false /* chooseLockSkipped */);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -328,6 +346,15 @@ public class ChooseLockGeneric extends SettingsActivity {
|
|||||||
if (resultCode != RESULT_CANCELED || mForChangeCredRequiredForBoot) {
|
if (resultCode != RESULT_CANCELED || mForChangeCredRequiredForBoot) {
|
||||||
getActivity().setResult(resultCode, data);
|
getActivity().setResult(resultCode, data);
|
||||||
finish();
|
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
|
} else if (requestCode == CHOOSE_LOCK_BEFORE_FINGERPRINT_REQUEST
|
||||||
&& resultCode == FingerprintEnrollBase.RESULT_FINISHED) {
|
&& resultCode == FingerprintEnrollBase.RESULT_FINISHED) {
|
||||||
@@ -374,7 +401,7 @@ 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 = intent.getIntExtra(MINIMUM_QUALITY_KEY, -1);
|
||||||
quality = upgradeQuality(quality);
|
quality = mController.upgradeQuality(quality);
|
||||||
final boolean hideDisabledPrefs = intent.getBooleanExtra(
|
final boolean hideDisabledPrefs = intent.getBooleanExtra(
|
||||||
HIDE_DISABLED_PREFS, false);
|
HIDE_DISABLED_PREFS, false);
|
||||||
final PreferenceScreen prefScreen = getPreferenceScreen();
|
final PreferenceScreen prefScreen = getPreferenceScreen();
|
||||||
@@ -387,7 +414,7 @@ public class ChooseLockGeneric extends SettingsActivity {
|
|||||||
updateCurrentPreference();
|
updateCurrentPreference();
|
||||||
updatePreferenceSummaryIfNeeded();
|
updatePreferenceSummaryIfNeeded();
|
||||||
} else {
|
} else {
|
||||||
updateUnlockMethodAndFinish(quality, false);
|
updateUnlockMethodAndFinish(quality, false, true /* chooseLockSkipped */);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -395,33 +422,26 @@ public class ChooseLockGeneric extends SettingsActivity {
|
|||||||
addPreferencesFromResource(R.xml.security_settings_picker);
|
addPreferencesFromResource(R.xml.security_settings_picker);
|
||||||
|
|
||||||
// Used for testing purposes
|
// 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_SKIP_FINGERPRINT).setViewId(R.id.lock_none);
|
||||||
findPreference(KEY_UNLOCK_SET_PIN).setViewId(R.id.lock_pin);
|
findPreference(ScreenLockType.PIN.preferenceKey).setViewId(R.id.lock_pin);
|
||||||
findPreference(KEY_UNLOCK_SET_PASSWORD).setViewId(R.id.lock_password);
|
findPreference(ScreenLockType.PASSWORD.preferenceKey).setViewId(R.id.lock_password);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updatePreferenceText() {
|
private void updatePreferenceText() {
|
||||||
if (mForFingerprint) {
|
if (mForFingerprint) {
|
||||||
final String key[] = { KEY_UNLOCK_SET_PATTERN,
|
setPreferenceTitle(ScreenLockType.PATTERN,
|
||||||
KEY_UNLOCK_SET_PIN,
|
R.string.fingerprint_unlock_set_unlock_pattern);
|
||||||
KEY_UNLOCK_SET_PASSWORD };
|
setPreferenceTitle(ScreenLockType.PIN, R.string.fingerprint_unlock_set_unlock_pin);
|
||||||
final int res[] = { R.string.fingerprint_unlock_set_unlock_pattern,
|
setPreferenceTitle(ScreenLockType.PASSWORD,
|
||||||
R.string.fingerprint_unlock_set_unlock_pin,
|
R.string.fingerprint_unlock_set_unlock_password);
|
||||||
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]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mManagedPasswordProvider.isSettingManagedPasswordSupported()) {
|
if (mManagedPasswordProvider.isSettingManagedPasswordSupported()) {
|
||||||
Preference managed = findPreference(KEY_UNLOCK_SET_MANAGED);
|
setPreferenceTitle(ScreenLockType.MANAGED,
|
||||||
managed.setTitle(mManagedPasswordProvider.getPickerOptionTitle(mForFingerprint));
|
mManagedPasswordProvider.getPickerOptionTitle(mForFingerprint));
|
||||||
} else {
|
} else {
|
||||||
removePreference(KEY_UNLOCK_SET_MANAGED);
|
removePreference(ScreenLockType.MANAGED.preferenceKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(mForFingerprint && mIsSetNewPassword)) {
|
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() {
|
private void updateCurrentPreference() {
|
||||||
String currentKey = getKeyForCurrent();
|
String currentKey = getKeyForCurrent();
|
||||||
Preference preference = findPreference(currentKey);
|
Preference preference = findPreference(currentKey);
|
||||||
@@ -441,39 +482,12 @@ public class ChooseLockGeneric extends SettingsActivity {
|
|||||||
final int credentialOwner = UserManager.get(getContext())
|
final int credentialOwner = UserManager.get(getContext())
|
||||||
.getCredentialOwnerProfile(mUserId);
|
.getCredentialOwnerProfile(mUserId);
|
||||||
if (mLockPatternUtils.isLockScreenDisabled(credentialOwner)) {
|
if (mLockPatternUtils.isLockScreenDisabled(credentialOwner)) {
|
||||||
return KEY_UNLOCK_SET_OFF;
|
return ScreenLockType.NONE.preferenceKey;
|
||||||
}
|
}
|
||||||
switch (mLockPatternUtils.getKeyguardStoredPasswordQuality(credentialOwner)) {
|
ScreenLockType lock =
|
||||||
case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
|
ScreenLockType.fromQuality(
|
||||||
return KEY_UNLOCK_SET_PATTERN;
|
mLockPatternUtils.getKeyguardStoredPasswordQuality(credentialOwner));
|
||||||
case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
|
return lock != null ? lock.preferenceKey : null;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/***
|
/***
|
||||||
@@ -501,54 +515,17 @@ public class ChooseLockGeneric extends SettingsActivity {
|
|||||||
int adminEnforcedQuality = mDPM.getPasswordQuality(null, mUserId);
|
int adminEnforcedQuality = mDPM.getPasswordQuality(null, mUserId);
|
||||||
EnforcedAdmin enforcedAdmin = RestrictedLockUtils.checkIfPasswordQualityIsSet(
|
EnforcedAdmin enforcedAdmin = RestrictedLockUtils.checkIfPasswordQualityIsSet(
|
||||||
getActivity(), mUserId);
|
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) {
|
if (pref instanceof RestrictedPreference) {
|
||||||
final String key = pref.getKey();
|
boolean visible = mController.isScreenLockVisible(lock);
|
||||||
boolean enabled = true;
|
boolean enabled = mController.isScreenLockEnabled(lock, quality);
|
||||||
boolean visible = true;
|
boolean disabledByAdmin =
|
||||||
boolean disabledByAdmin = false;
|
mController.isScreenLockDisabledByAdmin(lock, adminEnforcedQuality);
|
||||||
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;
|
|
||||||
}
|
|
||||||
if (hideDisabled) {
|
if (hideDisabled) {
|
||||||
visible = enabled;
|
visible = visible && enabled;
|
||||||
}
|
}
|
||||||
if (!visible) {
|
if (!visible) {
|
||||||
entries.removePreference(pref);
|
entries.removePreference(pref);
|
||||||
@@ -583,21 +560,10 @@ public class ChooseLockGeneric extends SettingsActivity {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
CharSequence summary = getString(R.string.secure_lock_encryption_warning);
|
setPreferenceSummary(ScreenLockType.PATTERN, R.string.secure_lock_encryption_warning);
|
||||||
|
setPreferenceSummary(ScreenLockType.PIN, R.string.secure_lock_encryption_warning);
|
||||||
PreferenceScreen screen = getPreferenceScreen();
|
setPreferenceSummary(ScreenLockType.PASSWORD, R.string.secure_lock_encryption_warning);
|
||||||
final int preferenceCount = screen.getPreferenceCount();
|
setPreferenceSummary(ScreenLockType.MANAGED, R.string.secure_lock_encryption_warning);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Intent getLockManagedPasswordIntent(String password) {
|
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 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 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}
|
* {@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.
|
// Sanity check. We should never get here without confirming user's existing password.
|
||||||
if (!mPasswordConfirmed) {
|
if (!mPasswordConfirmed) {
|
||||||
throw new IllegalStateException("Tried to update password without confirming it");
|
throw new IllegalStateException("Tried to update password without confirming it");
|
||||||
}
|
}
|
||||||
|
|
||||||
quality = upgradeQuality(quality);
|
quality = mController.upgradeQuality(quality);
|
||||||
Intent intent = getIntentForUnlockMethod(quality);
|
Intent intent = getIntentForUnlockMethod(quality);
|
||||||
if (intent != null) {
|
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,
|
startActivityForResult(intent,
|
||||||
mIsSetNewPassword && mHasChallenge
|
mIsSetNewPassword && mHasChallenge
|
||||||
? CHOOSE_LOCK_BEFORE_FINGERPRINT_REQUEST
|
? CHOOSE_LOCK_BEFORE_FINGERPRINT_REQUEST
|
||||||
@@ -831,35 +804,33 @@ public class ChooseLockGeneric extends SettingsActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean isUnlockMethodSecure(String unlockMethod) {
|
private boolean isUnlockMethodSecure(String unlockMethod) {
|
||||||
return !(KEY_UNLOCK_SET_OFF.equals(unlockMethod) ||
|
return !(ScreenLockType.SWIPE.preferenceKey.equals(unlockMethod) ||
|
||||||
KEY_UNLOCK_SET_NONE.equals(unlockMethod));
|
ScreenLockType.NONE.preferenceKey.equals(unlockMethod));
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean setUnlockMethod(String unlockMethod) {
|
private boolean setUnlockMethod(String unlockMethod) {
|
||||||
EventLog.writeEvent(EventLogTags.LOCK_SCREEN_TYPE, unlockMethod);
|
EventLog.writeEvent(EventLogTags.LOCK_SCREEN_TYPE, unlockMethod);
|
||||||
|
|
||||||
if (KEY_UNLOCK_SET_OFF.equals(unlockMethod)) {
|
ScreenLockType lock = ScreenLockType.fromKey(unlockMethod);
|
||||||
updateUnlockMethodAndFinish(
|
if (lock != null) {
|
||||||
DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, true /* disabled */ );
|
switch (lock) {
|
||||||
} else if (KEY_UNLOCK_SET_NONE.equals(unlockMethod)) {
|
case NONE:
|
||||||
updateUnlockMethodAndFinish(
|
case SWIPE:
|
||||||
DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, false /* disabled */ );
|
updateUnlockMethodAndFinish(
|
||||||
} else if (KEY_UNLOCK_SET_MANAGED.equals(unlockMethod)) {
|
lock.defaultQuality,
|
||||||
maybeEnableEncryption(DevicePolicyManager.PASSWORD_QUALITY_MANAGED, false);
|
lock == ScreenLockType.NONE,
|
||||||
} else if (KEY_UNLOCK_SET_PATTERN.equals(unlockMethod)) {
|
false /* chooseLockSkipped */);
|
||||||
maybeEnableEncryption(
|
return true;
|
||||||
DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, false);
|
case PATTERN:
|
||||||
} else if (KEY_UNLOCK_SET_PIN.equals(unlockMethod)) {
|
case PIN:
|
||||||
maybeEnableEncryption(
|
case PASSWORD:
|
||||||
DevicePolicyManager.PASSWORD_QUALITY_NUMERIC, false);
|
case MANAGED:
|
||||||
} else if (KEY_UNLOCK_SET_PASSWORD.equals(unlockMethod)) {
|
maybeEnableEncryption(lock.defaultQuality, false);
|
||||||
maybeEnableEncryption(
|
return true;
|
||||||
DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC, false);
|
}
|
||||||
} else {
|
|
||||||
Log.e(TAG, "Encountered unknown unlock method to set: " + unlockMethod);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
return true;
|
Log.e(TAG, "Encountered unknown unlock method to set: " + unlockMethod);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showFactoryResetProtectionWarningDialog(String unlockMethodToSet) {
|
private void showFactoryResetProtectionWarningDialog(String unlockMethodToSet) {
|
||||||
@@ -905,23 +876,12 @@ public class ChooseLockGeneric extends SettingsActivity {
|
|||||||
.setTitle(args.getInt(ARG_TITLE_RES))
|
.setTitle(args.getInt(ARG_TITLE_RES))
|
||||||
.setMessage(args.getInt(ARG_MESSAGE_RES))
|
.setMessage(args.getInt(ARG_MESSAGE_RES))
|
||||||
.setPositiveButton(R.string.unlock_disable_frp_warning_ok,
|
.setPositiveButton(R.string.unlock_disable_frp_warning_ok,
|
||||||
new DialogInterface.OnClickListener() {
|
(dialog, whichButton) -> {
|
||||||
@Override
|
String unlockMethod = args.getString(ARG_UNLOCK_METHOD_TO_SET);
|
||||||
public void onClick(DialogInterface dialog, int whichButton) {
|
((ChooseLockGenericFragment) getParentFragment())
|
||||||
((ChooseLockGenericFragment) getParentFragment())
|
.setUnlockMethod(unlockMethod);
|
||||||
.setUnlockMethod(
|
})
|
||||||
args.getString(ARG_UNLOCK_METHOD_TO_SET));
|
.setNegativeButton(R.string.cancel, (dialog, whichButton) -> dismiss())
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.setNegativeButton(R.string.cancel,
|
|
||||||
new DialogInterface.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(DialogInterface dialog, int whichButton) {
|
|
||||||
dismiss();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.create();
|
.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.app.admin.PasswordMetrics;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.graphics.Insets;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
@@ -171,7 +172,7 @@ public class ChooseLockPassword extends SettingsActivity {
|
|||||||
private int mPasswordMinNumeric = 0;
|
private int mPasswordMinNumeric = 0;
|
||||||
private int mPasswordMinNonLetter = 0;
|
private int mPasswordMinNonLetter = 0;
|
||||||
private int mPasswordMinLengthToFulfillAllPolicies = 0;
|
private int mPasswordMinLengthToFulfillAllPolicies = 0;
|
||||||
private int mUserId;
|
protected int mUserId;
|
||||||
private boolean mHideDrawer = false;
|
private boolean mHideDrawer = false;
|
||||||
/**
|
/**
|
||||||
* Password requirements that we need to verify.
|
* Password requirements that we need to verify.
|
||||||
@@ -188,7 +189,7 @@ public class ChooseLockPassword extends SettingsActivity {
|
|||||||
private TextView mHeaderText;
|
private TextView mHeaderText;
|
||||||
private String mFirstPin;
|
private String mFirstPin;
|
||||||
private RecyclerView mPasswordRestrictionView;
|
private RecyclerView mPasswordRestrictionView;
|
||||||
private boolean mIsAlphaMode;
|
protected boolean mIsAlphaMode;
|
||||||
private Button mCancelButton;
|
private Button mCancelButton;
|
||||||
private Button mNextButton;
|
private Button mNextButton;
|
||||||
|
|
||||||
@@ -291,6 +292,11 @@ public class ChooseLockPassword extends SettingsActivity {
|
|||||||
public void onViewCreated(View view, Bundle savedInstanceState) {
|
public void onViewCreated(View view, Bundle savedInstanceState) {
|
||||||
super.onViewCreated(view, 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 = (Button) view.findViewById(R.id.cancel_button);
|
||||||
mCancelButton.setOnClickListener(this);
|
mCancelButton.setOnClickListener(this);
|
||||||
mNextButton = (Button) view.findViewById(R.id.next_button);
|
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.
|
* Should be overridden if {@link #isManagedPasswordSupported()} returns true.
|
||||||
* @param forFingerprint Whether fingerprint unlock is enabled.
|
* @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
|
* 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,20 +111,16 @@ public class SetupChooseLockGeneric extends ChooseLockGeneric {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||||
if (resultCode != RESULT_CANCELED) {
|
if (data == null) {
|
||||||
if (data == null) {
|
data = new Intent();
|
||||||
data = new Intent();
|
|
||||||
}
|
|
||||||
// Add the password quality extra to the intent data that will be sent back for
|
|
||||||
// Setup Wizard.
|
|
||||||
LockPatternUtils lockPatternUtils = new LockPatternUtils(getActivity());
|
|
||||||
data.putExtra(EXTRA_PASSWORD_QUALITY,
|
|
||||||
lockPatternUtils.getKeyguardStoredPasswordQuality(UserHandle.myUserId()));
|
|
||||||
|
|
||||||
super.onActivityResult(requestCode, resultCode, data);
|
|
||||||
}
|
}
|
||||||
// If the started activity was cancelled (e.g. the user presses back), then this
|
// Add the password quality extra to the intent data that will be sent back for
|
||||||
// activity will be resumed to foreground.
|
// Setup Wizard.
|
||||||
|
LockPatternUtils lockPatternUtils = new LockPatternUtils(getActivity());
|
||||||
|
data.putExtra(EXTRA_PASSWORD_QUALITY,
|
||||||
|
lockPatternUtils.getKeyguardStoredPasswordQuality(UserHandle.myUserId()));
|
||||||
|
|
||||||
|
super.onActivityResult(requestCode, resultCode, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@@ -16,16 +16,24 @@
|
|||||||
|
|
||||||
package com.android.settings.password;
|
package com.android.settings.password;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
import android.app.Fragment;
|
import android.app.Fragment;
|
||||||
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;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.Button;
|
||||||
import android.widget.LinearLayout;
|
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.R;
|
||||||
import com.android.settings.SetupRedactionInterstitial;
|
import com.android.settings.SetupRedactionInterstitial;
|
||||||
import com.android.settings.SetupWizardUtils;
|
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
|
* 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);
|
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
|
@Override
|
||||||
protected Intent getRedactionInterstitialIntent(Context context) {
|
protected Intent getRedactionInterstitialIntent(Context context) {
|
||||||
@@ -76,5 +118,46 @@ public class SetupChooseLockPassword extends ChooseLockPassword {
|
|||||||
SetupRedactionInterstitial.setEnabled(context, true);
|
SetupRedactionInterstitial.setEnabled(context, true);
|
||||||
return null;
|
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));
|
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)
|
@Implements(Theme.class)
|
||||||
public static class SettingsShadowTheme extends ShadowTheme {
|
public static class SettingsShadowTheme extends ShadowTheme {
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user