Loading packages/SystemUI/res/layout/biometric_prompt_constraint_layout.xml +1 −1 Original line number Diff line number Diff line Loading @@ -47,7 +47,7 @@ android:layout_height="wrap_content" android:fillViewport="true" android:fadeScrollbars="false" android:paddingBottom="36dp" android:paddingBottom="24dp" android:paddingHorizontal="24dp" android:paddingTop="24dp" app:layout_constrainedHeight="true" Loading packages/SystemUI/res/values/dimens.xml +3 −3 Original line number Diff line number Diff line Loading @@ -1094,9 +1094,9 @@ <dimen name="remote_input_history_extra_height">60dp</dimen> <!-- Biometric Dialog values --> <dimen name="biometric_dialog_face_icon_size">54dp</dimen> <dimen name="biometric_dialog_fingerprint_icon_width">80dp</dimen> <dimen name="biometric_dialog_fingerprint_icon_height">80dp</dimen> <dimen name="biometric_dialog_face_icon_size">68dp</dimen> <dimen name="biometric_dialog_fingerprint_icon_width">100dp</dimen> <dimen name="biometric_dialog_fingerprint_icon_height">100dp</dimen> <dimen name="biometric_dialog_button_negative_max_width">160dp</dimen> <dimen name="biometric_dialog_button_positive_max_width">136dp</dimen> <dimen name="biometric_dialog_corner_size">28dp</dimen> Loading packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java +6 −2 Original line number Diff line number Diff line Loading @@ -230,9 +230,13 @@ public class AuthContainerView extends LinearLayout @Override public void onUseDeviceCredential() { mConfig.mCallback.onDeviceCredentialPressed(getRequestId()); if (constraintBp()) { addCredentialView(false /* animatePanel */, true /* animateContents */); } else { mHandler.postDelayed(() -> { addCredentialView(false /* animatePanel */, true /* animateContents */); }, mConfig.mSkipAnimation ? 0 : ANIMATE_CREDENTIAL_START_DELAY_MS); } // TODO(b/313469218): Remove Config mConfig.mPromptInfo.setAuthenticators(Authenticators.DEVICE_CREDENTIAL); Loading packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt +12 −4 Original line number Diff line number Diff line Loading @@ -87,7 +87,9 @@ object BiometricViewBinder { * * TODO(b/288175072): May be able to remove this once constraint layout is implemented */ if (!constraintBp()) { view.visibility = View.INVISIBLE } val accessibilityManager = view.context.getSystemService(AccessibilityManager::class.java)!! val textColorError = Loading @@ -102,6 +104,12 @@ object BiometricViewBinder { val descriptionView = view.requireViewById<TextView>(R.id.description) val customizedViewContainer = view.requireViewById<LinearLayout>(R.id.customized_view_container) val udfpsGuidanceView = if (constraintBp()) { view.requireViewById<View>(R.id.panel) } else { backgroundView } // set selected to enable marquee unless a screen reader is enabled logoView.isSelected = Loading Loading @@ -226,8 +234,8 @@ object BiometricViewBinder { } lifecycleScope.launch { viewModel.showBpWithoutIconForCredential.collect { if (!it) { viewModel.showBpWithoutIconForCredential.collect { showWithoutIcon -> if (!showWithoutIcon) { PromptIconViewBinder.bind( iconView, iconOverlayView, Loading Loading @@ -428,7 +436,7 @@ object BiometricViewBinder { } // Talkback directional guidance backgroundView.setOnHoverListener { _, event -> udfpsGuidanceView.setOnHoverListener { _, event -> launch { viewModel.onAnnounceAccessibilityHint( event, Loading packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewSizeBinder.kt +228 −121 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import android.animation.Animator import android.animation.AnimatorSet import android.animation.ValueAnimator import android.graphics.Outline import android.graphics.Rect import android.transition.AutoTransition import android.transition.TransitionManager import android.util.TypedValue Loading @@ -36,7 +37,6 @@ import androidx.constraintlayout.widget.ConstraintLayout import androidx.constraintlayout.widget.ConstraintSet import androidx.constraintlayout.widget.Guideline import androidx.core.animation.addListener import androidx.core.view.doOnAttach import androidx.core.view.doOnLayout import androidx.core.view.isGone import androidx.lifecycle.lifecycleScope Loading Loading @@ -106,6 +106,52 @@ object BiometricViewSizeBinder { ) .toInt() var currentSize: PromptSize? = null var currentPosition: PromptPosition = PromptPosition.Bottom panelView.outlineProvider = object : ViewOutlineProvider() { override fun getOutline(view: View, outline: Outline) { when (currentPosition) { PromptPosition.Right -> { outline.setRoundRect( 0, 0, view.width + cornerRadiusPx, view.height, cornerRadiusPx.toFloat() ) } PromptPosition.Left -> { outline.setRoundRect( -cornerRadiusPx, 0, view.width, view.height, cornerRadiusPx.toFloat() ) } PromptPosition.Top -> { outline.setRoundRect( 0, -cornerRadiusPx, view.width, view.height, cornerRadiusPx.toFloat() ) } PromptPosition.Bottom -> { outline.setRoundRect( 0, 0, view.width, view.height + cornerRadiusPx, cornerRadiusPx.toFloat() ) } } } } // ConstraintSets for animating between prompt sizes val mediumConstraintSet = ConstraintSet() mediumConstraintSet.clone(view as ConstraintLayout) Loading @@ -115,7 +161,9 @@ object BiometricViewSizeBinder { val largeConstraintSet = ConstraintSet() largeConstraintSet.clone(mediumConstraintSet) largeConstraintSet.constrainMaxWidth(R.id.panel, view.width) largeConstraintSet.constrainMaxWidth(R.id.panel, 0) largeConstraintSet.setGuidelineBegin(R.id.leftGuideline, 0) largeConstraintSet.setGuidelineEnd(R.id.rightGuideline, 0) // TODO: Investigate better way to handle 180 rotations val flipConstraintSet = ConstraintSet() Loading @@ -138,65 +186,134 @@ object BiometricViewSizeBinder { } } fun roundCorners(size: PromptSize, position: PromptPosition) { var left = 0 var top = 0 var right = 0 var bottom = 0 when (size) { PromptSize.SMALL, PromptSize.MEDIUM -> when (position) { PromptPosition.Right -> { left = 0 top = 0 right = view.width + cornerRadiusPx bottom = view.height view.repeatWhenAttached { lifecycleScope.launch { viewModel.iconPosition.collect { position -> if (position != Rect()) { val iconParams = iconHolderView.layoutParams as ConstraintLayout.LayoutParams if (position.left != 0) { iconParams.endToEnd = ConstraintSet.UNSET iconParams.leftMargin = position.left mediumConstraintSet.clear( R.id.biometric_icon, ConstraintSet.END ) mediumConstraintSet.connect( R.id.biometric_icon, ConstraintSet.START, ConstraintSet.PARENT_ID, ConstraintSet.START ) mediumConstraintSet.setMargin( R.id.biometric_icon, ConstraintSet.START, position.left ) smallConstraintSet.clear(R.id.biometric_icon, ConstraintSet.END) smallConstraintSet.connect( R.id.biometric_icon, ConstraintSet.START, ConstraintSet.PARENT_ID, ConstraintSet.START ) smallConstraintSet.setMargin( R.id.biometric_icon, ConstraintSet.START, position.left ) } PromptPosition.Left -> { left = -cornerRadiusPx top = 0 right = view.width bottom = view.height if (position.top != 0) { iconParams.bottomToBottom = ConstraintSet.UNSET iconParams.topMargin = position.top mediumConstraintSet.clear( R.id.biometric_icon, ConstraintSet.BOTTOM ) mediumConstraintSet.setMargin( R.id.biometric_icon, ConstraintSet.TOP, position.top ) smallConstraintSet.clear( R.id.biometric_icon, ConstraintSet.BOTTOM ) smallConstraintSet.setMargin( R.id.biometric_icon, ConstraintSet.TOP, position.top ) } PromptPosition.Top -> { left = 0 top = -cornerRadiusPx right = panelView.width bottom = view.height if (position.right != 0) { iconParams.startToStart = ConstraintSet.UNSET iconParams.rightMargin = position.right mediumConstraintSet.clear( R.id.biometric_icon, ConstraintSet.START ) mediumConstraintSet.connect( R.id.biometric_icon, ConstraintSet.END, ConstraintSet.PARENT_ID, ConstraintSet.END ) mediumConstraintSet.setMargin( R.id.biometric_icon, ConstraintSet.END, position.right ) smallConstraintSet.clear( R.id.biometric_icon, ConstraintSet.START ) smallConstraintSet.connect( R.id.biometric_icon, ConstraintSet.END, ConstraintSet.PARENT_ID, ConstraintSet.END ) smallConstraintSet.setMargin( R.id.biometric_icon, ConstraintSet.END, position.right ) } PromptPosition.Bottom -> { left = 0 top = 0 right = panelView.width bottom = view.height + cornerRadiusPx if (position.bottom != 0) { iconParams.topToTop = ConstraintSet.UNSET iconParams.bottomMargin = position.bottom mediumConstraintSet.clear( R.id.biometric_icon, ConstraintSet.TOP ) mediumConstraintSet.setMargin( R.id.biometric_icon, ConstraintSet.BOTTOM, position.bottom ) smallConstraintSet.clear(R.id.biometric_icon, ConstraintSet.TOP) smallConstraintSet.setMargin( R.id.biometric_icon, ConstraintSet.BOTTOM, position.bottom ) } iconHolderView.layoutParams = iconParams } PromptSize.LARGE -> { left = 0 top = 0 right = view.width bottom = view.height } } // Round the panel outline panelView.outlineProvider = object : ViewOutlineProvider() { override fun getOutline(view: View, outline: Outline) { outline.setRoundRect( left, top, right, bottom, cornerRadiusPx.toFloat() lifecycleScope.launch { viewModel.iconSize.collect { iconSize -> iconHolderView.layoutParams.width = iconSize.first iconHolderView.layoutParams.height = iconSize.second mediumConstraintSet.constrainWidth(R.id.biometric_icon, iconSize.first) mediumConstraintSet.constrainHeight( R.id.biometric_icon, iconSize.second ) } } } view.repeatWhenAttached { var currentSize: PromptSize? = null lifecycleScope.launch { viewModel.guidelineBounds.collect { bounds -> Loading Loading @@ -249,7 +366,6 @@ object BiometricViewSizeBinder { lifecycleScope.launch { combine(viewModel.position, viewModel.size, ::Pair).collect { (position, size) -> view.doOnAttach { setVisibilities(size) if (position.isLeft) { Loading @@ -274,8 +390,6 @@ object BiometricViewSizeBinder { ) } roundCorners(size, position) when { size.isSmall -> { if (position.isLeft) { Loading @@ -290,10 +404,7 @@ object BiometricViewSizeBinder { ANIMATE_SMALL_TO_MEDIUM_DURATION_MS.toLong() ) TransitionManager.beginDelayedTransition( view, autoTransition ) TransitionManager.beginDelayedTransition(view, autoTransition) if (position.isLeft) { flipConstraintSet.applyTo(view) Loading @@ -308,32 +419,28 @@ object BiometricViewSizeBinder { mediumConstraintSet.applyTo(view) } } size.isLarge -> { size.isLarge && currentSize.isMedium -> { val autoTransition = AutoTransition() autoTransition.setDuration( ANIMATE_MEDIUM_TO_LARGE_DURATION_MS.toLong() ) TransitionManager.beginDelayedTransition( view, autoTransition ) TransitionManager.beginDelayedTransition(view, autoTransition) largeConstraintSet.applyTo(view) } } currentSize = size view.visibility = View.VISIBLE viewModel.setIsIconViewLoaded(false) currentPosition = position notifyAccessibilityChanged() panelView.invalidateOutline() view.invalidate() view.requestLayout() } } } } } } else if (panelViewController != null) { val iconHolderView = view.requireViewById<View>(R.id.biometric_icon_frame) val iconPadding = view.resources.getDimension(R.dimen.biometric_dialog_icon_padding) Loading Loading
packages/SystemUI/res/layout/biometric_prompt_constraint_layout.xml +1 −1 Original line number Diff line number Diff line Loading @@ -47,7 +47,7 @@ android:layout_height="wrap_content" android:fillViewport="true" android:fadeScrollbars="false" android:paddingBottom="36dp" android:paddingBottom="24dp" android:paddingHorizontal="24dp" android:paddingTop="24dp" app:layout_constrainedHeight="true" Loading
packages/SystemUI/res/values/dimens.xml +3 −3 Original line number Diff line number Diff line Loading @@ -1094,9 +1094,9 @@ <dimen name="remote_input_history_extra_height">60dp</dimen> <!-- Biometric Dialog values --> <dimen name="biometric_dialog_face_icon_size">54dp</dimen> <dimen name="biometric_dialog_fingerprint_icon_width">80dp</dimen> <dimen name="biometric_dialog_fingerprint_icon_height">80dp</dimen> <dimen name="biometric_dialog_face_icon_size">68dp</dimen> <dimen name="biometric_dialog_fingerprint_icon_width">100dp</dimen> <dimen name="biometric_dialog_fingerprint_icon_height">100dp</dimen> <dimen name="biometric_dialog_button_negative_max_width">160dp</dimen> <dimen name="biometric_dialog_button_positive_max_width">136dp</dimen> <dimen name="biometric_dialog_corner_size">28dp</dimen> Loading
packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java +6 −2 Original line number Diff line number Diff line Loading @@ -230,9 +230,13 @@ public class AuthContainerView extends LinearLayout @Override public void onUseDeviceCredential() { mConfig.mCallback.onDeviceCredentialPressed(getRequestId()); if (constraintBp()) { addCredentialView(false /* animatePanel */, true /* animateContents */); } else { mHandler.postDelayed(() -> { addCredentialView(false /* animatePanel */, true /* animateContents */); }, mConfig.mSkipAnimation ? 0 : ANIMATE_CREDENTIAL_START_DELAY_MS); } // TODO(b/313469218): Remove Config mConfig.mPromptInfo.setAuthenticators(Authenticators.DEVICE_CREDENTIAL); Loading
packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt +12 −4 Original line number Diff line number Diff line Loading @@ -87,7 +87,9 @@ object BiometricViewBinder { * * TODO(b/288175072): May be able to remove this once constraint layout is implemented */ if (!constraintBp()) { view.visibility = View.INVISIBLE } val accessibilityManager = view.context.getSystemService(AccessibilityManager::class.java)!! val textColorError = Loading @@ -102,6 +104,12 @@ object BiometricViewBinder { val descriptionView = view.requireViewById<TextView>(R.id.description) val customizedViewContainer = view.requireViewById<LinearLayout>(R.id.customized_view_container) val udfpsGuidanceView = if (constraintBp()) { view.requireViewById<View>(R.id.panel) } else { backgroundView } // set selected to enable marquee unless a screen reader is enabled logoView.isSelected = Loading Loading @@ -226,8 +234,8 @@ object BiometricViewBinder { } lifecycleScope.launch { viewModel.showBpWithoutIconForCredential.collect { if (!it) { viewModel.showBpWithoutIconForCredential.collect { showWithoutIcon -> if (!showWithoutIcon) { PromptIconViewBinder.bind( iconView, iconOverlayView, Loading Loading @@ -428,7 +436,7 @@ object BiometricViewBinder { } // Talkback directional guidance backgroundView.setOnHoverListener { _, event -> udfpsGuidanceView.setOnHoverListener { _, event -> launch { viewModel.onAnnounceAccessibilityHint( event, Loading
packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewSizeBinder.kt +228 −121 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import android.animation.Animator import android.animation.AnimatorSet import android.animation.ValueAnimator import android.graphics.Outline import android.graphics.Rect import android.transition.AutoTransition import android.transition.TransitionManager import android.util.TypedValue Loading @@ -36,7 +37,6 @@ import androidx.constraintlayout.widget.ConstraintLayout import androidx.constraintlayout.widget.ConstraintSet import androidx.constraintlayout.widget.Guideline import androidx.core.animation.addListener import androidx.core.view.doOnAttach import androidx.core.view.doOnLayout import androidx.core.view.isGone import androidx.lifecycle.lifecycleScope Loading Loading @@ -106,6 +106,52 @@ object BiometricViewSizeBinder { ) .toInt() var currentSize: PromptSize? = null var currentPosition: PromptPosition = PromptPosition.Bottom panelView.outlineProvider = object : ViewOutlineProvider() { override fun getOutline(view: View, outline: Outline) { when (currentPosition) { PromptPosition.Right -> { outline.setRoundRect( 0, 0, view.width + cornerRadiusPx, view.height, cornerRadiusPx.toFloat() ) } PromptPosition.Left -> { outline.setRoundRect( -cornerRadiusPx, 0, view.width, view.height, cornerRadiusPx.toFloat() ) } PromptPosition.Top -> { outline.setRoundRect( 0, -cornerRadiusPx, view.width, view.height, cornerRadiusPx.toFloat() ) } PromptPosition.Bottom -> { outline.setRoundRect( 0, 0, view.width, view.height + cornerRadiusPx, cornerRadiusPx.toFloat() ) } } } } // ConstraintSets for animating between prompt sizes val mediumConstraintSet = ConstraintSet() mediumConstraintSet.clone(view as ConstraintLayout) Loading @@ -115,7 +161,9 @@ object BiometricViewSizeBinder { val largeConstraintSet = ConstraintSet() largeConstraintSet.clone(mediumConstraintSet) largeConstraintSet.constrainMaxWidth(R.id.panel, view.width) largeConstraintSet.constrainMaxWidth(R.id.panel, 0) largeConstraintSet.setGuidelineBegin(R.id.leftGuideline, 0) largeConstraintSet.setGuidelineEnd(R.id.rightGuideline, 0) // TODO: Investigate better way to handle 180 rotations val flipConstraintSet = ConstraintSet() Loading @@ -138,65 +186,134 @@ object BiometricViewSizeBinder { } } fun roundCorners(size: PromptSize, position: PromptPosition) { var left = 0 var top = 0 var right = 0 var bottom = 0 when (size) { PromptSize.SMALL, PromptSize.MEDIUM -> when (position) { PromptPosition.Right -> { left = 0 top = 0 right = view.width + cornerRadiusPx bottom = view.height view.repeatWhenAttached { lifecycleScope.launch { viewModel.iconPosition.collect { position -> if (position != Rect()) { val iconParams = iconHolderView.layoutParams as ConstraintLayout.LayoutParams if (position.left != 0) { iconParams.endToEnd = ConstraintSet.UNSET iconParams.leftMargin = position.left mediumConstraintSet.clear( R.id.biometric_icon, ConstraintSet.END ) mediumConstraintSet.connect( R.id.biometric_icon, ConstraintSet.START, ConstraintSet.PARENT_ID, ConstraintSet.START ) mediumConstraintSet.setMargin( R.id.biometric_icon, ConstraintSet.START, position.left ) smallConstraintSet.clear(R.id.biometric_icon, ConstraintSet.END) smallConstraintSet.connect( R.id.biometric_icon, ConstraintSet.START, ConstraintSet.PARENT_ID, ConstraintSet.START ) smallConstraintSet.setMargin( R.id.biometric_icon, ConstraintSet.START, position.left ) } PromptPosition.Left -> { left = -cornerRadiusPx top = 0 right = view.width bottom = view.height if (position.top != 0) { iconParams.bottomToBottom = ConstraintSet.UNSET iconParams.topMargin = position.top mediumConstraintSet.clear( R.id.biometric_icon, ConstraintSet.BOTTOM ) mediumConstraintSet.setMargin( R.id.biometric_icon, ConstraintSet.TOP, position.top ) smallConstraintSet.clear( R.id.biometric_icon, ConstraintSet.BOTTOM ) smallConstraintSet.setMargin( R.id.biometric_icon, ConstraintSet.TOP, position.top ) } PromptPosition.Top -> { left = 0 top = -cornerRadiusPx right = panelView.width bottom = view.height if (position.right != 0) { iconParams.startToStart = ConstraintSet.UNSET iconParams.rightMargin = position.right mediumConstraintSet.clear( R.id.biometric_icon, ConstraintSet.START ) mediumConstraintSet.connect( R.id.biometric_icon, ConstraintSet.END, ConstraintSet.PARENT_ID, ConstraintSet.END ) mediumConstraintSet.setMargin( R.id.biometric_icon, ConstraintSet.END, position.right ) smallConstraintSet.clear( R.id.biometric_icon, ConstraintSet.START ) smallConstraintSet.connect( R.id.biometric_icon, ConstraintSet.END, ConstraintSet.PARENT_ID, ConstraintSet.END ) smallConstraintSet.setMargin( R.id.biometric_icon, ConstraintSet.END, position.right ) } PromptPosition.Bottom -> { left = 0 top = 0 right = panelView.width bottom = view.height + cornerRadiusPx if (position.bottom != 0) { iconParams.topToTop = ConstraintSet.UNSET iconParams.bottomMargin = position.bottom mediumConstraintSet.clear( R.id.biometric_icon, ConstraintSet.TOP ) mediumConstraintSet.setMargin( R.id.biometric_icon, ConstraintSet.BOTTOM, position.bottom ) smallConstraintSet.clear(R.id.biometric_icon, ConstraintSet.TOP) smallConstraintSet.setMargin( R.id.biometric_icon, ConstraintSet.BOTTOM, position.bottom ) } iconHolderView.layoutParams = iconParams } PromptSize.LARGE -> { left = 0 top = 0 right = view.width bottom = view.height } } // Round the panel outline panelView.outlineProvider = object : ViewOutlineProvider() { override fun getOutline(view: View, outline: Outline) { outline.setRoundRect( left, top, right, bottom, cornerRadiusPx.toFloat() lifecycleScope.launch { viewModel.iconSize.collect { iconSize -> iconHolderView.layoutParams.width = iconSize.first iconHolderView.layoutParams.height = iconSize.second mediumConstraintSet.constrainWidth(R.id.biometric_icon, iconSize.first) mediumConstraintSet.constrainHeight( R.id.biometric_icon, iconSize.second ) } } } view.repeatWhenAttached { var currentSize: PromptSize? = null lifecycleScope.launch { viewModel.guidelineBounds.collect { bounds -> Loading Loading @@ -249,7 +366,6 @@ object BiometricViewSizeBinder { lifecycleScope.launch { combine(viewModel.position, viewModel.size, ::Pair).collect { (position, size) -> view.doOnAttach { setVisibilities(size) if (position.isLeft) { Loading @@ -274,8 +390,6 @@ object BiometricViewSizeBinder { ) } roundCorners(size, position) when { size.isSmall -> { if (position.isLeft) { Loading @@ -290,10 +404,7 @@ object BiometricViewSizeBinder { ANIMATE_SMALL_TO_MEDIUM_DURATION_MS.toLong() ) TransitionManager.beginDelayedTransition( view, autoTransition ) TransitionManager.beginDelayedTransition(view, autoTransition) if (position.isLeft) { flipConstraintSet.applyTo(view) Loading @@ -308,32 +419,28 @@ object BiometricViewSizeBinder { mediumConstraintSet.applyTo(view) } } size.isLarge -> { size.isLarge && currentSize.isMedium -> { val autoTransition = AutoTransition() autoTransition.setDuration( ANIMATE_MEDIUM_TO_LARGE_DURATION_MS.toLong() ) TransitionManager.beginDelayedTransition( view, autoTransition ) TransitionManager.beginDelayedTransition(view, autoTransition) largeConstraintSet.applyTo(view) } } currentSize = size view.visibility = View.VISIBLE viewModel.setIsIconViewLoaded(false) currentPosition = position notifyAccessibilityChanged() panelView.invalidateOutline() view.invalidate() view.requestLayout() } } } } } } else if (panelViewController != null) { val iconHolderView = view.requireViewById<View>(R.id.biometric_icon_frame) val iconPadding = view.resources.getDimension(R.dimen.biometric_dialog_icon_padding) Loading