Clean up choose lock intent creation
Consolidated the many variants of ChooseLock*.createIntent, so that it will take the same set of arguments. Also modified SetupChooseLock*.createIntent to modifyIntentForSetup, which will take the intent created by ChooseLock* and modify it for use with setup. Test: cd tests/robotests && mma Change-Id: I5ff033f459c33ec9980872a536b3996d89f2bbbb
This commit is contained in:
572
src/com/android/settings/password/ConfirmLockPattern.java
Normal file
572
src/com/android/settings/password/ConfirmLockPattern.java
Normal file
@@ -0,0 +1,572 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.password;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.os.CountDownTimer;
|
||||
import android.os.SystemClock;
|
||||
import android.os.UserManager;
|
||||
import android.os.storage.StorageManager;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.animation.AnimationUtils;
|
||||
import android.view.animation.Interpolator;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient;
|
||||
import com.android.internal.widget.LockPatternChecker;
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.internal.widget.LockPatternView;
|
||||
import com.android.internal.widget.LockPatternView.Cell;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SettingsActivity;
|
||||
import com.android.settingslib.animation.AppearAnimationCreator;
|
||||
import com.android.settingslib.animation.AppearAnimationUtils;
|
||||
import com.android.settingslib.animation.DisappearAnimationUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Launch this when you want the user to confirm their lock pattern.
|
||||
*
|
||||
* Sets an activity result of {@link Activity#RESULT_OK} when the user
|
||||
* successfully confirmed their pattern.
|
||||
*/
|
||||
public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity {
|
||||
|
||||
public static class InternalActivity extends ConfirmLockPattern {
|
||||
}
|
||||
|
||||
private enum Stage {
|
||||
NeedToUnlock,
|
||||
NeedToUnlockWrong,
|
||||
LockedOut
|
||||
}
|
||||
|
||||
@Override
|
||||
public Intent getIntent() {
|
||||
Intent modIntent = new Intent(super.getIntent());
|
||||
modIntent.putExtra(EXTRA_SHOW_FRAGMENT, ConfirmLockPatternFragment.class.getName());
|
||||
return modIntent;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isValidFragment(String fragmentName) {
|
||||
if (ConfirmLockPatternFragment.class.getName().equals(fragmentName)) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public static class ConfirmLockPatternFragment extends ConfirmDeviceCredentialBaseFragment
|
||||
implements AppearAnimationCreator<Object>, CredentialCheckResultTracker.Listener {
|
||||
|
||||
// how long we wait to clear a wrong pattern
|
||||
private static final int WRONG_PATTERN_CLEAR_TIMEOUT_MS = 2000;
|
||||
|
||||
private static final String FRAGMENT_TAG_CHECK_LOCK_RESULT = "check_lock_result";
|
||||
|
||||
private LockPatternView mLockPatternView;
|
||||
private AsyncTask<?, ?, ?> mPendingLockCheck;
|
||||
private CredentialCheckResultTracker mCredentialCheckResultTracker;
|
||||
private boolean mDisappearing = false;
|
||||
private CountDownTimer mCountdownTimer;
|
||||
|
||||
private TextView mHeaderTextView;
|
||||
private TextView mDetailsTextView;
|
||||
private View mLeftSpacerLandscape;
|
||||
private View mRightSpacerLandscape;
|
||||
|
||||
// caller-supplied text for various prompts
|
||||
private CharSequence mHeaderText;
|
||||
private CharSequence mDetailsText;
|
||||
|
||||
private AppearAnimationUtils mAppearAnimationUtils;
|
||||
private DisappearAnimationUtils mDisappearAnimationUtils;
|
||||
|
||||
// required constructor for fragments
|
||||
public ConfirmLockPatternFragment() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
ConfirmLockPattern activity = (ConfirmLockPattern) getActivity();
|
||||
View view = inflater.inflate(
|
||||
activity.getConfirmCredentialTheme() == ConfirmCredentialTheme.INTERNAL
|
||||
? R.layout.confirm_lock_pattern_internal
|
||||
: R.layout.confirm_lock_pattern,
|
||||
container,
|
||||
false);
|
||||
mHeaderTextView = (TextView) view.findViewById(R.id.headerText);
|
||||
mLockPatternView = (LockPatternView) view.findViewById(R.id.lockPattern);
|
||||
mDetailsTextView = (TextView) view.findViewById(R.id.detailsText);
|
||||
mErrorTextView = (TextView) view.findViewById(R.id.errorText);
|
||||
mLeftSpacerLandscape = view.findViewById(R.id.leftSpacer);
|
||||
mRightSpacerLandscape = view.findViewById(R.id.rightSpacer);
|
||||
|
||||
// make it so unhandled touch events within the unlock screen go to the
|
||||
// lock pattern view.
|
||||
final LinearLayoutWithDefaultTouchRecepient topLayout
|
||||
= (LinearLayoutWithDefaultTouchRecepient) view.findViewById(R.id.topLayout);
|
||||
topLayout.setDefaultTouchRecepient(mLockPatternView);
|
||||
|
||||
Intent intent = getActivity().getIntent();
|
||||
if (intent != null) {
|
||||
mHeaderText = intent.getCharSequenceExtra(
|
||||
ConfirmDeviceCredentialBaseFragment.HEADER_TEXT);
|
||||
mDetailsText = intent.getCharSequenceExtra(
|
||||
ConfirmDeviceCredentialBaseFragment.DETAILS_TEXT);
|
||||
}
|
||||
|
||||
mLockPatternView.setTactileFeedbackEnabled(
|
||||
mLockPatternUtils.isTactileFeedbackEnabled());
|
||||
mLockPatternView.setInStealthMode(!mLockPatternUtils.isVisiblePatternEnabled(
|
||||
mEffectiveUserId));
|
||||
mLockPatternView.setOnPatternListener(mConfirmExistingLockPatternListener);
|
||||
updateStage(Stage.NeedToUnlock);
|
||||
|
||||
if (savedInstanceState == null) {
|
||||
// on first launch, if no lock pattern is set, then finish with
|
||||
// success (don't want user to get stuck confirming something that
|
||||
// doesn't exist).
|
||||
if (!mLockPatternUtils.isLockPatternEnabled(mEffectiveUserId)) {
|
||||
getActivity().setResult(Activity.RESULT_OK);
|
||||
getActivity().finish();
|
||||
}
|
||||
}
|
||||
mAppearAnimationUtils = new AppearAnimationUtils(getContext(),
|
||||
AppearAnimationUtils.DEFAULT_APPEAR_DURATION, 2f /* translationScale */,
|
||||
1.3f /* delayScale */, AnimationUtils.loadInterpolator(
|
||||
getContext(), android.R.interpolator.linear_out_slow_in));
|
||||
mDisappearAnimationUtils = new DisappearAnimationUtils(getContext(),
|
||||
125, 4f /* translationScale */,
|
||||
0.3f /* delayScale */, AnimationUtils.loadInterpolator(
|
||||
getContext(), android.R.interpolator.fast_out_linear_in),
|
||||
new AppearAnimationUtils.RowTranslationScaler() {
|
||||
@Override
|
||||
public float getRowTranslationScale(int row, int numRows) {
|
||||
return (float)(numRows - row) / numRows;
|
||||
}
|
||||
});
|
||||
setAccessibilityTitle(mHeaderTextView.getText());
|
||||
|
||||
mCredentialCheckResultTracker = (CredentialCheckResultTracker) getFragmentManager()
|
||||
.findFragmentByTag(FRAGMENT_TAG_CHECK_LOCK_RESULT);
|
||||
if (mCredentialCheckResultTracker == null) {
|
||||
mCredentialCheckResultTracker = new CredentialCheckResultTracker();
|
||||
getFragmentManager().beginTransaction().add(mCredentialCheckResultTracker,
|
||||
FRAGMENT_TAG_CHECK_LOCK_RESULT).commit();
|
||||
}
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
// deliberately not calling super since we are managing this in full
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
|
||||
if (mCountdownTimer != null) {
|
||||
mCountdownTimer.cancel();
|
||||
}
|
||||
mCredentialCheckResultTracker.setListener(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return MetricsEvent.CONFIRM_LOCK_PATTERN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
|
||||
// if the user is currently locked out, enforce it.
|
||||
long deadline = mLockPatternUtils.getLockoutAttemptDeadline(mEffectiveUserId);
|
||||
if (deadline != 0) {
|
||||
mCredentialCheckResultTracker.clearResult();
|
||||
handleAttemptLockout(deadline);
|
||||
} else if (!mLockPatternView.isEnabled()) {
|
||||
// The deadline has passed, but the timer was cancelled. Or the pending lock
|
||||
// check was cancelled. Need to clean up.
|
||||
updateStage(Stage.NeedToUnlock);
|
||||
}
|
||||
mCredentialCheckResultTracker.setListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onShowError() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareEnterAnimation() {
|
||||
super.prepareEnterAnimation();
|
||||
mHeaderTextView.setAlpha(0f);
|
||||
mCancelButton.setAlpha(0f);
|
||||
mLockPatternView.setAlpha(0f);
|
||||
mDetailsTextView.setAlpha(0f);
|
||||
mFingerprintIcon.setAlpha(0f);
|
||||
}
|
||||
|
||||
private int getDefaultDetails() {
|
||||
boolean isStrongAuthRequired = isFingerprintDisallowedByStrongAuth();
|
||||
if (UserManager.get(getActivity()).isManagedProfile(mEffectiveUserId)) {
|
||||
return isStrongAuthRequired
|
||||
? R.string.lockpassword_strong_auth_required_reason_restart_work_pattern
|
||||
: R.string.lockpassword_confirm_your_pattern_generic_profile;
|
||||
} else {
|
||||
return isStrongAuthRequired
|
||||
? R.string.lockpassword_strong_auth_required_reason_restart_device_pattern
|
||||
: R.string.lockpassword_confirm_your_pattern_generic;
|
||||
}
|
||||
}
|
||||
|
||||
private Object[][] getActiveViews() {
|
||||
ArrayList<ArrayList<Object>> result = new ArrayList<>();
|
||||
result.add(new ArrayList<Object>(Collections.singletonList(mHeaderTextView)));
|
||||
result.add(new ArrayList<Object>(Collections.singletonList(mDetailsTextView)));
|
||||
if (mCancelButton.getVisibility() == View.VISIBLE) {
|
||||
result.add(new ArrayList<Object>(Collections.singletonList(mCancelButton)));
|
||||
}
|
||||
LockPatternView.CellState[][] cellStates = mLockPatternView.getCellStates();
|
||||
for (int i = 0; i < cellStates.length; i++) {
|
||||
ArrayList<Object> row = new ArrayList<>();
|
||||
for (int j = 0; j < cellStates[i].length; j++) {
|
||||
row.add(cellStates[i][j]);
|
||||
}
|
||||
result.add(row);
|
||||
}
|
||||
if (mFingerprintIcon.getVisibility() == View.VISIBLE) {
|
||||
result.add(new ArrayList<Object>(Collections.singletonList(mFingerprintIcon)));
|
||||
}
|
||||
Object[][] resultArr = new Object[result.size()][cellStates[0].length];
|
||||
for (int i = 0; i < result.size(); i++) {
|
||||
ArrayList<Object> row = result.get(i);
|
||||
for (int j = 0; j < row.size(); j++) {
|
||||
resultArr[i][j] = row.get(j);
|
||||
}
|
||||
}
|
||||
return resultArr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startEnterAnimation() {
|
||||
super.startEnterAnimation();
|
||||
mLockPatternView.setAlpha(1f);
|
||||
mAppearAnimationUtils.startAnimation2d(getActiveViews(), null, this);
|
||||
}
|
||||
|
||||
private void updateStage(Stage stage) {
|
||||
switch (stage) {
|
||||
case NeedToUnlock:
|
||||
if (mHeaderText != null) {
|
||||
mHeaderTextView.setText(mHeaderText);
|
||||
} else {
|
||||
mHeaderTextView.setText(R.string.lockpassword_confirm_your_pattern_header);
|
||||
}
|
||||
if (mDetailsText != null) {
|
||||
mDetailsTextView.setText(mDetailsText);
|
||||
} else {
|
||||
mDetailsTextView.setText(getDefaultDetails());
|
||||
}
|
||||
mErrorTextView.setText("");
|
||||
if (isProfileChallenge()) {
|
||||
updateErrorMessage(mLockPatternUtils.getCurrentFailedPasswordAttempts(
|
||||
mEffectiveUserId));
|
||||
}
|
||||
|
||||
mLockPatternView.setEnabled(true);
|
||||
mLockPatternView.enableInput();
|
||||
mLockPatternView.clearPattern();
|
||||
break;
|
||||
case NeedToUnlockWrong:
|
||||
mErrorTextView.setText(R.string.lockpattern_need_to_unlock_wrong);
|
||||
|
||||
mLockPatternView.setDisplayMode(LockPatternView.DisplayMode.Wrong);
|
||||
mLockPatternView.setEnabled(true);
|
||||
mLockPatternView.enableInput();
|
||||
break;
|
||||
case LockedOut:
|
||||
mLockPatternView.clearPattern();
|
||||
// enabled = false means: disable input, and have the
|
||||
// appearance of being disabled.
|
||||
mLockPatternView.setEnabled(false); // appearance of being disabled
|
||||
break;
|
||||
}
|
||||
|
||||
// Always announce the header for accessibility. This is a no-op
|
||||
// when accessibility is disabled.
|
||||
mHeaderTextView.announceForAccessibility(mHeaderTextView.getText());
|
||||
}
|
||||
|
||||
private Runnable mClearPatternRunnable = new Runnable() {
|
||||
public void run() {
|
||||
mLockPatternView.clearPattern();
|
||||
}
|
||||
};
|
||||
|
||||
// clear the wrong pattern unless they have started a new one
|
||||
// already
|
||||
private void postClearPatternRunnable() {
|
||||
mLockPatternView.removeCallbacks(mClearPatternRunnable);
|
||||
mLockPatternView.postDelayed(mClearPatternRunnable, WRONG_PATTERN_CLEAR_TIMEOUT_MS);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void authenticationSucceeded() {
|
||||
mCredentialCheckResultTracker.setResult(true, new Intent(), 0, mEffectiveUserId);
|
||||
}
|
||||
|
||||
private void startDisappearAnimation(final Intent intent) {
|
||||
if (mDisappearing) {
|
||||
return;
|
||||
}
|
||||
mDisappearing = true;
|
||||
|
||||
final ConfirmLockPattern activity = (ConfirmLockPattern) getActivity();
|
||||
// Bail if there is no active activity.
|
||||
if (activity == null || activity.isFinishing()) {
|
||||
return;
|
||||
}
|
||||
if (activity.getConfirmCredentialTheme() == ConfirmCredentialTheme.DARK) {
|
||||
mLockPatternView.clearPattern();
|
||||
mDisappearAnimationUtils.startAnimation2d(getActiveViews(),
|
||||
() -> {
|
||||
activity.setResult(RESULT_OK, intent);
|
||||
activity.finish();
|
||||
activity.overridePendingTransition(
|
||||
R.anim.confirm_credential_close_enter,
|
||||
R.anim.confirm_credential_close_exit);
|
||||
}, this);
|
||||
} else {
|
||||
activity.setResult(RESULT_OK, intent);
|
||||
activity.finish();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFingerprintIconVisibilityChanged(boolean visible) {
|
||||
if (mLeftSpacerLandscape != null && mRightSpacerLandscape != null) {
|
||||
|
||||
// In landscape, adjust spacing depending on fingerprint icon visibility.
|
||||
mLeftSpacerLandscape.setVisibility(visible ? View.GONE : View.VISIBLE);
|
||||
mRightSpacerLandscape.setVisibility(visible ? View.GONE : View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The pattern listener that responds according to a user confirming
|
||||
* an existing lock pattern.
|
||||
*/
|
||||
private LockPatternView.OnPatternListener mConfirmExistingLockPatternListener
|
||||
= new LockPatternView.OnPatternListener() {
|
||||
|
||||
public void onPatternStart() {
|
||||
mLockPatternView.removeCallbacks(mClearPatternRunnable);
|
||||
}
|
||||
|
||||
public void onPatternCleared() {
|
||||
mLockPatternView.removeCallbacks(mClearPatternRunnable);
|
||||
}
|
||||
|
||||
public void onPatternCellAdded(List<Cell> pattern) {
|
||||
|
||||
}
|
||||
|
||||
public void onPatternDetected(List<LockPatternView.Cell> pattern) {
|
||||
if (mPendingLockCheck != null || mDisappearing) {
|
||||
return;
|
||||
}
|
||||
|
||||
mLockPatternView.setEnabled(false);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
mCredentialCheckResultTracker.setResult(false, intent, 0, mEffectiveUserId);
|
||||
}
|
||||
|
||||
private boolean isInternalActivity() {
|
||||
return getActivity() instanceof ConfirmLockPattern.InternalActivity;
|
||||
}
|
||||
|
||||
private void startVerifyPattern(final List<LockPatternView.Cell> pattern,
|
||||
final Intent intent) {
|
||||
final int localEffectiveUserId = mEffectiveUserId;
|
||||
final int localUserId = mUserId;
|
||||
long challenge = getActivity().getIntent().getLongExtra(
|
||||
ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, 0);
|
||||
final LockPatternChecker.OnVerifyCallback onVerifyCallback =
|
||||
new LockPatternChecker.OnVerifyCallback() {
|
||||
@Override
|
||||
public void onVerified(byte[] token, int timeoutMs) {
|
||||
mPendingLockCheck = null;
|
||||
boolean matched = false;
|
||||
if (token != null) {
|
||||
matched = true;
|
||||
if (mReturnCredentials) {
|
||||
intent.putExtra(
|
||||
ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN,
|
||||
token);
|
||||
}
|
||||
}
|
||||
mCredentialCheckResultTracker.setResult(matched, intent, timeoutMs,
|
||||
localEffectiveUserId);
|
||||
}
|
||||
};
|
||||
mPendingLockCheck = (localEffectiveUserId == localUserId)
|
||||
? LockPatternChecker.verifyPattern(
|
||||
mLockPatternUtils, pattern, challenge, localUserId,
|
||||
onVerifyCallback)
|
||||
: LockPatternChecker.verifyTiedProfileChallenge(
|
||||
mLockPatternUtils, LockPatternUtils.patternToString(pattern),
|
||||
true, challenge, localUserId, onVerifyCallback);
|
||||
}
|
||||
|
||||
private void startCheckPattern(final List<LockPatternView.Cell> pattern,
|
||||
final Intent intent) {
|
||||
if (pattern.size() < LockPatternUtils.MIN_PATTERN_REGISTER_FAIL) {
|
||||
// Pattern size is less than the minimum, do not count it as an fail attempt.
|
||||
onPatternChecked(false, intent, 0, mEffectiveUserId, false /* newResult */);
|
||||
return;
|
||||
}
|
||||
|
||||
final int localEffectiveUserId = mEffectiveUserId;
|
||||
mPendingLockCheck = LockPatternChecker.checkPattern(
|
||||
mLockPatternUtils,
|
||||
pattern,
|
||||
localEffectiveUserId,
|
||||
new LockPatternChecker.OnCheckCallback() {
|
||||
@Override
|
||||
public void onChecked(boolean matched, int timeoutMs) {
|
||||
mPendingLockCheck = null;
|
||||
if (matched && isInternalActivity() && mReturnCredentials) {
|
||||
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_TYPE,
|
||||
StorageManager.CRYPT_TYPE_PATTERN);
|
||||
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD,
|
||||
LockPatternUtils.patternToString(pattern));
|
||||
}
|
||||
mCredentialCheckResultTracker.setResult(matched, intent, timeoutMs,
|
||||
localEffectiveUserId);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
private void onPatternChecked(boolean matched, Intent intent, int timeoutMs,
|
||||
int effectiveUserId, boolean newResult) {
|
||||
mLockPatternView.setEnabled(true);
|
||||
if (matched) {
|
||||
if (newResult) {
|
||||
reportSuccessfullAttempt();
|
||||
}
|
||||
startDisappearAnimation(intent);
|
||||
checkForPendingIntent();
|
||||
} else {
|
||||
if (timeoutMs > 0) {
|
||||
refreshLockScreen();
|
||||
long deadline = mLockPatternUtils.setLockoutAttemptDeadline(
|
||||
effectiveUserId, timeoutMs);
|
||||
handleAttemptLockout(deadline);
|
||||
} else {
|
||||
updateStage(Stage.NeedToUnlockWrong);
|
||||
postClearPatternRunnable();
|
||||
}
|
||||
if (newResult) {
|
||||
reportFailedAttempt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCredentialChecked(boolean matched, Intent intent, int timeoutMs,
|
||||
int effectiveUserId, boolean newResult) {
|
||||
onPatternChecked(matched, intent, timeoutMs, effectiveUserId, newResult);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getLastTryErrorMessage() {
|
||||
return R.string.lock_profile_wipe_warning_content_pattern;
|
||||
}
|
||||
|
||||
private void handleAttemptLockout(long elapsedRealtimeDeadline) {
|
||||
updateStage(Stage.LockedOut);
|
||||
long elapsedRealtime = SystemClock.elapsedRealtime();
|
||||
mCountdownTimer = new CountDownTimer(
|
||||
elapsedRealtimeDeadline - elapsedRealtime,
|
||||
LockPatternUtils.FAILED_ATTEMPT_COUNTDOWN_INTERVAL_MS) {
|
||||
|
||||
@Override
|
||||
public void onTick(long millisUntilFinished) {
|
||||
final int secondsCountdown = (int) (millisUntilFinished / 1000);
|
||||
mErrorTextView.setText(getString(
|
||||
R.string.lockpattern_too_many_failed_confirmation_attempts,
|
||||
secondsCountdown));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFinish() {
|
||||
updateStage(Stage.NeedToUnlock);
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createAnimation(Object obj, long delay,
|
||||
long duration, float translationY, final boolean appearing,
|
||||
Interpolator interpolator,
|
||||
final Runnable finishListener) {
|
||||
if (obj instanceof LockPatternView.CellState) {
|
||||
final LockPatternView.CellState animatedCell = (LockPatternView.CellState) obj;
|
||||
mLockPatternView.startCellStateAnimation(animatedCell,
|
||||
1f, appearing ? 1f : 0f, /* alpha */
|
||||
appearing ? translationY : 0f, /* startTranslation */
|
||||
appearing ? 0f : translationY, /* endTranslation */
|
||||
appearing ? 0f : 1f, 1f /* scale */,
|
||||
delay, duration, interpolator, finishListener);
|
||||
} else {
|
||||
mAppearAnimationUtils.createAnimation((View) obj, delay, duration, translationY,
|
||||
appearing, interpolator, finishListener);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user