diff options
| author | 2023-12-20 19:55:55 +0000 | |
|---|---|---|
| committer | 2023-12-20 19:55:55 +0000 | |
| commit | aa4f3398b58bafb8e0d4a68e63132eedbe61740c (patch) | |
| tree | 6dcf125eca54c9533ba903ea79b9a34db34f44b6 | |
| parent | b762c91eec7852c37a918895b70359d80400e321 (diff) | |
| parent | 0d1ba636d12d8cf3e37bcf8fe1ad82e0e4503843 (diff) | |
Merge "Fix race condition between PromptIconViewBinder and BiometricSizeBinder" into main
4 files changed, 55 insertions, 4 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java index ab23564a1df4..83d415fa936e 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 @@ public class AuthContainerView extends LinearLayout 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 90e4a3821634..a7fb6f72a41e 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 @@ object BiometricViewBinder { 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 7e16d1e1d668..f340bd81f951 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. */ @@ -92,8 +93,22 @@ object BiometricViewSizeBinder { // 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 @@ object BiometricViewSizeBinder { } } } - 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 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 -> |