Merge "Create version specific dir for generated libs." into main
diff --git a/audio/aidl/Android.bp b/audio/aidl/Android.bp
index 8bb8cd5..b67b9d2 100644
--- a/audio/aidl/Android.bp
+++ b/audio/aidl/Android.bp
@@ -64,6 +64,9 @@
             ],
             min_sdk_version: "31",
         },
+        rust: {
+            enabled: true,
+        },
     },
     versions_with_info: [
         {
@@ -112,6 +115,13 @@
     ],
 }
 
+rust_defaults {
+    name: "latest_android_hardware_audio_common_rust",
+    rustlibs: [
+        latest_android_hardware_audio_common + "-rust",
+    ],
+}
+
 aidl_interface_defaults {
     name: "latest_android_hardware_audio_common_import_interface",
     imports: [
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.aidl
new file mode 100644
index 0000000..c1dc51c
--- /dev/null
+++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.biometrics.fingerprint;
+/* @hide */
+@VintfStability
+union AcquiredInfoAndVendorCode {
+  android.hardware.biometrics.fingerprint.AcquiredInfo acquiredInfo = android.hardware.biometrics.fingerprint.AcquiredInfo.UNKNOWN;
+  int vendorCode;
+}
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/EnrollmentProgressStep.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/EnrollmentProgressStep.aidl
new file mode 100644
index 0000000..173ac17
--- /dev/null
+++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/EnrollmentProgressStep.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.biometrics.fingerprint;
+/* @hide */
+@VintfStability
+parcelable EnrollmentProgressStep {
+  int durationMs;
+  android.hardware.biometrics.fingerprint.AcquiredInfoAndVendorCode[] acquiredInfoAndVendorCodes;
+}
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/IVirtualHal.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/IVirtualHal.aidl
index 2c7e1a0..33ae83c 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/IVirtualHal.aidl
+++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/IVirtualHal.aidl
@@ -37,24 +37,26 @@
 interface IVirtualHal {
   oneway void setEnrollments(in int[] id);
   oneway void setEnrollmentHit(in int hit_id);
+  oneway void setNextEnrollment(in android.hardware.biometrics.fingerprint.NextEnrollment next_enrollment);
   oneway void setAuthenticatorId(in long id);
   oneway void setChallenge(in long challenge);
   oneway void setOperationAuthenticateFails(in boolean fail);
   oneway void setOperationAuthenticateLatency(in int[] latencyMs);
   oneway void setOperationAuthenticateDuration(in int durationMs);
   oneway void setOperationAuthenticateError(in int error);
-  oneway void setOperationAuthenticateAcquired(in int[] acquired);
+  oneway void setOperationAuthenticateAcquired(in android.hardware.biometrics.fingerprint.AcquiredInfoAndVendorCode[] acquired);
   oneway void setOperationEnrollError(in int error);
   oneway void setOperationEnrollLatency(in int[] latencyMs);
   oneway void setOperationDetectInteractionLatency(in int[] latencyMs);
   oneway void setOperationDetectInteractionError(in int error);
   oneway void setOperationDetectInteractionDuration(in int durationMs);
-  oneway void setOperationDetectInteractionAcquired(in int[] acquired);
+  oneway void setOperationDetectInteractionAcquired(in android.hardware.biometrics.fingerprint.AcquiredInfoAndVendorCode[] acquired);
   oneway void setLockout(in boolean lockout);
   oneway void setLockoutEnable(in boolean enable);
   oneway void setLockoutTimedThreshold(in int threshold);
   oneway void setLockoutTimedDuration(in int durationMs);
   oneway void setLockoutPermanentThreshold(in int threshold);
+  oneway void resetConfigurations();
   oneway void setType(in android.hardware.biometrics.fingerprint.FingerprintSensorType type);
   oneway void setSensorId(in int id);
   oneway void setSensorStrength(in android.hardware.biometrics.common.SensorStrength strength);
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/NextEnrollment.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/NextEnrollment.aidl
new file mode 100644
index 0000000..75ed070
--- /dev/null
+++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/NextEnrollment.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.biometrics.fingerprint;
+/* @hide */
+@VintfStability
+parcelable NextEnrollment {
+  int id;
+  android.hardware.biometrics.fingerprint.EnrollmentProgressStep[] progressSteps;
+  boolean result = true;
+}
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.aidl
new file mode 100644
index 0000000..c7be950
--- /dev/null
+++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/AcquiredInfoAndVendorCode.aidl
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.biometrics.fingerprint;
+
+import android.hardware.biometrics.fingerprint.AcquiredInfo;
+
+/**
+ * @hide
+ */
+@VintfStability
+union AcquiredInfoAndVendorCode {
+    /**
+     * Acquired info as specified in AcqauiredInfo.aidl
+     */
+    AcquiredInfo acquiredInfo = AcquiredInfo.UNKNOWN;
+
+    /**
+     * Vendor specific code
+     */
+    int vendorCode;
+}
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/EnrollmentProgressStep.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/EnrollmentProgressStep.aidl
new file mode 100644
index 0000000..bf038f6
--- /dev/null
+++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/EnrollmentProgressStep.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.biometrics.fingerprint;
+
+import android.hardware.biometrics.fingerprint.AcquiredInfoAndVendorCode;
+
+/**
+ * @hide
+ */
+@VintfStability
+parcelable EnrollmentProgressStep {
+    /**
+     * The duration of the enrollment step in milli-seconds
+     */
+    int durationMs;
+
+    /**
+     * The sequence of acquired info and vendor code to be issued by HAL during the step.
+     * The codes are evenly spreaded over the duration
+     */
+    AcquiredInfoAndVendorCode[] acquiredInfoAndVendorCodes;
+}
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IVirtualHal.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IVirtualHal.aidl
index 1599394..cb9135e 100644
--- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IVirtualHal.aidl
+++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IVirtualHal.aidl
@@ -17,7 +17,9 @@
 package android.hardware.biometrics.fingerprint;
 
 import android.hardware.biometrics.common.SensorStrength;
+import android.hardware.biometrics.fingerprint.AcquiredInfoAndVendorCode;
 import android.hardware.biometrics.fingerprint.FingerprintSensorType;
+import android.hardware.biometrics.fingerprint.NextEnrollment;
 import android.hardware.biometrics.fingerprint.SensorLocation;
 
 /**
@@ -54,6 +56,15 @@
     void setEnrollmentHit(in int hit_id);
 
     /**
+     * setNextEnrollment
+     *
+     * Set the next enrollment behavior
+     *
+     * @param next_enrollment specifies enrollment id, progress stages and final result
+     */
+    void setNextEnrollment(in NextEnrollment next_enrollment);
+
+    /**
      * setAuthenticatorId
      *
      * Set authenticator id in virtual HAL, the id is returned in ISession#getAuthenticatorId() call
@@ -137,7 +148,7 @@
      *
      * @param acquired[], one or more acquired info codes
      */
-    void setOperationAuthenticateAcquired(in int[] acquired);
+    void setOperationAuthenticateAcquired(in AcquiredInfoAndVendorCode[] acquired);
 
     /**
      * setOperationEnrollError
@@ -226,7 +237,7 @@
      *
      * @param acquired[], one or more acquired info codes
      */
-    void setOperationDetectInteractionAcquired(in int[] acquired);
+    void setOperationDetectInteractionAcquired(in AcquiredInfoAndVendorCode[] acquired);
 
     /**
      * setLockout
@@ -285,6 +296,13 @@
     void setLockoutPermanentThreshold(in int threshold);
 
     /**
+     * resetConfigurations
+     *
+     * Reset all virtual hal configurations to default values
+     */
+    void resetConfigurations();
+
+    /**
      * The following functions are used to configure Fingerprint Virtual HAL sensor properties
      *  refer to SensorProps.aidl and CommonProps.aidl for details of each property
      */
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/NextEnrollment.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/NextEnrollment.aidl
new file mode 100644
index 0000000..4b50850
--- /dev/null
+++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/NextEnrollment.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.biometrics.fingerprint;
+
+/**
+ * @hide
+ */
+@VintfStability
+parcelable NextEnrollment {
+    /**
+     *  Identifier of the next enrollment if successful
+     */
+    int id;
+
+    /**
+     *  Specification of the progress steps of the next enrollment, each step consists of duration
+     *  and sequence of acquired info codes to be generated by HAL.
+     *  See EnrollmentProgressStep.aidl for more details
+     */
+    android.hardware.biometrics.fingerprint.EnrollmentProgressStep[] progressSteps;
+
+    /**
+     * Success or failure of the next enrollment
+     */
+    boolean result = true;
+}
diff --git a/biometrics/fingerprint/aidl/default/VirtualHal.cpp b/biometrics/fingerprint/aidl/default/VirtualHal.cpp
index d2baaf5..e107d2f 100644
--- a/biometrics/fingerprint/aidl/default/VirtualHal.cpp
+++ b/biometrics/fingerprint/aidl/default/VirtualHal.cpp
@@ -27,6 +27,8 @@
 
 namespace aidl::android::hardware::biometrics::fingerprint {
 
+using Tag = AcquiredInfoAndVendorCode::Tag;
+
 ::ndk::ScopedAStatus VirtualHal::setEnrollments(const std::vector<int32_t>& enrollments) {
     Fingerprint::cfg().sourcedFromAidl();
     Fingerprint::cfg().setopt<OptIntVec>("enrollments", intVec2OptIntVec(enrollments));
@@ -39,6 +41,42 @@
     return ndk::ScopedAStatus::ok();
 }
 
+::ndk::ScopedAStatus VirtualHal::setNextEnrollment(
+        const ::aidl::android::hardware::biometrics::fingerprint::NextEnrollment& next_enrollment) {
+    Fingerprint::cfg().sourcedFromAidl();
+    std::ostringstream os;
+    os << next_enrollment.id << ":";
+
+    int stepSize = next_enrollment.progressSteps.size();
+    for (int i = 0; i < stepSize; i++) {
+        auto& step = next_enrollment.progressSteps[i];
+        os << step.durationMs;
+        int acSize = step.acquiredInfoAndVendorCodes.size();
+        for (int j = 0; j < acSize; j++) {
+            if (j == 0) os << "-[";
+            auto& acquiredInfoAndVendorCode = step.acquiredInfoAndVendorCodes[j];
+            if (acquiredInfoAndVendorCode.getTag() == AcquiredInfoAndVendorCode::vendorCode)
+                os << acquiredInfoAndVendorCode.get<Tag::vendorCode>();
+            else if (acquiredInfoAndVendorCode.getTag() == AcquiredInfoAndVendorCode::acquiredInfo)
+                os << (int)acquiredInfoAndVendorCode.get<Tag::acquiredInfo>();
+            else
+                LOG(FATAL) << "ERROR: wrong AcquiredInfoAndVendorCode union tag";
+            if (j == acSize - 1)
+                os << "]";
+            else
+                os << ",";
+        }
+        if (i == stepSize - 1)
+            os << ":";
+        else
+            os << ",";
+    }
+
+    os << (next_enrollment.result ? "true" : "false");
+    Fingerprint::cfg().set<std::string>("next_enrollment", os.str());
+    return ndk::ScopedAStatus::ok();
+}
+
 ::ndk::ScopedAStatus VirtualHal::setAuthenticatorId(int64_t in_id) {
     Fingerprint::cfg().sourcedFromAidl();
     Fingerprint::cfg().set<int64_t>("authenticator_id", in_id);
@@ -87,10 +125,10 @@
 }
 
 ::ndk::ScopedAStatus VirtualHal::setOperationAuthenticateAcquired(
-        const std::vector<int32_t>& in_acquired) {
+        const std::vector<AcquiredInfoAndVendorCode>& in_acquired) {
     Fingerprint::cfg().sourcedFromAidl();
     Fingerprint::cfg().setopt<OptIntVec>("operation_authenticate_acquired",
-                                         intVec2OptIntVec(in_acquired));
+                                         acquiredInfoVec2OptIntVec(in_acquired));
     return ndk::ScopedAStatus::ok();
 }
 
@@ -139,10 +177,10 @@
 }
 
 ::ndk::ScopedAStatus VirtualHal::setOperationDetectInteractionAcquired(
-        const std::vector<int32_t>& in_acquired) {
+        const std::vector<AcquiredInfoAndVendorCode>& in_acquired) {
     Fingerprint::cfg().sourcedFromAidl();
     Fingerprint::cfg().setopt<OptIntVec>("operation_detect_interaction_acquired",
-                                         intVec2OptIntVec(in_acquired));
+                                         acquiredInfoVec2OptIntVec(in_acquired));
     return ndk::ScopedAStatus::ok();
 }
 
@@ -188,6 +226,12 @@
     return ndk::ScopedAStatus::ok();
 }
 
+::ndk::ScopedAStatus VirtualHal::resetConfigurations() {
+    Fingerprint::cfg().sourcedFromAidl();
+    Fingerprint::cfg().init();
+    return ndk::ScopedAStatus::ok();
+}
+
 ::ndk::ScopedAStatus VirtualHal::setType(
         ::aidl::android::hardware::biometrics::fingerprint::FingerprintSensorType in_type) {
     Fingerprint::cfg().sourcedFromAidl();
@@ -254,6 +298,23 @@
     return optIntVec;
 }
 
+OptIntVec VirtualHal::acquiredInfoVec2OptIntVec(
+        const std::vector<AcquiredInfoAndVendorCode>& in_vec) {
+    OptIntVec optIntVec;
+    std::transform(in_vec.begin(), in_vec.end(), std::back_inserter(optIntVec),
+                   [](AcquiredInfoAndVendorCode ac) {
+                       int value;
+                       if (ac.getTag() == AcquiredInfoAndVendorCode::acquiredInfo)
+                           value = (int)ac.get<Tag::acquiredInfo>();
+                       else if (ac.getTag() == AcquiredInfoAndVendorCode::vendorCode)
+                           value = ac.get<Tag::vendorCode>();
+                       else
+                           LOG(FATAL) << "ERROR: wrong AcquiredInfoAndVendorCode tag";
+                       return std::optional<int>(value);
+                   });
+    return optIntVec;
+}
+
 ::ndk::ScopedAStatus VirtualHal::sanityCheckLatency(const std::vector<int32_t>& in_latency) {
     if (in_latency.size() == 0 || in_latency.size() > 2) {
         return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
diff --git a/biometrics/fingerprint/aidl/default/include/VirtualHal.h b/biometrics/fingerprint/aidl/default/include/VirtualHal.h
index 6cc4b66..e5f62fc 100644
--- a/biometrics/fingerprint/aidl/default/include/VirtualHal.h
+++ b/biometrics/fingerprint/aidl/default/include/VirtualHal.h
@@ -28,6 +28,9 @@
 
     ::ndk::ScopedAStatus setEnrollments(const std::vector<int32_t>& in_id) override;
     ::ndk::ScopedAStatus setEnrollmentHit(int32_t in_hit_id) override;
+    ::ndk::ScopedAStatus setNextEnrollment(
+            const ::aidl::android::hardware::biometrics::fingerprint::NextEnrollment&
+                    in_next_enrollment) override;
     ::ndk::ScopedAStatus setAuthenticatorId(int64_t in_id) override;
     ::ndk::ScopedAStatus setChallenge(int64_t in_challenge) override;
     ::ndk::ScopedAStatus setOperationAuthenticateFails(bool in_fail) override;
@@ -36,7 +39,7 @@
     ::ndk::ScopedAStatus setOperationAuthenticateDuration(int32_t in_duration) override;
     ::ndk::ScopedAStatus setOperationAuthenticateError(int32_t in_error) override;
     ::ndk::ScopedAStatus setOperationAuthenticateAcquired(
-            const std::vector<int32_t>& in_acquired) override;
+            const std::vector<AcquiredInfoAndVendorCode>& in_acquired) override;
     ::ndk::ScopedAStatus setOperationEnrollError(int32_t in_error) override;
     ::ndk::ScopedAStatus setOperationEnrollLatency(const std::vector<int32_t>& in_latency) override;
     ::ndk::ScopedAStatus setOperationDetectInteractionLatency(
@@ -44,12 +47,13 @@
     ::ndk::ScopedAStatus setOperationDetectInteractionError(int32_t in_error) override;
     ::ndk::ScopedAStatus setOperationDetectInteractionDuration(int32_t in_duration) override;
     ::ndk::ScopedAStatus setOperationDetectInteractionAcquired(
-            const std::vector<int32_t>& in_acquired) override;
+            const std::vector<AcquiredInfoAndVendorCode>& in_acquired) override;
     ::ndk::ScopedAStatus setLockout(bool in_lockout) override;
     ::ndk::ScopedAStatus setLockoutEnable(bool in_enable) override;
     ::ndk::ScopedAStatus setLockoutTimedThreshold(int32_t in_threshold) override;
     ::ndk::ScopedAStatus setLockoutTimedDuration(int32_t in_duration) override;
     ::ndk::ScopedAStatus setLockoutPermanentThreshold(int32_t in_threshold) override;
+    ::ndk::ScopedAStatus resetConfigurations() override;
     ::ndk::ScopedAStatus setType(
             ::aidl::android::hardware::biometrics::fingerprint::FingerprintSensorType in_type)
             override;
@@ -66,6 +70,7 @@
 
   private:
     OptIntVec intVec2OptIntVec(const std::vector<int32_t>& intVec);
+    OptIntVec acquiredInfoVec2OptIntVec(const std::vector<AcquiredInfoAndVendorCode>& intVec);
     ::ndk::ScopedAStatus sanityCheckLatency(const std::vector<int32_t>& in_latency);
     Fingerprint* mFp;
 };
diff --git a/biometrics/fingerprint/aidl/default/tests/VirtualHalTest.cpp b/biometrics/fingerprint/aidl/default/tests/VirtualHalTest.cpp
index d8495d1..3fe0b2a 100644
--- a/biometrics/fingerprint/aidl/default/tests/VirtualHalTest.cpp
+++ b/biometrics/fingerprint/aidl/default/tests/VirtualHalTest.cpp
@@ -100,6 +100,27 @@
     ASSERT_TRUE(Fingerprint::cfg().get<int32_t>("enrollment_hit") == 11);
 }
 
+TEST_F(VirtualHalTest, next_enrollment) {
+    struct {
+        std::string nextEnrollmentStr;
+        fingerprint::NextEnrollment nextEnrollment;
+    } testData[] = {
+            {"1:20:true", {1, {{20}}, true}},
+            {"1:50,60,70:true", {1, {{50}, {60}, {70}}, true}},
+            {"2:50-[8],60,70-[2,1002,1]:false",
+             {2,
+              {{50, {{AcquiredInfo::START}}},
+               {60},
+               {70, {{AcquiredInfo::PARTIAL}, {1002}, {AcquiredInfo::GOOD}}}},
+              false}},
+    };
+
+    for (auto& d : testData) {
+        mVhal->setNextEnrollment(d.nextEnrollment);
+        ASSERT_TRUE(Fingerprint::cfg().get<std::string>("next_enrollment") == d.nextEnrollmentStr);
+    }
+}
+
 TEST_F(VirtualHalTest, authenticator_id_int64) {
     mVhal->setAuthenticatorId(12345678900);
     ASSERT_TRUE(Fingerprint::cfg().get<int64_t>("authenticator_id") == 12345678900);
@@ -111,12 +132,16 @@
 }
 
 TEST_F(VirtualHalTest, operationAuthenticateAcquired_int32_vector) {
-    std::vector<int32_t> ac{1, 2, 3, 4, 5, 6, 7};
+    using Tag = AcquiredInfoAndVendorCode::Tag;
+    std::vector<AcquiredInfoAndVendorCode> ac{
+            {AcquiredInfo::START}, {AcquiredInfo::PARTIAL}, {1023}};
     mVhal->setOperationAuthenticateAcquired(ac);
     OptIntVec ac_get = Fingerprint::cfg().getopt<OptIntVec>("operation_authenticate_acquired");
     ASSERT_TRUE(ac_get.size() == ac.size());
     for (int i = 0; i < ac.size(); i++) {
-        ASSERT_TRUE(ac[i] == ac_get[i]);
+        int acCode = (ac[i].getTag() == Tag::acquiredInfo) ? (int)ac[i].get<Tag::acquiredInfo>()
+                                                           : ac[i].get<Tag::vendorCode>();
+        ASSERT_TRUE(acCode == ac_get[i]);
     }
 }
 
@@ -212,7 +237,7 @@
     mVhal->setOperationEnrollError(5);
     mVhal->setOperationEnrollLatency({4, 5});
     mVhal->setOperationDetectInteractionError(6);
-    mVhal->setOperationDetectInteractionAcquired({4, 3, 2});
+    mVhal->setOperationDetectInteractionAcquired({{AcquiredInfo::START}, {AcquiredInfo::GOOD}});
     mVhal->setLockout(false);
     mVhal->setLockoutEnable(false);
     mVhal->setSensorId(5);
diff --git a/bluetooth/finder/aidl/vts/VtsHalBluetoothFinderTargetTest.cpp b/bluetooth/finder/aidl/vts/VtsHalBluetoothFinderTargetTest.cpp
index fee9e242..be07a7d 100644
--- a/bluetooth/finder/aidl/vts/VtsHalBluetoothFinderTargetTest.cpp
+++ b/bluetooth/finder/aidl/vts/VtsHalBluetoothFinderTargetTest.cpp
@@ -18,7 +18,6 @@
 #include <aidl/Vintf.h>
 #include <aidl/android/hardware/bluetooth/finder/IBluetoothFinder.h>
 #include <android-base/logging.h>
-#include <android-base/properties.h>
 #include <android/binder_manager.h>
 #include <android/binder_process.h>
 #include <binder/IServiceManager.h>
@@ -72,12 +71,6 @@
   return bluetooth_finder->getPoweredOffFinderMode(status);
 }
 
-TEST_P(BluetoothFinderTest, PropertyIsSet) {
-  ASSERT_EQ(
-      android::base::GetProperty("ro.bluetooth.finder.supported", "false"),
-      "true");
-}
-
 TEST_P(BluetoothFinderTest, SendEidsSingle) {
   ScopedAStatus status = sendEids(1);
   ASSERT_TRUE(status.isOk());
diff --git a/broadcastradio/aidl/Android.bp b/broadcastradio/aidl/Android.bp
index 1540944..82ee949 100644
--- a/broadcastradio/aidl/Android.bp
+++ b/broadcastradio/aidl/Android.bp
@@ -36,6 +36,9 @@
             sdk_version: "module_current",
             min_sdk_version: "Tiramisu",
         },
+        rust: {
+            enabled: true,
+        },
     },
     versions_with_info: [
         {
@@ -68,3 +71,10 @@
         latest_android_hardware_broadcastradio + "-java",
     ],
 }
+
+rust_defaults {
+    name: "latest_android_hardware_broadcastradio_rust",
+    rustlibs: [
+        latest_android_hardware_broadcastradio + "-rust",
+    ],
+}
diff --git a/broadcastradio/aidl/rust_impl/Android.bp b/broadcastradio/aidl/rust_impl/Android.bp
new file mode 100644
index 0000000..d6f984e
--- /dev/null
+++ b/broadcastradio/aidl/rust_impl/Android.bp
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+rust_binary {
+    name: "android.hardware.broadcastradio-rust-service",
+    relative_install_path: "hw",
+    vendor: true,
+    srcs: ["src/*.rs"],
+    crate_root: "src/main.rs",
+    defaults: [
+        "latest_android_hardware_broadcastradio_rust",
+    ],
+    vintf_fragments: ["broadcastradio-rust-service.xml"],
+    init_rc: ["broadcastradio-rust-service.rc"],
+    rustlibs: [
+        "libbinder_rs",
+    ],
+}
diff --git a/broadcastradio/aidl/rust_impl/README.md b/broadcastradio/aidl/rust_impl/README.md
new file mode 100644
index 0000000..17e0c18
--- /dev/null
+++ b/broadcastradio/aidl/rust_impl/README.md
@@ -0,0 +1,13 @@
+# Rust Skeleton BroadcastRadio HAL implementation.
+
+WARNING: This is not a reference BroadcastRadio HAL implementation and does
+not contain any actual implementation.
+
+This folder contains a skeleton broadcast radio HAL implementation in Rust to
+demonstrate  how vendor may implement a Rust broadcast radio HAL. To run this
+broadcast radio HAL, include `android.hardware.broadcastradio-rust-service`
+in your image.
+
+This implementation returns `StatusCode::UNKNOWN_ERROR` for all operations
+and does not pass VTS/CTS. Vendor must replace the logic in
+`default_broadcastradio_hal.rs` with the actual implementation
\ No newline at end of file
diff --git a/broadcastradio/aidl/rust_impl/broadcastradio-rust-service.rc b/broadcastradio/aidl/rust_impl/broadcastradio-rust-service.rc
new file mode 100644
index 0000000..4dad616
--- /dev/null
+++ b/broadcastradio/aidl/rust_impl/broadcastradio-rust-service.rc
@@ -0,0 +1,5 @@
+service vendor.broadcastradio-default /vendor/bin/hw/android.hardware.broadcastradio-service.default
+    interface aidl android.hardware.broadcastradio.IBroadcastRadio/amfm
+    class hal
+    user audioserver
+    group audio
diff --git a/broadcastradio/aidl/rust_impl/broadcastradio-rust-service.xml b/broadcastradio/aidl/rust_impl/broadcastradio-rust-service.xml
new file mode 100644
index 0000000..ced2d78
--- /dev/null
+++ b/broadcastradio/aidl/rust_impl/broadcastradio-rust-service.xml
@@ -0,0 +1,23 @@
+<!--
+  ~ Copyright (C) 2024 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<manifest version="1.0" type="device">
+    <hal format="aidl">
+        <name>android.hardware.broadcastradio</name>
+        <version>2</version>
+        <fqname>IBroadcastRadio/amfm</fqname>
+    </hal>
+</manifest>
diff --git a/broadcastradio/aidl/rust_impl/src/default_broadcastradio_hal.rs b/broadcastradio/aidl/rust_impl/src/default_broadcastradio_hal.rs
new file mode 100644
index 0000000..ea2f9d3
--- /dev/null
+++ b/broadcastradio/aidl/rust_impl/src/default_broadcastradio_hal.rs
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+use android_hardware_broadcastradio::aidl::android::hardware::broadcastradio::{
+    AmFmRegionConfig::AmFmRegionConfig,
+    AnnouncementType::AnnouncementType,
+    ConfigFlag::ConfigFlag,
+    DabTableEntry::DabTableEntry,
+    IAnnouncementListener::IAnnouncementListener,
+    IBroadcastRadio::IBroadcastRadio,
+    ICloseHandle::ICloseHandle,
+    ITunerCallback::ITunerCallback,
+    ProgramFilter::ProgramFilter,
+    ProgramSelector::ProgramSelector,
+    Properties::Properties,
+    VendorKeyValue::VendorKeyValue,
+};
+use binder::{Interface, Result as BinderResult, StatusCode, Strong};
+use std::vec::Vec;
+
+/// This struct is defined to implement IBroadcastRadio AIDL interface.
+pub struct DefaultBroadcastRadioHal;
+
+impl Interface for DefaultBroadcastRadioHal {}
+
+impl IBroadcastRadio for DefaultBroadcastRadioHal {
+    fn getAmFmRegionConfig(&self, _full : bool) -> BinderResult<AmFmRegionConfig> {
+        Err(StatusCode::UNKNOWN_ERROR.into())
+    }
+
+    fn getDabRegionConfig(&self) -> BinderResult<Vec<DabTableEntry>> {
+        Err(StatusCode::UNKNOWN_ERROR.into())
+    }
+
+    fn getProperties(&self) -> BinderResult<Properties> {
+        Err(StatusCode::UNKNOWN_ERROR.into())
+    }
+
+    fn getImage(&self, _id : i32) -> BinderResult<Vec<u8>> {
+        Err(StatusCode::UNKNOWN_ERROR.into())
+    }
+
+    fn setTunerCallback(&self, _callback : &Strong<dyn ITunerCallback>) -> BinderResult<()> {
+        Err(StatusCode::UNKNOWN_ERROR.into())
+    }
+
+    fn unsetTunerCallback(&self) -> BinderResult<()> {
+        Err(StatusCode::UNKNOWN_ERROR.into())
+    }
+
+    fn tune(&self, _program : &ProgramSelector) -> BinderResult<()> {
+        Err(StatusCode::UNKNOWN_ERROR.into())
+    }
+
+    fn seek(&self, _direction_up : bool, _skip_sub_channel : bool) -> BinderResult<()> {
+        Err(StatusCode::UNKNOWN_ERROR.into())
+    }
+
+    fn step(&self, _direction_up : bool) -> BinderResult<()> {
+        Err(StatusCode::UNKNOWN_ERROR.into())
+    }
+
+    fn cancel(&self) -> BinderResult<()> {
+        Err(StatusCode::UNKNOWN_ERROR.into())
+    }
+
+    fn startProgramListUpdates(&self, _filter : &ProgramFilter) -> BinderResult<()> {
+        Err(StatusCode::UNKNOWN_ERROR.into())
+    }
+
+    fn stopProgramListUpdates(&self) -> BinderResult<()> {
+        Err(StatusCode::UNKNOWN_ERROR.into())
+    }
+
+    fn isConfigFlagSet(&self, _flag : ConfigFlag) -> BinderResult<bool> {
+        Err(StatusCode::UNKNOWN_ERROR.into())
+    }
+
+    fn setConfigFlag(&self, _flag : ConfigFlag, _value : bool) -> BinderResult<()> {
+        Err(StatusCode::UNKNOWN_ERROR.into())
+    }
+
+    fn setParameters(&self, _parameters : &[VendorKeyValue]) -> BinderResult<Vec<VendorKeyValue>> {
+        Err(StatusCode::UNKNOWN_ERROR.into())
+    }
+
+    fn getParameters(&self, _parameters : &[String]) -> BinderResult<Vec<VendorKeyValue>> {
+        Err(StatusCode::UNKNOWN_ERROR.into())
+    }
+
+    fn registerAnnouncementListener(&self, _listener : &Strong<dyn IAnnouncementListener>,
+            _enabled : &[AnnouncementType]) -> BinderResult<Strong<dyn ICloseHandle>> {
+        Err(StatusCode::UNKNOWN_ERROR.into())
+    }
+}
diff --git a/broadcastradio/aidl/rust_impl/src/main.rs b/broadcastradio/aidl/rust_impl/src/main.rs
new file mode 100644
index 0000000..c0bc055
--- /dev/null
+++ b/broadcastradio/aidl/rust_impl/src/main.rs
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ mod default_broadcastradio_hal;
+
+use android_hardware_broadcastradio::aidl::android::hardware::broadcastradio::IBroadcastRadio::BnBroadcastRadio;
+use crate::default_broadcastradio_hal::DefaultBroadcastRadioHal;
+
+fn main() {
+    binder::ProcessState::start_thread_pool();
+    let my_service = DefaultBroadcastRadioHal;
+    let service_name = "android.hardware.broadcastradio.IBroadcastRadio/amfm";
+    let my_service_binder = BnBroadcastRadio::new_binder(
+        my_service,
+        binder::BinderFeatures::default(),
+    );
+    binder::add_service(service_name, my_service_binder.as_binder())
+    		.expect(format!("Failed to register {}?", service_name).as_str());
+    // Does not return.
+    binder::ProcessState::join_thread_pool()
+}
diff --git a/camera/provider/aidl/vts/VtsAidlHalCameraProvider_TargetTest.cpp b/camera/provider/aidl/vts/VtsAidlHalCameraProvider_TargetTest.cpp
index 368e954..31e8014 100644
--- a/camera/provider/aidl/vts/VtsAidlHalCameraProvider_TargetTest.cpp
+++ b/camera/provider/aidl/vts/VtsAidlHalCameraProvider_TargetTest.cpp
@@ -341,6 +341,10 @@
             ret = device->getSessionCharacteristics(config, &session_chars);
             ASSERT_TRUE(ret.isOk());
             verifySessionCharacteristics(session_chars, camera_chars);
+
+            ret = mSession->close();
+            mSession = nullptr;
+            ASSERT_TRUE(ret.isOk());
         }
     } else {
         ALOGI("getSessionCharacteristics: Test skipped.\n");
diff --git a/gnss/aidl/vts/gnss_hal_test_cases.cpp b/gnss/aidl/vts/gnss_hal_test_cases.cpp
index 9381a0a..4309187 100644
--- a/gnss/aidl/vts/gnss_hal_test_cases.cpp
+++ b/gnss/aidl/vts/gnss_hal_test_cases.cpp
@@ -1714,7 +1714,8 @@
  * 2. verify the SvStatus are received at expected interval
  */
 TEST_P(GnssHalTest, TestSvStatusIntervals) {
-    if (aidl_gnss_hal_->getInterfaceVersion() <= 2) {
+    // Only runs on devices launched in Android 15+
+    if (aidl_gnss_hal_->getInterfaceVersion() <= 3) {
         return;
     }
     ALOGD("TestSvStatusIntervals");
diff --git a/security/keymint/aidl/default/Android.bp b/security/keymint/aidl/default/Android.bp
index 0cf53cf..fbb6140 100644
--- a/security/keymint/aidl/default/Android.bp
+++ b/security/keymint/aidl/default/Android.bp
@@ -7,6 +7,13 @@
     default_applicable_licenses: ["hardware_interfaces_license"],
 }
 
+// The following target has an insecure implementation of KeyMint where the
+// trusted application (TA) code runs in-process alongside the HAL service
+// code.
+//
+// A real device is required to run the TA code in a secure environment, as
+// per CDD 9.11 [C-1-1]: "MUST back up the keystore implementation with an
+// isolated execution environment."
 cc_binary {
     name: "android.hardware.security.keymint-service",
     relative_install_path: "hw",
@@ -46,6 +53,13 @@
     ],
 }
 
+// The following target has an insecure implementation of KeyMint where the
+// trusted application (TA) code runs in-process alongside the HAL service
+// code.
+//
+// A real device is required to run the TA code in a secure environment, as
+// per CDD 9.11 [C-1-1]: "MUST back up the keystore implementation with an
+// isolated execution environment."
 rust_binary {
     name: "android.hardware.security.keymint-service.nonsecure",
     relative_install_path: "hw",
diff --git a/security/keymint/aidl/default/main.rs b/security/keymint/aidl/default/main.rs
index 055c698..47143f4 100644
--- a/security/keymint/aidl/default/main.rs
+++ b/security/keymint/aidl/default/main.rs
@@ -17,11 +17,15 @@
 //! Default implementation of the KeyMint HAL and related HALs.
 //!
 //! This implementation of the HAL is only intended to allow testing and policy compliance.  A real
-//! implementation **must be implemented in a secure environment**.
+//! implementation **must implement the TA in a secure environment**, as per CDD 9.11 [C-1-1]:
+//! "MUST back up the keystore implementation with an isolated execution environment."
+//!
+//! The additional device-specific components that are required for a real implementation of KeyMint
+//! that is based on the Rust reference implementation are described in system/keymint/README.md.
 
 use kmr_hal::SerializedChannel;
 use kmr_hal_nonsecure::{attestation_id_info, get_boot_info};
-use log::{debug, error, info};
+use log::{debug, error, info, warn};
 use std::ops::DerefMut;
 use std::sync::{mpsc, Arc, Mutex};
 
@@ -62,7 +66,7 @@
         error!("{}", panic_info);
     }));
 
-    info!("Insecure KeyMint HAL service is starting.");
+    warn!("Insecure KeyMint HAL service is starting.");
 
     info!("Starting thread pool now.");
     binder::ProcessState::start_thread_pool();
diff --git a/security/keymint/aidl/vts/functional/KeyMintTest.cpp b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
index b65218f..65a4645 100644
--- a/security/keymint/aidl/vts/functional/KeyMintTest.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
@@ -22,6 +22,7 @@
 #include <algorithm>
 #include <iostream>
 #include <map>
+#include <set>
 
 #include <openssl/curve25519.h>
 #include <openssl/ec.h>
@@ -3588,6 +3589,42 @@
 }
 
 /*
+ * SigningOperationsTest.HmacMessageDigestUnique
+ *
+ * Verifies that HMAC with different keys gives different results.
+ */
+TEST_P(SigningOperationsTest, HmacMessageDigestUnique) {
+    for (int key_len : {64, 128, 192, 256, 512}) {
+        for (int msg_len = 0; msg_len <= 30; msg_len += 10) {
+            string message = string(msg_len, 'x');
+            for (auto digest : ValidDigests(false /* withNone */, false /* withMD5 */)) {
+                SCOPED_TRACE(testing::Message() << "Digest::" << digest << "::MsgLen::" << msg_len);
+
+                int count = 10;
+                std::set<string> results;
+                for (int ii = 0; ii < count; ii++) {
+                    ASSERT_EQ(ErrorCode::OK,
+                              GenerateKey(AuthorizationSetBuilder()
+                                                  .Authorization(TAG_NO_AUTH_REQUIRED)
+                                                  .HmacKey(key_len)
+                                                  .Digest(digest)
+                                                  .Authorization(TAG_MIN_MAC_LENGTH, 160)))
+                            << "Failed to create HMAC key with digest " << digest;
+                    string signature = MacMessage(message, digest, 160);
+                    EXPECT_EQ(160U / 8U, signature.size())
+                            << "Failed to sign with HMAC key with digest " << digest;
+                    CheckedDeleteKey();
+                    results.insert(signature);
+                }
+                EXPECT_EQ(results.size(), count)
+                        << "HMAC of a message '" << message << "' with " << count
+                        << " fresh keys only gave " << results.size() << " distinct results";
+            }
+        }
+    }
+}
+
+/*
  * SigningOperationsTest.HmacSha256TooLargeMacLength
  *
  * Verifies that HMAC fails in the correct way when asked to generate a MAC larger than the