Adjust UDFPS prompt for 3-button nav and landscape

Modifies the layout of BiometricPrompt for under-display fingerprint
sensors so that the fingerprint icon is aligned with the sensor when the
device is in the landscape orientation and/or using 3-button navigation.

Test: atest AuthBiometricViewTest
Test: Manually, using the biometric integration test app

Bug: 179044674
Change-Id: I4da075b4cbf8b7119c071361336ddebd0a505ce0
This commit is contained in:
Curtis Belmonte
2021-03-03 10:51:49 -08:00
parent 7660d7402d
commit 0c7065912d
7 changed files with 367 additions and 85 deletions

View File

@@ -39,37 +39,34 @@
<Space android:id="@+id/space_above_icon"
android:layout_width="match_parent"
android:layout_height="48dp"
android:visibility="visible" />
android:layout_height="48dp" />
<!-- Use a frame layout since certain biometrics (such as UDFPS) require the icon to be centered
within a certain area on the display. This makes it easy to 1) guarantee max size, and
2) center the icon within the reserved area. -->
<FrameLayout android:id="@+id/biometric_icon_frame"
<FrameLayout
android:id="@+id/biometric_icon_frame"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal">
<ImageView
android:id="@+id/biometric_icon"
android:layout_width="@dimen/biometric_dialog_biometric_icon_size"
android:layout_height="@dimen/biometric_dialog_biometric_icon_size"
android:layout_gravity="center"
android:scaleType="fitXY" />
</FrameLayout>
<!-- For sensors such as UDFPS, this view is used during custom measurement/layoutto add extra
<!-- For sensors such as UDFPS, this view is used during custom measurement/layout to add extra
padding so that the biometric icon is always in the right physical position. -->
<Space android:id="@+id/space_below_icon"
android:layout_width="match_parent"
android:layout_height="0dp"
android:visibility="gone" />
android:layout_height="12dp" />
<TextView
android:id="@+id/indicator"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingHorizontal="24dp"
android:paddingVertical="12dp"
android:textSize="12sp"
android:gravity="center_horizontal"
android:accessibilityLiveRegion="polite"
@@ -84,6 +81,7 @@
style="?android:attr/buttonBarStyle"
android:orientation="horizontal"
android:paddingTop="16dp">
<Space android:id="@+id/leftSpacer"
android:layout_width="8dp"
android:layout_height="match_parent"

View File

@@ -244,6 +244,8 @@
<item name="android:paddingTop">12dp</item>
<item name="android:paddingHorizontal">24dp</item>
<item name="android:textSize">24sp</item>
<item name="android:singleLine">true</item>
<item name="android:ellipsize">marquee</item>
</style>
<style name="TextAppearance.AuthCredential.Subtitle">
@@ -251,6 +253,8 @@
<item name="android:paddingTop">8dp</item>
<item name="android:paddingHorizontal">24dp</item>
<item name="android:textSize">16sp</item>
<item name="android:singleLine">true</item>
<item name="android:ellipsize">marquee</item>
</style>
<style name="TextAppearance.AuthCredential.Description">
@@ -258,6 +262,8 @@
<item name="android:paddingTop">8dp</item>
<item name="android:paddingHorizontal">24dp</item>
<item name="android:textSize">14sp</item>
<item name="android:singleLine">true</item>
<item name="android:ellipsize">marquee</item>
</style>
<style name="TextAppearance.AuthCredential.Error">

View File

@@ -16,17 +16,22 @@
package com.android.systemui.biometrics;
import android.annotation.IdRes;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.graphics.Insets;
import android.graphics.Rect;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Surface;
import android.view.View;
import android.view.WindowInsets;
import android.view.WindowManager;
import android.widget.FrameLayout;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.R;
/**
@@ -51,53 +56,38 @@ public class AuthBiometricUdfpsView extends AuthBiometricFingerprintView {
mSensorProps = prop;
}
/**
* For devices where the sensor is too high up, calculates the amount of padding necessary to
* move/center the biometric icon within the sensor's physical location.
*/
static int calculateBottomSpacerHeight(int displayHeightPx, int navbarHeightPx,
int dialogBottomMarginPx, @NonNull View buttonBar, @NonNull View textIndicator,
@NonNull FingerprintSensorPropertiesInternal sensorProperties) {
final int sensorDistanceFromBottom = displayHeightPx - sensorProperties.sensorLocationY
- sensorProperties.sensorRadius;
final int spacerHeight = sensorDistanceFromBottom
- textIndicator.getMeasuredHeight()
- buttonBar.getMeasuredHeight()
- dialogBottomMarginPx
- navbarHeightPx;
Log.d(TAG, "Display height: " + displayHeightPx
+ ", Distance from bottom: " + sensorDistanceFromBottom
+ ", Bottom margin: " + dialogBottomMarginPx
+ ", Navbar height: " + navbarHeightPx
+ ", Spacer height: " + spacerHeight);
return spacerHeight;
@Override
@NonNull
AuthDialog.LayoutParams onMeasureInternal(int width, int height) {
final int displayRotation = getDisplay().getRotation();
switch (displayRotation) {
case Surface.ROTATION_0:
return onMeasureInternalPortrait(width, height);
case Surface.ROTATION_90:
case Surface.ROTATION_270:
return onMeasureInternalLandscape(width, height);
default:
Log.e(TAG, "Unsupported display rotation: " + displayRotation);
return super.onMeasureInternal(width, height);
}
}
@Override
AuthDialog.LayoutParams onMeasureInternal(int width, int height) {
final View spaceBelowIcon = findViewById(R.id.space_below_icon);
spaceBelowIcon.setVisibility(View.VISIBLE);
@NonNull
private AuthDialog.LayoutParams onMeasureInternalPortrait(int width, int height) {
// Get the height of the everything below the icon. Currently, that's the indicator and
// button bar
final View textIndicator = findViewById(R.id.indicator);
final View buttonBar = findViewById(R.id.button_bar);
// button bar.
final int textIndicatorHeight = getViewHeightPx(R.id.indicator);
final int buttonBarHeight = getViewHeightPx(R.id.button_bar);
// Figure out where the bottom of the sensor anim should be.
// Navbar + dialogMargin + buttonBar + textIndicator + spacerHeight = sensorDistFromBottom
final int dialogBottomMarginPx = getResources()
.getDimensionPixelSize(R.dimen.biometric_dialog_border_padding);
final WindowManager wm = getContext().getSystemService(WindowManager.class);
final Rect bounds = wm.getCurrentWindowMetrics().getBounds();
final int navbarHeight = wm.getCurrentWindowMetrics().getWindowInsets()
.getInsets(WindowInsets.Type.navigationBars()).toRect().height();
final int displayHeight = bounds.height();
final int spacerHeight = calculateBottomSpacerHeight(displayHeight, navbarHeight,
dialogBottomMarginPx, buttonBar, textIndicator, mSensorProps);
final int dialogMargin = getDialogMarginPx();
final WindowManager windowManager = getContext().getSystemService(WindowManager.class);
final int displayHeight = getWindowBounds(windowManager).height();
final Insets navbarInsets = getNavbarInsets(windowManager);
final int bottomSpacerHeight = calculateBottomSpacerHeightForPortrait(
mSensorProps, displayHeight, textIndicatorHeight, buttonBarHeight,
dialogMargin, navbarInsets.bottom);
// Go through each of the children and do the custom measurement.
int totalHeight = 0;
@@ -105,22 +95,25 @@ public class AuthBiometricUdfpsView extends AuthBiometricFingerprintView {
final int sensorDiameter = mSensorProps.sensorRadius * 2;
for (int i = 0; i < numChildren; i++) {
final View child = getChildAt(i);
if (child.getId() == R.id.biometric_icon_frame) {
// Create a frame that's exactly the size of the sensor circle
child.measure(
MeasureSpec.makeMeasureSpec(sensorDiameter, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(sensorDiameter, MeasureSpec.EXACTLY));
} else if (child.getId() == R.id.biometric_icon) {
// Icon should never be larger than the circle
child.measure(
final FrameLayout iconFrame = (FrameLayout) child;
final View icon = iconFrame.getChildAt(0);
// Ensure that the icon is never larger than the sensor.
icon.measure(
MeasureSpec.makeMeasureSpec(sensorDiameter, MeasureSpec.AT_MOST),
MeasureSpec.makeMeasureSpec(sensorDiameter, MeasureSpec.AT_MOST));
// Create a frame that's exactly the height of the sensor circle.
iconFrame.measure(
MeasureSpec.makeMeasureSpec(
child.getLayoutParams().width, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(sensorDiameter, MeasureSpec.EXACTLY));
} else if (child.getId() == R.id.space_above_icon) {
child.measure(
MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(child.getLayoutParams().height,
MeasureSpec.EXACTLY));
MeasureSpec.makeMeasureSpec(
child.getLayoutParams().height, MeasureSpec.EXACTLY));
} else if (child.getId() == R.id.button_bar) {
child.measure(
MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
@@ -128,8 +121,9 @@ public class AuthBiometricUdfpsView extends AuthBiometricFingerprintView {
MeasureSpec.EXACTLY));
} else if (child.getId() == R.id.space_below_icon) {
// Set the spacer height so the fingerprint icon is on the physical sensor area
child.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(spacerHeight, MeasureSpec.EXACTLY));
child.measure(
MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(bottomSpacerHeight, MeasureSpec.EXACTLY));
} else {
child.measure(
MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
@@ -143,4 +137,184 @@ public class AuthBiometricUdfpsView extends AuthBiometricFingerprintView {
return new AuthDialog.LayoutParams(width, totalHeight);
}
@NonNull
private AuthDialog.LayoutParams onMeasureInternalLandscape(int width, int height) {
// Find the spacer height needed to vertically align the icon with the sensor.
final int titleHeight = getViewHeightPx(R.id.title);
final int subtitleHeight = getViewHeightPx(R.id.subtitle);
final int descriptionHeight = getViewHeightPx(R.id.description);
final int topSpacerHeight = getViewHeightPx(R.id.space_above_icon);
final int textIndicatorHeight = getViewHeightPx(R.id.indicator);
final int buttonBarHeight = getViewHeightPx(R.id.button_bar);
final WindowManager windowManager = getContext().getSystemService(WindowManager.class);
final Insets navbarInsets = getNavbarInsets(windowManager);
final int bottomSpacerHeight = calculateBottomSpacerHeightForLandscape(titleHeight,
subtitleHeight, descriptionHeight, topSpacerHeight, textIndicatorHeight,
buttonBarHeight, navbarInsets.bottom);
// Find the spacer width needed to horizontally align the icon with the sensor.
final int displayWidth = getWindowBounds(windowManager).width();
final int dialogMargin = getDialogMarginPx();
final int horizontalInset = navbarInsets.left + navbarInsets.right;
final int horizontalSpacerWidth = calculateHorizontalSpacerWidthForLandscape(
mSensorProps, displayWidth, dialogMargin, horizontalInset);
final int sensorDiameter = mSensorProps.sensorRadius * 2;
final int remeasuredWidth = sensorDiameter + 2 * horizontalSpacerWidth;
int remeasuredHeight = 0;
final int numChildren = getChildCount();
for (int i = 0; i < numChildren; i++) {
final View child = getChildAt(i);
if (child.getId() == R.id.biometric_icon_frame) {
final FrameLayout iconFrame = (FrameLayout) child;
final View icon = iconFrame.getChildAt(0);
// Ensure that the icon is never larger than the sensor.
icon.measure(
MeasureSpec.makeMeasureSpec(sensorDiameter, MeasureSpec.AT_MOST),
MeasureSpec.makeMeasureSpec(sensorDiameter, MeasureSpec.AT_MOST));
// Create a frame that's exactly the height of the sensor circle.
iconFrame.measure(
MeasureSpec.makeMeasureSpec(remeasuredWidth, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(sensorDiameter, MeasureSpec.EXACTLY));
} else if (child.getId() == R.id.space_above_icon || child.getId() == R.id.button_bar) {
// Adjust the width of the top spacer and button bar while preserving their heights.
child.measure(
MeasureSpec.makeMeasureSpec(remeasuredWidth, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(
child.getLayoutParams().height, MeasureSpec.EXACTLY));
} else if (child.getId() == R.id.space_below_icon) {
// Adjust the bottom spacer height to align the fingerprint icon with the sensor.
child.measure(
MeasureSpec.makeMeasureSpec(remeasuredWidth, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(bottomSpacerHeight, MeasureSpec.EXACTLY));
} else {
// Use the remeasured width for all other child views.
child.measure(
MeasureSpec.makeMeasureSpec(remeasuredWidth, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST));
}
if (child.getVisibility() != View.GONE) {
remeasuredHeight += child.getMeasuredHeight();
}
}
return new AuthDialog.LayoutParams(remeasuredWidth, remeasuredHeight);
}
private int getViewHeightPx(@IdRes int viewId) {
final View view = findViewById(viewId);
return view != null ? view.getMeasuredHeight() : 0;
}
private int getDialogMarginPx() {
return getResources().getDimensionPixelSize(R.dimen.biometric_dialog_border_padding);
}
@NonNull
private static Insets getNavbarInsets(@Nullable WindowManager windowManager) {
return windowManager != null && windowManager.getCurrentWindowMetrics() != null
? windowManager.getCurrentWindowMetrics().getWindowInsets()
.getInsets(WindowInsets.Type.navigationBars())
: Insets.NONE;
}
@NonNull
private static Rect getWindowBounds(@Nullable WindowManager windowManager) {
return windowManager != null && windowManager.getCurrentWindowMetrics() != null
? windowManager.getCurrentWindowMetrics().getBounds()
: new Rect();
}
/**
* For devices in portrait orientation where the sensor is too high up, calculates the amount of
* padding necessary to center the biometric icon within the sensor's physical location.
*/
@VisibleForTesting
static int calculateBottomSpacerHeightForPortrait(
@NonNull FingerprintSensorPropertiesInternal sensorProperties, int displayHeightPx,
int textIndicatorHeightPx, int buttonBarHeightPx, int dialogMarginPx,
int navbarBottomInsetPx) {
final int sensorDistanceFromBottom = displayHeightPx
- sensorProperties.sensorLocationY
- sensorProperties.sensorRadius;
final int spacerHeight = sensorDistanceFromBottom
- textIndicatorHeightPx
- buttonBarHeightPx
- dialogMarginPx
- navbarBottomInsetPx;
Log.d(TAG, "Display height: " + displayHeightPx
+ ", Distance from bottom: " + sensorDistanceFromBottom
+ ", Bottom margin: " + dialogMarginPx
+ ", Navbar bottom inset: " + navbarBottomInsetPx
+ ", Bottom spacer height (portrait): " + spacerHeight);
return spacerHeight;
}
/**
* For devices in landscape orientation where the sensor is too high up, calculates the amount
* of padding necessary to center the biometric icon within the sensor's physical location.
*/
@VisibleForTesting
static int calculateBottomSpacerHeightForLandscape(int titleHeightPx, int subtitleHeightPx,
int descriptionHeightPx, int topSpacerHeightPx, int textIndicatorHeightPx,
int buttonBarHeightPx, int navbarBottomInsetPx) {
final int dialogHeightAboveIcon = titleHeightPx
+ subtitleHeightPx
+ descriptionHeightPx
+ topSpacerHeightPx;
final int dialogHeightBelowIcon = textIndicatorHeightPx + buttonBarHeightPx;
final int bottomSpacerHeight = dialogHeightAboveIcon
- dialogHeightBelowIcon
- navbarBottomInsetPx;
Log.d(TAG, "Title height: " + titleHeightPx
+ ", Subtitle height: " + subtitleHeightPx
+ ", Description height: " + descriptionHeightPx
+ ", Top spacer height: " + topSpacerHeightPx
+ ", Text indicator height: " + textIndicatorHeightPx
+ ", Button bar height: " + buttonBarHeightPx
+ ", Navbar bottom inset: " + navbarBottomInsetPx
+ ", Bottom spacer height (landscape): " + bottomSpacerHeight);
return bottomSpacerHeight;
}
/**
* For devices in landscape orientation where the sensor is too left/right, calculates the
* amount of padding necessary to center the biometric icon within the sensor's physical
* location.
*/
@VisibleForTesting
static int calculateHorizontalSpacerWidthForLandscape(
@NonNull FingerprintSensorPropertiesInternal sensorProperties, int displayWidthPx,
int dialogMarginPx, int navbarHorizontalInsetPx) {
final int sensorDistanceFromEdge = displayWidthPx
- sensorProperties.sensorLocationY
- sensorProperties.sensorRadius;
final int horizontalPadding = sensorDistanceFromEdge
- dialogMarginPx
- navbarHorizontalInsetPx;
Log.d(TAG, "Display width: " + displayWidthPx
+ ", Distance from edge: " + sensorDistanceFromEdge
+ ", Dialog margin: " + dialogMarginPx
+ ", Navbar horizontal inset: " + navbarHorizontalInsetPx
+ ", Horizontal spacer width (landscape): " + horizontalPadding);
return horizontalPadding;
}
}

View File

@@ -742,6 +742,7 @@ public abstract class AuthBiometricView extends LinearLayout {
* @param height Height to constrain the measurements to.
* @return See {@link AuthDialog.LayoutParams}
*/
@NonNull
AuthDialog.LayoutParams onMeasureInternal(int width, int height) {
int totalHeight = 0;
final int numChildren = getChildCount();

View File

@@ -32,8 +32,10 @@ import android.os.IBinder;
import android.os.Looper;
import android.os.UserManager;
import android.util.Log;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Surface;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowInsets;
@@ -433,6 +435,29 @@ public class AuthContainerView extends LinearLayout
+ mConfig.mPromptInfo.getAuthenticators());
}
if (mBiometricView instanceof AuthBiometricUdfpsView) {
final int displayRotation = getDisplay().getRotation();
switch (displayRotation) {
case Surface.ROTATION_0:
mPanelController.setPosition(AuthPanelController.POSITION_BOTTOM);
setScrollViewGravity(Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM);
break;
case Surface.ROTATION_90:
mPanelController.setPosition(AuthPanelController.POSITION_RIGHT);
setScrollViewGravity(Gravity.CENTER_VERTICAL | Gravity.RIGHT);
break;
case Surface.ROTATION_270:
mPanelController.setPosition(AuthPanelController.POSITION_LEFT);
setScrollViewGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT);
break;
default:
Log.e(TAG, "Unsupported display rotation: " + displayRotation);
mPanelController.setPosition(AuthPanelController.POSITION_BOTTOM);
setScrollViewGravity(Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM);
break;
}
}
if (mConfig.mSkipIntro) {
mContainerState = STATE_SHOWING;
} else {
@@ -476,6 +501,13 @@ public class AuthContainerView extends LinearLayout
}
}
private void setScrollViewGravity(int gravity) {
final FrameLayout.LayoutParams params =
(FrameLayout.LayoutParams) mBiometricScrollView.getLayoutParams();
params.gravity = gravity;
mBiometricScrollView.setLayoutParams(params);
}
@Override
public void onDetachedFromWindow() {
super.onDetachedFromWindow();

View File

@@ -18,6 +18,7 @@ package com.android.systemui.biometrics;
import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
import android.annotation.IntDef;
import android.content.Context;
import android.graphics.Outline;
import android.util.Log;
@@ -27,10 +28,20 @@ import android.view.animation.AccelerateDecelerateInterpolator;
import com.android.systemui.R;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* Controls the back panel and its animations for the BiometricPrompt UI.
*/
public class AuthPanelController extends ViewOutlineProvider {
public static final int POSITION_BOTTOM = 1;
public static final int POSITION_LEFT = 2;
public static final int POSITION_RIGHT = 3;
@IntDef({POSITION_BOTTOM, POSITION_LEFT, POSITION_RIGHT})
@Retention(RetentionPolicy.SOURCE)
public @interface Position {}
private static final String TAG = "BiometricPrompt/AuthPanelController";
private static final boolean DEBUG = false;
@@ -38,6 +49,7 @@ public class AuthPanelController extends ViewOutlineProvider {
private final Context mContext;
private final View mPanelView;
@Position private int mPosition = POSITION_BOTTOM;
private boolean mUseFullScreen;
private int mContainerWidth;
@@ -51,21 +63,44 @@ public class AuthPanelController extends ViewOutlineProvider {
@Override
public void getOutline(View view, Outline outline) {
final int left = (mContainerWidth - mContentWidth) / 2;
final int right = mContainerWidth - left;
final int left = getLeftBound(mPosition);
final int right = left + mContentWidth;
// If the content fits within the container, shrink the height to wrap the content.
// Otherwise, set the outline to be the display size minus the margin - the content within
// is scrollable.
final int top = mContentHeight < mContainerHeight
? mContainerHeight - mContentHeight - mMargin
: mMargin;
// 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);
// TODO(b/139954942) Likely don't need to "+1" after we resolve the navbar styling.
final int bottom = mContainerHeight - mMargin + 1;
outline.setRoundRect(left, top, right, bottom, mCornerRadius);
}
private int getLeftBound(@Position int position) {
switch (position) {
case POSITION_BOTTOM:
return (mContainerWidth - mContentWidth) / 2;
case POSITION_LEFT:
return mMargin;
case POSITION_RIGHT:
return mContainerWidth - mContentWidth - mMargin;
default:
Log.e(TAG, "Unrecognized position: " + position);
return getLeftBound(POSITION_BOTTOM);
}
}
private int getTopBound(@Position int position) {
switch (position) {
case POSITION_BOTTOM:
return Math.max(mContainerHeight - mContentHeight - mMargin, mMargin);
case POSITION_LEFT:
case POSITION_RIGHT:
return Math.max((mContainerHeight - mContentHeight) / 2, mMargin);
default:
Log.e(TAG, "Unrecognized position: " + position);
return getTopBound(POSITION_BOTTOM);
}
}
public void setContainerDimensions(int containerWidth, int containerHeight) {
if (DEBUG) {
Log.v(TAG, "Container Width: " + containerWidth + " Height: " + containerHeight);
@@ -74,6 +109,10 @@ public class AuthPanelController extends ViewOutlineProvider {
mContainerHeight = containerHeight;
}
public void setPosition(@Position int position) {
mPosition = position;
}
public void setUseFullScreen(boolean fullScreen) {
mUseFullScreen = fullScreen;
}

View File

@@ -22,10 +22,8 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.hardware.biometrics.PromptInfo;
@@ -333,16 +331,12 @@ public class AuthBiometricViewTest extends SysuiTestCase {
}
@Test
public void testUdfpsBottomSpacerCalculation() {
public void testUdfpsBottomSpacerHeightForPortrait() {
final int displayHeightPx = 3000;
final int navbarHeightPx = 10;
final int dialogBottomMarginPx = 20;
final View buttonBar = mock(View.class);
when(buttonBar.getMeasuredHeight()).thenReturn(100);
final View textIndicator = mock(View.class);
when(textIndicator.getMeasuredHeight()).thenReturn(200);
final int buttonBarHeightPx = 100;
final int textIndicatorHeightPx = 200;
final int sensorLocationX = 540;
final int sensorLocationY = 1600;
@@ -353,9 +347,47 @@ public class AuthBiometricViewTest extends SysuiTestCase {
true /* resetLockoutRequiresHardwareAuthToken */, sensorLocationX, sensorLocationY,
sensorRadius);
assertEquals(970, AuthBiometricUdfpsView.calculateBottomSpacerHeight(
displayHeightPx, navbarHeightPx, dialogBottomMarginPx, buttonBar, textIndicator,
props));
assertEquals(970,
AuthBiometricUdfpsView.calculateBottomSpacerHeightForPortrait(
props, displayHeightPx, textIndicatorHeightPx, buttonBarHeightPx,
dialogBottomMarginPx, navbarHeightPx
));
}
@Test
public void testUdfpsBottomSpacerHeightForLandscape() {
final int titleHeightPx = 320;
final int subtitleHeightPx = 240;
final int descriptionHeightPx = 200;
final int topSpacerHeightPx = 550;
final int textIndicatorHeightPx = 190;
final int buttonBarHeightPx = 160;
final int navbarBottomInsetPx = 75;
assertEquals(885,
AuthBiometricUdfpsView.calculateBottomSpacerHeightForLandscape(
titleHeightPx, subtitleHeightPx, descriptionHeightPx, topSpacerHeightPx,
textIndicatorHeightPx, buttonBarHeightPx, navbarBottomInsetPx));
}
@Test
public void testUdfpsHorizontalSpacerWidthForLandscape() {
final int displayWidthPx = 3000;
final int dialogMarginPx = 20;
final int navbarHorizontalInsetPx = 75;
final int sensorLocationX = 540;
final int sensorLocationY = 1600;
final int sensorRadius = 100;
final FingerprintSensorPropertiesInternal props = new FingerprintSensorPropertiesInternal(
0 /* sensorId */, SensorProperties.STRENGTH_STRONG, 5 /* maxEnrollmentsPerUser */,
FingerprintSensorProperties.TYPE_UDFPS_OPTICAL,
true /* resetLockoutRequiresHardwareAuthToken */, sensorLocationX, sensorLocationY,
sensorRadius);
assertEquals(1205,
AuthBiometricUdfpsView.calculateHorizontalSpacerWidthForLandscape(
props, displayWidthPx, dialogMarginPx, navbarHorizontalInsetPx));
}
private PromptInfo buildPromptInfo(boolean allowDeviceCredential) {