Loading core/java/android/hardware/fingerprint/FingerprintSensorPropertiesInternal.java +27 −8 Original line number Diff line number Diff line Loading @@ -43,24 +43,36 @@ public class FingerprintSensorPropertiesInternal extends SensorPropertiesInterna * The location of the center of the sensor if applicable. For example, sensors of type * {@link FingerprintSensorProperties#TYPE_UDFPS_OPTICAL} would report this value as the * distance in pixels, measured from the left edge of the screen. * TODO: Value should be provided from the HAL */ public final int sensorLocationX = 540; public final int sensorLocationX; /** * The location of the center of the sensor if applicable. For example, sensors of type * {@link FingerprintSensorProperties#TYPE_UDFPS_OPTICAL} would report this value as the * distance in pixels, measured from the top edge of the screen. * TODO: Value should be provided from the HAL * */ public final int sensorLocationY = 1636; public final int sensorLocationY; /** * The radius of the sensor if applicable. For example, sensors of type * {@link FingerprintSensorProperties#TYPE_UDFPS_OPTICAL} would report this value as the radius * of the sensor, in pixels. */ public final int sensorRadius = 130; public final int sensorRadius; public FingerprintSensorPropertiesInternal(int sensorId, @SensorProperties.Strength int strength, int maxEnrollmentsPerUser, @FingerprintSensorProperties.SensorType int sensorType, boolean resetLockoutRequiresHardwareAuthToken, int sensorLocationX, int sensorLocationY, int sensorRadius) { super(sensorId, strength, maxEnrollmentsPerUser); this.sensorType = sensorType; this.resetLockoutRequiresHardwareAuthToken = resetLockoutRequiresHardwareAuthToken; this.sensorLocationX = sensorLocationX; this.sensorLocationY = sensorLocationY; this.sensorRadius = sensorRadius; } /** * Initializes SensorProperties with specified values Loading @@ -69,15 +81,19 @@ public class FingerprintSensorPropertiesInternal extends SensorPropertiesInterna @SensorProperties.Strength int strength, int maxEnrollmentsPerUser, @FingerprintSensorProperties.SensorType int sensorType, boolean resetLockoutRequiresHardwareAuthToken) { super(sensorId, strength, maxEnrollmentsPerUser); this.sensorType = sensorType; this.resetLockoutRequiresHardwareAuthToken = resetLockoutRequiresHardwareAuthToken; // TODO: Value should be provided from the HAL this(sensorId, strength, maxEnrollmentsPerUser, sensorType, resetLockoutRequiresHardwareAuthToken, 540 /* sensorLocationX */, 1636 /* sensorLocationY */, 130 /* sensorRadius */); } protected FingerprintSensorPropertiesInternal(Parcel in) { super(in); sensorType = in.readInt(); resetLockoutRequiresHardwareAuthToken = in.readBoolean(); sensorLocationX = in.readInt(); sensorLocationY = in.readInt(); sensorRadius = in.readInt(); } public static final Creator<FingerprintSensorPropertiesInternal> CREATOR = Loading @@ -103,6 +119,9 @@ public class FingerprintSensorPropertiesInternal extends SensorPropertiesInterna super.writeToParcel(dest, flags); dest.writeInt(sensorType); dest.writeBoolean(resetLockoutRequiresHardwareAuthToken); dest.writeInt(sensorLocationX); dest.writeInt(sensorLocationY); dest.writeInt(sensorRadius); } public boolean isAnyUdfpsType() { Loading packages/SystemUI/res/layout/auth_biometric_contents.xml +28 −7 Original line number Diff line number Diff line Loading @@ -37,13 +37,32 @@ android:gravity="@integer/biometric_dialog_text_gravity" style="@style/TextAppearance.AuthCredential.Description"/> <Space android:id="@+id/space_above_icon" android:layout_width="match_parent" android:layout_height="48dp" android:visibility="visible" /> <!-- 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" 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:paddingTop="48dp" android:layout_gravity="center_horizontal" android:layout_gravity="center" android:scaleType="fitXY" /> </FrameLayout> <!-- For sensors such as UDFPS, this view is used during custom measurement/layoutto 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" /> <TextView android:id="@+id/indicator" Loading @@ -54,6 +73,8 @@ android:textSize="12sp" android:gravity="center_horizontal" android:accessibilityLiveRegion="polite" android:singleLine="true" android:ellipsize="marquee" android:textColor="@color/biometric_dialog_gray"/> <LinearLayout Loading packages/SystemUI/res/layout/auth_biometric_udfps_view.xml 0 → 100644 +26 −0 Original line number Diff line number Diff line <!-- ~ Copyright (C) 2020 The Android Open Source Project ~ ~ Licensed under the Apache License, Version 2.0 (the "License"); ~ you may not use this file except in compliance with the License. ~ You may obtain a copy of the License at ~ ~ http://www.apache.org/licenses/LICENSE-2.0 ~ ~ Unless required by applicable law or agreed to in writing, software ~ distributed under the License is distributed on an "AS IS" BASIS, ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ~ See the License for the specific language governing permissions and ~ limitations under the License. --> <com.android.systemui.biometrics.AuthBiometricUdfpsView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/contents" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <include layout="@layout/auth_biometric_contents"/> </com.android.systemui.biometrics.AuthBiometricUdfpsView> No newline at end of file packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFaceView.java +2 −2 Original line number Diff line number Diff line Loading @@ -184,7 +184,7 @@ public class AuthBiometricFaceView extends AuthBiometricView { mIconController.updateState(mState, newState); if (newState == STATE_AUTHENTICATING_ANIMATING_IN || (newState == STATE_AUTHENTICATING && mSize == AuthDialog.SIZE_MEDIUM)) { (newState == STATE_AUTHENTICATING && getSize() == AuthDialog.SIZE_MEDIUM)) { resetErrorView(mContext, mIndicatorView); } Loading @@ -194,7 +194,7 @@ public class AuthBiometricFaceView extends AuthBiometricView { @Override public void onAuthenticationFailed(String failureReason) { if (mSize == AuthDialog.SIZE_MEDIUM) { if (getSize() == AuthDialog.SIZE_MEDIUM) { mTryAgainButton.setVisibility(View.VISIBLE); mPositiveButton.setVisibility(View.GONE); } Loading packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricUdfpsView.java 0 → 100644 +146 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.systemui.biometrics; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; import android.graphics.Rect; import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; import android.util.AttributeSet; import android.util.Log; import android.view.View; import android.view.WindowInsets; import android.view.WindowManager; import com.android.systemui.R; /** * Manages the layout for under-display fingerprint sensors (UDFPS). Ensures that UI elements * do not overlap with */ public class AuthBiometricUdfpsView extends AuthBiometricFingerprintView { private static final String TAG = "AuthBiometricUdfpsView"; @Nullable private FingerprintSensorPropertiesInternal mSensorProps; public AuthBiometricUdfpsView(Context context) { this(context, null /* attrs */); } public AuthBiometricUdfpsView(Context context, AttributeSet attrs) { super(context, attrs); } void setSensorProps(@NonNull FingerprintSensorPropertiesInternal prop) { 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 AuthDialog.LayoutParams onMeasureInternal(int width, int height) { final View spaceBelowIcon = findViewById(R.id.space_below_icon); spaceBelowIcon.setVisibility(View.VISIBLE); // 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); // 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); // Go through each of the children and do the custom measurement. int totalHeight = 0; final int numChildren = getChildCount(); 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( MeasureSpec.makeMeasureSpec(sensorDiameter, MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(sensorDiameter, MeasureSpec.AT_MOST)); } else if (child.getId() == R.id.space_above_icon) { child.measure( MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(child.getLayoutParams().height, MeasureSpec.EXACTLY)); } else if (child.getId() == R.id.button_bar) { child.measure( MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(child.getLayoutParams().height, 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)); } else { child.measure( MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST)); } if (child.getVisibility() != View.GONE) { totalHeight += child.getMeasuredHeight(); } } return new AuthDialog.LayoutParams(width, totalHeight); } } Loading
core/java/android/hardware/fingerprint/FingerprintSensorPropertiesInternal.java +27 −8 Original line number Diff line number Diff line Loading @@ -43,24 +43,36 @@ public class FingerprintSensorPropertiesInternal extends SensorPropertiesInterna * The location of the center of the sensor if applicable. For example, sensors of type * {@link FingerprintSensorProperties#TYPE_UDFPS_OPTICAL} would report this value as the * distance in pixels, measured from the left edge of the screen. * TODO: Value should be provided from the HAL */ public final int sensorLocationX = 540; public final int sensorLocationX; /** * The location of the center of the sensor if applicable. For example, sensors of type * {@link FingerprintSensorProperties#TYPE_UDFPS_OPTICAL} would report this value as the * distance in pixels, measured from the top edge of the screen. * TODO: Value should be provided from the HAL * */ public final int sensorLocationY = 1636; public final int sensorLocationY; /** * The radius of the sensor if applicable. For example, sensors of type * {@link FingerprintSensorProperties#TYPE_UDFPS_OPTICAL} would report this value as the radius * of the sensor, in pixels. */ public final int sensorRadius = 130; public final int sensorRadius; public FingerprintSensorPropertiesInternal(int sensorId, @SensorProperties.Strength int strength, int maxEnrollmentsPerUser, @FingerprintSensorProperties.SensorType int sensorType, boolean resetLockoutRequiresHardwareAuthToken, int sensorLocationX, int sensorLocationY, int sensorRadius) { super(sensorId, strength, maxEnrollmentsPerUser); this.sensorType = sensorType; this.resetLockoutRequiresHardwareAuthToken = resetLockoutRequiresHardwareAuthToken; this.sensorLocationX = sensorLocationX; this.sensorLocationY = sensorLocationY; this.sensorRadius = sensorRadius; } /** * Initializes SensorProperties with specified values Loading @@ -69,15 +81,19 @@ public class FingerprintSensorPropertiesInternal extends SensorPropertiesInterna @SensorProperties.Strength int strength, int maxEnrollmentsPerUser, @FingerprintSensorProperties.SensorType int sensorType, boolean resetLockoutRequiresHardwareAuthToken) { super(sensorId, strength, maxEnrollmentsPerUser); this.sensorType = sensorType; this.resetLockoutRequiresHardwareAuthToken = resetLockoutRequiresHardwareAuthToken; // TODO: Value should be provided from the HAL this(sensorId, strength, maxEnrollmentsPerUser, sensorType, resetLockoutRequiresHardwareAuthToken, 540 /* sensorLocationX */, 1636 /* sensorLocationY */, 130 /* sensorRadius */); } protected FingerprintSensorPropertiesInternal(Parcel in) { super(in); sensorType = in.readInt(); resetLockoutRequiresHardwareAuthToken = in.readBoolean(); sensorLocationX = in.readInt(); sensorLocationY = in.readInt(); sensorRadius = in.readInt(); } public static final Creator<FingerprintSensorPropertiesInternal> CREATOR = Loading @@ -103,6 +119,9 @@ public class FingerprintSensorPropertiesInternal extends SensorPropertiesInterna super.writeToParcel(dest, flags); dest.writeInt(sensorType); dest.writeBoolean(resetLockoutRequiresHardwareAuthToken); dest.writeInt(sensorLocationX); dest.writeInt(sensorLocationY); dest.writeInt(sensorRadius); } public boolean isAnyUdfpsType() { Loading
packages/SystemUI/res/layout/auth_biometric_contents.xml +28 −7 Original line number Diff line number Diff line Loading @@ -37,13 +37,32 @@ android:gravity="@integer/biometric_dialog_text_gravity" style="@style/TextAppearance.AuthCredential.Description"/> <Space android:id="@+id/space_above_icon" android:layout_width="match_parent" android:layout_height="48dp" android:visibility="visible" /> <!-- 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" 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:paddingTop="48dp" android:layout_gravity="center_horizontal" android:layout_gravity="center" android:scaleType="fitXY" /> </FrameLayout> <!-- For sensors such as UDFPS, this view is used during custom measurement/layoutto 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" /> <TextView android:id="@+id/indicator" Loading @@ -54,6 +73,8 @@ android:textSize="12sp" android:gravity="center_horizontal" android:accessibilityLiveRegion="polite" android:singleLine="true" android:ellipsize="marquee" android:textColor="@color/biometric_dialog_gray"/> <LinearLayout Loading
packages/SystemUI/res/layout/auth_biometric_udfps_view.xml 0 → 100644 +26 −0 Original line number Diff line number Diff line <!-- ~ Copyright (C) 2020 The Android Open Source Project ~ ~ Licensed under the Apache License, Version 2.0 (the "License"); ~ you may not use this file except in compliance with the License. ~ You may obtain a copy of the License at ~ ~ http://www.apache.org/licenses/LICENSE-2.0 ~ ~ Unless required by applicable law or agreed to in writing, software ~ distributed under the License is distributed on an "AS IS" BASIS, ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ~ See the License for the specific language governing permissions and ~ limitations under the License. --> <com.android.systemui.biometrics.AuthBiometricUdfpsView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/contents" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <include layout="@layout/auth_biometric_contents"/> </com.android.systemui.biometrics.AuthBiometricUdfpsView> No newline at end of file
packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFaceView.java +2 −2 Original line number Diff line number Diff line Loading @@ -184,7 +184,7 @@ public class AuthBiometricFaceView extends AuthBiometricView { mIconController.updateState(mState, newState); if (newState == STATE_AUTHENTICATING_ANIMATING_IN || (newState == STATE_AUTHENTICATING && mSize == AuthDialog.SIZE_MEDIUM)) { (newState == STATE_AUTHENTICATING && getSize() == AuthDialog.SIZE_MEDIUM)) { resetErrorView(mContext, mIndicatorView); } Loading @@ -194,7 +194,7 @@ public class AuthBiometricFaceView extends AuthBiometricView { @Override public void onAuthenticationFailed(String failureReason) { if (mSize == AuthDialog.SIZE_MEDIUM) { if (getSize() == AuthDialog.SIZE_MEDIUM) { mTryAgainButton.setVisibility(View.VISIBLE); mPositiveButton.setVisibility(View.GONE); } Loading
packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricUdfpsView.java 0 → 100644 +146 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.systemui.biometrics; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; import android.graphics.Rect; import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; import android.util.AttributeSet; import android.util.Log; import android.view.View; import android.view.WindowInsets; import android.view.WindowManager; import com.android.systemui.R; /** * Manages the layout for under-display fingerprint sensors (UDFPS). Ensures that UI elements * do not overlap with */ public class AuthBiometricUdfpsView extends AuthBiometricFingerprintView { private static final String TAG = "AuthBiometricUdfpsView"; @Nullable private FingerprintSensorPropertiesInternal mSensorProps; public AuthBiometricUdfpsView(Context context) { this(context, null /* attrs */); } public AuthBiometricUdfpsView(Context context, AttributeSet attrs) { super(context, attrs); } void setSensorProps(@NonNull FingerprintSensorPropertiesInternal prop) { 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 AuthDialog.LayoutParams onMeasureInternal(int width, int height) { final View spaceBelowIcon = findViewById(R.id.space_below_icon); spaceBelowIcon.setVisibility(View.VISIBLE); // 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); // 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); // Go through each of the children and do the custom measurement. int totalHeight = 0; final int numChildren = getChildCount(); 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( MeasureSpec.makeMeasureSpec(sensorDiameter, MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(sensorDiameter, MeasureSpec.AT_MOST)); } else if (child.getId() == R.id.space_above_icon) { child.measure( MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(child.getLayoutParams().height, MeasureSpec.EXACTLY)); } else if (child.getId() == R.id.button_bar) { child.measure( MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(child.getLayoutParams().height, 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)); } else { child.measure( MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST)); } if (child.getVisibility() != View.GONE) { totalHeight += child.getMeasuredHeight(); } } return new AuthDialog.LayoutParams(width, totalHeight); } }