diff options
| author | 2023-02-22 04:41:42 +0000 | |
|---|---|---|
| committer | 2023-02-22 04:41:42 +0000 | |
| commit | e871505cdb42e5ae520b3e0c7ad8f60aab9b671f (patch) | |
| tree | f4f471667a5abe157b2ba0715eb094fb46bf4c90 | |
| parent | 6297c432525083eed42bd4cbc78744565d998d99 (diff) | |
| parent | a13865edf3f879c3b5c11ac6707215fae09b2d7a (diff) | |
Merge "Move sidefps bouncer logic into interactor." into tm-qpr-dev
13 files changed, 311 insertions, 268 deletions
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java index eec788b7add8..f164e7d33642 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java @@ -492,12 +492,14 @@ public class KeyguardSecurityContainer extends ConstraintLayout { case MotionEvent.ACTION_MOVE: mVelocityTracker.addMovement(event); int pointerIndex = event.findPointerIndex(mActivePointerId); - float y = event.getY(pointerIndex); - if (mLastTouchY != -1) { - float dy = y - mLastTouchY; - setTranslationY(getTranslationY() + dy * TOUCH_Y_MULTIPLIER); + if (pointerIndex != -1) { + float y = event.getY(pointerIndex); + if (mLastTouchY != -1) { + float dy = y - mLastTouchY; + setTranslationY(getTranslationY() + dy * TOUCH_Y_MULTIPLIER); + } + mLastTouchY = y; } - mLastTouchY = y; break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java index 92cbb296f270..b8bb2603fa03 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java @@ -17,7 +17,6 @@ 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; @@ -36,7 +35,6 @@ import android.content.res.ColorStateList; import android.content.res.Configuration; import android.content.res.Resources; import android.hardware.biometrics.BiometricOverlayConstants; -import android.hardware.biometrics.BiometricSourceType; import android.media.AudioManager; import android.metrics.LogMaker; import android.os.SystemClock; @@ -320,7 +318,6 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard KeyguardSecurityContainerController.this.onDensityOrFontScaleChanged(); } }; - private boolean mBouncerVisible = false; private final KeyguardUpdateMonitorCallback mKeyguardUpdateMonitorCallback = new KeyguardUpdateMonitorCallback() { @Override @@ -355,19 +352,6 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard public void onDevicePolicyManagerStateChanged() { showPrimarySecurityScreen(false); } - - @Override - public void onBiometricRunningStateChanged(boolean running, - BiometricSourceType biometricSourceType) { - if (biometricSourceType == FINGERPRINT) { - updateSideFpsVisibility(); - } - } - - @Override - public void onStrongAuthStateChanged(int userId) { - updateSideFpsVisibility(); - } }; @Inject @@ -459,35 +443,24 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard getCurrentSecurityController().onPause(); } mView.onPause(); - // It might happen that onStartingToHide is not called when the device is locked while on - // bouncer. - setBouncerVisible(false); mView.clearFocus(); } - private void updateSideFpsVisibility() { + /** + * Shows and hides the side finger print sensor animation. + * + * @param isVisible sets whether we show or hide the side fps animation + */ + public void updateSideFpsVisibility(boolean isVisible) { if (!mSideFpsController.isPresent()) { return; } - final boolean sfpsEnabled = getResources().getBoolean( - R.bool.config_show_sidefps_hint_on_bouncer); - final boolean fpsDetectionRunning = mUpdateMonitor.isFingerprintDetectionRunning(); - final boolean isUnlockingWithFpAllowed = - mUpdateMonitor.isUnlockingWithFingerprintAllowed(); - boolean toShow = mBouncerVisible && sfpsEnabled && fpsDetectionRunning - && isUnlockingWithFpAllowed; - - if (DEBUG) { - Log.d(TAG, "sideFpsToShow=" + toShow + ", " - + "mBouncerVisible=" + mBouncerVisible + ", " - + "configEnabled=" + sfpsEnabled + ", " - + "fpsDetectionRunning=" + fpsDetectionRunning + ", " - + "isUnlockingWithFpAllowed=" + isUnlockingWithFpAllowed); - } - if (toShow) { - mSideFpsController.get().show(SideFpsUiRequestSource.PRIMARY_BOUNCER, - BiometricOverlayConstants.REASON_AUTH_KEYGUARD); + if (isVisible) { + mSideFpsController.get().show( + SideFpsUiRequestSource.PRIMARY_BOUNCER, + BiometricOverlayConstants.REASON_AUTH_KEYGUARD + ); } else { mSideFpsController.get().hide(SideFpsUiRequestSource.PRIMARY_BOUNCER); } @@ -636,7 +609,6 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard SysUiStatsLog.write(SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED, state); getCurrentSecurityController().onResume(reason); - updateSideFpsVisibility(); } mView.onResume( mSecurityModel.getSecurityMode(KeyguardUpdateMonitor.getCurrentUser()), @@ -690,22 +662,15 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard if (mCurrentSecurityMode != SecurityMode.None) { getCurrentSecurityController().onStartingToHide(); } - setBouncerVisible(false); } /** Called when the bouncer changes visibility. */ - public void onBouncerVisibilityChanged(@View.Visibility int visibility) { - setBouncerVisible(visibility == View.VISIBLE); - if (visibility == View.INVISIBLE) { + public void onBouncerVisibilityChanged(boolean isVisible) { + if (!isVisible) { mView.resetScale(); } } - private void setBouncerVisible(boolean visible) { - mBouncerVisible = visible; - updateSideFpsVisibility(); - } - /** * Shows the next security screen if there is one. * @param authenticated true if the user entered the correct authentication diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepository.kt index 4331fe66a0dc..0e85347c24b0 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepository.kt @@ -60,7 +60,6 @@ interface KeyguardBouncerRepository { */ val panelExpansionAmount: StateFlow<Float> val keyguardPosition: StateFlow<Float> - val onScreenTurnedOff: StateFlow<Boolean> val isBackButtonEnabled: StateFlow<Boolean?> /** Determines if user is already unlocked */ val keyguardAuthenticated: StateFlow<Boolean?> @@ -70,6 +69,8 @@ interface KeyguardBouncerRepository { val bouncerErrorMessage: CharSequence? val alternateBouncerVisible: StateFlow<Boolean> val alternateBouncerUIAvailable: StateFlow<Boolean> + val sideFpsShowing: StateFlow<Boolean> + var lastAlternateBouncerVisibleTime: Long fun setPrimaryScrimmed(isScrimmed: Boolean) @@ -98,11 +99,11 @@ interface KeyguardBouncerRepository { fun setIsBackButtonEnabled(isBackButtonEnabled: Boolean) - fun setOnScreenTurnedOff(onScreenTurnedOff: Boolean) - fun setAlternateVisible(isVisible: Boolean) fun setAlternateBouncerUIAvailable(isAvailable: Boolean) + + fun setSideFpsShowing(isShowing: Boolean) } @SysUISingleton @@ -142,8 +143,6 @@ constructor( override val panelExpansionAmount = _panelExpansionAmount.asStateFlow() private val _keyguardPosition = MutableStateFlow(0f) override val keyguardPosition = _keyguardPosition.asStateFlow() - private val _onScreenTurnedOff = MutableStateFlow(false) - override val onScreenTurnedOff = _onScreenTurnedOff.asStateFlow() private val _isBackButtonEnabled = MutableStateFlow<Boolean?>(null) override val isBackButtonEnabled = _isBackButtonEnabled.asStateFlow() private val _keyguardAuthenticated = MutableStateFlow<Boolean?>(null) @@ -165,6 +164,8 @@ constructor( private val _alternateBouncerUIAvailable = MutableStateFlow(false) override val alternateBouncerUIAvailable: StateFlow<Boolean> = _alternateBouncerUIAvailable.asStateFlow() + private val _sideFpsShowing = MutableStateFlow(false) + override val sideFpsShowing: StateFlow<Boolean> = _sideFpsShowing.asStateFlow() init { setUpLogging() @@ -235,8 +236,8 @@ constructor( _isBackButtonEnabled.value = isBackButtonEnabled } - override fun setOnScreenTurnedOff(onScreenTurnedOff: Boolean) { - _onScreenTurnedOff.value = onScreenTurnedOff + override fun setSideFpsShowing(isShowing: Boolean) { + _sideFpsShowing.value = isShowing } /** Sets up logs for state flows. */ @@ -276,9 +277,6 @@ constructor( .map { it.toInt() } .logDiffsForTable(buffer, "", "KeyguardPosition", -1) .launchIn(applicationScope) - onScreenTurnedOff - .logDiffsForTable(buffer, "", "OnScreenTurnedOff", false) - .launchIn(applicationScope) isBackButtonEnabled .filterNotNull() .logDiffsForTable(buffer, "", "IsBackButtonEnabled", false) @@ -293,6 +291,9 @@ constructor( alternateBouncerUIAvailable .logDiffsForTable(buffer, "", "IsAlternateBouncerUIAvailable", false) .launchIn(applicationScope) + sideFpsShowing + .logDiffsForTable(buffer, "", "isSideFpsShowing", false) + .launchIn(applicationScope) } companion object { diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractor.kt index 6610983a6ff6..c709fd18298c 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractor.kt @@ -16,6 +16,7 @@ package com.android.systemui.keyguard.domain.interactor +import android.content.Context import android.content.res.ColorStateList import android.hardware.biometrics.BiometricSourceType import android.os.Handler @@ -23,9 +24,13 @@ import android.os.Trace import android.os.UserHandle import android.os.UserManager import android.view.View +import android.util.Log +import com.android.keyguard.KeyguardConstants import com.android.keyguard.KeyguardSecurityModel import com.android.keyguard.KeyguardUpdateMonitor +import com.android.keyguard.KeyguardUpdateMonitorCallback import com.android.systemui.DejankUtils +import com.android.systemui.R import com.android.systemui.classifier.FalsingCollector import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Main @@ -62,8 +67,9 @@ constructor( private val primaryBouncerCallbackInteractor: PrimaryBouncerCallbackInteractor, private val falsingCollector: FalsingCollector, private val dismissCallbackRegistry: DismissCallbackRegistry, + private val context: Context, + private val keyguardUpdateMonitor: KeyguardUpdateMonitor, keyguardBypassController: KeyguardBypassController, - keyguardUpdateMonitor: KeyguardUpdateMonitor, ) { /** Whether we want to wait for face auth. */ private val primaryBouncerFaceDelay = @@ -90,7 +96,6 @@ constructor( } val keyguardAuthenticated: Flow<Boolean> = repository.keyguardAuthenticated.filterNotNull() - val screenTurnedOff: Flow<Unit> = repository.onScreenTurnedOff.filter { it }.map {} val show: Flow<KeyguardBouncerModel> = repository.primaryBouncerShow.filterNotNull() val hide: Flow<Unit> = repository.primaryBouncerHide.filter { it }.map {} val startingToHide: Flow<Unit> = repository.primaryBouncerStartingToHide.filter { it }.map {} @@ -115,6 +120,24 @@ constructor( } /** Allow for interaction when just about fully visible */ val isInteractable: Flow<Boolean> = bouncerExpansion.map { it > 0.9 } + val sideFpsShowing: Flow<Boolean> = repository.sideFpsShowing + + init { + keyguardUpdateMonitor.registerCallback( + object : KeyguardUpdateMonitorCallback() { + override fun onBiometricRunningStateChanged( + running: Boolean, + biometricSourceType: BiometricSourceType? + ) { + updateSideFpsVisibility() + } + + override fun onStrongAuthStateChanged(userId: Int) { + updateSideFpsVisibility() + } + } + ) + } // TODO(b/243685699): Move isScrimmed logic to data layer. // TODO(b/243695312): Encapsulate all of the show logic for the bouncer. @@ -122,7 +145,6 @@ constructor( @JvmOverloads fun show(isScrimmed: Boolean) { // Reset some states as we show the bouncer. - repository.setOnScreenTurnedOff(false) repository.setKeyguardAuthenticated(null) repository.setPrimaryHide(false) repository.setPrimaryStartingToHide(false) @@ -262,11 +284,6 @@ constructor( repository.setKeyguardAuthenticated(strongAuth) } - /** Tell the bouncer the screen has turned off. */ - fun onScreenTurnedOff() { - repository.setOnScreenTurnedOff(true) - } - /** Update the position of the bouncer when showing. */ fun setKeyguardPosition(position: Float) { repository.setKeyguardPosition(position) @@ -301,6 +318,35 @@ constructor( repository.setPrimaryStartDisappearAnimation(finishRunnable) } + /** Determine whether to show the side fps animation. */ + fun updateSideFpsVisibility() { + val sfpsEnabled: Boolean = + context.resources.getBoolean(R.bool.config_show_sidefps_hint_on_bouncer) + val fpsDetectionRunning: Boolean = keyguardUpdateMonitor.isFingerprintDetectionRunning + val isUnlockingWithFpAllowed: Boolean = + keyguardUpdateMonitor.isUnlockingWithFingerprintAllowed + val bouncerVisible = repository.primaryBouncerVisible.value + val toShow = + (repository.primaryBouncerVisible.value && + sfpsEnabled && + fpsDetectionRunning && + isUnlockingWithFpAllowed && + !isAnimatingAway()) + + if (KeyguardConstants.DEBUG) { + Log.d( + TAG, + ("sideFpsToShow=$toShow\n" + + "bouncerVisible=$bouncerVisible\n" + + "configEnabled=$sfpsEnabled\n" + + "fpsDetectionRunning=$fpsDetectionRunning\n" + + "isUnlockingWithFpAllowed=$isUnlockingWithFpAllowed\n" + + "isAnimatingAway=${isAnimatingAway()}") + ) + } + repository.setSideFpsShowing(toShow) + } + /** Returns whether bouncer is fully showing. */ fun isFullyShowing(): Boolean { return (repository.primaryBouncerShowingSoon.value || @@ -344,4 +390,8 @@ constructor( DejankUtils.removeCallbacks(showRunnable) mainHandler.removeCallbacks(showRunnable) } + + companion object { + private const val TAG = "PrimaryBouncerInteractor" + } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBouncerViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBouncerViewBinder.kt index 56f911f8b1da..7db567b2a0e9 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBouncerViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBouncerViewBinder.kt @@ -34,6 +34,7 @@ import com.android.systemui.keyguard.ui.viewmodel.KeyguardBouncerViewModel import com.android.systemui.lifecycle.repeatWhenAttached import com.android.systemui.plugins.ActivityStarter import kotlinx.coroutines.awaitCancellation +import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.filter import kotlinx.coroutines.launch @@ -121,7 +122,6 @@ object KeyguardBouncerViewBinder { launch { viewModel.hide.collect { securityContainerController.cancelDismissAction() - securityContainerController.onPause() securityContainerController.reset() } } @@ -155,13 +155,18 @@ object KeyguardBouncerViewBinder { launch { viewModel.isBouncerVisible.collect { isVisible -> - val visibility = if (isVisible) View.VISIBLE else View.INVISIBLE - view.visibility = visibility - securityContainerController.onBouncerVisibilityChanged(visibility) + view.visibility = if (isVisible) View.VISIBLE else View.INVISIBLE + securityContainerController.onBouncerVisibilityChanged(isVisible) } } launch { + viewModel.isBouncerVisible + .filter { !it } + .collect { securityContainerController.onPause() } + } + + launch { viewModel.isInteractable.collect { isInteractable -> securityContainerController.setInteractable(isInteractable) } @@ -204,10 +209,14 @@ object KeyguardBouncerViewBinder { } launch { - viewModel.screenTurnedOff.collect { - if (view.visibility == View.VISIBLE) { - securityContainerController.onPause() - } + viewModel.shouldUpdateSideFps.collect { + viewModel.updateSideFpsVisibility() + } + } + + launch { + viewModel.sideFpsShowing.collect { + securityContainerController.updateSideFpsVisibility(it) } } awaitCancellation() diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModel.kt index b8b3a8e5db20..97e94d8f3232 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModel.kt @@ -24,7 +24,9 @@ import com.android.systemui.keyguard.shared.model.BouncerShowMessageModel import com.android.systemui.keyguard.shared.model.KeyguardBouncerModel import javax.inject.Inject import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.merge /** Models UI state for the lock screen bouncer; handles user input. */ class KeyguardBouncerViewModel @@ -66,8 +68,16 @@ constructor( /** Observe whether keyguard is authenticated already. */ val keyguardAuthenticated: Flow<Boolean> = interactor.keyguardAuthenticated - /** Observe whether screen is turned off. */ - val screenTurnedOff: Flow<Unit> = interactor.screenTurnedOff + /** Observe whether the side fps is showing. */ + val sideFpsShowing: Flow<Boolean> = interactor.sideFpsShowing + + /** Observe whether we should update fps is showing. */ + val shouldUpdateSideFps: Flow<Unit> = + merge( + interactor.startingToHide, + interactor.isVisible.map {}, + interactor.startingDisappearAnimation.filterNotNull().map {} + ) /** Observe whether we want to update resources. */ fun notifyUpdateResources() { @@ -84,6 +94,10 @@ constructor( interactor.onMessageShown() } + fun updateSideFpsVisibility() { + interactor.updateSideFpsVisibility() + } + /** Observe whether back button is enabled. */ fun observeOnIsBackButtonEnabled(systemUiVisibility: () -> Int): Flow<Int> { return interactor.isBackButtonEnabled.map { enabled -> diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java index 39281da09749..b0e4668e2a45 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java @@ -790,7 +790,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb @Override public void onFinishedGoingToSleep() { - mPrimaryBouncerInteractor.onScreenTurnedOff(); + mPrimaryBouncerInteractor.hide(); } @Override diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java index bffbe17fb2eb..bbc7bc92e819 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java @@ -32,11 +32,9 @@ import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.clearInvocations; 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; @@ -44,7 +42,6 @@ import static org.mockito.Mockito.when; import android.content.res.Configuration; import android.content.res.Resources; import android.hardware.biometrics.BiometricOverlayConstants; -import android.hardware.biometrics.BiometricSourceType; import android.media.AudioManager; import android.telephony.TelephonyManager; import android.testing.AndroidTestingRunner; @@ -53,7 +50,6 @@ import android.testing.TestableResources; import android.view.Gravity; import android.view.LayoutInflater; import android.view.MotionEvent; -import android.view.View; import android.view.WindowInsetsController; import android.widget.FrameLayout; @@ -96,10 +92,8 @@ import java.util.Optional; @TestableLooper.RunWithLooper() public class KeyguardSecurityContainerControllerTest extends SysuiTestCase { private static final int TARGET_USER_ID = 100; - @Rule public MockitoRule mRule = MockitoJUnit.rule(); - @Mock private KeyguardSecurityContainer mView; @Mock @@ -368,134 +362,12 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase { } @Test - public void onBouncerVisibilityChanged_allConditionsGood_sideFpsHintShown() { - setupConditionsToEnableSideFpsHint(); - reset(mSideFpsController); - - mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE); - - verify(mSideFpsController).show(SideFpsUiRequestSource.PRIMARY_BOUNCER, - BiometricOverlayConstants.REASON_AUTH_KEYGUARD); - verify(mSideFpsController, never()).hide(any()); - } - - @Test - public void onBouncerVisibilityChanged_fpsSensorNotRunning_sideFpsHintHidden() { - setupConditionsToEnableSideFpsHint(); - setFingerprintDetectionRunning(false); - reset(mSideFpsController); - - mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE); - - verify(mSideFpsController).hide(SideFpsUiRequestSource.PRIMARY_BOUNCER); - verify(mSideFpsController, never()).show(any(), anyInt()); - } - - @Test - public void onBouncerVisibilityChanged_withoutSidedSecurity_sideFpsHintHidden() { - setupConditionsToEnableSideFpsHint(); - setSideFpsHintEnabledFromResources(false); - reset(mSideFpsController); - - mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE); - - verify(mSideFpsController).hide(SideFpsUiRequestSource.PRIMARY_BOUNCER); - verify(mSideFpsController, never()).show(any(), anyInt()); - } - - @Test - public void onBouncerVisibilityChanged_unlockingWithFingerprintNotAllowed_sideFpsHintHidden() { - setupConditionsToEnableSideFpsHint(); - setUnlockingWithFingerprintAllowed(false); - reset(mSideFpsController); - - mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE); - - verify(mSideFpsController).hide(SideFpsUiRequestSource.PRIMARY_BOUNCER); - verify(mSideFpsController, never()).show(any(), anyInt()); - } - - @Test - public void onBouncerVisibilityChanged_sideFpsHintShown_sideFpsHintHidden() { - setupGetSecurityView(); - setupConditionsToEnableSideFpsHint(); - mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE); - verify(mSideFpsController, atLeastOnce()).show(SideFpsUiRequestSource.PRIMARY_BOUNCER, - BiometricOverlayConstants.REASON_AUTH_KEYGUARD); - reset(mSideFpsController); - - mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.INVISIBLE); - - verify(mSideFpsController).hide(SideFpsUiRequestSource.PRIMARY_BOUNCER); - verify(mSideFpsController, never()).show(any(), anyInt()); - } - - @Test public void onBouncerVisibilityChanged_resetsScale() { - mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.INVISIBLE); - + mKeyguardSecurityContainerController.onBouncerVisibilityChanged(false); verify(mView).resetScale(); } @Test - public void onStartingToHide_sideFpsHintShown_sideFpsHintHidden() { - setupGetSecurityView(); - setupConditionsToEnableSideFpsHint(); - mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE); - verify(mSideFpsController, atLeastOnce()).show(SideFpsUiRequestSource.PRIMARY_BOUNCER, - BiometricOverlayConstants.REASON_AUTH_KEYGUARD); - reset(mSideFpsController); - - mKeyguardSecurityContainerController.onStartingToHide(); - - verify(mSideFpsController).hide(SideFpsUiRequestSource.PRIMARY_BOUNCER); - verify(mSideFpsController, never()).show(any(), anyInt()); - } - - @Test - public void onPause_sideFpsHintShown_sideFpsHintHidden() { - setupGetSecurityView(); - setupConditionsToEnableSideFpsHint(); - mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE); - verify(mSideFpsController, atLeastOnce()).show(SideFpsUiRequestSource.PRIMARY_BOUNCER, - BiometricOverlayConstants.REASON_AUTH_KEYGUARD); - reset(mSideFpsController); - - mKeyguardSecurityContainerController.onPause(); - - verify(mSideFpsController).hide(SideFpsUiRequestSource.PRIMARY_BOUNCER); - verify(mSideFpsController, never()).show(any(), anyInt()); - } - - @Test - public void onResume_sideFpsHintShouldBeShown_sideFpsHintShown() { - setupGetSecurityView(); - setupConditionsToEnableSideFpsHint(); - mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE); - reset(mSideFpsController); - - mKeyguardSecurityContainerController.onResume(0); - - verify(mSideFpsController).show(SideFpsUiRequestSource.PRIMARY_BOUNCER, - BiometricOverlayConstants.REASON_AUTH_KEYGUARD); - verify(mSideFpsController, never()).hide(any()); - } - - @Test - public void onResume_sideFpsHintShouldNotBeShown_sideFpsHintHidden() { - setupGetSecurityView(); - setupConditionsToEnableSideFpsHint(); - setSideFpsHintEnabledFromResources(false); - mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE); - reset(mSideFpsController); - - mKeyguardSecurityContainerController.onResume(0); - - verify(mSideFpsController).hide(SideFpsUiRequestSource.PRIMARY_BOUNCER); - verify(mSideFpsController, never()).show(any(), anyInt()); - } - - @Test public void showNextSecurityScreenOrFinish_setsSecurityScreenToPinAfterSimPinUnlock() { // GIVEN the current security method is SimPin when(mKeyguardUpdateMonitor.getUserHasTrust(anyInt())).thenReturn(false); @@ -719,39 +591,31 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase { any(KeyguardSecurityCallback.class)); } + @Test + public void testSideFpsControllerShow() { + mKeyguardSecurityContainerController.updateSideFpsVisibility(/* isVisible= */ true); + verify(mSideFpsController).show( + SideFpsUiRequestSource.PRIMARY_BOUNCER, + BiometricOverlayConstants.REASON_AUTH_KEYGUARD); + } + + @Test + public void testSideFpsControllerHide() { + mKeyguardSecurityContainerController.updateSideFpsVisibility(/* isVisible= */ false); + verify(mSideFpsController).hide(SideFpsUiRequestSource.PRIMARY_BOUNCER); + } + private KeyguardSecurityContainer.SwipeListener getRegisteredSwipeListener() { mKeyguardSecurityContainerController.onViewAttached(); verify(mView).setSwipeListener(mSwipeListenerArgumentCaptor.capture()); return mSwipeListenerArgumentCaptor.getValue(); } - private void setupConditionsToEnableSideFpsHint() { - attachView(); - setSideFpsHintEnabledFromResources(true); - setFingerprintDetectionRunning(true); - setUnlockingWithFingerprintAllowed(true); - } - 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 setSideFpsHintEnabledFromResources(boolean enabled) { - mTestableResources.addOverride(R.bool.config_show_sidefps_hint_on_bouncer, - enabled); - } - - private void setUnlockingWithFingerprintAllowed(boolean allowed) { - when(mKeyguardUpdateMonitor.isUnlockingWithFingerprintAllowed()).thenReturn(allowed); - } - private void setupGetSecurityView() { when(mKeyguardSecurityViewFlipperController.getSecurityView( any(), any(KeyguardSecurityCallback.class))) diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerWithCoroutinesTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerWithCoroutinesTest.kt index c73ff1dab3d8..54c9d392ad1c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerWithCoroutinesTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerWithCoroutinesTest.kt @@ -86,8 +86,9 @@ class UdfpsKeyguardViewControllerWithCoroutinesTest : UdfpsKeyguardViewControlle mock(PrimaryBouncerCallbackInteractor::class.java), mock(FalsingCollector::class.java), mock(DismissCallbackRegistry::class.java), + context, + mKeyguardUpdateMonitor, mock(KeyguardBypassController::class.java), - mKeyguardUpdateMonitor ) mAlternateBouncerInteractor = AlternateBouncerInteractor( diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorTest.kt index 46ed829e0574..6b7fd616e678 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorTest.kt @@ -19,11 +19,13 @@ package com.android.systemui.keyguard.domain.interactor import android.os.Looper import android.testing.AndroidTestingRunner import android.testing.TestableLooper.RunWithLooper +import android.testing.TestableResources import android.view.View import androidx.test.filters.SmallTest import com.android.keyguard.KeyguardSecurityModel import com.android.keyguard.KeyguardUpdateMonitor import com.android.systemui.DejankUtils +import com.android.systemui.R import com.android.systemui.SysuiTestCase import com.android.systemui.classifier.FalsingCollector import com.android.systemui.keyguard.DismissCallbackRegistry @@ -69,6 +71,7 @@ class PrimaryBouncerInteractorTest : SysuiTestCase() { @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor private val mainHandler = FakeHandler(Looper.getMainLooper()) private lateinit var underTest: PrimaryBouncerInteractor + private lateinit var resources: TestableResources @Before fun setUp() { @@ -84,18 +87,19 @@ class PrimaryBouncerInteractorTest : SysuiTestCase() { mPrimaryBouncerCallbackInteractor, falsingCollector, dismissCallbackRegistry, - keyguardBypassController, + context, keyguardUpdateMonitor, + keyguardBypassController, ) `when`(repository.primaryBouncerStartingDisappearAnimation.value).thenReturn(null) `when`(repository.primaryBouncerShow.value).thenReturn(null) `when`(bouncerView.delegate).thenReturn(bouncerViewDelegate) + resources = context.orCreateTestableResources } @Test fun testShow_isScrimmed() { underTest.show(true) - verify(repository).setOnScreenTurnedOff(false) verify(repository).setKeyguardAuthenticated(null) verify(repository).setPrimaryHide(false) verify(repository).setPrimaryStartingToHide(false) @@ -207,12 +211,6 @@ class PrimaryBouncerInteractorTest : SysuiTestCase() { } @Test - fun testOnScreenTurnedOff() { - underTest.onScreenTurnedOff() - verify(repository).setOnScreenTurnedOff(true) - } - - @Test fun testSetKeyguardPosition() { underTest.setKeyguardPosition(0f) verify(repository).setKeyguardPosition(0f) @@ -286,4 +284,98 @@ class PrimaryBouncerInteractorTest : SysuiTestCase() { `when`(bouncerViewDelegate.willDismissWithActions()).thenReturn(false) assertThat(underTest.willDismissWithAction()).isFalse() } + + @Test + fun testSideFpsVisibility() { + updateSideFpsVisibilityParameters( + isVisible = true, + sfpsEnabled = true, + fpsDetectionRunning = true, + isUnlockingWithFpAllowed = true, + isAnimatingAway = false + ) + underTest.updateSideFpsVisibility() + verify(repository).setSideFpsShowing(true) + } + + @Test + fun testSideFpsVisibility_notVisible() { + updateSideFpsVisibilityParameters( + isVisible = false, + sfpsEnabled = true, + fpsDetectionRunning = true, + isUnlockingWithFpAllowed = true, + isAnimatingAway = false + ) + underTest.updateSideFpsVisibility() + verify(repository).setSideFpsShowing(false) + } + + @Test + fun testSideFpsVisibility_sfpsNotEnabled() { + updateSideFpsVisibilityParameters( + isVisible = true, + sfpsEnabled = false, + fpsDetectionRunning = true, + isUnlockingWithFpAllowed = true, + isAnimatingAway = false + ) + underTest.updateSideFpsVisibility() + verify(repository).setSideFpsShowing(false) + } + + @Test + fun testSideFpsVisibility_fpsDetectionNotRunning() { + updateSideFpsVisibilityParameters( + isVisible = true, + sfpsEnabled = true, + fpsDetectionRunning = false, + isUnlockingWithFpAllowed = true, + isAnimatingAway = false + ) + underTest.updateSideFpsVisibility() + verify(repository).setSideFpsShowing(false) + } + + @Test + fun testSideFpsVisibility_UnlockingWithFpNotAllowed() { + updateSideFpsVisibilityParameters( + isVisible = true, + sfpsEnabled = true, + fpsDetectionRunning = true, + isUnlockingWithFpAllowed = false, + isAnimatingAway = false + ) + underTest.updateSideFpsVisibility() + verify(repository).setSideFpsShowing(false) + } + + @Test + fun testSideFpsVisibility_AnimatingAway() { + updateSideFpsVisibilityParameters( + isVisible = true, + sfpsEnabled = true, + fpsDetectionRunning = true, + isUnlockingWithFpAllowed = true, + isAnimatingAway = true + ) + underTest.updateSideFpsVisibility() + verify(repository).setSideFpsShowing(false) + } + + private fun updateSideFpsVisibilityParameters( + isVisible: Boolean, + sfpsEnabled: Boolean, + fpsDetectionRunning: Boolean, + isUnlockingWithFpAllowed: Boolean, + isAnimatingAway: Boolean + ) { + `when`(repository.primaryBouncerVisible.value).thenReturn(isVisible) + resources.addOverride(R.bool.config_show_sidefps_hint_on_bouncer, sfpsEnabled) + `when`(keyguardUpdateMonitor.isFingerprintDetectionRunning).thenReturn(fpsDetectionRunning) + `when`(keyguardUpdateMonitor.isUnlockingWithFingerprintAllowed) + .thenReturn(isUnlockingWithFpAllowed) + `when`(repository.primaryBouncerStartingDisappearAnimation.value) + .thenReturn(if (isAnimatingAway) Runnable {} else null) + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorWithCoroutinesTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorWithCoroutinesTest.kt index 75b74b0cfe28..f675e7997eb4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorWithCoroutinesTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorWithCoroutinesTest.kt @@ -26,7 +26,6 @@ import com.android.systemui.classifier.FalsingCollector import com.android.systemui.coroutines.collectLastValue import com.android.systemui.keyguard.DismissCallbackRegistry import com.android.systemui.keyguard.data.BouncerView -import com.android.systemui.keyguard.data.BouncerViewDelegate import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository import com.android.systemui.statusbar.phone.KeyguardBypassController import com.android.systemui.statusbar.policy.KeyguardStateController @@ -44,7 +43,6 @@ import org.mockito.MockitoAnnotations class PrimaryBouncerInteractorWithCoroutinesTest : SysuiTestCase() { private lateinit var repository: FakeKeyguardBouncerRepository @Mock private lateinit var bouncerView: BouncerView - @Mock private lateinit var bouncerViewDelegate: BouncerViewDelegate @Mock private lateinit var keyguardStateController: KeyguardStateController @Mock private lateinit var keyguardSecurityModel: KeyguardSecurityModel @Mock private lateinit var primaryBouncerCallbackInteractor: PrimaryBouncerCallbackInteractor @@ -69,8 +67,9 @@ class PrimaryBouncerInteractorWithCoroutinesTest : SysuiTestCase() { primaryBouncerCallbackInteractor, falsingCollector, dismissCallbackRegistry, - keyguardBypassController, + context, keyguardUpdateMonitor, + keyguardBypassController, ) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModelTest.kt index 586af626d29e..65e4c10265cd 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModelTest.kt @@ -16,15 +16,23 @@ package com.android.systemui.keyguard.ui.viewmodel +import android.os.Looper import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest +import com.android.keyguard.KeyguardSecurityModel +import com.android.keyguard.KeyguardUpdateMonitor import com.android.systemui.SysuiTestCase +import com.android.systemui.classifier.FalsingCollector +import com.android.systemui.keyguard.DismissCallbackRegistry import com.android.systemui.keyguard.data.BouncerView +import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository +import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerCallbackInteractor import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor import com.android.systemui.keyguard.shared.model.BouncerShowMessageModel +import com.android.systemui.statusbar.phone.KeyguardBypassController +import com.android.systemui.statusbar.policy.KeyguardStateController +import com.android.systemui.utils.os.FakeHandler import com.google.common.truth.Truth.assertThat -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.test.runCurrent @@ -33,7 +41,6 @@ import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mock -import org.mockito.Mockito import org.mockito.MockitoAnnotations @SmallTest @@ -41,31 +48,69 @@ import org.mockito.MockitoAnnotations @kotlinx.coroutines.ExperimentalCoroutinesApi class KeyguardBouncerViewModelTest : SysuiTestCase() { lateinit var underTest: KeyguardBouncerViewModel + lateinit var bouncerInteractor: PrimaryBouncerInteractor @Mock lateinit var bouncerView: BouncerView - @Mock lateinit var bouncerInteractor: PrimaryBouncerInteractor + @Mock private lateinit var keyguardStateController: KeyguardStateController + @Mock private lateinit var keyguardSecurityModel: KeyguardSecurityModel + @Mock private lateinit var primaryBouncerCallbackInteractor: PrimaryBouncerCallbackInteractor + @Mock private lateinit var falsingCollector: FalsingCollector + @Mock private lateinit var dismissCallbackRegistry: DismissCallbackRegistry + @Mock private lateinit var keyguardBypassController: KeyguardBypassController + @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor + private val mainHandler = FakeHandler(Looper.getMainLooper()) + val repository = FakeKeyguardBouncerRepository() @Before fun setup() { MockitoAnnotations.initMocks(this) + bouncerInteractor = + PrimaryBouncerInteractor( + repository, + bouncerView, + mainHandler, + keyguardStateController, + keyguardSecurityModel, + primaryBouncerCallbackInteractor, + falsingCollector, + dismissCallbackRegistry, + context, + keyguardUpdateMonitor, + keyguardBypassController, + ) underTest = KeyguardBouncerViewModel(bouncerView, bouncerInteractor) } @Test - fun setMessage() = - runTest { - val flow = MutableStateFlow<BouncerShowMessageModel?>(null) - var message: BouncerShowMessageModel? = null - Mockito.`when`(bouncerInteractor.showMessage) - .thenReturn(flow as Flow<BouncerShowMessageModel>) - // Reinitialize the view model. - underTest = KeyguardBouncerViewModel(bouncerView, bouncerInteractor) + fun setMessage() = runTest { + var message: BouncerShowMessageModel? = null + val job = underTest.bouncerShowMessage.onEach { message = it }.launchIn(this) - flow.value = BouncerShowMessageModel(message = "abc", colorStateList = null) + repository.setShowMessage(BouncerShowMessageModel("abc", null)) + // Run the tasks that are pending at this point of virtual time. + runCurrent() + assertThat(message?.message).isEqualTo("abc") + job.cancel() + } + + @Test + fun shouldUpdateSideFps() = runTest { + var count = 0 + val job = underTest.shouldUpdateSideFps.onEach { count++ }.launchIn(this) + repository.setPrimaryVisible(true) + // Run the tasks that are pending at this point of virtual time. + runCurrent() + assertThat(count).isEqualTo(1) + job.cancel() + } - val job = underTest.bouncerShowMessage.onEach { message = it }.launchIn(this) - // Run the tasks that are pending at this point of virtual time. - runCurrent() - assertThat(message?.message).isEqualTo("abc") - job.cancel() - } + @Test + fun sideFpsShowing() = runTest { + var sideFpsIsShowing = false + val job = underTest.sideFpsShowing.onEach { sideFpsIsShowing = it }.launchIn(this) + repository.setSideFpsShowing(true) + // Run the tasks that are pending at this point of virtual time. + runCurrent() + assertThat(sideFpsIsShowing).isEqualTo(true) + job.cancel() + } } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardBouncerRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardBouncerRepository.kt index 337421974562..9cdce20bbf1e 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardBouncerRepository.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardBouncerRepository.kt @@ -21,6 +21,7 @@ import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.E import com.android.systemui.keyguard.shared.model.BouncerShowMessageModel import com.android.systemui.keyguard.shared.model.KeyguardBouncerModel import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow /** Fake implementation of [KeyguardRepository] */ @@ -44,8 +45,6 @@ class FakeKeyguardBouncerRepository : KeyguardBouncerRepository { override val panelExpansionAmount = _panelExpansionAmount.asStateFlow() private val _keyguardPosition = MutableStateFlow(0f) override val keyguardPosition = _keyguardPosition.asStateFlow() - private val _onScreenTurnedOff = MutableStateFlow(false) - override val onScreenTurnedOff = _onScreenTurnedOff.asStateFlow() private val _isBackButtonEnabled = MutableStateFlow<Boolean?>(null) override val isBackButtonEnabled = _isBackButtonEnabled.asStateFlow() private val _keyguardAuthenticated = MutableStateFlow<Boolean?>(null) @@ -61,6 +60,8 @@ class FakeKeyguardBouncerRepository : KeyguardBouncerRepository { override var lastAlternateBouncerVisibleTime: Long = 0L private val _isAlternateBouncerUIAvailable = MutableStateFlow<Boolean>(false) override val alternateBouncerUIAvailable = _isAlternateBouncerUIAvailable.asStateFlow() + private val _sideFpsShowing: MutableStateFlow<Boolean> = MutableStateFlow(false) + override val sideFpsShowing: StateFlow<Boolean> = _sideFpsShowing.asStateFlow() override fun setPrimaryScrimmed(isScrimmed: Boolean) { _primaryBouncerScrimmed.value = isScrimmed @@ -122,7 +123,7 @@ class FakeKeyguardBouncerRepository : KeyguardBouncerRepository { _isBackButtonEnabled.value = isBackButtonEnabled } - override fun setOnScreenTurnedOff(onScreenTurnedOff: Boolean) { - _onScreenTurnedOff.value = onScreenTurnedOff + override fun setSideFpsShowing(isShowing: Boolean) { + _sideFpsShowing.value = isShowing } } |