diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java index 12fa401d7fea9..d32219a9817f8 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java @@ -336,6 +336,11 @@ public class KeyguardHostViewController extends ViewController mKeyguardSecurityContainerController.onStartingToHide(); } + /** Called when bouncer visibility changes. */ + public void onBouncerVisibilityChanged(@View.Visibility int visibility) { + mKeyguardSecurityContainerController.onBouncerVisibilityChanged(visibility); + } + public boolean hasDismissActions() { return mDismissAction != null || mCancelAction != null; } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java index 61e2624406079..5ee659be6dd28 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java @@ -17,6 +17,7 @@ package com.android.keyguard; import static android.app.StatusBarManager.SESSION_KEYGUARD; +import static android.hardware.biometrics.BiometricSourceType.FINGERPRINT; import static com.android.keyguard.KeyguardSecurityContainer.BOUNCER_DISMISS_BIOMETRIC; import static com.android.keyguard.KeyguardSecurityContainer.BOUNCER_DISMISS_EXTENDED_ACCESS; @@ -32,11 +33,13 @@ import android.app.admin.DevicePolicyManager; import android.content.Intent; import android.content.res.ColorStateList; import android.content.res.Configuration; +import android.hardware.biometrics.BiometricSourceType; import android.metrics.LogMaker; import android.os.UserHandle; import android.util.Log; import android.util.Slog; import android.view.MotionEvent; +import android.view.View; import androidx.annotation.Nullable; @@ -55,6 +58,7 @@ import com.android.keyguard.dagger.KeyguardBouncerScope; import com.android.settingslib.utils.ThreadUtils; import com.android.systemui.Gefingerpoken; import com.android.systemui.R; +import com.android.systemui.biometrics.SidefpsController; import com.android.systemui.classifier.FalsingCollector; import com.android.systemui.flags.FeatureFlags; import com.android.systemui.flags.Flags; @@ -67,6 +71,8 @@ import com.android.systemui.statusbar.policy.UserSwitcherController; import com.android.systemui.util.ViewController; import com.android.systemui.util.settings.GlobalSettings; +import java.util.Optional; + import javax.inject.Inject; /** Controller for {@link KeyguardSecurityContainer} */ @@ -93,6 +99,7 @@ public class KeyguardSecurityContainerController extends ViewController mSidefpsController; private int mLastOrientation = Configuration.ORIENTATION_UNDEFINED; @@ -236,13 +243,27 @@ public class KeyguardSecurityContainerController extends ViewController sidefpsController) { super(view); mLockPatternUtils = lockPatternUtils; mUpdateMonitor = keyguardUpdateMonitor; @@ -280,6 +302,7 @@ public class KeyguardSecurityContainerController extends ViewController mSidefpsController; @Inject Factory(KeyguardSecurityContainer view, @@ -673,7 +723,8 @@ public class KeyguardSecurityContainerController extends ViewController sidefpsController) { mView = view; mAdminSecondaryLockScreenControllerFactory = adminSecondaryLockScreenControllerFactory; mLockPatternUtils = lockPatternUtils; @@ -690,6 +741,7 @@ public class KeyguardSecurityContainerController extends ViewController providesOptionalSidefpsController( + @Nullable FingerprintManager fingerprintManager, + Provider sidefpsControllerProvider) { + if (!hasSideFpsSensor(fingerprintManager)) { + return Optional.empty(); + } + return Optional.of(sidefpsControllerProvider.get()); + } } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/SidefpsController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/SidefpsController.kt index 04e2dccda5284..bbffb73b7503d 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/SidefpsController.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/SidefpsController.kt @@ -34,16 +34,16 @@ import android.hardware.fingerprint.ISidefpsController import android.os.Handler import android.util.Log import android.util.RotationUtils -import android.view.View.AccessibilityDelegate -import android.view.accessibility.AccessibilityEvent import android.view.Display import android.view.Gravity import android.view.LayoutInflater import android.view.Surface import android.view.View +import android.view.View.AccessibilityDelegate import android.view.ViewPropertyAnimator import android.view.WindowInsets import android.view.WindowManager +import android.view.accessibility.AccessibilityEvent import androidx.annotation.RawRes import com.airbnb.lottie.LottieAnimationView import com.airbnb.lottie.LottieProperty @@ -70,13 +70,12 @@ class SidefpsController @Inject constructor( private val activityTaskManager: ActivityTaskManager, overviewProxyService: OverviewProxyService, displayManager: DisplayManager, - @Main mainExecutor: DelayableExecutor, + @Main private val mainExecutor: DelayableExecutor, @Main private val handler: Handler ) { @VisibleForTesting val sensorProps: FingerprintSensorPropertiesInternal = fingerprintManager - ?.sensorPropertiesInternal - ?.firstOrNull { it.isAnySidefpsType } + ?.sideFpsSensorProperties ?: throw IllegalStateException("no side fingerprint sensor") @VisibleForTesting @@ -135,25 +134,34 @@ class SidefpsController @Inject constructor( } init { - fingerprintManager?.setSidefpsController(object : ISidefpsController.Stub() { - override fun show( - sensorId: Int, - @BiometricOverlayConstants.ShowReason reason: Int - ) = if (reason.isReasonToShow(activityTaskManager)) doShow() else hide(sensorId) + fingerprintManager?.setSidefpsController( + object : ISidefpsController.Stub() { + override fun show( + sensorId: Int, + @BiometricOverlayConstants.ShowReason reason: Int + ) = if (reason.isReasonToShow(activityTaskManager)) show() else hide() - private fun doShow() = mainExecutor.execute { - if (overlayView == null) { - createOverlayForDisplay() - } else { - Log.v(TAG, "overlay already shown") - } - } - - override fun hide(sensorId: Int) = mainExecutor.execute { overlayView = null } - }) + override fun hide(sensorId: Int) = hide() + }) overviewProxyService.addCallback(overviewProxyListener) } + /** Shows the side fps overlay if not already shown. */ + fun show() { + mainExecutor.execute { + if (overlayView == null) { + createOverlayForDisplay() + } else { + Log.v(TAG, "overlay already shown") + } + } + } + + /** Hides the fps overlay if shown. */ + fun hide() { + mainExecutor.execute { overlayView = null } + } + private fun onOrientationChanged() { if (overlayView != null) { createOverlayForDisplay() @@ -266,6 +274,12 @@ class SidefpsController @Inject constructor( } } +private val FingerprintManager?.sideFpsSensorProperties: FingerprintSensorPropertiesInternal? + get() = this?.sensorPropertiesInternal?.firstOrNull { it.isAnySidefpsType } + +/** Returns [True] when the device has a side fingerprint sensor. */ +fun FingerprintManager?.hasSideFpsSensor(): Boolean = this?.sideFpsSensorProperties != null + @BiometricOverlayConstants.ShowReason private fun Int.isReasonToShow(activityTaskManager: ActivityTaskManager): Boolean = when (this) { REASON_AUTH_KEYGUARD -> false diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java index ed3d4ad8ad5d8..4ddaffcb57618 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java @@ -266,6 +266,9 @@ public class KeyguardBouncer { private void setVisibility(@View.Visibility int visibility) { mContainer.setVisibility(visibility); + if (mKeyguardViewController != null) { + mKeyguardViewController.onBouncerVisibilityChanged(visibility); + } dispatchVisibilityChanged(); } @@ -645,7 +648,7 @@ public class KeyguardBouncer { /** * Invoked when the bouncer expansion reaches {@link KeyguardBouncer#EXPANSION_VISIBLE}. * This is NOT called each time the bouncer is shown, but rather only when the fully - * shown amount has changed based on the panel expansion. The bouncer is visibility + * shown amount has changed based on the panel expansion. The bouncer's visibility * can still change when the expansion amount hasn't changed. * See {@link KeyguardBouncer#isShowing()} for the checks for the bouncer showing state. */ diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardHostViewControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardHostViewControllerTest.java index ac1a83c269e0e..4021652295c10 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardHostViewControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardHostViewControllerTest.java @@ -20,6 +20,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -31,6 +32,7 @@ import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.testing.TestableResources; import android.view.Gravity; +import android.view.View; import android.view.ViewGroup; import android.widget.FrameLayout; @@ -42,6 +44,7 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; @@ -103,6 +106,17 @@ public class KeyguardHostViewControllerTest extends SysuiTestCase { verify(mKeyguardSecurityContainerController).onStartingToHide(); } + @Test + public void onBouncerVisible_propagatesToKeyguardSecurityContainerController() { + mKeyguardHostViewController.onBouncerVisibilityChanged(ViewGroup.VISIBLE); + mKeyguardHostViewController.onBouncerVisibilityChanged(ViewGroup.INVISIBLE); + + InOrder order = inOrder(mKeyguardSecurityContainerController); + order.verify(mKeyguardSecurityContainerController).onBouncerVisibilityChanged(View.VISIBLE); + order.verify(mKeyguardSecurityContainerController).onBouncerVisibilityChanged( + View.INVISIBLE); + } + @Test public void testGravityReappliedOnConfigurationChange() { FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams( diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java index bc351427310dd..68e49c0a1d4b6 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java @@ -25,17 +25,21 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.reset; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.content.res.Configuration; import android.content.res.Resources; +import android.hardware.biometrics.BiometricSourceType; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.view.MotionEvent; +import android.view.View; import android.view.WindowInsetsController; import androidx.test.filters.SmallTest; @@ -46,6 +50,7 @@ import com.android.internal.widget.LockPatternUtils; import com.android.keyguard.KeyguardSecurityModel.SecurityMode; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; +import com.android.systemui.biometrics.SidefpsController; import com.android.systemui.classifier.FalsingCollector; import com.android.systemui.flags.FeatureFlags; import com.android.systemui.log.SessionTracker; @@ -59,10 +64,14 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; import org.mockito.Mock; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; +import java.util.Optional; + @SmallTest @RunWith(AndroidTestingRunner.class) @TestableLooper.RunWithLooper() @@ -124,6 +133,14 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase { private SessionTracker mSessionTracker; @Mock private KeyguardViewController mKeyguardViewController; + @Mock + private SidefpsController mSidefpsController; + @Mock + private KeyguardPasswordViewController mKeyguardPasswordViewControllerMock; + + @Captor + private ArgumentCaptor mKeyguardUpdateMonitorCallback; + private Configuration mConfiguration; private KeyguardSecurityContainerController mKeyguardSecurityContainerController; @@ -160,7 +177,7 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase { mKeyguardStateController, mKeyguardSecurityViewFlipperController, mConfigurationController, mFalsingCollector, mFalsingManager, mUserSwitcherController, mFeatureFlags, mGlobalSettings, - mSessionTracker).create(mSecurityCallback); + mSessionTracker, Optional.of(mSidefpsController)).create(mSecurityCallback); } @Test @@ -258,9 +275,7 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase { @Test public void showSecurityScreen_twoHandedMode_flagEnabled_noOneHandedMode() { when(mResources.getBoolean(R.bool.can_use_one_handed_bouncer)).thenReturn(true); - when(mKeyguardSecurityViewFlipperController.getSecurityView( - eq(SecurityMode.Password), any(KeyguardSecurityCallback.class))) - .thenReturn((KeyguardInputViewController) mKeyguardPasswordViewController); + setupGetSecurityView(); mKeyguardSecurityContainerController.showSecurityScreen(SecurityMode.Password); verify(mView).initMode(MODE_DEFAULT, mGlobalSettings, mFalsingManager, @@ -276,4 +291,126 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase { verify(mUserSwitcherController) .removeUserSwitchCallback(any(UserSwitcherController.UserSwitchCallback.class)); } + + @Test + public void onBouncerVisibilityChanged_allConditionsGood_sideFpsHintShown() { + setupConditionsToEnableSideFpsHint(); + reset(mSidefpsController); + + mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE); + + verify(mSidefpsController).show(); + verify(mSidefpsController, never()).hide(); + } + + @Test + public void onBouncerVisibilityChanged_fpsSensorNotRunning_sideFpsHintHidden() { + setupConditionsToEnableSideFpsHint(); + setFingerprintDetectionRunning(false); + reset(mSidefpsController); + + mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE); + + verify(mSidefpsController).hide(); + verify(mSidefpsController, never()).show(); + } + + @Test + public void onBouncerVisibilityChanged_withoutSidedSecurity_sideFpsHintHidden() { + setupConditionsToEnableSideFpsHint(); + setSidedSecurityMode(false); + reset(mSidefpsController); + + mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE); + + verify(mSidefpsController).hide(); + verify(mSidefpsController, never()).show(); + } + + @Test + public void onBouncerVisibilityChanged_needsStrongAuth_sideFpsHintHidden() { + setupConditionsToEnableSideFpsHint(); + setNeedsStrongAuth(true); + reset(mSidefpsController); + + mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE); + + verify(mSidefpsController).hide(); + verify(mSidefpsController, never()).show(); + } + + @Test + public void onBouncerVisibilityChanged_sideFpsHintShown_sideFpsHintHidden() { + setupGetSecurityView(); + setupConditionsToEnableSideFpsHint(); + mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE); + verify(mSidefpsController, atLeastOnce()).show(); + reset(mSidefpsController); + + mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.INVISIBLE); + + verify(mSidefpsController).hide(); + verify(mSidefpsController, never()).show(); + } + + @Test + public void onStartingToHide_sideFpsHintShown_sideFpsHintHidden() { + setupGetSecurityView(); + setupConditionsToEnableSideFpsHint(); + mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE); + verify(mSidefpsController, atLeastOnce()).show(); + reset(mSidefpsController); + + mKeyguardSecurityContainerController.onStartingToHide(); + + verify(mSidefpsController).hide(); + verify(mSidefpsController, never()).show(); + } + + @Test + public void onPause_sideFpsHintShown_sideFpsHintHidden() { + setupGetSecurityView(); + setupConditionsToEnableSideFpsHint(); + mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE); + verify(mSidefpsController, atLeastOnce()).show(); + reset(mSidefpsController); + + mKeyguardSecurityContainerController.onPause(); + + verify(mSidefpsController).hide(); + verify(mSidefpsController, never()).show(); + } + + private void setupConditionsToEnableSideFpsHint() { + attachView(); + setSidedSecurityMode(true); + setFingerprintDetectionRunning(true); + setNeedsStrongAuth(false); + } + + private void attachView() { + mKeyguardSecurityContainerController.onViewAttached(); + verify(mKeyguardUpdateMonitor).registerCallback(mKeyguardUpdateMonitorCallback.capture()); + } + + private void setFingerprintDetectionRunning(boolean running) { + when(mKeyguardUpdateMonitor.isFingerprintDetectionRunning()).thenReturn(running); + mKeyguardUpdateMonitorCallback.getValue().onBiometricRunningStateChanged(running, + BiometricSourceType.FINGERPRINT); + } + + private void setSidedSecurityMode(boolean sided) { + when(mView.isSidedSecurityMode()).thenReturn(sided); + } + + private void setNeedsStrongAuth(boolean needed) { + when(mKeyguardUpdateMonitor.userNeedsStrongAuth()).thenReturn(needed); + mKeyguardUpdateMonitorCallback.getValue().onStrongAuthStateChanged(/* userId= */ 0); + } + + private void setupGetSecurityView() { + when(mKeyguardSecurityViewFlipperController.getSecurityView( + any(), any(KeyguardSecurityCallback.class))) + .thenReturn((KeyguardInputViewController) mKeyguardPasswordViewControllerMock); + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/SidefpsControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/SidefpsControllerTest.kt index dec2b82ed88f6..6157ccbd597a1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/SidefpsControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/SidefpsControllerTest.kt @@ -62,7 +62,6 @@ import org.mockito.ArgumentCaptor import org.mockito.ArgumentMatchers.eq import org.mockito.Captor import org.mockito.Mock -import org.mockito.Mockito.`when` import org.mockito.Mockito.any import org.mockito.Mockito.anyFloat import org.mockito.Mockito.anyInt @@ -72,6 +71,7 @@ import org.mockito.Mockito.never import org.mockito.Mockito.reset import org.mockito.Mockito.times import org.mockito.Mockito.verify +import org.mockito.Mockito.`when` as whenEver import org.mockito.junit.MockitoJUnit private const val DISPLAY_ID = 2 @@ -126,15 +126,15 @@ class SidefpsControllerTest : SysuiTestCase() { context.addMockSystemService(DisplayManager::class.java, displayManager) context.addMockSystemService(WindowManager::class.java, windowManager) - `when`(layoutInflater.inflate(R.layout.sidefps_view, null, false)).thenReturn(sidefpsView) - `when`(sidefpsView.findViewById(eq(R.id.sidefps_animation))) + whenEver(layoutInflater.inflate(R.layout.sidefps_view, null, false)).thenReturn(sidefpsView) + whenEver(sidefpsView.findViewById(eq(R.id.sidefps_animation))) .thenReturn(mock(LottieAnimationView::class.java)) with(mock(ViewPropertyAnimator::class.java)) { - `when`(sidefpsView.animate()).thenReturn(this) - `when`(alpha(anyFloat())).thenReturn(this) - `when`(setStartDelay(anyLong())).thenReturn(this) - `when`(setDuration(anyLong())).thenReturn(this) - `when`(setListener(any())).thenAnswer { + whenEver(sidefpsView.animate()).thenReturn(this) + whenEver(alpha(anyFloat())).thenReturn(this) + whenEver(setStartDelay(anyLong())).thenReturn(this) + whenEver(setDuration(anyLong())).thenReturn(this) + whenEver(setListener(any())).thenAnswer { (it.arguments[0] as Animator.AnimatorListener) .onAnimationEnd(mock(Animator::class.java)) this @@ -177,7 +177,7 @@ class SidefpsControllerTest : SysuiTestCase() { displayBounds = Rect(0, 0, displayWidth, displayHeight) var locations = listOf(sensorLocation) - `when`(fingerprintManager.sensorPropertiesInternal).thenReturn( + whenEver(fingerprintManager.sensorPropertiesInternal).thenReturn( listOf( FingerprintSensorPropertiesInternal( SENSOR_ID, @@ -196,12 +196,12 @@ class SidefpsControllerTest : SysuiTestCase() { displayInfo.initInfo() val dmGlobal = mock(DisplayManagerGlobal::class.java) val display = Display(dmGlobal, DISPLAY_ID, displayInfo, DEFAULT_DISPLAY_ADJUSTMENTS) - `when`(dmGlobal.getDisplayInfo(eq(DISPLAY_ID))).thenReturn(displayInfo) - `when`(windowManager.defaultDisplay).thenReturn(display) - `when`(windowManager.maximumWindowMetrics).thenReturn( + whenEver(dmGlobal.getDisplayInfo(eq(DISPLAY_ID))).thenReturn(displayInfo) + whenEver(windowManager.defaultDisplay).thenReturn(display) + whenEver(windowManager.maximumWindowMetrics).thenReturn( WindowMetrics(displayBounds, WindowInsets.CONSUMED) ) - `when`(windowManager.currentWindowMetrics).thenReturn( + whenEver(windowManager.currentWindowMetrics).thenReturn( WindowMetrics(displayBounds, windowInsets) ) @@ -277,13 +277,13 @@ class SidefpsControllerTest : SysuiTestCase() { @Test fun testShowsForMostSettings() = testWithDisplay { - `when`(activityTaskManager.getTasks(anyInt())).thenReturn(listOf(fpEnrollTask())) + whenEver(activityTaskManager.getTasks(anyInt())).thenReturn(listOf(fpEnrollTask())) testIgnoredFor(REASON_AUTH_SETTINGS, ignored = false) } @Test fun testIgnoredForVerySpecificSettings() = testWithDisplay { - `when`(activityTaskManager.getTasks(anyInt())).thenReturn(listOf(fpSettingsTask())) + whenEver(activityTaskManager.getTasks(anyInt())).thenReturn(listOf(fpSettingsTask())) testIgnoredFor(REASON_AUTH_SETTINGS) } @@ -424,6 +424,20 @@ class SidefpsControllerTest : SysuiTestCase() { assertThat(overlayViewParamsCaptor.value.x).isEqualTo(displayWidth - boundsWidth) assertThat(overlayViewParamsCaptor.value.y).isEqualTo(sensorLocation.sensorLocationY) } + + @Test + fun hasSideFpsSensor_withSensorProps_returnsTrue() = testWithDisplay { + // By default all those tests assume the side fps sensor is available. + + assertThat(fingerprintManager.hasSideFpsSensor()).isTrue() + } + + @Test + fun hasSideFpsSensor_withoutSensorProps_returnsFalse() { + whenEver(fingerprintManager.sensorPropertiesInternal).thenReturn(null) + + assertThat(fingerprintManager.hasSideFpsSensor()).isFalse() + } } private fun insetsForSmallNavbar() = insetsWithBottom(60) diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java index 39021d8732d37..60a3d95e24f6c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java @@ -229,6 +229,15 @@ public class KeyguardBouncerTest extends SysuiTestCase { verify(mContainer).announceForAccessibility(any()); } + @Test + public void show_notifiesKeyguardViewController() { + mBouncer.ensureView(); + + mBouncer.show(/* resetSecuritySelection= */ false); + + verify(mKeyguardHostViewController).onBouncerVisibilityChanged(View.VISIBLE); + } + @Test public void testHide_notifiesFalsingManager() { mBouncer.hide(false);