Update Fingerprint/Face getSensorProperties

For each modality, updates/adds getSensorProperties() to return a list
of all sensors, containing their sensorId and other properties.

Bug: 160024833
Bug: 145978626

Test: atest KeyguardUpdateMonitorTest
Test: enroll/auth on fingerprint/face devices

Change-Id: I9adc4798183f53881f3592a8e72e6bd3595fbf1e
This commit is contained in:
Kevin Chyn
2020-07-17 14:22:51 -07:00
parent e1e6d6cb35
commit c486219bcb
14 changed files with 206 additions and 87 deletions

View File

@@ -47,6 +47,7 @@ import android.view.Surface;
import com.android.internal.R;
import com.android.internal.os.SomeArgs;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -622,16 +623,16 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
*/
@RequiresPermission(USE_BIOMETRIC_INTERNAL)
@NonNull
public FaceSensorProperties getSensorProperties() {
public List<FaceSensorProperties> getSensorProperties() {
try {
if (mService == null || !mService.isHardwareDetected(mContext.getOpPackageName())) {
return new FaceSensorProperties();
return new ArrayList<>();
}
return mService.getSensorProperties(mContext.getOpPackageName());
} catch (RemoteException e) {
e.rethrowFromSystemServer();
}
return new FaceSensorProperties();
return new ArrayList<>();
}
/**

View File

@@ -25,23 +25,19 @@ import android.os.Parcelable;
*/
public class FaceSensorProperties implements Parcelable {
public final int sensorId;
public final boolean supportsFaceDetection;
/**
* Creates a SensorProperties class with safe default values
*/
public FaceSensorProperties() {
supportsFaceDetection = false;
}
/**
* Initializes SensorProperties with specified values
*/
public FaceSensorProperties(boolean supportsFaceDetection) {
public FaceSensorProperties(int sensorId, boolean supportsFaceDetection) {
this.sensorId = sensorId;
this.supportsFaceDetection = supportsFaceDetection;
}
protected FaceSensorProperties(Parcel in) {
sensorId = in.readInt();
supportsFaceDetection = in.readBoolean();
}
@@ -65,6 +61,7 @@ public class FaceSensorProperties implements Parcelable {
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(sensorId);
dest.writeBoolean(supportsFaceDetection);
}
}

View File

@@ -28,6 +28,9 @@ import android.view.Surface;
* @hide
*/
interface IFaceService {
// Retrieve static sensor properties for all face sensors
List<FaceSensorProperties> getSensorProperties(String opPackageName);
// Authenticate the given sessionId with a face
void authenticate(IBinder token, long operationId, int userid, IFaceServiceReceiver receiver,
String opPackageName);
@@ -88,9 +91,6 @@ interface IFaceService {
// Determine if a user has at least one enrolled face
boolean hasEnrolledFaces(int userId, String opPackageName);
// Retrieve static sensor properties
FaceSensorProperties getSensorProperties(String opPackageName);
// Return the LockoutTracker status for the specified user
int getLockoutModeForUser(int userId);

View File

@@ -50,6 +50,7 @@ import android.util.Slog;
import android.view.Surface;
import java.security.Signature;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
@@ -736,24 +737,6 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing
return hasEnrolledFingerprints(userId);
}
/**
* @hide
*/
@RequiresPermission(USE_BIOMETRIC_INTERNAL)
public boolean isUdfps() {
if (mService == null) {
Slog.w(TAG, "isUdfps: no fingerprint service");
return false;
}
try {
return mService.isUdfps();
} catch (RemoteException e) {
e.rethrowFromSystemServer();
}
return false;
}
/**
* @hide
*/
@@ -861,6 +844,24 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing
return false;
}
/**
* Get statically configured sensor properties.
* @hide
*/
@RequiresPermission(USE_BIOMETRIC_INTERNAL)
@NonNull
public List<FingerprintSensorProperties> getSensorProperties() {
try {
if (mService == null || !mService.isHardwareDetected(mContext.getOpPackageName())) {
return new ArrayList<>();
}
return mService.getSensorProperties(mContext.getOpPackageName());
} catch (RemoteException e) {
e.rethrowFromSystemServer();
}
return new ArrayList<>();
}
/**
* @hide
*/

View File

@@ -0,0 +1,18 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.hardware.fingerprint;
parcelable FingerprintSensorProperties;

View File

@@ -0,0 +1,85 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.hardware.fingerprint;
import android.annotation.IntDef;
import android.hardware.face.FaceSensorProperties;
import android.os.Parcel;
import android.os.Parcelable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* Container for fingerprint sensor properties.
* @hide
*/
public class FingerprintSensorProperties implements Parcelable {
public static final int TYPE_UNKNOWN = 0;
public static final int TYPE_REAR = 1;
public static final int TYPE_UDFPS = 2;
public static final int TYPE_POWER_BUTTON = 3;
@IntDef({
TYPE_UNKNOWN,
TYPE_REAR,
TYPE_UDFPS,
TYPE_POWER_BUTTON})
@Retention(RetentionPolicy.SOURCE)
public @interface SensorType {}
public final int sensorId;
public final @SensorType int sensorType;
/**
* Initializes SensorProperties with specified values
*/
public FingerprintSensorProperties(int sensorId, @SensorType int sensorType) {
this.sensorId = sensorId;
this.sensorType = sensorType;
}
protected FingerprintSensorProperties(Parcel in) {
sensorId = in.readInt();
sensorType = in.readInt();
}
public static final Creator<FingerprintSensorProperties> CREATOR =
new Creator<FingerprintSensorProperties>() {
@Override
public FingerprintSensorProperties createFromParcel(Parcel in) {
return new FingerprintSensorProperties(in);
}
@Override
public FingerprintSensorProperties[] newArray(int size) {
return new FingerprintSensorProperties[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(sensorId);
dest.writeInt(sensorType);
}
}

View File

@@ -21,6 +21,7 @@ import android.hardware.fingerprint.IFingerprintClientActiveCallback;
import android.hardware.fingerprint.IFingerprintServiceReceiver;
import android.hardware.fingerprint.IUdfpsOverlayController;
import android.hardware.fingerprint.Fingerprint;
import android.hardware.fingerprint.FingerprintSensorProperties;
import android.view.Surface;
import java.util.List;
@@ -29,6 +30,9 @@ import java.util.List;
* @hide
*/
interface IFingerprintService {
// Retrieve static sensor properties for all fingerprint sensors
List<FingerprintSensorProperties> getSensorProperties(String opPackageName);
// Authenticate the given sessionId with a fingerprint. This is protected by
// USE_FINGERPRINT/USE_BIOMETRIC permission. This is effectively deprecated, since it only comes
// through FingerprintManager now.
@@ -122,9 +126,6 @@ interface IFingerprintService {
// Notifies about a finger leaving the sensor area.
void onFingerUp();
// Returns whether the sensor is an under-display fingerprint sensor (UDFPS).
boolean isUdfps();
// Sets the controller for managing the UDFPS overlay.
void setUdfpsOverlayController(in IUdfpsOverlayController controller);
}

View File

@@ -1338,7 +1338,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
private CancellationSignal mFaceCancelSignal;
private FingerprintManager mFpm;
private FaceManager mFaceManager;
private FaceSensorProperties mFaceSensorProperties;
private List<FaceSensorProperties> mFaceSensorProperties;
private boolean mFingerprintLockedOut;
private TelephonyManager mTelephonyManager;
@@ -2100,7 +2100,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
}
mFaceCancelSignal = new CancellationSignal();
if (isEncryptedOrLockdown(userId) && mFaceSensorProperties.supportsFaceDetection) {
// This would need to be updated for multi-sensor devices
final boolean supportsFaceDetection = !mFaceSensorProperties.isEmpty()
&& mFaceSensorProperties.get(0).supportsFaceDetection;
if (isEncryptedOrLockdown(userId) && supportsFaceDetection) {
mFaceManager.detectFace(mFaceCancelSignal, mFaceDetectionCallback, userId);
} else {
mFaceManager.authenticate(null /* crypto */, mFaceCancelSignal,

View File

@@ -38,6 +38,7 @@ import android.hardware.biometrics.IBiometricSysuiReceiver;
import android.hardware.biometrics.PromptInfo;
import android.hardware.face.FaceManager;
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintSensorProperties;
import android.hardware.fingerprint.IFingerprintService;
import android.os.Bundle;
import android.os.Handler;
@@ -265,6 +266,7 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
context.registerReceiver(mBroadcastReceiver, filter);
}
@SuppressWarnings("deprecation")
@Override
public void start() {
mCommandQueue.addCallback(this);
@@ -273,10 +275,13 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
final FingerprintManager fpm = mContext.getSystemService(FingerprintManager.class);
if (fpm != null && fpm.isHardwareDetected()) {
// TODO(b/160024833): Enumerate through all of the sensors and check whether
// at least one of them is UDFPS.
if (fpm.isUdfps()) {
mUdfpsController = new UdfpsController(mContext, mWindowManager);
final List<FingerprintSensorProperties> fingerprintSensorProperties =
fpm.getSensorProperties();
for (FingerprintSensorProperties props : fingerprintSensorProperties) {
if (props.sensorType == FingerprintSensorProperties.TYPE_UDFPS) {
mUdfpsController = new UdfpsController(mContext, mWindowManager);
break;
}
}
}

View File

@@ -132,6 +132,8 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
@Mock
private FaceManager mFaceManager;
@Mock
private List<FaceSensorProperties> mFaceSensorProperties;
@Mock
private BiometricManager mBiometricManager;
@Mock
private PackageManager mPackageManager;
@@ -175,7 +177,13 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
when(mFaceManager.isHardwareDetected()).thenReturn(true);
when(mFaceManager.hasEnrolledTemplates()).thenReturn(true);
when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(true);
when(mFaceManager.getSensorProperties()).thenReturn(new FaceSensorProperties());
when(mFaceManager.getSensorProperties()).thenReturn(mFaceSensorProperties);
// IBiometricsFace@1.0 does not support detection, only authentication.
when(mFaceSensorProperties.isEmpty()).thenReturn(false);
when(mFaceSensorProperties.get(anyInt())).thenReturn(new FaceSensorProperties(0 /* id */,
false /* supportsFaceDetection */));
when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
when(mFingerprintManager.hasEnrolledTemplates(anyInt())).thenReturn(true);
when(mUserManager.isUserUnlocked(anyInt())).thenReturn(true);

View File

@@ -29,8 +29,8 @@ import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.face.V1_0.IBiometricsFace;
import android.hardware.biometrics.face.V1_0.IBiometricsFaceClientCallback;
import android.hardware.face.Face;
import android.hardware.face.IFaceServiceReceiver;
import android.hardware.face.FaceSensorProperties;
import android.hardware.face.IFaceServiceReceiver;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
@@ -269,7 +269,7 @@ class Face10 implements IHwBinder.DeathRecipient {
Face10(@NonNull Context context, int sensorId,
@NonNull LockoutResetDispatcher lockoutResetDispatcher) {
mFaceSensorProperties = new FaceSensorProperties(false /* supportsFaceDetect */);
mFaceSensorProperties = new FaceSensorProperties(sensorId, false /* supportsFaceDetect */);
mContext = context;
mSensorId = sensorId;
mScheduler = new BiometricScheduler(TAG, null /* gestureAvailabilityTracker */);
@@ -559,7 +559,7 @@ class Face10 implements IHwBinder.DeathRecipient {
return daemon != null;
}
FaceSensorProperties getFaceSensorProperties() {
@NonNull FaceSensorProperties getFaceSensorProperties() {
return mFaceSensorProperties;
}

View File

@@ -44,6 +44,7 @@ import com.android.server.biometrics.sensors.LockoutTracker;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -64,6 +65,20 @@ public class FaceService extends SystemService {
* Receives the incoming binder calls from FaceManager.
*/
private final class FaceServiceWrapper extends IFaceService.Stub {
@Override // Binder call
public List<FaceSensorProperties> getSensorProperties(String opPackageName) {
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
final List<FaceSensorProperties> properties = new ArrayList<>();
if (mFace10 != null) {
properties.add(mFace10.getFaceSensorProperties());
}
Slog.d(TAG, "Retrieved sensor properties for: " + opPackageName
+ ", sensors: " + properties.size());
return properties;
}
@Override // Binder call
public void generateChallenge(IBinder token, IFaceServiceReceiver receiver,
String opPackageName) {
@@ -239,12 +254,6 @@ public class FaceService extends SystemService {
return !mFace10.getEnrolledFaces(userId).isEmpty();
}
@Override // Binder call
public FaceSensorProperties getSensorProperties(String opPackageName) {
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
return mFace10.getFaceSensorProperties();
}
@Override
public @LockoutTracker.LockoutMode int getLockoutModeForUser(int userId) {
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);

View File

@@ -31,6 +31,7 @@ import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprint;
import android.hardware.biometrics.fingerprint.V2_2.IBiometricsFingerprintClientCallback;
import android.hardware.fingerprint.Fingerprint;
import android.hardware.fingerprint.FingerprintSensorProperties;
import android.hardware.fingerprint.IFingerprintServiceReceiver;
import android.hardware.fingerprint.IUdfpsOverlayController;
import android.os.Handler;
@@ -85,7 +86,7 @@ class Fingerprint21 implements IHwBinder.DeathRecipient {
private final Context mContext;
private final IActivityTaskManager mActivityTaskManager;
private final SensorProperties mSensorProperties;
private final FingerprintSensorProperties mSensorProperties;
private final BiometricScheduler mScheduler;
private final Handler mHandler;
private final LockoutResetDispatcher mLockoutResetDispatcher;
@@ -98,25 +99,6 @@ class Fingerprint21 implements IHwBinder.DeathRecipient {
@Nullable private IUdfpsOverlayController mUdfpsOverlayController;
private int mCurrentUserId = UserHandle.USER_NULL;
/**
* Static properties that never change for a given sensor.
*/
private static final class SensorProperties {
// Unique sensorId
final int sensorId;
// Is the sensor under-display
final boolean isUdfps;
// Supports finger detection without exposing accept/reject and without incrementing the
// lockout counter
final boolean supportsFingerDetectOnly;
SensorProperties(int sensorId, boolean isUdfps, boolean supportsFingerDetectOnly) {
this.sensorId = sensorId;
this.isUdfps = isUdfps;
this.supportsFingerDetectOnly = supportsFingerDetectOnly;
}
}
private final class BiometricTaskStackListener extends TaskStackListener {
@Override
public void onTaskStackChanged() {
@@ -314,9 +296,11 @@ class Fingerprint21 implements IHwBinder.DeathRecipient {
isUdfps = false;
}
}
// Fingerprint2.1 supports finger-detect only since lockout is controlled in the framework.
mSensorProperties = new SensorProperties(sensorId, isUdfps,
true /* supportsFingerDetectOnly */);
final @FingerprintSensorProperties.SensorType int sensorType =
isUdfps ? FingerprintSensorProperties.TYPE_UDFPS
: FingerprintSensorProperties.TYPE_REAR;
mSensorProperties = new FingerprintSensorProperties(sensorId, sensorType);
}
@Override
@@ -558,6 +542,10 @@ class Fingerprint21 implements IHwBinder.DeathRecipient {
return daemon != null;
}
@NonNull FingerprintSensorProperties getFingerprintSensorProperties() {
return mSensorProperties;
}
void rename(int fingerId, int userId, String name) {
mHandler.post(() -> {
FingerprintUtils.getInstance().renameBiometricForUser(mContext, userId, fingerId, name);
@@ -592,10 +580,6 @@ class Fingerprint21 implements IHwBinder.DeathRecipient {
udfps.onFingerUp();
}
boolean isUdfps() {
return mSensorProperties.isUdfps;
}
void setUdfpsOverlayController(IUdfpsOverlayController controller) {
mUdfpsOverlayController = controller;
}

View File

@@ -23,10 +23,8 @@ import static android.Manifest.permission.RESET_FINGERPRINT_LOCKOUT;
import static android.Manifest.permission.USE_BIOMETRIC;
import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL;
import static android.Manifest.permission.USE_FINGERPRINT;
import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE;
import android.annotation.NonNull;
import android.app.ActivityManager;
import android.app.AppOpsManager;
import android.content.Context;
import android.content.pm.PackageManager;
@@ -34,6 +32,7 @@ import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.IBiometricSensorReceiver;
import android.hardware.biometrics.IBiometricServiceLockoutResetCallback;
import android.hardware.fingerprint.Fingerprint;
import android.hardware.fingerprint.FingerprintSensorProperties;
import android.hardware.fingerprint.IFingerprintClientActiveCallback;
import android.hardware.fingerprint.IFingerprintService;
import android.hardware.fingerprint.IFingerprintServiceReceiver;
@@ -42,7 +41,6 @@ import android.os.Binder;
import android.os.IBinder;
import android.os.NativeHandle;
import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.EventLog;
import android.util.Slog;
@@ -58,6 +56,7 @@ import com.android.server.biometrics.sensors.LockoutTracker;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -80,6 +79,20 @@ public class FingerprintService extends SystemService {
* Receives the incoming binder calls from FingerprintManager.
*/
private final class FingerprintServiceWrapper extends IFingerprintService.Stub {
@Override // Binder call
public List<FingerprintSensorProperties> getSensorProperties(String opPackageName) {
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
final List<FingerprintSensorProperties> properties = new ArrayList<>();
if (mFingerprint21 != null) {
properties.add(mFingerprint21.getFingerprintSensorProperties());
}
Slog.d(TAG, "Retrieved sensor properties for: " + opPackageName
+ ", sensors: " + properties.size());
return properties;
}
@Override // Binder call
public void generateChallenge(IBinder token, IFingerprintServiceReceiver receiver,
String opPackageName) {
@@ -364,12 +377,6 @@ public class FingerprintService extends SystemService {
mFingerprint21.onFingerUp();
}
@Override
public boolean isUdfps() {
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
return mFingerprint21.isUdfps();
}
@Override
public void setUdfpsOverlayController(IUdfpsOverlayController controller) {
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);