summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/src/com/android/keyguard/AdminSecondaryLockScreenController.java30
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java5
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java2
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardInputView.java42
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java160
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java5
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java539
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java460
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSecurityModel.java19
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewController.java58
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java1
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/AdminSecondaryLockScreenControllerTest.java23
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java151
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java62
14 files changed, 654 insertions, 903 deletions
diff --git a/packages/SystemUI/src/com/android/keyguard/AdminSecondaryLockScreenController.java b/packages/SystemUI/src/com/android/keyguard/AdminSecondaryLockScreenController.java
index 23195af8bdea..e99245fa438f 100644
--- a/packages/SystemUI/src/com/android/keyguard/AdminSecondaryLockScreenController.java
+++ b/packages/SystemUI/src/com/android/keyguard/AdminSecondaryLockScreenController.java
@@ -33,13 +33,9 @@ import android.view.SurfaceView;
import android.view.ViewGroup;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.keyguard.dagger.KeyguardBouncerScope;
-import com.android.systemui.dagger.qualifiers.Main;
import java.util.NoSuchElementException;
-import javax.inject.Inject;
-
/**
* Encapsulates all logic for secondary lockscreen state management.
*/
@@ -146,9 +142,9 @@ public class AdminSecondaryLockScreenController {
}
};
- private AdminSecondaryLockScreenController(Context context, KeyguardSecurityContainer parent,
+ public AdminSecondaryLockScreenController(Context context, ViewGroup parent,
KeyguardUpdateMonitor updateMonitor, KeyguardSecurityCallback callback,
- @Main Handler handler) {
+ Handler handler) {
mContext = context;
mHandler = handler;
mParent = parent;
@@ -238,26 +234,4 @@ public class AdminSecondaryLockScreenController {
getHolder().removeCallback(mSurfaceHolderCallback);
}
}
-
- @KeyguardBouncerScope
- public static class Factory {
- private final Context mContext;
- private final KeyguardSecurityContainer mParent;
- private final KeyguardUpdateMonitor mUpdateMonitor;
- private final Handler mHandler;
-
- @Inject
- public Factory(Context context, KeyguardSecurityContainer parent,
- KeyguardUpdateMonitor updateMonitor, @Main Handler handler) {
- mContext = context;
- mParent = parent;
- mUpdateMonitor = updateMonitor;
- mHandler = handler;
- }
-
- public AdminSecondaryLockScreenController create(KeyguardSecurityCallback callback) {
- return new AdminSecondaryLockScreenController(mContext, mParent, mUpdateMonitor,
- callback, mHandler);
- }
- }
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java
index 889309dd72e7..88f4176f5eac 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java
@@ -28,6 +28,7 @@ import android.util.AttributeSet;
import android.view.HapticFeedbackConstants;
import android.view.KeyEvent;
import android.view.View;
+import android.widget.LinearLayout;
import com.android.internal.util.LatencyTracker;
import com.android.internal.widget.LockPatternChecker;
@@ -39,8 +40,8 @@ import com.android.systemui.R;
/**
* Base class for PIN and password unlock screens.
*/
-public abstract class KeyguardAbsKeyInputView extends KeyguardInputView
- implements EmergencyButton.EmergencyButtonCallback {
+public abstract class KeyguardAbsKeyInputView extends LinearLayout
+ implements KeyguardSecurityView, EmergencyButton.EmergencyButtonCallback {
protected KeyguardSecurityCallback mCallback;
protected LockPatternUtils mLockPatternUtils;
protected AsyncTask<?, ?, ?> mPendingLockCheck;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java
index b0a5533b0745..7aabb17de90c 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java
@@ -336,7 +336,7 @@ public class KeyguardHostViewController extends ViewController<KeyguardHostView>
}
public SecurityMode getCurrentSecurityMode() {
- return mKeyguardSecurityContainerController.getCurrentSecuritySelection();
+ return mKeyguardSecurityContainerController.getCurrentSecurityMode();
}
public int getTop() {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardInputView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardInputView.java
deleted file mode 100644
index 976ec02e4f29..000000000000
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardInputView.java
+++ /dev/null
@@ -1,42 +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.content.Context;
-import android.util.AttributeSet;
-import android.widget.LinearLayout;
-
-import androidx.annotation.Nullable;
-
-/**
- * A Base class for all Keyguard password/pattern/pin related inputs.
- */
-public abstract class KeyguardInputView extends LinearLayout implements KeyguardSecurityView {
-
- public KeyguardInputView(Context context) {
- super(context);
- }
-
- public KeyguardInputView(Context context,
- @Nullable AttributeSet attrs) {
- super(context, attrs);
- }
-
- public KeyguardInputView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- }
-}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java
deleted file mode 100644
index b0b2cd8c74d9..000000000000
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java
+++ /dev/null
@@ -1,160 +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.content.res.ColorStateList;
-import android.view.MotionEvent;
-
-import com.android.internal.widget.LockPatternUtils;
-import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
-import com.android.systemui.util.ViewController;
-
-import javax.inject.Inject;
-
-
-/** Controller for a {@link KeyguardSecurityView}. */
-public class KeyguardInputViewController extends ViewController<KeyguardInputView>
- implements KeyguardSecurityView {
-
- private final SecurityMode mSecurityMode;
- private final LockPatternUtils mLockPatternUtils;
-
- private KeyguardInputViewController(KeyguardInputView view, SecurityMode securityMode,
- LockPatternUtils lockPatternUtils,
- KeyguardSecurityCallback keyguardSecurityCallback) {
- super(view);
- mSecurityMode = securityMode;
- mLockPatternUtils = lockPatternUtils;
- mView.setKeyguardCallback(keyguardSecurityCallback);
- }
-
- @Override
- public void init() {
- super.init();
- mView.reset();
- }
-
- @Override
- protected void onViewAttached() {
- }
-
- @Override
- protected void onViewDetached() {
- }
-
- SecurityMode getSecurityMode() {
- return mSecurityMode;
- }
-
-
- @Override
- public void setKeyguardCallback(KeyguardSecurityCallback callback) {
- mView.setKeyguardCallback(callback);
- }
-
- @Override
- public void setLockPatternUtils(LockPatternUtils utils) {
- mView.setLockPatternUtils(utils);
- }
-
- @Override
- public void reset() {
- mView.reset();
- }
-
- @Override
- public void onPause() {
- mView.onPause();
- }
-
- @Override
- public void onResume(int reason) {
- mView.onResume(reason);
- }
-
- @Override
- public boolean needsInput() {
- return mView.needsInput();
- }
-
- @Override
- public KeyguardSecurityCallback getCallback() {
- return mView.getCallback();
- }
-
- @Override
- public void showPromptReason(int reason) {
- mView.showPromptReason(reason);
- }
-
- @Override
- public void showMessage(CharSequence message, ColorStateList colorState) {
- mView.showMessage(message, colorState);
- }
-
- @Override
- public void showUsabilityHint() {
- mView.showUsabilityHint();
- }
-
- @Override
- public void startAppearAnimation() {
- mView.startAppearAnimation();
- }
-
- @Override
- public boolean startDisappearAnimation(Runnable finishRunnable) {
- return mView.startDisappearAnimation(finishRunnable);
- }
-
- @Override
- public CharSequence getTitle() {
- return mView.getTitle();
- }
-
- @Override
- public boolean disallowInterceptTouch(MotionEvent event) {
- return mView.disallowInterceptTouch(event);
- }
-
- @Override
- public void onStartingToHide() {
- mView.onStartingToHide();
- }
-
- public void showSelf() {
- KeyguardSecurityViewFlipper flipper = (KeyguardSecurityViewFlipper) mView.getParent();
- flipper.setDisplayedChild(flipper.indexOfChild(mView));
- }
-
- /** Factory for a {@link KeyguardInputViewController}. */
- public static class Factory {
- private final LockPatternUtils mLockPatternUtils;
-
- @Inject
- public Factory(LockPatternUtils lockPatternUtils) {
- mLockPatternUtils = lockPatternUtils;
- }
-
- /** Create a new {@link KeyguardInputViewController}. */
- public KeyguardInputViewController create(KeyguardInputView keyguardInputView,
- SecurityMode securityMode, KeyguardSecurityCallback keyguardSecurityCallback) {
- return new KeyguardInputViewController(keyguardInputView, securityMode,
- mLockPatternUtils, keyguardSecurityCallback);
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java
index 44535bfef4ce..c4a9fcb45284 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java
@@ -32,6 +32,7 @@ import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
+import android.widget.LinearLayout;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.LatencyTracker;
@@ -47,8 +48,8 @@ import com.android.systemui.R;
import java.util.List;
-public class KeyguardPatternView extends KeyguardInputView
- implements AppearAnimationCreator<LockPatternView.CellState>,
+public class KeyguardPatternView extends LinearLayout implements KeyguardSecurityView,
+ AppearAnimationCreator<LockPatternView.CellState>,
EmergencyButton.EmergencyButtonCallback {
private static final String TAG = "SecurityPatternView";
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index e83795b70eed..81d37a830f8f 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -19,6 +19,8 @@ import static android.view.WindowInsets.Type.ime;
import static android.view.WindowInsets.Type.systemBars;
import static android.view.WindowInsetsAnimation.Callback.DISPATCH_MODE_STOP;
+import static com.android.systemui.DejankUtils.whitelistIpcs;
+
import static java.lang.Integer.max;
import android.animation.Animator;
@@ -26,14 +28,25 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.app.Activity;
import android.app.AlertDialog;
+import android.app.admin.DevicePolicyManager;
import android.content.Context;
+import android.content.Intent;
+import android.content.res.ColorStateList;
import android.graphics.Insets;
import android.graphics.Rect;
+import android.metrics.LogMaker;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.UserHandle;
import android.util.AttributeSet;
+import android.util.Log;
import android.util.MathUtils;
+import android.util.Slog;
import android.util.TypedValue;
+import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.VelocityTracker;
+import android.view.View;
import android.view.ViewConfiguration;
import android.view.WindowInsets;
import android.view.WindowInsetsAnimation;
@@ -48,30 +61,42 @@ import androidx.annotation.VisibleForTesting;
import androidx.dynamicanimation.animation.DynamicAnimation;
import androidx.dynamicanimation.animation.SpringAnimation;
+import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.UiEvent;
import com.android.internal.logging.UiEventLogger;
+import com.android.internal.logging.UiEventLoggerImpl;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
+import com.android.settingslib.utils.ThreadUtils;
+import com.android.systemui.Dependency;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
+import com.android.systemui.SystemUIFactory;
+import com.android.systemui.shared.system.SysUiStatsLog;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.util.InjectionInflationController;
import java.util.List;
-public class KeyguardSecurityContainer extends FrameLayout {
- static final int USER_TYPE_PRIMARY = 1;
- static final int USER_TYPE_WORK_PROFILE = 2;
- static final int USER_TYPE_SECONDARY_USER = 3;
+public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSecurityView {
+ private static final boolean DEBUG = KeyguardConstants.DEBUG;
+ private static final String TAG = "KeyguardSecurityView";
+
+ private static final int USER_TYPE_PRIMARY = 1;
+ private static final int USER_TYPE_WORK_PROFILE = 2;
+ private static final int USER_TYPE_SECONDARY_USER = 3;
// Bouncer is dismissed due to no security.
- static final int BOUNCER_DISMISS_NONE_SECURITY = 0;
+ private static final int BOUNCER_DISMISS_NONE_SECURITY = 0;
// Bouncer is dismissed due to pin, password or pattern entered.
- static final int BOUNCER_DISMISS_PASSWORD = 1;
+ private static final int BOUNCER_DISMISS_PASSWORD = 1;
// Bouncer is dismissed due to biometric (face, fingerprint or iris) authenticated.
- static final int BOUNCER_DISMISS_BIOMETRIC = 2;
+ private static final int BOUNCER_DISMISS_BIOMETRIC = 2;
// Bouncer is dismissed due to extended access granted.
- static final int BOUNCER_DISMISS_EXTENDED_ACCESS = 3;
+ private static final int BOUNCER_DISMISS_EXTENDED_ACCESS = 3;
// Bouncer is dismissed due to sim card unlock code entered.
- static final int BOUNCER_DISMISS_SIM = 4;
+ private static final int BOUNCER_DISMISS_SIM = 4;
// Make the view move slower than the finger, as if the spring were applying force.
private static final float TOUCH_Y_MULTIPLIER = 0.25f;
@@ -80,23 +105,36 @@ public class KeyguardSecurityContainer extends FrameLayout {
// How much to scale the default slop by, to avoid accidental drags.
private static final float SLOP_SCALE = 4f;
+ private static final UiEventLogger sUiEventLogger = new UiEventLoggerImpl();
+
private static final long IME_DISAPPEAR_DURATION_MS = 125;
+ private KeyguardSecurityModel mSecurityModel;
+ private LockPatternUtils mLockPatternUtils;
+
@VisibleForTesting
KeyguardSecurityViewFlipper mSecurityViewFlipper;
+ private boolean mIsVerifyUnlockOnly;
+ private SecurityMode mCurrentSecuritySelection = SecurityMode.Invalid;
+ private KeyguardSecurityView mCurrentSecurityView;
+ private SecurityCallback mSecurityCallback;
private AlertDialog mAlertDialog;
+ private InjectionInflationController mInjectionInflationController;
private boolean mSwipeUpToRetry;
+ private AdminSecondaryLockScreenController mSecondaryLockScreenController;
private final ViewConfiguration mViewConfiguration;
private final SpringAnimation mSpringAnimation;
private final VelocityTracker mVelocityTracker = VelocityTracker.obtain();
+ private final KeyguardUpdateMonitor mUpdateMonitor;
+ private final KeyguardStateController mKeyguardStateController;
+ private final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class);
private float mLastTouchY = -1;
private int mActivePointerId = -1;
private boolean mIsDragging;
private float mStartTouchY = -1;
private boolean mDisappearAnimRunning;
- private SwipeListener mSwipeListener;
private final WindowInsetsAnimation.Callback mWindowInsetsAnimationCallback =
new WindowInsetsAnimation.Callback(DISPATCH_MODE_STOP) {
@@ -146,28 +184,21 @@ public class KeyguardSecurityContainer extends FrameLayout {
}
};
- KeyguardSecurityViewFlipper getSecurityViewFlipper() {
- return mSecurityViewFlipper;
- }
-
// Used to notify the container when something interesting happens.
public interface SecurityCallback {
- boolean dismiss(boolean authenticated, int targetUserId, boolean bypassSecondaryLockScreen);
- void userActivity();
- void onSecurityModeChanged(SecurityMode securityMode, boolean needsInput);
+ public boolean dismiss(boolean authenticated, int targetUserId,
+ boolean bypassSecondaryLockScreen);
+ public void userActivity();
+ public void onSecurityModeChanged(SecurityMode securityMode, boolean needsInput);
/**
* @param strongAuth wheher the user has authenticated with strong authentication like
* pattern, password or PIN but not by trust agents or fingerprint
* @param targetUserId a user that needs to be the foreground user at the finish completion.
*/
- void finish(boolean strongAuth, int targetUserId);
- void reset();
- void onCancelClicked();
- }
-
- public interface SwipeListener {
- void onSwipeUp();
+ public void finish(boolean strongAuth, int targetUserId);
+ public void reset();
+ public void onCancelClicked();
}
@VisibleForTesting
@@ -218,24 +249,52 @@ public class KeyguardSecurityContainer extends FrameLayout {
public KeyguardSecurityContainer(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
+ mSecurityModel = Dependency.get(KeyguardSecurityModel.class);
+ mLockPatternUtils = new LockPatternUtils(context);
+ mUpdateMonitor = Dependency.get(KeyguardUpdateMonitor.class);
mSpringAnimation = new SpringAnimation(this, DynamicAnimation.Y);
+ mInjectionInflationController = new InjectionInflationController(
+ SystemUIFactory.getInstance().getSysUIComponent().createViewInstanceCreatorFactory());
mViewConfiguration = ViewConfiguration.get(context);
+ mKeyguardStateController = Dependency.get(KeyguardStateController.class);
+ mSecondaryLockScreenController = new AdminSecondaryLockScreenController(context, this,
+ mUpdateMonitor, mCallback, new Handler(Looper.myLooper()));
+ }
+
+ public void setSecurityCallback(SecurityCallback callback) {
+ mSecurityCallback = callback;
}
- void onResume(SecurityMode securityMode, boolean faceAuthEnabled) {
+ @Override
+ public void onResume(int reason) {
+ if (mCurrentSecuritySelection != SecurityMode.None) {
+ getSecurityView(mCurrentSecuritySelection).onResume(reason);
+ }
mSecurityViewFlipper.setWindowInsetsAnimationCallback(mWindowInsetsAnimationCallback);
- updateBiometricRetry(securityMode, faceAuthEnabled);
+ updateBiometricRetry();
}
+ @Override
public void onPause() {
if (mAlertDialog != null) {
mAlertDialog.dismiss();
mAlertDialog = null;
}
+ mSecondaryLockScreenController.hide();
+ if (mCurrentSecuritySelection != SecurityMode.None) {
+ getSecurityView(mCurrentSecuritySelection).onPause();
+ }
mSecurityViewFlipper.setWindowInsetsAnimationCallback(null);
}
@Override
+ public void onStartingToHide() {
+ if (mCurrentSecuritySelection != SecurityMode.None) {
+ getSecurityView(mCurrentSecuritySelection).onStartingToHide();
+ }
+ }
+
+ @Override
public boolean shouldDelayChildPressedState() {
return true;
}
@@ -257,12 +316,13 @@ public class KeyguardSecurityContainer extends FrameLayout {
return false;
}
// Avoid dragging the pattern view
- if (mSecurityViewFlipper.getSecurityView().disallowInterceptTouch(event)) {
+ if (mCurrentSecurityView.disallowInterceptTouch(event)) {
return false;
}
int index = event.findPointerIndex(mActivePointerId);
float touchSlop = mViewConfiguration.getScaledTouchSlop() * SLOP_SCALE;
- if (index != -1 && mStartTouchY - event.getY(index) > touchSlop) {
+ if (mCurrentSecurityView != null && index != -1
+ && mStartTouchY - event.getY(index) > touchSlop) {
mIsDragging = true;
return true;
}
@@ -310,28 +370,31 @@ public class KeyguardSecurityContainer extends FrameLayout {
}
if (action == MotionEvent.ACTION_UP) {
if (-getTranslationY() > TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
- MIN_DRAG_SIZE, getResources().getDisplayMetrics())) {
- if (mSwipeListener != null) {
- mSwipeListener.onSwipeUp();
- }
+ MIN_DRAG_SIZE, getResources().getDisplayMetrics())
+ && !mUpdateMonitor.isFaceDetectionRunning()) {
+ mUpdateMonitor.requestFaceAuth();
+ mCallback.userActivity();
+ showMessage(null, null);
}
}
return true;
}
- void setSwipeListener(SwipeListener swipeListener) {
- mSwipeListener = swipeListener;
- }
-
private void startSpringAnimation(float startVelocity) {
mSpringAnimation
.setStartVelocity(startVelocity)
.animateToFinalPosition(0);
}
- public void startDisappearAnimation(SecurityMode securitySelection) {
+ public void startAppearAnimation() {
+ if (mCurrentSecuritySelection != SecurityMode.None) {
+ getSecurityView(mCurrentSecuritySelection).startAppearAnimation();
+ }
+ }
+
+ public boolean startDisappearAnimation(Runnable onFinishRunnable) {
mDisappearAnimRunning = true;
- if (securitySelection == SecurityMode.Password) {
+ if (mCurrentSecuritySelection == SecurityMode.Password) {
mSecurityViewFlipper.getWindowInsetsController().controlWindowInsetsAnimation(ime(),
IME_DISAPPEAR_DURATION_MS,
Interpolators.LINEAR, null, new WindowInsetsAnimationControlListener() {
@@ -376,13 +439,19 @@ public class KeyguardSecurityContainer extends FrameLayout {
}
});
}
+ if (mCurrentSecuritySelection != SecurityMode.None) {
+ return getSecurityView(mCurrentSecuritySelection).startDisappearAnimation(
+ onFinishRunnable);
+ }
+ return false;
}
/**
* Enables/disables swipe up to retry on the bouncer.
*/
- private void updateBiometricRetry(SecurityMode securityMode, boolean faceAuthEnabled) {
- mSwipeUpToRetry = faceAuthEnabled
+ private void updateBiometricRetry() {
+ SecurityMode securityMode = getSecurityMode();
+ mSwipeUpToRetry = mKeyguardStateController.isFaceAuthEnabled()
&& securityMode != SecurityMode.SimPin
&& securityMode != SecurityMode.SimPuk
&& securityMode != SecurityMode.None;
@@ -392,15 +461,53 @@ public class KeyguardSecurityContainer extends FrameLayout {
return mSecurityViewFlipper.getTitle();
}
+ @VisibleForTesting
+ protected KeyguardSecurityView getSecurityView(SecurityMode securityMode) {
+ final int securityViewIdForMode = getSecurityViewIdForMode(securityMode);
+ KeyguardSecurityView view = null;
+ final int children = mSecurityViewFlipper.getChildCount();
+ for (int child = 0; child < children; child++) {
+ if (mSecurityViewFlipper.getChildAt(child).getId() == securityViewIdForMode) {
+ view = ((KeyguardSecurityView)mSecurityViewFlipper.getChildAt(child));
+ break;
+ }
+ }
+ int layoutId = getLayoutIdFor(securityMode);
+ if (view == null && layoutId != 0) {
+ final LayoutInflater inflater = LayoutInflater.from(mContext);
+ if (DEBUG) Log.v(TAG, "inflating id = " + layoutId);
+ View v = mInjectionInflationController.injectable(inflater)
+ .inflate(layoutId, mSecurityViewFlipper, false);
+ mSecurityViewFlipper.addView(v);
+ updateSecurityView(v);
+ view = (KeyguardSecurityView)v;
+ view.reset();
+ }
+
+ return view;
+ }
+
+ private void updateSecurityView(View view) {
+ if (view instanceof KeyguardSecurityView) {
+ KeyguardSecurityView ksv = (KeyguardSecurityView) view;
+ ksv.setKeyguardCallback(mCallback);
+ ksv.setLockPatternUtils(mLockPatternUtils);
+ } else {
+ Log.w(TAG, "View " + view + " is not a KeyguardSecurityView");
+ }
+ }
@Override
public void onFinishInflate() {
super.onFinishInflate();
mSecurityViewFlipper = findViewById(R.id.view_flipper);
+ mSecurityViewFlipper.setLockPatternUtils(mLockPatternUtils);
}
public void setLockPatternUtils(LockPatternUtils utils) {
- mSecurityViewFlipper.setLockPatternUtils(utils);
+ mLockPatternUtils = utils;
+ mSecurityModel.setLockPatternUtils(utils);
+ mSecurityViewFlipper.setLockPatternUtils(mLockPatternUtils);
}
@Override
@@ -432,12 +539,11 @@ public class KeyguardSecurityContainer extends FrameLayout {
mAlertDialog.show();
}
- void showTimeoutDialog(int userId, int timeoutMs, LockPatternUtils lockPatternUtils,
- SecurityMode securityMode) {
- int timeoutInSeconds = timeoutMs / 1000;
+ private void showTimeoutDialog(int userId, int timeoutMs) {
+ int timeoutInSeconds = (int) timeoutMs / 1000;
int messageId = 0;
- switch (securityMode) {
+ switch (mSecurityModel.getSecurityMode(userId)) {
case Pattern:
messageId = R.string.kg_too_many_failed_pattern_attempts_dialog_message;
break;
@@ -457,13 +563,13 @@ public class KeyguardSecurityContainer extends FrameLayout {
if (messageId != 0) {
final String message = mContext.getString(messageId,
- lockPatternUtils.getCurrentFailedPasswordAttempts(userId),
+ mLockPatternUtils.getCurrentFailedPasswordAttempts(userId),
timeoutInSeconds);
showDialog(null, message);
}
}
- void showAlmostAtWipeDialog(int attempts, int remaining, int userType) {
+ private void showAlmostAtWipeDialog(int attempts, int remaining, int userType) {
String message = null;
switch (userType) {
case USER_TYPE_PRIMARY:
@@ -482,7 +588,7 @@ public class KeyguardSecurityContainer extends FrameLayout {
showDialog(null, message);
}
- void showWipeDialog(int attempts, int userType) {
+ private void showWipeDialog(int attempts, int userType) {
String message = null;
switch (userType) {
case USER_TYPE_PRIMARY:
@@ -501,19 +607,356 @@ public class KeyguardSecurityContainer extends FrameLayout {
showDialog(null, message);
}
+ private void reportFailedUnlockAttempt(int userId, int timeoutMs) {
+ // +1 for this time
+ final int failedAttempts = mLockPatternUtils.getCurrentFailedPasswordAttempts(userId) + 1;
+
+ if (DEBUG) Log.d(TAG, "reportFailedPatternAttempt: #" + failedAttempts);
+
+ final DevicePolicyManager dpm = mLockPatternUtils.getDevicePolicyManager();
+ final int failedAttemptsBeforeWipe =
+ dpm.getMaximumFailedPasswordsForWipe(null, userId);
+
+ final int remainingBeforeWipe = failedAttemptsBeforeWipe > 0 ?
+ (failedAttemptsBeforeWipe - failedAttempts)
+ : Integer.MAX_VALUE; // because DPM returns 0 if no restriction
+ if (remainingBeforeWipe < LockPatternUtils.FAILED_ATTEMPTS_BEFORE_WIPE_GRACE) {
+ // The user has installed a DevicePolicyManager that requests a user/profile to be wiped
+ // N attempts. Once we get below the grace period, we post this dialog every time as a
+ // clear warning until the deletion fires.
+ // Check which profile has the strictest policy for failed password attempts
+ final int expiringUser = dpm.getProfileWithMinimumFailedPasswordsForWipe(userId);
+ int userType = USER_TYPE_PRIMARY;
+ if (expiringUser == userId) {
+ // TODO: http://b/23522538
+ if (expiringUser != UserHandle.USER_SYSTEM) {
+ userType = USER_TYPE_SECONDARY_USER;
+ }
+ } else if (expiringUser != UserHandle.USER_NULL) {
+ userType = USER_TYPE_WORK_PROFILE;
+ } // If USER_NULL, which shouldn't happen, leave it as USER_TYPE_PRIMARY
+ if (remainingBeforeWipe > 0) {
+ showAlmostAtWipeDialog(failedAttempts, remainingBeforeWipe, userType);
+ } else {
+ // Too many attempts. The device will be wiped shortly.
+ Slog.i(TAG, "Too many unlock attempts; user " + expiringUser + " will be wiped!");
+ showWipeDialog(failedAttempts, userType);
+ }
+ }
+ mLockPatternUtils.reportFailedPasswordAttempt(userId);
+ if (timeoutMs > 0) {
+ mLockPatternUtils.reportPasswordLockout(timeoutMs, userId);
+ showTimeoutDialog(userId, timeoutMs);
+ }
+ }
+
+ /**
+ * Shows the primary security screen for the user. This will be either the multi-selector
+ * or the user's security method.
+ * @param turningOff true if the device is being turned off
+ */
+ void showPrimarySecurityScreen(boolean turningOff) {
+ SecurityMode securityMode = whitelistIpcs(() -> mSecurityModel.getSecurityMode(
+ KeyguardUpdateMonitor.getCurrentUser()));
+ if (DEBUG) Log.v(TAG, "showPrimarySecurityScreen(turningOff=" + turningOff + ")");
+ showSecurityScreen(securityMode);
+ }
+
+ /**
+ * Shows the next security screen if there is one.
+ * @param authenticated true if the user entered the correct authentication
+ * @param targetUserId a user that needs to be the foreground user at the finish (if called)
+ * completion.
+ * @param bypassSecondaryLockScreen true if the user is allowed to bypass the secondary
+ * secondary lock screen requirement, if any.
+ * @return true if keyguard is done
+ */
+ boolean showNextSecurityScreenOrFinish(boolean authenticated, int targetUserId,
+ boolean bypassSecondaryLockScreen) {
+ if (DEBUG) Log.d(TAG, "showNextSecurityScreenOrFinish(" + authenticated + ")");
+ boolean finish = false;
+ boolean strongAuth = false;
+ int eventSubtype = -1;
+ BouncerUiEvent uiEvent = BouncerUiEvent.UNKNOWN;
+ if (mUpdateMonitor.getUserHasTrust(targetUserId)) {
+ finish = true;
+ eventSubtype = BOUNCER_DISMISS_EXTENDED_ACCESS;
+ uiEvent = BouncerUiEvent.BOUNCER_DISMISS_EXTENDED_ACCESS;
+ } else if (mUpdateMonitor.getUserUnlockedWithBiometric(targetUserId)) {
+ finish = true;
+ eventSubtype = BOUNCER_DISMISS_BIOMETRIC;
+ uiEvent = BouncerUiEvent.BOUNCER_DISMISS_BIOMETRIC;
+ } else if (SecurityMode.None == mCurrentSecuritySelection) {
+ SecurityMode securityMode = mSecurityModel.getSecurityMode(targetUserId);
+ if (SecurityMode.None == securityMode) {
+ finish = true; // no security required
+ eventSubtype = BOUNCER_DISMISS_NONE_SECURITY;
+ uiEvent = BouncerUiEvent.BOUNCER_DISMISS_NONE_SECURITY;
+ } else {
+ showSecurityScreen(securityMode); // switch to the alternate security view
+ }
+ } else if (authenticated) {
+ switch (mCurrentSecuritySelection) {
+ case Pattern:
+ case Password:
+ case PIN:
+ strongAuth = true;
+ finish = true;
+ eventSubtype = BOUNCER_DISMISS_PASSWORD;
+ uiEvent = BouncerUiEvent.BOUNCER_DISMISS_PASSWORD;
+ break;
+
+ case SimPin:
+ case SimPuk:
+ // Shortcut for SIM PIN/PUK to go to directly to user's security screen or home
+ SecurityMode securityMode = mSecurityModel.getSecurityMode(targetUserId);
+ if (securityMode == SecurityMode.None && mLockPatternUtils.isLockScreenDisabled(
+ KeyguardUpdateMonitor.getCurrentUser())) {
+ finish = true;
+ eventSubtype = BOUNCER_DISMISS_SIM;
+ uiEvent = BouncerUiEvent.BOUNCER_DISMISS_SIM;
+ } else {
+ showSecurityScreen(securityMode);
+ }
+ break;
+
+ default:
+ Log.v(TAG, "Bad security screen " + mCurrentSecuritySelection + ", fail safe");
+ showPrimarySecurityScreen(false);
+ break;
+ }
+ }
+ // Check for device admin specified additional security measures.
+ if (finish && !bypassSecondaryLockScreen) {
+ Intent secondaryLockscreenIntent =
+ mUpdateMonitor.getSecondaryLockscreenRequirement(targetUserId);
+ if (secondaryLockscreenIntent != null) {
+ mSecondaryLockScreenController.show(secondaryLockscreenIntent);
+ return false;
+ }
+ }
+ if (eventSubtype != -1) {
+ mMetricsLogger.write(new LogMaker(MetricsEvent.BOUNCER)
+ .setType(MetricsEvent.TYPE_DISMISS).setSubtype(eventSubtype));
+ }
+ if (uiEvent != BouncerUiEvent.UNKNOWN) {
+ sUiEventLogger.log(uiEvent);
+ }
+ if (finish) {
+ mSecurityCallback.finish(strongAuth, targetUserId);
+ }
+ return finish;
+ }
+
+ /**
+ * Switches to the given security view unless it's already being shown, in which case
+ * this is a no-op.
+ *
+ * @param securityMode
+ */
+ private void showSecurityScreen(SecurityMode securityMode) {
+ if (DEBUG) Log.d(TAG, "showSecurityScreen(" + securityMode + ")");
+
+ if (securityMode == mCurrentSecuritySelection) return;
+
+ KeyguardSecurityView oldView = getSecurityView(mCurrentSecuritySelection);
+ KeyguardSecurityView newView = getSecurityView(securityMode);
+
+ // Emulate Activity life cycle
+ if (oldView != null) {
+ oldView.onPause();
+ oldView.setKeyguardCallback(mNullCallback); // ignore requests from old view
+ }
+ if (securityMode != SecurityMode.None) {
+ newView.onResume(KeyguardSecurityView.VIEW_REVEALED);
+ newView.setKeyguardCallback(mCallback);
+ }
+
+ // Find and show this child.
+ final int childCount = mSecurityViewFlipper.getChildCount();
+
+ final int securityViewIdForMode = getSecurityViewIdForMode(securityMode);
+ for (int i = 0; i < childCount; i++) {
+ if (mSecurityViewFlipper.getChildAt(i).getId() == securityViewIdForMode) {
+ mSecurityViewFlipper.setDisplayedChild(i);
+ break;
+ }
+ }
+
+ mCurrentSecuritySelection = securityMode;
+ mCurrentSecurityView = newView;
+ mSecurityCallback.onSecurityModeChanged(securityMode,
+ securityMode != SecurityMode.None && newView.needsInput());
+ }
+
+ private KeyguardSecurityCallback mCallback = new KeyguardSecurityCallback() {
+ public void userActivity() {
+ if (mSecurityCallback != null) {
+ mSecurityCallback.userActivity();
+ }
+ }
+
+ @Override
+ public void onUserInput() {
+ mUpdateMonitor.cancelFaceAuth();
+ }
+
+ @Override
+ public void dismiss(boolean authenticated, int targetId) {
+ dismiss(authenticated, targetId, /* bypassSecondaryLockScreen */ false);
+ }
+
+ @Override
+ public void dismiss(boolean authenticated, int targetId,
+ boolean bypassSecondaryLockScreen) {
+ mSecurityCallback.dismiss(authenticated, targetId, bypassSecondaryLockScreen);
+ }
+
+ public boolean isVerifyUnlockOnly() {
+ return mIsVerifyUnlockOnly;
+ }
+
+ public void reportUnlockAttempt(int userId, boolean success, int timeoutMs) {
+ if (success) {
+ SysUiStatsLog.write(SysUiStatsLog.KEYGUARD_BOUNCER_PASSWORD_ENTERED,
+ SysUiStatsLog.KEYGUARD_BOUNCER_PASSWORD_ENTERED__RESULT__SUCCESS);
+ mLockPatternUtils.reportSuccessfulPasswordAttempt(userId);
+ // Force a garbage collection in an attempt to erase any lockscreen password left in
+ // memory. Do it asynchronously with a 5-sec delay to avoid making the keyguard
+ // dismiss animation janky.
+ ThreadUtils.postOnBackgroundThread(() -> {
+ try {
+ Thread.sleep(5000);
+ } catch (InterruptedException ignored) { }
+ Runtime.getRuntime().gc();
+ });
+ } else {
+ SysUiStatsLog.write(SysUiStatsLog.KEYGUARD_BOUNCER_PASSWORD_ENTERED,
+ SysUiStatsLog.KEYGUARD_BOUNCER_PASSWORD_ENTERED__RESULT__FAILURE);
+ KeyguardSecurityContainer.this.reportFailedUnlockAttempt(userId, timeoutMs);
+ }
+ mMetricsLogger.write(new LogMaker(MetricsEvent.BOUNCER)
+ .setType(success ? MetricsEvent.TYPE_SUCCESS : MetricsEvent.TYPE_FAILURE));
+ sUiEventLogger.log(success ? BouncerUiEvent.BOUNCER_PASSWORD_SUCCESS
+ : BouncerUiEvent.BOUNCER_PASSWORD_FAILURE);
+ }
+
+ public void reset() {
+ mSecurityCallback.reset();
+ }
+
+ public void onCancelClicked() {
+ mSecurityCallback.onCancelClicked();
+ }
+ };
+
+ // The following is used to ignore callbacks from SecurityViews that are no longer current
+ // (e.g. face unlock). This avoids unwanted asynchronous events from messing with the
+ // state for the current security method.
+ private KeyguardSecurityCallback mNullCallback = new KeyguardSecurityCallback() {
+ @Override
+ public void userActivity() { }
+ @Override
+ public void reportUnlockAttempt(int userId, boolean success, int timeoutMs) { }
+ @Override
+ public boolean isVerifyUnlockOnly() { return false; }
+ @Override
+ public void dismiss(boolean securityVerified, int targetUserId) { }
+ @Override
+ public void dismiss(boolean authenticated, int targetId,
+ boolean bypassSecondaryLockScreen) { }
+ @Override
+ public void onUserInput() { }
+ @Override
+ public void reset() {}
+ };
+
+ private int getSecurityViewIdForMode(SecurityMode securityMode) {
+ switch (securityMode) {
+ case Pattern: return R.id.keyguard_pattern_view;
+ case PIN: return R.id.keyguard_pin_view;
+ case Password: return R.id.keyguard_password_view;
+ case SimPin: return R.id.keyguard_sim_pin_view;
+ case SimPuk: return R.id.keyguard_sim_puk_view;
+ }
+ return 0;
+ }
+
+ @VisibleForTesting
+ public int getLayoutIdFor(SecurityMode securityMode) {
+ switch (securityMode) {
+ case Pattern: return R.layout.keyguard_pattern_view;
+ case PIN: return R.layout.keyguard_pin_view;
+ case Password: return R.layout.keyguard_password_view;
+ case SimPin: return R.layout.keyguard_sim_pin_view;
+ case SimPuk: return R.layout.keyguard_sim_puk_view;
+ default:
+ return 0;
+ }
+ }
+
+ public SecurityMode getSecurityMode() {
+ return mSecurityModel.getSecurityMode(KeyguardUpdateMonitor.getCurrentUser());
+ }
+
+ public SecurityMode getCurrentSecurityMode() {
+ return mCurrentSecuritySelection;
+ }
+
+ public KeyguardSecurityView getCurrentSecurityView() {
+ return mCurrentSecurityView;
+ }
+
+ public void verifyUnlock() {
+ mIsVerifyUnlockOnly = true;
+ showSecurityScreen(getSecurityMode());
+ }
+
+ public SecurityMode getCurrentSecuritySelection() {
+ return mCurrentSecuritySelection;
+ }
+
+ public void dismiss(boolean authenticated, int targetUserId) {
+ mCallback.dismiss(authenticated, targetUserId);
+ }
+
public boolean needsInput() {
return mSecurityViewFlipper.needsInput();
}
+ @Override
+ public void setKeyguardCallback(KeyguardSecurityCallback callback) {
+ mSecurityViewFlipper.setKeyguardCallback(callback);
+ }
+
+ @Override
public void reset() {
mSecurityViewFlipper.reset();
mDisappearAnimRunning = false;
}
+ @Override
public KeyguardSecurityCallback getCallback() {
return mSecurityViewFlipper.getCallback();
}
+ @Override
+ public void showPromptReason(int reason) {
+ if (mCurrentSecuritySelection != SecurityMode.None) {
+ if (reason != PROMPT_REASON_NONE) {
+ Log.i(TAG, "Strong auth required, reason: " + reason);
+ }
+ getSecurityView(mCurrentSecuritySelection).showPromptReason(reason);
+ }
+ }
+
+ public void showMessage(CharSequence message, ColorStateList colorState) {
+ if (mCurrentSecuritySelection != SecurityMode.None) {
+ getSecurityView(mCurrentSecuritySelection).showMessage(message, colorState);
+ }
+ }
+
+ @Override
public void showUsabilityHint() {
mSecurityViewFlipper.showUsabilityHint();
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
index 11f951be9a15..17f25bd08ef4 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
@@ -16,197 +16,33 @@
package com.android.keyguard;
-import static com.android.keyguard.KeyguardSecurityContainer.BOUNCER_DISMISS_BIOMETRIC;
-import static com.android.keyguard.KeyguardSecurityContainer.BOUNCER_DISMISS_EXTENDED_ACCESS;
-import static com.android.keyguard.KeyguardSecurityContainer.BOUNCER_DISMISS_NONE_SECURITY;
-import static com.android.keyguard.KeyguardSecurityContainer.BOUNCER_DISMISS_PASSWORD;
-import static com.android.keyguard.KeyguardSecurityContainer.BOUNCER_DISMISS_SIM;
-import static com.android.keyguard.KeyguardSecurityContainer.USER_TYPE_PRIMARY;
-import static com.android.keyguard.KeyguardSecurityContainer.USER_TYPE_SECONDARY_USER;
-import static com.android.keyguard.KeyguardSecurityContainer.USER_TYPE_WORK_PROFILE;
-import static com.android.systemui.DejankUtils.whitelistIpcs;
-
-import android.app.admin.DevicePolicyManager;
-import android.content.Intent;
import android.content.res.ColorStateList;
-import android.metrics.LogMaker;
-import android.os.UserHandle;
-import android.util.Log;
-import android.util.Slog;
-import android.view.LayoutInflater;
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.UiEventLogger;
-import com.android.internal.logging.nano.MetricsProto;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.widget.LockPatternUtils;
-import com.android.keyguard.KeyguardSecurityContainer.BouncerUiEvent;
import com.android.keyguard.KeyguardSecurityContainer.SecurityCallback;
-import com.android.keyguard.KeyguardSecurityContainer.SwipeListener;
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
-import com.android.settingslib.utils.ThreadUtils;
-import com.android.systemui.R;
-import com.android.systemui.shared.system.SysUiStatsLog;
-import com.android.systemui.statusbar.policy.KeyguardStateController;
-import com.android.systemui.util.InjectionInflationController;
import com.android.systemui.util.ViewController;
-import java.util.ArrayList;
-import java.util.List;
-
import javax.inject.Inject;
/** Controller for {@link KeyguardSecurityContainer} */
-public class KeyguardSecurityContainerController extends ViewController<KeyguardSecurityContainer>
- implements KeyguardSecurityView {
+public class KeyguardSecurityContainerController extends ViewController<KeyguardSecurityContainer> {
- private static final boolean DEBUG = KeyguardConstants.DEBUG;
- private static final String TAG = "KeyguardSecurityView";
-
- private final AdminSecondaryLockScreenController mAdminSecondaryLockScreenController;
private final LockPatternUtils mLockPatternUtils;
- private final KeyguardUpdateMonitor mUpdateMonitor;
- private final KeyguardSecurityModel mSecurityModel;
- private final MetricsLogger mMetricsLogger;
- private final UiEventLogger mUiEventLogger;
- private final KeyguardStateController mKeyguardStateController;
- private final LayoutInflater mLayoutInflater;
- private final KeyguardInputViewController.Factory mKeyguardSecurityViewControllerFactory;
- private final List<KeyguardInputViewController> mChildren = new ArrayList<>();
-
- private SecurityCallback mSecurityCallback;
- private SecurityMode mCurrentSecuritySelection = SecurityMode.Invalid;
- private KeyguardSecurityView mCurrentSecurityView;
-
- private KeyguardSecurityCallback mKeyguardSecurityCallback = new KeyguardSecurityCallback() {
- public void userActivity() {
- if (mSecurityCallback != null) {
- mSecurityCallback.userActivity();
- }
- }
-
- @Override
- public void onUserInput() {
- mUpdateMonitor.cancelFaceAuth();
- }
-
- @Override
- public void dismiss(boolean authenticated, int targetId) {
- dismiss(authenticated, targetId, /* bypassSecondaryLockScreen */ false);
- }
-
- @Override
- public void dismiss(boolean authenticated, int targetId,
- boolean bypassSecondaryLockScreen) {
- mSecurityCallback.dismiss(authenticated, targetId, bypassSecondaryLockScreen);
- }
-
- public boolean isVerifyUnlockOnly() {
- return false;
- }
-
- public void reportUnlockAttempt(int userId, boolean success, int timeoutMs) {
- if (success) {
- SysUiStatsLog.write(SysUiStatsLog.KEYGUARD_BOUNCER_PASSWORD_ENTERED,
- SysUiStatsLog.KEYGUARD_BOUNCER_PASSWORD_ENTERED__RESULT__SUCCESS);
- mLockPatternUtils.reportSuccessfulPasswordAttempt(userId);
- // Force a garbage collection in an attempt to erase any lockscreen password left in
- // memory. Do it asynchronously with a 5-sec delay to avoid making the keyguard
- // dismiss animation janky.
- ThreadUtils.postOnBackgroundThread(() -> {
- try {
- Thread.sleep(5000);
- } catch (InterruptedException ignored) { }
- Runtime.getRuntime().gc();
- });
- } else {
- SysUiStatsLog.write(SysUiStatsLog.KEYGUARD_BOUNCER_PASSWORD_ENTERED,
- SysUiStatsLog.KEYGUARD_BOUNCER_PASSWORD_ENTERED__RESULT__FAILURE);
- reportFailedUnlockAttempt(userId, timeoutMs);
- }
- mMetricsLogger.write(new LogMaker(MetricsEvent.BOUNCER)
- .setType(success ? MetricsEvent.TYPE_SUCCESS : MetricsEvent.TYPE_FAILURE));
- mUiEventLogger.log(success ? BouncerUiEvent.BOUNCER_PASSWORD_SUCCESS
- : BouncerUiEvent.BOUNCER_PASSWORD_FAILURE);
- }
-
- public void reset() {
- mSecurityCallback.reset();
- }
-
- public void onCancelClicked() {
- mSecurityCallback.onCancelClicked();
- }
- };
-
- // The following is used to ignore callbacks from SecurityViews that are no longer current
- // (e.g. face unlock). This avoids unwanted asynchronous events from messing with the
- // state for the current security method.
- private KeyguardSecurityCallback mNullCallback = new KeyguardSecurityCallback() {
- @Override
- public void userActivity() { }
- @Override
- public void reportUnlockAttempt(int userId, boolean success, int timeoutMs) { }
- @Override
- public boolean isVerifyUnlockOnly() {
- return false;
- }
- @Override
- public void dismiss(boolean securityVerified, int targetUserId) { }
- @Override
- public void dismiss(boolean authenticated, int targetId,
- boolean bypassSecondaryLockScreen) { }
- @Override
- public void onUserInput() { }
- @Override
- public void reset() {}
- };
-
- private SwipeListener mSwipeListener = new SwipeListener() {
- @Override
- public void onSwipeUp() {
- if (!mUpdateMonitor.isFaceDetectionRunning()) {
- mUpdateMonitor.requestFaceAuth();
- mKeyguardSecurityCallback.userActivity();
- showMessage(null, null);
- }
- }
- };
+ private final KeyguardSecurityViewController.Factory mKeyguardSecurityViewControllerFactory;
@Inject
KeyguardSecurityContainerController(KeyguardSecurityContainer view,
- AdminSecondaryLockScreenController.Factory adminSecondaryLockScreenControllerFactory,
LockPatternUtils lockPatternUtils,
- KeyguardUpdateMonitor keyguardUpdateMonitor,
- KeyguardSecurityModel keyguardSecurityModel,
- MetricsLogger metricsLogger,
- UiEventLogger uiEventLogger,
- KeyguardStateController keyguardStateController,
- LayoutInflater layoutInflater,
- InjectionInflationController injectionInflationController,
- KeyguardInputViewController.Factory keyguardSecurityViewControllerFactory) {
+ KeyguardSecurityViewController.Factory keyguardSecurityViewControllerFactory) {
super(view);
mLockPatternUtils = lockPatternUtils;
- mUpdateMonitor = keyguardUpdateMonitor;
- mSecurityModel = keyguardSecurityModel;
- mMetricsLogger = metricsLogger;
- mUiEventLogger = uiEventLogger;
- mKeyguardStateController = keyguardStateController;
- mLayoutInflater = injectionInflationController.injectable(layoutInflater);
view.setLockPatternUtils(mLockPatternUtils);
mKeyguardSecurityViewControllerFactory = keyguardSecurityViewControllerFactory;
- mAdminSecondaryLockScreenController = adminSecondaryLockScreenControllerFactory.create(
- mKeyguardSecurityCallback);
- }
-
- @Override
- public void init() {
- super.init();
}
@Override
protected void onViewAttached() {
- mView.setSwipeListener(mSwipeListener);
}
@Override
@@ -215,48 +51,27 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
/** */
public void onPause() {
- mAdminSecondaryLockScreenController.hide();
- if (mCurrentSecuritySelection != SecurityMode.None) {
- getSecurityView(mCurrentSecuritySelection).onPause();
- }
mView.onPause();
}
-
- /**
- * Shows the primary security screen for the user. This will be either the multi-selector
- * or the user's security method.
- * @param turningOff true if the device is being turned off
- */
public void showPrimarySecurityScreen(boolean turningOff) {
- SecurityMode securityMode = whitelistIpcs(() -> mSecurityModel.getSecurityMode(
- KeyguardUpdateMonitor.getCurrentUser()));
- if (DEBUG) Log.v(TAG, "showPrimarySecurityScreen(turningOff=" + turningOff + ")");
- showSecurityScreen(securityMode);
+ mView.showPrimarySecurityScreen(turningOff);
}
- @Override
public void showPromptReason(int reason) {
- if (mCurrentSecuritySelection != SecurityMode.None) {
- if (reason != PROMPT_REASON_NONE) {
- Log.i(TAG, "Strong auth required, reason: " + reason);
- }
- getSecurityView(mCurrentSecuritySelection).showPromptReason(reason);
- }
+ mView.showPromptReason(reason);
}
public void showMessage(CharSequence message, ColorStateList colorState) {
- if (mCurrentSecuritySelection != SecurityMode.None) {
- getSecurityView(mCurrentSecuritySelection).showMessage(message, colorState);
- }
+ mView.showMessage(message, colorState);
}
public SecurityMode getCurrentSecuritySelection() {
- return mCurrentSecuritySelection;
+ return mView.getCurrentSecuritySelection();
}
public void dismiss(boolean authenticated, int targetUserId) {
- mKeyguardSecurityCallback.dismiss(authenticated, targetUserId);
+ mView.dismiss(authenticated, targetUserId);
}
public void reset() {
@@ -267,276 +82,37 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
return mView.getTitle();
}
- @Override
- public void onResume(int reason) {
- if (mCurrentSecuritySelection != SecurityMode.None) {
- getSecurityView(mCurrentSecuritySelection).onResume(reason);
- }
- mView.onResume(
- mSecurityModel.getSecurityMode(KeyguardUpdateMonitor.getCurrentUser()),
- mKeyguardStateController.isFaceAuthEnabled());
+ public void onResume(int screenOn) {
+ mView.onResume(screenOn);
}
public void startAppearAnimation() {
- if (mCurrentSecuritySelection != SecurityMode.None) {
- getSecurityView(mCurrentSecuritySelection).startAppearAnimation();
- }
+ mView.startAppearAnimation();
}
public boolean startDisappearAnimation(Runnable onFinishRunnable) {
- mView.startDisappearAnimation(getCurrentSecuritySelection());
-
- if (mCurrentSecuritySelection != SecurityMode.None) {
- return getSecurityView(mCurrentSecuritySelection).startDisappearAnimation(
- onFinishRunnable);
- }
-
- return false;
+ return mView.startDisappearAnimation(onFinishRunnable);
}
public void onStartingToHide() {
- if (mCurrentSecuritySelection != SecurityMode.None) {
- getSecurityView(mCurrentSecuritySelection).onStartingToHide();
- }
+ mView.onStartingToHide();
}
public void setSecurityCallback(SecurityCallback securityCallback) {
- mSecurityCallback = securityCallback;
+ mView.setSecurityCallback(securityCallback);
}
- /**
- * Shows the next security screen if there is one.
- * @param authenticated true if the user entered the correct authentication
- * @param targetUserId a user that needs to be the foreground user at the finish (if called)
- * completion.
- * @param bypassSecondaryLockScreen true if the user is allowed to bypass the secondary
- * secondary lock screen requirement, if any.
- * @return true if keyguard is done
- */
public boolean showNextSecurityScreenOrFinish(boolean authenticated, int targetUserId,
boolean bypassSecondaryLockScreen) {
-
- if (DEBUG) Log.d(TAG, "showNextSecurityScreenOrFinish(" + authenticated + ")");
- boolean finish = false;
- boolean strongAuth = false;
- int eventSubtype = -1;
- BouncerUiEvent uiEvent = BouncerUiEvent.UNKNOWN;
- if (mUpdateMonitor.getUserHasTrust(targetUserId)) {
- finish = true;
- eventSubtype = BOUNCER_DISMISS_EXTENDED_ACCESS;
- uiEvent = BouncerUiEvent.BOUNCER_DISMISS_EXTENDED_ACCESS;
- } else if (mUpdateMonitor.getUserUnlockedWithBiometric(targetUserId)) {
- finish = true;
- eventSubtype = BOUNCER_DISMISS_BIOMETRIC;
- uiEvent = BouncerUiEvent.BOUNCER_DISMISS_BIOMETRIC;
- } else if (SecurityMode.None == getCurrentSecuritySelection()) {
- SecurityMode securityMode = mSecurityModel.getSecurityMode(targetUserId);
- if (SecurityMode.None == securityMode) {
- finish = true; // no security required
- eventSubtype = BOUNCER_DISMISS_NONE_SECURITY;
- uiEvent = BouncerUiEvent.BOUNCER_DISMISS_NONE_SECURITY;
- } else {
- showSecurityScreen(securityMode); // switch to the alternate security view
- }
- } else if (authenticated) {
- switch (getCurrentSecuritySelection()) {
- case Pattern:
- case Password:
- case PIN:
- strongAuth = true;
- finish = true;
- eventSubtype = BOUNCER_DISMISS_PASSWORD;
- uiEvent = BouncerUiEvent.BOUNCER_DISMISS_PASSWORD;
- break;
-
- case SimPin:
- case SimPuk:
- // Shortcut for SIM PIN/PUK to go to directly to user's security screen or home
- SecurityMode securityMode = mSecurityModel.getSecurityMode(targetUserId);
- if (securityMode == SecurityMode.None && mLockPatternUtils.isLockScreenDisabled(
- KeyguardUpdateMonitor.getCurrentUser())) {
- finish = true;
- eventSubtype = BOUNCER_DISMISS_SIM;
- uiEvent = BouncerUiEvent.BOUNCER_DISMISS_SIM;
- } else {
- showSecurityScreen(securityMode);
- }
- break;
-
- default:
- Log.v(TAG, "Bad security screen " + getCurrentSecuritySelection()
- + ", fail safe");
- showPrimarySecurityScreen(false);
- break;
- }
- }
- // Check for device admin specified additional security measures.
- if (finish && !bypassSecondaryLockScreen) {
- Intent secondaryLockscreenIntent =
- mUpdateMonitor.getSecondaryLockscreenRequirement(targetUserId);
- if (secondaryLockscreenIntent != null) {
- mAdminSecondaryLockScreenController.show(secondaryLockscreenIntent);
- return false;
- }
- }
- if (eventSubtype != -1) {
- mMetricsLogger.write(new LogMaker(MetricsProto.MetricsEvent.BOUNCER)
- .setType(MetricsProto.MetricsEvent.TYPE_DISMISS).setSubtype(eventSubtype));
- }
- if (uiEvent != BouncerUiEvent.UNKNOWN) {
- mUiEventLogger.log(uiEvent);
- }
- if (finish) {
- mSecurityCallback.finish(strongAuth, targetUserId);
- }
- return finish;
+ return mView.showNextSecurityScreenOrFinish(
+ authenticated, targetUserId, bypassSecondaryLockScreen);
}
public boolean needsInput() {
return mView.needsInput();
}
-
- /**
- * Switches to the given security view unless it's already being shown, in which case
- * this is a no-op.
- *
- * @param securityMode
- */
- void showSecurityScreen(SecurityMode securityMode) {
- if (DEBUG) Log.d(TAG, "showSecurityScreen(" + securityMode + ")");
-
- if (securityMode == mCurrentSecuritySelection) return;
-
- KeyguardSecurityView oldView = getSecurityView(mCurrentSecuritySelection);
- KeyguardSecurityView newView = getSecurityView(securityMode);
-
- // Emulate Activity life cycle
- if (oldView != null) {
- oldView.onPause();
- oldView.setKeyguardCallback(mNullCallback); // ignore requests from old view
- }
- if (newView != null) {
- newView.onResume(KeyguardSecurityView.VIEW_REVEALED);
- newView.setKeyguardCallback(mKeyguardSecurityCallback);
- }
-
- // Find and show this child.
- for (KeyguardInputViewController child : mChildren) {
- if (child.getSecurityMode().equals(securityMode)) {
- child.showSelf();
- }
- }
-
- mCurrentSecuritySelection = securityMode;
- mCurrentSecurityView = newView;
- mSecurityCallback.onSecurityModeChanged(
- securityMode, newView != null && newView.needsInput());
- }
-
- public void reportFailedUnlockAttempt(int userId, int timeoutMs) {
- // +1 for this time
- final int failedAttempts = mLockPatternUtils.getCurrentFailedPasswordAttempts(userId) + 1;
-
- if (DEBUG) Log.d(TAG, "reportFailedPatternAttempt: #" + failedAttempts);
-
- final DevicePolicyManager dpm = mLockPatternUtils.getDevicePolicyManager();
- final int failedAttemptsBeforeWipe =
- dpm.getMaximumFailedPasswordsForWipe(null, userId);
-
- final int remainingBeforeWipe = failedAttemptsBeforeWipe > 0
- ? (failedAttemptsBeforeWipe - failedAttempts)
- : Integer.MAX_VALUE; // because DPM returns 0 if no restriction
- if (remainingBeforeWipe < LockPatternUtils.FAILED_ATTEMPTS_BEFORE_WIPE_GRACE) {
- // The user has installed a DevicePolicyManager that requests a user/profile to be wiped
- // N attempts. Once we get below the grace period, we post this dialog every time as a
- // clear warning until the deletion fires.
- // Check which profile has the strictest policy for failed password attempts
- final int expiringUser = dpm.getProfileWithMinimumFailedPasswordsForWipe(userId);
- int userType = USER_TYPE_PRIMARY;
- if (expiringUser == userId) {
- // TODO: http://b/23522538
- if (expiringUser != UserHandle.USER_SYSTEM) {
- userType = USER_TYPE_SECONDARY_USER;
- }
- } else if (expiringUser != UserHandle.USER_NULL) {
- userType = USER_TYPE_WORK_PROFILE;
- } // If USER_NULL, which shouldn't happen, leave it as USER_TYPE_PRIMARY
- if (remainingBeforeWipe > 0) {
- mView.showAlmostAtWipeDialog(failedAttempts, remainingBeforeWipe, userType);
- } else {
- // Too many attempts. The device will be wiped shortly.
- Slog.i(TAG, "Too many unlock attempts; user " + expiringUser + " will be wiped!");
- mView.showWipeDialog(failedAttempts, userType);
- }
- }
- mLockPatternUtils.reportFailedPasswordAttempt(userId);
- if (timeoutMs > 0) {
- mLockPatternUtils.reportPasswordLockout(timeoutMs, userId);
- mView.showTimeoutDialog(userId, timeoutMs, mLockPatternUtils,
- mSecurityModel.getSecurityMode(userId));
- }
- }
-
- @Override
- public void setKeyguardCallback(KeyguardSecurityCallback callback) {
- // no-op. This should never be reset.
- }
-
- @Override
- public void setLockPatternUtils(LockPatternUtils utils) {
- // We already have one of these.
- }
-
- @Override
- public KeyguardSecurityCallback getCallback() {
- return mView.getCallback();
- }
-
- @Override
- public void showUsabilityHint() {
- mView.showUsabilityHint();
- }
-
- private KeyguardSecurityView getSecurityView(SecurityMode securityMode) {
- KeyguardInputViewController childController = null;
- for (KeyguardInputViewController mChild : mChildren) {
- if (mChild.getSecurityMode() == securityMode) {
- childController = mChild;
- break;
- }
- }
-
- if (childController == null
- && securityMode != SecurityMode.None && securityMode != SecurityMode.Invalid) {
-
- int layoutId = getLayoutIdFor(securityMode);
- KeyguardInputView view = null;
- if (layoutId != 0) {
- if (DEBUG) Log.v(TAG, "inflating id = " + layoutId);
- view = (KeyguardInputView) mLayoutInflater.inflate(
- layoutId, mView.getSecurityViewFlipper(), false);
- mView.getSecurityViewFlipper().addView(view);
- childController = mKeyguardSecurityViewControllerFactory.create(
- view, securityMode, mKeyguardSecurityCallback);
-
- mChildren.add(childController);
- }
- }
-
- return childController;
+ public SecurityMode getCurrentSecurityMode() {
+ return mView.getCurrentSecurityMode();
}
-
- private int getLayoutIdFor(SecurityMode securityMode) {
- switch (securityMode) {
- case Pattern: return com.android.systemui.R.layout.keyguard_pattern_view;
- case PIN: return com.android.systemui.R.layout.keyguard_pin_view;
- case Password: return com.android.systemui.R.layout.keyguard_password_view;
- case SimPin: return com.android.systemui.R.layout.keyguard_sim_pin_view;
- case SimPuk: return R.layout.keyguard_sim_puk_view;
- default:
- return 0;
- }
- }
-
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityModel.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityModel.java
index c77c86711abf..ac2160ecb4ae 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityModel.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityModel.java
@@ -18,14 +18,13 @@ package com.android.keyguard;
import static com.android.systemui.DejankUtils.whitelistIpcs;
import android.app.admin.DevicePolicyManager;
-import android.content.res.Resources;
+import android.content.Context;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import com.android.internal.widget.LockPatternUtils;
import com.android.systemui.Dependency;
import com.android.systemui.dagger.SysUISingleton;
-import com.android.systemui.dagger.qualifiers.Main;
import javax.inject.Inject;
@@ -34,7 +33,7 @@ public class KeyguardSecurityModel {
/**
* The different types of security available.
- * @see KeyguardSecurityContainerController#showSecurityScreen
+ * @see KeyguardSecurityContainer#showSecurityScreen
*/
public enum SecurityMode {
Invalid, // NULL state
@@ -46,15 +45,21 @@ public class KeyguardSecurityModel {
SimPuk // Unlock by entering a sim puk
}
+ private final Context mContext;
private final boolean mIsPukScreenAvailable;
- private final LockPatternUtils mLockPatternUtils;
+ private LockPatternUtils mLockPatternUtils;
@Inject
- KeyguardSecurityModel(@Main Resources resources, LockPatternUtils lockPatternUtils) {
- mIsPukScreenAvailable = resources.getBoolean(
+ KeyguardSecurityModel(Context context) {
+ mContext = context;
+ mLockPatternUtils = new LockPatternUtils(context);
+ mIsPukScreenAvailable = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_enable_puk_unlock_screen);
- mLockPatternUtils = lockPatternUtils;
+ }
+
+ void setLockPatternUtils(LockPatternUtils utils) {
+ mLockPatternUtils = utils;
}
public SecurityMode getSecurityMode(int userId) {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewController.java
new file mode 100644
index 000000000000..ef9ba19fbb43
--- /dev/null
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewController.java
@@ -0,0 +1,58 @@
+/*
+ * 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.view.View;
+
+import com.android.systemui.util.ViewController;
+
+import javax.inject.Inject;
+
+
+/** Controller for a {@link KeyguardSecurityView}. */
+public class KeyguardSecurityViewController extends ViewController<View> {
+
+ private final KeyguardSecurityView mView;
+
+ private KeyguardSecurityViewController(KeyguardSecurityView view) {
+ super((View) view);
+ // KeyguardSecurityView isn't actually a View, so we need to track it ourselves.
+ mView = view;
+ }
+
+ @Override
+ protected void onViewAttached() {
+
+ }
+
+ @Override
+ protected void onViewDetached() {
+
+ }
+
+ /** Factory for a {@link KeyguardSecurityViewController}. */
+ public static class Factory {
+ @Inject
+ public Factory() {
+ }
+
+ /** Create a new {@link KeyguardSecurityViewController}. */
+ public KeyguardSecurityViewController create(KeyguardSecurityView view) {
+ return new KeyguardSecurityViewController(view);
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
index eb431274b8a3..38e12a6ed5f8 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
@@ -288,7 +288,6 @@ public class DependencyProvider {
/** */
@Provides
- @SysUISingleton
public LockPatternUtils provideLockPatternUtils(Context context) {
return new LockPatternUtils(context);
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/AdminSecondaryLockScreenControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/AdminSecondaryLockScreenControllerTest.java
index dffad6ccbea5..9be2d124026c 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/AdminSecondaryLockScreenControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/AdminSecondaryLockScreenControllerTest.java
@@ -41,6 +41,8 @@ import android.testing.TestableLooper.RunWithLooper;
import android.testing.ViewUtils;
import android.view.SurfaceControlViewHost;
import android.view.SurfaceView;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
import androidx.test.filters.SmallTest;
@@ -65,7 +67,7 @@ public class AdminSecondaryLockScreenControllerTest extends SysuiTestCase {
private ComponentName mComponentName;
private Intent mServiceIntent;
private TestableLooper mTestableLooper;
- private KeyguardSecurityContainer mKeyguardSecurityContainer;
+ private ViewGroup mParent;
@Mock
private Handler mHandler;
@@ -82,8 +84,8 @@ public class AdminSecondaryLockScreenControllerTest extends SysuiTestCase {
public void setUp() {
MockitoAnnotations.initMocks(this);
- mKeyguardSecurityContainer = spy(new KeyguardSecurityContainer(mContext));
- ViewUtils.attachView(mKeyguardSecurityContainer);
+ mParent = spy(new FrameLayout(mContext));
+ ViewUtils.attachView(mParent);
mTestableLooper = TestableLooper.get(this);
mComponentName = new ComponentName(mContext, "FakeKeyguardClient.class");
@@ -94,14 +96,13 @@ public class AdminSecondaryLockScreenControllerTest extends SysuiTestCase {
when(mKeyguardClient.queryLocalInterface(anyString())).thenReturn(mKeyguardClient);
when(mKeyguardClient.asBinder()).thenReturn(mKeyguardClient);
- mTestController = new AdminSecondaryLockScreenController.Factory(
- mContext, mKeyguardSecurityContainer, mUpdateMonitor, mHandler)
- .create(mKeyguardCallback);
+ mTestController = new AdminSecondaryLockScreenController(
+ mContext, mParent, mUpdateMonitor, mKeyguardCallback, mHandler);
}
@After
public void tearDown() {
- ViewUtils.detachView(mKeyguardSecurityContainer);
+ ViewUtils.detachView(mParent);
}
@Test
@@ -145,7 +146,7 @@ public class AdminSecondaryLockScreenControllerTest extends SysuiTestCase {
SurfaceView v = verifySurfaceReady();
mTestController.hide();
- verify(mKeyguardSecurityContainer).removeView(v);
+ verify(mParent).removeView(v);
assertThat(mContext.isBound(mComponentName)).isFalse();
}
@@ -153,7 +154,7 @@ public class AdminSecondaryLockScreenControllerTest extends SysuiTestCase {
public void testHide_notShown() throws Exception {
mTestController.hide();
// Nothing should happen if trying to hide when the view isn't attached yet.
- verify(mKeyguardSecurityContainer, never()).removeView(any(SurfaceView.class));
+ verify(mParent, never()).removeView(any(SurfaceView.class));
}
@Test
@@ -181,7 +182,7 @@ public class AdminSecondaryLockScreenControllerTest extends SysuiTestCase {
private SurfaceView verifySurfaceReady() throws Exception {
mTestableLooper.processAllMessages();
ArgumentCaptor<SurfaceView> captor = ArgumentCaptor.forClass(SurfaceView.class);
- verify(mKeyguardSecurityContainer).addView(captor.capture());
+ verify(mParent).addView(captor.capture());
mTestableLooper.processAllMessages();
verify(mKeyguardClient).onCreateKeyguardSurface(any(), any(IKeyguardCallback.class));
@@ -189,7 +190,7 @@ public class AdminSecondaryLockScreenControllerTest extends SysuiTestCase {
}
private void verifyViewDismissed(SurfaceView v) throws Exception {
- verify(mKeyguardSecurityContainer).removeView(v);
+ verify(mParent).removeView(v);
verify(mKeyguardCallback).dismiss(true, TARGET_USER_ID, true);
assertThat(mContext.isBound(mComponentName)).isFalse();
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java
deleted file mode 100644
index 560b15948591..000000000000
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java
+++ /dev/null
@@ -1,151 +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 org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyBoolean;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
-import android.view.LayoutInflater;
-import android.view.ViewGroup;
-import android.view.WindowInsetsController;
-
-import androidx.test.filters.SmallTest;
-
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.UiEventLogger;
-import com.android.internal.widget.LockPatternUtils;
-import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
-import com.android.systemui.SysuiTestCase;
-import com.android.systemui.statusbar.policy.KeyguardStateController;
-import com.android.systemui.util.InjectionInflationController;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.junit.MockitoJUnit;
-import org.mockito.junit.MockitoRule;
-
-@SmallTest
-@RunWith(AndroidTestingRunner.class)
-@TestableLooper.RunWithLooper()
-public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
-
- @Rule
- public MockitoRule mRule = MockitoJUnit.rule();
-
- @Mock
- private KeyguardSecurityContainer mView;
- @Mock
- private AdminSecondaryLockScreenController.Factory mAdminSecondaryLockScreenControllerFactory;
- @Mock
- private AdminSecondaryLockScreenController mAdminSecondaryLockScreenController;
- @Mock
- private LockPatternUtils mLockPatternUtils;
- @Mock
- private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
- @Mock
- private KeyguardSecurityModel mKeyguardSecurityModel;
- @Mock
- private MetricsLogger mMetricsLogger;
- @Mock
- private UiEventLogger mUiEventLogger;
- @Mock
- private KeyguardStateController mKeyguardStateController;
- @Mock
- private LayoutInflater mLayoutInflater;
- @Mock
- private InjectionInflationController mInjectionInflationController;
- @Mock
- private KeyguardInputViewController.Factory mKeyguardSecurityViewControllerFactory;
- @Mock
- private KeyguardInputViewController mKeyguardInputViewController;
- @Mock
- private KeyguardInputView mInputView;
- @Mock
- private KeyguardSecurityContainer.SecurityCallback mSecurityCallback;
- @Mock
- private WindowInsetsController mWindowInsetsController;
- @Mock
- private KeyguardSecurityViewFlipper mSecurityViewFlipper;
-
- private KeyguardSecurityContainerController mKeyguardSecurityContainerController;
-
- @Before
- public void setup() {
- when(mAdminSecondaryLockScreenControllerFactory.create(any(KeyguardSecurityCallback.class)))
- .thenReturn(mAdminSecondaryLockScreenController);
- when(mInjectionInflationController.injectable(mLayoutInflater)).thenReturn(mLayoutInflater);
- when(mKeyguardSecurityViewControllerFactory.create(
- any(KeyguardInputView.class), any(SecurityMode.class),
- any(KeyguardSecurityCallback.class)))
- .thenReturn(mKeyguardInputViewController);
- when(mView.getSecurityViewFlipper()).thenReturn(mSecurityViewFlipper);
- when(mSecurityViewFlipper.getWindowInsetsController()).thenReturn(mWindowInsetsController);
-
- mKeyguardSecurityContainerController = new KeyguardSecurityContainerController(
- mView, mAdminSecondaryLockScreenControllerFactory, mLockPatternUtils,
- mKeyguardUpdateMonitor, mKeyguardSecurityModel, mMetricsLogger, mUiEventLogger,
- mKeyguardStateController, mLayoutInflater, mInjectionInflationController,
- mKeyguardSecurityViewControllerFactory
- );
-
- mKeyguardSecurityContainerController.setSecurityCallback(mSecurityCallback);
- }
-
- @Test
- public void showSecurityScreen_canInflateAllModes() {
- KeyguardSecurityModel.SecurityMode[] modes =
- KeyguardSecurityModel.SecurityMode.values();
- for (KeyguardSecurityModel.SecurityMode mode : modes) {
- reset(mLayoutInflater);
- when(mLayoutInflater.inflate(anyInt(), eq(mSecurityViewFlipper), eq(false)))
- .thenReturn(mInputView);
- when(mKeyguardInputViewController.getSecurityMode()).thenReturn(mode);
- mKeyguardSecurityContainerController.showSecurityScreen(mode);
- if (mode == SecurityMode.Invalid || mode == SecurityMode.None) {
- verify(mLayoutInflater, never()).inflate(
- anyInt(), any(ViewGroup.class), anyBoolean());
- } else {
- verify(mLayoutInflater).inflate(anyInt(), eq(mSecurityViewFlipper), eq(false));
- }
- }
- }
-
- @Test
- public void startDisappearAnimation_animatesKeyboard() {
- when(mKeyguardSecurityModel.getSecurityMode(anyInt())).thenReturn(
- KeyguardSecurityModel.SecurityMode.Password);
- when(mKeyguardInputViewController.getSecurityMode()).thenReturn(
- KeyguardSecurityModel.SecurityMode.Password);
- when(mLayoutInflater.inflate(anyInt(), eq(mSecurityViewFlipper), eq(false)))
- .thenReturn(mInputView);
- mKeyguardSecurityContainerController.showPrimarySecurityScreen(false /* turningOff */);
-
- mKeyguardSecurityContainerController.startDisappearAnimation(null);
- verify(mKeyguardInputViewController).startDisappearAnimation(eq(null));
- }
-}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
index 854be1f76722..a867825e223d 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
@@ -19,19 +19,23 @@ package com.android.keyguard;
import static android.view.WindowInsets.Type.ime;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.content.Context;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import android.view.LayoutInflater;
import android.view.WindowInsetsController;
import androidx.test.filters.SmallTest;
-import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
+import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
import org.junit.Before;
import org.junit.Rule;
@@ -46,26 +50,68 @@ import org.mockito.junit.MockitoRule;
@TestableLooper.RunWithLooper()
public class KeyguardSecurityContainerTest extends SysuiTestCase {
- @Rule
- public MockitoRule mRule = MockitoJUnit.rule();
-
+ @Mock
+ private KeyguardSecurityModel mKeyguardSecurityModel;
+ @Mock
+ private KeyguardStateController mKeyguardStateController;
+ @Mock
+ private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+ @Mock
+ private KeyguardSecurityContainer.SecurityCallback mSecurityCallback;
+ @Mock
+ private KeyguardSecurityView mSecurityView;
@Mock
private WindowInsetsController mWindowInsetsController;
@Mock
private KeyguardSecurityViewFlipper mSecurityViewFlipper;
-
+ @Rule
+ public MockitoRule mRule = MockitoJUnit.rule();
private KeyguardSecurityContainer mKeyguardSecurityContainer;
@Before
public void setup() {
- when(mSecurityViewFlipper.getWindowInsetsController()).thenReturn(mWindowInsetsController);
- mKeyguardSecurityContainer = new KeyguardSecurityContainer(getContext());
+ mDependency.injectTestDependency(KeyguardStateController.class, mKeyguardStateController);
+ mDependency.injectTestDependency(KeyguardSecurityModel.class, mKeyguardSecurityModel);
+ mDependency.injectTestDependency(KeyguardUpdateMonitor.class, mKeyguardUpdateMonitor);
+ mKeyguardSecurityContainer = new KeyguardSecurityContainer(getContext()) {
+ @Override
+ protected KeyguardSecurityView getSecurityView(
+ KeyguardSecurityModel.SecurityMode securityMode) {
+ return mSecurityView;
+ }
+ };
mKeyguardSecurityContainer.mSecurityViewFlipper = mSecurityViewFlipper;
+ when(mSecurityViewFlipper.getWindowInsetsController()).thenReturn(mWindowInsetsController);
+ mKeyguardSecurityContainer.setSecurityCallback(mSecurityCallback);
+ }
+
+ @Test
+ public void showSecurityScreen_canInflateAllModes() {
+ Context context = getContext();
+
+ for (int theme : new int[] {R.style.Theme_SystemUI, R.style.Theme_SystemUI_Light}) {
+ context.setTheme(theme);
+ final LayoutInflater inflater = LayoutInflater.from(context);
+ KeyguardSecurityModel.SecurityMode[] modes =
+ KeyguardSecurityModel.SecurityMode.values();
+ for (KeyguardSecurityModel.SecurityMode mode : modes) {
+ final int resId = mKeyguardSecurityContainer.getLayoutIdFor(mode);
+ if (resId == 0) {
+ continue;
+ }
+ inflater.inflate(resId, null /* root */, false /* attach */);
+ }
+ }
}
@Test
public void startDisappearAnimation_animatesKeyboard() {
- mKeyguardSecurityContainer.startDisappearAnimation(SecurityMode.Password);
+ when(mKeyguardSecurityModel.getSecurityMode(anyInt())).thenReturn(
+ KeyguardSecurityModel.SecurityMode.Password);
+ mKeyguardSecurityContainer.showPrimarySecurityScreen(false /* turningOff */);
+
+ mKeyguardSecurityContainer.startDisappearAnimation(null);
+ verify(mSecurityView).startDisappearAnimation(eq(null));
verify(mWindowInsetsController).controlWindowInsetsAnimation(eq(ime()), anyLong(), any(),
any(), any());
}