diff options
19 files changed, 346 insertions, 105 deletions
diff --git a/core/java/android/hardware/biometrics/SensorLocationInternal.aidl b/core/java/android/hardware/biometrics/SensorLocationInternal.aidl new file mode 100644 index 000000000000..098190449d53 --- /dev/null +++ b/core/java/android/hardware/biometrics/SensorLocationInternal.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2021 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 android.hardware.biometrics; + +// @hide +parcelable SensorLocationInternal; diff --git a/core/java/android/hardware/biometrics/SensorLocationInternal.java b/core/java/android/hardware/biometrics/SensorLocationInternal.java new file mode 100644 index 000000000000..fb25a2fcd823 --- /dev/null +++ b/core/java/android/hardware/biometrics/SensorLocationInternal.java @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2021 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 android.hardware.biometrics; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.os.Parcel; +import android.os.Parcelable; + +/** + * The location of a sensor relative to a physical display. + * + * Note that the location may change depending on other attributes of the device, such as + * fold status, which are not yet included in this class. + * @hide + */ +public class SensorLocationInternal implements Parcelable { + + /** Default value to use when the sensor's location is unknown or undefined. */ + public static final SensorLocationInternal DEFAULT = new SensorLocationInternal("", 0, 0, 0); + + /** + * The stable display id. + */ + @NonNull + public final String displayId; + + /** + * 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. + */ + 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. + * + */ + 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; + + public SensorLocationInternal(@Nullable String displayId, + int sensorLocationX, int sensorLocationY, int sensorRadius) { + this.displayId = displayId != null ? displayId : ""; + this.sensorLocationX = sensorLocationX; + this.sensorLocationY = sensorLocationY; + this.sensorRadius = sensorRadius; + } + + protected SensorLocationInternal(Parcel in) { + displayId = in.readString16NoHelper(); + sensorLocationX = in.readInt(); + sensorLocationY = in.readInt(); + sensorRadius = in.readInt(); + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(displayId); + dest.writeInt(sensorLocationX); + dest.writeInt(sensorLocationY); + dest.writeInt(sensorRadius); + } + + @Override + public int describeContents() { + return 0; + } + + public static final Creator<SensorLocationInternal> CREATOR = + new Creator<SensorLocationInternal>() { + @Override + public SensorLocationInternal createFromParcel(Parcel in) { + return new SensorLocationInternal(in); + } + + @Override + public SensorLocationInternal[] newArray(int size) { + return new SensorLocationInternal[size]; + } + }; + + @Override + public String toString() { + return "[id: " + displayId + + ", x: " + sensorLocationX + + ", y: " + sensorLocationY + + ", r: " + sensorRadius + "]"; + } +} diff --git a/core/java/android/hardware/fingerprint/FingerprintSensorPropertiesInternal.java b/core/java/android/hardware/fingerprint/FingerprintSensorPropertiesInternal.java index 45c6b290be11..4bf9a740f971 100644 --- a/core/java/android/hardware/fingerprint/FingerprintSensorPropertiesInternal.java +++ b/core/java/android/hardware/fingerprint/FingerprintSensorPropertiesInternal.java @@ -21,7 +21,9 @@ import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_UDFP import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_UDFPS_ULTRASONIC; import android.annotation.NonNull; +import android.annotation.Nullable; import android.hardware.biometrics.ComponentInfoInternal; +import android.hardware.biometrics.SensorLocationInternal; import android.hardware.biometrics.SensorProperties; import android.hardware.biometrics.SensorPropertiesInternal; import android.os.Parcel; @@ -38,34 +40,14 @@ public class FingerprintSensorPropertiesInternal extends SensorPropertiesInterna */ public final @FingerprintSensorProperties.SensorType int sensorType; - /** - * 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. - */ - 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. - * - */ - 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; + private final List<SensorLocationInternal> mSensorLocations; public FingerprintSensorPropertiesInternal(int sensorId, @SensorProperties.Strength int strength, int maxEnrollmentsPerUser, @NonNull List<ComponentInfoInternal> componentInfo, @FingerprintSensorProperties.SensorType int sensorType, - boolean resetLockoutRequiresHardwareAuthToken, int sensorLocationX, int sensorLocationY, - int sensorRadius) { + boolean resetLockoutRequiresHardwareAuthToken, + @NonNull List<SensorLocationInternal> sensorLocations) { // IBiometricsFingerprint@2.1 handles lockout in the framework, so the challenge is not // required as it can only be generated/attested/verified by TEE components. // IFingerprint@1.0 handles lockout below the HAL, but does not require a challenge. See @@ -73,9 +55,7 @@ public class FingerprintSensorPropertiesInternal extends SensorPropertiesInterna super(sensorId, strength, maxEnrollmentsPerUser, componentInfo, resetLockoutRequiresHardwareAuthToken, false /* resetLockoutRequiresChallenge */); this.sensorType = sensorType; - this.sensorLocationX = sensorLocationX; - this.sensorLocationY = sensorLocationY; - this.sensorRadius = sensorRadius; + this.mSensorLocations = List.copyOf(sensorLocations); } /** @@ -88,16 +68,15 @@ public class FingerprintSensorPropertiesInternal extends SensorPropertiesInterna boolean resetLockoutRequiresHardwareAuthToken) { // TODO(b/179175438): Value should be provided from the HAL this(sensorId, strength, maxEnrollmentsPerUser, componentInfo, sensorType, - resetLockoutRequiresHardwareAuthToken, 540 /* sensorLocationX */, - 1636 /* sensorLocationY */, 130 /* sensorRadius */); + resetLockoutRequiresHardwareAuthToken, List.of(new SensorLocationInternal( + "" /* displayId */, 540 /* sensorLocationX */, 1636 /* sensorLocationY */, + 130 /* sensorRadius */))); } protected FingerprintSensorPropertiesInternal(Parcel in) { super(in); sensorType = in.readInt(); - sensorLocationX = in.readInt(); - sensorLocationY = in.readInt(); - sensorRadius = in.readInt(); + mSensorLocations = in.createTypedArrayList(SensorLocationInternal.CREATOR); } public static final Creator<FingerprintSensorPropertiesInternal> CREATOR = @@ -122,9 +101,7 @@ public class FingerprintSensorPropertiesInternal extends SensorPropertiesInterna public void writeToParcel(Parcel dest, int flags) { super.writeToParcel(dest, flags); dest.writeInt(sensorType); - dest.writeInt(sensorLocationX); - dest.writeInt(sensorLocationY); - dest.writeInt(sensorRadius); + dest.writeTypedList(mSensorLocations); } public boolean isAnyUdfpsType() { @@ -150,6 +127,44 @@ public class FingerprintSensorPropertiesInternal extends SensorPropertiesInterna } } + /** + * Get the default location. + * + * Use this method when the sensor's relationship to the displays on the device do not + * matter. + * @return + */ + @NonNull + public SensorLocationInternal getLocation() { + final SensorLocationInternal location = getLocation("" /* displayId */); + return location != null ? location : SensorLocationInternal.DEFAULT; + } + + /** + * Get the location of a sensor relative to a physical display layout. + * + * @param displayId stable display id + * @return location or null if none is specified + */ + @Nullable + public SensorLocationInternal getLocation(String displayId) { + for (SensorLocationInternal location : mSensorLocations) { + if (location.displayId.equals(displayId)) { + return location; + } + } + return null; + } + + /** + * Gets all locations relative to all supported display layouts. + * @return supported locations + */ + @NonNull + public List<SensorLocationInternal> getAllLocations() { + return mSensorLocations; + } + @Override public String toString() { return "ID: " + sensorId + ", Strength: " + sensorStrength + ", Type: " + sensorType; diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index d5f4cad699c5..c075648ae5e8 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -4576,6 +4576,20 @@ --> </integer-array> + <!-- An array of arrays of side fingerprint sensor properties relative to each display. + Note: this value is temporary and is expected to be queried directly + from the HAL in the future. --> + <array name="config_sfps_sensor_props" translatable="false"> + <!-- + <array> + <item>displayId</item> + <item>sensorLocationX</item> + <item>sensorLocationY</item> + <item>sensorRadius</item> + <array> + --> + </array> + <!-- How long it takes for the HW to start illuminating after the illumination is requested. --> <integer name="config_udfps_illumination_transition_ms">50</integer> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 7fe73e5067b9..9c392ce335a9 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -2608,6 +2608,7 @@ <java-symbol type="array" name="config_biometric_sensors" /> <java-symbol type="bool" name="allow_test_udfps" /> <java-symbol type="array" name="config_udfps_sensor_props" /> + <java-symbol type="array" name="config_sfps_sensor_props" /> <java-symbol type="integer" name="config_udfps_illumination_transition_ms" /> <java-symbol type="bool" name="config_is_powerbutton_fps" /> diff --git a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java index 2a4022ca57b6..a1151956b51a 100644 --- a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java @@ -27,6 +27,7 @@ import android.graphics.Rect; import android.graphics.drawable.AnimatedVectorDrawable; import android.graphics.drawable.Drawable; import android.hardware.biometrics.BiometricSourceType; +import android.hardware.biometrics.SensorLocationInternal; import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; import android.media.AudioAttributes; import android.os.Process; @@ -330,8 +331,9 @@ public class LockIconViewController extends ViewController<LockIconView> impleme private void updateLockIconLocation() { if (mUdfpsSupported) { FingerprintSensorPropertiesInternal props = mAuthController.getUdfpsProps().get(0); - mView.setCenterLocation(new PointF(props.sensorLocationX, props.sensorLocationY), - props.sensorRadius); + final SensorLocationInternal location = props.getLocation(); + mView.setCenterLocation(new PointF(location.sensorLocationX, location.sensorLocationY), + location.sensorRadius); } else { mView.setCenterLocation( new PointF(mWidthPixels / 2, diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt index 9c818fff5018..b4b296ed9a6c 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt @@ -223,7 +223,7 @@ class AuthRippleController @Inject constructor( private fun updateUdfpsDependentParams() { authController.udfpsProps?.let { if (it.size > 0) { - udfpsRadius = it[0].sensorRadius.toFloat() + udfpsRadius = it[0].location.sensorRadius.toFloat() udfpsController = udfpsControllerProvider.get() if (mView.isAttachedToWindow) { diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/SidefpsController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/SidefpsController.kt index 54d5934d880d..c0731b25f7b2 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/SidefpsController.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/SidefpsController.kt @@ -17,6 +17,7 @@ package com.android.systemui.biometrics import android.content.Context import android.graphics.PixelFormat +import android.graphics.Rect import android.hardware.display.DisplayManager import android.hardware.fingerprint.FingerprintManager import android.hardware.fingerprint.FingerprintSensorPropertiesInternal @@ -56,21 +57,8 @@ class SidefpsController @Inject constructor( @VisibleForTesting val sensorProps: FingerprintSensorPropertiesInternal = fingerprintManager ?.sensorPropertiesInternal - ?.filter { it.isAnySidefpsType } - // TODO(b/188690214): remove - should directly come from HAL - ?.map { props -> - FingerprintSensorPropertiesInternal( - props.sensorId, - props.sensorStrength, - props.maxEnrollmentsPerUser, - props.componentInfo, - props.sensorType, - props.resetLockoutRequiresHardwareAuthToken, - 25 /* sensorLocationX */, - 610 /* sensorLocationY */, - 112 /* sensorRadius */ - ) - }?.firstOrNull() ?: throw IllegalStateException("no side fingerprint sensor") + ?.firstOrNull { it.isAnySidefpsType } + ?: throw IllegalStateException("no side fingerprint sensor") @VisibleForTesting val orientationListener = BiometricDisplayListener( @@ -131,29 +119,49 @@ class SidefpsController @Inject constructor( private fun createOverlayForDisplay(): View { val view = layoutInflater.inflate(R.layout.sidefps_view, null, false) - val display = context.display!! - val isPortrait = display.isPortrait() - val size = windowManager.maximumWindowMetrics.bounds - val displayWidth = if (isPortrait) size.width() else size.height() - val displayHeight = if (isPortrait) size.height() else size.width() val lottie = view.findViewById(R.id.sidefps_animation) as LottieAnimationView lottie.setAnimation(display.asSideFpsAnimation()) view.rotation = display.asSideFpsAnimationRotation() + updateOverlayParams(display, lottie.composition?.bounds ?: Rect()) + lottie.addLottieOnCompositionLoadedListener { + if (overlayView == view) { + updateOverlayParams(display, it.bounds) + windowManager.updateViewLayout(overlayView, overlayViewParams) + } + } + + return view + } + + private fun updateOverlayParams(display: Display, bounds: Rect) { + val isPortrait = display.isPortrait() + val size = windowManager.maximumWindowMetrics.bounds + val displayWidth = if (isPortrait) size.width() else size.height() + val displayHeight = if (isPortrait) size.height() else size.width() + val offsets = sensorProps.getLocation(display.uniqueId).let { location -> + if (location == null) { + Log.w(TAG, "No location specified for display: ${display.uniqueId}") + } + location ?: sensorProps.location + } + // ignore sensorLocationX and sensorRadius since it's assumed to be on the side // of the device and centered at sensorLocationY val (x, y) = when (display.rotation) { - Surface.ROTATION_90 -> Pair(sensorProps.sensorLocationY, 0) - Surface.ROTATION_270 -> Pair(displayHeight - sensorProps.sensorLocationY, displayWidth) - Surface.ROTATION_180 -> Pair(0, displayHeight - sensorProps.sensorLocationY) - else -> Pair(displayWidth, sensorProps.sensorLocationY) + Surface.ROTATION_90 -> + Pair(offsets.sensorLocationY, 0) + Surface.ROTATION_270 -> + Pair(displayHeight - offsets.sensorLocationY - bounds.width(), displayWidth) + Surface.ROTATION_180 -> + Pair(0, displayHeight - offsets.sensorLocationY - bounds.height()) + else -> + Pair(displayWidth, offsets.sensorLocationY) } overlayViewParams.x = x overlayViewParams.y = y - - return view } } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java index fccca24fa73a..63fb8e2b8ac1 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java @@ -33,6 +33,7 @@ import android.graphics.PixelFormat; import android.graphics.Point; import android.graphics.RectF; import android.hardware.biometrics.BiometricOverlayConstants; +import android.hardware.biometrics.SensorLocationInternal; import android.hardware.display.DisplayManager; import android.hardware.fingerprint.FingerprintManager; import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; @@ -643,10 +644,11 @@ public class UdfpsController implements DozeReceiver { // on lockscreen and for the udfps light reveal animation on keyguard. // Keyguard is only shown in portrait mode for now, so this will need to // be updated if that ever changes. - return new RectF(mSensorProps.sensorLocationX - mSensorProps.sensorRadius, - mSensorProps.sensorLocationY - mSensorProps.sensorRadius, - mSensorProps.sensorLocationX + mSensorProps.sensorRadius, - mSensorProps.sensorLocationY + mSensorProps.sensorRadius); + final SensorLocationInternal location = mSensorProps.getLocation(); + return new RectF(location.sensorLocationX - location.sensorRadius, + location.sensorLocationY - location.sensorRadius, + location.sensorLocationX + location.sensorRadius, + location.sensorLocationY + location.sensorRadius); } private void updateOverlay() { @@ -670,10 +672,11 @@ public class UdfpsController implements DozeReceiver { } // Default dimensions assume portrait mode. - mCoreLayoutParams.x = mSensorProps.sensorLocationX - mSensorProps.sensorRadius - paddingX; - mCoreLayoutParams.y = mSensorProps.sensorLocationY - mSensorProps.sensorRadius - paddingY; - mCoreLayoutParams.height = 2 * mSensorProps.sensorRadius + 2 * paddingX; - mCoreLayoutParams.width = 2 * mSensorProps.sensorRadius + 2 * paddingY; + final SensorLocationInternal location = mSensorProps.getLocation(); + mCoreLayoutParams.x = location.sensorLocationX - location.sensorRadius - paddingX; + mCoreLayoutParams.y = location.sensorLocationY - location.sensorRadius - paddingY; + mCoreLayoutParams.height = 2 * location.sensorRadius + 2 * paddingX; + mCoreLayoutParams.width = 2 * location.sensorRadius + 2 * paddingY; Point p = new Point(); // Gets the size based on the current rotation of the display. @@ -686,9 +689,9 @@ public class UdfpsController implements DozeReceiver { && mKeyguardUpdateMonitor.isGoingToSleep()) { break; } - mCoreLayoutParams.x = mSensorProps.sensorLocationY - mSensorProps.sensorRadius + mCoreLayoutParams.x = location.sensorLocationY - location.sensorRadius - paddingX; - mCoreLayoutParams.y = p.y - mSensorProps.sensorLocationX - mSensorProps.sensorRadius + mCoreLayoutParams.y = p.y - location.sensorLocationX - location.sensorRadius - paddingY; break; @@ -697,9 +700,9 @@ public class UdfpsController implements DozeReceiver { && mKeyguardUpdateMonitor.isGoingToSleep()) { break; } - mCoreLayoutParams.x = p.x - mSensorProps.sensorLocationY - mSensorProps.sensorRadius + mCoreLayoutParams.x = p.x - location.sensorLocationY - location.sensorRadius - paddingX; - mCoreLayoutParams.y = mSensorProps.sensorLocationX - mSensorProps.sensorRadius + mCoreLayoutParams.y = location.sensorLocationX - location.sensorRadius - paddingY; break; diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsDialogMeasureAdapter.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsDialogMeasureAdapter.java index 7ccfb865cd5a..6cc8acf07c50 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsDialogMeasureAdapter.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsDialogMeasureAdapter.java @@ -21,6 +21,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.graphics.Insets; import android.graphics.Rect; +import android.hardware.biometrics.SensorLocationInternal; import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; import android.util.Log; import android.view.Surface; @@ -93,7 +94,7 @@ public class UdfpsDialogMeasureAdapter { // Go through each of the children and do the custom measurement. int totalHeight = 0; final int numChildren = mView.getChildCount(); - final int sensorDiameter = mSensorProps.sensorRadius * 2; + final int sensorDiameter = mSensorProps.getLocation().sensorRadius * 2; for (int i = 0; i < numChildren; i++) { final View child = mView.getChildAt(i); if (child.getId() == R.id.biometric_icon_frame) { @@ -160,7 +161,7 @@ public class UdfpsDialogMeasureAdapter { final int horizontalSpacerWidth = calculateHorizontalSpacerWidthForLandscape( mSensorProps, displayWidth, dialogMargin, horizontalInset); - final int sensorDiameter = mSensorProps.sensorRadius * 2; + final int sensorDiameter = mSensorProps.getLocation().sensorRadius * 2; final int remeasuredWidth = sensorDiameter + 2 * horizontalSpacerWidth; int remeasuredHeight = 0; @@ -257,10 +258,10 @@ public class UdfpsDialogMeasureAdapter { @NonNull FingerprintSensorPropertiesInternal sensorProperties, int displayHeightPx, int textIndicatorHeightPx, int buttonBarHeightPx, int dialogMarginPx, int navbarBottomInsetPx) { - + final SensorLocationInternal location = sensorProperties.getLocation(); final int sensorDistanceFromBottom = displayHeightPx - - sensorProperties.sensorLocationY - - sensorProperties.sensorRadius; + - location.sensorLocationY + - location.sensorRadius; final int spacerHeight = sensorDistanceFromBottom - textIndicatorHeightPx @@ -318,10 +319,10 @@ public class UdfpsDialogMeasureAdapter { static int calculateHorizontalSpacerWidthForLandscape( @NonNull FingerprintSensorPropertiesInternal sensorProperties, int displayWidthPx, int dialogMarginPx, int navbarHorizontalInsetPx) { - + final SensorLocationInternal location = sensorProperties.getLocation(); final int sensorDistanceFromEdge = displayWidthPx - - sensorProperties.sensorLocationY - - sensorProperties.sensorRadius; + - location.sensorLocationY + - location.sensorRadius; final int horizontalPadding = sensorDistanceFromEdge - dialogMarginPx diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollView.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollView.java index d9edef48b3d4..c83006d8092a 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollView.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollView.java @@ -63,7 +63,7 @@ public class UdfpsEnrollView extends UdfpsAnimationView { void updateSensorLocation(@NonNull FingerprintSensorPropertiesInternal sensorProps) { View fingerprintAccessibilityView = findViewById(R.id.udfps_enroll_accessibility_view); - final int sensorHeight = sensorProps.sensorRadius * 2; + final int sensorHeight = sensorProps.getLocation().sensorRadius * 2; final int sensorWidth = sensorHeight; ViewGroup.LayoutParams params = fingerprintAccessibilityView.getLayoutParams(); params.width = sensorWidth; diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java index 15f77ffc08fd..6d31ef0e7701 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java @@ -25,6 +25,7 @@ import android.graphics.Color; import android.graphics.Paint; import android.graphics.PointF; import android.graphics.RectF; +import android.hardware.biometrics.SensorLocationInternal; import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; import android.os.Build; import android.os.UserHandle; @@ -141,11 +142,12 @@ public class UdfpsView extends FrameLayout implements DozeReceiver, UdfpsIllumin : mAnimationViewController.getPaddingX(); int paddingY = mAnimationViewController == null ? 0 : mAnimationViewController.getPaddingY(); + final SensorLocationInternal location = mSensorProps.getLocation(); mSensorRect.set( paddingX, paddingY, - 2 * mSensorProps.sensorRadius + paddingX, - 2 * mSensorProps.sensorRadius + paddingY); + 2 * location.sensorRadius + paddingX, + 2 * location.sensorRadius + paddingY); if (mAnimationViewController != null) { mAnimationViewController.onSensorRectUpdated(new RectF(mSensorRect)); diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFaceToFingerprintViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFaceToFingerprintViewTest.java index b6d1e42a4763..619d48d1e306 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFaceToFingerprintViewTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFaceToFingerprintViewTest.java @@ -29,6 +29,7 @@ import static org.mockito.Mockito.verify; import android.content.Context; import android.hardware.biometrics.ComponentInfoInternal; +import android.hardware.biometrics.SensorLocationInternal; import android.hardware.biometrics.SensorProperties; import android.hardware.fingerprint.FingerprintSensorProperties; import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; @@ -257,9 +258,10 @@ public class AuthBiometricFaceToFingerprintViewTest extends SysuiTestCase { componentInfo, FingerprintSensorProperties.TYPE_UDFPS_OPTICAL, true /* resetLockoutRequiresHardwareAuthToken */, - 540 /* sensorLocationX */, - 1600 /* sensorLocationY */, - 100 /* sensorRadius */); + List.of(new SensorLocationInternal("" /* displayId */, + 540 /* sensorLocationX */, + 1600 /* sensorLocationY */, + 100 /* sensorRadius */))); } public class TestableView extends AuthBiometricFaceToFingerprintView { diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsDialogMeasureAdapterTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsDialogMeasureAdapterTest.java index 88b4039fd2cd..27755edecba6 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsDialogMeasureAdapterTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsDialogMeasureAdapterTest.java @@ -19,6 +19,7 @@ package com.android.systemui.biometrics; import static org.junit.Assert.assertEquals; import android.hardware.biometrics.ComponentInfoInternal; +import android.hardware.biometrics.SensorLocationInternal; import android.hardware.biometrics.SensorProperties; import android.hardware.fingerprint.FingerprintSensorProperties; import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; @@ -61,8 +62,9 @@ public class UdfpsDialogMeasureAdapterTest extends SysuiTestCase { 0 /* sensorId */, SensorProperties.STRENGTH_STRONG, 5 /* maxEnrollmentsPerUser */, componentInfo, FingerprintSensorProperties.TYPE_UDFPS_OPTICAL, - true /* resetLockoutRequiresHardwareAuthToken */, sensorLocationX, sensorLocationY, - sensorRadius); + true /* resetLockoutRequiresHardwareAuthToken */, + List.of(new SensorLocationInternal("" /* displayId */, + sensorLocationX, sensorLocationY, sensorRadius))); assertEquals(970, UdfpsDialogMeasureAdapter.calculateBottomSpacerHeightForPortrait( @@ -125,8 +127,9 @@ public class UdfpsDialogMeasureAdapterTest extends SysuiTestCase { 0 /* sensorId */, SensorProperties.STRENGTH_STRONG, 5 /* maxEnrollmentsPerUser */, componentInfo, FingerprintSensorProperties.TYPE_UDFPS_OPTICAL, - true /* resetLockoutRequiresHardwareAuthToken */, sensorLocationX, sensorLocationY, - sensorRadius); + true /* resetLockoutRequiresHardwareAuthToken */, + List.of(new SensorLocationInternal("" /* displayId */, + sensorLocationX, sensorLocationY, sensorRadius))); assertEquals(1205, UdfpsDialogMeasureAdapter.calculateHorizontalSpacerWidthForLandscape( diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/LockIconViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/LockIconViewControllerTest.java index d279bbb02cee..3e9fbcfa1e9d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/LockIconViewControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/LockIconViewControllerTest.java @@ -25,6 +25,7 @@ import static org.mockito.Mockito.when; import android.content.Context; import android.content.res.Resources; import android.graphics.PointF; +import android.hardware.biometrics.SensorLocationInternal; import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; import android.os.Vibrator; import android.testing.AndroidTestingRunner; @@ -132,7 +133,8 @@ public class LockIconViewControllerTest extends SysuiTestCase { /* component info */ new ArrayList<>(), /* sensorType */ 3, /* resetLockoutRequiresHwToken */ false, - (int) udfpsLocation.x, (int) udfpsLocation.y, radius); + List.of(new SensorLocationInternal("" /* displayId */, + (int) udfpsLocation.x, (int) udfpsLocation.y, radius))); when(mAuthController.getUdfpsSensorLocation()).thenReturn(udfpsLocation); when(mAuthController.getUdfpsProps()).thenReturn(List.of(fpProps)); @@ -165,7 +167,8 @@ public class LockIconViewControllerTest extends SysuiTestCase { /* component info */ new ArrayList<>(), /* sensorType */ 3, /* resetLockoutRequiresHwToken */ false, - (int) udfpsLocation.x, (int) udfpsLocation.y, radius); + List.of(new SensorLocationInternal("" /* displayId */, + (int) udfpsLocation.x, (int) udfpsLocation.y, radius))); when(mAuthController.getUdfpsSensorLocation()).thenReturn(udfpsLocation); when(mAuthController.getUdfpsProps()).thenReturn(List.of(fpProps)); diff --git a/services/core/java/com/android/server/biometrics/AuthService.java b/services/core/java/com/android/server/biometrics/AuthService.java index b42f8980d1c0..9c8ccd946b7f 100644 --- a/services/core/java/com/android/server/biometrics/AuthService.java +++ b/services/core/java/com/android/server/biometrics/AuthService.java @@ -47,6 +47,7 @@ import android.hardware.biometrics.IInvalidationCallback; import android.hardware.biometrics.ITestSession; import android.hardware.biometrics.ITestSessionCallback; import android.hardware.biometrics.PromptInfo; +import android.hardware.biometrics.SensorLocationInternal; import android.hardware.biometrics.SensorPropertiesInternal; import android.hardware.face.FaceSensorProperties; import android.hardware.face.FaceSensorPropertiesInternal; @@ -766,8 +767,9 @@ public class AuthService extends SystemService { if (isUdfps && udfpsProps.length == 3) { return new FingerprintSensorPropertiesInternal(sensorId, Utils.authenticatorStrengthToPropertyStrength(strength), maxEnrollmentsPerUser, - componentInfo, sensorType, resetLockoutRequiresHardwareAuthToken, udfpsProps[0], - udfpsProps[1], udfpsProps[2]); + componentInfo, sensorType, resetLockoutRequiresHardwareAuthToken, + List.of(new SensorLocationInternal("" /* display */, + udfpsProps[0], udfpsProps[1], udfpsProps[2]))); } else { return new FingerprintSensorPropertiesInternal(sensorId, Utils.authenticatorStrengthToPropertyStrength(strength), maxEnrollmentsPerUser, diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java index 4c37934486e1..0defc3fb6a50 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java @@ -25,10 +25,12 @@ import android.app.ActivityTaskManager; import android.app.TaskStackListener; import android.content.Context; import android.content.pm.UserInfo; +import android.content.res.TypedArray; import android.hardware.biometrics.ComponentInfoInternal; import android.hardware.biometrics.IInvalidationCallback; import android.hardware.biometrics.ITestSession; import android.hardware.biometrics.ITestSessionCallback; +import android.hardware.biometrics.SensorLocationInternal; import android.hardware.biometrics.common.ComponentInfo; import android.hardware.biometrics.fingerprint.IFingerprint; import android.hardware.biometrics.fingerprint.SensorProps; @@ -145,6 +147,8 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi mActivityTaskManager = ActivityTaskManager.getInstance(); mTaskStackListener = new BiometricTaskStackListener(); + final List<SensorLocationInternal> workaroundLocations = getWorkaroundSensorProps(context); + for (SensorProps prop : props) { final int sensorId = prop.commonProps.sensorId; @@ -164,9 +168,12 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi componentInfo, prop.sensorType, true /* resetLockoutRequiresHardwareAuthToken */, - prop.sensorLocations[0].sensorLocationX, - prop.sensorLocations[0].sensorLocationY, - prop.sensorLocations[0].sensorRadius); + !workaroundLocations.isEmpty() ? workaroundLocations : + List.of(new SensorLocationInternal( + "" /* displayId */, + prop.sensorLocations[0].sensorLocationX, + prop.sensorLocations[0].sensorLocationY, + prop.sensorLocations[0].sensorRadius))); final Sensor sensor = new Sensor(getTag() + "/" + sensorId, this, mContext, mHandler, internalProp, lockoutResetDispatcher, gestureAvailabilityDispatcher); @@ -647,4 +654,45 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi void setTestHalEnabled(boolean enabled) { mTestHalEnabled = enabled; } + + // TODO(b/174868353): workaround for gaps in HAL interface (remove and get directly from HAL) + // reads values via an overlay instead of querying the HAL + @NonNull + private List<SensorLocationInternal> getWorkaroundSensorProps(@NonNull Context context) { + final List<SensorLocationInternal> sensorLocations = new ArrayList<>(); + + final TypedArray sfpsProps = context.getResources().obtainTypedArray( + com.android.internal.R.array.config_sfps_sensor_props); + for (int i = 0; i < sfpsProps.length(); i++) { + final int id = sfpsProps.getResourceId(i, -1); + if (id > 0) { + final SensorLocationInternal location = parseSensorLocation( + context.getResources().obtainTypedArray(id)); + if (location != null) { + sensorLocations.add(location); + } + } + } + sfpsProps.recycle(); + + return sensorLocations; + } + + @Nullable + private SensorLocationInternal parseSensorLocation(@Nullable TypedArray array) { + if (array == null) { + return null; + } + + try { + return new SensorLocationInternal( + array.getString(0), + array.getInt(1, 0), + array.getInt(2, 0), + array.getInt(3, 0)); + } catch (Exception e) { + Slog.w(getTag(), "malformed sensor location", e); + } + return null; + } } diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java index 79ad8e1a5c70..dd68b4d37e2a 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java @@ -426,8 +426,7 @@ public class Fingerprint21UdfpsMock extends Fingerprint21 implements TrustManage mSensorProperties = new FingerprintSensorPropertiesInternal(sensorProps.sensorId, sensorProps.sensorStrength, maxTemplatesAllowed, sensorProps.componentInfo, FingerprintSensorProperties.TYPE_UDFPS_OPTICAL, - resetLockoutRequiresHardwareAuthToken, sensorProps.sensorLocationX, - sensorProps.sensorLocationY, sensorProps.sensorRadius); + resetLockoutRequiresHardwareAuthToken, sensorProps.getAllLocations()); mMockHalResultController = controller; mUserHasTrust = new SparseBooleanArray(); mTrustManager = context.getSystemService(TrustManager.class); diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProviderTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProviderTest.java index b51918e24b13..8b7c90d985b5 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProviderTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProviderTest.java @@ -19,10 +19,13 @@ package com.android.server.biometrics.sensors.fingerprint.aidl; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; +import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import android.content.Context; +import android.content.res.Resources; +import android.content.res.TypedArray; import android.hardware.biometrics.common.CommonProps; import android.hardware.biometrics.fingerprint.IFingerprint; import android.hardware.biometrics.fingerprint.SensorLocation; @@ -56,6 +59,8 @@ public class FingerprintProviderTest { @Mock private Context mContext; @Mock + private Resources mResources; + @Mock private UserManager mUserManager; @Mock private GestureAvailabilityDispatcher mGestureAvailabilityDispatcher; @@ -74,19 +79,21 @@ public class FingerprintProviderTest { public void setUp() { MockitoAnnotations.initMocks(this); + when(mContext.getResources()).thenReturn(mResources); + when(mResources.obtainTypedArray(anyInt())).thenReturn(mock(TypedArray.class)); when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager); when(mUserManager.getAliveUsers()).thenReturn(new ArrayList<>()); final SensorProps sensor1 = new SensorProps(); sensor1.commonProps = new CommonProps(); sensor1.commonProps.sensorId = 0; - sensor1.sensorLocations = new SensorLocation[] {new SensorLocation()}; + sensor1.sensorLocations = new SensorLocation[]{new SensorLocation()}; final SensorProps sensor2 = new SensorProps(); sensor2.commonProps = new CommonProps(); sensor2.commonProps.sensorId = 1; - sensor2.sensorLocations = new SensorLocation[] {new SensorLocation()}; + sensor2.sensorLocations = new SensorLocation[]{new SensorLocation()}; - mSensorProps = new SensorProps[] {sensor1, sensor2}; + mSensorProps = new SensorProps[]{sensor1, sensor2}; mLockoutResetDispatcher = new LockoutResetDispatcher(mContext); |