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

Commit ffcfa4be authored by Beverly's avatar Beverly Committed by Beverly Tai
Browse files

Remove DeviceEntryHapticsRepository & update Interactor

Instead of having the data go through the interactor to
update the repository, let's use other repositories
as the source of truth.

Updates DeviceEntryHapticsInteractorTest to use Kosmos.

Flag: NONE
Test: atest DeviceEntryHapticsInteractorTest DefaultDeviceEntrySectionTest BiometricsUnlockControllerTest
Fixes: 314363343
Change-Id: Ia18eefb6c31fd323b2f71a851b05cc6774ef613d
parent e2b283d9
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@ import androidx.test.filters.SmallTest
import com.android.internal.widget.LockPatternUtils
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
import com.android.systemui.scene.SceneTestUtils
import com.android.systemui.statusbar.phone.KeyguardBypassController
import com.android.systemui.statusbar.policy.KeyguardStateController
@@ -38,6 +39,7 @@ class DeviceEntryRepositoryTest : SysuiTestCase() {
    private val testUtils = SceneTestUtils(this)
    private val testScope = testUtils.testScope
    private val userRepository = FakeUserRepository()
    private val keyguardRepository = FakeKeyguardRepository()

    private lateinit var underTest: DeviceEntryRepository

@@ -55,6 +57,7 @@ class DeviceEntryRepositoryTest : SysuiTestCase() {
                lockPatternUtils = lockPatternUtils,
                keyguardBypassController = keyguardBypassController,
                keyguardStateController = keyguardStateController,
                keyguardRepository = keyguardRepository,
            )
        testScope.runCurrent()
    }
+0 −2
Original line number Diff line number Diff line
package com.android.systemui.deviceentry

import com.android.systemui.deviceentry.data.repository.DeviceEntryHapticsRepositoryModule
import com.android.systemui.deviceentry.data.repository.DeviceEntryRepositoryModule
import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition
import dagger.Module
@@ -10,7 +9,6 @@ import dagger.multibindings.Multibinds
    includes =
        [
            DeviceEntryRepositoryModule::class,
            DeviceEntryHapticsRepositoryModule::class,
        ],
)
abstract class DeviceEntryModule {
+17 −0
Original line number Diff line number Diff line
@@ -7,26 +7,36 @@ import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCall
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.keyguard.data.repository.KeyguardRepository
import com.android.systemui.keyguard.shared.model.BiometricUnlockModel
import com.android.systemui.keyguard.shared.model.BiometricUnlockSource
import com.android.systemui.statusbar.phone.KeyguardBypassController
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.user.data.repository.UserRepository
import com.android.systemui.util.kotlin.sample
import dagger.Binds
import dagger.Module
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.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.withContext

/** Interface for classes that can access device-entry-related application state. */
interface DeviceEntryRepository {
    /** Whether the device is immediately entering the device after a biometric unlock. */
    val enteringDeviceFromBiometricUnlock: Flow<BiometricUnlockSource>

    /**
     * Whether the device is unlocked.
     *
@@ -73,7 +83,14 @@ constructor(
    private val lockPatternUtils: LockPatternUtils,
    private val keyguardBypassController: KeyguardBypassController,
    keyguardStateController: KeyguardStateController,
    keyguardRepository: KeyguardRepository,
) : DeviceEntryRepository {
    override val enteringDeviceFromBiometricUnlock =
        keyguardRepository.biometricUnlockState
            .filter { BiometricUnlockModel.dismissesKeyguard(it) }
            .sample(
                keyguardRepository.biometricUnlockSource.filterNotNull(),
            )

    private val _isUnlocked = MutableStateFlow(false)

+70 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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.deviceentry.domain.interactor

import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.deviceentry.shared.DeviceEntryBiometricMode
import com.android.systemui.keyguard.data.repository.BiometricSettingsRepository
import com.android.systemui.keyguard.shared.model.FailedFaceAuthenticationStatus
import javax.inject.Inject
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.map

/** Business logic for device entry biometric states that may differ based on the biometric mode. */
@ExperimentalCoroutinesApi
@SysUISingleton
class DeviceEntryBiometricAuthInteractor
@Inject
constructor(
    biometricSettingsRepository: BiometricSettingsRepository,
    deviceEntryFaceAuthInteractor: DeviceEntryFaceAuthInteractor,
) {
    private val biometricMode: Flow<DeviceEntryBiometricMode> =
        combine(
            biometricSettingsRepository.isFingerprintEnrolledAndEnabled,
            biometricSettingsRepository.isFaceAuthEnrolledAndEnabled,
        ) { fingerprintEnrolled, faceEnrolled ->
            if (fingerprintEnrolled && faceEnrolled) {
                DeviceEntryBiometricMode.CO_EXPERIENCE
            } else if (fingerprintEnrolled) {
                DeviceEntryBiometricMode.FINGERPRINT_ONLY
            } else if (faceEnrolled) {
                DeviceEntryBiometricMode.FACE_ONLY
            } else {
                DeviceEntryBiometricMode.NONE
            }
        }
    private val faceOnly: Flow<Boolean> =
        biometricMode.map { it == DeviceEntryBiometricMode.FACE_ONLY }

    /**
     * Triggered if face is the only biometric that can be used for device entry and a face failure
     * occurs.
     */
    val faceOnlyFaceFailure: Flow<FailedFaceAuthenticationStatus> =
        faceOnly.flatMapLatest { faceOnly ->
            if (faceOnly) {
                deviceEntryFaceAuthInteractor.faceFailure
            } else {
                emptyFlow()
            }
        }
}
+34 −0
Original line number Diff line number Diff line
@@ -13,43 +13,22 @@
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.android.systemui.deviceentry.data.repository

package com.android.systemui.deviceentry.domain.interactor

import com.android.systemui.dagger.SysUISingleton
import dagger.Binds
import dagger.Module
import com.android.systemui.keyguard.data.repository.DeviceEntryFaceAuthRepository
import com.android.systemui.keyguard.shared.model.FailedFaceAuthenticationStatus
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.filterIsInstance

/** Fake implementation of [DeviceEntryHapticsRepository] */
@SysUISingleton
class FakeDeviceEntryHapticsRepository @Inject constructor() : DeviceEntryHapticsRepository {
    private var _successHapticRequest: MutableStateFlow<Boolean> = MutableStateFlow(false)
    override val successHapticRequest: Flow<Boolean> = _successHapticRequest.asStateFlow()

    private var _errorHapticRequest: MutableStateFlow<Boolean> = MutableStateFlow(false)
    override val errorHapticRequest: Flow<Boolean> = _errorHapticRequest.asStateFlow()

    override fun requestSuccessHaptic() {
        _successHapticRequest.value = true
    }

    override fun handleSuccessHaptic() {
        _successHapticRequest.value = false
    }

    override fun requestErrorHaptic() {
        _errorHapticRequest.value = true
    }

    override fun handleErrorHaptic() {
        _errorHapticRequest.value = false
    }
}

@Module
interface FakeDeviceEntryHapticsRepositoryModule {
    @Binds fun bindFake(fake: FakeDeviceEntryHapticsRepository): DeviceEntryHapticsRepository
class DeviceEntryFaceAuthInteractor
@Inject
constructor(
    repository: DeviceEntryFaceAuthRepository,
) {
    val faceFailure: Flow<FailedFaceAuthenticationStatus> =
        repository.authenticationStatus.filterIsInstance<FailedFaceAuthenticationStatus>()
}
Loading