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

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