Merge "Fix ADR half cycle ambiguity doc (hardware/interfaces)" into sc-dev
diff --git a/automotive/vehicle/2.0/vts/functional/VtsHalAutomotiveVehicleV2_0TargetTest.cpp b/automotive/vehicle/2.0/vts/functional/VtsHalAutomotiveVehicleV2_0TargetTest.cpp
index 7f1d4d1..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;
         }
     }
 }
@@ -241,6 +256,7 @@
     ASSERT_NE(StatusCode::OK, mVehicle->subscribe(cb, options));
 }
 
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VehicleHalHidlTest);
 INSTANTIATE_TEST_SUITE_P(
         PerInstance, VehicleHalHidlTest,
         testing::ValuesIn(android::hardware::getAllHalInstanceNames(IVehicle::descriptor)),
diff --git a/biometrics/face/aidl/vts/VtsHalBiometricsFaceTargetTest.cpp b/biometrics/face/aidl/vts/VtsHalBiometricsFaceTargetTest.cpp
index ada6f73..47a7813 100644
--- a/biometrics/face/aidl/vts/VtsHalBiometricsFaceTargetTest.cpp
+++ b/biometrics/face/aidl/vts/VtsHalBiometricsFaceTargetTest.cpp
@@ -32,21 +32,8 @@
 constexpr int kSensorId = 0;
 constexpr int kUserId = 0;
 
-enum class MethodName {
-    kOnError,
-    kOnSessionClosed,
-};
-
-struct Invocation {
-    MethodName methodName;
-    Error error;
-    int32_t vendorCode;
-};
-
 class SessionCallback : public BnSessionCallback {
   public:
-    explicit SessionCallback(Invocation* inv) : mInv(inv) {}
-
     ndk::ScopedAStatus onChallengeGenerated(int64_t /*challenge*/) override {
         return ndk::ScopedAStatus::ok();
     }
@@ -64,11 +51,11 @@
     }
 
     ndk::ScopedAStatus onError(Error error, int32_t vendorCode) override {
-        *mInv = {};
-        mInv->methodName = MethodName::kOnError;
-        mInv->error = error;
-        mInv->vendorCode = vendorCode;
-
+        auto lock = std::lock_guard<std::mutex>{mMutex};
+        mError = error;
+        mVendorCode = vendorCode;
+        mOnErrorInvoked = true;
+        mCv.notify_one();
         return ndk::ScopedAStatus::ok();
     }
 
@@ -121,14 +108,18 @@
     }
 
     ndk::ScopedAStatus onSessionClosed() override {
-        *mInv = {};
-        mInv->methodName = MethodName::kOnSessionClosed;
-
+        auto lock = std::lock_guard<std::mutex>{mMutex};
+        mOnSessionClosedInvoked = true;
+        mCv.notify_one();
         return ndk::ScopedAStatus::ok();
     }
 
-  private:
-    Invocation* mInv;
+    std::mutex mMutex;
+    std::condition_variable mCv;
+    Error mError = Error::UNKNOWN;
+    int32_t mVendorCode = 0;
+    bool mOnErrorInvoked = false;
+    bool mOnSessionClosedInvoked = false;
 };
 
 class Face : public testing::TestWithParam<std::string> {
@@ -140,12 +131,11 @@
     }
 
     std::shared_ptr<IFace> mHal;
-    Invocation mInv;
 };
 
 TEST_P(Face, AuthenticateTest) {
     // Prepare the callback.
-    auto cb = ndk::SharedRefBase::make<SessionCallback>(&mInv);
+    auto cb = ndk::SharedRefBase::make<SessionCallback>();
 
     // Create a session
     std::shared_ptr<ISession> session;
@@ -155,15 +145,18 @@
     std::shared_ptr<common::ICancellationSignal> cancellationSignal;
     ASSERT_TRUE(session->authenticate(0 /* operationId */, &cancellationSignal).isOk());
 
+    auto lock = std::unique_lock<std::mutex>(cb->mMutex);
+    cb->mCv.wait(lock, [&cb] { return cb->mOnErrorInvoked; });
     // Get the results
-    EXPECT_EQ(mInv.methodName, MethodName::kOnError);
-    EXPECT_EQ(mInv.error, Error::UNABLE_TO_PROCESS);
-    EXPECT_EQ(mInv.vendorCode, 0);
+    EXPECT_EQ(cb->mError, Error::UNABLE_TO_PROCESS);
+    EXPECT_EQ(cb->mVendorCode, 0);
+    lock.unlock();
 
     // Close the session
     ASSERT_TRUE(session->close().isOk());
 
-    EXPECT_EQ(mInv.methodName, MethodName::kOnSessionClosed);
+    lock.lock();
+    cb->mCv.wait(lock, [&cb] { return cb->mOnSessionClosedInvoked; });
 }
 
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Face);
@@ -180,4 +173,3 @@
     ABinderProcess_startThreadPool();
     return RUN_ALL_TESTS();
 }
-
diff --git a/biometrics/fingerprint/aidl/default/tests/WorkerThreadTest.cpp b/biometrics/fingerprint/aidl/default/tests/WorkerThreadTest.cpp
index 8443336..b2417bd 100644
--- a/biometrics/fingerprint/aidl/default/tests/WorkerThreadTest.cpp
+++ b/biometrics/fingerprint/aidl/default/tests/WorkerThreadTest.cpp
@@ -73,24 +73,29 @@
     constexpr int NUM_TASKS = 10000;
     WorkerThread worker(NUM_TASKS);
 
+    std::mutex mut;
+    std::condition_variable cv;
+    bool finished = false;
     std::vector<int> results;
+
     for (int i = 0; i < NUM_TASKS; ++i) {
-        worker.schedule(Callable::from([&results, i] {
+        worker.schedule(Callable::from([&mut, &results, i] {
             // Delay tasks differently to provoke races.
             std::this_thread::sleep_for(std::chrono::nanoseconds(100 - i % 100));
-            // Unguarded write to results to provoke races.
+            auto lock = std::lock_guard(mut);
             results.push_back(i);
         }));
     }
 
-    std::promise<void> promise;
-    auto future = promise.get_future();
-
     // Schedule a special task to signal when all of the tasks are finished.
-    worker.schedule(
-            Callable::from([promise = std::move(promise)]() mutable { promise.set_value(); }));
-    future.wait();
+    worker.schedule(Callable::from([&mut, &cv, &finished] {
+        auto lock = std::lock_guard(mut);
+        finished = true;
+        cv.notify_one();
+    }));
 
+    auto lock = std::unique_lock(mut);
+    cv.wait(lock, [&finished] { return finished; });
     ASSERT_EQ(results.size(), NUM_TASKS);
     EXPECT_TRUE(std::is_sorted(results.begin(), results.end()));
 }
diff --git a/camera/metadata/3.5/types.hal b/camera/metadata/3.5/types.hal
index 99d6115..d32bc91 100644
--- a/camera/metadata/3.5/types.hal
+++ b/camera/metadata/3.5/types.hal
@@ -73,7 +73,7 @@
 
     ANDROID_CONTROL_END_3_5,
 
-    /** android.scaler.availableRotateAndCropModes [static, byte[], hidden]
+    /** android.scaler.availableRotateAndCropModes [static, byte[], public]
      *
      * <p>List of rotate-and-crop modes for ANDROID_SCALER_ROTATE_AND_CROP that are supported by this camera device.</p>
      *
@@ -81,7 +81,7 @@
      */
     ANDROID_SCALER_AVAILABLE_ROTATE_AND_CROP_MODES = android.hardware.camera.metadata@3.4::CameraMetadataTag:ANDROID_SCALER_END_3_4,
 
-    /** android.scaler.rotateAndCrop [dynamic, enum, hidden]
+    /** android.scaler.rotateAndCrop [dynamic, enum, public]
      *
      * <p>Whether a rotation-and-crop operation is applied to processed
      * outputs from the camera.</p>
diff --git a/camera/metadata/3.6/types.hal b/camera/metadata/3.6/types.hal
index 97cac7c..185687c 100644
--- a/camera/metadata/3.6/types.hal
+++ b/camera/metadata/3.6/types.hal
@@ -348,6 +348,14 @@
     ANDROID_SCALER_MULTI_RESOLUTION_STREAM_SUPPORTED_TRUE,
 };
 
+/** android.sensor.testPatternMode enumeration values added since v3.2
+ * @see ANDROID_SENSOR_TEST_PATTERN_MODE
+ */
+enum CameraMetadataEnumAndroidSensorTestPatternMode :
+        @3.2::CameraMetadataEnumAndroidSensorTestPatternMode {
+    ANDROID_SENSOR_TEST_PATTERN_MODE_BLACK,
+};
+
 /** android.sensor.pixelMode enumeration values
  * @see ANDROID_SENSOR_PIXEL_MODE
  */
diff --git a/current.txt b/current.txt
index 387f9ec..908ecc4 100644
--- a/current.txt
+++ b/current.txt
@@ -4,6 +4,7 @@
 # Test HALs
 
 717c17cd380bb48710dff601d1a03351d4ebc28028353d5d60489248f506523c android.hardware.tests.lazy@1.0::ILazy
+67222a2ed4071b6c232e671ce0f4be4f85c1c6fb017ec2355396adaae1fe26be android.hardware.tests.lazy@1.1::ILazy
 
 # HALs released in Android O
 
@@ -767,6 +768,7 @@
 98592d193a717066facf91428426e5abe211e3bd718bc372e29fb944ddbe6e7c android.hardware.wifi.supplicant@1.3::types
 
 # ABI preserving changes to HALs during Android S
+159a0069336035852e9eca6354b86b7990680d1b239f23ef2f631b01807c4cb9 android.hardware.camera.metadata@3.5::types
 e042522daa4b5f7fd4a0a19bcdadb93c79a1b04c09ef2c9813a3a8941032f3f5 android.hardware.contexthub@1.0::IContexthub
 c2f64133b83ede65c9939ef97ab5bd867b73faf3dba0e7e69f77c3c43d9e487e android.hardware.contexthub@1.0::IContexthubCallback
 bda492ec4021d13869de72bd6f8c15c5837b78d6136b8d538efec5320573a5ec android.hardware.gnss@1.0::IGnssMeasurementCallback
@@ -825,6 +827,9 @@
 b4cbc1f2d38787f2ad069a8e4d10c0896287531a2596f0de0283e390b0ecf05d android.hardware.audio.effect@7.0::IVirtualizerEffect
 2b5681e1ea6a2db0dc1e84edb96d3de2f7daf306046543e7956be76dcb8f20fb android.hardware.audio.effect@7.0::IVisualizerEffect
 fa1e2d78e66fd662de93cb479ffd55947fe54f51cb53915814b3d3e3036c86a5 android.hardware.audio.effect@7.0::types
+e3865e74cb1a6e6afd38c7aa84115cb109ce47b972132de5242bc3838d2771f6 android.hardware.automotive.vehicle@2.0::types
+b3caf524c46a47d67e6453a34419e1881942d059e146cda740502670e9a752c3 android.hardware.automotive.vehicle@2.0::IVehicle
+7ce8728b27600e840cacf0a832f6942819fe535f9d3797ae052d5eef5065921c android.hardware.automotive.vehicle@2.0::IVehicleCallback
 b525e91d886379c13588f4975bb04d625d46e1f41b4453792c4b2db1e7ff4340 android.hardware.biometrics.fingerprint@2.3::IBiometricsFingerprint
 4baf8e0eca4aa896cc9ceb7bb676aaf4fa21372ef8b49eed68eced1221c3dc0d android.hardware.bluetooth.audio@2.1::IBluetoothAudioProvider
 d417a9212c8f96e3a06a2f221c8c5756c765355b2b81de2b2a65d4c9eee85401 android.hardware.bluetooth.audio@2.1::IBluetoothAudioProvidersFactory
@@ -834,7 +839,7 @@
 3be6faa3d11ad9c7ec01a1a0a009cf11cb65d701d109dab37613ce9cfb3cdd60 android.hardware.camera.device@3.7::ICameraDeviceSession
 3740ec773b2eb8fa6bd8c6e879eedb56c4e4306b88f1c20fa51103d791d871b1 android.hardware.camera.device@3.7::ICameraInjectionSession
 21f023685571daf46148097d98b89cea353f07e3ed83b2ed5685b23bd136c3ee android.hardware.camera.device@3.7::types
-f655c93132d223369ff6ddc621cb721f82dde6cc85ab9df2cbde6cb24cf2c885 android.hardware.camera.metadata@3.6::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
 3500d3c4e2d49eeed2f3239330a166beb2db2d5071b84d9c738b048c2d54a3d9 android.hardware.contexthub@1.2::IContexthub
diff --git a/gnss/aidl/vts/gnss_hal_test_cases.cpp b/gnss/aidl/vts/gnss_hal_test_cases.cpp
index 9d8562d..5964f81 100644
--- a/gnss/aidl/vts/gnss_hal_test_cases.cpp
+++ b/gnss/aidl/vts/gnss_hal_test_cases.cpp
@@ -311,27 +311,42 @@
     EXPECT_TRUE(gnssPowerIndicationCallback->gnss_power_stats_cbq_.retrieve(
             gnssPowerIndicationCallback->last_gnss_power_stats_, kTimeoutSec));
     EXPECT_EQ(gnssPowerIndicationCallback->gnss_power_stats_cbq_.calledCount(), 2);
+
     auto powerStats2 = gnssPowerIndicationCallback->last_gnss_power_stats_;
 
-    // Elapsed realtime must increase
-    EXPECT_GT(powerStats2.elapsedRealtime.timestampNs, powerStats1.elapsedRealtime.timestampNs);
+    if ((gnssPowerIndicationCallback->last_capabilities_ &
+         (int)GnssPowerIndicationCallback::CAPABILITY_TOTAL)) {
+        // Elapsed realtime must increase
+        EXPECT_GT(powerStats2.elapsedRealtime.timestampNs, powerStats1.elapsedRealtime.timestampNs);
 
-    // Total energy must increase
-    EXPECT_GT(powerStats2.totalEnergyMilliJoule, powerStats1.totalEnergyMilliJoule);
+        // Total energy must increase
+        EXPECT_GT(powerStats2.totalEnergyMilliJoule, powerStats1.totalEnergyMilliJoule);
+    }
 
     // At least oone of singleband and multiband acquisition energy must increase
     bool singlebandAcqEnergyIncreased = powerStats2.singlebandAcquisitionModeEnergyMilliJoule >
                                         powerStats1.singlebandAcquisitionModeEnergyMilliJoule;
     bool multibandAcqEnergyIncreased = powerStats2.multibandAcquisitionModeEnergyMilliJoule >
                                        powerStats1.multibandAcquisitionModeEnergyMilliJoule;
-    EXPECT_TRUE(singlebandAcqEnergyIncreased || multibandAcqEnergyIncreased);
+
+    if ((gnssPowerIndicationCallback->last_capabilities_ &
+         (int)GnssPowerIndicationCallback::CAPABILITY_SINGLEBAND_ACQUISITION) ||
+        (gnssPowerIndicationCallback->last_capabilities_ &
+         (int)GnssPowerIndicationCallback::CAPABILITY_MULTIBAND_ACQUISITION)) {
+        EXPECT_TRUE(singlebandAcqEnergyIncreased || multibandAcqEnergyIncreased);
+    }
 
     // At least one of singleband and multiband tracking energy must increase
     bool singlebandTrackingEnergyIncreased = powerStats2.singlebandTrackingModeEnergyMilliJoule >
                                              powerStats1.singlebandTrackingModeEnergyMilliJoule;
     bool multibandTrackingEnergyIncreased = powerStats2.multibandTrackingModeEnergyMilliJoule >
                                             powerStats1.multibandTrackingModeEnergyMilliJoule;
-    EXPECT_TRUE(singlebandTrackingEnergyIncreased || multibandTrackingEnergyIncreased);
+    if ((gnssPowerIndicationCallback->last_capabilities_ &
+         (int)GnssPowerIndicationCallback::CAPABILITY_SINGLEBAND_TRACKING) ||
+        (gnssPowerIndicationCallback->last_capabilities_ &
+         (int)GnssPowerIndicationCallback::CAPABILITY_MULTIBAND_TRACKING)) {
+        EXPECT_TRUE(singlebandTrackingEnergyIncreased || multibandTrackingEnergyIncreased);
+    }
 
     // Clean up
     StopAndClearLocations();
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/OWNERS b/graphics/composer/2.1/vts/OWNERS
index 0b42d2e..ea06752 100644
--- a/graphics/composer/2.1/vts/OWNERS
+++ b/graphics/composer/2.1/vts/OWNERS
@@ -1,6 +1,6 @@
 # Graphics team
+adyabr@google.com
 lpy@google.com
-vhau@google.com
 
 # VTS team
 yim@google.com
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..7a1568b 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);
@@ -465,24 +463,24 @@
 
             // 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 +591,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 +604,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 7d0a83b..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));
 }
@@ -561,17 +568,28 @@
             setActiveConfig(display, config1);
             sendRefreshFrame(display, nullptr);
 
-            int32_t vsyncPeriod1 = mComposerClient->getDisplayAttribute_2_4(
+            const auto vsyncPeriod1 = mComposerClient->getDisplayAttribute_2_4(
                     display.get(), config1,
                     IComposerClient::IComposerClient::Attribute::VSYNC_PERIOD);
-            int32_t vsyncPeriod2 = mComposerClient->getDisplayAttribute_2_4(
+            const auto configGroup1 = mComposerClient->getDisplayAttribute_2_4(
+                    display.get(), config1,
+                    IComposerClient::IComposerClient::Attribute::CONFIG_GROUP);
+            const auto vsyncPeriod2 = mComposerClient->getDisplayAttribute_2_4(
                     display.get(), config2,
                     IComposerClient::IComposerClient::Attribute::VSYNC_PERIOD);
+            const auto configGroup2 = mComposerClient->getDisplayAttribute_2_4(
+                    display.get(), config2,
+                    IComposerClient::IComposerClient::Attribute::CONFIG_GROUP);
 
             if (vsyncPeriod1 == vsyncPeriod2) {
                 return;  // continue
             }
 
+            // We don't allow delayed change when changing config groups
+            if (params.delayForChange > 0 && configGroup1 != configGroup2) {
+                return;  // continue
+            }
+
             VsyncPeriodChangeTimeline timeline;
             IComposerClient::VsyncPeriodChangeConstraints constraints = {
                     .desiredTimeNanos = systemTime() + params.delayForChange,
diff --git a/identity/TEST_MAPPING b/identity/TEST_MAPPING
index f35f4b7..85cf91f 100644
--- a/identity/TEST_MAPPING
+++ b/identity/TEST_MAPPING
@@ -8,6 +8,9 @@
     },
     {
       "name": "android.hardware.identity-support-lib-test"
+    },
+    {
+      "name": "libeic_test"
     }
   ]
 }
diff --git a/identity/aidl/default/Android.bp b/identity/aidl/default/Android.bp
index 7c68aee..28c4893 100644
--- a/identity/aidl/default/Android.bp
+++ b/identity/aidl/default/Android.bp
@@ -114,6 +114,43 @@
     ],
 }
 
+cc_test {
+    name: "libeic_test",
+    srcs: [
+        "EicTests.cpp",
+        "FakeSecureHardwareProxy.cpp",
+    ],
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-g",
+        "-DEIC_DEBUG",
+    ],
+    local_include_dirs: [
+         "common",
+    ],
+    shared_libs: [
+        "liblog",
+        "libcrypto",
+        "libkeymaster_messages",
+    ],
+    static_libs: [
+        "libbase",
+        "libcppbor_external",
+        "libcppcose_rkp",
+        "libutils",
+        "libsoft_attestation_cert",
+        "libkeymaster_portable",
+        "libsoft_attestation_cert",
+        "libpuresoftkeymasterdevice",
+        "android.hardware.identity-support-lib",
+        "android.hardware.identity-libeic-library",
+    ],
+    test_suites: [
+        "general-tests",
+    ],
+}
+
 prebuilt_etc {
     name: "android.hardware.identity_credential.xml",
     sub_dir: "permissions",
diff --git a/identity/aidl/default/EicTests.cpp b/identity/aidl/default/EicTests.cpp
new file mode 100644
index 0000000..a28080d
--- /dev/null
+++ b/identity/aidl/default/EicTests.cpp
@@ -0,0 +1,85 @@
+/*
+ * 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 <gtest/gtest.h>
+#include <optional>
+#include <string>
+#include <vector>
+
+#include "FakeSecureHardwareProxy.h"
+
+// Most of libeic is tested as part of VTS since there's almost a 1:1 mapping between
+// the HAL and libeic interfaces. This test suite is mainly for the few things which
+// doesn't map directly.
+//
+
+using std::optional;
+using std::string;
+using std::vector;
+
+using android::hardware::identity::AccessCheckResult;
+using android::hardware::identity::FakeSecureHardwarePresentationProxy;
+using android::hardware::identity::FakeSecureHardwareProvisioningProxy;
+
+TEST(EicTest, AccessControlIsEnforced) {
+    // First provision the credential...
+    //
+    FakeSecureHardwareProvisioningProxy provisioningProxy;
+    bool isTestCredential = false;
+    provisioningProxy.initialize(isTestCredential);
+    optional<vector<uint8_t>> credKey =
+            provisioningProxy.createCredentialKey({0x01, 0x02}, {0x03, 0x04});
+    ASSERT_TRUE(credKey.has_value());
+    string docType = "org.iso.18013.5.1.mDL";
+    ASSERT_TRUE(provisioningProxy.startPersonalization(0, {1}, docType, 125));
+
+    vector<int> acpIds = {};
+    string nameSpace = "org.iso.18013.5.1";
+    string name = "NonAccessibleElement";
+    vector<uint8_t> content = {0x63, 0x46, 0x6f, 0x6f};  // "Foo" tstr
+    ASSERT_TRUE(provisioningProxy.beginAddEntry(acpIds, nameSpace, name, content.size()));
+    optional<vector<uint8_t>> encContent =
+            provisioningProxy.addEntryValue(acpIds, nameSpace, name, content);
+    ASSERT_TRUE(encContent.has_value());
+    ASSERT_EQ(encContent->size(), content.size() + 28);
+
+    optional<vector<uint8_t>> signatureOfToBeSigned = provisioningProxy.finishAddingEntries();
+    ASSERT_TRUE(signatureOfToBeSigned.has_value());
+
+    optional<vector<uint8_t>> credData = provisioningProxy.finishGetCredentialData(docType);
+    ASSERT_TRUE(credData.has_value());
+    ASSERT_TRUE(provisioningProxy.shutdown());
+
+    // Then present data from it...
+    //
+    FakeSecureHardwarePresentationProxy presentationProxy;
+    ASSERT_TRUE(presentationProxy.initialize(isTestCredential, docType, credData.value()));
+    AccessCheckResult res =
+            presentationProxy.startRetrieveEntryValue(nameSpace, name, 1, content.size(), acpIds);
+    ASSERT_EQ(res, AccessCheckResult::kNoAccessControlProfiles);
+
+    // Ensure that we can't get the data out if startRetrieveEntryValue() returned
+    // something other than kOk... See b/190757775 for details.
+    //
+    optional<vector<uint8_t>> decContent =
+            presentationProxy.retrieveEntryValue(encContent.value(), nameSpace, name, acpIds);
+    ASSERT_FALSE(decContent.has_value());
+}
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    return RUN_ALL_TESTS();
+}
diff --git a/identity/aidl/default/libeic/EicPresentation.c b/identity/aidl/default/libeic/EicPresentation.c
index 9e033b3..3d13766 100644
--- a/identity/aidl/default/libeic/EicPresentation.c
+++ b/identity/aidl/default/libeic/EicPresentation.c
@@ -633,6 +633,8 @@
 
     // We'll need to calc and store a digest of additionalData to check that it's the same
     // additionalData being passed in for every eicPresentationRetrieveEntryValue() call...
+    //
+    ctx->accessCheckOk = false;
     if (!eicCborCalcEntryAdditionalData(accessControlProfileIds, numAccessControlProfileIds,
                                         nameSpace, name, additionalDataCbor,
                                         additionalDataCborBufSize, &additionalDataCborSize,
@@ -680,6 +682,7 @@
 
     if (result == EIC_ACCESS_CHECK_RESULT_OK) {
         eicCborAppendString(&ctx->cbor, name);
+        ctx->accessCheckOk = true;
     }
     return result;
 }
@@ -702,10 +705,15 @@
                                         calculatedSha256)) {
         return false;
     }
+
     if (eicCryptoMemCmp(calculatedSha256, ctx->additionalDataSha256, EIC_SHA256_DIGEST_SIZE) != 0) {
         eicDebug("SHA-256 mismatch of additionalData");
         return false;
     }
+    if (!ctx->accessCheckOk) {
+        eicDebug("Attempting to retrieve a value for which access is not granted");
+        return false;
+    }
 
     if (!eicOpsDecryptAes128Gcm(ctx->storageKey, encryptedContent, encryptedContentSize,
                                 additionalDataCbor, additionalDataCborSize, content)) {
diff --git a/identity/aidl/default/libeic/EicPresentation.h b/identity/aidl/default/libeic/EicPresentation.h
index 7cad068..c888049 100644
--- a/identity/aidl/default/libeic/EicPresentation.h
+++ b/identity/aidl/default/libeic/EicPresentation.h
@@ -70,6 +70,10 @@
     // Set to true initialized as a test credential.
     bool testCredential;
 
+    // Set to true if the evaluation of access control checks in
+    // eicPresentationStartRetrieveEntryValue() resulted EIC_ACCESS_CHECK_RESULT_OK
+    bool accessCheckOk;
+
     // These are bitmasks indicating which of the possible 32 access control profiles are
     // authorized. They are built up by eicPresentationValidateAccessControlProfile().
     //
diff --git a/input/classifier/1.0/vts/functional/Android.bp b/input/classifier/1.0/vts/functional/Android.bp
index e170f4a..58945d3 100644
--- a/input/classifier/1.0/vts/functional/Android.bp
+++ b/input/classifier/1.0/vts/functional/Android.bp
@@ -26,7 +26,10 @@
 cc_test {
     name: "VtsHalInputClassifierV1_0TargetTest",
     defaults: ["VtsHalTargetTestDefaults"],
-    srcs: ["VtsHalInputClassifierV1_0TargetTest.cpp"],
+    srcs: [
+        ":inputconstants_aidl",
+        "VtsHalInputClassifierV1_0TargetTest.cpp",
+    ],
     header_libs: ["jni_headers"],
     static_libs: [
         "android.hardware.input.classifier@1.0",
diff --git a/keymaster/4.0/support/attestation_record.cpp b/keymaster/4.0/support/attestation_record.cpp
index bc294bd..342b3e2 100644
--- a/keymaster/4.0/support/attestation_record.cpp
+++ b/keymaster/4.0/support/attestation_record.cpp
@@ -71,6 +71,7 @@
     ASN1_INTEGER_SET* padding;
     ASN1_INTEGER* ec_curve;
     ASN1_INTEGER* rsa_public_exponent;
+    ASN1_NULL* rollback_resistance;
     ASN1_INTEGER* active_date_time;
     ASN1_INTEGER* origination_expire_date_time;
     ASN1_INTEGER* usage_expire_date_time;
@@ -78,56 +79,84 @@
     ASN1_INTEGER* user_auth_type;
     ASN1_INTEGER* auth_timeout;
     ASN1_NULL* allow_while_on_body;
+    ASN1_NULL* trusted_user_presence_required;
+    ASN1_NULL* trusted_confirmation_required;
+    ASN1_NULL* unlocked_device_required;
     ASN1_NULL* all_applications;
     ASN1_OCTET_STRING* application_id;
     ASN1_INTEGER* creation_date_time;
     ASN1_INTEGER* origin;
-    ASN1_NULL* rollback_resistance;
     KM_ROOT_OF_TRUST* root_of_trust;
     ASN1_INTEGER* os_version;
     ASN1_INTEGER* os_patchlevel;
     ASN1_OCTET_STRING* attestation_application_id;
-    ASN1_NULL* trusted_user_presence_required;
-    ASN1_NULL* trusted_confirmation_required;
-    ASN1_NULL* unlocked_device_required;
+    ASN1_OCTET_STRING* attestation_id_brand;
+    ASN1_OCTET_STRING* attestation_id_device;
+    ASN1_OCTET_STRING* attestation_id_product;
+    ASN1_OCTET_STRING* attestation_id_serial;
+    ASN1_OCTET_STRING* attestation_id_imei;
+    ASN1_OCTET_STRING* attestation_id_meid;
+    ASN1_OCTET_STRING* attestation_id_manufacturer;
+    ASN1_OCTET_STRING* attestation_id_model;
     ASN1_INTEGER* vendor_patchlevel;
     ASN1_INTEGER* boot_patchlevel;
 } KM_AUTH_LIST;
 
 ASN1_SEQUENCE(KM_AUTH_LIST) = {
-    ASN1_EXP_SET_OF_OPT(KM_AUTH_LIST, purpose, ASN1_INTEGER, TAG_PURPOSE.maskedTag()),
-    ASN1_EXP_OPT(KM_AUTH_LIST, algorithm, ASN1_INTEGER, TAG_ALGORITHM.maskedTag()),
-    ASN1_EXP_OPT(KM_AUTH_LIST, key_size, ASN1_INTEGER, TAG_KEY_SIZE.maskedTag()),
-    ASN1_EXP_SET_OF_OPT(KM_AUTH_LIST, digest, ASN1_INTEGER, TAG_DIGEST.maskedTag()),
-    ASN1_EXP_SET_OF_OPT(KM_AUTH_LIST, padding, ASN1_INTEGER, TAG_PADDING.maskedTag()),
-    ASN1_EXP_OPT(KM_AUTH_LIST, ec_curve, ASN1_INTEGER, TAG_EC_CURVE.maskedTag()),
-    ASN1_EXP_OPT(KM_AUTH_LIST, rsa_public_exponent, ASN1_INTEGER,
-                 TAG_RSA_PUBLIC_EXPONENT.maskedTag()),
-    ASN1_EXP_OPT(KM_AUTH_LIST, rollback_resistance, ASN1_NULL, TAG_ROLLBACK_RESISTANCE.maskedTag()),
-    ASN1_EXP_OPT(KM_AUTH_LIST, active_date_time, ASN1_INTEGER, TAG_ACTIVE_DATETIME.maskedTag()),
-    ASN1_EXP_OPT(KM_AUTH_LIST, origination_expire_date_time, ASN1_INTEGER,
-                 TAG_ORIGINATION_EXPIRE_DATETIME.maskedTag()),
-    ASN1_EXP_OPT(KM_AUTH_LIST, usage_expire_date_time, ASN1_INTEGER,
-                 TAG_USAGE_EXPIRE_DATETIME.maskedTag()),
-    ASN1_EXP_OPT(KM_AUTH_LIST, no_auth_required, ASN1_NULL, TAG_NO_AUTH_REQUIRED.maskedTag()),
-    ASN1_EXP_OPT(KM_AUTH_LIST, user_auth_type, ASN1_INTEGER, TAG_USER_AUTH_TYPE.maskedTag()),
-    ASN1_EXP_OPT(KM_AUTH_LIST, auth_timeout, ASN1_INTEGER, TAG_AUTH_TIMEOUT.maskedTag()),
-    ASN1_EXP_OPT(KM_AUTH_LIST, allow_while_on_body, ASN1_NULL, TAG_ALLOW_WHILE_ON_BODY.maskedTag()),
-    ASN1_EXP_OPT(KM_AUTH_LIST, trusted_user_presence_required, ASN1_NULL,
-                 TAG_TRUSTED_USER_PRESENCE_REQUIRED.maskedTag()),
-    ASN1_EXP_OPT(KM_AUTH_LIST, trusted_confirmation_required, ASN1_NULL,
-                 TAG_TRUSTED_CONFIRMATION_REQUIRED.maskedTag()),
-    ASN1_EXP_OPT(KM_AUTH_LIST, unlocked_device_required, ASN1_NULL,
-                 TAG_UNLOCKED_DEVICE_REQUIRED.maskedTag()),
-    ASN1_EXP_OPT(KM_AUTH_LIST, creation_date_time, ASN1_INTEGER, TAG_CREATION_DATETIME.maskedTag()),
-    ASN1_EXP_OPT(KM_AUTH_LIST, origin, ASN1_INTEGER, TAG_ORIGIN.maskedTag()),
-    ASN1_EXP_OPT(KM_AUTH_LIST, root_of_trust, KM_ROOT_OF_TRUST, TAG_ROOT_OF_TRUST.maskedTag()),
-    ASN1_EXP_OPT(KM_AUTH_LIST, os_version, ASN1_INTEGER, TAG_OS_VERSION.maskedTag()),
-    ASN1_EXP_OPT(KM_AUTH_LIST, os_patchlevel, ASN1_INTEGER, TAG_OS_PATCHLEVEL.maskedTag()),
-    ASN1_EXP_OPT(KM_AUTH_LIST, vendor_patchlevel, ASN1_INTEGER, TAG_VENDOR_PATCHLEVEL.maskedTag()),
-    ASN1_EXP_OPT(KM_AUTH_LIST, boot_patchlevel, ASN1_INTEGER, TAG_BOOT_PATCHLEVEL.maskedTag()),
-    ASN1_EXP_OPT(KM_AUTH_LIST, attestation_application_id, ASN1_OCTET_STRING,
-                 TAG_ATTESTATION_APPLICATION_ID.maskedTag()),
+        ASN1_EXP_SET_OF_OPT(KM_AUTH_LIST, purpose, ASN1_INTEGER, TAG_PURPOSE.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, algorithm, ASN1_INTEGER, TAG_ALGORITHM.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, key_size, ASN1_INTEGER, TAG_KEY_SIZE.maskedTag()),
+        ASN1_EXP_SET_OF_OPT(KM_AUTH_LIST, digest, ASN1_INTEGER, TAG_DIGEST.maskedTag()),
+        ASN1_EXP_SET_OF_OPT(KM_AUTH_LIST, padding, ASN1_INTEGER, TAG_PADDING.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, ec_curve, ASN1_INTEGER, TAG_EC_CURVE.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, rsa_public_exponent, ASN1_INTEGER,
+                     TAG_RSA_PUBLIC_EXPONENT.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, rollback_resistance, ASN1_NULL,
+                     TAG_ROLLBACK_RESISTANCE.maskedTag()),
+
+        ASN1_EXP_OPT(KM_AUTH_LIST, active_date_time, ASN1_INTEGER, TAG_ACTIVE_DATETIME.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, origination_expire_date_time, ASN1_INTEGER,
+                     TAG_ORIGINATION_EXPIRE_DATETIME.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, usage_expire_date_time, ASN1_INTEGER,
+                     TAG_USAGE_EXPIRE_DATETIME.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, no_auth_required, ASN1_NULL, TAG_NO_AUTH_REQUIRED.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, user_auth_type, ASN1_INTEGER, TAG_USER_AUTH_TYPE.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, auth_timeout, ASN1_INTEGER, TAG_AUTH_TIMEOUT.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, allow_while_on_body, ASN1_NULL,
+                     TAG_ALLOW_WHILE_ON_BODY.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, trusted_user_presence_required, ASN1_NULL,
+                     TAG_TRUSTED_USER_PRESENCE_REQUIRED.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, trusted_confirmation_required, ASN1_NULL,
+                     TAG_TRUSTED_CONFIRMATION_REQUIRED.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, unlocked_device_required, ASN1_NULL,
+                     TAG_UNLOCKED_DEVICE_REQUIRED.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, creation_date_time, ASN1_INTEGER,
+                     TAG_CREATION_DATETIME.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, origin, ASN1_INTEGER, TAG_ORIGIN.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, root_of_trust, KM_ROOT_OF_TRUST, TAG_ROOT_OF_TRUST.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, os_version, ASN1_INTEGER, TAG_OS_VERSION.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, os_patchlevel, ASN1_INTEGER, TAG_OS_PATCHLEVEL.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, attestation_application_id, ASN1_OCTET_STRING,
+                     TAG_ATTESTATION_APPLICATION_ID.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_brand, ASN1_OCTET_STRING,
+                     TAG_ATTESTATION_ID_BRAND.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_device, ASN1_OCTET_STRING,
+                     TAG_ATTESTATION_ID_DEVICE.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_product, ASN1_OCTET_STRING,
+                     TAG_ATTESTATION_ID_PRODUCT.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_serial, ASN1_OCTET_STRING,
+                     TAG_ATTESTATION_ID_SERIAL.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_imei, ASN1_OCTET_STRING,
+                     TAG_ATTESTATION_ID_IMEI.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_meid, ASN1_OCTET_STRING,
+                     TAG_ATTESTATION_ID_MEID.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_manufacturer, ASN1_OCTET_STRING,
+                     TAG_ATTESTATION_ID_MANUFACTURER.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_model, ASN1_OCTET_STRING,
+                     TAG_ATTESTATION_ID_MODEL.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, vendor_patchlevel, ASN1_INTEGER,
+                     TAG_VENDOR_PATCHLEVEL.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, boot_patchlevel, ASN1_INTEGER, TAG_BOOT_PATCHLEVEL.maskedTag()),
 } ASN1_SEQUENCE_END(KM_AUTH_LIST);
 IMPLEMENT_ASN1_FUNCTIONS(KM_AUTH_LIST);
 
@@ -259,6 +288,14 @@
     copyAuthTag(record->usage_expire_date_time, TAG_USAGE_EXPIRE_DATETIME, auth_list);
     copyAuthTag(record->user_auth_type, TAG_USER_AUTH_TYPE, auth_list);
     copyAuthTag(record->attestation_application_id, TAG_ATTESTATION_APPLICATION_ID, auth_list);
+    copyAuthTag(record->attestation_id_brand, TAG_ATTESTATION_ID_BRAND, auth_list);
+    copyAuthTag(record->attestation_id_device, TAG_ATTESTATION_ID_DEVICE, auth_list);
+    copyAuthTag(record->attestation_id_product, TAG_ATTESTATION_ID_PRODUCT, auth_list);
+    copyAuthTag(record->attestation_id_serial, TAG_ATTESTATION_ID_SERIAL, auth_list);
+    copyAuthTag(record->attestation_id_imei, TAG_ATTESTATION_ID_IMEI, auth_list);
+    copyAuthTag(record->attestation_id_meid, TAG_ATTESTATION_ID_MEID, auth_list);
+    copyAuthTag(record->attestation_id_manufacturer, TAG_ATTESTATION_ID_MANUFACTURER, auth_list);
+    copyAuthTag(record->attestation_id_model, TAG_ATTESTATION_ID_MODEL, auth_list);
     copyAuthTag(record->vendor_patchlevel, TAG_VENDOR_PATCHLEVEL, auth_list);
     copyAuthTag(record->boot_patchlevel, TAG_BOOT_PATCHLEVEL, auth_list);
     copyAuthTag(record->trusted_user_presence_required, TAG_TRUSTED_USER_PRESENCE_REQUIRED,
diff --git a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
index 9e37ed0..01c502c 100644
--- a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
+++ b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
@@ -96,6 +96,18 @@
     return count > 0;
 }
 
+// If the given property is available, add it to the tag set under the given tag ID.
+template <Tag tag>
+void add_tag_from_prop(AuthorizationSetBuilder* tags, TypedTag<TagType::BYTES, tag> ttag,
+                       const char* prop) {
+    char value[PROPERTY_VALUE_MAX];
+    int len = property_get(prop, value, /* default = */ "");
+    if (len > 0) {
+        tags->Authorization(ttag, reinterpret_cast<const uint8_t*>(value),
+                            static_cast<size_t>(len));
+    }
+}
+
 constexpr char hex_value[256] = {0, 0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,  //
                                  0, 0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,  //
                                  0, 0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,  //
@@ -4409,6 +4421,95 @@
 }
 
 /*
+ * AttestationTest.EcAttestationID
+ *
+ * Verifies that attesting to EC keys with correct attestation ID fields works and generates the
+ * expected output.
+ */
+TEST_P(AttestationTest, EcAttestationID) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                                 .Authorization(TAG_NO_AUTH_REQUIRED)
+                                                 .EcdsaSigningKey(EcCurve::P_256)
+                                                 .Digest(Digest::SHA_2_256)
+                                                 .Authorization(TAG_INCLUDE_UNIQUE_ID)));
+
+    // Collection of valid attestation ID tags.
+    auto attestation_id_tags = AuthorizationSetBuilder();
+    add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_BRAND, "ro.product.brand");
+    add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_DEVICE, "ro.product.device");
+    add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_PRODUCT, "ro.product.name");
+    add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_SERIAL, "ro.serial");
+    add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_MANUFACTURER,
+                      "ro.product.manufacturer");
+    add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_MODEL, "ro.product.model");
+
+    for (const KeyParameter& tag : attestation_id_tags) {
+        AuthorizationSetBuilder builder =
+                AuthorizationSetBuilder()
+                        .Authorization(TAG_ATTESTATION_CHALLENGE, HidlBuf("challenge"))
+                        .Authorization(TAG_ATTESTATION_APPLICATION_ID, HidlBuf("foo"));
+        // Include one of the (valid) attestation ID tags.
+        builder.push_back(tag);
+        hidl_vec<hidl_vec<uint8_t>> cert_chain;
+        auto result = AttestKey(builder, &cert_chain);
+        if (result == ErrorCode::CANNOT_ATTEST_IDS) {
+            continue;
+        }
+
+        ASSERT_EQ(ErrorCode::OK, result);
+        EXPECT_GE(cert_chain.size(), 2U);
+
+        std::vector<KeyParameter> expected_hw_enforced = key_characteristics_.hardwareEnforced;
+        expected_hw_enforced.push_back(tag);
+
+        EXPECT_TRUE(verify_attestation_record(
+                "challenge", "foo", key_characteristics_.softwareEnforced,
+                hidl_vec<KeyParameter>(expected_hw_enforced), SecLevel(), cert_chain[0]));
+    }
+}
+
+/*
+ * AttestationTest.EcAttestationMismatchID
+ *
+ * Verifies that attesting to EC keys with incorrect attestation ID fields fails.
+ */
+TEST_P(AttestationTest, EcAttestationMismatchID) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                                 .Authorization(TAG_NO_AUTH_REQUIRED)
+                                                 .EcdsaSigningKey(EcCurve::P_256)
+                                                 .Digest(Digest::SHA_2_256)
+                                                 .Authorization(TAG_INCLUDE_UNIQUE_ID)));
+
+    // Collection of invalid attestation ID tags.
+    std::string invalid = "completely-invalid";
+    auto invalid_tags =
+            AuthorizationSetBuilder()
+                    .Authorization(V4_0::TAG_ATTESTATION_ID_BRAND, invalid.data(), invalid.size())
+                    .Authorization(V4_0::TAG_ATTESTATION_ID_DEVICE, invalid.data(), invalid.size())
+                    .Authorization(V4_0::TAG_ATTESTATION_ID_PRODUCT, invalid.data(), invalid.size())
+                    .Authorization(V4_0::TAG_ATTESTATION_ID_SERIAL, invalid.data(), invalid.size())
+                    .Authorization(V4_0::TAG_ATTESTATION_ID_IMEI, invalid.data(), invalid.size())
+                    .Authorization(V4_0::TAG_ATTESTATION_ID_MEID, invalid.data(), invalid.size())
+                    .Authorization(V4_0::TAG_ATTESTATION_ID_MANUFACTURER, invalid.data(),
+                                   invalid.size())
+                    .Authorization(V4_0::TAG_ATTESTATION_ID_MODEL, invalid.data(), invalid.size());
+
+    for (const KeyParameter& invalid_tag : invalid_tags) {
+        AuthorizationSetBuilder builder =
+                AuthorizationSetBuilder()
+                        .Authorization(TAG_ATTESTATION_CHALLENGE, HidlBuf("challenge"))
+                        .Authorization(TAG_ATTESTATION_APPLICATION_ID, HidlBuf("foo"));
+        // Include one of the invalid attestation ID tags.
+        builder.push_back(invalid_tag);
+        hidl_vec<hidl_vec<uint8_t>> cert_chain;
+        auto result = AttestKey(builder, &cert_chain);
+
+        EXPECT_TRUE(result == ErrorCode::CANNOT_ATTEST_IDS || result == ErrorCode::INVALID_TAG)
+                << "result: " << static_cast<int32_t>(result);
+    }
+}
+
+/*
  * AttestationTest.EcAttestationRequiresAttestationAppId
  *
  * Verifies that attesting to EC keys requires app ID
diff --git a/keymaster/4.1/support/attestation_record.cpp b/keymaster/4.1/support/attestation_record.cpp
index 207a7e8..15230d5 100644
--- a/keymaster/4.1/support/attestation_record.cpp
+++ b/keymaster/4.1/support/attestation_record.cpp
@@ -79,6 +79,8 @@
     ASN1_INTEGER_SET* padding;
     ASN1_INTEGER* ec_curve;
     ASN1_INTEGER* rsa_public_exponent;
+    ASN1_NULL* rollback_resistance;
+    ASN1_NULL* early_boot_only;
     ASN1_INTEGER* active_date_time;
     ASN1_INTEGER* origination_expire_date_time;
     ASN1_INTEGER* usage_expire_date_time;
@@ -86,21 +88,27 @@
     ASN1_INTEGER* user_auth_type;
     ASN1_INTEGER* auth_timeout;
     ASN1_NULL* allow_while_on_body;
+    ASN1_NULL* trusted_user_presence_required;
+    ASN1_NULL* trusted_confirmation_required;
+    ASN1_NULL* unlocked_device_required;
     ASN1_NULL* all_applications;
     ASN1_OCTET_STRING* application_id;
     ASN1_INTEGER* creation_date_time;
     ASN1_INTEGER* origin;
-    ASN1_NULL* rollback_resistance;
     KM_ROOT_OF_TRUST* root_of_trust;
     ASN1_INTEGER* os_version;
     ASN1_INTEGER* os_patchlevel;
     ASN1_OCTET_STRING* attestation_application_id;
-    ASN1_NULL* trusted_user_presence_required;
-    ASN1_NULL* trusted_confirmation_required;
-    ASN1_NULL* unlocked_device_required;
+    ASN1_OCTET_STRING* attestation_id_brand;
+    ASN1_OCTET_STRING* attestation_id_device;
+    ASN1_OCTET_STRING* attestation_id_product;
+    ASN1_OCTET_STRING* attestation_id_serial;
+    ASN1_OCTET_STRING* attestation_id_imei;
+    ASN1_OCTET_STRING* attestation_id_meid;
+    ASN1_OCTET_STRING* attestation_id_manufacturer;
+    ASN1_OCTET_STRING* attestation_id_model;
     ASN1_INTEGER* vendor_patchlevel;
     ASN1_INTEGER* boot_patchlevel;
-    ASN1_NULL* early_boot_only;
     ASN1_NULL* device_unique_attestation;
     ASN1_NULL* identity_credential_key;
 } KM_AUTH_LIST;
@@ -116,6 +124,7 @@
                      TAG_RSA_PUBLIC_EXPONENT.maskedTag()),
         ASN1_EXP_OPT(KM_AUTH_LIST, rollback_resistance, ASN1_NULL,
                      TAG_ROLLBACK_RESISTANCE.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, early_boot_only, ASN1_NULL, TAG_EARLY_BOOT_ONLY.maskedTag()),
         ASN1_EXP_OPT(KM_AUTH_LIST, active_date_time, ASN1_INTEGER, TAG_ACTIVE_DATETIME.maskedTag()),
         ASN1_EXP_OPT(KM_AUTH_LIST, origination_expire_date_time, ASN1_INTEGER,
                      TAG_ORIGINATION_EXPIRE_DATETIME.maskedTag()),
@@ -138,12 +147,27 @@
         ASN1_EXP_OPT(KM_AUTH_LIST, root_of_trust, KM_ROOT_OF_TRUST, TAG_ROOT_OF_TRUST.maskedTag()),
         ASN1_EXP_OPT(KM_AUTH_LIST, os_version, ASN1_INTEGER, TAG_OS_VERSION.maskedTag()),
         ASN1_EXP_OPT(KM_AUTH_LIST, os_patchlevel, ASN1_INTEGER, TAG_OS_PATCHLEVEL.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, attestation_application_id, ASN1_OCTET_STRING,
+                     TAG_ATTESTATION_APPLICATION_ID.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_brand, ASN1_OCTET_STRING,
+                     TAG_ATTESTATION_ID_BRAND.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_device, ASN1_OCTET_STRING,
+                     TAG_ATTESTATION_ID_DEVICE.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_product, ASN1_OCTET_STRING,
+                     TAG_ATTESTATION_ID_PRODUCT.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_serial, ASN1_OCTET_STRING,
+                     TAG_ATTESTATION_ID_SERIAL.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_imei, ASN1_OCTET_STRING,
+                     TAG_ATTESTATION_ID_IMEI.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_meid, ASN1_OCTET_STRING,
+                     TAG_ATTESTATION_ID_MEID.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_manufacturer, ASN1_OCTET_STRING,
+                     TAG_ATTESTATION_ID_MANUFACTURER.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_model, ASN1_OCTET_STRING,
+                     TAG_ATTESTATION_ID_MODEL.maskedTag()),
         ASN1_EXP_OPT(KM_AUTH_LIST, vendor_patchlevel, ASN1_INTEGER,
                      TAG_VENDOR_PATCHLEVEL.maskedTag()),
         ASN1_EXP_OPT(KM_AUTH_LIST, boot_patchlevel, ASN1_INTEGER, TAG_BOOT_PATCHLEVEL.maskedTag()),
-        ASN1_EXP_OPT(KM_AUTH_LIST, attestation_application_id, ASN1_OCTET_STRING,
-                     TAG_ATTESTATION_APPLICATION_ID.maskedTag()),
-        ASN1_EXP_OPT(KM_AUTH_LIST, early_boot_only, ASN1_NULL, TAG_EARLY_BOOT_ONLY.maskedTag()),
         ASN1_EXP_OPT(KM_AUTH_LIST, device_unique_attestation, ASN1_NULL,
                      TAG_DEVICE_UNIQUE_ATTESTATION.maskedTag()),
         ASN1_EXP_OPT(KM_AUTH_LIST, identity_credential_key, ASN1_NULL,
@@ -279,6 +303,14 @@
     copyAuthTag(record->usage_expire_date_time, TAG_USAGE_EXPIRE_DATETIME, auth_list);
     copyAuthTag(record->user_auth_type, TAG_USER_AUTH_TYPE, auth_list);
     copyAuthTag(record->attestation_application_id, TAG_ATTESTATION_APPLICATION_ID, auth_list);
+    copyAuthTag(record->attestation_id_brand, TAG_ATTESTATION_ID_BRAND, auth_list);
+    copyAuthTag(record->attestation_id_device, TAG_ATTESTATION_ID_DEVICE, auth_list);
+    copyAuthTag(record->attestation_id_product, TAG_ATTESTATION_ID_PRODUCT, auth_list);
+    copyAuthTag(record->attestation_id_serial, TAG_ATTESTATION_ID_SERIAL, auth_list);
+    copyAuthTag(record->attestation_id_imei, TAG_ATTESTATION_ID_IMEI, auth_list);
+    copyAuthTag(record->attestation_id_meid, TAG_ATTESTATION_ID_MEID, auth_list);
+    copyAuthTag(record->attestation_id_manufacturer, TAG_ATTESTATION_ID_MANUFACTURER, auth_list);
+    copyAuthTag(record->attestation_id_model, TAG_ATTESTATION_ID_MODEL, auth_list);
     copyAuthTag(record->vendor_patchlevel, TAG_VENDOR_PATCHLEVEL, auth_list);
     copyAuthTag(record->boot_patchlevel, TAG_BOOT_PATCHLEVEL, auth_list);
     copyAuthTag(record->trusted_user_presence_required, TAG_TRUSTED_USER_PRESENCE_REQUIRED,
diff --git a/keymaster/4.1/support/include/keymasterV4_1/keymaster_tags.h b/keymaster/4.1/support/include/keymasterV4_1/keymaster_tags.h
index 40eb142..e8db56a 100644
--- a/keymaster/4.1/support/include/keymasterV4_1/keymaster_tags.h
+++ b/keymaster/4.1/support/include/keymasterV4_1/keymaster_tags.h
@@ -53,6 +53,14 @@
 using V4_0::TAG_ASSOCIATED_DATA;
 using V4_0::TAG_ATTESTATION_APPLICATION_ID;
 using V4_0::TAG_ATTESTATION_CHALLENGE;
+using V4_0::TAG_ATTESTATION_ID_BRAND;
+using V4_0::TAG_ATTESTATION_ID_DEVICE;
+using V4_0::TAG_ATTESTATION_ID_IMEI;
+using V4_0::TAG_ATTESTATION_ID_MANUFACTURER;
+using V4_0::TAG_ATTESTATION_ID_MEID;
+using V4_0::TAG_ATTESTATION_ID_MODEL;
+using V4_0::TAG_ATTESTATION_ID_PRODUCT;
+using V4_0::TAG_ATTESTATION_ID_SERIAL;
 using V4_0::TAG_AUTH_TIMEOUT;
 using V4_0::TAG_BLOB_USAGE_REQUIREMENTS;
 using V4_0::TAG_BLOCK_MODE;
diff --git a/keymaster/4.1/vts/functional/DeviceUniqueAttestationTest.cpp b/keymaster/4.1/vts/functional/DeviceUniqueAttestationTest.cpp
index 0639da8..4a57f44 100644
--- a/keymaster/4.1/vts/functional/DeviceUniqueAttestationTest.cpp
+++ b/keymaster/4.1/vts/functional/DeviceUniqueAttestationTest.cpp
@@ -16,6 +16,7 @@
 
 #define LOG_TAG "keymaster_hidl_hal_test"
 #include <cutils/log.h>
+#include <vector>
 
 #include "Keymaster4_1HidlTest.h"
 
@@ -26,6 +27,8 @@
 #include <keymasterV4_1/attestation_record.h>
 #include <keymasterV4_1/authorization_set.h>
 
+using android::hardware::keymaster::V4_0::test::add_tag_from_prop;
+
 // Not to dump the attestation by default. Can enable by specify the parameter
 // "--dump_attestations" on lunching VTS
 static bool dumpAttestations = false;
@@ -172,10 +175,42 @@
     attestation.software_enforced.Sort();
     attestation.hardware_enforced.Sort();
 
-    EXPECT_EQ(filter_tags(expected_sw_enforced), filter_tags(attestation.software_enforced))
-            << DIFFERENCE(expected_sw_enforced, attestation.software_enforced);
-    EXPECT_EQ(filter_tags(expected_hw_enforced), filter_tags(attestation.hardware_enforced))
-            << DIFFERENCE(expected_hw_enforced, attestation.hardware_enforced);
+    expected_sw_enforced = filter_tags(expected_sw_enforced);
+    expected_hw_enforced = filter_tags(expected_hw_enforced);
+    AuthorizationSet attestation_sw_enforced = filter_tags(attestation.software_enforced);
+    AuthorizationSet attestation_hw_enforced = filter_tags(attestation.hardware_enforced);
+
+    EXPECT_EQ(expected_sw_enforced, attestation_sw_enforced)
+            << DIFFERENCE(expected_sw_enforced, attestation_sw_enforced);
+    EXPECT_EQ(expected_hw_enforced, attestation_hw_enforced)
+            << DIFFERENCE(expected_hw_enforced, attestation_hw_enforced);
+}
+
+X509_Ptr parse_cert_blob(const std::vector<uint8_t>& blob) {
+    const uint8_t* p = blob.data();
+    return X509_Ptr(d2i_X509(nullptr /* allocate new */, &p, blob.size()));
+}
+
+bool check_certificate_chain_signatures(const hidl_vec<hidl_vec<uint8_t>>& cert_chain) {
+    // TODO: Check that root is self-signed once b/187803288 is resolved.
+    for (size_t i = 0; i < cert_chain.size() - 1; ++i) {
+        X509_Ptr key_cert(parse_cert_blob(cert_chain[i]));
+        X509_Ptr signing_cert(parse_cert_blob(cert_chain[i + 1]));
+
+        if (!key_cert.get() || !signing_cert.get()) {
+            return false;
+        }
+
+        EVP_PKEY_Ptr signing_pubkey(X509_get_pubkey(signing_cert.get()));
+        if (!signing_pubkey.get()) {
+            return false;
+        }
+
+        if (!X509_verify(key_cert.get(), signing_pubkey.get())) {
+            return false;
+        }
+    }
+    return true;
 }
 
 }  // namespace
@@ -243,6 +278,7 @@
 
     EXPECT_EQ(ErrorCode::OK, result);
     EXPECT_EQ(2U, cert_chain.size());
+    EXPECT_TRUE(check_certificate_chain_signatures(cert_chain));
     if (dumpAttestations) {
       for (auto cert_ : cert_chain) dumpContent(bin2hex(cert_));
     }
@@ -289,6 +325,7 @@
 
     EXPECT_EQ(ErrorCode::OK, result);
     EXPECT_EQ(2U, cert_chain.size());
+    EXPECT_TRUE(check_certificate_chain_signatures(cert_chain));
     if (dumpAttestations) {
       for (auto cert_ : cert_chain) dumpContent(bin2hex(cert_));
     }
@@ -312,6 +349,106 @@
             SecLevel());
 }
 
+TEST_P(DeviceUniqueAttestationTest, EcdsaDeviceUniqueAttestationID) {
+    if (SecLevel() != SecurityLevel::STRONGBOX) return;
+
+    ASSERT_EQ(ErrorCode::OK, convert(GenerateKey(AuthorizationSetBuilder()
+                                                         .Authorization(TAG_NO_AUTH_REQUIRED)
+                                                         .EcdsaSigningKey(256)
+                                                         .Digest(Digest::SHA_2_256)
+                                                         .Authorization(TAG_INCLUDE_UNIQUE_ID))));
+
+    // Collection of valid attestation ID tags.
+    auto attestation_id_tags = AuthorizationSetBuilder();
+    add_tag_from_prop(&attestation_id_tags, V4_0::TAG_ATTESTATION_ID_BRAND, "ro.product.brand");
+    add_tag_from_prop(&attestation_id_tags, V4_0::TAG_ATTESTATION_ID_DEVICE, "ro.product.device");
+    add_tag_from_prop(&attestation_id_tags, V4_0::TAG_ATTESTATION_ID_PRODUCT, "ro.product.name");
+    add_tag_from_prop(&attestation_id_tags, V4_0::TAG_ATTESTATION_ID_SERIAL, "ro.serial");
+    add_tag_from_prop(&attestation_id_tags, V4_0::TAG_ATTESTATION_ID_MANUFACTURER,
+                      "ro.product.manufacturer");
+    add_tag_from_prop(&attestation_id_tags, V4_0::TAG_ATTESTATION_ID_MODEL, "ro.product.model");
+
+    for (const KeyParameter& tag : attestation_id_tags) {
+        hidl_vec<hidl_vec<uint8_t>> cert_chain;
+        HidlBuf challenge("challenge");
+        HidlBuf app_id("foo");
+        AuthorizationSetBuilder builder =
+                AuthorizationSetBuilder()
+                        .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION)
+                        .Authorization(TAG_ATTESTATION_CHALLENGE, challenge)
+                        .Authorization(TAG_ATTESTATION_APPLICATION_ID, app_id);
+        builder.push_back(tag);
+        ErrorCode result = convert(AttestKey(builder, &cert_chain));
+
+        // It is optional for Strong box to support DeviceUniqueAttestation.
+        if (result == ErrorCode::CANNOT_ATTEST_IDS) return;
+
+        ASSERT_EQ(ErrorCode::OK, result);
+        EXPECT_EQ(2U, cert_chain.size());
+        if (dumpAttestations) {
+            for (auto cert_ : cert_chain) dumpContent(bin2hex(cert_));
+        }
+        auto [err, attestation] = parse_attestation_record(cert_chain[0]);
+        ASSERT_EQ(ErrorCode::OK, err);
+
+        AuthorizationSetBuilder hw_enforced =
+                AuthorizationSetBuilder()
+                        .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION)
+                        .Authorization(TAG_NO_AUTH_REQUIRED)
+                        .EcdsaSigningKey(256)
+                        .Digest(Digest::SHA_2_256)
+                        .Authorization(TAG_ORIGIN, KeyOrigin::GENERATED)
+                        .Authorization(TAG_OS_VERSION, os_version())
+                        .Authorization(TAG_OS_PATCHLEVEL, os_patch_level());
+        hw_enforced.push_back(tag);
+        check_attestation_record(
+                attestation, challenge,
+                /* sw_enforced */
+                AuthorizationSetBuilder().Authorization(TAG_ATTESTATION_APPLICATION_ID, app_id),
+                hw_enforced, SecLevel());
+    }
+}
+
+TEST_P(DeviceUniqueAttestationTest, EcdsaDeviceUniqueAttestationMismatchID) {
+    if (SecLevel() != SecurityLevel::STRONGBOX) return;
+
+    ASSERT_EQ(ErrorCode::OK, convert(GenerateKey(AuthorizationSetBuilder()
+                                                         .Authorization(TAG_NO_AUTH_REQUIRED)
+                                                         .EcdsaSigningKey(256)
+                                                         .Digest(Digest::SHA_2_256)
+                                                         .Authorization(TAG_INCLUDE_UNIQUE_ID))));
+
+    // Collection of invalid attestation ID tags.
+    std::string invalid = "completely-invalid";
+    auto attestation_id_tags =
+            AuthorizationSetBuilder()
+                    .Authorization(V4_0::TAG_ATTESTATION_ID_BRAND, invalid.data(), invalid.size())
+                    .Authorization(V4_0::TAG_ATTESTATION_ID_DEVICE, invalid.data(), invalid.size())
+                    .Authorization(V4_0::TAG_ATTESTATION_ID_PRODUCT, invalid.data(), invalid.size())
+                    .Authorization(V4_0::TAG_ATTESTATION_ID_SERIAL, invalid.data(), invalid.size())
+                    .Authorization(V4_0::TAG_ATTESTATION_ID_IMEI, invalid.data(), invalid.size())
+                    .Authorization(V4_0::TAG_ATTESTATION_ID_MEID, invalid.data(), invalid.size())
+                    .Authorization(V4_0::TAG_ATTESTATION_ID_MANUFACTURER, invalid.data(),
+                                   invalid.size())
+                    .Authorization(V4_0::TAG_ATTESTATION_ID_MODEL, invalid.data(), invalid.size());
+
+    for (const KeyParameter& invalid_tag : attestation_id_tags) {
+        hidl_vec<hidl_vec<uint8_t>> cert_chain;
+        HidlBuf challenge("challenge");
+        HidlBuf app_id("foo");
+        AuthorizationSetBuilder builder =
+                AuthorizationSetBuilder()
+                        .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION)
+                        .Authorization(TAG_ATTESTATION_CHALLENGE, challenge)
+                        .Authorization(TAG_ATTESTATION_APPLICATION_ID, app_id);
+        builder.push_back(invalid_tag);
+        ErrorCode result = convert(AttestKey(builder, &cert_chain));
+
+        EXPECT_TRUE(result == ErrorCode::CANNOT_ATTEST_IDS || result == ErrorCode::INVALID_TAG)
+                << "result: " << static_cast<int32_t>(result);
+    }
+}
+
 INSTANTIATE_KEYMASTER_4_1_HIDL_TEST(DeviceUniqueAttestationTest);
 
 }  // namespace test
diff --git a/keymaster/4.1/vts/functional/Keymaster4_1HidlTest.h b/keymaster/4.1/vts/functional/Keymaster4_1HidlTest.h
index f8c1fad..670ccfb 100644
--- a/keymaster/4.1/vts/functional/Keymaster4_1HidlTest.h
+++ b/keymaster/4.1/vts/functional/Keymaster4_1HidlTest.h
@@ -18,6 +18,8 @@
 
 #include <android/hardware/keymaster/4.1/IKeymasterDevice.h>
 
+#include <android-base/properties.h>
+
 #include <KeymasterHidlTest.h>
 #include <keymasterV4_1/authorization_set.h>
 
@@ -159,3 +161,17 @@
                              android::hardware::PrintInstanceNameToString)
 
 }  // namespace android::hardware::keymaster::V4_1::test
+
+namespace android::hardware::keymaster::V4_0::test {
+
+// If the given property is available, add it to the tag set under the given tag ID.
+template <Tag tag>
+void add_tag_from_prop(AuthorizationSetBuilder* tags, TypedTag<TagType::BYTES, tag> ttag,
+                       const char* prop) {
+    std::string prop_value = ::android::base::GetProperty(prop, /* default= */ "");
+    if (!prop_value.empty()) {
+        tags->Authorization(ttag, prop_value.data(), prop_value.size());
+    }
+}
+
+}  // namespace android::hardware::keymaster::V4_0::test
diff --git a/power/aidl/vts/VtsHalPowerTargetTest.cpp b/power/aidl/vts/VtsHalPowerTargetTest.cpp
index 5bb088a..ffab66c 100644
--- a/power/aidl/vts/VtsHalPowerTargetTest.cpp
+++ b/power/aidl/vts/VtsHalPowerTargetTest.cpp
@@ -22,6 +22,7 @@
 #include <android/binder_ibinder.h>
 #include <android/binder_manager.h>
 #include <android/binder_process.h>
+#include <android/binder_status.h>
 
 #include <unistd.h>
 
@@ -82,6 +83,11 @@
         DurationWrapper(1000000000L, 4L),
 };
 
+inline bool isUnknownOrUnsupported(const ndk::ScopedAStatus& status) {
+    return status.getStatus() == STATUS_UNKNOWN_TRANSACTION ||
+           status.getExceptionCode() == EX_UNSUPPORTED_OPERATION;
+}
+
 class PowerAidl : public testing::TestWithParam<std::string> {
   public:
     virtual void SetUp() override {
@@ -147,7 +153,7 @@
     int64_t rate = -1;
     auto status = power->getHintSessionPreferredRate(&rate);
     if (!status.isOk()) {
-        ASSERT_EQ(EX_UNSUPPORTED_OPERATION, status.getExceptionCode());
+        EXPECT_TRUE(isUnknownOrUnsupported(status));
         return;
     }
 
@@ -159,7 +165,7 @@
     std::shared_ptr<IPowerHintSession> session;
     auto status = power->createHintSession(getpid(), getuid(), kSelfTids, 16666666L, &session);
     if (!status.isOk()) {
-        ASSERT_EQ(EX_UNSUPPORTED_OPERATION, status.getExceptionCode());
+        EXPECT_TRUE(isUnknownOrUnsupported(status));
         return;
     }
     ASSERT_NE(nullptr, session);
@@ -173,10 +179,9 @@
     std::shared_ptr<IPowerHintSession> session;
     auto status = power->createHintSession(getpid(), getuid(), kEmptyTids, 16666666L, &session);
     ASSERT_FALSE(status.isOk());
-    if (EX_UNSUPPORTED_OPERATION == status.getExceptionCode()) {
+    if (isUnknownOrUnsupported(status)) {
         return;
     }
-    // Test with empty tid list
     ASSERT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode());
 }
 
@@ -184,7 +189,7 @@
     std::shared_ptr<IPowerHintSession> session;
     auto status = power->createHintSession(getpid(), getuid(), kSelfTids, 16666666L, &session);
     if (!status.isOk()) {
-        ASSERT_EQ(EX_UNSUPPORTED_OPERATION, status.getExceptionCode());
+        EXPECT_TRUE(isUnknownOrUnsupported(status));
         return;
     }
     ASSERT_NE(nullptr, session);
diff --git a/radio/1.6/vts/functional/radio_hidl_hal_api.cpp b/radio/1.6/vts/functional/radio_hidl_hal_api.cpp
index fd8da6e..a6eb2d8 100644
--- a/radio/1.6/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.6/vts/functional/radio_hidl_hal_api.cpp
@@ -52,6 +52,49 @@
 }
 
 /*
+ * Test IRadio.getAllowedNetworkTypesBitmap for the response returned.
+ */
+TEST_P(RadioHidlTest_v1_6, getAllowedNetworkTypesBitmap) {
+    serial = GetRandomSerialNumber();
+    ::android::hardware::hidl_bitfield<::android::hardware::radio::V1_4::RadioAccessFamily>
+            allowedNetworkTypesBitmap{};
+    allowedNetworkTypesBitmap |= ::android::hardware::radio::V1_4::RadioAccessFamily::LTE;
+
+    radio_v1_6->setAllowedNetworkTypesBitmap(serial, allowedNetworkTypesBitmap);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
+
+    if (radioRsp_v1_6->rspInfo.error == ::android::hardware::radio::V1_6::RadioError::NONE) {
+        sleep(3);  // wait for modem
+        serial = GetRandomSerialNumber();
+        radio_v1_6->getAllowedNetworkTypesBitmap(serial);
+
+        EXPECT_EQ(std::cv_status::no_timeout, wait());
+        EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
+        EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
+
+        if (getRadioHalCapabilities()) {
+            ASSERT_TRUE(CheckAnyOfErrors(
+                    radioRsp_v1_6->rspInfo.error,
+                    {::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED}));
+        } else {
+            ASSERT_TRUE(CheckAnyOfErrors(
+                    radioRsp_v1_6->rspInfo.error,
+                    {::android::hardware::radio::V1_6::RadioError::NONE,
+                     ::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE,
+                     ::android::hardware::radio::V1_6::RadioError::OPERATION_NOT_ALLOWED,
+                     ::android::hardware::radio::V1_6::RadioError::MODE_NOT_SUPPORTED,
+                     ::android::hardware::radio::V1_6::RadioError::INTERNAL_ERR,
+                     ::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS,
+                     ::android::hardware::radio::V1_6::RadioError::MODEM_ERR,
+                     ::android::hardware::radio::V1_6::RadioError::NO_RESOURCES}));
+        }
+    }
+}
+
+/*
  * Test IRadio.setupDataCall_1_6() for the response returned.
  */
 TEST_P(RadioHidlTest_v1_6, setupDataCall_1_6) {
diff --git a/radio/1.6/vts/functional/radio_response.cpp b/radio/1.6/vts/functional/radio_response.cpp
index b1e679b..e1b9f56 100644
--- a/radio/1.6/vts/functional/radio_response.cpp
+++ b/radio/1.6/vts/functional/radio_response.cpp
@@ -1172,10 +1172,13 @@
 }
 
 Return<void> RadioResponse_v1_6::getAllowedNetworkTypesBitmapResponse(
-        const ::android::hardware::radio::V1_6::RadioResponseInfo& /*info*/,
+        const ::android::hardware::radio::V1_6::RadioResponseInfo& info,
         const ::android::hardware::hidl_bitfield<
                 ::android::hardware::radio::V1_4::RadioAccessFamily>
-        /*networkTypeBitmap*/) {
+                networkTypeBitmap) {
+    rspInfo = info;
+    networkTypeBitmapResponse = networkTypeBitmap;
+    parent_v1_6.notify(info.serial);
     return Void();
 }
 
diff --git a/security/keymint/aidl/android/hardware/security/keymint/DeviceInfo.aidl b/security/keymint/aidl/android/hardware/security/keymint/DeviceInfo.aidl
index 3ea14a1..32d69cd 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/DeviceInfo.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/DeviceInfo.aidl
@@ -37,10 +37,13 @@
      *         ? "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"
      *     }
      */
     byte[] deviceInfo;
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/KeyCreationResult.aidl b/security/keymint/aidl/android/hardware/security/keymint/KeyCreationResult.aidl
index f93dbba..fd6bf65 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/KeyCreationResult.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/KeyCreationResult.aidl
@@ -159,18 +159,17 @@
      *     purpose                    [1] EXPLICIT SET OF INTEGER OPTIONAL,
      *     algorithm                  [2] EXPLICIT INTEGER OPTIONAL,
      *     keySize                    [3] EXPLICIT INTEGER OPTIONAL,
-     *     blockMode                  [4] EXPLICIT SET OF INTEGER OPTIONAL,
      *     digest                     [5] EXPLICIT SET OF INTEGER OPTIONAL,
      *     padding                    [6] EXPLICIT SET OF INTEGER OPTIONAL,
-     *     callerNonce                [7] EXPLICIT NULL OPTIONAL,
-     *     minMacLength               [8] EXPLICIT INTEGER OPTIONAL,
      *     ecCurve                    [10] EXPLICIT INTEGER OPTIONAL,
      *     rsaPublicExponent          [200] EXPLICIT INTEGER OPTIONAL,
+     *     mgfDigest                  [203] EXPLICIT SET OF INTEGER OPTIONAL,
      *     rollbackResistance         [303] EXPLICIT NULL OPTIONAL,
+     *     earlyBootOnly              [305] EXPLICIT NULL OPTIONAL,
      *     activeDateTime             [400] EXPLICIT INTEGER OPTIONAL,
      *     originationExpireDateTime  [401] EXPLICIT INTEGER OPTIONAL,
      *     usageExpireDateTime        [402] EXPLICIT INTEGER OPTIONAL,
-     *     userSecureId               [502] EXPLICIT INTEGER OPTIONAL,
+     *     usageCountLimit            [405] EXPLICIT INTEGER OPTIONAL,
      *     noAuthRequired             [503] EXPLICIT NULL OPTIONAL,
      *     userAuthType               [504] EXPLICIT INTEGER OPTIONAL,
      *     authTimeout                [505] EXPLICIT INTEGER OPTIONAL,
@@ -194,6 +193,7 @@
      *     attestationIdModel         [717] EXPLICIT OCTET_STRING OPTIONAL,
      *     vendorPatchLevel           [718] EXPLICIT INTEGER OPTIONAL,
      *     bootPatchLevel             [719] EXPLICIT INTEGER OPTIONAL,
+     *     deviceUniqueAttestation    [720] EXPLICIT NULL OPTIONAL,
      * }
      */
     Certificate[] certificateChain;
diff --git a/security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl b/security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl
index 5199062..31dbb28 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,44 +133,38 @@
      *         ? -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 = {
+     *     VerifiedDeviceInfo = {
      *         ? "brand" : tstr,
      *         ? "manufacturer" : tstr,
      *         ? "product" : tstr,
      *         ? "model" : tstr,
      *         ? "board" : tstr,
+     *         ? "device" : tstr,
      *         ? "vb_state" : "green" / "yellow" / "orange",
      *         ? "bootloader_state" : "locked" / "unlocked",
      *         ? "os_version" : tstr,
@@ -165,6 +172,39 @@
      *         ? "boot_patch_level" : uint,          // YYYYMMDD
      *         ? "vendor_patch_level" : uint,        // YYYYMMDD
      *     }
+     *
+     *     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 4ff4574..58e02b3 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl
@@ -831,14 +831,24 @@
     /**
      * DEVICE_UNIQUE_ATTESTATION is an argument to IKeyMintDevice::attested key generation/import
      * operations.  It indicates that attestation using a device-unique key is requested, rather
-     * than a batch key.  When a device-unique key is used, only the attestation certificate is
-     * returned; no additional chained certificates are provided.  It's up to the caller to
-     * recognize the device-unique signing key.  Only SecurityLevel::STRONGBOX IKeyMintDevices may
-     * support device-unique attestations.  SecurityLevel::TRUSTED_ENVIRONMENT IKeyMintDevices must
-     * return ErrorCode::INVALID_ARGUMENT if they receive DEVICE_UNIQUE_ATTESTATION.
+     * than a batch key.  When a device-unique key is used, the returned chain should contain two
+     * certificates:
+     *    * The attestation certificate, containing the attestation extension, as described in
+            KeyCreationResult.aidl.
+     *    * A self-signed root certificate, signed by the device-unique key.
+     * No additional chained certificates are provided. Only SecurityLevel::STRONGBOX
+     * IKeyMintDevices may support device-unique attestations.  SecurityLevel::TRUSTED_ENVIRONMENT
+     * IKeyMintDevices must return ErrorCode::INVALID_ARGUMENT if they receive
+     * DEVICE_UNIQUE_ATTESTATION.
      * SecurityLevel::STRONGBOX IKeyMintDevices need not support DEVICE_UNIQUE_ATTESTATION, and
      * return ErrorCode::CANNOT_ATTEST_IDS if they do not support it.
      *
+     * The caller needs to obtain the device-unique keys out-of-band and compare them against the
+     * key used to sign the self-signed root certificate.
+     * To ease this process, the IKeyMintDevice implementation should include, both in the subject
+     * and issuer fields of the self-signed root, the unique identifier of the device. Using the
+     * unique identifier will make it straightforward for the caller to link a device to its key.
+     *
      * IKeyMintDevice implementations that support device-unique attestation MUST add the
      * DEVICE_UNIQUE_ATTESTATION tag to device-unique attestations.
      */
diff --git a/security/keymint/aidl/vts/functional/AttestKeyTest.cpp b/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
index ae2becd..a312723 100644
--- a/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
+++ b/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
@@ -556,7 +556,7 @@
                                                      .EcdsaSigningKey(curve)
                                                      .AttestKey()
                                                      .SetDefaultValidity(),
-                                             {} /* attestation siging key */, &attest_key.keyBlob,
+                                             {} /* attestation signing key */, &attest_key.keyBlob,
                                              &attest_key_characteristics, &attest_key_cert_chain));
 
         ASSERT_GT(attest_key_cert_chain.size(), 0);
@@ -640,7 +640,7 @@
             ErrorCode::OK,
             GenerateKey(
                     AuthorizationSetBuilder().EcdsaSigningKey(EcCurve::P_256).SetDefaultValidity(),
-                    {} /* attestation siging key */, &non_attest_key.keyBlob,
+                    {} /* attestation signing key */, &non_attest_key.keyBlob,
                     &non_attest_key_characteristics, &non_attest_key_cert_chain));
 
     ASSERT_GT(non_attest_key_cert_chain.size(), 0);
@@ -662,6 +662,124 @@
                           &attested_key_cert_chain));
 }
 
+TEST_P(AttestKeyTest, EcdsaAttestationID) {
+    // Create attestation key.
+    AttestationKey attest_key;
+    vector<KeyCharacteristics> attest_key_characteristics;
+    vector<Certificate> attest_key_cert_chain;
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                                 .EcdsaSigningKey(EcCurve::P_256)
+                                                 .AttestKey()
+                                                 .SetDefaultValidity(),
+                                         {} /* attestation signing key */, &attest_key.keyBlob,
+                                         &attest_key_characteristics, &attest_key_cert_chain));
+    attest_key.issuerSubjectName = make_name_from_str("Android Keystore Key");
+    ASSERT_GT(attest_key_cert_chain.size(), 0);
+    EXPECT_EQ(attest_key_cert_chain.size(), 1);
+    EXPECT_TRUE(IsSelfSigned(attest_key_cert_chain));
+
+    // Collection of valid attestation ID tags.
+    auto attestation_id_tags = AuthorizationSetBuilder();
+    add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_BRAND, "ro.product.brand");
+    add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_DEVICE, "ro.product.device");
+    add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_PRODUCT, "ro.product.name");
+    add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_SERIAL, "ro.serial");
+    add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_MANUFACTURER,
+                      "ro.product.manufacturer");
+    add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_MODEL, "ro.product.model");
+
+    for (const KeyParameter& tag : attestation_id_tags) {
+        SCOPED_TRACE(testing::Message() << "+tag-" << tag);
+        // Use attestation key to sign an ECDSA key, but include an attestation ID field.
+        AuthorizationSetBuilder builder = AuthorizationSetBuilder()
+                                                  .EcdsaSigningKey(EcCurve::P_256)
+                                                  .Authorization(TAG_NO_AUTH_REQUIRED)
+                                                  .AttestationChallenge("challenge")
+                                                  .AttestationApplicationId("foo")
+                                                  .SetDefaultValidity();
+        builder.push_back(tag);
+        vector<uint8_t> attested_key_blob;
+        vector<KeyCharacteristics> attested_key_characteristics;
+        vector<Certificate> attested_key_cert_chain;
+        auto result = GenerateKey(builder, attest_key, &attested_key_blob,
+                                  &attested_key_characteristics, &attested_key_cert_chain);
+        if (result == ErrorCode::CANNOT_ATTEST_IDS) {
+            continue;
+        }
+
+        ASSERT_EQ(result, ErrorCode::OK);
+
+        CheckedDeleteKey(&attested_key_blob);
+
+        AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
+        AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
+
+        // The attested key characteristics will not contain APPLICATION_ID_* fields (their
+        // spec definitions all have "Must never appear in KeyCharacteristics"), but the
+        // attestation extension should contain them, so make sure the extra tag is added.
+        hw_enforced.push_back(tag);
+
+        EXPECT_TRUE(verify_attestation_record("challenge", "foo", sw_enforced, hw_enforced,
+                                              SecLevel(),
+                                              attested_key_cert_chain[0].encodedCertificate));
+    }
+    CheckedDeleteKey(&attest_key.keyBlob);
+}
+
+TEST_P(AttestKeyTest, EcdsaAttestationMismatchID) {
+    // Create attestation key.
+    AttestationKey attest_key;
+    vector<KeyCharacteristics> attest_key_characteristics;
+    vector<Certificate> attest_key_cert_chain;
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                                 .EcdsaSigningKey(EcCurve::P_256)
+                                                 .AttestKey()
+                                                 .SetDefaultValidity(),
+                                         {} /* attestation signing key */, &attest_key.keyBlob,
+                                         &attest_key_characteristics, &attest_key_cert_chain));
+    attest_key.issuerSubjectName = make_name_from_str("Android Keystore Key");
+    ASSERT_GT(attest_key_cert_chain.size(), 0);
+    EXPECT_EQ(attest_key_cert_chain.size(), 1);
+    EXPECT_TRUE(IsSelfSigned(attest_key_cert_chain));
+
+    // Collection of invalid attestation ID tags.
+    auto attestation_id_tags =
+            AuthorizationSetBuilder()
+                    .Authorization(TAG_ATTESTATION_ID_BRAND, "bogus-brand")
+                    .Authorization(TAG_ATTESTATION_ID_DEVICE, "devious-device")
+                    .Authorization(TAG_ATTESTATION_ID_PRODUCT, "punctured-product")
+                    .Authorization(TAG_ATTESTATION_ID_SERIAL, "suspicious-serial")
+                    .Authorization(TAG_ATTESTATION_ID_IMEI, "invalid-imei")
+                    .Authorization(TAG_ATTESTATION_ID_MEID, "mismatching-meid")
+                    .Authorization(TAG_ATTESTATION_ID_MANUFACTURER, "malformed-manufacturer")
+                    .Authorization(TAG_ATTESTATION_ID_MODEL, "malicious-model");
+    vector<uint8_t> key_blob;
+    vector<KeyCharacteristics> key_characteristics;
+
+    for (const KeyParameter& invalid_tag : attestation_id_tags) {
+        SCOPED_TRACE(testing::Message() << "+tag-" << invalid_tag);
+
+        // Use attestation key to sign an ECDSA key, but include an invalid
+        // attestation ID field.
+        AuthorizationSetBuilder builder = AuthorizationSetBuilder()
+                                                  .EcdsaSigningKey(EcCurve::P_256)
+                                                  .Authorization(TAG_NO_AUTH_REQUIRED)
+                                                  .AttestationChallenge("challenge")
+                                                  .AttestationApplicationId("foo")
+                                                  .SetDefaultValidity();
+        builder.push_back(invalid_tag);
+        vector<uint8_t> attested_key_blob;
+        vector<KeyCharacteristics> attested_key_characteristics;
+        vector<Certificate> attested_key_cert_chain;
+        auto result = GenerateKey(builder, attest_key, &attested_key_blob,
+                                  &attested_key_characteristics, &attested_key_cert_chain);
+
+        ASSERT_TRUE(result == ErrorCode::CANNOT_ATTEST_IDS || result == ErrorCode::INVALID_TAG)
+                << "result = " << result;
+    }
+    CheckedDeleteKey(&attest_key.keyBlob);
+}
+
 INSTANTIATE_KEYMINT_AIDL_TEST(AttestKeyTest);
 
 }  // namespace aidl::android::hardware::security::keymint::test
diff --git a/security/keymint/aidl/vts/functional/DeviceUniqueAttestationTest.cpp b/security/keymint/aidl/vts/functional/DeviceUniqueAttestationTest.cpp
index b0f056a..a3ed3ad 100644
--- a/security/keymint/aidl/vts/functional/DeviceUniqueAttestationTest.cpp
+++ b/security/keymint/aidl/vts/functional/DeviceUniqueAttestationTest.cpp
@@ -29,7 +29,7 @@
   protected:
     void CheckUniqueAttestationResults(const vector<uint8_t>& key_blob,
                                        const vector<KeyCharacteristics>& key_characteristics,
-                                       const AuthorizationSet& hw_enforced, int key_size) {
+                                       const AuthorizationSet& hw_enforced) {
         ASSERT_GT(cert_chain_.size(), 0);
 
         if (KeyMintAidlTestBase::dump_Attestations) {
@@ -40,10 +40,11 @@
 
         AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
 
-        EXPECT_TRUE(crypto_params.Contains(TAG_KEY_SIZE, key_size)) << "Key size missing";
-
+        // The device-unique attestation chain should contain exactly two certificates:
+        // * The leaf with the attestation extension.
+        // * A self-signed root, signed using the device-unique key.
+        ASSERT_EQ(cert_chain_.size(), 2);
         EXPECT_TRUE(ChainSignaturesAreValid(cert_chain_));
-        ASSERT_GT(cert_chain_.size(), 0);
 
         AuthorizationSet sw_enforced = SwEnforcedAuthorizations(key_characteristics);
         EXPECT_TRUE(verify_attestation_record("challenge", "foo", sw_enforced, hw_enforced,
@@ -133,17 +134,32 @@
 
     ASSERT_EQ(ErrorCode::OK, result);
 
-    AuthorizationSet hw_enforced = AuthorizationSetBuilder()
-                                           .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION)
-                                           .Authorization(TAG_NO_AUTH_REQUIRED)
-                                           .RsaSigningKey(2048, 65537)
-                                           .Digest(Digest::SHA_2_256)
-                                           .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)
-                                           .Authorization(TAG_ORIGIN, KeyOrigin::GENERATED)
-                                           .Authorization(TAG_OS_VERSION, os_version())
-                                           .Authorization(TAG_OS_PATCHLEVEL, os_patch_level());
+    AuthorizationSetBuilder hw_enforced =
+            AuthorizationSetBuilder()
+                    .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION)
+                    .Authorization(TAG_NO_AUTH_REQUIRED)
+                    .RsaSigningKey(2048, 65537)
+                    .Digest(Digest::SHA_2_256)
+                    .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)
+                    .Authorization(TAG_ORIGIN, KeyOrigin::GENERATED)
+                    .Authorization(TAG_OS_VERSION, os_version())
+                    .Authorization(TAG_OS_PATCHLEVEL, os_patch_level());
 
-    CheckUniqueAttestationResults(key_blob, key_characteristics, hw_enforced, key_size);
+    // Any patchlevels attached to the key should also be present in the attestation extension.
+    AuthorizationSet auths;
+    for (const auto& entry : key_characteristics) {
+        auths.push_back(AuthorizationSet(entry.authorizations));
+    }
+    auto vendor_pl = auths.GetTagValue(TAG_VENDOR_PATCHLEVEL);
+    if (vendor_pl) {
+        hw_enforced.Authorization(TAG_VENDOR_PATCHLEVEL, *vendor_pl);
+    }
+    auto boot_pl = auths.GetTagValue(TAG_BOOT_PATCHLEVEL);
+    if (boot_pl) {
+        hw_enforced.Authorization(TAG_BOOT_PATCHLEVEL, *boot_pl);
+    }
+
+    CheckUniqueAttestationResults(key_blob, key_characteristics, hw_enforced);
 }
 
 /*
@@ -157,11 +173,10 @@
 
     vector<uint8_t> key_blob;
     vector<KeyCharacteristics> key_characteristics;
-    int key_size = 256;
 
     auto result = GenerateKey(AuthorizationSetBuilder()
                                       .Authorization(TAG_NO_AUTH_REQUIRED)
-                                      .EcdsaSigningKey(256)
+                                      .EcdsaSigningKey(EcCurve::P_256)
                                       .Digest(Digest::SHA_2_256)
                                       .Authorization(TAG_INCLUDE_UNIQUE_ID)
                                       .AttestationChallenge("challenge")
@@ -173,17 +188,137 @@
     if (result == ErrorCode::CANNOT_ATTEST_IDS) return;
     ASSERT_EQ(ErrorCode::OK, result);
 
-    AuthorizationSet hw_enforced = AuthorizationSetBuilder()
-                                           .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION)
-                                           .Authorization(TAG_NO_AUTH_REQUIRED)
-                                           .EcdsaSigningKey(EcCurve::P_256)
-                                           .Digest(Digest::SHA_2_256)
-                                           .Authorization(TAG_EC_CURVE, EcCurve::P_256)
-                                           .Authorization(TAG_ORIGIN, KeyOrigin::GENERATED)
-                                           .Authorization(TAG_OS_VERSION, os_version())
-                                           .Authorization(TAG_OS_PATCHLEVEL, os_patch_level());
+    AuthorizationSetBuilder hw_enforced =
+            AuthorizationSetBuilder()
+                    .Authorization(TAG_NO_AUTH_REQUIRED)
+                    .EcdsaSigningKey(EcCurve::P_256)
+                    .Digest(Digest::SHA_2_256)
+                    .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION)
+                    .Authorization(TAG_ORIGIN, KeyOrigin::GENERATED)
+                    .Authorization(TAG_OS_VERSION, os_version())
+                    .Authorization(TAG_OS_PATCHLEVEL, os_patch_level());
+    // Any patchlevels attached to the key should also be present in the attestation extension.
+    AuthorizationSet auths;
+    for (const auto& entry : key_characteristics) {
+        auths.push_back(AuthorizationSet(entry.authorizations));
+    }
+    auto vendor_pl = auths.GetTagValue(TAG_VENDOR_PATCHLEVEL);
+    if (vendor_pl) {
+        hw_enforced.Authorization(TAG_VENDOR_PATCHLEVEL, *vendor_pl);
+    }
+    auto boot_pl = auths.GetTagValue(TAG_BOOT_PATCHLEVEL);
+    if (boot_pl) {
+        hw_enforced.Authorization(TAG_BOOT_PATCHLEVEL, *boot_pl);
+    }
 
-    CheckUniqueAttestationResults(key_blob, key_characteristics, hw_enforced, key_size);
+    CheckUniqueAttestationResults(key_blob, key_characteristics, hw_enforced);
+}
+
+/*
+ * DeviceUniqueAttestationTest.EcdsaDeviceUniqueAttestationID
+ *
+ * Verifies that device unique attestation can include IDs that do match the
+ * local device.
+ */
+TEST_P(DeviceUniqueAttestationTest, EcdsaDeviceUniqueAttestationID) {
+    if (SecLevel() != SecurityLevel::STRONGBOX) return;
+
+    // Collection of valid attestation ID tags.
+    auto attestation_id_tags = AuthorizationSetBuilder();
+    add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_BRAND, "ro.product.brand");
+    add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_DEVICE, "ro.product.device");
+    add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_PRODUCT, "ro.product.name");
+    add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_SERIAL, "ro.serial");
+    add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_MANUFACTURER,
+                      "ro.product.manufacturer");
+    add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_MODEL, "ro.product.model");
+    vector<uint8_t> key_blob;
+    vector<KeyCharacteristics> key_characteristics;
+
+    for (const KeyParameter& tag : attestation_id_tags) {
+        SCOPED_TRACE(testing::Message() << "+tag-" << tag);
+        AuthorizationSetBuilder builder = AuthorizationSetBuilder()
+                                                  .Authorization(TAG_NO_AUTH_REQUIRED)
+                                                  .EcdsaSigningKey(EcCurve::P_256)
+                                                  .Digest(Digest::SHA_2_256)
+                                                  .Authorization(TAG_INCLUDE_UNIQUE_ID)
+                                                  .AttestationChallenge("challenge")
+                                                  .AttestationApplicationId("foo")
+                                                  .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION);
+        builder.push_back(tag);
+        auto result = GenerateKey(builder, &key_blob, &key_characteristics);
+
+        // It is optional for Strong box to support DeviceUniqueAttestation.
+        if (result == ErrorCode::CANNOT_ATTEST_IDS) return;
+        ASSERT_EQ(ErrorCode::OK, result);
+
+        AuthorizationSetBuilder hw_enforced =
+                AuthorizationSetBuilder()
+                        .Authorization(TAG_NO_AUTH_REQUIRED)
+                        .EcdsaSigningKey(EcCurve::P_256)
+                        .Digest(Digest::SHA_2_256)
+                        .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION)
+                        .Authorization(TAG_ORIGIN, KeyOrigin::GENERATED)
+                        .Authorization(TAG_OS_VERSION, os_version())
+                        .Authorization(TAG_OS_PATCHLEVEL, os_patch_level());
+        // Expect the specified tag to be present in the attestation extension.
+        hw_enforced.push_back(tag);
+        // Any patchlevels attached to the key should also be present in the attestation extension.
+        AuthorizationSet auths;
+        for (const auto& entry : key_characteristics) {
+            auths.push_back(AuthorizationSet(entry.authorizations));
+        }
+        auto vendor_pl = auths.GetTagValue(TAG_VENDOR_PATCHLEVEL);
+        if (vendor_pl) {
+            hw_enforced.Authorization(TAG_VENDOR_PATCHLEVEL, *vendor_pl);
+        }
+        auto boot_pl = auths.GetTagValue(TAG_BOOT_PATCHLEVEL);
+        if (boot_pl) {
+            hw_enforced.Authorization(TAG_BOOT_PATCHLEVEL, *boot_pl);
+        }
+        CheckUniqueAttestationResults(key_blob, key_characteristics, hw_enforced);
+    }
+}
+
+/*
+ * DeviceUniqueAttestationTest.EcdsaDeviceUniqueAttestationMismatchID
+ *
+ * Verifies that device unique attestation rejects attempts to attest to IDs that
+ * don't match the local device.
+ */
+TEST_P(DeviceUniqueAttestationTest, EcdsaDeviceUniqueAttestationMismatchID) {
+    if (SecLevel() != SecurityLevel::STRONGBOX) return;
+
+    // Collection of invalid attestation ID tags.
+    auto attestation_id_tags =
+            AuthorizationSetBuilder()
+                    .Authorization(TAG_ATTESTATION_ID_BRAND, "bogus-brand")
+                    .Authorization(TAG_ATTESTATION_ID_DEVICE, "devious-device")
+                    .Authorization(TAG_ATTESTATION_ID_PRODUCT, "punctured-product")
+                    .Authorization(TAG_ATTESTATION_ID_SERIAL, "suspicious-serial")
+                    .Authorization(TAG_ATTESTATION_ID_IMEI, "invalid-imei")
+                    .Authorization(TAG_ATTESTATION_ID_MEID, "mismatching-meid")
+                    .Authorization(TAG_ATTESTATION_ID_MANUFACTURER, "malformed-manufacturer")
+                    .Authorization(TAG_ATTESTATION_ID_MODEL, "malicious-model");
+    vector<uint8_t> key_blob;
+    vector<KeyCharacteristics> key_characteristics;
+
+    for (const KeyParameter& invalid_tag : attestation_id_tags) {
+        SCOPED_TRACE(testing::Message() << "+tag-" << invalid_tag);
+        AuthorizationSetBuilder builder = AuthorizationSetBuilder()
+                                                  .Authorization(TAG_NO_AUTH_REQUIRED)
+                                                  .EcdsaSigningKey(EcCurve::P_256)
+                                                  .Digest(Digest::SHA_2_256)
+                                                  .Authorization(TAG_INCLUDE_UNIQUE_ID)
+                                                  .AttestationChallenge("challenge")
+                                                  .AttestationApplicationId("foo")
+                                                  .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION);
+        // Add the tag that doesn't match the local device's real ID.
+        builder.push_back(invalid_tag);
+        auto result = GenerateKey(builder, &key_blob, &key_characteristics);
+
+        ASSERT_TRUE(result == ErrorCode::CANNOT_ATTEST_IDS || result == ErrorCode::INVALID_TAG);
+    }
 }
 
 INSTANTIATE_KEYMINT_AIDL_TEST(DeviceUniqueAttestationTest);
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 4d31fa4..d592d36 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
@@ -21,6 +21,7 @@
 
 #include <aidl/Gtest.h>
 #include <aidl/Vintf.h>
+#include <android-base/properties.h>
 #include <binder/IServiceManager.h>
 #include <binder/ProcessState.h>
 #include <gtest/gtest.h>
@@ -75,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);
 
@@ -252,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)
@@ -313,6 +316,16 @@
     long challenge_;
 };
 
+// If the given property is available, add it to the tag set under the given tag ID.
+template <Tag tag>
+void add_tag_from_prop(AuthorizationSetBuilder* tags, TypedTag<TagType::BYTES, tag> ttag,
+                       const char* prop) {
+    std::string prop_value = ::android::base::GetProperty(prop, /* default= */ "");
+    if (!prop_value.empty()) {
+        tags->Authorization(ttag, prop_value.data(), prop_value.size());
+    }
+}
+
 vector<uint8_t> build_serial_blob(const uint64_t serial_int);
 void verify_subject(const X509* cert, const string& subject, bool self_signed);
 void verify_serial(X509* cert, const uint64_t expected_serial);
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..78f8f08 100644
--- a/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
+++ b/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
@@ -335,8 +335,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))
diff --git a/security/keymint/support/attestation_record.cpp b/security/keymint/support/attestation_record.cpp
index a48f770..2462228 100644
--- a/security/keymint/support/attestation_record.cpp
+++ b/security/keymint/support/attestation_record.cpp
@@ -64,6 +64,7 @@
 } ASN1_SEQUENCE_END(KM_ROOT_OF_TRUST);
 IMPLEMENT_ASN1_FUNCTIONS(KM_ROOT_OF_TRUST);
 
+// Fields ordered in tag order.
 typedef struct km_auth_list {
     ASN1_INTEGER_SET* purpose;
     ASN1_INTEGER* algorithm;
@@ -72,32 +73,38 @@
     ASN1_INTEGER_SET* padding;
     ASN1_INTEGER* ec_curve;
     ASN1_INTEGER* rsa_public_exponent;
+    ASN1_INTEGER_SET* mgf_digest;
+    ASN1_NULL* rollback_resistance;
+    ASN1_NULL* early_boot_only;
     ASN1_INTEGER* active_date_time;
     ASN1_INTEGER* origination_expire_date_time;
     ASN1_INTEGER* usage_expire_date_time;
+    ASN1_INTEGER* usage_count_limit;
     ASN1_NULL* no_auth_required;
     ASN1_INTEGER* user_auth_type;
     ASN1_INTEGER* auth_timeout;
     ASN1_NULL* allow_while_on_body;
-    ASN1_NULL* all_applications;
-    ASN1_OCTET_STRING* application_id;
+    ASN1_NULL* trusted_user_presence_required;
+    ASN1_NULL* trusted_confirmation_required;
+    ASN1_NULL* unlocked_device_required;
     ASN1_INTEGER* creation_date_time;
     ASN1_INTEGER* origin;
-    ASN1_NULL* rollback_resistance;
     KM_ROOT_OF_TRUST* root_of_trust;
     ASN1_INTEGER* os_version;
     ASN1_INTEGER* os_patchlevel;
     ASN1_OCTET_STRING* attestation_application_id;
-    ASN1_NULL* trusted_user_presence_required;
-    ASN1_NULL* trusted_confirmation_required;
-    ASN1_NULL* unlocked_device_required;
+    ASN1_OCTET_STRING* attestation_id_brand;
+    ASN1_OCTET_STRING* attestation_id_device;
+    ASN1_OCTET_STRING* attestation_id_product;
+    ASN1_OCTET_STRING* attestation_id_serial;
+    ASN1_OCTET_STRING* attestation_id_imei;
+    ASN1_OCTET_STRING* attestation_id_meid;
+    ASN1_OCTET_STRING* attestation_id_manufacturer;
+    ASN1_OCTET_STRING* attestation_id_model;
     ASN1_INTEGER* vendor_patchlevel;
     ASN1_INTEGER* boot_patchlevel;
-    ASN1_NULL* early_boot_only;
     ASN1_NULL* device_unique_attestation;
-    ASN1_NULL* storage_key;
     ASN1_NULL* identity_credential;
-    ASN1_INTEGER* usage_count_limit;
 } KM_AUTH_LIST;
 
 ASN1_SEQUENCE(KM_AUTH_LIST) = {
@@ -109,13 +116,18 @@
         ASN1_EXP_OPT(KM_AUTH_LIST, ec_curve, ASN1_INTEGER, TAG_EC_CURVE.maskedTag()),
         ASN1_EXP_OPT(KM_AUTH_LIST, rsa_public_exponent, ASN1_INTEGER,
                      TAG_RSA_PUBLIC_EXPONENT.maskedTag()),
+        ASN1_EXP_SET_OF_OPT(KM_AUTH_LIST, mgf_digest, ASN1_INTEGER,
+                            TAG_RSA_OAEP_MGF_DIGEST.maskedTag()),
         ASN1_EXP_OPT(KM_AUTH_LIST, rollback_resistance, ASN1_NULL,
                      TAG_ROLLBACK_RESISTANCE.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, early_boot_only, ASN1_NULL, TAG_EARLY_BOOT_ONLY.maskedTag()),
         ASN1_EXP_OPT(KM_AUTH_LIST, active_date_time, ASN1_INTEGER, TAG_ACTIVE_DATETIME.maskedTag()),
         ASN1_EXP_OPT(KM_AUTH_LIST, origination_expire_date_time, ASN1_INTEGER,
                      TAG_ORIGINATION_EXPIRE_DATETIME.maskedTag()),
         ASN1_EXP_OPT(KM_AUTH_LIST, usage_expire_date_time, ASN1_INTEGER,
                      TAG_USAGE_EXPIRE_DATETIME.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, usage_count_limit, ASN1_INTEGER,
+                     TAG_USAGE_COUNT_LIMIT.maskedTag()),
         ASN1_EXP_OPT(KM_AUTH_LIST, no_auth_required, ASN1_NULL, TAG_NO_AUTH_REQUIRED.maskedTag()),
         ASN1_EXP_OPT(KM_AUTH_LIST, user_auth_type, ASN1_INTEGER, TAG_USER_AUTH_TYPE.maskedTag()),
         ASN1_EXP_OPT(KM_AUTH_LIST, auth_timeout, ASN1_INTEGER, TAG_AUTH_TIMEOUT.maskedTag()),
@@ -133,19 +145,31 @@
         ASN1_EXP_OPT(KM_AUTH_LIST, root_of_trust, KM_ROOT_OF_TRUST, TAG_ROOT_OF_TRUST.maskedTag()),
         ASN1_EXP_OPT(KM_AUTH_LIST, os_version, ASN1_INTEGER, TAG_OS_VERSION.maskedTag()),
         ASN1_EXP_OPT(KM_AUTH_LIST, os_patchlevel, ASN1_INTEGER, TAG_OS_PATCHLEVEL.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, attestation_application_id, ASN1_OCTET_STRING,
+                     TAG_ATTESTATION_APPLICATION_ID.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_brand, ASN1_OCTET_STRING,
+                     TAG_ATTESTATION_ID_BRAND.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_device, ASN1_OCTET_STRING,
+                     TAG_ATTESTATION_ID_DEVICE.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_product, ASN1_OCTET_STRING,
+                     TAG_ATTESTATION_ID_PRODUCT.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_serial, ASN1_OCTET_STRING,
+                     TAG_ATTESTATION_ID_SERIAL.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_imei, ASN1_OCTET_STRING,
+                     TAG_ATTESTATION_ID_IMEI.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_meid, ASN1_OCTET_STRING,
+                     TAG_ATTESTATION_ID_MEID.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_manufacturer, ASN1_OCTET_STRING,
+                     TAG_ATTESTATION_ID_MANUFACTURER.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_model, ASN1_OCTET_STRING,
+                     TAG_ATTESTATION_ID_MODEL.maskedTag()),
         ASN1_EXP_OPT(KM_AUTH_LIST, vendor_patchlevel, ASN1_INTEGER,
                      TAG_VENDOR_PATCHLEVEL.maskedTag()),
         ASN1_EXP_OPT(KM_AUTH_LIST, boot_patchlevel, ASN1_INTEGER, TAG_BOOT_PATCHLEVEL.maskedTag()),
-        ASN1_EXP_OPT(KM_AUTH_LIST, attestation_application_id, ASN1_OCTET_STRING,
-                     TAG_ATTESTATION_APPLICATION_ID.maskedTag()),
-        ASN1_EXP_OPT(KM_AUTH_LIST, early_boot_only, ASN1_NULL, TAG_EARLY_BOOT_ONLY.maskedTag()),
         ASN1_EXP_OPT(KM_AUTH_LIST, device_unique_attestation, ASN1_NULL,
                      TAG_DEVICE_UNIQUE_ATTESTATION.maskedTag()),
-        ASN1_EXP_OPT(KM_AUTH_LIST, storage_key, ASN1_NULL, TAG_STORAGE_KEY.maskedTag()),
         ASN1_EXP_OPT(KM_AUTH_LIST, identity_credential, ASN1_NULL,
                      TAG_IDENTITY_CREDENTIAL_KEY.maskedTag()),
-        ASN1_EXP_OPT(KM_AUTH_LIST, usage_count_limit, ASN1_INTEGER,
-                     TAG_USAGE_COUNT_LIMIT.maskedTag()),
 } ASN1_SEQUENCE_END(KM_AUTH_LIST);
 IMPLEMENT_ASN1_FUNCTIONS(KM_AUTH_LIST);
 
@@ -155,9 +179,9 @@
     ASN1_INTEGER* keymint_version;
     ASN1_ENUMERATED* keymint_security_level;
     ASN1_OCTET_STRING* attestation_challenge;
+    ASN1_INTEGER* unique_id;
     KM_AUTH_LIST* software_enforced;
     KM_AUTH_LIST* tee_enforced;
-    ASN1_INTEGER* unique_id;
 } KM_KEY_DESCRIPTION;
 
 ASN1_SEQUENCE(KM_KEY_DESCRIPTION) = {
@@ -253,41 +277,52 @@
 }
 
 // Extract the values from the specified ASN.1 record and place them in auth_list.
+// Does nothing with root-of-trust field.
 static ErrorCode extract_auth_list(const KM_AUTH_LIST* record, AuthorizationSet* auth_list) {
     if (!record) return ErrorCode::OK;
 
-    copyAuthTag(record->active_date_time, TAG_ACTIVE_DATETIME, auth_list);
-    copyAuthTag(record->algorithm, TAG_ALGORITHM, auth_list);
-    copyAuthTag(record->application_id, TAG_APPLICATION_ID, auth_list);
-    copyAuthTag(record->auth_timeout, TAG_AUTH_TIMEOUT, auth_list);
-    copyAuthTag(record->creation_date_time, TAG_CREATION_DATETIME, auth_list);
-    copyAuthTag(record->digest, TAG_DIGEST, auth_list);
-    copyAuthTag(record->ec_curve, TAG_EC_CURVE, auth_list);
-    copyAuthTag(record->key_size, TAG_KEY_SIZE, auth_list);
-    copyAuthTag(record->no_auth_required, TAG_NO_AUTH_REQUIRED, auth_list);
-    copyAuthTag(record->origin, TAG_ORIGIN, auth_list);
-    copyAuthTag(record->origination_expire_date_time, TAG_ORIGINATION_EXPIRE_DATETIME, auth_list);
-    copyAuthTag(record->os_patchlevel, TAG_OS_PATCHLEVEL, auth_list);
-    copyAuthTag(record->os_version, TAG_OS_VERSION, auth_list);
-    copyAuthTag(record->padding, TAG_PADDING, auth_list);
+    // Fields ordered in tag order.
     copyAuthTag(record->purpose, TAG_PURPOSE, auth_list);
-    copyAuthTag(record->rollback_resistance, TAG_ROLLBACK_RESISTANCE, auth_list);
+    copyAuthTag(record->algorithm, TAG_ALGORITHM, auth_list);
+    copyAuthTag(record->key_size, TAG_KEY_SIZE, auth_list);
+    copyAuthTag(record->digest, TAG_DIGEST, auth_list);
+    copyAuthTag(record->padding, TAG_PADDING, auth_list);
+    copyAuthTag(record->ec_curve, TAG_EC_CURVE, auth_list);
     copyAuthTag(record->rsa_public_exponent, TAG_RSA_PUBLIC_EXPONENT, auth_list);
+    copyAuthTag(record->mgf_digest, TAG_RSA_OAEP_MGF_DIGEST, auth_list);
+    copyAuthTag(record->rollback_resistance, TAG_ROLLBACK_RESISTANCE, auth_list);
+    copyAuthTag(record->early_boot_only, TAG_EARLY_BOOT_ONLY, auth_list);
+    copyAuthTag(record->active_date_time, TAG_ACTIVE_DATETIME, auth_list);
+    copyAuthTag(record->origination_expire_date_time, TAG_ORIGINATION_EXPIRE_DATETIME, auth_list);
     copyAuthTag(record->usage_expire_date_time, TAG_USAGE_EXPIRE_DATETIME, auth_list);
+    copyAuthTag(record->usage_count_limit, TAG_USAGE_COUNT_LIMIT, auth_list);
+    copyAuthTag(record->no_auth_required, TAG_NO_AUTH_REQUIRED, auth_list);
     copyAuthTag(record->user_auth_type, TAG_USER_AUTH_TYPE, auth_list);
-    copyAuthTag(record->attestation_application_id, TAG_ATTESTATION_APPLICATION_ID, auth_list);
-    copyAuthTag(record->vendor_patchlevel, TAG_VENDOR_PATCHLEVEL, auth_list);
-    copyAuthTag(record->boot_patchlevel, TAG_BOOT_PATCHLEVEL, auth_list);
+    copyAuthTag(record->auth_timeout, TAG_AUTH_TIMEOUT, auth_list);
+    copyAuthTag(record->allow_while_on_body, TAG_ALLOW_WHILE_ON_BODY, auth_list);
     copyAuthTag(record->trusted_user_presence_required, TAG_TRUSTED_USER_PRESENCE_REQUIRED,
                 auth_list);
     copyAuthTag(record->trusted_confirmation_required, TAG_TRUSTED_CONFIRMATION_REQUIRED,
                 auth_list);
     copyAuthTag(record->unlocked_device_required, TAG_UNLOCKED_DEVICE_REQUIRED, auth_list);
-    copyAuthTag(record->early_boot_only, TAG_EARLY_BOOT_ONLY, auth_list);
+    copyAuthTag(record->creation_date_time, TAG_CREATION_DATETIME, auth_list);
+    copyAuthTag(record->origin, TAG_ORIGIN, auth_list);
+    // root_of_trust dealt with separately
+    copyAuthTag(record->os_version, TAG_OS_VERSION, auth_list);
+    copyAuthTag(record->os_patchlevel, TAG_OS_PATCHLEVEL, auth_list);
+    copyAuthTag(record->attestation_application_id, TAG_ATTESTATION_APPLICATION_ID, auth_list);
+    copyAuthTag(record->attestation_id_brand, TAG_ATTESTATION_ID_BRAND, auth_list);
+    copyAuthTag(record->attestation_id_device, TAG_ATTESTATION_ID_DEVICE, auth_list);
+    copyAuthTag(record->attestation_id_product, TAG_ATTESTATION_ID_PRODUCT, auth_list);
+    copyAuthTag(record->attestation_id_serial, TAG_ATTESTATION_ID_SERIAL, auth_list);
+    copyAuthTag(record->attestation_id_imei, TAG_ATTESTATION_ID_IMEI, auth_list);
+    copyAuthTag(record->attestation_id_meid, TAG_ATTESTATION_ID_MEID, auth_list);
+    copyAuthTag(record->attestation_id_manufacturer, TAG_ATTESTATION_ID_MANUFACTURER, auth_list);
+    copyAuthTag(record->attestation_id_model, TAG_ATTESTATION_ID_MODEL, auth_list);
+    copyAuthTag(record->vendor_patchlevel, TAG_VENDOR_PATCHLEVEL, auth_list);
+    copyAuthTag(record->boot_patchlevel, TAG_BOOT_PATCHLEVEL, auth_list);
     copyAuthTag(record->device_unique_attestation, TAG_DEVICE_UNIQUE_ATTESTATION, auth_list);
-    copyAuthTag(record->storage_key, TAG_STORAGE_KEY, auth_list);
     copyAuthTag(record->identity_credential, TAG_IDENTITY_CREDENTIAL_KEY, auth_list);
-    copyAuthTag(record->usage_count_limit, TAG_USAGE_COUNT_LIMIT, auth_list);
 
     return ErrorCode::OK;
 }
diff --git a/security/keymint/support/keymint_utils.cpp b/security/keymint/support/keymint_utils.cpp
index 2dbdfa8..1e0733f 100644
--- a/security/keymint/support/keymint_utils.cpp
+++ b/security/keymint/support/keymint_utils.cpp
@@ -32,10 +32,11 @@
 
 constexpr char kPlatformPatchlevelProp[] = "ro.build.version.security_patch";
 constexpr char kVendorPatchlevelProp[] = "ro.vendor.build.security_patch";
-constexpr char kPatchlevelRegex[] = "^([0-9]{4})-([0-9]{2})-[0-9]{2}$";
+constexpr char kPatchlevelRegex[] = "^([0-9]{4})-([0-9]{2})-([0-9]{2})$";
 constexpr size_t kYearMatch = 1;
 constexpr size_t kMonthMatch = 2;
-constexpr size_t kPatchlevelMatchCount = kMonthMatch + 1;
+constexpr size_t kDayMatch = 3;
+constexpr size_t kPatchlevelMatchCount = kDayMatch + 1;
 
 uint32_t match_to_uint32(const char* expression, const regmatch_t& match) {
     if (match.rm_so == -1) return 0;
@@ -53,8 +54,6 @@
     return prop_value;
 }
 
-}  // anonymous namespace
-
 uint32_t getOsVersion(const char* version_str) {
     regex_t regex;
     if (regcomp(&regex, kPlatformVersionRegex, REG_EXTENDED)) {
@@ -76,12 +75,9 @@
     return (major * 100 + minor) * 100 + subminor;
 }
 
-uint32_t getOsVersion() {
-    std::string version = wait_and_get_property(kPlatformVersionProp);
-    return getOsVersion(version.c_str());
-}
+enum class PatchlevelOutput { kYearMonthDay, kYearMonth };
 
-uint32_t getPatchlevel(const char* patchlevel_str) {
+uint32_t getPatchlevel(const char* patchlevel_str, PatchlevelOutput detail) {
     regex_t regex;
     if (regcomp(&regex, kPatchlevelRegex, REG_EXTENDED) != 0) {
         return 0;
@@ -100,17 +96,35 @@
     if (month < 1 || month > 12) {
         return 0;
     }
-    return year * 100 + month;
+
+    switch (detail) {
+        case PatchlevelOutput::kYearMonthDay: {
+            uint32_t day = match_to_uint32(patchlevel_str, matches[kDayMatch]);
+            if (day < 1 || day > 31) {
+                return 0;
+            }
+            return year * 10000 + month * 100 + day;
+        }
+        case PatchlevelOutput::kYearMonth:
+            return year * 100 + month;
+    }
+}
+
+}  // anonymous namespace
+
+uint32_t getOsVersion() {
+    std::string version = wait_and_get_property(kPlatformVersionProp);
+    return getOsVersion(version.c_str());
 }
 
 uint32_t getOsPatchlevel() {
     std::string patchlevel = wait_and_get_property(kPlatformPatchlevelProp);
-    return getPatchlevel(patchlevel.c_str());
+    return getPatchlevel(patchlevel.c_str(), PatchlevelOutput::kYearMonth);
 }
 
 uint32_t getVendorPatchlevel() {
     std::string patchlevel = wait_and_get_property(kVendorPatchlevelProp);
-    return getPatchlevel(patchlevel.c_str());
+    return getPatchlevel(patchlevel.c_str(), PatchlevelOutput::kYearMonthDay);
 }
 
 }  // namespace aidl::android::hardware::security::keymint
diff --git a/security/keymint/support/remote_prov_utils.cpp b/security/keymint/support/remote_prov_utils.cpp
index da10eb2..33f1ed3 100644
--- a/security/keymint/support/remote_prov_utils.cpp
+++ b/security/keymint/support/remote_prov_utils.cpp
@@ -78,7 +78,7 @@
     return EekChain{eekChain.encode(), pub_key, priv_key};
 }
 
-ErrMsgOr<bytevec> verifyAndParseCoseSign1Cwt(bool ignoreSignature, const cppbor::Array* coseSign1,
+ErrMsgOr<bytevec> verifyAndParseCoseSign1Cwt(const cppbor::Array* coseSign1,
                                              const bytevec& signingCoseKey, const bytevec& aad) {
     if (!coseSign1 || coseSign1->size() != kCoseSign1EntryCount) {
         return "Invalid COSE_Sign1";
@@ -115,27 +115,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 +143,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();
         }
diff --git a/security/secureclock/aidl/vts/functional/SecureClockAidlTest.cpp b/security/secureclock/aidl/vts/functional/SecureClockAidlTest.cpp
index 31f4854..bf332d5 100644
--- a/security/secureclock/aidl/vts/functional/SecureClockAidlTest.cpp
+++ b/security/secureclock/aidl/vts/functional/SecureClockAidlTest.cpp
@@ -114,6 +114,7 @@
     EXPECT_EQ(ErrorCode::OK, result1.error);
     EXPECT_EQ(1U, result1.token.challenge);
     EXPECT_GT(result1.token.timestamp.milliSeconds, 0U);
+    EXPECT_EQ(32U, result1.token.mac.size());
 
     unsigned long time_to_sleep = 200;
     sleep_ms(time_to_sleep);
@@ -123,6 +124,7 @@
     EXPECT_EQ(ErrorCode::OK, result2.error);
     EXPECT_EQ(2U, result2.token.challenge);
     EXPECT_GT(result2.token.timestamp.milliSeconds, 0U);
+    EXPECT_EQ(32U, result2.token.mac.size());
 
     auto host_time_delta = result2_time - result1_time;
 
@@ -153,6 +155,7 @@
     EXPECT_EQ(ErrorCode::OK, result1.error);
     EXPECT_EQ(0U, result1.token.challenge);
     EXPECT_GT(result1.token.timestamp.milliSeconds, 0U);
+    EXPECT_EQ(32U, result1.token.mac.size());
 
     unsigned long time_to_sleep = 200;
     sleep_ms(time_to_sleep);
@@ -162,6 +165,7 @@
     EXPECT_EQ(ErrorCode::OK, result2.error);
     EXPECT_EQ(1U, result2.token.challenge);
     EXPECT_GT(result2.token.timestamp.milliSeconds, 0U);
+    EXPECT_EQ(32U, result2.token.mac.size());
 
     auto host_time_delta = result2_time - result1_time;
 
diff --git a/security/sharedsecret/aidl/vts/functional/SharedSecretAidlTest.cpp b/security/sharedsecret/aidl/vts/functional/SharedSecretAidlTest.cpp
index 8426120..919f882 100644
--- a/security/sharedsecret/aidl/vts/functional/SharedSecretAidlTest.cpp
+++ b/security/sharedsecret/aidl/vts/functional/SharedSecretAidlTest.cpp
@@ -48,6 +48,9 @@
         SharedSecretParameters params;
         auto error = GetReturnErrorCode(sharedSecret->getSharedSecretParameters(&params));
         EXPECT_EQ(ErrorCode::OK, error);
+        EXPECT_TRUE(params.seed.size() == 0 || params.seed.size() == 32);
+        EXPECT_TRUE(params.nonce.size() == 32);
+
         GetParamsResult result;
         result.tie() = std::tie(error, params);
         return result;
@@ -234,6 +237,45 @@
     }
 }
 
+TEST_F(SharedSecretAidlTest, ComputeSharedSecretShortNonce) {
+    auto sharedSecrets = allSharedSecrets();
+    if (sharedSecrets.empty()) {
+        GTEST_SKIP() << "Skipping the test as no shared secret service is found.";
+    }
+    auto fixup_hmac = finally([&]() { computeAllSharedSecrets(getAllSharedSecretParameters()); });
+
+    auto params = getAllSharedSecretParameters();
+    ASSERT_EQ(sharedSecrets.size(), params.size())
+            << "One or more shared secret services failed to provide parameters.";
+
+    // All should be well in the normal case
+    auto responses = computeAllSharedSecrets(params);
+
+    ASSERT_GT(responses.size(), 0U);
+    vector<uint8_t> correct_response = responses[0].sharing_check;
+    verifyResponses(correct_response, responses);
+
+    // Pick a random param and shorten that nonce by one.
+    size_t param_to_tweak = rand() % params.size();
+    auto& to_tweak = params[param_to_tweak].nonce;
+    ASSERT_TRUE(to_tweak.size() == 32);
+    to_tweak.resize(31);
+
+    responses = computeAllSharedSecrets(params);
+    for (size_t i = 0; i < responses.size(); ++i) {
+        if (i == param_to_tweak) {
+            EXPECT_EQ(ErrorCode::INVALID_ARGUMENT, responses[i].error)
+                    << "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.";
+        }
+    }
+}
+
 TEST_F(SharedSecretAidlTest, ComputeSharedSecretCorruptSeed) {
     auto sharedSecrets = allSharedSecrets();
     if (sharedSecrets.empty()) {
@@ -275,6 +317,45 @@
         }
     }
 }
+
+TEST_F(SharedSecretAidlTest, ComputeSharedSecretShortSeed) {
+    auto sharedSecrets = allSharedSecrets();
+    if (sharedSecrets.empty()) {
+        GTEST_SKIP() << "Skipping the test as no shared secret service is found.";
+    }
+    auto fixup_hmac = finally([&]() { computeAllSharedSecrets(getAllSharedSecretParameters()); });
+    auto params = getAllSharedSecretParameters();
+    ASSERT_EQ(sharedSecrets.size(), params.size())
+            << "One or more shared secret service failed to provide parameters.";
+
+    // All should be well in the normal case
+    auto responses = computeAllSharedSecrets(params);
+
+    ASSERT_GT(responses.size(), 0U);
+    vector<uint8_t> correct_response = responses[0].sharing_check;
+    verifyResponses(correct_response, responses);
+
+    // Pick a random param and modify the seed to be of (invalid) length 31.
+    auto param_to_tweak = rand() % params.size();
+    auto& to_tweak = params[param_to_tweak].seed;
+    ASSERT_TRUE(to_tweak.size() == 32 || to_tweak.size() == 0);
+    to_tweak.resize(31);
+
+    responses = computeAllSharedSecrets(params);
+    for (size_t i = 0; i < responses.size(); ++i) {
+        if (i == param_to_tweak) {
+            EXPECT_EQ(ErrorCode::INVALID_ARGUMENT, responses[i].error)
+                    << "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.";
+        }
+    }
+}
+
 }  // namespace aidl::android::hardware::security::sharedsecret::test
 
 int main(int argc, char** argv) {
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/VtsHalVibratorManagerTargetTest.cpp b/vibrator/aidl/vts/VtsHalVibratorManagerTargetTest.cpp
index 9789188..44fa3be 100644
--- a/vibrator/aidl/vts/VtsHalVibratorManagerTargetTest.cpp
+++ b/vibrator/aidl/vts/VtsHalVibratorManagerTargetTest.cpp
@@ -71,6 +71,11 @@
     std::vector<int32_t> vibratorIds;
 };
 
+inline bool isUnknownOrUnsupported(Status status) {
+    return status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
+           status.transactionError() == android::UNKNOWN_TRANSACTION;
+}
+
 TEST_P(VibratorAidl, ValidateExistingVibrators) {
     sp<IVibrator> vibrator;
     for (auto& id : vibratorIds) {
@@ -101,8 +106,8 @@
 
 TEST_P(VibratorAidl, PrepareSyncedNotSupported) {
     if (!(capabilities & IVibratorManager::CAP_SYNC)) {
-        EXPECT_EQ(Status::EX_UNSUPPORTED_OPERATION,
-                  manager->prepareSynced(vibratorIds).exceptionCode());
+        Status status = manager->prepareSynced(vibratorIds);
+        EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
     }
 }
 
@@ -116,8 +121,8 @@
         for (auto& id : vibratorIds) {
             EXPECT_TRUE(manager->getVibrator(id, &vibrator).isOk());
             ASSERT_NE(vibrator, nullptr);
-            EXPECT_EQ(Status::EX_UNSUPPORTED_OPERATION,
-                      vibrator->on(durationMs, nullptr).exceptionCode());
+            Status status = vibrator->on(durationMs, nullptr);
+            EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
         }
         EXPECT_TRUE(manager->cancelSynced().isOk());
     }
@@ -134,7 +139,7 @@
             ASSERT_NE(vibrator, nullptr);
             int32_t lengthMs = 0;
             Status status = vibrator->perform(kEffects[0], kEffectStrengths[0], nullptr, &lengthMs);
-            EXPECT_EQ(Status::EX_UNSUPPORTED_OPERATION, status.exceptionCode());
+            EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
         }
         EXPECT_TRUE(manager->cancelSynced().isOk());
     }
@@ -157,7 +162,7 @@
             EXPECT_TRUE(manager->getVibrator(id, &vibrator).isOk());
             ASSERT_NE(vibrator, nullptr);
             Status status = vibrator->compose(composite, nullptr);
-            EXPECT_EQ(Status::EX_UNSUPPORTED_OPERATION, status.exceptionCode());
+            EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
         }
         EXPECT_TRUE(manager->cancelSynced().isOk());
     }
@@ -191,8 +196,8 @@
 
 TEST_P(VibratorAidl, TriggerSyncNotSupported) {
     if (!(capabilities & IVibratorManager::CAP_SYNC)) {
-        EXPECT_EQ(Status::EX_UNSUPPORTED_OPERATION,
-                  manager->triggerSynced(nullptr).exceptionCode());
+        Status status = manager->triggerSynced(nullptr);
+        EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
     }
 }
 
@@ -201,8 +206,8 @@
     if (!(capabilities & IVibratorManager::CAP_TRIGGER_CALLBACK)) {
         sp<CompletionCallback> callback = new CompletionCallback([] {});
         EXPECT_TRUE(manager->prepareSynced(vibratorIds).isOk());
-        EXPECT_EQ(Status::EX_UNSUPPORTED_OPERATION,
-                  manager->triggerSynced(callback).exceptionCode());
+        Status status = manager->triggerSynced(callback);
+        EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
     }
 }
 
diff --git a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
index 713ec75..c56bd9a 100644
--- a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
+++ b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
@@ -112,6 +112,11 @@
     int32_t capabilities;
 };
 
+inline bool isUnknownOrUnsupported(Status status) {
+    return status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
+           status.transactionError() == android::UNKNOWN_TRANSACTION;
+}
+
 static float getResonantFrequencyHz(sp<IVibrator> vibrator, int32_t capabilities) {
     float resonantFrequencyHz;
     Status status = vibrator->getResonantFrequency(&resonantFrequencyHz);
@@ -119,7 +124,7 @@
         EXPECT_GT(resonantFrequencyHz, 0);
         EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
     } else {
-        EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
+        EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
     }
     return resonantFrequencyHz;
 }
@@ -131,7 +136,7 @@
         EXPECT_GT(freqResolutionHz, 0);
         EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
     } else {
-        EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
+        EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
     }
     return freqResolutionHz;
 }
@@ -147,7 +152,7 @@
         EXPECT_GT(freqMinimumHz, 0);
         EXPECT_LE(freqMinimumHz, resonantFrequencyHz);
     } else {
-        EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
+        EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
     }
     return freqMinimumHz;
 }
@@ -158,7 +163,7 @@
     if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) {
         EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
     } else {
-        EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
+        EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
     }
 
     float freqMaximumHz =
@@ -219,7 +224,8 @@
 TEST_P(VibratorAidl, OnCallbackNotSupported) {
     if (!(capabilities & IVibrator::CAP_ON_CALLBACK)) {
         sp<CompletionCallback> callback = new CompletionCallback([] {});
-        EXPECT_EQ(Status::EX_UNSUPPORTED_OPERATION, vibrator->on(250, callback).exceptionCode());
+        Status status = vibrator->on(250, callback);
+        EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
     }
 }
 
@@ -240,8 +246,8 @@
                 EXPECT_GT(lengthMs, 0);
                 usleep(lengthMs * 1000);
             } else {
-                EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION)
-                    << toString(effect) << " " << toString(strength);
+                EXPECT_TRUE(isUnknownOrUnsupported(status))
+                        << status << " " << toString(effect) << " " << toString(strength);
             }
         }
     }
@@ -270,7 +276,7 @@
                 EXPECT_TRUE(status.isOk());
                 EXPECT_GT(lengthMs, 0);
             } else {
-                EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
+                EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
             }
 
             if (!status.isOk())
@@ -293,7 +299,7 @@
             sp<CompletionCallback> callback = new CompletionCallback([] {});
             int lengthMs;
             Status status = vibrator->perform(effect, strength, callback, &lengthMs);
-            EXPECT_EQ(Status::EX_UNSUPPORTED_OPERATION, status.exceptionCode());
+            EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
         }
     }
 }
@@ -303,16 +309,16 @@
         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) {
         for (EffectStrength strength : kInvalidEffectStrengths) {
             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);
         }
     }
 }
@@ -338,7 +344,8 @@
 
 TEST_P(VibratorAidl, AmplitudeReturnsUnsupportedMatchingCapabilities) {
     if ((capabilities & IVibrator::CAP_AMPLITUDE_CONTROL) == 0) {
-        EXPECT_EQ(Status::EX_UNSUPPORTED_OPERATION, vibrator->setAmplitude(1).exceptionCode());
+        Status status = vibrator->setAmplitude(1);
+        EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
     }
 }
 
@@ -362,7 +369,7 @@
         if (supportsExternalAmplitudeControl) {
             EXPECT_TRUE(amplitudeStatus.isOk());
         } else {
-            EXPECT_EQ(amplitudeStatus.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
+            EXPECT_TRUE(isUnknownOrUnsupported(amplitudeStatus)) << amplitudeStatus;
         }
         EXPECT_TRUE(vibrator->setExternalControl(false).isOk());
     } else {
@@ -372,8 +379,8 @@
 
 TEST_P(VibratorAidl, ExternalControlUnsupportedMatchingCapabilities) {
     if ((capabilities & IVibrator::CAP_EXTERNAL_CONTROL) == 0) {
-        EXPECT_EQ(Status::EX_UNSUPPORTED_OPERATION,
-                  vibrator->setExternalControl(true).exceptionCode());
+        Status status = vibrator->setExternalControl(true);
+        EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
     }
 }
 
@@ -410,7 +417,7 @@
             if (isPrimitiveSupported) {
                 EXPECT_EQ(Status::EX_NONE, status.exceptionCode());
             } else {
-                EXPECT_EQ(Status::EX_UNSUPPORTED_OPERATION, status.exceptionCode());
+                EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
             }
         }
     }
@@ -473,8 +480,8 @@
                 effect.primitive = primitive;
                 effect.scale = 1.0f;
             }
-            EXPECT_EQ(Status::EX_UNSUPPORTED_OPERATION,
-                      vibrator->compose(composite, nullptr).exceptionCode());
+            Status status = vibrator->compose(composite, nullptr);
+            EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
             vibrator->off();
         }
     }
@@ -618,8 +625,8 @@
                     EXPECT_EQ(Status::EX_NONE, status.exceptionCode())
                         << toString(effect) << " " << toString(strength);
                 } else {
-                    EXPECT_EQ(Status::EX_UNSUPPORTED_OPERATION, status.exceptionCode())
-                        << toString(effect) << " " << toString(strength);
+                    EXPECT_TRUE(isUnknownOrUnsupported(status))
+                            << status << " " << toString(effect) << " " << toString(strength);
                 }
             }
         }
@@ -639,7 +646,7 @@
         ASSERT_GT(qFactor, 0);
         EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
     } else {
-        EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
+        EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
     }
 }
 
@@ -668,7 +675,7 @@
             ASSERT_LE(e, 1.0);
         }
     } else {
-        EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
+        EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
     }
 }
 
@@ -679,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;
     }
 }
 
@@ -690,7 +697,7 @@
         ASSERT_NE(maxSize, 0);
         EXPECT_EQ(status.exceptionCode(), Status::EX_NONE);
     } else {
-        EXPECT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
+        EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
     }
 }
 
@@ -703,7 +710,7 @@
         ASSERT_TRUE(isDefaultNoneSupported);
         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.0/vts/OWNERS b/wifi/1.0/vts/OWNERS
index e7b2fc5..cf81c79 100644
--- a/wifi/1.0/vts/OWNERS
+++ b/wifi/1.0/vts/OWNERS
@@ -1,2 +1,2 @@
-kumaranand@google.com
+arabawy@google.com
 etancohen@google.com
diff --git a/wifi/1.1/vts/OWNERS b/wifi/1.1/vts/OWNERS
index e7b2fc5..cf81c79 100644
--- a/wifi/1.1/vts/OWNERS
+++ b/wifi/1.1/vts/OWNERS
@@ -1,2 +1,2 @@
-kumaranand@google.com
+arabawy@google.com
 etancohen@google.com
diff --git a/wifi/1.2/vts/OWNERS b/wifi/1.2/vts/OWNERS
index e7b2fc5..cf81c79 100644
--- a/wifi/1.2/vts/OWNERS
+++ b/wifi/1.2/vts/OWNERS
@@ -1,2 +1,2 @@
-kumaranand@google.com
+arabawy@google.com
 etancohen@google.com
diff --git a/wifi/1.3/vts/OWNERS b/wifi/1.3/vts/OWNERS
index e7b2fc5..cf81c79 100644
--- a/wifi/1.3/vts/OWNERS
+++ b/wifi/1.3/vts/OWNERS
@@ -1,2 +1,2 @@
-kumaranand@google.com
+arabawy@google.com
 etancohen@google.com
diff --git a/wifi/1.4/vts/OWNERS b/wifi/1.4/vts/OWNERS
index e7b2fc5..cf81c79 100644
--- a/wifi/1.4/vts/OWNERS
+++ b/wifi/1.4/vts/OWNERS
@@ -1,2 +1,2 @@
-kumaranand@google.com
+arabawy@google.com
 etancohen@google.com
diff --git a/wifi/1.5/default/OWNERS b/wifi/1.5/default/OWNERS
index e7b2fc5..cf81c79 100644
--- a/wifi/1.5/default/OWNERS
+++ b/wifi/1.5/default/OWNERS
@@ -1,2 +1,2 @@
-kumaranand@google.com
+arabawy@google.com
 etancohen@google.com
diff --git a/wifi/1.5/default/wifi_chip.cpp b/wifi/1.5/default/wifi_chip.cpp
index 961f9da..6fa9601 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/vts/OWNERS b/wifi/1.5/vts/OWNERS
index e7b2fc5..cf81c79 100644
--- a/wifi/1.5/vts/OWNERS
+++ b/wifi/1.5/vts/OWNERS
@@ -1,2 +1,2 @@
-kumaranand@google.com
+arabawy@google.com
 etancohen@google.com
diff --git a/wifi/hostapd/1.0/vts/OWNERS b/wifi/hostapd/1.0/vts/OWNERS
index e7b2fc5..cf81c79 100644
--- a/wifi/hostapd/1.0/vts/OWNERS
+++ b/wifi/hostapd/1.0/vts/OWNERS
@@ -1,2 +1,2 @@
-kumaranand@google.com
+arabawy@google.com
 etancohen@google.com
diff --git a/wifi/hostapd/1.1/vts/OWNERS b/wifi/hostapd/1.1/vts/OWNERS
index e7b2fc5..cf81c79 100644
--- a/wifi/hostapd/1.1/vts/OWNERS
+++ b/wifi/hostapd/1.1/vts/OWNERS
@@ -1,2 +1,2 @@
-kumaranand@google.com
+arabawy@google.com
 etancohen@google.com
diff --git a/wifi/hostapd/1.2/vts/OWNERS b/wifi/hostapd/1.2/vts/OWNERS
index e7b2fc5..cf81c79 100644
--- a/wifi/hostapd/1.2/vts/OWNERS
+++ b/wifi/hostapd/1.2/vts/OWNERS
@@ -1,2 +1,2 @@
-kumaranand@google.com
+arabawy@google.com
 etancohen@google.com
diff --git a/wifi/hostapd/1.3/vts/OWNERS b/wifi/hostapd/1.3/vts/OWNERS
index e7b2fc5..cf81c79 100644
--- a/wifi/hostapd/1.3/vts/OWNERS
+++ b/wifi/hostapd/1.3/vts/OWNERS
@@ -1,2 +1,2 @@
-kumaranand@google.com
+arabawy@google.com
 etancohen@google.com
diff --git a/wifi/supplicant/1.2/vts/OWNERS b/wifi/supplicant/1.2/vts/OWNERS
index e7b2fc5..cf81c79 100644
--- a/wifi/supplicant/1.2/vts/OWNERS
+++ b/wifi/supplicant/1.2/vts/OWNERS
@@ -1,2 +1,2 @@
-kumaranand@google.com
+arabawy@google.com
 etancohen@google.com
diff --git a/wifi/supplicant/1.3/vts/OWNERS b/wifi/supplicant/1.3/vts/OWNERS
index e7b2fc5..cf81c79 100644
--- a/wifi/supplicant/1.3/vts/OWNERS
+++ b/wifi/supplicant/1.3/vts/OWNERS
@@ -1,2 +1,2 @@
-kumaranand@google.com
+arabawy@google.com
 etancohen@google.com
diff --git a/wifi/supplicant/1.4/vts/OWNERS b/wifi/supplicant/1.4/vts/OWNERS
index e7b2fc5..cf81c79 100644
--- a/wifi/supplicant/1.4/vts/OWNERS
+++ b/wifi/supplicant/1.4/vts/OWNERS
@@ -1,2 +1,2 @@
-kumaranand@google.com
+arabawy@google.com
 etancohen@google.com