forked from LeddaZ/frameworks_base
Face VHAL for user build
Bug: 326227403 Test: atest android.hardware.biometrics.face.* -c Test: atest CtsBiometricsTestCases -c Flag: TEST_ONLY Change-Id: I869b68eba81166aacfc2a8a35c303940722214f3
This commit is contained in:
parent
d014c14c78
commit
7b3dcebe63
|
@ -99,6 +99,7 @@ filegroup {
|
|||
":android.hardware.biometrics.common-V4-java-source",
|
||||
":android.hardware.biometrics.fingerprint-V5-java-source",
|
||||
":android.hardware.biometrics.fingerprint.virtualhal-java-source",
|
||||
":android.hardware.biometrics.face.virtualhal-java-source",
|
||||
":android.hardware.biometrics.face-V4-java-source",
|
||||
":android.hardware.gnss-V2-java-source",
|
||||
":android.hardware.graphics.common-V3-java-source",
|
||||
|
|
|
@ -22,6 +22,7 @@ import android.annotation.Nullable;
|
|||
import android.content.Context;
|
||||
import android.hardware.biometrics.face.IFace;
|
||||
import android.hardware.biometrics.face.SensorProps;
|
||||
import android.hardware.biometrics.face.virtualhal.IVirtualHal;
|
||||
import android.os.Binder;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
@ -160,6 +161,41 @@ public class FaceSensorConfigurations implements Parcelable {
|
|||
dest.writeByte((byte) (mResetLockoutRequiresChallenge ? 1 : 0));
|
||||
dest.writeMap(mSensorPropsMap);
|
||||
}
|
||||
/**
|
||||
* Remap fqName of VHAL because the `virtual` instance is registered
|
||||
* with IVirtulalHal now (IFace previously)
|
||||
* @param fqName fqName to be translated
|
||||
* @return real fqName
|
||||
*/
|
||||
public static String remapFqName(String fqName) {
|
||||
if (!fqName.contains(IFace.DESCRIPTOR + "/virtual")) {
|
||||
return fqName; //no remap needed for real hardware HAL
|
||||
} else {
|
||||
//new Vhal instance name
|
||||
return fqName.replace("IFace", "virtualhal.IVirtualHal");
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @param fqName aidl interface instance name
|
||||
* @return aidl interface
|
||||
*/
|
||||
public static IFace getIFace(String fqName) {
|
||||
if (fqName.contains("virtual")) {
|
||||
String fqNameMapped = remapFqName(fqName);
|
||||
Slog.i(TAG, "getIFace fqName is mapped: " + fqName + "->" + fqNameMapped);
|
||||
try {
|
||||
IVirtualHal vhal = IVirtualHal.Stub.asInterface(
|
||||
Binder.allowBlocking(ServiceManager.waitForService(fqNameMapped)));
|
||||
return vhal.getFaceHal();
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "Remote exception in vhal.getFaceHal() call" + fqNameMapped);
|
||||
}
|
||||
}
|
||||
|
||||
return IFace.Stub.asInterface(
|
||||
Binder.allowBlocking(ServiceManager.waitForDeclaredService(fqName)));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns face sensor props for the HAL {@param instance}.
|
||||
|
@ -173,14 +209,13 @@ public class FaceSensorConfigurations implements Parcelable {
|
|||
return props;
|
||||
}
|
||||
|
||||
final String fqName = IFace.DESCRIPTOR + "/" + instance;
|
||||
IFace face = IFace.Stub.asInterface(Binder.allowBlocking(
|
||||
ServiceManager.waitForDeclaredService(fqName)));
|
||||
try {
|
||||
if (face != null) {
|
||||
props = face.getSensorProps();
|
||||
final String fqName = IFace.DESCRIPTOR + "/" + instance;
|
||||
final IFace fp = getIFace(fqName);
|
||||
if (fp != null) {
|
||||
props = fp.getSensorProps();
|
||||
} else {
|
||||
Slog.e(TAG, "Unable to get declared service: " + fqName);
|
||||
Log.d(TAG, "IFace null for instance " + instance);
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
Log.d(TAG, "Unable to get sensor properties!");
|
||||
|
|
|
@ -49,7 +49,6 @@ import android.hardware.biometrics.ITestSessionCallback;
|
|||
import android.hardware.biometrics.PromptInfo;
|
||||
import android.hardware.biometrics.SensorLocationInternal;
|
||||
import android.hardware.biometrics.SensorPropertiesInternal;
|
||||
import android.hardware.biometrics.face.IFace;
|
||||
import android.hardware.face.FaceSensorConfigurations;
|
||||
import android.hardware.face.FaceSensorProperties;
|
||||
import android.hardware.face.FaceSensorPropertiesInternal;
|
||||
|
@ -73,6 +72,7 @@ import com.android.internal.R;
|
|||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.util.ArrayUtils;
|
||||
import com.android.server.SystemService;
|
||||
import com.android.server.biometrics.sensors.face.FaceService;
|
||||
import com.android.server.biometrics.sensors.fingerprint.FingerprintService;
|
||||
import com.android.server.companion.virtual.VirtualDeviceManagerInternal;
|
||||
|
||||
|
@ -211,7 +211,7 @@ public class AuthService extends SystemService {
|
|||
*/
|
||||
@VisibleForTesting
|
||||
public String[] getFaceAidlInstances() {
|
||||
return ServiceManager.getDeclaredInstances(IFace.DESCRIPTOR);
|
||||
return FaceService.getDeclaredInstances();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -19,6 +19,7 @@ package com.android.server.biometrics.sensors.face;
|
|||
import static android.Manifest.permission.INTERACT_ACROSS_USERS;
|
||||
import static android.Manifest.permission.MANAGE_FACE;
|
||||
import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL;
|
||||
import static android.hardware.face.FaceSensorConfigurations.getIFace;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
|
@ -60,6 +61,7 @@ import android.util.proto.ProtoOutputStream;
|
|||
import android.view.Surface;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.util.ArrayUtils;
|
||||
import com.android.internal.util.DumpUtils;
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.server.SystemService;
|
||||
|
@ -753,7 +755,7 @@ public class FaceService extends SystemService {
|
|||
public FaceService(Context context) {
|
||||
this(context, null /* faceProviderFunction */, () -> IBiometricService.Stub.asInterface(
|
||||
ServiceManager.getService(Context.BIOMETRIC_SERVICE)), null /* faceProvider */,
|
||||
() -> ServiceManager.getDeclaredInstances(IFace.DESCRIPTOR));
|
||||
() -> getDeclaredInstances());
|
||||
}
|
||||
|
||||
@VisibleForTesting FaceService(Context context,
|
||||
|
@ -778,8 +780,7 @@ public class FaceService extends SystemService {
|
|||
|
||||
mFaceProvider = faceProvider != null ? faceProvider : (name) -> {
|
||||
final String fqName = IFace.DESCRIPTOR + "/" + name;
|
||||
final IFace face = IFace.Stub.asInterface(
|
||||
Binder.allowBlocking(ServiceManager.waitForDeclaredService(fqName)));
|
||||
final IFace face = getIFace(fqName);
|
||||
if (face == null) {
|
||||
Slog.e(TAG, "Unable to get declared service: " + fqName);
|
||||
return null;
|
||||
|
@ -835,6 +836,23 @@ public class FaceService extends SystemService {
|
|||
*/
|
||||
public static native void releaseSurfaceHandle(@NonNull NativeHandle handle);
|
||||
|
||||
/**
|
||||
* Get all face hal instances declared in manifest
|
||||
* @return instance names
|
||||
*/
|
||||
public static String[] getDeclaredInstances() {
|
||||
String[] a = ServiceManager.getDeclaredInstances(IFace.DESCRIPTOR);
|
||||
Slog.i(TAG, "Before:getDeclaredInstances: IFace instance found, a.length="
|
||||
+ a.length);
|
||||
if (!ArrayUtils.contains(a, "virtual")) {
|
||||
// Now, the virtual hal is registered with IVirtualHal interface and it is also
|
||||
// moved from vendor to system_ext partition without a device manifest. So
|
||||
// if the old vhal is not declared, add here.
|
||||
a = ArrayUtils.appendElement(String.class, a, "virtual");
|
||||
}
|
||||
Slog.i(TAG, "After:getDeclaredInstances: a.length=" + a.length);
|
||||
return a;
|
||||
}
|
||||
|
||||
void syncEnrollmentsNow() {
|
||||
Utils.checkPermissionOrShell(getContext(), MANAGE_FACE);
|
||||
|
|
|
@ -23,6 +23,9 @@ import android.hardware.biometrics.ITestSessionCallback;
|
|||
import android.hardware.biometrics.face.AuthenticationFrame;
|
||||
import android.hardware.biometrics.face.BaseFrame;
|
||||
import android.hardware.biometrics.face.EnrollmentFrame;
|
||||
import android.hardware.biometrics.face.virtualhal.AcquiredInfoAndVendorCode;
|
||||
import android.hardware.biometrics.face.virtualhal.EnrollmentProgressStep;
|
||||
import android.hardware.biometrics.face.virtualhal.NextEnrollment;
|
||||
import android.hardware.face.Face;
|
||||
import android.hardware.face.FaceAuthenticationFrame;
|
||||
import android.hardware.face.FaceEnrollFrame;
|
||||
|
@ -50,6 +53,7 @@ import java.util.Set;
|
|||
public class BiometricTestSessionImpl extends ITestSession.Stub {
|
||||
|
||||
private static final String TAG = "face/aidl/BiometricTestSessionImpl";
|
||||
private static final int VHAL_ENROLLMENT_ID = 9999;
|
||||
|
||||
@NonNull private final Context mContext;
|
||||
private final int mSensorId;
|
||||
|
@ -144,16 +148,35 @@ public class BiometricTestSessionImpl extends ITestSession.Stub {
|
|||
|
||||
super.setTestHalEnabled_enforcePermission();
|
||||
|
||||
mProvider.setTestHalEnabled(enabled);
|
||||
mSensor.setTestHalEnabled(enabled);
|
||||
mProvider.setTestHalEnabled(enabled);
|
||||
}
|
||||
|
||||
@android.annotation.EnforcePermission(android.Manifest.permission.TEST_BIOMETRIC)
|
||||
@Override
|
||||
public void startEnroll(int userId) {
|
||||
public void startEnroll(int userId) throws RemoteException {
|
||||
|
||||
super.startEnroll_enforcePermission();
|
||||
|
||||
Slog.i(TAG, "startEnroll(): isVhalForTesting=" + mProvider.isVhalForTesting());
|
||||
if (mProvider.isVhalForTesting()) {
|
||||
final AcquiredInfoAndVendorCode[] acquiredInfoAndVendorCodes =
|
||||
{new AcquiredInfoAndVendorCode()};
|
||||
final EnrollmentProgressStep[] enrollmentProgressSteps =
|
||||
{new EnrollmentProgressStep(), new EnrollmentProgressStep()};
|
||||
enrollmentProgressSteps[0].durationMs = 100;
|
||||
enrollmentProgressSteps[0].acquiredInfoAndVendorCodes = acquiredInfoAndVendorCodes;
|
||||
enrollmentProgressSteps[1].durationMs = 200;
|
||||
enrollmentProgressSteps[1].acquiredInfoAndVendorCodes = acquiredInfoAndVendorCodes;
|
||||
|
||||
final NextEnrollment nextEnrollment = new NextEnrollment();
|
||||
nextEnrollment.id = VHAL_ENROLLMENT_ID;
|
||||
nextEnrollment.progressSteps = enrollmentProgressSteps;
|
||||
nextEnrollment.result = true;
|
||||
mProvider.getVhal().setNextEnrollment(nextEnrollment);
|
||||
mProvider.getVhal().setOperationAuthenticateDuration(6000);
|
||||
}
|
||||
|
||||
mProvider.scheduleEnroll(mSensorId, new Binder(), new byte[69], userId, mReceiver,
|
||||
mContext.getOpPackageName(), new int[0] /* disabledFeatures */,
|
||||
null /* previewSurface */, false /* debugConsent */,
|
||||
|
@ -166,6 +189,10 @@ public class BiometricTestSessionImpl extends ITestSession.Stub {
|
|||
|
||||
super.finishEnroll_enforcePermission();
|
||||
|
||||
if (mProvider.isVhalForTesting()) {
|
||||
return;
|
||||
}
|
||||
|
||||
int nextRandomId = mRandom.nextInt();
|
||||
while (mEnrollmentIds.contains(nextRandomId)) {
|
||||
nextRandomId = mRandom.nextInt();
|
||||
|
@ -178,11 +205,16 @@ public class BiometricTestSessionImpl extends ITestSession.Stub {
|
|||
|
||||
@android.annotation.EnforcePermission(android.Manifest.permission.TEST_BIOMETRIC)
|
||||
@Override
|
||||
public void acceptAuthentication(int userId) {
|
||||
public void acceptAuthentication(int userId) throws RemoteException {
|
||||
|
||||
// Fake authentication with any of the existing faces
|
||||
super.acceptAuthentication_enforcePermission();
|
||||
|
||||
if (mProvider.isVhalForTesting()) {
|
||||
mProvider.getVhal().setEnrollmentHit(VHAL_ENROLLMENT_ID);
|
||||
return;
|
||||
}
|
||||
|
||||
List<Face> faces = FaceUtils.getInstance(mSensorId)
|
||||
.getBiometricsForUser(mContext, userId);
|
||||
if (faces.isEmpty()) {
|
||||
|
@ -196,10 +228,15 @@ public class BiometricTestSessionImpl extends ITestSession.Stub {
|
|||
|
||||
@android.annotation.EnforcePermission(android.Manifest.permission.TEST_BIOMETRIC)
|
||||
@Override
|
||||
public void rejectAuthentication(int userId) {
|
||||
public void rejectAuthentication(int userId) throws RemoteException {
|
||||
|
||||
super.rejectAuthentication_enforcePermission();
|
||||
|
||||
if (mProvider.isVhalForTesting()) {
|
||||
mProvider.getVhal().setEnrollmentHit(VHAL_ENROLLMENT_ID + 1);
|
||||
return;
|
||||
}
|
||||
|
||||
mSensor.getSessionForUser(userId).getHalSessionCallback().onAuthenticationFailed();
|
||||
}
|
||||
|
||||
|
@ -236,11 +273,17 @@ public class BiometricTestSessionImpl extends ITestSession.Stub {
|
|||
|
||||
@android.annotation.EnforcePermission(android.Manifest.permission.TEST_BIOMETRIC)
|
||||
@Override
|
||||
public void cleanupInternalState(int userId) {
|
||||
public void cleanupInternalState(int userId) throws RemoteException {
|
||||
|
||||
super.cleanupInternalState_enforcePermission();
|
||||
|
||||
Slog.d(TAG, "cleanupInternalState: " + userId);
|
||||
|
||||
if (mProvider.isVhalForTesting()) {
|
||||
Slog.i(TAG, "cleanup virtualhal configurations");
|
||||
mProvider.getVhal().resetConfigurations(); //setEnrollments(new int[]{});
|
||||
}
|
||||
|
||||
mProvider.scheduleInternalCleanup(mSensorId, userId, new ClientMonitorCallback() {
|
||||
@Override
|
||||
public void onClientStarted(@NonNull BaseClientMonitor clientMonitor) {
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
|
||||
package com.android.server.biometrics.sensors.face.aidl;
|
||||
|
||||
import static android.hardware.face.FaceSensorConfigurations.getIFace;
|
||||
import static android.hardware.face.FaceSensorConfigurations.remapFqName;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.ActivityManager;
|
||||
|
@ -32,6 +35,7 @@ import android.hardware.biometrics.ITestSession;
|
|||
import android.hardware.biometrics.ITestSessionCallback;
|
||||
import android.hardware.biometrics.face.IFace;
|
||||
import android.hardware.biometrics.face.SensorProps;
|
||||
import android.hardware.biometrics.face.virtualhal.IVirtualHal;
|
||||
import android.hardware.face.Face;
|
||||
import android.hardware.face.FaceAuthenticateOptions;
|
||||
import android.hardware.face.FaceEnrollOptions;
|
||||
|
@ -54,6 +58,7 @@ import com.android.server.biometrics.AuthenticationStatsBroadcastReceiver;
|
|||
import com.android.server.biometrics.AuthenticationStatsCollector;
|
||||
import com.android.server.biometrics.BiometricDanglingReceiver;
|
||||
import com.android.server.biometrics.BiometricHandlerProvider;
|
||||
import com.android.server.biometrics.Flags;
|
||||
import com.android.server.biometrics.Utils;
|
||||
import com.android.server.biometrics.log.BiometricContext;
|
||||
import com.android.server.biometrics.log.BiometricLogger;
|
||||
|
@ -130,6 +135,11 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
|
|||
private AuthenticationStatsCollector mAuthenticationStatsCollector;
|
||||
@Nullable
|
||||
private IFace mDaemon;
|
||||
@Nullable
|
||||
private IVirtualHal mVhal;
|
||||
@Nullable
|
||||
private String mHalInstanceNameCurrent;
|
||||
|
||||
|
||||
private final class BiometricTaskStackListener extends TaskStackListener {
|
||||
@Override
|
||||
|
@ -286,14 +296,37 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
|
|||
if (mTestHalEnabled) {
|
||||
return true;
|
||||
}
|
||||
return ServiceManager.checkService(IFace.DESCRIPTOR + "/" + mHalInstanceName) != null;
|
||||
return ServiceManager.checkService(
|
||||
remapFqName(IFace.DESCRIPTOR + "/" + mHalInstanceName)) != null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@VisibleForTesting
|
||||
synchronized IFace getHalInstance() {
|
||||
if (mTestHalEnabled) {
|
||||
return new TestHal();
|
||||
if (Flags.useVhalForTesting()) {
|
||||
if (!mHalInstanceNameCurrent.contains("virtual")) {
|
||||
Slog.i(getTag(), "Switching face hal from " + mHalInstanceName
|
||||
+ " to virtual hal");
|
||||
mHalInstanceNameCurrent = "virtual";
|
||||
mDaemon = null;
|
||||
}
|
||||
} else {
|
||||
// Enabling the test HAL for a single sensor in a multi-sensor HAL currently enables
|
||||
// the test HAL for all sensors under that HAL. This can be updated in the future if
|
||||
// necessary.
|
||||
return new TestHal();
|
||||
}
|
||||
} else {
|
||||
if (mHalInstanceNameCurrent == null) {
|
||||
mHalInstanceNameCurrent = mHalInstanceName;
|
||||
} else if (mHalInstanceNameCurrent.contains("virtual")
|
||||
&& mHalInstanceNameCurrent != mHalInstanceName) {
|
||||
Slog.i(getTag(), "Switching face from virtual hal " + "to "
|
||||
+ mHalInstanceName);
|
||||
mHalInstanceNameCurrent = mHalInstanceName;
|
||||
mDaemon = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (mDaemon != null) {
|
||||
|
@ -302,10 +335,7 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
|
|||
|
||||
Slog.d(getTag(), "Daemon was null, reconnecting");
|
||||
|
||||
mDaemon = IFace.Stub.asInterface(
|
||||
Binder.allowBlocking(
|
||||
ServiceManager.waitForDeclaredService(
|
||||
IFace.DESCRIPTOR + "/" + mHalInstanceName)));
|
||||
mDaemon = getIFace(IFace.DESCRIPTOR + "/" + mHalInstanceNameCurrent);
|
||||
if (mDaemon == null) {
|
||||
Slog.e(getTag(), "Unable to get daemon");
|
||||
return null;
|
||||
|
@ -833,7 +863,13 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
|
|||
}
|
||||
|
||||
void setTestHalEnabled(boolean enabled) {
|
||||
final boolean changed = enabled != mTestHalEnabled;
|
||||
mTestHalEnabled = enabled;
|
||||
Slog.i(getTag(), "setTestHalEnabled(): isVhalForTestingFlags=" + Flags.useVhalForTesting()
|
||||
+ " mTestHalEnabled=" + mTestHalEnabled + " changed=" + changed);
|
||||
if (changed && isVhalForTesting()) {
|
||||
getHalInstance();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -850,10 +886,41 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
|
|||
return mTestHalEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if vhal_for_testing feature is enabled and test is active
|
||||
*/
|
||||
public boolean isVhalForTesting() {
|
||||
return (Flags.useVhalForTesting() && mTestHalEnabled);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sends a face re enroll notification.
|
||||
*/
|
||||
public void sendFaceReEnrollNotification() {
|
||||
mAuthenticationStatsCollector.sendFaceReEnrollNotification();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a fingerprint enroll notification.
|
||||
*/
|
||||
public void sendFingerprintReEnrollNotification() {
|
||||
mAuthenticationStatsCollector.sendFingerprintReEnrollNotification();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return virtual hal AIDL interface if it is used for testing
|
||||
*
|
||||
*/
|
||||
public IVirtualHal getVhal() throws RemoteException {
|
||||
if (mVhal == null && isVhalForTesting()) {
|
||||
mVhal = IVirtualHal.Stub.asInterface(
|
||||
Binder.allowBlocking(
|
||||
ServiceManager.waitForService(
|
||||
IVirtualHal.DESCRIPTOR + "/"
|
||||
+ mHalInstanceNameCurrent)));
|
||||
Slog.d(getTag(), "getVhal " + mHalInstanceNameCurrent);
|
||||
}
|
||||
return mVhal;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package com.android.server.biometrics.sensors.face.aidl;
|
||||
|
||||
import static android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_HW_UNAVAILABLE;
|
||||
import static android.hardware.face.FaceSensorConfigurations.remapFqName;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
|
@ -337,7 +338,8 @@ public class Sensor {
|
|||
if (mTestHalEnabled) {
|
||||
return true;
|
||||
}
|
||||
return ServiceManager.checkService(IFace.DESCRIPTOR + "/" + halInstanceName) != null;
|
||||
return ServiceManager.checkService(
|
||||
remapFqName(IFace.DESCRIPTOR + "/" + halInstanceName)) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue