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:
Dave Mankoff
2020-09-22 00:24:04 +00:00
parent bdc667325a
commit 87f6d21e67
8 changed files with 349 additions and 485 deletions

View File

@@ -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);
}
}

View File

@@ -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;

View File

@@ -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);
}
}

View File

@@ -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();
}
}

View File

@@ -256,7 +256,6 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
public void reset() {
mView.reset();
mSecurityViewFlipperController.reset();
}
public CharSequence getTitle() {

View File

@@ -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);
}

View File

@@ -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("")
}
}

View File

@@ -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("")
}
}