Merge changes from topic "revert-20691780-cherrypick-modernize_alt_bouncer-2av1xvqe7q-EXOZAWOBTI"

* changes:
  Revert "Modernize alternate bouncer logic"
  Revert "Remove ScrimController from BiometricUnlockController"
This commit is contained in:
Beverly Tai
2022-12-12 15:30:45 +00:00
committed by Android (Google) Code Review
40 changed files with 429 additions and 1101 deletions

View File

@@ -366,7 +366,7 @@ constructor(
val dialog = animatedDialog.dialog
// Don't animate if the dialog is not showing or if we are locked and going to show the
// primary bouncer.
// bouncer.
if (
!dialog.isShowing ||
(!callback.isUnlocked() && !callback.isShowingAlternateAuthOnUnlock())

View File

@@ -691,13 +691,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
updateBiometricListeningState(BIOMETRIC_ACTION_STOP, FACE_AUTH_STOPPED_KEYGUARD_GOING_AWAY);
}
/**
* Whether keyguard is going away due to screen off or device entry.
*/
public boolean isKeyguardGoingAway() {
return mKeyguardGoingAway;
}
/**
* Updates KeyguardUpdateMonitor's internal state to know if keyguard is showing and if
* its occluded. The keyguard is considered visible if its showing and NOT occluded.

View File

@@ -18,7 +18,6 @@ package com.android.systemui.biometrics;
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE;
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_REAR;
import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_AWAKE;
import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_GOING_TO_SLEEP;
@@ -80,7 +79,6 @@ import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.doze.DozeReceiver;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.keyguard.data.repository.BiometricType;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.VibratorHelper;
@@ -90,10 +88,8 @@ import com.android.systemui.util.concurrency.Execution;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
@@ -162,7 +158,6 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks,
@Nullable private List<FingerprintSensorPropertiesInternal> mUdfpsProps;
@Nullable private List<FingerprintSensorPropertiesInternal> mSidefpsProps;
@NonNull private final Map<Integer, Boolean> mFpEnrolledForUser = new HashMap<>();
@NonNull private final SparseBooleanArray mUdfpsEnrolledForUser;
@NonNull private final SparseBooleanArray mFaceEnrolledForUser;
@NonNull private final SparseBooleanArray mSfpsEnrolledForUser;
@@ -175,6 +170,7 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks,
private final @Background DelayableExecutor mBackgroundExecutor;
private final DisplayInfo mCachedDisplayInfo = new DisplayInfo();
private final VibratorHelper mVibratorHelper;
private void vibrateSuccess(int modality) {
@@ -352,21 +348,12 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks,
mExecution.assertIsMainThread();
Log.d(TAG, "handleEnrollmentsChanged, userId: " + userId + ", sensorId: " + sensorId
+ ", hasEnrollments: " + hasEnrollments);
BiometricType sensorBiometricType = BiometricType.UNKNOWN;
if (mFpProps != null) {
for (FingerprintSensorPropertiesInternal prop: mFpProps) {
if (mUdfpsProps == null) {
Log.d(TAG, "handleEnrollmentsChanged, mUdfpsProps is null");
} else {
for (FingerprintSensorPropertiesInternal prop : mUdfpsProps) {
if (prop.sensorId == sensorId) {
mFpEnrolledForUser.put(userId, hasEnrollments);
if (prop.isAnyUdfpsType()) {
sensorBiometricType = BiometricType.UNDER_DISPLAY_FINGERPRINT;
mUdfpsEnrolledForUser.put(userId, hasEnrollments);
} else if (prop.isAnySidefpsType()) {
sensorBiometricType = BiometricType.SIDE_FINGERPRINT;
mSfpsEnrolledForUser.put(userId, hasEnrollments);
} else if (prop.sensorType == TYPE_REAR) {
sensorBiometricType = BiometricType.REAR_FINGERPRINT;
}
break;
mUdfpsEnrolledForUser.put(userId, hasEnrollments);
}
}
}
@@ -376,14 +363,20 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks,
for (FaceSensorPropertiesInternal prop : mFaceProps) {
if (prop.sensorId == sensorId) {
mFaceEnrolledForUser.put(userId, hasEnrollments);
sensorBiometricType = BiometricType.FACE;
break;
}
}
}
if (mSidefpsProps == null) {
Log.d(TAG, "handleEnrollmentsChanged, mSidefpsProps is null");
} else {
for (FingerprintSensorPropertiesInternal prop : mSidefpsProps) {
if (prop.sensorId == sensorId) {
mSfpsEnrolledForUser.put(userId, hasEnrollments);
}
}
}
for (Callback cb : mCallbacks) {
cb.onEnrollmentsChanged(modality);
cb.onEnrollmentsChanged(sensorBiometricType, userId, hasEnrollments);
}
}
@@ -636,11 +629,6 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks,
}
}
/** Get FP sensor properties */
public @Nullable List<FingerprintSensorPropertiesInternal> getFingerprintProperties() {
return mFpProps;
}
/**
* @return where the face sensor exists in pixels in the current device orientation. Returns
* null if no face sensor exists.
@@ -893,7 +881,7 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks,
}
@Override
public void setBiometricContextListener(IBiometricContextListener listener) {
public void setBiometicContextListener(IBiometricContextListener listener) {
mBiometricContextListener = listener;
notifyDozeChanged(mStatusBarStateController.isDozing(),
mWakefulnessLifecycle.getWakefulness());
@@ -1152,13 +1140,6 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks,
return mCurrentDialog != null;
}
/**
* Whether the passed userId has enrolled at least one fingerprint.
*/
public boolean isFingerprintEnrolled(int userId) {
return mFpEnrolledForUser.getOrDefault(userId, false);
}
private void showDialog(SomeArgs args, boolean skipAnimation, Bundle savedState) {
mCurrentDialogArgs = args;
@@ -1341,16 +1322,6 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks,
*/
default void onEnrollmentsChanged(@Modality int modality) {}
/**
* Called when UDFPS enrollments have changed. This is called after boot and on changes to
* enrollment.
*/
default void onEnrollmentsChanged(
@NonNull BiometricType biometricType,
int userId,
boolean hasEnrollments
) {}
/**
* Called when the biometric prompt starts showing.
*/

View File

@@ -189,6 +189,11 @@ abstract class UdfpsAnimationViewController<T : UdfpsAnimationView>(
*/
open fun listenForTouchesOutsideView(): Boolean = false
/**
* Called on touches outside of the view if listenForTouchesOutsideView returns true
*/
open fun onTouchOutsideView() {}
/**
* Called when a view should announce an accessibility event.
*/

View File

@@ -74,7 +74,6 @@ import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.Flags;
import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor;
import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -151,7 +150,6 @@ public class UdfpsController implements DozeReceiver, Dumpable {
@NonNull private final ActivityLaunchAnimator mActivityLaunchAnimator;
@NonNull private final PrimaryBouncerInteractor mPrimaryBouncerInteractor;
@Nullable private final TouchProcessor mTouchProcessor;
@NonNull private final AlternateBouncerInteractor mAlternateBouncerInteractor;
// Currently the UdfpsController supports a single UDFPS sensor. If devices have multiple
// sensors, this, in addition to a lot of the code here, will be updated.
@@ -239,12 +237,12 @@ public class UdfpsController implements DozeReceiver, Dumpable {
mShadeExpansionStateManager, mKeyguardViewManager,
mKeyguardUpdateMonitor, mDialogManager, mDumpManager,
mLockscreenShadeTransitionController, mConfigurationController,
mKeyguardStateController,
mSystemClock, mKeyguardStateController,
mUnlockedScreenOffAnimationController,
mUdfpsDisplayMode, requestId, reason, callback,
(view, event, fromUdfpsView) -> onTouch(requestId, event,
fromUdfpsView), mActivityLaunchAnimator, mFeatureFlags,
mPrimaryBouncerInteractor, mAlternateBouncerInteractor)));
mPrimaryBouncerInteractor)));
}
@Override
@@ -363,13 +361,13 @@ public class UdfpsController implements DozeReceiver, Dumpable {
if (!mOverlayParams.equals(overlayParams)) {
mOverlayParams = overlayParams;
final boolean wasShowingAlternateBouncer = mAlternateBouncerInteractor.isVisibleState();
final boolean wasShowingAltAuth = mKeyguardViewManager.isShowingAlternateBouncer();
// When the bounds change it's always necessary to re-create the overlay's window with
// new LayoutParams. If the overlay needs to be shown, this will re-create and show the
// overlay with the updated LayoutParams. Otherwise, the overlay will remain hidden.
redrawOverlay();
if (wasShowingAlternateBouncer) {
if (wasShowingAltAuth) {
mKeyguardViewManager.showBouncer(true);
}
}
@@ -577,6 +575,9 @@ public class UdfpsController implements DozeReceiver, Dumpable {
final UdfpsView udfpsView = mOverlay.getOverlayView();
boolean handled = false;
switch (event.getActionMasked()) {
case MotionEvent.ACTION_OUTSIDE:
udfpsView.onTouchOutsideView();
return true;
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_HOVER_ENTER:
Trace.beginSection("UdfpsController.onTouch.ACTION_DOWN");
@@ -750,8 +751,7 @@ public class UdfpsController implements DozeReceiver, Dumpable {
@NonNull Optional<Provider<AlternateUdfpsTouchProvider>> alternateTouchProvider,
@NonNull @BiometricsBackground Executor biometricsExecutor,
@NonNull PrimaryBouncerInteractor primaryBouncerInteractor,
@NonNull SinglePointerTouchProcessor singlePointerTouchProcessor,
@NonNull AlternateBouncerInteractor alternateBouncerInteractor) {
@NonNull SinglePointerTouchProcessor singlePointerTouchProcessor) {
mContext = context;
mExecution = execution;
mVibrator = vibrator;
@@ -791,7 +791,6 @@ public class UdfpsController implements DozeReceiver, Dumpable {
mBiometricExecutor = biometricsExecutor;
mPrimaryBouncerInteractor = primaryBouncerInteractor;
mAlternateBouncerInteractor = alternateBouncerInteractor;
mTouchProcessor = mFeatureFlags.isEnabled(Flags.UDFPS_NEW_TOUCH_DETECTION)
? singlePointerTouchProcessor : null;
@@ -886,7 +885,9 @@ public class UdfpsController implements DozeReceiver, Dumpable {
onFingerUp(mOverlay.getRequestId(), oldView);
}
final boolean removed = mOverlay.hide();
mKeyguardViewManager.hideAlternateBouncer(true);
if (mKeyguardViewManager.isShowingAlternateBouncer()) {
mKeyguardViewManager.hideAlternateBouncer(true);
}
Log.v(TAG, "hideUdfpsOverlay | removing window: " + removed);
} else {
Log.v(TAG, "hideUdfpsOverlay | the overlay is already hidden");

View File

@@ -50,7 +50,6 @@ import com.android.systemui.animation.ActivityLaunchAnimator
import com.android.systemui.dump.DumpManager
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor
import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.shade.ShadeExpansionStateManager
@@ -60,6 +59,7 @@ import com.android.systemui.statusbar.phone.SystemUIDialogManager
import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.time.SystemClock
private const val TAG = "UdfpsControllerOverlay"
@@ -86,6 +86,7 @@ class UdfpsControllerOverlay @JvmOverloads constructor(
private val dumpManager: DumpManager,
private val transitionController: LockscreenShadeTransitionController,
private val configurationController: ConfigurationController,
private val systemClock: SystemClock,
private val keyguardStateController: KeyguardStateController,
private val unlockedScreenOffAnimationController: UnlockedScreenOffAnimationController,
private var udfpsDisplayModeProvider: UdfpsDisplayModeProvider,
@@ -96,8 +97,7 @@ class UdfpsControllerOverlay @JvmOverloads constructor(
private val activityLaunchAnimator: ActivityLaunchAnimator,
private val featureFlags: FeatureFlags,
private val primaryBouncerInteractor: PrimaryBouncerInteractor,
private val alternateBouncerInteractor: AlternateBouncerInteractor,
private val isDebuggable: Boolean = Build.IS_DEBUGGABLE,
private val isDebuggable: Boolean = Build.IS_DEBUGGABLE
) {
/** The view, when [isShowing], or null. */
var overlayView: UdfpsView? = null
@@ -255,14 +255,14 @@ class UdfpsControllerOverlay @JvmOverloads constructor(
dumpManager,
transitionController,
configurationController,
systemClock,
keyguardStateController,
unlockedScreenOffAnimationController,
dialogManager,
controller,
activityLaunchAnimator,
featureFlags,
primaryBouncerInteractor,
alternateBouncerInteractor,
primaryBouncerInteractor
)
}
REASON_AUTH_BP -> {

View File

@@ -31,7 +31,6 @@ import com.android.systemui.animation.Interpolators
import com.android.systemui.dump.DumpManager
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor
import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor
import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.plugins.statusbar.StatusBarStateController
@@ -43,13 +42,13 @@ import com.android.systemui.statusbar.notification.stack.StackStateAnimator
import com.android.systemui.statusbar.phone.KeyguardBouncer
import com.android.systemui.statusbar.phone.KeyguardBouncer.PrimaryBouncerExpansionCallback
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager.AlternateBouncer
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager.KeyguardViewManagerCallback
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager.LegacyAlternateBouncer
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager.OccludingAppBiometricUI
import com.android.systemui.statusbar.phone.SystemUIDialogManager
import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.time.SystemClock
import java.io.PrintWriter
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
@@ -66,27 +65,25 @@ constructor(
dumpManager: DumpManager,
private val lockScreenShadeTransitionController: LockscreenShadeTransitionController,
private val configurationController: ConfigurationController,
private val systemClock: SystemClock,
private val keyguardStateController: KeyguardStateController,
private val unlockedScreenOffAnimationController: UnlockedScreenOffAnimationController,
systemUIDialogManager: SystemUIDialogManager,
private val udfpsController: UdfpsController,
private val activityLaunchAnimator: ActivityLaunchAnimator,
featureFlags: FeatureFlags,
private val primaryBouncerInteractor: PrimaryBouncerInteractor,
private val alternateBouncerInteractor: AlternateBouncerInteractor,
private val primaryBouncerInteractor: PrimaryBouncerInteractor
) :
UdfpsAnimationViewController<UdfpsKeyguardView>(
view,
statusBarStateController,
shadeExpansionStateManager,
systemUIDialogManager,
dumpManager,
dumpManager
) {
private val useExpandedOverlay: Boolean =
featureFlags.isEnabled(Flags.UDFPS_NEW_TOUCH_DETECTION)
private val isModernBouncerEnabled: Boolean = featureFlags.isEnabled(Flags.MODERN_BOUNCER)
private val isModernAlternateBouncerEnabled: Boolean =
featureFlags.isEnabled(Flags.MODERN_ALTERNATE_BOUNCER)
private var showingUdfpsBouncer = false
private var udfpsRequested = false
private var qsExpansion = 0f
@@ -94,6 +91,7 @@ constructor(
private var statusBarState = 0
private var transitionToFullShadeProgress = 0f
private var lastDozeAmount = 0f
private var lastUdfpsBouncerShowTime: Long = -1
private var panelExpansionFraction = 0f
private var launchTransitionFadingAway = false
private var isLaunchingActivity = false
@@ -246,8 +244,20 @@ constructor(
}
}
private val occludingAppBiometricUI: OccludingAppBiometricUI =
object : OccludingAppBiometricUI {
private val mAlternateBouncer: AlternateBouncer =
object : AlternateBouncer {
override fun showAlternateBouncer(): Boolean {
return showUdfpsBouncer(true)
}
override fun hideAlternateBouncer(): Boolean {
return showUdfpsBouncer(false)
}
override fun isShowingAlternateBouncer(): Boolean {
return showingUdfpsBouncer
}
override fun requestUdfps(request: Boolean, color: Int) {
udfpsRequested = request
view.requestUdfps(request, color)
@@ -265,19 +275,16 @@ constructor(
override fun onInit() {
super.onInit()
keyguardViewManager.setOccludingAppBiometricUI(occludingAppBiometricUI)
keyguardViewManager.setAlternateBouncer(mAlternateBouncer)
}
init {
if (isModernBouncerEnabled || isModernAlternateBouncerEnabled) {
if (isModernBouncerEnabled) {
view.repeatWhenAttached {
// repeatOnLifecycle CREATED (as opposed to STARTED) because the Bouncer expansion
// can make the view not visible; and we still want to listen for events
// that may make the view visible again.
repeatOnLifecycle(Lifecycle.State.CREATED) {
if (isModernBouncerEnabled) listenForBouncerExpansion(this)
if (isModernAlternateBouncerEnabled) listenForAlternateBouncerVisibility(this)
}
repeatOnLifecycle(Lifecycle.State.CREATED) { listenForBouncerExpansion(this) }
}
}
}
@@ -293,18 +300,8 @@ constructor(
}
}
@VisibleForTesting
internal suspend fun listenForAlternateBouncerVisibility(scope: CoroutineScope): Job {
return scope.launch {
alternateBouncerInteractor.isVisible.collect { isVisible: Boolean ->
showUdfpsBouncer(isVisible)
}
}
}
public override fun onViewAttached() {
super.onViewAttached()
alternateBouncerInteractor.setAlternateBouncerUIAvailable(true)
val dozeAmount = statusBarStateController.dozeAmount
lastDozeAmount = dozeAmount
stateListener.onDozeAmountChanged(dozeAmount, dozeAmount)
@@ -329,8 +326,7 @@ constructor(
view.updatePadding()
updateAlpha()
updatePauseAuth()
keyguardViewManager.setLegacyAlternateBouncer(legacyAlternateBouncer)
keyguardViewManager.setOccludingAppBiometricUI(occludingAppBiometricUI)
keyguardViewManager.setAlternateBouncer(mAlternateBouncer)
lockScreenShadeTransitionController.udfpsKeyguardViewController = this
activityLaunchAnimator.addListener(activityLaunchAnimatorListener)
view.mUseExpandedOverlay = useExpandedOverlay
@@ -338,12 +334,10 @@ constructor(
override fun onViewDetached() {
super.onViewDetached()
alternateBouncerInteractor.setAlternateBouncerUIAvailable(false)
faceDetectRunning = false
keyguardStateController.removeCallback(keyguardStateControllerCallback)
statusBarStateController.removeCallback(stateListener)
keyguardViewManager.removeLegacyAlternateBouncer(legacyAlternateBouncer)
keyguardViewManager.removeOccludingAppBiometricUI(occludingAppBiometricUI)
keyguardViewManager.removeAlternateAuthInterceptor(mAlternateBouncer)
keyguardUpdateMonitor.requestFaceAuthOnOccludingApp(false)
configurationController.removeCallback(configurationListener)
shadeExpansionStateManager.removeExpansionListener(shadeExpansionListener)
@@ -362,16 +356,7 @@ constructor(
override fun dump(pw: PrintWriter, args: Array<String>) {
super.dump(pw, args)
pw.println("isModernBouncerEnabled=$isModernBouncerEnabled")
pw.println("isModernAlternateBouncerEnabled=$isModernAlternateBouncerEnabled")
pw.println("showingUdfpsAltBouncer=$showingUdfpsBouncer")
pw.println(
"altBouncerInteractor#isAlternateBouncerVisible=" +
"${alternateBouncerInteractor.isVisibleState()}"
)
pw.println(
"altBouncerInteractor#canShowAlternateBouncerForFingerprint=" +
"${alternateBouncerInteractor.canShowAlternateBouncerForFingerprint()}"
)
pw.println("faceDetectRunning=$faceDetectRunning")
pw.println("statusBarState=" + StatusBarState.toString(statusBarState))
pw.println("transitionToFullShadeProgress=$transitionToFullShadeProgress")
@@ -399,6 +384,9 @@ constructor(
}
val udfpsAffordanceWasNotShowing = shouldPauseAuth()
showingUdfpsBouncer = show
if (showingUdfpsBouncer) {
lastUdfpsBouncerShowTime = systemClock.uptimeMillis()
}
if (showingUdfpsBouncer) {
if (udfpsAffordanceWasNotShowing) {
view.animateInUdfpsBouncer(null)
@@ -464,7 +452,7 @@ constructor(
return if (isModernBouncerEnabled) {
inputBouncerExpansion == 1f
} else {
keyguardViewManager.isBouncerShowing && !alternateBouncerInteractor.isVisibleState()
keyguardViewManager.isBouncerShowing && !keyguardViewManager.isShowingAlternateBouncer
}
}
@@ -472,6 +460,30 @@ constructor(
return true
}
override fun onTouchOutsideView() {
maybeShowInputBouncer()
}
/**
* If we were previously showing the udfps bouncer, hide it and instead show the regular
* (pin/pattern/password) bouncer.
*
* Does nothing if we weren't previously showing the UDFPS bouncer.
*/
private fun maybeShowInputBouncer() {
if (showingUdfpsBouncer && hasUdfpsBouncerShownWithMinTime()) {
keyguardViewManager.showPrimaryBouncer(true)
}
}
/**
* Whether the udfps bouncer has shown for at least 200ms before allowing touches outside of the
* udfps icon area to dismiss the udfps bouncer and show the pin/pattern/password bouncer.
*/
private fun hasUdfpsBouncerShownWithMinTime(): Boolean {
return systemClock.uptimeMillis() - lastUdfpsBouncerShowTime > 200
}
/**
* Set the progress we're currently transitioning to the full shade. 0.0f means we're not
* transitioning yet, while 1.0f means we've fully dragged down. For example, start swiping down
@@ -533,7 +545,7 @@ constructor(
if (isModernBouncerEnabled) {
return
}
val altBouncerShowing = alternateBouncerInteractor.isVisibleState()
val altBouncerShowing = keyguardViewManager.isShowingAlternateBouncer
if (altBouncerShowing || !keyguardViewManager.primaryBouncerIsOrWillBeShowing()) {
inputBouncerHiddenAmount = 1f
} else if (keyguardViewManager.isBouncerShowing) {
@@ -542,21 +554,6 @@ constructor(
}
}
private val legacyAlternateBouncer: LegacyAlternateBouncer =
object : LegacyAlternateBouncer {
override fun showAlternateBouncer(): Boolean {
return showUdfpsBouncer(true)
}
override fun hideAlternateBouncer(): Boolean {
return showUdfpsBouncer(false)
}
override fun isShowingAlternateBouncer(): Boolean {
return showingUdfpsBouncer
}
}
companion object {
const val TAG = "UdfpsKeyguardViewController"
}

View File

@@ -111,6 +111,10 @@ class UdfpsView(
}
}
fun onTouchOutsideView() {
animationViewController?.onTouchOutsideView()
}
override fun onAttachedToWindow() {
super.onAttachedToWindow()
Log.v(TAG, "onAttachedToWindow")

View File

@@ -175,13 +175,6 @@ object Flags {
@JvmField
val LIGHT_REVEAL_MIGRATION = unreleasedFlag(218, "light_reveal_migration", teamfood = true)
/**
* Whether to use the new alternate bouncer architecture, a refactor of and eventual replacement
* of the Alternate/Authentication Bouncer. No visual UI changes.
*/
// TODO(b/260619425): Tracking Bug
@JvmField val MODERN_ALTERNATE_BOUNCER = unreleasedFlag(219, "modern_alternate_bouncer")
// 300 - power menu
// TODO(b/254512600): Tracking Bug
@JvmField val POWER_MENU_LITE = releasedFlag(300, "power_menu_lite")

View File

@@ -1,184 +0,0 @@
/*
* Copyright (C) 2022 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.systemui.keyguard.data.repository
import android.app.admin.DevicePolicyManager
import android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED
import android.content.Context
import android.content.IntentFilter
import android.os.Looper
import android.os.UserHandle
import com.android.internal.widget.LockPatternUtils
import com.android.systemui.biometrics.AuthController
import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.user.data.repository.UserRepository
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.transformLatest
/**
* Acts as source of truth for biometric features.
*
* Abstracts-away data sources and their schemas so the rest of the app doesn't need to worry about
* upstream changes.
*/
interface BiometricRepository {
/** Whether any fingerprints are enrolled for the current user. */
val isFingerprintEnrolled: StateFlow<Boolean>
/**
* Whether the current user is allowed to use a strong biometric for device entry based on
* Android Security policies. If false, the user may be able to use primary authentication for
* device entry.
*/
val isStrongBiometricAllowed: StateFlow<Boolean>
/** Whether fingerprint feature is enabled for the current user by the DevicePolicy */
val isFingerprintEnabledByDevicePolicy: StateFlow<Boolean>
}
@SysUISingleton
class BiometricRepositoryImpl
@Inject
constructor(
context: Context,
lockPatternUtils: LockPatternUtils,
broadcastDispatcher: BroadcastDispatcher,
authController: AuthController,
userRepository: UserRepository,
devicePolicyManager: DevicePolicyManager,
@Application scope: CoroutineScope,
@Background backgroundDispatcher: CoroutineDispatcher,
@Main looper: Looper,
) : BiometricRepository {
/** UserId of the current selected user. */
private val selectedUserId: Flow<Int> =
userRepository.selectedUserInfo.map { it.id }.distinctUntilChanged()
override val isFingerprintEnrolled: StateFlow<Boolean> =
selectedUserId
.flatMapLatest { userId ->
conflatedCallbackFlow {
val callback =
object : AuthController.Callback {
override fun onEnrollmentsChanged(
sensorBiometricType: BiometricType,
userId: Int,
hasEnrollments: Boolean
) {
if (sensorBiometricType.isFingerprint) {
trySendWithFailureLogging(
hasEnrollments,
TAG,
"update fpEnrollment"
)
}
}
}
authController.addCallback(callback)
awaitClose { authController.removeCallback(callback) }
}
}
.stateIn(
scope,
started = SharingStarted.Eagerly,
initialValue =
authController.isFingerprintEnrolled(userRepository.getSelectedUserInfo().id)
)
override val isStrongBiometricAllowed: StateFlow<Boolean> =
selectedUserId
.flatMapLatest { currUserId ->
conflatedCallbackFlow {
val callback =
object : LockPatternUtils.StrongAuthTracker(context, looper) {
override fun onStrongAuthRequiredChanged(userId: Int) {
if (currUserId != userId) {
return
}
trySendWithFailureLogging(
isBiometricAllowedForUser(true, currUserId),
TAG
)
}
override fun onIsNonStrongBiometricAllowedChanged(userId: Int) {
// no-op
}
}
lockPatternUtils.registerStrongAuthTracker(callback)
awaitClose { lockPatternUtils.unregisterStrongAuthTracker(callback) }
}
}
.stateIn(
scope,
started = SharingStarted.Eagerly,
initialValue =
lockPatternUtils.isBiometricAllowedForUser(
userRepository.getSelectedUserInfo().id
)
)
override val isFingerprintEnabledByDevicePolicy: StateFlow<Boolean> =
selectedUserId
.flatMapLatest { userId ->
broadcastDispatcher
.broadcastFlow(
filter = IntentFilter(ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED),
user = UserHandle.ALL
)
.transformLatest {
emit(
(devicePolicyManager.getKeyguardDisabledFeatures(null, userId) and
DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT) == 0
)
}
.flowOn(backgroundDispatcher)
.distinctUntilChanged()
}
.stateIn(
scope,
started = SharingStarted.Eagerly,
initialValue =
devicePolicyManager.getKeyguardDisabledFeatures(
null,
userRepository.getSelectedUserInfo().id
) and DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT == 0
)
companion object {
private const val TAG = "BiometricsRepositoryImpl"
}
}

View File

@@ -1,33 +0,0 @@
/*
* Copyright (C) 2022 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.systemui.keyguard.data.repository
enum class BiometricType(val isFingerprint: Boolean) {
// An unsupported biometric type
UNKNOWN(false),
// Fingerprint sensor that is located on the back (opposite side of the display) of the device
REAR_FINGERPRINT(true),
// Fingerprint sensor that is located under the display
UNDER_DISPLAY_FINGERPRINT(true),
// Fingerprint sensor that is located on the side of the device, typically on the power button
SIDE_FINGERPRINT(true),
FACE(false),
}

View File

@@ -16,15 +16,14 @@
package com.android.systemui.keyguard.data.repository
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.keyguard.ViewMediatorCallback
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.shared.model.BouncerShowMessageModel
import com.android.systemui.keyguard.shared.model.KeyguardBouncerModel
import com.android.systemui.statusbar.phone.KeyguardBouncer
import com.android.systemui.util.time.SystemClock
import javax.inject.Inject
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
/** Encapsulates app state for the lock screen primary and alternate bouncer. */
@@ -33,7 +32,7 @@ class KeyguardBouncerRepository
@Inject
constructor(
private val viewMediatorCallback: ViewMediatorCallback,
private val clock: SystemClock,
keyguardUpdateMonitor: KeyguardUpdateMonitor,
) {
/** Values associated with the PrimaryBouncer (pin/pattern/password) input. */
private val _primaryBouncerVisible = MutableStateFlow(false)
@@ -78,14 +77,6 @@ constructor(
val bouncerErrorMessage: CharSequence?
get() = viewMediatorCallback.consumeCustomMessage()
/** Values associated with the AlternateBouncer */
private val _isAlternateBouncerVisible = MutableStateFlow(false)
val isAlternateBouncerVisible = _isAlternateBouncerVisible.asStateFlow()
var lastAlternateBouncerVisibleTime: Long = NOT_VISIBLE
private val _isAlternateBouncerUIAvailable = MutableStateFlow<Boolean>(false)
val isAlternateBouncerUIAvailable: StateFlow<Boolean> =
_isAlternateBouncerUIAvailable.asStateFlow()
fun setPrimaryScrimmed(isScrimmed: Boolean) {
_primaryBouncerScrimmed.value = isScrimmed
}
@@ -94,19 +85,6 @@ constructor(
_primaryBouncerVisible.value = isVisible
}
fun setAlternateVisible(isVisible: Boolean) {
if (isVisible && !_isAlternateBouncerVisible.value) {
lastAlternateBouncerVisibleTime = clock.uptimeMillis()
} else if (!isVisible) {
lastAlternateBouncerVisibleTime = NOT_VISIBLE
}
_isAlternateBouncerVisible.value = isVisible
}
fun setAlternateBouncerUIAvailable(isAvailable: Boolean) {
_isAlternateBouncerUIAvailable.value = isAvailable
}
fun setPrimaryShow(keyguardBouncerModel: KeyguardBouncerModel?) {
_primaryBouncerShow.value = keyguardBouncerModel
}
@@ -154,8 +132,4 @@ constructor(
fun setOnScreenTurnedOff(onScreenTurnedOff: Boolean) {
_onScreenTurnedOff.value = onScreenTurnedOff
}
companion object {
private const val NOT_VISIBLE = -1L
}
}

View File

@@ -30,6 +30,4 @@ interface KeyguardRepositoryModule {
@Binds
fun lightRevealScrimRepository(impl: LightRevealScrimRepositoryImpl): LightRevealScrimRepository
@Binds fun biometricRepository(impl: BiometricRepositoryImpl): BiometricRepository
}

View File

@@ -1,126 +0,0 @@
/*
* Copyright (C) 2022 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.systemui.keyguard.domain.interactor
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.data.repository.BiometricRepository
import com.android.systemui.keyguard.data.repository.KeyguardBouncerRepository
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager.LegacyAlternateBouncer
import com.android.systemui.util.time.SystemClock
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
/** Encapsulates business logic for interacting with the lock-screen alternate bouncer. */
@SysUISingleton
class AlternateBouncerInteractor
@Inject
constructor(
private val bouncerRepository: KeyguardBouncerRepository,
private val biometricRepository: BiometricRepository,
private val systemClock: SystemClock,
private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
featureFlags: FeatureFlags,
) {
val isModernAlternateBouncerEnabled = featureFlags.isEnabled(Flags.MODERN_ALTERNATE_BOUNCER)
var legacyAlternateBouncer: LegacyAlternateBouncer? = null
var legacyAlternateBouncerVisibleTime: Long = NOT_VISIBLE
val isVisible: Flow<Boolean> = bouncerRepository.isAlternateBouncerVisible
/**
* Sets the correct bouncer states to show the alternate bouncer if it can show.
* @return whether alternateBouncer is visible
*/
fun show(): Boolean {
return when {
isModernAlternateBouncerEnabled -> {
bouncerRepository.setAlternateVisible(canShowAlternateBouncerForFingerprint())
isVisibleState()
}
canShowAlternateBouncerForFingerprint() -> {
if (legacyAlternateBouncer?.showAlternateBouncer() == true) {
legacyAlternateBouncerVisibleTime = systemClock.uptimeMillis()
true
} else {
false
}
}
else -> false
}
}
/**
* Sets the correct bouncer states to hide the bouncer. Should only be called through
* StatusBarKeyguardViewManager until ScrimController is refactored to use
* alternateBouncerInteractor.
* @return true if the alternate bouncer was newly hidden, else false.
*/
fun hide(): Boolean {
return if (isModernAlternateBouncerEnabled) {
val wasAlternateBouncerVisible = isVisibleState()
bouncerRepository.setAlternateVisible(false)
wasAlternateBouncerVisible && !isVisibleState()
} else {
legacyAlternateBouncer?.hideAlternateBouncer() ?: false
}
}
fun isVisibleState(): Boolean {
return if (isModernAlternateBouncerEnabled) {
bouncerRepository.isAlternateBouncerVisible.value
} else {
legacyAlternateBouncer?.isShowingAlternateBouncer ?: false
}
}
fun setAlternateBouncerUIAvailable(isAvailable: Boolean) {
bouncerRepository.setAlternateBouncerUIAvailable(isAvailable)
}
fun canShowAlternateBouncerForFingerprint(): Boolean {
return if (isModernAlternateBouncerEnabled) {
bouncerRepository.isAlternateBouncerUIAvailable.value &&
biometricRepository.isFingerprintEnrolled.value &&
biometricRepository.isStrongBiometricAllowed.value &&
biometricRepository.isFingerprintEnabledByDevicePolicy.value
} else {
legacyAlternateBouncer != null &&
keyguardUpdateMonitor.isUnlockingWithBiometricAllowed(true)
}
}
/**
* Whether the alt bouncer has shown for a minimum time before allowing touches to dismiss the
* alternate bouncer and show the primary bouncer.
*/
fun hasAlternateBouncerShownWithMinTime(): Boolean {
return if (isModernAlternateBouncerEnabled) {
(systemClock.uptimeMillis() - bouncerRepository.lastAlternateBouncerVisibleTime) >
MIN_VISIBILITY_DURATION_UNTIL_TOUCHES_DISMISS_ALTERNATE_BOUNCER_MS
} else {
systemClock.uptimeMillis() - legacyAlternateBouncerVisibleTime > 200
}
}
companion object {
private const val MIN_VISIBILITY_DURATION_UNTIL_TOUCHES_DISMISS_ALTERNATE_BOUNCER_MS = 200L
private const val NOT_VISIBLE = -1L
}
}

View File

@@ -136,7 +136,6 @@ import com.android.systemui.flags.Flags;
import com.android.systemui.fragments.FragmentHostManager.FragmentListener;
import com.android.systemui.fragments.FragmentService;
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor;
import com.android.systemui.keyguard.domain.interactor.KeyguardBottomAreaInteractor;
import com.android.systemui.keyguard.ui.viewmodel.KeyguardBottomAreaViewModel;
import com.android.systemui.media.controls.pipeline.MediaDataManager;
@@ -352,7 +351,6 @@ public final class NotificationPanelViewController implements Dumpable {
private final FragmentListener mQsFragmentListener = new QsFragmentListener();
private final AccessibilityDelegate mAccessibilityDelegate = new ShadeAccessibilityDelegate();
private final NotificationGutsManager mGutsManager;
private final AlternateBouncerInteractor mAlternateBouncerInteractor;
private long mDownTime;
private boolean mTouchSlopExceededBeforeDown;
@@ -759,7 +757,6 @@ public final class NotificationPanelViewController implements Dumpable {
SystemClock systemClock,
KeyguardBottomAreaViewModel keyguardBottomAreaViewModel,
KeyguardBottomAreaInteractor keyguardBottomAreaInteractor,
AlternateBouncerInteractor alternateBouncerInteractor,
DumpManager dumpManager) {
keyguardStateController.addCallback(new KeyguardStateController.Callback() {
@Override
@@ -940,7 +937,6 @@ public final class NotificationPanelViewController implements Dumpable {
unlockAnimationStarted(playingCannedAnimation, isWakeAndUnlock, startDelay);
}
});
mAlternateBouncerInteractor = alternateBouncerInteractor;
dumpManager.registerDumpable(this);
}
@@ -4814,7 +4810,7 @@ public final class NotificationPanelViewController implements Dumpable {
mUpdateFlingVelocity = vel;
}
} else if (!mCentralSurfaces.isBouncerShowing()
&& !mAlternateBouncerInteractor.isVisibleState()
&& !mStatusBarKeyguardViewManager.isShowingAlternateBouncer()
&& !mKeyguardStateController.isKeyguardGoingAway()) {
onEmptySpaceClick();
onTrackingStopped(true);

View File

@@ -38,7 +38,6 @@ import com.android.systemui.dock.DockManager;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.Flags;
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor;
import com.android.systemui.keyguard.ui.binder.KeyguardBouncerViewBinder;
import com.android.systemui.keyguard.ui.viewmodel.KeyguardBouncerViewModel;
import com.android.systemui.statusbar.DragDownHelper;
@@ -79,7 +78,6 @@ public class NotificationShadeWindowViewController {
private final AmbientState mAmbientState;
private final PulsingGestureListener mPulsingGestureListener;
private final NotificationInsetsController mNotificationInsetsController;
private final AlternateBouncerInteractor mAlternateBouncerInteractor;
private GestureDetector mPulsingWakeupGestureHandler;
private View mBrightnessMirror;
@@ -120,8 +118,7 @@ public class NotificationShadeWindowViewController {
PulsingGestureListener pulsingGestureListener,
FeatureFlags featureFlags,
KeyguardBouncerViewModel keyguardBouncerViewModel,
KeyguardBouncerComponent.Factory keyguardBouncerComponentFactory,
AlternateBouncerInteractor alternateBouncerInteractor
KeyguardBouncerComponent.Factory keyguardBouncerComponentFactory
) {
mLockscreenShadeTransitionController = transitionController;
mFalsingCollector = falsingCollector;
@@ -141,7 +138,6 @@ public class NotificationShadeWindowViewController {
mAmbientState = ambientState;
mPulsingGestureListener = pulsingGestureListener;
mNotificationInsetsController = notificationInsetsController;
mAlternateBouncerInteractor = alternateBouncerInteractor;
// This view is not part of the newly inflated expanded status bar.
mBrightnessMirror = mView.findViewById(R.id.brightness_mirror_container);
@@ -293,7 +289,7 @@ public class NotificationShadeWindowViewController {
return true;
}
if (mAlternateBouncerInteractor.isVisibleState()) {
if (mStatusBarKeyguardViewManager.isShowingAlternateBouncer()) {
// capture all touches if the alt auth bouncer is showing
return true;
}
@@ -331,7 +327,7 @@ public class NotificationShadeWindowViewController {
handled = !mService.isPulsing();
}
if (mAlternateBouncerInteractor.isVisibleState()) {
if (mStatusBarKeyguardViewManager.isShowingAlternateBouncer()) {
// eat the touch
handled = true;
}

View File

@@ -332,7 +332,7 @@ public class CommandQueue extends IStatusBar.Stub implements
/**
* @see IStatusBar#setBiometicContextListener(IBiometricContextListener)
*/
default void setBiometricContextListener(IBiometricContextListener listener) {
default void setBiometicContextListener(IBiometricContextListener listener) {
}
/**
@@ -1580,7 +1580,7 @@ public class CommandQueue extends IStatusBar.Stub implements
}
case MSG_SET_BIOMETRICS_LISTENER:
for (int i = 0; i < mCallbacks.size(); i++) {
mCallbacks.get(i).setBiometricContextListener(
mCallbacks.get(i).setBiometicContextListener(
(IBiometricContextListener) msg.obj);
}
break;

View File

@@ -90,7 +90,6 @@ import com.android.systemui.dock.DockManager;
import com.android.systemui.keyguard.KeyguardIndication;
import com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController;
import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
@@ -156,7 +155,6 @@ public class KeyguardIndicationController {
private final KeyguardBypassController mKeyguardBypassController;
private final AccessibilityManager mAccessibilityManager;
private final Handler mHandler;
private final AlternateBouncerInteractor mAlternateBouncerInteractor;
@VisibleForTesting
public KeyguardIndicationRotateTextViewController mRotateTextViewController;
@@ -236,8 +234,7 @@ public class KeyguardIndicationController {
KeyguardBypassController keyguardBypassController,
AccessibilityManager accessibilityManager,
FaceHelpMessageDeferral faceHelpMessageDeferral,
KeyguardLogger keyguardLogger,
AlternateBouncerInteractor alternateBouncerInteractor) {
KeyguardLogger keyguardLogger) {
mContext = context;
mBroadcastDispatcher = broadcastDispatcher;
mDevicePolicyManager = devicePolicyManager;
@@ -259,7 +256,6 @@ public class KeyguardIndicationController {
mScreenLifecycle = screenLifecycle;
mKeyguardLogger = keyguardLogger;
mScreenLifecycle.addObserver(mScreenObserver);
mAlternateBouncerInteractor = alternateBouncerInteractor;
mFaceAcquiredMessageDeferral = faceHelpMessageDeferral;
mCoExFaceAcquisitionMsgIdsToShow = new HashSet<>();
@@ -932,7 +928,7 @@ public class KeyguardIndicationController {
}
if (mStatusBarKeyguardViewManager.isBouncerShowing()) {
if (mAlternateBouncerInteractor.isVisibleState()) {
if (mStatusBarKeyguardViewManager.isShowingAlternateBouncer()) {
return; // udfps affordance is highlighted, no need to show action to unlock
} else if (mKeyguardUpdateMonitor.isFaceEnrolled()) {
String message = mContext.getString(R.string.keyguard_retry);

View File

@@ -31,7 +31,6 @@ import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dump.DumpHandler;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor;
import com.android.systemui.media.controls.pipeline.MediaDataManager;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -62,6 +61,7 @@ import com.android.systemui.statusbar.phone.ManagedProfileControllerImpl;
import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.phone.StatusBarIconControllerImpl;
import com.android.systemui.statusbar.phone.StatusBarIconList;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.systemui.statusbar.phone.StatusBarRemoteInputCallback;
import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController;
import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallFlags;
@@ -280,7 +280,7 @@ public interface CentralSurfacesDependenciesModule {
@SysUISingleton
static DialogLaunchAnimator provideDialogLaunchAnimator(IDreamManager dreamManager,
KeyguardStateController keyguardStateController,
Lazy<AlternateBouncerInteractor> alternateBouncerInteractor,
Lazy<StatusBarKeyguardViewManager> statusBarKeyguardViewManager,
InteractionJankMonitor interactionJankMonitor) {
DialogLaunchAnimator.Callback callback = new DialogLaunchAnimator.Callback() {
@Override
@@ -300,7 +300,7 @@ public interface CentralSurfacesDependenciesModule {
@Override
public boolean isShowingAlternateAuthOnUnlock() {
return alternateBouncerInteractor.get().canShowAlternateBouncerForFingerprint();
return statusBarKeyguardViewManager.get().canShowAlternateBouncer();
}
};
return new DialogLaunchAnimator(callback, interactionJankMonitor);

View File

@@ -157,6 +157,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
private KeyguardViewController mKeyguardViewController;
private DozeScrimController mDozeScrimController;
private KeyguardViewMediator mKeyguardViewMediator;
private ScrimController mScrimController;
private PendingAuthenticated mPendingAuthenticated = null;
private boolean mHasScreenTurnedOnSinceAuthenticating;
private boolean mFadedAwayAfterWakeAndUnlock;
@@ -255,7 +256,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
@Inject
public BiometricUnlockController(
DozeScrimController dozeScrimController,
KeyguardViewMediator keyguardViewMediator,
KeyguardViewMediator keyguardViewMediator, ScrimController scrimController,
NotificationShadeWindowController notificationShadeWindowController,
KeyguardStateController keyguardStateController, Handler handler,
KeyguardUpdateMonitor keyguardUpdateMonitor,
@@ -284,6 +285,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
mNotificationShadeWindowController = notificationShadeWindowController;
mDozeScrimController = dozeScrimController;
mKeyguardViewMediator = keyguardViewMediator;
mScrimController = scrimController;
mKeyguardStateController = keyguardStateController;
mHandler = handler;
mConsecutiveFpFailureThreshold = resources.getInteger(
@@ -364,6 +366,12 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
Trace.endSection();
}
private boolean pulsingOrAod() {
final ScrimState scrimState = mScrimController.getState();
return scrimState == ScrimState.AOD
|| scrimState == ScrimState.PULSING;
}
@Override
public void onBiometricAuthenticated(int userId, BiometricSourceType biometricSourceType,
boolean isStrongBiometric) {
@@ -408,7 +416,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
boolean wasDeviceInteractive = mUpdateMonitor.isDeviceInteractive();
mMode = mode;
mHasScreenTurnedOnSinceAuthenticating = false;
if (mMode == MODE_WAKE_AND_UNLOCK_PULSING) {
if (mMode == MODE_WAKE_AND_UNLOCK_PULSING && pulsingOrAod()) {
// If we are waking the device up while we are pulsing the clock and the
// notifications would light up first, creating an unpleasant animation.
// Defer changing the screen brightness by forcing doze brightness on our window

View File

@@ -157,7 +157,6 @@ import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor;
import com.android.systemui.keyguard.ui.binder.LightRevealScrimViewBinder;
import com.android.systemui.keyguard.ui.viewmodel.LightRevealScrimViewModel;
import com.android.systemui.navigationbar.NavigationBarController;
@@ -466,7 +465,6 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
private final ShadeController mShadeController;
private final InitController mInitController;
private final Lazy<CameraLauncher> mCameraLauncherLazy;
private final AlternateBouncerInteractor mAlternateBouncerInteractor;
private final PluginDependencyProvider mPluginDependencyProvider;
private final KeyguardDismissUtil mKeyguardDismissUtil;
@@ -745,9 +743,7 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
WiredChargingRippleController wiredChargingRippleController,
IDreamManager dreamManager,
Lazy<CameraLauncher> cameraLauncherLazy,
Lazy<LightRevealScrimViewModel> lightRevealScrimViewModelLazy,
AlternateBouncerInteractor alternateBouncerInteractor
) {
Lazy<LightRevealScrimViewModel> lightRevealScrimViewModelLazy) {
mContext = context;
mNotificationsController = notificationsController;
mFragmentService = fragmentService;
@@ -825,7 +821,6 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
mWallpaperManager = wallpaperManager;
mJankMonitor = jankMonitor;
mCameraLauncherLazy = cameraLauncherLazy;
mAlternateBouncerInteractor = alternateBouncerInteractor;
mLockscreenShadeTransitionController = lockscreenShadeTransitionController;
mStartingSurfaceOptional = startingSurfaceOptional;
@@ -3227,7 +3222,8 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
private void showBouncerOrLockScreenIfKeyguard() {
// If the keyguard is animating away, we aren't really the keyguard anymore and should not
// show the bouncer/lockscreen.
if (!mKeyguardViewMediator.isHiding() && !mKeyguardUpdateMonitor.isKeyguardGoingAway()) {
if (!mKeyguardViewMediator.isHiding()
&& !mKeyguardUnlockAnimationController.isPlayingCannedUnlockAnimation()) {
if (mState == StatusBarState.SHADE_LOCKED) {
// shade is showing while locked on the keyguard, so go back to showing the
// lock screen where users can use the UDFPS affordance to enter the device
@@ -3706,7 +3702,7 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
boolean launchingAffordanceWithPreview = mLaunchingAffordance;
mScrimController.setLaunchingAffordanceWithPreview(launchingAffordanceWithPreview);
if (mAlternateBouncerInteractor.isVisibleState()) {
if (mStatusBarKeyguardViewManager.isShowingAlternateBouncer()) {
if (mState == StatusBarState.SHADE || mState == StatusBarState.SHADE_LOCKED
|| mTransitionToFullShadeProgress > 0f) {
mScrimController.transitionTo(ScrimState.AUTH_SCRIMMED_SHADE);

View File

@@ -58,7 +58,6 @@ import com.android.systemui.dreams.DreamOverlayStateController;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.Flags;
import com.android.systemui.keyguard.data.BouncerView;
import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor;
import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerCallbackInteractor;
import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor;
import com.android.systemui.navigationbar.NavigationBarView;
@@ -135,7 +134,6 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
private KeyguardMessageAreaController<AuthKeyguardMessageArea> mKeyguardMessageAreaController;
private final PrimaryBouncerCallbackInteractor mPrimaryBouncerCallbackInteractor;
private final PrimaryBouncerInteractor mPrimaryBouncerInteractor;
private final AlternateBouncerInteractor mAlternateBouncerInteractor;
private final BouncerView mPrimaryBouncerView;
private final Lazy<com.android.systemui.shade.ShadeController> mShadeController;
@@ -254,7 +252,6 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
private float mQsExpansion;
final Set<KeyguardViewManagerCallback> mCallbacks = new HashSet<>();
private boolean mIsModernBouncerEnabled;
private boolean mIsModernAlternateBouncerEnabled;
private OnDismissAction mAfterKeyguardGoneAction;
private Runnable mKeyguardGoneCancelAction;
@@ -271,7 +268,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
private final LatencyTracker mLatencyTracker;
private final KeyguardSecurityModel mKeyguardSecurityModel;
@Nullable private KeyguardBypassController mBypassController;
@Nullable private OccludingAppBiometricUI mOccludingAppBiometricUI;
@Nullable private AlternateBouncer mAlternateBouncer;
private final KeyguardUpdateMonitorCallback mUpdateMonitorCallback =
new KeyguardUpdateMonitorCallback() {
@@ -308,8 +305,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
FeatureFlags featureFlags,
PrimaryBouncerCallbackInteractor primaryBouncerCallbackInteractor,
PrimaryBouncerInteractor primaryBouncerInteractor,
BouncerView primaryBouncerView,
AlternateBouncerInteractor alternateBouncerInteractor) {
BouncerView primaryBouncerView) {
mContext = context;
mViewMediatorCallback = callback;
mLockPatternUtils = lockPatternUtils;
@@ -333,8 +329,6 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
mFoldAodAnimationController = sysUIUnfoldComponent
.map(SysUIUnfoldComponent::getFoldAodAnimationController).orElse(null);
mIsModernBouncerEnabled = featureFlags.isEnabled(Flags.MODERN_BOUNCER);
mIsModernAlternateBouncerEnabled = featureFlags.isEnabled(Flags.MODERN_ALTERNATE_BOUNCER);
mAlternateBouncerInteractor = alternateBouncerInteractor;
}
@Override
@@ -367,51 +361,23 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
}
/**
* Sets the given legacy alternate bouncer to null if it's the current alternate bouncer. Else,
* does nothing. Only used if modern alternate bouncer is NOT enabled.
*/
public void removeLegacyAlternateBouncer(
@NonNull LegacyAlternateBouncer alternateBouncerLegacy) {
if (!mIsModernAlternateBouncerEnabled) {
if (Objects.equals(mAlternateBouncerInteractor.getLegacyAlternateBouncer(),
alternateBouncerLegacy)) {
mAlternateBouncerInteractor.setLegacyAlternateBouncer(null);
hideAlternateBouncer(true);
}
}
}
/**
* Sets a new legacy alternate bouncer. Only used if mdoern alternate bouncer is NOT enable.
*/
public void setLegacyAlternateBouncer(@NonNull LegacyAlternateBouncer alternateBouncerLegacy) {
if (!mIsModernAlternateBouncerEnabled) {
if (!Objects.equals(mAlternateBouncerInteractor.getLegacyAlternateBouncer(),
alternateBouncerLegacy)) {
mAlternateBouncerInteractor.setLegacyAlternateBouncer(alternateBouncerLegacy);
hideAlternateBouncer(false);
}
}
}
/**
* Sets the given OccludingAppBiometricUI to null if it's the current auth interceptor. Else,
* Sets the given alt auth interceptor to null if it's the current auth interceptor. Else,
* does nothing.
*/
public void removeOccludingAppBiometricUI(@NonNull OccludingAppBiometricUI biometricUI) {
if (Objects.equals(mOccludingAppBiometricUI, biometricUI)) {
mOccludingAppBiometricUI = null;
public void removeAlternateAuthInterceptor(@NonNull AlternateBouncer authInterceptor) {
if (Objects.equals(mAlternateBouncer, authInterceptor)) {
mAlternateBouncer = null;
hideAlternateBouncer(true);
}
}
/**
* Sets a new OccludingAppBiometricUI.
* Sets a new alt auth interceptor.
*/
public void setOccludingAppBiometricUI(@NonNull OccludingAppBiometricUI biometricUI) {
if (!Objects.equals(mOccludingAppBiometricUI, biometricUI)) {
mOccludingAppBiometricUI = biometricUI;
public void setAlternateBouncer(@NonNull AlternateBouncer authInterceptor) {
if (!Objects.equals(mAlternateBouncer, authInterceptor)) {
mAlternateBouncer = authInterceptor;
hideAlternateBouncer(false);
}
}
@@ -598,11 +564,18 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
* {@see KeyguardBouncer#show(boolean, boolean)}
*/
public void showBouncer(boolean scrimmed) {
if (!mAlternateBouncerInteractor.show()) {
showPrimaryBouncer(scrimmed);
} else {
updateAlternateBouncerShowing(mAlternateBouncerInteractor.isVisibleState());
if (canShowAlternateBouncer()) {
updateAlternateBouncerShowing(mAlternateBouncer.showAlternateBouncer());
return;
}
showPrimaryBouncer(scrimmed);
}
/** Whether we can show the alternate bouncer instead of the primary bouncer. */
public boolean canShowAlternateBouncer() {
return mAlternateBouncer != null
&& mKeyguardUpdateManager.isUnlockingWithBiometricAllowed(true);
}
/**
@@ -666,9 +639,9 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
mKeyguardGoneCancelAction = cancelAction;
mDismissActionWillAnimateOnKeyguard = r != null && r.willRunAnimationOnKeyguard();
// If there is an alternate auth interceptor (like the UDFPS), show that one
// If there is an an alternate auth interceptor (like the UDFPS), show that one
// instead of the bouncer.
if (mAlternateBouncerInteractor.canShowAlternateBouncerForFingerprint()) {
if (canShowAlternateBouncer()) {
if (!afterKeyguardGone) {
if (mPrimaryBouncer != null) {
mPrimaryBouncer.setDismissAction(mAfterKeyguardGoneAction,
@@ -681,7 +654,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
mKeyguardGoneCancelAction = null;
}
updateAlternateBouncerShowing(mAlternateBouncerInteractor.show());
updateAlternateBouncerShowing(mAlternateBouncer.showAlternateBouncer());
return;
}
@@ -750,7 +723,10 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
@Override
public void hideAlternateBouncer(boolean forceUpdateScrim) {
updateAlternateBouncerShowing(mAlternateBouncerInteractor.hide() || forceUpdateScrim);
final boolean updateScrim = (mAlternateBouncer != null
&& mAlternateBouncer.hideAlternateBouncer())
|| forceUpdateScrim;
updateAlternateBouncerShowing(updateScrim);
}
private void updateAlternateBouncerShowing(boolean updateScrim) {
@@ -760,7 +736,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
return;
}
final boolean isShowingAlternateBouncer = mAlternateBouncerInteractor.isVisibleState();
final boolean isShowingAlternateBouncer = isShowingAlternateBouncer();
if (mKeyguardMessageAreaController != null) {
mKeyguardMessageAreaController.setIsVisible(isShowingAlternateBouncer);
mKeyguardMessageAreaController.setMessage("");
@@ -1114,7 +1090,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
@Override
public boolean isBouncerShowing() {
return primaryBouncerIsShowing() || mAlternateBouncerInteractor.isVisibleState();
return primaryBouncerIsShowing() || isShowingAlternateBouncer();
}
@Override
@@ -1358,7 +1334,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
mPrimaryBouncerInteractor.notifyKeyguardAuthenticated(strongAuth);
}
if (mAlternateBouncerInteractor.isVisibleState()) {
if (mAlternateBouncer != null && isShowingAlternateBouncer()) {
hideAlternateBouncer(false);
executeAfterKeyguardGoneAction();
}
@@ -1366,7 +1342,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
/** Display security message to relevant KeyguardMessageArea. */
public void setKeyguardMessage(String message, ColorStateList colorState) {
if (mAlternateBouncerInteractor.isVisibleState()) {
if (isShowingAlternateBouncer()) {
if (mKeyguardMessageAreaController != null) {
mKeyguardMessageAreaController.setMessage(message);
}
@@ -1440,7 +1416,6 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
public void dump(PrintWriter pw) {
pw.println("StatusBarKeyguardViewManager:");
pw.println(" mIsModernAlternateBouncerEnabled: " + mIsModernAlternateBouncerEnabled);
pw.println(" mRemoteInputActive: " + mRemoteInputActive);
pw.println(" mDozing: " + mDozing);
pw.println(" mAfterKeyguardGoneAction: " + mAfterKeyguardGoneAction);
@@ -1458,9 +1433,9 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
mPrimaryBouncer.dump(pw);
}
if (mOccludingAppBiometricUI != null) {
pw.println("mOccludingAppBiometricUI:");
mOccludingAppBiometricUI.dump(pw);
if (mAlternateBouncer != null) {
pw.println("AlternateBouncer:");
mAlternateBouncer.dump(pw);
}
}
@@ -1512,17 +1487,14 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
return mPrimaryBouncer;
}
public boolean isShowingAlternateBouncer() {
return mAlternateBouncer != null && mAlternateBouncer.isShowingAlternateBouncer();
}
/**
* For any touches on the NPVC, show the primary bouncer if the alternate bouncer is currently
* showing.
* Forward touches to callbacks.
*/
public void onTouch(MotionEvent event) {
if (mAlternateBouncerInteractor.isVisibleState()
&& mAlternateBouncerInteractor.hasAlternateBouncerShownWithMinTime()) {
showPrimaryBouncer(true);
}
// Forward NPVC touches to callbacks in case they want to respond to touches
for (KeyguardViewManagerCallback callback: mCallbacks) {
callback.onTouch(event);
}
@@ -1565,8 +1537,8 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
*/
public void requestFp(boolean request, int udfpsColor) {
mKeyguardUpdateManager.requestFingerprintAuthOnOccludingApp(request);
if (mOccludingAppBiometricUI != null) {
mOccludingAppBiometricUI.requestUdfps(request, udfpsColor);
if (mAlternateBouncer != null) {
mAlternateBouncer.requestUdfps(request, udfpsColor);
}
}
@@ -1637,9 +1609,10 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
}
/**
* @Deprecated Delegate used to send show and hide events to an alternate bouncer.
* Delegate used to send show and hide events to an alternate authentication method instead of
* the regular pin/pattern/password bouncer.
*/
public interface LegacyAlternateBouncer {
public interface AlternateBouncer {
/**
* Show alternate authentication bouncer.
* @return whether alternate auth method was newly shown
@@ -1656,13 +1629,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
* @return true if the alternate auth bouncer is showing
*/
boolean isShowingAlternateBouncer();
}
/**
* Delegate used to send show and hide events to an alternate authentication method instead of
* the regular pin/pattern/password bouncer.
*/
public interface OccludingAppBiometricUI {
/**
* Use when an app occluding the keyguard would like to give the user ability to
* unlock the device using udfps.

View File

@@ -812,7 +812,7 @@ public class AuthControllerTest extends SysuiTestCase {
public void testForwardsDozeEvents() throws RemoteException {
when(mStatusBarStateController.isDozing()).thenReturn(true);
when(mWakefulnessLifecycle.getWakefulness()).thenReturn(WAKEFULNESS_AWAKE);
mAuthController.setBiometricContextListener(mContextListener);
mAuthController.setBiometicContextListener(mContextListener);
mStatusBarStateListenerCaptor.getValue().onDozingChanged(true);
mStatusBarStateListenerCaptor.getValue().onDozingChanged(false);
@@ -827,7 +827,7 @@ public class AuthControllerTest extends SysuiTestCase {
public void testForwardsWakeEvents() throws RemoteException {
when(mStatusBarStateController.isDozing()).thenReturn(false);
when(mWakefulnessLifecycle.getWakefulness()).thenReturn(WAKEFULNESS_AWAKE);
mAuthController.setBiometricContextListener(mContextListener);
mAuthController.setBiometicContextListener(mContextListener);
mWakefullnessObserverCaptor.getValue().onStartedGoingToSleep();
mWakefullnessObserverCaptor.getValue().onFinishedGoingToSleep();

View File

@@ -43,7 +43,6 @@ import com.android.systemui.SysuiTestCase
import com.android.systemui.animation.ActivityLaunchAnimator
import com.android.systemui.dump.DumpManager
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor
import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.shade.ShadeExpansionStateManager
@@ -53,6 +52,7 @@ import com.android.systemui.statusbar.phone.SystemUIDialogManager
import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.time.SystemClock
import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Rule
@@ -95,6 +95,7 @@ class UdfpsControllerOverlayTest : SysuiTestCase() {
@Mock private lateinit var dumpManager: DumpManager
@Mock private lateinit var transitionController: LockscreenShadeTransitionController
@Mock private lateinit var configurationController: ConfigurationController
@Mock private lateinit var systemClock: SystemClock
@Mock private lateinit var keyguardStateController: KeyguardStateController
@Mock private lateinit var unlockedScreenOffAnimationController:
UnlockedScreenOffAnimationController
@@ -105,8 +106,7 @@ class UdfpsControllerOverlayTest : SysuiTestCase() {
@Mock private lateinit var udfpsEnrollView: UdfpsEnrollView
@Mock private lateinit var activityLaunchAnimator: ActivityLaunchAnimator
@Mock private lateinit var featureFlags: FeatureFlags
@Mock private lateinit var primaryBouncerInteractor: PrimaryBouncerInteractor
@Mock private lateinit var alternateBouncerInteractor: AlternateBouncerInteractor
@Mock private lateinit var mPrimaryBouncerInteractor: PrimaryBouncerInteractor
@Captor private lateinit var layoutParamsCaptor: ArgumentCaptor<WindowManager.LayoutParams>
private val onTouch = { _: View, _: MotionEvent, _: Boolean -> true }
@@ -138,10 +138,10 @@ class UdfpsControllerOverlayTest : SysuiTestCase() {
context, fingerprintManager, inflater, windowManager, accessibilityManager,
statusBarStateController, shadeExpansionStateManager, statusBarKeyguardViewManager,
keyguardUpdateMonitor, dialogManager, dumpManager, transitionController,
configurationController, keyguardStateController,
configurationController, systemClock, keyguardStateController,
unlockedScreenOffAnimationController, udfpsDisplayMode, REQUEST_ID, reason,
controllerCallback, onTouch, activityLaunchAnimator, featureFlags,
primaryBouncerInteractor, alternateBouncerInteractor, isDebuggable,
mPrimaryBouncerInteractor, isDebuggable
)
block()
}

View File

@@ -78,7 +78,6 @@ import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.Flags;
import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor;
import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -200,8 +199,6 @@ public class UdfpsControllerTest extends SysuiTestCase {
private PrimaryBouncerInteractor mPrimaryBouncerInteractor;
@Mock
private SinglePointerTouchProcessor mSinglePointerTouchProcessor;
@Mock
private AlternateBouncerInteractor mAlternateBouncerInteractor;
// Capture listeners so that they can be used to send events
@Captor
@@ -290,8 +287,7 @@ public class UdfpsControllerTest extends SysuiTestCase {
mDisplayManager, mHandler, mConfigurationController, mSystemClock,
mUnlockedScreenOffAnimationController, mSystemUIDialogManager, mLatencyTracker,
mActivityLaunchAnimator, alternateTouchProvider, mBiometricsExecutor,
mPrimaryBouncerInteractor, mSinglePointerTouchProcessor,
mAlternateBouncerInteractor);
mPrimaryBouncerInteractor, mSinglePointerTouchProcessor);
verify(mFingerprintManager).setUdfpsOverlayController(mOverlayCaptor.capture());
mOverlayController = mOverlayCaptor.getValue();
verify(mScreenLifecycle).addObserver(mScreenObserverCaptor.capture());
@@ -405,7 +401,7 @@ public class UdfpsControllerTest extends SysuiTestCase {
// GIVEN overlay was showing and the udfps bouncer is showing
mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, mOpticalProps.sensorId,
BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
when(mAlternateBouncerInteractor.isVisibleState()).thenReturn(true);
when(mStatusBarKeyguardViewManager.isShowingAlternateBouncer()).thenReturn(true);
// WHEN the overlay is hidden
mOverlayController.hideUdfpsOverlay(mOpticalProps.sensorId);

View File

@@ -30,7 +30,6 @@ import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FakeFeatureFlags;
import com.android.systemui.flags.Flags;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor;
import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.shade.ShadeExpansionChangeEvent;
@@ -44,6 +43,7 @@ import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.concurrency.DelayableExecutor;
import com.android.systemui.util.time.FakeSystemClock;
import org.junit.Before;
import org.mockito.ArgumentCaptor;
@@ -73,9 +73,9 @@ public class UdfpsKeyguardViewControllerBaseTest extends SysuiTestCase {
protected @Mock ActivityLaunchAnimator mActivityLaunchAnimator;
protected @Mock KeyguardBouncer mBouncer;
protected @Mock PrimaryBouncerInteractor mPrimaryBouncerInteractor;
protected @Mock AlternateBouncerInteractor mAlternateBouncerInteractor;
protected FakeFeatureFlags mFeatureFlags = new FakeFeatureFlags();
protected FakeSystemClock mSystemClock = new FakeSystemClock();
protected UdfpsKeyguardViewController mController;
@@ -86,6 +86,10 @@ public class UdfpsKeyguardViewControllerBaseTest extends SysuiTestCase {
private @Captor ArgumentCaptor<ShadeExpansionListener> mExpansionListenerCaptor;
protected List<ShadeExpansionListener> mExpansionListeners;
private @Captor ArgumentCaptor<StatusBarKeyguardViewManager.AlternateBouncer>
mAlternateBouncerCaptor;
protected StatusBarKeyguardViewManager.AlternateBouncer mAlternateBouncer;
private @Captor ArgumentCaptor<KeyguardStateController.Callback>
mKeyguardStateControllerCallbackCaptor;
protected KeyguardStateController.Callback mKeyguardStateControllerCallback;
@@ -131,6 +135,12 @@ public class UdfpsKeyguardViewControllerBaseTest extends SysuiTestCase {
}
}
protected void captureAltAuthInterceptor() {
verify(mStatusBarKeyguardViewManager).setAlternateBouncer(
mAlternateBouncerCaptor.capture());
mAlternateBouncer = mAlternateBouncerCaptor.getValue();
}
protected void captureKeyguardStateControllerCallback() {
verify(mKeyguardStateController).addCallback(
mKeyguardStateControllerCallbackCaptor.capture());
@@ -150,7 +160,6 @@ public class UdfpsKeyguardViewControllerBaseTest extends SysuiTestCase {
protected UdfpsKeyguardViewController createUdfpsKeyguardViewController(
boolean useModernBouncer, boolean useExpandedOverlay) {
mFeatureFlags.set(Flags.MODERN_BOUNCER, useModernBouncer);
mFeatureFlags.set(Flags.MODERN_ALTERNATE_BOUNCER, useModernBouncer);
mFeatureFlags.set(Flags.UDFPS_NEW_TOUCH_DETECTION, useExpandedOverlay);
when(mStatusBarKeyguardViewManager.getPrimaryBouncer()).thenReturn(
useModernBouncer ? null : mBouncer);
@@ -163,14 +172,14 @@ public class UdfpsKeyguardViewControllerBaseTest extends SysuiTestCase {
mDumpManager,
mLockscreenShadeTransitionController,
mConfigurationController,
mSystemClock,
mKeyguardStateController,
mUnlockedScreenOffAnimationController,
mDialogManager,
mUdfpsController,
mActivityLaunchAnimator,
mFeatureFlags,
mPrimaryBouncerInteractor,
mAlternateBouncerInteractor);
mPrimaryBouncerInteractor);
return controller;
}
}

View File

@@ -19,15 +19,18 @@ package com.android.systemui.biometrics;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.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.testing.TestableLooper.RunWithLooper;
import android.view.MotionEvent;
import androidx.test.filters.SmallTest;
@@ -43,8 +46,7 @@ import org.mockito.Captor;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper(setAsMainLooper = true)
@RunWithLooper
public class UdfpsKeyguardViewControllerTest extends UdfpsKeyguardViewControllerBaseTest {
private @Captor ArgumentCaptor<KeyguardBouncer.PrimaryBouncerExpansionCallback>
mBouncerExpansionCallbackCaptor;
@@ -70,6 +72,8 @@ public class UdfpsKeyguardViewControllerTest extends UdfpsKeyguardViewController
assertTrue(mController.shouldPauseAuth());
}
@Test
public void testRegistersExpansionChangedListenerOnAttached() {
mController.onViewAttached();
@@ -233,9 +237,85 @@ public class UdfpsKeyguardViewControllerTest extends UdfpsKeyguardViewController
public void testOverrideShouldPauseAuthOnShadeLocked() {
mController.onViewAttached();
captureStatusBarStateListeners();
captureAltAuthInterceptor();
sendStatusBarStateChanged(StatusBarState.SHADE_LOCKED);
assertTrue(mController.shouldPauseAuth());
mAlternateBouncer.showAlternateBouncer(); // force show
assertFalse(mController.shouldPauseAuth());
assertTrue(mAlternateBouncer.isShowingAlternateBouncer());
mAlternateBouncer.hideAlternateBouncer(); // stop force show
assertTrue(mController.shouldPauseAuth());
assertFalse(mAlternateBouncer.isShowingAlternateBouncer());
}
@Test
public void testOnDetachedStateReset() {
// GIVEN view is attached
mController.onViewAttached();
captureAltAuthInterceptor();
// WHEN view is detached
mController.onViewDetached();
// THEN remove alternate auth interceptor
verify(mStatusBarKeyguardViewManager).removeAlternateAuthInterceptor(mAlternateBouncer);
}
@Test
public void testHiddenUdfpsBouncerOnTouchOutside_nothingHappens() {
// GIVEN view is attached
mController.onViewAttached();
captureAltAuthInterceptor();
// GIVEN udfps bouncer isn't showing
mAlternateBouncer.hideAlternateBouncer();
// WHEN touch is observed outside the view
mController.onTouchOutsideView();
// THEN bouncer / alt auth methods are never called
verify(mStatusBarKeyguardViewManager, never()).showPrimaryBouncer(anyBoolean());
verify(mStatusBarKeyguardViewManager, never()).showBouncer(anyBoolean());
verify(mStatusBarKeyguardViewManager, never()).hideAlternateBouncer(anyBoolean());
}
@Test
public void testShowingUdfpsBouncerOnTouchOutsideWithinThreshold_nothingHappens() {
// GIVEN view is attached
mController.onViewAttached();
captureAltAuthInterceptor();
// GIVEN udfps bouncer is showing
mAlternateBouncer.showAlternateBouncer();
// WHEN touch is observed outside the view 200ms later (just within threshold)
mSystemClock.advanceTime(200);
mController.onTouchOutsideView();
// THEN bouncer / alt auth methods are never called because not enough time has passed
verify(mStatusBarKeyguardViewManager, never()).showPrimaryBouncer(anyBoolean());
verify(mStatusBarKeyguardViewManager, never()).showBouncer(anyBoolean());
verify(mStatusBarKeyguardViewManager, never()).hideAlternateBouncer(anyBoolean());
}
@Test
public void testShowingUdfpsBouncerOnTouchOutsideAboveThreshold_showPrimaryBouncer() {
// GIVEN view is attached
mController.onViewAttached();
captureAltAuthInterceptor();
// GIVEN udfps bouncer is showing
mAlternateBouncer.showAlternateBouncer();
// WHEN touch is observed outside the view 205ms later
mSystemClock.advanceTime(205);
mController.onTouchOutsideView();
// THEN show the bouncer
verify(mStatusBarKeyguardViewManager).showPrimaryBouncer(eq(true));
}
@Test
@@ -253,6 +333,25 @@ public class UdfpsKeyguardViewControllerTest extends UdfpsKeyguardViewController
verify(mView).setUnpausedAlpha(0);
}
@Test
public void testShowUdfpsBouncer() {
// GIVEN view is attached and status bar expansion is 0
mController.onViewAttached();
captureStatusBarExpansionListeners();
captureKeyguardStateControllerCallback();
captureAltAuthInterceptor();
updateStatusBarExpansion(0, true);
reset(mView);
when(mView.getContext()).thenReturn(mResourceContext);
when(mResourceContext.getString(anyInt())).thenReturn("test string");
// WHEN status bar expansion is 0 but udfps bouncer is requested
mAlternateBouncer.showAlternateBouncer();
// THEN alpha is 255
verify(mView).setUnpausedAlpha(255);
}
@Test
public void testTransitionToFullShadeProgress() {
// GIVEN view is attached and status bar expansion is 1f
@@ -270,6 +369,24 @@ public class UdfpsKeyguardViewControllerTest extends UdfpsKeyguardViewController
verify(mView).setUnpausedAlpha((int) ((1f - transitionProgress) * 255));
}
@Test
public void testShowUdfpsBouncer_transitionToFullShadeProgress() {
// GIVEN view is attached and status bar expansion is 1f
mController.onViewAttached();
captureStatusBarExpansionListeners();
captureKeyguardStateControllerCallback();
captureAltAuthInterceptor();
updateStatusBarExpansion(1f, true);
mAlternateBouncer.showAlternateBouncer();
reset(mView);
// WHEN we're transitioning to the full shade
mController.setTransitionToFullShadeProgress(1.0f);
// THEN alpha is 255 (b/c udfps bouncer is requested)
verify(mView).setUnpausedAlpha(255);
}
@Test
public void testUpdatePanelExpansion_pauseAuth() {
// GIVEN view is attached + on the keyguard

View File

@@ -21,32 +21,23 @@ import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
import androidx.test.filters.SmallTest
import com.android.keyguard.KeyguardSecurityModel
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.keyguard.DismissCallbackRegistry
import com.android.systemui.keyguard.data.BouncerView
import com.android.systemui.keyguard.data.repository.BiometricRepository
import com.android.systemui.keyguard.data.repository.KeyguardBouncerRepository
import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor
import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerCallbackInteractor
import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor
import com.android.systemui.statusbar.StatusBarState
import com.android.systemui.statusbar.phone.KeyguardBouncer
import com.android.systemui.statusbar.phone.KeyguardBypassController
import com.android.systemui.util.time.FakeSystemClock
import com.android.systemui.util.time.SystemClock
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.yield
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers.any
import org.mockito.Mockito.mock
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
@RunWith(AndroidTestingRunner::class)
@@ -62,7 +53,7 @@ class UdfpsKeyguardViewControllerWithCoroutinesTest : UdfpsKeyguardViewControlle
keyguardBouncerRepository =
KeyguardBouncerRepository(
mock(com.android.keyguard.ViewMediatorCallback::class.java),
FakeSystemClock()
mKeyguardUpdateMonitor
)
super.setUp()
}
@@ -81,43 +72,15 @@ class UdfpsKeyguardViewControllerWithCoroutinesTest : UdfpsKeyguardViewControlle
mock(KeyguardBypassController::class.java),
mKeyguardUpdateMonitor
)
mAlternateBouncerInteractor =
AlternateBouncerInteractor(
keyguardBouncerRepository,
mock(BiometricRepository::class.java),
mock(SystemClock::class.java),
mock(KeyguardUpdateMonitor::class.java),
mock(FeatureFlags::class.java)
)
return createUdfpsKeyguardViewController(
/* useModernBouncer */ true, /* useExpandedOverlay */
false
)
}
/** After migration, replaces LockIconViewControllerTest version */
@Test
fun shadeLocked_showAlternateBouncer_unpauseAuth() =
runBlocking(IMMEDIATE) {
// GIVEN view is attached + on the SHADE_LOCKED (udfps view not showing)
mController.onViewAttached()
captureStatusBarStateListeners()
sendStatusBarStateChanged(StatusBarState.SHADE_LOCKED)
// WHEN alternate bouncer is requested
val job = mController.listenForAlternateBouncerVisibility(this)
keyguardBouncerRepository.setAlternateVisible(true)
yield()
// THEN udfps view will animate in & pause auth is updated to NOT pause
verify(mView).animateInUdfpsBouncer(any())
assertFalse(mController.shouldPauseAuth())
job.cancel()
}
/** After migration to MODERN_BOUNCER, replaces UdfpsKeyguardViewControllerTest version */
@Test
fun shouldPauseAuthBouncerShowing() =
fun testShouldPauseAuthBouncerShowing() =
runBlocking(IMMEDIATE) {
// GIVEN view attached and we're on the keyguard
mController.onViewAttached()

View File

@@ -79,6 +79,15 @@ class UdfpsViewTest : SysuiTestCase() {
ViewUtils.detachView(view)
}
@Test
fun forwardsEvents() {
view.dozeTimeTick()
verify(animationViewController).dozeTimeTick()
view.onTouchOutsideView()
verify(animationViewController).onTouchOutsideView()
}
@Test
fun layoutSizeFitsSensor() {
val params = withArgCaptor<RectF> {

View File

@@ -1,176 +0,0 @@
/*
* Copyright (C) 2022 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.systemui.keyguard.data.repository
import android.app.admin.DevicePolicyManager
import android.content.Intent
import android.content.pm.UserInfo
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
import androidx.test.filters.SmallTest
import com.android.internal.widget.LockPatternUtils
import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_NOT_REQUIRED
import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT
import com.android.systemui.SysuiTestCase
import com.android.systemui.biometrics.AuthController
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.user.data.repository.FakeUserRepository
import com.android.systemui.util.mockito.argumentCaptor
import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestDispatcher
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers.any
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.Mock
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
@SmallTest
@TestableLooper.RunWithLooper(setAsMainLooper = true)
@RunWith(AndroidTestingRunner::class)
class BiometricRepositoryTest : SysuiTestCase() {
private lateinit var underTest: BiometricRepository
@Mock private lateinit var authController: AuthController
@Mock private lateinit var lockPatternUtils: LockPatternUtils
@Mock private lateinit var devicePolicyManager: DevicePolicyManager
private lateinit var userRepository: FakeUserRepository
private lateinit var testDispatcher: TestDispatcher
private lateinit var testScope: TestScope
private var testableLooper: TestableLooper? = null
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
testableLooper = TestableLooper.get(this)
testDispatcher = StandardTestDispatcher()
testScope = TestScope(testDispatcher)
userRepository = FakeUserRepository()
}
private suspend fun createBiometricRepository() {
userRepository.setUserInfos(listOf(PRIMARY_USER))
userRepository.setSelectedUserInfo(PRIMARY_USER)
underTest =
BiometricRepositoryImpl(
context = context,
lockPatternUtils = lockPatternUtils,
broadcastDispatcher = fakeBroadcastDispatcher,
authController = authController,
userRepository = userRepository,
devicePolicyManager = devicePolicyManager,
scope = testScope.backgroundScope,
backgroundDispatcher = testDispatcher,
looper = testableLooper!!.looper,
)
}
@Test
fun fingerprintEnrollmentChange() =
testScope.runTest {
createBiometricRepository()
val fingerprintEnabledByDevicePolicy = collectLastValue(underTest.isFingerprintEnrolled)
runCurrent()
val captor = argumentCaptor<AuthController.Callback>()
verify(authController).addCallback(captor.capture())
whenever(authController.isFingerprintEnrolled(anyInt())).thenReturn(true)
captor.value.onEnrollmentsChanged(
BiometricType.UNDER_DISPLAY_FINGERPRINT,
PRIMARY_USER_ID,
true
)
assertThat(fingerprintEnabledByDevicePolicy()).isTrue()
whenever(authController.isFingerprintEnrolled(anyInt())).thenReturn(false)
captor.value.onEnrollmentsChanged(
BiometricType.UNDER_DISPLAY_FINGERPRINT,
PRIMARY_USER_ID,
false
)
assertThat(fingerprintEnabledByDevicePolicy()).isFalse()
}
@Test
fun strongBiometricAllowedChange() =
testScope.runTest {
createBiometricRepository()
val strongBiometricAllowed = collectLastValue(underTest.isStrongBiometricAllowed)
runCurrent()
val captor = argumentCaptor<LockPatternUtils.StrongAuthTracker>()
verify(lockPatternUtils).registerStrongAuthTracker(captor.capture())
captor.value
.getStub()
.onStrongAuthRequiredChanged(STRONG_AUTH_NOT_REQUIRED, PRIMARY_USER_ID)
testableLooper?.processAllMessages() // StrongAuthTracker uses the TestableLooper
assertThat(strongBiometricAllowed()).isTrue()
captor.value
.getStub()
.onStrongAuthRequiredChanged(STRONG_AUTH_REQUIRED_AFTER_BOOT, PRIMARY_USER_ID)
testableLooper?.processAllMessages() // StrongAuthTracker uses the TestableLooper
assertThat(strongBiometricAllowed()).isFalse()
}
@Test
fun fingerprintDisabledByDpmChange() =
testScope.runTest {
createBiometricRepository()
val fingerprintEnabledByDevicePolicy =
collectLastValue(underTest.isFingerprintEnabledByDevicePolicy)
runCurrent()
whenever(devicePolicyManager.getKeyguardDisabledFeatures(any(), anyInt()))
.thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT)
broadcastDPMStateChange()
assertThat(fingerprintEnabledByDevicePolicy()).isFalse()
whenever(devicePolicyManager.getKeyguardDisabledFeatures(any(), anyInt())).thenReturn(0)
broadcastDPMStateChange()
assertThat(fingerprintEnabledByDevicePolicy()).isTrue()
}
private fun broadcastDPMStateChange() {
fakeBroadcastDispatcher.registeredReceivers.forEach { receiver ->
receiver.onReceive(
context,
Intent(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED)
)
}
}
companion object {
private const val PRIMARY_USER_ID = 0
private val PRIMARY_USER =
UserInfo(
/* id= */ PRIMARY_USER_ID,
/* name= */ "primary user",
/* flags= */ UserInfo.FLAG_PRIMARY
)
}
}

View File

@@ -1,146 +0,0 @@
/*
* Copyright (C) 2022 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.systemui.keyguard.domain.interactor
import androidx.test.filters.SmallTest
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.keyguard.ViewMediatorCallback
import com.android.systemui.SysuiTestCase
import com.android.systemui.flags.FakeFeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.data.repository.FakeBiometricRepository
import com.android.systemui.keyguard.data.repository.KeyguardBouncerRepository
import com.android.systemui.util.time.FakeSystemClock
import com.android.systemui.util.time.SystemClock
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
import org.mockito.Mock
import org.mockito.Mockito.mock
import org.mockito.MockitoAnnotations
@SmallTest
@RunWith(JUnit4::class)
class AlternateBouncerInteractorTest : SysuiTestCase() {
private lateinit var underTest: AlternateBouncerInteractor
private lateinit var bouncerRepository: KeyguardBouncerRepository
private lateinit var biometricRepository: FakeBiometricRepository
@Mock private lateinit var systemClock: SystemClock
@Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
private lateinit var featureFlags: FakeFeatureFlags
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
bouncerRepository =
KeyguardBouncerRepository(mock(ViewMediatorCallback::class.java), FakeSystemClock())
biometricRepository = FakeBiometricRepository()
featureFlags = FakeFeatureFlags().apply { this.set(Flags.MODERN_ALTERNATE_BOUNCER, true) }
underTest =
AlternateBouncerInteractor(
bouncerRepository,
biometricRepository,
systemClock,
keyguardUpdateMonitor,
featureFlags,
)
}
@Test
fun canShowAlternateBouncerForFingerprint_givenCanShow() {
givenCanShowAlternateBouncer()
assertTrue(underTest.canShowAlternateBouncerForFingerprint())
}
@Test
fun canShowAlternateBouncerForFingerprint_alternateBouncerUIUnavailable() {
givenCanShowAlternateBouncer()
bouncerRepository.setAlternateBouncerUIAvailable(false)
assertFalse(underTest.canShowAlternateBouncerForFingerprint())
}
@Test
fun canShowAlternateBouncerForFingerprint_noFingerprintsEnrolled() {
givenCanShowAlternateBouncer()
biometricRepository.setFingerprintEnrolled(false)
assertFalse(underTest.canShowAlternateBouncerForFingerprint())
}
@Test
fun canShowAlternateBouncerForFingerprint_strongBiometricNotAllowed() {
givenCanShowAlternateBouncer()
biometricRepository.setStrongBiometricAllowed(false)
assertFalse(underTest.canShowAlternateBouncerForFingerprint())
}
@Test
fun canShowAlternateBouncerForFingerprint_devicePolicyDoesNotAllowFingerprint() {
givenCanShowAlternateBouncer()
biometricRepository.setFingerprintEnabledByDevicePolicy(false)
assertFalse(underTest.canShowAlternateBouncerForFingerprint())
}
@Test
fun show_whenCanShow() {
givenCanShowAlternateBouncer()
assertTrue(underTest.show())
assertTrue(bouncerRepository.isAlternateBouncerVisible.value)
}
@Test
fun show_whenCannotShow() {
givenCannotShowAlternateBouncer()
assertFalse(underTest.show())
assertFalse(bouncerRepository.isAlternateBouncerVisible.value)
}
@Test
fun hide_wasPreviouslyShowing() {
bouncerRepository.setAlternateVisible(true)
assertTrue(underTest.hide())
assertFalse(bouncerRepository.isAlternateBouncerVisible.value)
}
@Test
fun hide_wasNotPreviouslyShowing() {
bouncerRepository.setAlternateVisible(false)
assertFalse(underTest.hide())
assertFalse(bouncerRepository.isAlternateBouncerVisible.value)
}
private fun givenCanShowAlternateBouncer() {
bouncerRepository.setAlternateBouncerUIAvailable(true)
biometricRepository.setFingerprintEnrolled(true)
biometricRepository.setStrongBiometricAllowed(true)
biometricRepository.setFingerprintEnabledByDevicePolicy(true)
}
private fun givenCannotShowAlternateBouncer() {
biometricRepository.setFingerprintEnrolled(false)
}
}

View File

@@ -103,7 +103,6 @@ import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.fragments.FragmentHostManager;
import com.android.systemui.fragments.FragmentService;
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor;
import com.android.systemui.keyguard.domain.interactor.KeyguardBottomAreaInteractor;
import com.android.systemui.keyguard.ui.viewmodel.KeyguardBottomAreaViewModel;
import com.android.systemui.media.controls.pipeline.MediaDataManager;
@@ -286,7 +285,6 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase {
@Mock private ViewTreeObserver mViewTreeObserver;
@Mock private KeyguardBottomAreaViewModel mKeyguardBottomAreaViewModel;
@Mock private KeyguardBottomAreaInteractor mKeyguardBottomAreaInteractor;
@Mock private AlternateBouncerInteractor mAlternateBouncerInteractor;
@Mock private MotionEvent mDownMotionEvent;
@Captor
private ArgumentCaptor<NotificationStackScrollLayout.OnEmptySpaceClickListener>
@@ -502,7 +500,6 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase {
systemClock,
mKeyguardBottomAreaViewModel,
mKeyguardBottomAreaInteractor,
mAlternateBouncerInteractor,
mDumpManager);
mNotificationPanelViewController.initDependencies(
mCentralSurfaces,

View File

@@ -30,7 +30,6 @@ import com.android.systemui.classifier.FalsingCollectorFake
import com.android.systemui.dock.DockManager
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.keyguard.KeyguardUnlockAnimationController
import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor
import com.android.systemui.keyguard.ui.viewmodel.KeyguardBouncerViewModel
import com.android.systemui.shade.NotificationShadeWindowView.InteractionEventHandler
import com.android.systemui.statusbar.LockscreenShadeTransitionController
@@ -98,8 +97,6 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() {
private lateinit var pulsingGestureListener: PulsingGestureListener
@Mock
private lateinit var notificationInsetsController: NotificationInsetsController
@Mock
private lateinit var alternateBouncerInteractor: AlternateBouncerInteractor
@Mock lateinit var keyguardBouncerComponentFactory: KeyguardBouncerComponent.Factory
@Mock lateinit var keyguardBouncerContainer: ViewGroup
@Mock lateinit var keyguardBouncerComponent: KeyguardBouncerComponent
@@ -135,8 +132,7 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() {
pulsingGestureListener,
featureFlags,
keyguardBouncerViewModel,
keyguardBouncerComponentFactory,
alternateBouncerInteractor
keyguardBouncerComponentFactory
)
underTest.setupExpandedStatusBar()

View File

@@ -40,7 +40,6 @@ import com.android.systemui.classifier.FalsingCollectorFake;
import com.android.systemui.dock.DockManager;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor;
import com.android.systemui.keyguard.ui.viewmodel.KeyguardBouncerViewModel;
import com.android.systemui.statusbar.DragDownHelper;
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
@@ -94,7 +93,6 @@ public class NotificationShadeWindowViewTest extends SysuiTestCase {
@Mock private KeyguardBouncerViewModel mKeyguardBouncerViewModel;
@Mock private KeyguardBouncerComponent.Factory mKeyguardBouncerComponentFactory;
@Mock private NotificationInsetsController mNotificationInsetsController;
@Mock private AlternateBouncerInteractor mAlternateBouncerInteractor;
@Captor private ArgumentCaptor<NotificationShadeWindowView.InteractionEventHandler>
mInteractionEventHandlerCaptor;
@@ -134,8 +132,7 @@ public class NotificationShadeWindowViewTest extends SysuiTestCase {
mPulsingGestureListener,
mFeatureFlags,
mKeyguardBouncerViewModel,
mKeyguardBouncerComponentFactory,
mAlternateBouncerInteractor
mKeyguardBouncerComponentFactory
);
mController.setupExpandedStatusBar();
mController.setDragDownHelper(mDragDownHelper);
@@ -158,7 +155,7 @@ public class NotificationShadeWindowViewTest extends SysuiTestCase {
// WHEN showing alt auth, not dozing, drag down helper doesn't want to intercept
when(mStatusBarStateController.isDozing()).thenReturn(false);
when(mAlternateBouncerInteractor.isVisibleState()).thenReturn(true);
when(mStatusBarKeyguardViewManager.isShowingAlternateBouncer()).thenReturn(true);
when(mDragDownHelper.onInterceptTouchEvent(any())).thenReturn(false);
// THEN we should intercept touch
@@ -171,7 +168,7 @@ public class NotificationShadeWindowViewTest extends SysuiTestCase {
// WHEN not showing alt auth, not dozing, drag down helper doesn't want to intercept
when(mStatusBarStateController.isDozing()).thenReturn(false);
when(mAlternateBouncerInteractor.isVisibleState()).thenReturn(false);
when(mStatusBarKeyguardViewManager.isShowingAlternateBouncer()).thenReturn(false);
when(mDragDownHelper.onInterceptTouchEvent(any())).thenReturn(false);
// THEN we shouldn't intercept touch
@@ -184,7 +181,7 @@ public class NotificationShadeWindowViewTest extends SysuiTestCase {
// WHEN showing alt auth, not dozing, drag down helper doesn't want to intercept
when(mStatusBarStateController.isDozing()).thenReturn(false);
when(mAlternateBouncerInteractor.isVisibleState()).thenReturn(true);
when(mStatusBarKeyguardViewManager.isShowingAlternateBouncer()).thenReturn(true);
when(mDragDownHelper.onInterceptTouchEvent(any())).thenReturn(false);
// THEN we should handle the touch

View File

@@ -99,7 +99,6 @@ import com.android.systemui.dock.DockManager;
import com.android.systemui.keyguard.KeyguardIndication;
import com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController;
import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
@@ -178,8 +177,6 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase {
@Mock
private FaceHelpMessageDeferral mFaceHelpMessageDeferral;
@Mock
private AlternateBouncerInteractor mAlternateBouncerInteractor;
@Mock
private ScreenLifecycle mScreenLifecycle;
@Mock
private AuthController mAuthController;
@@ -276,8 +273,7 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase {
mUserManager, mExecutor, mExecutor, mFalsingManager,
mAuthController, mLockPatternUtils, mScreenLifecycle,
mKeyguardBypassController, mAccessibilityManager,
mFaceHelpMessageDeferral, mock(KeyguardLogger.class),
mAlternateBouncerInteractor);
mFaceHelpMessageDeferral, mock(KeyguardLogger.class));
mController.init();
mController.setIndicationArea(mIndicationArea);
verify(mStatusBarStateController).addCallback(mStatusBarStateListenerCaptor.capture());

View File

@@ -86,6 +86,8 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase {
@Mock
private KeyguardViewMediator mKeyguardViewMediator;
@Mock
private ScrimController mScrimController;
@Mock
private BiometricUnlockController.BiometricModeListener mBiometricModeListener;
@Mock
private KeyguardStateController mKeyguardStateController;
@@ -131,7 +133,7 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase {
when(mVibratorHelper.hasVibrator()).thenReturn(true);
mDependency.injectTestDependency(NotificationMediaManager.class, mMediaManager);
mBiometricUnlockController = new BiometricUnlockController(mDozeScrimController,
mKeyguardViewMediator,
mKeyguardViewMediator, mScrimController,
mNotificationShadeWindowController, mKeyguardStateController, mHandler,
mUpdateMonitor, res.getResources(), mKeyguardBypassController,
mMetricsLogger, mDumpManager, mPowerManager, mLogger,

View File

@@ -106,7 +106,6 @@ import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor;
import com.android.systemui.keyguard.ui.viewmodel.LightRevealScrimViewModel;
import com.android.systemui.navigationbar.NavigationBarController;
import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
@@ -294,7 +293,6 @@ public class CentralSurfacesImplTest extends SysuiTestCase {
@Mock private WiredChargingRippleController mWiredChargingRippleController;
@Mock private Lazy<CameraLauncher> mCameraLauncherLazy;
@Mock private CameraLauncher mCameraLauncher;
@Mock private AlternateBouncerInteractor mAlternateBouncerInteractor;
/**
* The process of registering/unregistering a predictive back callback requires a
* ViewRootImpl, which is present IRL, but may be missing during a Mockito unit test.
@@ -502,9 +500,7 @@ public class CentralSurfacesImplTest extends SysuiTestCase {
mWiredChargingRippleController,
mDreamManager,
mCameraLauncherLazy,
() -> mLightRevealScrimViewModel,
mAlternateBouncerInteractor
) {
() -> mLightRevealScrimViewModel) {
@Override
protected ViewRootImpl getViewRootImpl() {
return mViewRootImpl;

View File

@@ -56,7 +56,6 @@ import com.android.systemui.dreams.DreamOverlayStateController;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.keyguard.data.BouncerView;
import com.android.systemui.keyguard.data.BouncerViewDelegate;
import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor;
import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerCallbackInteractor;
import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor;
import com.android.systemui.navigationbar.NavigationModeController;
@@ -106,6 +105,7 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
@Mock private KeyguardBouncer.Factory mKeyguardBouncerFactory;
@Mock private KeyguardMessageAreaController.Factory mKeyguardMessageAreaFactory;
@Mock private KeyguardMessageAreaController mKeyguardMessageAreaController;
@Mock private StatusBarKeyguardViewManager.AlternateBouncer mAlternateBouncer;
@Mock private KeyguardMessageArea mKeyguardMessageArea;
@Mock private ShadeController mShadeController;
@Mock private SysUIUnfoldComponent mSysUiUnfoldComponent;
@@ -115,7 +115,6 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
@Mock private KeyguardSecurityModel mKeyguardSecurityModel;
@Mock private PrimaryBouncerCallbackInteractor mPrimaryBouncerCallbackInteractor;
@Mock private PrimaryBouncerInteractor mPrimaryBouncerInteractor;
@Mock private AlternateBouncerInteractor mAlternateBouncerInteractor;
@Mock private BouncerView mBouncerView;
@Mock private BouncerViewDelegate mBouncerViewDelegate;
@@ -164,8 +163,7 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
mFeatureFlags,
mPrimaryBouncerCallbackInteractor,
mPrimaryBouncerInteractor,
mBouncerView,
mAlternateBouncerInteractor) {
mBouncerView) {
@Override
public ViewRootImpl getViewRootImpl() {
return mViewRootImpl;
@@ -436,35 +434,37 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
@Test
public void testShowing_whenAlternateAuthShowing() {
mStatusBarKeyguardViewManager.setAlternateBouncer(mAlternateBouncer);
when(mPrimaryBouncerInteractor.isFullyShowing()).thenReturn(false);
when(mAlternateBouncerInteractor.isVisibleState()).thenReturn(true);
when(mAlternateBouncer.isShowingAlternateBouncer()).thenReturn(true);
assertTrue(
"Is showing not accurate when alternative bouncer is visible",
"Is showing not accurate when alternative auth showing",
mStatusBarKeyguardViewManager.isBouncerShowing());
}
@Test
public void testWillBeShowing_whenAlternateAuthShowing() {
mStatusBarKeyguardViewManager.setAlternateBouncer(mAlternateBouncer);
when(mPrimaryBouncerInteractor.isFullyShowing()).thenReturn(false);
when(mAlternateBouncerInteractor.isVisibleState()).thenReturn(true);
when(mAlternateBouncer.isShowingAlternateBouncer()).thenReturn(true);
assertTrue(
"Is or will be showing not accurate when alternate bouncer is visible",
"Is or will be showing not accurate when alternative auth showing",
mStatusBarKeyguardViewManager.primaryBouncerIsOrWillBeShowing());
}
@Test
public void testHideAlternateBouncer_onShowPrimaryBouncer() {
reset(mAlternateBouncerInteractor);
// GIVEN alt bouncer is showing
public void testHideAlternateBouncer_onShowBouncer() {
// GIVEN alt auth is showing
mStatusBarKeyguardViewManager.setAlternateBouncer(mAlternateBouncer);
when(mPrimaryBouncerInteractor.isFullyShowing()).thenReturn(false);
when(mAlternateBouncerInteractor.isVisibleState()).thenReturn(true);
when(mAlternateBouncer.isShowingAlternateBouncer()).thenReturn(true);
reset(mAlternateBouncer);
// WHEN showBouncer is called
mStatusBarKeyguardViewManager.showPrimaryBouncer(true);
// THEN alt bouncer should be hidden
verify(mAlternateBouncerInteractor).hide();
verify(mAlternateBouncer).hideAlternateBouncer();
}
@Test
@@ -479,9 +479,11 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
@Test
public void testShowAltAuth_unlockingWithBiometricNotAllowed() {
// GIVEN cannot use alternate bouncer
// GIVEN alt auth exists, unlocking with biometric isn't allowed
mStatusBarKeyguardViewManager.setAlternateBouncer(mAlternateBouncer);
when(mPrimaryBouncerInteractor.isFullyShowing()).thenReturn(false);
when(mAlternateBouncerInteractor.canShowAlternateBouncerForFingerprint()).thenReturn(false);
when(mKeyguardUpdateMonitor.isUnlockingWithBiometricAllowed(anyBoolean()))
.thenReturn(false);
// WHEN showGenericBouncer is called
final boolean scrimmed = true;
@@ -489,19 +491,21 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
// THEN regular bouncer is shown
verify(mPrimaryBouncerInteractor).show(eq(scrimmed));
verify(mAlternateBouncer, never()).showAlternateBouncer();
}
@Test
public void testShowAlternateBouncer_unlockingWithBiometricAllowed() {
// GIVEN will show alternate bouncer
// GIVEN alt auth exists, unlocking with biometric is allowed
mStatusBarKeyguardViewManager.setAlternateBouncer(mAlternateBouncer);
when(mPrimaryBouncerInteractor.isFullyShowing()).thenReturn(false);
when(mAlternateBouncerInteractor.show()).thenReturn(true);
when(mKeyguardUpdateMonitor.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(true);
// WHEN showGenericBouncer is called
mStatusBarKeyguardViewManager.showBouncer(true);
// THEN alt auth bouncer is shown
verify(mAlternateBouncerInteractor).show();
verify(mAlternateBouncer).showAlternateBouncer();
verify(mPrimaryBouncerInteractor, never()).show(anyBoolean());
}
@@ -609,8 +613,7 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
mFeatureFlags,
mPrimaryBouncerCallbackInteractor,
mPrimaryBouncerInteractor,
mBouncerView,
mAlternateBouncerInteractor) {
mBouncerView) {
@Override
public ViewRootImpl getViewRootImpl() {
return mViewRootImpl;

View File

@@ -56,7 +56,6 @@ import com.android.systemui.dreams.DreamOverlayStateController;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.keyguard.data.BouncerView;
import com.android.systemui.keyguard.data.BouncerViewDelegate;
import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor;
import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerCallbackInteractor;
import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor;
import com.android.systemui.navigationbar.NavigationModeController;
@@ -110,6 +109,7 @@ public class StatusBarKeyguardViewManagerTest_Old extends SysuiTestCase {
@Mock private KeyguardMessageAreaController.Factory mKeyguardMessageAreaFactory;
@Mock private KeyguardMessageAreaController mKeyguardMessageAreaController;
@Mock private KeyguardBouncer mPrimaryBouncer;
@Mock private StatusBarKeyguardViewManager.AlternateBouncer mAlternateBouncer;
@Mock private KeyguardMessageArea mKeyguardMessageArea;
@Mock private ShadeController mShadeController;
@Mock private SysUIUnfoldComponent mSysUiUnfoldComponent;
@@ -119,7 +119,6 @@ public class StatusBarKeyguardViewManagerTest_Old extends SysuiTestCase {
@Mock private KeyguardSecurityModel mKeyguardSecurityModel;
@Mock private PrimaryBouncerCallbackInteractor mPrimaryBouncerCallbackInteractor;
@Mock private PrimaryBouncerInteractor mPrimaryBouncerInteractor;
@Mock private AlternateBouncerInteractor mAlternateBouncerInteractor;
@Mock private BouncerView mBouncerView;
@Mock private BouncerViewDelegate mBouncerViewDelegate;
@@ -170,8 +169,7 @@ public class StatusBarKeyguardViewManagerTest_Old extends SysuiTestCase {
mFeatureFlags,
mPrimaryBouncerCallbackInteractor,
mPrimaryBouncerInteractor,
mBouncerView,
mAlternateBouncerInteractor) {
mBouncerView) {
@Override
public ViewRootImpl getViewRootImpl() {
return mViewRootImpl;
@@ -440,6 +438,41 @@ public class StatusBarKeyguardViewManagerTest_Old extends SysuiTestCase {
verify(cancelAction, never()).run();
}
@Test
public void testShowing_whenAlternateAuthShowing() {
mStatusBarKeyguardViewManager.setAlternateBouncer(mAlternateBouncer);
when(mPrimaryBouncer.isShowing()).thenReturn(false);
when(mAlternateBouncer.isShowingAlternateBouncer()).thenReturn(true);
assertTrue(
"Is showing not accurate when alternative auth showing",
mStatusBarKeyguardViewManager.isBouncerShowing());
}
@Test
public void testWillBeShowing_whenAlternateAuthShowing() {
mStatusBarKeyguardViewManager.setAlternateBouncer(mAlternateBouncer);
when(mPrimaryBouncer.isShowing()).thenReturn(false);
when(mAlternateBouncer.isShowingAlternateBouncer()).thenReturn(true);
assertTrue(
"Is or will be showing not accurate when alternative auth showing",
mStatusBarKeyguardViewManager.primaryBouncerIsOrWillBeShowing());
}
@Test
public void testHideAlternateBouncer_onShowBouncer() {
// GIVEN alt auth is showing
mStatusBarKeyguardViewManager.setAlternateBouncer(mAlternateBouncer);
when(mPrimaryBouncer.isShowing()).thenReturn(false);
when(mAlternateBouncer.isShowingAlternateBouncer()).thenReturn(true);
reset(mAlternateBouncer);
// WHEN showBouncer is called
mStatusBarKeyguardViewManager.showPrimaryBouncer(true);
// THEN alt bouncer should be hidden
verify(mAlternateBouncer).hideAlternateBouncer();
}
@Test
public void testBouncerIsOrWillBeShowing_whenBouncerIsInTransit() {
when(mPrimaryBouncer.isShowing()).thenReturn(false);
@@ -450,6 +483,38 @@ public class StatusBarKeyguardViewManagerTest_Old extends SysuiTestCase {
mStatusBarKeyguardViewManager.primaryBouncerIsOrWillBeShowing());
}
@Test
public void testShowAltAuth_unlockingWithBiometricNotAllowed() {
// GIVEN alt auth exists, unlocking with biometric isn't allowed
mStatusBarKeyguardViewManager.setAlternateBouncer(mAlternateBouncer);
when(mPrimaryBouncer.isShowing()).thenReturn(false);
when(mKeyguardUpdateMonitor.isUnlockingWithBiometricAllowed(anyBoolean()))
.thenReturn(false);
// WHEN showGenericBouncer is called
final boolean scrimmed = true;
mStatusBarKeyguardViewManager.showBouncer(scrimmed);
// THEN regular bouncer is shown
verify(mPrimaryBouncer).show(anyBoolean(), eq(scrimmed));
verify(mAlternateBouncer, never()).showAlternateBouncer();
}
@Test
public void testShowAlternateBouncer_unlockingWithBiometricAllowed() {
// GIVEN alt auth exists, unlocking with biometric is allowed
mStatusBarKeyguardViewManager.setAlternateBouncer(mAlternateBouncer);
when(mPrimaryBouncer.isShowing()).thenReturn(false);
when(mKeyguardUpdateMonitor.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(true);
// WHEN showGenericBouncer is called
mStatusBarKeyguardViewManager.showBouncer(true);
// THEN alt auth bouncer is shown
verify(mAlternateBouncer).showAlternateBouncer();
verify(mPrimaryBouncer, never()).show(anyBoolean(), anyBoolean());
}
@Test
public void testUpdateResources_delegatesToBouncer() {
mStatusBarKeyguardViewManager.updateResources();
@@ -563,8 +628,7 @@ public class StatusBarKeyguardViewManagerTest_Old extends SysuiTestCase {
mFeatureFlags,
mPrimaryBouncerCallbackInteractor,
mPrimaryBouncerInteractor,
mBouncerView,
mAlternateBouncerInteractor) {
mBouncerView) {
@Override
public ViewRootImpl getViewRootImpl() {
return mViewRootImpl;

View File

@@ -1,47 +0,0 @@
/*
* Copyright (C) 2022 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.systemui.keyguard.data.repository
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
class FakeBiometricRepository : BiometricRepository {
private val _isFingerprintEnrolled = MutableStateFlow<Boolean>(false)
override val isFingerprintEnrolled: StateFlow<Boolean> = _isFingerprintEnrolled.asStateFlow()
private val _isStrongBiometricAllowed = MutableStateFlow(false)
override val isStrongBiometricAllowed = _isStrongBiometricAllowed.asStateFlow()
private val _isFingerprintEnabledByDevicePolicy = MutableStateFlow(false)
override val isFingerprintEnabledByDevicePolicy =
_isFingerprintEnabledByDevicePolicy.asStateFlow()
fun setFingerprintEnrolled(isFingerprintEnrolled: Boolean) {
_isFingerprintEnrolled.value = isFingerprintEnrolled
}
fun setStrongBiometricAllowed(isStrongBiometricAllowed: Boolean) {
_isStrongBiometricAllowed.value = isStrongBiometricAllowed
}
fun setFingerprintEnabledByDevicePolicy(isFingerprintEnabledByDevicePolicy: Boolean) {
_isFingerprintEnabledByDevicePolicy.value = isFingerprintEnabledByDevicePolicy
}
}