Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1684f166 authored by Beverly Tai's avatar Beverly Tai Committed by Automerger Merge Worker
Browse files

Merge "Add SideFps AlternateBouncer" into tm-qpr-dev am: 2818aa41 am: aa362779

parents e0eaedb8 aa362779
Loading
Loading
Loading
Loading
+27 −0
Original line number Diff line number Diff line
@@ -54,12 +54,18 @@ import com.android.internal.annotations.VisibleForTesting
import com.android.systemui.Dumpable
import com.android.systemui.R
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Main
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.recents.OverviewProxyService
import com.android.systemui.util.concurrency.DelayableExecutor
import java.io.PrintWriter
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch

private const val TAG = "SideFpsController"

@@ -79,6 +85,9 @@ constructor(
    displayManager: DisplayManager,
    @Main private val mainExecutor: DelayableExecutor,
    @Main private val handler: Handler,
    private val alternateBouncerInteractor: AlternateBouncerInteractor,
    @Application private val scope: CoroutineScope,
    private val featureFlags: FeatureFlags,
    dumpManager: DumpManager
) : Dumpable {
    val requests: HashSet<SideFpsUiRequestSource> = HashSet()
@@ -168,9 +177,26 @@ constructor(
            }
        )
        overviewProxyService.addCallback(overviewProxyListener)
        listenForAlternateBouncerVisibility()

        dumpManager.registerDumpable(this)
    }

    private fun listenForAlternateBouncerVisibility() {
        alternateBouncerInteractor.setAlternateBouncerUIAvailable(true)
        if (featureFlags.isEnabled(Flags.MODERN_ALTERNATE_BOUNCER)) {
            scope.launch {
                alternateBouncerInteractor.isVisible.collect { isVisible: Boolean ->
                    if (isVisible) {
                        show(SideFpsUiRequestSource.ALTERNATE_BOUNCER)
                    } else {
                        hide(SideFpsUiRequestSource.ALTERNATE_BOUNCER)
                    }
                }
            }
        }
    }

    /** Shows the side fps overlay if not already shown. */
    fun show(request: SideFpsUiRequestSource) {
        requests.add(request)
@@ -423,4 +449,5 @@ enum class SideFpsUiRequestSource {
    AUTO_SHOW,
    /** Pin, pattern or password bouncer */
    PRIMARY_BOUNCER,
    ALTERNATE_BOUNCER
}
+30 −21
Original line number Diff line number Diff line
@@ -22,14 +22,18 @@ import com.android.keyguard.KeyguardUpdateMonitorCallback
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 javax.inject.Inject
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.stateIn

/** Encapsulates state about device entry fingerprint auth mechanism. */
interface DeviceEntryFingerprintAuthRepository {
    /** Whether the device entry fingerprint auth is locked out. */
    val isLockedOut: Flow<Boolean>
    val isLockedOut: StateFlow<Boolean>
}

/**
@@ -44,9 +48,11 @@ class DeviceEntryFingerprintAuthRepositoryImpl
@Inject
constructor(
    val keyguardUpdateMonitor: KeyguardUpdateMonitor,
    @Application scope: CoroutineScope,
) : DeviceEntryFingerprintAuthRepository {

    override val isLockedOut: Flow<Boolean> = conflatedCallbackFlow {
    override val isLockedOut: StateFlow<Boolean> =
        conflatedCallbackFlow {
                val sendLockoutUpdate =
                    fun() {
                        trySendWithFailureLogging(
@@ -57,7 +63,9 @@ constructor(
                    }
                val callback =
                    object : KeyguardUpdateMonitorCallback() {
                override fun onLockedOutStateChanged(biometricSourceType: BiometricSourceType?) {
                        override fun onLockedOutStateChanged(
                            biometricSourceType: BiometricSourceType?
                        ) {
                            if (biometricSourceType == BiometricSourceType.FINGERPRINT) {
                                sendLockoutUpdate()
                            }
@@ -67,6 +75,7 @@ constructor(
                sendLockoutUpdate()
                awaitClose { keyguardUpdateMonitor.removeCallback(callback) }
            }
            .stateIn(scope, started = SharingStarted.Eagerly, initialValue = false)

    companion object {
        const val TAG = "DeviceEntryFingerprintAuthRepositoryImpl"
+5 −0
Original line number Diff line number Diff line
@@ -32,4 +32,9 @@ interface KeyguardRepositoryModule {
    fun lightRevealScrimRepository(impl: LightRevealScrimRepositoryImpl): LightRevealScrimRepository

    @Binds fun biometricRepository(impl: BiometricRepositoryImpl): BiometricRepository

    @Binds
    fun deviceEntryFingerprintAuthRepository(
        impl: DeviceEntryFingerprintAuthRepositoryImpl
    ): DeviceEntryFingerprintAuthRepository
}
+4 −1
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ 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.DeviceEntryFingerprintAuthRepository
import com.android.systemui.keyguard.data.repository.KeyguardBouncerRepository
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager.LegacyAlternateBouncer
import com.android.systemui.util.time.SystemClock
@@ -34,6 +35,7 @@ class AlternateBouncerInteractor
constructor(
    private val bouncerRepository: KeyguardBouncerRepository,
    private val biometricRepository: BiometricRepository,
    private val deviceEntryFingerprintAuthRepository: DeviceEntryFingerprintAuthRepository,
    private val systemClock: SystemClock,
    private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
    featureFlags: FeatureFlags,
@@ -99,7 +101,8 @@ constructor(
            bouncerRepository.isAlternateBouncerUIAvailable.value &&
                biometricRepository.isFingerprintEnrolled.value &&
                biometricRepository.isStrongBiometricAllowed.value &&
                biometricRepository.isFingerprintEnabledByDevicePolicy.value
                biometricRepository.isFingerprintEnabledByDevicePolicy.value &&
                !deviceEntryFingerprintAuthRepository.isLockedOut.value
        } else {
            legacyAlternateBouncer != null &&
                keyguardUpdateMonitor.isUnlockingWithBiometricAllowed(true)
+56 −2
Original line number Diff line number Diff line
@@ -51,14 +51,24 @@ import android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG
import android.view.WindowMetrics
import androidx.test.filters.SmallTest
import com.airbnb.lottie.LottieAnimationView
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.keyguard.ViewMediatorCallback
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.SysuiTestableContext
import com.android.systemui.dump.DumpManager
import com.android.systemui.flags.FakeFeatureFlags
import com.android.systemui.flags.Flags.MODERN_ALTERNATE_BOUNCER
import com.android.systemui.keyguard.data.repository.FakeBiometricRepository
import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFingerprintAuthRepository
import com.android.systemui.keyguard.data.repository.KeyguardBouncerRepository
import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor
import com.android.systemui.log.table.TableLogBuffer
import com.android.systemui.recents.OverviewProxyService
import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.test.TestCoroutineScope
import org.junit.Before
import org.junit.Rule
import org.junit.Test
@@ -101,6 +111,9 @@ class SideFpsControllerTest : SysuiTestCase() {
    @Captor lateinit var overlayCaptor: ArgumentCaptor<View>
    @Captor lateinit var overlayViewParamsCaptor: ArgumentCaptor<WindowManager.LayoutParams>

    private lateinit var keyguardBouncerRepository: KeyguardBouncerRepository
    private lateinit var alternateBouncerInteractor: AlternateBouncerInteractor
    private val featureFlags = FakeFeatureFlags()
    private val executor = FakeExecutor(FakeSystemClock())
    private lateinit var overlayController: ISidefpsController
    private lateinit var sideFpsController: SideFpsController
@@ -121,6 +134,24 @@ class SideFpsControllerTest : SysuiTestCase() {

    @Before
    fun setup() {
        featureFlags.set(MODERN_ALTERNATE_BOUNCER, true)
        keyguardBouncerRepository =
            KeyguardBouncerRepository(
                mock(ViewMediatorCallback::class.java),
                FakeSystemClock(),
                TestCoroutineScope(),
                mock(TableLogBuffer::class.java),
            )
        alternateBouncerInteractor =
            AlternateBouncerInteractor(
                keyguardBouncerRepository,
                FakeBiometricRepository(),
                FakeDeviceEntryFingerprintAuthRepository(),
                FakeSystemClock(),
                mock(KeyguardUpdateMonitor::class.java),
                featureFlags,
            )

        context.addMockSystemService(DisplayManager::class.java, displayManager)
        context.addMockSystemService(WindowManager::class.java, windowManager)

@@ -217,7 +248,10 @@ class SideFpsControllerTest : SysuiTestCase() {
                displayManager,
                executor,
                handler,
                dumpManager
                alternateBouncerInteractor,
                TestCoroutineScope(),
                featureFlags,
                dumpManager,
            )

        overlayController =
@@ -507,6 +541,26 @@ class SideFpsControllerTest : SysuiTestCase() {

    private fun verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible: Boolean) {
        sideFpsController.overlayOffsets = sensorLocation
    }

    fun alternateBouncerVisibility_showAndHideSideFpsUI() = testWithDisplay {
        // WHEN alternate bouncer is visible
        keyguardBouncerRepository.setAlternateVisible(true)
        executor.runAllReady()

        // THEN side fps shows UI
        verify(windowManager).addView(any(), any())
        verify(windowManager, never()).removeView(any())

        // WHEN alternate bouncer is no longer visible
        keyguardBouncerRepository.setAlternateVisible(false)
        executor.runAllReady()

        // THEN side fps UI is hidden
        verify(windowManager).removeView(any())
    }

    private fun hidesWithTaskbar(visible: Boolean) {
        overlayController.show(SENSOR_ID, REASON_UNKNOWN)
        executor.runAllReady()

@@ -515,7 +569,7 @@ class SideFpsControllerTest : SysuiTestCase() {

        verify(windowManager).addView(any(), any())
        verify(windowManager, never()).removeView(any())
        verify(sideFpsView).visibility = if (sfpsViewVisible) View.VISIBLE else View.GONE
        verify(sideFpsView).visibility = if (visible) View.VISIBLE else View.GONE
    }

    /**
Loading