Introduce LockscreenCredential

Bug: 65239740
Test: make RunSettingsRoboTests ROBOTEST_FILTER=com.android.settings.password
Change-Id: Icb73d639291d6d2eda8015e18e93d0906f916bb2
This commit is contained in:
Rubin Xu
2019-09-11 17:36:37 +01:00
parent 4c1bfdfe73
commit 010116a173
13 changed files with 189 additions and 152 deletions

View File

@@ -727,7 +727,7 @@ public class CryptKeeper extends Activity implements TextView.OnEditorActionList
public void onPatternDetected(List<LockPatternView.Cell> pattern) { public void onPatternDetected(List<LockPatternView.Cell> pattern) {
mLockPatternView.setEnabled(false); mLockPatternView.setEnabled(false);
if (pattern.size() >= MIN_LENGTH_BEFORE_REPORT) { if (pattern.size() >= MIN_LENGTH_BEFORE_REPORT) {
new DecryptTask().execute(LockPatternUtils.patternToString(pattern)); new DecryptTask().execute(new String(LockPatternUtils.patternToByteArray(pattern)));
} else { } else {
// Allow user to make as many of these as they want. // Allow user to make as many of these as they want.
fakeUnlockAttempt(mLockPatternView); fakeUnlockAttempt(mLockPatternView);

View File

@@ -61,6 +61,7 @@ import androidx.preference.Preference;
import androidx.preference.PreferenceScreen; import androidx.preference.PreferenceScreen;
import com.android.internal.widget.LockPatternUtils; import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.LockscreenCredential;
import com.android.settings.EncryptionInterstitial; import com.android.settings.EncryptionInterstitial;
import com.android.settings.EventLogTags; import com.android.settings.EventLogTags;
import com.android.settings.R; import com.android.settings.R;
@@ -151,7 +152,7 @@ public class ChooseLockGeneric extends SettingsActivity {
private boolean mPasswordConfirmed = false; private boolean mPasswordConfirmed = false;
private boolean mWaitingForConfirmation = false; private boolean mWaitingForConfirmation = false;
private boolean mForChangeCredRequiredForBoot = false; private boolean mForChangeCredRequiredForBoot = false;
private byte[] mUserPassword; private LockscreenCredential mUserPassword;
private LockPatternUtils mLockPatternUtils; private LockPatternUtils mLockPatternUtils;
private FingerprintManager mFingerprintManager; private FingerprintManager mFingerprintManager;
private FaceManager mFaceManager; private FaceManager mFaceManager;
@@ -207,7 +208,7 @@ public class ChooseLockGeneric extends SettingsActivity {
.getBooleanExtra(CONFIRM_CREDENTIALS, true); .getBooleanExtra(CONFIRM_CREDENTIALS, true);
if (getActivity() instanceof ChooseLockGeneric.InternalActivity) { if (getActivity() instanceof ChooseLockGeneric.InternalActivity) {
mPasswordConfirmed = !confirmCredentials; mPasswordConfirmed = !confirmCredentials;
mUserPassword = getActivity().getIntent().getByteArrayExtra( mUserPassword = getActivity().getIntent().getParcelableExtra(
ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD); ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
} }
@@ -233,7 +234,7 @@ public class ChooseLockGeneric extends SettingsActivity {
mPasswordConfirmed = savedInstanceState.getBoolean(PASSWORD_CONFIRMED); mPasswordConfirmed = savedInstanceState.getBoolean(PASSWORD_CONFIRMED);
mWaitingForConfirmation = savedInstanceState.getBoolean(WAITING_FOR_CONFIRMATION); mWaitingForConfirmation = savedInstanceState.getBoolean(WAITING_FOR_CONFIRMATION);
if (mUserPassword == null) { if (mUserPassword == null) {
mUserPassword = savedInstanceState.getByteArray( mUserPassword = savedInstanceState.getParcelable(
ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD); ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
} }
} }
@@ -392,11 +393,11 @@ public class ChooseLockGeneric extends SettingsActivity {
if (requestCode == CONFIRM_EXISTING_REQUEST && resultCode == Activity.RESULT_OK) { if (requestCode == CONFIRM_EXISTING_REQUEST && resultCode == Activity.RESULT_OK) {
mPasswordConfirmed = true; mPasswordConfirmed = true;
mUserPassword = data != null mUserPassword = data != null
? data.getByteArrayExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD) ? data.getParcelableExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD)
: null; : null;
updatePreferencesOrFinish(false /* isRecreatingActivity */); updatePreferencesOrFinish(false /* isRecreatingActivity */);
if (mForChangeCredRequiredForBoot) { if (mForChangeCredRequiredForBoot) {
if (!(mUserPassword == null || mUserPassword.length == 0)) { if (mUserPassword != null && !mUserPassword.isNone()) {
maybeEnableEncryption( maybeEnableEncryption(
mLockPatternUtils.getKeyguardStoredPasswordQuality(mUserId), false); mLockPatternUtils.getKeyguardStoredPasswordQuality(mUserId), false);
} else { } else {
@@ -459,7 +460,7 @@ public class ChooseLockGeneric extends SettingsActivity {
outState.putBoolean(PASSWORD_CONFIRMED, mPasswordConfirmed); outState.putBoolean(PASSWORD_CONFIRMED, mPasswordConfirmed);
outState.putBoolean(WAITING_FOR_CONFIRMATION, mWaitingForConfirmation); outState.putBoolean(WAITING_FOR_CONFIRMATION, mWaitingForConfirmation);
if (mUserPassword != null) { if (mUserPassword != null) {
outState.putByteArray(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD, mUserPassword); outState.putParcelable(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD, mUserPassword);
} }
} }
@@ -682,7 +683,7 @@ public class ChooseLockGeneric extends SettingsActivity {
setPreferenceSummary(ScreenLockType.MANAGED, R.string.secure_lock_encryption_warning); setPreferenceSummary(ScreenLockType.MANAGED, R.string.secure_lock_encryption_warning);
} }
protected Intent getLockManagedPasswordIntent(byte[] password) { protected Intent getLockManagedPasswordIntent(LockscreenCredential password) {
return mManagedPasswordProvider.createIntent(false, password); return mManagedPasswordProvider.createIntent(false, password);
} }
@@ -759,7 +760,8 @@ public class ChooseLockGeneric extends SettingsActivity {
if (quality == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) { if (quality == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
// Clearing of user biometrics when screen lock is cleared is done at // Clearing of user biometrics when screen lock is cleared is done at
// LockSettingsService.removeBiometricsForUser(). // LockSettingsService.removeBiometricsForUser().
mChooseLockSettingsHelper.utils().clearLock(mUserPassword, mUserId); mChooseLockSettingsHelper.utils().setLockCredential(
LockscreenCredential.createNone(), mUserPassword, mUserId);
mChooseLockSettingsHelper.utils().setLockScreenDisabled(disabled, mUserId); mChooseLockSettingsHelper.utils().setLockScreenDisabled(disabled, mUserId);
getActivity().setResult(Activity.RESULT_OK); getActivity().setResult(Activity.RESULT_OK);
finish(); finish();

View File

@@ -63,6 +63,7 @@ import androidx.recyclerview.widget.RecyclerView;
import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.widget.LockPatternUtils; import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.LockPatternUtils.RequestThrottledException; import com.android.internal.widget.LockPatternUtils.RequestThrottledException;
import com.android.internal.widget.LockscreenCredential;
import com.android.internal.widget.TextViewInputDisabler; import com.android.internal.widget.TextViewInputDisabler;
import com.android.settings.EncryptionInterstitial; import com.android.settings.EncryptionInterstitial;
import com.android.settings.R; import com.android.settings.R;
@@ -124,7 +125,7 @@ public class ChooseLockPassword extends SettingsActivity {
return this; return this;
} }
public IntentBuilder setPassword(byte[] password) { public IntentBuilder setPassword(LockscreenCredential password) {
mIntent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD, password); mIntent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD, password);
return this; return this;
} }
@@ -180,13 +181,13 @@ public class ChooseLockPassword extends SettingsActivity {
public static class ChooseLockPasswordFragment extends InstrumentedFragment public static class ChooseLockPasswordFragment extends InstrumentedFragment
implements OnEditorActionListener, TextWatcher, SaveAndFinishWorker.Listener { implements OnEditorActionListener, TextWatcher, SaveAndFinishWorker.Listener {
private static final String KEY_FIRST_PIN = "first_pin"; private static final String KEY_FIRST_PASSWORD = "first_password";
private static final String KEY_UI_STAGE = "ui_stage"; private static final String KEY_UI_STAGE = "ui_stage";
private static final String KEY_CURRENT_PASSWORD = "current_password"; private static final String KEY_CURRENT_CREDENTIAL = "current_credential";
private static final String FRAGMENT_TAG_SAVE_AND_FINISH = "save_and_finish_worker"; private static final String FRAGMENT_TAG_SAVE_AND_FINISH = "save_and_finish_worker";
private byte[] mCurrentPassword; private LockscreenCredential mCurrentCredential;
private byte[] mChosenPassword; private LockscreenCredential mChosenPassword;
private boolean mHasChallenge; private boolean mHasChallenge;
private long mChallenge; private long mChallenge;
private ImeAwareEditText mPasswordEntry; private ImeAwareEditText mPasswordEntry;
@@ -215,7 +216,7 @@ public class ChooseLockPassword extends SettingsActivity {
protected boolean mForFingerprint; protected boolean mForFingerprint;
protected boolean mForFace; protected boolean mForFace;
private byte[] mFirstPin; private LockscreenCredential mFirstPassword;
private RecyclerView mPasswordRestrictionView; private RecyclerView mPasswordRestrictionView;
protected boolean mIsAlphaMode; protected boolean mIsAlphaMode;
protected FooterButton mSkipOrClearButton; protected FooterButton mSkipOrClearButton;
@@ -394,13 +395,13 @@ public class ChooseLockPassword extends SettingsActivity {
SaveAndFinishWorker w = new SaveAndFinishWorker(); SaveAndFinishWorker w = new SaveAndFinishWorker();
final boolean required = getActivity().getIntent().getBooleanExtra( final boolean required = getActivity().getIntent().getBooleanExtra(
EncryptionInterstitial.EXTRA_REQUIRE_PASSWORD, true); EncryptionInterstitial.EXTRA_REQUIRE_PASSWORD, true);
byte[] currentBytes = intent.getByteArrayExtra( LockscreenCredential currentCredential = intent.getParcelableExtra(
ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD); ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
w.setBlocking(true); w.setBlocking(true);
w.setListener(this); w.setListener(this);
w.start(mChooseLockSettingsHelper.utils(), required, false, 0, w.start(mChooseLockSettingsHelper.utils(), required, false, 0,
currentBytes, currentBytes, mRequestedQuality, mUserId); currentCredential, currentCredential, mUserId);
} }
mTextChangedHandler = new TextChangedHandler(); mTextChangedHandler = new TextChangedHandler();
} }
@@ -482,7 +483,7 @@ public class ChooseLockPassword extends SettingsActivity {
Intent intent = getActivity().getIntent(); Intent intent = getActivity().getIntent();
final boolean confirmCredentials = intent.getBooleanExtra( final boolean confirmCredentials = intent.getBooleanExtra(
ChooseLockGeneric.CONFIRM_CREDENTIALS, true); ChooseLockGeneric.CONFIRM_CREDENTIALS, true);
mCurrentPassword = intent.getByteArrayExtra( mCurrentCredential = intent.getParcelableExtra(
ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD); ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
mHasChallenge = intent.getBooleanExtra( mHasChallenge = intent.getBooleanExtra(
ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, false); ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, false);
@@ -497,15 +498,15 @@ public class ChooseLockPassword extends SettingsActivity {
} else { } else {
// restore from previous state // restore from previous state
mFirstPin = savedInstanceState.getByteArray(KEY_FIRST_PIN); mFirstPassword = savedInstanceState.getParcelable(KEY_FIRST_PASSWORD);
final String state = savedInstanceState.getString(KEY_UI_STAGE); final String state = savedInstanceState.getString(KEY_UI_STAGE);
if (state != null) { if (state != null) {
mUiStage = Stage.valueOf(state); mUiStage = Stage.valueOf(state);
updateStage(mUiStage); updateStage(mUiStage);
} }
if (mCurrentPassword == null) { if (mCurrentCredential == null) {
mCurrentPassword = savedInstanceState.getByteArray(KEY_CURRENT_PASSWORD); mCurrentCredential = savedInstanceState.getParcelable(KEY_CURRENT_CREDENTIAL);
} }
// Re-attach to the exiting worker if there is one. // Re-attach to the exiting worker if there is one.
@@ -563,8 +564,8 @@ public class ChooseLockPassword extends SettingsActivity {
public void onSaveInstanceState(Bundle outState) { public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState); super.onSaveInstanceState(outState);
outState.putString(KEY_UI_STAGE, mUiStage.name()); outState.putString(KEY_UI_STAGE, mUiStage.name());
outState.putByteArray(KEY_FIRST_PIN, mFirstPin); outState.putParcelable(KEY_FIRST_PASSWORD, mFirstPassword);
outState.putByteArray(KEY_CURRENT_PASSWORD, mCurrentPassword); outState.putParcelable(KEY_CURRENT_CREDENTIAL, mCurrentCredential);
} }
@Override @Override
@@ -577,7 +578,7 @@ public class ChooseLockPassword extends SettingsActivity {
getActivity().setResult(RESULT_FINISHED); getActivity().setResult(RESULT_FINISHED);
getActivity().finish(); getActivity().finish();
} else { } else {
mCurrentPassword = data.getByteArrayExtra( mCurrentCredential = data.getParcelableExtra(
ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD); ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
} }
break; break;
@@ -722,7 +723,8 @@ public class ChooseLockPassword extends SettingsActivity {
* @return the validation result. * @return the validation result.
*/ */
@VisibleForTesting @VisibleForTesting
int validatePassword(byte[] password) { int validatePassword(LockscreenCredential credential) {
final byte[] password = credential.getCredential();
int errorCode = NO_ERROR; int errorCode = NO_ERROR;
final PasswordMetrics metrics = PasswordMetrics.computeForPassword(password); final PasswordMetrics metrics = PasswordMetrics.computeForPassword(password);
mergeMinComplexityAndDpmRequirements(metrics.quality); mergeMinComplexityAndDpmRequirements(metrics.quality);
@@ -812,7 +814,8 @@ public class ChooseLockPassword extends SettingsActivity {
private byte[] getPasswordHistoryHashFactor() { private byte[] getPasswordHistoryHashFactor() {
if (mPasswordHistoryHashFactor == null) { if (mPasswordHistoryHashFactor == null) {
mPasswordHistoryHashFactor = mLockPatternUtils.getPasswordHistoryHashFactor( mPasswordHistoryHashFactor = mLockPatternUtils.getPasswordHistoryHashFactor(
mCurrentPassword, mUserId); mCurrentCredential != null ? mCurrentCredential
: LockscreenCredential.createNone(), mUserId);
} }
return mPasswordHistoryHashFactor; return mPasswordHistoryHashFactor;
} }
@@ -820,20 +823,22 @@ public class ChooseLockPassword extends SettingsActivity {
public void handleNext() { public void handleNext() {
if (mSaveAndFinishWorker != null) return; if (mSaveAndFinishWorker != null) return;
// TODO(b/120484642): This is a point of entry for passwords from the UI // TODO(b/120484642): This is a point of entry for passwords from the UI
mChosenPassword = LockPatternUtils.charSequenceToByteArray(mPasswordEntry.getText()); final Editable passwordText = mPasswordEntry.getText();
if (mChosenPassword == null || mChosenPassword.length == 0) { if (TextUtils.isEmpty(passwordText)) {
return; return;
} }
mChosenPassword = mIsAlphaMode ? LockscreenCredential.createPassword(passwordText)
: LockscreenCredential.createPin(passwordText);
if (mUiStage == Stage.Introduction) { if (mUiStage == Stage.Introduction) {
if (validatePassword(mChosenPassword) == NO_ERROR) { if (validatePassword(mChosenPassword) == NO_ERROR) {
mFirstPin = mChosenPassword; mFirstPassword = mChosenPassword;
mPasswordEntry.setText(""); mPasswordEntry.setText("");
updateStage(Stage.NeedToConfirm); updateStage(Stage.NeedToConfirm);
} else { } else {
Arrays.fill(mChosenPassword, (byte) 0); mChosenPassword.zeroize();
} }
} else if (mUiStage == Stage.NeedToConfirm) { } else if (mUiStage == Stage.NeedToConfirm) {
if (Arrays.equals(mFirstPin, mChosenPassword)) { if (mChosenPassword.equals(mFirstPassword)) {
startSaveAndFinish(); startSaveAndFinish();
} else { } else {
CharSequence tmp = mPasswordEntry.getText(); CharSequence tmp = mPasswordEntry.getText();
@@ -841,7 +846,7 @@ public class ChooseLockPassword extends SettingsActivity {
Selection.setSelection((Spannable) tmp, 0, tmp.length()); Selection.setSelection((Spannable) tmp, 0, tmp.length());
} }
updateStage(Stage.ConfirmWrong); updateStage(Stage.ConfirmWrong);
Arrays.fill(mChosenPassword, (byte) 0); mChosenPassword.zeroize();
} }
} }
} }
@@ -954,8 +959,11 @@ public class ChooseLockPassword extends SettingsActivity {
*/ */
protected void updateUi() { protected void updateUi() {
final boolean canInput = mSaveAndFinishWorker == null; final boolean canInput = mSaveAndFinishWorker == null;
byte[] password = LockPatternUtils.charSequenceToByteArray(mPasswordEntry.getText());
final int length = password.length; LockscreenCredential password = mIsAlphaMode
? LockscreenCredential.createPasswordOrNone(mPasswordEntry.getText())
: LockscreenCredential.createPinOrNone(mPasswordEntry.getText());
final int length = password.size();
if (mUiStage == Stage.Introduction) { if (mUiStage == Stage.Introduction) {
mPasswordRestrictionView.setVisibility(View.VISIBLE); mPasswordRestrictionView.setVisibility(View.VISIBLE);
final int errorCode = validatePassword(password); final int errorCode = validatePassword(password);
@@ -981,7 +989,7 @@ public class ChooseLockPassword extends SettingsActivity {
setNextText(mUiStage.buttonText); setNextText(mUiStage.buttonText);
mPasswordEntryInputDisabler.setInputEnabled(canInput); mPasswordEntryInputDisabler.setInputEnabled(canInput);
Arrays.fill(password, (byte) 0); password.zeroize();
} }
protected int toVisibility(boolean visibleOrGone) { protected int toVisibility(boolean visibleOrGone) {
@@ -1033,7 +1041,7 @@ public class ChooseLockPassword extends SettingsActivity {
final boolean required = getActivity().getIntent().getBooleanExtra( final boolean required = getActivity().getIntent().getBooleanExtra(
EncryptionInterstitial.EXTRA_REQUIRE_PASSWORD, true); EncryptionInterstitial.EXTRA_REQUIRE_PASSWORD, true);
mSaveAndFinishWorker.start(mLockPatternUtils, required, mHasChallenge, mChallenge, mSaveAndFinishWorker.start(mLockPatternUtils, required, mHasChallenge, mChallenge,
mChosenPassword, mCurrentPassword, mRequestedQuality, mUserId); mChosenPassword, mCurrentCredential, mUserId);
} }
@Override @Override
@@ -1041,13 +1049,13 @@ public class ChooseLockPassword extends SettingsActivity {
getActivity().setResult(RESULT_FINISHED, resultData); getActivity().setResult(RESULT_FINISHED, resultData);
if (mChosenPassword != null) { if (mChosenPassword != null) {
Arrays.fill(mChosenPassword, (byte) 0); mChosenPassword.zeroize();
} }
if (mCurrentPassword != null) { if (mCurrentCredential != null) {
Arrays.fill(mCurrentPassword, (byte) 0); mCurrentCredential.zeroize();
} }
if (mFirstPin != null) { if (mFirstPassword != null) {
Arrays.fill(mFirstPin, (byte) 0); mFirstPassword.zeroize();
} }
mPasswordEntry.setText(""); mPasswordEntry.setText("");
@@ -1088,18 +1096,18 @@ public class ChooseLockPassword extends SettingsActivity {
public static class SaveAndFinishWorker extends SaveChosenLockWorkerBase { public static class SaveAndFinishWorker extends SaveChosenLockWorkerBase {
private byte[] mChosenPassword; private LockscreenCredential mChosenPassword;
private byte[] mCurrentPassword; private LockscreenCredential mCurrentCredential;
private int mRequestedQuality;
public void start(LockPatternUtils utils, boolean required, public void start(LockPatternUtils utils, boolean required,
boolean hasChallenge, long challenge, boolean hasChallenge, long challenge,
byte[] chosenPassword, byte[] currentPassword, int requestedQuality, int userId) { LockscreenCredential chosenPassword, LockscreenCredential currentCredential,
int userId) {
prepare(utils, required, hasChallenge, challenge, userId); prepare(utils, required, hasChallenge, challenge, userId);
mChosenPassword = chosenPassword; mChosenPassword = chosenPassword;
mCurrentPassword = currentPassword; mCurrentCredential = currentCredential != null ? currentCredential
mRequestedQuality = requestedQuality; : LockscreenCredential.createNone();
mUserId = userId; mUserId = userId;
start(); start();
@@ -1107,13 +1115,13 @@ public class ChooseLockPassword extends SettingsActivity {
@Override @Override
protected Pair<Boolean, Intent> saveAndVerifyInBackground() { protected Pair<Boolean, Intent> saveAndVerifyInBackground() {
final boolean success = mUtils.saveLockPassword( final boolean success = mUtils.setLockCredential(
mChosenPassword, mCurrentPassword, mRequestedQuality, mUserId); mChosenPassword, mCurrentCredential, mUserId);
Intent result = null; Intent result = null;
if (success && mHasChallenge) { if (success && mHasChallenge) {
byte[] token; byte[] token;
try { try {
token = mUtils.verifyPassword(mChosenPassword, mChallenge, mUserId); token = mUtils.verifyCredential(mChosenPassword, mChallenge, mUserId);
} catch (RequestThrottledException e) { } catch (RequestThrottledException e) {
token = null; token = null;
} }

View File

@@ -36,12 +36,14 @@ import android.widget.TextView;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient; import com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient;
import com.android.internal.widget.LockPatternUtils; import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.LockPatternUtils.RequestThrottledException; import com.android.internal.widget.LockPatternUtils.RequestThrottledException;
import com.android.internal.widget.LockPatternView; import com.android.internal.widget.LockPatternView;
import com.android.internal.widget.LockPatternView.Cell; import com.android.internal.widget.LockPatternView.Cell;
import com.android.internal.widget.LockPatternView.DisplayMode; import com.android.internal.widget.LockPatternView.DisplayMode;
import com.android.internal.widget.LockscreenCredential;
import com.android.settings.EncryptionInterstitial; import com.android.settings.EncryptionInterstitial;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.SettingsActivity; import com.android.settings.SettingsActivity;
@@ -116,7 +118,7 @@ public class ChooseLockPattern extends SettingsActivity {
return this; return this;
} }
public IntentBuilder setPattern(byte[] pattern) { public IntentBuilder setPattern(LockscreenCredential pattern) {
mIntent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD, pattern); mIntent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD, pattern);
return this; return this;
} }
@@ -188,7 +190,7 @@ public class ChooseLockPattern extends SettingsActivity {
private static final String FRAGMENT_TAG_SAVE_AND_FINISH = "save_and_finish_worker"; private static final String FRAGMENT_TAG_SAVE_AND_FINISH = "save_and_finish_worker";
private byte[] mCurrentPattern; private LockscreenCredential mCurrentCredential;
private boolean mHasChallenge; private boolean mHasChallenge;
private long mChallenge; private long mChallenge;
protected TextView mTitleText; protected TextView mTitleText;
@@ -198,7 +200,7 @@ public class ChooseLockPattern extends SettingsActivity {
protected TextView mFooterText; protected TextView mFooterText;
protected FooterButton mSkipOrClearButton; protected FooterButton mSkipOrClearButton;
private FooterButton mNextButton; private FooterButton mNextButton;
protected List<LockPatternView.Cell> mChosenPattern = null; @VisibleForTesting protected LockscreenCredential mChosenPattern;
private ColorStateList mDefaultHeaderColorList; private ColorStateList mDefaultHeaderColorList;
// ScrollView that contains title and header, only exist in land mode // ScrollView that contains title and header, only exist in land mode
@@ -225,7 +227,7 @@ public class ChooseLockPattern extends SettingsActivity {
getActivity().setResult(RESULT_FINISHED); getActivity().setResult(RESULT_FINISHED);
getActivity().finish(); getActivity().finish();
} else { } else {
mCurrentPattern = data.getByteArrayExtra( mCurrentCredential = data.getParcelableExtra(
ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD); ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
} }
@@ -262,16 +264,19 @@ public class ChooseLockPattern extends SettingsActivity {
if (mUiStage == Stage.NeedToConfirm || mUiStage == Stage.ConfirmWrong) { if (mUiStage == Stage.NeedToConfirm || mUiStage == Stage.ConfirmWrong) {
if (mChosenPattern == null) throw new IllegalStateException( if (mChosenPattern == null) throw new IllegalStateException(
"null chosen pattern in stage 'need to confirm"); "null chosen pattern in stage 'need to confirm");
if (mChosenPattern.equals(pattern)) { try (LockscreenCredential confirmPattern =
updateStage(Stage.ChoiceConfirmed); LockscreenCredential.createPattern(pattern)) {
} else { if (mChosenPattern.equals(confirmPattern)) {
updateStage(Stage.ConfirmWrong); updateStage(Stage.ChoiceConfirmed);
} else {
updateStage(Stage.ConfirmWrong);
}
} }
} else if (mUiStage == Stage.Introduction || mUiStage == Stage.ChoiceTooShort){ } else if (mUiStage == Stage.Introduction || mUiStage == Stage.ChoiceTooShort){
if (pattern.size() < LockPatternUtils.MIN_LOCK_PATTERN_SIZE) { if (pattern.size() < LockPatternUtils.MIN_LOCK_PATTERN_SIZE) {
updateStage(Stage.ChoiceTooShort); updateStage(Stage.ChoiceTooShort);
} else { } else {
mChosenPattern = new ArrayList<LockPatternView.Cell>(pattern); mChosenPattern = LockscreenCredential.createPattern(pattern);
updateStage(Stage.FirstChoiceValid); updateStage(Stage.FirstChoiceValid);
} }
} else { } else {
@@ -458,12 +463,12 @@ public class ChooseLockPattern extends SettingsActivity {
SaveAndFinishWorker w = new SaveAndFinishWorker(); SaveAndFinishWorker w = new SaveAndFinishWorker();
final boolean required = getActivity().getIntent().getBooleanExtra( final boolean required = getActivity().getIntent().getBooleanExtra(
EncryptionInterstitial.EXTRA_REQUIRE_PASSWORD, true); EncryptionInterstitial.EXTRA_REQUIRE_PASSWORD, true);
byte[] current = intent.getByteArrayExtra( LockscreenCredential current = intent.getParcelableExtra(
ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD); ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
w.setBlocking(true); w.setBlocking(true);
w.setListener(this); w.setListener(this);
w.start(mChooseLockSettingsHelper.utils(), required, w.start(mChooseLockSettingsHelper.utils(), required,
false, 0, LockPatternUtils.byteArrayToPattern(current), current, mUserId); false, 0, current, current, mUserId);
} }
mForFingerprint = intent.getBooleanExtra( mForFingerprint = intent.getBooleanExtra(
ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, false); ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, false);
@@ -541,8 +546,8 @@ public class ChooseLockPattern extends SettingsActivity {
final boolean confirmCredentials = getActivity().getIntent() final boolean confirmCredentials = getActivity().getIntent()
.getBooleanExtra(ChooseLockGeneric.CONFIRM_CREDENTIALS, true); .getBooleanExtra(ChooseLockGeneric.CONFIRM_CREDENTIALS, true);
Intent intent = getActivity().getIntent(); Intent intent = getActivity().getIntent();
mCurrentPattern = mCurrentCredential =
intent.getByteArrayExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD); intent.getParcelableExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
mHasChallenge = intent.getBooleanExtra( mHasChallenge = intent.getBooleanExtra(
ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, false); ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, false);
mChallenge = intent.getLongExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, 0); mChallenge = intent.getLongExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, 0);
@@ -565,13 +570,10 @@ public class ChooseLockPattern extends SettingsActivity {
} }
} else { } else {
// restore from previous state // restore from previous state
final byte[] pattern = savedInstanceState.getByteArray(KEY_PATTERN_CHOICE); mChosenPattern = savedInstanceState.getParcelable(KEY_PATTERN_CHOICE);
if (pattern != null) {
mChosenPattern = LockPatternUtils.byteArrayToPattern(pattern);
}
if (mCurrentPattern == null) { if (mCurrentCredential == null) {
mCurrentPattern = savedInstanceState.getByteArray(KEY_CURRENT_PATTERN); mCurrentCredential = savedInstanceState.getParcelable(KEY_CURRENT_PATTERN);
} }
updateStage(Stage.values()[savedInstanceState.getInt(KEY_UI_STAGE)]); updateStage(Stage.values()[savedInstanceState.getInt(KEY_UI_STAGE)]);
@@ -606,6 +608,7 @@ public class ChooseLockPattern extends SettingsActivity {
public void handleLeftButton() { public void handleLeftButton() {
if (mUiStage.leftMode == LeftButtonMode.Retry) { if (mUiStage.leftMode == LeftButtonMode.Retry) {
mChosenPattern.zeroize();
mChosenPattern = null; mChosenPattern = null;
mLockPatternView.clearPattern(); mLockPatternView.clearPattern();
updateStage(Stage.Introduction); updateStage(Stage.Introduction);
@@ -667,12 +670,11 @@ public class ChooseLockPattern extends SettingsActivity {
outState.putInt(KEY_UI_STAGE, mUiStage.ordinal()); outState.putInt(KEY_UI_STAGE, mUiStage.ordinal());
if (mChosenPattern != null) { if (mChosenPattern != null) {
outState.putByteArray(KEY_PATTERN_CHOICE, outState.putParcelable(KEY_PATTERN_CHOICE, mChosenPattern);
LockPatternUtils.patternToByteArray(mChosenPattern));
} }
if (mCurrentPattern != null) { if (mCurrentCredential != null) {
outState.putByteArray(KEY_CURRENT_PATTERN, mCurrentPattern); outState.putParcelable(KEY_CURRENT_PATTERN, mCurrentCredential);
} }
} }
@@ -812,15 +814,18 @@ public class ChooseLockPattern extends SettingsActivity {
final boolean required = getActivity().getIntent().getBooleanExtra( final boolean required = getActivity().getIntent().getBooleanExtra(
EncryptionInterstitial.EXTRA_REQUIRE_PASSWORD, true); EncryptionInterstitial.EXTRA_REQUIRE_PASSWORD, true);
mSaveAndFinishWorker.start(mChooseLockSettingsHelper.utils(), required, mSaveAndFinishWorker.start(mChooseLockSettingsHelper.utils(), required,
mHasChallenge, mChallenge, mChosenPattern, mCurrentPattern, mUserId); mHasChallenge, mChallenge, mChosenPattern, mCurrentCredential, mUserId);
} }
@Override @Override
public void onChosenLockSaveFinished(boolean wasSecureBefore, Intent resultData) { public void onChosenLockSaveFinished(boolean wasSecureBefore, Intent resultData) {
getActivity().setResult(RESULT_FINISHED, resultData); getActivity().setResult(RESULT_FINISHED, resultData);
if (mCurrentPattern != null) { if (mChosenPattern != null) {
Arrays.fill(mCurrentPattern, (byte) 0); mChosenPattern.zeroize();
}
if (mCurrentCredential != null) {
mCurrentCredential.zeroize();
} }
if (!wasSecureBefore) { if (!wasSecureBefore) {
@@ -835,16 +840,17 @@ public class ChooseLockPattern extends SettingsActivity {
public static class SaveAndFinishWorker extends SaveChosenLockWorkerBase { public static class SaveAndFinishWorker extends SaveChosenLockWorkerBase {
private List<LockPatternView.Cell> mChosenPattern; private LockscreenCredential mChosenPattern;
private byte[] mCurrentPattern; private LockscreenCredential mCurrentCredential;
private boolean mLockVirgin; private boolean mLockVirgin;
public void start(LockPatternUtils utils, boolean credentialRequired, public void start(LockPatternUtils utils, boolean credentialRequired, boolean hasChallenge,
boolean hasChallenge, long challenge, long challenge, LockscreenCredential chosenPattern,
List<LockPatternView.Cell> chosenPattern, byte[] currentPattern, int userId) { LockscreenCredential currentCredential, int userId) {
prepare(utils, credentialRequired, hasChallenge, challenge, userId); prepare(utils, credentialRequired, hasChallenge, challenge, userId);
mCurrentPattern = currentPattern; mCurrentCredential = currentCredential != null ? currentCredential
: LockscreenCredential.createNone();
mChosenPattern = chosenPattern; mChosenPattern = chosenPattern;
mUserId = userId; mUserId = userId;
@@ -856,12 +862,13 @@ public class ChooseLockPattern extends SettingsActivity {
@Override @Override
protected Pair<Boolean, Intent> saveAndVerifyInBackground() { protected Pair<Boolean, Intent> saveAndVerifyInBackground() {
final int userId = mUserId; final int userId = mUserId;
final boolean success = mUtils.saveLockPattern(mChosenPattern, mCurrentPattern, userId); final boolean success = mUtils.setLockCredential(mChosenPattern, mCurrentCredential,
userId);
Intent result = null; Intent result = null;
if (success && mHasChallenge) { if (success && mHasChallenge) {
byte[] token; byte[] token;
try { try {
token = mUtils.verifyPattern(mChosenPattern, mChallenge, userId); token = mUtils.verifyCredential(mChosenPattern, mChallenge, userId);
} catch (RequestThrottledException e) { } catch (RequestThrottledException e) {
token = null; token = null;
} }

View File

@@ -27,6 +27,7 @@ import android.os.CountDownTimer;
import android.os.SystemClock; import android.os.SystemClock;
import android.os.UserManager; import android.os.UserManager;
import android.os.storage.StorageManager; import android.os.storage.StorageManager;
import android.text.Editable;
import android.text.InputType; import android.text.InputType;
import android.text.TextUtils; import android.text.TextUtils;
import android.view.KeyEvent; import android.view.KeyEvent;
@@ -44,6 +45,7 @@ import androidx.fragment.app.Fragment;
import com.android.internal.widget.LockPatternChecker; import com.android.internal.widget.LockPatternChecker;
import com.android.internal.widget.LockPatternUtils; import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.LockscreenCredential;
import com.android.internal.widget.TextViewInputDisabler; import com.android.internal.widget.TextViewInputDisabler;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.widget.ImeAwareEditText; import com.android.settings.widget.ImeAwareEditText;
@@ -332,10 +334,13 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
} }
// TODO(b/120484642): This is a point of entry for passwords from the UI // TODO(b/120484642): This is a point of entry for passwords from the UI
final byte[] pin = LockPatternUtils.charSequenceToByteArray(mPasswordEntry.getText()); final Editable passwordText = mPasswordEntry.getText();
if (pin == null || pin.length == 0) { if (TextUtils.isEmpty(passwordText)) {
return; return;
} }
final LockscreenCredential credential =
mIsAlpha ? LockscreenCredential.createPassword(passwordText)
: LockscreenCredential.createPin(passwordText);
mPasswordEntryInputDisabler.setInputEnabled(false); mPasswordEntryInputDisabler.setInputEnabled(false);
final boolean verifyChallenge = getActivity().getIntent().getBooleanExtra( final boolean verifyChallenge = getActivity().getIntent().getBooleanExtra(
@@ -344,11 +349,11 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
Intent intent = new Intent(); Intent intent = new Intent();
if (verifyChallenge) { if (verifyChallenge) {
if (isInternalActivity()) { if (isInternalActivity()) {
startVerifyPassword(pin, intent); startVerifyPassword(credential, intent);
return; return;
} }
} else { } else {
startCheckPassword(pin, intent); startCheckPassword(credential, intent);
return; return;
} }
@@ -359,7 +364,7 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
return getActivity() instanceof ConfirmLockPassword.InternalActivity; return getActivity() instanceof ConfirmLockPassword.InternalActivity;
} }
private void startVerifyPassword(final byte[] pin, final Intent intent) { private void startVerifyPassword(LockscreenCredential credential, final Intent intent) {
long challenge = getActivity().getIntent().getLongExtra( long challenge = getActivity().getIntent().getLongExtra(
ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, 0); ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, 0);
final int localEffectiveUserId = mEffectiveUserId; final int localEffectiveUserId = mEffectiveUserId;
@@ -383,29 +388,32 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
} }
}; };
mPendingLockCheck = (localEffectiveUserId == localUserId) mPendingLockCheck = (localEffectiveUserId == localUserId)
? LockPatternChecker.verifyPassword( ? LockPatternChecker.verifyCredential(
mLockPatternUtils, pin, challenge, localUserId, onVerifyCallback) mLockPatternUtils, credential, challenge, localUserId, onVerifyCallback)
: LockPatternChecker.verifyTiedProfileChallenge( : LockPatternChecker.verifyTiedProfileChallenge(
mLockPatternUtils, pin, false, challenge, localUserId, mLockPatternUtils, credential, challenge, localUserId,
onVerifyCallback); onVerifyCallback);
} }
private void startCheckPassword(final byte[] pin, final Intent intent) { private void startCheckPassword(final LockscreenCredential credential,
final Intent intent) {
final int localEffectiveUserId = mEffectiveUserId; final int localEffectiveUserId = mEffectiveUserId;
mPendingLockCheck = LockPatternChecker.checkPassword( mPendingLockCheck = LockPatternChecker.checkCredential(
mLockPatternUtils, mLockPatternUtils,
pin, credential,
localEffectiveUserId, localEffectiveUserId,
new LockPatternChecker.OnCheckCallback() { new LockPatternChecker.OnCheckCallback() {
@Override @Override
public void onChecked(boolean matched, int timeoutMs) { public void onChecked(boolean matched, int timeoutMs) {
mPendingLockCheck = null; mPendingLockCheck = null;
if (matched && isInternalActivity() && mReturnCredentials) { if (matched && isInternalActivity() && mReturnCredentials) {
// TODO: get rid of EXTRA_KEY_TYPE, since EXTRA_KEY_PASSWORD already
// distinguishes beteween PIN and password.
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_TYPE, intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_TYPE,
mIsAlpha ? StorageManager.CRYPT_TYPE_PASSWORD mIsAlpha ? StorageManager.CRYPT_TYPE_PASSWORD
: StorageManager.CRYPT_TYPE_PIN); : StorageManager.CRYPT_TYPE_PIN);
intent.putExtra( intent.putExtra(
ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD, pin); ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD, credential);
} }
mCredentialCheckResultTracker.setResult(matched, intent, timeoutMs, mCredentialCheckResultTracker.setResult(matched, intent, timeoutMs,
localEffectiveUserId); localEffectiveUserId);

View File

@@ -37,6 +37,7 @@ import com.android.internal.widget.LockPatternChecker;
import com.android.internal.widget.LockPatternUtils; import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.LockPatternView; import com.android.internal.widget.LockPatternView;
import com.android.internal.widget.LockPatternView.Cell; import com.android.internal.widget.LockPatternView.Cell;
import com.android.internal.widget.LockscreenCredential;
import com.android.settings.R; import com.android.settings.R;
import com.android.settingslib.animation.AppearAnimationCreator; import com.android.settingslib.animation.AppearAnimationCreator;
import com.android.settingslib.animation.AppearAnimationUtils; import com.android.settingslib.animation.AppearAnimationUtils;
@@ -401,14 +402,16 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity {
final boolean verifyChallenge = getActivity().getIntent().getBooleanExtra( final boolean verifyChallenge = getActivity().getIntent().getBooleanExtra(
ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, false); ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, false);
final LockscreenCredential credential = LockscreenCredential.createPattern(pattern);
//TODO: how to sanitize this?
Intent intent = new Intent(); Intent intent = new Intent();
if (verifyChallenge) { if (verifyChallenge) {
if (isInternalActivity()) { if (isInternalActivity()) {
startVerifyPattern(pattern, intent); startVerifyPattern(credential, intent);
return; return;
} }
} else { } else {
startCheckPattern(pattern, intent); startCheckPattern(credential, intent);
return; return;
} }
@@ -419,7 +422,7 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity {
return getActivity() instanceof ConfirmLockPattern.InternalActivity; return getActivity() instanceof ConfirmLockPattern.InternalActivity;
} }
private void startVerifyPattern(final List<LockPatternView.Cell> pattern, private void startVerifyPattern(final LockscreenCredential pattern,
final Intent intent) { final Intent intent) {
final int localEffectiveUserId = mEffectiveUserId; final int localEffectiveUserId = mEffectiveUserId;
final int localUserId = mUserId; final int localUserId = mUserId;
@@ -444,15 +447,15 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity {
} }
}; };
mPendingLockCheck = (localEffectiveUserId == localUserId) mPendingLockCheck = (localEffectiveUserId == localUserId)
? LockPatternChecker.verifyPattern( ? LockPatternChecker.verifyCredential(
mLockPatternUtils, pattern, challenge, localUserId, mLockPatternUtils, pattern, challenge, localUserId,
onVerifyCallback) onVerifyCallback)
: LockPatternChecker.verifyTiedProfileChallenge( : LockPatternChecker.verifyTiedProfileChallenge(
mLockPatternUtils, LockPatternUtils.patternToByteArray(pattern), mLockPatternUtils, pattern,
true, challenge, localUserId, onVerifyCallback); challenge, localUserId, onVerifyCallback);
} }
private void startCheckPattern(final List<LockPatternView.Cell> pattern, private void startCheckPattern(final LockscreenCredential pattern,
final Intent intent) { final Intent intent) {
if (pattern.size() < LockPatternUtils.MIN_PATTERN_REGISTER_FAIL) { if (pattern.size() < LockPatternUtils.MIN_PATTERN_REGISTER_FAIL) {
// Pattern size is less than the minimum, do not count it as an fail attempt. // Pattern size is less than the minimum, do not count it as an fail attempt.
@@ -461,7 +464,7 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity {
} }
final int localEffectiveUserId = mEffectiveUserId; final int localEffectiveUserId = mEffectiveUserId;
mPendingLockCheck = LockPatternChecker.checkPattern( mPendingLockCheck = LockPatternChecker.checkCredential(
mLockPatternUtils, mLockPatternUtils,
pattern, pattern,
localEffectiveUserId, localEffectiveUserId,
@@ -473,7 +476,7 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity {
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_TYPE, intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_TYPE,
StorageManager.CRYPT_TYPE_PATTERN); StorageManager.CRYPT_TYPE_PATTERN);
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD, intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD,
LockPatternUtils.patternToByteArray(pattern)); pattern);
} }
mCredentialCheckResultTracker.setResult(matched, intent, timeoutMs, mCredentialCheckResultTracker.setResult(matched, intent, timeoutMs,
localEffectiveUserId); localEffectiveUserId);

View File

@@ -19,6 +19,8 @@ package com.android.settings.password;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import com.android.internal.widget.LockscreenCredential;
/** /**
* Helper for handling managed passwords in security settings UI. * Helper for handling managed passwords in security settings UI.
* It provides resources that should be shown in settings UI when lock password quality is set to * It provides resources that should be shown in settings UI when lock password quality is set to
@@ -59,7 +61,7 @@ public class ManagedLockPasswordProvider {
* @param password Current lock password. * @param password Current lock password.
* @return Intent that should update lock password to a managed password. * @return Intent that should update lock password to a managed password.
*/ */
Intent createIntent(boolean requirePasswordToDecrypt, byte[] password) { Intent createIntent(boolean requirePasswordToDecrypt, LockscreenCredential password) {
return null; return null;
} }
} }

View File

@@ -37,6 +37,7 @@ import android.widget.Button;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
import androidx.preference.Preference; import androidx.preference.Preference;
import com.android.internal.widget.LockscreenCredential;
import com.android.settings.CryptKeeperConfirm; import com.android.settings.CryptKeeperConfirm;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.SettingsActivity; import com.android.settings.SettingsActivity;
@@ -193,9 +194,10 @@ public class CryptKeeperSettings extends InstrumentedPreferenceFragment {
// confirmation prompt; otherwise, go back to the initial state. // confirmation prompt; otherwise, go back to the initial state.
if (resultCode == Activity.RESULT_OK && data != null) { if (resultCode == Activity.RESULT_OK && data != null) {
int type = data.getIntExtra(ChooseLockSettingsHelper.EXTRA_KEY_TYPE, -1); int type = data.getIntExtra(ChooseLockSettingsHelper.EXTRA_KEY_TYPE, -1);
byte[] password = data.getByteArrayExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD); LockscreenCredential password = data.getParcelableExtra(
if (!(password == null || password.length == 0)) { ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
showFinalConfirmation(type, password); if (password != null && !password.isNone()) {
showFinalConfirmation(type, password.getCredential());
} }
} }
} }

View File

@@ -32,6 +32,7 @@ import androidx.preference.Preference;
import androidx.preference.PreferenceScreen; import androidx.preference.PreferenceScreen;
import com.android.internal.widget.LockPatternUtils; import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.LockscreenCredential;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.Utils; import com.android.settings.Utils;
import com.android.settings.core.PreferenceControllerMixin; import com.android.settings.core.PreferenceControllerMixin;
@@ -70,8 +71,8 @@ public class LockUnificationPreferenceController extends AbstractPreferenceContr
private RestrictedSwitchPreference mUnifyProfile; private RestrictedSwitchPreference mUnifyProfile;
private byte[] mCurrentDevicePassword; private LockscreenCredential mCurrentDevicePassword;
private byte[] mCurrentProfilePassword; private LockscreenCredential mCurrentProfilePassword;
private boolean mKeepDeviceLock; private boolean mKeepDeviceLock;
@Override @Override
@@ -89,6 +90,8 @@ public class LockUnificationPreferenceController extends AbstractPreferenceContr
.getSecurityFeatureProvider() .getSecurityFeatureProvider()
.getLockPatternUtils(context); .getLockPatternUtils(context);
mProfileUserId = Utils.getManagedProfileId(mUm, MY_USER_ID); mProfileUserId = Utils.getManagedProfileId(mUm, MY_USER_ID);
mCurrentDevicePassword = LockscreenCredential.createNone();
mCurrentProfilePassword = LockscreenCredential.createNone();
} }
@Override @Override
@@ -151,13 +154,13 @@ public class LockUnificationPreferenceController extends AbstractPreferenceContr
} else if (requestCode == UNIFY_LOCK_CONFIRM_DEVICE_REQUEST } else if (requestCode == UNIFY_LOCK_CONFIRM_DEVICE_REQUEST
&& resultCode == Activity.RESULT_OK) { && resultCode == Activity.RESULT_OK) {
mCurrentDevicePassword = mCurrentDevicePassword =
data.getByteArrayExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD); data.getParcelableExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
launchConfirmProfileLock(); launchConfirmProfileLock();
return true; return true;
} else if (requestCode == UNIFY_LOCK_CONFIRM_PROFILE_REQUEST } else if (requestCode == UNIFY_LOCK_CONFIRM_PROFILE_REQUEST
&& resultCode == Activity.RESULT_OK) { && resultCode == Activity.RESULT_OK) {
mCurrentProfilePassword = mCurrentProfilePassword =
data.getByteArrayExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD); data.getParcelableExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
unifyLocks(); unifyLocks();
return true; return true;
} }
@@ -221,17 +224,8 @@ public class LockUnificationPreferenceController extends AbstractPreferenceContr
} }
private void unifyKeepingWorkLock() { private void unifyKeepingWorkLock() {
final int profileQuality = mLockPatternUtils.setLockCredential(
mLockPatternUtils.getKeyguardStoredPasswordQuality(mProfileUserId); mCurrentProfilePassword, mCurrentDevicePassword, MY_USER_ID);
// PASSWORD_QUALITY_SOMETHING means pattern, everything above means PIN/password.
if (profileQuality == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING) {
mLockPatternUtils.saveLockPattern(
LockPatternUtils.byteArrayToPattern(mCurrentProfilePassword),
mCurrentDevicePassword, MY_USER_ID);
} else {
mLockPatternUtils.saveLockPassword(
mCurrentProfilePassword, mCurrentDevicePassword, profileQuality, MY_USER_ID);
}
mLockPatternUtils.setSeparateProfileChallengeEnabled(mProfileUserId, false, mLockPatternUtils.setSeparateProfileChallengeEnabled(mProfileUserId, false,
mCurrentProfilePassword); mCurrentProfilePassword);
final boolean profilePatternVisibility = final boolean profilePatternVisibility =

View File

@@ -41,6 +41,7 @@ import android.app.admin.DevicePolicyManager.PasswordComplexity;
import android.content.Intent; import android.content.Intent;
import android.os.UserHandle; import android.os.UserHandle;
import com.android.internal.widget.LockscreenCredential;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.password.ChooseLockPassword.ChooseLockPasswordFragment; import com.android.settings.password.ChooseLockPassword.ChooseLockPasswordFragment;
import com.android.settings.password.ChooseLockPassword.IntentBuilder; import com.android.settings.password.ChooseLockPassword.IntentBuilder;
@@ -87,7 +88,7 @@ public class ChooseLockPasswordTest {
@Test @Test
public void intentBuilder_setPassword_shouldAddExtras() { public void intentBuilder_setPassword_shouldAddExtras() {
Intent intent = new IntentBuilder(application) Intent intent = new IntentBuilder(application)
.setPassword("password".getBytes()) .setPassword(LockscreenCredential.createPassword("password"))
.setPasswordQuality(DevicePolicyManager.PASSWORD_QUALITY_NUMERIC) .setPasswordQuality(DevicePolicyManager.PASSWORD_QUALITY_NUMERIC)
.setUserId(123) .setUserId(123)
.build(); .build();
@@ -95,9 +96,10 @@ public class ChooseLockPasswordTest {
assertThat(intent.getBooleanExtra(ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, true)) assertThat(intent.getBooleanExtra(ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, true))
.named("EXTRA_KEY_HAS_CHALLENGE") .named("EXTRA_KEY_HAS_CHALLENGE")
.isFalse(); .isFalse();
assertThat(intent.getByteArrayExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD)) assertThat((LockscreenCredential) intent.getParcelableExtra(
ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD))
.named("EXTRA_KEY_PASSWORD") .named("EXTRA_KEY_PASSWORD")
.isEqualTo("password".getBytes()); .isEqualTo(LockscreenCredential.createPassword("password"));
assertThat(intent.getIntExtra(PASSWORD_TYPE_KEY, 0)) assertThat(intent.getIntExtra(PASSWORD_TYPE_KEY, 0))
.named("PASSWORD_TYPE_KEY") .named("PASSWORD_TYPE_KEY")
.isEqualTo(DevicePolicyManager.PASSWORD_QUALITY_NUMERIC); .isEqualTo(DevicePolicyManager.PASSWORD_QUALITY_NUMERIC);
@@ -154,7 +156,7 @@ public class ChooseLockPasswordTest {
assertPasswordValidationResult( assertPasswordValidationResult(
/* minComplexity= */ PASSWORD_COMPLEXITY_NONE, /* minComplexity= */ PASSWORD_COMPLEXITY_NONE,
/* passwordType= */ PASSWORD_QUALITY_ALPHABETIC, /* passwordType= */ PASSWORD_QUALITY_ALPHABETIC,
/* userEnteredPassword= */ "", /* userEnteredPassword= */ LockscreenCredential.createNone(),
"Must contain at least 1 letter", "Must contain at least 1 letter",
"Must be at least 10 characters"); "Must be at least 10 characters");
} }
@@ -166,7 +168,7 @@ public class ChooseLockPasswordTest {
assertPasswordValidationResult( assertPasswordValidationResult(
/* minComplexity= */ PASSWORD_COMPLEXITY_HIGH, /* minComplexity= */ PASSWORD_COMPLEXITY_HIGH,
/* passwordType= */ PASSWORD_QUALITY_NUMERIC, /* passwordType= */ PASSWORD_QUALITY_NUMERIC,
/* userEnteredPassword= */ "", /* userEnteredPassword= */ LockscreenCredential.createNone(),
"PIN must be at least 8 digits"); "PIN must be at least 8 digits");
} }
@@ -177,7 +179,7 @@ public class ChooseLockPasswordTest {
assertPasswordValidationResult( assertPasswordValidationResult(
/* minComplexity= */ PASSWORD_COMPLEXITY_MEDIUM, /* minComplexity= */ PASSWORD_COMPLEXITY_MEDIUM,
/* passwordType= */ PASSWORD_QUALITY_ALPHABETIC, /* passwordType= */ PASSWORD_QUALITY_ALPHABETIC,
/* userEnteredPassword= */ "", /* userEnteredPassword= */ LockscreenCredential.createNone(),
"Must contain at least 1 letter", "Must contain at least 1 letter",
"Must be at least 4 characters"); "Must be at least 4 characters");
} }
@@ -190,7 +192,7 @@ public class ChooseLockPasswordTest {
assertPasswordValidationResult( assertPasswordValidationResult(
/* minComplexity= */ PASSWORD_COMPLEXITY_LOW, /* minComplexity= */ PASSWORD_COMPLEXITY_LOW,
/* passwordType= */ PASSWORD_QUALITY_ALPHABETIC, /* passwordType= */ PASSWORD_QUALITY_ALPHABETIC,
/* userEnteredPassword= */ "", /* userEnteredPassword= */ LockscreenCredential.createNone(),
"Must contain at least 1 letter", "Must contain at least 1 letter",
"Must contain at least 1 numerical digit", "Must contain at least 1 numerical digit",
"Must be at least 9 characters"); "Must be at least 9 characters");
@@ -204,7 +206,7 @@ public class ChooseLockPasswordTest {
assertPasswordValidationResult( assertPasswordValidationResult(
/* minComplexity= */ PASSWORD_COMPLEXITY_MEDIUM, /* minComplexity= */ PASSWORD_COMPLEXITY_MEDIUM,
/* passwordType= */ PASSWORD_QUALITY_NUMERIC, /* passwordType= */ PASSWORD_QUALITY_NUMERIC,
/* userEnteredPassword= */ "", /* userEnteredPassword= */ LockscreenCredential.createNone(),
"PIN must be at least 11 digits"); "PIN must be at least 11 digits");
} }
@@ -216,7 +218,7 @@ public class ChooseLockPasswordTest {
assertPasswordValidationResult( assertPasswordValidationResult(
/* minComplexity= */ PASSWORD_COMPLEXITY_HIGH, /* minComplexity= */ PASSWORD_COMPLEXITY_HIGH,
/* passwordType= */ PASSWORD_QUALITY_ALPHABETIC, /* passwordType= */ PASSWORD_QUALITY_ALPHABETIC,
/* userEnteredPassword= */ "", /* userEnteredPassword= */ LockscreenCredential.createNone(),
"Must contain at least 2 special symbols", "Must contain at least 2 special symbols",
"Must be at least 6 characters"); "Must be at least 6 characters");
} }
@@ -229,7 +231,7 @@ public class ChooseLockPasswordTest {
assertPasswordValidationResult( assertPasswordValidationResult(
/* minComplexity= */ PASSWORD_COMPLEXITY_NONE, /* minComplexity= */ PASSWORD_COMPLEXITY_NONE,
/* passwordType= */ PASSWORD_QUALITY_NUMERIC, /* passwordType= */ PASSWORD_QUALITY_NUMERIC,
/* userEnteredPassword= */ "12345678", /* userEnteredPassword= */ LockscreenCredential.createPassword("12345678"),
"Ascending, descending, or repeated sequence of digits isn't allowed"); "Ascending, descending, or repeated sequence of digits isn't allowed");
} }
@@ -241,7 +243,7 @@ public class ChooseLockPasswordTest {
assertPasswordValidationResult( assertPasswordValidationResult(
/* minComplexity= */ PASSWORD_COMPLEXITY_NONE, /* minComplexity= */ PASSWORD_COMPLEXITY_NONE,
/* passwordType= */ PASSWORD_QUALITY_ALPHABETIC, /* passwordType= */ PASSWORD_QUALITY_ALPHABETIC,
/* userEnteredPassword= */ "12345678", /* userEnteredPassword= */ LockscreenCredential.createPassword("12345678"),
"Ascending, descending, or repeated sequence of digits isn't allowed"); "Ascending, descending, or repeated sequence of digits isn't allowed");
} }
@@ -253,7 +255,7 @@ public class ChooseLockPasswordTest {
assertPasswordValidationResult( assertPasswordValidationResult(
/* minComplexity= */ PASSWORD_COMPLEXITY_HIGH, /* minComplexity= */ PASSWORD_COMPLEXITY_HIGH,
/* passwordType= */ PASSWORD_QUALITY_NUMERIC, /* passwordType= */ PASSWORD_QUALITY_NUMERIC,
/* userEnteredPassword= */ "12345678", /* userEnteredPassword= */ LockscreenCredential.createPassword("12345678"),
"Ascending, descending, or repeated sequence of digits isn't allowed"); "Ascending, descending, or repeated sequence of digits isn't allowed");
} }
@@ -265,7 +267,7 @@ public class ChooseLockPasswordTest {
assertPasswordValidationResult( assertPasswordValidationResult(
/* minComplexity= */ PASSWORD_COMPLEXITY_HIGH, /* minComplexity= */ PASSWORD_COMPLEXITY_HIGH,
/* passwordType= */ PASSWORD_QUALITY_NUMERIC, /* passwordType= */ PASSWORD_QUALITY_NUMERIC,
/* userEnteredPassword= */ "12345678", /* userEnteredPassword= */ LockscreenCredential.createPassword("12345678"),
"Ascending, descending, or repeated sequence of digits isn't allowed"); "Ascending, descending, or repeated sequence of digits isn't allowed");
} }
@@ -277,7 +279,7 @@ public class ChooseLockPasswordTest {
assertPasswordValidationResult( assertPasswordValidationResult(
/* minComplexity= */ PASSWORD_COMPLEXITY_LOW, /* minComplexity= */ PASSWORD_COMPLEXITY_LOW,
/* passwordType= */ PASSWORD_QUALITY_ALPHABETIC, /* passwordType= */ PASSWORD_QUALITY_ALPHABETIC,
/* userEnteredPassword= */ "12345678", /* userEnteredPassword= */ LockscreenCredential.createPassword("12345678"),
"Must contain at least 1 letter"); "Must contain at least 1 letter");
} }
@@ -288,7 +290,7 @@ public class ChooseLockPasswordTest {
assertPasswordValidationResult( assertPasswordValidationResult(
/* minComplexity= */ PASSWORD_COMPLEXITY_HIGH, /* minComplexity= */ PASSWORD_COMPLEXITY_HIGH,
/* passwordType= */ PASSWORD_QUALITY_ALPHABETIC, /* passwordType= */ PASSWORD_QUALITY_ALPHABETIC,
/* userEnteredPassword= */ "", /* userEnteredPassword= */ LockscreenCredential.createNone(),
"Must contain at least 1 letter", "Must contain at least 1 letter",
"Must be at least 6 characters"); "Must be at least 6 characters");
} }
@@ -300,7 +302,7 @@ public class ChooseLockPasswordTest {
assertPasswordValidationResult( assertPasswordValidationResult(
/* minComplexity= */ PASSWORD_COMPLEXITY_HIGH, /* minComplexity= */ PASSWORD_COMPLEXITY_HIGH,
/* passwordType= */ PASSWORD_QUALITY_ALPHABETIC, /* passwordType= */ PASSWORD_QUALITY_ALPHABETIC,
/* userEnteredPassword= */ "1", /* userEnteredPassword= */ LockscreenCredential.createPassword("1"),
"Must contain at least 1 letter", "Must contain at least 1 letter",
"Must be at least 6 characters"); "Must be at least 6 characters");
} }
@@ -312,7 +314,7 @@ public class ChooseLockPasswordTest {
assertPasswordValidationResult( assertPasswordValidationResult(
/* minComplexity= */ PASSWORD_COMPLEXITY_HIGH, /* minComplexity= */ PASSWORD_COMPLEXITY_HIGH,
/* passwordType= */ PASSWORD_QUALITY_ALPHABETIC, /* passwordType= */ PASSWORD_QUALITY_ALPHABETIC,
/* userEnteredPassword= */ "b", /* userEnteredPassword= */ LockscreenCredential.createPassword("b"),
"Must be at least 6 characters"); "Must be at least 6 characters");
} }
@@ -323,7 +325,7 @@ public class ChooseLockPasswordTest {
assertPasswordValidationResult( assertPasswordValidationResult(
/* minComplexity= */ PASSWORD_COMPLEXITY_HIGH, /* minComplexity= */ PASSWORD_COMPLEXITY_HIGH,
/* passwordType= */ PASSWORD_QUALITY_ALPHABETIC, /* passwordType= */ PASSWORD_QUALITY_ALPHABETIC,
/* userEnteredPassword= */ "b1", /* userEnteredPassword= */ LockscreenCredential.createPassword("b1"),
"Must be at least 6 characters"); "Must be at least 6 characters");
} }
@@ -359,16 +361,15 @@ public class ChooseLockPasswordTest {
} }
private void assertPasswordValidationResult(@PasswordComplexity int minComplexity, private void assertPasswordValidationResult(@PasswordComplexity int minComplexity,
int passwordType, String userEnteredPassword, String... expectedValidationResult) { int passwordType, LockscreenCredential userEnteredPassword,
String... expectedValidationResult) {
Intent intent = new Intent(); Intent intent = new Intent();
intent.putExtra(CONFIRM_CREDENTIALS, false); intent.putExtra(CONFIRM_CREDENTIALS, false);
intent.putExtra(PASSWORD_TYPE_KEY, passwordType); intent.putExtra(PASSWORD_TYPE_KEY, passwordType);
intent.putExtra(EXTRA_KEY_REQUESTED_MIN_COMPLEXITY, minComplexity); intent.putExtra(EXTRA_KEY_REQUESTED_MIN_COMPLEXITY, minComplexity);
ChooseLockPassword activity = buildChooseLockPasswordActivity(intent); ChooseLockPassword activity = buildChooseLockPasswordActivity(intent);
ChooseLockPasswordFragment fragment = getChooseLockPasswordFragment(activity); ChooseLockPasswordFragment fragment = getChooseLockPasswordFragment(activity);
byte[] userEnteredPasswordBytes = userEnteredPassword != null int validateResult = fragment.validatePassword(userEnteredPassword);
? userEnteredPassword.getBytes() : null;
int validateResult = fragment.validatePassword(userEnteredPasswordBytes);
String[] messages = fragment.convertErrorCodeToMessages(validateResult); String[] messages = fragment.convertErrorCodeToMessages(validateResult);
assertThat(messages).asList().containsExactly((Object[]) expectedValidationResult); assertThat(messages).asList().containsExactly((Object[]) expectedValidationResult);

View File

@@ -24,6 +24,8 @@ import android.content.Intent;
import android.os.UserHandle; import android.os.UserHandle;
import android.view.View; import android.view.View;
import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.LockscreenCredential;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.password.ChooseLockPattern.ChooseLockPatternFragment; import com.android.settings.password.ChooseLockPattern.ChooseLockPatternFragment;
import com.android.settings.password.ChooseLockPattern.IntentBuilder; import com.android.settings.password.ChooseLockPattern.IntentBuilder;
@@ -52,7 +54,7 @@ public class ChooseLockPatternTest {
@Test @Test
public void intentBuilder_setPattern_shouldAddExtras() { public void intentBuilder_setPattern_shouldAddExtras() {
Intent intent = new IntentBuilder(application) Intent intent = new IntentBuilder(application)
.setPattern("pattern".getBytes()) .setPattern(createPattern("1234"))
.setUserId(123) .setUserId(123)
.build(); .build();
@@ -60,10 +62,10 @@ public class ChooseLockPatternTest {
.getBooleanExtra(ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, true)) .getBooleanExtra(ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, true))
.named("EXTRA_KEY_HAS_CHALLENGE") .named("EXTRA_KEY_HAS_CHALLENGE")
.isFalse(); .isFalse();
assertThat(intent assertThat((LockscreenCredential) intent
.getByteArrayExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD)) .getParcelableExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD))
.named("EXTRA_KEY_PASSWORD") .named("EXTRA_KEY_PASSWORD")
.isEqualTo("pattern".getBytes()); .isEqualTo(createPattern("1234"));
assertThat(intent.getIntExtra(Intent.EXTRA_USER_ID, 0)) assertThat(intent.getIntExtra(Intent.EXTRA_USER_ID, 0))
.named("EXTRA_USER_ID") .named("EXTRA_USER_ID")
.isEqualTo(123); .isEqualTo(123);
@@ -120,4 +122,9 @@ public class ChooseLockPatternTest {
.build()) .build())
.setup().get(); .setup().get();
} }
private LockscreenCredential createPattern(String patternString) {
return LockscreenCredential.createPattern(LockPatternUtils.byteArrayToPattern(
patternString.getBytes()));
}
} }

View File

@@ -20,6 +20,7 @@ import android.app.admin.DevicePolicyManager;
import android.content.ComponentName; import android.content.ComponentName;
import com.android.internal.widget.LockPatternUtils; import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.LockscreenCredential;
import org.robolectric.annotation.Implementation; import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements; import org.robolectric.annotation.Implements;
@@ -66,7 +67,8 @@ public class ShadowLockPatternUtils {
} }
@Implementation @Implementation
protected byte[] getPasswordHistoryHashFactor(byte[] currentPassword, int userId) { protected byte[] getPasswordHistoryHashFactor(LockscreenCredential currentPassword,
int userId) {
return null; return null;
} }

View File

@@ -43,6 +43,7 @@ import androidx.test.runner.lifecycle.ActivityLifecycleMonitorRegistry;
import androidx.test.runner.lifecycle.Stage; import androidx.test.runner.lifecycle.Stage;
import com.android.internal.widget.LockPatternUtils; import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.LockscreenCredential;
import org.junit.Before; import org.junit.Before;
import org.junit.Rule; import org.junit.Rule;
@@ -150,7 +151,7 @@ public class ChooseLockGenericTest {
.putExtra(LockPatternUtils.PASSWORD_TYPE_KEY, .putExtra(LockPatternUtils.PASSWORD_TYPE_KEY,
DevicePolicyManager.PASSWORD_QUALITY_NUMERIC) DevicePolicyManager.PASSWORD_QUALITY_NUMERIC)
.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD, .putExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD,
"12345") LockscreenCredential.createPin("12345"))
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getInstrumentation().getContext().startActivity(newPasswordIntent); getInstrumentation().getContext().startActivity(newPasswordIntent);
mDevice.waitForIdle(); mDevice.waitForIdle();