Loading Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -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", Loading core/java/android/hardware/face/FaceSensorConfigurations.java +41 −6 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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}. Loading @@ -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!"); Loading services/core/java/com/android/server/biometrics/AuthService.java +2 −2 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -211,7 +211,7 @@ public class AuthService extends SystemService { */ @VisibleForTesting public String[] getFaceAidlInstances() { return ServiceManager.getDeclaredInstances(IFace.DESCRIPTOR); return FaceService.getDeclaredInstances(); } /** Loading services/core/java/com/android/server/biometrics/sensors/face/FaceService.java +21 −3 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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, Loading @@ -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; Loading Loading @@ -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); Loading services/core/java/com/android/server/biometrics/sensors/face/aidl/BiometricTestSessionImpl.java +48 −5 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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 */, Loading @@ -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(); Loading @@ -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()) { Loading @@ -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(); } Loading Loading @@ -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) { Loading Loading
Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -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", Loading
core/java/android/hardware/face/FaceSensorConfigurations.java +41 −6 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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}. Loading @@ -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!"); Loading
services/core/java/com/android/server/biometrics/AuthService.java +2 −2 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -211,7 +211,7 @@ public class AuthService extends SystemService { */ @VisibleForTesting public String[] getFaceAidlInstances() { return ServiceManager.getDeclaredInstances(IFace.DESCRIPTOR); return FaceService.getDeclaredInstances(); } /** Loading
services/core/java/com/android/server/biometrics/sensors/face/FaceService.java +21 −3 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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, Loading @@ -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; Loading Loading @@ -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); Loading
services/core/java/com/android/server/biometrics/sensors/face/aidl/BiometricTestSessionImpl.java +48 −5 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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 */, Loading @@ -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(); Loading @@ -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()) { Loading @@ -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(); } Loading Loading @@ -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) { Loading