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

Commit 051341ea authored by Android Build Coastguard Worker's avatar Android Build Coastguard Worker
Browse files

Merge cherrypicks of ['googleplex-android-review.googlesource.com/27422283',...

Merge cherrypicks of ['googleplex-android-review.googlesource.com/27422283', 'googleplex-android-review.googlesource.com/27417143'] into 24Q3-release.

Change-Id: Iac86620e578416d8716d1898d334705871cd32c1
parents 846e276b 851afea4
Loading
Loading
Loading
Loading
+0 −103
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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.keyguard.data.repository

import android.hardware.fingerprint.FingerprintManager
import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.biometrics.data.repository.FingerprintPropertyRepositoryImpl
import com.android.systemui.coroutines.collectLastValue
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
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.Mockito.verify
import org.mockito.junit.MockitoJUnit
import org.mockito.junit.MockitoRule

@ExperimentalCoroutinesApi
@RunWith(AndroidJUnit4::class)
@SmallTest
class FingerprintPropertyRepositoryTest : SysuiTestCase() {
    @JvmField @Rule val mockitoRule: MockitoRule = MockitoJUnit.rule()
    private val testScope = TestScope()
    private lateinit var underTest: FingerprintPropertyRepositoryImpl
    @Mock private lateinit var fingerprintManager: FingerprintManager
    @Captor
    private lateinit var fingerprintCallbackCaptor:
        ArgumentCaptor<IFingerprintAuthenticatorsRegisteredCallback>

    @Before
    fun setup() {
        underTest =
            FingerprintPropertyRepositoryImpl(
                testScope.backgroundScope,
                Dispatchers.Main.immediate,
                fingerprintManager,
            )
    }

    @Test
    fun propertiesInitialized_onStartFalse() =
        testScope.runTest {
            val propertiesInitialized by collectLastValue(underTest.propertiesInitialized)
            assertThat(propertiesInitialized).isFalse()
        }

    @Test
    fun propertiesInitialized_onStartTrue() =
        testScope.runTest {
            //            // collect sensorType to update fingerprintCallback before
            // propertiesInitialized
            //            // is listened for
            val sensorType by collectLastValue(underTest.sensorType)
            runCurrent()
            captureFingerprintCallback()

            fingerprintCallbackCaptor.value.onAllAuthenticatorsRegistered(emptyList())
            val propertiesInitialized by collectLastValue(underTest.propertiesInitialized)
            assertThat(propertiesInitialized).isTrue()
        }

    @Test
    fun propertiesInitialized_updatedToTrue() =
        testScope.runTest {
            val propertiesInitialized by collectLastValue(underTest.propertiesInitialized)
            assertThat(propertiesInitialized).isFalse()

            captureFingerprintCallback()
            fingerprintCallbackCaptor.value.onAllAuthenticatorsRegistered(emptyList())
            assertThat(propertiesInitialized).isTrue()
        }

    private fun captureFingerprintCallback() {
        verify(fingerprintManager)
            .addAuthenticatorsRegisteredCallback(fingerprintCallbackCaptor.capture())
    }
}
+20 −5
Original line number Diff line number Diff line
@@ -30,10 +30,10 @@ import com.android.systemui.biometrics.shared.model.SensorStrength
import com.android.systemui.biometrics.shared.model.toSensorStrength
import com.android.systemui.biometrics.shared.model.toSensorType
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 com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
@@ -41,6 +41,8 @@ import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.stateIn
@@ -111,9 +113,6 @@ constructor(
                initialValue = UNINITIALIZED_PROPS,
            )

    override val propertiesInitialized: Flow<Boolean> =
        props.map { it != UNINITIALIZED_PROPS }.onStart { emit(props.value != UNINITIALIZED_PROPS) }

    override val sensorId: Flow<Int> = props.map { it.sensorId }

    override val strength: Flow<SensorStrength> = props.map { it.sensorStrength.toSensorStrength() }
@@ -134,9 +133,25 @@ constructor(
            }
        }

    override val propertiesInitialized: Flow<Boolean> =
        combine(
                props
                    .map { it != UNINITIALIZED_PROPS }
                    .onStart { emit(props.value != UNINITIALIZED_PROPS) },
                sensorId.map {}.onStart { if (props.value != UNINITIALIZED_PROPS) emit(Unit) },
                sensorLocations
                    .map {}
                    .onStart { if (props.value != UNINITIALIZED_PROPS) emit(Unit) },
                sensorType.map {}.onStart { if (props.value != UNINITIALIZED_PROPS) emit(Unit) },
                strength.map {}.onStart { if (props.value != UNINITIALIZED_PROPS) emit(Unit) },
            ) { initialized, _, _, _, _ ->
                initialized
            }
            .distinctUntilChanged()

    companion object {
        private const val TAG = "FingerprintPropertyRepositoryImpl"
        val UNINITIALIZED_PROPS =
        private val UNINITIALIZED_PROPS =
            FingerprintSensorPropertiesInternal(
                -2 /* sensorId */,
                SensorProperties.STRENGTH_CONVENIENCE,
+1 −1
Original line number Diff line number Diff line
@@ -52,7 +52,7 @@ constructor(
            .map { it.isUdfps() }
            .stateIn(
                scope = applicationScope,
                started = SharingStarted.WhileSubscribed(),
                started = SharingStarted.Eagerly,
                initialValue = repository.sensorType.value.isUdfps(),
            )

+14 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.systemui.deviceentry.domain.interactor

import com.android.systemui.biometrics.domain.interactor.FingerprintPropertyInteractor
import com.android.systemui.biometrics.shared.model.SensorLocation
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.data.repository.BiometricSettingsRepository
import com.android.systemui.keyguard.data.repository.DeviceEntryFingerprintAuthRepository
@@ -58,4 +59,17 @@ constructor(
                flowOf(false)
            }
        }

    /**
     * Location of the under-display fingerprint sensor on the display. Null if the device does not
     * support UDFPS.
     */
    val udfpsLocation: Flow<SensorLocation?> =
        isUdfpsSupported.flatMapLatest {
            if (it) {
                fingerprintPropertyInteractor.sensorLocation
            } else {
                flowOf(null)
            }
        }
}
+1 −11
Original line number Diff line number Diff line
@@ -20,7 +20,6 @@
package com.android.systemui.keyguard.domain.interactor

import android.content.Context
import android.util.Log
import com.android.systemui.biometrics.domain.interactor.FingerprintPropertyInteractor
import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor
import com.android.systemui.dagger.SysUISingleton
@@ -43,7 +42,6 @@ import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch

@SysUISingleton
@@ -80,15 +78,7 @@ constructor(
    private val refreshEvents: Flow<Unit> =
        merge(
            configurationInteractor.onAnyConfigurationChange,
            fingerprintPropertyInteractor.propertiesInitialized
                .filter { it }
                .map { Unit }
                .onEach {
                    Log.d(
                        "KeyguardBlueprintInteractor",
                        "triggering refreshEvent from fpPropertiesInitialized"
                    )
                },
            fingerprintPropertyInteractor.propertiesInitialized.filter { it }.map {},
        )

    init {
Loading