Merge changes I18c15685,I53d30dd0 into main
* changes:
Wait to set propertiesInitialized to true
Revert "Always emit latest propertiesInitialized value onStart"
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/FingerprintPropertyRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/FingerprintPropertyRepositoryTest.kt
deleted file mode 100644
index 1e7ed63..0000000
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/FingerprintPropertyRepositoryTest.kt
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * 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())
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/FingerprintPropertyRepository.kt b/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/FingerprintPropertyRepository.kt
index 6b61adc..ba51d02 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/FingerprintPropertyRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/FingerprintPropertyRepository.kt
@@ -30,10 +30,10 @@
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.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 @@
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 @@
}
}
+ 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,
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/FingerprintPropertyInteractor.kt b/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/FingerprintPropertyInteractor.kt
index d5b450d..a74b0b0 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/FingerprintPropertyInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/FingerprintPropertyInteractor.kt
@@ -52,7 +52,7 @@
.map { it.isUdfps() }
.stateIn(
scope = applicationScope,
- started = SharingStarted.WhileSubscribed(),
+ started = SharingStarted.Eagerly,
initialValue = repository.sensorType.value.isUdfps(),
)
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryUdfpsInteractor.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryUdfpsInteractor.kt
index 80b52ed..6c6d730 100644
--- a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryUdfpsInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryUdfpsInteractor.kt
@@ -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 @@
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)
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractor.kt
index b1ef76e..7cee258 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractor.kt
@@ -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.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 @@
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 {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySection.kt
index 29041d1..0b8376a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySection.kt
@@ -21,6 +21,7 @@
import android.graphics.Point
import android.graphics.Rect
import android.util.DisplayMetrics
+import android.util.Log
import android.view.View
import android.view.WindowManager
import androidx.annotation.VisibleForTesting
@@ -116,6 +117,10 @@
override fun applyConstraints(constraintSet: ConstraintSet) {
val isUdfpsSupported =
if (DeviceEntryUdfpsRefactor.isEnabled) {
+ Log.d(
+ "DefaultDeviceEntrySection",
+ "isUdfpsSupported=${deviceEntryIconViewModel.get().isUdfpsSupported.value}"
+ )
deviceEntryIconViewModel.get().isUdfpsSupported.value
} else {
authController.isUdfpsSupported
@@ -138,8 +143,24 @@
val iconRadiusPx = (defaultDensity * 36).toInt()
if (isUdfpsSupported) {
- authController.udfpsLocation?.let { udfpsLocation ->
- centerIcon(udfpsLocation, authController.udfpsRadius, constraintSet)
+ if (DeviceEntryUdfpsRefactor.isEnabled) {
+ deviceEntryIconViewModel.get().udfpsLocation.value?.let { udfpsLocation ->
+ Log.d(
+ "DeviceEntrySection",
+ "udfpsLocation=$udfpsLocation" +
+ " unusedAuthController=${authController.udfpsLocation}"
+ )
+ centerIcon(
+ Point(udfpsLocation.centerX.toInt(), udfpsLocation.centerY.toInt()),
+ udfpsLocation.radius,
+ constraintSet
+ )
+ }
+ } else {
+ authController.udfpsLocation?.let { udfpsLocation ->
+ Log.d("DeviceEntrySection", "udfpsLocation=$udfpsLocation")
+ centerIcon(udfpsLocation, authController.udfpsRadius, constraintSet)
+ }
}
} else {
centerIcon(
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModel.kt
index ae83c9e..8d90933 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModel.kt
@@ -20,6 +20,7 @@
import android.animation.IntEvaluator
import com.android.keyguard.KeyguardViewController
import com.android.systemui.accessibility.domain.interactor.AccessibilityInteractor
+import com.android.systemui.biometrics.shared.model.SensorLocation
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor
@@ -73,6 +74,12 @@
@Application private val scope: CoroutineScope,
) {
val isUdfpsSupported: StateFlow<Boolean> = deviceEntryUdfpsInteractor.isUdfpsSupported
+ val udfpsLocation: StateFlow<SensorLocation?> =
+ deviceEntryUdfpsInteractor.udfpsLocation.stateIn(
+ scope = scope,
+ started = SharingStarted.Eagerly,
+ initialValue = null,
+ )
private val intEvaluator = IntEvaluator()
private val floatEvaluator = FloatEvaluator()
private val showingAlternateBouncer: Flow<Boolean> =