Update side fsp sensor position via overlay.
This is a temporary workaround and the overlay properties can be removed when the information is available from the HAL. Bug: 174868353 Fix: 188690214 Test: manual (enroll and verify icon location) Change-Id: I2b6826756814727368007e55bfc88d28c4a78bea
This commit is contained in:
@@ -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;
|
||||
@@ -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 + "]";
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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" />
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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));
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user