Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7b3dcebe authored by Jeff Pu's avatar Jeff Pu
Browse files

Face VHAL for user build

Bug: 326227403

Test: atest android.hardware.biometrics.face.* -c
Test: atest CtsBiometricsTestCases -c
Flag: TEST_ONLY
Change-Id: I869b68eba81166aacfc2a8a35c303940722214f3
parent d014c14c
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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",
+41 −6
Original line number Diff line number Diff line
@@ -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!");
+2 −2
Original line number Diff line number Diff line
@@ -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();
        }

        /**
+21 −3
Original line number Diff line number Diff line
@@ -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);
+48 −5
Original line number Diff line number Diff line
@@ -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) {
Loading