summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/hardware/biometrics/SensorLocationInternal.aidl19
-rw-r--r--core/java/android/hardware/biometrics/SensorLocationInternal.java112
-rw-r--r--core/java/android/hardware/fingerprint/FingerprintSensorPropertiesInternal.java83
-rw-r--r--core/res/res/values/config.xml14
-rw-r--r--core/res/res/values/symbols.xml1
-rw-r--r--packages/SystemUI/src/com/android/keyguard/LockIconViewController.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/SidefpsController.kt60
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java27
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/UdfpsDialogMeasureAdapter.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollView.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFaceToFingerprintViewTest.java8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsDialogMeasureAdapterTest.java11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/LockIconViewControllerTest.java7
-rw-r--r--services/core/java/com/android/server/biometrics/AuthService.java6
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java54
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java3
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProviderTest.java13
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);