diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java index e089fd32829d0..4db371bed5178 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java @@ -28,6 +28,7 @@ import android.annotation.Nullable; import android.annotation.StringRes; import android.content.Context; import android.content.res.Configuration; +import android.graphics.Insets; import android.hardware.biometrics.BiometricAuthenticator.Modality; import android.hardware.biometrics.BiometricPrompt; import android.hardware.biometrics.PromptInfo; @@ -298,9 +299,25 @@ public abstract class AuthBiometricView extends LinearLayout { mJankListener = jankListener; } + private void updatePaddings(int size) { + final Insets navBarInsets = Utils.getNavbarInsets(mContext); + if (size != AuthDialog.SIZE_LARGE) { + if (mPanelController.getPosition() == AuthPanelController.POSITION_LEFT) { + setPadding(navBarInsets.left, 0, 0, 0); + } else if (mPanelController.getPosition() == AuthPanelController.POSITION_RIGHT) { + setPadding(0, 0, navBarInsets.right, 0); + } else { + setPadding(0, 0, 0, navBarInsets.bottom); + } + } else { + setPadding(0, 0, 0, 0); + } + } + @VisibleForTesting final void updateSize(@AuthDialog.DialogSize int newSize) { Log.v(TAG, "Current size: " + mSize + " New size: " + newSize); + updatePaddings(newSize); if (newSize == AuthDialog.SIZE_SMALL) { mTitleView.setVisibility(View.GONE); mSubtitleView.setVisibility(View.GONE); @@ -527,6 +544,11 @@ public abstract class AuthBiometricView extends LinearLayout { mState = newState; } + void onOrientationChanged() { + // Update padding and AuthPanel outline by calling updateSize when the orientation changed. + updateSize(mSize); + } + public void onDialogAnimatedIn() { updateState(STATE_AUTHENTICATING); } @@ -868,6 +890,25 @@ public abstract class AuthBiometricView extends LinearLayout { } mLayoutParams = onMeasureInternal(width, height); + + final Insets navBarInsets = Utils.getNavbarInsets(mContext); + final int navBarHeight = navBarInsets.bottom; + final int navBarWidth; + if (mPanelController.getPosition() == AuthPanelController.POSITION_LEFT) { + navBarWidth = navBarInsets.left; + } else if (mPanelController.getPosition() == AuthPanelController.POSITION_RIGHT) { + navBarWidth = navBarInsets.right; + } else { + navBarWidth = 0; + } + + // The actual auth dialog w/h should include navigation bar size. + if (navBarWidth != 0 || navBarHeight != 0) { + mLayoutParams = new AuthDialog.LayoutParams( + mLayoutParams.mMediumWidth + navBarWidth, + mLayoutParams.mMediumHeight + navBarInsets.bottom); + } + setMeasuredDimension(mLayoutParams.mMediumWidth, mLayoutParams.mMediumHeight); } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java index ce85124fa7a76..e775c2e2a3fab 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java @@ -19,6 +19,7 @@ package com.android.systemui.biometrics; import static android.hardware.biometrics.BiometricManager.BIOMETRIC_MULTI_SENSOR_DEFAULT; import static android.hardware.biometrics.BiometricManager.BiometricMultiSensorMode; import static android.hardware.biometrics.SensorProperties.STRENGTH_STRONG; +import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; import static com.android.internal.jank.InteractionJankMonitor.CUJ_BIOMETRIC_PROMPT_TRANSITION; @@ -512,6 +513,9 @@ public class AuthContainerView extends LinearLayout @Override public void onOrientationChanged() { maybeUpdatePositionForUdfps(true /* invalidate */); + if (mBiometricView != null) { + mBiometricView.onOrientationChanged(); + } } @Override @@ -899,7 +903,9 @@ public class AuthContainerView extends LinearLayout windowFlags, PixelFormat.TRANSLUCENT); lp.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS; - lp.setFitInsetsTypes(lp.getFitInsetsTypes() & ~WindowInsets.Type.ime()); + lp.setFitInsetsTypes(lp.getFitInsetsTypes() & ~WindowInsets.Type.ime() + & ~WindowInsets.Type.systemBars()); + lp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; lp.setTitle("BiometricPrompt"); lp.accessibilityTitle = title; lp.dimAmount = BACKGROUND_DIM_AMOUNT; diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthPanelController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthPanelController.java index 5c616f005d4d9..ad100716eceb7 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthPanelController.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthPanelController.java @@ -20,6 +20,7 @@ import android.animation.AnimatorSet; import android.animation.ValueAnimator; import android.annotation.IntDef; import android.content.Context; +import android.graphics.Insets; import android.graphics.Outline; import android.util.Log; import android.view.View; @@ -64,13 +65,12 @@ public class AuthPanelController extends ViewOutlineProvider { @Override public void getOutline(View view, Outline outline) { final int left = getLeftBound(mPosition); - final int right = left + mContentWidth; + final int right = getRightBound(mPosition, left); // If the content fits in the container, shrink the height to wrap it. Otherwise, expand to // fill the display (minus the margin), since the content is scrollable. final int top = getTopBound(mPosition); - final int bottom = Math.min(top + mContentHeight, mContainerHeight - mMargin); - + final int bottom = getBottomBound(top); outline.setRoundRect(left, top, right, bottom, mCornerRadius); } @@ -79,6 +79,10 @@ public class AuthPanelController extends ViewOutlineProvider { case POSITION_BOTTOM: return (mContainerWidth - mContentWidth) / 2; case POSITION_LEFT: + if (!mUseFullScreen) { + final Insets navBarInsets = Utils.getNavbarInsets(mContext); + return mMargin + navBarInsets.left; + } return mMargin; case POSITION_RIGHT: return mContainerWidth - mContentWidth - mMargin; @@ -88,6 +92,27 @@ public class AuthPanelController extends ViewOutlineProvider { } } + private int getRightBound(@Position int position, int left) { + if (!mUseFullScreen) { + final Insets navBarInsets = Utils.getNavbarInsets(mContext); + if (position == POSITION_RIGHT) { + return left + mContentWidth - navBarInsets.right; + } else if (position == POSITION_LEFT) { + return left + mContentWidth - navBarInsets.left; + } + } + return left + mContentWidth; + } + + private int getBottomBound(int top) { + if (!mUseFullScreen) { + final Insets navBarInsets = Utils.getNavbarInsets(mContext); + return Math.min(top + mContentHeight - navBarInsets.bottom, + mContainerHeight - mMargin - navBarInsets.bottom); + } + return Math.min(top + mContentHeight, mContainerHeight - mMargin); + } + private int getTopBound(@Position int position) { switch (position) { case POSITION_BOTTOM: @@ -113,6 +138,10 @@ public class AuthPanelController extends ViewOutlineProvider { mPosition = position; } + public @Position int getPosition() { + return mPosition; + } + public void setUseFullScreen(boolean fullScreen) { mUseFullScreen = fullScreen; } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/Utils.kt b/packages/SystemUI/src/com/android/systemui/biometrics/Utils.kt index d0d6f4cbf166a..b538085fa40de 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/Utils.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/Utils.kt @@ -26,13 +26,16 @@ import android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX import android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_SOMETHING import android.content.Context import android.content.pm.PackageManager +import android.graphics.Insets import android.hardware.biometrics.BiometricManager.Authenticators import android.hardware.biometrics.PromptInfo import android.hardware.biometrics.SensorPropertiesInternal import android.os.UserManager import android.util.DisplayMetrics import android.view.ViewGroup +import android.view.WindowInsets import android.view.WindowManager +import android.view.WindowMetrics import android.view.accessibility.AccessibilityEvent import android.view.accessibility.AccessibilityManager import com.android.internal.widget.LockPatternUtils @@ -114,6 +117,14 @@ object Utils { return hasPermission && "android" == clientPackage } + @JvmStatic + fun getNavbarInsets(context: Context): Insets { + val windowManager: WindowManager? = context.getSystemService(WindowManager::class.java) + val windowMetrics: WindowMetrics? = windowManager?.maximumWindowMetrics + return windowMetrics?.windowInsets?.getInsets(WindowInsets.Type.navigationBars()) + ?: Insets.NONE + } + @Retention(RetentionPolicy.SOURCE) @IntDef(CREDENTIAL_PIN, CREDENTIAL_PATTERN, CREDENTIAL_PASSWORD) internal annotation class CredentialType diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt index a361bbc69ef3b..9d68cf3aee017 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt @@ -504,6 +504,21 @@ class AuthContainerViewTest : SysuiTestCase() { waitForIdleSync() assertThat(isAttachedToWindow()).isTrue() } + + @Test + fun testLayoutParams_hasCutoutModeAlwaysFlag() { + val layoutParams = AuthContainerView.getLayoutParams(windowToken, "") + val lpFlags = layoutParams.flags + + assertThat((lpFlags and WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS) + != 0).isTrue() + } + + @Test + fun testLayoutParams_excludesSystemBarInsets() { + val layoutParams = AuthContainerView.getLayoutParams(windowToken, "") + assertThat((layoutParams.fitInsetsTypes and WindowInsets.Type.systemBars()) == 0).isTrue() + } } private fun AuthContainerView.hasBiometricPrompt() =