Retrieve IFIngerprint from IVirtual interface over
Fingerprint Virtual HAL

Bug: 326227403
Test: atest CtsBiometricsTestCases -c
Flag: TEST_ONLY
Change-Id: I85f697a4e217e27f6371a7d80c9d42c0f7e1ed57
diff --git a/Android.bp b/Android.bp
index f8907f3..258440f 100644
--- a/Android.bp
+++ b/Android.bp
@@ -98,6 +98,7 @@
         ":android.frameworks.location.altitude-V2-java-source",
         ":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-V4-java-source",
         ":android.hardware.gnss-V2-java-source",
         ":android.hardware.graphics.common-V3-java-source",
diff --git a/core/java/android/hardware/fingerprint/FingerprintSensorConfigurations.java b/core/java/android/hardware/fingerprint/FingerprintSensorConfigurations.java
index 43c0da9..48c5887 100644
--- a/core/java/android/hardware/fingerprint/FingerprintSensorConfigurations.java
+++ b/core/java/android/hardware/fingerprint/FingerprintSensorConfigurations.java
@@ -23,12 +23,14 @@
 import android.content.Context;
 import android.hardware.biometrics.fingerprint.IFingerprint;
 import android.hardware.biometrics.fingerprint.SensorProps;
+import android.hardware.biometrics.fingerprint.virtualhal.IVirtualHal;
 import android.os.Binder;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.util.Log;
+import android.util.Slog;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -162,6 +164,43 @@
         dest.writeMap(mSensorPropsMap);
     }
 
+
+    /**
+     * Remap fqName of VHAL because the `virtual` instance is registered
+     * with IVirtulalHal now (IFingerprint previously)
+     * @param fqName fqName to be translated
+     * @return real fqName
+     */
+    public static String remapFqName(String fqName) {
+        if (!fqName.contains(IFingerprint.DESCRIPTOR + "/virtual")) {
+            return fqName;  //no remap needed for real hardware HAL
+        } else {
+            //new Vhal instance name
+            return fqName.replace("IFingerprint", "virtualhal.IVirtualHal");
+        }
+    }
+
+    /**
+     * @param fqName aidl interface instance name
+     * @return aidl interface
+     */
+    public static IFingerprint getIFingerprint(String fqName) {
+        if (fqName.contains("virtual")) {
+            String fqNameMapped = remapFqName(fqName);
+            Slog.i(TAG, "getIFingerprint fqName is mapped: " + fqName + "->" + fqNameMapped);
+            try {
+                IVirtualHal vhal = IVirtualHal.Stub.asInterface(
+                        Binder.allowBlocking(ServiceManager.waitForService(fqNameMapped)));
+                return vhal.getFingerprintHal();
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Remote exception in vhal.getFingerprintHal() call" + fqNameMapped);
+            }
+        }
+
+        return IFingerprint.Stub.asInterface(
+                Binder.allowBlocking(ServiceManager.waitForDeclaredService(fqName)));
+    }
+
     /**
      * Returns fingerprint sensor props for the HAL {@param instance}.
      */
@@ -176,8 +215,7 @@
 
         try {
             final String fqName = IFingerprint.DESCRIPTOR + "/" + instance;
-            final IFingerprint fp = IFingerprint.Stub.asInterface(Binder.allowBlocking(
-                    ServiceManager.waitForDeclaredService(fqName)));
+            final IFingerprint fp = getIFingerprint(fqName);
             if (fp != null) {
                 props = fp.getSensorProps();
             } else {
diff --git a/services/core/java/com/android/server/biometrics/AuthService.java b/services/core/java/com/android/server/biometrics/AuthService.java
index 2a16872..dba6c33 100644
--- a/services/core/java/com/android/server/biometrics/AuthService.java
+++ b/services/core/java/com/android/server/biometrics/AuthService.java
@@ -50,7 +50,6 @@
 import android.hardware.biometrics.SensorLocationInternal;
 import android.hardware.biometrics.SensorPropertiesInternal;
 import android.hardware.biometrics.face.IFace;
-import android.hardware.biometrics.fingerprint.IFingerprint;
 import android.hardware.face.FaceSensorConfigurations;
 import android.hardware.face.FaceSensorProperties;
 import android.hardware.face.FaceSensorPropertiesInternal;
@@ -74,6 +73,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ArrayUtils;
 import com.android.server.SystemService;
+import com.android.server.biometrics.sensors.fingerprint.FingerprintService;
 import com.android.server.companion.virtual.VirtualDeviceManagerInternal;
 
 import java.util.ArrayList;
@@ -203,7 +203,7 @@
          */
         @VisibleForTesting
         public String[] getFingerprintAidlInstances() {
-            return ServiceManager.getDeclaredInstances(IFingerprint.DESCRIPTOR);
+            return FingerprintService.getDeclaredInstances();
         }
 
         /**
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
index 60cfd5a..2f6ba0b 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
@@ -26,6 +26,7 @@
 import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ERROR_USER_CANCELED;
 import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ERROR_VENDOR;
 import static android.hardware.biometrics.SensorProperties.STRENGTH_STRONG;
+import static android.hardware.fingerprint.FingerprintSensorConfigurations.getIFingerprint;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -78,6 +79,7 @@
 
 import com.android.internal.R;
 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;
@@ -1015,7 +1017,7 @@
         this(context, BiometricContext.getInstance(context),
                 () -> IBiometricService.Stub.asInterface(
                         ServiceManager.getService(Context.BIOMETRIC_SERVICE)),
-                () -> ServiceManager.getDeclaredInstances(IFingerprint.DESCRIPTOR),
+                () -> getDeclaredInstances(),
                 null /* fingerprintProvider */,
                 null /* fingerprintProviderFunction */);
     }
@@ -1039,8 +1041,7 @@
         mFingerprintProvider = fingerprintProvider != null ? fingerprintProvider :
                 (name) -> {
                     final String fqName = IFingerprint.DESCRIPTOR + "/" + name;
-                    final IFingerprint fp = IFingerprint.Stub.asInterface(
-                            Binder.allowBlocking(ServiceManager.waitForDeclaredService(fqName)));
+                    final IFingerprint fp = getIFingerprint(fqName);
                     if (fp != null) {
                         try {
                             return new FingerprintProvider(getContext(),
@@ -1129,6 +1130,24 @@
         publishBinderService(Context.FINGERPRINT_SERVICE, mServiceWrapper);
     }
 
+    /**
+     * Get all fingerprint hal instances declared in manifest
+     * @return instance names
+     */
+    public static String[] getDeclaredInstances() {
+        String[] a = ServiceManager.getDeclaredInstances(IFingerprint.DESCRIPTOR);
+        Slog.i(TAG, "Before:getDeclaredInstances: IFingerprint 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;
+    }
+
     @NonNull
     private List<Fingerprint> getEnrolledFingerprintsDeprecated(int userId, String opPackageName) {
         final Pair<Integer, ServiceProvider> provider = mRegistry.getSingleProvider();
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/BiometricTestSessionImpl.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/BiometricTestSessionImpl.java
index caa2c1c..fd3d996 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/BiometricTestSessionImpl.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/BiometricTestSessionImpl.java
@@ -20,9 +20,9 @@
 import android.content.Context;
 import android.hardware.biometrics.ITestSession;
 import android.hardware.biometrics.ITestSessionCallback;
-import android.hardware.biometrics.fingerprint.AcquiredInfoAndVendorCode;
-import android.hardware.biometrics.fingerprint.EnrollmentProgressStep;
-import android.hardware.biometrics.fingerprint.NextEnrollment;
+import android.hardware.biometrics.fingerprint.virtualhal.AcquiredInfoAndVendorCode;
+import android.hardware.biometrics.fingerprint.virtualhal.EnrollmentProgressStep;
+import android.hardware.biometrics.fingerprint.virtualhal.NextEnrollment;
 import android.hardware.fingerprint.Fingerprint;
 import android.hardware.fingerprint.FingerprintEnrollOptions;
 import android.hardware.fingerprint.FingerprintManager;
@@ -300,4 +300,4 @@
         super.getSensorId_enforcePermission();
         return mSensorId;
     }
-}
\ No newline at end of file
+}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
index 9edaa4e..8195efe 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
@@ -17,6 +17,8 @@
 package com.android.server.biometrics.sensors.fingerprint.aidl;
 
 import static android.hardware.fingerprint.FingerprintManager.SENSOR_ID_ANY;
+import static android.hardware.fingerprint.FingerprintSensorConfigurations.getIFingerprint;
+import static android.hardware.fingerprint.FingerprintSensorConfigurations.remapFqName;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -34,9 +36,9 @@
 import android.hardware.biometrics.ITestSessionCallback;
 import android.hardware.biometrics.SensorLocationInternal;
 import android.hardware.biometrics.fingerprint.IFingerprint;
-import android.hardware.biometrics.fingerprint.IVirtualHal;
 import android.hardware.biometrics.fingerprint.PointerContext;
 import android.hardware.biometrics.fingerprint.SensorProps;
+import android.hardware.biometrics.fingerprint.virtualhal.IVirtualHal;
 import android.hardware.fingerprint.Fingerprint;
 import android.hardware.fingerprint.FingerprintAuthenticateOptions;
 import android.hardware.fingerprint.FingerprintEnrollOptions;
@@ -291,7 +293,8 @@
         if (mTestHalEnabled) {
             return true;
         }
-        return (ServiceManager.checkService(IFingerprint.DESCRIPTOR + "/" + mHalInstanceName)
+        return (ServiceManager.checkService(
+                remapFqName(IFingerprint.DESCRIPTOR + "/" + mHalInstanceName))
                 != null);
     }
 
@@ -330,10 +333,7 @@
 
         Slog.d(getTag(), "Daemon was null, reconnecting");
 
-        mDaemon = IFingerprint.Stub.asInterface(
-                Binder.allowBlocking(
-                        ServiceManager.waitForDeclaredService(
-                                IFingerprint.DESCRIPTOR + "/" + mHalInstanceNameCurrent)));
+        mDaemon = getIFingerprint(IFingerprint.DESCRIPTOR + "/" + mHalInstanceNameCurrent);
         if (mDaemon == null) {
             Slog.e(getTag(), "Unable to get daemon");
             return null;
@@ -905,8 +905,8 @@
     void setTestHalEnabled(boolean enabled) {
         final boolean changed = enabled != mTestHalEnabled;
         mTestHalEnabled = enabled;
-        Slog.i(getTag(), "setTestHalEnabled(): useVhalForTesting=" + Flags.useVhalForTesting()
-                + "mTestHalEnabled=" + mTestHalEnabled + " changed=" + changed);
+        Slog.i(getTag(), "setTestHalEnabled(): useVhalForTestingFlags=" + Flags.useVhalForTesting()
+                + " mTestHalEnabled=" + mTestHalEnabled + " changed=" + changed);
         if (changed && useVhalForTesting()) {
             getHalInstance();
         }
@@ -999,12 +999,13 @@
      */
     public IVirtualHal getVhal() throws RemoteException {
         if (mVhal == null && useVhalForTesting()) {
-            mVhal = IVirtualHal.Stub.asInterface(mDaemon.asBinder().getExtension());
-            if (mVhal == null) {
-                Slog.e(getTag(), "Unable to get fingerprint virtualhal interface");
-            }
+            mVhal = IVirtualHal.Stub.asInterface(
+                    Binder.allowBlocking(
+                            ServiceManager.waitForService(
+                                    IVirtualHal.DESCRIPTOR + "/"
+                                            + mHalInstanceNameCurrent)));
+            Slog.d(getTag(), "getVhal " + mHalInstanceNameCurrent);
         }
-
         return mVhal;
     }
 
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java
index d12d7b2..25d1fe7 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java
@@ -16,6 +16,8 @@
 
 package com.android.server.biometrics.sensors.fingerprint.aidl;
 
+import static android.hardware.fingerprint.FingerprintSensorConfigurations.remapFqName;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
@@ -356,8 +358,8 @@
         if (mTestHalEnabled) {
             return true;
         }
-        return (ServiceManager.checkService(IFingerprint.DESCRIPTOR + "/" + halInstance)
-                != null);
+        return (ServiceManager.checkService(
+                remapFqName(IFingerprint.DESCRIPTOR + "/" + halInstance)) != null);
     }
 
     @NonNull protected BiometricContext getBiometricContext() {