Merge "Use VSR to tell libhwtrust_cxx how to validate"
diff --git a/audio/aidl/common/Android.bp b/audio/aidl/common/Android.bp
index a3f7f0b..4c6a74e 100644
--- a/audio/aidl/common/Android.bp
+++ b/audio/aidl/common/Android.bp
@@ -41,6 +41,20 @@
     ],
 }
 
+cc_library {
+    name: "libaudioaidlranges",
+    host_supported: true,
+    vendor_available: true,
+    static_libs: [
+        "android.hardware.audio.effect-V1-ndk",
+    ],
+    export_include_dirs: ["include"],
+    header_libs: ["libaudioaidl_headers"],
+    srcs: [
+        "EffectRangeSpecific.cpp",
+    ],
+}
+
 cc_test {
     name: "libaudioaidlcommon_test",
     host_supported: true,
diff --git a/audio/aidl/common/EffectRangeSpecific.cpp b/audio/aidl/common/EffectRangeSpecific.cpp
new file mode 100644
index 0000000..bd78ea0
--- /dev/null
+++ b/audio/aidl/common/EffectRangeSpecific.cpp
@@ -0,0 +1,161 @@
+/*

+ * Copyright (C) 2023 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 <aidl/android/hardware/audio/effect/DynamicsProcessing.h>

+#include <aidl/android/hardware/audio/effect/Range.h>

+

+#include "EffectRangeSpecific.h"

+#include "effect-impl/EffectRange.h"

+

+namespace aidl::android::hardware::audio::effect {

+

+namespace DynamicsProcessingRanges {

+

+static bool isInputGainConfigInRange(const std::vector<DynamicsProcessing::InputGain>& cfgs,

+                                     const DynamicsProcessing::InputGain& min,

+                                     const DynamicsProcessing::InputGain& max) {

+    auto func = [](const DynamicsProcessing::InputGain& arg) {

+        return std::make_tuple(arg.channel, arg.gainDb);

+    };

+    return isTupleInRange(cfgs, min, max, func);

+}

+

+static bool isLimiterConfigInRange(const std::vector<DynamicsProcessing::LimiterConfig>& cfgs,

+                                   const DynamicsProcessing::LimiterConfig& min,

+                                   const DynamicsProcessing::LimiterConfig& max) {

+    auto func = [](const DynamicsProcessing::LimiterConfig& arg) {

+        return std::make_tuple(arg.channel, arg.enable, arg.linkGroup, arg.attackTimeMs,

+                               arg.releaseTimeMs, arg.ratio, arg.thresholdDb, arg.postGainDb);

+    };

+    return isTupleInRange(cfgs, min, max, func);

+}

+

+static bool isMbcBandConfigInRange(const std::vector<DynamicsProcessing::MbcBandConfig>& cfgs,

+                                   const DynamicsProcessing::MbcBandConfig& min,

+                                   const DynamicsProcessing::MbcBandConfig& max) {

+    auto func = [](const DynamicsProcessing::MbcBandConfig& arg) {

+        return std::make_tuple(arg.channel, arg.band, arg.enable, arg.cutoffFrequencyHz,

+                               arg.attackTimeMs, arg.releaseTimeMs, arg.ratio, arg.thresholdDb,

+                               arg.kneeWidthDb, arg.noiseGateThresholdDb, arg.expanderRatio,

+                               arg.preGainDb, arg.postGainDb);

+    };

+    return isTupleInRange(cfgs, min, max, func);

+}

+

+static bool isEqBandConfigInRange(const std::vector<DynamicsProcessing::EqBandConfig>& cfgs,

+                                  const DynamicsProcessing::EqBandConfig& min,

+                                  const DynamicsProcessing::EqBandConfig& max) {

+    auto func = [](const DynamicsProcessing::EqBandConfig& arg) {

+        return std::make_tuple(arg.channel, arg.band, arg.enable, arg.cutoffFrequencyHz,

+                               arg.gainDb);

+    };

+    return isTupleInRange(cfgs, min, max, func);

+}

+

+static bool isChannelConfigInRange(const std::vector<DynamicsProcessing::ChannelConfig>& cfgs,

+                                   const DynamicsProcessing::ChannelConfig& min,

+                                   const DynamicsProcessing::ChannelConfig& max) {

+    auto func = [](const DynamicsProcessing::ChannelConfig& arg) {

+        return std::make_tuple(arg.channel, arg.enable);

+    };

+    return isTupleInRange(cfgs, min, max, func);

+}

+

+static bool isEngineConfigInRange(const DynamicsProcessing::EngineArchitecture& cfg,

+                                  const DynamicsProcessing::EngineArchitecture& min,

+                                  const DynamicsProcessing::EngineArchitecture& max) {

+    auto func = [](const DynamicsProcessing::EngineArchitecture& arg) {

+        return std::make_tuple(arg.resolutionPreference, arg.preferredProcessingDurationMs,

+                               arg.preEqStage.inUse, arg.preEqStage.bandCount,

+                               arg.postEqStage.inUse, arg.postEqStage.bandCount, arg.mbcStage.inUse,

+                               arg.mbcStage.bandCount, arg.limiterInUse);

+    };

+    return isTupleInRange(func(cfg), func(min), func(max));

+}

+

+static int locateMinMaxForTag(DynamicsProcessing::Tag tag,

+                              const std::vector<Range::DynamicsProcessingRange>& ranges) {

+    for (int i = 0; i < (int)ranges.size(); i++) {

+        if (tag == ranges[i].min.getTag() && tag == ranges[i].max.getTag()) {

+            return i;

+        }

+    }

+    return -1;

+}

+

+bool isParamInRange(const DynamicsProcessing& dp,

+                    const std::vector<Range::DynamicsProcessingRange>& ranges) {

+    auto tag = dp.getTag();

+    int i = locateMinMaxForTag(tag, ranges);

+    if (i == -1) return true;

+

+    switch (tag) {

+        case DynamicsProcessing::engineArchitecture: {

+            return isEngineConfigInRange(

+                    dp.get<DynamicsProcessing::engineArchitecture>(),

+                    ranges[i].min.get<DynamicsProcessing::engineArchitecture>(),

+                    ranges[i].max.get<DynamicsProcessing::engineArchitecture>());

+        }

+        case DynamicsProcessing::preEq: {

+            return isChannelConfigInRange(dp.get<DynamicsProcessing::preEq>(),

+                                          ranges[i].min.get<DynamicsProcessing::preEq>()[0],

+                                          ranges[i].max.get<DynamicsProcessing::preEq>()[0]);

+        }

+        case DynamicsProcessing::postEq: {

+            return isChannelConfigInRange(dp.get<DynamicsProcessing::postEq>(),

+                                          ranges[i].min.get<DynamicsProcessing::postEq>()[0],

+                                          ranges[i].max.get<DynamicsProcessing::postEq>()[0]);

+        }

+        case DynamicsProcessing::mbc: {

+            return isChannelConfigInRange(dp.get<DynamicsProcessing::mbc>(),

+                                          ranges[i].min.get<DynamicsProcessing::mbc>()[0],

+                                          ranges[i].max.get<DynamicsProcessing::mbc>()[0]);

+        }

+        case DynamicsProcessing::preEqBand: {

+            return isEqBandConfigInRange(dp.get<DynamicsProcessing::preEqBand>(),

+                                         ranges[i].min.get<DynamicsProcessing::preEqBand>()[0],

+                                         ranges[i].max.get<DynamicsProcessing::preEqBand>()[0]);

+        }

+        case DynamicsProcessing::postEqBand: {

+            return isEqBandConfigInRange(dp.get<DynamicsProcessing::postEqBand>(),

+                                         ranges[i].min.get<DynamicsProcessing::postEqBand>()[0],

+                                         ranges[i].max.get<DynamicsProcessing::postEqBand>()[0]);

+        }

+        case DynamicsProcessing::mbcBand: {

+            return isMbcBandConfigInRange(dp.get<DynamicsProcessing::mbcBand>(),

+                                          ranges[i].min.get<DynamicsProcessing::mbcBand>()[0],

+                                          ranges[i].max.get<DynamicsProcessing::mbcBand>()[0]);

+        }

+        case DynamicsProcessing::limiter: {

+            return isLimiterConfigInRange(dp.get<DynamicsProcessing::limiter>(),

+                                          ranges[i].min.get<DynamicsProcessing::limiter>()[0],

+                                          ranges[i].max.get<DynamicsProcessing::limiter>()[0]);

+        }

+        case DynamicsProcessing::inputGain: {

+            return isInputGainConfigInRange(dp.get<DynamicsProcessing::inputGain>(),

+                                            ranges[i].min.get<DynamicsProcessing::inputGain>()[0],

+                                            ranges[i].max.get<DynamicsProcessing::inputGain>()[0]);

+        }

+        default: {

+            return true;

+        }

+    }

+    return true;

+}

+

+}  // namespace DynamicsProcessingRanges

+

+}  // namespace aidl::android::hardware::audio::effect
\ No newline at end of file
diff --git a/audio/aidl/common/include/EffectRangeSpecific.h b/audio/aidl/common/include/EffectRangeSpecific.h
new file mode 100644
index 0000000..c7262bb
--- /dev/null
+++ b/audio/aidl/common/include/EffectRangeSpecific.h
@@ -0,0 +1,28 @@
+/*

+ * Copyright (C) 2023 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.

+ */

+

+#pragma once

+

+namespace aidl::android::hardware::audio::effect {

+

+namespace DynamicsProcessingRanges {

+

+bool isParamInRange(const DynamicsProcessing& dp,

+                    const std::vector<Range::DynamicsProcessingRange>& ranges);

+

+}  // namespace DynamicsProcessingRanges

+

+}  // namespace aidl::android::hardware::audio::effect
\ No newline at end of file
diff --git a/audio/aidl/default/include/effect-impl/EffectRange.h b/audio/aidl/default/include/effect-impl/EffectRange.h
new file mode 100644
index 0000000..a3ea01f
--- /dev/null
+++ b/audio/aidl/default/include/effect-impl/EffectRange.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#pragma once
+
+#include <algorithm>
+#include <tuple>
+#include <utility>
+#include <vector>
+
+namespace aidl::android::hardware::audio::effect {
+
+template <typename T>
+bool isInRange(const T& value, const T& low, const T& high) {
+    return (value >= low) && (value <= high);
+}
+
+template <typename T, std::size_t... Is>
+bool isTupleInRange(const T& test, const T& min, const T& max, std::index_sequence<Is...>) {
+    return (isInRange(std::get<Is>(test), std::get<Is>(min), std::get<Is>(max)) && ...);
+}
+
+template <typename T, std::size_t TupSize = std::tuple_size_v<T>>
+bool isTupleInRange(const T& test, const T& min, const T& max) {
+    return isTupleInRange(test, min, max, std::make_index_sequence<TupSize>{});
+}
+
+template <typename T, typename F>
+bool isTupleInRange(const std::vector<T>& cfgs, const T& min, const T& max, const F& func) {
+    auto minT = func(min), maxT = func(max);
+    return std::all_of(cfgs.cbegin(), cfgs.cend(),
+                       [&](const T& cfg) { return isTupleInRange(func(cfg), minT, maxT); });
+}
+
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/vts/Android.bp b/audio/aidl/vts/Android.bp
index 18aa6f0..852255d 100644
--- a/audio/aidl/vts/Android.bp
+++ b/audio/aidl/vts/Android.bp
@@ -84,6 +84,7 @@
 cc_test {
     name: "VtsHalDynamicsProcessingTargetTest",
     defaults: ["VtsHalAudioTargetTestDefaults"],
+    static_libs: ["libaudioaidlranges"],
     srcs: ["VtsHalDynamicsProcessingTest.cpp"],
 }
 
diff --git a/audio/aidl/vts/EffectHelper.h b/audio/aidl/vts/EffectHelper.h
index f6683cc..831977b 100644
--- a/audio/aidl/vts/EffectHelper.h
+++ b/audio/aidl/vts/EffectHelper.h
@@ -228,10 +228,10 @@
      */
     template <typename S, typename = std::enable_if_t<std::is_arithmetic_v<S>>>
     static std::set<S> expandTestValueBasic(std::set<S>& s) {
-        const auto min = *s.begin(), max = *s.rbegin();
         const auto minLimit = std::numeric_limits<S>::min(),
                    maxLimit = std::numeric_limits<S>::max();
         if (s.size()) {
+            const auto min = *s.begin(), max = *s.rbegin();
             s.insert(min + (max - min) / 2);
             if (min != minLimit) {
                 s.insert(min - 1);
diff --git a/audio/aidl/vts/VtsHalDynamicsProcessingTest.cpp b/audio/aidl/vts/VtsHalDynamicsProcessingTest.cpp
index c62a24e..033e3b5 100644
--- a/audio/aidl/vts/VtsHalDynamicsProcessingTest.cpp
+++ b/audio/aidl/vts/VtsHalDynamicsProcessingTest.cpp
@@ -25,8 +25,10 @@
 #include <Utils.h>
 
 #include "EffectHelper.h"
+#include "EffectRangeSpecific.h"
 
 using namespace android;
+using namespace aidl::android::hardware::audio::effect::DynamicsProcessingRanges;
 
 using aidl::android::hardware::audio::effect::Descriptor;
 using aidl::android::hardware::audio::effect::DynamicsProcessing;
@@ -95,6 +97,19 @@
     template <typename T>
     bool isAidlVectorEqual(const std::vector<T>& source, const std::vector<T>& target);
 
+    template <typename T>
+    bool isChannelConfigValid(const std::vector<T>& cfgs) {
+        auto& channelCount = mChannelCount;
+        return std::all_of(cfgs.cbegin(), cfgs.cend(), [channelCount](const T& cfg) {
+            return (cfg.channel >= 0 && cfg.channel < channelCount);
+        });
+    }
+
+    template <typename T>
+    bool isBandConfigValid(const std::vector<T>& cfgs, int bandCount);
+
+    bool isParamValid(const DynamicsProcessing::Tag& tag, const DynamicsProcessing& dp);
+
     // get set params and validate
     void SetAndGetDynamicsProcessingParameters();
 
@@ -133,9 +148,11 @@
     static const std::set<DynamicsProcessing::StageEnablement> kStageEnablementTestSet;
     static const std::set<std::vector<DynamicsProcessing::InputGain>> kInputGainTestSet;
 
+  protected:
+    int mChannelCount;
+
   private:
     int32_t mChannelLayout;
-    int mChannelCount;
     std::vector<std::pair<DynamicsProcessing::Tag, DynamicsProcessing>> mTags;
     void CleanUp() {
         mTags.clear();
@@ -152,6 +169,8 @@
                 {.inUse = true, .bandCount = DynamicsProcessingTestHelper::kBandCount},
                 {.inUse = true, .bandCount = 0},
                 {.inUse = true, .bandCount = -1},
+                {.inUse = false, .bandCount = 0},
+                {.inUse = false, .bandCount = -1},
                 {.inUse = false, .bandCount = DynamicsProcessingTestHelper::kBandCount}};
 
 // test value set for DynamicsProcessing::ChannelConfig
@@ -161,9 +180,7 @@
                  {.channel = 0, .enable = true},
                  {.channel = 1, .enable = false},
                  {.channel = 2, .enable = true}},
-
                 {{.channel = -1, .enable = false}, {.channel = 2, .enable = true}},
-
                 {{.channel = 0, .enable = true}, {.channel = 1, .enable = true}}};
 
 // test value set for DynamicsProcessing::InputGain
@@ -172,10 +189,65 @@
                 {{.channel = 0, .gainDb = 10.f},
                  {.channel = 1, .gainDb = 0.f},
                  {.channel = 2, .gainDb = -10.f}},
-
                 {{.channel = -1, .gainDb = -10.f}, {.channel = -2, .gainDb = 10.f}},
+                {{.channel = -1, .gainDb = 10.f}, {.channel = 0, .gainDb = -10.f}},
+                {{.channel = 0, .gainDb = 10.f}, {.channel = 1, .gainDb = -10.f}}};
 
-                {{.channel = -1, .gainDb = 10.f}, {.channel = 0, .gainDb = -10.f}}};
+template <typename T>
+bool DynamicsProcessingTestHelper::isBandConfigValid(const std::vector<T>& cfgs, int bandCount) {
+    std::vector<float> freqs(cfgs.size(), -1);
+    for (auto cfg : cfgs) {
+        if (cfg.channel < 0 || cfg.channel >= mChannelCount) return false;
+        if (cfg.band < 0 || cfg.band >= bandCount) return false;
+        freqs[cfg.band] = cfg.cutoffFrequencyHz;
+    }
+    if (std::count(freqs.begin(), freqs.end(), -1)) return false;
+    return std::is_sorted(freqs.begin(), freqs.end());
+}
+
+bool DynamicsProcessingTestHelper::isParamValid(const DynamicsProcessing::Tag& tag,
+                                                const DynamicsProcessing& dp) {
+    switch (tag) {
+        case DynamicsProcessing::preEq: {
+            if (!mEngineConfigApplied.preEqStage.inUse) return false;
+            return isChannelConfigValid(dp.get<DynamicsProcessing::preEq>());
+        }
+        case DynamicsProcessing::postEq: {
+            if (!mEngineConfigApplied.postEqStage.inUse) return false;
+            return isChannelConfigValid(dp.get<DynamicsProcessing::postEq>());
+        }
+        case DynamicsProcessing::mbc: {
+            if (!mEngineConfigApplied.mbcStage.inUse) return false;
+            return isChannelConfigValid(dp.get<DynamicsProcessing::mbc>());
+        }
+        case DynamicsProcessing::preEqBand: {
+            if (!mEngineConfigApplied.preEqStage.inUse) return false;
+            return isBandConfigValid(dp.get<DynamicsProcessing::preEqBand>(),
+                                     mEngineConfigApplied.preEqStage.bandCount);
+        }
+        case DynamicsProcessing::postEqBand: {
+            if (!mEngineConfigApplied.postEqStage.inUse) return false;
+            return isBandConfigValid(dp.get<DynamicsProcessing::postEqBand>(),
+                                     mEngineConfigApplied.postEqStage.bandCount);
+        }
+        case DynamicsProcessing::mbcBand: {
+            if (!mEngineConfigApplied.mbcStage.inUse) return false;
+            return isBandConfigValid(dp.get<DynamicsProcessing::mbcBand>(),
+                                     mEngineConfigApplied.mbcStage.bandCount);
+        }
+        case DynamicsProcessing::limiter: {
+            if (!mEngineConfigApplied.limiterInUse) return false;
+            return isChannelConfigValid(dp.get<DynamicsProcessing::limiter>());
+        }
+        case DynamicsProcessing::inputGain: {
+            return isChannelConfigValid(dp.get<DynamicsProcessing::inputGain>());
+        }
+        default: {
+            return true;
+        }
+    }
+    return true;
+}
 
 bool DynamicsProcessingTestHelper::isParamEqual(const DynamicsProcessing::Tag& tag,
                                                 const DynamicsProcessing& dpRef,
@@ -270,8 +342,8 @@
         // validate parameter
         Descriptor desc;
         ASSERT_STATUS(EX_NONE, mEffect->getDescriptor(&desc));
-        const bool valid =
-                isParameterValid<DynamicsProcessing, Range::dynamicsProcessing>(dp, desc);
+        bool valid = isParamInRange(dp, desc.capability.range.get<Range::dynamicsProcessing>());
+        if (valid) valid = isParamValid(tag, dp);
         const binder_exception_t expected = valid ? EX_NONE : EX_ILLEGAL_ARGUMENT;
 
         // set parameter
@@ -429,10 +501,11 @@
         ::testing::Combine(
                 testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
                         IFactory::descriptor, getEffectTypeUuidDynamicsProcessing())),
-                testing::Values(DynamicsProcessing::ResolutionPreference::FAVOR_TIME_RESOLUTION,
-                                DynamicsProcessing::ResolutionPreference::
-                                        FAVOR_FREQUENCY_RESOLUTION),  // variant
-                testing::Values(-10.f, 0.f, 10.f),                    // processing duration
+                testing::Values(
+                        DynamicsProcessing::ResolutionPreference::FAVOR_TIME_RESOLUTION,
+                        DynamicsProcessing::ResolutionPreference::FAVOR_FREQUENCY_RESOLUTION,
+                        static_cast<DynamicsProcessing::ResolutionPreference>(-1)),  // variant
+                testing::Values(-10.f, 0.f, 10.f),  // processing duration
                 testing::ValuesIn(
                         DynamicsProcessingTestHelper::kStageEnablementTestSet),  // preEQ/postEQ/mbc
                 testing::Bool()),                                                // limiter enable
@@ -515,12 +588,12 @@
     LIMITER_MAX_NUM,
 };
 using LimiterConfigTestAdditional = std::array<float, LIMITER_MAX_NUM>;
-// attachTime, releaseTime, ratio, thresh, postGain
+// attackTime, releaseTime, ratio, thresh, postGain
 static constexpr std::array<LimiterConfigTestAdditional, 4> kLimiterConfigTestAdditionalParam = {
         {{-1, -60, -2.5, -2, -3.14},
          {-1, 60, -2.5, 2, -3.14},
          {1, -60, 2.5, -2, 3.14},
-         {1, 60, 2.5, 2, 3.14}}};
+         {1, 60, 2.5, -2, 3.14}}};
 
 using LimiterConfigTestParams =
         std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int32_t, bool, int32_t, bool,
@@ -669,15 +742,13 @@
 enum EqBandConfigTestParamName {
     EQ_BAND_INSTANCE_NAME,
     EQ_BAND_CHANNEL,
-    EQ_BAND_CHANNEL_ENABLE,
     EQ_BAND_ENABLE,
     EQ_BAND_CUT_OFF_FREQ,
     EQ_BAND_GAIN,
     EQ_BAND_STAGE_IN_USE
 };
 using EqBandConfigTestParams = std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int32_t,
-                                          std::vector<DynamicsProcessing::ChannelConfig>, bool,
-                                          std::vector<std::pair<int, float>>, float, bool>;
+                                          bool, std::vector<std::pair<int, float>>, float, bool>;
 
 void fillEqBandConfig(std::vector<DynamicsProcessing::EqBandConfig>& cfgs,
                       const EqBandConfigTestParams& params) {
@@ -698,8 +769,7 @@
   public:
     DynamicsProcessingTestEqBandConfig()
         : DynamicsProcessingTestHelper(std::get<EQ_BAND_INSTANCE_NAME>(GetParam())),
-          mStageInUse(std::get<EQ_BAND_STAGE_IN_USE>(GetParam())),
-          mChannelConfig(std::get<EQ_BAND_CHANNEL_ENABLE>(GetParam())) {
+          mStageInUse(std::get<EQ_BAND_STAGE_IN_USE>(GetParam())) {
         fillEqBandConfig(mCfgs, GetParam());
     }
 
@@ -709,14 +779,18 @@
 
     std::vector<DynamicsProcessing::EqBandConfig> mCfgs;
     const bool mStageInUse;
-    const std::vector<DynamicsProcessing::ChannelConfig> mChannelConfig;
 };
 
 TEST_P(DynamicsProcessingTestEqBandConfig, SetAndGetPreEqBandConfig) {
     mEngineConfigPreset.preEqStage.inUse = mStageInUse;
     mEngineConfigPreset.preEqStage.bandCount = mCfgs.size();
     EXPECT_NO_FATAL_FAILURE(addEngineConfig(mEngineConfigPreset));
-    EXPECT_NO_FATAL_FAILURE(addPreEqChannelConfig(mChannelConfig));
+    std::vector<DynamicsProcessing::ChannelConfig> cfgs(mChannelCount);
+    for (int i = 0; i < mChannelCount; i++) {
+        cfgs[i].channel = i;
+        cfgs[i].enable = true;
+    }
+    EXPECT_NO_FATAL_FAILURE(addPreEqChannelConfig(cfgs));
     EXPECT_NO_FATAL_FAILURE(addPreEqBandConfigs(mCfgs));
     SetAndGetDynamicsProcessingParameters();
 }
@@ -725,7 +799,12 @@
     mEngineConfigPreset.postEqStage.inUse = mStageInUse;
     mEngineConfigPreset.postEqStage.bandCount = mCfgs.size();
     EXPECT_NO_FATAL_FAILURE(addEngineConfig(mEngineConfigPreset));
-    EXPECT_NO_FATAL_FAILURE(addPostEqChannelConfig(mChannelConfig));
+    std::vector<DynamicsProcessing::ChannelConfig> cfgs(mChannelCount);
+    for (int i = 0; i < mChannelCount; i++) {
+        cfgs[i].channel = i;
+        cfgs[i].enable = true;
+    }
+    EXPECT_NO_FATAL_FAILURE(addPostEqChannelConfig(cfgs));
     EXPECT_NO_FATAL_FAILURE(addPostEqBandConfigs(mCfgs));
     SetAndGetDynamicsProcessingParameters();
 }
@@ -776,28 +855,23 @@
 
 INSTANTIATE_TEST_SUITE_P(
         DynamicsProcessingTest, DynamicsProcessingTestEqBandConfig,
-        ::testing::Combine(
-                testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
-                        IFactory::descriptor, getEffectTypeUuidDynamicsProcessing())),
-                testing::Values(-1, 0, 10),  // channel ID
-                testing::ValuesIn(
-                        DynamicsProcessingTestHelper::kChannelConfigTestSet),  // channel enable
-                testing::Bool(),                                               // band enable
-                testing::ValuesIn(kBands),       // cut off frequencies
-                testing::Values(-3.14f, 3.14f),  // gain
-                testing::Bool()),                // stage in use
+        ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
+                                   IFactory::descriptor, getEffectTypeUuidDynamicsProcessing())),
+                           testing::Values(-1, 0, 10),      // channel ID
+                           testing::Bool(),                 // band enable
+                           testing::ValuesIn(kBands),       // cut off frequencies
+                           testing::Values(-3.14f, 3.14f),  // gain
+                           testing::Values(true)),          // stage in use
         [](const auto& info) {
             auto descriptor = std::get<EQ_BAND_INSTANCE_NAME>(info.param).second;
             std::vector<DynamicsProcessing::EqBandConfig> cfgs;
             fillEqBandConfig(cfgs, info.param);
-            std::string enable =
-                    ::android::internal::ToString(std::get<EQ_BAND_CHANNEL_ENABLE>(info.param));
             std::string bands = ::android::internal::ToString(cfgs);
             std::string stageInUse = std::to_string(std::get<EQ_BAND_STAGE_IN_USE>(info.param));
             std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
                                descriptor.common.name + "_UUID_" +
-                               descriptor.common.id.uuid.toString() + "_" + enable + "_bands_" +
-                               bands + "_stageInUse_" + stageInUse;
+                               descriptor.common.id.uuid.toString() + "_bands_" + bands +
+                               "_stageInUse_" + stageInUse;
             std::replace_if(
                     name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
             return name;
@@ -811,7 +885,6 @@
 enum MbcBandConfigParamName {
     MBC_BAND_INSTANCE_NAME,
     MBC_BAND_CHANNEL,
-    MBC_BAND_CHANNEL_CONFIG,
     MBC_BAND_ENABLE,
     MBC_BAND_CUTOFF_FREQ,
     MBC_BAND_STAGE_IN_USE,
@@ -831,16 +904,15 @@
 };
 using TestParamsMbcBandConfigAdditional = std::array<float, MBC_ADD_MAX_NUM>;
 
-// attachTime, releaseTime, ratio, thresh, kneeWidth, noise, expander, preGain, postGain
+// attackTime, releaseTime, ratio, thresh, kneeWidth, noise, expander, preGain, postGain
 static constexpr std::array<TestParamsMbcBandConfigAdditional, 4> kMbcBandConfigAdditionalParam = {
         {{-3, -10, -2, -2, -5, -90, -2.5, -2, -2},
          {0, 0, 0, 0, 0, 0, 0, 0, 0},
          {-3, 10, -2, 2, -5, 90, -2.5, 2, -2},
-         {3, 10, 2, 2, 5, 90, 2.5, 2, 2}}};
+         {3, 10, 2, -2, -5, 90, 2.5, 2, 2}}};
 
 using TestParamsMbcBandConfig =
-        std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int32_t,
-                   std::vector<DynamicsProcessing::ChannelConfig>, bool,
+        std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int32_t, bool,
                    std::vector<std::pair<int, float>>, bool, TestParamsMbcBandConfigAdditional>;
 
 void fillMbcBandConfig(std::vector<DynamicsProcessing::MbcBandConfig>& cfgs,
@@ -873,8 +945,7 @@
   public:
     DynamicsProcessingTestMbcBandConfig()
         : DynamicsProcessingTestHelper(std::get<MBC_BAND_INSTANCE_NAME>(GetParam())),
-          mStageInUse(std::get<MBC_BAND_STAGE_IN_USE>(GetParam())),
-          mChannelConfig(std::get<MBC_BAND_CHANNEL_CONFIG>(GetParam())) {
+          mStageInUse(std::get<MBC_BAND_STAGE_IN_USE>(GetParam())) {
         fillMbcBandConfig(mCfgs, GetParam());
     }
 
@@ -884,42 +955,41 @@
 
     std::vector<DynamicsProcessing::MbcBandConfig> mCfgs;
     const bool mStageInUse;
-    const std::vector<DynamicsProcessing::ChannelConfig> mChannelConfig;
 };
 
 TEST_P(DynamicsProcessingTestMbcBandConfig, SetAndGetMbcBandConfig) {
     mEngineConfigPreset.mbcStage.inUse = mStageInUse;
     mEngineConfigPreset.mbcStage.bandCount = mCfgs.size();
     EXPECT_NO_FATAL_FAILURE(addEngineConfig(mEngineConfigPreset));
-    EXPECT_NO_FATAL_FAILURE(addMbcChannelConfig(mChannelConfig));
+    std::vector<DynamicsProcessing::ChannelConfig> cfgs(mChannelCount);
+    for (int i = 0; i < mChannelCount; i++) {
+        cfgs[i].channel = i;
+        cfgs[i].enable = true;
+    }
+    EXPECT_NO_FATAL_FAILURE(addMbcChannelConfig(cfgs));
     EXPECT_NO_FATAL_FAILURE(addMbcBandConfigs(mCfgs));
     SetAndGetDynamicsProcessingParameters();
 }
 
 INSTANTIATE_TEST_SUITE_P(
         DynamicsProcessingTest, DynamicsProcessingTestMbcBandConfig,
-        ::testing::Combine(
-                testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
-                        IFactory::descriptor, getEffectTypeUuidDynamicsProcessing())),
-                testing::Values(-1, 0, 10),  // channel count
-                testing::ValuesIn(
-                        DynamicsProcessingTestHelper::kChannelConfigTestSet),  // channel config
-                testing::Bool(),                                               // enable
-                testing::ValuesIn(kBands),                          // cut off frequencies
-                testing::Bool(),                                    // stage in use
-                testing::ValuesIn(kMbcBandConfigAdditionalParam)),  // Additional
+        ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
+                                   IFactory::descriptor, getEffectTypeUuidDynamicsProcessing())),
+                           testing::Values(-1, 0, 10),  // channel count
+                           testing::Bool(),             // enable
+                           testing::ValuesIn(kBands),   // cut off frequencies
+                           testing::Bool(),             // stage in use
+                           testing::ValuesIn(kMbcBandConfigAdditionalParam)),  // Additional
         [](const auto& info) {
             auto descriptor = std::get<MBC_BAND_INSTANCE_NAME>(info.param).second;
             std::vector<DynamicsProcessing::MbcBandConfig> cfgs;
             fillMbcBandConfig(cfgs, info.param);
-            std::string enable =
-                    ::android::internal::ToString(std::get<MBC_BAND_CHANNEL_CONFIG>(info.param));
             std::string mbcBands = ::android::internal::ToString(cfgs);
             std::string stageInUse = std::to_string(std::get<MBC_BAND_STAGE_IN_USE>(info.param));
             std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
                                descriptor.common.name + "_UUID_" +
-                               descriptor.common.id.uuid.toString() + "_enable_" + enable +
-                               "_bands_" + mbcBands + "_stageInUse_" + stageInUse;
+                               descriptor.common.id.uuid.toString() + "_bands_" + mbcBands +
+                               "_stageInUse_" + stageInUse;
             std::replace_if(
                     name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
             return name;
diff --git a/automotive/occupant_awareness/aidl/default/Android.bp b/automotive/occupant_awareness/aidl/default/Android.bp
index 66af9de..1ae8689 100644
--- a/automotive/occupant_awareness/aidl/default/Android.bp
+++ b/automotive/occupant_awareness/aidl/default/Android.bp
@@ -26,6 +26,7 @@
 cc_binary {
     name: "android.hardware.automotive.occupant_awareness@1.0-service",
     init_rc: ["android.hardware.automotive.occupant_awareness@1.0-service.rc"],
+    vintf_fragments: ["android.hardware.automotive.occupant_awareness-service.xml"],
     relative_install_path: "hw",
     vendor: true,
     srcs: [
diff --git a/automotive/occupant_awareness/aidl/default/android.hardware.automotive.occupant_awareness-service.xml b/automotive/occupant_awareness/aidl/default/android.hardware.automotive.occupant_awareness-service.xml
new file mode 100644
index 0000000..b4f8fa5
--- /dev/null
+++ b/automotive/occupant_awareness/aidl/default/android.hardware.automotive.occupant_awareness-service.xml
@@ -0,0 +1,7 @@
+<manifest version="1.0" type="device">
+    <hal format="aidl">
+        <name>android.hardware.automotive.occupant_awareness</name>
+        <version>1</version>
+        <fqname>IOccupantAwareness/default</fqname>
+    </hal>
+</manifest>
diff --git a/bluetooth/aidl/TEST_MAPPING b/bluetooth/aidl/TEST_MAPPING
index 342a1e4..f059c04 100644
--- a/bluetooth/aidl/TEST_MAPPING
+++ b/bluetooth/aidl/TEST_MAPPING
@@ -1,7 +1,13 @@
 {
   "presubmit" : [
     {
-      "name" : "VtsHalBluetoothTargetTest"
+      "name" : "VtsHalBluetoothTargetTest",
+      "options": [
+        {
+          // TODO(b/275847929)
+          "exclude-filter": "VtsHalBluetoothTargetTest.PerInstance/BluetoothAidlTest#Cdd_C_12_1_Bluetooth5Requirements/0_android_hardware_bluetooth_IBluetoothHci_default"
+        }
+      ]
     }
   ]
 }
diff --git a/bluetooth/aidl/vts/Android.bp b/bluetooth/aidl/vts/Android.bp
index 414f707..5fc0b2e 100644
--- a/bluetooth/aidl/vts/Android.bp
+++ b/bluetooth/aidl/vts/Android.bp
@@ -13,7 +13,17 @@
         "VtsHalTargetTestDefaults",
         "use_libaidlvintf_gtest_helper_static",
     ],
-    srcs: ["VtsHalBluetoothTargetTest.cpp"],
+    srcs: [
+        "VtsHalBluetoothTargetTest.cpp",
+        ":BluetoothPacketSources",
+        ":BluetoothHciPacketSources",
+    ],
+    generated_headers: [
+        "BluetoothGeneratedPackets_h",
+    ],
+    include_dirs: [
+        "packages/modules/Bluetooth/system/gd",
+    ],
     shared_libs: [
         "libbase",
         "libbinder_ndk",
@@ -45,4 +55,8 @@
     tidy_flags: [
         "--header-filter=^.*tools\\/rootcanal\\/(model|include|net|desktop)\\/(.(?!\\.pb\\.h))*$",
     ],
+    tidy_disabled_srcs: [
+        ":BluetoothPacketSources",
+        ":BluetoothHciPacketSources",
+    ],
 }
diff --git a/bluetooth/aidl/vts/VtsHalBluetoothTargetTest.cpp b/bluetooth/aidl/vts/VtsHalBluetoothTargetTest.cpp
index 3704c3d..529e092 100644
--- a/bluetooth/aidl/vts/VtsHalBluetoothTargetTest.cpp
+++ b/bluetooth/aidl/vts/VtsHalBluetoothTargetTest.cpp
@@ -24,27 +24,50 @@
 #include <android/binder_manager.h>
 #include <android/binder_process.h>
 #include <binder/IServiceManager.h>
-#include <binder/ProcessState.h>
 
 #include <atomic>
 #include <chrono>
 #include <condition_variable>
 #include <future>
-#include <mutex>
 #include <queue>
 #include <thread>
+#include <utility>
 #include <vector>
 
+// TODO: Remove custom logging defines from PDL packets.
+#undef LOG_INFO
+#undef LOG_DEBUG
+#undef LOG_TAG
+#define LOG_TAG "VtsHalBluetooth"
+#include "hci/hci_packets.h"
+#include "packet/raw_builder.h"
+
 using aidl::android::hardware::bluetooth::IBluetoothHci;
 using aidl::android::hardware::bluetooth::IBluetoothHciCallbacks;
 using aidl::android::hardware::bluetooth::Status;
 using ndk::ScopedAStatus;
 using ndk::SpAIBinder;
 
-// Bluetooth Core Specification 3.0 + HS
-static constexpr uint8_t kHciMinimumHciVersion = 5;
-// Bluetooth Core Specification 3.0 + HS
-static constexpr uint8_t kHciMinimumLmpVersion = 5;
+using ::bluetooth::hci::CommandBuilder;
+using ::bluetooth::hci::CommandCompleteView;
+using ::bluetooth::hci::CommandView;
+using ::bluetooth::hci::ErrorCode;
+using ::bluetooth::hci::EventView;
+using ::bluetooth::hci::LeReadLocalSupportedFeaturesBuilder;
+using ::bluetooth::hci::LeReadLocalSupportedFeaturesCompleteView;
+using ::bluetooth::hci::LeReadNumberOfSupportedAdvertisingSetsBuilder;
+using ::bluetooth::hci::LeReadNumberOfSupportedAdvertisingSetsCompleteView;
+using ::bluetooth::hci::LeReadResolvingListSizeBuilder;
+using ::bluetooth::hci::LeReadResolvingListSizeCompleteView;
+using ::bluetooth::hci::LLFeaturesBits;
+using ::bluetooth::hci::OpCode;
+using ::bluetooth::hci::OpCodeText;
+using ::bluetooth::hci::PacketView;
+using ::bluetooth::hci::ReadLocalVersionInformationBuilder;
+using ::bluetooth::hci::ReadLocalVersionInformationCompleteView;
+
+static constexpr uint8_t kMinLeAdvSetForBt5 = 16;
+static constexpr uint8_t kMinLeResolvingListForBt5 = 8;
 
 static constexpr size_t kNumHciCommandsBandwidth = 100;
 static constexpr size_t kNumScoPacketsBandwidth = 100;
@@ -55,65 +78,14 @@
 static constexpr std::chrono::milliseconds kWaitForAclDataTimeout(1000);
 static constexpr std::chrono::milliseconds kInterfaceCloseDelayMs(200);
 
-static constexpr uint8_t kCommandHciShouldBeUnknown[] = {
-    0xff, 0x3B, 0x08, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
-static constexpr uint8_t kCommandHciReadLocalVersionInformation[] = {0x01, 0x10,
-                                                                     0x00};
-static constexpr uint8_t kCommandHciReadBufferSize[] = {0x05, 0x10, 0x00};
-static constexpr uint8_t kCommandHciWriteLoopbackModeLocal[] = {0x02, 0x18,
-                                                                0x01, 0x01};
-static constexpr uint8_t kCommandHciReset[] = {0x03, 0x0c, 0x00};
-static constexpr uint8_t kCommandHciSynchronousFlowControlEnable[] = {
-    0x2f, 0x0c, 0x01, 0x01};
-static constexpr uint8_t kCommandHciWriteLocalName[] = {0x13, 0x0c, 0xf8};
-static constexpr uint8_t kHciStatusSuccess = 0x00;
-static constexpr uint8_t kHciStatusUnknownHciCommand = 0x01;
-
-static constexpr uint8_t kEventConnectionComplete = 0x03;
-static constexpr uint8_t kEventCommandComplete = 0x0e;
-static constexpr uint8_t kEventCommandStatus = 0x0f;
-static constexpr uint8_t kEventNumberOfCompletedPackets = 0x13;
-static constexpr uint8_t kEventLoopbackCommand = 0x19;
-
-static constexpr size_t kEventCodeByte = 0;
-static constexpr size_t kEventLengthByte = 1;
-static constexpr size_t kEventFirstPayloadByte = 2;
-static constexpr size_t kEventCommandStatusStatusByte = 2;
-static constexpr size_t kEventCommandStatusOpcodeLsByte = 4;    // Bytes 4 and 5
-static constexpr size_t kEventCommandCompleteOpcodeLsByte = 3;  // Bytes 3 and 4
-static constexpr size_t kEventCommandCompleteStatusByte = 5;
-static constexpr size_t kEventCommandCompleteFirstParamByte = 6;
-static constexpr size_t kEventLocalHciVersionByte =
-    kEventCommandCompleteFirstParamByte;
-static constexpr size_t kEventLocalLmpVersionByte =
-    kEventLocalHciVersionByte + 3;
-
-static constexpr size_t kEventConnectionCompleteParamLength = 11;
-static constexpr size_t kEventConnectionCompleteType = 11;
-static constexpr size_t kEventConnectionCompleteTypeSco = 0;
-static constexpr size_t kEventConnectionCompleteTypeAcl = 1;
-static constexpr size_t kEventConnectionCompleteHandleLsByte = 3;
-
-static constexpr size_t kEventNumberOfCompletedPacketsNumHandles = 2;
-
-static constexpr size_t kAclBroadcastFlagOffset = 6;
-static constexpr uint8_t kAclBroadcastFlagPointToPoint = 0x0;
-static constexpr uint8_t kAclBroadcastPointToPoint =
-    (kAclBroadcastFlagPointToPoint << kAclBroadcastFlagOffset);
-
-static constexpr uint8_t kAclPacketBoundaryFlagOffset = 4;
-static constexpr uint8_t kAclPacketBoundaryFlagFirstAutoFlushable = 0x2;
-static constexpr uint8_t kAclPacketBoundaryFirstAutoFlushable =
-    kAclPacketBoundaryFlagFirstAutoFlushable << kAclPacketBoundaryFlagOffset;
-
 // To discard Qualcomm ACL debugging
 static constexpr uint16_t kAclHandleQcaDebugMessage = 0xedc;
 
 class ThroughputLogger {
  public:
-  ThroughputLogger(std::string task)
+  explicit ThroughputLogger(std::string task)
       : total_bytes_(0),
-        task_(task),
+        task_(std::move(task)),
         start_time_(std::chrono::steady_clock::now()) {}
 
   ~ThroughputLogger() {
@@ -142,7 +114,7 @@
 // The main test class for Bluetooth HAL.
 class BluetoothAidlTest : public ::testing::TestWithParam<std::string> {
  public:
-  virtual void SetUp() override {
+  void SetUp() override {
     // currently test passthrough mode only
     hci = IBluetoothHci::fromBinder(
         SpAIBinder(AServiceManager_waitForService(GetParam().c_str())));
@@ -158,7 +130,7 @@
     ASSERT_NE(bluetooth_hci_death_recipient, nullptr);
     ASSERT_EQ(STATUS_OK,
               AIBinder_linkToDeath(hci->asBinder().get(),
-                                   bluetooth_hci_death_recipient, 0));
+                                   bluetooth_hci_death_recipient, nullptr));
 
     hci_cb = ndk::SharedRefBase::make<BluetoothHciCallbacks>(*this);
     ASSERT_NE(hci_cb, nullptr);
@@ -179,7 +151,7 @@
     ASSERT_TRUE(future.get());
   }
 
-  virtual void TearDown() override {
+  void TearDown() override {
     ALOGI("TearDown");
     // Should not be checked in production code
     ASSERT_TRUE(hci->close().isOk());
@@ -205,8 +177,14 @@
   void handle_no_ops();
   void discard_qca_debugging();
   void wait_for_event(bool timeout_is_error);
-  void wait_for_command_complete_event(std::vector<uint8_t> cmd);
+  void wait_for_command_complete_event(OpCode opCode,
+                                       std::vector<uint8_t>& complete_event);
+  // Wait until a command complete is received.
+  // Command complete will be consumed after this method
+  void wait_and_validate_command_complete_event(OpCode opCode);
   int wait_for_completed_packets_event(uint16_t handle);
+  void send_and_wait_for_cmd_complete(std::unique_ptr<CommandBuilder> cmd,
+                                      std::vector<uint8_t>& cmd_complete);
 
   // A simple test implementation of BluetoothHciCallbacks.
   class BluetoothHciCallbacks
@@ -214,36 +192,41 @@
     BluetoothAidlTest& parent_;
 
    public:
-    BluetoothHciCallbacks(BluetoothAidlTest& parent) : parent_(parent){};
+    explicit BluetoothHciCallbacks(BluetoothAidlTest& parent)
+        : parent_(parent){};
 
-    virtual ~BluetoothHciCallbacks() = default;
+    ~BluetoothHciCallbacks() override = default;
 
-    ndk::ScopedAStatus initializationComplete(Status status) {
+    ndk::ScopedAStatus initializationComplete(Status status) override {
       parent_.initialized_promise.set_value(status == Status::SUCCESS);
       ALOGV("%s (status = %d)", __func__, static_cast<int>(status));
       return ScopedAStatus::ok();
     };
 
-    ndk::ScopedAStatus hciEventReceived(const std::vector<uint8_t>& event) {
+    ndk::ScopedAStatus hciEventReceived(
+        const std::vector<uint8_t>& event) override {
       parent_.event_cb_count++;
       parent_.event_queue.push(event);
-      ALOGV("Event received (length = %d)", static_cast<int>(event.size()));
+      ALOGI("Event received (length = %d)", static_cast<int>(event.size()));
       return ScopedAStatus::ok();
     };
 
-    ndk::ScopedAStatus aclDataReceived(const std::vector<uint8_t>& data) {
+    ndk::ScopedAStatus aclDataReceived(
+        const std::vector<uint8_t>& data) override {
       parent_.acl_cb_count++;
       parent_.acl_queue.push(data);
       return ScopedAStatus::ok();
     };
 
-    ndk::ScopedAStatus scoDataReceived(const std::vector<uint8_t>& data) {
+    ndk::ScopedAStatus scoDataReceived(
+        const std::vector<uint8_t>& data) override {
       parent_.sco_cb_count++;
       parent_.sco_queue.push(data);
       return ScopedAStatus::ok();
     };
 
-    ndk::ScopedAStatus isoDataReceived(const std::vector<uint8_t>& data) {
+    ndk::ScopedAStatus isoDataReceived(
+        const std::vector<uint8_t>& data) override {
       parent_.iso_cb_count++;
       parent_.iso_queue.push(data);
       return ScopedAStatus::ok();
@@ -253,7 +236,8 @@
   template <class T>
   class WaitQueue {
    public:
-    WaitQueue(){};
+    WaitQueue() = default;
+    ;
 
     virtual ~WaitQueue() = default;
 
@@ -283,6 +267,14 @@
       return true;
     };
 
+    void pop() {
+      std::lock_guard<std::mutex> lock(m_);
+      if (q_.empty()) {
+        return;
+      }
+      q_.pop();
+    };
+
     bool front(T& v) {
       std::lock_guard<std::mutex> lock(m_);
       if (q_.empty()) {
@@ -329,22 +321,22 @@
 
   std::shared_ptr<IBluetoothHci> hci;
   std::shared_ptr<BluetoothHciCallbacks> hci_cb;
-  AIBinder_DeathRecipient* bluetooth_hci_death_recipient;
+  AIBinder_DeathRecipient* bluetooth_hci_death_recipient{};
   WaitQueue<std::vector<uint8_t>> event_queue;
   WaitQueue<std::vector<uint8_t>> acl_queue;
   WaitQueue<std::vector<uint8_t>> sco_queue;
   WaitQueue<std::vector<uint8_t>> iso_queue;
 
   std::promise<bool> initialized_promise;
-  int event_cb_count;
-  int sco_cb_count;
-  int acl_cb_count;
-  int iso_cb_count;
+  int event_cb_count{};
+  int sco_cb_count{};
+  int acl_cb_count{};
+  int iso_cb_count{};
 
-  int max_acl_data_packet_length;
-  int max_sco_data_packet_length;
-  int max_acl_data_packets;
-  int max_sco_data_packets;
+  int max_acl_data_packet_length{};
+  int max_sco_data_packet_length{};
+  int max_acl_data_packets{};
+  int max_sco_data_packets{};
 
   std::vector<uint16_t> sco_connection_handles;
   std::vector<uint16_t> acl_connection_handles;
@@ -355,17 +347,20 @@
   while (!event_queue.empty()) {
     std::vector<uint8_t> event;
     event_queue.front(event);
-    ASSERT_GE(event.size(),
-              static_cast<size_t>(kEventCommandCompleteStatusByte));
-    bool event_is_no_op =
-        (event[kEventCodeByte] == kEventCommandComplete) &&
-        (event[kEventCommandCompleteOpcodeLsByte] == 0x00) &&
-        (event[kEventCommandCompleteOpcodeLsByte + 1] == 0x00);
-    event_is_no_op |= (event[kEventCodeByte] == kEventCommandStatus) &&
-                      (event[kEventCommandStatusOpcodeLsByte] == 0x00) &&
-                      (event[kEventCommandStatusOpcodeLsByte + 1] == 0x00);
-    if (event_is_no_op) {
-      event_queue.pop(event);
+    auto complete_view = ::bluetooth::hci::CommandCompleteView::Create(
+        ::bluetooth::hci::EventView::Create(::bluetooth::hci::PacketView<true>(
+            std::make_shared<std::vector<uint8_t>>(event))));
+    auto status_view = ::bluetooth::hci::CommandCompleteView::Create(
+        ::bluetooth::hci::EventView::Create(::bluetooth::hci::PacketView<true>(
+            std::make_shared<std::vector<uint8_t>>(event))));
+    bool is_complete_no_op =
+        complete_view.IsValid() &&
+        complete_view.GetCommandOpCode() == ::bluetooth::hci::OpCode::NONE;
+    bool is_status_no_op =
+        status_view.IsValid() &&
+        status_view.GetCommandOpCode() == ::bluetooth::hci::OpCode::NONE;
+    if (is_complete_no_op || is_status_no_op) {
+      event_queue.pop();
     } else {
       break;
     }
@@ -377,12 +372,12 @@
   while (!acl_queue.empty()) {
     std::vector<uint8_t> acl_packet;
     acl_queue.front(acl_packet);
-    uint16_t connection_handle = acl_packet[1] & 0xF;
-    connection_handle <<= 8;
-    connection_handle |= acl_packet[0];
-    bool packet_is_no_op = connection_handle == kAclHandleQcaDebugMessage;
-    if (packet_is_no_op) {
-      acl_queue.pop(acl_packet);
+    auto acl_view =
+        ::bluetooth::hci::AclView::Create(::bluetooth::hci::PacketView<true>(
+            std::make_shared<std::vector<uint8_t>>(acl_packet)));
+    EXPECT_TRUE(acl_view.IsValid());
+    if (acl_view.GetHandle() == kAclHandleQcaDebugMessage) {
+      acl_queue.pop();
     } else {
       break;
     }
@@ -407,48 +402,49 @@
   }
 }
 
-// Wait until a command complete is received.
 void BluetoothAidlTest::wait_for_command_complete_event(
-    std::vector<uint8_t> cmd) {
+    OpCode opCode, std::vector<uint8_t>& complete_event) {
   ASSERT_NO_FATAL_FAILURE(wait_for_event());
-  std::vector<uint8_t> event;
   ASSERT_FALSE(event_queue.empty());
-  ASSERT_TRUE(event_queue.pop(event));
+  ASSERT_TRUE(event_queue.pop(complete_event));
+  auto complete_view = ::bluetooth::hci::CommandCompleteView::Create(
+      ::bluetooth::hci::EventView::Create(::bluetooth::hci::PacketView<true>(
+          std::make_shared<std::vector<uint8_t>>(complete_event))));
+  ASSERT_TRUE(complete_view.IsValid());
+  ASSERT_EQ(complete_view.GetCommandOpCode(), opCode);
+  ASSERT_EQ(complete_view.GetPayload()[0],
+            static_cast<uint8_t>(::bluetooth::hci::ErrorCode::SUCCESS));
+}
 
-  ASSERT_GT(event.size(), static_cast<size_t>(kEventCommandCompleteStatusByte));
-  ASSERT_EQ(kEventCommandComplete, event[kEventCodeByte]);
-  ASSERT_EQ(cmd[0], event[kEventCommandCompleteOpcodeLsByte]);
-  ASSERT_EQ(cmd[1], event[kEventCommandCompleteOpcodeLsByte + 1]);
-  ASSERT_EQ(kHciStatusSuccess, event[kEventCommandCompleteStatusByte]);
+void BluetoothAidlTest::wait_and_validate_command_complete_event(
+    ::bluetooth::hci::OpCode opCode) {
+  std::vector<uint8_t> complete_event;
+  ASSERT_NO_FATAL_FAILURE(
+      wait_for_command_complete_event(opCode, complete_event));
 }
 
 // Send the command to read the controller's buffer sizes.
 void BluetoothAidlTest::setBufferSizes() {
-  std::vector<uint8_t> cmd{
-      kCommandHciReadBufferSize,
-      kCommandHciReadBufferSize + sizeof(kCommandHciReadBufferSize)};
+  std::vector<uint8_t> cmd;
+  ::bluetooth::packet::BitInserter bi{cmd};
+  ::bluetooth::hci::ReadBufferSizeBuilder::Create()->Serialize(bi);
   hci->sendHciCommand(cmd);
 
   ASSERT_NO_FATAL_FAILURE(wait_for_event());
-  if (event_queue.empty()) {
-    return;
-  }
   std::vector<uint8_t> event;
   ASSERT_TRUE(event_queue.pop(event));
+  auto complete_view = ::bluetooth::hci::ReadBufferSizeCompleteView::Create(
+      ::bluetooth::hci::CommandCompleteView::Create(
+          ::bluetooth::hci::EventView::Create(
+              ::bluetooth::hci::PacketView<true>(
+                  std::make_shared<std::vector<uint8_t>>(event)))));
 
-  ASSERT_EQ(kEventCommandComplete, event[kEventCodeByte]);
-  ASSERT_EQ(cmd[0], event[kEventCommandCompleteOpcodeLsByte]);
-  ASSERT_EQ(cmd[1], event[kEventCommandCompleteOpcodeLsByte + 1]);
-  ASSERT_EQ(kHciStatusSuccess, event[kEventCommandCompleteStatusByte]);
-
-  max_acl_data_packet_length =
-      event[kEventCommandCompleteStatusByte + 1] +
-      (event[kEventCommandCompleteStatusByte + 2] << 8);
-  max_sco_data_packet_length = event[kEventCommandCompleteStatusByte + 3];
-  max_acl_data_packets = event[kEventCommandCompleteStatusByte + 4] +
-                         (event[kEventCommandCompleteStatusByte + 5] << 8);
-  max_sco_data_packets = event[kEventCommandCompleteStatusByte + 6] +
-                         (event[kEventCommandCompleteStatusByte + 7] << 8);
+  ASSERT_TRUE(complete_view.IsValid());
+  ASSERT_EQ(complete_view.GetStatus(), ::bluetooth::hci::ErrorCode::SUCCESS);
+  max_acl_data_packet_length = complete_view.GetAclDataPacketLength();
+  max_sco_data_packet_length = complete_view.GetSynchronousDataPacketLength();
+  max_acl_data_packets = complete_view.GetTotalNumAclDataPackets();
+  max_sco_data_packets = complete_view.GetTotalNumSynchronousDataPackets();
 
   ALOGD("%s: ACL max %d num %d SCO max %d num %d", __func__,
         static_cast<int>(max_acl_data_packet_length),
@@ -459,39 +455,39 @@
 
 // Enable flow control packets for SCO
 void BluetoothAidlTest::setSynchronousFlowControlEnable() {
-  std::vector<uint8_t> cmd{kCommandHciSynchronousFlowControlEnable,
-                           kCommandHciSynchronousFlowControlEnable +
-                               sizeof(kCommandHciSynchronousFlowControlEnable)};
+  std::vector<uint8_t> cmd;
+  ::bluetooth::packet::BitInserter bi{cmd};
+  ::bluetooth::hci::WriteSynchronousFlowControlEnableBuilder::Create(
+      ::bluetooth::hci::Enable::ENABLED)
+      ->Serialize(bi);
   hci->sendHciCommand(cmd);
 
-  wait_for_command_complete_event(cmd);
+  wait_and_validate_command_complete_event(
+      ::bluetooth::hci::OpCode::WRITE_SYNCHRONOUS_FLOW_CONTROL_ENABLE);
 }
 
 // Send an HCI command (in Loopback mode) and check the response.
 void BluetoothAidlTest::sendAndCheckHci(int num_packets) {
-  ThroughputLogger logger = {__func__};
-  int command_size = 0;
+  ThroughputLogger logger{__func__};
+  size_t command_size = 0;
+  char new_name[] = "John Jacob Jingleheimer Schmidt ___________________";
+  size_t new_name_length = strlen(new_name);
   for (int n = 0; n < num_packets; n++) {
-    // Send an HCI packet
-    std::vector<uint8_t> write_name{
-        kCommandHciWriteLocalName,
-        kCommandHciWriteLocalName + sizeof(kCommandHciWriteLocalName)};
-    // With a name
-    char new_name[] = "John Jacob Jingleheimer Schmidt ___________________0";
-    size_t new_name_length = strlen(new_name);
+    // The name to set is new_name
+    std::array<uint8_t, 248> name_array{};
     for (size_t i = 0; i < new_name_length; i++) {
-      write_name.push_back(static_cast<uint8_t>(new_name[i]));
+      name_array[i] = new_name[i];
     }
     // And the packet number
-    size_t i = new_name_length - 1;
-    for (int digits = n; digits > 0; digits = digits / 10, i--) {
-      write_name[i] = static_cast<uint8_t>('0' + digits % 10);
+    char number[11] = "0000000000";
+    snprintf(number, sizeof(number), "%010d", static_cast<int>(n));
+    for (size_t i = new_name_length; i < new_name_length + sizeof(number) - 1;
+         i++) {
+      name_array[new_name_length + i] = number[i];
     }
-    // And padding
-    for (size_t i = 0; i < 248 - new_name_length; i++) {
-      write_name.push_back(static_cast<uint8_t>(0));
-    }
-
+    std::vector<uint8_t> write_name;
+    ::bluetooth::packet::BitInserter bi{write_name};
+    ::bluetooth::hci::WriteLocalNameBuilder::Create(name_array)->Serialize(bi);
     hci->sendHciCommand(write_name);
 
     // Check the loopback of the HCI packet
@@ -499,28 +495,17 @@
 
     std::vector<uint8_t> event;
     ASSERT_TRUE(event_queue.pop(event));
-
-    size_t compare_length = (write_name.size() > static_cast<size_t>(0xff)
-                                 ? static_cast<size_t>(0xff)
-                                 : write_name.size());
-    ASSERT_GT(event.size(), compare_length + kEventFirstPayloadByte - 1);
-
-    ASSERT_EQ(kEventLoopbackCommand, event[kEventCodeByte]);
-    ASSERT_EQ(compare_length, event[kEventLengthByte]);
-
-    // Don't compare past the end of the event.
-    if (compare_length + kEventFirstPayloadByte > event.size()) {
-      compare_length = event.size() - kEventFirstPayloadByte;
-      ALOGE("Only comparing %d bytes", static_cast<int>(compare_length));
-    }
+    auto event_view = ::bluetooth::hci::LoopbackCommandView::Create(
+        ::bluetooth::hci::EventView::Create(::bluetooth::hci::PacketView<true>(
+            std::make_shared<std::vector<uint8_t>>(event))));
+    ASSERT_TRUE(event_view.IsValid());
+    std::vector<uint8_t> looped_back_command{event_view.GetPayload().begin(),
+                                             event_view.GetPayload().end()};
+    ASSERT_EQ(looped_back_command, write_name);
 
     if (n == num_packets - 1) {
       command_size = write_name.size();
     }
-
-    for (size_t i = 0; i < compare_length; i++) {
-      ASSERT_EQ(write_name[i], event[kEventFirstPayloadByte + i]);
-    }
   }
   logger.setTotalBytes(command_size * num_packets * 2);
 }
@@ -528,16 +513,18 @@
 // Send a SCO data packet (in Loopback mode) and check the response.
 void BluetoothAidlTest::sendAndCheckSco(int num_packets, size_t size,
                                         uint16_t handle) {
-  ThroughputLogger logger = {__func__};
+  ThroughputLogger logger{__func__};
   for (int n = 0; n < num_packets; n++) {
     // Send a SCO packet
     std::vector<uint8_t> sco_packet;
-    sco_packet.push_back(static_cast<uint8_t>(handle & 0xff));
-    sco_packet.push_back(static_cast<uint8_t>((handle & 0x0f00) >> 8));
-    sco_packet.push_back(static_cast<uint8_t>(size & 0xff));
+    std::vector<uint8_t> payload;
     for (size_t i = 0; i < size; i++) {
-      sco_packet.push_back(static_cast<uint8_t>(i + n));
+      payload.push_back(static_cast<uint8_t>(i + n));
     }
+    ::bluetooth::packet::BitInserter bi{sco_packet};
+    ::bluetooth::hci::ScoBuilder::Create(
+        handle, ::bluetooth::hci::PacketStatusFlag::CORRECTLY_RECEIVED, payload)
+        ->Serialize(bi);
     hci->sendScoData(sco_packet);
 
     // Check the loopback of the SCO packet
@@ -545,21 +532,7 @@
     ASSERT_TRUE(
         sco_queue.tryPopWithTimeout(sco_loopback, kWaitForScoDataTimeout));
 
-    ASSERT_EQ(sco_packet.size(), sco_loopback.size());
-    size_t successful_bytes = 0;
-
-    for (size_t i = 0; i < sco_packet.size(); i++) {
-      if (sco_packet[i] == sco_loopback[i]) {
-        successful_bytes = i;
-      } else {
-        ALOGE("Miscompare at %d (expected %x, got %x)", static_cast<int>(i),
-              sco_packet[i], sco_loopback[i]);
-        ALOGE("At %d (expected %x, got %x)", static_cast<int>(i + 1),
-              sco_packet[i + 1], sco_loopback[i + 1]);
-        break;
-      }
-    }
-    ASSERT_EQ(sco_packet.size(), successful_bytes + 1);
+    ASSERT_EQ(sco_packet, sco_loopback);
   }
   logger.setTotalBytes(num_packets * size * 2);
 }
@@ -567,19 +540,20 @@
 // Send an ACL data packet (in Loopback mode) and check the response.
 void BluetoothAidlTest::sendAndCheckAcl(int num_packets, size_t size,
                                         uint16_t handle) {
-  ThroughputLogger logger = {__func__};
+  ThroughputLogger logger{__func__};
   for (int n = 0; n < num_packets; n++) {
-    // Send an ACL packet
-    std::vector<uint8_t> acl_packet;
-    acl_packet.push_back(static_cast<uint8_t>(handle & 0xff));
-    acl_packet.push_back(static_cast<uint8_t>((handle & 0x0f00) >> 8) |
-                         kAclBroadcastPointToPoint |
-                         kAclPacketBoundaryFirstAutoFlushable);
-    acl_packet.push_back(static_cast<uint8_t>(size & 0xff));
-    acl_packet.push_back(static_cast<uint8_t>((size & 0xff00) >> 8));
+    // Send an ACL packet with counting data
+    auto payload = std::make_unique<::bluetooth::packet::RawBuilder>();
     for (size_t i = 0; i < size; i++) {
-      acl_packet.push_back(static_cast<uint8_t>(i + n));
+      payload->AddOctets1(static_cast<uint8_t>(i + n));
     }
+    std::vector<uint8_t> acl_packet;
+    ::bluetooth::packet::BitInserter bi{acl_packet};
+    ::bluetooth::hci::AclBuilder::Create(
+        handle,
+        ::bluetooth::hci::PacketBoundaryFlag::FIRST_AUTOMATICALLY_FLUSHABLE,
+        ::bluetooth::hci::BroadcastFlag::POINT_TO_POINT, std::move(payload))
+        ->Serialize(bi);
     hci->sendAclData(acl_packet);
 
     std::vector<uint8_t> acl_loopback;
@@ -587,21 +561,7 @@
     ASSERT_TRUE(
         acl_queue.tryPopWithTimeout(acl_loopback, kWaitForAclDataTimeout));
 
-    ASSERT_EQ(acl_packet.size(), acl_loopback.size());
-    size_t successful_bytes = 0;
-
-    for (size_t i = 0; i < acl_packet.size(); i++) {
-      if (acl_packet[i] == acl_loopback[i]) {
-        successful_bytes = i;
-      } else {
-        ALOGE("Miscompare at %d (expected %x, got %x)", static_cast<int>(i),
-              acl_packet[i], acl_loopback[i]);
-        ALOGE("At %d (expected %x, got %x)", static_cast<int>(i + 1),
-              acl_packet[i + 1], acl_loopback[i + 1]);
-        break;
-      }
-    }
-    ASSERT_EQ(acl_packet.size(), successful_bytes + 1);
+    ASSERT_EQ(acl_packet, acl_loopback);
   }
   logger.setTotalBytes(num_packets * size * 2);
 }
@@ -620,23 +580,29 @@
     }
     std::vector<uint8_t> event;
     EXPECT_TRUE(event_queue.pop(event));
-
-    EXPECT_EQ(kEventNumberOfCompletedPackets, event[kEventCodeByte]);
-    EXPECT_EQ(1, event[kEventNumberOfCompletedPacketsNumHandles]);
-
-    uint16_t event_handle = event[3] + (event[4] << 8);
-    EXPECT_EQ(handle, event_handle);
-
-    packets_processed += event[5] + (event[6] << 8);
+    auto event_view = ::bluetooth::hci::NumberOfCompletedPacketsView::Create(
+        ::bluetooth::hci::EventView::Create(::bluetooth::hci::PacketView<true>(
+            std::make_shared<std::vector<uint8_t>>(event))));
+    if (!event_view.IsValid()) {
+      ADD_FAILURE();
+      return packets_processed;
+    }
+    auto completed_packets = event_view.GetCompletedPackets();
+    for (const auto& entry : completed_packets) {
+      EXPECT_EQ(handle, entry.connection_handle_);
+      packets_processed += entry.host_num_of_completed_packets_;
+    }
   }
   return packets_processed;
 }
 
 // Send local loopback command and initialize SCO and ACL handles.
 void BluetoothAidlTest::enterLoopbackMode() {
-  std::vector<uint8_t> cmd{kCommandHciWriteLoopbackModeLocal,
-                           kCommandHciWriteLoopbackModeLocal +
-                               sizeof(kCommandHciWriteLoopbackModeLocal)};
+  std::vector<uint8_t> cmd;
+  ::bluetooth::packet::BitInserter bi{cmd};
+  ::bluetooth::hci::WriteLoopbackModeBuilder::Create(
+      bluetooth::hci::LoopbackMode::ENABLE_LOCAL)
+      ->Serialize(bi);
   hci->sendHciCommand(cmd);
 
   // Receive connection complete events with data channels
@@ -652,97 +618,128 @@
     }
     std::vector<uint8_t> event;
     ASSERT_TRUE(event_queue.pop(event));
-    ASSERT_GT(event.size(),
-              static_cast<size_t>(kEventCommandCompleteStatusByte));
-    if (event[kEventCodeByte] == kEventConnectionComplete) {
-      ASSERT_GT(event.size(),
-                static_cast<size_t>(kEventConnectionCompleteType));
-      ASSERT_EQ(event[kEventLengthByte], kEventConnectionCompleteParamLength);
-      uint8_t connection_type = event[kEventConnectionCompleteType];
+    auto event_view =
+        ::bluetooth::hci::EventView::Create(::bluetooth::hci::PacketView<true>(
+            std::make_shared<std::vector<uint8_t>>(event)));
+    ASSERT_TRUE(event_view.IsValid());
 
-      ASSERT_TRUE(connection_type == kEventConnectionCompleteTypeSco ||
-                  connection_type == kEventConnectionCompleteTypeAcl);
-
-      // Save handles
-      uint16_t handle = event[kEventConnectionCompleteHandleLsByte] |
-                        event[kEventConnectionCompleteHandleLsByte + 1] << 8;
-      if (connection_type == kEventConnectionCompleteTypeSco) {
-        sco_connection_handles.push_back(handle);
-      } else {
-        acl_connection_handles.push_back(handle);
+    if (event_view.GetEventCode() ==
+        ::bluetooth::hci::EventCode::CONNECTION_COMPLETE) {
+      auto complete_view =
+          ::bluetooth::hci::ConnectionCompleteView::Create(event_view);
+      ASSERT_TRUE(complete_view.IsValid());
+      switch (complete_view.GetLinkType()) {
+        case ::bluetooth::hci::LinkType::ACL:
+          acl_connection_handles.push_back(complete_view.GetConnectionHandle());
+          break;
+        case ::bluetooth::hci::LinkType::SCO:
+          sco_connection_handles.push_back(complete_view.GetConnectionHandle());
+          break;
+        default:
+          ASSERT_EQ(complete_view.GetLinkType(),
+                    ::bluetooth::hci::LinkType::ACL);
       }
-
-      ALOGD("Connect complete type = %d handle = %d",
-            event[kEventConnectionCompleteType], handle);
       connection_event_count++;
     } else {
-      ASSERT_EQ(kEventCommandComplete, event[kEventCodeByte]);
-      ASSERT_EQ(cmd[0], event[kEventCommandCompleteOpcodeLsByte]);
-      ASSERT_EQ(cmd[1], event[kEventCommandCompleteOpcodeLsByte + 1]);
-      ASSERT_EQ(kHciStatusSuccess, event[kEventCommandCompleteStatusByte]);
+      auto command_complete_view =
+          ::bluetooth::hci::WriteLoopbackModeCompleteView::Create(
+              ::bluetooth::hci::CommandCompleteView::Create(event_view));
+      ASSERT_TRUE(command_complete_view.IsValid());
+      ASSERT_EQ(::bluetooth::hci::ErrorCode::SUCCESS,
+                command_complete_view.GetStatus());
       command_complete_received = true;
     }
   }
 }
 
+void BluetoothAidlTest::send_and_wait_for_cmd_complete(
+    std::unique_ptr<CommandBuilder> cmd, std::vector<uint8_t>& cmd_complete) {
+  std::vector<uint8_t> cmd_bytes = cmd->SerializeToBytes();
+  hci->sendHciCommand(cmd_bytes);
+
+  auto view = CommandView::Create(
+      PacketView<true>(std::make_shared<std::vector<uint8_t>>(cmd_bytes)));
+  ASSERT_TRUE(view.IsValid());
+  ALOGI("Waiting for %s[0x%x]", OpCodeText(view.GetOpCode()).c_str(),
+        static_cast<int>(view.GetOpCode()));
+  ASSERT_NO_FATAL_FAILURE(
+      wait_for_command_complete_event(view.GetOpCode(), cmd_complete));
+}
+
 // Empty test: Initialize()/Close() are called in SetUp()/TearDown().
 TEST_P(BluetoothAidlTest, InitializeAndClose) {}
 
 // Send an HCI Reset with sendHciCommand and wait for a command complete event.
 TEST_P(BluetoothAidlTest, HciReset) {
-  std::vector<uint8_t> reset{kCommandHciReset,
-                             kCommandHciReset + sizeof(kCommandHciReset)};
+  std::vector<uint8_t> reset;
+  ::bluetooth::packet::BitInserter bi{reset};
+  ::bluetooth::hci::ResetBuilder::Create()->Serialize(bi);
   hci->sendHciCommand(reset);
 
-  wait_for_command_complete_event(reset);
+  wait_and_validate_command_complete_event(::bluetooth::hci::OpCode::RESET);
 }
 
 // Read and check the HCI version of the controller.
 TEST_P(BluetoothAidlTest, HciVersionTest) {
-  std::vector<uint8_t> cmd{kCommandHciReadLocalVersionInformation,
-                           kCommandHciReadLocalVersionInformation +
-                               sizeof(kCommandHciReadLocalVersionInformation)};
+  std::vector<uint8_t> cmd;
+  ::bluetooth::packet::BitInserter bi{cmd};
+  ::bluetooth::hci::ReadLocalVersionInformationBuilder::Create()->Serialize(bi);
   hci->sendHciCommand(cmd);
 
   ASSERT_NO_FATAL_FAILURE(wait_for_event());
 
   std::vector<uint8_t> event;
   ASSERT_TRUE(event_queue.pop(event));
-  ASSERT_GT(event.size(), static_cast<size_t>(kEventLocalLmpVersionByte));
-
-  ASSERT_EQ(kEventCommandComplete, event[kEventCodeByte]);
-  ASSERT_EQ(cmd[0], event[kEventCommandCompleteOpcodeLsByte]);
-  ASSERT_EQ(cmd[1], event[kEventCommandCompleteOpcodeLsByte + 1]);
-  ASSERT_EQ(kHciStatusSuccess, event[kEventCommandCompleteStatusByte]);
-
-  ASSERT_LE(kHciMinimumHciVersion, event[kEventLocalHciVersionByte]);
-  ASSERT_LE(kHciMinimumLmpVersion, event[kEventLocalLmpVersionByte]);
+  auto complete_view =
+      ::bluetooth::hci::ReadLocalVersionInformationCompleteView::Create(
+          ::bluetooth::hci::CommandCompleteView::Create(
+              ::bluetooth::hci::EventView::Create(
+                  ::bluetooth::hci::PacketView<true>(
+                      std::make_shared<std::vector<uint8_t>>(event)))));
+  ASSERT_TRUE(complete_view.IsValid());
+  ASSERT_EQ(::bluetooth::hci::ErrorCode::SUCCESS, complete_view.GetStatus());
+  auto version = complete_view.GetLocalVersionInformation();
+  ASSERT_LE(::bluetooth::hci::HciVersion::V_3_0, version.hci_version_);
+  ASSERT_LE(::bluetooth::hci::LmpVersion::V_3_0, version.lmp_version_);
 }
 
 // Send an unknown HCI command and wait for the error message.
 TEST_P(BluetoothAidlTest, HciUnknownCommand) {
-  std::vector<uint8_t> cmd{
-      kCommandHciShouldBeUnknown,
-      kCommandHciShouldBeUnknown + sizeof(kCommandHciShouldBeUnknown)};
+  std::vector<uint8_t> cmd;
+  ::bluetooth::packet::BitInserter bi{cmd};
+  ::bluetooth::hci::CommandBuilder::Create(
+      static_cast<::bluetooth::hci::OpCode>(0x3cff),
+      std::make_unique<::bluetooth::packet::RawBuilder>())
+      ->Serialize(bi);
   hci->sendHciCommand(cmd);
 
   ASSERT_NO_FATAL_FAILURE(wait_for_event());
 
   std::vector<uint8_t> event;
   ASSERT_TRUE(event_queue.pop(event));
+  auto event_view =
+      ::bluetooth::hci::EventView::Create(::bluetooth::hci::PacketView<true>(
+          std::make_shared<std::vector<uint8_t>>(event)));
+  ASSERT_TRUE(event_view.IsValid());
 
-  ASSERT_GT(event.size(), static_cast<size_t>(kEventCommandCompleteStatusByte));
-  if (event[kEventCodeByte] == kEventCommandComplete) {
-    ASSERT_EQ(cmd[0], event[kEventCommandCompleteOpcodeLsByte]);
-    ASSERT_EQ(cmd[1], event[kEventCommandCompleteOpcodeLsByte + 1]);
-    ASSERT_EQ(kHciStatusUnknownHciCommand,
-              event[kEventCommandCompleteStatusByte]);
-  } else {
-    ASSERT_EQ(kEventCommandStatus, event[kEventCodeByte]);
-    ASSERT_EQ(cmd[0], event[kEventCommandStatusOpcodeLsByte]);
-    ASSERT_EQ(cmd[1], event[kEventCommandStatusOpcodeLsByte + 1]);
-    ASSERT_EQ(kHciStatusUnknownHciCommand,
-              event[kEventCommandStatusStatusByte]);
+  switch (event_view.GetEventCode()) {
+    case ::bluetooth::hci::EventCode::COMMAND_COMPLETE: {
+      auto command_complete =
+          ::bluetooth::hci::CommandCompleteView::Create(event_view);
+      ASSERT_TRUE(command_complete.IsValid());
+      ASSERT_EQ(command_complete.GetPayload()[0],
+                static_cast<uint8_t>(
+                    ::bluetooth::hci::ErrorCode::UNKNOWN_HCI_COMMAND));
+    } break;
+    case ::bluetooth::hci::EventCode::COMMAND_STATUS: {
+      auto command_status =
+          ::bluetooth::hci::CommandStatusView::Create(event_view);
+      ASSERT_TRUE(command_status.IsValid());
+      ASSERT_EQ(command_status.GetStatus(),
+                ::bluetooth::hci::ErrorCode::UNKNOWN_HCI_COMMAND);
+    } break;
+    default:
+      ADD_FAILURE();
   }
 }
 
@@ -851,20 +848,24 @@
 
 // Set all bits in the event mask
 TEST_P(BluetoothAidlTest, SetEventMask) {
-  std::vector<uint8_t> set_event_mask{
-      0x01, 0x0c, 0x08 /*parameter bytes*/, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-      0xff, 0xff};
-  hci->sendHciCommand({set_event_mask});
-  wait_for_command_complete_event(set_event_mask);
+  std::vector<uint8_t> cmd;
+  ::bluetooth::packet::BitInserter bi{cmd};
+  uint64_t full_mask = UINT64_MAX;
+  ::bluetooth::hci::SetEventMaskBuilder::Create(full_mask)->Serialize(bi);
+  hci->sendHciCommand(cmd);
+  wait_and_validate_command_complete_event(
+      ::bluetooth::hci::OpCode::SET_EVENT_MASK);
 }
 
 // Set all bits in the LE event mask
 TEST_P(BluetoothAidlTest, SetLeEventMask) {
-  std::vector<uint8_t> set_event_mask{
-      0x20, 0x0c, 0x08 /*parameter bytes*/, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-      0xff, 0xff};
-  hci->sendHciCommand({set_event_mask});
-  wait_for_command_complete_event(set_event_mask);
+  std::vector<uint8_t> cmd;
+  ::bluetooth::packet::BitInserter bi{cmd};
+  uint64_t full_mask = UINT64_MAX;
+  ::bluetooth::hci::LeSetEventMaskBuilder::Create(full_mask)->Serialize(bi);
+  hci->sendHciCommand(cmd);
+  wait_and_validate_command_complete_event(
+      ::bluetooth::hci::OpCode::LE_SET_EVENT_MASK);
 }
 
 // Call initialize twice, second one should fail.
@@ -872,28 +873,32 @@
   class SecondCb
       : public aidl::android::hardware::bluetooth::BnBluetoothHciCallbacks {
    public:
-    ndk::ScopedAStatus initializationComplete(Status status) {
+    ndk::ScopedAStatus initializationComplete(Status status) override {
       EXPECT_EQ(status, Status::ALREADY_INITIALIZED);
       init_promise.set_value();
       return ScopedAStatus::ok();
     };
 
-    ndk::ScopedAStatus hciEventReceived(const std::vector<uint8_t>& /*event*/) {
+    ndk::ScopedAStatus hciEventReceived(
+        const std::vector<uint8_t>& /*event*/) override {
       ADD_FAILURE();
       return ScopedAStatus::ok();
     };
 
-    ndk::ScopedAStatus aclDataReceived(const std::vector<uint8_t>& /*data*/) {
+    ndk::ScopedAStatus aclDataReceived(
+        const std::vector<uint8_t>& /*data*/) override {
       ADD_FAILURE();
       return ScopedAStatus::ok();
     };
 
-    ndk::ScopedAStatus scoDataReceived(const std::vector<uint8_t>& /*data*/) {
+    ndk::ScopedAStatus scoDataReceived(
+        const std::vector<uint8_t>& /*data*/) override {
       ADD_FAILURE();
       return ScopedAStatus::ok();
     };
 
-    ndk::ScopedAStatus isoDataReceived(const std::vector<uint8_t>& /*data*/) {
+    ndk::ScopedAStatus isoDataReceived(
+        const std::vector<uint8_t>& /*data*/) override {
       ADD_FAILURE();
       return ScopedAStatus::ok();
     };
@@ -909,6 +914,66 @@
   ASSERT_EQ(status, std::future_status::ready);
 }
 
+TEST_P(BluetoothAidlTest, Cdd_C_12_1_Bluetooth5Requirements) {
+  std::vector<uint8_t> version_event;
+  send_and_wait_for_cmd_complete(ReadLocalVersionInformationBuilder::Create(),
+                                 version_event);
+  auto version_view = ReadLocalVersionInformationCompleteView::Create(
+      CommandCompleteView::Create(EventView::Create(PacketView<true>(
+          std::make_shared<std::vector<uint8_t>>(version_event)))));
+  ASSERT_TRUE(version_view.IsValid());
+  ASSERT_EQ(::bluetooth::hci::ErrorCode::SUCCESS, version_view.GetStatus());
+  auto version = version_view.GetLocalVersionInformation();
+  if (version.hci_version_ < ::bluetooth::hci::HciVersion::V_5_0) {
+    // This test does not apply to controllers below 5.0
+    return;
+  };
+  // When HCI version is 5.0, LMP version must also be at least 5.0
+  ASSERT_GE(static_cast<int>(version.lmp_version_),
+            static_cast<int>(version.hci_version_));
+
+  std::vector<uint8_t> le_features_event;
+  send_and_wait_for_cmd_complete(LeReadLocalSupportedFeaturesBuilder::Create(),
+                                 le_features_event);
+  auto le_features_view = LeReadLocalSupportedFeaturesCompleteView::Create(
+      CommandCompleteView::Create(EventView::Create(PacketView<true>(
+          std::make_shared<std::vector<uint8_t>>(le_features_event)))));
+  ASSERT_TRUE(le_features_view.IsValid());
+  ASSERT_EQ(::bluetooth::hci::ErrorCode::SUCCESS, le_features_view.GetStatus());
+  auto le_features = le_features_view.GetLeFeatures();
+  ASSERT_TRUE(le_features & static_cast<uint64_t>(LLFeaturesBits::LL_PRIVACY));
+  ASSERT_TRUE(le_features & static_cast<uint64_t>(LLFeaturesBits::LE_2M_PHY));
+  ASSERT_TRUE(le_features &
+              static_cast<uint64_t>(LLFeaturesBits::LE_CODED_PHY));
+  ASSERT_TRUE(le_features &
+              static_cast<uint64_t>(LLFeaturesBits::LE_EXTENDED_ADVERTISING));
+
+  std::vector<uint8_t> num_adv_set_event;
+  send_and_wait_for_cmd_complete(
+      LeReadNumberOfSupportedAdvertisingSetsBuilder::Create(),
+      num_adv_set_event);
+  auto num_adv_set_view =
+      LeReadNumberOfSupportedAdvertisingSetsCompleteView::Create(
+          CommandCompleteView::Create(EventView::Create(PacketView<true>(
+              std::make_shared<std::vector<uint8_t>>(num_adv_set_event)))));
+  ASSERT_TRUE(num_adv_set_view.IsValid());
+  ASSERT_EQ(::bluetooth::hci::ErrorCode::SUCCESS, num_adv_set_view.GetStatus());
+  auto num_adv_set = num_adv_set_view.GetNumberSupportedAdvertisingSets();
+  ASSERT_GE(num_adv_set, kMinLeAdvSetForBt5);
+
+  std::vector<uint8_t> num_resolving_list_event;
+  send_and_wait_for_cmd_complete(LeReadResolvingListSizeBuilder::Create(),
+                                 num_resolving_list_event);
+  auto num_resolving_list_view = LeReadResolvingListSizeCompleteView::Create(
+      CommandCompleteView::Create(EventView::Create(PacketView<true>(
+          std::make_shared<std::vector<uint8_t>>(num_resolving_list_event)))));
+  ASSERT_TRUE(num_resolving_list_view.IsValid());
+  ASSERT_EQ(::bluetooth::hci::ErrorCode::SUCCESS,
+            num_resolving_list_view.GetStatus());
+  auto num_resolving_list = num_resolving_list_view.GetResolvingListSize();
+  ASSERT_GE(num_resolving_list, kMinLeResolvingListForBt5);
+}
+
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(BluetoothAidlTest);
 INSTANTIATE_TEST_SUITE_P(PerInstance, BluetoothAidlTest,
                          testing::ValuesIn(android::getAidlHalInstanceNames(
diff --git a/gnss/aidl/vts/gnss_hal_test.cpp b/gnss/aidl/vts/gnss_hal_test.cpp
index 3907f57..64e51c7 100644
--- a/gnss/aidl/vts/gnss_hal_test.cpp
+++ b/gnss/aidl/vts/gnss_hal_test.cpp
@@ -447,6 +447,7 @@
                                               const int numMeasurementEvents,
                                               const int timeoutSeconds,
                                               std::vector<int>& deltasMs) {
+    callback->gnss_data_cbq_.reset();  // throw away the initial measurements if any
     int64_t lastElapsedRealtimeMillis = 0;
     for (int i = 0; i < numMeasurementEvents; i++) {
         GnssData lastGnssData;
diff --git a/identity/OWNERS b/identity/OWNERS
index 6969910..9353bbc 100644
--- a/identity/OWNERS
+++ b/identity/OWNERS
@@ -1,2 +1,4 @@
+# Bug component: 1084909
+
 swillden@google.com
 zeuthen@google.com
diff --git a/identity/aidl/vts/Android.bp b/identity/aidl/vts/Android.bp
index 5e303bb..6f7ab54 100644
--- a/identity/aidl/vts/Android.bp
+++ b/identity/aidl/vts/Android.bp
@@ -61,16 +61,3 @@
     ],
     require_root: true,
 }
-
-java_test_host {
-    name: "IdentityCredentialImplementedTest",
-    libs: [
-        "tradefed",
-        "vts-core-tradefed-harness",
-    ],
-    srcs: ["src/**/*.java"],
-    test_suites: [
-        "vts",
-    ],
-    test_config: "IdentityCredentialImplementedTest.xml",
-}
diff --git a/identity/aidl/vts/IdentityCredentialImplementedTest.xml b/identity/aidl/vts/IdentityCredentialImplementedTest.xml
deleted file mode 100644
index 4276ae6..0000000
--- a/identity/aidl/vts/IdentityCredentialImplementedTest.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2022 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.
--->
-<configuration description="Runs IdentityCredentialImplementedTest">
-  <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" />
-
-  <test class="com.android.tradefed.testtype.HostTest" >
-    <option name="jar" value="IdentityCredentialImplementedTest.jar" />
-  </test>
-</configuration>
diff --git a/identity/aidl/vts/src/com/android/tests/security/identity/IdentityCredentialImplementedTest.java b/identity/aidl/vts/src/com/android/tests/security/identity/IdentityCredentialImplementedTest.java
deleted file mode 100644
index 4936f8c..0000000
--- a/identity/aidl/vts/src/com/android/tests/security/identity/IdentityCredentialImplementedTest.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.tests.security.identity;
-
-import static org.junit.Assert.fail;
-import static org.junit.Assume.assumeTrue;
-
-import android.platform.test.annotations.RequiresDevice;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-// This is a host-test which executes shell commands on the device. It would be
-// nicer to have this be a Device test (like CTS) but this is currently not
-// possible, see https://source.android.com/docs/core/tests/vts
-
-@RunWith(DeviceJUnit4ClassRunner.class)
-public class IdentityCredentialImplementedTest extends BaseHostJUnit4Test {
-    // Returns the ro.vendor.api_level or 0 if not set.
-    //
-    // Throws NumberFormatException if ill-formatted.
-    //
-    // Throws DeviceNotAvailableException if device is not available.
-    //
-    private int getVendorApiLevel() throws NumberFormatException, DeviceNotAvailableException {
-        String vendorApiLevelString =
-                getDevice().executeShellCommand("getprop ro.vendor.api_level").trim();
-        if (vendorApiLevelString.isEmpty()) {
-            return 0;
-        }
-        return Integer.parseInt(vendorApiLevelString);
-    }
-
-    // As of Android 14 VSR (vendor API level 34), Identity Credential is required at feature
-    // version 202301 or later.
-    @RequiresDevice
-    @Test
-    public void testIdentityCredentialIsImplemented() throws Exception {
-        int vendorApiLevel = getVendorApiLevel();
-        assumeTrue(vendorApiLevel >= 34);
-
-        final String minimumFeatureVersionNeeded = "202301";
-
-        String result = getDevice().executeShellCommand(
-                "pm has-feature android.hardware.identity_credential "
-                + minimumFeatureVersionNeeded);
-        if (!result.trim().equals("true")) {
-            fail("Identity Credential feature version " + minimumFeatureVersionNeeded
-                    + " required but not found");
-        }
-    }
-}
diff --git a/security/keymint/aidl/vts/functional/KeyMintTest.cpp b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
index c45dd3f..63b2e73 100644
--- a/security/keymint/aidl/vts/functional/KeyMintTest.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
@@ -26,6 +26,7 @@
 #include <openssl/ec.h>
 #include <openssl/evp.h>
 #include <openssl/mem.h>
+#include <openssl/x509.h>
 #include <openssl/x509v3.h>
 
 #include <cutils/properties.h>
@@ -1059,6 +1060,42 @@
 }
 
 /*
+ * NewKeyGenerationTest.RsaWithSpecifiedValidity
+ *
+ * Verifies that KeyMint respects specified NOT_BEFORE and NOT_AFTER certificate dates.
+ */
+TEST_P(NewKeyGenerationTest, RsaWithSpecifiedValidity) {
+    vector<uint8_t> key_blob;
+    vector<KeyCharacteristics> key_characteristics;
+    ASSERT_EQ(ErrorCode::OK,
+              GenerateKey(AuthorizationSetBuilder()
+                                  .RsaSigningKey(2048, 65537)
+                                  .Digest(Digest::NONE)
+                                  .Padding(PaddingMode::NONE)
+                                  .Authorization(TAG_CERTIFICATE_NOT_BEFORE,
+                                                 1183806000000 /* 2007-07-07T11:00:00Z */)
+                                  .Authorization(TAG_CERTIFICATE_NOT_AFTER,
+                                                 1916049600000 /* 2030-09-19T12:00:00Z */),
+                          &key_blob, &key_characteristics));
+    ASSERT_GT(cert_chain_.size(), 0);
+
+    X509_Ptr cert(parse_cert_blob(cert_chain_[0].encodedCertificate));
+    ASSERT_TRUE(!!cert.get());
+
+    const ASN1_TIME* not_before = X509_get0_notBefore(cert.get());
+    ASSERT_NE(not_before, nullptr);
+    time_t not_before_time;
+    ASSERT_EQ(ASN1_TIME_to_time_t(not_before, &not_before_time), 1);
+    EXPECT_EQ(not_before_time, 1183806000);
+
+    const ASN1_TIME* not_after = X509_get0_notAfter(cert.get());
+    ASSERT_NE(not_after, nullptr);
+    time_t not_after_time;
+    ASSERT_EQ(ASN1_TIME_to_time_t(not_after, &not_after_time), 1);
+    EXPECT_EQ(not_after_time, 1916049600);
+}
+
+/*
  * NewKeyGenerationTest.RsaWithAttestation
  *
  * Verifies that keymint can generate all required RSA key sizes with attestation, and that the
diff --git a/security/keymint/support/remote_prov_utils.cpp b/security/keymint/support/remote_prov_utils.cpp
index 0c0af45..ffcaa95 100644
--- a/security/keymint/support/remote_prov_utils.cpp
+++ b/security/keymint/support/remote_prov_utils.cpp
@@ -467,16 +467,16 @@
         case 3:
             if (isTeeDeviceInfo(*parsed) && parsed->size() != kNumTeeDeviceInfoEntries) {
                 error += fmt::format(
-                        "Err: Incorrect number of device info entries. Expected {} but got"
+                        "Err: Incorrect number of device info entries. Expected {} but got "
                         "{}\n",
                         kNumTeeDeviceInfoEntries, parsed->size());
             }
             // TEE IRPC instances require all entries to be present in DeviceInfo. Non-TEE instances
             // may omit `os_version`
-            if (!isTeeDeviceInfo(*parsed) && (parsed->size() != kNumTeeDeviceInfoEntries ||
+            if (!isTeeDeviceInfo(*parsed) && (parsed->size() != kNumTeeDeviceInfoEntries &&
                                               parsed->size() != kNumTeeDeviceInfoEntries - 1)) {
                 error += fmt::format(
-                        "Err: Incorrect number of device info entries. Expected {} or {} but got"
+                        "Err: Incorrect number of device info entries. Expected {} or {} but got "
                         "{}\n",
                         kNumTeeDeviceInfoEntries - 1, kNumTeeDeviceInfoEntries, parsed->size());
             }
diff --git a/security/rkp/CHANGELOG.md b/security/rkp/CHANGELOG.md
index 9409a6d..f425284 100644
--- a/security/rkp/CHANGELOG.md
+++ b/security/rkp/CHANGELOG.md
@@ -31,7 +31,7 @@
 * IRemotelyProvisionedComponent
   * The need for an EEK has been removed. There is no longer an encrypted portion of the CSR.
   * Keys for new CSR format must be generated with test mode set to false, effectively removing test
-    mode in the new CSR flow. Old behavior is kept unchanged for backwards compatibility.
+    mode in the new CSR flow.
   * The schema for the CSR itself has been significantly simplified, please see
     IRemotelyProvisionedComponent.aidl for more details. Notably,
     * the chain of signing, MACing, and encryption operations has been replaced with a single
diff --git a/security/rkp/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl b/security/rkp/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
index 35b83dd..7960c7f 100644
--- a/security/rkp/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
+++ b/security/rkp/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
@@ -144,9 +144,9 @@
     byte[] generateEcdsaP256KeyPair(in boolean testMode, out MacedPublicKey macedPublicKey);
 
     /**
-     * This method can be removed in version 3 of the HAL. The header is kept around for
-     * backwards compatibility purposes. From v3, this method is allowed to raise a
-     * ServiceSpecificException with an error code of STATUS_REMOVED.
+     * This method has been deprecated since version 3 of the HAL. The header is kept around for
+     * backwards compatibility purposes. From v3, this method must raise a ServiceSpecificException
+     * with an error code of STATUS_REMOVED.
      *
      * For v1 and v2 implementations:
      * generateCertificateRequest creates a certificate request to be sent to the provisioning
diff --git a/security/rkp/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp b/security/rkp/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
index bf40976..9f68bfa 100644
--- a/security/rkp/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
+++ b/security/rkp/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
@@ -408,16 +408,8 @@
         ASSERT_FALSE(HasFatalFailure());
 
         if (rpcHardwareInfo.versionNumber >= VERSION_WITHOUT_TEST_MODE) {
-            bytevec keysToSignMac;
-            DeviceInfo deviceInfo;
-            ProtectedData protectedData;
-            auto status = provisionable_->generateCertificateRequest(
-                    false, {}, {}, {}, &deviceInfo, &protectedData, &keysToSignMac);
-            if (!status.isOk() && (status.getServiceSpecificError() ==
-                                   BnRemotelyProvisionedComponent::STATUS_REMOVED)) {
-                GTEST_SKIP() << "This test case applies to RKP v3+ only if "
-                             << "generateCertificateRequest() is implemented.";
-            }
+            GTEST_SKIP() << "This test case only applies to RKP v1 and v2. "
+                         << "RKP version discovered: " << rpcHardwareInfo.versionNumber;
         }
     }
 };
@@ -798,6 +790,20 @@
               BnRemotelyProvisionedComponent::STATUS_TEST_KEY_IN_PRODUCTION_REQUEST);
 }
 
+/**
+ * Call generateCertificateRequest(). Make sure it's removed.
+ */
+TEST_P(CertificateRequestV2Test, CertificateRequestV1Removed) {
+    bytevec keysToSignMac;
+    DeviceInfo deviceInfo;
+    ProtectedData protectedData;
+    auto status = provisionable_->generateCertificateRequest(
+            true /* testMode */, {} /* keysToSign */, {} /* EEK chain */, challenge_, &deviceInfo,
+            &protectedData, &keysToSignMac);
+    ASSERT_FALSE(status.isOk()) << status.getMessage();
+    EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_REMOVED);
+}
+
 void parse_root_of_trust(const vector<uint8_t>& attestation_cert,
                          vector<uint8_t>* verified_boot_key, VerifiedBoot* verified_boot_state,
                          bool* device_locked, vector<uint8_t>* verified_boot_hash) {
diff --git a/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorSessionAppConfigTlvTypes.aidl b/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorSessionAppConfigTlvTypes.aidl
index 8413f06..c3ac401 100644
--- a/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorSessionAppConfigTlvTypes.aidl
+++ b/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorSessionAppConfigTlvTypes.aidl
@@ -40,6 +40,7 @@
   CCC_UWB_CONFIG_ID = 164,
   CCC_PULSESHAPE_COMBO = 165,
   CCC_URSK_TTL = 166,
+  CCC_LAST_INDEX_USED = 168,
   NB_OF_RANGE_MEASUREMENTS = 227,
   NB_OF_AZIMUTH_MEASUREMENTS = 228,
   NB_OF_ELEVATION_MEASUREMENTS = 229,
diff --git a/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorSessionAppConfigTlvTypes.aidl b/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorSessionAppConfigTlvTypes.aidl
index f303ed9..65bb1c9 100644
--- a/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorSessionAppConfigTlvTypes.aidl
+++ b/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorSessionAppConfigTlvTypes.aidl
@@ -46,6 +46,8 @@
     CCC_PULSESHAPE_COMBO = 0xA5,
     /** 2 byte data */
     CCC_URSK_TTL = 0xA6,
+    /** 4 byte data */
+    CCC_LAST_INDEX_USED = 0xA8,
 
     /**
      * Range 0xE3 - 0xFF is reserved for proprietary use in the FIRA spec.