summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Grace Cheng <graciecheng@google.com> 2024-01-02 18:38:20 +0000
committer Grace Cheng <graciecheng@google.com> 2024-01-04 20:05:51 +0000
commit188b2bdd2623c46f17c316265cde4fdcf9afe59d (patch)
tree7d8877d8a8d81541548704f24f9d8b399e0e32d0
parentae34ea145b10c8473045612da483c813312c38ac (diff)
Fix race condition between PromptIconViewBinder and BiometricSizeBinder
Sets BiometricPrompt view invisible until all resizing is complete. Adds new MutableStateFlow updated on iconView onCompositionLoadedListener, and combines this new flow with the BiometricSizeBinder viewModel.size collect call, to force the resizing logic to wait for the iconAsset to update first to account for it in the prompt size. Reworking of ag/25666425 to avoid CTS failures the original CL caused Flag: NONE Fixes: 313605043 Bug: 317291041 Test: atest CtsBiometricsTestCases Test: (manual) manually verified prompt appears only once and in the correct size, no resizing visible to the user Change-Id: Ic3cbf1785737c19c5434030d45a73b2435328a71
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt9
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewSizeBinder.kt20
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/PromptIconViewBinder.kt50
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt22
4 files changed, 84 insertions, 17 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt
index 90e4a3821634..7b8cb829e03f 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt
@@ -77,6 +77,13 @@ object BiometricViewBinder {
applicationScope: CoroutineScope,
vibratorHelper: VibratorHelper,
): Spaghetti {
+ /**
+ * View is only set visible in BiometricViewSizeBinder once PromptSize is determined that
+ * accounts for iconView size, to prevent prompt resizing being visible to the user.
+ *
+ * TODO(b/288175072): May be able to remove this once constraint layout is implemented
+ */
+ view.visibility = View.INVISIBLE
val accessibilityManager = view.context.getSystemService(AccessibilityManager::class.java)!!
val textColorError =
@@ -102,7 +109,7 @@ object BiometricViewBinder {
iconView,
iconOverlayView,
view.getUpdatedFingerprintAffordanceSize(),
- viewModel.iconViewModel
+ viewModel
)
val indicatorMessageView = view.requireViewById<TextView>(R.id.indicator)
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewSizeBinder.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewSizeBinder.kt
index 7e16d1e1d668..1a7b6c974d0c 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewSizeBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewSizeBinder.kt
@@ -30,7 +30,6 @@ import androidx.core.animation.addListener
import androidx.core.view.doOnLayout
import androidx.core.view.isGone
import androidx.lifecycle.lifecycleScope
-import com.android.systemui.res.R
import com.android.systemui.biometrics.AuthPanelController
import com.android.systemui.biometrics.Utils
import com.android.systemui.biometrics.ui.BiometricPromptLayout
@@ -41,6 +40,8 @@ import com.android.systemui.biometrics.ui.viewmodel.isMedium
import com.android.systemui.biometrics.ui.viewmodel.isNullOrNotSmall
import com.android.systemui.biometrics.ui.viewmodel.isSmall
import com.android.systemui.lifecycle.repeatWhenAttached
+import com.android.systemui.res.R
+import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.launch
/** Helper for [BiometricViewBinder] to handle resize transitions. */
@@ -93,7 +94,20 @@ object BiometricViewSizeBinder {
view.repeatWhenAttached {
var currentSize: PromptSize? = null
lifecycleScope.launch {
- viewModel.size.collect { size ->
+ /**
+ * View is only set visible in BiometricViewSizeBinder once PromptSize is
+ * determined that accounts for iconView size, to prevent prompt resizing being
+ * visible to the user.
+ *
+ * TODO(b/288175072): May be able to remove isIconViewLoaded once constraint
+ * layout is implemented
+ */
+ combine(viewModel.isIconViewLoaded, viewModel.size, ::Pair).collect {
+ (isIconViewLoaded, size) ->
+ if (!isIconViewLoaded) {
+ return@collect
+ }
+
// prepare for animated size transitions
for (v in viewsToHideWhenSmall) {
v.showTextOrHide(forceHide = size.isSmall)
@@ -198,6 +212,8 @@ object BiometricViewSizeBinder {
}
currentSize = size
+ view.visibility = View.VISIBLE
+ viewModel.setIsIconViewLoaded(false)
notifyAccessibilityChanged()
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/PromptIconViewBinder.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/PromptIconViewBinder.kt
index 475ef18e5099..6e3bcf575072 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/PromptIconViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/PromptIconViewBinder.kt
@@ -26,6 +26,7 @@ import com.airbnb.lottie.LottieAnimationView
import com.android.settingslib.widget.LottieColorUtils
import com.android.systemui.biometrics.ui.viewmodel.PromptIconViewModel
import com.android.systemui.biometrics.ui.viewmodel.PromptIconViewModel.AuthType
+import com.android.systemui.biometrics.ui.viewmodel.PromptViewModel
import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.util.kotlin.Utils.Companion.toQuad
import com.android.systemui.util.kotlin.Utils.Companion.toQuint
@@ -45,8 +46,9 @@ object PromptIconViewBinder {
iconView: LottieAnimationView,
iconOverlayView: LottieAnimationView,
iconViewLayoutParamSizeOverride: Pair<Int, Int>?,
- viewModel: PromptIconViewModel
+ promptViewModel: PromptViewModel
) {
+ val viewModel = promptViewModel.iconViewModel
iconView.repeatWhenAttached {
repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.onConfigurationChanged(iconView.context.resources.configuration)
@@ -71,25 +73,45 @@ object PromptIconViewBinder {
}
launch {
+ var width: Int
+ var height: Int
viewModel.activeAuthType.collect { activeAuthType ->
- if (iconViewLayoutParamSizeOverride == null) {
- val width: Int
- val height: Int
- when (activeAuthType) {
- AuthType.Fingerprint,
- AuthType.Coex -> {
- width = viewModel.fingerprintIconWidth
- height = viewModel.fingerprintIconHeight
- }
- AuthType.Face -> {
- width = viewModel.faceIconWidth
- height = viewModel.faceIconHeight
+ when (activeAuthType) {
+ AuthType.Fingerprint,
+ AuthType.Coex -> {
+ width = viewModel.fingerprintIconWidth
+ height = viewModel.fingerprintIconHeight
+
+ /**
+ * View is only set visible in BiometricViewSizeBinder once
+ * PromptSize is determined that accounts for iconView size, to
+ * prevent prompt resizing being visible to the user.
+ *
+ * TODO(b/288175072): May be able to remove this once constraint
+ * layout is implemented
+ */
+ iconView.removeAllLottieOnCompositionLoadedListener()
+ iconView.addLottieOnCompositionLoadedListener {
+ promptViewModel.setIsIconViewLoaded(true)
}
}
+ AuthType.Face -> {
+ width = viewModel.faceIconWidth
+ height = viewModel.faceIconHeight
+ /**
+ * Set to true by default since face icon is a drawable, which
+ * doesn't have a LottieOnCompositionLoadedListener equivalent.
+ *
+ * TODO(b/318569643): To be updated once face assets are updated
+ * from drawables
+ */
+ promptViewModel.setIsIconViewLoaded(true)
+ }
+ }
+ if (iconViewLayoutParamSizeOverride == null) {
iconView.layoutParams.width = width
iconView.layoutParams.height = height
-
iconOverlayView.layoutParams.width = width
iconOverlayView.layoutParams.height = height
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt
index 6d0a58e202bd..d899827ebb2e 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt
@@ -192,6 +192,28 @@ constructor(
val iconViewModel: PromptIconViewModel =
PromptIconViewModel(this, displayStateInteractor, promptSelectorInteractor)
+ private val _isIconViewLoaded = MutableStateFlow(false)
+
+ /**
+ * For prompts with an iconView, false until the prompt's iconView animation has been loaded in
+ * the view, otherwise true by default. Used for BiometricViewSizeBinder to wait for the icon
+ * asset to be loaded before determining the prompt size.
+ */
+ val isIconViewLoaded: Flow<Boolean> =
+ combine(credentialKind, _isIconViewLoaded.asStateFlow()) { credentialKind, isIconViewLoaded
+ ->
+ if (credentialKind is PromptKind.Biometric) {
+ isIconViewLoaded
+ } else {
+ true
+ }
+ }
+
+ // Sets whether the prompt's iconView animation has been loaded in the view yet.
+ fun setIsIconViewLoaded(iconViewLoaded: Boolean) {
+ _isIconViewLoaded.value = iconViewLoaded
+ }
+
/** Padding for prompt UI elements */
val promptPadding: Flow<Rect> =
combine(size, displayStateInteractor.currentRotation) { size, rotation ->