Merge "Make auth dialog in large size expand into cutout area" into udc-dev

This commit is contained in:
Shawn Lin
2023-05-17 06:31:10 +00:00
committed by Android (Google) Code Review
5 changed files with 106 additions and 4 deletions

View File

@@ -28,6 +28,7 @@ import android.annotation.Nullable;
import android.annotation.StringRes; import android.annotation.StringRes;
import android.content.Context; import android.content.Context;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.graphics.Insets;
import android.hardware.biometrics.BiometricAuthenticator.Modality; import android.hardware.biometrics.BiometricAuthenticator.Modality;
import android.hardware.biometrics.BiometricPrompt; import android.hardware.biometrics.BiometricPrompt;
import android.hardware.biometrics.PromptInfo; import android.hardware.biometrics.PromptInfo;
@@ -298,9 +299,25 @@ public abstract class AuthBiometricView extends LinearLayout {
mJankListener = jankListener; 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 @VisibleForTesting
final void updateSize(@AuthDialog.DialogSize int newSize) { final void updateSize(@AuthDialog.DialogSize int newSize) {
Log.v(TAG, "Current size: " + mSize + " New size: " + newSize); Log.v(TAG, "Current size: " + mSize + " New size: " + newSize);
updatePaddings(newSize);
if (newSize == AuthDialog.SIZE_SMALL) { if (newSize == AuthDialog.SIZE_SMALL) {
mTitleView.setVisibility(View.GONE); mTitleView.setVisibility(View.GONE);
mSubtitleView.setVisibility(View.GONE); mSubtitleView.setVisibility(View.GONE);
@@ -527,6 +544,11 @@ public abstract class AuthBiometricView extends LinearLayout {
mState = newState; mState = newState;
} }
void onOrientationChanged() {
// Update padding and AuthPanel outline by calling updateSize when the orientation changed.
updateSize(mSize);
}
public void onDialogAnimatedIn() { public void onDialogAnimatedIn() {
updateState(STATE_AUTHENTICATING); updateState(STATE_AUTHENTICATING);
} }
@@ -868,6 +890,25 @@ public abstract class AuthBiometricView extends LinearLayout {
} }
mLayoutParams = onMeasureInternal(width, height); 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); setMeasuredDimension(mLayoutParams.mMediumWidth, mLayoutParams.mMediumHeight);
} }

View File

@@ -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.BIOMETRIC_MULTI_SENSOR_DEFAULT;
import static android.hardware.biometrics.BiometricManager.BiometricMultiSensorMode; import static android.hardware.biometrics.BiometricManager.BiometricMultiSensorMode;
import static android.hardware.biometrics.SensorProperties.STRENGTH_STRONG; 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; import static com.android.internal.jank.InteractionJankMonitor.CUJ_BIOMETRIC_PROMPT_TRANSITION;
@@ -512,6 +513,9 @@ public class AuthContainerView extends LinearLayout
@Override @Override
public void onOrientationChanged() { public void onOrientationChanged() {
maybeUpdatePositionForUdfps(true /* invalidate */); maybeUpdatePositionForUdfps(true /* invalidate */);
if (mBiometricView != null) {
mBiometricView.onOrientationChanged();
}
} }
@Override @Override
@@ -899,7 +903,9 @@ public class AuthContainerView extends LinearLayout
windowFlags, windowFlags,
PixelFormat.TRANSLUCENT); PixelFormat.TRANSLUCENT);
lp.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS; 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.setTitle("BiometricPrompt");
lp.accessibilityTitle = title; lp.accessibilityTitle = title;
lp.dimAmount = BACKGROUND_DIM_AMOUNT; lp.dimAmount = BACKGROUND_DIM_AMOUNT;

View File

@@ -20,6 +20,7 @@ import android.animation.AnimatorSet;
import android.animation.ValueAnimator; import android.animation.ValueAnimator;
import android.annotation.IntDef; import android.annotation.IntDef;
import android.content.Context; import android.content.Context;
import android.graphics.Insets;
import android.graphics.Outline; import android.graphics.Outline;
import android.util.Log; import android.util.Log;
import android.view.View; import android.view.View;
@@ -64,13 +65,12 @@ public class AuthPanelController extends ViewOutlineProvider {
@Override @Override
public void getOutline(View view, Outline outline) { public void getOutline(View view, Outline outline) {
final int left = getLeftBound(mPosition); 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 // 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. // fill the display (minus the margin), since the content is scrollable.
final int top = getTopBound(mPosition); 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); outline.setRoundRect(left, top, right, bottom, mCornerRadius);
} }
@@ -79,6 +79,10 @@ public class AuthPanelController extends ViewOutlineProvider {
case POSITION_BOTTOM: case POSITION_BOTTOM:
return (mContainerWidth - mContentWidth) / 2; return (mContainerWidth - mContentWidth) / 2;
case POSITION_LEFT: case POSITION_LEFT:
if (!mUseFullScreen) {
final Insets navBarInsets = Utils.getNavbarInsets(mContext);
return mMargin + navBarInsets.left;
}
return mMargin; return mMargin;
case POSITION_RIGHT: case POSITION_RIGHT:
return mContainerWidth - mContentWidth - mMargin; 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) { private int getTopBound(@Position int position) {
switch (position) { switch (position) {
case POSITION_BOTTOM: case POSITION_BOTTOM:
@@ -113,6 +138,10 @@ public class AuthPanelController extends ViewOutlineProvider {
mPosition = position; mPosition = position;
} }
public @Position int getPosition() {
return mPosition;
}
public void setUseFullScreen(boolean fullScreen) { public void setUseFullScreen(boolean fullScreen) {
mUseFullScreen = fullScreen; mUseFullScreen = fullScreen;
} }

View File

@@ -26,13 +26,16 @@ import android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX
import android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_SOMETHING import android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_SOMETHING
import android.content.Context import android.content.Context
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.graphics.Insets
import android.hardware.biometrics.BiometricManager.Authenticators import android.hardware.biometrics.BiometricManager.Authenticators
import android.hardware.biometrics.PromptInfo import android.hardware.biometrics.PromptInfo
import android.hardware.biometrics.SensorPropertiesInternal import android.hardware.biometrics.SensorPropertiesInternal
import android.os.UserManager import android.os.UserManager
import android.util.DisplayMetrics import android.util.DisplayMetrics
import android.view.ViewGroup import android.view.ViewGroup
import android.view.WindowInsets
import android.view.WindowManager import android.view.WindowManager
import android.view.WindowMetrics
import android.view.accessibility.AccessibilityEvent import android.view.accessibility.AccessibilityEvent
import android.view.accessibility.AccessibilityManager import android.view.accessibility.AccessibilityManager
import com.android.internal.widget.LockPatternUtils import com.android.internal.widget.LockPatternUtils
@@ -114,6 +117,14 @@ object Utils {
return hasPermission && "android" == clientPackage 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) @Retention(RetentionPolicy.SOURCE)
@IntDef(CREDENTIAL_PIN, CREDENTIAL_PATTERN, CREDENTIAL_PASSWORD) @IntDef(CREDENTIAL_PIN, CREDENTIAL_PATTERN, CREDENTIAL_PASSWORD)
internal annotation class CredentialType internal annotation class CredentialType

View File

@@ -504,6 +504,21 @@ class AuthContainerViewTest : SysuiTestCase() {
waitForIdleSync() waitForIdleSync()
assertThat(isAttachedToWindow()).isTrue() 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() = private fun AuthContainerView.hasBiometricPrompt() =