Merge "Clear ringbuffer after dumping to file" into sc-dev
diff --git a/audio/common/all-versions/test/utility/Android.bp b/audio/common/all-versions/test/utility/Android.bp
index 1602d25..757f8a8 100644
--- a/audio/common/all-versions/test/utility/Android.bp
+++ b/audio/common/all-versions/test/utility/Android.bp
@@ -25,7 +25,7 @@
 
 cc_library_static {
     name: "android.hardware.audio.common.test.utility",
-    defaults : ["hidl_defaults"],
+    defaults: ["hidl_defaults"],
     srcs: ["src/ValidateXml.cpp"],
     cflags: [
         "-O0",
@@ -34,7 +34,34 @@
     ],
     local_include_dirs: ["include/utility"],
     export_include_dirs: ["include"],
-    shared_libs: ["libxml2", "liblog"],
+    shared_libs: [
+        "libxml2",
+        "liblog",
+    ],
     static_libs: ["libgtest"],
     export_static_lib_headers: ["libgtest"],
 }
+
+// Note: this isn't a VTS test, but rather a unit test
+// to verify correctness of test utilities.
+cc_test {
+    name: "android.hardware.audio.common.test.utility_tests",
+    host_supported: true,
+    local_include_dirs: ["include/utility"],
+    srcs: [
+        "src/ValidateXml.cpp",
+        "tests/utility_tests.cpp",
+    ],
+    cflags: [
+        "-Werror",
+        "-Wall",
+        "-g",
+    ],
+    shared_libs: [
+        "libbase",
+        "libxml2",
+        "liblog",
+    ],
+    static_libs: ["libgtest"],
+    test_suites: ["general-tests"],
+}
diff --git a/audio/common/all-versions/test/utility/TEST_MAPPING b/audio/common/all-versions/test/utility/TEST_MAPPING
new file mode 100644
index 0000000..0bc1871
--- /dev/null
+++ b/audio/common/all-versions/test/utility/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "presubmit": [
+    {
+      "name": "android.hardware.audio.common.test.utility_tests"
+    }
+  ]
+}
diff --git a/audio/common/all-versions/test/utility/src/ValidateXml.cpp b/audio/common/all-versions/test/utility/src/ValidateXml.cpp
index a866104..f111c01 100644
--- a/audio/common/all-versions/test/utility/src/ValidateXml.cpp
+++ b/audio/common/all-versions/test/utility/src/ValidateXml.cpp
@@ -112,7 +112,8 @@
         return ::testing::AssertionFailure() << "Failed to parse xml\n" << context();
     }
 
-    if (xmlXIncludeProcess(doc.get()) == -1) {
+    // Process 'include' directives w/o modifying elements loaded from included files.
+    if (xmlXIncludeProcessFlags(doc.get(), XML_PARSE_NOBASEFIX) == -1) {
         return ::testing::AssertionFailure() << "Failed to resolve xincludes in xml\n" << context();
     }
 
diff --git a/audio/common/all-versions/test/utility/tests/utility_tests.cpp b/audio/common/all-versions/test/utility/tests/utility_tests.cpp
new file mode 100644
index 0000000..c523066
--- /dev/null
+++ b/audio/common/all-versions/test/utility/tests/utility_tests.cpp
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+#include <android-base/file.h>
+#include <gtest/gtest.h>
+
+#include <ValidateXml.h>
+
+using ::android::hardware::audio::common::test::utility::validateXml;
+
+const char* XSD_SOURCE =
+        "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+        "<xs:schema version=\"2.0\""
+        "           elementFormDefault=\"qualified\""
+        "           attributeFormDefault=\"unqualified\""
+        "           xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">"
+        "  <xs:element name=\"audioPolicyConfiguration\">"
+        "    <xs:complexType>"
+        "      <xs:sequence>"
+        "        <xs:element name=\"modules\">"
+        "          <xs:complexType>"
+        "            <xs:sequence>"
+        "              <xs:element name=\"module\" maxOccurs=\"unbounded\">"
+        "                <xs:complexType>"
+        "                  <xs:attribute name=\"name\" type=\"xs:string\" use=\"required\"/>"
+        "                </xs:complexType>"
+        "              </xs:element>"
+        "            </xs:sequence>"
+        "          </xs:complexType>"
+        "        </xs:element>"
+        "      </xs:sequence>"
+        "    </xs:complexType>"
+        "  </xs:element>"
+        "</xs:schema>";
+
+const char* INVALID_XML_SOURCE =
+        "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"
+        "<audioPolicyKonfiguration />";
+
+const char* VALID_XML_SOURCE =
+        "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"
+        "<audioPolicyConfiguration>"
+        "  <modules>"
+        "    <module name=\"aaa\" />"
+        "    %s"
+        "  </modules>"
+        "</audioPolicyConfiguration>";
+
+const char* MODULE_SOURCE = "<module name=\"bbb\" />";
+
+const char* XI_INCLUDE = "<xi:include xmlns:xi=\"http://www.w3.org/2001/XInclude\" href=\"%s\" />";
+
+const char* XML_INCLUDED_SOURCE = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>%s";
+
+namespace {
+
+std::string substitute(const char* fmt, const char* param) {
+    std::string buffer(static_cast<size_t>(strlen(fmt) + strlen(param)), '\0');
+    snprintf(buffer.data(), buffer.size(), fmt, param);
+    return buffer;
+}
+
+std::string substitute(const char* fmt, const std::string& s) {
+    return substitute(fmt, s.c_str());
+}
+
+}  // namespace
+
+TEST(ValidateXml, InvalidXml) {
+    TemporaryFile xml;
+    ASSERT_TRUE(android::base::WriteStringToFile(INVALID_XML_SOURCE, xml.path)) << strerror(errno);
+    TemporaryFile xsd;
+    ASSERT_TRUE(android::base::WriteStringToFile(XSD_SOURCE, xsd.path)) << strerror(errno);
+    EXPECT_FALSE(validateXml("xml", "xsd", xml.path, xsd.path));
+}
+
+TEST(ValidateXml, ValidXml) {
+    TemporaryFile xml;
+    ASSERT_TRUE(
+            android::base::WriteStringToFile(substitute(VALID_XML_SOURCE, MODULE_SOURCE), xml.path))
+            << strerror(errno);
+    TemporaryFile xsd;
+    ASSERT_TRUE(android::base::WriteStringToFile(XSD_SOURCE, xsd.path)) << strerror(errno);
+    EXPECT_TRUE(validateXml("xml", "xsd", xml.path, xsd.path));
+}
+
+TEST(ValidateXml, IncludeAbsolutePath) {
+    TemporaryFile xmlInclude;
+    ASSERT_TRUE(android::base::WriteStringToFile(substitute(XML_INCLUDED_SOURCE, MODULE_SOURCE),
+                                                 xmlInclude.path))
+            << strerror(errno);
+    TemporaryFile xml;
+    ASSERT_TRUE(android::base::WriteStringToFile(
+            substitute(VALID_XML_SOURCE, substitute(XI_INCLUDE, xmlInclude.path)), xml.path))
+            << strerror(errno);
+    TemporaryFile xsd;
+    ASSERT_TRUE(android::base::WriteStringToFile(XSD_SOURCE, xsd.path)) << strerror(errno);
+    EXPECT_TRUE(validateXml("xml", "xsd", xml.path, xsd.path));
+}
+
+TEST(ValidateXml, IncludeSameDirRelativePath) {
+    TemporaryFile xmlInclude;
+    ASSERT_TRUE(android::base::WriteStringToFile(substitute(XML_INCLUDED_SOURCE, MODULE_SOURCE),
+                                                 xmlInclude.path))
+            << strerror(errno);
+    TemporaryFile xml;
+    ASSERT_EQ(android::base::Dirname(xml.path), android::base::Dirname(xmlInclude.path));
+    ASSERT_TRUE(android::base::WriteStringToFile(
+            substitute(VALID_XML_SOURCE,
+                       substitute(XI_INCLUDE, android::base::Basename(xmlInclude.path))),
+            xml.path))
+            << strerror(errno);
+    TemporaryFile xsd;
+    ASSERT_TRUE(android::base::WriteStringToFile(XSD_SOURCE, xsd.path)) << strerror(errno);
+    EXPECT_TRUE(validateXml("xml", "xsd", xml.path, xsd.path));
+}
+
+TEST(ValidateXml, IncludeSubdirRelativePath) {
+    TemporaryDir xmlIncludeDir;
+    TemporaryFile xmlInclude(xmlIncludeDir.path);
+    ASSERT_TRUE(android::base::WriteStringToFile(substitute(XML_INCLUDED_SOURCE, MODULE_SOURCE),
+                                                 xmlInclude.path))
+            << strerror(errno);
+    TemporaryFile xml;
+    ASSERT_EQ(android::base::Dirname(xml.path), android::base::Dirname(xmlIncludeDir.path));
+    ASSERT_TRUE(android::base::WriteStringToFile(
+            substitute(VALID_XML_SOURCE,
+                       substitute(XI_INCLUDE, android::base::Basename(xmlIncludeDir.path) + "/" +
+                                                      android::base::Basename(xmlInclude.path))),
+            xml.path))
+            << strerror(errno);
+    TemporaryFile xsd;
+    ASSERT_TRUE(android::base::WriteStringToFile(XSD_SOURCE, xsd.path)) << strerror(errno);
+    EXPECT_TRUE(validateXml("xml", "xsd", xml.path, xsd.path));
+}
+
+TEST(ValidateXml, IncludeParentDirRelativePath) {
+    // An XML file from a subdirectory includes a file from the parent directory using '..' syntax.
+    TemporaryFile xmlInclude;
+    ASSERT_TRUE(android::base::WriteStringToFile(substitute(XML_INCLUDED_SOURCE, MODULE_SOURCE),
+                                                 xmlInclude.path))
+            << strerror(errno);
+    TemporaryDir xmlIncludeDir;
+    TemporaryFile xmlParentInclude(xmlIncludeDir.path);
+    ASSERT_TRUE(android::base::WriteStringToFile(
+            substitute(XML_INCLUDED_SOURCE,
+                       substitute(XI_INCLUDE, "../" + android::base::Basename(xmlInclude.path))),
+            xmlParentInclude.path))
+            << strerror(errno);
+    TemporaryFile xml;
+    ASSERT_EQ(android::base::Dirname(xml.path), android::base::Dirname(xmlInclude.path));
+    ASSERT_EQ(android::base::Dirname(xml.path), android::base::Dirname(xmlIncludeDir.path));
+    ASSERT_TRUE(android::base::WriteStringToFile(
+            substitute(
+                    VALID_XML_SOURCE,
+                    substitute(XI_INCLUDE, android::base::Basename(xmlIncludeDir.path) + "/" +
+                                                   android::base::Basename(xmlParentInclude.path))),
+            xml.path))
+            << strerror(errno);
+    TemporaryFile xsd;
+    ASSERT_TRUE(android::base::WriteStringToFile(XSD_SOURCE, xsd.path)) << strerror(errno);
+    EXPECT_TRUE(validateXml("xml", "xsd", xml.path, xsd.path));
+}
diff --git a/automotive/vehicle/2.0/vts/functional/VtsHalAutomotiveVehicleV2_0TargetTest.cpp b/automotive/vehicle/2.0/vts/functional/VtsHalAutomotiveVehicleV2_0TargetTest.cpp
index 4ac0aa5..8adec84 100644
--- a/automotive/vehicle/2.0/vts/functional/VtsHalAutomotiveVehicleV2_0TargetTest.cpp
+++ b/automotive/vehicle/2.0/vts/functional/VtsHalAutomotiveVehicleV2_0TargetTest.cpp
@@ -18,6 +18,7 @@
 
 #include <android/hardware/automotive/vehicle/2.0/IVehicle.h>
 #include <utils/Log.h>
+#include <unordered_set>
 
 #include <gtest/gtest.h>
 #include <hidl/GtestPrinter.h>
@@ -184,20 +185,34 @@
 TEST_P(VehicleHalHidlTest, setProp) {
     ALOGD("VehicleHalHidlTest::setProp");
     hidl_vec<VehiclePropConfig> propConfigs;
+    // skip hvac related properties
+    std::unordered_set<int32_t> hvacProps = {(int)VehicleProperty::HVAC_DEFROSTER,
+                                             (int)VehicleProperty::HVAC_AC_ON,
+                                             (int)VehicleProperty::HVAC_MAX_AC_ON,
+                                             (int)VehicleProperty::HVAC_MAX_DEFROST_ON,
+                                             (int)VehicleProperty::HVAC_RECIRC_ON,
+                                             (int)VehicleProperty::HVAC_DUAL_ON,
+                                             (int)VehicleProperty::HVAC_AUTO_ON,
+                                             (int)VehicleProperty::HVAC_POWER_ON,
+                                             (int)VehicleProperty::HVAC_AUTO_RECIRC_ON,
+                                             (int)VehicleProperty::HVAC_ELECTRIC_DEFROSTER_ON};
     mVehicle->getAllPropConfigs(
             [&propConfigs](const hidl_vec<VehiclePropConfig>& cfgs) { propConfigs = cfgs; });
     for (const VehiclePropConfig& cfg : propConfigs) {
         // test on boolean and writable property
-        if (cfg.access == VehiclePropertyAccess::READ_WRITE && isBooleanGlobalProp(cfg.prop)) {
+        if (cfg.access == VehiclePropertyAccess::READ_WRITE && isBooleanGlobalProp(cfg.prop) &&
+            !hvacProps.count(cfg.prop)) {
             invokeGet(cfg.prop, 0);
             int setValue = mActualValue.value.int32Values[0] == 1 ? 0 : 1;
             VehiclePropValue propToSet = mActualValue;
             propToSet.value.int32Values[0] = setValue;
-            ASSERT_EQ(StatusCode::OK, mVehicle->set(propToSet));
+            ASSERT_EQ(StatusCode::OK, mVehicle->set(propToSet))
+                    << "Invalid status code for setting property: " << cfg.prop;
             // check set success
             invokeGet(cfg.prop, 0);
             ASSERT_EQ(StatusCode::OK, mActualStatusCode);
-            ASSERT_EQ(setValue, mActualValue.value.int32Values[0]);
+            ASSERT_EQ(setValue, mActualValue.value.int32Values[0])
+                    << "Failed to set value for property: " << cfg.prop;
         }
     }
 }
diff --git a/biometrics/face/aidl/android/hardware/biometrics/face/EnrollmentType.aidl b/biometrics/face/aidl/android/hardware/biometrics/face/EnrollmentType.aidl
index d7f3175..c960933 100644
--- a/biometrics/face/aidl/android/hardware/biometrics/face/EnrollmentType.aidl
+++ b/biometrics/face/aidl/android/hardware/biometrics/face/EnrollmentType.aidl
@@ -19,6 +19,15 @@
 @VintfStability
 @Backing(type="byte")
 enum EnrollmentType {
+    /**
+     * Default enrollment type.
+     */
     DEFAULT,
+
+    /**
+     * Enrollment type for people with limited vision or mobility. For example,
+     * enrollment of this type will not ask the user to move their head or
+     * look directly at the device.
+     */
     ACCESSIBILITY,
 }
diff --git a/biometrics/face/aidl/android/hardware/biometrics/face/FaceSensorType.aidl b/biometrics/face/aidl/android/hardware/biometrics/face/FaceSensorType.aidl
index 57f39d4..a5ed2e8 100644
--- a/biometrics/face/aidl/android/hardware/biometrics/face/FaceSensorType.aidl
+++ b/biometrics/face/aidl/android/hardware/biometrics/face/FaceSensorType.aidl
@@ -16,4 +16,23 @@
 
 package android.hardware.biometrics.face;
 
-@VintfStability @Backing(type="byte") enum FaceSensorType { UNKNOWN, RGB, IR }
+@VintfStability
+@Backing(type="byte")
+enum FaceSensorType {
+    /**
+     * Placeholder value used for default initialization of FaceSensorType.
+     * This value means FaceSensorType wasn't explicitly initialized and must
+     * be discarded by the recipient.
+     */
+    UNKNOWN,
+
+    /**
+     * The face sensor is an RGB camera.
+     */
+    RGB,
+
+    /**
+     * The face sensor is an infrared camera.
+     */
+    IR,
+}
diff --git a/biometrics/face/aidl/android/hardware/biometrics/face/IFace.aidl b/biometrics/face/aidl/android/hardware/biometrics/face/IFace.aidl
index 11cdf77..4d7e59e 100644
--- a/biometrics/face/aidl/android/hardware/biometrics/face/IFace.aidl
+++ b/biometrics/face/aidl/android/hardware/biometrics/face/IFace.aidl
@@ -25,28 +25,30 @@
     /**
      * getSensorProps:
      *
-     * @return A list of properties for all face sensors available to the HAL.
+     * @return A list of properties for all of the face sensors supported by the HAL.
      */
     SensorProps[] getSensorProps();
 
     /**
      * createSession:
      *
-     * Creates a session that can be used by the framework to perform operations such as
-     * enroll, authenticate, etc. for the given sensorId and userId.
+     * Creates an instance of ISession that can be used by the framework to perform operations such
+     * as ISession#enroll, ISession#authenticate, etc. for the given sensorId and userId.
      *
-     * Calling this method while there is an active session is considered an error. If the
-     * framework is in a bad state and for some reason cannot close its session, it should use
-     * the reset method below.
+     * Calling this method while there is an active session is considered an error. If the framework
+     * wants to create a new session when it already has an active session, it must first cancel the
+     * current operation if it's cancellable or wait until it completes. Then, the framework must
+     * explicitly close the session with ISession#close. Once the framework receives
+     * ISessionCallback#onSessionClosed, a new session can be created.
      *
      * Implementations must store user-specific state or metadata in /data/vendor_de/<user>/facedata
      * as specified by the SELinux policy. The directory /data/vendor_de is managed by vold (see
      * vold_prepare_subdirs.cpp). Implementations may store additional user-specific data, such as
-     * embeddings or templates in StrongBox.
+     * embeddings or templates, in StrongBox.
      *
-     * @param sensorId The sensorId with which this session is being created.
-     * @param userId The userId with which this session is being created.
-     * @param cb A callback to notify the framework about the session's results and events.
+     * @param sensorId The sensorId for which this session is being created.
+     * @param userId The userId for which this session is being created.
+     * @param cb A callback to notify the framework about the session's events.
      * @return A new session.
      */
     ISession createSession(in int sensorId, in int userId, in ISessionCallback cb);
diff --git a/biometrics/face/aidl/android/hardware/biometrics/face/ISession.aidl b/biometrics/face/aidl/android/hardware/biometrics/face/ISession.aidl
index a9a8c16..2a57e3a 100644
--- a/biometrics/face/aidl/android/hardware/biometrics/face/ISession.aidl
+++ b/biometrics/face/aidl/android/hardware/biometrics/face/ISession.aidl
@@ -24,13 +24,12 @@
 import android.hardware.keymaster.HardwareAuthToken;
 
 /**
- * Operations that can be performed for unique sessions retrieved via IFace#createSession.
  * Operations defined within this interface can be divided into the following categories:
  * 1) Cancellable operations. These are usually the operations that can execute for several
- *     minutes. To allow for cancellation, they return an instance of ICancellationSignal that
- *     lets the framework cancel them by calling ICancellationSignal#cancel. If such an operation
- *     is cancelled, it must notify the framework by calling ISessionCallback#onError with
- *     Error::CANCELED.
+ *    minutes. To allow for cancellation, they return an instance of ICancellationSignal that
+ *    lets the framework cancel them by calling ICancellationSignal#cancel. If such an operation
+ *    is cancelled, it must notify the framework by calling ISessionCallback#onError with
+ *    Error::CANCELED.
  * 2) Non-cancellable operations. Such operations cannot be cancelled once started.
  *
  * The lifecycle of an operation ends when one of its terminal callbacks is called. For example,
@@ -83,15 +82,20 @@
      * | 0        | 10     | <Time4>    | <Random4> |
      * ----------------------------------------------
      *
+     * Callbacks that signify the end of this operation's lifecycle:
+     *   - ISessionCallback#onChallengeGenerated
+     *
      */
     void generateChallenge();
 
     /**
      * revokeChallenge:
      *
-     * Revokes a challenge that was previously generated. Note that if an invalid combination of
-     * parameters is requested, the implementation must still notify the framework using the
-     * provided callback.
+     * Revokes a challenge that was previously generated. Note that if a non-existent challenge is
+     * provided, the HAL must still notify the framework using ISessionCallback#onChallengeRevoked.
+     *
+     * Callbacks that signify the end of this operation's lifecycle:
+     *   - ISessionCallback#onChallengeRevoked
      *
      * @param challenge Challenge that should be revoked.
      */
@@ -100,9 +104,9 @@
     /**
      * getEnrollmentConfig:
      *
-     * Returns the enrollment configuration depending on the provided enrollment type. Enrollment
-     * configuration determines how many stages the enrollment will have and the requirements for
-     * each of the stages.
+     * Returns the enrollment configuration for the provided enrollment type. Enrollment
+     * configuration determines how many stages the enrollment will have and the requirements
+     * for each of the stages.
      *
      * @param enrollmentType See the EnrollmentType enum.
      * @return An EnrollmentStageConfig array that describes each enrollment stage.
@@ -117,22 +121,28 @@
      * At any point during enrollment, if a non-recoverable error occurs, the HAL must notify the
      * framework via ISessionCallback#onError with the applicable enrollment-specific error.
      *
-     * Before capturing face data, the implementation must first verify the authenticity and
-     * integrity of the provided HardwareAuthToken. In addition, it must check that the challenge
-     * within the provided HardwareAuthToken is valid. See ISession#generateChallenge. If any of
-     * the above checks fail, the framework must be notified using ISessionCallback#onError with
-     * Error::UNABLE_TO_PROCESS.
+     * Before capturing face data, the HAL must first verify the authenticity and integrity of the
+     * provided HardwareAuthToken. In addition, it must check that the challenge within the provided
+     * HardwareAuthToken is valid. See ISession#generateChallenge. If any of the above checks fail,
+     * the framework must be notified using ISessionCallback#onError with Error::UNABLE_TO_PROCESS.
      *
-     * During enrollment, the implementation may notify the framework via
-     * ISessionCallback#onAcquired with messages that may be used to guide the user. This callback
-     * can be invoked multiple times if necessary. Similarly, the framework may be notified of
-     * enrollment progress changes via ISessionCallback#onEnrollmentProgress. Once the framework is
-     * notified that there are 0 "remaining" steps, the framework may cache the "enrollmentId". See
+     * During enrollment, the HAL may notify the framework via ISessionCallback#onAcquired with
+     * messages that may be used to guide the user. This callback can be invoked multiple times if
+     * necessary. Similarly, the framework may be notified of enrollment progress changes via
+     * ISessionCallback#onEnrollmentProgress. Once the framework is notified that there are 0
+     * "remaining" steps, the framework may cache the "enrollmentId". See
      * ISessionCallback#onEnrollmentProgress for more info.
      *
      * When a face is successfully added and before the framework is notified of remaining=0, the
-     * implementation MUST update and associate this (sensorId, userId) pair with a new
-     * entropy-encoded random identifier. See ISession#getAuthenticatorId for more information.
+     * HAL must update and associate this (sensorId, userId) pair with a new entropy-encoded random
+     * identifier. See ISession#getAuthenticatorId for more information.
+     *
+     * Callbacks that signify the end of this operation's lifecycle:
+     *   - ISessionCallback#onError
+     *   - ISessionCallback#onEnrollmentProgress(enrollmentId, remaining=0)
+     *
+     * Other applicable callbacks:
+     *   - ISessionCallback#onAcquired
      *
      * @param hat See above documentation.
      * @param enrollmentType See the EnrollmentType enum.
@@ -154,15 +164,18 @@
      * At any point during authentication, if a non-recoverable error occurs, the HAL must notify
      * the framework via ISessionCallback#onError with the applicable authentication-specific error.
      *
-     * During authentication, the implementation may notify the framework via
-     * ISessionCallback#onAcquired with messages that may be used to guide the user. This callback
-     * can be invoked multiple times if necessary.
+     * During authentication, the HAL may notify the framework via ISessionCallback#onAcquired with
+     * messages that may be used to guide the user. This callback can be invoked multiple times if
+     * necessary.
      *
-     * The HAL must notify the framework of accepts/rejects via ISessionCallback#onAuthentication*.
+     * The HAL must notify the framework of accepts/rejects via
+     * ISessionCallback#onAuthenticationSucceeded and ISessionCallback#onAuthenticationFailed,
+     * correspondingly.
      *
-     * The authentication lifecycle ends when either
-     *   1) A face is accepted, and ISessionCallback#onAuthenticationSucceeded is invoked, or
-     *   2) Any non-recoverable error occurs (such as lockout). See the full list of
+     * The authentication lifecycle ends when any of the following happens:
+     *   1) A face is accepted, and ISessionCallback#onAuthenticationSucceeded is invoked.
+     *   2) A face is rejected, and ISessionCallback#onAuthenticationFailed is invoked.
+     *   3) Any non-recoverable error occurs (such as lockout). See the full list of
      *      authentication-specific errors in the Error enum.
      *
      * Note that upon successful authentication, the lockout counter for this (sensorId, userId)
@@ -174,16 +187,26 @@
      * must be set with the operationId passed in during #authenticate. If the sensor is NOT
      * SensorStrength::STRONG, the HardwareAuthToken MUST be null.
      *
+     * Callbacks that signify the end of this operation's lifecycle:
+     *   - ISessionCallback#onError
+     *   - ISessionCallback#onAuthenticationSucceeded
+     *   - ISessionCallback#onAuthenticationFailed
+     *
+     * Other applicable callbacks:
+     *   - ISessionCallback#onAcquired
+     *   - ISessionCallback#onLockoutTimed
+     *   - ISessionCallback#onLockoutPermanent
+     *
      * @param operationId For sensors configured as SensorStrength::STRONG, this must be used ONLY
      *                    upon successful authentication and wrapped in the HardwareAuthToken's
      *                    "challenge" field and sent to the framework via
-     *                    ISessionCallback#onAuthenticated. The operationId is an opaque identifier
-     *                    created from a separate secure subsystem such as, but not limited to
-     *                    KeyStore/KeyMaster. The HardwareAuthToken can then be used as an
-     *                    attestation for the provided operation. For example, this is used
-     *                    to unlock biometric-bound auth-per-use keys (see
+     *                    ISessionCallback#onAuthenticationSucceeded. The operationId is an opaque
+     *                    identifier created from a separate secure subsystem such as, but not
+     *                    limited to KeyStore/KeyMaster. The HardwareAuthToken can then be used as
+     *                    an attestation for the provided operation. For example, this is used to
+     *                    unlock biometric-bound auth-per-use keys (see
      *                    setUserAuthenticationParameters in KeyGenParameterSpec.Builder and
-     *                    KeyProtection.Builder.
+     *                    KeyProtection.Builder).
      * @return ICancellationSignal An object that can be used by the framework to cancel this
      * operation.
      */
@@ -193,32 +216,36 @@
      * detectInteraction:
      *
      * A request to start looking for faces without performing matching. Must only be called if
-     * SensorProps#supportsDetectInteraction is true. If invoked on implementations that do not
-     * support this functionality, the HAL must respond with ISession#onError(UNABLE_TO_PROCESS, 0).
+     * SensorProps#supportsDetectInteraction is true. If invoked on HALs that do not support this
+     * functionality, the HAL must respond with ISession#onError(UNABLE_TO_PROCESS, 0).
      *
-     * The framework will use this method in cases where determing user presence is required, but
-     * identifying/authentication is not. For example, when the device is encrypted (first boot) or
-     * in lockdown mode.
+     * The framework will use this operation in cases where determining user presence is required,
+     * but identifying/authenticating is not. For example, when the device is encrypted (first boot)
+     * or in lockdown mode.
      *
      * At any point during detectInteraction, if a non-recoverable error occurs, the HAL must notify
      * the framework via ISessionCallback#onError with the applicable error.
      *
-     * The implementation must only check for a face-like image was detected (e.g. to
-     * minimize interactions due to non-face objects), and the lockout counter must not
-     * be modified.
+     * The HAL must only check whether a face-like image was detected (e.g. to minimize interactions
+     * due to non-face objects), and the lockout counter must not be modified.
      *
-     * Upon detecting any face, the implementation must invoke
-     * ISessionCallback#onInteractionDetected.
+     * Upon detecting any face, the HAL must invoke ISessionCallback#onInteractionDetected.
      *
-     * The lifecycle of this operation ends when either
+     * The lifecycle of this operation ends when either:
      * 1) Any face is detected and the framework is notified via
-     *    ISessionCallback#onInteractiondetected
-     * 2) The operation was cancelled by the framework (see ICancellationSignal)
-     * 3) An error occurred, for example ERROR::TIMEOUT
+     *    ISessionCallback#onInteractionDetected.
+     * 2) An error occurrs, for example Error::TIMEOUT.
      *
-     * Note that if the operation is canceled, the implementation must notify the framework via
+     * Note that if the operation is canceled, the HAL must notify the framework via
      * ISessionCallback#onError with Error::CANCELED.
      *
+     * Callbacks that signify the end of this operation's lifecycle:
+     *   - ISessionCallback#onError
+     *   - ISessionCallback#onInteractionDetected
+     *
+     * Other applicable callbacks:
+     *   - ISessionCallback#onAcquired
+     *
      * @return ICancellationSignal An object that can be used by the framework to cancel this
      * operation.
      */
@@ -227,12 +254,14 @@
     /*
      * enumerateEnrollments:
      *
-     * A request to enumerate (list) the enrollments for this (sensorId, userId) pair. The
-     * framework typically uses this to ensure that its cache is in sync with the HAL.
+     * A request to enumerate (list) the enrollments for this (sensorId, userId) pair. The framework
+     * typically uses this to ensure that its cache is in sync with the HAL.
      *
-     * The implementation must then notify the framework with a list of enrollments applicable
-     * for the current session via ISessionCallback#onEnrollmentsEnumerated.
+     * The HAL must then notify the framework with a list of enrollments applicable for the current
+     * session via ISessionCallback#onEnrollmentsEnumerated.
      *
+     * Callbacks that signify the end of this operation's lifecycle:
+     *   - ISessionCallback#onEnrollmentsEnumerated
      */
     void enumerateEnrollments();
 
@@ -242,8 +271,12 @@
      * A request to remove the enrollments for this (sensorId, userId) pair.
      *
      * After removing the enrollmentIds from everywhere necessary (filesystem, secure subsystems,
-     * etc), the implementation must notify the framework via ISessionCallback#onEnrollmentsRemoved.
+     * etc), the HAL must notify the framework via ISessionCallback#onEnrollmentsRemoved.
      *
+     * Callbacks that signify the end of this operation's lifecycle:
+     *   - ISessionCallback#onEnrollmentsRemoved
+     *
+     * @param enrollmentIds a list of enrollments that should be removed.
      */
     void removeEnrollments(in int[] enrollmentIds);
 
@@ -257,6 +290,10 @@
      *
      * The HAL must notify the framework about the result by calling
      * ISessionCallback#onFeaturesRetrieved.
+     *
+     * Callbacks that signify the end of this operation's lifecycle:
+     *   - ISessionCallback#onError
+     *   - ISessionCallback#onFeaturesRetrieved
      */
     void getFeatures();
 
@@ -264,15 +301,19 @@
      * setFeature:
      *
      * Enables or disables a feature for this (sensorId, userId) pair. Because certain features may
-     * decrease security, the user must enter their password before this method is invoked
-     * (see @param hat). The HAL must verify the hat before changing any feature state.
+     * decrease security, the user must enter their password before this operation is invoked
+     * (see @param hat). The HAL must verify the HAT before changing any feature state.
      *
-     * If the hat is invalid or if the user is not enrolled, the HAL must invoke
+     * If the HAT is invalid or if the user is not enrolled, the HAL must invoke
      * ISessionCallback#onError with Error::UNABLE_TO_PROCESS.
      *
      * After the feature is successfully set, the HAL must notify the framework by calling
      * ISessionCallback#onFeatureSet.
      *
+     * Callbacks that signify the end of this operation's lifecycle:
+     *   - ISessionCallback#onError
+     *   - ISessionCallback#onFeatureSet
+     *
      * @param hat HardwareAuthToken See above documentation.
      * @param feature The feature to be enabled or disabled.
      * @param enabled Whether the provided features should be enabled or disabled.
@@ -295,8 +336,8 @@
      * KeyProtection.Builder.setInvalidatedByBiometricEnrollment.
      *
      * In addition, upon successful face authentication, the signed HAT that is returned to
-     * the framework via ISessionCallback#onAuthenticated must contain this identifier in the
-     * authenticatorId field.
+     * the framework via ISessionCallback#onAuthenticationSucceeded must contain this identifier in
+     * the authenticatorId field.
      *
      * Returns an entropy-encoded random identifier associated with the current set of enrollments
      * via ISessionCallback#onAuthenticatorIdRetrieved. The authenticatorId
@@ -305,20 +346,21 @@
      *   3) MUST not change if a face is deleted.
      *   4) MUST be an entropy-encoded random number
      *
+     * Callbacks that signify the end of this operation's lifecycle:
+     *   - ISessionCallback#onAuthenticatorIdRetrieved
      */
     void getAuthenticatorId();
 
     /**
      * invalidateAuthenticatorId:
      *
-     * This method only applies to sensors that are configured as SensorStrength::STRONG. If invoked
-     * by the framework for sensor of other strengths, the HAL should immediately invoke
+     * This operation only applies to sensors that are configured as SensorStrength::STRONG. If
+     * invoked by the framework for sensors of other strengths, the HAL should immediately invoke
      * ISessionCallback#onAuthenticatorIdInvalidated.
      *
      * The following only applies to sensors that are configured as SensorStrength::STRONG.
      *
-     * When invoked by the framework, the implementation must perform the following sequence of
-     * events:
+     * When invoked by the framework, the HAL must perform the following sequence of events:
      *   1) Update the authenticatorId with a new entropy-encoded random number
      *   2) Persist the new authenticatorId to non-ephemeral storage
      *   3) Notify the framework that the above is completed, via
@@ -326,18 +368,20 @@
      *
      * A practical use case of invalidation would be when the user adds a new enrollment to a sensor
      * managed by a different HAL instance. The public android.security.keystore APIs bind keys to
-     * "all biometrics" rather than "face-only" or "face-only" (see #getAuthenticatorId
-     * for more details). As such, the framework would coordinate invalidation across multiple
-     * biometric HALs as necessary.
+     * "all biometrics" rather than "fingerprint-only" or "face-only" (see #getAuthenticatorId for
+     * more details). As such, the framework would coordinate invalidation across multiple biometric
+     * HALs as necessary.
      *
+     * Callbacks that signify the end of this operation's lifecycle:
+     *   - ISessionCallback#onAuthenticatorIdInvalidated
      */
     void invalidateAuthenticatorId();
 
     /**
      * resetLockout:
      *
-     * Requests the implementation to clear the lockout counter. Upon receiving this request, the
-     * implementation must perform the following:
+     * Requests the HAL to clear the lockout counter. Upon receiving this request, the HAL must
+     * perform the following:
      *   1) Verify the authenticity and integrity of the provided HAT
      *   2) Verify that the timestamp provided within the HAT is relatively recent (e.g. on the
      *      order of minutes, not hours).
@@ -373,6 +417,9 @@
      * See the Android CDD section 7.3.10 for the full set of lockout and rate-limiting
      * requirements.
      *
+     * Callbacks that signify the end of this operation's lifecycle:
+     *   - ISessionCallback#onLockoutCleared
+     *
      * @param hat HardwareAuthToken See above documentation.
      */
     void resetLockout(in HardwareAuthToken hat);
@@ -384,9 +431,14 @@
      * If the HAL is busy performing a cancellable operation, the operation must be explicitly
      * cancelled with a call to ICancellationSignal#cancel before the session can be closed.
      *
+     * After a session is closed, the HAL must notify the framework by calling
+     * ISessionCallback#onSessionClosed.
+     *
      * All sessions must be explicitly closed. Calling IFace#createSession while there is an active
      * session is considered an error.
      *
+     * Callbacks that signify the end of this operation's lifecycle:
+     *   - ISessionCallback#onSessionClosed
      */
     void close();
 }
diff --git a/biometrics/face/aidl/android/hardware/biometrics/face/ISessionCallback.aidl b/biometrics/face/aidl/android/hardware/biometrics/face/ISessionCallback.aidl
index 23570bd..b3c348d 100644
--- a/biometrics/face/aidl/android/hardware/biometrics/face/ISessionCallback.aidl
+++ b/biometrics/face/aidl/android/hardware/biometrics/face/ISessionCallback.aidl
@@ -37,11 +37,11 @@
 
     /**
      * This method must only be used to notify the framework during the following operations:
-     *   1) ISession#authenticate
-     *   2) ISession#detectInteraction
+     *   - ISession#authenticate
+     *   - ISession#detectInteraction
      *
-     * These messages may be used to provide user guidance multiple times if necessary per
-     * operation.
+     * These messages may be used to provide user guidance multiple times per operation if
+     * necessary.
      *
      * @param frame See the AuthenticationFrame enum.
      */
@@ -51,8 +51,8 @@
      * This method must only be used to notify the framework during the ISession#enroll
      * operation.
      *
-     * These messages may be used to provide user guidance multiple times if necessary per
-     * operation.
+     * These messages may be used to provide user guidance multiple times per operation if
+     * necessary.
      *
      * @param frame See the EnrollmentFrame enum.
      */
@@ -60,18 +60,18 @@
 
     /**
      * This method must only be used to notify the framework during the following operations:
-     *   1) ISession#enroll
-     *   2) ISession#authenticate
-     *   3) ISession#detectInteraction
-     *   4) ISession#invalidateAuthenticatorId
-     *   5) ISession#resetLockout
+     *   - ISession#enroll
+     *   - ISession#authenticate
+     *   - ISession#detectInteraction
+     *   - ISession#invalidateAuthenticatorId
+     *   - ISession#resetLockout
      *
      * These messages may be used to notify the framework or user that a non-recoverable error
      * has occurred. The operation is finished, and the HAL must proceed with the next operation
      * or return to the idling state.
      *
-     * Note that cancellation (see common::ICancellationSignal) and preemption must be followed with
-     * an Error::CANCELED message.
+     * Note that cancellation (see common::ICancellationSignal) must be followed with an
+     * Error::CANCELED message.
      *
      * @param error See the Error enum.
      * @param vendorCode Only valid if error == Error::VENDOR. The vendorCode must be used to index
diff --git a/biometrics/face/aidl/default/Session.cpp b/biometrics/face/aidl/default/Session.cpp
index d980c5f..0cb7c95 100644
--- a/biometrics/face/aidl/default/Session.cpp
+++ b/biometrics/face/aidl/default/Session.cpp
@@ -34,12 +34,15 @@
     }
 };
 
-Session::Session(std::shared_ptr<ISessionCallback> cb) : cb_(std::move(cb)) {}
+Session::Session(std::shared_ptr<ISessionCallback> cb)
+    : cb_(std::move(cb)), mRandom(std::mt19937::default_seed) {}
 
 ndk::ScopedAStatus Session::generateChallenge() {
     LOG(INFO) << "generateChallenge";
     if (cb_) {
-        cb_->onChallengeGenerated(0);
+        std::uniform_int_distribution<int64_t> dist;
+        auto challenge = dist(mRandom);
+        cb_->onChallengeGenerated(challenge);
     }
     return ndk::ScopedAStatus::ok();
 }
@@ -63,6 +66,9 @@
         const std::vector<Feature>& /*features*/, const NativeHandle& /*previewSurface*/,
         std::shared_ptr<biometrics::common::ICancellationSignal>* /*return_val*/) {
     LOG(INFO) << "enroll";
+    if (cb_) {
+        cb_->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorError */);
+    }
     return ndk::ScopedAStatus::ok();
 }
 
@@ -100,6 +106,9 @@
 
 ndk::ScopedAStatus Session::getFeatures() {
     LOG(INFO) << "getFeatures";
+    if (cb_) {
+        cb_->onFeaturesRetrieved({});
+    }
     return ndk::ScopedAStatus::ok();
 }
 
@@ -119,6 +128,9 @@
 
 ndk::ScopedAStatus Session::invalidateAuthenticatorId() {
     LOG(INFO) << "invalidateAuthenticatorId";
+    if (cb_) {
+        cb_->onAuthenticatorIdInvalidated(0);
+    }
     return ndk::ScopedAStatus::ok();
 }
 
diff --git a/biometrics/face/aidl/default/Session.h b/biometrics/face/aidl/default/Session.h
index caf81f8..4d213e3 100644
--- a/biometrics/face/aidl/default/Session.h
+++ b/biometrics/face/aidl/default/Session.h
@@ -16,6 +16,8 @@
 
 #pragma once
 
+#include <random>
+
 #include <aidl/android/hardware/biometrics/face/BnSession.h>
 #include <aidl/android/hardware/biometrics/face/ISessionCallback.h>
 
@@ -68,6 +70,7 @@
 
   private:
     std::shared_ptr<ISessionCallback> cb_;
+    std::mt19937 mRandom;
 };
 
 }  // namespace aidl::android::hardware::biometrics::face
diff --git a/biometrics/face/aidl/vts/VtsHalBiometricsFaceTargetTest.cpp b/biometrics/face/aidl/vts/VtsHalBiometricsFaceTargetTest.cpp
index 47a7813..4dc44f1 100644
--- a/biometrics/face/aidl/vts/VtsHalBiometricsFaceTargetTest.cpp
+++ b/biometrics/face/aidl/vts/VtsHalBiometricsFaceTargetTest.cpp
@@ -29,16 +29,26 @@
 
 using namespace std::literals::chrono_literals;
 
+using aidl::android::hardware::common::NativeHandle;
+
 constexpr int kSensorId = 0;
 constexpr int kUserId = 0;
 
 class SessionCallback : public BnSessionCallback {
   public:
-    ndk::ScopedAStatus onChallengeGenerated(int64_t /*challenge*/) override {
+    ndk::ScopedAStatus onChallengeGenerated(int64_t challenge) override {
+        auto lock = std::lock_guard{mMutex};
+        mOnChallengeGeneratedInvoked = true;
+        mGeneratedChallenge = challenge;
+        mCv.notify_one();
         return ndk::ScopedAStatus::ok();
     }
 
-    ndk::ScopedAStatus onChallengeRevoked(int64_t /*challenge*/) override {
+    ndk::ScopedAStatus onChallengeRevoked(int64_t challenge) override {
+        auto lock = std::lock_guard{mMutex};
+        mOnChallengeRevokedInvoked = true;
+        mRevokedChallenge = challenge;
+        mCv.notify_one();
         return ndk::ScopedAStatus::ok();
     }
 
@@ -50,10 +60,9 @@
         return ndk::ScopedAStatus::ok();
     }
 
-    ndk::ScopedAStatus onError(Error error, int32_t vendorCode) override {
+    ndk::ScopedAStatus onError(Error error, int32_t /*vendorCode*/) override {
         auto lock = std::lock_guard<std::mutex>{mMutex};
         mError = error;
-        mVendorCode = vendorCode;
         mOnErrorInvoked = true;
         mCv.notify_one();
         return ndk::ScopedAStatus::ok();
@@ -83,15 +92,24 @@
 
     ndk::ScopedAStatus onEnrollmentsEnumerated(
             const std::vector<int32_t>& /*enrollmentIds*/) override {
+        auto lock = std::lock_guard{mMutex};
+        mOnEnrollmentsEnumeratedInvoked = true;
+        mCv.notify_one();
         return ndk::ScopedAStatus::ok();
     }
 
     ndk::ScopedAStatus onEnrollmentsRemoved(
             const std::vector<int32_t>& /*enrollmentIds*/) override {
+        auto lock = std::lock_guard{mMutex};
+        mOnEnrollmentsRemovedInvoked = true;
+        mCv.notify_one();
         return ndk::ScopedAStatus::ok();
     }
 
     ndk::ScopedAStatus onFeaturesRetrieved(const std::vector<Feature>& /*features*/) override {
+        auto lock = std::lock_guard{mMutex};
+        mOnFeaturesRetrievedInvoked = true;
+        mCv.notify_one();
         return ndk::ScopedAStatus::ok();
     }
 
@@ -100,10 +118,16 @@
     }
 
     ndk::ScopedAStatus onAuthenticatorIdRetrieved(int64_t /*authenticatorId*/) override {
+        auto lock = std::lock_guard{mMutex};
+        mOnAuthenticatorIdRetrievedInvoked = true;
+        mCv.notify_one();
         return ndk::ScopedAStatus::ok();
     }
 
     ndk::ScopedAStatus onAuthenticatorIdInvalidated(int64_t /*newAuthenticatorId*/) override {
+        auto lock = std::lock_guard{mMutex};
+        mOnAuthenticatorIdInvalidatedInvoked = true;
+        mCv.notify_one();
         return ndk::ScopedAStatus::ok();
     }
 
@@ -117,46 +141,177 @@
     std::mutex mMutex;
     std::condition_variable mCv;
     Error mError = Error::UNKNOWN;
-    int32_t mVendorCode = 0;
+    int64_t mGeneratedChallenge = 0;
+    int64_t mRevokedChallenge = 0;
+    bool mOnChallengeGeneratedInvoked = false;
+    bool mOnChallengeRevokedInvoked = false;
     bool mOnErrorInvoked = false;
+    bool mOnEnrollmentsEnumeratedInvoked = false;
+    bool mOnEnrollmentsRemovedInvoked = false;
+    bool mOnFeaturesRetrievedInvoked = false;
+    bool mOnAuthenticatorIdRetrievedInvoked = false;
+    bool mOnAuthenticatorIdInvalidatedInvoked = false;
     bool mOnSessionClosedInvoked = false;
 };
 
 class Face : public testing::TestWithParam<std::string> {
   protected:
     void SetUp() override {
-        AIBinder* binder = AServiceManager_waitForService(GetParam().c_str());
-        ASSERT_NE(binder, nullptr);
-        mHal = IFace::fromBinder(ndk::SpAIBinder(binder));
+        // Prepare the callback.
+        mCb = ndk::SharedRefBase::make<SessionCallback>();
+
+        int retries = 0;
+        bool isOk = false;
+        // If the first attempt to create a session fails, we try to create a session again. The
+        // first attempt might fail if the framework already has an active session. The AIDL
+        // contract doesn't allow to create a new session without closing the old one. However, we
+        // can't close the framework's session from VTS. The expectation here is that the HAL will
+        // crash after the first illegal attempt to create a session, then it will restart, and then
+        // we'll be able to create a session.
+        do {
+            // Get an instance of the HAL.
+            AIBinder* binder = AServiceManager_waitForService(GetParam().c_str());
+            ASSERT_NE(binder, nullptr);
+            mHal = IFace::fromBinder(ndk::SpAIBinder(binder));
+
+            // Create a session.
+            isOk = mHal->createSession(kSensorId, kUserId, mCb, &mSession).isOk();
+            ++retries;
+        } while (!isOk && retries < 2);
+
+        ASSERT_TRUE(isOk);
+    }
+
+    void TearDown() override {
+        // Close the mSession.
+        ASSERT_TRUE(mSession->close().isOk());
+
+        // Make sure the mSession is closed.
+        auto lock = std::unique_lock<std::mutex>(mCb->mMutex);
+        mCb->mCv.wait(lock, [this] { return mCb->mOnSessionClosedInvoked; });
     }
 
     std::shared_ptr<IFace> mHal;
+    std::shared_ptr<SessionCallback> mCb;
+    std::shared_ptr<ISession> mSession;
 };
 
-TEST_P(Face, AuthenticateTest) {
-    // Prepare the callback.
-    auto cb = ndk::SharedRefBase::make<SessionCallback>();
+TEST_P(Face, GetSensorPropsWorksTest) {
+    std::vector<SensorProps> sensorProps;
 
-    // Create a session
-    std::shared_ptr<ISession> session;
-    ASSERT_TRUE(mHal->createSession(kSensorId, kUserId, cb, &session).isOk());
+    // Call the method.
+    ASSERT_TRUE(mHal->getSensorProps(&sensorProps).isOk());
 
-    // Call authenticate
+    // Make sure the sensorProps aren't empty.
+    ASSERT_FALSE(sensorProps.empty());
+    ASSERT_FALSE(sensorProps[0].commonProps.componentInfo.empty());
+}
+
+TEST_P(Face, EnrollWithBadHatResultsInErrorTest) {
+    // Call the method.
+    auto hat = keymaster::HardwareAuthToken{};
     std::shared_ptr<common::ICancellationSignal> cancellationSignal;
-    ASSERT_TRUE(session->authenticate(0 /* operationId */, &cancellationSignal).isOk());
+    ASSERT_TRUE(
+            mSession->enroll(hat, EnrollmentType::DEFAULT, {}, NativeHandle{}, &cancellationSignal)
+                    .isOk());
 
-    auto lock = std::unique_lock<std::mutex>(cb->mMutex);
-    cb->mCv.wait(lock, [&cb] { return cb->mOnErrorInvoked; });
-    // Get the results
-    EXPECT_EQ(cb->mError, Error::UNABLE_TO_PROCESS);
-    EXPECT_EQ(cb->mVendorCode, 0);
+    // Make sure an error is returned.
+    auto lock = std::unique_lock{mCb->mMutex};
+    mCb->mCv.wait(lock, [this] { return mCb->mOnErrorInvoked; });
+}
+
+TEST_P(Face, GenerateChallengeProducesUniqueChallengesTest) {
+    static constexpr int kIterations = 100;
+
+    auto challenges = std::set<int>{};
+    for (unsigned int i = 0; i < kIterations; ++i) {
+        // Call the method.
+        ASSERT_TRUE(mSession->generateChallenge().isOk());
+
+        // Check that the generated challenge is unique and not 0.
+        auto lock = std::unique_lock{mCb->mMutex};
+        mCb->mCv.wait(lock, [this] { return mCb->mOnChallengeGeneratedInvoked; });
+        ASSERT_NE(mCb->mGeneratedChallenge, 0);
+        ASSERT_EQ(challenges.find(mCb->mGeneratedChallenge), challenges.end());
+
+        challenges.insert(mCb->mGeneratedChallenge);
+        mCb->mOnChallengeGeneratedInvoked = false;
+    }
+}
+
+TEST_P(Face, RevokeChallengeWorksForNonexistentChallengeTest) {
+    const int64_t nonexistentChallenge = 123;
+
+    // Call the method.
+    ASSERT_TRUE(mSession->revokeChallenge(nonexistentChallenge).isOk());
+
+    // Check that the challenge is revoked and matches the requested challenge.
+    auto lock = std::unique_lock{mCb->mMutex};
+    mCb->mCv.wait(lock, [this] { return mCb->mOnChallengeRevokedInvoked; });
+    ASSERT_EQ(mCb->mRevokedChallenge, nonexistentChallenge);
+}
+
+TEST_P(Face, RevokeChallengeWorksForExistentChallengeTest) {
+    // Generate a challenge.
+    ASSERT_TRUE(mSession->generateChallenge().isOk());
+
+    // Wait for the result.
+    auto lock = std::unique_lock{mCb->mMutex};
+    mCb->mCv.wait(lock, [this] { return mCb->mOnChallengeGeneratedInvoked; });
     lock.unlock();
 
-    // Close the session
-    ASSERT_TRUE(session->close().isOk());
+    // Revoke the challenge.
+    ASSERT_TRUE(mSession->revokeChallenge(mCb->mGeneratedChallenge).isOk());
 
+    // Check that the challenge is revoked and matches the requested challenge.
     lock.lock();
-    cb->mCv.wait(lock, [&cb] { return cb->mOnSessionClosedInvoked; });
+    mCb->mCv.wait(lock, [this] { return mCb->mOnChallengeRevokedInvoked; });
+    ASSERT_EQ(mCb->mRevokedChallenge, mCb->mGeneratedChallenge);
+}
+
+TEST_P(Face, EnumerateEnrollmentsWorksTest) {
+    // Call the method.
+    ASSERT_TRUE(mSession->enumerateEnrollments().isOk());
+
+    // Wait for the result.
+    auto lock = std::unique_lock{mCb->mMutex};
+    mCb->mCv.wait(lock, [this] { return mCb->mOnEnrollmentsEnumeratedInvoked; });
+}
+
+TEST_P(Face, RemoveEnrollmentsWorksTest) {
+    // Call the method.
+    ASSERT_TRUE(mSession->removeEnrollments({}).isOk());
+
+    // Wait for the result.
+    auto lock = std::unique_lock{mCb->mMutex};
+    mCb->mCv.wait(lock, [this] { return mCb->mOnEnrollmentsRemovedInvoked; });
+}
+
+TEST_P(Face, GetFeaturesWorksTest) {
+    // Call the method.
+    ASSERT_TRUE(mSession->getFeatures().isOk());
+
+    // Wait for the result.
+    auto lock = std::unique_lock{mCb->mMutex};
+    mCb->mCv.wait(lock, [this] { return mCb->mOnFeaturesRetrievedInvoked; });
+}
+
+TEST_P(Face, GetAuthenticatorIdWorksTest) {
+    // Call the method.
+    ASSERT_TRUE(mSession->getAuthenticatorId().isOk());
+
+    // Wait for the result.
+    auto lock = std::unique_lock{mCb->mMutex};
+    mCb->mCv.wait(lock, [this] { return mCb->mOnAuthenticatorIdRetrievedInvoked; });
+}
+
+TEST_P(Face, InvalidateAuthenticatorIdWorksTest) {
+    // Call the method.
+    ASSERT_TRUE(mSession->invalidateAuthenticatorId().isOk());
+
+    // Wait for the result.
+    auto lock = std::unique_lock{mCb->mMutex};
+    mCb->mCv.wait(lock, [this] { return mCb->mOnAuthenticatorIdInvalidatedInvoked; });
 }
 
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Face);
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IFingerprint.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IFingerprint.aidl
index 271a9bf..75f90a1 100644
--- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IFingerprint.aidl
+++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IFingerprint.aidl
@@ -25,31 +25,31 @@
     /**
      * getSensorProps:
      *
-     * @return A list of properties for all sensors that an instance of the HAL supports.
+     * @return A list of properties for all of the fingerprint sensors supported by the HAL.
      */
     SensorProps[] getSensorProps();
 
     /**
      * createSession:
      *
-     * Creates a instance of ISession which can be used by the framework to perform operations
-     * such as ISession#enroll, ISession#authenticate, etc. for the given sensorId and userId.
+     * Creates an instance of ISession that can be used by the framework to perform operations such
+     * as ISession#enroll, ISession#authenticate, etc. for the given sensorId and userId.
      *
      * Calling this method while there is an active session is considered an error. If the framework
      * wants to create a new session when it already has an active session, it must first cancel the
-     * current operation if it's cancellable, or wait until it completes. Then, the framework must
+     * current operation if it's cancellable or wait until it completes. Then, the framework must
      * explicitly close the session with ISession#close. Once the framework receives
      * ISessionCallback#onSessionClosed, a new session can be created.
      *
      * Implementations must store user-specific state or metadata in /data/vendor_de/<user>/fpdata
-     * as specified by the SeLinux policy. This directory is created/removed by vold (see
+     * as specified by the SELinux policy. The directory /data/vendor_de is managed by vold (see
      * vold_prepare_subdirs.cpp). Implementations may store additional user-specific data, such as
-     * embeddings or templates in StrongBox.
+     * embeddings or templates, in StrongBox.
      *
-     * @param sensorId The sensor with which this session is being created.
-     * @param userId The userId with which this session is being created.
-     * @param cb Used to notify the framework.
-     * @return A new session
+     * @param sensorId The sensorId for which this session is being created.
+     * @param userId The userId for which this session is being created.
+     * @param cb A callback to notify the framework about the session's events.
+     * @return A new session.
      */
     ISession createSession(in int sensorId, in int userId, in ISessionCallback cb);
 }
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISession.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISession.aidl
index 02ef138..f1d96d3 100644
--- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISession.aidl
+++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISession.aidl
@@ -20,30 +20,29 @@
 import android.hardware.keymaster.HardwareAuthToken;
 
 /**
- * Operations that can be performed for unique sessions retrieved via IFingerprint#createSession.
- * Methods defined within this interface can be split into the following categories:
- *   1) Non-interrupting operations. These operations are handled by the HAL in FIFO order.
- *   1a) Cancellable operations. These are usually the operations that can execute for several
- *       minutes. To allow for cancellation, they return an instance of ICancellationSignal that
- *       lets the framework cancel them by calling ICancellationSignal#cancel. If such an operation
- *       is cancelled, it must notify the framework by calling ISessionCallback#onError with
- *       Error::CANCELED.
- *   1b) Non-cancellable operations. Such operations cannot be cancelled once started.
+ * Operations defined within this interface can be split into the following categories:
+ *   1) Non-interrupting operations. These operations are handled by the HAL in a FIFO order.
+ *     1a) Cancellable operations. These operations can usually run for several minutes. To allow
+ *         for cancellation, they return an instance of ICancellationSignal that allows the
+ *         framework to cancel them by calling ICancellationSignal#cancel. If such an operation is
+ *         cancelled, it must notify the framework by calling ISessionCallback#onError with
+ *         Error::CANCELED.
+ *     1b) Non-cancellable operations. Such operations cannot be cancelled once started.
  *   2) Interrupting operations. These operations may be invoked by the framework immediately,
  *      regardless of whether another operation is executing. For example, on devices with sensors
- *      of FingerprintSensorType::UNDER_DISPLAY_*, ISession#onFingerDown may be invoked while the
+ *      of FingerprintSensorType::UNDER_DISPLAY_*, ISession#onPointerDown may be invoked while the
  *      HAL is executing ISession#enroll, ISession#authenticate or ISession#detectInteraction.
  *
- * The lifecycle of a non-interrupting operation ends when one of its terminal callbacks is called.
- * For example, ISession#authenticate is considered completed when either of the following callbacks
- * is called: ISessionCallback#onError or ISessionCallback#onAuthenticationSucceeded.
+ * The lifecycle of a non-interrupting operation ends when one of its final callbacks is called.
+ * For example, ISession#authenticate is considered completed when either ISessionCallback#onError
+ * or ISessionCallback#onAuthenticationSucceeded is called.
  *
  * The lifecycle of an interrupting operation ends when it returns. Interrupting operations do not
  * have callbacks.
  *
  * ISession only supports execution of one non-interrupting operation at a time, regardless of
- * whether it's cancellable. The framework must wait for a corresponding callback indicating the end
- * of the current non-interrupting operation before a new non-interrupting operation can be started.
+ * whether it's cancellable. The framework must wait for a callback indicating the end of the
+ * current non-interrupting operation before a new non-interrupting operation can be started.
  */
 @VintfStability
 interface ISession {
@@ -89,15 +88,19 @@
      * | 0        | 10     | <Time4>    | <Random4> |
      * ----------------------------------------------
      *
+     * Callbacks that signify the end of this operation's lifecycle:
+     *   - ISessionCallback#onChallengeGenerated
      */
     void generateChallenge();
 
     /**
      * revokeChallenge:
      *
-     * Revokes a challenge that was previously generated. Note that if an invalid combination of
-     * parameters is requested, the implementation must still notify the framework using the
-     * provided callback.
+     * Revokes a challenge that was previously generated. Note that if a non-existent challenge is
+     * provided, the HAL must still notify the framework using ISessionCallback#onChallengeRevoked.
+     *
+     * Callbacks that signify the end of this operation's lifecycle:
+     *   - ISessionCallback#onChallengeRevoked
      *
      * @param challenge Challenge that should be revoked.
      */
@@ -111,26 +114,33 @@
      * At any point during enrollment, if a non-recoverable error occurs, the HAL must notify the
      * framework via ISessionCallback#onError with the applicable enrollment-specific error.
      *
-     * Before capturing fingerprint data, the implementation must first verify the authenticity and
-     * integrity of the provided HardwareAuthToken. In addition, it must check that the challenge
-     * within the provided HardwareAuthToken is valid. See ISession#generateChallenge. If any of
-     * the above checks fail, the framework must be notified via ISessionCallback#onError and the
-     * HAL must notify the framework when it returns to the idle state. See
+     * Before capturing fingerprint data, the HAL must first verify the authenticity and integrity
+     * of the provided HardwareAuthToken. In addition, it must check that the challenge within the
+     * provided HardwareAuthToken is valid. See ISession#generateChallenge. If any of the above
+     * checks fail, the framework must be notified using ISessionCallback#onError with
      * Error::UNABLE_TO_PROCESS.
      *
-     * During enrollment, the implementation may notify the framework via
-     * ISessionCallback#onAcquired with messages that may be used to guide the user. This callback
-     * can be invoked multiple times if necessary. Similarly, the framework may be notified of
-     * enrollment progress changes via ISessionCallback#onEnrollmentProgress. Once the framework is
-     * notified that there are 0 "remaining" steps, the framework may cache the "enrollmentId". See
-     * ISessionCallback#onEnrollmentProgress for more info. The HAL must notify the framework once
-     * it returns to the idle state.
+     * During enrollment, the HAL may notify the framework via ISessionCallback#onAcquired with
+     * messages that may be used to guide the user. This callback can be invoked multiple times if
+     * necessary. Similarly, the framework may be notified of enrollment progress changes via
+     * ISessionCallback#onEnrollmentProgress. Once the framework is notified that there are 0
+     * "remaining" steps, the framework may cache the "enrollmentId". See
+     * ISessionCallback#onEnrollmentProgress for more info.
      *
      * When a finger is successfully added and before the framework is notified of remaining=0, the
-     * implementation MUST update and associate this (sensorId, userId) pair with a new new
-     * entropy-encoded random identifier. See ISession#getAuthenticatorId for more information.
+     * HAL must update and associate this (sensorId, userId) pair with a new entropy-encoded random
+     * identifier. See ISession#getAuthenticatorId for more information.
+     *
+     * Callbacks that signify the end of this operation's lifecycle:
+     *   - ISessionCallback#onError
+     *   - ISessionCallback#onEnrollmentProgress(enrollmentId, remaining=0)
+     *
+     * Other applicable callbacks:
+     *   - ISessionCallback#onAcquired
      *
      * @param hat See above documentation.
+     * @return ICancellationSignal An object that can be used by the framework to cancel this
+     * operation.
      */
     ICancellationSignal enroll(in HardwareAuthToken hat);
 
@@ -142,14 +152,16 @@
      * At any point during authentication, if a non-recoverable error occurs, the HAL must notify
      * the framework via ISessionCallback#onError with the applicable authentication-specific error.
      *
-     * During authentication, the implementation may notify the framework via
-     * ISessionCallback#onAcquired with messages that may be used to guide the user. This callback
-     * can be invoked multiple times if necessary.
+     * During authentication, the HAL may notify the framework via ISessionCallback#onAcquired with
+     * messages that may be used to guide the user. This callback can be invoked multiple times if
+     * necessary.
      *
-     * The HAL must notify the framework of accepts/rejects via ISessionCallback#onAuthentication*.
+     * The HAL must notify the framework of accepts and rejects via
+     * ISessionCallback#onAuthenticationSucceeded and ISessionCallback#onAuthenticationFailed,
+     * correspondingly.
      *
-     * The authentication lifecycle ends when either
-     *   1) A fingerprint is accepted, and ISessionCallback#onAuthenticationSucceeded is invoked, or
+     * The authentication lifecycle ends when either:
+     *   1) A fingerprint is accepted, and ISessionCallback#onAuthenticationSucceeded is invoked.
      *   2) Any non-recoverable error occurs (such as lockout). See the full list of
      *      authentication-specific errors in the Error enum.
      *
@@ -162,16 +174,28 @@
      * must be set with the operationId passed in during #authenticate. If the sensor is NOT
      * SensorStrength::STRONG, the HardwareAuthToken MUST be null.
      *
+     * Callbacks that signify the end of this operation's lifecycle:
+     *   - ISessionCallback#onError
+     *   - ISessionCallback#onAuthenticationSucceeded
+     *
+     * Other applicable callbacks:
+     *   - ISessionCallback#onAcquired
+     *   - ISessionCallback#onAuthenticationFailed
+     *   - ISessionCallback#onLockoutTimed
+     *   - ISessionCallback#onLockoutPermanent
+     *
      * @param operationId For sensors configured as SensorStrength::STRONG, this must be used ONLY
      *                    upon successful authentication and wrapped in the HardwareAuthToken's
      *                    "challenge" field and sent to the framework via
-     *                    ISessionCallback#onAuthenticated. The operationId is an opaque identifier
-     *                    created from a separate secure subsystem such as, but not limited to
-     *                    KeyStore/KeyMaster. The HardwareAuthToken can then be used as an
-     *                    attestation for the provided operation. For example, this is used
-     *                    to unlock biometric-bound auth-per-use keys (see
+     *                    ISessionCallback#onAuthenticationSucceeded. The operationId is an opaque
+     *                    identifier created from a separate secure subsystem such as, but not
+     *                    limited to KeyStore/KeyMaster. The HardwareAuthToken can then be used as
+     *                    an attestation for the provided operation. For example, this is used to
+     *                    unlock biometric-bound auth-per-use keys (see
      *                    setUserAuthenticationParameters in KeyGenParameterSpec.Builder and
-     *                    KeyProtection.Builder.
+     *                    KeyProtection.Builder).
+     * @return ICancellationSignal An object that can be used by the framework to cancel this
+     * operation.
      */
     ICancellationSignal authenticate(in long operationId);
 
@@ -179,44 +203,52 @@
      * detectInteraction:
      *
      * A request to start looking for fingerprints without performing matching. Must only be called
-     * if SensorProps#supportsDetectInteraction is true. If invoked on implementations that do not
-     * support this functionality, the HAL must respond with ISession#onError(UNABLE_TO_PROCESS, 0).
+     * if SensorProps#supportsDetectInteraction is true. If invoked on HALs that do not support this
+     * functionality, the HAL must respond with ISession#onError(UNABLE_TO_PROCESS, 0).
      *
-     * The framework will use this method in cases where determing user presence is required, but
-     * identifying/authentication is not. For example, when the device is encrypted (first boot) or
-     * in lockdown mode.
+     * The framework will use this operation in cases where determining user presence is required,
+     * but identifying/authenticating is not. For example, when the device is encrypted (first boot)
+     * or in lockdown mode.
      *
      * At any point during detectInteraction, if a non-recoverable error occurs, the HAL must notify
      * the framework via ISessionCallback#onError with the applicable error.
      *
-     * The implementation must only check for a fingerprint-like image was detected (e.g. to
-     * minimize interactions due to non-fingerprint objects), and the lockout counter must not
-     * be modified.
+     * The HAL must only check whether a fingerprint-like image was detected (e.g. to minimize
+     * interactions due to non-fingerprint objects), and the lockout counter must not be modified.
      *
-     * Upon detecting any fingerprint, the implementation must invoke
-     * ISessionCallback#onInteractionDetected.
+     * Upon detecting any fingerprint, the HAL must invoke ISessionCallback#onInteractionDetected.
      *
-     * The lifecycle of this operation ends when either
+     * The lifecycle of this operation ends when either:
      * 1) Any fingerprint is detected and the framework is notified via
-     *    ISessionCallback#onInteractiondetected
-     * 2) The operation was cancelled by the framework (see ICancellationSignal)
-     * 3) The HAL ends the operation, for example when a subsequent operation pre-empts this one.
+     *    ISessionCallback#onInteractionDetected.
+     * 2) An error occurs, for example Error::TIMEOUT.
      *
-     * Note that if the operation is canceled, the implementation must notify the framework via
+     * Note that if the operation is canceled, the HAL must notify the framework via
      * ISessionCallback#onError with Error::CANCELED.
      *
+     * Callbacks that signify the end of this operation's lifecycle:
+     *   - ISessionCallback#onError
+     *   - ISessionCallback#onInteractionDetected
+     *
+     * Other applicable callbacks:
+     *   - ISessionCallback#onAcquired
+     *
+     * @return ICancellationSignal An object that can be used by the framework to cancel this
+     * operation.
      */
     ICancellationSignal detectInteraction();
 
     /*
      * enumerateEnrollments:
      *
-     * A request to enumerate (list) the enrollments for this (sensorId, userId) pair. The
-     * framework typically uses this to ensure that its cache is in sync with the HAL.
+     * A request to enumerate (list) the enrollments for this (sensorId, userId) pair. The framework
+     * typically uses this to ensure that its cache is in sync with the HAL.
      *
-     * The implementation must then notify the framework with a list of enrollments applicable
-     * for the current session via ISessionCallback#onEnrollmentsEnumerated.
+     * The HAL must then notify the framework with a list of enrollments applicable for the current
+     * session via ISessionCallback#onEnrollmentsEnumerated.
      *
+     * Callbacks that signify the end of this operation's lifecycle:
+     *   - ISessionCallback#onEnrollmentsEnumerated
      */
     void enumerateEnrollments();
 
@@ -226,8 +258,12 @@
      * A request to remove the enrollments for this (sensorId, userId) pair.
      *
      * After removing the enrollmentIds from everywhere necessary (filesystem, secure subsystems,
-     * etc), the implementation must notify the framework via ISessionCallback#onEnrollmentsRemoved.
+     * etc), the HAL must notify the framework via ISessionCallback#onEnrollmentsRemoved.
      *
+     * Callbacks that signify the end of this operation's lifecycle:
+     *   - ISessionCallback#onEnrollmentsRemoved
+     *
+     * @param enrollmentIds a list of enrollments that should be removed.
      */
     void removeEnrollments(in int[] enrollmentIds);
 
@@ -240,15 +276,15 @@
      * The following only applies to sensors that are configured as SensorStrength::STRONG.
      *
      * The authenticatorId is a (sensorId, user)-specific identifier which can be used during key
-     * generation and key import to to associate a key (in KeyStore / KeyMaster) with the current
-     * set of enrolled fingerprints. For example, the following public Android APIs allow for keys
-     * to be invalidated when the user adds a new enrollment after the key was created:
+     * generation and import to associate the key (in KeyStore / KeyMaster) with the current set of
+     * enrolled fingerprints. For example, the following public Android APIs allow for keys to be
+     * invalidated when the user adds a new enrollment after the key was created:
      * KeyGenParameterSpec.Builder.setInvalidatedByBiometricEnrollment and
      * KeyProtection.Builder.setInvalidatedByBiometricEnrollment.
      *
      * In addition, upon successful fingerprint authentication, the signed HAT that is returned to
-     * the framework via ISessionCallback#onAuthenticated must contain this identifier in the
-     * authenticatorId field.
+     * the framework via ISessionCallback#onAuthenticationSucceeded must contain this identifier in
+     * the authenticatorId field.
      *
      * Returns an entropy-encoded random identifier associated with the current set of enrollments
      * via ISessionCallback#onAuthenticatorIdRetrieved. The authenticatorId
@@ -257,20 +293,21 @@
      *   3) MUST not change if a fingerprint is deleted.
      *   4) MUST be an entropy-encoded random number
      *
+     * Callbacks that signify the end of this operation's lifecycle:
+     *   - ISessionCallback#onAuthenticatorIdRetrieved
      */
     void getAuthenticatorId();
 
     /**
      * invalidateAuthenticatorId:
      *
-     * This method only applies to sensors that are configured as SensorStrength::STRONG. If invoked
-     * by the framework for sensor of other strengths, the HAL should immediately invoke
+     * This operation only applies to sensors that are configured as SensorStrength::STRONG. If
+     * invoked by the framework for sensors of other strengths, the HAL should immediately invoke
      * ISessionCallback#onAuthenticatorIdInvalidated.
      *
      * The following only applies to sensors that are configured as SensorStrength::STRONG.
      *
-     * When invoked by the framework, the implementation must perform the following sequence of
-     * events:
+     * When invoked by the framework, the HAL must perform the following sequence of events:
      *   1) Update the authenticatorId with a new entropy-encoded random number
      *   2) Persist the new authenticatorId to non-ephemeral storage
      *   3) Notify the framework that the above is completed, via
@@ -278,23 +315,25 @@
      *
      * A practical use case of invalidation would be when the user adds a new enrollment to a sensor
      * managed by a different HAL instance. The public android.security.keystore APIs bind keys to
-     * "all biometrics" rather than "fingerprint-only" or "face-only" (see #getAuthenticatorId
-     * for more details). As such, the framework would coordinate invalidation across multiple
-     * biometric HALs as necessary.
+     * "all biometrics" rather than "fingerprint-only" or "face-only" (see #getAuthenticatorId for
+     * more details). As such, the framework would coordinate invalidation across multiple biometric
+     * HALs as necessary.
      *
+     * Callbacks that signify the end of this operation's lifecycle:
+     *   - ISessionCallback#onAuthenticatorIdInvalidated
      */
     void invalidateAuthenticatorId();
 
     /**
      * resetLockout:
      *
-     * Requests the implementation to clear the lockout counter. Upon receiving this request, the
-     * implementation must perform the following:
+     * Requests the HAL to clear the lockout counter. Upon receiving this request, the HAL must
+     * perform the following:
      *   1) Verify the authenticity and integrity of the provided HAT
      *   2) Verify that the timestamp provided within the HAT is relatively recent (e.g. on the
      *      order of minutes, not hours).
      * If either of the checks fail, the HAL must invoke ISessionCallback#onError with
-     * Error::UNABLE_TO_PROCESS and return to the idling state.
+     * Error::UNABLE_TO_PROCESS.
      *
      * Upon successful verification, the HAL must clear the lockout counter and notify the framework
      * via ISessionCallback#onLockoutCleared.
@@ -325,6 +364,9 @@
      * See the Android CDD section 7.3.10 for the full set of lockout and rate-limiting
      * requirements.
      *
+     * Callbacks that signify the end of this operation's lifecycle:
+     *   - ISessionCallback#onLockoutCleared
+     *
      * @param hat HardwareAuthToken See above documentation.
      */
     void resetLockout(in HardwareAuthToken hat);
@@ -343,6 +385,8 @@
      * All sessions must be explicitly closed. Calling IFingerprint#createSession while there is an
      * active session is considered an error.
      *
+     * Callbacks that signify the end of this operation's lifecycle:
+     *   - ISessionCallback#onSessionClosed
      */
     void close();
 
@@ -353,16 +397,16 @@
     /**
      * onPointerDown:
      *
-     * This method only applies to sensors that are configured as
+     * This operation only applies to sensors that are configured as
      * FingerprintSensorType::UNDER_DISPLAY_*. If invoked erroneously by the framework for sensors
      * of other types, the HAL must treat this as a no-op and return immediately.
      *
-     * For sensors of type FingerprintSensorType::UNDER_DISPLAY_*, this method is used to notify the
-     * HAL of display touches. This method can be invoked when the HAL is performing any one of:
-     * ISession#authenticate, ISession#enroll, ISession#detectInteraction.
+     * This operation is used to notify the HAL of display touches. This operation can be invoked
+     * when the HAL is performing any one of: ISession#authenticate, ISession#enroll,
+     * ISession#detectInteraction.
      *
-     * Note that the framework will only invoke this method if the event occurred on the display on
-     * which this sensor is located.
+     * Note that the framework will only invoke this operation if the event occurred on the display
+     * on which this sensor is located.
      *
      * Note that for sensors which require illumination such as
      * FingerprintSensorType::UNDER_DISPLAY_OPTICAL, and where illumination is handled below the
@@ -379,10 +423,13 @@
     /**
      * onPointerUp:
      *
-     * This method only applies to sensors that are configured as
+     * This operation only applies to sensors that are configured as
      * FingerprintSensorType::UNDER_DISPLAY_*. If invoked for sensors of other types, the HAL must
      * treat this as a no-op and return immediately.
      *
+     * This operation can be invoked when the HAL is performing any one of: ISession#authenticate,
+     * ISession#enroll, ISession#detectInteraction.
+     *
      * @param pointerId See android.view.MotionEvent#getPointerId
      */
     void onPointerUp(in int pointerId);
@@ -390,12 +437,15 @@
     /*
      * onUiReady:
      *
-     * This method only applies to sensors that are configured as
+     * This operation only applies to sensors that are configured as
      * FingerprintSensorType::UNDER_DISPLAY_OPTICAL. If invoked for sensors of other types, the HAL
      * must treat this as a no-op and return immediately.
      *
+     * This operation can be invoked when the HAL is performing any one of: ISession#authenticate,
+     * ISession#enroll, ISession#detectInteraction.
+     *
      * For FingerprintSensorType::UNDER_DISPLAY_OPTICAL where illumination is handled above the
-     * HAL, the framework will invoke this method to notify that the illumination has started.
+     * HAL, the framework will invoke this operation to notify when the illumination is showing.
      */
     void onUiReady();
 }
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISessionCallback.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISessionCallback.aidl
index 95657b3..f699966 100644
--- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISessionCallback.aidl
+++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISessionCallback.aidl
@@ -34,12 +34,12 @@
 
     /**
      * This method must only be used to notify the framework during the following operations:
-     *   1) ISession#enroll
-     *   2) ISession#authenticate
-     *   3) ISession#detectInteraction
+     *   - ISession#enroll
+     *   - ISession#authenticate
+     *   - ISession#detectInteraction
      *
-     * These messages may be used to provide user guidance multiple times if necessary per
-     * operation.
+     * These messages may be used to provide user guidance multiple times per operation if
+     * necessary.
      *
      * @param info See the AcquiredInfo enum.
      * @param vendorCode Only valid if info == AcquiredInfo::VENDOR. The vendorCode must be used to
@@ -51,18 +51,18 @@
 
     /**
      * This method must only be used to notify the framework during the following operations:
-     *   1) ISession#enroll
-     *   2) ISession#authenticate
-     *   3) ISession#detectInteraction
-     *   4) ISession#invalidateAuthenticatorId
-     *   5) ISession#resetLockout
+     *   - ISession#enroll
+     *   - ISession#authenticate
+     *   - ISession#detectInteraction
+     *   - ISession#invalidateAuthenticatorId
+     *   - ISession#resetLockout
      *
      * These messages may be used to notify the framework or user that a non-recoverable error
      * has occurred. The operation is finished, and the HAL can proceed with the next operation
      * or return to the idling state.
      *
-     * Note that cancellation (see common::ICancellationSignal) and preemption must be followed with
-     * an Error::CANCELED message.
+     * Note that cancellation (see common::ICancellationSignal) must be followed with an
+     * Error::CANCELED message.
      *
      * @param error See the Error enum.
      * @param vendorCode Only valid if error == Error::VENDOR. The vendorCode must be used to index
@@ -100,8 +100,8 @@
      * This method must only be used to notify the framework during ISession#authenticate.
      *
      * Used to notify the framework upon rejected attempts. Note that the authentication
-     * lifecycle ends when either 1) a fingerprint is accepted, or 2) an occurred. The
-     * authentication lifecycle does NOT end when a fingerprint is rejected.
+     * lifecycle ends when either 1) a fingerprint is accepted, or 2) an error occurred.
+     * The authentication lifecycle does NOT end when a fingerprint is rejected.
      */
     void onAuthenticationFailed();
 
diff --git a/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngine.h b/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngine.h
index 6667f7a..b927770 100644
--- a/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngine.h
+++ b/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngine.h
@@ -17,14 +17,19 @@
 #pragma once
 
 #include <android-base/logging.h>
+#include <random>
 
 namespace aidl::android::hardware::biometrics::fingerprint {
 
 class FakeFingerprintEngine {
   public:
+    FakeFingerprintEngine() : mRandom(std::mt19937::default_seed) {}
+
     void generateChallengeImpl(ISessionCallback* cb) {
         LOG(INFO) << "generateChallengeImpl";
-        cb->onChallengeGenerated(0 /* challenge */);
+        std::uniform_int_distribution<int64_t> dist;
+        auto challenge = dist(mRandom);
+        cb->onChallengeGenerated(challenge);
     }
 
     void revokeChallengeImpl(ISessionCallback* cb, int64_t challenge) {
@@ -32,8 +37,13 @@
         cb->onChallengeRevoked(challenge);
     }
 
-    void enrollImpl(ISessionCallback* cb, const keymaster::HardwareAuthToken& /*hat*/) {
+    void enrollImpl(ISessionCallback* cb, const keymaster::HardwareAuthToken& hat) {
         LOG(INFO) << "enrollImpl";
+        // Do proper HAT verification in the real implementation.
+        if (hat.mac.empty()) {
+            cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorError */);
+            return;
+        }
         cb->onEnrollmentProgress(0 /* enrollmentId */, 0 /* remaining */);
     }
 
@@ -71,6 +81,8 @@
         LOG(INFO) << "resetLockoutImpl";
         cb->onLockoutCleared();
     }
+
+    std::mt19937 mRandom;
 };
 
 }  // namespace aidl::android::hardware::biometrics::fingerprint
diff --git a/biometrics/fingerprint/aidl/vts/VtsHalBiometricsFingerprintTargetTest.cpp b/biometrics/fingerprint/aidl/vts/VtsHalBiometricsFingerprintTargetTest.cpp
index f1cfb17..1cd8c76 100644
--- a/biometrics/fingerprint/aidl/vts/VtsHalBiometricsFingerprintTargetTest.cpp
+++ b/biometrics/fingerprint/aidl/vts/VtsHalBiometricsFingerprintTargetTest.cpp
@@ -35,13 +35,19 @@
 
 class SessionCallback : public BnSessionCallback {
   public:
-    explicit SessionCallback(std::promise<void>&& promise) : mPromise(std::move(promise)) {}
-
-    ndk::ScopedAStatus onChallengeGenerated(int64_t /*challenge*/) override {
+    ndk::ScopedAStatus onChallengeGenerated(int64_t challenge) override {
+        auto lock = std::lock_guard{mMutex};
+        mOnChallengeGeneratedInvoked = true;
+        mGeneratedChallenge = challenge;
+        mCv.notify_one();
         return ndk::ScopedAStatus::ok();
     }
 
-    ndk::ScopedAStatus onChallengeRevoked(int64_t /*challenge*/) override {
+    ndk::ScopedAStatus onChallengeRevoked(int64_t challenge) override {
+        auto lock = std::lock_guard{mMutex};
+        mOnChallengeRevokedInvoked = true;
+        mRevokedChallenge = challenge;
+        mCv.notify_one();
         return ndk::ScopedAStatus::ok();
     }
 
@@ -49,7 +55,11 @@
         return ndk::ScopedAStatus::ok();
     }
 
-    ndk::ScopedAStatus onError(Error /*error*/, int32_t /*vendorCode*/) override {
+    ndk::ScopedAStatus onError(Error error, int32_t /*vendorCode*/) override {
+        auto lock = std::lock_guard{mMutex};
+        mError = error;
+        mOnErrorInvoked = true;
+        mCv.notify_one();
         return ndk::ScopedAStatus::ok();
     }
 
@@ -77,63 +87,203 @@
 
     ndk::ScopedAStatus onEnrollmentsEnumerated(
             const std::vector<int32_t>& /*enrollmentIds*/) override {
+        auto lock = std::lock_guard{mMutex};
+        mOnEnrollmentsEnumeratedInvoked = true;
+        mCv.notify_one();
         return ndk::ScopedAStatus::ok();
     }
 
     ndk::ScopedAStatus onEnrollmentsRemoved(
             const std::vector<int32_t>& /*enrollmentIds*/) override {
+        auto lock = std::lock_guard{mMutex};
+        mOnEnrollmentsRemovedInvoked = true;
+        mCv.notify_one();
         return ndk::ScopedAStatus::ok();
     }
 
     ndk::ScopedAStatus onAuthenticatorIdRetrieved(int64_t /*authenticatorId*/) override {
+        auto lock = std::lock_guard{mMutex};
+        mOnAuthenticatorIdRetrievedInvoked = true;
+        mCv.notify_one();
         return ndk::ScopedAStatus::ok();
     }
 
     ndk::ScopedAStatus onAuthenticatorIdInvalidated(int64_t /*newAuthenticatorId*/) override {
+        auto lock = std::lock_guard{mMutex};
+        mOnAuthenticatorIdInvalidatedInvoked = true;
+        mCv.notify_one();
         return ndk::ScopedAStatus::ok();
     }
 
     ndk::ScopedAStatus onSessionClosed() override {
-        mPromise.set_value();
+        auto lock = std::lock_guard{mMutex};
+        mOnSessionClosedInvoked = true;
+        mCv.notify_one();
         return ndk::ScopedAStatus::ok();
     }
 
-  private:
-    std::promise<void> mPromise;
+    std::mutex mMutex;
+    std::condition_variable mCv;
+    Error mError = Error::UNKNOWN;
+    int64_t mGeneratedChallenge = 0;
+    int64_t mRevokedChallenge = 0;
+    bool mOnChallengeGeneratedInvoked = false;
+    bool mOnChallengeRevokedInvoked = false;
+    bool mOnErrorInvoked = false;
+    bool mOnEnrollmentsEnumeratedInvoked = false;
+    bool mOnEnrollmentsRemovedInvoked = false;
+    bool mOnAuthenticatorIdRetrievedInvoked = false;
+    bool mOnAuthenticatorIdInvalidatedInvoked = false;
+    bool mOnSessionClosedInvoked = false;
 };
 
 class Fingerprint : public testing::TestWithParam<std::string> {
   protected:
     void SetUp() override {
-        AIBinder* binder = AServiceManager_waitForService(GetParam().c_str());
-        ASSERT_NE(binder, nullptr);
-        mHal = IFingerprint::fromBinder(ndk::SpAIBinder(binder));
+        // Prepare the callback.
+        mCb = ndk::SharedRefBase::make<SessionCallback>();
+
+        int retries = 0;
+        bool isOk = false;
+        // If the first attempt to create a session fails, we try to create a session again. The
+        // first attempt might fail if the framework already has an active session. The AIDL
+        // contract doesn't allow to create a new session without closing the old one. However, we
+        // can't close the framework's session from VTS. The expectation here is that the HAL will
+        // crash after the first illegal attempt to create a session, then it will restart, and then
+        // we'll be able to create a session.
+        do {
+            // Get an instance of the HAL.
+            AIBinder* binder = AServiceManager_waitForService(GetParam().c_str());
+            ASSERT_NE(binder, nullptr);
+            mHal = IFingerprint::fromBinder(ndk::SpAIBinder(binder));
+
+            // Create a session.
+            isOk = mHal->createSession(kSensorId, kUserId, mCb, &mSession).isOk();
+            ++retries;
+        } while (!isOk && retries < 2);
+
+        ASSERT_TRUE(isOk);
+    }
+
+    void TearDown() override {
+        // Close the mSession.
+        ASSERT_TRUE(mSession->close().isOk());
+
+        // Make sure the mSession is closed.
+        auto lock = std::unique_lock<std::mutex>(mCb->mMutex);
+        mCb->mCv.wait(lock, [this] { return mCb->mOnSessionClosedInvoked; });
     }
 
     std::shared_ptr<IFingerprint> mHal;
+    std::shared_ptr<SessionCallback> mCb;
+    std::shared_ptr<ISession> mSession;
 };
 
-TEST_P(Fingerprint, AuthenticateTest) {
-    auto promise = std::promise<void>{};
-    auto future = promise.get_future();
-    // Prepare the callback.
-    auto cb = ndk::SharedRefBase::make<SessionCallback>(std::move(promise));
+TEST_P(Fingerprint, GetSensorPropsWorksTest) {
+    std::vector<SensorProps> sensorProps;
 
-    // Create a session
-    std::shared_ptr<ISession> session;
-    ASSERT_TRUE(mHal->createSession(kSensorId, kUserId, cb, &session).isOk());
+    // Call the method.
+    ASSERT_TRUE(mHal->getSensorProps(&sensorProps).isOk());
 
-    // Call authenticate
+    // Make sure the sensorProps aren't empty.
+    ASSERT_FALSE(sensorProps.empty());
+    ASSERT_FALSE(sensorProps[0].commonProps.componentInfo.empty());
+}
+
+TEST_P(Fingerprint, EnrollWithBadHatResultsInErrorTest) {
+    // Call the method.
+    auto hat = keymaster::HardwareAuthToken{};
     std::shared_ptr<common::ICancellationSignal> cancellationSignal;
-    ASSERT_TRUE(session->authenticate(-1 /* operationId */, &cancellationSignal).isOk());
+    ASSERT_TRUE(mSession->enroll(hat, &cancellationSignal).isOk());
 
-    // Get the results
-    // TODO(b/166799066): test authenticate.
+    // Make sure an error is returned.
+    auto lock = std::unique_lock{mCb->mMutex};
+    mCb->mCv.wait(lock, [this] { return mCb->mOnErrorInvoked; });
+}
 
-    // Close the session
-    ASSERT_TRUE(session->close().isOk());
-    auto status = future.wait_for(1s);
-    ASSERT_EQ(status, std::future_status::ready);
+TEST_P(Fingerprint, GenerateChallengeProducesUniqueChallengesTest) {
+    static constexpr int kIterations = 100;
+
+    auto challenges = std::set<int>{};
+    for (unsigned int i = 0; i < kIterations; ++i) {
+        // Call the method.
+        ASSERT_TRUE(mSession->generateChallenge().isOk());
+
+        // Check that the generated challenge is unique and not 0.
+        auto lock = std::unique_lock{mCb->mMutex};
+        mCb->mCv.wait(lock, [this] { return mCb->mOnChallengeGeneratedInvoked; });
+        ASSERT_NE(mCb->mGeneratedChallenge, 0);
+        ASSERT_EQ(challenges.find(mCb->mGeneratedChallenge), challenges.end());
+
+        challenges.insert(mCb->mGeneratedChallenge);
+        mCb->mOnChallengeGeneratedInvoked = false;
+    }
+}
+
+TEST_P(Fingerprint, RevokeChallengeWorksForNonexistentChallengeTest) {
+    const int64_t nonexistentChallenge = 123;
+
+    // Call the method.
+    ASSERT_TRUE(mSession->revokeChallenge(nonexistentChallenge).isOk());
+
+    // Check that the challenge is revoked and matches the requested challenge.
+    auto lock = std::unique_lock{mCb->mMutex};
+    mCb->mCv.wait(lock, [this] { return mCb->mOnChallengeRevokedInvoked; });
+    ASSERT_EQ(mCb->mRevokedChallenge, nonexistentChallenge);
+}
+
+TEST_P(Fingerprint, RevokeChallengeWorksForExistentChallengeTest) {
+    // Generate a challenge.
+    ASSERT_TRUE(mSession->generateChallenge().isOk());
+
+    // Wait for the result.
+    auto lock = std::unique_lock{mCb->mMutex};
+    mCb->mCv.wait(lock, [this] { return mCb->mOnChallengeGeneratedInvoked; });
+    lock.unlock();
+
+    // Revoke the challenge.
+    ASSERT_TRUE(mSession->revokeChallenge(mCb->mGeneratedChallenge).isOk());
+
+    // Check that the challenge is revoked and matches the requested challenge.
+    lock.lock();
+    mCb->mCv.wait(lock, [this] { return mCb->mOnChallengeRevokedInvoked; });
+    ASSERT_EQ(mCb->mRevokedChallenge, mCb->mGeneratedChallenge);
+}
+
+TEST_P(Fingerprint, EnumerateEnrollmentsWorksTest) {
+    // Call the method.
+    ASSERT_TRUE(mSession->enumerateEnrollments().isOk());
+
+    // Wait for the result.
+    auto lock = std::unique_lock{mCb->mMutex};
+    mCb->mCv.wait(lock, [this] { return mCb->mOnEnrollmentsEnumeratedInvoked; });
+}
+
+TEST_P(Fingerprint, RemoveEnrollmentsWorksTest) {
+    // Call the method.
+    ASSERT_TRUE(mSession->removeEnrollments({}).isOk());
+
+    // Wait for the result.
+    auto lock = std::unique_lock{mCb->mMutex};
+    mCb->mCv.wait(lock, [this] { return mCb->mOnEnrollmentsRemovedInvoked; });
+}
+
+TEST_P(Fingerprint, GetAuthenticatorIdWorksTest) {
+    // Call the method.
+    ASSERT_TRUE(mSession->getAuthenticatorId().isOk());
+
+    // Wait for the result.
+    auto lock = std::unique_lock{mCb->mMutex};
+    mCb->mCv.wait(lock, [this] { return mCb->mOnAuthenticatorIdRetrievedInvoked; });
+}
+
+TEST_P(Fingerprint, InvalidateAuthenticatorIdWorksTest) {
+    // Call the method.
+    ASSERT_TRUE(mSession->invalidateAuthenticatorId().isOk());
+
+    // Wait for the result.
+    auto lock = std::unique_lock{mCb->mMutex};
+    mCb->mCv.wait(lock, [this] { return mCb->mOnAuthenticatorIdInvalidatedInvoked; });
 }
 
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Fingerprint);
diff --git a/camera/device/3.7/types.hal b/camera/device/3.7/types.hal
index 6910e65..55aceb8 100644
--- a/camera/device/3.7/types.hal
+++ b/camera/device/3.7/types.hal
@@ -42,7 +42,7 @@
     /**
      * The surface group id used for multi-resolution output streams.
      *
-     * This works simliar to the surfaceGroupId of OutputConfiguration in the
+     * This works similar to the surfaceGroupId of OutputConfiguration in the
      * public API, with the exception that this is for multi-resolution image
      * reader and is used by the camera HAL to choose a target stream within
      * the same group to which images are written. All streams in the same group
diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index 41a08f9..49e00f4 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -230,10 +230,10 @@
         return false;
     }
 
-    int getCameraDeviceVersion(const hidl_string& deviceName,
-            const hidl_string &providerType) {
+    int getCameraDeviceVersionAndId(const hidl_string& deviceName,
+            const hidl_string &providerType, std::string* id) {
         std::string version;
-        bool match = matchDeviceName(deviceName, providerType, &version, nullptr);
+        bool match = matchDeviceName(deviceName, providerType, &version, id);
         if (!match) {
             return -1;
         }
@@ -256,6 +256,11 @@
         return 0;
     }
 
+    int getCameraDeviceVersion(const hidl_string& deviceName,
+            const hidl_string &providerType) {
+        return getCameraDeviceVersionAndId(deviceName, providerType, nullptr);
+    }
+
     bool parseProviderName(const std::string& name, std::string *type /*out*/,
             uint32_t *id /*out*/) {
         if (!type || !id) {
@@ -930,6 +935,7 @@
             camera_metadata_ro_entry* streamConfigs,
             camera_metadata_ro_entry* maxResolutionStreamConfigs,
             const camera_metadata_t* staticMetadata);
+    static bool isColorCamera(const camera_metadata_t *metadata);
 
     static V3_2::DataspaceFlags getDataspace(PixelFormat format);
 
@@ -6179,6 +6185,167 @@
     }
 }
 
+// Test the multi-camera API requirement for Google Requirement Freeze S
+// Note that this requirement can only be partially tested. If a vendor
+// device doesn't expose a physical camera in any shape or form, there is no way
+// the test can catch it.
+TEST_P(CameraHidlTest, grfSMultiCameraTest) {
+    const int socGrfApi = property_get_int32("ro.board.first_api_level", /*default*/ -1);
+    if (socGrfApi < 31 /*S*/) {
+        // Non-GRF devices, or version < 31 Skip
+        ALOGI("%s: socGrfApi level is %d. Skipping", __FUNCTION__, socGrfApi);
+        return;
+    }
+
+    // Test that if more than one color cameras facing the same direction are
+    // supported, there must be at least one logical camera facing that
+    // direction.
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
+    // Front and back facing non-logical color cameras
+    std::set<std::string> frontColorCameras, rearColorCameras;
+    // Front and back facing logical cameras' physical camera Id sets
+    std::set<std::set<std::string>> frontPhysicalIds, rearPhysicalIds;
+    for (const auto& name : cameraDeviceNames) {
+        std::string cameraId;
+        int deviceVersion = getCameraDeviceVersionAndId(name, mProviderType, &cameraId);
+        switch (deviceVersion) {
+            case CAMERA_DEVICE_API_VERSION_3_7:
+            case CAMERA_DEVICE_API_VERSION_3_6:
+            case CAMERA_DEVICE_API_VERSION_3_5:
+            case CAMERA_DEVICE_API_VERSION_3_4:
+            case CAMERA_DEVICE_API_VERSION_3_3:
+            case CAMERA_DEVICE_API_VERSION_3_2: {
+                ::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice> device3_x;
+                ALOGI("getCameraCharacteristics: Testing camera device %s", name.c_str());
+                Return<void> ret;
+                ret = mProvider->getCameraDeviceInterface_V3_x(
+                        name, [&](auto status, const auto& device) {
+                            ALOGI("getCameraDeviceInterface_V3_x returns status:%d", (int)status);
+                            ASSERT_EQ(Status::OK, status);
+                            ASSERT_NE(device, nullptr);
+                            device3_x = device;
+                        });
+                ASSERT_TRUE(ret.isOk());
+
+                ret = device3_x->getCameraCharacteristics([&](auto status, const auto& chars) {
+                    ASSERT_EQ(Status::OK, status);
+                    const camera_metadata_t* metadata = (camera_metadata_t*)chars.data();
+
+                    // Skip if this is not a color camera.
+                    if (!CameraHidlTest::isColorCamera(metadata)) {
+                        return;
+                    }
+
+                    // Check camera facing. Skip if facing is neither FRONT
+                    // nor BACK. If this is not a logical camera, only note down
+                    // the camera ID, and skip.
+                    camera_metadata_ro_entry entry;
+                    int retcode = find_camera_metadata_ro_entry(
+                            metadata, ANDROID_LENS_FACING, &entry);
+                    ASSERT_EQ(retcode, 0);
+                    ASSERT_GT(entry.count, 0);
+                    uint8_t facing = entry.data.u8[0];
+                    bool isLogicalCamera = (isLogicalMultiCamera(metadata) == Status::OK);
+                    if (facing == ANDROID_LENS_FACING_FRONT) {
+                        if (!isLogicalCamera) {
+                            frontColorCameras.insert(cameraId);
+                            return;
+                        }
+                    } else if (facing == ANDROID_LENS_FACING_BACK) {
+                        if (!isLogicalCamera) {
+                            rearColorCameras.insert(cameraId);
+                            return;
+                        }
+                    } else {
+                        // Not FRONT or BACK facing. Skip.
+                        return;
+                    }
+
+                    // Check logical camera's physical camera IDs for color
+                    // cameras.
+                    std::unordered_set<std::string> physicalCameraIds;
+                    Status s = getPhysicalCameraIds(metadata, &physicalCameraIds);
+                    ASSERT_EQ(Status::OK, s);
+                    if (facing == ANDROID_LENS_FACING_FRONT) {
+                        frontPhysicalIds.emplace(physicalCameraIds.begin(), physicalCameraIds.end());
+                    } else {
+                        rearPhysicalIds.emplace(physicalCameraIds.begin(), physicalCameraIds.end());
+                    }
+                    for (const auto& physicalId : physicalCameraIds) {
+                        // Skip if the physicalId is publicly available
+                        for (auto& deviceName : cameraDeviceNames) {
+                            std::string publicVersion, publicId;
+                            ASSERT_TRUE(::matchDeviceName(deviceName, mProviderType,
+                                                          &publicVersion, &publicId));
+                            if (physicalId == publicId) {
+                                // Skip because public Ids will be iterated in outer loop.
+                                return;
+                            }
+                        }
+
+                        auto castResult = device::V3_5::ICameraDevice::castFrom(device3_x);
+                        ASSERT_TRUE(castResult.isOk());
+                        ::android::sp<::android::hardware::camera::device::V3_5::ICameraDevice>
+                                device3_5 = castResult;
+                        ASSERT_NE(device3_5, nullptr);
+
+                        // Check camera characteristics for hidden camera id
+                        Return<void> ret = device3_5->getPhysicalCameraCharacteristics(
+                                physicalId, [&](auto status, const auto& chars) {
+                            ASSERT_EQ(Status::OK, status);
+                            const camera_metadata_t* physicalMetadata =
+                                    (camera_metadata_t*)chars.data();
+
+                            if (CameraHidlTest::isColorCamera(physicalMetadata)) {
+                                if (facing == ANDROID_LENS_FACING_FRONT) {
+                                    frontColorCameras.insert(physicalId);
+                                } else if (facing == ANDROID_LENS_FACING_BACK) {
+                                    rearColorCameras.insert(physicalId);
+                                }
+                            }
+                        });
+                        ASSERT_TRUE(ret.isOk());
+                    }
+                });
+                ASSERT_TRUE(ret.isOk());
+            } break;
+            case CAMERA_DEVICE_API_VERSION_1_0: {
+                // Not applicable
+            } break;
+            default: {
+                ALOGE("%s: Unsupported device version %d", __func__, deviceVersion);
+                ADD_FAILURE();
+            } break;
+        }
+    }
+
+    // If there are more than one color cameras facing one direction, a logical
+    // multi-camera must be defined consisting of all color cameras facing that
+    // direction.
+    if (frontColorCameras.size() > 1) {
+        bool hasFrontLogical = false;
+        for (const auto& physicalIds : frontPhysicalIds) {
+            if (std::includes(physicalIds.begin(), physicalIds.end(),
+                    frontColorCameras.begin(), frontColorCameras.end())) {
+                hasFrontLogical = true;
+                break;
+            }
+        }
+        ASSERT_TRUE(hasFrontLogical);
+    }
+    if (rearColorCameras.size() > 1) {
+        bool hasRearLogical = false;
+        for (const auto& physicalIds : rearPhysicalIds) {
+            if (std::includes(physicalIds.begin(), physicalIds.end(),
+                    rearColorCameras.begin(), rearColorCameras.end())) {
+                hasRearLogical = true;
+                break;
+            }
+        }
+        ASSERT_TRUE(hasRearLogical);
+    }
+}
+
 // Retrieve all valid output stream resolutions from the camera
 // static characteristics.
 Status CameraHidlTest::getAvailableOutputStreams(const camera_metadata_t* staticMeta,
@@ -6651,6 +6818,23 @@
     return ret;
 }
 
+bool CameraHidlTest::isColorCamera(const camera_metadata_t *metadata) {
+    camera_metadata_ro_entry entry;
+    int retcode = find_camera_metadata_ro_entry(
+            metadata, ANDROID_REQUEST_AVAILABLE_CAPABILITIES, &entry);
+    if ((0 == retcode) && (entry.count > 0)) {
+        bool isBackwardCompatible = (std::find(entry.data.u8, entry.data.u8 + entry.count,
+                ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE) !=
+                entry.data.u8 + entry.count);
+        bool isMonochrome = (std::find(entry.data.u8, entry.data.u8 + entry.count,
+                ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME) !=
+                entry.data.u8 + entry.count);
+        bool isColor = isBackwardCompatible && !isMonochrome;
+        return isColor;
+    }
+    return false;
+}
+
 // Retrieve the reprocess input-output format map from the static
 // camera characteristics.
 Status CameraHidlTest::getZSLInputOutputMap(camera_metadata_t *staticMeta,
diff --git a/current.txt b/current.txt
index 8230852..9fdd81d 100644
--- a/current.txt
+++ b/current.txt
@@ -772,7 +772,7 @@
 e042522daa4b5f7fd4a0a19bcdadb93c79a1b04c09ef2c9813a3a8941032f3f5 android.hardware.contexthub@1.0::IContexthub
 c2f64133b83ede65c9939ef97ab5bd867b73faf3dba0e7e69f77c3c43d9e487e android.hardware.contexthub@1.0::IContexthubCallback
 bda492ec4021d13869de72bd6f8c15c5837b78d6136b8d538efec5320573a5ec android.hardware.gnss@1.0::IGnssMeasurementCallback
-6a271e493907e8ba20912e42771bd0d99ae45431a851d5675ef9496d02510a34 android.hardware.gnss@1.1::IGnssMeasurementCallback
+7ae2025662e30e690a3ffa1c65cc972c6297a68638174055c33cbf3d2e4bbddc android.hardware.gnss@1.1::IGnssMeasurementCallback
 11e9e1a1fd0c9b3d9648750d4b10dc2a839d3a6688904c3fc49500a4e7ca75b0 android.hardware.gnss@2.1::IGnssMeasurementCallback
 2c331a9605f3a08d9c1e0a36169ca57758bc43c11a78ef3f3730509885e52c15 android.hardware.graphics.composer@2.4::IComposerClient
 3da3ce039247872d95c6bd48621dbfdfa1c2d2a91a90f257862f87ee2bc46300 android.hardware.health@2.1::types
@@ -838,7 +838,7 @@
 1a1dff6e8d25dbc02a69fed3c077dd0782b30331ca3f345848ec52fc67744224 android.hardware.camera.device@3.7::ICameraDevice
 3be6faa3d11ad9c7ec01a1a0a009cf11cb65d701d109dab37613ce9cfb3cdd60 android.hardware.camera.device@3.7::ICameraDeviceSession
 3740ec773b2eb8fa6bd8c6e879eedb56c4e4306b88f1c20fa51103d791d871b1 android.hardware.camera.device@3.7::ICameraInjectionSession
-21f023685571daf46148097d98b89cea353f07e3ed83b2ed5685b23bd136c3ee android.hardware.camera.device@3.7::types
+d272697484c41bbf76a0924d2aaebf065ce37a822fcb438316eb5dd2d112f052 android.hardware.camera.device@3.7::types
 e932e7ef95210142e1fd3a4504e1d19bdb1acc988450f1ced543f3401f67855a android.hardware.camera.metadata@3.6::types
 98ff825a7d37e5ab983502d13cec1f2e5a9cac9b674b6ff1a52bcf540f4e315e android.hardware.camera.provider@2.7::ICameraProvider
 51fd14005859b16be55872660c34f5d423c77a2abcc5d4bdd5a537c40f32516b android.hardware.camera.provider@2.7::types
diff --git a/gnss/1.1/IGnssMeasurementCallback.hal b/gnss/1.1/IGnssMeasurementCallback.hal
index 36841ee..f94c67a 100644
--- a/gnss/1.1/IGnssMeasurementCallback.hal
+++ b/gnss/1.1/IGnssMeasurementCallback.hal
@@ -24,13 +24,38 @@
      * Flags indicating the Accumulated Delta Range's states.
      *
      * See the table below for a detailed interpretation of each state. This is
-     * a continuation of the table from 1.1/IGnssMeasurementCallback.hal.
+     * a continuation of the table from 1.0/IGnssMeasurementCallback.hal.
      *
      * +---------------------+-------------------+-----------------------------+
      * | ADR_STATE           | Time of relevance | Interpretation              |
      * +---------------------+-------------------+-----------------------------+
      * | HALF_CYCLE_RESOLVED | ADR(t)            | Half cycle ambiguity is     |
      * |                     |                   | resolved at time t.         |
+     * |                     |                   |                             |
+     * |                     |                   | For signals that have       |
+     * |                     |                   | databits, the carrier phase |
+     * |                     |                   | tracking loops typically    |
+     * |                     |                   | use a costas loop           |
+     * |                     |                   | discriminator. This type of |
+     * |                     |                   | tracking loop introduces a  |
+     * |                     |                   | half-cycle ambiguity that   |
+     * |                     |                   | is resolved by searching    |
+     * |                     |                   | through the received data   |
+     * |                     |                   | for known patterns of       |
+     * |                     |                   | databits (e.g. GPS uses the |
+     * |                     |                   | TLM word) which then        |
+     * |                     |                   | determines the polarity of  |
+     * |                     |                   | the incoming data and       |
+     * |                     |                   | resolves the half-cycle     |
+     * |                     |                   | ambiguity.                  |
+     * |                     |                   |                             |
+     * |                     |                   | Before the half-cycle       |
+     * |                     |                   | ambiguity has been resolved |
+     * |                     |                   | it is possible that the     |
+     * |                     |                   | ADR_STATE_VALID flag is     |
+     * |                     |                   | set, but the ADR_STATE_     |
+     * |                     |                   | HALF_CYCLE_RESOLVED flag is |
+     * |                     |                   | not set.                    |
      * +---------------------+-------------------+-----------------------------+
      */
     enum GnssAccumulatedDeltaRangeState
diff --git a/gnss/aidl/android/hardware/gnss/GnssMeasurement.aidl b/gnss/aidl/android/hardware/gnss/GnssMeasurement.aidl
index 58f29c5..efecddd 100644
--- a/gnss/aidl/android/hardware/gnss/GnssMeasurement.aidl
+++ b/gnss/aidl/android/hardware/gnss/GnssMeasurement.aidl
@@ -438,6 +438,31 @@
      * +---------------------+-------------------+-----------------------------+
      * | HALF_CYCLE_RESOLVED | ADR(t)            | Half cycle ambiguity is     |
      * |                     |                   | resolved at time t.         |
+     * |                     |                   |                             |
+     * |                     |                   | For signals that have       |
+     * |                     |                   | databits, the carrier phase |
+     * |                     |                   | tracking loops typically    |
+     * |                     |                   | use a costas loop           |
+     * |                     |                   | discriminator. This type of |
+     * |                     |                   | tracking loop introduces a  |
+     * |                     |                   | half-cycle ambiguity that   |
+     * |                     |                   | is resolved by searching    |
+     * |                     |                   | through the received data   |
+     * |                     |                   | for known patterns of       |
+     * |                     |                   | databits (e.g. GPS uses the |
+     * |                     |                   | TLM word) which then        |
+     * |                     |                   | determines the polarity of  |
+     * |                     |                   | the incoming data and       |
+     * |                     |                   | resolves the half-cycle     |
+     * |                     |                   | ambiguity.                  |
+     * |                     |                   |                             |
+     * |                     |                   | Before the half-cycle       |
+     * |                     |                   | ambiguity has been resolved |
+     * |                     |                   | it is possible that the     |
+     * |                     |                   | ADR_STATE_VALID flag is     |
+     * |                     |                   | set, but the ADR_STATE_     |
+     * |                     |                   | HALF_CYCLE_RESOLVED flag is |
+     * |                     |                   | not set.                    |
      * +---------------------+-------------------+-----------------------------+
      */
     const int ADR_STATE_UNKNOWN = 0;
diff --git a/graphics/composer/2.1/utils/vts/ComposerVts.cpp b/graphics/composer/2.1/utils/vts/ComposerVts.cpp
index 4b6b7c8..55aaf12 100644
--- a/graphics/composer/2.1/utils/vts/ComposerVts.cpp
+++ b/graphics/composer/2.1/utils/vts/ComposerVts.cpp
@@ -308,6 +308,12 @@
     writer->reset();
 }
 
+NativeHandleWrapper::~NativeHandleWrapper() {
+    if (mHandle) {
+        mGralloc.freeBuffer(mHandle);
+    }
+}
+
 Gralloc::Gralloc() {
     [this] {
         ASSERT_NO_FATAL_FAILURE(mGralloc4 = std::make_shared<Gralloc4>("default", "default",
@@ -324,9 +330,10 @@
     }();
 }
 
-const native_handle_t* Gralloc::allocate(uint32_t width, uint32_t height, uint32_t layerCount,
-                                         PixelFormat format, uint64_t usage, bool import,
-                                         uint32_t* outStride) {
+const NativeHandleWrapper Gralloc::allocate(uint32_t width, uint32_t height, uint32_t layerCount,
+                                            PixelFormat format, uint64_t usage, bool import,
+                                            uint32_t* outStride) {
+    const native_handle_t* handle;
     if (mGralloc4) {
         IMapper4::BufferDescriptorInfo info{};
         info.width = width;
@@ -334,7 +341,7 @@
         info.layerCount = layerCount;
         info.format = static_cast<android::hardware::graphics::common::V1_2::PixelFormat>(format);
         info.usage = usage;
-        return mGralloc4->allocate(info, import, outStride);
+        handle = mGralloc4->allocate(info, import, outStride);
     } else if (mGralloc3) {
         IMapper3::BufferDescriptorInfo info{};
         info.width = width;
@@ -342,7 +349,7 @@
         info.layerCount = layerCount;
         info.format = static_cast<android::hardware::graphics::common::V1_2::PixelFormat>(format);
         info.usage = usage;
-        return mGralloc3->allocate(info, import, outStride);
+        handle = mGralloc3->allocate(info, import, outStride);
     } else {
         IMapper2::BufferDescriptorInfo info{};
         info.width = width;
@@ -350,8 +357,9 @@
         info.layerCount = layerCount;
         info.format = format;
         info.usage = usage;
-        return mGralloc2->allocate(info, import, outStride);
+        handle = mGralloc2->allocate(info, import, outStride);
     }
+    return NativeHandleWrapper(*this, handle);
 }
 
 void* Gralloc::lock(const native_handle_t* bufferHandle, uint64_t cpuUsage,
diff --git a/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/ComposerVts.h b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/ComposerVts.h
index 63aa713..2949823 100644
--- a/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/ComposerVts.h
+++ b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/ComposerVts.h
@@ -136,13 +136,30 @@
     int32_t height;
 };
 
+class Gralloc;
+
+// RAII wrapper around native_handle_t*
+class NativeHandleWrapper {
+  public:
+    NativeHandleWrapper(Gralloc& gralloc, const native_handle_t* handle)
+        : mGralloc(gralloc), mHandle(handle) {}
+
+    ~NativeHandleWrapper();
+
+    const native_handle_t* get() { return mHandle; }
+
+  private:
+    Gralloc& mGralloc;
+    const native_handle_t* mHandle;
+};
+
 class Gralloc {
   public:
     explicit Gralloc();
 
-    const native_handle_t* allocate(uint32_t width, uint32_t height, uint32_t layerCount,
-                                    PixelFormat format, uint64_t usage, bool import = true,
-                                    uint32_t* outStride = nullptr);
+    const NativeHandleWrapper allocate(uint32_t width, uint32_t height, uint32_t layerCount,
+                                       PixelFormat format, uint64_t usage, bool import = true,
+                                       uint32_t* outStride = nullptr);
 
     void* lock(const native_handle_t* bufferHandle, uint64_t cpuUsage,
                const AccessRegion& accessRegionRect, int acquireFence);
diff --git a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
index f0250c0..4822678 100644
--- a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
+++ b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
@@ -666,7 +666,7 @@
         ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::TearDown());
     }
 
-    const native_handle_t* allocate() {
+    NativeHandleWrapper allocate() {
         uint64_t usage =
                 static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN |
                                       BufferUsage::COMPOSER_OVERLAY);
@@ -727,11 +727,11 @@
         display = mComposerClient->createVirtualDisplay(64, 64, PixelFormat::IMPLEMENTATION_DEFINED,
                                                         kBufferSlotCount, &format));
 
-    const native_handle_t* handle;
-    ASSERT_NO_FATAL_FAILURE(handle = allocate());
+    std::unique_ptr<NativeHandleWrapper> handle;
+    ASSERT_NO_FATAL_FAILURE(handle.reset(new NativeHandleWrapper(allocate())));
 
     mWriter->selectDisplay(display);
-    mWriter->setOutputBuffer(0, handle, -1);
+    mWriter->setOutputBuffer(0, handle->get(), -1);
     execute();
 }
 
@@ -783,7 +783,7 @@
     mComposerClient->setColorMode(mPrimaryDisplay, ColorMode::NATIVE);
 
     auto handle = allocate();
-    ASSERT_NE(nullptr, handle);
+    ASSERT_NE(nullptr, handle.get());
 
     IComposerClient::Rect displayFrame{0, 0, mDisplayWidth, mDisplayHeight};
 
@@ -800,7 +800,7 @@
     mWriter->setLayerZOrder(10);
     mWriter->setLayerBlendMode(IComposerClient::BlendMode::NONE);
     mWriter->setLayerSurfaceDamage(std::vector<IComposerClient::Rect>(1, displayFrame));
-    mWriter->setLayerBuffer(0, handle, -1);
+    mWriter->setLayerBuffer(0, handle.get(), -1);
     mWriter->setLayerDataspace(Dataspace::UNKNOWN);
 
     mWriter->validateDisplay();
@@ -817,8 +817,8 @@
 
     mWriter->selectLayer(layer);
     auto handle2 = allocate();
-    ASSERT_NE(nullptr, handle2);
-    mWriter->setLayerBuffer(0, handle2, -1);
+    ASSERT_NE(nullptr, handle2.get());
+    mWriter->setLayerBuffer(0, handle2.get(), -1);
     mWriter->setLayerSurfaceDamage(std::vector<IComposerClient::Rect>(1, {0, 0, 10, 10}));
     mWriter->presentDisplay();
     execute();
@@ -833,12 +833,12 @@
                                 mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
 
     auto handle = allocate();
-    ASSERT_NE(nullptr, handle);
+    ASSERT_NE(nullptr, handle.get());
     IComposerClient::Rect displayFrame{0, 0, mDisplayWidth, mDisplayHeight};
 
     mWriter->selectDisplay(mPrimaryDisplay);
     mWriter->selectLayer(layer);
-    mWriter->setLayerBuffer(0, handle, -1);
+    mWriter->setLayerBuffer(0, handle.get(), -1);
     mWriter->setLayerCompositionType(IComposerClient::Composition::CURSOR);
     mWriter->setLayerDisplayFrame(displayFrame);
     mWriter->setLayerPlaneAlpha(1);
@@ -871,7 +871,7 @@
  */
 TEST_P(GraphicsComposerHidlCommandTest, SET_LAYER_BUFFER) {
     auto handle = allocate();
-    ASSERT_NE(nullptr, handle);
+    ASSERT_NE(nullptr, handle.get());
 
     Layer layer;
     ASSERT_NO_FATAL_FAILURE(layer =
@@ -879,7 +879,7 @@
 
     mWriter->selectDisplay(mPrimaryDisplay);
     mWriter->selectLayer(layer);
-    mWriter->setLayerBuffer(0, handle, -1);
+    mWriter->setLayerBuffer(0, handle.get(), -1);
     execute();
 }
 
@@ -1003,7 +1003,7 @@
     }
 
     auto handle = allocate();
-    ASSERT_NE(nullptr, handle);
+    ASSERT_NE(nullptr, handle.get());
 
     Layer layer;
     ASSERT_NO_FATAL_FAILURE(layer =
@@ -1011,7 +1011,7 @@
 
     mWriter->selectDisplay(mPrimaryDisplay);
     mWriter->selectLayer(layer);
-    mWriter->setLayerSidebandStream(handle);
+    mWriter->setLayerSidebandStream(handle.get());
     execute();
 }
 
diff --git a/graphics/composer/2.2/utils/vts/ReadbackVts.cpp b/graphics/composer/2.2/utils/vts/ReadbackVts.cpp
index 19f5e8c..30596fc 100644
--- a/graphics/composer/2.2/utils/vts/ReadbackVts.cpp
+++ b/graphics/composer/2.2/utils/vts/ReadbackVts.cpp
@@ -208,22 +208,13 @@
     mAccessRegion.height = height;
 }
 
-ReadbackBuffer::~ReadbackBuffer() {
-    if (mBufferHandle != nullptr) {
-        mGralloc->freeBuffer(mBufferHandle);
-    }
-}
-
 void ReadbackBuffer::setReadbackBuffer() {
-    if (mBufferHandle != nullptr) {
-        mGralloc->freeBuffer(mBufferHandle);
-        mBufferHandle = nullptr;
-    }
-    mBufferHandle = mGralloc->allocate(mWidth, mHeight, mLayerCount, mFormat, mUsage,
-                                       /*import*/ true, &mStride);
-    ASSERT_NE(false, mGralloc->validateBufferSize(mBufferHandle, mWidth, mHeight, mLayerCount,
-                                                  mFormat, mUsage, mStride));
-    ASSERT_NO_FATAL_FAILURE(mComposerClient->setReadbackBuffer(mDisplay, mBufferHandle, -1));
+    mBufferHandle.reset(new Gralloc::NativeHandleWrapper(
+            mGralloc->allocate(mWidth, mHeight, mLayerCount, mFormat, mUsage,
+                               /*import*/ true, &mStride)));
+    ASSERT_NE(false, mGralloc->validateBufferSize(mBufferHandle->get(), mWidth, mHeight,
+                                                  mLayerCount, mFormat, mUsage, mStride));
+    ASSERT_NO_FATAL_FAILURE(mComposerClient->setReadbackBuffer(mDisplay, mBufferHandle->get(), -1));
 }
 
 void ReadbackBuffer::checkReadbackBuffer(std::vector<IComposerClient::Color> expectedColors) {
@@ -231,11 +222,11 @@
     int32_t fenceHandle;
     ASSERT_NO_FATAL_FAILURE(mComposerClient->getReadbackBufferFence(mDisplay, &fenceHandle));
 
-    void* bufData = mGralloc->lock(mBufferHandle, mUsage, mAccessRegion, fenceHandle);
+    void* bufData = mGralloc->lock(mBufferHandle->get(), mUsage, mAccessRegion, fenceHandle);
     ASSERT_TRUE(mPixelFormat == PixelFormat::RGB_888 || mPixelFormat == PixelFormat::RGBA_8888);
     ReadbackHelper::compareColorBuffers(expectedColors, bufData, mStride, mWidth, mHeight,
                                         mPixelFormat);
-    int32_t unlockFence = mGralloc->unlock(mBufferHandle);
+    int32_t unlockFence = mGralloc->unlock(mBufferHandle->get());
     if (unlockFence != -1) {
         sync_wait(unlockFence, -1);
         close(unlockFence);
@@ -281,23 +272,17 @@
     setSourceCrop({0, 0, (float)width, (float)height});
 }
 
-TestBufferLayer::~TestBufferLayer() {
-    if (mBufferHandle != nullptr) {
-        mGralloc->freeBuffer(mBufferHandle);
-    }
-}
-
 void TestBufferLayer::write(const std::shared_ptr<CommandWriterBase>& writer) {
     TestLayer::write(writer);
     writer->setLayerCompositionType(mComposition);
     writer->setLayerVisibleRegion(std::vector<IComposerClient::Rect>(1, mDisplayFrame));
-    if (mBufferHandle != nullptr) writer->setLayerBuffer(0, mBufferHandle, mFillFence);
+    if (mBufferHandle != nullptr) writer->setLayerBuffer(0, mBufferHandle->get(), mFillFence);
 }
 
 LayerSettings TestBufferLayer::toRenderEngineLayerSettings() {
     LayerSettings layerSettings = TestLayer::toRenderEngineLayerSettings();
     layerSettings.source.buffer.buffer = std::make_shared<renderengine::ExternalTexture>(
-            new GraphicBuffer(mBufferHandle, GraphicBuffer::CLONE_HANDLE, mWidth, mHeight,
+            new GraphicBuffer(mBufferHandle->get(), GraphicBuffer::CLONE_HANDLE, mWidth, mHeight,
                               static_cast<int32_t>(mFormat), 1, mUsage, mStride),
             mRenderEngine.getInternalRenderEngine(),
             renderengine::ExternalTexture::Usage::READABLE);
@@ -318,10 +303,10 @@
 }
 
 void TestBufferLayer::fillBuffer(std::vector<IComposerClient::Color> expectedColors) {
-    void* bufData = mGralloc->lock(mBufferHandle, mUsage, mAccessRegion, -1);
+    void* bufData = mGralloc->lock(mBufferHandle->get(), mUsage, mAccessRegion, -1);
     ASSERT_NO_FATAL_FAILURE(
             ReadbackHelper::fillBuffer(mWidth, mHeight, mStride, bufData, mFormat, expectedColors));
-    mFillFence = mGralloc->unlock(mBufferHandle);
+    mFillFence = mGralloc->unlock(mBufferHandle->get());
     if (mFillFence != -1) {
         sync_wait(mFillFence, -1);
         close(mFillFence);
@@ -329,16 +314,13 @@
 }
 
 void TestBufferLayer::setBuffer(std::vector<IComposerClient::Color> colors) {
-    if (mBufferHandle != nullptr) {
-        mGralloc->freeBuffer(mBufferHandle);
-        mBufferHandle = nullptr;
-    }
-    mBufferHandle = mGralloc->allocate(mWidth, mHeight, mLayerCount, mFormat, mUsage,
-                                       /*import*/ true, &mStride);
-    ASSERT_NE(nullptr, mBufferHandle);
+    mBufferHandle.reset(new Gralloc::NativeHandleWrapper(
+            mGralloc->allocate(mWidth, mHeight, mLayerCount, mFormat, mUsage,
+                               /*import*/ true, &mStride)));
+    ASSERT_NE(nullptr, mBufferHandle->get());
     ASSERT_NO_FATAL_FAILURE(fillBuffer(colors));
-    ASSERT_NE(false, mGralloc->validateBufferSize(mBufferHandle, mWidth, mHeight, mLayerCount,
-                                                  mFormat, mUsage, mStride));
+    ASSERT_NE(false, mGralloc->validateBufferSize(mBufferHandle->get(), mWidth, mHeight,
+                                                  mLayerCount, mFormat, mUsage, mStride));
 }
 
 void TestBufferLayer::setDataspace(Dataspace dataspace,
diff --git a/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h
index 6bc2732..d3bba17 100644
--- a/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h
+++ b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h
@@ -93,10 +93,12 @@
 
 class Gralloc : public V2_1::vts::Gralloc {
   public:
+    using NativeHandleWrapper = V2_1::vts::NativeHandleWrapper;
+
     Gralloc();
-    const native_handle_t* allocate(uint32_t width, uint32_t height, uint32_t layerCount,
-                                    PixelFormat format, uint64_t usage, bool import = true,
-                                    uint32_t* outStride = nullptr) {
+    const NativeHandleWrapper allocate(uint32_t width, uint32_t height, uint32_t layerCount,
+                                       PixelFormat format, uint64_t usage, bool import = true,
+                                       uint32_t* outStride = nullptr) {
         return V2_1::vts::Gralloc::allocate(
                 width, height, layerCount,
                 static_cast<android::hardware::graphics::common::V1_0::PixelFormat>(format), usage,
diff --git a/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ReadbackVts.h b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ReadbackVts.h
index b24e3b6..58efde9 100644
--- a/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ReadbackVts.h
+++ b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ReadbackVts.h
@@ -25,6 +25,8 @@
 #include <mapper-vts/2.1/MapperVts.h>
 #include <renderengine/RenderEngine.h>
 
+#include <memory>
+
 namespace android {
 namespace hardware {
 namespace graphics {
@@ -116,8 +118,6 @@
             PixelFormat format,
             IComposerClient::Composition composition = IComposerClient::Composition::DEVICE);
 
-    ~TestBufferLayer();
-
     void write(const std::shared_ptr<CommandWriterBase>& writer) override;
 
     LayerSettings toRenderEngineLayerSettings() override;
@@ -143,7 +143,7 @@
     std::shared_ptr<Gralloc> mGralloc;
     TestRenderEngine& mRenderEngine;
     int32_t mFillFence;
-    const native_handle_t* mBufferHandle = nullptr;
+    std::unique_ptr<Gralloc::NativeHandleWrapper> mBufferHandle;
 };
 
 class ReadbackHelper {
@@ -182,7 +182,6 @@
     ReadbackBuffer(Display display, const std::shared_ptr<ComposerClient>& client,
                    const std::shared_ptr<Gralloc>& gralloc, uint32_t width, uint32_t height,
                    PixelFormat pixelFormat, Dataspace dataspace);
-    ~ReadbackBuffer();
 
     void setReadbackBuffer();
 
@@ -196,7 +195,7 @@
     uint64_t mUsage;
     AccessRegion mAccessRegion;
     uint32_t mStride;
-    const native_handle_t* mBufferHandle = nullptr;
+    std::unique_ptr<Gralloc::NativeHandleWrapper> mBufferHandle = nullptr;
     PixelFormat mPixelFormat;
     Dataspace mDataspace;
     Display mDisplay;
diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp
index 8d52173..7a053f1 100644
--- a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp
+++ b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp
@@ -39,15 +39,13 @@
 namespace vts {
 namespace {
 
-using android::GraphicBuffer;
 using android::Rect;
-using android::hardware::hidl_handle;
 using common::V1_1::BufferUsage;
 using common::V1_1::Dataspace;
 using common::V1_1::PixelFormat;
-using mapper::V2_1::IMapper;
 using V2_1::Config;
 using V2_1::Display;
+using V2_1::vts::NativeHandleWrapper;
 using V2_1::vts::TestCommandReader;
 using vts::Gralloc;
 
@@ -355,9 +353,9 @@
         // This following buffer call should have no effect
         uint64_t usage =
                 static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN);
-        const native_handle_t* bufferHandle =
+        NativeHandleWrapper bufferHandle =
                 mGralloc->allocate(mDisplayWidth, mDisplayHeight, 1, PixelFormat::RGBA_8888, usage);
-        mWriter->setLayerBuffer(0, bufferHandle, -1);
+        mWriter->setLayerBuffer(0, bufferHandle.get(), -1);
 
         // expected color for each pixel
         std::vector<IComposerClient::Color> expectedColors(mDisplayWidth * mDisplayHeight);
@@ -460,29 +458,30 @@
                           << " pixel format: PixelFormat::RGBA_8888 dataspace: "
                           << ReadbackHelper::getDataspaceString(clientDataspace)
                           << " unsupported for display" << std::endl;
+                mReader->mCompositionChanges.clear();
                 continue;
             }
 
             // create client target buffer
             uint32_t clientStride;
-            const native_handle_t* clientBufferHandle =
+            NativeHandleWrapper clientBufferHandle =
                     mGralloc->allocate(layer->mWidth, layer->mHeight, layer->mLayerCount,
                                        clientFormat, clientUsage, /*import*/ true, &clientStride);
-            ASSERT_NE(nullptr, clientBufferHandle);
+            ASSERT_NE(nullptr, clientBufferHandle.get());
 
             void* clientBufData =
-                    mGralloc->lock(clientBufferHandle, clientUsage, layer->mAccessRegion, -1);
+                    mGralloc->lock(clientBufferHandle.get(), clientUsage, layer->mAccessRegion, -1);
 
             ASSERT_NO_FATAL_FAILURE(ReadbackHelper::fillBuffer(layer->mWidth, layer->mHeight,
                                                                clientStride, clientBufData,
                                                                clientFormat, expectedColors));
-            int clientFence = mGralloc->unlock(clientBufferHandle);
+            int clientFence = mGralloc->unlock(clientBufferHandle.get());
             if (clientFence != -1) {
                 sync_wait(clientFence, -1);
                 close(clientFence);
             }
 
-            mWriter->setClientTarget(0, clientBufferHandle, clientFence, clientDataspace,
+            mWriter->setClientTarget(0, clientBufferHandle.get(), clientFence, clientDataspace,
                                      std::vector<IComposerClient::Rect>(1, damage));
 
             layer->setToClientComposition(mWriter);
@@ -593,12 +592,12 @@
         // create client target buffer
         ASSERT_EQ(1, mReader->mCompositionChanges[0].second);
         uint32_t clientStride;
-        const native_handle_t* clientBufferHandle =
+        NativeHandleWrapper clientBufferHandle =
                 mGralloc->allocate(mDisplayWidth, mDisplayHeight, clientLayer->mLayerCount,
                                    clientFormat, clientUsage, /*import*/ true, &clientStride);
-        ASSERT_NE(nullptr, clientBufferHandle);
+        ASSERT_NE(nullptr, clientBufferHandle.get());
 
-        void* clientBufData = mGralloc->lock(clientBufferHandle, clientUsage,
+        void* clientBufData = mGralloc->lock(clientBufferHandle.get(), clientUsage,
                                              {0, 0, mDisplayWidth, mDisplayHeight}, -1);
 
         std::vector<IComposerClient::Color> clientColors(mDisplayWidth * mDisplayHeight);
@@ -606,13 +605,13 @@
         ASSERT_NO_FATAL_FAILURE(ReadbackHelper::fillBuffer(mDisplayWidth, mDisplayHeight,
                                                            clientStride, clientBufData,
                                                            clientFormat, clientColors));
-        int clientFence = mGralloc->unlock(clientBufferHandle);
+        int clientFence = mGralloc->unlock(clientBufferHandle.get());
         if (clientFence != -1) {
             sync_wait(clientFence, -1);
             close(clientFence);
         }
 
-        mWriter->setClientTarget(0, clientBufferHandle, clientFence, clientDataspace,
+        mWriter->setClientTarget(0, clientBufferHandle.get(), clientFence, clientDataspace,
                                  std::vector<IComposerClient::Rect>(1, clientFrame));
         clientLayer->setToClientComposition(mWriter);
         mWriter->validateDisplay();
diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
index 31ec885..7e25a2e 100644
--- a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
+++ b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
@@ -36,13 +36,11 @@
 namespace {
 
 using common::V1_0::BufferUsage;
-using common::V1_0::ColorTransform;
-using common::V1_0::Transform;
 using common::V1_1::ColorMode;
 using common::V1_1::Dataspace;
 using common::V1_1::PixelFormat;
 using common::V1_1::RenderIntent;
-using mapper::V2_0::IMapper;
+using V2_1::vts::NativeHandleWrapper;
 
 class GraphicsComposerHidlTest : public ::testing::TestWithParam<std::string> {
   protected:
@@ -154,7 +152,7 @@
         ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::TearDown());
     }
 
-    const native_handle_t* allocate() {
+    NativeHandleWrapper allocate() {
         uint64_t usage =
                 static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN);
         return mGralloc->allocate(/*width*/ 64, /*height*/ 64, /*layerCount*/ 1,
@@ -440,12 +438,12 @@
             static_cast<uint64_t>(BufferUsage::COMPOSER_OVERLAY | BufferUsage::CPU_READ_OFTEN);
 
     std::unique_ptr<Gralloc> gralloc;
-    const native_handle_t* buffer;
+    std::unique_ptr<NativeHandleWrapper> buffer;
     ASSERT_NO_FATAL_FAILURE(gralloc = std::make_unique<Gralloc>());
-    ASSERT_NO_FATAL_FAILURE(buffer = gralloc->allocate(mDisplayWidth, mDisplayHeight, 1,
-                                                       mReadbackPixelFormat, usage));
+    ASSERT_NO_FATAL_FAILURE(buffer.reset(new NativeHandleWrapper(
+            gralloc->allocate(mDisplayWidth, mDisplayHeight, 1, mReadbackPixelFormat, usage))));
 
-    mComposerClient->setReadbackBuffer(mPrimaryDisplay, buffer, -1);
+    mComposerClient->setReadbackBuffer(mPrimaryDisplay, buffer->get(), -1);
 }
 
 /**
@@ -463,12 +461,13 @@
             static_cast<uint64_t>(BufferUsage::COMPOSER_OVERLAY | BufferUsage::CPU_READ_OFTEN);
 
     std::unique_ptr<Gralloc> gralloc;
-    const native_handle_t* buffer;
+    std::unique_ptr<NativeHandleWrapper> buffer;
     ASSERT_NO_FATAL_FAILURE(gralloc = std::make_unique<Gralloc>());
-    ASSERT_NO_FATAL_FAILURE(buffer = gralloc->allocate(mDisplayWidth, mDisplayHeight, 1,
-                                                       mReadbackPixelFormat, usage));
+    ASSERT_NO_FATAL_FAILURE(buffer.reset(new NativeHandleWrapper(
+            gralloc->allocate(mDisplayWidth, mDisplayHeight, 1, mReadbackPixelFormat, usage))));
 
-    Error error = mComposerClient->getRaw()->setReadbackBuffer(mInvalidDisplayId, buffer, nullptr);
+    Error error =
+            mComposerClient->getRaw()->setReadbackBuffer(mInvalidDisplayId, buffer->get(), nullptr);
     ASSERT_EQ(Error::BAD_DISPLAY, error);
 }
 
diff --git a/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp b/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp
index 8b42654..54ba79d 100644
--- a/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp
+++ b/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp
@@ -38,12 +38,10 @@
 namespace vts {
 namespace {
 
-using common::V1_0::BufferUsage;
 using common::V1_1::RenderIntent;
 using common::V1_2::ColorMode;
 using common::V1_2::Dataspace;
 using common::V1_2::PixelFormat;
-using mapper::V2_0::IMapper;
 using V2_2::vts::Gralloc;
 
 class GraphicsComposerHidlTest : public ::testing::TestWithParam<std::string> {
@@ -140,12 +138,6 @@
         ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::TearDown());
     }
 
-    const native_handle_t* allocate() {
-        return mGralloc->allocate(
-                64, 64, 1, static_cast<common::V1_1::PixelFormat>(PixelFormat::RGBA_8888),
-                static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN));
-    }
-
     void execute() { mComposerClient->execute(mReader.get(), mWriter.get()); }
 
     std::unique_ptr<CommandWriterBase> mWriter;
diff --git a/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp b/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp
index 2f0429c..5aceda7 100644
--- a/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp
+++ b/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp
@@ -52,8 +52,8 @@
 using common::V1_2::ColorMode;
 using common::V1_2::Dataspace;
 using common::V1_2::PixelFormat;
-using mapper::V2_0::IMapper;
 using V2_1::Layer;
+using V2_1::vts::NativeHandleWrapper;
 using V2_2::Transform;
 using V2_2::vts::Gralloc;
 
@@ -159,7 +159,7 @@
 
     void execute() { mComposerClient->execute(mReader.get(), mWriter.get()); }
 
-    const native_handle_t* allocate(int32_t width, int32_t height) {
+    NativeHandleWrapper allocate(int32_t width, int32_t height) {
         return mGralloc->allocate(
                 width, height, /*layerCount*/ 1,
                 static_cast<common::V1_1::PixelFormat>(PixelFormat::RGBA_8888),
@@ -493,46 +493,53 @@
     IComposerClient::FRect displayCrop = display.getCrop();
     int32_t displayWidth = static_cast<int32_t>(std::ceilf(displayCrop.right - displayCrop.left));
     int32_t displayHeight = static_cast<int32_t>(std::ceilf(displayCrop.bottom - displayCrop.top));
-    auto handle = allocate(displayWidth, displayHeight);
-    ASSERT_NE(nullptr, handle);
-
     Layer layer;
     ASSERT_NO_FATAL_FAILURE(layer = mComposerClient->createLayer(display.get(), kBufferSlotCount));
-    mWriter->selectLayer(layer);
-    mWriter->setLayerCompositionType(IComposerClient::Composition::DEVICE);
-    mWriter->setLayerDisplayFrame(display.getFrameRect());
-    mWriter->setLayerPlaneAlpha(1);
-    mWriter->setLayerSourceCrop(display.getCrop());
-    mWriter->setLayerTransform(static_cast<Transform>(0));
-    mWriter->setLayerVisibleRegion(std::vector<IComposerClient::Rect>(1, display.getFrameRect()));
-    mWriter->setLayerZOrder(10);
-    mWriter->setLayerBlendMode(IComposerClient::BlendMode::NONE);
-    mWriter->setLayerSurfaceDamage(std::vector<IComposerClient::Rect>(1, display.getFrameRect()));
-    mWriter->setLayerBuffer(0, handle, -1);
-    mWriter->setLayerDataspace(Dataspace::UNKNOWN);
 
-    mWriter->validateDisplay();
-    execute();
-    ASSERT_EQ(0, mReader->mErrors.size());
-    mReader->mCompositionChanges.clear();
+    {
+        auto handle = allocate(displayWidth, displayHeight);
+        ASSERT_NE(nullptr, handle.get());
 
-    mWriter->presentDisplay();
-    execute();
-    ASSERT_EQ(0, mReader->mErrors.size());
+        mWriter->selectLayer(layer);
+        mWriter->setLayerCompositionType(IComposerClient::Composition::DEVICE);
+        mWriter->setLayerDisplayFrame(display.getFrameRect());
+        mWriter->setLayerPlaneAlpha(1);
+        mWriter->setLayerSourceCrop(display.getCrop());
+        mWriter->setLayerTransform(static_cast<Transform>(0));
+        mWriter->setLayerVisibleRegion(
+                std::vector<IComposerClient::Rect>(1, display.getFrameRect()));
+        mWriter->setLayerZOrder(10);
+        mWriter->setLayerBlendMode(IComposerClient::BlendMode::NONE);
+        mWriter->setLayerSurfaceDamage(
+                std::vector<IComposerClient::Rect>(1, display.getFrameRect()));
+        mWriter->setLayerBuffer(0, handle.get(), -1);
+        mWriter->setLayerDataspace(Dataspace::UNKNOWN);
 
-    mWriter->selectLayer(layer);
-    auto handle2 = allocate(displayWidth, displayHeight);
-    ASSERT_NE(nullptr, handle2);
+        mWriter->validateDisplay();
+        execute();
+        ASSERT_EQ(0, mReader->mErrors.size());
+        mReader->mCompositionChanges.clear();
 
-    mWriter->setLayerBuffer(0, handle2, -1);
-    mWriter->setLayerSurfaceDamage(std::vector<IComposerClient::Rect>(1, {0, 0, 10, 10}));
-    mWriter->validateDisplay();
-    execute();
-    ASSERT_EQ(0, mReader->mErrors.size());
-    mReader->mCompositionChanges.clear();
+        mWriter->presentDisplay();
+        execute();
+        ASSERT_EQ(0, mReader->mErrors.size());
+    }
 
-    mWriter->presentDisplay();
-    execute();
+    {
+        auto handle = allocate(displayWidth, displayHeight);
+        ASSERT_NE(nullptr, handle.get());
+
+        mWriter->selectLayer(layer);
+        mWriter->setLayerBuffer(0, handle.get(), -1);
+        mWriter->setLayerSurfaceDamage(std::vector<IComposerClient::Rect>(1, {0, 0, 10, 10}));
+        mWriter->validateDisplay();
+        execute();
+        ASSERT_EQ(0, mReader->mErrors.size());
+        mReader->mCompositionChanges.clear();
+
+        mWriter->presentDisplay();
+        execute();
+    }
 
     ASSERT_NO_FATAL_FAILURE(mComposerClient->destroyLayer(display.get(), layer));
 }
diff --git a/memtrack/aidl/android/hardware/memtrack/IMemtrack.aidl b/memtrack/aidl/android/hardware/memtrack/IMemtrack.aidl
index e78d4d7..13c3389 100644
--- a/memtrack/aidl/android/hardware/memtrack/IMemtrack.aidl
+++ b/memtrack/aidl/android/hardware/memtrack/IMemtrack.aidl
@@ -31,12 +31,14 @@
  * accounting for stride, bit depth, rounding up to page size, etc.
  *
  * The following getMemory() categories are important for memory accounting in
- * `dumpsys meminfo` and should be reported as described below:
+ * Android frameworks (e.g. `dumpsys meminfo`) and should be reported as described
+ * below:
  *
  * - MemtrackType::GRAPHICS and MemtrackRecord::FLAG_SMAPS_UNACCOUNTED
- *     This should report the PSS of all DMA buffers mapped by the process
- *     with the specified PID. This PSS can be calculated using ReadDmaBufPss()
- *     form libdmabufinfo.
+ *     This should report the PSS of all CPU-Mapped DMA-BUFs (buffers mapped into
+ *     the process address space) and all GPU-Mapped DMA-BUFs (buffers mapped into
+ *     the GPU device address space on behalf of the process), removing any overlap
+ *     between the CPU-mapped and GPU-mapped sets.
  *
  * - MemtrackType::GL and MemtrackRecord::FLAG_SMAPS_UNACCOUNTED
  *     This category should report all GPU private allocations for the specified
@@ -46,6 +48,10 @@
  *     Any other memory not accounted for in /proc/<pid>/smaps if any, otherwise
  *     this should return 0.
  *
+ * SMAPS_UNACCOUNTED memory should also include memory that is mapped with
+ * VM_PFNMAP flag set. For these mappings PSS and RSS are reported as 0 in smaps.
+ * Such mappings have no backing page structs from which PSS/RSS can be calculated.
+ *
  * Constructor for the interface should be used to perform memtrack management
  * setup actions and must be called once before any calls to getMemory().
  */
diff --git a/neuralnetworks/aidl/utils/src/Device.cpp b/neuralnetworks/aidl/utils/src/Device.cpp
index 0fd453b..e80de0b 100644
--- a/neuralnetworks/aidl/utils/src/Device.cpp
+++ b/neuralnetworks/aidl/utils/src/Device.cpp
@@ -119,7 +119,7 @@
                           << numberOfCacheFiles.numDataCache << " vs " << nn::kMaxNumberOfCacheFiles
                           << ")";
     }
-    return std::make_pair(numberOfCacheFiles.numDataCache, numberOfCacheFiles.numModelCache);
+    return std::make_pair(numberOfCacheFiles.numModelCache, numberOfCacheFiles.numDataCache);
 }
 
 }  // namespace
diff --git a/neuralnetworks/aidl/utils/test/DeviceTest.cpp b/neuralnetworks/aidl/utils/test/DeviceTest.cpp
index e53b0a8..f121aca 100644
--- a/neuralnetworks/aidl/utils/test/DeviceTest.cpp
+++ b/neuralnetworks/aidl/utils/test/DeviceTest.cpp
@@ -58,7 +58,7 @@
 const std::shared_ptr<BnDevice> kInvalidDevice;
 constexpr PerformanceInfo kNoPerformanceInfo = {.execTime = std::numeric_limits<float>::max(),
                                                 .powerUsage = std::numeric_limits<float>::max()};
-constexpr NumberOfCacheFiles kNumberOfCacheFiles = {.numModelCache = nn::kMaxNumberOfCacheFiles,
+constexpr NumberOfCacheFiles kNumberOfCacheFiles = {.numModelCache = nn::kMaxNumberOfCacheFiles - 1,
                                                     .numDataCache = nn::kMaxNumberOfCacheFiles};
 
 constexpr auto makeStatusOk = [] { return ndk::ScopedAStatus::ok(); };
@@ -300,6 +300,21 @@
     EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
 }
 
+TEST(DeviceTest, getNumberOfCacheFilesNeeded) {
+    // setup call
+    const auto mockDevice = createMockDevice();
+    EXPECT_CALL(*mockDevice, getNumberOfCacheFilesNeeded(_)).Times(1);
+
+    // run test
+    const auto result = Device::create(kName, mockDevice);
+
+    // verify result
+    ASSERT_TRUE(result.has_value());
+    constexpr auto kNumberOfCacheFilesPair = std::make_pair<uint32_t, uint32_t>(
+            kNumberOfCacheFiles.numModelCache, kNumberOfCacheFiles.numDataCache);
+    EXPECT_EQ(result.value()->getNumberOfCacheFilesNeeded(), kNumberOfCacheFilesPair);
+}
+
 TEST(DeviceTest, getNumberOfCacheFilesNeededError) {
     // setup call
     const auto mockDevice = createMockDevice();
diff --git a/security/keymint/aidl/android/hardware/security/keymint/DeviceInfo.aidl b/security/keymint/aidl/android/hardware/security/keymint/DeviceInfo.aidl
index 3ea14a1..b0761bf 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/DeviceInfo.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/DeviceInfo.aidl
@@ -37,10 +37,19 @@
      *         ? "board" : tstr,
      *         ? "vb_state" : "green" / "yellow" / "orange",    // Taken from the AVB values
      *         ? "bootloader_state" : "locked" / "unlocked",    // Taken from the AVB values
+     *         ? "vbmeta_digest": bstr,                         // Taken from the AVB values
      *         ? "os_version" : tstr,                    // Same as android.os.Build.VERSION.release
      *         ? "system_patch_level" : uint,                   // YYYYMMDD
      *         ? "boot_patch_level" : uint,                     // YYYYMMDD
      *         ? "vendor_patch_level" : uint,                   // YYYYMMDD
+     *         "version" : 1,                      // The CDDL schema version.
+     *         "security_level" : "tee" / "strongbox"
+     *         "att_id_state": "locked" / "open",  // Attestation IDs State. If "locked", this
+     *                                             // indicates a device's attestable IDs are
+     *                                             // factory-locked and immutable. If "open",
+     *                                             // this indicates the device is still in a
+     *                                             // provisionable state and the attestable IDs
+     *                                             // are not yet frozen.
      *     }
      */
     byte[] deviceInfo;
diff --git a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
index 9cc795d..2241735 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
@@ -277,6 +277,10 @@
      *   must return ErrorCode::INVALID_ARGUMENT.  The values 3 and 65537 must be supported.  It is
      *   recommended to support all prime values up to 2^64.
      *
+     * o Tag::CERTIFICATE_NOT_BEFORE and Tag::CERTIFICATE_NOT_AFTER specify the valid date range for
+     *   the returned X.509 certificate holding the public key. If omitted, generateKey must return
+     *   ErrorCode::MISSING_NOT_BEFORE or ErrorCode::MISSING_NOT_AFTER.
+     *
      * The following parameters are not necessary to generate a usable RSA key, but generateKey must
      * not return an error if they are omitted:
      *
@@ -297,6 +301,10 @@
      * Tag::EC_CURVE must be provided to generate an ECDSA key.  If it is not provided, generateKey
      * must return ErrorCode::UNSUPPORTED_KEY_SIZE. TEE IKeyMintDevice implementations must support
      * all curves.  StrongBox implementations must support P_256.
+
+     * Tag::CERTIFICATE_NOT_BEFORE and Tag::CERTIFICATE_NOT_AFTER must be provided to specify the
+     * valid date range for the returned X.509 certificate holding the public key. If omitted,
+     * generateKey must return ErrorCode::MISSING_NOT_BEFORE or ErrorCode::MISSING_NOT_AFTER.
      *
      * == AES Keys ==
      *
@@ -805,9 +813,10 @@
     byte[] convertStorageKeyToEphemeral(in byte[] storageKeyBlob);
 
     /**
-     * Returns parameters associated with the provided key. This should match the
-     * KeyCharacteristics present in the KeyCreationResult returned by generateKey(),
-     * importKey(), or importWrappedKey().
+     * Returns KeyMint-enforced parameters associated with the provided key. The returned tags are
+     * a subset of KeyCharacteristics found in the KeyCreationResult returned by generateKey(),
+     * importKey(), or importWrappedKey(). The returned value is a subset, as it does not include
+     * any Keystore-enforced parameters.
      *
      * @param keyBlob The opaque descriptor returned by generateKey, importKey or importWrappedKey.
      *
diff --git a/security/keymint/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl b/security/keymint/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
index 04d91d0..a29fb08 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
@@ -33,8 +33,8 @@
  *
  * The root of trust for secure provisioning is something called the "Boot Certificate Chain", or
  * BCC. The BCC is a chain of public key certificates, represented as COSE_Sign1 objects containing
- * COSE_Key representations of the public keys. The "root" of the BCC is a self-signed certificate
- * for a device-unique public key, denoted DK_pub. All public keys in the BCC are device-unique. The
+ * COSE_Key representations of the public keys. The "root" of the BCC is
+ * a device-unique public key, denoted DK_pub. All public keys in the BCC are device-unique. The
  * public key from each certificate in the chain is used to sign the next certificate in the
  * chain. The final, "leaf" certificate contains a public key, denoted KM_pub, whose corresponding
  * private key, denoted KM_priv, is available for use by the IRemotelyProvisionedComponent.
@@ -58,12 +58,8 @@
  * (given the necessary input), but no stage can compute the secret of any preceding stage. Updating
  * the firmware or configuration of any stage changes the key pair of that stage, and of all
  * subsequent stages, and no attacker who compromised the previous version of the updated firmware
- * can know or predict the post-update key pairs.
- *
- * The first BCC certificate is special because its contained public key, DK_pub, will never change,
- * making it a permanent, device-unique identifier. Although the remaining keys in the BCC are also
- * device-unique, they are not necessarily permanent, since they can change when the device software
- * is updated.
+ * can know or predict the post-update key pairs. It is recommended and expected that the BCC is
+ * constructed using the Open Profile for DICE.
  *
  * When the provisioning server receives a message signed by KM_priv and containing a BCC that
  * chains from DK_pub to KM_pub, it can be certain that (barring vulnerabilities in some boot
@@ -78,7 +74,7 @@
  * While a proper BCC, as described above, reflects the complete boot sequence from boot ROM to the
  * secure area image of the IRemotelyProvisionedComponent, it's also possible to use a "degenerate"
  * BCC which consists only of a single, self-signed certificate containing the public key of a
- * hardware-bound key pair. This is an appropriate solution for devices which haven't implemented
+ * hardware-bound key pair. This is an appopriate solution for devices which haven't implemented
  * everything necessary to produce a proper BCC, but can derive a unique key pair in the secure
  * area.  In this degenerate case, DK_pub is the same as KM_pub.
  *
@@ -141,7 +137,7 @@
      *        privateKeyHandle, that the contained public key is for remote certification.
      *
      * @return data representing a handle to the private key. The format is implementation-defined,
-     *         but note that specific services may define a required format.
+     *         but note that specific services may define a required format. KeyMint does.
      */
     byte[] generateEcdsaP256KeyPair(in boolean testMode, out MacedPublicKey macedPublicKey);
 
@@ -162,65 +158,90 @@
      *        If testMode is false, the keysToCertify array must not contain any keys flagged as
      *        test keys. Otherwise, the method must return STATUS_TEST_KEY_IN_PRODUCTION_REQUEST.
      *
-     * @param in endpointEncryptionKey contains an X25519 public key which will be used to encrypt
+     * @param in endpointEncryptionKey contains an X22519 public key which will be used to encrypt
      *        the BCC. For flexibility, this is represented as a certificate chain, represented as a
      *        CBOR array of COSE_Sign1 objects, ordered from root to leaf. The leaf contains the
      *        X25519 encryption key, each other element is an Ed25519 key signing the next in the
-     *        chain. The root is self-signed.
+     *        chain. The root is self-signed. An implementor may also choose to use P256 as an
+     *        alternative curve for signing and encryption instead of Curve 25519.
      *
      *            EekChain = [ + SignedSignatureKey, SignedEek ]
      *
      *            SignedSignatureKey = [              // COSE_Sign1
      *                protected: bstr .cbor {
-     *                    1 : -8,                     // Algorithm : EdDSA
+     *                    1 : AlgorithmEdDSA / AlgorithmES256,  // Algorithm
      *                },
-     *                unprotected: { },
-     *                payload: bstr .cbor SignatureKey,
-     *                signature: bstr PureEd25519(.cbor SignatureKeySignatureInput)
+     *                unprotected: {},
+     *                payload: bstr .cbor SignatureKeyEd25519 /
+     *                         bstr .cbor SignatureKeyP256,
+     *                signature: bstr PureEd25519(.cbor SignatureKeySignatureInput) /
+     *                           bstr ECDSA(.cbor SignatureKeySignatureInput)
      *            ]
      *
-     *            SignatureKey = {                    // COSE_Key
+     *            SignatureKeyEd25519 = {                    // COSE_Key
      *                 1 : 1,                         // Key type : Octet Key Pair
-     *                 3 : -8,                        // Algorithm : EdDSA
+     *                 3 : AlgorithmEdDSA,            // Algorithm
      *                 -1 : 6,                        // Curve : Ed25519
      *                 -2 : bstr                      // Ed25519 public key
      *            }
      *
+     *            SignatureKeyP256 = {
+     *                 1 : 2,                         // Key type : EC2
+     *                 3 : AlgorithmES256,            // Algorithm
+     *                 -1 : 1,                        // Curve: P256
+     *                 -2 : bstr,                     // X coordinate
+     *                 -3 : bstr                      // Y coordinate
+     *            }
+     *
      *            SignatureKeySignatureInput = [
      *                context: "Signature1",
      *                body_protected: bstr .cbor {
-     *                    1 : -8,                     // Algorithm : EdDSA
+     *                    1 : AlgorithmEdDSA / AlgorithmES256,     // Algorithm
      *                },
      *                external_aad: bstr .size 0,
-     *                payload: bstr .cbor SignatureKey
+     *                payload: bstr .cbor SignatureKeyEd25519 /
+     *                         bstr .cbor SignatureKeyP256
      *            ]
      *
      *            SignedEek = [                       // COSE_Sign1
      *                protected: bstr .cbor {
-     *                    1 : -8,                     // Algorithm : EdDSA
+     *                    1 : AlgorithmEdDSA / AlgorithmES256,  // Algorithm
      *                },
-     *                unprotected: { },
-     *                payload: bstr .cbor Eek,
-     *                signature: bstr PureEd25519(.cbor EekSignatureInput)
+     *                unprotected: {},
+     *                payload: bstr .cbor EekX25519 / .cbor EekP256,
+     *                signature: bstr PureEd25519(.cbor EekSignatureInput) /
+     *                           bstr ECDSA(.cbor EekSignatureInput)
      *            ]
      *
-     *            Eek = {                             // COSE_Key
-     *                1 : 1,                          // Key type : Octet Key Pair
-     *                2 : bstr                        // KID : EEK ID
-     *                3 : -25,                        // Algorithm : ECDH-ES + HKDF-256
-     *                -1 : 4,                         // Curve : X25519
-     *                -2 : bstr                       // X25519 public key
+     *            EekX25519 = {            // COSE_Key
+     *                1 : 1,               // Key type : Octet Key Pair
+     *                2 : bstr             // KID : EEK ID
+     *                3 : -25,             // Algorithm : ECDH-ES + HKDF-256
+     *                -1 : 4,              // Curve : X25519
+     *                -2 : bstr            // Ed25519 public key
+     *            }
+     *
+     *            EekP256 = {              // COSE_Key
+     *                1 : 2,               // Key type : EC2
+     *                2 : bstr             // KID : EEK ID
+     *                3 : -25,             // Algorithm : ECDH-ES + HKDF-256
+     *                -1 : 1,              // Curve : P256
+     *                -2 : bstr            // Sender X coordinate
+     *                -3 : bstr            // Sender Y coordinate
      *            }
      *
      *            EekSignatureInput = [
      *                context: "Signature1",
      *                body_protected: bstr .cbor {
-     *                    1 : -8,                     // Algorithm : EdDSA
+     *                    1 : AlgorithmEdDSA / AlgorithmES256,     // Algorithm
      *                },
      *                external_aad: bstr .size 0,
-     *                payload: bstr .cbor Eek
+     *                payload: bstr .cbor EekX25519 / .cbor EekP256
      *            ]
      *
+     *            AlgorithmES256 = -7
+     *            AlgorithmEdDSA = -8
+     *
      *        If the contents of endpointEncryptionKey do not match the SignedEek structure above,
      *        the method must return STATUS_INVALID_EEK.
      *
@@ -228,7 +249,7 @@
      *        in the chain, which implies that it must not attempt to validate the signature.
      *
      *        If testMode is false, the method must validate the chain signatures, and must verify
-     *        that the public key in the root certificate is in its pre-configured set of
+     *        that the public key in the root certifictate is in its pre-configured set of
      *        authorized EEK root keys. If the public key is not in the database, or if signature
      *        verification fails, the method must return STATUS_INVALID_EEK.
      *
@@ -236,8 +257,13 @@
      *        by the secure area. See the description of the 'signature' output parameter for
      *        details.
      *
-     * @param out keysToSignMac contains the MAC of KeysToSign in the CertificateRequest
-     *        structure. Specifically, it contains:
+     * @param out DeviceInfo contains the VerifiedDeviceInfo portion of the DeviceInfo array in
+     *        CertificateRequest. The structure is described within the DeviceInfo.aidl file.
+     *
+     * @param out ProtectedData contains the encrypted BCC and the ephemeral MAC key used to
+     *        authenticate the keysToSign (see keysToSignMac output argument).
+     *
+     * @return The of KeysToSign in the CertificateRequest structure. Specifically, it contains:
      *
      *            HMAC-256(EK_mac, .cbor KeysToMacStructure)
      *
@@ -248,11 +274,11 @@
      *                protected : bstr .cbor {
      *                    1 : 5,                           // Algorithm : HMAC-256
      *                },
-     *                unprotected : { },
+     *                unprotected : {},
      *                // Payload is PublicKeys from keysToSign argument, in provided order.
      *                payload: bstr .cbor [ * PublicKey ],
      *                tag: bstr
-     *           ]
+     *            ]
      *
      *            KeysToMacStructure = [
      *                context : "MAC0",
@@ -261,9 +287,6 @@
      *                // Payload is PublicKeys from keysToSign argument, in provided order.
      *                payload : bstr .cbor [ * PublicKey ]
      *            ]
-     *
-     * @param out ProtectedData contains the encrypted BCC and the ephemeral MAC key used to
-     *        authenticate the keysToSign (see keysToSignMac output argument).
      */
     byte[] generateCertificateRequest(in boolean testMode, in MacedPublicKey[] keysToSign,
             in byte[] endpointEncryptionCertChain, in byte[] challenge, out DeviceInfo deviceInfo,
diff --git a/security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl b/security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl
index 5199062..24cdbc1 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl
@@ -40,11 +40,7 @@
      *                     1 : -25         // Algorithm : ECDH-ES + HKDF-256
      *                 },
      *                 unprotected : {
-     *                     -1 : {          // COSE_Key
-     *                         1 : 1,      // Key type : Octet Key Pair
-     *                         -1 : 4,     // Curve : X25519
-     *                         -2 : bstr   // Sender X25519 public key
-     *                     }
+     *                     -1 : PubKeyX25519 / PubKeyEcdhP256  // Of the sender
      *                     4 : bstr,       // KID : EEK ID
      *                 },
      *                 ciphertext : nil
@@ -67,7 +63,7 @@
      *             other : bstr            // EEK pubkey
      *         ],
      *         SuppPubInfo : [
-     *             128,                    // Output key length
+     *             256,                    // Output key length
      *             protected : bstr .size 0
      *         ]
      *     ]
@@ -75,34 +71,51 @@
      *     ProtectedDataPayload [
      *         SignedMac,
      *         Bcc,
+     *         ? AdditionalDKSignatures,
+     *     ]
+     *     AdditionalDKSignatures = {
+     *         + SignerName => DKCertChain
+     *     }
+     *
+     *     SignerName = tstr
+     *
+     *     DKCertChain = [
+     *         2* Certificate                      // Root -> Leaf.  Root is the vendor
+     *                                             // self-signed cert, leaf contains DK_pub
      *     ]
      *
-     *     SignedMac = [                       // COSE_Sign1
-     *         bstr .cbor {                    // Protected params
-     *             1 : -8,                     // Algorithm : EdDSA
+     *     Certificate = COSE_Sign1 of a public key
+     *
+     *     SignedMac = [                                  // COSE_Sign1
+     *         bstr .cbor {                               // Protected params
+     *             1 : AlgorithmEdDSA / AlgorithmES256,   // Algorithm
      *         },
-     *         { },                            // Unprotected params
+     *         {},                   // Unprotected params
      *         bstr .size 32,                  // MAC key
-     *         bstr PureEd25519(DK_priv, .cbor SignedMac_structure)
+     *         bstr PureEd25519(KM_priv, .cbor SignedMac_structure) /
+     *              ECDSA(KM_priv, bstr .cbor SignedMac_structure)
      *     ]
      *
      *     SignedMac_structure = [
      *         "Signature1",
-     *         bstr .cbor {                    // Protected params
-     *             1 : -8,                     // Algorithm : EdDSA
+     *         bstr .cbor {                               // Protected params
+     *             1 : AlgorithmEdDSA / AlgorithmES256,   // Algorithm
      *         },
      *         bstr .cbor SignedMacAad
-     *         bstr .size 32                   // MAC key
+     *         bstr .size 32                              // MAC key
      *     ]
      *
      *     SignedMacAad = [
      *         challenge : bstr,
-     *         DeviceInfo
+     *         VerifiedDeviceInfo,
+     *         tag: bstr                 // This is the tag from COSE_Mac0 of
+     *                                   // KeysToCertify, to tie the key set to
+     *                                   // the signature.
      *     ]
      *
      *     Bcc = [
-     *         PubKey,                        // DK_pub
-     *         + BccEntry,                    // Root -> leaf (KM_pub)
+     *         PubKeyEd25519 / PubKeyECDSA256, // DK_pub
+     *         + BccEntry,                     // Root -> leaf (KM_pub)
      *     ]
      *
      *     BccPayload = {                     // CWT
@@ -120,51 +133,65 @@
      *         ? -4670549 : bstr,             // Authority Hash
      *         ? -4670550 : bstr,             // Authority Descriptor
      *         ? -4670551 : bstr,             // Mode
-     *         -4670552 : bstr .cbor PubKey   // Subject Public Key
+     *         -4670552 : bstr .cbor PubKeyEd25519 /
+     *                    bstr .cbor PubKeyECDSA256   // Subject Public Key
      *         -4670553 : bstr                // Key Usage
      *     }
      *
-     *     BccEntry = [                       // COSE_Sign1
-     *         protected: bstr .cbor {
-     *             1 : -8,                    // Algorithm : EdDSA
+     *     BccEntry = [                                  // COSE_Sign1 (untagged)
+     *         protected : bstr .cbor {
+     *             1 : AlgorithmEdDSA / AlgorithmES256,  // Algorithm
      *         },
-     *         unprotected: { },
+     *         unprotected: {},
      *         payload: bstr .cbor BccPayload,
-     *         // First entry in the chain is signed by DK_pub, the others are each signed by their
-     *         // immediate predecessor.  See RFC 8032 for signature representation.
-     *         signature: bstr .cbor PureEd25519(SigningKey, bstr .cbor BccEntryInput)
+     *         signature: bstr .cbor PureEd25519(SigningKey, bstr .cbor BccEntryInput) /
+     *                    bstr .cbor ECDSA(SigningKey, bstr .cbor BccEntryInput)
+     *         // See RFC 8032 for details of how to encode the signature value for Ed25519.
      *     ]
      *
-     *     PubKey = {                         // COSE_Key
-     *         1 : 1,                         // Key type : octet key pair
-     *         3 : -8,                        // Algorithm : EdDSA
-     *         4 : 2,                         // Ops: Verify
-     *         -1 : 6,                        // Curve : Ed25519
-     *         -2 : bstr                      // X coordinate, little-endian
-     *     }
-     *
      *     BccEntryInput = [
      *         context: "Signature1",
      *         protected: bstr .cbor {
-     *             1 : -8,                    // Algorithm : EdDSA
+     *             1 : AlgorithmEdDSA / AlgorithmES256,  // Algorithm
      *         },
      *         external_aad: bstr .size 0,
      *         payload: bstr .cbor BccPayload
      *     ]
      *
-     *     DeviceInfo = {
-     *         ? "brand" : tstr,
-     *         ? "manufacturer" : tstr,
-     *         ? "product" : tstr,
-     *         ? "model" : tstr,
-     *         ? "board" : tstr,
-     *         ? "vb_state" : "green" / "yellow" / "orange",
-     *         ? "bootloader_state" : "locked" / "unlocked",
-     *         ? "os_version" : tstr,
-     *         ? "system_patch_level" : uint,        // YYYYMMDD
-     *         ? "boot_patch_level" : uint,          // YYYYMMDD
-     *         ? "vendor_patch_level" : uint,        // YYYYMMDD
+     *     VerifiedDeviceInfo = DeviceInfo  // See DeviceInfo.aidl
+     *
+     *     PubKeyX25519 = {                 // COSE_Key
+     *          1 : 1,                      // Key type : Octet Key Pair
+     *         -1 : 4,                      // Curve : X25519
+     *         -2 : bstr                    // Sender X25519 public key
      *     }
+     *
+     *     PubKeyEd25519 = {                // COSE_Key
+     *         1 : 1,                         // Key type : octet key pair
+     *         3 : AlgorithmEdDSA,            // Algorithm : EdDSA
+     *         4 : 2,                         // Ops: Verify
+     *         -1 : 6,                        // Curve : Ed25519
+     *         -2 : bstr                      // X coordinate, little-endian
+     *     }
+     *
+     *     PubKeyEcdhP256 = {              // COSE_Key
+     *          1 : 2,      // Key type : EC2
+     *          -1 : 1,     // Curve : P256
+     *          -2 : bstr   // Sender X coordinate
+     *          -3 : bstr   // Sender Y coordinate
+     *     }
+     *
+     *     PubKeyECDSA256 = {                 // COSE_Key
+     *         1 : 2,                         // Key type : EC2
+     *         3 : AlgorithmES256,            // Algorithm : ECDSA w/ SHA-256
+     *         4 : 2,                         // Ops: Verify
+     *         -1 : 1,                        // Curve: P256
+     *         -2 : bstr,                     // X coordinate
+     *         -3 : bstr                      // Y coordinate
+     *     }
+     *
+     *     AlgorithmES256 = -7
+     *     AlgorithmEdDSA = -8
      */
     byte[] protectedData;
 }
diff --git a/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl b/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl
index 58e02b3..01bf54b 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl
@@ -18,10 +18,6 @@
 
 import android.hardware.security.keymint.TagType;
 
-// TODO(seleneh) : note aidl currently does not support double nested enum definitions such as
-// ROOT_OF_TRUST = TagType:BYTES | 704.  So we are forced to write definitions as
-// ROOT_OF_TRUST = (9 << 28) for now.  Will need to flip this back later when aidl support is added.
-
 /**
  * Tag specifies various kinds of tags that can be set in KeyParameter to identify what kind of
  * data are stored in KeyParameter.
@@ -33,7 +29,7 @@
     /**
      * Tag::INVALID should never be set.  It means you hit an error.
      */
-    INVALID = (0 << 28) | 0,
+    INVALID = 0,
 
     /**
      * Tag::PURPOSE specifies the set of purposes for which the key may be used.  Possible values
@@ -47,7 +43,7 @@
      *
      * Must be hardware-enforced.
      */
-    PURPOSE = (2 << 28) /* TagType:ENUM_REP */ | 1,
+    PURPOSE = TagType.ENUM_REP | 1,
 
     /**
      * Tag::ALGORITHM specifies the cryptographic algorithm with which the key is used.  This tag
@@ -56,7 +52,7 @@
      *
      * Must be hardware-enforced.
      */
-    ALGORITHM = (1 << 28) /* TagType:ENUM */ | 2,
+    ALGORITHM = TagType.ENUM | 2,
 
     /**
      * Tag::KEY_SIZE specifies the size, in bits, of the key, measuring in the normal way for the
@@ -68,7 +64,7 @@
      *
      * Must be hardware-enforced.
      */
-    KEY_SIZE = (3 << 28) /* TagType:UINT */ | 3,
+    KEY_SIZE = TagType.UINT | 3,
 
     /**
      * Tag::BLOCK_MODE specifies the block cipher mode(s) with which the key may be used.  This tag
@@ -81,7 +77,7 @@
      *
      * Must be hardware-enforced.
      */
-    BLOCK_MODE = (2 << 28) /* TagType:ENUM_REP */ | 4,
+    BLOCK_MODE = TagType.ENUM_REP | 4,
 
     /**
      * Tag::DIGEST specifies the digest algorithms that may be used with the key to perform signing
@@ -95,7 +91,7 @@
      *
      * Must be hardware-enforced.
      */
-    DIGEST = (2 << 28) /* TagType:ENUM_REP */ | 5,
+    DIGEST = TagType.ENUM_REP | 5,
 
     /**
      * Tag::PADDING specifies the padding modes that may be used with the key.  This tag is relevant
@@ -123,7 +119,7 @@
      *
      * Must be hardware-enforced.
      */
-    PADDING = (2 << 28) /* TagType:ENUM_REP */ | 6,
+    PADDING = TagType.ENUM_REP | 6,
 
     /**
      * Tag::CALLER_NONCE specifies that the caller can provide a nonce for nonce-requiring
@@ -136,7 +132,7 @@
      *
      * Must be hardware-enforced.
      */
-    CALLER_NONCE = (7 << 28) /* TagType:BOOL */ | 7,
+    CALLER_NONCE = TagType.BOOL | 7,
 
     /**
      * Tag::MIN_MAC_LENGTH specifies the minimum length of MAC that can be requested or verified
@@ -149,7 +145,7 @@
      *
      * Must be hardware-enforced.
      */
-    MIN_MAC_LENGTH = (3 << 28) /* TagType:UINT */ | 8,
+    MIN_MAC_LENGTH = TagType.UINT | 8,
 
     // Tag 9 reserved
 
@@ -159,7 +155,7 @@
      *
      * Must be hardware-enforced.
      */
-    EC_CURVE = (1 << 28) /* TagType:ENUM */ | 10,
+    EC_CURVE = TagType.ENUM | 10,
 
     /**
      * Tag::RSA_PUBLIC_EXPONENT specifies the value of the public exponent for an RSA key pair.
@@ -173,7 +169,7 @@
      *
      * Must be hardware-enforced.
      */
-    RSA_PUBLIC_EXPONENT = (5 << 28) /* TagType:ULONG */ | 200,
+    RSA_PUBLIC_EXPONENT = TagType.ULONG | 200,
 
     // Tag 201 reserved
 
@@ -184,7 +180,7 @@
      *
      * Must be hardware-enforced.
      */
-    INCLUDE_UNIQUE_ID = (7 << 28) /* TagType:BOOL */ | 202,
+    INCLUDE_UNIQUE_ID = TagType.BOOL | 202,
 
     /**
      * Tag::RSA_OAEP_MGF_DIGEST specifies the MGF1 digest algorithms that may be used with RSA
@@ -197,7 +193,7 @@
      *
      * Must be hardware-enforced.
      */
-    RSA_OAEP_MGF_DIGEST = (2 << 28) /* TagType:ENUM_REP */ | 203,
+    RSA_OAEP_MGF_DIGEST = TagType.ENUM_REP | 203,
 
     // Tag 301 reserved
 
@@ -209,7 +205,7 @@
      *
      * Must be hardware-enforced.
      */
-    BOOTLOADER_ONLY = (7 << 28) /* TagType:BOOL */ | 302,
+    BOOTLOADER_ONLY = TagType.BOOL | 302,
 
     /**
      * Tag::ROLLBACK_RESISTANCE specifies that the key has rollback resistance, meaning that when
@@ -224,10 +220,10 @@
      *
      * Must be hardware-enforced.
      */
-    ROLLBACK_RESISTANCE = (7 << 28) /* TagType:BOOL */ | 303,
+    ROLLBACK_RESISTANCE = TagType.BOOL | 303,
 
     // Reserved for future use.
-    HARDWARE_TYPE = (1 << 28) /* TagType:ENUM */ | 304,
+    HARDWARE_TYPE = TagType.ENUM | 304,
 
     /**
      * Keys tagged with EARLY_BOOT_ONLY may only be used during early boot, until
@@ -236,7 +232,7 @@
      * provided to IKeyMintDevice::importKey, the import must fail with
      * ErrorCode::EARLY_BOOT_ENDED.
      */
-    EARLY_BOOT_ONLY = (7 << 28) /* TagType:BOOL */ | 305,
+    EARLY_BOOT_ONLY = TagType.BOOL | 305,
 
     /**
      * Tag::ACTIVE_DATETIME specifies the date and time at which the key becomes active, in
@@ -245,7 +241,7 @@
      *
      * Need not be hardware-enforced.
      */
-    ACTIVE_DATETIME = (6 << 28) /* TagType:DATE */ | 400,
+    ACTIVE_DATETIME = TagType.DATE | 400,
 
     /**
      * Tag::ORIGINATION_EXPIRE_DATETIME specifies the date and time at which the key expires for
@@ -257,7 +253,7 @@
      *
      * Need not be hardware-enforced.
      */
-    ORIGINATION_EXPIRE_DATETIME = (6 << 28) /* TagType:DATE */ | 401,
+    ORIGINATION_EXPIRE_DATETIME = TagType.DATE | 401,
 
     /**
      * Tag::USAGE_EXPIRE_DATETIME specifies the date and time at which the key expires for
@@ -269,7 +265,7 @@
      *
      * Need not be hardware-enforced.
      */
-    USAGE_EXPIRE_DATETIME = (6 << 28) /* TagType:DATE */ | 402,
+    USAGE_EXPIRE_DATETIME = TagType.DATE | 402,
 
     /**
      * TODO(seleneh) this tag need to be deleted.
@@ -293,8 +289,10 @@
      * fails because the table is full, KeyMint returns ErrorCode::TOO_MANY_OPERATIONS.
      *
      * Must be hardware-enforced.
+     *
+     * TODO(b/191738660): Remove in KeyMint V2. Currently only used for FDE.
      */
-    MIN_SECONDS_BETWEEN_OPS = (3 << 28) /* TagType:UINT */ | 403,
+    MIN_SECONDS_BETWEEN_OPS = TagType.UINT | 403,
 
     /**
      * Tag::MAX_USES_PER_BOOT specifies the maximum number of times that a key may be used between
@@ -314,7 +312,7 @@
      *
      * Must be hardware-enforced.
      */
-    MAX_USES_PER_BOOT = (3 << 28) /* TagType:UINT */ | 404,
+    MAX_USES_PER_BOOT = TagType.UINT | 404,
 
     /**
      * Tag::USAGE_COUNT_LIMIT specifies the number of times that a key may be used. This can be
@@ -343,14 +341,14 @@
      * record. This tag must have the same SecurityLevel as the tag that is added to the key
      * characteristics.
      */
-    USAGE_COUNT_LIMIT = (3 << 28) | 405, /* TagType:UINT */
+    USAGE_COUNT_LIMIT = TagType.UINT | 405,
 
     /**
      * Tag::USER_ID specifies the ID of the Android user that is permitted to use the key.
      *
      * Must not be hardware-enforced.
      */
-    USER_ID = (3 << 28) /* TagType:UINT */ | 501,
+    USER_ID = TagType.UINT | 501,
 
     /**
      * Tag::USER_SECURE_ID specifies that a key may only be used under a particular secure user
@@ -383,7 +381,7 @@
      *
      * Must be hardware-enforced.
      */
-    USER_SECURE_ID = (10 << 28) /* TagType:ULONG_REP */ | 502,
+    USER_SECURE_ID = TagType.ULONG_REP | 502,
 
     /**
      * Tag::NO_AUTH_REQUIRED specifies that no authentication is required to use this key.  This tag
@@ -391,7 +389,7 @@
      *
      * Must be hardware-enforced.
      */
-    NO_AUTH_REQUIRED = (7 << 28) /* TagType:BOOL */ | 503,
+    NO_AUTH_REQUIRED = TagType.BOOL | 503,
 
     /**
      * Tag::USER_AUTH_TYPE specifies the types of user authenticators that may be used to authorize
@@ -410,7 +408,7 @@
      *
      * Must be hardware-enforced.
      */
-    USER_AUTH_TYPE = (1 << 28) /* TagType:ENUM */ | 504,
+    USER_AUTH_TYPE = TagType.ENUM | 504,
 
     /**
      * Tag::AUTH_TIMEOUT specifies the time in seconds for which the key is authorized for use,
@@ -424,7 +422,7 @@
      *
      * Must be hardware-enforced.
      */
-    AUTH_TIMEOUT = (3 << 28) /* TagType:UINT */ | 505,
+    AUTH_TIMEOUT = TagType.UINT | 505,
 
     /**
      * Tag::ALLOW_WHILE_ON_BODY specifies that the key may be used after authentication timeout if
@@ -432,7 +430,7 @@
      *
      * Cannot be hardware-enforced.
      */
-    ALLOW_WHILE_ON_BODY = (7 << 28) /* TagType:BOOL */ | 506,
+    ALLOW_WHILE_ON_BODY = TagType.BOOL | 506,
 
     /**
      * TRUSTED_USER_PRESENCE_REQUIRED is an optional feature that specifies that this key must be
@@ -479,29 +477,31 @@
      *
      * Must be hardware-enforced.
      */
-    TRUSTED_USER_PRESENCE_REQUIRED = (7 << 28) /* TagType:BOOL */ | 507,
+    TRUSTED_USER_PRESENCE_REQUIRED = TagType.BOOL | 507,
 
     /**
      * Tag::TRUSTED_CONFIRMATION_REQUIRED is only applicable to keys with KeyPurpose SIGN, and
-     *  specifies that this key must not be usable unless the user provides confirmation of the data
-     *  to be signed.  Confirmation is proven to keyMint via an approval token.  See
-     *  CONFIRMATION_TOKEN, as well as the ConfirmationUI HAL.
+     * specifies that this key must not be usable unless the user provides confirmation of the data
+     * to be signed.  Confirmation is proven to keyMint via an approval token.  See the authToken
+     * parameter of begin(), as well as the ConfirmationUI HAL.
      *
      * If an attempt to use a key with this tag does not have a cryptographically valid
-     * CONFIRMATION_TOKEN provided to finish() or if the data provided to update()/finish() does not
+     * token provided to finish() or if the data provided to update()/finish() does not
      * match the data described in the token, keyMint must return NO_USER_CONFIRMATION.
      *
      * Must be hardware-enforced.
      */
-    TRUSTED_CONFIRMATION_REQUIRED = (7 << 28) /* TagType:BOOL */ | 508,
+    TRUSTED_CONFIRMATION_REQUIRED = TagType.BOOL | 508,
 
     /**
      * Tag::UNLOCKED_DEVICE_REQUIRED specifies that the key may only be used when the device is
-     * unlocked.
+     * unlocked, as reported to KeyMint via authToken operation parameter and the
+     * IKeyMintDevice::deviceLocked() method
      *
-     * Must be software-enforced.
+     * Must be hardware-enforced (but is also keystore-enforced on a per-user basis: see the
+     * deviceLocked() documentation).
      */
-    UNLOCKED_DEVICE_REQUIRED = (7 << 28) /* TagType:BOOL */ | 509,
+    UNLOCKED_DEVICE_REQUIRED = TagType.BOOL | 509,
 
     /**
      * Tag::APPLICATION_ID.  When provided to generateKey or importKey, this tag specifies data
@@ -517,7 +517,7 @@
      *
      * Must never appear in KeyCharacteristics.
      */
-    APPLICATION_ID = (9 << 28) /* TagType:BYTES */ | 601,
+    APPLICATION_ID = TagType.BYTES | 601,
 
     /*
      * Semantically unenforceable tags, either because they have no specific meaning or because
@@ -538,7 +538,7 @@
      *
      * Must never appear in KeyCharacteristics.
      */
-    APPLICATION_DATA = (9 << 28) /* TagType:BYTES */ | 700,
+    APPLICATION_DATA = TagType.BYTES | 700,
 
     /**
      * Tag::CREATION_DATETIME specifies the date and time the key was created, in milliseconds since
@@ -546,7 +546,7 @@
      *
      * Must be in the software-enforced list, if provided.
      */
-    CREATION_DATETIME = (6 << 28) /* TagType:DATE */ | 701,
+    CREATION_DATETIME = TagType.DATE | 701,
 
     /**
      * Tag::ORIGIN specifies where the key was created, if known.  This tag must not be specified
@@ -555,7 +555,7 @@
      *
      * Must be hardware-enforced.
      */
-    ORIGIN = (1 << 28) /* TagType:ENUM */ | 702,
+    ORIGIN = TagType.ENUM | 702,
 
     // 703 is unused.
 
@@ -567,7 +567,7 @@
      *
      * Must never appear in KeyCharacteristics.
      */
-    ROOT_OF_TRUST = (9 << 28) /* TagType:BYTES */ | 704,
+    ROOT_OF_TRUST = TagType.BYTES | 704,
 
     /**
      * Tag::OS_VERSION specifies the system OS version with which the key may be used.  This tag is
@@ -590,7 +590,7 @@
      *
      * Must be hardware-enforced.
      */
-    OS_VERSION = (3 << 28) /* TagType:UINT */ | 705,
+    OS_VERSION = TagType.UINT | 705,
 
     /**
      * Tag::OS_PATCHLEVEL specifies the system security patch level with which the key may be used.
@@ -611,7 +611,7 @@
      *
      * Must be hardware-enforced.
      */
-    OS_PATCHLEVEL = (3 << 28) /* TagType:UINT */ | 706,
+    OS_PATCHLEVEL = TagType.UINT | 706,
 
     /**
      * Tag::UNIQUE_ID specifies a unique, time-based identifier.  This tag is never provided to or
@@ -646,7 +646,7 @@
      *
      * Must be hardware-enforced.
      */
-    UNIQUE_ID = (9 << 28) /* TagType:BYTES */ | 707,
+    UNIQUE_ID = TagType.BYTES | 707,
 
     /**
      * Tag::ATTESTATION_CHALLENGE is used to deliver a "challenge" value to the attested key
@@ -655,7 +655,7 @@
      *
      * Must never appear in KeyCharacteristics.
      */
-    ATTESTATION_CHALLENGE = (9 << 28) /* TagType:BYTES */ | 708,
+    ATTESTATION_CHALLENGE = TagType.BYTES | 708,
 
     /**
      * Tag::ATTESTATION_APPLICATION_ID identifies the set of applications which may use a key, used
@@ -681,7 +681,7 @@
      *
      * Cannot be hardware-enforced.
      */
-    ATTESTATION_APPLICATION_ID = (9 << 28) /* TagType:BYTES */ | 709,
+    ATTESTATION_APPLICATION_ID = TagType.BYTES | 709,
 
     /**
      * Tag::ATTESTATION_ID_BRAND provides the device's brand name, as returned by Build.BRAND in
@@ -694,7 +694,7 @@
      *
      * Must never appear in KeyCharacteristics.
      */
-    ATTESTATION_ID_BRAND = (9 << 28) /* TagType:BYTES */ | 710,
+    ATTESTATION_ID_BRAND = TagType.BYTES | 710,
 
     /**
      * Tag::ATTESTATION_ID_DEVICE provides the device's device name, as returned by Build.DEVICE in
@@ -707,7 +707,7 @@
      *
      * Must never appear in KeyCharacteristics.
      */
-    ATTESTATION_ID_DEVICE = (9 << 28) /* TagType:BYTES */ | 711,
+    ATTESTATION_ID_DEVICE = TagType.BYTES | 711,
 
     /**
      * Tag::ATTESTATION_ID_PRODUCT provides the device's product name, as returned by Build.PRODUCT
@@ -720,7 +720,7 @@
      *
      * Must never appear in KeyCharacteristics.
      */
-    ATTESTATION_ID_PRODUCT = (9 << 28) /* TagType:BYTES */ | 712,
+    ATTESTATION_ID_PRODUCT = TagType.BYTES | 712,
 
     /**
      * Tag::ATTESTATION_ID_SERIAL the device's serial number.  This field must be set only when
@@ -732,7 +732,7 @@
      *
      * Must never appear in KeyCharacteristics.
      */
-    ATTESTATION_ID_SERIAL = (9 << 28) /* TagType:BYTES */ | 713,
+    ATTESTATION_ID_SERIAL = TagType.BYTES | 713,
 
     /**
      * Tag::ATTESTATION_ID_IMEI provides the IMEIs for all radios on the device to attested key
@@ -745,7 +745,7 @@
      *
      * Must never appear in KeyCharacteristics.
      */
-    ATTESTATION_ID_IMEI = (9 << 28) /* TagType:BYTES */ | 714,
+    ATTESTATION_ID_IMEI = TagType.BYTES | 714,
 
     /**
      * Tag::ATTESTATION_ID_MEID provides the MEIDs for all radios on the device to attested key
@@ -758,7 +758,7 @@
      *
      * Must never appear in KeyCharacteristics.
      */
-    ATTESTATION_ID_MEID = (9 << 28) /* TagType:BYTES */ | 715,
+    ATTESTATION_ID_MEID = TagType.BYTES | 715,
 
     /**
      * Tag::ATTESTATION_ID_MANUFACTURER provides the device's manufacturer name, as returned by
@@ -771,7 +771,7 @@
      *
      * Must never appear in KeyCharacteristics.
      */
-    ATTESTATION_ID_MANUFACTURER = (9 << 28) /* TagType:BYTES */ | 716,
+    ATTESTATION_ID_MANUFACTURER = TagType.BYTES | 716,
 
     /**
      * Tag::ATTESTATION_ID_MODEL provides the device's model name, as returned by Build.MODEL in
@@ -784,7 +784,7 @@
      *
      * Must never appear in KeyCharacteristics.
      */
-    ATTESTATION_ID_MODEL = (9 << 28) /* TagType:BYTES */ | 717,
+    ATTESTATION_ID_MODEL = TagType.BYTES | 717,
 
     /**
      * Tag::VENDOR_PATCHLEVEL specifies the vendor image security patch level with which the key may
@@ -806,7 +806,7 @@
      *
      * Must be hardware-enforced.
      */
-    VENDOR_PATCHLEVEL = (3 << 28) /* TagType:UINT */ | 718,
+    VENDOR_PATCHLEVEL = TagType.UINT | 718,
 
     /**
      * Tag::BOOT_PATCHLEVEL specifies the boot image (kernel) security patch level with which the
@@ -826,7 +826,7 @@
      *
      * Must be hardware-enforced.
      */
-    BOOT_PATCHLEVEL = (3 << 28) /* TagType:UINT */ | 719,
+    BOOT_PATCHLEVEL = TagType.UINT | 719,
 
     /**
      * DEVICE_UNIQUE_ATTESTATION is an argument to IKeyMintDevice::attested key generation/import
@@ -852,7 +852,7 @@
      * IKeyMintDevice implementations that support device-unique attestation MUST add the
      * DEVICE_UNIQUE_ATTESTATION tag to device-unique attestations.
      */
-    DEVICE_UNIQUE_ATTESTATION = (7 << 28) /* TagType:BOOL */ | 720,
+    DEVICE_UNIQUE_ATTESTATION = TagType.BOOL | 720,
 
     /**
      * IDENTITY_CREDENTIAL_KEY is never used by IKeyMintDevice, is not a valid argument to key
@@ -860,7 +860,7 @@
      * attestation.  It is used in attestations produced by the IIdentityCredential HAL when that
      * HAL attests to Credential Keys.  IIdentityCredential produces KeyMint-style attestations.
      */
-    IDENTITY_CREDENTIAL_KEY = (7 << 28) /* TagType:BOOL */ | 721,
+    IDENTITY_CREDENTIAL_KEY = TagType.BOOL | 721,
 
     /**
      * To prevent keys from being compromised if an attacker acquires read access to system / kernel
@@ -870,19 +870,21 @@
      *
      * STORAGE_KEY is used to denote that a key generated or imported is a key used for storage
      * encryption. Keys of this type can either be generated or imported or secure imported using
-     * keyMint. exportKey() can be used to re-wrap storage key with a per-boot ephemeral key
-     * wrapped key once the key characteristics are enforced.
+     * keyMint. The convertStorageKeyToEphemeral() method of IKeyMintDevice can be used to re-wrap
+     * storage key with a per-boot ephemeral key wrapped key once the key characteristics are
+     * enforced.
      *
      * Keys with this tag cannot be used for any operation within keyMint.
      * ErrorCode::INVALID_OPERATION is returned when a key with Tag::STORAGE_KEY is provided to
      * begin().
      */
-    STORAGE_KEY = (7 << 28) /* TagType:BOOL */ | 722,
+    STORAGE_KEY = TagType.BOOL | 722,
 
     /**
-     * TODO: Delete when keystore1 is deleted.
+     * OBSOLETE: Do not use. See IKeyMintOperation.updateAad instead.
+     * TODO(b/191738660): Remove in KeyMint v2.
      */
-    ASSOCIATED_DATA = (9 << 28) /* TagType:BYTES */ | 1000,
+    ASSOCIATED_DATA = TagType.BYTES | 1000,
 
     /**
      * Tag::NONCE is used to provide or return a nonce or Initialization Vector (IV) for AES-GCM,
@@ -897,7 +899,7 @@
      *
      * Must never appear in KeyCharacteristics.
      */
-    NONCE = (9 << 28) /* TagType:BYTES */ | 1001,
+    NONCE = TagType.BYTES | 1001,
 
     /**
      * Tag::MAC_LENGTH provides the requested length of a MAC or GCM authentication tag, in bits.
@@ -908,7 +910,7 @@
      *
      * Must never appear in KeyCharacteristics.
      */
-    MAC_LENGTH = (3 << 28) /* TagType:UINT */ | 1003,
+    MAC_LENGTH = TagType.UINT | 1003,
 
     /**
      * Tag::RESET_SINCE_ID_ROTATION specifies whether the device has been factory reset since the
@@ -916,16 +918,15 @@
      *
      * Must never appear in KeyCharacteristics.
      */
-    RESET_SINCE_ID_ROTATION = (7 << 28) /* TagType:BOOL */ | 1004,
+    RESET_SINCE_ID_ROTATION = TagType.BOOL | 1004,
 
     /**
-     * Tag::CONFIRMATION_TOKEN is used to deliver a cryptographic token proving that the user
-     * confirmed a signing request.  The content is a full-length HMAC-SHA256 value.  See the
-     * ConfirmationUI HAL for details of token computation.
+     * OBSOLETE: Do not use. See the authToken parameter for IKeyMintDevice::begin and for
+     * IKeyMintOperation methods instead.
      *
-     * Must never appear in KeyCharacteristics.
+     * TODO(b/191738660): Delete when keystore1 is deleted.
      */
-    CONFIRMATION_TOKEN = (9 << 28) /* TagType:BYTES */ | 1005,
+    CONFIRMATION_TOKEN = TagType.BYTES | 1005,
 
     /**
      * Tag::CERTIFICATE_SERIAL specifies the serial number to be assigned to the attestation
@@ -933,7 +934,7 @@
      * keyMint in the attestation parameters during generateKey() and importKey().  If not provided,
      * the serial shall default to 1.
      */
-    CERTIFICATE_SERIAL = (8 << 28) /* TagType:BIGNUM */ | 1006,
+    CERTIFICATE_SERIAL = TagType.BIGNUM | 1006,
 
     /**
      * Tag::CERTIFICATE_SUBJECT the certificate subject.  The value is a DER encoded X509 NAME.
@@ -941,7 +942,7 @@
      * during generateKey and importKey. If not provided the subject name shall default to
      * CN="Android Keystore Key".
      */
-    CERTIFICATE_SUBJECT = (9 << 28) /* TagType:BYTES */ | 1007,
+    CERTIFICATE_SUBJECT = TagType.BYTES | 1007,
 
     /**
      * Tag::CERTIFICATE_NOT_BEFORE the beginning of the validity of the certificate in UNIX epoch
@@ -949,7 +950,7 @@
      * certificates.  ErrorCode::MISSING_NOT_BEFORE must be returned if this tag is not provided if
      * this tag is not provided to generateKey or importKey.
      */
-    CERTIFICATE_NOT_BEFORE = (6 << 28) /* TagType:DATE */ | 1008,
+    CERTIFICATE_NOT_BEFORE = TagType.DATE | 1008,
 
     /**
      * Tag::CERTIFICATE_NOT_AFTER the end of the validity of the certificate in UNIX epoch time in
@@ -957,7 +958,7 @@
      * ErrorCode::MISSING_NOT_AFTER must be returned if this tag is not provided to generateKey or
      * importKey.
      */
-    CERTIFICATE_NOT_AFTER = (6 << 28) /* TagType:DATE */ | 1009,
+    CERTIFICATE_NOT_AFTER = TagType.DATE | 1009,
 
     /**
      * Tag::MAX_BOOT_LEVEL specifies a maximum boot level at which a key should function.
@@ -968,5 +969,5 @@
      *
      * Cannot be hardware enforced in this version.
      */
-    MAX_BOOT_LEVEL = (3 << 28) /* TagType:UINT */ | 1010,
+    MAX_BOOT_LEVEL = TagType.UINT | 1010,
 }
diff --git a/security/keymint/aidl/vts/functional/Android.bp b/security/keymint/aidl/vts/functional/Android.bp
index ff08ce6..386029f 100644
--- a/security/keymint/aidl/vts/functional/Android.bp
+++ b/security/keymint/aidl/vts/functional/Android.bp
@@ -23,16 +23,11 @@
     default_applicable_licenses: ["hardware_interfaces_license"],
 }
 
-cc_test {
-    name: "VtsAidlKeyMintTargetTest",
+cc_defaults {
+    name: "keymint_vts_defaults",
     defaults: [
-        "VtsHalTargetTestDefaults",
         "use_libaidlvintf_gtest_helper_static",
-    ],
-    srcs: [
-        "AttestKeyTest.cpp",
-        "DeviceUniqueAttestationTest.cpp",
-        "KeyMintTest.cpp",
+        "VtsHalTargetTestDefaults",
     ],
     shared_libs: [
         "libbinder_ndk",
@@ -43,9 +38,24 @@
         "android.hardware.security.secureclock-V1-ndk_platform",
         "libcppbor_external",
         "libcppcose_rkp",
+        "libjsoncpp",
         "libkeymint",
         "libkeymint_remote_prov_support",
         "libkeymint_support",
+    ],
+}
+
+cc_test {
+    name: "VtsAidlKeyMintTargetTest",
+    defaults: [
+        "keymint_vts_defaults",
+    ],
+    srcs: [
+        "AttestKeyTest.cpp",
+        "DeviceUniqueAttestationTest.cpp",
+        "KeyMintTest.cpp",
+    ],
+    static_libs: [
         "libkeymint_vts_test_utils",
     ],
     test_suites: [
@@ -57,8 +67,7 @@
 cc_test_library {
     name: "libkeymint_vts_test_utils",
     defaults: [
-        "VtsHalTargetTestDefaults",
-        "use_libaidlvintf_gtest_helper_static",
+        "keymint_vts_defaults",
     ],
     srcs: [
         "KeyMintAidlTestBase.cpp",
@@ -66,45 +75,22 @@
     export_include_dirs: [
         ".",
     ],
-    shared_libs: [
-        "libbinder_ndk",
-        "libcrypto",
-    ],
     static_libs: [
-        "android.hardware.security.keymint-V1-ndk_platform",
-        "android.hardware.security.secureclock-V1-ndk_platform",
-        "libcppbor_external",
-        "libcppcose_rkp",
         "libgmock_ndk",
-        "libkeymint",
-        "libkeymint_remote_prov_support",
-        "libkeymint_support",
     ],
 }
 
 cc_test {
     name: "VtsHalRemotelyProvisionedComponentTargetTest",
     defaults: [
-        "VtsHalTargetTestDefaults",
-        "use_libaidlvintf_gtest_helper_static",
+        "keymint_vts_defaults",
     ],
     srcs: [
         "VtsRemotelyProvisionedComponentTests.cpp",
     ],
-    shared_libs: [
-        "libbinder_ndk",
-        "libcrypto",
-    ],
     static_libs: [
-        "android.hardware.security.keymint-V1-ndk_platform",
-        "android.hardware.security.secureclock-V1-ndk_platform",
-        "libcppbor_external",
-        "libcppcose_rkp",
         "libgmock_ndk",
         "libkeymaster_portable",
-        "libkeymint",
-        "libkeymint_support",
-        "libkeymint_remote_prov_support",
         "libkeymint_vts_test_utils",
         "libpuresoftkeymasterdevice",
     ],
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
index 44b8274..5359b3b 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
@@ -62,6 +62,9 @@
 
 namespace {
 
+// Invalid value for a patchlevel (which is of form YYYYMMDD).
+const uint32_t kInvalidPatchlevel = 99998877;
+
 // Overhead for PKCS#1 v1.5 signature padding of undigested messages.  Digested messages have
 // additional overhead, for the digest algorithmIdentifier required by PKCS#1.
 const size_t kPkcs1UndigestedSignaturePaddingOverhead = 11;
@@ -126,10 +129,9 @@
 // Attestations don't contain everything in key authorization lists, so we need to filter the key
 // lists to produce the lists that we expect to match the attestations.
 auto kTagsToFilter = {
-    Tag::CREATION_DATETIME,
-    Tag::EC_CURVE,
-    Tag::HARDWARE_TYPE,
-    Tag::INCLUDE_UNIQUE_ID,
+        Tag::CREATION_DATETIME,
+        Tag::HARDWARE_TYPE,
+        Tag::INCLUDE_UNIQUE_ID,
 };
 
 AuthorizationSet filtered_tags(const AuthorizationSet& set) {
@@ -163,6 +165,28 @@
 bool KeyMintAidlTestBase::arm_deleteAllKeys = false;
 bool KeyMintAidlTestBase::dump_Attestations = false;
 
+uint32_t KeyMintAidlTestBase::boot_patch_level(
+        const vector<KeyCharacteristics>& key_characteristics) {
+    // The boot patchlevel is not available as a property, but should be present
+    // in the key characteristics of any created key.
+    AuthorizationSet allAuths;
+    for (auto& entry : key_characteristics) {
+        allAuths.push_back(AuthorizationSet(entry.authorizations));
+    }
+    auto patchlevel = allAuths.GetTagValue(TAG_BOOT_PATCHLEVEL);
+    if (patchlevel.has_value()) {
+        return patchlevel.value();
+    } else {
+        // No boot patchlevel is available. Return a value that won't match anything
+        // and so will trigger test failures.
+        return kInvalidPatchlevel;
+    }
+}
+
+uint32_t KeyMintAidlTestBase::boot_patch_level() {
+    return boot_patch_level(key_characteristics_);
+}
+
 ErrorCode KeyMintAidlTestBase::GetReturnErrorCode(const Status& result) {
     if (result.isOk()) return ErrorCode::OK;
 
@@ -998,16 +1022,7 @@
             }
             break;
         case Algorithm::EC:
-            switch (SecLevel()) {
-                case SecurityLevel::SOFTWARE:
-                case SecurityLevel::TRUSTED_ENVIRONMENT:
-                    return {224, 256, 384, 521};
-                case SecurityLevel::STRONGBOX:
-                    return {256};
-                default:
-                    ADD_FAILURE() << "Invalid security level " << uint32_t(SecLevel());
-                    break;
-            }
+            ADD_FAILURE() << "EC keys must be specified by curve not size";
             break;
         case Algorithm::AES:
             return {128, 256};
@@ -1123,9 +1138,11 @@
 }
 
 vector<EcCurve> KeyMintAidlTestBase::InvalidCurves() {
-    if (SecLevel() == SecurityLevel::TRUSTED_ENVIRONMENT) return {};
-    CHECK(SecLevel() == SecurityLevel::STRONGBOX);
-    return {EcCurve::P_224, EcCurve::P_384, EcCurve::P_521};
+    if (SecLevel() == SecurityLevel::STRONGBOX) {
+        return {EcCurve::P_224, EcCurve::P_384, EcCurve::P_521};
+    } else {
+        return {};
+    }
 }
 
 vector<Digest> KeyMintAidlTestBase::ValidDigests(bool withNone, bool withMD5) {
@@ -1293,9 +1310,9 @@
     AuthorizationSet att_sw_enforced;
     AuthorizationSet att_hw_enforced;
     uint32_t att_attestation_version;
-    uint32_t att_keymaster_version;
+    uint32_t att_keymint_version;
     SecurityLevel att_attestation_security_level;
-    SecurityLevel att_keymaster_security_level;
+    SecurityLevel att_keymint_security_level;
     vector<uint8_t> att_challenge;
     vector<uint8_t> att_unique_id;
     vector<uint8_t> att_app_id;
@@ -1304,8 +1321,8 @@
                                           attest_rec->length,               //
                                           &att_attestation_version,         //
                                           &att_attestation_security_level,  //
-                                          &att_keymaster_version,           //
-                                          &att_keymaster_security_level,    //
+                                          &att_keymint_version,             //
+                                          &att_keymint_security_level,      //
                                           &att_challenge,                   //
                                           &att_sw_enforced,                 //
                                           &att_hw_enforced,                 //
@@ -1324,14 +1341,14 @@
         expected_sw_enforced.push_back(TAG_ATTESTATION_APPLICATION_ID, appId);
     }
 
-    EXPECT_EQ(att_keymaster_version, 100U);
-    EXPECT_EQ(security_level, att_keymaster_security_level);
+    EXPECT_EQ(att_keymint_version, 100U);
+    EXPECT_EQ(security_level, att_keymint_security_level);
     EXPECT_EQ(security_level, att_attestation_security_level);
 
 
     char property_value[PROPERTY_VALUE_MAX] = {};
     // TODO(b/136282179): When running under VTS-on-GSI the TEE-backed
-    // keymaster implementation will report YYYYMM dates instead of YYYYMMDD
+    // keymint implementation will report YYYYMM dates instead of YYYYMMDD
     // for the BOOT_PATCH_LEVEL.
     if (avb_verification_enabled()) {
         for (int i = 0; i < att_hw_enforced.size(); i++) {
@@ -1370,13 +1387,6 @@
         EXPECT_TRUE(expected_hw_enforced.Contains(TAG_NO_AUTH_REQUIRED));
     }
 
-    // Alternatively this checks the opposite - a false boolean tag (one that isn't provided in
-    // the authorization list during key generation) isn't being attested to in the certificate.
-    EXPECT_FALSE(expected_sw_enforced.Contains(TAG_TRUSTED_USER_PRESENCE_REQUIRED));
-    EXPECT_FALSE(att_sw_enforced.Contains(TAG_TRUSTED_USER_PRESENCE_REQUIRED));
-    EXPECT_FALSE(expected_hw_enforced.Contains(TAG_TRUSTED_USER_PRESENCE_REQUIRED));
-    EXPECT_FALSE(att_hw_enforced.Contains(TAG_TRUSTED_USER_PRESENCE_REQUIRED));
-
     if (att_hw_enforced.Contains(TAG_ALGORITHM, Algorithm::EC)) {
         // For ECDSA keys, either an EC_CURVE or a KEY_SIZE can be specified, but one must be.
         EXPECT_TRUE(att_hw_enforced.Contains(TAG_EC_CURVE) ||
@@ -1442,9 +1452,7 @@
 
     att_sw_enforced.Sort();
     expected_sw_enforced.Sort();
-    auto a = filtered_tags(expected_sw_enforced);
-    auto b = filtered_tags(att_sw_enforced);
-    EXPECT_EQ(a, b);
+    EXPECT_EQ(filtered_tags(expected_sw_enforced), filtered_tags(att_sw_enforced));
 
     att_hw_enforced.Sort();
     expected_hw_enforced.Sort();
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
index 82f192a..d592d36 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
@@ -76,6 +76,8 @@
     uint32_t os_version() { return os_version_; }
     uint32_t os_patch_level() { return os_patch_level_; }
     uint32_t vendor_patch_level() { return vendor_patch_level_; }
+    uint32_t boot_patch_level(const vector<KeyCharacteristics>& key_characteristics);
+    uint32_t boot_patch_level();
 
     ErrorCode GetReturnErrorCode(const Status& result);
 
@@ -253,7 +255,7 @@
         /* ECDSA */
         KeyData ecdsaKeyData;
         AuthorizationSetBuilder ecdsaBuilder = AuthorizationSetBuilder()
-                                                       .EcdsaSigningKey(256)
+                                                       .EcdsaSigningKey(EcCurve::P_256)
                                                        .Authorization(tagToTest)
                                                        .Digest(Digest::SHA_2_256)
                                                        .Authorization(TAG_NO_AUTH_REQUIRED)
diff --git a/security/keymint/aidl/vts/functional/KeyMintTest.cpp b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
index 295be1a..d41d270 100644
--- a/security/keymint/aidl/vts/functional/KeyMintTest.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
@@ -18,6 +18,8 @@
 #include <cutils/log.h>
 
 #include <signal.h>
+
+#include <algorithm>
 #include <iostream>
 
 #include <openssl/ec.h>
@@ -1362,11 +1364,11 @@
  * have correct characteristics.
  */
 TEST_P(NewKeyGenerationTest, Ecdsa) {
-    for (auto key_size : ValidKeySizes(Algorithm::EC)) {
+    for (auto curve : ValidCurves()) {
         vector<uint8_t> key_blob;
         vector<KeyCharacteristics> key_characteristics;
         ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
-                                                     .EcdsaSigningKey(key_size)
+                                                     .EcdsaSigningKey(curve)
                                                      .Digest(Digest::NONE)
                                                      .SetDefaultValidity(),
                                              &key_blob, &key_characteristics));
@@ -1377,8 +1379,7 @@
         AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
 
         EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::EC));
-        EXPECT_TRUE(crypto_params.Contains(TAG_KEY_SIZE, key_size))
-                << "Key size " << key_size << "missing";
+        EXPECT_TRUE(crypto_params.Contains(TAG_EC_CURVE, curve)) << "Curve " << curve << "missing";
 
         CheckedDeleteKey(&key_blob);
     }
@@ -1400,13 +1401,13 @@
     uint64_t serial_int = 0xFFFFFFFFFFFFFFFF;
     vector<uint8_t> serial_blob(build_serial_blob(serial_int));
 
-    for (auto key_size : ValidKeySizes(Algorithm::EC)) {
+    for (auto curve : ValidCurves()) {
         vector<uint8_t> key_blob;
         vector<KeyCharacteristics> key_characteristics;
         ASSERT_EQ(ErrorCode::OK,
                   GenerateKey(AuthorizationSetBuilder()
                                       .Authorization(TAG_NO_AUTH_REQUIRED)
-                                      .EcdsaSigningKey(key_size)
+                                      .EcdsaSigningKey(curve)
                                       .Digest(Digest::NONE)
                                       .AttestationChallenge(challenge)
                                       .AttestationApplicationId(app_id)
@@ -1421,8 +1422,7 @@
         AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
 
         EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::EC));
-        EXPECT_TRUE(crypto_params.Contains(TAG_KEY_SIZE, key_size))
-                << "Key size " << key_size << "missing";
+        EXPECT_TRUE(crypto_params.Contains(TAG_EC_CURVE, curve)) << "Curve " << curve << "missing";
 
         EXPECT_TRUE(ChainSignaturesAreValid(cert_chain_));
         ASSERT_GT(cert_chain_.size(), 0);
@@ -1439,6 +1439,170 @@
 }
 
 /*
+ * NewKeyGenerationTest.EcdsaAttestationTags
+ *
+ * Verifies that creation of an attested ECDSA key includes various tags in the
+ * attestation extension.
+ */
+TEST_P(NewKeyGenerationTest, EcdsaAttestationTags) {
+    auto challenge = "hello";
+    auto app_id = "foo";
+    auto subject = "cert subj 2";
+    vector<uint8_t> subject_der(make_name_from_str(subject));
+    uint64_t serial_int = 0x1010;
+    vector<uint8_t> serial_blob(build_serial_blob(serial_int));
+    const AuthorizationSetBuilder base_builder =
+            AuthorizationSetBuilder()
+                    .Authorization(TAG_NO_AUTH_REQUIRED)
+                    .EcdsaSigningKey(EcCurve::P_256)
+                    .Digest(Digest::NONE)
+                    .AttestationChallenge(challenge)
+                    .AttestationApplicationId(app_id)
+                    .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
+                    .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
+                    .SetDefaultValidity();
+
+    // Various tags that map to fields in the attestation extension ASN.1 schema.
+    auto extra_tags = AuthorizationSetBuilder()
+                              .Authorization(TAG_ROLLBACK_RESISTANCE)
+                              .Authorization(TAG_EARLY_BOOT_ONLY)
+                              .Authorization(TAG_ACTIVE_DATETIME, 1619621648000)
+                              .Authorization(TAG_ORIGINATION_EXPIRE_DATETIME, 1619621648000)
+                              .Authorization(TAG_USAGE_EXPIRE_DATETIME, 1619621999000)
+                              .Authorization(TAG_USAGE_COUNT_LIMIT, 42)
+                              .Authorization(TAG_AUTH_TIMEOUT, 100000)
+                              .Authorization(TAG_ALLOW_WHILE_ON_BODY)
+                              .Authorization(TAG_TRUSTED_USER_PRESENCE_REQUIRED)
+                              .Authorization(TAG_TRUSTED_CONFIRMATION_REQUIRED)
+                              .Authorization(TAG_UNLOCKED_DEVICE_REQUIRED)
+                              .Authorization(TAG_CREATION_DATETIME, 1619621648000);
+    for (const KeyParameter& tag : extra_tags) {
+        SCOPED_TRACE(testing::Message() << "tag-" << tag);
+        vector<uint8_t> key_blob;
+        vector<KeyCharacteristics> key_characteristics;
+        AuthorizationSetBuilder builder = base_builder;
+        builder.push_back(tag);
+        auto result = GenerateKey(builder, &key_blob, &key_characteristics);
+        if (result == ErrorCode::ROLLBACK_RESISTANCE_UNAVAILABLE &&
+            tag.tag == TAG_ROLLBACK_RESISTANCE) {
+            continue;
+        }
+        if (result == ErrorCode::UNSUPPORTED_TAG &&
+            (tag.tag == TAG_ALLOW_WHILE_ON_BODY || tag.tag == TAG_TRUSTED_USER_PRESENCE_REQUIRED)) {
+            // Optional tag not supported by this KeyMint implementation.
+            continue;
+        }
+        ASSERT_EQ(result, ErrorCode::OK);
+        ASSERT_GT(key_blob.size(), 0U);
+
+        EXPECT_TRUE(ChainSignaturesAreValid(cert_chain_));
+        ASSERT_GT(cert_chain_.size(), 0);
+        verify_subject_and_serial(cert_chain_[0], serial_int, subject, /* self_signed = */ false);
+
+        AuthorizationSet hw_enforced = HwEnforcedAuthorizations(key_characteristics);
+        AuthorizationSet sw_enforced = SwEnforcedAuthorizations(key_characteristics);
+        if (tag.tag != TAG_ATTESTATION_APPLICATION_ID) {
+            // Expect to find most of the extra tags in the key characteristics
+            // of the generated key (but not for ATTESTATION_APPLICATION_ID).
+            EXPECT_TRUE(hw_enforced.Contains(tag.tag) || sw_enforced.Contains(tag.tag))
+                    << tag << " not in hw:" << hw_enforced << " nor sw:" << sw_enforced;
+        }
+
+        // Verifying the attestation record will check for the specific tag because
+        // it's included in the authorizations.
+        EXPECT_TRUE(verify_attestation_record(challenge, app_id, sw_enforced, hw_enforced,
+                                              SecLevel(), cert_chain_[0].encodedCertificate));
+
+        CheckedDeleteKey(&key_blob);
+    }
+
+    // Device attestation IDs should be rejected for normal attestation requests; these fields
+    // are only used for device unique attestation.
+    auto invalid_tags = AuthorizationSetBuilder()
+                                .Authorization(TAG_ATTESTATION_ID_BRAND, "brand")
+                                .Authorization(TAG_ATTESTATION_ID_DEVICE, "device")
+                                .Authorization(TAG_ATTESTATION_ID_PRODUCT, "product")
+                                .Authorization(TAG_ATTESTATION_ID_SERIAL, "serial")
+                                .Authorization(TAG_ATTESTATION_ID_IMEI, "imei")
+                                .Authorization(TAG_ATTESTATION_ID_MEID, "meid")
+                                .Authorization(TAG_ATTESTATION_ID_MANUFACTURER, "manufacturer")
+                                .Authorization(TAG_ATTESTATION_ID_MODEL, "model");
+    for (const KeyParameter& tag : invalid_tags) {
+        SCOPED_TRACE(testing::Message() << "tag-" << tag);
+        vector<uint8_t> key_blob;
+        vector<KeyCharacteristics> key_characteristics;
+        AuthorizationSetBuilder builder =
+                AuthorizationSetBuilder()
+                        .Authorization(TAG_NO_AUTH_REQUIRED)
+                        .EcdsaSigningKey(EcCurve::P_256)
+                        .Digest(Digest::NONE)
+                        .AttestationChallenge(challenge)
+                        .AttestationApplicationId(app_id)
+                        .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
+                        .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
+                        .SetDefaultValidity();
+        builder.push_back(tag);
+        ASSERT_EQ(ErrorCode::CANNOT_ATTEST_IDS,
+                  GenerateKey(builder, &key_blob, &key_characteristics));
+    }
+}
+
+/*
+ * NewKeyGenerationTest.EcdsaAttestationTagNoApplicationId
+ *
+ * Verifies that creation of an attested ECDSA key does not include APPLICATION_ID.
+ */
+TEST_P(NewKeyGenerationTest, EcdsaAttestationTagNoApplicationId) {
+    auto challenge = "hello";
+    auto attest_app_id = "foo";
+    auto subject = "cert subj 2";
+    vector<uint8_t> subject_der(make_name_from_str(subject));
+    uint64_t serial_int = 0x1010;
+    vector<uint8_t> serial_blob(build_serial_blob(serial_int));
+
+    // Earlier versions of the attestation extension schema included a slot:
+    //     applicationId  [601] EXPLICIT OCTET_STRING OPTIONAL,
+    // This should never have been included, and should never be filled in.
+    // Generate an attested key that include APPLICATION_ID and APPLICATION_DATA,
+    // to confirm that this field never makes it into the attestation extension.
+    vector<uint8_t> key_blob;
+    vector<KeyCharacteristics> key_characteristics;
+    auto result = GenerateKey(AuthorizationSetBuilder()
+                                      .Authorization(TAG_NO_AUTH_REQUIRED)
+                                      .EcdsaSigningKey(EcCurve::P_256)
+                                      .Digest(Digest::NONE)
+                                      .AttestationChallenge(challenge)
+                                      .AttestationApplicationId(attest_app_id)
+                                      .Authorization(TAG_APPLICATION_ID, "client_id")
+                                      .Authorization(TAG_APPLICATION_DATA, "appdata")
+                                      .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
+                                      .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
+                                      .SetDefaultValidity(),
+                              &key_blob, &key_characteristics);
+    ASSERT_EQ(result, ErrorCode::OK);
+    ASSERT_GT(key_blob.size(), 0U);
+
+    EXPECT_TRUE(ChainSignaturesAreValid(cert_chain_));
+    ASSERT_GT(cert_chain_.size(), 0);
+    verify_subject_and_serial(cert_chain_[0], serial_int, subject, /* self_signed = */ false);
+
+    AuthorizationSet hw_enforced = HwEnforcedAuthorizations(key_characteristics);
+    AuthorizationSet sw_enforced = SwEnforcedAuthorizations(key_characteristics);
+    EXPECT_TRUE(verify_attestation_record(challenge, attest_app_id, sw_enforced, hw_enforced,
+                                          SecLevel(), cert_chain_[0].encodedCertificate));
+
+    // Check that the app id is not in the cert.
+    string app_id = "clientid";
+    std::vector<uint8_t> needle(reinterpret_cast<const uint8_t*>(app_id.data()),
+                                reinterpret_cast<const uint8_t*>(app_id.data()) + app_id.size());
+    ASSERT_EQ(std::search(cert_chain_[0].encodedCertificate.begin(),
+                          cert_chain_[0].encodedCertificate.end(), needle.begin(), needle.end()),
+              cert_chain_[0].encodedCertificate.end());
+
+    CheckedDeleteKey(&key_blob);
+}
+
+/*
  * NewKeyGenerationTest.EcdsaSelfSignAttestation
  *
  * Verifies that if no challenge is provided to an Ecdsa key generation, then
@@ -1451,12 +1615,12 @@
     uint64_t serial_int = 0x123456FFF1234;
     vector<uint8_t> serial_blob(build_serial_blob(serial_int));
 
-    for (auto key_size : ValidKeySizes(Algorithm::EC)) {
+    for (auto curve : ValidCurves()) {
         vector<uint8_t> key_blob;
         vector<KeyCharacteristics> key_characteristics;
         ASSERT_EQ(ErrorCode::OK,
                   GenerateKey(AuthorizationSetBuilder()
-                                      .EcdsaSigningKey(key_size)
+                                      .EcdsaSigningKey(curve)
                                       .Digest(Digest::NONE)
                                       .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
                                       .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
@@ -1469,8 +1633,7 @@
         AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
 
         EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::EC));
-        EXPECT_TRUE(crypto_params.Contains(TAG_KEY_SIZE, key_size))
-                << "Key size " << key_size << "missing";
+        EXPECT_TRUE(crypto_params.Contains(TAG_EC_CURVE, curve)) << "Curve " << curve << "missing";
 
         EXPECT_TRUE(ChainSignaturesAreValid(cert_chain_));
         verify_subject_and_serial(cert_chain_[0], serial_int, subject, false);
@@ -1512,11 +1675,11 @@
 TEST_P(NewKeyGenerationTest, EcdsaIgnoreAppId) {
     auto app_id = "foo";
 
-    for (auto key_size : ValidKeySizes(Algorithm::EC)) {
+    for (auto curve : ValidCurves()) {
         vector<uint8_t> key_blob;
         vector<KeyCharacteristics> key_characteristics;
         ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
-                                                     .EcdsaSigningKey(key_size)
+                                                     .EcdsaSigningKey(curve)
                                                      .Digest(Digest::NONE)
                                                      .AttestationApplicationId(app_id)
                                                      .SetDefaultValidity(),
@@ -1529,8 +1692,7 @@
         AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
 
         EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::EC));
-        EXPECT_TRUE(crypto_params.Contains(TAG_KEY_SIZE, key_size))
-                << "Key size " << key_size << "missing";
+        EXPECT_TRUE(crypto_params.Contains(TAG_EC_CURVE, curve)) << "Curve " << curve << "missing";
 
         EXPECT_TRUE(ChainSignaturesAreValid(cert_chain_));
         ASSERT_EQ(cert_chain_.size(), 1);
@@ -1552,7 +1714,6 @@
  */
 TEST_P(NewKeyGenerationTest, AttestationApplicationIDLengthProperlyEncoded) {
     auto challenge = "hello";
-    auto key_size = 256;
     std::vector<uint32_t> app_id_lengths{143, 258};
 
     for (uint32_t length : app_id_lengths) {
@@ -1561,7 +1722,7 @@
         vector<KeyCharacteristics> key_characteristics;
         ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
                                                      .Authorization(TAG_NO_AUTH_REQUIRED)
-                                                     .EcdsaSigningKey(key_size)
+                                                     .EcdsaSigningKey(EcCurve::P_256)
                                                      .Digest(Digest::NONE)
                                                      .AttestationChallenge(challenge)
                                                      .AttestationApplicationId(app_id)
@@ -1574,8 +1735,7 @@
         AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
 
         EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::EC));
-        EXPECT_TRUE(crypto_params.Contains(TAG_KEY_SIZE, key_size))
-                << "Key size " << key_size << "missing";
+        EXPECT_TRUE(crypto_params.Contains(TAG_EC_CURVE, EcCurve::P_256)) << "Curve P256 missing";
 
         EXPECT_TRUE(ChainSignaturesAreValid(cert_chain_));
         ASSERT_GT(cert_chain_.size(), 0);
@@ -1597,11 +1757,11 @@
  * resulting keys have correct characteristics.
  */
 TEST_P(NewKeyGenerationTest, LimitedUsageEcdsa) {
-    for (auto key_size : ValidKeySizes(Algorithm::EC)) {
+    for (auto curve : ValidCurves()) {
         vector<uint8_t> key_blob;
         vector<KeyCharacteristics> key_characteristics;
         ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
-                                                     .EcdsaSigningKey(key_size)
+                                                     .EcdsaSigningKey(curve)
                                                      .Digest(Digest::NONE)
                                                      .Authorization(TAG_USAGE_COUNT_LIMIT, 1)
                                                      .SetDefaultValidity(),
@@ -1614,8 +1774,7 @@
         AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
 
         EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::EC));
-        EXPECT_TRUE(crypto_params.Contains(TAG_KEY_SIZE, key_size))
-                << "Key size " << key_size << "missing";
+        EXPECT_TRUE(crypto_params.Contains(TAG_EC_CURVE, curve)) << "Curve " << curve << "missing";
 
         // Check the usage count limit tag appears in the authorizations.
         AuthorizationSet auths;
@@ -1632,7 +1791,7 @@
 /*
  * NewKeyGenerationTest.EcdsaDefaultSize
  *
- * Verifies that failing to specify a key size for EC key generation returns
+ * Verifies that failing to specify a curve for EC key generation returns
  * UNSUPPORTED_KEY_SIZE.
  */
 TEST_P(NewKeyGenerationTest, EcdsaDefaultSize) {
@@ -1651,20 +1810,23 @@
  * UNSUPPORTED_KEY_SIZE.
  */
 TEST_P(NewKeyGenerationTest, EcdsaInvalidSize) {
-    for (auto key_size : InvalidKeySizes(Algorithm::EC)) {
+    for (auto curve : InvalidCurves()) {
         vector<uint8_t> key_blob;
         vector<KeyCharacteristics> key_characteristics;
         ASSERT_EQ(ErrorCode::UNSUPPORTED_KEY_SIZE, GenerateKey(AuthorizationSetBuilder()
-                                                                       .EcdsaSigningKey(key_size)
+                                                                       .EcdsaSigningKey(curve)
                                                                        .Digest(Digest::NONE)
                                                                        .SetDefaultValidity(),
                                                                &key_blob, &key_characteristics));
     }
 
-    ASSERT_EQ(ErrorCode::UNSUPPORTED_KEY_SIZE, GenerateKey(AuthorizationSetBuilder()
-                                                                   .EcdsaSigningKey(190)
-                                                                   .Digest(Digest::NONE)
-                                                                   .SetDefaultValidity()));
+    ASSERT_EQ(ErrorCode::UNSUPPORTED_KEY_SIZE,
+              GenerateKey(AuthorizationSetBuilder()
+                                  .Authorization(TAG_ALGORITHM, Algorithm::EC)
+                                  .Authorization(TAG_KEY_SIZE, 190)
+                                  .SigningKey()
+                                  .Digest(Digest::NONE)
+                                  .SetDefaultValidity()));
 }
 
 /*
@@ -1676,29 +1838,13 @@
 TEST_P(NewKeyGenerationTest, EcdsaMismatchKeySize) {
     if (SecLevel() == SecurityLevel::STRONGBOX) return;
 
-    ASSERT_EQ(ErrorCode::INVALID_ARGUMENT,
-              GenerateKey(AuthorizationSetBuilder()
-                                  .EcdsaSigningKey(224)
-                                  .Authorization(TAG_EC_CURVE, EcCurve::P_256)
-                                  .Digest(Digest::NONE)
-                                  .SetDefaultValidity()));
-}
-
-/*
- * NewKeyGenerationTest.EcdsaAllValidSizes
- *
- * Verifies that keymint supports all required EC key sizes.
- */
-TEST_P(NewKeyGenerationTest, EcdsaAllValidSizes) {
-    auto valid_sizes = ValidKeySizes(Algorithm::EC);
-    for (size_t size : valid_sizes) {
-        EXPECT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
-                                                     .EcdsaSigningKey(size)
-                                                     .Digest(Digest::NONE)
-                                                     .SetDefaultValidity()))
-                << "Failed to generate size: " << size;
-        CheckedDeleteKey();
-    }
+    auto result = GenerateKey(AuthorizationSetBuilder()
+                                      .Authorization(TAG_KEY_SIZE, 224)
+                                      .Authorization(TAG_EC_CURVE, EcCurve::P_256)
+                                      .Digest(Digest::NONE)
+                                      .SetDefaultValidity());
+    ASSERT_TRUE(result == ErrorCode::INVALID_ARGUMENT ||
+                result == ErrorCode::UNSUPPORTED_ALGORITHM);
 }
 
 /*
@@ -2471,31 +2617,6 @@
 }
 
 /*
- * SigningOperationsTest.EcdsaAllSizesAndHashes
- *
- * Verifies that ECDSA operations succeed with all possible key sizes and hashes.
- */
-TEST_P(SigningOperationsTest, EcdsaAllSizesAndHashes) {
-    for (auto key_size : ValidKeySizes(Algorithm::EC)) {
-        for (auto digest : ValidDigests(false /* withNone */, false /* withMD5 */)) {
-            ErrorCode error = GenerateKey(AuthorizationSetBuilder()
-                                                  .Authorization(TAG_NO_AUTH_REQUIRED)
-                                                  .EcdsaSigningKey(key_size)
-                                                  .Digest(digest)
-                                                  .SetDefaultValidity());
-            EXPECT_EQ(ErrorCode::OK, error) << "Failed to generate ECDSA key with size " << key_size
-                                            << " and digest " << digest;
-            if (error != ErrorCode::OK) continue;
-
-            string message(1024, 'a');
-            if (digest == Digest::NONE) message.resize(key_size / 8);
-            SignMessage(message, AuthorizationSetBuilder().Digest(digest));
-            CheckedDeleteKey();
-        }
-    }
-}
-
-/*
  * SigningOperationsTest.EcdsaAllDigestsAndCurves
  *
  * Verifies ECDSA signature/verification for all digests and curves.
@@ -2560,7 +2681,7 @@
 TEST_P(SigningOperationsTest, EcdsaNoDigestHugeData) {
     ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
                                                  .Authorization(TAG_NO_AUTH_REQUIRED)
-                                                 .EcdsaSigningKey(256)
+                                                 .EcdsaSigningKey(EcCurve::P_256)
                                                  .Digest(Digest::NONE)
                                                  .SetDefaultValidity()));
     string message(1 * 1024, 'a');
@@ -2575,7 +2696,7 @@
 TEST_P(SigningOperationsTest, EcUseRequiresCorrectAppIdAppData) {
     ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
                                                  .Authorization(TAG_NO_AUTH_REQUIRED)
-                                                 .EcdsaSigningKey(256)
+                                                 .EcdsaSigningKey(EcCurve::P_256)
                                                  .Digest(Digest::NONE)
                                                  .Authorization(TAG_APPLICATION_ID, "clientid")
                                                  .Authorization(TAG_APPLICATION_DATA, "appdata")
@@ -2612,7 +2733,7 @@
 TEST_P(SigningOperationsTest, EcdsaIncompatibleDigest) {
     ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
                                                  .Authorization(TAG_NO_AUTH_REQUIRED)
-                                                 .EcdsaSigningKey(256)
+                                                 .EcdsaSigningKey(EcCurve::P_256)
                                                  .Digest(Digest::NONE)
                                                  .Digest(Digest::SHA1)
                                                  .SetDefaultValidity()));
@@ -3000,13 +3121,12 @@
 TEST_P(ImportKeyTest, EcdsaSuccess) {
     ASSERT_EQ(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
                                                .Authorization(TAG_NO_AUTH_REQUIRED)
-                                               .EcdsaSigningKey(256)
+                                               .EcdsaSigningKey(EcCurve::P_256)
                                                .Digest(Digest::SHA_2_256)
                                                .SetDefaultValidity(),
                                        KeyFormat::PKCS8, ec_256_key));
 
     CheckCryptoParam(TAG_ALGORITHM, Algorithm::EC);
-    CheckCryptoParam(TAG_KEY_SIZE, 256U);
     CheckCryptoParam(TAG_DIGEST, Digest::SHA_2_256);
     CheckCryptoParam(TAG_EC_CURVE, EcCurve::P_256);
 
@@ -3027,13 +3147,12 @@
 TEST_P(ImportKeyTest, EcdsaP256RFC5915Success) {
     ASSERT_EQ(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
                                                .Authorization(TAG_NO_AUTH_REQUIRED)
-                                               .EcdsaSigningKey(256)
+                                               .EcdsaSigningKey(EcCurve::P_256)
                                                .Digest(Digest::SHA_2_256)
                                                .SetDefaultValidity(),
                                        KeyFormat::PKCS8, ec_256_key_rfc5915));
 
     CheckCryptoParam(TAG_ALGORITHM, Algorithm::EC);
-    CheckCryptoParam(TAG_KEY_SIZE, 256U);
     CheckCryptoParam(TAG_DIGEST, Digest::SHA_2_256);
     CheckCryptoParam(TAG_EC_CURVE, EcCurve::P_256);
 
@@ -3053,13 +3172,12 @@
 TEST_P(ImportKeyTest, EcdsaP256SEC1Success) {
     ASSERT_EQ(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
                                                .Authorization(TAG_NO_AUTH_REQUIRED)
-                                               .EcdsaSigningKey(256)
+                                               .EcdsaSigningKey(EcCurve::P_256)
                                                .Digest(Digest::SHA_2_256)
                                                .SetDefaultValidity(),
                                        KeyFormat::PKCS8, ec_256_key_sec1));
 
     CheckCryptoParam(TAG_ALGORITHM, Algorithm::EC);
-    CheckCryptoParam(TAG_KEY_SIZE, 256U);
     CheckCryptoParam(TAG_DIGEST, Digest::SHA_2_256);
     CheckCryptoParam(TAG_EC_CURVE, EcCurve::P_256);
 
@@ -3080,13 +3198,12 @@
     if (SecLevel() == SecurityLevel::STRONGBOX) return;
     ASSERT_EQ(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
                                                .Authorization(TAG_NO_AUTH_REQUIRED)
-                                               .EcdsaSigningKey(521)
+                                               .EcdsaSigningKey(EcCurve::P_521)
                                                .Digest(Digest::SHA_2_256)
                                                .SetDefaultValidity(),
                                        KeyFormat::PKCS8, ec_521_key));
 
     CheckCryptoParam(TAG_ALGORITHM, Algorithm::EC);
-    CheckCryptoParam(TAG_KEY_SIZE, 521U);
     CheckCryptoParam(TAG_DIGEST, Digest::SHA_2_256);
     CheckCryptoParam(TAG_EC_CURVE, EcCurve::P_521);
     CheckOrigin();
@@ -3098,21 +3215,6 @@
 }
 
 /*
- * ImportKeyTest.EcdsaSizeMismatch
- *
- * Verifies that importing an ECDSA key pair with a size that doesn't match the key fails in the
- * correct way.
- */
-TEST_P(ImportKeyTest, EcdsaSizeMismatch) {
-    ASSERT_EQ(ErrorCode::IMPORT_PARAMETER_MISMATCH,
-              ImportKey(AuthorizationSetBuilder()
-                                .EcdsaSigningKey(224 /* Doesn't match key */)
-                                .Digest(Digest::NONE)
-                                .SetDefaultValidity(),
-                        KeyFormat::PKCS8, ec_256_key));
-}
-
-/*
  * ImportKeyTest.EcdsaCurveMismatch
  *
  * Verifies that importing an ECDSA key pair with a curve that doesn't match the key fails in
@@ -3975,7 +4077,7 @@
 TEST_P(EncryptionOperationsTest, EcdsaEncrypt) {
     ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
                                                  .Authorization(TAG_NO_AUTH_REQUIRED)
-                                                 .EcdsaSigningKey(256)
+                                                 .EcdsaSigningKey(EcCurve::P_256)
                                                  .Digest(Digest::NONE)
                                                  .SetDefaultValidity()));
     auto params = AuthorizationSetBuilder().Digest(Digest::NONE);
@@ -6418,7 +6520,7 @@
     ASSERT_EQ(ErrorCode::EARLY_BOOT_ENDED, ImportKey(AuthorizationSetBuilder()
                                                              .Authorization(TAG_NO_AUTH_REQUIRED)
                                                              .Authorization(TAG_EARLY_BOOT_ONLY)
-                                                             .EcdsaSigningKey(256)
+                                                             .EcdsaSigningKey(EcCurve::P_256)
                                                              .Digest(Digest::SHA_2_256)
                                                              .SetDefaultValidity(),
                                                      KeyFormat::PKCS8, ec_256_key));
diff --git a/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp b/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
index a177317..af951e8 100644
--- a/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
+++ b/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
@@ -29,6 +29,7 @@
 #include <openssl/ec_key.h>
 #include <openssl/x509.h>
 #include <remote_prov/remote_prov_utils.h>
+#include <vector>
 
 #include "KeyMintAidlTestBase.h"
 
@@ -102,8 +103,8 @@
     return std::move(corruptSig);
 }
 
-ErrMsgOr<EekChain> corrupt_sig_chain(const EekChain& eek, int which) {
-    auto [chain, _, parseErr] = cppbor::parse(eek.chain);
+ErrMsgOr<bytevec> corrupt_sig_chain(const bytevec& encodedEekChain, int which) {
+    auto [chain, _, parseErr] = cppbor::parse(encodedEekChain);
     if (!chain || !chain->asArray()) {
         return "EekChain parse failed";
     }
@@ -125,7 +126,7 @@
             corruptChain.add(eekChain->get(ii)->clone());
         }
     }
-    return EekChain{corruptChain.encode(), eek.last_pubkey, eek.last_privkey};
+    return corruptChain.encode();
 }
 
 string device_suffix(const string& name) {
@@ -271,14 +272,14 @@
 class CertificateRequestTest : public VtsRemotelyProvisionedComponentTests {
   protected:
     CertificateRequestTest() : eekId_(string_to_bytevec("eekid")), challenge_(randomBytes(32)) {
-        generateEek(3);
+        generateTestEekChain(3);
     }
 
-    void generateEek(size_t eekLength) {
+    void generateTestEekChain(size_t eekLength) {
         auto chain = generateEekChain(eekLength, eekId_);
         EXPECT_TRUE(chain) << chain.message();
-        if (chain) eekChain_ = chain.moveValue();
-        eekLength_ = eekLength;
+        if (chain) testEekChain_ = chain.moveValue();
+        testEekLength_ = eekLength;
     }
 
     void generateKeys(bool testMode, size_t numKeys) {
@@ -297,7 +298,8 @@
     }
 
     void checkProtectedData(const DeviceInfo& deviceInfo, const cppbor::Array& keysToSign,
-                            const bytevec& keysToSignMac, const ProtectedData& protectedData) {
+                            const bytevec& keysToSignMac, const ProtectedData& protectedData,
+                            std::vector<BccEntryData>* bccOutput = nullptr) {
         auto [parsedProtectedData, _, protDataErrMsg] = cppbor::parse(protectedData.protectedData);
         ASSERT_TRUE(parsedProtectedData) << protDataErrMsg;
         ASSERT_TRUE(parsedProtectedData->asArray());
@@ -307,8 +309,9 @@
         ASSERT_TRUE(senderPubkey) << senderPubkey.message();
         EXPECT_EQ(senderPubkey->second, eekId_);
 
-        auto sessionKey = x25519_HKDF_DeriveKey(eekChain_.last_pubkey, eekChain_.last_privkey,
-                                                senderPubkey->first, false /* senderIsA */);
+        auto sessionKey =
+                x25519_HKDF_DeriveKey(testEekChain_.last_pubkey, testEekChain_.last_privkey,
+                                      senderPubkey->first, false /* senderIsA */);
         ASSERT_TRUE(sessionKey) << sessionKey.message();
 
         auto protectedDataPayload =
@@ -335,8 +338,7 @@
         ASSERT_TRUE(deviceInfoMap->asMap());
 
         auto& signingKey = bccContents->back().pubKey;
-        auto macKey = verifyAndParseCoseSign1(/* ignore_signature = */ false, signedMac->asArray(),
-                                              signingKey,
+        auto macKey = verifyAndParseCoseSign1(signedMac->asArray(), signingKey,
                                               cppbor::Array()  // SignedMacAad
                                                       .add(challenge_)
                                                       .add(std::move(deviceInfoMap))
@@ -355,11 +357,15 @@
 
         auto macPayload = verifyAndParseCoseMac0(&coseMac0, *macKey);
         ASSERT_TRUE(macPayload) << macPayload.message();
+
+        if (bccOutput) {
+            *bccOutput = std::move(*bccContents);
+        }
     }
 
     bytevec eekId_;
-    size_t eekLength_;
-    EekChain eekChain_;
+    size_t testEekLength_;
+    EekChain testEekChain_;
     bytevec challenge_;
     std::vector<MacedPublicKey> keysToSign_;
     cppbor::Array cborKeysToSign_;
@@ -373,13 +379,13 @@
     bool testMode = true;
     for (size_t eekLength : {2, 3, 7}) {
         SCOPED_TRACE(testing::Message() << "EEK of length " << eekLength);
-        generateEek(eekLength);
+        generateTestEekChain(eekLength);
 
         bytevec keysToSignMac;
         DeviceInfo deviceInfo;
         ProtectedData protectedData;
         auto status = provisionable_->generateCertificateRequest(
-                testMode, {} /* keysToSign */, eekChain_.chain, challenge_, &deviceInfo,
+                testMode, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo,
                 &protectedData, &keysToSignMac);
         ASSERT_TRUE(status.isOk()) << status.getMessage();
 
@@ -388,31 +394,62 @@
 }
 
 /**
- * Generate an empty certificate request in prod mode.  Generation will fail because we don't have a
- * valid GEEK.
- *
- * TODO(swillden): Get a valid GEEK and use it so the generation can succeed, though we won't be
- * able to decrypt.
+ * Ensure that test mode outputs a unique BCC root key every time we request a
+ * certificate request. Else, it's possible that the test mode API could be used
+ * to fingerprint devices. Only the GEEK should be allowed to decrypt the same
+ * device public key multiple times.
  */
-TEST_P(CertificateRequestTest, EmptyRequest_prodMode) {
-    bool testMode = false;
-    for (size_t eekLength : {2, 3, 7}) {
-        SCOPED_TRACE(testing::Message() << "EEK of length " << eekLength);
-        generateEek(eekLength);
+TEST_P(CertificateRequestTest, NewKeyPerCallInTestMode) {
+    constexpr bool testMode = true;
 
-        bytevec keysToSignMac;
-        DeviceInfo deviceInfo;
-        ProtectedData protectedData;
-        auto status = provisionable_->generateCertificateRequest(
-                testMode, {} /* keysToSign */, eekChain_.chain, challenge_, &deviceInfo,
-                &protectedData, &keysToSignMac);
-        EXPECT_FALSE(status.isOk());
-        EXPECT_EQ(status.getServiceSpecificError(),
-                  BnRemotelyProvisionedComponent::STATUS_INVALID_EEK);
+    bytevec keysToSignMac;
+    DeviceInfo deviceInfo;
+    ProtectedData protectedData;
+    auto status = provisionable_->generateCertificateRequest(
+            testMode, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo,
+            &protectedData, &keysToSignMac);
+    ASSERT_TRUE(status.isOk()) << status.getMessage();
+
+    std::vector<BccEntryData> firstBcc;
+    checkProtectedData(deviceInfo, /*keysToSign=*/cppbor::Array(), keysToSignMac, protectedData,
+                       &firstBcc);
+
+    status = provisionable_->generateCertificateRequest(
+            testMode, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo,
+            &protectedData, &keysToSignMac);
+    ASSERT_TRUE(status.isOk()) << status.getMessage();
+
+    std::vector<BccEntryData> secondBcc;
+    checkProtectedData(deviceInfo, /*keysToSign=*/cppbor::Array(), keysToSignMac, protectedData,
+                       &secondBcc);
+
+    // Verify that none of the keys in the first BCC are repeated in the second one.
+    for (const auto& i : firstBcc) {
+        for (auto& j : secondBcc) {
+            ASSERT_THAT(i.pubKey, testing::Not(testing::ElementsAreArray(j.pubKey)))
+                    << "Found a repeated pubkey in two generateCertificateRequest test mode calls";
+        }
     }
 }
 
 /**
+ * Generate an empty certificate request in prod mode. This test must be run explicitly, and
+ * is not run by default. Not all devices are GMS devices, and therefore they do not all
+ * trust the Google EEK root.
+ */
+TEST_P(CertificateRequestTest, DISABLED_EmptyRequest_prodMode) {
+    bool testMode = false;
+
+    bytevec keysToSignMac;
+    DeviceInfo deviceInfo;
+    ProtectedData protectedData;
+    auto status = provisionable_->generateCertificateRequest(
+            testMode, {} /* keysToSign */, getProdEekChain(), challenge_, &deviceInfo,
+            &protectedData, &keysToSignMac);
+    EXPECT_TRUE(status.isOk());
+}
+
+/**
  * Generate a non-empty certificate request in test mode.  Decrypt, parse and validate the contents.
  */
 TEST_P(CertificateRequestTest, NonEmptyRequest_testMode) {
@@ -421,13 +458,13 @@
 
     for (size_t eekLength : {2, 3, 7}) {
         SCOPED_TRACE(testing::Message() << "EEK of length " << eekLength);
-        generateEek(eekLength);
+        generateTestEekChain(eekLength);
 
         bytevec keysToSignMac;
         DeviceInfo deviceInfo;
         ProtectedData protectedData;
         auto status = provisionable_->generateCertificateRequest(
-                testMode, keysToSign_, eekChain_.chain, challenge_, &deviceInfo, &protectedData,
+                testMode, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo, &protectedData,
                 &keysToSignMac);
         ASSERT_TRUE(status.isOk()) << status.getMessage();
 
@@ -436,30 +473,21 @@
 }
 
 /**
- * Generate a non-empty certificate request in prod mode.  Must fail because we don't have a valid
- * GEEK.
- *
- * TODO(swillden): Get a valid GEEK and use it so the generation can succeed, though we won't be
- * able to decrypt.
+ * Generate a non-empty certificate request in prod mode. This test must be run explicitly, and
+ * is not run by default. Not all devices are GMS devices, and therefore they do not all
+ * trust the Google EEK root.
  */
-TEST_P(CertificateRequestTest, NonEmptyRequest_prodMode) {
+TEST_P(CertificateRequestTest, DISABLED_NonEmptyRequest_prodMode) {
     bool testMode = false;
     generateKeys(testMode, 4 /* numKeys */);
 
-    for (size_t eekLength : {2, 3, 7}) {
-        SCOPED_TRACE(testing::Message() << "EEK of length " << eekLength);
-        generateEek(eekLength);
-
-        bytevec keysToSignMac;
-        DeviceInfo deviceInfo;
-        ProtectedData protectedData;
-        auto status = provisionable_->generateCertificateRequest(
-                testMode, keysToSign_, eekChain_.chain, challenge_, &deviceInfo, &protectedData,
-                &keysToSignMac);
-        EXPECT_FALSE(status.isOk());
-        EXPECT_EQ(status.getServiceSpecificError(),
-                  BnRemotelyProvisionedComponent::STATUS_INVALID_EEK);
-    }
+    bytevec keysToSignMac;
+    DeviceInfo deviceInfo;
+    ProtectedData protectedData;
+    auto status = provisionable_->generateCertificateRequest(
+            testMode, keysToSign_, getProdEekChain(), challenge_, &deviceInfo, &protectedData,
+            &keysToSignMac);
+    EXPECT_TRUE(status.isOk());
 }
 
 /**
@@ -474,8 +502,8 @@
     DeviceInfo deviceInfo;
     ProtectedData protectedData;
     auto status = provisionable_->generateCertificateRequest(
-            testMode, {keyWithCorruptMac}, eekChain_.chain, challenge_, &deviceInfo, &protectedData,
-            &keysToSignMac);
+            testMode, {keyWithCorruptMac}, testEekChain_.chain, challenge_, &deviceInfo,
+            &protectedData, &keysToSignMac);
     ASSERT_FALSE(status.isOk()) << status.getMessage();
     EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_MAC);
 }
@@ -484,7 +512,7 @@
  * Generate a non-empty certificate request in prod mode, but with the MAC corrupted on the keypair.
  */
 TEST_P(CertificateRequestTest, NonEmptyRequestCorruptMac_prodMode) {
-    bool testMode = true;
+    bool testMode = false;
     generateKeys(testMode, 1 /* numKeys */);
     MacedPublicKey keyWithCorruptMac = corrupt_maced_key(keysToSign_[0]).moveValue();
 
@@ -492,38 +520,35 @@
     DeviceInfo deviceInfo;
     ProtectedData protectedData;
     auto status = provisionable_->generateCertificateRequest(
-            testMode, {keyWithCorruptMac}, eekChain_.chain, challenge_, &deviceInfo, &protectedData,
-            &keysToSignMac);
+            testMode, {keyWithCorruptMac}, getProdEekChain(), challenge_, &deviceInfo,
+            &protectedData, &keysToSignMac);
     ASSERT_FALSE(status.isOk()) << status.getMessage();
-    auto rc = status.getServiceSpecificError();
-
-    // TODO(drysdale): drop the INVALID_EEK potential error code when a real GEEK is available.
-    EXPECT_TRUE(rc == BnRemotelyProvisionedComponent::STATUS_INVALID_EEK ||
-                rc == BnRemotelyProvisionedComponent::STATUS_INVALID_MAC);
+    EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_MAC);
 }
 
 /**
  * Generate a non-empty certificate request in prod mode that has a corrupt EEK chain.
  * Confirm that the request is rejected.
- *
- * TODO(drysdale): Update to use a valid GEEK, so that the test actually confirms that the
- * implementation is checking signatures.
  */
 TEST_P(CertificateRequestTest, NonEmptyCorruptEekRequest_prodMode) {
     bool testMode = false;
     generateKeys(testMode, 4 /* numKeys */);
 
-    for (size_t ii = 0; ii < eekLength_; ii++) {
-        auto chain = corrupt_sig_chain(eekChain_, ii);
+    auto prodEekChain = getProdEekChain();
+    auto [parsedChain, _, parseErr] = cppbor::parse(prodEekChain);
+    ASSERT_NE(parsedChain, nullptr) << parseErr;
+    ASSERT_NE(parsedChain->asArray(), nullptr);
+
+    for (int ii = 0; ii < parsedChain->asArray()->size(); ++ii) {
+        auto chain = corrupt_sig_chain(prodEekChain, ii);
         ASSERT_TRUE(chain) << chain.message();
-        EekChain corruptEek = chain.moveValue();
 
         bytevec keysToSignMac;
         DeviceInfo deviceInfo;
         ProtectedData protectedData;
-        auto status = provisionable_->generateCertificateRequest(
-                testMode, keysToSign_, corruptEek.chain, challenge_, &deviceInfo, &protectedData,
-                &keysToSignMac);
+        auto status = provisionable_->generateCertificateRequest(testMode, keysToSign_, *chain,
+                                                                 challenge_, &deviceInfo,
+                                                                 &protectedData, &keysToSignMac);
         ASSERT_FALSE(status.isOk());
         ASSERT_EQ(status.getServiceSpecificError(),
                   BnRemotelyProvisionedComponent::STATUS_INVALID_EEK);
@@ -533,9 +558,6 @@
 /**
  * Generate a non-empty certificate request in prod mode that has an incomplete EEK chain.
  * Confirm that the request is rejected.
- *
- * TODO(drysdale): Update to use a valid GEEK, so that the test actually confirms that the
- * implementation is checking signatures.
  */
 TEST_P(CertificateRequestTest, NonEmptyIncompleteEekRequest_prodMode) {
     bool testMode = false;
@@ -543,7 +565,7 @@
 
     // Build an EEK chain that omits the first self-signed cert.
     auto truncatedChain = cppbor::Array();
-    auto [chain, _, parseErr] = cppbor::parse(eekChain_.chain);
+    auto [chain, _, parseErr] = cppbor::parse(getProdEekChain());
     ASSERT_TRUE(chain);
     auto eekChain = chain->asArray();
     ASSERT_NE(eekChain, nullptr);
@@ -572,7 +594,7 @@
     DeviceInfo deviceInfo;
     ProtectedData protectedData;
     auto status = provisionable_->generateCertificateRequest(
-            true /* testMode */, keysToSign_, eekChain_.chain, challenge_, &deviceInfo,
+            true /* testMode */, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo,
             &protectedData, &keysToSignMac);
     ASSERT_FALSE(status.isOk());
     ASSERT_EQ(status.getServiceSpecificError(),
@@ -590,7 +612,7 @@
     DeviceInfo deviceInfo;
     ProtectedData protectedData;
     auto status = provisionable_->generateCertificateRequest(
-            false /* testMode */, keysToSign_, eekChain_.chain, challenge_, &deviceInfo,
+            false /* testMode */, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo,
             &protectedData, &keysToSignMac);
     ASSERT_FALSE(status.isOk());
     ASSERT_EQ(status.getServiceSpecificError(),
diff --git a/security/keymint/support/Android.bp b/security/keymint/support/Android.bp
index 718133a..9e218b6 100644
--- a/security/keymint/support/Android.bp
+++ b/security/keymint/support/Android.bp
@@ -57,8 +57,28 @@
         "include",
     ],
     shared_libs: [
+        "libbase",
         "libcppbor_external",
         "libcppcose_rkp",
         "libcrypto",
+        "libjsoncpp",
+    ],
+}
+
+cc_test {
+    name: "libkeymint_remote_prov_support_test",
+    srcs: ["remote_prov_utils_test.cpp"],
+    static_libs: [
+        "libgmock",
+        "libgtest_main",
+    ],
+    shared_libs: [
+        "libbase",
+        "libcppbor_external",
+        "libcppcose_rkp",
+        "libcrypto",
+        "libjsoncpp",
+        "libkeymaster_portable",
+        "libkeymint_remote_prov_support",
     ],
 }
diff --git a/security/keymint/support/include/remote_prov/remote_prov_utils.h b/security/keymint/support/include/remote_prov/remote_prov_utils.h
index e4261f3..406b7a9 100644
--- a/security/keymint/support/include/remote_prov/remote_prov_utils.h
+++ b/security/keymint/support/include/remote_prov/remote_prov_utils.h
@@ -27,6 +27,31 @@
 
 extern bytevec kTestMacKey;
 
+// The Google root key for the Endpoint Encryption Key chain, encoded as COSE_Sign1
+inline constexpr uint8_t kCoseEncodedRootCert[] = {
+        0x84, 0x43, 0xa1, 0x01, 0x27, 0xa0, 0x58, 0x2a, 0xa4, 0x01, 0x01, 0x03, 0x27, 0x20, 0x06,
+        0x21, 0x58, 0x20, 0x99, 0xb9, 0xee, 0xdd, 0x5e, 0xe4, 0x52, 0xf6, 0x85, 0xc6, 0x4c, 0x62,
+        0xdc, 0x3e, 0x61, 0xab, 0x57, 0x48, 0x7d, 0x75, 0x37, 0x29, 0xad, 0x76, 0x80, 0x32, 0xd2,
+        0xb3, 0xcb, 0x63, 0x58, 0xd9, 0x58, 0x40, 0x1e, 0x22, 0x08, 0x4b, 0xa4, 0xb7, 0xa4, 0xc8,
+        0xd7, 0x4e, 0x03, 0x0e, 0xfe, 0xb8, 0xaf, 0x14, 0x4c, 0xa7, 0x3b, 0x6f, 0xa5, 0xcd, 0xdc,
+        0xda, 0x79, 0xc6, 0x2b, 0x64, 0xfe, 0x99, 0x39, 0xaf, 0x76, 0xe7, 0x80, 0xfa, 0x66, 0x00,
+        0x85, 0x0d, 0x07, 0x98, 0x2a, 0xac, 0x91, 0x5c, 0xa7, 0x25, 0x14, 0x49, 0x06, 0x34, 0x75,
+        0xca, 0x8a, 0x27, 0x7a, 0xd9, 0xe3, 0x5a, 0x49, 0xeb, 0x02, 0x03};
+
+// The Google Endpoint Encryption Key certificate, encoded as COSE_Sign1
+inline constexpr uint8_t kCoseEncodedGeekCert[] = {
+        0x84, 0x43, 0xa1, 0x01, 0x27, 0xa0, 0x58, 0x4e, 0xa5, 0x01, 0x01, 0x02, 0x58, 0x20,
+        0xd0, 0xae, 0xc1, 0x15, 0xca, 0x2a, 0xcf, 0x73, 0xae, 0x6b, 0xcc, 0xcb, 0xd1, 0x96,
+        0x1d, 0x65, 0xe8, 0xb1, 0xdd, 0xd7, 0x4a, 0x1a, 0x37, 0xb9, 0x43, 0x3a, 0x97, 0xd5,
+        0x99, 0xdf, 0x98, 0x08, 0x03, 0x38, 0x18, 0x20, 0x04, 0x21, 0x58, 0x20, 0xbe, 0x85,
+        0xe7, 0x46, 0xc4, 0xa3, 0x42, 0x5a, 0x40, 0xd9, 0x36, 0x3a, 0xa6, 0x15, 0xd0, 0x2c,
+        0x58, 0x7e, 0x3d, 0xdc, 0x33, 0x02, 0x32, 0xd2, 0xfc, 0x5e, 0x1e, 0x87, 0x25, 0x5f,
+        0x72, 0x60, 0x58, 0x40, 0x9b, 0xcf, 0x90, 0xe2, 0x2e, 0x4b, 0xab, 0xd1, 0x18, 0xb1,
+        0x0e, 0x8e, 0x5d, 0x20, 0x27, 0x4b, 0x84, 0x58, 0xfe, 0xfc, 0x32, 0x90, 0x7e, 0x72,
+        0x05, 0x83, 0xbc, 0xd7, 0x82, 0xbe, 0xfa, 0x64, 0x78, 0x2d, 0x54, 0x10, 0x4b, 0xc0,
+        0x31, 0xbf, 0x6b, 0xe8, 0x1e, 0x35, 0xe2, 0xf0, 0x2d, 0xce, 0x6c, 0x2f, 0x4f, 0xf2,
+        0xf5, 0x4f, 0xa5, 0xd4, 0x83, 0xad, 0x96, 0xa2, 0xf1, 0x87, 0x58, 0x04};
+
 /**
  * Generates random bytes.
  */
@@ -44,6 +69,11 @@
  */
 ErrMsgOr<EekChain> generateEekChain(size_t length, const bytevec& eekId);
 
+/**
+ * Returns the CBOR-encoded, production Google Endpoint Encryption Key chain.
+ */
+bytevec getProdEekChain();
+
 struct BccEntryData {
     bytevec pubKey;
 };
@@ -57,4 +87,26 @@
  */
 ErrMsgOr<std::vector<BccEntryData>> validateBcc(const cppbor::Array* bcc);
 
+struct JsonOutput {
+    static JsonOutput Ok(std::string json) { return {std::move(json), ""}; }
+    static JsonOutput Error(std::string error) { return {"", std::move(error)}; }
+
+    std::string output;
+    std::string error;  // if non-empty, this describes what went wrong
+};
+
+/**
+ * Take a given certificate request and output a JSON blob containing both the
+ * build fingerprint and certificate request. This data may be serialized, then
+ * later uploaded to the remote provisioning service. The input csr is not
+ * validated, only encoded.
+ *
+ * Output format:
+ *   {
+ *     "build_fingerprint": <string>
+ *     "csr": <base64 CBOR CSR>
+ *   }
+ */
+JsonOutput jsonEncodeCsrWithBuild(const cppbor::Array& csr);
+
 }  // namespace aidl::android::hardware::security::keymint::remote_prov
diff --git a/security/keymint/support/remote_prov_utils.cpp b/security/keymint/support/remote_prov_utils.cpp
index da10eb2..0cbee51 100644
--- a/security/keymint/support/remote_prov_utils.cpp
+++ b/security/keymint/support/remote_prov_utils.cpp
@@ -14,11 +14,15 @@
  * limitations under the License.
  */
 
-#include <remote_prov/remote_prov_utils.h>
+#include <iterator>
+#include <tuple>
 
-#include <openssl/rand.h>
-
+#include <android-base/properties.h>
 #include <cppbor.h>
+#include <json/json.h>
+#include <openssl/base64.h>
+#include <openssl/rand.h>
+#include <remote_prov/remote_prov_utils.h>
 
 namespace aidl::android::hardware::security::keymint::remote_prov {
 
@@ -31,6 +35,10 @@
 }
 
 ErrMsgOr<EekChain> generateEekChain(size_t length, const bytevec& eekId) {
+    if (length < 2) {
+        return "EEK chain must contain at least 2 certs.";
+    }
+
     auto eekChain = cppbor::Array();
 
     bytevec prev_priv_key;
@@ -78,7 +86,19 @@
     return EekChain{eekChain.encode(), pub_key, priv_key};
 }
 
-ErrMsgOr<bytevec> verifyAndParseCoseSign1Cwt(bool ignoreSignature, const cppbor::Array* coseSign1,
+bytevec getProdEekChain() {
+    bytevec prodEek;
+    prodEek.reserve(1 + sizeof(kCoseEncodedRootCert) + sizeof(kCoseEncodedGeekCert));
+
+    // In CBOR encoding, 0x82 indicates an array of two items
+    prodEek.push_back(0x82);
+    prodEek.insert(prodEek.end(), std::begin(kCoseEncodedRootCert), std::end(kCoseEncodedRootCert));
+    prodEek.insert(prodEek.end(), std::begin(kCoseEncodedGeekCert), std::end(kCoseEncodedGeekCert));
+
+    return prodEek;
+}
+
+ErrMsgOr<bytevec> verifyAndParseCoseSign1Cwt(const cppbor::Array* coseSign1,
                                              const bytevec& signingCoseKey, const bytevec& aad) {
     if (!coseSign1 || coseSign1->size() != kCoseSign1EntryCount) {
         return "Invalid COSE_Sign1";
@@ -115,27 +135,22 @@
     auto serializedKey = parsedPayload->asMap()->get(-4670552)->clone();
     if (!serializedKey || !serializedKey->asBstr()) return "Could not find key entry";
 
-    if (!ignoreSignature) {
-        bool selfSigned = signingCoseKey.empty();
-        auto key = CoseKey::parseEd25519(selfSigned ? serializedKey->asBstr()->value()
-                                                    : signingCoseKey);
-        if (!key) return "Bad signing key: " + key.moveMessage();
+    bool selfSigned = signingCoseKey.empty();
+    auto key =
+            CoseKey::parseEd25519(selfSigned ? serializedKey->asBstr()->value() : signingCoseKey);
+    if (!key) return "Bad signing key: " + key.moveMessage();
 
-        bytevec signatureInput = cppbor::Array()
-                                         .add("Signature1")
-                                         .add(*protectedParams)
-                                         .add(aad)
-                                         .add(*payload)
-                                         .encode();
+    bytevec signatureInput =
+            cppbor::Array().add("Signature1").add(*protectedParams).add(aad).add(*payload).encode();
 
-        if (!ED25519_verify(signatureInput.data(), signatureInput.size(), signature->value().data(),
-                            key->getBstrValue(CoseKey::PUBKEY_X)->data())) {
-            return "Signature verification failed";
-        }
+    if (!ED25519_verify(signatureInput.data(), signatureInput.size(), signature->value().data(),
+                        key->getBstrValue(CoseKey::PUBKEY_X)->data())) {
+        return "Signature verification failed";
     }
 
     return serializedKey->asBstr()->value();
 }
+
 ErrMsgOr<std::vector<BccEntryData>> validateBcc(const cppbor::Array* bcc) {
     if (!bcc || bcc->size() == 0) return "Invalid BCC";
 
@@ -148,8 +163,7 @@
         if (!entry || entry->size() != kCoseSign1EntryCount) {
             return "Invalid BCC entry " + std::to_string(i) + ": " + prettyPrint(entry);
         }
-        auto payload = verifyAndParseCoseSign1Cwt(false /* ignoreSignature */, entry,
-                                                  std::move(prevKey), bytevec{} /* AAD */);
+        auto payload = verifyAndParseCoseSign1Cwt(entry, std::move(prevKey), bytevec{} /* AAD */);
         if (!payload) {
             return "Failed to verify entry " + std::to_string(i) + ": " + payload.moveMessage();
         }
@@ -168,4 +182,36 @@
     return result;
 }
 
+JsonOutput jsonEncodeCsrWithBuild(const cppbor::Array& csr) {
+    const std::string kFingerprintProp = "ro.build.fingerprint";
+
+    if (!::android::base::WaitForPropertyCreation(kFingerprintProp)) {
+        return JsonOutput::Error("Unable to read build fingerprint");
+    }
+
+    bytevec csrCbor = csr.encode();
+    size_t base64Length;
+    int rc = EVP_EncodedLength(&base64Length, csrCbor.size());
+    if (!rc) {
+        return JsonOutput::Error("Error getting base64 length. Size overflow?");
+    }
+
+    std::vector<char> base64(base64Length);
+    rc = EVP_EncodeBlock(reinterpret_cast<uint8_t*>(base64.data()), csrCbor.data(), csrCbor.size());
+    ++rc;  // Account for NUL, which BoringSSL does not for some reason.
+    if (rc != base64Length) {
+        return JsonOutput::Error("Error writing base64. Expected " + std::to_string(base64Length) +
+                                 " bytes to be written, but " + std::to_string(rc) +
+                                 " bytes were actually written.");
+    }
+
+    Json::Value json(Json::objectValue);
+    json["build_fingerprint"] = ::android::base::GetProperty(kFingerprintProp, /*default=*/"");
+    json["csr"] = base64.data();  // Boring writes a NUL-terminated c-string
+
+    Json::StreamWriterBuilder factory;
+    factory["indentation"] = "";  // disable pretty formatting
+    return JsonOutput::Ok(Json::writeString(factory, json));
+}
+
 }  // namespace aidl::android::hardware::security::keymint::remote_prov
diff --git a/security/keymint/support/remote_prov_utils_test.cpp b/security/keymint/support/remote_prov_utils_test.cpp
new file mode 100644
index 0000000..8697c51
--- /dev/null
+++ b/security/keymint/support/remote_prov_utils_test.cpp
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2021 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.
+ */
+
+#include <android-base/properties.h>
+#include <cppbor_parse.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <keymaster/android_keymaster_utils.h>
+#include <keymaster/logger.h>
+#include <keymaster/remote_provisioning_utils.h>
+#include <openssl/curve25519.h>
+#include <remote_prov/remote_prov_utils.h>
+#include <cstdint>
+#include "cppbor.h"
+#include "keymaster/cppcose/cppcose.h"
+
+namespace aidl::android::hardware::security::keymint::remote_prov {
+namespace {
+
+using ::keymaster::KeymasterBlob;
+using ::keymaster::validateAndExtractEekPubAndId;
+using ::testing::ElementsAreArray;
+
+TEST(RemoteProvUtilsTest, GenerateEekChainInvalidLength) {
+    ASSERT_FALSE(generateEekChain(1, /*eekId=*/{}));
+}
+
+TEST(RemoteProvUtilsTest, GenerateEekChain) {
+    bytevec kTestEekId = {'t', 'e', 's', 't', 'I', 'd', 0};
+    for (size_t length : {2, 3, 31}) {
+        auto get_eek_result = generateEekChain(length, kTestEekId);
+        ASSERT_TRUE(get_eek_result) << get_eek_result.message();
+
+        auto& [chain, pubkey, privkey] = *get_eek_result;
+
+        auto validation_result = validateAndExtractEekPubAndId(
+                /*testMode=*/true, KeymasterBlob(chain.data(), chain.size()));
+        ASSERT_TRUE(validation_result.isOk());
+
+        auto& [eekPub, eekId] = *validation_result;
+        EXPECT_THAT(eekId, ElementsAreArray(kTestEekId));
+        EXPECT_THAT(eekPub, ElementsAreArray(pubkey));
+    }
+}
+
+TEST(RemoteProvUtilsTest, GetProdEekChain) {
+    auto chain = getProdEekChain();
+
+    auto validation_result = validateAndExtractEekPubAndId(
+            /*testMode=*/false, KeymasterBlob(chain.data(), chain.size()));
+    ASSERT_TRUE(validation_result.isOk()) << "Error: " << validation_result.moveError();
+
+    auto& [eekPub, eekId] = *validation_result;
+
+    auto [geekCert, ignoredNewPos, error] =
+            cppbor::parse(kCoseEncodedGeekCert, sizeof(kCoseEncodedGeekCert));
+    ASSERT_NE(geekCert, nullptr) << "Error: " << error;
+    ASSERT_NE(geekCert->asArray(), nullptr);
+
+    auto& encodedGeekCoseKey = geekCert->asArray()->get(kCoseSign1Payload);
+    ASSERT_NE(encodedGeekCoseKey, nullptr);
+    ASSERT_NE(encodedGeekCoseKey->asBstr(), nullptr);
+
+    auto geek = CoseKey::parse(encodedGeekCoseKey->asBstr()->value());
+    ASSERT_TRUE(geek) << "Error: " << geek.message();
+
+    const std::vector<uint8_t> empty;
+    EXPECT_THAT(eekId, ElementsAreArray(geek->getBstrValue(CoseKey::KEY_ID).value_or(empty)));
+    EXPECT_THAT(eekPub, ElementsAreArray(geek->getBstrValue(CoseKey::PUBKEY_X).value_or(empty)));
+}
+
+TEST(RemoteProvUtilsTest, JsonEncodeCsr) {
+    cppbor::Array array;
+    array.add(1);
+
+    auto [json, error] = jsonEncodeCsrWithBuild(array);
+
+    ASSERT_TRUE(error.empty()) << error;
+
+    std::string expected = R"({"build_fingerprint":")" +
+                           ::android::base::GetProperty("ro.build.fingerprint", /*default=*/"") +
+                           R"(","csr":"gQE="})";
+
+    ASSERT_EQ(json, expected);
+}
+
+}  // namespace
+}  // namespace aidl::android::hardware::security::keymint::remote_prov
diff --git a/security/sharedsecret/aidl/vts/functional/SharedSecretAidlTest.cpp b/security/sharedsecret/aidl/vts/functional/SharedSecretAidlTest.cpp
index 919f882..51938ba 100644
--- a/security/sharedsecret/aidl/vts/functional/SharedSecretAidlTest.cpp
+++ b/security/sharedsecret/aidl/vts/functional/SharedSecretAidlTest.cpp
@@ -268,10 +268,16 @@
                     << "Shared secret service that provided tweaked param should fail to compute "
                        "shared secret";
         } else {
-            EXPECT_EQ(ErrorCode::OK, responses[i].error) << "Others should succeed";
-            EXPECT_NE(correct_response, responses[i].sharing_check)
-                    << "Others should calculate a different shared secret, due to the tweaked "
-                       "nonce.";
+            // Other services *may* succeed, or may notice the invalid size for the nonce.
+            // However, if another service completes the computation, it should get the 'wrong'
+            // answer.
+            if (responses[i].error == ErrorCode::OK) {
+                EXPECT_NE(correct_response, responses[i].sharing_check)
+                        << "Others should calculate a different shared secret, due to the tweaked "
+                           "nonce.";
+            } else {
+                EXPECT_EQ(ErrorCode::INVALID_ARGUMENT, responses[i].error);
+            }
         }
     }
 }
@@ -348,10 +354,16 @@
                     << "Shared secret service that provided tweaked param should fail to compute "
                        "shared secret";
         } else {
-            EXPECT_EQ(ErrorCode::OK, responses[i].error) << "Others should succeed";
-            EXPECT_NE(correct_response, responses[i].sharing_check)
-                    << "Others should calculate a different shared secret, due to the tweaked "
-                       "nonce.";
+            // Other services *may* succeed, or may notice the invalid size for the seed.
+            // However, if another service completes the computation, it should get the 'wrong'
+            // answer.
+            if (responses[i].error == ErrorCode::OK) {
+                EXPECT_NE(correct_response, responses[i].sharing_check)
+                        << "Others should calculate a different shared secret, due to the tweaked "
+                           "seed.";
+            } else {
+                EXPECT_EQ(ErrorCode::INVALID_ARGUMENT, responses[i].error);
+            }
         }
     }
 }
diff --git a/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp b/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp
index 1f579ba..d46cf5a 100644
--- a/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp
+++ b/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp
@@ -24,7 +24,9 @@
 #include <log/log.h>
 #include <utils/SystemClock.h>
 
+#include <algorithm>
 #include <cinttypes>
+#include <unordered_map>
 #include <vector>
 
 using ::android::hardware::Return;
@@ -149,6 +151,7 @@
 TEST_P(SensorsHidlTest, SensorListValid) {
     S()->getSensorsList([&](const auto& list) {
         const size_t count = list.size();
+        std::unordered_map<int32_t, std::vector<std::string>> sensorTypeNameMap;
         for (size_t i = 0; i < count; ++i) {
             const auto& s = list[i];
             SCOPED_TRACE(::testing::Message()
@@ -167,6 +170,14 @@
             EXPECT_FALSE(s.name.empty());
             EXPECT_FALSE(s.vendor.empty());
 
+            // Make sure that sensors of the same type have a unique name.
+            std::vector<std::string>& v = sensorTypeNameMap[static_cast<int32_t>(s.type)];
+            bool isUniqueName = std::find(v.begin(), v.end(), s.name) == v.end();
+            EXPECT_TRUE(isUniqueName) << "Duplicate sensor Name: " << s.name;
+            if (isUniqueName) {
+                v.push_back(s.name);
+            }
+
             // Test power > 0, maxRange > 0
             EXPECT_LE(0, s.power);
             EXPECT_LT(0, s.maxRange);
diff --git a/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h b/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h
index 47a8cc0..ea5dc70 100644
--- a/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h
+++ b/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h
@@ -26,10 +26,12 @@
 #include <log/log.h>
 #include <utils/SystemClock.h>
 
+#include <algorithm>
 #include <cinttypes>
 #include <condition_variable>
 #include <cstring>
 #include <map>
+#include <unordered_map>
 #include <vector>
 
 /**
@@ -373,6 +375,7 @@
 TEST_P(SensorsHidlTest, SensorListValid) {
     getSensors()->getSensorsList([&](const auto& list) {
         const size_t count = list.size();
+        std::unordered_map<int32_t, std::vector<std::string>> sensorTypeNameMap;
         for (size_t i = 0; i < count; ++i) {
             const auto& s = list[i];
             SCOPED_TRACE(::testing::Message()
@@ -393,6 +396,14 @@
             EXPECT_FALSE(s.name.empty());
             EXPECT_FALSE(s.vendor.empty());
 
+            // Make sure that sensors of the same type have a unique name.
+            std::vector<std::string>& v = sensorTypeNameMap[static_cast<int32_t>(s.type)];
+            bool isUniqueName = std::find(v.begin(), v.end(), s.name) == v.end();
+            EXPECT_TRUE(isUniqueName) << "Duplicate sensor Name: " << s.name;
+            if (isUniqueName) {
+                v.push_back(s.name);
+            }
+
             // Test power > 0, maxRange > 0
             EXPECT_LE(0, s.power);
             EXPECT_LT(0, s.maxRange);
diff --git a/vibrator/aidl/default/Vibrator.cpp b/vibrator/aidl/default/Vibrator.cpp
index c6682b3..5755ce5 100644
--- a/vibrator/aidl/default/Vibrator.cpp
+++ b/vibrator/aidl/default/Vibrator.cpp
@@ -138,6 +138,11 @@
 
 ndk::ScopedAStatus Vibrator::getPrimitiveDuration(CompositePrimitive primitive,
                                                   int32_t* durationMs) {
+    std::vector<CompositePrimitive> supported;
+    getSupportedPrimitives(&supported);
+    if (std::find(supported.begin(), supported.end(), primitive) == supported.end()) {
+        return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+    }
     if (primitive != CompositePrimitive::NOOP) {
         *durationMs = 100;
     } else {
diff --git a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
index 4d49a12..c56bd9a 100644
--- a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
+++ b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
@@ -309,8 +309,8 @@
         for (EffectStrength strength : kEffectStrengths) {
             int32_t lengthMs;
             Status status = vibrator->perform(effect, strength, nullptr /*callback*/, &lengthMs);
-            EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION)
-                << toString(effect) << " " << toString(strength);
+            EXPECT_TRUE(isUnknownOrUnsupported(status))
+                    << status << toString(effect) << " " << toString(strength);
         }
     }
     for (Effect effect : kEffects) {
@@ -686,7 +686,7 @@
         ASSERT_NE(durationMs, 0);
         EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
     } else {
-        EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
+        EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
     }
 }
 
diff --git a/wifi/1.5/default/android.hardware.wifi@1.0-service-lazy.rc b/wifi/1.5/default/android.hardware.wifi@1.0-service-lazy.rc
index 061689d..bc6bb6a 100644
--- a/wifi/1.5/default/android.hardware.wifi@1.0-service-lazy.rc
+++ b/wifi/1.5/default/android.hardware.wifi@1.0-service-lazy.rc
@@ -4,6 +4,7 @@
     interface android.hardware.wifi@1.2::IWifi default
     interface android.hardware.wifi@1.3::IWifi default
     interface android.hardware.wifi@1.4::IWifi default
+    interface android.hardware.wifi@1.5::IWifi default
     oneshot
     disabled
     class hal
diff --git a/wifi/1.5/default/wifi_ap_iface.cpp b/wifi/1.5/default/wifi_ap_iface.cpp
index b438a4a..1ae7905 100644
--- a/wifi/1.5/default/wifi_ap_iface.cpp
+++ b/wifi/1.5/default/wifi_ap_iface.cpp
@@ -136,24 +136,25 @@
 
 WifiStatus WifiApIface::setMacAddressInternal(
     const std::array<uint8_t, 6>& mac) {
-    bool status;
     // Support random MAC up to 2 interfaces
     if (instances_.size() == 2) {
         int rbyte = 1;
         for (auto const& intf : instances_) {
             std::array<uint8_t, 6> rmac = mac;
-            // reverse the bits to avoid clision
+            // reverse the bits to avoid collision
             rmac[rbyte] = 0xff - rmac[rbyte];
-            status = iface_util_.lock()->setMacAddress(intf, rmac);
-            if (!status) {
+            if (!iface_util_.lock()->setMacAddress(intf, rmac)) {
                 LOG(INFO) << "Failed to set random mac address on " << intf;
+                return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
             }
             rbyte++;
         }
-    } else {
-        status = iface_util_.lock()->setMacAddress(ifname_, mac);
     }
-    if (!status) {
+    // It also needs to set mac address for bridged interface, otherwise the mac
+    // address of bridged interface will be changed after one of instance
+    // down.
+    if (!iface_util_.lock()->setMacAddress(ifname_, mac)) {
+        LOG(ERROR) << "Fail to config MAC for interface " << ifname_;
         return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
     }
     return createWifiStatus(WifiStatusCode::SUCCESS);
@@ -181,6 +182,18 @@
                 return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
             }
         }
+        // It needs to set mac address for bridged interface, otherwise the mac
+        // address of the bridged interface will be changed after one of the
+        // instance down. Thus we are generating a random MAC address for the
+        // bridged interface even if we got the request to reset the Factory
+        // MAC. Since the bridged interface is an internal interface for the
+        // operation of bpf and others networking operation.
+        if (!iface_util_.lock()->setMacAddress(
+                ifname_, iface_util_.lock()->createRandomMacAddress())) {
+            LOG(ERROR) << "Fail to config MAC for bridged interface "
+                       << ifname_;
+            return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
+        }
     } else {
         getMacResult = getFactoryMacAddressInternal(ifname_);
         LOG(DEBUG) << "Reset MAC to factory MAC on " << ifname_;
diff --git a/wifi/1.5/default/wifi_chip.cpp b/wifi/1.5/default/wifi_chip.cpp
index 024747a..82d794c 100644
--- a/wifi/1.5/default/wifi_chip.cpp
+++ b/wifi/1.5/default/wifi_chip.cpp
@@ -1059,7 +1059,8 @@
     // Requires to remove one of the instance in bridge mode
     for (auto const& it : br_ifaces_ap_instances_) {
         if (it.first == ifname) {
-            for (auto const& iface : it.second) {
+            std::vector<std::string> ap_instances = it.second;
+            for (auto const& iface : ap_instances) {
                 if (iface == ifInstanceName) {
                     if (!iface_util_->removeIfaceFromBridge(it.first, iface)) {
                         LOG(ERROR)
@@ -1075,13 +1076,20 @@
                                    << " " << legacyErrorToString(legacy_status);
                         return createWifiStatusFromLegacyError(legacy_status);
                     }
+                    ap_instances.erase(
+                        std::remove(ap_instances.begin(), ap_instances.end(),
+                                    ifInstanceName),
+                        ap_instances.end());
+                    br_ifaces_ap_instances_[ifname] = ap_instances;
+                    break;
                 }
             }
             break;
         }
     }
-    br_ifaces_ap_instances_.erase(ifInstanceName);
     iface->removeInstance(ifInstanceName);
+    setActiveWlanIfaceNameProperty(getFirstActiveWlanIfaceName());
+
     return createWifiStatus(WifiStatusCode::SUCCESS);
 }
 
diff --git a/wifi/1.5/default/wifi_iface_util.cpp b/wifi/1.5/default/wifi_iface_util.cpp
index d1434e3..7bf830b 100644
--- a/wifi/1.5/default/wifi_iface_util.cpp
+++ b/wifi/1.5/default/wifi_iface_util.cpp
@@ -86,9 +86,9 @@
         event_handlers.on_state_toggle_off_on(iface_name);
     }
     if (!success) {
-        LOG(ERROR) << "SetMacAddress failed.";
+        LOG(ERROR) << "SetMacAddress failed on " << iface_name;
     } else {
-        LOG(DEBUG) << "SetMacAddress succeeded.";
+        LOG(DEBUG) << "SetMacAddress succeeded on " << iface_name;
     }
     return success;
 }
diff --git a/wifi/1.5/default/wifi_iface_util.h b/wifi/1.5/default/wifi_iface_util.h
index b449077..544f575 100644
--- a/wifi/1.5/default/wifi_iface_util.h
+++ b/wifi/1.5/default/wifi_iface_util.h
@@ -71,10 +71,10 @@
 
     virtual bool removeIfaceFromBridge(const std::string& br_name,
                                        const std::string& if_name);
+    // Get a random MAC address.
+    virtual std::array<uint8_t, 6> createRandomMacAddress();
 
    private:
-    std::array<uint8_t, 6> createRandomMacAddress();
-
     std::weak_ptr<wifi_system::InterfaceTool> iface_tool_;
     std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
     std::unique_ptr<std::array<uint8_t, 6>> random_mac_address_;