Loading packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java +41 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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); } Loading Loading @@ -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); } Loading packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java +7 −1 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -512,6 +513,9 @@ public class AuthContainerView extends LinearLayout @Override public void onOrientationChanged() { maybeUpdatePositionForUdfps(true /* invalidate */); if (mBiometricView != null) { mBiometricView.onOrientationChanged(); } } @Override Loading Loading @@ -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; Loading packages/SystemUI/src/com/android/systemui/biometrics/AuthPanelController.java +32 −3 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); } Loading @@ -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; Loading @@ -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: Loading @@ -113,6 +138,10 @@ public class AuthPanelController extends ViewOutlineProvider { mPosition = position; } public @Position int getPosition() { return mPosition; } public void setUseFullScreen(boolean fullScreen) { mUseFullScreen = fullScreen; } Loading packages/SystemUI/src/com/android/systemui/biometrics/Utils.kt +11 −0 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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 Loading packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt +15 −0 Original line number Diff line number Diff line Loading @@ -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() = Loading Loading
packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java +41 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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); } Loading Loading @@ -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); } Loading
packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java +7 −1 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -512,6 +513,9 @@ public class AuthContainerView extends LinearLayout @Override public void onOrientationChanged() { maybeUpdatePositionForUdfps(true /* invalidate */); if (mBiometricView != null) { mBiometricView.onOrientationChanged(); } } @Override Loading Loading @@ -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; Loading
packages/SystemUI/src/com/android/systemui/biometrics/AuthPanelController.java +32 −3 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); } Loading @@ -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; Loading @@ -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: Loading @@ -113,6 +138,10 @@ public class AuthPanelController extends ViewOutlineProvider { mPosition = position; } public @Position int getPosition() { return mPosition; } public void setUseFullScreen(boolean fullScreen) { mUseFullScreen = fullScreen; } Loading
packages/SystemUI/src/com/android/systemui/biometrics/Utils.kt +11 −0 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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 Loading
packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt +15 −0 Original line number Diff line number Diff line Loading @@ -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() = Loading