Pass extra information to face HAL

Test: atest BiometricContextproviderTest
Bug: 305284901
Change-Id: I3d00157b2b00048466d1e893a96ffa1c51a7a591
diff --git a/Android.bp b/Android.bp
index c1fb41f..23234fd 100644
--- a/Android.bp
+++ b/Android.bp
@@ -95,7 +95,7 @@
         ":platform-compat-native-aidl",
 
         // AIDL sources from external directories
-        ":android.hardware.biometrics.common-V3-java-source",
+        ":android.hardware.biometrics.common-V4-java-source",
         ":android.hardware.biometrics.fingerprint-V3-java-source",
         ":android.hardware.gnss-V2-java-source",
         ":android.hardware.graphics.common-V3-java-source",
diff --git a/services/core/java/com/android/server/biometrics/log/BiometricContextProvider.java b/services/core/java/com/android/server/biometrics/log/BiometricContextProvider.java
index 7452228..95a047f 100644
--- a/services/core/java/com/android/server/biometrics/log/BiometricContextProvider.java
+++ b/services/core/java/com/android/server/biometrics/log/BiometricContextProvider.java
@@ -116,8 +116,10 @@
             service.setBiometicContextListener(new IBiometricContextListener.Stub() {
                 @Override
                 public void onFoldChanged(int foldState) {
-                    mFoldState = foldState;
-                    // no need to notify, not sent to HAL
+                    if (mFoldState != foldState) {
+                        mFoldState = foldState;
+                        notifyChanged();
+                    }
                 }
 
                 @Override
@@ -254,6 +256,7 @@
                 + "isAwake: " + isAwake() +  ", "
                 + "isDisplayOn: " + isDisplayOn() +  ", "
                 + "dock: " + getDockedState() + ", "
-                + "rotation: " + getCurrentRotation() + "]";
+                + "rotation: " + getCurrentRotation() + ", "
+                + "foldState: " + mFoldState + "]";
     }
 }
diff --git a/services/core/java/com/android/server/biometrics/log/OperationContextExt.java b/services/core/java/com/android/server/biometrics/log/OperationContextExt.java
index f78ca43..b4e0dff 100644
--- a/services/core/java/com/android/server/biometrics/log/OperationContextExt.java
+++ b/services/core/java/com/android/server/biometrics/log/OperationContextExt.java
@@ -23,6 +23,7 @@
 import android.hardware.biometrics.IBiometricContextListener;
 import android.hardware.biometrics.common.AuthenticateReason;
 import android.hardware.biometrics.common.DisplayState;
+import android.hardware.biometrics.common.FoldState;
 import android.hardware.biometrics.common.OperationContext;
 import android.hardware.biometrics.common.OperationReason;
 import android.hardware.biometrics.common.WakeReason;
@@ -250,6 +251,7 @@
     OperationContextExt update(@NonNull BiometricContext biometricContext, boolean isCrypto) {
         mAidlContext.isAod = biometricContext.isAod();
         mAidlContext.displayState = toAidlDisplayState(biometricContext.getDisplayState());
+        mAidlContext.foldState = toAidlFoldState(biometricContext.getFoldState());
         mAidlContext.isCrypto = isCrypto;
         setFirstSessionId(biometricContext);
 
@@ -276,6 +278,19 @@
         return DisplayState.UNKNOWN;
     }
 
+    @FoldState
+    private static int toAidlFoldState(@IBiometricContextListener.FoldState int state) {
+        switch (state) {
+            case IBiometricContextListener.FoldState.FULLY_CLOSED:
+                return FoldState.FULLY_CLOSED;
+            case IBiometricContextListener.FoldState.FULLY_OPENED:
+                return FoldState.FULLY_OPENED;
+            case IBiometricContextListener.FoldState.HALF_OPENED:
+                return FoldState.HALF_OPENED;
+        }
+        return FoldState.UNKNOWN;
+    }
+
     private void setFirstSessionId(@NonNull BiometricContext biometricContext) {
         if (mIsBP) {
             mSessionInfo = biometricContext.getBiometricPromptSessionInfo();
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricContextProviderTest.java b/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricContextProviderTest.java
index 4375105..1b9e6fb 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricContextProviderTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricContextProviderTest.java
@@ -179,6 +179,29 @@
     }
 
     @Test
+    public void testSubscribesToFoldState() throws RemoteException {
+        final List<Integer> actual = new ArrayList<>();
+        final List<Integer> expected = List.of(FoldState.FULLY_CLOSED, FoldState.FULLY_OPENED,
+                FoldState.UNKNOWN, FoldState.HALF_OPENED);
+        mProvider.subscribe(mOpContext, ctx -> {
+            assertThat(ctx).isSameInstanceAs(mOpContext.toAidlContext());
+            assertThat(mProvider.getFoldState()).isEqualTo(ctx.foldState);
+            actual.add(ctx.foldState);
+        });
+
+        for (int v : expected) {
+            mListener.onFoldChanged(v);
+        }
+
+        assertThat(actual).containsExactly(
+                FoldState.FULLY_CLOSED,
+                FoldState.FULLY_OPENED,
+                FoldState.UNKNOWN,
+                FoldState.HALF_OPENED
+        ).inOrder();
+    }
+
+    @Test
     public void testSubscribesToDisplayState() throws RemoteException {
         final List<Integer> actual = new ArrayList<>();
         final List<Integer> expected = List.of(AuthenticateOptions.DISPLAY_STATE_AOD,