Merge "Fix race condition between PromptIconViewBinder and BiometricSizeBinder" into main
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
index ab23564..83d415f 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
@@ -403,6 +403,13 @@
final BiometricPromptLayout view = (BiometricPromptLayout) layoutInflater.inflate(
R.layout.biometric_prompt_layout, null, false);
+ /**
+ * 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.setVisibility(View.INVISIBLE);
mBiometricView = BiometricViewBinder.bind(view, viewModel, mPanelController,
// TODO(b/201510778): This uses the wrong timeout in some cases
getJankListener(view, TRANSIT,
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 90e4a38..a7fb6f7 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
@@ -97,7 +97,13 @@
val iconOverlayView = view.requireViewById<LottieAnimationView>(R.id.biometric_icon_overlay)
val iconView = view.requireViewById<LottieAnimationView>(R.id.biometric_icon)
-
+ /**
+ * 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.addLottieOnCompositionLoadedListener { viewModel.setIsIconViewLoaded(true) }
PromptIconViewBinder.bind(
iconView,
iconOverlayView,
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 7e16d1e..f340bd8 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.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.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. */
@@ -92,8 +93,22 @@
// TODO(b/251476085): migrate the legacy panel controller and simplify this
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)
@@ -196,8 +211,9 @@
}
}
}
-
currentSize = size
+ view.visibility = View.VISIBLE
+ viewModel.setIsIconViewLoaded(false)
notifyAccessibilityChanged()
}
}
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 6d0a58e..d899827e 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 @@
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 ->