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

Commit 29f92770 authored by Beverly Tai's avatar Beverly Tai Committed by Android (Google) Code Review
Browse files

Merge "Remove DeviceEntryHapticsRepository & update Interactor" into main

parents 9eb42136 ffcfa4be
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