Revert "6/N Add Controller for KeyguardPatternView"
Revert submission 12585643-b166448040-keyguard-message-area Reason for revert: http://b/169081305 & http://b/169020145 Reverted Changes: I6fa05012c:4/N Setup Controller fo KeyguardSecurityContainer.... Iecf265744:5/N Add KeyguardSecurityViewFlipperController. I90ab99b2f:6/N Add Controller for KeyguardPatternView I4b74eddd1:7/N controllers for remaining Keyguard Password Vi... I805286374:8/N Remove View Injection from KeyguardMessageArea... I362755980:9/N Clean Up Keyguard Class Structure Change-Id: I11dff38ad9c36e0de5eec8f6e8662a173e1191cc Fixes: 169081305 Fixes: 169020145
This commit is contained in:
@@ -19,7 +19,6 @@ package com.android.keyguard;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import com.android.internal.util.LatencyTracker;
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
|
||||
import com.android.systemui.util.ViewController;
|
||||
@@ -28,21 +27,18 @@ import javax.inject.Inject;
|
||||
|
||||
|
||||
/** Controller for a {@link KeyguardSecurityView}. */
|
||||
public class KeyguardInputViewController<T extends KeyguardInputView> extends ViewController<T>
|
||||
public class KeyguardInputViewController extends ViewController<KeyguardInputView>
|
||||
implements KeyguardSecurityView {
|
||||
|
||||
private final SecurityMode mSecurityMode;
|
||||
private final LockPatternUtils mLockPatternUtils;
|
||||
private final KeyguardSecurityCallback mKeyguardSecurityCallback;
|
||||
private KeyguardMessageAreaController mMessageAreaController;
|
||||
|
||||
protected KeyguardInputViewController(T view, SecurityMode securityMode,
|
||||
private KeyguardInputViewController(KeyguardInputView view, SecurityMode securityMode,
|
||||
LockPatternUtils lockPatternUtils,
|
||||
KeyguardSecurityCallback keyguardSecurityCallback) {
|
||||
super(view);
|
||||
mSecurityMode = securityMode;
|
||||
mLockPatternUtils = lockPatternUtils;
|
||||
mKeyguardSecurityCallback = keyguardSecurityCallback;
|
||||
mView.setKeyguardCallback(keyguardSecurityCallback);
|
||||
}
|
||||
|
||||
@@ -147,31 +143,17 @@ public class KeyguardInputViewController<T extends KeyguardInputView> extends Vi
|
||||
|
||||
/** Factory for a {@link KeyguardInputViewController}. */
|
||||
public static class Factory {
|
||||
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
|
||||
private final LockPatternUtils mLockPatternUtils;
|
||||
private final LatencyTracker mLatencyTracker;
|
||||
private final KeyguardMessageAreaController.Factory mMessageAreaControllerFactory;
|
||||
|
||||
@Inject
|
||||
public Factory(KeyguardUpdateMonitor keyguardUpdateMonitor,
|
||||
LockPatternUtils lockPatternUtils,
|
||||
LatencyTracker latencyTracker,
|
||||
KeyguardMessageAreaController.Factory messageAreaControllerFactory) {
|
||||
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
|
||||
public Factory(LockPatternUtils lockPatternUtils) {
|
||||
mLockPatternUtils = lockPatternUtils;
|
||||
mLatencyTracker = latencyTracker;
|
||||
mMessageAreaControllerFactory = messageAreaControllerFactory;
|
||||
}
|
||||
|
||||
/** Create a new {@link KeyguardInputViewController}. */
|
||||
public KeyguardInputViewController create(KeyguardInputView keyguardInputView,
|
||||
SecurityMode securityMode, KeyguardSecurityCallback keyguardSecurityCallback) {
|
||||
if (keyguardInputView instanceof KeyguardPatternView) {
|
||||
return new KeyguardPatternViewController((KeyguardPatternView) keyguardInputView,
|
||||
mKeyguardUpdateMonitor, securityMode, mLockPatternUtils,
|
||||
keyguardSecurityCallback, mLatencyTracker, mMessageAreaControllerFactory);
|
||||
}
|
||||
return new KeyguardInputViewController<>(keyguardInputView, securityMode,
|
||||
return new KeyguardInputViewController(keyguardInputView, securityMode,
|
||||
mLockPatternUtils, keyguardSecurityCallback);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package com.android.keyguard;
|
||||
|
||||
import android.content.res.ColorStateList;
|
||||
|
||||
import com.android.systemui.statusbar.policy.ConfigurationController;
|
||||
import com.android.systemui.util.ViewController;
|
||||
|
||||
@@ -39,25 +37,17 @@ public class KeyguardMessageAreaController extends ViewController<KeyguardMessag
|
||||
|
||||
@Override
|
||||
protected void onViewAttached() {
|
||||
//mConfigurationController.addCallback();
|
||||
//mKeyguardUpdateMonitor.registerCallback();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onViewDetached() {
|
||||
//mConfigurationController.removeCallback();
|
||||
//mKeyguardUpdateMonitor.removeCallback();
|
||||
}
|
||||
|
||||
public void setMessage(CharSequence s) {
|
||||
mView.setMessage(s);
|
||||
}
|
||||
|
||||
public void setMessage(int resId) {
|
||||
mView.setMessage(resId);
|
||||
}
|
||||
|
||||
public void setNextMessageColor(ColorStateList colorState) {
|
||||
mView.setNextMessageColor(colorState);
|
||||
}
|
||||
|
||||
/** Factory for creating {@link com.android.keyguard.KeyguardMessageAreaController}. */
|
||||
/** Factory for createing {@link com.android.keyguard.KeyguardMessageAreaController}. */
|
||||
public static class Factory {
|
||||
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
|
||||
private final ConfigurationController mConfigurationController;
|
||||
|
||||
@@ -15,41 +15,61 @@
|
||||
*/
|
||||
package com.android.keyguard;
|
||||
|
||||
import static com.android.internal.util.LatencyTracker.ACTION_CHECK_CREDENTIAL;
|
||||
import static com.android.internal.util.LatencyTracker.ACTION_CHECK_CREDENTIAL_UNLOCKED;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.graphics.Rect;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.CountDownTimer;
|
||||
import android.os.SystemClock;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.animation.AnimationUtils;
|
||||
import android.view.animation.Interpolator;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.util.LatencyTracker;
|
||||
import com.android.internal.widget.LockPatternChecker;
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.internal.widget.LockPatternView;
|
||||
import com.android.internal.widget.LockscreenCredential;
|
||||
import com.android.settingslib.animation.AppearAnimationCreator;
|
||||
import com.android.settingslib.animation.AppearAnimationUtils;
|
||||
import com.android.settingslib.animation.DisappearAnimationUtils;
|
||||
import com.android.systemui.Dependency;
|
||||
import com.android.systemui.R;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class KeyguardPatternView extends KeyguardInputView
|
||||
implements AppearAnimationCreator<LockPatternView.CellState> {
|
||||
implements AppearAnimationCreator<LockPatternView.CellState>,
|
||||
EmergencyButton.EmergencyButtonCallback {
|
||||
|
||||
private static final String TAG = "SecurityPatternView";
|
||||
private static final boolean DEBUG = KeyguardConstants.DEBUG;
|
||||
|
||||
// how long before we clear the wrong pattern
|
||||
private static final int PATTERN_CLEAR_TIMEOUT_MS = 2000;
|
||||
|
||||
// how long we stay awake after each key beyond MIN_PATTERN_BEFORE_POKE_WAKELOCK
|
||||
private static final int UNLOCK_PATTERN_WAKE_INTERVAL_MS = 7000;
|
||||
|
||||
// how many cells the user has to cross before we poke the wakelock
|
||||
private static final int MIN_PATTERN_BEFORE_POKE_WAKELOCK = 2;
|
||||
|
||||
// How much we scale up the duration of the disappear animation when the current user is locked
|
||||
public static final float DISAPPEAR_MULTIPLIER_LOCKED = 1.5f;
|
||||
|
||||
// Extra padding, in pixels, that should eat touch events.
|
||||
private static final int PATTERNS_TOUCH_AREA_EXTENSION = 40;
|
||||
|
||||
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
|
||||
private final AppearAnimationUtils mAppearAnimationUtils;
|
||||
private final DisappearAnimationUtils mDisappearAnimationUtils;
|
||||
private final DisappearAnimationUtils mDisappearAnimationUtilsLocked;
|
||||
@@ -57,6 +77,9 @@ public class KeyguardPatternView extends KeyguardInputView
|
||||
private final Rect mTempRect = new Rect();
|
||||
private final Rect mLockPatternScreenBounds = new Rect();
|
||||
|
||||
private CountDownTimer mCountdownTimer = null;
|
||||
private LockPatternUtils mLockPatternUtils;
|
||||
private AsyncTask<?, ?, ?> mPendingLockCheck;
|
||||
private LockPatternView mLockPatternView;
|
||||
private KeyguardSecurityCallback mCallback;
|
||||
|
||||
@@ -68,17 +91,34 @@ public class KeyguardPatternView extends KeyguardInputView
|
||||
*/
|
||||
private long mLastPokeTime = -UNLOCK_PATTERN_WAKE_INTERVAL_MS;
|
||||
|
||||
/**
|
||||
* Useful for clearing out the wrong pattern after a delay
|
||||
*/
|
||||
private Runnable mCancelPatternRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mLockPatternView.clearPattern();
|
||||
}
|
||||
};
|
||||
@VisibleForTesting
|
||||
KeyguardMessageArea mSecurityMessageDisplay;
|
||||
private View mEcaView;
|
||||
private ViewGroup mContainer;
|
||||
private int mDisappearYTranslation;
|
||||
|
||||
enum FooterMode {
|
||||
Normal,
|
||||
ForgotLockPattern,
|
||||
VerifyUnlocked
|
||||
}
|
||||
|
||||
public KeyguardPatternView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public KeyguardPatternView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
mKeyguardUpdateMonitor = Dependency.get(KeyguardUpdateMonitor.class);
|
||||
mAppearAnimationUtils = new AppearAnimationUtils(context,
|
||||
AppearAnimationUtils.DEFAULT_APPEAR_DURATION, 1.5f /* translationScale */,
|
||||
2.0f /* delayScale */, AnimationUtils.loadInterpolator(
|
||||
@@ -102,16 +142,39 @@ public class KeyguardPatternView extends KeyguardInputView
|
||||
|
||||
@Override
|
||||
public void setLockPatternUtils(LockPatternUtils utils) {
|
||||
mLockPatternUtils = utils;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
mLockPatternUtils = mLockPatternUtils == null
|
||||
? new LockPatternUtils(mContext) : mLockPatternUtils;
|
||||
|
||||
mLockPatternView = findViewById(R.id.lockPatternView);
|
||||
mLockPatternView.setSaveEnabled(false);
|
||||
mLockPatternView.setOnPatternListener(new UnlockPatternListener());
|
||||
mLockPatternView.setInStealthMode(!mLockPatternUtils.isVisiblePatternEnabled(
|
||||
KeyguardUpdateMonitor.getCurrentUser()));
|
||||
|
||||
// vibrate mode will be the same for the life of this screen
|
||||
mLockPatternView.setTactileFeedbackEnabled(mLockPatternUtils.isTactileFeedbackEnabled());
|
||||
|
||||
mEcaView = findViewById(R.id.keyguard_selector_fade_container);
|
||||
mContainer = findViewById(R.id.container);
|
||||
|
||||
EmergencyButton button = findViewById(R.id.emergency_call_button);
|
||||
if (button != null) {
|
||||
button.setCallback(this);
|
||||
}
|
||||
|
||||
View cancelBtn = findViewById(R.id.cancel_button);
|
||||
if (cancelBtn != null) {
|
||||
cancelBtn.setOnClickListener(view -> {
|
||||
mCallback.reset();
|
||||
mCallback.onCancelClicked();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -120,6 +183,11 @@ public class KeyguardPatternView extends KeyguardInputView
|
||||
mSecurityMessageDisplay = KeyguardMessageArea.findSecurityMessageDisplay(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEmergencyButtonClickedWhenInCall() {
|
||||
mCallback.reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent ev) {
|
||||
boolean result = super.onTouchEvent(ev);
|
||||
@@ -149,6 +217,31 @@ public class KeyguardPatternView extends KeyguardInputView
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
// reset lock pattern
|
||||
mLockPatternView.setInStealthMode(!mLockPatternUtils.isVisiblePatternEnabled(
|
||||
KeyguardUpdateMonitor.getCurrentUser()));
|
||||
mLockPatternView.enableInput();
|
||||
mLockPatternView.setEnabled(true);
|
||||
mLockPatternView.clearPattern();
|
||||
|
||||
if (mSecurityMessageDisplay == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// if the user is currently locked out, enforce it.
|
||||
long deadline = mLockPatternUtils.getLockoutAttemptDeadline(
|
||||
KeyguardUpdateMonitor.getCurrentUser());
|
||||
if (deadline != 0) {
|
||||
handleAttemptLockout(deadline);
|
||||
} else {
|
||||
displayDefaultSecurityMessage();
|
||||
}
|
||||
}
|
||||
|
||||
private void displayDefaultSecurityMessage() {
|
||||
if (mSecurityMessageDisplay != null) {
|
||||
mSecurityMessageDisplay.setMessage("");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -161,6 +254,148 @@ public class KeyguardPatternView extends KeyguardInputView
|
||||
|| mLockPatternScreenBounds.contains((int) event.getRawX(), (int) event.getRawY());
|
||||
}
|
||||
|
||||
/** TODO: hook this up */
|
||||
public void cleanUp() {
|
||||
if (DEBUG) Log.v(TAG, "Cleanup() called on " + this);
|
||||
mLockPatternUtils = null;
|
||||
mLockPatternView.setOnPatternListener(null);
|
||||
}
|
||||
|
||||
private class UnlockPatternListener implements LockPatternView.OnPatternListener {
|
||||
|
||||
@Override
|
||||
public void onPatternStart() {
|
||||
mLockPatternView.removeCallbacks(mCancelPatternRunnable);
|
||||
mSecurityMessageDisplay.setMessage("");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPatternCleared() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPatternCellAdded(List<LockPatternView.Cell> pattern) {
|
||||
mCallback.userActivity();
|
||||
mCallback.onUserInput();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPatternDetected(final List<LockPatternView.Cell> pattern) {
|
||||
mKeyguardUpdateMonitor.setCredentialAttempted();
|
||||
mLockPatternView.disableInput();
|
||||
if (mPendingLockCheck != null) {
|
||||
mPendingLockCheck.cancel(false);
|
||||
}
|
||||
|
||||
final int userId = KeyguardUpdateMonitor.getCurrentUser();
|
||||
if (pattern.size() < LockPatternUtils.MIN_PATTERN_REGISTER_FAIL) {
|
||||
mLockPatternView.enableInput();
|
||||
onPatternChecked(userId, false, 0, false /* not valid - too short */);
|
||||
return;
|
||||
}
|
||||
|
||||
if (LatencyTracker.isEnabled(mContext)) {
|
||||
LatencyTracker.getInstance(mContext).onActionStart(ACTION_CHECK_CREDENTIAL);
|
||||
LatencyTracker.getInstance(mContext).onActionStart(ACTION_CHECK_CREDENTIAL_UNLOCKED);
|
||||
}
|
||||
mPendingLockCheck = LockPatternChecker.checkCredential(
|
||||
mLockPatternUtils,
|
||||
LockscreenCredential.createPattern(pattern),
|
||||
userId,
|
||||
new LockPatternChecker.OnCheckCallback() {
|
||||
|
||||
@Override
|
||||
public void onEarlyMatched() {
|
||||
if (LatencyTracker.isEnabled(mContext)) {
|
||||
LatencyTracker.getInstance(mContext).onActionEnd(
|
||||
ACTION_CHECK_CREDENTIAL);
|
||||
}
|
||||
onPatternChecked(userId, true /* matched */, 0 /* timeoutMs */,
|
||||
true /* isValidPattern */);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChecked(boolean matched, int timeoutMs) {
|
||||
if (LatencyTracker.isEnabled(mContext)) {
|
||||
LatencyTracker.getInstance(mContext).onActionEnd(
|
||||
ACTION_CHECK_CREDENTIAL_UNLOCKED);
|
||||
}
|
||||
mLockPatternView.enableInput();
|
||||
mPendingLockCheck = null;
|
||||
if (!matched) {
|
||||
onPatternChecked(userId, false /* matched */, timeoutMs,
|
||||
true /* isValidPattern */);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancelled() {
|
||||
// We already got dismissed with the early matched callback, so we
|
||||
// cancelled the check. However, we still need to note down the latency.
|
||||
if (LatencyTracker.isEnabled(mContext)) {
|
||||
LatencyTracker.getInstance(mContext).onActionEnd(
|
||||
ACTION_CHECK_CREDENTIAL_UNLOCKED);
|
||||
}
|
||||
}
|
||||
});
|
||||
if (pattern.size() > MIN_PATTERN_BEFORE_POKE_WAKELOCK) {
|
||||
mCallback.userActivity();
|
||||
mCallback.onUserInput();
|
||||
}
|
||||
}
|
||||
|
||||
private void onPatternChecked(int userId, boolean matched, int timeoutMs,
|
||||
boolean isValidPattern) {
|
||||
boolean dismissKeyguard = KeyguardUpdateMonitor.getCurrentUser() == userId;
|
||||
if (matched) {
|
||||
mCallback.reportUnlockAttempt(userId, true, 0);
|
||||
if (dismissKeyguard) {
|
||||
mLockPatternView.setDisplayMode(LockPatternView.DisplayMode.Correct);
|
||||
mCallback.dismiss(true, userId);
|
||||
}
|
||||
} else {
|
||||
mLockPatternView.setDisplayMode(LockPatternView.DisplayMode.Wrong);
|
||||
if (isValidPattern) {
|
||||
mCallback.reportUnlockAttempt(userId, false, timeoutMs);
|
||||
if (timeoutMs > 0) {
|
||||
long deadline = mLockPatternUtils.setLockoutAttemptDeadline(
|
||||
userId, timeoutMs);
|
||||
handleAttemptLockout(deadline);
|
||||
}
|
||||
}
|
||||
if (timeoutMs == 0) {
|
||||
mSecurityMessageDisplay.setMessage(R.string.kg_wrong_pattern);
|
||||
mLockPatternView.postDelayed(mCancelPatternRunnable, PATTERN_CLEAR_TIMEOUT_MS);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handleAttemptLockout(long elapsedRealtimeDeadline) {
|
||||
mLockPatternView.clearPattern();
|
||||
mLockPatternView.setEnabled(false);
|
||||
final long elapsedRealtime = SystemClock.elapsedRealtime();
|
||||
final long secondsInFuture = (long) Math.ceil(
|
||||
(elapsedRealtimeDeadline - elapsedRealtime) / 1000.0);
|
||||
mCountdownTimer = new CountDownTimer(secondsInFuture * 1000, 1000) {
|
||||
|
||||
@Override
|
||||
public void onTick(long millisUntilFinished) {
|
||||
final int secondsRemaining = (int) Math.round(millisUntilFinished / 1000.0);
|
||||
mSecurityMessageDisplay.setMessage(mContext.getResources().getQuantityString(
|
||||
R.plurals.kg_too_many_failed_attempts_countdown,
|
||||
secondsRemaining, secondsRemaining));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFinish() {
|
||||
mLockPatternView.setEnabled(true);
|
||||
displayDefaultSecurityMessage();
|
||||
}
|
||||
|
||||
}.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean needsInput() {
|
||||
return false;
|
||||
@@ -168,6 +403,15 @@ public class KeyguardPatternView extends KeyguardInputView
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
if (mCountdownTimer != null) {
|
||||
mCountdownTimer.cancel();
|
||||
mCountdownTimer = null;
|
||||
}
|
||||
if (mPendingLockCheck != null) {
|
||||
mPendingLockCheck.cancel(false);
|
||||
mPendingLockCheck = null;
|
||||
}
|
||||
displayDefaultSecurityMessage();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -181,10 +425,36 @@ public class KeyguardPatternView extends KeyguardInputView
|
||||
|
||||
@Override
|
||||
public void showPromptReason(int reason) {
|
||||
switch (reason) {
|
||||
case PROMPT_REASON_RESTART:
|
||||
mSecurityMessageDisplay.setMessage(R.string.kg_prompt_reason_restart_pattern);
|
||||
break;
|
||||
case PROMPT_REASON_TIMEOUT:
|
||||
mSecurityMessageDisplay.setMessage(R.string.kg_prompt_reason_timeout_pattern);
|
||||
break;
|
||||
case PROMPT_REASON_DEVICE_ADMIN:
|
||||
mSecurityMessageDisplay.setMessage(R.string.kg_prompt_reason_device_admin);
|
||||
break;
|
||||
case PROMPT_REASON_USER_REQUEST:
|
||||
mSecurityMessageDisplay.setMessage(R.string.kg_prompt_reason_user_request);
|
||||
break;
|
||||
case PROMPT_REASON_PREPARE_FOR_UPDATE:
|
||||
mSecurityMessageDisplay.setMessage(R.string.kg_prompt_reason_timeout_pattern);
|
||||
break;
|
||||
case PROMPT_REASON_NONE:
|
||||
break;
|
||||
default:
|
||||
mSecurityMessageDisplay.setMessage(R.string.kg_prompt_reason_timeout_pattern);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showMessage(CharSequence message, ColorStateList colorState) {
|
||||
if (colorState != null) {
|
||||
mSecurityMessageDisplay.setNextMessageColor(colorState);
|
||||
}
|
||||
mSecurityMessageDisplay.setMessage(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -213,18 +483,11 @@ public class KeyguardPatternView extends KeyguardInputView
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #startDisappearAnimation(boolean, Runnable)}
|
||||
*/
|
||||
@Override
|
||||
public boolean startDisappearAnimation(Runnable finishRunnable) {
|
||||
// TODO(b/166448040): remove this when possible
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean startDisappearAnimation(boolean needsSlowUnlockTransition,
|
||||
final Runnable finishRunnable) {
|
||||
float durationMultiplier = needsSlowUnlockTransition ? DISAPPEAR_MULTIPLIER_LOCKED : 1f;
|
||||
public boolean startDisappearAnimation(final Runnable finishRunnable) {
|
||||
float durationMultiplier = mKeyguardUpdateMonitor.needsSlowUnlockTransition()
|
||||
? DISAPPEAR_MULTIPLIER_LOCKED
|
||||
: 1f;
|
||||
mLockPatternView.clearPattern();
|
||||
enableClipping(false);
|
||||
setTranslationY(0);
|
||||
@@ -233,8 +496,10 @@ public class KeyguardPatternView extends KeyguardInputView
|
||||
-mDisappearAnimationUtils.getStartTranslation(),
|
||||
mDisappearAnimationUtils.getInterpolator());
|
||||
|
||||
DisappearAnimationUtils disappearAnimationUtils = needsSlowUnlockTransition
|
||||
? mDisappearAnimationUtilsLocked : mDisappearAnimationUtils;
|
||||
DisappearAnimationUtils disappearAnimationUtils = mKeyguardUpdateMonitor
|
||||
.needsSlowUnlockTransition()
|
||||
? mDisappearAnimationUtilsLocked
|
||||
: mDisappearAnimationUtils;
|
||||
disappearAnimationUtils.startAnimation2d(mLockPatternView.getCellStates(),
|
||||
() -> {
|
||||
enableClipping(true);
|
||||
@@ -283,7 +548,7 @@ public class KeyguardPatternView extends KeyguardInputView
|
||||
|
||||
@Override
|
||||
public CharSequence getTitle() {
|
||||
return getResources().getString(
|
||||
return getContext().getString(
|
||||
com.android.internal.R.string.keyguard_accessibility_pattern_unlock);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,344 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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.keyguard;
|
||||
|
||||
import static com.android.internal.util.LatencyTracker.ACTION_CHECK_CREDENTIAL;
|
||||
import static com.android.internal.util.LatencyTracker.ACTION_CHECK_CREDENTIAL_UNLOCKED;
|
||||
|
||||
import android.content.res.ColorStateList;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.CountDownTimer;
|
||||
import android.os.SystemClock;
|
||||
import android.view.View;
|
||||
|
||||
import com.android.internal.util.LatencyTracker;
|
||||
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.internal.widget.LockscreenCredential;
|
||||
import com.android.keyguard.EmergencyButton.EmergencyButtonCallback;
|
||||
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
|
||||
import com.android.systemui.R;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class KeyguardPatternViewController
|
||||
extends KeyguardInputViewController<KeyguardPatternView> {
|
||||
|
||||
// how many cells the user has to cross before we poke the wakelock
|
||||
private static final int MIN_PATTERN_BEFORE_POKE_WAKELOCK = 2;
|
||||
|
||||
// how long before we clear the wrong pattern
|
||||
private static final int PATTERN_CLEAR_TIMEOUT_MS = 2000;
|
||||
|
||||
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
|
||||
private final LockPatternUtils mLockPatternUtils;
|
||||
private final LatencyTracker mLatencyTracker;
|
||||
private final KeyguardMessageAreaController.Factory mMessageAreaControllerFactory;
|
||||
|
||||
private KeyguardMessageAreaController mMessageAreaController;
|
||||
private LockPatternView mLockPatternView;
|
||||
private CountDownTimer mCountdownTimer;
|
||||
private KeyguardSecurityCallback mCallback;
|
||||
private AsyncTask<?, ?, ?> mPendingLockCheck;
|
||||
|
||||
private EmergencyButtonCallback mEmergencyButtonCallback = new EmergencyButtonCallback() {
|
||||
@Override
|
||||
public void onEmergencyButtonClickedWhenInCall() {
|
||||
mCallback.reset();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Useful for clearing out the wrong pattern after a delay
|
||||
*/
|
||||
private Runnable mCancelPatternRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mLockPatternView.clearPattern();
|
||||
}
|
||||
};
|
||||
|
||||
private class UnlockPatternListener implements LockPatternView.OnPatternListener {
|
||||
|
||||
@Override
|
||||
public void onPatternStart() {
|
||||
mLockPatternView.removeCallbacks(mCancelPatternRunnable);
|
||||
mMessageAreaController.setMessage("");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPatternCleared() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPatternCellAdded(List<Cell> pattern) {
|
||||
mCallback.userActivity();
|
||||
mCallback.onUserInput();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPatternDetected(final List<LockPatternView.Cell> pattern) {
|
||||
mKeyguardUpdateMonitor.setCredentialAttempted();
|
||||
mLockPatternView.disableInput();
|
||||
if (mPendingLockCheck != null) {
|
||||
mPendingLockCheck.cancel(false);
|
||||
}
|
||||
|
||||
final int userId = KeyguardUpdateMonitor.getCurrentUser();
|
||||
if (pattern.size() < LockPatternUtils.MIN_PATTERN_REGISTER_FAIL) {
|
||||
mLockPatternView.enableInput();
|
||||
onPatternChecked(userId, false, 0, false /* not valid - too short */);
|
||||
return;
|
||||
}
|
||||
|
||||
mLatencyTracker.onActionStart(ACTION_CHECK_CREDENTIAL);
|
||||
mLatencyTracker.onActionStart(ACTION_CHECK_CREDENTIAL_UNLOCKED);
|
||||
mPendingLockCheck = LockPatternChecker.checkCredential(
|
||||
mLockPatternUtils,
|
||||
LockscreenCredential.createPattern(pattern),
|
||||
userId,
|
||||
new LockPatternChecker.OnCheckCallback() {
|
||||
|
||||
@Override
|
||||
public void onEarlyMatched() {
|
||||
mLatencyTracker.onActionEnd(ACTION_CHECK_CREDENTIAL);
|
||||
onPatternChecked(userId, true /* matched */, 0 /* timeoutMs */,
|
||||
true /* isValidPattern */);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChecked(boolean matched, int timeoutMs) {
|
||||
mLatencyTracker.onActionEnd(ACTION_CHECK_CREDENTIAL_UNLOCKED);
|
||||
mLockPatternView.enableInput();
|
||||
mPendingLockCheck = null;
|
||||
if (!matched) {
|
||||
onPatternChecked(userId, false /* matched */, timeoutMs,
|
||||
true /* isValidPattern */);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancelled() {
|
||||
// We already got dismissed with the early matched callback, so we
|
||||
// cancelled the check. However, we still need to note down the latency.
|
||||
mLatencyTracker.onActionEnd(ACTION_CHECK_CREDENTIAL_UNLOCKED);
|
||||
}
|
||||
});
|
||||
if (pattern.size() > MIN_PATTERN_BEFORE_POKE_WAKELOCK) {
|
||||
mCallback.userActivity();
|
||||
mCallback.onUserInput();
|
||||
}
|
||||
}
|
||||
|
||||
private void onPatternChecked(int userId, boolean matched, int timeoutMs,
|
||||
boolean isValidPattern) {
|
||||
boolean dismissKeyguard = KeyguardUpdateMonitor.getCurrentUser() == userId;
|
||||
if (matched) {
|
||||
mCallback.reportUnlockAttempt(userId, true, 0);
|
||||
if (dismissKeyguard) {
|
||||
mLockPatternView.setDisplayMode(LockPatternView.DisplayMode.Correct);
|
||||
mCallback.dismiss(true, userId);
|
||||
}
|
||||
} else {
|
||||
mLockPatternView.setDisplayMode(LockPatternView.DisplayMode.Wrong);
|
||||
if (isValidPattern) {
|
||||
mCallback.reportUnlockAttempt(userId, false, timeoutMs);
|
||||
if (timeoutMs > 0) {
|
||||
long deadline = mLockPatternUtils.setLockoutAttemptDeadline(
|
||||
userId, timeoutMs);
|
||||
handleAttemptLockout(deadline);
|
||||
}
|
||||
}
|
||||
if (timeoutMs == 0) {
|
||||
mMessageAreaController.setMessage(R.string.kg_wrong_pattern);
|
||||
mLockPatternView.postDelayed(mCancelPatternRunnable, PATTERN_CLEAR_TIMEOUT_MS);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected KeyguardPatternViewController(KeyguardPatternView view,
|
||||
KeyguardUpdateMonitor keyguardUpdateMonitor,
|
||||
SecurityMode securityMode,
|
||||
LockPatternUtils lockPatternUtils,
|
||||
KeyguardSecurityCallback keyguardSecurityCallback,
|
||||
LatencyTracker latencyTracker,
|
||||
KeyguardMessageAreaController.Factory messageAreaControllerFactory) {
|
||||
super(view, securityMode, lockPatternUtils, keyguardSecurityCallback);
|
||||
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
|
||||
mLockPatternUtils = lockPatternUtils;
|
||||
mLatencyTracker = latencyTracker;
|
||||
mMessageAreaControllerFactory = messageAreaControllerFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onViewAttached() {
|
||||
KeyguardMessageArea kma = KeyguardMessageArea.findSecurityMessageDisplay(mView);
|
||||
mMessageAreaController = mMessageAreaControllerFactory.create(kma);
|
||||
mLockPatternView = mView.findViewById(R.id.lockPatternView);
|
||||
mLockPatternView.setOnPatternListener(new UnlockPatternListener());
|
||||
mLockPatternView.setSaveEnabled(false);
|
||||
mLockPatternView.setInStealthMode(!mLockPatternUtils.isVisiblePatternEnabled(
|
||||
KeyguardUpdateMonitor.getCurrentUser()));
|
||||
// vibrate mode will be the same for the life of this screen
|
||||
mLockPatternView.setTactileFeedbackEnabled(mLockPatternUtils.isTactileFeedbackEnabled());
|
||||
|
||||
EmergencyButton button = mView.findViewById(R.id.emergency_call_button);
|
||||
if (button != null) {
|
||||
button.setCallback(mEmergencyButtonCallback);
|
||||
}
|
||||
|
||||
View cancelBtn = mView.findViewById(R.id.cancel_button);
|
||||
if (cancelBtn != null) {
|
||||
cancelBtn.setOnClickListener(view -> {
|
||||
mCallback.reset();
|
||||
mCallback.onCancelClicked();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onViewDetached() {
|
||||
super.onViewDetached();
|
||||
mLockPatternView.setOnPatternListener(null);
|
||||
EmergencyButton button = mView.findViewById(R.id.emergency_call_button);
|
||||
if (button != null) {
|
||||
button.setCallback(null);
|
||||
}
|
||||
View cancelBtn = mView.findViewById(R.id.cancel_button);
|
||||
if (cancelBtn != null) {
|
||||
cancelBtn.setOnClickListener(null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
// reset lock pattern
|
||||
mLockPatternView.setInStealthMode(!mLockPatternUtils.isVisiblePatternEnabled(
|
||||
KeyguardUpdateMonitor.getCurrentUser()));
|
||||
mLockPatternView.enableInput();
|
||||
mLockPatternView.setEnabled(true);
|
||||
mLockPatternView.clearPattern();
|
||||
|
||||
// if the user is currently locked out, enforce it.
|
||||
long deadline = mLockPatternUtils.getLockoutAttemptDeadline(
|
||||
KeyguardUpdateMonitor.getCurrentUser());
|
||||
if (deadline != 0) {
|
||||
handleAttemptLockout(deadline);
|
||||
} else {
|
||||
displayDefaultSecurityMessage();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
|
||||
if (mCountdownTimer != null) {
|
||||
mCountdownTimer.cancel();
|
||||
mCountdownTimer = null;
|
||||
}
|
||||
|
||||
if (mPendingLockCheck != null) {
|
||||
mPendingLockCheck.cancel(false);
|
||||
mPendingLockCheck = null;
|
||||
}
|
||||
displayDefaultSecurityMessage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setKeyguardCallback(KeyguardSecurityCallback callback) {
|
||||
mCallback = callback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showPromptReason(int reason) {
|
||||
/// TODO: move all this logic into the MessageAreaController?
|
||||
switch (reason) {
|
||||
case PROMPT_REASON_RESTART:
|
||||
mMessageAreaController.setMessage(R.string.kg_prompt_reason_restart_pattern);
|
||||
break;
|
||||
case PROMPT_REASON_TIMEOUT:
|
||||
mMessageAreaController.setMessage(R.string.kg_prompt_reason_timeout_pattern);
|
||||
break;
|
||||
case PROMPT_REASON_DEVICE_ADMIN:
|
||||
mMessageAreaController.setMessage(R.string.kg_prompt_reason_device_admin);
|
||||
break;
|
||||
case PROMPT_REASON_USER_REQUEST:
|
||||
mMessageAreaController.setMessage(R.string.kg_prompt_reason_user_request);
|
||||
break;
|
||||
case PROMPT_REASON_PREPARE_FOR_UPDATE:
|
||||
mMessageAreaController.setMessage(R.string.kg_prompt_reason_timeout_pattern);
|
||||
break;
|
||||
case PROMPT_REASON_NONE:
|
||||
break;
|
||||
default:
|
||||
mMessageAreaController.setMessage(R.string.kg_prompt_reason_timeout_pattern);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showMessage(CharSequence message, ColorStateList colorState) {
|
||||
if (colorState != null) {
|
||||
mMessageAreaController.setNextMessageColor(colorState);
|
||||
}
|
||||
mMessageAreaController.setMessage(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startAppearAnimation() {
|
||||
super.startAppearAnimation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean startDisappearAnimation(Runnable finishRunnable) {
|
||||
return mView.startDisappearAnimation(
|
||||
mKeyguardUpdateMonitor.needsSlowUnlockTransition(), finishRunnable);
|
||||
}
|
||||
|
||||
private void displayDefaultSecurityMessage() {
|
||||
mMessageAreaController.setMessage("");
|
||||
}
|
||||
|
||||
private void handleAttemptLockout(long elapsedRealtimeDeadline) {
|
||||
mLockPatternView.clearPattern();
|
||||
mLockPatternView.setEnabled(false);
|
||||
final long elapsedRealtime = SystemClock.elapsedRealtime();
|
||||
final long secondsInFuture = (long) Math.ceil(
|
||||
(elapsedRealtimeDeadline - elapsedRealtime) / 1000.0);
|
||||
mCountdownTimer = new CountDownTimer(secondsInFuture * 1000, 1000) {
|
||||
|
||||
@Override
|
||||
public void onTick(long millisUntilFinished) {
|
||||
final int secondsRemaining = (int) Math.round(millisUntilFinished / 1000.0);
|
||||
mMessageAreaController.setMessage(mView.getResources().getQuantityString(
|
||||
R.plurals.kg_too_many_failed_attempts_countdown,
|
||||
secondsRemaining, secondsRemaining));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFinish() {
|
||||
mLockPatternView.setEnabled(true);
|
||||
displayDefaultSecurityMessage();
|
||||
}
|
||||
|
||||
}.start();
|
||||
}
|
||||
}
|
||||
@@ -256,7 +256,6 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
|
||||
|
||||
public void reset() {
|
||||
mView.reset();
|
||||
mSecurityViewFlipperController.reset();
|
||||
}
|
||||
|
||||
public CharSequence getTitle() {
|
||||
|
||||
@@ -80,9 +80,7 @@ public class KeyguardSecurityViewFlipperController
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
for (KeyguardInputViewController child : mChildren) {
|
||||
child.reset();
|
||||
}
|
||||
mView.reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -158,7 +156,6 @@ public class KeyguardSecurityViewFlipperController
|
||||
mView.addView(view);
|
||||
childController = mKeyguardSecurityViewControllerFactory.create(
|
||||
view, securityMode, keyguardSecurityCallback);
|
||||
childController.init();
|
||||
|
||||
mChildren.add(childController);
|
||||
}
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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.keyguard
|
||||
|
||||
import android.testing.AndroidTestingRunner
|
||||
import android.testing.TestableLooper
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.internal.util.LatencyTracker
|
||||
import com.android.internal.widget.LockPatternUtils
|
||||
import com.android.internal.widget.LockPatternView
|
||||
import com.android.systemui.R
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.Mock
|
||||
import org.mockito.Mockito.`when`
|
||||
import org.mockito.Mockito.verify
|
||||
import org.mockito.MockitoAnnotations
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner::class)
|
||||
@TestableLooper.RunWithLooper
|
||||
class KeyguardPatternViewControllerTest : SysuiTestCase() {
|
||||
@Mock
|
||||
private lateinit var mKeyguardPatternView: KeyguardPatternView
|
||||
@Mock
|
||||
private lateinit var mKeyguardUpdateMonitor: KeyguardUpdateMonitor
|
||||
@Mock
|
||||
private lateinit var mSecurityMode: KeyguardSecurityModel.SecurityMode
|
||||
@Mock
|
||||
private lateinit var mLockPatternUtils: LockPatternUtils
|
||||
@Mock
|
||||
private lateinit var mKeyguardSecurityCallback: KeyguardSecurityCallback
|
||||
@Mock
|
||||
private lateinit var mLatencyTracker: LatencyTracker
|
||||
@Mock
|
||||
private lateinit
|
||||
var mKeyguardMessageAreaControllerFactory: KeyguardMessageAreaController.Factory
|
||||
@Mock
|
||||
private lateinit var mKeyguardMessageArea: KeyguardMessageArea
|
||||
@Mock
|
||||
private lateinit var mKeyguardMessageAreaController: KeyguardMessageAreaController
|
||||
@Mock
|
||||
private lateinit var mLockPatternView: LockPatternView
|
||||
|
||||
private lateinit var mKeyguardPatternViewController: KeyguardPatternViewController
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
MockitoAnnotations.initMocks(this)
|
||||
`when`(mKeyguardPatternView.isAttachedToWindow).thenReturn(true)
|
||||
`when`(mKeyguardPatternView.findViewById<KeyguardMessageArea>(R.id.keyguard_message_area))
|
||||
.thenReturn(mKeyguardMessageArea)
|
||||
`when`(mKeyguardPatternView.findViewById<LockPatternView>(R.id.lockPatternView))
|
||||
.thenReturn(mLockPatternView)
|
||||
`when`(mKeyguardMessageAreaControllerFactory.create(mKeyguardMessageArea))
|
||||
.thenReturn(mKeyguardMessageAreaController)
|
||||
mKeyguardPatternViewController = KeyguardPatternViewController(mKeyguardPatternView,
|
||||
mKeyguardUpdateMonitor, mSecurityMode, mLockPatternUtils, mKeyguardSecurityCallback,
|
||||
mLatencyTracker, mKeyguardMessageAreaControllerFactory)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun onPause_clearsTextField() {
|
||||
mKeyguardPatternViewController.init()
|
||||
mKeyguardPatternViewController.onPause()
|
||||
verify(mKeyguardMessageAreaController).setMessage("")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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.keyguard
|
||||
|
||||
import androidx.test.filters.SmallTest
|
||||
import android.testing.AndroidTestingRunner
|
||||
import android.testing.TestableLooper
|
||||
import android.view.LayoutInflater
|
||||
|
||||
import com.android.systemui.R
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.statusbar.policy.ConfigurationController
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.Mockito.mock
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner::class)
|
||||
@TestableLooper.RunWithLooper
|
||||
class KeyguardPatternViewTest : SysuiTestCase() {
|
||||
|
||||
private lateinit var mKeyguardPatternView: KeyguardPatternView
|
||||
private lateinit var mSecurityMessage: KeyguardMessageArea
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
val inflater = LayoutInflater.from(context)
|
||||
mDependency.injectMockDependency(KeyguardUpdateMonitor::class.java)
|
||||
mKeyguardPatternView = inflater.inflate(R.layout.keyguard_pattern_view, null)
|
||||
as KeyguardPatternView
|
||||
mSecurityMessage = KeyguardMessageArea(mContext, null,
|
||||
mock(KeyguardUpdateMonitor::class.java), mock(ConfigurationController::class.java))
|
||||
mKeyguardPatternView.mSecurityMessageDisplay = mSecurityMessage
|
||||
}
|
||||
|
||||
@Test
|
||||
fun onPause_clearsTextField() {
|
||||
mSecurityMessage.setMessage("an old message")
|
||||
mKeyguardPatternView.onPause()
|
||||
assertThat(mSecurityMessage.text).isEqualTo("")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user