diff options
8 files changed, 349 insertions, 485 deletions
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java index 552e62052e6f..83fcac6579f2 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java @@ -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); } } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardMessageAreaController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardMessageAreaController.java index 78ac4e48501b..f056bdbb9706 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardMessageAreaController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardMessageAreaController.java @@ -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; diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java index 8baee3b306ef..44535bfef4ce 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java @@ -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 @@ -121,6 +184,11 @@ public class KeyguardPatternView extends KeyguardInputView } @Override + public void onEmergencyButtonClickedWhenInCall() { + mCallback.reset(); + } + + @Override public boolean onTouchEvent(MotionEvent ev) { boolean result = super.onTouchEvent(ev); // as long as the user is entering a pattern (i.e sending a touch event that was handled @@ -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); } } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java deleted file mode 100644 index 5e547d3120bf..000000000000 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java +++ /dev/null @@ -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(); - } -} diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java index 342f3de2ede3..87d3dd818232 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java @@ -256,7 +256,6 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard public void reset() { mView.reset(); - mSecurityViewFlipperController.reset(); } public CharSequence getTitle() { diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipperController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipperController.java index 806847579d61..07cfdb8672c5 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipperController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipperController.java @@ -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); } diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt deleted file mode 100644 index c69ec1a254c3..000000000000 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt +++ /dev/null @@ -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("") - } -} diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewTest.kt new file mode 100644 index 000000000000..b4363cf215f1 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewTest.kt @@ -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("") + } +} |