Migrate settings UI to use async security check

Bug: 20697812
Change-Id: Ieb0090ddb61198a60abb1e34ff9c6e8476c33789
This commit is contained in:
Xiyuan Xia
2015-05-05 16:04:00 -07:00
parent ec36780b6a
commit bf9ac6b4fb
4 changed files with 255 additions and 59 deletions

View File

@@ -17,6 +17,7 @@
package com.android.settings; package com.android.settings;
import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.MetricsLogger;
import com.android.internal.widget.LockPatternChecker;
import com.android.internal.widget.LockPatternUtils; import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.PasswordEntryKeyboardHelper; import com.android.internal.widget.PasswordEntryKeyboardHelper;
import com.android.internal.widget.PasswordEntryKeyboardView; import com.android.internal.widget.PasswordEntryKeyboardView;
@@ -28,6 +29,7 @@ import android.app.admin.DevicePolicyManager;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.inputmethodservice.KeyboardView; import android.inputmethodservice.KeyboardView;
import android.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.Message; import android.os.Message;
@@ -134,6 +136,7 @@ public class ChooseLockPassword extends SettingsActivity {
private int mPasswordMinNumeric = 0; private int mPasswordMinNumeric = 0;
private int mPasswordMinNonLetter = 0; private int mPasswordMinNonLetter = 0;
private LockPatternUtils mLockPatternUtils; private LockPatternUtils mLockPatternUtils;
private AsyncTask<?, ?, ?> mPendingLockCheck;
private int mRequestedQuality = DevicePolicyManager.PASSWORD_QUALITY_NUMERIC; private int mRequestedQuality = DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
private ChooseLockSettingsHelper mChooseLockSettingsHelper; private ChooseLockSettingsHelper mChooseLockSettingsHelper;
private Stage mUiStage = Stage.Introduction; private Stage mUiStage = Stage.Introduction;
@@ -312,12 +315,17 @@ public class ChooseLockPassword extends SettingsActivity {
public void onResume() { public void onResume() {
super.onResume(); super.onResume();
updateStage(mUiStage); updateStage(mUiStage);
mPasswordEntry.setEnabled(true);
mKeyboardView.requestFocus(); mKeyboardView.requestFocus();
} }
@Override @Override
public void onPause() { public void onPause() {
mHandler.removeMessages(MSG_SHOW_ERROR); mHandler.removeMessages(MSG_SHOW_ERROR);
if (mPendingLockCheck != null) {
mPendingLockCheck.cancel(false);
mPendingLockCheck = null;
}
super.onPause(); super.onPause();
} }
@@ -489,19 +497,12 @@ public class ChooseLockPassword extends SettingsActivity {
UserHandle.myUserId()); UserHandle.myUserId());
if (mHasChallenge) { if (mHasChallenge) {
Intent intent = new Intent(); startVerifyPassword(pin, wasSecureBefore);
byte[] token = mLockPatternUtils.verifyPassword(pin, mChallenge, return;
UserHandle.myUserId());
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token);
getActivity().setResult(RESULT_FINISHED, intent);
} else { } else {
getActivity().setResult(RESULT_FINISHED); getActivity().setResult(RESULT_FINISHED);
} }
getActivity().finish(); finishConfirmStage(wasSecureBefore);
mDone = true;
if (!wasSecureBefore) {
startActivity(getRedactionInterstitialIntent(getActivity()));
}
} else { } else {
CharSequence tmp = mPasswordEntry.getText(); CharSequence tmp = mPasswordEntry.getText();
if (tmp != null) { if (tmp != null) {
@@ -515,6 +516,43 @@ public class ChooseLockPassword extends SettingsActivity {
} }
} }
private void startVerifyPassword(final String pin, final boolean wasSecureBefore) {
mPasswordEntry.setEnabled(false);
setNextEnabled(false);
if (mPendingLockCheck != null) {
mPendingLockCheck.cancel(false);
}
mPendingLockCheck = LockPatternChecker.verifyPassword(
mLockPatternUtils,
pin,
mChallenge,
UserHandle.myUserId(),
new LockPatternChecker.OnVerifyCallback() {
@Override
public void onVerified(byte[] token) {
mPasswordEntry.setEnabled(true);
setNextEnabled(true);
mPendingLockCheck = null;
Intent intent = new Intent();
intent.putExtra(
ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN,
token);
getActivity().setResult(RESULT_FINISHED, intent);
finishConfirmStage(wasSecureBefore);
}
});
}
private void finishConfirmStage(boolean wasSecureBefore) {
getActivity().finish();
mDone = true;
if (!wasSecureBefore) {
startActivity(getRedactionInterstitialIntent(getActivity()));
}
}
protected void setNextEnabled(boolean enabled) { protected void setNextEnabled(boolean enabled) {
mNextButton.setEnabled(enabled); mNextButton.setEnabled(enabled);
} }

View File

@@ -19,6 +19,7 @@ package com.android.settings;
import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.MetricsLogger;
import com.google.android.collect.Lists; import com.google.android.collect.Lists;
import com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient; import com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient;
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;
@@ -30,6 +31,7 @@ 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.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
import android.os.UserHandle; import android.os.UserHandle;
import android.view.KeyEvent; import android.view.KeyEvent;
@@ -350,6 +352,7 @@ public class ChooseLockPattern extends SettingsActivity {
}; };
private ChooseLockSettingsHelper mChooseLockSettingsHelper; private ChooseLockSettingsHelper mChooseLockSettingsHelper;
private AsyncTask<?, ?, ?> mPendingLockCheck;
private static final String KEY_UI_STAGE = "uiStage"; private static final String KEY_UI_STAGE = "uiStage";
private static final String KEY_PATTERN_CHOICE = "chosenPattern"; private static final String KEY_PATTERN_CHOICE = "chosenPattern";
@@ -432,6 +435,21 @@ public class ChooseLockPattern extends SettingsActivity {
mDone = false; mDone = false;
} }
@Override
public void onResume() {
super.onResume();
mLockPatternView.enableInput();
}
@Override
public void onPause() {
super.onPause();
if (mPendingLockCheck != null) {
mPendingLockCheck.cancel(false);
mPendingLockCheck = null;
}
}
protected Intent getRedactionInterstitialIntent(Context context) { protected Intent getRedactionInterstitialIntent(Context context) {
return RedactionInterstitial.createStartIntent(context); return RedactionInterstitial.createStartIntent(context);
} }
@@ -623,15 +641,42 @@ public class ChooseLockPattern extends SettingsActivity {
} }
if (mHasChallenge) { if (mHasChallenge) {
Intent intent = new Intent(); startVerifyPattern(utils);
byte[] token = utils.verifyPattern(mChosenPattern, mChallenge, return;
UserHandle.myUserId());
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token);
getActivity().setResult(RESULT_FINISHED, intent);
} else { } else {
getActivity().setResult(RESULT_FINISHED); getActivity().setResult(RESULT_FINISHED);
} }
doFinish();
}
private void startVerifyPattern(LockPatternUtils utils) {
mLockPatternView.disableInput();
if (mPendingLockCheck != null) {
mPendingLockCheck.cancel(false);
}
mPendingLockCheck = LockPatternChecker.verifyPattern(
utils,
mChosenPattern,
mChallenge,
UserHandle.myUserId(),
new LockPatternChecker.OnVerifyCallback() {
@Override
public void onVerified(byte[] token) {
mLockPatternView.enableInput();
mPendingLockCheck = null;
Intent intent = new Intent();
intent.putExtra(
ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token);
getActivity().setResult(RESULT_FINISHED, intent);
doFinish();
}
});
}
private void doFinish() {
getActivity().finish(); getActivity().finish();
mDone = true; mDone = true;
} }

View File

@@ -20,10 +20,12 @@ import android.annotation.Nullable;
import android.os.UserHandle; import android.os.UserHandle;
import android.text.TextUtils; import android.text.TextUtils;
import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.MetricsLogger;
import com.android.internal.widget.LockPatternChecker;
import com.android.internal.widget.LockPatternUtils; import com.android.internal.widget.LockPatternUtils;
import android.app.admin.DevicePolicyManager; import android.app.admin.DevicePolicyManager;
import android.content.Intent; import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
import android.os.CountDownTimer; import android.os.CountDownTimer;
import android.os.Handler; import android.os.Handler;
@@ -65,6 +67,7 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
private static final long ERROR_MESSAGE_TIMEOUT = 3000; private static final long ERROR_MESSAGE_TIMEOUT = 3000;
private TextView mPasswordEntry; private TextView mPasswordEntry;
private LockPatternUtils mLockPatternUtils; private LockPatternUtils mLockPatternUtils;
private AsyncTask<?, ?, ?> mPendingLockCheck;
private TextView mHeaderTextView; private TextView mHeaderTextView;
private TextView mDetailsTextView; private TextView mDetailsTextView;
private TextView mErrorTextView; private TextView mErrorTextView;
@@ -148,6 +151,10 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
mCountdownTimer.cancel(); mCountdownTimer.cancel();
mCountdownTimer = null; mCountdownTimer = null;
} }
if (mPendingLockCheck != null) {
mPendingLockCheck.cancel(false);
mPendingLockCheck = null;
}
} }
@Override @Override
@@ -161,6 +168,8 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
long deadline = mLockPatternUtils.getLockoutAttemptDeadline(UserHandle.myUserId()); long deadline = mLockPatternUtils.getLockoutAttemptDeadline(UserHandle.myUserId());
if (deadline != 0) { if (deadline != 0) {
handleAttemptLockout(deadline); handleAttemptLockout(deadline);
} else {
mPasswordEntry.setEnabled(true);
} }
} }
@@ -178,32 +187,79 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
} }
private void handleNext() { private void handleNext() {
mPasswordEntry.setEnabled(false);
if (mPendingLockCheck != null) {
mPendingLockCheck.cancel(false);
}
final String pin = mPasswordEntry.getText().toString(); final String pin = mPasswordEntry.getText().toString();
final boolean verifyChallenge = getActivity().getIntent().getBooleanExtra( final boolean verifyChallenge = getActivity().getIntent().getBooleanExtra(
ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, false); ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, false);
boolean matched = false;
Intent intent = new Intent(); Intent intent = new Intent();
if (verifyChallenge) { if (verifyChallenge) {
if (getActivity() instanceof ConfirmLockPassword.InternalActivity) { if (isInternalActivity()) {
long challenge = getActivity().getIntent().getLongExtra( startVerifyPassword(pin, intent);
ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, 0); return;
byte[] token = mLockPatternUtils.verifyPassword(pin, challenge,
UserHandle.myUserId());
if (token != null) {
matched = true;
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token);
}
}
} else if (mLockPatternUtils.checkPassword(pin, UserHandle.myUserId())) {
matched = true;
if (getActivity() instanceof ConfirmLockPassword.InternalActivity) {
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_TYPE,
mIsAlpha ? StorageManager.CRYPT_TYPE_PASSWORD
: StorageManager.CRYPT_TYPE_PIN);
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD, pin);
} }
} else {
startCheckPassword(pin, intent);
return;
} }
onPasswordChecked(false, intent);
}
private boolean isInternalActivity() {
return getActivity() instanceof ConfirmLockPassword.InternalActivity;
}
private void startVerifyPassword(final String pin, final Intent intent) {
long challenge = getActivity().getIntent().getLongExtra(
ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, 0);
mPendingLockCheck = LockPatternChecker.verifyPassword(
mLockPatternUtils,
pin,
challenge,
UserHandle.myUserId(),
new LockPatternChecker.OnVerifyCallback() {
@Override
public void onVerified(byte[] token) {
mPendingLockCheck = null;
boolean matched = false;
if (token != null) {
matched = true;
intent.putExtra(
ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN,
token);
}
onPasswordChecked(matched, intent);
}
});
}
private void startCheckPassword(final String pin, final Intent intent) {
mPendingLockCheck = LockPatternChecker.checkPassword(
mLockPatternUtils,
pin,
UserHandle.myUserId(),
new LockPatternChecker.OnCheckCallback() {
@Override
public void onChecked(boolean matched) {
mPendingLockCheck = null;
if (matched && isInternalActivity()) {
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_TYPE,
mIsAlpha ? StorageManager.CRYPT_TYPE_PASSWORD
: StorageManager.CRYPT_TYPE_PIN);
intent.putExtra(
ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD, pin);
}
onPasswordChecked(matched, intent);
}
});
}
private void onPasswordChecked(boolean matched, Intent intent) {
mPasswordEntry.setEnabled(true);
if (matched) { if (matched) {
getActivity().setResult(RESULT_OK, intent); getActivity().setResult(RESULT_OK, intent);
getActivity().finish(); getActivity().finish();

View File

@@ -20,6 +20,7 @@ import com.android.internal.logging.MetricsLogger;
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.LinearLayoutWithDefaultTouchRecepient; import com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient;
import com.android.internal.widget.LockPatternChecker;
import com.android.internal.widget.LockPatternView.Cell; import com.android.internal.widget.LockPatternView.Cell;
import android.annotation.Nullable; import android.annotation.Nullable;
@@ -27,6 +28,7 @@ import android.app.Activity;
import android.content.Intent; import android.content.Intent;
import android.os.CountDownTimer; import android.os.CountDownTimer;
import android.os.SystemClock; import android.os.SystemClock;
import android.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
import android.os.UserHandle; import android.os.UserHandle;
import android.os.storage.StorageManager; import android.os.storage.StorageManager;
@@ -77,6 +79,7 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity {
private LockPatternView mLockPatternView; private LockPatternView mLockPatternView;
private LockPatternUtils mLockPatternUtils; private LockPatternUtils mLockPatternUtils;
private AsyncTask<?, ?, ?> mPendingLockCheck;
private int mNumWrongConfirmAttempts; private int mNumWrongConfirmAttempts;
private CountDownTimer mCountdownTimer; private CountDownTimer mCountdownTimer;
@@ -157,6 +160,10 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity {
if (mCountdownTimer != null) { if (mCountdownTimer != null) {
mCountdownTimer.cancel(); mCountdownTimer.cancel();
} }
if (mPendingLockCheck != null) {
mPendingLockCheck.cancel(false);
mPendingLockCheck = null;
}
} }
@Override @Override
@@ -173,8 +180,8 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity {
if (deadline != 0) { if (deadline != 0) {
handleAttemptLockout(deadline); handleAttemptLockout(deadline);
} else if (!mLockPatternView.isEnabled()) { } else if (!mLockPatternView.isEnabled()) {
// The deadline has passed, but the timer was cancelled... // The deadline has passed, but the timer was cancelled. Or the pending lock
// Need to clean up. // check was cancelled. Need to clean up.
mNumWrongConfirmAttempts = 0; mNumWrongConfirmAttempts = 0;
updateStage(Stage.NeedToUnlock); updateStage(Stage.NeedToUnlock);
} }
@@ -198,6 +205,7 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity {
mLockPatternView.setEnabled(true); mLockPatternView.setEnabled(true);
mLockPatternView.enableInput(); mLockPatternView.enableInput();
mLockPatternView.clearPattern();
break; break;
case NeedToUnlockWrong: case NeedToUnlockWrong:
mErrorTextView.setText(R.string.lockpattern_need_to_unlock_wrong); mErrorTextView.setText(R.string.lockpattern_need_to_unlock_wrong);
@@ -269,32 +277,81 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity {
} }
public void onPatternDetected(List<LockPatternView.Cell> pattern) { public void onPatternDetected(List<LockPatternView.Cell> pattern) {
final boolean verifyChallenge = getActivity().getIntent().getBooleanExtra( mLockPatternView.setEnabled(false);
ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, false); if (mPendingLockCheck != null) {
boolean matched = false; mPendingLockCheck.cancel(false);
Intent intent = new Intent();
if (verifyChallenge) {
if (getActivity() instanceof ConfirmLockPattern.InternalActivity) {
long challenge = getActivity().getIntent().getLongExtra(
ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, 0);
byte[] token = mLockPatternUtils.verifyPattern(pattern, challenge,
UserHandle.myUserId());
if (token != null) {
matched = true;
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token);
}
}
} else if (mLockPatternUtils.checkPattern(pattern, UserHandle.myUserId())) {
matched = true;
if (getActivity() instanceof ConfirmLockPattern.InternalActivity) {
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_TYPE,
StorageManager.CRYPT_TYPE_PATTERN);
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD,
LockPatternUtils.patternToString(pattern));
}
} }
final boolean verifyChallenge = getActivity().getIntent().getBooleanExtra(
ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, false);
Intent intent = new Intent();
if (verifyChallenge) {
if (isInternalActivity()) {
startVerifyPattern(pattern, intent);
return;
}
} else {
startCheckPattern(pattern, intent);
return;
}
onPatternChecked(pattern, false, intent);
}
private boolean isInternalActivity() {
return getActivity() instanceof ConfirmLockPattern.InternalActivity;
}
private void startVerifyPattern(final List<LockPatternView.Cell> pattern,
final Intent intent) {
long challenge = getActivity().getIntent().getLongExtra(
ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, 0);
mPendingLockCheck = LockPatternChecker.verifyPattern(
mLockPatternUtils,
pattern,
challenge,
UserHandle.myUserId(),
new LockPatternChecker.OnVerifyCallback() {
@Override
public void onVerified(byte[] token) {
mPendingLockCheck = null;
boolean matched = false;
if (token != null) {
matched = true;
intent.putExtra(
ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN,
token);
}
onPatternChecked(pattern, matched, intent);
}
});
}
private void startCheckPattern(final List<LockPatternView.Cell> pattern,
final Intent intent) {
mPendingLockCheck = LockPatternChecker.checkPattern(
mLockPatternUtils,
pattern,
UserHandle.myUserId(),
new LockPatternChecker.OnCheckCallback() {
@Override
public void onChecked(boolean matched) {
mPendingLockCheck = null;
if (matched && isInternalActivity()) {
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_TYPE,
StorageManager.CRYPT_TYPE_PATTERN);
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD,
LockPatternUtils.patternToString(pattern));
}
onPatternChecked(pattern, matched, intent);
}
});
}
private void onPatternChecked(List<LockPatternView.Cell> pattern,
boolean matched,
Intent intent) {
mLockPatternView.setEnabled(true);
if (matched) { if (matched) {
getActivity().setResult(Activity.RESULT_OK, intent); getActivity().setResult(Activity.RESULT_OK, intent);
getActivity().finish(); getActivity().finish();