Merge "Revert^2 "Add PER_DISPLAY_MAX_BRIGHTNESS VHAL property."" into main
diff --git a/audio/aidl/android/hardware/audio/core/stream-out-async-sm.gv b/audio/aidl/android/hardware/audio/core/stream-out-async-sm.gv
index a3f0de9..56b7926 100644
--- a/audio/aidl/android/hardware/audio/core/stream-out-async-sm.gv
+++ b/audio/aidl/android/hardware/audio/core/stream-out-async-sm.gv
@@ -51,9 +51,7 @@
     DRAIN_PAUSED -> DRAINING [label="start"];         // consumer -> active
     DRAIN_PAUSED -> TRANSFER_PAUSED [label="burst"];  // producer -> active
     DRAIN_PAUSED -> IDLE [label="flush"];             // buffer is cleared
-    IDLE -> ERROR [label="←IStreamCallback.onError"];
-    DRAINING -> ERROR [label="←IStreamCallback.onError"];
-    TRANSFERRING -> ERROR [label="←IStreamCallback.onError"];
+    ANY_STATE -> ERROR [label="←IStreamCallback.onError"];
     ANY_STATE -> CLOSED [label="→IStream*.close"];
     CLOSED -> F;
 }
diff --git a/audio/aidl/default/audio_effects_config.xml b/audio/aidl/default/audio_effects_config.xml
index 9547865..c01eb3f 100644
--- a/audio/aidl/default/audio_effects_config.xml
+++ b/audio/aidl/default/audio_effects_config.xml
@@ -77,7 +77,6 @@
         <effect name="dynamics_processing" library="dynamics_processing" uuid="e0e6539b-1781-7261-676f-6d7573696340"/>
         <effect name="haptic_generator" library="haptic_generator" uuid="97c4acd1-8b82-4f2f-832e-c2fe5d7a9931"/>
         <effect name="loudness_enhancer" library="loudness_enhancer" uuid="fa415329-2034-4bea-b5dc-5b381c8d1e2c"/>
-        <effect name="env_reverb" library="env_reverbsw" uuid="fa819886-588b-11ed-9b6a-0242ac120002"/>
         <effect name="reverb_env_aux" library="reverb" uuid="4a387fc0-8ab3-11df-8bad-0002a5d5c51b"/>
         <effect name="reverb_env_ins" library="reverb" uuid="c7a511a0-a3bb-11df-860e-0002a5d5c51b"/>
         <effect name="reverb_pre_aux" library="reverb" uuid="f29a1400-a3bb-11df-8ddc-0002a5d5c51b"/>
diff --git a/audio/aidl/vts/Android.bp b/audio/aidl/vts/Android.bp
index b236831..cbd42c0 100644
--- a/audio/aidl/vts/Android.bp
+++ b/audio/aidl/vts/Android.bp
@@ -121,6 +121,9 @@
     name: "VtsHalEnvironmentalReverbTargetTest",
     defaults: ["VtsHalAudioEffectTargetTestDefaults"],
     srcs: ["VtsHalEnvironmentalReverbTargetTest.cpp"],
+    shared_libs: [
+        "libaudioutils",
+    ],
 }
 
 cc_test {
diff --git a/audio/aidl/vts/VtsHalBassBoostTargetTest.cpp b/audio/aidl/vts/VtsHalBassBoostTargetTest.cpp
index abc5a91..5ce2a20 100644
--- a/audio/aidl/vts/VtsHalBassBoostTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalBassBoostTargetTest.cpp
@@ -114,7 +114,7 @@
     }
 
     static constexpr int kSamplingFrequency = 44100;
-    static constexpr int kDurationMilliSec = 2000;
+    static constexpr int kDurationMilliSec = 720;
     static constexpr int kInputSize = kSamplingFrequency * kDurationMilliSec / 1000;
     long mInputFrameCount, mOutputFrameCount;
     std::shared_ptr<IFactory> mFactory;
@@ -231,7 +231,7 @@
         return gains[0] - gains[1];
     }
 
-    static constexpr int kNPointFFT = 32768;
+    static constexpr int kNPointFFT = 16384;
     static constexpr float kBinWidth = (float)kSamplingFrequency / kNPointFFT;
     std::set<int> mStrengthValues;
     int32_t mChannelLayout;
diff --git a/audio/aidl/vts/VtsHalEnvironmentalReverbTargetTest.cpp b/audio/aidl/vts/VtsHalEnvironmentalReverbTargetTest.cpp
index 93a3dcd..c7c6505 100644
--- a/audio/aidl/vts/VtsHalEnvironmentalReverbTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalEnvironmentalReverbTargetTest.cpp
@@ -16,28 +16,132 @@
 
 #define LOG_TAG "VtsHalEnvironmentalReverbTest"
 #include <android-base/logging.h>
+#include <audio_utils/power.h>
+#include <system/audio.h>
 
 #include "EffectHelper.h"
 
 using namespace android;
-
-using aidl::android::hardware::audio::effect::Descriptor;
-using aidl::android::hardware::audio::effect::EnvironmentalReverb;
-using aidl::android::hardware::audio::effect::getEffectTypeUuidEnvReverb;
-using aidl::android::hardware::audio::effect::IEffect;
-using aidl::android::hardware::audio::effect::IFactory;
-using aidl::android::hardware::audio::effect::Parameter;
+using namespace aidl::android::hardware::audio::effect;
+using aidl::android::hardware::audio::common::getChannelCount;
 using android::hardware::audio::common::testing::detail::TestExecutionTracer;
+using TagVectorPair = std::pair<EnvironmentalReverb::Tag, std::vector<int>>;
+using TagValuePair = std::pair<EnvironmentalReverb::Tag, int>;
 
+static constexpr int kMaxRoomLevel = 0;
+static constexpr int kMinRoomLevel = -6000;
+static constexpr int kMinRoomHfLevel = -4000;
+static constexpr int kMinDecayTime = 0;
+static constexpr int kMinHfRatio = 100;
+static constexpr int kMinLevel = -6000;
+static constexpr int kMinDensity = 0;
+static constexpr int kMinDiffusion = 0;
+static constexpr int kMinDelay = 0;
+
+static const std::vector<TagVectorPair> kParamsIncreasingVector = {
+
+        {EnvironmentalReverb::roomLevelMb, {-3500, -2800, -2100, -1400, -700, 0}},
+        {EnvironmentalReverb::roomHfLevelMb, {-4000, -3200, -2400, -1600, -800, 0}},
+        {EnvironmentalReverb::decayTimeMs, {800, 1600, 2400, 3200, 4000}},
+        {EnvironmentalReverb::decayHfRatioPm, {100, 600, 1100, 1600, 2000}},
+        {EnvironmentalReverb::levelMb, {-3500, -2800, -2100, -1400, -700, 0}},
+};
+
+static const std::vector<TagValuePair> kParamsMinimumValue = {
+        {EnvironmentalReverb::roomLevelMb, kMinRoomLevel},
+        {EnvironmentalReverb::decayTimeMs, kMinDecayTime},
+        {EnvironmentalReverb::levelMb, kMinLevel}};
+
+std::vector<std::pair<std::shared_ptr<IFactory>, Descriptor>> kDescPair;
+
+using Maker = std::set<int> (*)();
+static const std::array<Maker, static_cast<int>(EnvironmentalReverb::bypass) + 1>
+        kTestValueSetMaker = {
+                nullptr,
+                []() -> std::set<int> {
+                    return EffectHelper::getTestValueSet<EnvironmentalReverb, int,
+                                                         Range::environmentalReverb,
+                                                         EnvironmentalReverb::roomLevelMb>(
+                            kDescPair, EffectHelper::expandTestValueBasic<int>);
+                },
+                []() -> std::set<int> {
+                    return EffectHelper::getTestValueSet<EnvironmentalReverb, int,
+                                                         Range::environmentalReverb,
+                                                         EnvironmentalReverb::roomHfLevelMb>(
+                            kDescPair, EffectHelper::expandTestValueBasic<int>);
+                },
+                []() -> std::set<int> {
+                    return EffectHelper::getTestValueSet<EnvironmentalReverb, int,
+                                                         Range::environmentalReverb,
+                                                         EnvironmentalReverb::decayTimeMs>(
+                            kDescPair, EffectHelper::expandTestValueBasic<int>);
+                },
+                []() -> std::set<int> {
+                    return EffectHelper::getTestValueSet<EnvironmentalReverb, int,
+                                                         Range::environmentalReverb,
+                                                         EnvironmentalReverb::decayHfRatioPm>(
+                            kDescPair, EffectHelper::expandTestValueBasic<int>);
+                },
+                nullptr,
+                nullptr,
+                []() -> std::set<int> {
+                    return EffectHelper::getTestValueSet<EnvironmentalReverb, int,
+                                                         Range::environmentalReverb,
+                                                         EnvironmentalReverb::levelMb>(
+                            kDescPair, EffectHelper::expandTestValueBasic<int>);
+                },
+                []() -> std::set<int> {
+                    return EffectHelper::getTestValueSet<EnvironmentalReverb, int,
+                                                         Range::environmentalReverb,
+                                                         EnvironmentalReverb::delayMs>(
+                            kDescPair, EffectHelper::expandTestValueBasic<int>);
+                },
+                []() -> std::set<int> {
+                    return EffectHelper::getTestValueSet<EnvironmentalReverb, int,
+                                                         Range::environmentalReverb,
+                                                         EnvironmentalReverb::diffusionPm>(
+                            kDescPair, EffectHelper::expandTestValueBasic<int>);
+                },
+                []() -> std::set<int> {
+                    return EffectHelper::getTestValueSet<EnvironmentalReverb, int,
+                                                         Range::environmentalReverb,
+                                                         EnvironmentalReverb::densityPm>(
+                            kDescPair, EffectHelper::expandTestValueBasic<int>);
+                },
+                []() -> std::set<int> {
+                    return EffectHelper::getTestValueSet<EnvironmentalReverb, int,
+                                                         Range::environmentalReverb,
+                                                         EnvironmentalReverb::bypass>(
+                            kDescPair, EffectHelper::expandTestValueBasic<int>);
+                },
+};
+
+static std::vector<TagValuePair> buildSetAndGetTestParams() {
+    std::vector<TagValuePair> valueTag;
+    for (EnvironmentalReverb::Tag tag : ndk::enum_range<EnvironmentalReverb::Tag>()) {
+        std::set<int> values;
+        int intTag = static_cast<int>(tag);
+        if (intTag <= static_cast<int>(EnvironmentalReverb::bypass) &&
+            kTestValueSetMaker[intTag] != nullptr) {
+            values = kTestValueSetMaker[intTag]();
+        }
+
+        for (const auto& value : values) {
+            valueTag.push_back(std::make_pair(tag, value));
+        }
+    }
+
+    return valueTag;
+}
 /**
- * Here we focus on specific parameter checking, general IEffect interfaces testing performed in
- * VtsAudioEffectTargetTest.
- * Testing parameter range, assuming the parameter supported by effect is in this range.
- * This range is verified with IEffect.getDescriptor() and range defined in the documentation, for
- * any index supported value test expects EX_NONE from IEffect.setParameter(), otherwise expects
- * EX_ILLEGAL_ARGUMENT.
+ * Tests do the following:
+ * - Testing parameter range supported by the effect. Range is verified with IEffect.getDescriptor()
+ *   and range defined in the documentation.
+ * - Validating the effect by comparing the outputs of the supported parameters.
  */
 
+enum ParamName { DESCRIPTOR_INDEX, TAG_VALUE_PAIR };
+
 class EnvironmentalReverbHelper : public EffectHelper {
   public:
     EnvironmentalReverbHelper(std::pair<std::shared_ptr<IFactory>, Descriptor> pair) {
@@ -51,8 +155,7 @@
         Parameter::Specific specific = getDefaultParamSpecific();
         Parameter::Common common = createParamCommon(
                 0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */,
-                kInputFrameCount /* iFrameCount */, kOutputFrameCount /* oFrameCount */);
-        IEffect::OpenEffectReturn ret;
+                mFrameCount /* iFrameCount */, mFrameCount /* oFrameCount */);
         ASSERT_NO_FATAL_FAILURE(open(mEffect, common, specific, &ret, EX_NONE));
         ASSERT_NE(nullptr, mEffect);
     }
@@ -63,475 +166,291 @@
     }
 
     Parameter::Specific getDefaultParamSpecific() {
-        EnvironmentalReverb er = EnvironmentalReverb::make<EnvironmentalReverb::roomLevelMb>(-6000);
+        EnvironmentalReverb er =
+                EnvironmentalReverb::make<EnvironmentalReverb::roomLevelMb>(kMaxRoomLevel);
         Parameter::Specific specific =
                 Parameter::Specific::make<Parameter::Specific::environmentalReverb>(er);
         return specific;
     }
 
-    static const long kInputFrameCount = 0x100, kOutputFrameCount = 0x100;
-    std::shared_ptr<IFactory> mFactory;
-    std::shared_ptr<IEffect> mEffect;
-    Descriptor mDescriptor;
-    int mRoomLevel = -6000;
-    int mRoomHfLevel = 0;
-    int mDecayTime = 1000;
-    int mDecayHfRatio = 500;
-    int mLevel = -6000;
-    int mDelay = 40;
-    int mDiffusion = 1000;
-    int mDensity = 1000;
-    bool mBypass = false;
+    bool isParamValid(EnvironmentalReverb env) {
+        return isParameterValid<EnvironmentalReverb, Range::environmentalReverb>(env, mDescriptor);
+    }
 
-    void SetAndGetReverbParameters() {
-        for (auto& it : mTags) {
-            auto& tag = it.first;
-            auto& er = it.second;
+    Parameter createParam(EnvironmentalReverb env) {
+        return Parameter::make<Parameter::specific>(
+                Parameter::Specific::make<Parameter::Specific::environmentalReverb>(env));
+    }
 
-            // validate parameter
-            Descriptor desc;
-            ASSERT_STATUS(EX_NONE, mEffect->getDescriptor(&desc));
-            const bool valid = isParameterValid<EnvironmentalReverb, Range::environmentalReverb>(
-                    it.second, desc);
-            const binder_exception_t expected = valid ? EX_NONE : EX_ILLEGAL_ARGUMENT;
+    void setAndVerifyParam(binder_exception_t expected, EnvironmentalReverb env,
+                           EnvironmentalReverb::Tag tag) {
+        auto expectedParam = createParam(env);
 
-            // set
-            Parameter expectParam;
-            Parameter::Specific specific;
-            specific.set<Parameter::Specific::environmentalReverb>(er);
-            expectParam.set<Parameter::specific>(specific);
-            EXPECT_STATUS(expected, mEffect->setParameter(expectParam)) << expectParam.toString();
+        EXPECT_STATUS(expected, mEffect->setParameter(expectedParam)) << expectedParam.toString();
 
-            // only get if parameter in range and set success
-            if (expected == EX_NONE) {
-                Parameter getParam;
-                Parameter::Id id;
-                EnvironmentalReverb::Id erId;
-                erId.set<EnvironmentalReverb::Id::commonTag>(tag);
-                id.set<Parameter::Id::environmentalReverbTag>(erId);
-                // if set success, then get should match
-                EXPECT_STATUS(expected, mEffect->getParameter(id, &getParam));
-                EXPECT_EQ(expectParam, getParam);
-            }
+        if (expected == EX_NONE) {
+            auto erId = EnvironmentalReverb::Id::make<EnvironmentalReverb::Id::commonTag>(
+                    EnvironmentalReverb::Tag(tag));
+
+            auto id = Parameter::Id::make<Parameter::Id::environmentalReverbTag>(erId);
+
+            // get parameter
+            Parameter getParam;
+            EXPECT_STATUS(EX_NONE, mEffect->getParameter(id, &getParam));
+            EXPECT_EQ(expectedParam, getParam) << "\nexpectedParam:" << expectedParam.toString()
+                                               << "\ngetParam:" << getParam.toString();
         }
     }
 
-    void addRoomLevelParam() {
-        EnvironmentalReverb er;
-        er.set<EnvironmentalReverb::roomLevelMb>(mRoomLevel);
-        mTags.push_back({EnvironmentalReverb::roomLevelMb, er});
+    bool isAuxiliary() {
+        return mDescriptor.common.flags.type ==
+               aidl::android::hardware::audio::effect::Flags::Type::AUXILIARY;
     }
 
-    void addRoomHfLevelParam(int roomHfLevel) {
-        EnvironmentalReverb er;
-        er.set<EnvironmentalReverb::roomHfLevelMb>(roomHfLevel);
-        mTags.push_back({EnvironmentalReverb::roomHfLevelMb, er});
+    float computeOutputEnergy(const std::vector<float>& input, std::vector<float> output) {
+        if (!isAuxiliary()) {
+            // Extract auxiliary output
+            for (size_t i = 0; i < output.size(); i++) {
+                output[i] -= input[i];
+            }
+        }
+        return audio_utils_compute_energy_mono(output.data(), AUDIO_FORMAT_PCM_FLOAT,
+                                               output.size());
     }
 
-    void addDecayTimeParam(int decayTime) {
-        EnvironmentalReverb er;
-        er.set<EnvironmentalReverb::decayTimeMs>(decayTime);
-        mTags.push_back({EnvironmentalReverb::decayTimeMs, er});
+    void generateSineWaveInput(std::vector<float>& input) {
+        int frequency = 1000;
+        size_t kSamplingFrequency = 44100;
+        for (size_t i = 0; i < input.size(); i++) {
+            input[i] = sin(2 * M_PI * frequency * i / kSamplingFrequency);
+        }
+    }
+    using Maker = EnvironmentalReverb (*)(int);
+
+    static constexpr std::array<Maker, static_cast<int>(EnvironmentalReverb::bypass) + 1>
+            kEnvironmentalReverbParamMaker = {
+                    nullptr,
+                    [](int value) -> EnvironmentalReverb {
+                        return EnvironmentalReverb::make<EnvironmentalReverb::roomLevelMb>(value);
+                    },
+                    [](int value) -> EnvironmentalReverb {
+                        return EnvironmentalReverb::make<EnvironmentalReverb::roomHfLevelMb>(value);
+                    },
+                    [](int value) -> EnvironmentalReverb {
+                        return EnvironmentalReverb::make<EnvironmentalReverb::decayTimeMs>(value);
+                    },
+                    [](int value) -> EnvironmentalReverb {
+                        return EnvironmentalReverb::make<EnvironmentalReverb::decayHfRatioPm>(
+                                value);
+                    },
+                    nullptr,
+                    nullptr,
+                    [](int value) -> EnvironmentalReverb {
+                        return EnvironmentalReverb::make<EnvironmentalReverb::levelMb>(value);
+                    },
+                    [](int value) -> EnvironmentalReverb {
+                        return EnvironmentalReverb::make<EnvironmentalReverb::delayMs>(value);
+                    },
+                    [](int value) -> EnvironmentalReverb {
+                        return EnvironmentalReverb::make<EnvironmentalReverb::diffusionPm>(value);
+                    },
+                    [](int value) -> EnvironmentalReverb {
+                        return EnvironmentalReverb::make<EnvironmentalReverb::densityPm>(value);
+                    },
+                    [](int value) -> EnvironmentalReverb {
+                        return EnvironmentalReverb::make<EnvironmentalReverb::bypass>(value);
+                    }};
+
+    void createEnvParam(EnvironmentalReverb::Tag tag, int paramValue) {
+        int intTag = static_cast<int>(tag);
+        if (intTag <= static_cast<int>(EnvironmentalReverb::bypass) &&
+            kEnvironmentalReverbParamMaker[intTag] != NULL) {
+            mEnvParam = kEnvironmentalReverbParamMaker[intTag](paramValue);
+        } else {
+            GTEST_SKIP() << "Invalid parameter, skipping the test\n";
+        }
     }
 
-    void addDecayHfRatioParam(int decayHfRatio) {
-        EnvironmentalReverb er;
-        er.set<EnvironmentalReverb::decayHfRatioPm>(decayHfRatio);
-        mTags.push_back({EnvironmentalReverb::decayHfRatioPm, er});
+    void setParameterAndProcess(std::vector<float>& input, std::vector<float>& output, int val,
+                                EnvironmentalReverb::Tag tag) {
+        createEnvParam(tag, val);
+        if (isParamValid(mEnvParam)) {
+            ASSERT_NO_FATAL_FAILURE(setAndVerifyParam(EX_NONE, mEnvParam, tag));
+            ASSERT_NO_FATAL_FAILURE(processAndWriteToOutput(input, output, mEffect, &ret));
+        }
     }
 
-    void addLevelParam(int level) {
-        EnvironmentalReverb er;
-        er.set<EnvironmentalReverb::levelMb>(level);
-        mTags.push_back({EnvironmentalReverb::levelMb, er});
-    }
+    static constexpr int kSamplingFrequency = 44100;
+    static constexpr int kDurationMilliSec = 500;
+    static constexpr int kBufferSize = kSamplingFrequency * kDurationMilliSec / 1000;
 
-    void addDelayParam(int delay) {
-        EnvironmentalReverb er;
-        er.set<EnvironmentalReverb::delayMs>(delay);
-        mTags.push_back({EnvironmentalReverb::delayMs, er});
-    }
+    int mStereoChannelCount =
+            getChannelCount(AudioChannelLayout::make<AudioChannelLayout::layoutMask>(
+                    AudioChannelLayout::LAYOUT_STEREO));
+    int mFrameCount = kBufferSize / mStereoChannelCount;
 
-    void addDiffusionParam(int diffusion) {
-        EnvironmentalReverb er;
-        er.set<EnvironmentalReverb::diffusionPm>(diffusion);
-        mTags.push_back({EnvironmentalReverb::diffusionPm, er});
-    }
-
-    void addDensityParam(int density) {
-        EnvironmentalReverb er;
-        er.set<EnvironmentalReverb::densityPm>(density);
-        mTags.push_back({EnvironmentalReverb::densityPm, er});
-    }
-
-    void addBypassParam(bool bypass) {
-        EnvironmentalReverb er;
-        er.set<EnvironmentalReverb::bypass>(bypass);
-        mTags.push_back({EnvironmentalReverb::bypass, er});
-    }
-
-  private:
-    std::vector<std::pair<EnvironmentalReverb::Tag, EnvironmentalReverb>> mTags;
-    void CleanUp() { mTags.clear(); }
+    std::shared_ptr<IFactory> mFactory;
+    std::shared_ptr<IEffect> mEffect;
+    IEffect::OpenEffectReturn ret;
+    Descriptor mDescriptor;
+    EnvironmentalReverb mEnvParam;
 };
 
-class EnvironmentalReverbRoomLevelTest
+class EnvironmentalReverbParamTest
     : public ::testing::TestWithParam<
-              std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int>>,
+              std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, TagValuePair>>,
       public EnvironmentalReverbHelper {
   public:
-    EnvironmentalReverbRoomLevelTest() : EnvironmentalReverbHelper(std::get<0>(GetParam())) {
-        mRoomLevel = std::get<1>(GetParam());
+    EnvironmentalReverbParamTest()
+        : EnvironmentalReverbHelper(std::get<DESCRIPTOR_INDEX>(GetParam())) {
+        std::tie(mTag, mParamValue) = std::get<TAG_VALUE_PAIR>(GetParam());
     }
-
     void SetUp() override { SetUpReverb(); }
-
     void TearDown() override { TearDownReverb(); }
+
+    EnvironmentalReverb::Tag mTag;
+    int mParamValue;
 };
 
-TEST_P(EnvironmentalReverbRoomLevelTest, SetAndGetRoomLevel) {
-    EXPECT_NO_FATAL_FAILURE(addRoomLevelParam());
-    SetAndGetReverbParameters();
+TEST_P(EnvironmentalReverbParamTest, SetAndGetParameter) {
+    createEnvParam(mTag, mParamValue);
+    ASSERT_NO_FATAL_FAILURE(setAndVerifyParam(
+            isParamValid(mEnvParam) ? EX_NONE : EX_ILLEGAL_ARGUMENT, mEnvParam, mTag));
 }
 
-std::vector<std::pair<std::shared_ptr<IFactory>, Descriptor>> kDescPair;
-
 INSTANTIATE_TEST_SUITE_P(
-        EnvironmentalReverbTest, EnvironmentalReverbRoomLevelTest,
+        EnvironmentalReverbTest, EnvironmentalReverbParamTest,
         ::testing::Combine(
                 testing::ValuesIn(kDescPair = EffectFactoryHelper::getAllEffectDescriptors(
                                           IFactory::descriptor, getEffectTypeUuidEnvReverb())),
-                testing::ValuesIn(EffectHelper::getTestValueSet<EnvironmentalReverb, int,
-                                                                Range::environmentalReverb,
-                                                                EnvironmentalReverb::roomLevelMb>(
-                        kDescPair, EffectHelper::expandTestValueBasic<int>))),
-        [](const testing::TestParamInfo<EnvironmentalReverbRoomLevelTest::ParamType>& info) {
-            auto descriptor = std::get<0>(info.param).second;
-            std::string roomLevel = std::to_string(std::get<1>(info.param));
-
-            std::string name = getPrefix(descriptor) + "_roomLevel" + roomLevel;
+                testing::ValuesIn(buildSetAndGetTestParams())),
+        [](const testing::TestParamInfo<EnvironmentalReverbParamTest::ParamType>& info) {
+            auto descriptor = std::get<DESCRIPTOR_INDEX>(info.param).second;
+            auto tag = std::get<TAG_VALUE_PAIR>(info.param).first;
+            auto val = std::get<TAG_VALUE_PAIR>(info.param).second;
+            std::string name =
+                    getPrefix(descriptor) + "_Tag_" + toString(tag) + std::to_string(val);
             std::replace_if(
                     name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
             return name;
         });
-GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EnvironmentalReverbRoomLevelTest);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EnvironmentalReverbParamTest);
 
-class EnvironmentalReverbRoomHfLevelTest
+class EnvironmentalReverbDataTest
     : public ::testing::TestWithParam<
-              std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int>>,
+              std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, TagVectorPair>>,
       public EnvironmentalReverbHelper {
   public:
-    EnvironmentalReverbRoomHfLevelTest() : EnvironmentalReverbHelper(std::get<0>(GetParam())) {
-        mRoomHfLevel = std::get<1>(GetParam());
+    EnvironmentalReverbDataTest()
+        : EnvironmentalReverbHelper(std::get<DESCRIPTOR_INDEX>(GetParam())) {
+        std::tie(mTag, mParamValues) = std::get<TAG_VALUE_PAIR>(GetParam());
+        mInput.resize(kBufferSize);
+        generateSineWaveInput(mInput);
+    }
+    void SetUp() override { SetUpReverb(); }
+    void TearDown() override { TearDownReverb(); }
+
+    void assertEnergyIncreasingWithParameter(bool bypass) {
+        createEnvParam(EnvironmentalReverb::bypass, bypass);
+        ASSERT_NO_FATAL_FAILURE(setAndVerifyParam(EX_NONE, mEnvParam, EnvironmentalReverb::bypass));
+        float baseEnergy = 0;
+        for (int val : mParamValues) {
+            std::vector<float> output(kBufferSize);
+            setParameterAndProcess(mInput, output, val, mTag);
+            float energy = computeOutputEnergy(mInput, output);
+            ASSERT_GT(energy, baseEnergy);
+            baseEnergy = energy;
+        }
     }
 
-    void SetUp() override { SetUpReverb(); }
+    void assertZeroEnergyWithBypass(bool bypass) {
+        createEnvParam(EnvironmentalReverb::bypass, bypass);
+        ASSERT_NO_FATAL_FAILURE(setAndVerifyParam(EX_NONE, mEnvParam, EnvironmentalReverb::bypass));
+        for (int val : mParamValues) {
+            std::vector<float> output(kBufferSize);
+            setParameterAndProcess(mInput, output, val, mTag);
+            float energy = computeOutputEnergy(mInput, output);
+            ASSERT_EQ(energy, 0);
+        }
+    }
 
-    void TearDown() override { TearDownReverb(); }
+    EnvironmentalReverb::Tag mTag;
+    std::vector<int> mParamValues;
+    std::vector<float> mInput;
 };
 
-TEST_P(EnvironmentalReverbRoomHfLevelTest, SetAndGetRoomHfLevel) {
-    EXPECT_NO_FATAL_FAILURE(addRoomHfLevelParam(mRoomHfLevel));
-    SetAndGetReverbParameters();
+TEST_P(EnvironmentalReverbDataTest, IncreasingParamValue) {
+    assertEnergyIncreasingWithParameter(false);
+}
+
+TEST_P(EnvironmentalReverbDataTest, WithBypassEnabled) {
+    assertZeroEnergyWithBypass(true);
 }
 
 INSTANTIATE_TEST_SUITE_P(
-        EnvironmentalReverbTest, EnvironmentalReverbRoomHfLevelTest,
-        ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
-                                   IFactory::descriptor, getEffectTypeUuidEnvReverb())),
-                           testing::ValuesIn(EffectHelper::getTestValueSet<
-                                             EnvironmentalReverb, int, Range::environmentalReverb,
-                                             EnvironmentalReverb::roomHfLevelMb>(
-                                   kDescPair, EffectHelper::expandTestValueBasic<int>))),
-        [](const testing::TestParamInfo<EnvironmentalReverbRoomHfLevelTest::ParamType>& info) {
-            auto descriptor = std::get<0>(info.param).second;
-            std::string roomHfLevel = std::to_string(std::get<1>(info.param));
-
-            std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
-                               descriptor.common.name + "_UUID_" +
-                               toString(descriptor.common.id.uuid) + "_roomHfLevel" + roomHfLevel;
-            std::replace_if(
-                    name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
+        EnvironmentalReverbTest, EnvironmentalReverbDataTest,
+        ::testing::Combine(
+                testing::ValuesIn(kDescPair = EffectFactoryHelper::getAllEffectDescriptors(
+                                          IFactory::descriptor, getEffectTypeUuidEnvReverb())),
+                testing::ValuesIn(kParamsIncreasingVector)),
+        [](const testing::TestParamInfo<EnvironmentalReverbDataTest::ParamType>& info) {
+            auto descriptor = std::get<DESCRIPTOR_INDEX>(info.param).second;
+            auto tag = std::get<TAG_VALUE_PAIR>(info.param).first;
+            std::string name = getPrefix(descriptor) + "_Tag_" + toString(tag);
             return name;
         });
-GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EnvironmentalReverbRoomHfLevelTest);
 
-class EnvironmentalReverbDecayTimeTest
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EnvironmentalReverbDataTest);
+
+class EnvironmentalReverbMinimumParamTest
     : public ::testing::TestWithParam<
-              std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int>>,
+              std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, TagValuePair>>,
       public EnvironmentalReverbHelper {
   public:
-    EnvironmentalReverbDecayTimeTest() : EnvironmentalReverbHelper(std::get<0>(GetParam())) {
-        mDecayTime = std::get<1>(GetParam());
+    EnvironmentalReverbMinimumParamTest()
+        : EnvironmentalReverbHelper(std::get<DESCRIPTOR_INDEX>(GetParam())) {
+        std::tie(mTag, mValue) = std::get<TAG_VALUE_PAIR>(GetParam());
     }
-
-    void SetUp() override { SetUpReverb(); }
-
+    void SetUp() override {
+        SetUpReverb();
+        createEnvParam(EnvironmentalReverb::roomLevelMb, kMinRoomLevel);
+        ASSERT_NO_FATAL_FAILURE(
+                setAndVerifyParam(EX_NONE, mEnvParam, EnvironmentalReverb::roomLevelMb));
+    }
     void TearDown() override { TearDownReverb(); }
+
+    EnvironmentalReverb::Tag mTag;
+    int mValue;
 };
 
-TEST_P(EnvironmentalReverbDecayTimeTest, SetAndGetDecayTime) {
-    EXPECT_NO_FATAL_FAILURE(addDecayTimeParam(mDecayTime));
-    SetAndGetReverbParameters();
+TEST_P(EnvironmentalReverbMinimumParamTest, MinimumValueTest) {
+    std::vector<float> input(kBufferSize);
+    generateSineWaveInput(input);
+    std::vector<float> output(kBufferSize);
+    setParameterAndProcess(input, output, mValue, mTag);
+    float energy = computeOutputEnergy(input, output);
+    // No Auxiliary output for minimum param values
+    ASSERT_EQ(energy, 0);
 }
 
 INSTANTIATE_TEST_SUITE_P(
-        EnvironmentalReverbTest, EnvironmentalReverbDecayTimeTest,
-        ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
-                                   IFactory::descriptor, getEffectTypeUuidEnvReverb())),
-                           testing::ValuesIn(EffectHelper::getTestValueSet<
-                                             EnvironmentalReverb, int, Range::environmentalReverb,
-                                             EnvironmentalReverb::decayTimeMs>(
-                                   kDescPair, EffectHelper::expandTestValueBasic<int>))),
-        [](const testing::TestParamInfo<EnvironmentalReverbDecayTimeTest::ParamType>& info) {
-            auto descriptor = std::get<0>(info.param).second;
-            std::string decayTime = std::to_string(std::get<1>(info.param));
-
-            std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
-                               descriptor.common.name + "_UUID_" +
-                               toString(descriptor.common.id.uuid) + "_decayTime" + decayTime;
+        EnvironmentalReverbTest, EnvironmentalReverbMinimumParamTest,
+        ::testing::Combine(
+                testing::ValuesIn(kDescPair = EffectFactoryHelper::getAllEffectDescriptors(
+                                          IFactory::descriptor, getEffectTypeUuidEnvReverb())),
+                testing::ValuesIn(kParamsMinimumValue)),
+        [](const testing::TestParamInfo<EnvironmentalReverbMinimumParamTest::ParamType>& info) {
+            auto descriptor = std::get<DESCRIPTOR_INDEX>(info.param).second;
+            auto tag = std::get<TAG_VALUE_PAIR>(info.param).first;
+            auto val = std::get<TAG_VALUE_PAIR>(info.param).second;
+            std::string name =
+                    getPrefix(descriptor) + "_Tag_" + toString(tag) + std::to_string(val);
             std::replace_if(
                     name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
             return name;
         });
-GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EnvironmentalReverbDecayTimeTest);
 
-class EnvironmentalReverbDecayHfRatioTest
-    : public ::testing::TestWithParam<
-              std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int>>,
-      public EnvironmentalReverbHelper {
-  public:
-    EnvironmentalReverbDecayHfRatioTest() : EnvironmentalReverbHelper(std::get<0>(GetParam())) {
-        mDecayHfRatio = std::get<1>(GetParam());
-    }
-
-    void SetUp() override { SetUpReverb(); }
-
-    void TearDown() override { TearDownReverb(); }
-};
-
-TEST_P(EnvironmentalReverbDecayHfRatioTest, SetAndGetDecayHfRatio) {
-    EXPECT_NO_FATAL_FAILURE(addDecayHfRatioParam(mDecayHfRatio));
-    SetAndGetReverbParameters();
-}
-
-INSTANTIATE_TEST_SUITE_P(
-        EnvironmentalReverbTest, EnvironmentalReverbDecayHfRatioTest,
-        ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
-                                   IFactory::descriptor, getEffectTypeUuidEnvReverb())),
-                           testing::ValuesIn(EffectHelper::getTestValueSet<
-                                             EnvironmentalReverb, int, Range::environmentalReverb,
-                                             EnvironmentalReverb::decayHfRatioPm>(
-                                   kDescPair, EffectHelper::expandTestValueBasic<int>))),
-        [](const testing::TestParamInfo<EnvironmentalReverbDecayHfRatioTest::ParamType>& info) {
-            auto descriptor = std::get<0>(info.param).second;
-            std::string decayHfRatio = std::to_string(std::get<1>(info.param));
-
-            std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
-                               descriptor.common.name + "_UUID_" +
-                               toString(descriptor.common.id.uuid) + "_decayHfRatio" + decayHfRatio;
-            std::replace_if(
-                    name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
-            return name;
-        });
-GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EnvironmentalReverbDecayHfRatioTest);
-
-class EnvironmentalReverbLevelTest
-    : public ::testing::TestWithParam<
-              std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int>>,
-      public EnvironmentalReverbHelper {
-  public:
-    EnvironmentalReverbLevelTest() : EnvironmentalReverbHelper(std::get<0>(GetParam())) {
-        mLevel = std::get<1>(GetParam());
-    }
-
-    void SetUp() override { SetUpReverb(); }
-
-    void TearDown() override { TearDownReverb(); }
-};
-
-TEST_P(EnvironmentalReverbLevelTest, SetAndGetLevel) {
-    EXPECT_NO_FATAL_FAILURE(addLevelParam(mLevel));
-    SetAndGetReverbParameters();
-}
-
-INSTANTIATE_TEST_SUITE_P(
-        EnvironmentalReverbTest, EnvironmentalReverbLevelTest,
-        ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
-                                   IFactory::descriptor, getEffectTypeUuidEnvReverb())),
-                           testing::ValuesIn(EffectHelper::getTestValueSet<
-                                             EnvironmentalReverb, int, Range::environmentalReverb,
-                                             EnvironmentalReverb::levelMb>(
-                                   kDescPair, EffectHelper::expandTestValueBasic<int>))),
-        [](const testing::TestParamInfo<EnvironmentalReverbDecayHfRatioTest::ParamType>& info) {
-            auto descriptor = std::get<0>(info.param).second;
-            std::string level = std::to_string(std::get<1>(info.param));
-
-            std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
-                               descriptor.common.name + "_UUID_" +
-                               toString(descriptor.common.id.uuid) + "_level" + level;
-            std::replace_if(
-                    name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
-            return name;
-        });
-GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EnvironmentalReverbLevelTest);
-
-class EnvironmentalReverbDelayTest
-    : public ::testing::TestWithParam<
-              std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int>>,
-      public EnvironmentalReverbHelper {
-  public:
-    EnvironmentalReverbDelayTest() : EnvironmentalReverbHelper(std::get<0>(GetParam())) {
-        mDelay = std::get<1>(GetParam());
-    }
-
-    void SetUp() override { SetUpReverb(); }
-
-    void TearDown() override { TearDownReverb(); }
-};
-
-TEST_P(EnvironmentalReverbDelayTest, SetAndGetDelay) {
-    EXPECT_NO_FATAL_FAILURE(addDelayParam(mDelay));
-    SetAndGetReverbParameters();
-}
-
-INSTANTIATE_TEST_SUITE_P(
-        EnvironmentalReverbTest, EnvironmentalReverbDelayTest,
-        ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
-                                   IFactory::descriptor, getEffectTypeUuidEnvReverb())),
-                           testing::ValuesIn(EffectHelper::getTestValueSet<
-                                             EnvironmentalReverb, int, Range::environmentalReverb,
-                                             EnvironmentalReverb::delayMs>(
-                                   kDescPair, EffectHelper::expandTestValueBasic<int>))),
-        [](const testing::TestParamInfo<EnvironmentalReverbDelayTest::ParamType>& info) {
-            auto descriptor = std::get<0>(info.param).second;
-            std::string delay = std::to_string(std::get<1>(info.param));
-
-            std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
-                               descriptor.common.name + "_UUID_" +
-                               toString(descriptor.common.id.uuid) + "_delay" + delay;
-            std::replace_if(
-                    name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
-            return name;
-        });
-GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EnvironmentalReverbDelayTest);
-
-class EnvironmentalReverbDiffusionTest
-    : public ::testing::TestWithParam<
-              std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int>>,
-      public EnvironmentalReverbHelper {
-  public:
-    EnvironmentalReverbDiffusionTest() : EnvironmentalReverbHelper(std::get<0>(GetParam())) {
-        mDiffusion = std::get<1>(GetParam());
-    }
-
-    void SetUp() override { SetUpReverb(); }
-
-    void TearDown() override { TearDownReverb(); }
-};
-
-TEST_P(EnvironmentalReverbDiffusionTest, SetAndGetDiffusion) {
-    EXPECT_NO_FATAL_FAILURE(addDiffusionParam(mDiffusion));
-    SetAndGetReverbParameters();
-}
-
-INSTANTIATE_TEST_SUITE_P(
-        EnvironmentalReverbTest, EnvironmentalReverbDiffusionTest,
-        ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
-                                   IFactory::descriptor, getEffectTypeUuidEnvReverb())),
-                           testing::ValuesIn(EffectHelper::getTestValueSet<
-                                             EnvironmentalReverb, int, Range::environmentalReverb,
-                                             EnvironmentalReverb::diffusionPm>(
-                                   kDescPair, EffectHelper::expandTestValueBasic<int>))),
-        [](const testing::TestParamInfo<EnvironmentalReverbDiffusionTest::ParamType>& info) {
-            auto descriptor = std::get<0>(info.param).second;
-            std::string diffusion = std::to_string(std::get<1>(info.param));
-
-            std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
-                               descriptor.common.name + "_UUID_" +
-                               toString(descriptor.common.id.uuid) + "_diffusion" + diffusion;
-            std::replace_if(
-                    name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
-            return name;
-        });
-GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EnvironmentalReverbDiffusionTest);
-
-class EnvironmentalReverbDensityTest
-    : public ::testing::TestWithParam<
-              std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int>>,
-      public EnvironmentalReverbHelper {
-  public:
-    EnvironmentalReverbDensityTest() : EnvironmentalReverbHelper(std::get<0>(GetParam())) {
-        mDensity = std::get<1>(GetParam());
-    }
-
-    void SetUp() override { SetUpReverb(); }
-
-    void TearDown() override { TearDownReverb(); }
-};
-
-TEST_P(EnvironmentalReverbDensityTest, SetAndGetDensity) {
-    EXPECT_NO_FATAL_FAILURE(addDensityParam(mDensity));
-    SetAndGetReverbParameters();
-}
-
-INSTANTIATE_TEST_SUITE_P(
-        EnvironmentalReverbTest, EnvironmentalReverbDensityTest,
-        ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
-                                   IFactory::descriptor, getEffectTypeUuidEnvReverb())),
-                           testing::ValuesIn(EffectHelper::getTestValueSet<
-                                             EnvironmentalReverb, int, Range::environmentalReverb,
-                                             EnvironmentalReverb::densityPm>(
-                                   kDescPair, EffectHelper::expandTestValueBasic<int>))),
-        [](const testing::TestParamInfo<EnvironmentalReverbDensityTest::ParamType>& info) {
-            auto descriptor = std::get<0>(info.param).second;
-            std::string density = std::to_string(std::get<1>(info.param));
-
-            std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
-                               descriptor.common.name + "_UUID_" +
-                               toString(descriptor.common.id.uuid) + "_density" + density;
-            std::replace_if(
-                    name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
-            return name;
-        });
-GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EnvironmentalReverbDensityTest);
-
-class EnvironmentalReverbBypassTest
-    : public ::testing::TestWithParam<
-              std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, bool>>,
-      public EnvironmentalReverbHelper {
-  public:
-    EnvironmentalReverbBypassTest() : EnvironmentalReverbHelper(std::get<0>(GetParam())) {
-        mBypass = std::get<1>(GetParam());
-    }
-
-    void SetUp() override { SetUpReverb(); }
-
-    void TearDown() override { TearDownReverb(); }
-};
-
-TEST_P(EnvironmentalReverbBypassTest, SetAndGetBypass) {
-    EXPECT_NO_FATAL_FAILURE(addBypassParam(mBypass));
-    SetAndGetReverbParameters();
-}
-
-INSTANTIATE_TEST_SUITE_P(
-        EnvironmentalReverbTest, EnvironmentalReverbBypassTest,
-        ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
-                                   IFactory::descriptor, getEffectTypeUuidEnvReverb())),
-                           testing::Bool()),
-        [](const testing::TestParamInfo<EnvironmentalReverbBypassTest::ParamType>& info) {
-            auto descriptor = std::get<0>(info.param).second;
-            std::string bypass = std::to_string(std::get<1>(info.param));
-
-            std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
-                               descriptor.common.name + "_UUID_" +
-                               toString(descriptor.common.id.uuid) + "_bypass" + bypass;
-            std::replace_if(
-                    name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
-            return name;
-        });
-GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EnvironmentalReverbBypassTest);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EnvironmentalReverbMinimumParamTest);
 
 int main(int argc, char** argv) {
     ::testing::InitGoogleTest(&argc, argv);
diff --git a/audio/aidl/vts/VtsHalPresetReverbTargetTest.cpp b/audio/aidl/vts/VtsHalPresetReverbTargetTest.cpp
index 2229ff8..542f0d8 100644
--- a/audio/aidl/vts/VtsHalPresetReverbTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalPresetReverbTargetTest.cpp
@@ -82,7 +82,7 @@
     }
 
     static constexpr int kSamplingFrequency = 44100;
-    static constexpr int kDurationMilliSec = 2000;
+    static constexpr int kDurationMilliSec = 500;
     static constexpr int kBufferSize = kSamplingFrequency * kDurationMilliSec / 1000;
     int mStereoChannelCount =
             getChannelCount(AudioChannelLayout::make<AudioChannelLayout::layoutMask>(
diff --git a/audio/aidl/vts/VtsHalVirtualizerTargetTest.cpp b/audio/aidl/vts/VtsHalVirtualizerTargetTest.cpp
index f121f7c..b449f3c 100644
--- a/audio/aidl/vts/VtsHalVirtualizerTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalVirtualizerTargetTest.cpp
@@ -96,7 +96,7 @@
 
     static constexpr int kSamplingFrequency = 44100;
     static constexpr int kDefaultChannelLayout = AudioChannelLayout::LAYOUT_STEREO;
-    static constexpr int kDurationMilliSec = 2000;
+    static constexpr int kDurationMilliSec = 720;
     static constexpr int kBufferSize = kSamplingFrequency * kDurationMilliSec / 1000;
     int kChannelCount = getChannelCount(
             AudioChannelLayout::make<AudioChannelLayout::layoutMask>(kDefaultChannelLayout));
diff --git a/audio/aidl/vts/VtsHalVolumeTargetTest.cpp b/audio/aidl/vts/VtsHalVolumeTargetTest.cpp
index 4115eca..2c21d2e 100644
--- a/audio/aidl/vts/VtsHalVolumeTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalVolumeTargetTest.cpp
@@ -94,7 +94,7 @@
     }
 
     static constexpr int kSamplingFrequency = 44100;
-    static constexpr int kDurationMilliSec = 2000;
+    static constexpr int kDurationMilliSec = 720;
     static constexpr int kBufferSize = kSamplingFrequency * kDurationMilliSec / 1000;
     static constexpr int kMinLevel = -96;
     static constexpr int kDefaultChannelLayout = AudioChannelLayout::LAYOUT_STEREO;
@@ -180,7 +180,7 @@
     const int kVsrApiLevel;
     static constexpr int kMaxAudioSample = 1;
     static constexpr int kTransitionDuration = 300;
-    static constexpr int kNPointFFT = 32768;
+    static constexpr int kNPointFFT = 16384;
     static constexpr float kBinWidth = (float)kSamplingFrequency / kNPointFFT;
     static constexpr size_t offset = kSamplingFrequency * kTransitionDuration / 1000;
     static constexpr float kBaseLevel = 0;
diff --git a/automotive/can/1.0/default/Android.bp b/automotive/can/1.0/default/Android.bp
index 05691d9..0a68fbc 100644
--- a/automotive/can/1.0/default/Android.bp
+++ b/automotive/can/1.0/default/Android.bp
@@ -55,7 +55,6 @@
     ],
     static_libs: [
         "android.hardware.automotive.can@libnetdevice",
-        "android.hardware.automotive@libc++fs",
         "libnl++",
     ],
     vintf_fragments: ["manifest_android.hardware.automotive.can@1.0.xml"],
diff --git a/automotive/can/1.0/default/CanBus.h b/automotive/can/1.0/default/CanBus.h
index 8b73258..977bfcc 100644
--- a/automotive/can/1.0/default/CanBus.h
+++ b/automotive/can/1.0/default/CanBus.h
@@ -24,6 +24,7 @@
 #include <utils/Mutex.h>
 
 #include <atomic>
+#include <mutex>
 #include <thread>
 
 namespace android::hardware::automotive::can::V1_0::implementation {
diff --git a/automotive/can/1.0/default/CanController.cpp b/automotive/can/1.0/default/CanController.cpp
index 1b5bf5b..4a7ab7e 100644
--- a/automotive/can/1.0/default/CanController.cpp
+++ b/automotive/can/1.0/default/CanController.cpp
@@ -23,7 +23,7 @@
 #include <android-base/logging.h>
 #include <android/hidl/manager/1.2/IServiceManager.h>
 
-#include <automotive/filesystem>
+#include <filesystem>
 #include <fstream>
 #include <regex>
 
@@ -31,7 +31,7 @@
 
 using IfId = ICanController::BusConfig::InterfaceId;
 using IfIdDisc = ICanController::BusConfig::InterfaceId::hidl_discriminator;
-namespace fs = android::hardware::automotive::filesystem;
+namespace fs = ::std::filesystem;
 
 namespace fsErrors {
 static const std::error_code ok;
diff --git a/automotive/can/1.0/default/libc++fs/.clang-format b/automotive/can/1.0/default/libc++fs/.clang-format
deleted file mode 100644
index dd59681..0000000
--- a/automotive/can/1.0/default/libc++fs/.clang-format
+++ /dev/null
@@ -1,13 +0,0 @@
-BasedOnStyle: LLVM
-
----
-Language: Cpp
-Standard: Cpp03
-
-AlwaysBreakTemplateDeclarations: true
-PointerAlignment: Left
-
-# Disable formatting options which may break tests.
-SortIncludes: false
-ReflowComments: false
----
diff --git a/automotive/can/1.0/default/libc++fs/Android.bp b/automotive/can/1.0/default/libc++fs/Android.bp
deleted file mode 100644
index 0641991..0000000
--- a/automotive/can/1.0/default/libc++fs/Android.bp
+++ /dev/null
@@ -1,70 +0,0 @@
-//
-// Copyright (C) 2020 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.
-//
-
-// TODO(152067309): Stop building this yourself once it's ABI stable and has
-// been made vendor available. Just use libc++fs instead of this.
-
-package {
-    // See: http://go/android-license-faq
-    // A large-scale-change added 'default_applicable_licenses' to import
-    // all of the 'license_kinds' from "hardware_interfaces_license"
-    // to get the below license kinds:
-    //   SPDX-license-identifier-NCSA
-    default_applicable_licenses: ["hardware_interfaces_license"],
-}
-
-cc_defaults {
-    name: "android.hardware.automotive@libc++fsdefaults",
-    local_include_dirs: ["include"],
-    export_include_dirs: ["include"],
-    cflags: [
-        "-Wall",
-        "-Werror",
-        "-Wno-unused-parameter",
-    ],
-    cppflags: [
-        "-std=c++17",
-        "-fexceptions",
-        "-DLIBCXX_BUILDING_LIBCXXABI",
-        "-D_LIBCPP_BUILDING_LIBRARY",
-    ],
-    rtti: true,
-}
-
-cc_library_static {
-    name: "android.hardware.automotive@libc++fs",
-    recovery_available: true,
-    vendor: true,
-    defaults: ["android.hardware.automotive@libc++fsdefaults"],
-    srcs: [
-        "src/filesystem/directory_iterator.cpp",
-        "src/filesystem/operations.cpp",
-    ],
-    multilib: {
-        lib32: {
-            // off_t usage is constrained to within the libc++ source (not the
-            // headers), so we can build the filesystem library with a 64-bit
-            // off_t on LP32 to get large file support without needing all users
-            // of the library to match.
-            cflags: ["-D_FILE_OFFSET_BITS=64"],
-        },
-    },
-    target: {
-        windows: {
-            enabled: false,
-        },
-    },
-}
diff --git a/automotive/can/1.0/default/libc++fs/include/automotive/filesystem b/automotive/can/1.0/default/libc++fs/include/automotive/filesystem
deleted file mode 100644
index bd3dda5..0000000
--- a/automotive/can/1.0/default/libc++fs/include/automotive/filesystem
+++ /dev/null
@@ -1,2713 +0,0 @@
-// -*- C++ -*-
-//===--------------------------- filesystem -------------------------------===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef _LIBAUTO_FILESYSTEM
-#define _LIBAUTO_FILESYSTEM
-
-// TODO(152067309): Remove this once the libc++ upgrade is complete.
-#include <__config>
-#if defined(_LIBCPP_VERSION) && _LIBCPP_VERSION > 8000
-
-#include <filesystem>
-namespace android::hardware::automotive {
-namespace filesystem = std::filesystem;
-}
-
-#else
-
-/*
-    filesystem synopsis
-
-    namespace android::hardware::automotive { namespace filesystem {
-
-    class path;
-
-    void swap(path& lhs, path& rhs) noexcept;
-    size_t hash_value(const path& p) noexcept;
-
-    bool operator==(const path& lhs, const path& rhs) noexcept;
-    bool operator!=(const path& lhs, const path& rhs) noexcept;
-    bool operator< (const path& lhs, const path& rhs) noexcept;
-    bool operator<=(const path& lhs, const path& rhs) noexcept;
-    bool operator> (const path& lhs, const path& rhs) noexcept;
-    bool operator>=(const path& lhs, const path& rhs) noexcept;
-
-    path operator/ (const path& lhs, const path& rhs);
-
-    // fs.path.io operators are friends of path.
-    template <class charT, class traits>
-    friend basic_ostream<charT, traits>&
-    operator<<(basic_ostream<charT, traits>& os, const path& p);
-
-    template <class charT, class traits>
-    friend basic_istream<charT, traits>&
-    operator>>(basic_istream<charT, traits>& is, path& p);
-
-    template <class Source>
-      path u8path(const Source& source);
-    template <class InputIterator>
-      path u8path(InputIterator first, InputIterator last);
-
-    class filesystem_error;
-    class directory_entry;
-
-    class directory_iterator;
-
-    // enable directory_iterator range-based for statements
-    directory_iterator begin(directory_iterator iter) noexcept;
-    directory_iterator end(const directory_iterator&) noexcept;
-
-    class recursive_directory_iterator;
-
-    // enable recursive_directory_iterator range-based for statements
-    recursive_directory_iterator begin(recursive_directory_iterator iter) noexcept;
-    recursive_directory_iterator end(const recursive_directory_iterator&) noexcept;
-
-    class file_status;
-
-    struct space_info
-    {
-      uintmax_t capacity;
-      uintmax_t free;
-      uintmax_t available;
-    };
-
-    enum class file_type;
-    enum class perms;
-    enum class perm_options;
-    enum class copy_options;
-    enum class directory_options;
-
-    typedef chrono::time_point<trivial-clock>  file_time_type;
-
-    // operational functions
-
-    path absolute(const path& p);
-    path absolute(const path& p, error_code &ec);
-
-    path canonical(const path& p);
-    path canonical(const path& p, error_code& ec);
-
-    void copy(const path& from, const path& to);
-    void copy(const path& from, const path& to, error_code& ec);
-    void copy(const path& from, const path& to, copy_options options);
-    void copy(const path& from, const path& to, copy_options options,
-                   error_code& ec);
-
-    bool copy_file(const path& from, const path& to);
-    bool copy_file(const path& from, const path& to, error_code& ec);
-    bool copy_file(const path& from, const path& to, copy_options option);
-    bool copy_file(const path& from, const path& to, copy_options option,
-                           error_code& ec);
-
-    void copy_symlink(const path& existing_symlink, const path& new_symlink);
-    void copy_symlink(const path& existing_symlink, const path& new_symlink,
-                              error_code& ec) noexcept;
-
-    bool create_directories(const path& p);
-    bool create_directories(const path& p, error_code& ec);
-
-    bool create_directory(const path& p);
-    bool create_directory(const path& p, error_code& ec) noexcept;
-
-    bool create_directory(const path& p, const path& attributes);
-    bool create_directory(const path& p, const path& attributes,
-                                  error_code& ec) noexcept;
-
-    void create_directory_symlink(const path& to, const path& new_symlink);
-    void create_directory_symlink(const path& to, const path& new_symlink,
-                                          error_code& ec) noexcept;
-
-    void create_hard_link(const path& to, const path& new_hard_link);
-    void create_hard_link(const path& to, const path& new_hard_link,
-                                  error_code& ec) noexcept;
-
-    void create_symlink(const path& to, const path& new_symlink);
-    void create_symlink(const path& to, const path& new_symlink,
-                                error_code& ec) noexcept;
-
-    path current_path();
-    path current_path(error_code& ec);
-    void current_path(const path& p);
-    void current_path(const path& p, error_code& ec) noexcept;
-
-    bool exists(file_status s) noexcept;
-    bool exists(const path& p);
-    bool exists(const path& p, error_code& ec) noexcept;
-
-    bool equivalent(const path& p1, const path& p2);
-    bool equivalent(const path& p1, const path& p2, error_code& ec) noexcept;
-
-    uintmax_t    file_size(const path& p);
-    uintmax_t    file_size(const path& p, error_code& ec) noexcept;
-
-    uintmax_t    hard_link_count(const path& p);
-    uintmax_t    hard_link_count(const path& p, error_code& ec) noexcept;
-
-    bool is_block_file(file_status s) noexcept;
-    bool is_block_file(const path& p);
-    bool is_block_file(const path& p, error_code& ec) noexcept;
-
-    bool is_character_file(file_status s) noexcept;
-    bool is_character_file(const path& p);
-    bool is_character_file(const path& p, error_code& ec) noexcept;
-
-    bool is_directory(file_status s) noexcept;
-    bool is_directory(const path& p);
-    bool is_directory(const path& p, error_code& ec) noexcept;
-
-    bool is_empty(const path& p);
-    bool is_empty(const path& p, error_code& ec) noexcept;
-
-    bool is_fifo(file_status s) noexcept;
-    bool is_fifo(const path& p);
-    bool is_fifo(const path& p, error_code& ec) noexcept;
-
-    bool is_other(file_status s) noexcept;
-    bool is_other(const path& p);
-    bool is_other(const path& p, error_code& ec) noexcept;
-
-    bool is_regular_file(file_status s) noexcept;
-    bool is_regular_file(const path& p);
-    bool is_regular_file(const path& p, error_code& ec) noexcept;
-
-    bool is_socket(file_status s) noexcept;
-    bool is_socket(const path& p);
-    bool is_socket(const path& p, error_code& ec) noexcept;
-
-    bool is_symlink(file_status s) noexcept;
-    bool is_symlink(const path& p);
-    bool is_symlink(const path& p, error_code& ec) noexcept;
-
-    file_time_type  last_write_time(const path& p);
-    file_time_type  last_write_time(const path& p, error_code& ec) noexcept;
-    void last_write_time(const path& p, file_time_type new_time);
-    void last_write_time(const path& p, file_time_type new_time,
-                                 error_code& ec) noexcept;
-
-    void permissions(const path& p, perms prms,
-                     perm_options opts=perm_options::replace);
-    void permissions(const path& p, perms prms, error_code& ec) noexcept;
-    void permissions(const path& p, perms prms, perm_options opts,
-                     error_code& ec);
-
-    path proximate(const path& p, error_code& ec);
-    path proximate(const path& p, const path& base = current_path());
-    path proximate(const path& p, const path& base, error_code &ec);
-
-    path read_symlink(const path& p);
-    path read_symlink(const path& p, error_code& ec);
-
-    path relative(const path& p, error_code& ec);
-    path relative(const path& p, const path& base=current_path());
-    path relative(const path& p, const path& base, error_code& ec);
-
-    bool remove(const path& p);
-    bool remove(const path& p, error_code& ec) noexcept;
-
-    uintmax_t    remove_all(const path& p);
-    uintmax_t    remove_all(const path& p, error_code& ec);
-
-    void rename(const path& from, const path& to);
-    void rename(const path& from, const path& to, error_code& ec) noexcept;
-
-    void resize_file(const path& p, uintmax_t size);
-    void resize_file(const path& p, uintmax_t size, error_code& ec) noexcept;
-
-    space_info   space(const path& p);
-    space_info   space(const path& p, error_code& ec) noexcept;
-
-    file_status  status(const path& p);
-    file_status  status(const path& p, error_code& ec) noexcept;
-
-    bool status_known(file_status s) noexcept;
-
-    file_status  symlink_status(const path& p);
-    file_status  symlink_status(const path& p, error_code& ec) noexcept;
-
-    path temp_directory_path();
-    path temp_directory_path(error_code& ec);
-
-    path weakly_canonical(path const& p);
-    path weakly_canonical(path const& p, error_code& ec);
-
-
-} }  // namespace android::hardware::automotive::filesystem
-
-*/
-
-#include <__config>
-#include <cstddef>
-#include <cstdlib>
-#include <chrono>
-#include <iterator>
-#include <iosfwd>
-#include <locale>
-#include <memory>
-#include <stack>
-#include <string>
-#include <system_error>
-#include <utility>
-#include <iomanip> // for quoted
-#include <string_view>
-#include <version>
-
-#include <__debug>
-
-#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
-#pragma GCC system_header
-#endif
-
-_LIBCPP_PUSH_MACROS
-#include <__undef_macros>
-
-#ifndef _LIBCPP_CXX03_LANG
-
-namespace android::hardware::automotive::filesystem {
-using namespace std;
-using namespace std::chrono;
-
-using std::basic_string;
-using std::enable_if;
-using std::error_code;
-using std::false_type;
-
-#ifndef _VSTD
-#define _LIBAUTO_UNDEF_VSTD
-#define _VSTD std
-#endif
-
-#ifdef _VSTD_FS
-#pragma push_macro("_VSTD_FS")
-#else
-#define _LIBAUTO_UNDEF_VSTD_FS
-#endif
-#define _VSTD_FS android::hardware::automotive::filesystem
-
-/* Begin copy of _FilesystemClock from include/chrono */
-struct _FilesystemClock {
-#if !defined(_LIBCPP_HAS_NO_INT128)
-  typedef __int128_t rep;
-  typedef nano period;
-#else
-  typedef long long rep;
-  typedef nano period;
-#endif
-
-  typedef chrono::duration<rep, period> duration;
-  typedef chrono::time_point<_FilesystemClock> time_point;
-
-  static _LIBCPP_CONSTEXPR_AFTER_CXX11 const bool is_steady = false;
-
-  _LIBCPP_FUNC_VIS static time_point now() noexcept;
-
-  _LIBCPP_INLINE_VISIBILITY
-  static time_t to_time_t(const time_point& __t) noexcept {
-      typedef chrono::duration<rep> __secs;
-      return time_t(
-          chrono::duration_cast<__secs>(__t.time_since_epoch()).count());
-  }
-
-  _LIBCPP_INLINE_VISIBILITY
-  static time_point from_time_t(time_t __t) noexcept {
-      typedef chrono::duration<rep> __secs;
-      return time_point(__secs(__t));
-  }
-};
-/* End copy of _FilesystemClock from include/chrono */
-
-typedef chrono::time_point<_FilesystemClock> file_time_type;
-
-struct _LIBCPP_TYPE_VIS space_info {
-  uintmax_t capacity;
-  uintmax_t free;
-  uintmax_t available;
-};
-
-enum class _LIBCPP_ENUM_VIS file_type : signed char {
-  none = 0,
-  not_found = -1,
-  regular = 1,
-  directory = 2,
-  symlink = 3,
-  block = 4,
-  character = 5,
-  fifo = 6,
-  socket = 7,
-  unknown = 8
-};
-
-enum class _LIBCPP_ENUM_VIS perms : unsigned {
-  none = 0,
-
-  owner_read = 0400,
-  owner_write = 0200,
-  owner_exec = 0100,
-  owner_all = 0700,
-
-  group_read = 040,
-  group_write = 020,
-  group_exec = 010,
-  group_all = 070,
-
-  others_read = 04,
-  others_write = 02,
-  others_exec = 01,
-  others_all = 07,
-
-  all = 0777,
-
-  set_uid = 04000,
-  set_gid = 02000,
-  sticky_bit = 01000,
-  mask = 07777,
-  unknown = 0xFFFF,
-};
-
-_LIBCPP_INLINE_VISIBILITY
-inline constexpr perms operator&(perms _LHS, perms _RHS) {
-  return static_cast<perms>(static_cast<unsigned>(_LHS) &
-                            static_cast<unsigned>(_RHS));
-}
-
-_LIBCPP_INLINE_VISIBILITY
-inline constexpr perms operator|(perms _LHS, perms _RHS) {
-  return static_cast<perms>(static_cast<unsigned>(_LHS) |
-                            static_cast<unsigned>(_RHS));
-}
-
-_LIBCPP_INLINE_VISIBILITY
-inline constexpr perms operator^(perms _LHS, perms _RHS) {
-  return static_cast<perms>(static_cast<unsigned>(_LHS) ^
-                            static_cast<unsigned>(_RHS));
-}
-
-_LIBCPP_INLINE_VISIBILITY
-inline constexpr perms operator~(perms _LHS) {
-  return static_cast<perms>(~static_cast<unsigned>(_LHS));
-}
-
-_LIBCPP_INLINE_VISIBILITY
-inline perms& operator&=(perms& _LHS, perms _RHS) { return _LHS = _LHS & _RHS; }
-
-_LIBCPP_INLINE_VISIBILITY
-inline perms& operator|=(perms& _LHS, perms _RHS) { return _LHS = _LHS | _RHS; }
-
-_LIBCPP_INLINE_VISIBILITY
-inline perms& operator^=(perms& _LHS, perms _RHS) { return _LHS = _LHS ^ _RHS; }
-
-enum class _LIBCPP_ENUM_VIS perm_options : unsigned char {
-  replace = 1,
-  add = 2,
-  remove = 4,
-  nofollow = 8
-};
-
-_LIBCPP_INLINE_VISIBILITY
-inline constexpr perm_options operator&(perm_options _LHS, perm_options _RHS) {
-  return static_cast<perm_options>(static_cast<unsigned>(_LHS) &
-                                   static_cast<unsigned>(_RHS));
-}
-
-_LIBCPP_INLINE_VISIBILITY
-inline constexpr perm_options operator|(perm_options _LHS, perm_options _RHS) {
-  return static_cast<perm_options>(static_cast<unsigned>(_LHS) |
-                                   static_cast<unsigned>(_RHS));
-}
-
-_LIBCPP_INLINE_VISIBILITY
-inline constexpr perm_options operator^(perm_options _LHS, perm_options _RHS) {
-  return static_cast<perm_options>(static_cast<unsigned>(_LHS) ^
-                                   static_cast<unsigned>(_RHS));
-}
-
-_LIBCPP_INLINE_VISIBILITY
-inline constexpr perm_options operator~(perm_options _LHS) {
-  return static_cast<perm_options>(~static_cast<unsigned>(_LHS));
-}
-
-_LIBCPP_INLINE_VISIBILITY
-inline perm_options& operator&=(perm_options& _LHS, perm_options _RHS) {
-  return _LHS = _LHS & _RHS;
-}
-
-_LIBCPP_INLINE_VISIBILITY
-inline perm_options& operator|=(perm_options& _LHS, perm_options _RHS) {
-  return _LHS = _LHS | _RHS;
-}
-
-_LIBCPP_INLINE_VISIBILITY
-inline perm_options& operator^=(perm_options& _LHS, perm_options _RHS) {
-  return _LHS = _LHS ^ _RHS;
-}
-
-enum class _LIBCPP_ENUM_VIS copy_options : unsigned short {
-  none = 0,
-  skip_existing = 1,
-  overwrite_existing = 2,
-  update_existing = 4,
-  recursive = 8,
-  copy_symlinks = 16,
-  skip_symlinks = 32,
-  directories_only = 64,
-  create_symlinks = 128,
-  create_hard_links = 256,
-  __in_recursive_copy = 512,
-};
-
-_LIBCPP_INLINE_VISIBILITY
-inline constexpr copy_options operator&(copy_options _LHS, copy_options _RHS) {
-  return static_cast<copy_options>(static_cast<unsigned short>(_LHS) &
-                                   static_cast<unsigned short>(_RHS));
-}
-
-_LIBCPP_INLINE_VISIBILITY
-inline constexpr copy_options operator|(copy_options _LHS, copy_options _RHS) {
-  return static_cast<copy_options>(static_cast<unsigned short>(_LHS) |
-                                   static_cast<unsigned short>(_RHS));
-}
-
-_LIBCPP_INLINE_VISIBILITY
-inline constexpr copy_options operator^(copy_options _LHS, copy_options _RHS) {
-  return static_cast<copy_options>(static_cast<unsigned short>(_LHS) ^
-                                   static_cast<unsigned short>(_RHS));
-}
-
-_LIBCPP_INLINE_VISIBILITY
-inline constexpr copy_options operator~(copy_options _LHS) {
-  return static_cast<copy_options>(~static_cast<unsigned short>(_LHS));
-}
-
-_LIBCPP_INLINE_VISIBILITY
-inline copy_options& operator&=(copy_options& _LHS, copy_options _RHS) {
-  return _LHS = _LHS & _RHS;
-}
-
-_LIBCPP_INLINE_VISIBILITY
-inline copy_options& operator|=(copy_options& _LHS, copy_options _RHS) {
-  return _LHS = _LHS | _RHS;
-}
-
-_LIBCPP_INLINE_VISIBILITY
-inline copy_options& operator^=(copy_options& _LHS, copy_options _RHS) {
-  return _LHS = _LHS ^ _RHS;
-}
-
-enum class _LIBCPP_ENUM_VIS directory_options : unsigned char {
-  none = 0,
-  follow_directory_symlink = 1,
-  skip_permission_denied = 2
-};
-
-_LIBCPP_INLINE_VISIBILITY
-inline constexpr directory_options operator&(directory_options _LHS,
-                                             directory_options _RHS) {
-  return static_cast<directory_options>(static_cast<unsigned char>(_LHS) &
-                                        static_cast<unsigned char>(_RHS));
-}
-
-_LIBCPP_INLINE_VISIBILITY
-inline constexpr directory_options operator|(directory_options _LHS,
-                                             directory_options _RHS) {
-  return static_cast<directory_options>(static_cast<unsigned char>(_LHS) |
-                                        static_cast<unsigned char>(_RHS));
-}
-
-_LIBCPP_INLINE_VISIBILITY
-inline constexpr directory_options operator^(directory_options _LHS,
-                                             directory_options _RHS) {
-  return static_cast<directory_options>(static_cast<unsigned char>(_LHS) ^
-                                        static_cast<unsigned char>(_RHS));
-}
-
-_LIBCPP_INLINE_VISIBILITY
-inline constexpr directory_options operator~(directory_options _LHS) {
-  return static_cast<directory_options>(~static_cast<unsigned char>(_LHS));
-}
-
-_LIBCPP_INLINE_VISIBILITY
-inline directory_options& operator&=(directory_options& _LHS,
-                                     directory_options _RHS) {
-  return _LHS = _LHS & _RHS;
-}
-
-_LIBCPP_INLINE_VISIBILITY
-inline directory_options& operator|=(directory_options& _LHS,
-                                     directory_options _RHS) {
-  return _LHS = _LHS | _RHS;
-}
-
-_LIBCPP_INLINE_VISIBILITY
-inline directory_options& operator^=(directory_options& _LHS,
-                                     directory_options _RHS) {
-  return _LHS = _LHS ^ _RHS;
-}
-
-class _LIBCPP_TYPE_VIS file_status {
-public:
-  // constructors
-  _LIBCPP_INLINE_VISIBILITY
-  file_status() noexcept : file_status(file_type::none) {}
-  _LIBCPP_INLINE_VISIBILITY
-  explicit file_status(file_type __ft, perms __prms = perms::unknown) noexcept
-      : __ft_(__ft),
-        __prms_(__prms) {}
-
-  file_status(const file_status&) noexcept = default;
-  file_status(file_status&&) noexcept = default;
-
-  _LIBCPP_INLINE_VISIBILITY
-  ~file_status() {}
-
-  file_status& operator=(const file_status&) noexcept = default;
-  file_status& operator=(file_status&&) noexcept = default;
-
-  // observers
-  _LIBCPP_INLINE_VISIBILITY
-  file_type type() const noexcept { return __ft_; }
-
-  _LIBCPP_INLINE_VISIBILITY
-  perms permissions() const noexcept { return __prms_; }
-
-  // modifiers
-  _LIBCPP_INLINE_VISIBILITY
-  void type(file_type __ft) noexcept { __ft_ = __ft; }
-
-  _LIBCPP_INLINE_VISIBILITY
-  void permissions(perms __p) noexcept { __prms_ = __p; }
-
-private:
-  file_type __ft_;
-  perms __prms_;
-};
-
-class _LIBCPP_TYPE_VIS directory_entry;
-
-template <class _Tp>
-struct __can_convert_char {
-  static const bool value = false;
-};
-template <class _Tp>
-struct __can_convert_char<const _Tp> : public __can_convert_char<_Tp> {};
-template <>
-struct __can_convert_char<char> {
-  static const bool value = true;
-  using __char_type = char;
-};
-template <>
-struct __can_convert_char<wchar_t> {
-  static const bool value = true;
-  using __char_type = wchar_t;
-};
-template <>
-struct __can_convert_char<char16_t> {
-  static const bool value = true;
-  using __char_type = char16_t;
-};
-template <>
-struct __can_convert_char<char32_t> {
-  static const bool value = true;
-  using __char_type = char32_t;
-};
-
-template <class _ECharT>
-typename enable_if<__can_convert_char<_ECharT>::value, bool>::type
-__is_separator(_ECharT __e) {
-  return __e == _ECharT('/');
-}
-
-struct _NullSentinal {};
-
-template <class _Tp>
-using _Void = void;
-
-template <class _Tp, class = void>
-struct __is_pathable_string : public false_type {};
-
-template <class _ECharT, class _Traits, class _Alloc>
-struct __is_pathable_string<
-    basic_string<_ECharT, _Traits, _Alloc>,
-    _Void<typename __can_convert_char<_ECharT>::__char_type> >
-    : public __can_convert_char<_ECharT> {
-  using _Str = basic_string<_ECharT, _Traits, _Alloc>;
-  using _Base = __can_convert_char<_ECharT>;
-  static _ECharT const* __range_begin(_Str const& __s) { return __s.data(); }
-  static _ECharT const* __range_end(_Str const& __s) {
-    return __s.data() + __s.length();
-  }
-  static _ECharT __first_or_null(_Str const& __s) {
-    return __s.empty() ? _ECharT{} : __s[0];
-  }
-};
-
-template <class _ECharT, class _Traits>
-struct __is_pathable_string<
-    basic_string_view<_ECharT, _Traits>,
-    _Void<typename __can_convert_char<_ECharT>::__char_type> >
-    : public __can_convert_char<_ECharT> {
-  using _Str = basic_string_view<_ECharT, _Traits>;
-  using _Base = __can_convert_char<_ECharT>;
-  static _ECharT const* __range_begin(_Str const& __s) { return __s.data(); }
-  static _ECharT const* __range_end(_Str const& __s) {
-    return __s.data() + __s.length();
-  }
-  static _ECharT __first_or_null(_Str const& __s) {
-    return __s.empty() ? _ECharT{} : __s[0];
-  }
-};
-
-template <class _Source, class _DS = typename decay<_Source>::type,
-          class _UnqualPtrType =
-              typename remove_const<typename remove_pointer<_DS>::type>::type,
-          bool _IsCharPtr = is_pointer<_DS>::value&&
-              __can_convert_char<_UnqualPtrType>::value>
-struct __is_pathable_char_array : false_type {};
-
-template <class _Source, class _ECharT, class _UPtr>
-struct __is_pathable_char_array<_Source, _ECharT*, _UPtr, true>
-    : __can_convert_char<typename remove_const<_ECharT>::type> {
-  using _Base = __can_convert_char<typename remove_const<_ECharT>::type>;
-
-  static _ECharT const* __range_begin(const _ECharT* __b) { return __b; }
-  static _ECharT const* __range_end(const _ECharT* __b) {
-    using _Iter = const _ECharT*;
-    const _ECharT __sentinal = _ECharT{};
-    _Iter __e = __b;
-    for (; *__e != __sentinal; ++__e)
-      ;
-    return __e;
-  }
-
-  static _ECharT __first_or_null(const _ECharT* __b) { return *__b; }
-};
-
-template <class _Iter, bool _IsIt = __is_input_iterator<_Iter>::value,
-          class = void>
-struct __is_pathable_iter : false_type {};
-
-template <class _Iter>
-struct __is_pathable_iter<
-    _Iter, true,
-    _Void<typename __can_convert_char<
-        typename iterator_traits<_Iter>::value_type>::__char_type> >
-    : __can_convert_char<typename iterator_traits<_Iter>::value_type> {
-  using _ECharT = typename iterator_traits<_Iter>::value_type;
-  using _Base = __can_convert_char<_ECharT>;
-
-  static _Iter __range_begin(_Iter __b) { return __b; }
-  static _NullSentinal __range_end(_Iter) { return _NullSentinal{}; }
-
-  static _ECharT __first_or_null(_Iter __b) { return *__b; }
-};
-
-template <class _Tp, bool _IsStringT = __is_pathable_string<_Tp>::value,
-          bool _IsCharIterT = __is_pathable_char_array<_Tp>::value,
-          bool _IsIterT = !_IsCharIterT && __is_pathable_iter<_Tp>::value>
-struct __is_pathable : false_type {
-  static_assert(!_IsStringT && !_IsCharIterT && !_IsIterT, "Must all be false");
-};
-
-template <class _Tp>
-struct __is_pathable<_Tp, true, false, false> : __is_pathable_string<_Tp> {};
-
-template <class _Tp>
-struct __is_pathable<_Tp, false, true, false> : __is_pathable_char_array<_Tp> {
-};
-
-template <class _Tp>
-struct __is_pathable<_Tp, false, false, true> : __is_pathable_iter<_Tp> {};
-
-template <class _ECharT>
-struct _PathCVT {
-  static_assert(__can_convert_char<_ECharT>::value,
-                "Char type not convertible");
-
-  typedef __narrow_to_utf8<sizeof(_ECharT) * __CHAR_BIT__> _Narrower;
-
-  static void __append_range(string& __dest, _ECharT const* __b,
-                             _ECharT const* __e) {
-    _Narrower()(back_inserter(__dest), __b, __e);
-  }
-
-  template <class _Iter>
-  static void __append_range(string& __dest, _Iter __b, _Iter __e) {
-    static_assert(!is_same<_Iter, _ECharT*>::value, "Call const overload");
-    if (__b == __e)
-      return;
-    basic_string<_ECharT> __tmp(__b, __e);
-    _Narrower()(back_inserter(__dest), __tmp.data(),
-                __tmp.data() + __tmp.length());
-  }
-
-  template <class _Iter>
-  static void __append_range(string& __dest, _Iter __b, _NullSentinal) {
-    static_assert(!is_same<_Iter, _ECharT*>::value, "Call const overload");
-    const _ECharT __sentinal = _ECharT{};
-    if (*__b == __sentinal)
-      return;
-    basic_string<_ECharT> __tmp;
-    for (; *__b != __sentinal; ++__b)
-      __tmp.push_back(*__b);
-    _Narrower()(back_inserter(__dest), __tmp.data(),
-                __tmp.data() + __tmp.length());
-  }
-
-  template <class _Source>
-  static void __append_source(string& __dest, _Source const& __s) {
-    using _Traits = __is_pathable<_Source>;
-    __append_range(__dest, _Traits::__range_begin(__s),
-                   _Traits::__range_end(__s));
-  }
-};
-
-template <>
-struct _PathCVT<char> {
-
-  template <class _Iter>
-  static typename enable_if<__is_exactly_input_iterator<_Iter>::value>::type
-  __append_range(string& __dest, _Iter __b, _Iter __e) {
-    for (; __b != __e; ++__b)
-      __dest.push_back(*__b);
-  }
-
-  template <class _Iter>
-  static typename enable_if<__is_forward_iterator<_Iter>::value>::type
-  __append_range(string& __dest, _Iter __b, _Iter __e) {
-    __dest.__append_forward_unsafe(__b, __e);
-  }
-
-  template <class _Iter>
-  static void __append_range(string& __dest, _Iter __b, _NullSentinal) {
-    const char __sentinal = char{};
-    for (; *__b != __sentinal; ++__b)
-      __dest.push_back(*__b);
-  }
-
-  template <class _Source>
-  static void __append_source(string& __dest, _Source const& __s) {
-    using _Traits = __is_pathable<_Source>;
-    __append_range(__dest, _Traits::__range_begin(__s),
-                   _Traits::__range_end(__s));
-  }
-};
-
-class _LIBCPP_TYPE_VIS path {
-  template <class _SourceOrIter, class _Tp = path&>
-  using _EnableIfPathable =
-      typename enable_if<__is_pathable<_SourceOrIter>::value, _Tp>::type;
-
-  template <class _Tp>
-  using _SourceChar = typename __is_pathable<_Tp>::__char_type;
-
-  template <class _Tp>
-  using _SourceCVT = _PathCVT<_SourceChar<_Tp> >;
-
-public:
-  typedef char value_type;
-  typedef basic_string<value_type> string_type;
-  typedef _VSTD::string_view __string_view;
-  static constexpr value_type preferred_separator = '/';
-
-  enum class _LIBCPP_ENUM_VIS format : unsigned char {
-    auto_format,
-    native_format,
-    generic_format
-  };
-
-  // constructors and destructor
-  _LIBCPP_INLINE_VISIBILITY path() noexcept {}
-  _LIBCPP_INLINE_VISIBILITY path(const path& __p) : __pn_(__p.__pn_) {}
-  _LIBCPP_INLINE_VISIBILITY path(path&& __p) noexcept
-      : __pn_(_VSTD::move(__p.__pn_)) {}
-
-  _LIBCPP_INLINE_VISIBILITY
-  path(string_type&& __s, format = format::auto_format) noexcept
-      : __pn_(_VSTD::move(__s)) {}
-
-  template <class _Source, class = _EnableIfPathable<_Source, void> >
-  path(const _Source& __src, format = format::auto_format) {
-    _SourceCVT<_Source>::__append_source(__pn_, __src);
-  }
-
-  template <class _InputIt>
-  path(_InputIt __first, _InputIt __last, format = format::auto_format) {
-    typedef typename iterator_traits<_InputIt>::value_type _ItVal;
-    _PathCVT<_ItVal>::__append_range(__pn_, __first, __last);
-  }
-
-  // TODO Implement locale conversions.
-  template <class _Source, class = _EnableIfPathable<_Source, void> >
-  path(const _Source& __src, const locale& __loc, format = format::auto_format);
-  template <class _InputIt>
-  path(_InputIt __first, _InputIt _last, const locale& __loc,
-       format = format::auto_format);
-
-  _LIBCPP_INLINE_VISIBILITY
-  ~path() = default;
-
-  // assignments
-  _LIBCPP_INLINE_VISIBILITY
-  path& operator=(const path& __p) {
-    __pn_ = __p.__pn_;
-    return *this;
-  }
-
-  _LIBCPP_INLINE_VISIBILITY
-  path& operator=(path&& __p) noexcept {
-    __pn_ = _VSTD::move(__p.__pn_);
-    return *this;
-  }
-
-  template <class = void>
-  _LIBCPP_INLINE_VISIBILITY path& operator=(string_type&& __s) noexcept {
-    __pn_ = _VSTD::move(__s);
-    return *this;
-  }
-
-  _LIBCPP_INLINE_VISIBILITY
-  path& assign(string_type&& __s) noexcept {
-    __pn_ = _VSTD::move(__s);
-    return *this;
-  }
-
-  template <class _Source>
-  _LIBCPP_INLINE_VISIBILITY _EnableIfPathable<_Source>
-  operator=(const _Source& __src) {
-    return this->assign(__src);
-  }
-
-  template <class _Source>
-  _EnableIfPathable<_Source> assign(const _Source& __src) {
-    __pn_.clear();
-    _SourceCVT<_Source>::__append_source(__pn_, __src);
-    return *this;
-  }
-
-  template <class _InputIt>
-  path& assign(_InputIt __first, _InputIt __last) {
-    typedef typename iterator_traits<_InputIt>::value_type _ItVal;
-    __pn_.clear();
-    _PathCVT<_ItVal>::__append_range(__pn_, __first, __last);
-    return *this;
-  }
-
-private:
-  template <class _ECharT>
-  static bool __source_is_absolute(_ECharT __first_or_null) {
-    return __is_separator(__first_or_null);
-  }
-
-public:
-  // appends
-  path& operator/=(const path& __p) {
-    if (__p.is_absolute()) {
-      __pn_ = __p.__pn_;
-      return *this;
-    }
-    if (has_filename())
-      __pn_ += preferred_separator;
-    __pn_ += __p.native();
-    return *this;
-  }
-
-  // FIXME: Use _LIBCPP_DIAGNOSE_WARNING to produce a diagnostic when __src
-  // is known at compile time to be "/' since the user almost certainly intended
-  // to append a separator instead of overwriting the path with "/"
-  template <class _Source>
-  _LIBCPP_INLINE_VISIBILITY _EnableIfPathable<_Source>
-  operator/=(const _Source& __src) {
-    return this->append(__src);
-  }
-
-  template <class _Source>
-  _EnableIfPathable<_Source> append(const _Source& __src) {
-    using _Traits = __is_pathable<_Source>;
-    using _CVT = _PathCVT<_SourceChar<_Source> >;
-    if (__source_is_absolute(_Traits::__first_or_null(__src)))
-      __pn_.clear();
-    else if (has_filename())
-      __pn_ += preferred_separator;
-    _CVT::__append_source(__pn_, __src);
-    return *this;
-  }
-
-  template <class _InputIt>
-  path& append(_InputIt __first, _InputIt __last) {
-    typedef typename iterator_traits<_InputIt>::value_type _ItVal;
-    static_assert(__can_convert_char<_ItVal>::value, "Must convertible");
-    using _CVT = _PathCVT<_ItVal>;
-    if (__first != __last && __source_is_absolute(*__first))
-      __pn_.clear();
-    else if (has_filename())
-      __pn_ += preferred_separator;
-    _CVT::__append_range(__pn_, __first, __last);
-    return *this;
-  }
-
-  // concatenation
-  _LIBCPP_INLINE_VISIBILITY
-  path& operator+=(const path& __x) {
-    __pn_ += __x.__pn_;
-    return *this;
-  }
-
-  _LIBCPP_INLINE_VISIBILITY
-  path& operator+=(const string_type& __x) {
-    __pn_ += __x;
-    return *this;
-  }
-
-  _LIBCPP_INLINE_VISIBILITY
-  path& operator+=(__string_view __x) {
-    __pn_ += __x;
-    return *this;
-  }
-
-  _LIBCPP_INLINE_VISIBILITY
-  path& operator+=(const value_type* __x) {
-    __pn_ += __x;
-    return *this;
-  }
-
-  _LIBCPP_INLINE_VISIBILITY
-  path& operator+=(value_type __x) {
-    __pn_ += __x;
-    return *this;
-  }
-
-  template <class _ECharT>
-  typename enable_if<__can_convert_char<_ECharT>::value, path&>::type
-  operator+=(_ECharT __x) {
-    basic_string<_ECharT> __tmp;
-    __tmp += __x;
-    _PathCVT<_ECharT>::__append_source(__pn_, __tmp);
-    return *this;
-  }
-
-  template <class _Source>
-  _EnableIfPathable<_Source> operator+=(const _Source& __x) {
-    return this->concat(__x);
-  }
-
-  template <class _Source>
-  _EnableIfPathable<_Source> concat(const _Source& __x) {
-    _SourceCVT<_Source>::__append_source(__pn_, __x);
-    return *this;
-  }
-
-  template <class _InputIt>
-  path& concat(_InputIt __first, _InputIt __last) {
-    typedef typename iterator_traits<_InputIt>::value_type _ItVal;
-    _PathCVT<_ItVal>::__append_range(__pn_, __first, __last);
-    return *this;
-  }
-
-  // modifiers
-  _LIBCPP_INLINE_VISIBILITY
-  void clear() noexcept { __pn_.clear(); }
-
-  path& make_preferred() { return *this; }
-
-  _LIBCPP_INLINE_VISIBILITY
-  path& remove_filename() {
-    auto __fname = __filename();
-    if (!__fname.empty())
-      __pn_.erase(__fname.data() - __pn_.data());
-    return *this;
-  }
-
-  path& replace_filename(const path& __replacement) {
-    remove_filename();
-    return (*this /= __replacement);
-  }
-
-  path& replace_extension(const path& __replacement = path());
-
-  _LIBCPP_INLINE_VISIBILITY
-  void swap(path& __rhs) noexcept { __pn_.swap(__rhs.__pn_); }
-
-  // private helper to allow reserving memory in the path
-  _LIBCPP_INLINE_VISIBILITY
-  void __reserve(size_t __s) { __pn_.reserve(__s); }
-
-  // native format observers
-  _LIBCPP_INLINE_VISIBILITY
-  const string_type& native() const noexcept { return __pn_; }
-
-  _LIBCPP_INLINE_VISIBILITY
-  const value_type* c_str() const noexcept { return __pn_.c_str(); }
-
-  _LIBCPP_INLINE_VISIBILITY operator string_type() const { return __pn_; }
-
-  template <class _ECharT, class _Traits = char_traits<_ECharT>,
-            class _Allocator = allocator<_ECharT> >
-  basic_string<_ECharT, _Traits, _Allocator>
-  string(const _Allocator& __a = _Allocator()) const {
-    using _CVT = __widen_from_utf8<sizeof(_ECharT) * __CHAR_BIT__>;
-    using _Str = basic_string<_ECharT, _Traits, _Allocator>;
-    _Str __s(__a);
-    __s.reserve(__pn_.size());
-    _CVT()(back_inserter(__s), __pn_.data(), __pn_.data() + __pn_.size());
-    return __s;
-  }
-
-  _LIBCPP_INLINE_VISIBILITY std::string string() const { return __pn_; }
-  _LIBCPP_INLINE_VISIBILITY std::wstring wstring() const {
-    return string<wchar_t>();
-  }
-  _LIBCPP_INLINE_VISIBILITY std::string u8string() const { return __pn_; }
-  _LIBCPP_INLINE_VISIBILITY std::u16string u16string() const {
-    return string<char16_t>();
-  }
-  _LIBCPP_INLINE_VISIBILITY std::u32string u32string() const {
-    return string<char32_t>();
-  }
-
-  // generic format observers
-  template <class _ECharT, class _Traits = char_traits<_ECharT>,
-            class _Allocator = allocator<_ECharT> >
-  basic_string<_ECharT, _Traits, _Allocator>
-  generic_string(const _Allocator& __a = _Allocator()) const {
-    return string<_ECharT, _Traits, _Allocator>(__a);
-  }
-
-  std::string generic_string() const { return __pn_; }
-  std::wstring generic_wstring() const { return string<wchar_t>(); }
-  std::string generic_u8string() const { return __pn_; }
-  std::u16string generic_u16string() const { return string<char16_t>(); }
-  std::u32string generic_u32string() const { return string<char32_t>(); }
-
-private:
-  int __compare(__string_view) const;
-  __string_view __root_name() const;
-  __string_view __root_directory() const;
-  __string_view __root_path_raw() const;
-  __string_view __relative_path() const;
-  __string_view __parent_path() const;
-  __string_view __filename() const;
-  __string_view __stem() const;
-  __string_view __extension() const;
-
-public:
-  // compare
-  _LIBCPP_INLINE_VISIBILITY int compare(const path& __p) const noexcept {
-    return __compare(__p.__pn_);
-  }
-  _LIBCPP_INLINE_VISIBILITY int compare(const string_type& __s) const {
-    return __compare(__s);
-  }
-  _LIBCPP_INLINE_VISIBILITY int compare(__string_view __s) const {
-    return __compare(__s);
-  }
-  _LIBCPP_INLINE_VISIBILITY int compare(const value_type* __s) const {
-    return __compare(__s);
-  }
-
-  // decomposition
-  _LIBCPP_INLINE_VISIBILITY path root_name() const {
-    return string_type(__root_name());
-  }
-  _LIBCPP_INLINE_VISIBILITY path root_directory() const {
-    return string_type(__root_directory());
-  }
-  _LIBCPP_INLINE_VISIBILITY path root_path() const {
-    return root_name().append(string_type(__root_directory()));
-  }
-  _LIBCPP_INLINE_VISIBILITY path relative_path() const {
-    return string_type(__relative_path());
-  }
-  _LIBCPP_INLINE_VISIBILITY path parent_path() const {
-    return string_type(__parent_path());
-  }
-  _LIBCPP_INLINE_VISIBILITY path filename() const {
-    return string_type(__filename());
-  }
-  _LIBCPP_INLINE_VISIBILITY path stem() const { return string_type(__stem()); }
-  _LIBCPP_INLINE_VISIBILITY path extension() const {
-    return string_type(__extension());
-  }
-
-  // query
-  _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY bool
-  empty() const noexcept {
-    return __pn_.empty();
-  }
-
-  _LIBCPP_INLINE_VISIBILITY bool has_root_name() const {
-    return !__root_name().empty();
-  }
-  _LIBCPP_INLINE_VISIBILITY bool has_root_directory() const {
-    return !__root_directory().empty();
-  }
-  _LIBCPP_INLINE_VISIBILITY bool has_root_path() const {
-    return !__root_path_raw().empty();
-  }
-  _LIBCPP_INLINE_VISIBILITY bool has_relative_path() const {
-    return !__relative_path().empty();
-  }
-  _LIBCPP_INLINE_VISIBILITY bool has_parent_path() const {
-    return !__parent_path().empty();
-  }
-  _LIBCPP_INLINE_VISIBILITY bool has_filename() const {
-    return !__filename().empty();
-  }
-  _LIBCPP_INLINE_VISIBILITY bool has_stem() const { return !__stem().empty(); }
-  _LIBCPP_INLINE_VISIBILITY bool has_extension() const {
-    return !__extension().empty();
-  }
-
-  _LIBCPP_INLINE_VISIBILITY bool is_absolute() const {
-    return has_root_directory();
-  }
-  _LIBCPP_INLINE_VISIBILITY bool is_relative() const { return !is_absolute(); }
-
-  // relative paths
-  path lexically_normal() const;
-  path lexically_relative(const path& __base) const;
-
-  _LIBCPP_INLINE_VISIBILITY path lexically_proximate(const path& __base) const {
-    path __result = this->lexically_relative(__base);
-    if (__result.native().empty())
-      return *this;
-    return __result;
-  }
-
-  // iterators
-  class _LIBCPP_TYPE_VIS iterator;
-  typedef iterator const_iterator;
-
-  iterator begin() const;
-  iterator end() const;
-
-  template <class _CharT, class _Traits>
-  _LIBCPP_INLINE_VISIBILITY friend
-      typename enable_if<is_same<_CharT, char>::value &&
-                             is_same<_Traits, char_traits<char> >::value,
-                         basic_ostream<_CharT, _Traits>&>::type
-      operator<<(basic_ostream<_CharT, _Traits>& __os, const path& __p) {
-    __os << std::__quoted(__p.native());
-    return __os;
-  }
-
-  template <class _CharT, class _Traits>
-  _LIBCPP_INLINE_VISIBILITY friend
-      typename enable_if<!is_same<_CharT, char>::value ||
-                             !is_same<_Traits, char_traits<char> >::value,
-                         basic_ostream<_CharT, _Traits>&>::type
-      operator<<(basic_ostream<_CharT, _Traits>& __os, const path& __p) {
-    __os << std::__quoted(__p.string<_CharT, _Traits>());
-    return __os;
-  }
-
-  template <class _CharT, class _Traits>
-  _LIBCPP_INLINE_VISIBILITY friend basic_istream<_CharT, _Traits>&
-  operator>>(basic_istream<_CharT, _Traits>& __is, path& __p) {
-    basic_string<_CharT, _Traits> __tmp;
-    __is >> __quoted(__tmp);
-    __p = __tmp;
-    return __is;
-  }
-
-  friend _LIBCPP_INLINE_VISIBILITY bool operator==(const path& __lhs, const path& __rhs) noexcept {
-    return __lhs.compare(__rhs) == 0;
-  }
-  friend _LIBCPP_INLINE_VISIBILITY bool operator!=(const path& __lhs, const path& __rhs) noexcept {
-    return __lhs.compare(__rhs) != 0;
-  }
-  friend _LIBCPP_INLINE_VISIBILITY bool operator<(const path& __lhs, const path& __rhs) noexcept {
-    return __lhs.compare(__rhs) < 0;
-  }
-  friend _LIBCPP_INLINE_VISIBILITY bool operator<=(const path& __lhs, const path& __rhs) noexcept {
-    return __lhs.compare(__rhs) <= 0;
-  }
-  friend _LIBCPP_INLINE_VISIBILITY bool operator>(const path& __lhs, const path& __rhs) noexcept {
-    return __lhs.compare(__rhs) > 0;
-  }
-  friend _LIBCPP_INLINE_VISIBILITY bool operator>=(const path& __lhs, const path& __rhs) noexcept {
-    return __lhs.compare(__rhs) >= 0;
-  }
-
-  friend _LIBCPP_INLINE_VISIBILITY path operator/(const path& __lhs,
-                                                  const path& __rhs) {
-    path __result(__lhs);
-    __result /= __rhs;
-    return __result;
-  }
-private:
-  inline _LIBCPP_INLINE_VISIBILITY path&
-  __assign_view(__string_view const& __s) noexcept {
-    __pn_ = string_type(__s);
-    return *this;
-  }
-  string_type __pn_;
-};
-
-inline _LIBCPP_INLINE_VISIBILITY void swap(path& __lhs, path& __rhs) noexcept {
-  __lhs.swap(__rhs);
-}
-
-_LIBCPP_FUNC_VIS
-size_t hash_value(const path& __p) noexcept;
-
-template <class _Source>
-_LIBCPP_INLINE_VISIBILITY
-    typename enable_if<__is_pathable<_Source>::value, path>::type
-    u8path(const _Source& __s) {
-  static_assert(
-      is_same<typename __is_pathable<_Source>::__char_type, char>::value,
-      "u8path(Source const&) requires Source have a character type of type "
-      "'char'");
-  return path(__s);
-}
-
-template <class _InputIt>
-_LIBCPP_INLINE_VISIBILITY
-    typename enable_if<__is_pathable<_InputIt>::value, path>::type
-    u8path(_InputIt __f, _InputIt __l) {
-  static_assert(
-      is_same<typename __is_pathable<_InputIt>::__char_type, char>::value,
-      "u8path(Iter, Iter) requires Iter have a value_type of type 'char'");
-  return path(__f, __l);
-}
-
-class _LIBCPP_TYPE_VIS path::iterator {
-public:
-  enum _ParserState : unsigned char {
-    _Singular,
-    _BeforeBegin,
-    _InRootName,
-    _InRootDir,
-    _InFilenames,
-    _InTrailingSep,
-    _AtEnd
-  };
-
-public:
-  typedef bidirectional_iterator_tag iterator_category;
-
-  typedef path value_type;
-  typedef std::ptrdiff_t difference_type;
-  typedef const path* pointer;
-  typedef const path& reference;
-
-  typedef void
-      __stashing_iterator_tag; // See reverse_iterator and __is_stashing_iterator
-
-public:
-  _LIBCPP_INLINE_VISIBILITY
-  iterator()
-      : __stashed_elem_(), __path_ptr_(nullptr), __entry_(),
-        __state_(_Singular) {}
-
-  iterator(const iterator&) = default;
-  ~iterator() = default;
-
-  iterator& operator=(const iterator&) = default;
-
-  _LIBCPP_INLINE_VISIBILITY
-  reference operator*() const { return __stashed_elem_; }
-
-  _LIBCPP_INLINE_VISIBILITY
-  pointer operator->() const { return &__stashed_elem_; }
-
-  _LIBCPP_INLINE_VISIBILITY
-  iterator& operator++() {
-    _LIBCPP_ASSERT(__state_ != _Singular,
-                   "attempting to increment a singular iterator");
-    _LIBCPP_ASSERT(__state_ != _AtEnd,
-                   "attempting to increment the end iterator");
-    return __increment();
-  }
-
-  _LIBCPP_INLINE_VISIBILITY
-  iterator operator++(int) {
-    iterator __it(*this);
-    this->operator++();
-    return __it;
-  }
-
-  _LIBCPP_INLINE_VISIBILITY
-  iterator& operator--() {
-    _LIBCPP_ASSERT(__state_ != _Singular,
-                   "attempting to decrement a singular iterator");
-    _LIBCPP_ASSERT(__entry_.data() != __path_ptr_->native().data(),
-                   "attempting to decrement the begin iterator");
-    return __decrement();
-  }
-
-  _LIBCPP_INLINE_VISIBILITY
-  iterator operator--(int) {
-    iterator __it(*this);
-    this->operator--();
-    return __it;
-  }
-
-private:
-  friend class path;
-
-  inline _LIBCPP_INLINE_VISIBILITY friend bool operator==(const iterator&,
-                                                          const iterator&);
-
-  iterator& __increment();
-  iterator& __decrement();
-
-  path __stashed_elem_;
-  const path* __path_ptr_;
-  path::__string_view __entry_;
-  _ParserState __state_;
-};
-
-inline _LIBCPP_INLINE_VISIBILITY bool operator==(const path::iterator& __lhs,
-                                                 const path::iterator& __rhs) {
-  return __lhs.__path_ptr_ == __rhs.__path_ptr_ &&
-         __lhs.__entry_.data() == __rhs.__entry_.data();
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool operator!=(const path::iterator& __lhs,
-                                                 const path::iterator& __rhs) {
-  return !(__lhs == __rhs);
-}
-
-class _LIBCPP_EXCEPTION_ABI filesystem_error : public system_error {
-public:
-  _LIBCPP_INLINE_VISIBILITY
-  filesystem_error(const string& __what, error_code __ec)
-      : system_error(__ec, __what),
-        __storage_(make_shared<_Storage>(path(), path())) {
-    __create_what(0);
-  }
-
-  _LIBCPP_INLINE_VISIBILITY
-  filesystem_error(const string& __what, const path& __p1, error_code __ec)
-      : system_error(__ec, __what),
-        __storage_(make_shared<_Storage>(__p1, path())) {
-    __create_what(1);
-  }
-
-  _LIBCPP_INLINE_VISIBILITY
-  filesystem_error(const string& __what, const path& __p1, const path& __p2,
-                   error_code __ec)
-      : system_error(__ec, __what),
-        __storage_(make_shared<_Storage>(__p1, __p2)) {
-    __create_what(2);
-  }
-
-  _LIBCPP_INLINE_VISIBILITY
-  const path& path1() const noexcept { return __storage_->__p1_; }
-
-  _LIBCPP_INLINE_VISIBILITY
-  const path& path2() const noexcept { return __storage_->__p2_; }
-
-  ~filesystem_error() override; // key function
-
-  _LIBCPP_INLINE_VISIBILITY
-  const char* what() const noexcept override {
-    return __storage_->__what_.c_str();
-  }
-
-  _LIBCPP_FUNC_VIS
-  void __create_what(int __num_paths);
-
-private:
-  struct _Storage {
-    _LIBCPP_INLINE_VISIBILITY
-    _Storage(const path& __p1, const path& __p2) : __p1_(__p1), __p2_(__p2) {}
-
-    path __p1_;
-    path __p2_;
-    string __what_;
-  };
-  shared_ptr<_Storage> __storage_;
-};
-
-template <class... _Args>
-_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY
-#ifndef _LIBCPP_NO_EXCEPTIONS
-    void
-    __throw_filesystem_error(_Args&&... __args) {
-  throw filesystem_error(std::forward<_Args>(__args)...);
-}
-#else
-    void
-    __throw_filesystem_error(_Args&&...) {
-  _VSTD::abort();
-}
-#endif
-
-// operational functions
-
-_LIBCPP_FUNC_VIS
-path __absolute(const path&, error_code* __ec = nullptr);
-_LIBCPP_FUNC_VIS
-path __canonical(const path&, error_code* __ec = nullptr);
-_LIBCPP_FUNC_VIS
-void __copy(const path& __from, const path& __to, copy_options __opt,
-            error_code* __ec = nullptr);
-_LIBCPP_FUNC_VIS
-bool __copy_file(const path& __from, const path& __to, copy_options __opt,
-                 error_code* __ec = nullptr);
-_LIBCPP_FUNC_VIS
-void __copy_symlink(const path& __existing_symlink, const path& __new_symlink,
-                    error_code* __ec = nullptr);
-_LIBCPP_FUNC_VIS
-bool __create_directories(const path& p, error_code* ec = nullptr);
-_LIBCPP_FUNC_VIS
-bool __create_directory(const path& p, error_code* ec = nullptr);
-_LIBCPP_FUNC_VIS
-bool __create_directory(const path& p, const path& attributes,
-                        error_code* ec = nullptr);
-_LIBCPP_FUNC_VIS
-void __create_directory_symlink(const path& __to, const path& __new_symlink,
-                                error_code* __ec = nullptr);
-_LIBCPP_FUNC_VIS
-void __create_hard_link(const path& __to, const path& __new_hard_link,
-                        error_code* __ec = nullptr);
-_LIBCPP_FUNC_VIS
-void __create_symlink(const path& __to, const path& __new_symlink,
-                      error_code* __ec = nullptr);
-_LIBCPP_FUNC_VIS
-path __current_path(error_code* __ec = nullptr);
-_LIBCPP_FUNC_VIS
-void __current_path(const path&, error_code* __ec = nullptr);
-_LIBCPP_FUNC_VIS
-bool __equivalent(const path&, const path&, error_code* __ec = nullptr);
-_LIBCPP_FUNC_VIS
-uintmax_t __file_size(const path&, error_code* __ec = nullptr);
-_LIBCPP_FUNC_VIS
-uintmax_t __hard_link_count(const path&, error_code* __ec = nullptr);
-_LIBCPP_FUNC_VIS
-bool __fs_is_empty(const path& p, error_code* ec = nullptr);
-_LIBCPP_FUNC_VIS
-file_time_type __last_write_time(const path& p, error_code* ec = nullptr);
-_LIBCPP_FUNC_VIS
-void __last_write_time(const path& p, file_time_type new_time,
-                       error_code* ec = nullptr);
-_LIBCPP_FUNC_VIS
-void __permissions(const path&, perms, perm_options, error_code* = nullptr);
-_LIBCPP_FUNC_VIS
-path __read_symlink(const path& p, error_code* ec = nullptr);
-_LIBCPP_FUNC_VIS
-bool __remove(const path& p, error_code* ec = nullptr);
-_LIBCPP_FUNC_VIS
-uintmax_t __remove_all(const path& p, error_code* ec = nullptr);
-_LIBCPP_FUNC_VIS
-void __rename(const path& from, const path& to, error_code* ec = nullptr);
-_LIBCPP_FUNC_VIS
-void __resize_file(const path& p, uintmax_t size, error_code* ec = nullptr);
-_LIBCPP_FUNC_VIS
-space_info __space(const path&, error_code* __ec = nullptr);
-_LIBCPP_FUNC_VIS
-file_status __status(const path&, error_code* __ec = nullptr);
-_LIBCPP_FUNC_VIS
-file_status __symlink_status(const path&, error_code* __ec = nullptr);
-_LIBCPP_FUNC_VIS
-path __system_complete(const path&, error_code* __ec = nullptr);
-_LIBCPP_FUNC_VIS
-path __temp_directory_path(error_code* __ec = nullptr);
-_LIBCPP_FUNC_VIS
-path __weakly_canonical(path const& __p, error_code* __ec = nullptr);
-
-inline _LIBCPP_INLINE_VISIBILITY path current_path() {
-  return __current_path();
-}
-
-inline _LIBCPP_INLINE_VISIBILITY path current_path(error_code& __ec) {
-  return __current_path(&__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY void current_path(const path& __p) {
-  __current_path(__p);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY void current_path(const path& __p,
-                                                   error_code& __ec) noexcept {
-  __current_path(__p, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY path absolute(const path& __p) {
-  return __absolute(__p);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY path absolute(const path& __p,
-                                               error_code& __ec) {
-  return __absolute(__p, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY path canonical(const path& __p) {
-  return __canonical(__p);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY path canonical(const path& __p,
-                                                error_code& __ec) {
-  return __canonical(__p, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY void copy(const path& __from,
-                                           const path& __to) {
-  __copy(__from, __to, copy_options::none);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY void copy(const path& __from, const path& __to,
-                                           error_code& __ec) {
-  __copy(__from, __to, copy_options::none, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY void copy(const path& __from, const path& __to,
-                                           copy_options __opt) {
-  __copy(__from, __to, __opt);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY void copy(const path& __from, const path& __to,
-                                           copy_options __opt,
-                                           error_code& __ec) {
-  __copy(__from, __to, __opt, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool copy_file(const path& __from,
-                                                const path& __to) {
-  return __copy_file(__from, __to, copy_options::none);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool
-copy_file(const path& __from, const path& __to, error_code& __ec) {
-  return __copy_file(__from, __to, copy_options::none, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool
-copy_file(const path& __from, const path& __to, copy_options __opt) {
-  return __copy_file(__from, __to, __opt);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool copy_file(const path& __from,
-                                                const path& __to,
-                                                copy_options __opt,
-                                                error_code& __ec) {
-  return __copy_file(__from, __to, __opt, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY void copy_symlink(const path& __existing,
-                                                   const path& __new) {
-  __copy_symlink(__existing, __new);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY void
-copy_symlink(const path& __ext, const path& __new, error_code& __ec) noexcept {
-  __copy_symlink(__ext, __new, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool create_directories(const path& __p) {
-  return __create_directories(__p);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool create_directories(const path& __p,
-                                                         error_code& __ec) {
-  return __create_directories(__p, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool create_directory(const path& __p) {
-  return __create_directory(__p);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool
-create_directory(const path& __p, error_code& __ec) noexcept {
-  return __create_directory(__p, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool create_directory(const path& __p,
-                                                       const path& __attrs) {
-  return __create_directory(__p, __attrs);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool
-create_directory(const path& __p, const path& __attrs,
-                 error_code& __ec) noexcept {
-  return __create_directory(__p, __attrs, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY void
-create_directory_symlink(const path& __to, const path& __new) {
-  __create_directory_symlink(__to, __new);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY void
-create_directory_symlink(const path& __to, const path& __new,
-                         error_code& __ec) noexcept {
-  __create_directory_symlink(__to, __new, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY void create_hard_link(const path& __to,
-                                                       const path& __new) {
-  __create_hard_link(__to, __new);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY void
-create_hard_link(const path& __to, const path& __new,
-                 error_code& __ec) noexcept {
-  __create_hard_link(__to, __new, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY void create_symlink(const path& __to,
-                                                     const path& __new) {
-  __create_symlink(__to, __new);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY void
-create_symlink(const path& __to, const path& __new, error_code& __ec) noexcept {
-  return __create_symlink(__to, __new, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool status_known(file_status __s) noexcept {
-  return __s.type() != file_type::none;
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool exists(file_status __s) noexcept {
-  return status_known(__s) && __s.type() != file_type::not_found;
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool exists(const path& __p) {
-  return exists(__status(__p));
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool exists(const path& __p,
-                                             error_code& __ec) noexcept {
-  auto __s = __status(__p, &__ec);
-  if (status_known(__s))
-    __ec.clear();
-  return exists(__s);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool equivalent(const path& __p1,
-                                                 const path& __p2) {
-  return __equivalent(__p1, __p2);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool
-equivalent(const path& __p1, const path& __p2, error_code& __ec) noexcept {
-  return __equivalent(__p1, __p2, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY uintmax_t file_size(const path& __p) {
-  return __file_size(__p);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY uintmax_t
-file_size(const path& __p, error_code& __ec) noexcept {
-  return __file_size(__p, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY uintmax_t hard_link_count(const path& __p) {
-  return __hard_link_count(__p);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY uintmax_t
-hard_link_count(const path& __p, error_code& __ec) noexcept {
-  return __hard_link_count(__p, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool is_block_file(file_status __s) noexcept {
-  return __s.type() == file_type::block;
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool is_block_file(const path& __p) {
-  return is_block_file(__status(__p));
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool is_block_file(const path& __p,
-                                                    error_code& __ec) noexcept {
-  return is_block_file(__status(__p, &__ec));
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool
-is_character_file(file_status __s) noexcept {
-  return __s.type() == file_type::character;
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool is_character_file(const path& __p) {
-  return is_character_file(__status(__p));
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool
-is_character_file(const path& __p, error_code& __ec) noexcept {
-  return is_character_file(__status(__p, &__ec));
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool is_directory(file_status __s) noexcept {
-  return __s.type() == file_type::directory;
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool is_directory(const path& __p) {
-  return is_directory(__status(__p));
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool is_directory(const path& __p,
-                                                   error_code& __ec) noexcept {
-  return is_directory(__status(__p, &__ec));
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool is_empty(const path& __p) {
-  return __fs_is_empty(__p);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool is_empty(const path& __p,
-                                               error_code& __ec) {
-  return __fs_is_empty(__p, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool is_fifo(file_status __s) noexcept {
-  return __s.type() == file_type::fifo;
-}
-inline _LIBCPP_INLINE_VISIBILITY bool is_fifo(const path& __p) {
-  return is_fifo(__status(__p));
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool is_fifo(const path& __p,
-                                              error_code& __ec) noexcept {
-  return is_fifo(__status(__p, &__ec));
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool
-is_regular_file(file_status __s) noexcept {
-  return __s.type() == file_type::regular;
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool is_regular_file(const path& __p) {
-  return is_regular_file(__status(__p));
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool
-is_regular_file(const path& __p, error_code& __ec) noexcept {
-  return is_regular_file(__status(__p, &__ec));
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool is_socket(file_status __s) noexcept {
-  return __s.type() == file_type::socket;
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool is_socket(const path& __p) {
-  return is_socket(__status(__p));
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool is_socket(const path& __p,
-                                                error_code& __ec) noexcept {
-  return is_socket(__status(__p, &__ec));
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool is_symlink(file_status __s) noexcept {
-  return __s.type() == file_type::symlink;
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool is_symlink(const path& __p) {
-  return is_symlink(__symlink_status(__p));
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool is_symlink(const path& __p,
-                                                 error_code& __ec) noexcept {
-  return is_symlink(__symlink_status(__p, &__ec));
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool is_other(file_status __s) noexcept {
-  return exists(__s) && !is_regular_file(__s) && !is_directory(__s) &&
-         !is_symlink(__s);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool is_other(const path& __p) {
-  return is_other(__status(__p));
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool is_other(const path& __p,
-                                               error_code& __ec) noexcept {
-  return is_other(__status(__p, &__ec));
-}
-
-inline _LIBCPP_INLINE_VISIBILITY file_time_type
-last_write_time(const path& __p) {
-  return __last_write_time(__p);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY file_time_type
-last_write_time(const path& __p, error_code& __ec) noexcept {
-  return __last_write_time(__p, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY void last_write_time(const path& __p,
-                                                      file_time_type __t) {
-  __last_write_time(__p, __t);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY void
-last_write_time(const path& __p, file_time_type __t,
-                error_code& __ec) noexcept {
-  __last_write_time(__p, __t, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY void
-permissions(const path& __p, perms __prms,
-            perm_options __opts = perm_options::replace) {
-  __permissions(__p, __prms, __opts);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY void permissions(const path& __p, perms __prms,
-                                                  error_code& __ec) noexcept {
-  __permissions(__p, __prms, perm_options::replace, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY void permissions(const path& __p, perms __prms,
-                                                  perm_options __opts,
-                                                  error_code& __ec) {
-  __permissions(__p, __prms, __opts, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY path proximate(const path& __p,
-                                                const path& __base,
-                                                error_code& __ec) {
-  path __tmp = __weakly_canonical(__p, &__ec);
-  if (__ec)
-    return {};
-  path __tmp_base = __weakly_canonical(__base, &__ec);
-  if (__ec)
-    return {};
-  return __tmp.lexically_proximate(__tmp_base);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY path proximate(const path& __p,
-                                                error_code& __ec) {
-  return proximate(__p, current_path(), __ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY path
-proximate(const path& __p, const path& __base = current_path()) {
-  return __weakly_canonical(__p).lexically_proximate(
-      __weakly_canonical(__base));
-}
-
-inline _LIBCPP_INLINE_VISIBILITY path read_symlink(const path& __p) {
-  return __read_symlink(__p);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY path read_symlink(const path& __p,
-                                                   error_code& __ec) {
-  return __read_symlink(__p, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY path relative(const path& __p,
-                                               const path& __base,
-                                               error_code& __ec) {
-  path __tmp = __weakly_canonical(__p, &__ec);
-  if (__ec)
-    return path();
-  path __tmpbase = __weakly_canonical(__base, &__ec);
-  if (__ec)
-    return path();
-  return __tmp.lexically_relative(__tmpbase);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY path relative(const path& __p,
-                                               error_code& __ec) {
-  return relative(__p, current_path(), __ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY path
-relative(const path& __p, const path& __base = current_path()) {
-  return __weakly_canonical(__p).lexically_relative(__weakly_canonical(__base));
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool remove(const path& __p) {
-  return __remove(__p);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool remove(const path& __p,
-                                             error_code& __ec) noexcept {
-  return __remove(__p, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY uintmax_t remove_all(const path& __p) {
-  return __remove_all(__p);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY uintmax_t remove_all(const path& __p,
-                                                      error_code& __ec) {
-  return __remove_all(__p, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY void rename(const path& __from,
-                                             const path& __to) {
-  return __rename(__from, __to);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY void
-rename(const path& __from, const path& __to, error_code& __ec) noexcept {
-  return __rename(__from, __to, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY void resize_file(const path& __p,
-                                                  uintmax_t __ns) {
-  return __resize_file(__p, __ns);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY void
-resize_file(const path& __p, uintmax_t __ns, error_code& __ec) noexcept {
-  return __resize_file(__p, __ns, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY space_info space(const path& __p) {
-  return __space(__p);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY space_info space(const path& __p,
-                                                  error_code& __ec) noexcept {
-  return __space(__p, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY file_status status(const path& __p) {
-  return __status(__p);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY file_status status(const path& __p,
-                                                    error_code& __ec) noexcept {
-  return __status(__p, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY file_status symlink_status(const path& __p) {
-  return __symlink_status(__p);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY file_status
-symlink_status(const path& __p, error_code& __ec) noexcept {
-  return __symlink_status(__p, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY path temp_directory_path() {
-  return __temp_directory_path();
-}
-
-inline _LIBCPP_INLINE_VISIBILITY path temp_directory_path(error_code& __ec) {
-  return __temp_directory_path(&__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY path weakly_canonical(path const& __p) {
-  return __weakly_canonical(__p);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY path weakly_canonical(path const& __p,
-                                                       error_code& __ec) {
-  return __weakly_canonical(__p, &__ec);
-}
-
-class directory_iterator;
-class recursive_directory_iterator;
-class __dir_stream;
-
-class directory_entry {
-  typedef _VSTD_FS::path _Path;
-
-public:
-  // constructors and destructors
-  directory_entry() noexcept = default;
-  directory_entry(directory_entry const&) = default;
-  directory_entry(directory_entry&&) noexcept = default;
-
-  _LIBCPP_INLINE_VISIBILITY
-  explicit directory_entry(_Path const& __p) : __p_(__p) {
-    error_code __ec;
-    __refresh(&__ec);
-  }
-
-  _LIBCPP_INLINE_VISIBILITY
-  directory_entry(_Path const& __p, error_code& __ec) : __p_(__p) {
-    __refresh(&__ec);
-  }
-
-  ~directory_entry() {}
-
-  directory_entry& operator=(directory_entry const&) = default;
-  directory_entry& operator=(directory_entry&&) noexcept = default;
-
-  _LIBCPP_INLINE_VISIBILITY
-  void assign(_Path const& __p) {
-    __p_ = __p;
-    error_code __ec;
-    __refresh(&__ec);
-  }
-
-  _LIBCPP_INLINE_VISIBILITY
-  void assign(_Path const& __p, error_code& __ec) {
-    __p_ = __p;
-    __refresh(&__ec);
-  }
-
-  _LIBCPP_INLINE_VISIBILITY
-  void replace_filename(_Path const& __p) {
-    __p_.replace_filename(__p);
-    error_code __ec;
-    __refresh(&__ec);
-  }
-
-  _LIBCPP_INLINE_VISIBILITY
-  void replace_filename(_Path const& __p, error_code& __ec) {
-    __p_ = __p_.parent_path() / __p;
-    __refresh(&__ec);
-  }
-
-  _LIBCPP_INLINE_VISIBILITY
-  void refresh() { __refresh(); }
-
-  _LIBCPP_INLINE_VISIBILITY
-  void refresh(error_code& __ec) noexcept { __refresh(&__ec); }
-
-  _LIBCPP_INLINE_VISIBILITY
-  _Path const& path() const noexcept { return __p_; }
-
-  _LIBCPP_INLINE_VISIBILITY
-  operator const _Path&() const noexcept { return __p_; }
-
-  _LIBCPP_INLINE_VISIBILITY
-  bool exists() const { return _VSTD_FS::exists(file_status{__get_ft()}); }
-
-  _LIBCPP_INLINE_VISIBILITY
-  bool exists(error_code& __ec) const noexcept {
-    return _VSTD_FS::exists(file_status{__get_ft(&__ec)});
-  }
-
-  _LIBCPP_INLINE_VISIBILITY
-  bool is_block_file() const { return __get_ft() == file_type::block; }
-
-  _LIBCPP_INLINE_VISIBILITY
-  bool is_block_file(error_code& __ec) const noexcept {
-    return __get_ft(&__ec) == file_type::block;
-  }
-
-  _LIBCPP_INLINE_VISIBILITY
-  bool is_character_file() const { return __get_ft() == file_type::character; }
-
-  _LIBCPP_INLINE_VISIBILITY
-  bool is_character_file(error_code& __ec) const noexcept {
-    return __get_ft(&__ec) == file_type::character;
-  }
-
-  _LIBCPP_INLINE_VISIBILITY
-  bool is_directory() const { return __get_ft() == file_type::directory; }
-
-  _LIBCPP_INLINE_VISIBILITY
-  bool is_directory(error_code& __ec) const noexcept {
-    return __get_ft(&__ec) == file_type::directory;
-  }
-
-  _LIBCPP_INLINE_VISIBILITY
-  bool is_fifo() const { return __get_ft() == file_type::fifo; }
-
-  _LIBCPP_INLINE_VISIBILITY
-  bool is_fifo(error_code& __ec) const noexcept {
-    return __get_ft(&__ec) == file_type::fifo;
-  }
-
-  _LIBCPP_INLINE_VISIBILITY
-  bool is_other() const { return _VSTD_FS::is_other(file_status{__get_ft()}); }
-
-  _LIBCPP_INLINE_VISIBILITY
-  bool is_other(error_code& __ec) const noexcept {
-    return _VSTD_FS::is_other(file_status{__get_ft(&__ec)});
-  }
-
-  _LIBCPP_INLINE_VISIBILITY
-  bool is_regular_file() const { return __get_ft() == file_type::regular; }
-
-  _LIBCPP_INLINE_VISIBILITY
-  bool is_regular_file(error_code& __ec) const noexcept {
-    return __get_ft(&__ec) == file_type::regular;
-  }
-
-  _LIBCPP_INLINE_VISIBILITY
-  bool is_socket() const { return __get_ft() == file_type::socket; }
-
-  _LIBCPP_INLINE_VISIBILITY
-  bool is_socket(error_code& __ec) const noexcept {
-    return __get_ft(&__ec) == file_type::socket;
-  }
-
-  _LIBCPP_INLINE_VISIBILITY
-  bool is_symlink() const { return __get_sym_ft() == file_type::symlink; }
-
-  _LIBCPP_INLINE_VISIBILITY
-  bool is_symlink(error_code& __ec) const noexcept {
-    return __get_sym_ft(&__ec) == file_type::symlink;
-  }
-  _LIBCPP_INLINE_VISIBILITY
-  uintmax_t file_size() const { return __get_size(); }
-
-  _LIBCPP_INLINE_VISIBILITY
-  uintmax_t file_size(error_code& __ec) const noexcept {
-    return __get_size(&__ec);
-  }
-
-  _LIBCPP_INLINE_VISIBILITY
-  uintmax_t hard_link_count() const { return __get_nlink(); }
-
-  _LIBCPP_INLINE_VISIBILITY
-  uintmax_t hard_link_count(error_code& __ec) const noexcept {
-    return __get_nlink(&__ec);
-  }
-
-  _LIBCPP_INLINE_VISIBILITY
-  file_time_type last_write_time() const { return __get_write_time(); }
-
-  _LIBCPP_INLINE_VISIBILITY
-  file_time_type last_write_time(error_code& __ec) const noexcept {
-    return __get_write_time(&__ec);
-  }
-
-  _LIBCPP_INLINE_VISIBILITY
-  file_status status() const { return __get_status(); }
-
-  _LIBCPP_INLINE_VISIBILITY
-  file_status status(error_code& __ec) const noexcept {
-    return __get_status(&__ec);
-  }
-
-  _LIBCPP_INLINE_VISIBILITY
-  file_status symlink_status() const { return __get_symlink_status(); }
-
-  _LIBCPP_INLINE_VISIBILITY
-  file_status symlink_status(error_code& __ec) const noexcept {
-    return __get_symlink_status(&__ec);
-  }
-
-  _LIBCPP_INLINE_VISIBILITY
-  bool operator<(directory_entry const& __rhs) const noexcept {
-    return __p_ < __rhs.__p_;
-  }
-
-  _LIBCPP_INLINE_VISIBILITY
-  bool operator==(directory_entry const& __rhs) const noexcept {
-    return __p_ == __rhs.__p_;
-  }
-
-  _LIBCPP_INLINE_VISIBILITY
-  bool operator!=(directory_entry const& __rhs) const noexcept {
-    return __p_ != __rhs.__p_;
-  }
-
-  _LIBCPP_INLINE_VISIBILITY
-  bool operator<=(directory_entry const& __rhs) const noexcept {
-    return __p_ <= __rhs.__p_;
-  }
-
-  _LIBCPP_INLINE_VISIBILITY
-  bool operator>(directory_entry const& __rhs) const noexcept {
-    return __p_ > __rhs.__p_;
-  }
-
-  _LIBCPP_INLINE_VISIBILITY
-  bool operator>=(directory_entry const& __rhs) const noexcept {
-    return __p_ >= __rhs.__p_;
-  }
-
-private:
-  friend class directory_iterator;
-  friend class recursive_directory_iterator;
-  friend class __dir_stream;
-
-  enum _CacheType : unsigned char {
-    _Empty,
-    _IterSymlink,
-    _IterNonSymlink,
-    _RefreshSymlink,
-    _RefreshSymlinkUnresolved,
-    _RefreshNonSymlink
-  };
-
-  struct __cached_data {
-    uintmax_t __size_;
-    uintmax_t __nlink_;
-    file_time_type __write_time_;
-    perms __sym_perms_;
-    perms __non_sym_perms_;
-    file_type __type_;
-    _CacheType __cache_type_;
-
-    _LIBCPP_INLINE_VISIBILITY
-    __cached_data() noexcept { __reset(); }
-
-    _LIBCPP_INLINE_VISIBILITY
-    void __reset() {
-      __cache_type_ = _Empty;
-      __type_ = file_type::none;
-      __sym_perms_ = __non_sym_perms_ = perms::unknown;
-      __size_ = __nlink_ = uintmax_t(-1);
-      __write_time_ = file_time_type::min();
-    }
-  };
-
-  _LIBCPP_INLINE_VISIBILITY
-  static __cached_data __create_iter_result(file_type __ft) {
-    __cached_data __data;
-    __data.__type_ = __ft;
-    __data.__cache_type_ = [&]() {
-      switch (__ft) {
-      case file_type::none:
-        return _Empty;
-      case file_type::symlink:
-        return _IterSymlink;
-      default:
-        return _IterNonSymlink;
-      }
-    }();
-    return __data;
-  }
-
-  _LIBCPP_INLINE_VISIBILITY
-  void __assign_iter_entry(_Path&& __p, __cached_data __dt) {
-    __p_ = std::move(__p);
-    __data_ = __dt;
-  }
-
-  _LIBCPP_FUNC_VIS
-  error_code __do_refresh() noexcept;
-
-  _LIBCPP_INLINE_VISIBILITY
-  static bool __is_dne_error(error_code const& __ec) {
-    if (!__ec)
-      return true;
-    switch (static_cast<errc>(__ec.value())) {
-    case errc::no_such_file_or_directory:
-    case errc::not_a_directory:
-      return true;
-    default:
-      return false;
-    }
-  }
-
-  _LIBCPP_INLINE_VISIBILITY
-  void __handle_error(const char* __msg, error_code* __dest_ec,
-                      error_code const& __ec, bool __allow_dne = false) const {
-    if (__dest_ec) {
-      *__dest_ec = __ec;
-      return;
-    }
-    if (__ec && (!__allow_dne || !__is_dne_error(__ec)))
-      __throw_filesystem_error(__msg, __p_, __ec);
-  }
-
-  _LIBCPP_INLINE_VISIBILITY
-  void __refresh(error_code* __ec = nullptr) {
-    __handle_error("in directory_entry::refresh", __ec, __do_refresh(),
-                   /*allow_dne*/ true);
-  }
-
-  _LIBCPP_INLINE_VISIBILITY
-  file_type __get_sym_ft(error_code* __ec = nullptr) const {
-    switch (__data_.__cache_type_) {
-    case _Empty:
-      return __symlink_status(__p_, __ec).type();
-    case _IterSymlink:
-    case _RefreshSymlink:
-    case _RefreshSymlinkUnresolved:
-      if (__ec)
-        __ec->clear();
-      return file_type::symlink;
-    case _IterNonSymlink:
-    case _RefreshNonSymlink:
-      file_status __st(__data_.__type_);
-      if (__ec && !_VSTD_FS::exists(__st))
-        *__ec = make_error_code(errc::no_such_file_or_directory);
-      else if (__ec)
-        __ec->clear();
-      return __data_.__type_;
-    }
-    _LIBCPP_UNREACHABLE();
-  }
-
-  _LIBCPP_INLINE_VISIBILITY
-  file_type __get_ft(error_code* __ec = nullptr) const {
-    switch (__data_.__cache_type_) {
-    case _Empty:
-    case _IterSymlink:
-    case _RefreshSymlinkUnresolved:
-      return __status(__p_, __ec).type();
-    case _IterNonSymlink:
-    case _RefreshNonSymlink:
-    case _RefreshSymlink: {
-      file_status __st(__data_.__type_);
-      if (__ec && !_VSTD_FS::exists(__st))
-        *__ec = make_error_code(errc::no_such_file_or_directory);
-      else if (__ec)
-        __ec->clear();
-      return __data_.__type_;
-    }
-    }
-    _LIBCPP_UNREACHABLE();
-  }
-
-  _LIBCPP_INLINE_VISIBILITY
-  file_status __get_status(error_code* __ec = nullptr) const {
-    switch (__data_.__cache_type_) {
-    case _Empty:
-    case _IterNonSymlink:
-    case _IterSymlink:
-    case _RefreshSymlinkUnresolved:
-      return __status(__p_, __ec);
-    case _RefreshNonSymlink:
-    case _RefreshSymlink:
-      return file_status(__get_ft(__ec), __data_.__non_sym_perms_);
-    }
-    _LIBCPP_UNREACHABLE();
-  }
-
-  _LIBCPP_INLINE_VISIBILITY
-  file_status __get_symlink_status(error_code* __ec = nullptr) const {
-    switch (__data_.__cache_type_) {
-    case _Empty:
-    case _IterNonSymlink:
-    case _IterSymlink:
-      return __symlink_status(__p_, __ec);
-    case _RefreshNonSymlink:
-      return file_status(__get_sym_ft(__ec), __data_.__non_sym_perms_);
-    case _RefreshSymlink:
-    case _RefreshSymlinkUnresolved:
-      return file_status(__get_sym_ft(__ec), __data_.__sym_perms_);
-    }
-    _LIBCPP_UNREACHABLE();
-  }
-
-  _LIBCPP_INLINE_VISIBILITY
-  uintmax_t __get_size(error_code* __ec = nullptr) const {
-    switch (__data_.__cache_type_) {
-    case _Empty:
-    case _IterNonSymlink:
-    case _IterSymlink:
-    case _RefreshSymlinkUnresolved:
-      return _VSTD_FS::__file_size(__p_, __ec);
-    case _RefreshSymlink:
-    case _RefreshNonSymlink: {
-      error_code __m_ec;
-      file_status __st(__get_ft(&__m_ec));
-      __handle_error("in directory_entry::file_size", __ec, __m_ec);
-      if (_VSTD_FS::exists(__st) && !_VSTD_FS::is_regular_file(__st)) {
-        errc __err_kind = _VSTD_FS::is_directory(__st) ? errc::is_a_directory
-                                                       : errc::not_supported;
-        __handle_error("in directory_entry::file_size", __ec,
-                       make_error_code(__err_kind));
-      }
-      return __data_.__size_;
-    }
-    }
-    _LIBCPP_UNREACHABLE();
-  }
-
-  _LIBCPP_INLINE_VISIBILITY
-  uintmax_t __get_nlink(error_code* __ec = nullptr) const {
-    switch (__data_.__cache_type_) {
-    case _Empty:
-    case _IterNonSymlink:
-    case _IterSymlink:
-    case _RefreshSymlinkUnresolved:
-      return _VSTD_FS::__hard_link_count(__p_, __ec);
-    case _RefreshSymlink:
-    case _RefreshNonSymlink: {
-      error_code __m_ec;
-      (void)__get_ft(&__m_ec);
-      __handle_error("in directory_entry::hard_link_count", __ec, __m_ec);
-      return __data_.__nlink_;
-    }
-    }
-    _LIBCPP_UNREACHABLE();
-  }
-
-  _LIBCPP_INLINE_VISIBILITY
-  file_time_type __get_write_time(error_code* __ec = nullptr) const {
-    switch (__data_.__cache_type_) {
-    case _Empty:
-    case _IterNonSymlink:
-    case _IterSymlink:
-    case _RefreshSymlinkUnresolved:
-      return _VSTD_FS::__last_write_time(__p_, __ec);
-    case _RefreshSymlink:
-    case _RefreshNonSymlink: {
-      error_code __m_ec;
-      file_status __st(__get_ft(&__m_ec));
-      __handle_error("in directory_entry::last_write_time", __ec, __m_ec);
-      if (_VSTD_FS::exists(__st) &&
-          __data_.__write_time_ == file_time_type::min())
-        __handle_error("in directory_entry::last_write_time", __ec,
-                       make_error_code(errc::value_too_large));
-      return __data_.__write_time_;
-    }
-    }
-    _LIBCPP_UNREACHABLE();
-  }
-
-private:
-  _Path __p_;
-  __cached_data __data_;
-};
-
-class __dir_element_proxy {
-public:
-  inline _LIBCPP_INLINE_VISIBILITY directory_entry operator*() {
-    return _VSTD::move(__elem_);
-  }
-
-private:
-  friend class directory_iterator;
-  friend class recursive_directory_iterator;
-  explicit __dir_element_proxy(directory_entry const& __e) : __elem_(__e) {}
-  __dir_element_proxy(__dir_element_proxy&& __o)
-      : __elem_(_VSTD::move(__o.__elem_)) {}
-  directory_entry __elem_;
-};
-
-class directory_iterator {
-public:
-  typedef directory_entry value_type;
-  typedef ptrdiff_t difference_type;
-  typedef value_type const* pointer;
-  typedef value_type const& reference;
-  typedef input_iterator_tag iterator_category;
-
-public:
-  //ctor & dtor
-  directory_iterator() noexcept {}
-
-  explicit directory_iterator(const path& __p)
-      : directory_iterator(__p, nullptr) {}
-
-  directory_iterator(const path& __p, directory_options __opts)
-      : directory_iterator(__p, nullptr, __opts) {}
-
-  directory_iterator(const path& __p, error_code& __ec)
-      : directory_iterator(__p, &__ec) {}
-
-  directory_iterator(const path& __p, directory_options __opts,
-                     error_code& __ec)
-      : directory_iterator(__p, &__ec, __opts) {}
-
-  directory_iterator(const directory_iterator&) = default;
-  directory_iterator(directory_iterator&&) = default;
-  directory_iterator& operator=(const directory_iterator&) = default;
-
-  directory_iterator& operator=(directory_iterator&& __o) noexcept {
-    // non-default implementation provided to support self-move assign.
-    if (this != &__o) {
-      __imp_ = _VSTD::move(__o.__imp_);
-    }
-    return *this;
-  }
-
-  ~directory_iterator() = default;
-
-  const directory_entry& operator*() const {
-    _LIBCPP_ASSERT(__imp_, "The end iterator cannot be dereferenced");
-    return __dereference();
-  }
-
-  const directory_entry* operator->() const { return &**this; }
-
-  directory_iterator& operator++() { return __increment(); }
-
-  __dir_element_proxy operator++(int) {
-    __dir_element_proxy __p(**this);
-    __increment();
-    return __p;
-  }
-
-  directory_iterator& increment(error_code& __ec) { return __increment(&__ec); }
-
-private:
-  inline _LIBCPP_INLINE_VISIBILITY friend bool
-  operator==(const directory_iterator& __lhs,
-             const directory_iterator& __rhs) noexcept;
-
-  // construct the dir_stream
-  _LIBCPP_FUNC_VIS
-  directory_iterator(const path&, error_code*,
-                     directory_options = directory_options::none);
-
-  _LIBCPP_FUNC_VIS
-  directory_iterator& __increment(error_code* __ec = nullptr);
-
-  _LIBCPP_FUNC_VIS
-  const directory_entry& __dereference() const;
-
-private:
-  shared_ptr<__dir_stream> __imp_;
-};
-
-inline _LIBCPP_INLINE_VISIBILITY bool
-operator==(const directory_iterator& __lhs,
-           const directory_iterator& __rhs) noexcept {
-  return __lhs.__imp_ == __rhs.__imp_;
-}
-
-inline _LIBCPP_INLINE_VISIBILITY bool
-operator!=(const directory_iterator& __lhs,
-           const directory_iterator& __rhs) noexcept {
-  return !(__lhs == __rhs);
-}
-
-// enable directory_iterator range-based for statements
-inline _LIBCPP_INLINE_VISIBILITY directory_iterator
-begin(directory_iterator __iter) noexcept {
-  return __iter;
-}
-
-inline _LIBCPP_INLINE_VISIBILITY directory_iterator
-end(const directory_iterator&) noexcept {
-  return directory_iterator();
-}
-
-class recursive_directory_iterator {
-public:
-  using value_type = directory_entry;
-  using difference_type = std::ptrdiff_t;
-  using pointer = directory_entry const*;
-  using reference = directory_entry const&;
-  using iterator_category = std::input_iterator_tag;
-
-public:
-  // constructors and destructor
-  _LIBCPP_INLINE_VISIBILITY
-  recursive_directory_iterator() noexcept : __rec_(false) {}
-
-  _LIBCPP_INLINE_VISIBILITY
-  explicit recursive_directory_iterator(
-      const path& __p, directory_options __xoptions = directory_options::none)
-      : recursive_directory_iterator(__p, __xoptions, nullptr) {}
-
-  _LIBCPP_INLINE_VISIBILITY
-  recursive_directory_iterator(const path& __p, directory_options __xoptions,
-                               error_code& __ec)
-      : recursive_directory_iterator(__p, __xoptions, &__ec) {}
-
-  _LIBCPP_INLINE_VISIBILITY
-  recursive_directory_iterator(const path& __p, error_code& __ec)
-      : recursive_directory_iterator(__p, directory_options::none, &__ec) {}
-
-  recursive_directory_iterator(const recursive_directory_iterator&) = default;
-  recursive_directory_iterator(recursive_directory_iterator&&) = default;
-
-  recursive_directory_iterator&
-  operator=(const recursive_directory_iterator&) = default;
-
-  _LIBCPP_INLINE_VISIBILITY
-  recursive_directory_iterator&
-  operator=(recursive_directory_iterator&& __o) noexcept {
-    // non-default implementation provided to support self-move assign.
-    if (this != &__o) {
-      __imp_ = _VSTD::move(__o.__imp_);
-      __rec_ = __o.__rec_;
-    }
-    return *this;
-  }
-
-  ~recursive_directory_iterator() = default;
-
-  _LIBCPP_INLINE_VISIBILITY
-  const directory_entry& operator*() const { return __dereference(); }
-
-  _LIBCPP_INLINE_VISIBILITY
-  const directory_entry* operator->() const { return &__dereference(); }
-
-  recursive_directory_iterator& operator++() { return __increment(); }
-
-  _LIBCPP_INLINE_VISIBILITY
-  __dir_element_proxy operator++(int) {
-    __dir_element_proxy __p(**this);
-    __increment();
-    return __p;
-  }
-
-  _LIBCPP_INLINE_VISIBILITY
-  recursive_directory_iterator& increment(error_code& __ec) {
-    return __increment(&__ec);
-  }
-
-  _LIBCPP_FUNC_VIS directory_options options() const;
-  _LIBCPP_FUNC_VIS int depth() const;
-
-  _LIBCPP_INLINE_VISIBILITY
-  void pop() { __pop(); }
-
-  _LIBCPP_INLINE_VISIBILITY
-  void pop(error_code& __ec) { __pop(&__ec); }
-
-  _LIBCPP_INLINE_VISIBILITY
-  bool recursion_pending() const { return __rec_; }
-
-  _LIBCPP_INLINE_VISIBILITY
-  void disable_recursion_pending() { __rec_ = false; }
-
-private:
-  recursive_directory_iterator(const path& __p, directory_options __opt,
-                               error_code* __ec);
-
-  _LIBCPP_FUNC_VIS
-  const directory_entry& __dereference() const;
-
-  _LIBCPP_FUNC_VIS
-  bool __try_recursion(error_code* __ec);
-
-  _LIBCPP_FUNC_VIS
-  void __advance(error_code* __ec = nullptr);
-
-  _LIBCPP_FUNC_VIS
-  recursive_directory_iterator& __increment(error_code* __ec = nullptr);
-
-  _LIBCPP_FUNC_VIS
-  void __pop(error_code* __ec = nullptr);
-
-  inline _LIBCPP_INLINE_VISIBILITY friend bool
-  operator==(const recursive_directory_iterator&,
-             const recursive_directory_iterator&) noexcept;
-
-  struct __shared_imp;
-  shared_ptr<__shared_imp> __imp_;
-  bool __rec_;
-}; // class recursive_directory_iterator
-
-inline _LIBCPP_INLINE_VISIBILITY bool
-operator==(const recursive_directory_iterator& __lhs,
-           const recursive_directory_iterator& __rhs) noexcept {
-  return __lhs.__imp_ == __rhs.__imp_;
-}
-
-_LIBCPP_INLINE_VISIBILITY
-inline bool operator!=(const recursive_directory_iterator& __lhs,
-                       const recursive_directory_iterator& __rhs) noexcept {
-  return !(__lhs == __rhs);
-}
-// enable recursive_directory_iterator range-based for statements
-inline _LIBCPP_INLINE_VISIBILITY recursive_directory_iterator
-begin(recursive_directory_iterator __iter) noexcept {
-  return __iter;
-}
-
-inline _LIBCPP_INLINE_VISIBILITY recursive_directory_iterator
-end(const recursive_directory_iterator&) noexcept {
-  return recursive_directory_iterator();
-}
-
-}  // namespace android::hardware::automotive::filesystem
-#ifdef _LIBAUTO_UNDEF_VSTD
-#undef _VSTD
-#undef _LIBAUTO_UNDEF_VSTD
-#endif
-
-#ifndef _LIBAUTO_UNDEF_VSTD_FS
-#pragma pop_macro("_VSTD_FS")
-#else
-#undef _VSTD
-#undef _LIBAUTO_UNDEF_VSTD_FS
-#endif
-
-#endif // !_LIBCPP_CXX03_LANG
-
-_LIBCPP_POP_MACROS
-
-#endif  // defined(_LIBCPP_VERSION) && _LIBCPP_VERSION > 8000
-
-#endif // _LIBAUTO_FILESYSTEM
diff --git a/automotive/can/1.0/default/libc++fs/src/filesystem/directory_iterator.cpp b/automotive/can/1.0/default/libc++fs/src/filesystem/directory_iterator.cpp
deleted file mode 100644
index 0dbf492..0000000
--- a/automotive/can/1.0/default/libc++fs/src/filesystem/directory_iterator.cpp
+++ /dev/null
@@ -1,405 +0,0 @@
-//===------------------ directory_iterator.cpp ----------------------------===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// TODO(152067309): Remove this once the libc++ upgrade is complete.
-#include <__config>
-#if defined(_LIBCPP_VERSION) && _LIBCPP_VERSION <= 8000
-
-/* clang-format off */
-#include "automotive/filesystem"
-#include <__config>
-
-#if defined(_LIBCPP_WIN32API)
-#define WIN32_LEAN_AND_MEAN
-#include <Windows.h>
-#else
-#include <dirent.h>
-#endif
-#include <errno.h>
-
-#include "filesystem_common.h"
-
-namespace android::hardware::automotive::filesystem {
-
-namespace detail {
-namespace {
-
-#if !defined(_LIBCPP_WIN32API)
-template <class DirEntT, class = decltype(DirEntT::d_type)>
-static file_type get_file_type(DirEntT* ent, int) {
-  switch (ent->d_type) {
-  case DT_BLK:
-    return file_type::block;
-  case DT_CHR:
-    return file_type::character;
-  case DT_DIR:
-    return file_type::directory;
-  case DT_FIFO:
-    return file_type::fifo;
-  case DT_LNK:
-    return file_type::symlink;
-  case DT_REG:
-    return file_type::regular;
-  case DT_SOCK:
-    return file_type::socket;
-  // Unlike in lstat, hitting "unknown" here simply means that the underlying
-  // filesystem doesn't support d_type. Report is as 'none' so we correctly
-  // set the cache to empty.
-  case DT_UNKNOWN:
-    break;
-  }
-  return file_type::none;
-}
-
-template <class DirEntT>
-static file_type get_file_type(DirEntT* ent, long) {
-  return file_type::none;
-}
-
-static pair<string_view, file_type> posix_readdir(DIR* dir_stream,
-                                                  error_code& ec) {
-  struct dirent* dir_entry_ptr = nullptr;
-  errno = 0; // zero errno in order to detect errors
-  ec.clear();
-  if ((dir_entry_ptr = ::readdir(dir_stream)) == nullptr) {
-    if (errno)
-      ec = capture_errno();
-    return {};
-  } else {
-    return {dir_entry_ptr->d_name, get_file_type(dir_entry_ptr, 0)};
-  }
-}
-#else
-
-static file_type get_file_type(const WIN32_FIND_DATA& data) {
-  //auto attrs = data.dwFileAttributes;
-  // FIXME(EricWF)
-  return file_type::unknown;
-}
-static uintmax_t get_file_size(const WIN32_FIND_DATA& data) {
-  return (data.nFileSizeHight * (MAXDWORD + 1)) + data.nFileSizeLow;
-}
-static file_time_type get_write_time(const WIN32_FIND_DATA& data) {
-  ULARGE_INTEGER tmp;
-  FILETIME& time = data.ftLastWriteTime;
-  tmp.u.LowPart = time.dwLowDateTime;
-  tmp.u.HighPart = time.dwHighDateTime;
-  return file_time_type(file_time_type::duration(time.QuadPart));
-}
-
-#endif
-
-} // namespace
-} // namespace detail
-
-using detail::ErrorHandler;
-
-#if defined(_LIBCPP_WIN32API)
-class __dir_stream {
-public:
-  __dir_stream() = delete;
-  __dir_stream& operator=(const __dir_stream&) = delete;
-
-  __dir_stream(__dir_stream&& __ds) noexcept : __stream_(__ds.__stream_),
-                                               __root_(move(__ds.__root_)),
-                                               __entry_(move(__ds.__entry_)) {
-    __ds.__stream_ = INVALID_HANDLE_VALUE;
-  }
-
-  __dir_stream(const path& root, directory_options opts, error_code& ec)
-      : __stream_(INVALID_HANDLE_VALUE), __root_(root) {
-    __stream_ = ::FindFirstFileEx(root.c_str(), &__data_);
-    if (__stream_ == INVALID_HANDLE_VALUE) {
-      ec = error_code(::GetLastError(), generic_category());
-      const bool ignore_permission_denied =
-          bool(opts & directory_options::skip_permission_denied);
-      if (ignore_permission_denied && ec.value() == ERROR_ACCESS_DENIED)
-        ec.clear();
-      return;
-    }
-  }
-
-  ~__dir_stream() noexcept {
-    if (__stream_ == INVALID_HANDLE_VALUE)
-      return;
-    close();
-  }
-
-  bool good() const noexcept { return __stream_ != INVALID_HANDLE_VALUE; }
-
-  bool advance(error_code& ec) {
-    while (::FindNextFile(__stream_, &__data_)) {
-      if (!strcmp(__data_.cFileName, ".") || strcmp(__data_.cFileName, ".."))
-        continue;
-      // FIXME: Cache more of this
-      //directory_entry::__cached_data cdata;
-      //cdata.__type_ = get_file_type(__data_);
-      //cdata.__size_ = get_file_size(__data_);
-      //cdata.__write_time_ = get_write_time(__data_);
-      __entry_.__assign_iter_entry(
-          __root_ / __data_.cFileName,
-          directory_entry::__create_iter_result(get_file_type(__data)));
-      return true;
-    }
-    ec = error_code(::GetLastError(), generic_category());
-    close();
-    return false;
-  }
-
-private:
-  error_code close() noexcept {
-    error_code ec;
-    if (!::FindClose(__stream_))
-      ec = error_code(::GetLastError(), generic_category());
-    __stream_ = INVALID_HANDLE_VALUE;
-    return ec;
-  }
-
-  HANDLE __stream_{INVALID_HANDLE_VALUE};
-  WIN32_FIND_DATA __data_;
-
-public:
-  path __root_;
-  directory_entry __entry_;
-};
-#else
-class __dir_stream {
-public:
-  __dir_stream() = delete;
-  __dir_stream& operator=(const __dir_stream&) = delete;
-
-  __dir_stream(__dir_stream&& other) noexcept : __stream_(other.__stream_),
-                                                __root_(std::move(other.__root_)),
-                                                __entry_(std::move(other.__entry_)) {
-    other.__stream_ = nullptr;
-  }
-
-  __dir_stream(const path& root, directory_options opts, error_code& ec)
-      : __stream_(nullptr), __root_(root) {
-    if ((__stream_ = ::opendir(root.c_str())) == nullptr) {
-      ec = detail::capture_errno();
-      const bool allow_eacess =
-          bool(opts & directory_options::skip_permission_denied);
-      if (allow_eacess && ec.value() == EACCES)
-        ec.clear();
-      return;
-    }
-    advance(ec);
-  }
-
-  ~__dir_stream() noexcept {
-    if (__stream_)
-      close();
-  }
-
-  bool good() const noexcept { return __stream_ != nullptr; }
-
-  bool advance(error_code& ec) {
-    while (true) {
-      auto str_type_pair = detail::posix_readdir(__stream_, ec);
-      auto& str = str_type_pair.first;
-      if (str == "." || str == "..") {
-        continue;
-      } else if (ec || str.empty()) {
-        close();
-        return false;
-      } else {
-        __entry_.__assign_iter_entry(
-            __root_ / str,
-            directory_entry::__create_iter_result(str_type_pair.second));
-        return true;
-      }
-    }
-  }
-
-private:
-  error_code close() noexcept {
-    error_code m_ec;
-    if (::closedir(__stream_) == -1)
-      m_ec = detail::capture_errno();
-    __stream_ = nullptr;
-    return m_ec;
-  }
-
-  DIR* __stream_{nullptr};
-
-public:
-  path __root_;
-  directory_entry __entry_;
-};
-#endif
-
-// directory_iterator
-
-directory_iterator::directory_iterator(const path& p, error_code* ec,
-                                       directory_options opts) {
-  ErrorHandler<void> err("directory_iterator::directory_iterator(...)", ec, &p);
-
-  error_code m_ec;
-  __imp_ = make_shared<__dir_stream>(p, opts, m_ec);
-  if (ec)
-    *ec = m_ec;
-  if (!__imp_->good()) {
-    __imp_.reset();
-    if (m_ec)
-      err.report(m_ec);
-  }
-}
-
-directory_iterator& directory_iterator::__increment(error_code* ec) {
-  _LIBCPP_ASSERT(__imp_, "Attempting to increment an invalid iterator");
-  ErrorHandler<void> err("directory_iterator::operator++()", ec);
-
-  error_code m_ec;
-  if (!__imp_->advance(m_ec)) {
-    path root = std::move(__imp_->__root_);
-    __imp_.reset();
-    if (m_ec)
-      err.report(m_ec, "at root \"%s\"", root);
-  }
-  return *this;
-}
-
-directory_entry const& directory_iterator::__dereference() const {
-  _LIBCPP_ASSERT(__imp_, "Attempting to dereference an invalid iterator");
-  return __imp_->__entry_;
-}
-
-// recursive_directory_iterator
-
-struct recursive_directory_iterator::__shared_imp {
-  stack<__dir_stream> __stack_;
-  directory_options __options_;
-};
-
-recursive_directory_iterator::recursive_directory_iterator(
-    const path& p, directory_options opt, error_code* ec)
-    : __imp_(nullptr), __rec_(true) {
-  ErrorHandler<void> err("recursive_directory_iterator", ec, &p);
-
-  error_code m_ec;
-  __dir_stream new_s(p, opt, m_ec);
-  if (m_ec)
-    err.report(m_ec);
-  if (m_ec || !new_s.good())
-    return;
-
-  __imp_ = make_shared<__shared_imp>();
-  __imp_->__options_ = opt;
-  __imp_->__stack_.push(std::move(new_s));
-}
-
-void recursive_directory_iterator::__pop(error_code* ec) {
-  _LIBCPP_ASSERT(__imp_, "Popping the end iterator");
-  if (ec)
-    ec->clear();
-  __imp_->__stack_.pop();
-  if (__imp_->__stack_.size() == 0)
-    __imp_.reset();
-  else
-    __advance(ec);
-}
-
-directory_options recursive_directory_iterator::options() const {
-  return __imp_->__options_;
-}
-
-int recursive_directory_iterator::depth() const {
-  return __imp_->__stack_.size() - 1;
-}
-
-const directory_entry& recursive_directory_iterator::__dereference() const {
-  return __imp_->__stack_.top().__entry_;
-}
-
-recursive_directory_iterator&
-recursive_directory_iterator::__increment(error_code* ec) {
-  if (ec)
-    ec->clear();
-  if (recursion_pending()) {
-    if (__try_recursion(ec) || (ec && *ec))
-      return *this;
-  }
-  __rec_ = true;
-  __advance(ec);
-  return *this;
-}
-
-void recursive_directory_iterator::__advance(error_code* ec) {
-  ErrorHandler<void> err("recursive_directory_iterator::operator++()", ec);
-
-  const directory_iterator end_it;
-  auto& stack = __imp_->__stack_;
-  error_code m_ec;
-  while (stack.size() > 0) {
-    if (stack.top().advance(m_ec))
-      return;
-    if (m_ec)
-      break;
-    stack.pop();
-  }
-
-  if (m_ec) {
-    path root = std::move(stack.top().__root_);
-    __imp_.reset();
-    err.report(m_ec, "at root \"%s\"", root);
-  } else {
-    __imp_.reset();
-  }
-}
-
-bool recursive_directory_iterator::__try_recursion(error_code* ec) {
-  ErrorHandler<void> err("recursive_directory_iterator::operator++()", ec);
-
-  bool rec_sym = bool(options() & directory_options::follow_directory_symlink);
-
-  auto& curr_it = __imp_->__stack_.top();
-
-  bool skip_rec = false;
-  error_code m_ec;
-  if (!rec_sym) {
-    file_status st(curr_it.__entry_.__get_sym_ft(&m_ec));
-    if (m_ec && status_known(st))
-      m_ec.clear();
-    if (m_ec || is_symlink(st) || !is_directory(st))
-      skip_rec = true;
-  } else {
-    file_status st(curr_it.__entry_.__get_ft(&m_ec));
-    if (m_ec && status_known(st))
-      m_ec.clear();
-    if (m_ec || !is_directory(st))
-      skip_rec = true;
-  }
-
-  if (!skip_rec) {
-    __dir_stream new_it(curr_it.__entry_.path(), __imp_->__options_, m_ec);
-    if (new_it.good()) {
-      __imp_->__stack_.push(std::move(new_it));
-      return true;
-    }
-  }
-  if (m_ec) {
-    const bool allow_eacess =
-        bool(__imp_->__options_ & directory_options::skip_permission_denied);
-    if (m_ec.value() == EACCES && allow_eacess) {
-      if (ec)
-        ec->clear();
-    } else {
-      path at_ent = std::move(curr_it.__entry_.__p_);
-      __imp_.reset();
-      err.report(m_ec, "attempting recursion into \"%s\"", at_ent);
-    }
-  }
-  return false;
-}
-
-}  // namespace android::hardware::automotive::filesystem
-/* clang-format on */
-
-#endif // defined(_LIBCPP_VERSION) && _LIBCPP_VERSION <= 8000
diff --git a/automotive/can/1.0/default/libc++fs/src/filesystem/filesystem_common.h b/automotive/can/1.0/default/libc++fs/src/filesystem/filesystem_common.h
deleted file mode 100644
index 4f44661..0000000
--- a/automotive/can/1.0/default/libc++fs/src/filesystem/filesystem_common.h
+++ /dev/null
@@ -1,441 +0,0 @@
-//===----------------------------------------------------------------------===////
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===////
-/* clang-format off */
-#ifndef AUTO_FILESYSTEM_COMMON_H
-#define AUTO_FILESYSTEM_COMMON_H
-
-#include "automotive/filesystem"
-#include <array>
-#include <chrono>
-#include <cstdlib>
-#include <climits>
-
-#include <unistd.h>
-#include <sys/stat.h>
-#include <sys/statvfs.h>
-#include <sys/time.h> // for ::utimes as used in __last_write_time
-#include <fcntl.h>    /* values for fchmodat */
-
-#if !defined(__APPLE__)
-// We can use the presence of UTIME_OMIT to detect platforms that provide
-// utimensat.
-#if defined(UTIME_OMIT)
-#define _LIBCPP_USE_UTIMENSAT
-#endif
-#endif
-
-#if defined(__GNUC__)
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wunused-function"
-#endif
-
-namespace android::hardware::automotive::filesystem {
-using namespace std::chrono;
-
-using std::error_code;
-using std::is_floating_point;
-using std::micro;
-using std::nano;
-using std::ratio;
-
-namespace detail {
-namespace {
-
-static string format_string_imp(const char* msg, ...) {
-  // we might need a second shot at this, so pre-emptivly make a copy
-  struct GuardVAList {
-    va_list& target;
-    bool active = true;
-    GuardVAList(va_list& target) : target(target), active(true) {}
-    void clear() {
-      if (active)
-        va_end(target);
-      active = false;
-    }
-    ~GuardVAList() {
-      if (active)
-        va_end(target);
-    }
-  };
-  va_list args;
-  va_start(args, msg);
-  GuardVAList args_guard(args);
-
-  va_list args_cp;
-  va_copy(args_cp, args);
-  GuardVAList args_copy_guard(args_cp);
-
-  std::string result;
-
-  array<char, 256> local_buff;
-  size_t size_with_null = local_buff.size();
-  auto ret = ::vsnprintf(local_buff.data(), size_with_null, msg, args_cp);
-
-  args_copy_guard.clear();
-
-  // handle empty expansion
-  if (ret == 0)
-    return result;
-  if (static_cast<size_t>(ret) < size_with_null) {
-    result.assign(local_buff.data(), static_cast<size_t>(ret));
-    return result;
-  }
-
-  // we did not provide a long enough buffer on our first attempt. The
-  // return value is the number of bytes (excluding the null byte) that are
-  // needed for formatting.
-  size_with_null = static_cast<size_t>(ret) + 1;
-  result.__resize_default_init(size_with_null - 1);
-  ret = ::vsnprintf(&result[0], size_with_null, msg, args);
-  _LIBCPP_ASSERT(static_cast<size_t>(ret) == (size_with_null - 1), "TODO");
-
-  return result;
-}
-
-const char* unwrap(string const& s) { return s.c_str(); }
-const char* unwrap(path const& p) { return p.native().c_str(); }
-template <class Arg>
-Arg const& unwrap(Arg const& a) {
-  static_assert(!is_class<Arg>::value, "cannot pass class here");
-  return a;
-}
-
-template <class... Args>
-string format_string(const char* fmt, Args const&... args) {
-  return format_string_imp(fmt, unwrap(args)...);
-}
-
-error_code capture_errno() {
-  _LIBCPP_ASSERT(errno, "Expected errno to be non-zero");
-  return error_code(errno, generic_category());
-}
-
-template <class T>
-T error_value();
-template <>
-_LIBCPP_CONSTEXPR_AFTER_CXX11 void error_value<void>() {}
-template <>
-bool error_value<bool>() {
-  return false;
-}
-template <>
-uintmax_t error_value<uintmax_t>() {
-  return uintmax_t(-1);
-}
-template <>
-_LIBCPP_CONSTEXPR_AFTER_CXX11 file_time_type error_value<file_time_type>() {
-  return file_time_type::min();
-}
-template <>
-path error_value<path>() {
-  return {};
-}
-
-template <class T>
-struct ErrorHandler {
-  const char* func_name;
-  error_code* ec = nullptr;
-  const path* p1 = nullptr;
-  const path* p2 = nullptr;
-
-  ErrorHandler(const char* fname, error_code* ec, const path* p1 = nullptr,
-               const path* p2 = nullptr)
-      : func_name(fname), ec(ec), p1(p1), p2(p2) {
-    if (ec)
-      ec->clear();
-  }
-
-  T report(const error_code& m_ec) const {
-    if (ec) {
-      *ec = m_ec;
-      return error_value<T>();
-    }
-    string what = string("in ") + func_name;
-    switch (bool(p1) + bool(p2)) {
-    case 0:
-      __throw_filesystem_error(what, m_ec);
-    case 1:
-      __throw_filesystem_error(what, *p1, m_ec);
-    case 2:
-      __throw_filesystem_error(what, *p1, *p2, m_ec);
-    }
-    _LIBCPP_UNREACHABLE();
-  }
-
-  template <class... Args>
-  T report(const error_code& m_ec, const char* msg, Args const&... args) const {
-    if (ec) {
-      *ec = m_ec;
-      return error_value<T>();
-    }
-    string what =
-        string("in ") + func_name + ": " + format_string(msg, args...);
-    switch (bool(p1) + bool(p2)) {
-    case 0:
-      __throw_filesystem_error(what, m_ec);
-    case 1:
-      __throw_filesystem_error(what, *p1, m_ec);
-    case 2:
-      __throw_filesystem_error(what, *p1, *p2, m_ec);
-    }
-    _LIBCPP_UNREACHABLE();
-  }
-
-  T report(errc const& err) const { return report(make_error_code(err)); }
-
-  template <class... Args>
-  T report(errc const& err, const char* msg, Args const&... args) const {
-    return report(make_error_code(err), msg, args...);
-  }
-
-private:
-  ErrorHandler(ErrorHandler const&) = delete;
-  ErrorHandler& operator=(ErrorHandler const&) = delete;
-};
-
-using chrono::duration;
-using chrono::duration_cast;
-
-using TimeSpec = struct ::timespec;
-using StatT = struct ::stat;
-
-template <class FileTimeT, class TimeT,
-          bool IsFloat = is_floating_point<typename FileTimeT::rep>::value>
-struct time_util_base {
-  using rep = typename FileTimeT::rep;
-  using fs_duration = typename FileTimeT::duration;
-  using fs_seconds = duration<rep>;
-  using fs_nanoseconds = duration<rep, nano>;
-  using fs_microseconds = duration<rep, micro>;
-
-  static constexpr rep max_seconds =
-      duration_cast<fs_seconds>(FileTimeT::duration::max()).count();
-
-  static constexpr rep max_nsec =
-      duration_cast<fs_nanoseconds>(FileTimeT::duration::max() -
-                                    fs_seconds(max_seconds))
-          .count();
-
-  static constexpr rep min_seconds =
-      duration_cast<fs_seconds>(FileTimeT::duration::min()).count();
-
-  static constexpr rep min_nsec_timespec =
-      duration_cast<fs_nanoseconds>(
-          (FileTimeT::duration::min() - fs_seconds(min_seconds)) +
-          fs_seconds(1))
-          .count();
-
-private:
-#if _LIBCPP_STD_VER > 11 && !defined(_LIBCPP_HAS_NO_CXX14_CONSTEXPR)
-  static constexpr fs_duration get_min_nsecs() {
-    return duration_cast<fs_duration>(
-        fs_nanoseconds(min_nsec_timespec) -
-        duration_cast<fs_nanoseconds>(fs_seconds(1)));
-  }
-  // Static assert that these values properly round trip.
-  static_assert(fs_seconds(min_seconds) + get_min_nsecs() ==
-                    FileTimeT::duration::min(),
-                "value doesn't roundtrip");
-
-  static constexpr bool check_range() {
-    // This kinda sucks, but it's what happens when we don't have __int128_t.
-    if (sizeof(TimeT) == sizeof(rep)) {
-      typedef duration<long long, ratio<3600 * 24 * 365> > Years;
-      return duration_cast<Years>(fs_seconds(max_seconds)) > Years(250) &&
-             duration_cast<Years>(fs_seconds(min_seconds)) < Years(-250);
-    }
-    return max_seconds >= numeric_limits<TimeT>::max() &&
-           min_seconds <= numeric_limits<TimeT>::min();
-  }
-  static_assert(check_range(), "the representable range is unacceptable small");
-#endif
-};
-
-template <class FileTimeT, class TimeT>
-struct time_util_base<FileTimeT, TimeT, true> {
-  using rep = typename FileTimeT::rep;
-  using fs_duration = typename FileTimeT::duration;
-  using fs_seconds = duration<rep>;
-  using fs_nanoseconds = duration<rep, nano>;
-  using fs_microseconds = duration<rep, micro>;
-
-  static const rep max_seconds;
-  static const rep max_nsec;
-  static const rep min_seconds;
-  static const rep min_nsec_timespec;
-};
-
-template <class FileTimeT, class TimeT>
-const typename FileTimeT::rep
-    time_util_base<FileTimeT, TimeT, true>::max_seconds =
-        duration_cast<fs_seconds>(FileTimeT::duration::max()).count();
-
-template <class FileTimeT, class TimeT>
-const typename FileTimeT::rep time_util_base<FileTimeT, TimeT, true>::max_nsec =
-    duration_cast<fs_nanoseconds>(FileTimeT::duration::max() -
-                                  fs_seconds(max_seconds))
-        .count();
-
-template <class FileTimeT, class TimeT>
-const typename FileTimeT::rep
-    time_util_base<FileTimeT, TimeT, true>::min_seconds =
-        duration_cast<fs_seconds>(FileTimeT::duration::min()).count();
-
-template <class FileTimeT, class TimeT>
-const typename FileTimeT::rep
-    time_util_base<FileTimeT, TimeT, true>::min_nsec_timespec =
-        duration_cast<fs_nanoseconds>((FileTimeT::duration::min() -
-                                       fs_seconds(min_seconds)) +
-                                      fs_seconds(1))
-            .count();
-
-template <class FileTimeT, class TimeT, class TimeSpecT>
-struct time_util : time_util_base<FileTimeT, TimeT> {
-  using Base = time_util_base<FileTimeT, TimeT>;
-  using Base::max_nsec;
-  using Base::max_seconds;
-  using Base::min_nsec_timespec;
-  using Base::min_seconds;
-
-  using typename Base::fs_duration;
-  using typename Base::fs_microseconds;
-  using typename Base::fs_nanoseconds;
-  using typename Base::fs_seconds;
-
-public:
-  template <class CType, class ChronoType>
-  static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool checked_set(CType* out,
-                                                        ChronoType time) {
-    using Lim = numeric_limits<CType>;
-    if (time > Lim::max() || time < Lim::min())
-      return false;
-    *out = static_cast<CType>(time);
-    return true;
-  }
-
-  static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool is_representable(TimeSpecT tm) {
-    if (tm.tv_sec >= 0) {
-      return tm.tv_sec < max_seconds ||
-             (tm.tv_sec == max_seconds && tm.tv_nsec <= max_nsec);
-    } else if (tm.tv_sec == (min_seconds - 1)) {
-      return tm.tv_nsec >= min_nsec_timespec;
-    } else {
-      return tm.tv_sec >= min_seconds;
-    }
-  }
-
-  static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool is_representable(FileTimeT tm) {
-    auto secs = duration_cast<fs_seconds>(tm.time_since_epoch());
-    auto nsecs = duration_cast<fs_nanoseconds>(tm.time_since_epoch() - secs);
-    if (nsecs.count() < 0) {
-      secs = secs + fs_seconds(1);
-      nsecs = nsecs + fs_seconds(1);
-    }
-    using TLim = numeric_limits<TimeT>;
-    if (secs.count() >= 0)
-      return secs.count() <= TLim::max();
-    return secs.count() >= TLim::min();
-  }
-
-  static _LIBCPP_CONSTEXPR_AFTER_CXX11 FileTimeT
-  convert_from_timespec(TimeSpecT tm) {
-    if (tm.tv_sec >= 0 || tm.tv_nsec == 0) {
-      return FileTimeT(fs_seconds(tm.tv_sec) +
-                       duration_cast<fs_duration>(fs_nanoseconds(tm.tv_nsec)));
-    } else { // tm.tv_sec < 0
-      auto adj_subsec = duration_cast<fs_duration>(fs_seconds(1) -
-                                                   fs_nanoseconds(tm.tv_nsec));
-      auto Dur = fs_seconds(tm.tv_sec + 1) - adj_subsec;
-      return FileTimeT(Dur);
-    }
-  }
-
-  template <class SubSecT>
-  static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool
-  set_times_checked(TimeT* sec_out, SubSecT* subsec_out, FileTimeT tp) {
-    auto dur = tp.time_since_epoch();
-    auto sec_dur = duration_cast<fs_seconds>(dur);
-    auto subsec_dur = duration_cast<fs_nanoseconds>(dur - sec_dur);
-    // The tv_nsec and tv_usec fields must not be negative so adjust accordingly
-    if (subsec_dur.count() < 0) {
-      if (sec_dur.count() > min_seconds) {
-        sec_dur = sec_dur - fs_seconds(1);
-        subsec_dur = subsec_dur + fs_seconds(1);
-      } else {
-        subsec_dur = fs_nanoseconds::zero();
-      }
-    }
-    return checked_set(sec_out, sec_dur.count()) &&
-           checked_set(subsec_out, subsec_dur.count());
-  }
-  static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool convert_to_timespec(TimeSpecT& dest,
-                                                                FileTimeT tp) {
-    if (!is_representable(tp))
-      return false;
-    return set_times_checked(&dest.tv_sec, &dest.tv_nsec, tp);
-  }
-};
-
-using fs_time = time_util<file_time_type, time_t, TimeSpec>;
-
-#if defined(__APPLE__)
-TimeSpec extract_mtime(StatT const& st) { return st.st_mtimespec; }
-TimeSpec extract_atime(StatT const& st) { return st.st_atimespec; }
-#else
-TimeSpec extract_mtime(StatT const& st) { return st.st_mtim; }
-TimeSpec extract_atime(StatT const& st) { return st.st_atim; }
-#endif
-
-// allow the utimes implementation to compile even it we're not going
-// to use it.
-
-bool posix_utimes(const path& p, std::array<TimeSpec, 2> const& TS,
-                  error_code& ec) {
-  using namespace chrono;
-  auto Convert = [](long nsec) {
-    using int_type = decltype(std::declval< ::timeval>().tv_usec);
-    auto dur = duration_cast<microseconds>(nanoseconds(nsec)).count();
-    return static_cast<int_type>(dur);
-  };
-  struct ::timeval ConvertedTS[2] = {{TS[0].tv_sec, Convert(TS[0].tv_nsec)},
-                                     {TS[1].tv_sec, Convert(TS[1].tv_nsec)}};
-  if (::utimes(p.c_str(), ConvertedTS) == -1) {
-    ec = capture_errno();
-    return true;
-  }
-  return false;
-}
-
-#if defined(_LIBCPP_USE_UTIMENSAT)
-bool posix_utimensat(const path& p, std::array<TimeSpec, 2> const& TS,
-                     error_code& ec) {
-  if (::utimensat(AT_FDCWD, p.c_str(), TS.data(), 0) == -1) {
-    ec = capture_errno();
-    return true;
-  }
-  return false;
-}
-#endif
-
-bool set_file_times(const path& p, std::array<TimeSpec, 2> const& TS,
-                    error_code& ec) {
-#if !defined(_LIBCPP_USE_UTIMENSAT)
-  return posix_utimes(p, TS, ec);
-#else
-  return posix_utimensat(p, TS, ec);
-#endif
-}
-
-} // namespace
-} // end namespace detail
-
-}  // namespace android::hardware::automotive::filesystem
-
-#endif // AUTO_FILESYSTEM_COMMON_H
-/* clang-format on */
diff --git a/automotive/can/1.0/default/libc++fs/src/filesystem/operations.cpp b/automotive/can/1.0/default/libc++fs/src/filesystem/operations.cpp
deleted file mode 100644
index 6a76bdc..0000000
--- a/automotive/can/1.0/default/libc++fs/src/filesystem/operations.cpp
+++ /dev/null
@@ -1,1780 +0,0 @@
-//===--------------------- filesystem/ops.cpp -----------------------------===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// TODO(152067309): Remove this once the libc++ upgrade is complete.
-#include <__config>
-#if defined(_LIBCPP_VERSION) && _LIBCPP_VERSION <= 8000
-
-/* clang-format off */
-#include "automotive/filesystem"
-#include <array>
-#include <iterator>
-#include <fstream>
-#include <random> /* for unique_path */
-#include <string_view>
-#include <type_traits>
-#include <vector>
-#include <cstdlib>
-#include <climits>
-
-#include "filesystem_common.h"
-
-#include <unistd.h>
-#include <sys/stat.h>
-#include <sys/statvfs.h>
-#include <time.h>
-#include <fcntl.h> /* values for fchmodat */
-
-#if defined(__linux__)
-#include <linux/version.h>
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)
-#include <sys/sendfile.h>
-#define _LIBCPP_USE_SENDFILE
-#endif
-#elif defined(__APPLE__) || __has_include(<copyfile.h>)
-#include <copyfile.h>
-#define _LIBCPP_USE_COPYFILE
-#endif
-
-#if !defined(__APPLE__)
-#define _LIBCPP_USE_CLOCK_GETTIME
-#endif
-
-#if !defined(CLOCK_REALTIME) || !defined(_LIBCPP_USE_CLOCK_GETTIME)
-#include <sys/time.h> // for gettimeofday and timeval
-#endif                // !defined(CLOCK_REALTIME)
-
-#if defined(_LIBCPP_COMPILER_GCC)
-#if _GNUC_VER < 500
-#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
-#endif
-#endif
-
-namespace android::hardware::automotive::filesystem {
-
-#ifdef _VSTD_FS
-#pragma push_macro("_VSTD_FS")
-#else
-#define _LIBAUTO_UNDEF_VSTD_FS
-#endif
-#define _VSTD_FS android::hardware::automotive::filesystem
-
-namespace {
-namespace parser {
-
-using string_view_t = path::__string_view;
-using string_view_pair = pair<string_view_t, string_view_t>;
-using PosPtr = path::value_type const*;
-
-struct PathParser {
-  enum ParserState : unsigned char {
-    // Zero is a special sentinel value used by default constructed iterators.
-    PS_BeforeBegin = path::iterator::_BeforeBegin,
-    PS_InRootName = path::iterator::_InRootName,
-    PS_InRootDir = path::iterator::_InRootDir,
-    PS_InFilenames = path::iterator::_InFilenames,
-    PS_InTrailingSep = path::iterator::_InTrailingSep,
-    PS_AtEnd = path::iterator::_AtEnd
-  };
-
-  const string_view_t Path;
-  string_view_t RawEntry;
-  ParserState State;
-
-private:
-  PathParser(string_view_t P, ParserState State) noexcept : Path(P),
-                                                            State(State) {}
-
-public:
-  PathParser(string_view_t P, string_view_t E, unsigned char S)
-      : Path(P), RawEntry(E), State(static_cast<ParserState>(S)) {
-    // S cannot be '0' or PS_BeforeBegin.
-  }
-
-  static PathParser CreateBegin(string_view_t P) noexcept {
-    PathParser PP(P, PS_BeforeBegin);
-    PP.increment();
-    return PP;
-  }
-
-  static PathParser CreateEnd(string_view_t P) noexcept {
-    PathParser PP(P, PS_AtEnd);
-    return PP;
-  }
-
-  PosPtr peek() const noexcept {
-    auto TkEnd = getNextTokenStartPos();
-    auto End = getAfterBack();
-    return TkEnd == End ? nullptr : TkEnd;
-  }
-
-  void increment() noexcept {
-    const PosPtr End = getAfterBack();
-    const PosPtr Start = getNextTokenStartPos();
-    if (Start == End)
-      return makeState(PS_AtEnd);
-
-    switch (State) {
-    case PS_BeforeBegin: {
-      PosPtr TkEnd = consumeSeparator(Start, End);
-      if (TkEnd)
-        return makeState(PS_InRootDir, Start, TkEnd);
-      else
-        return makeState(PS_InFilenames, Start, consumeName(Start, End));
-    }
-    case PS_InRootDir:
-      return makeState(PS_InFilenames, Start, consumeName(Start, End));
-
-    case PS_InFilenames: {
-      PosPtr SepEnd = consumeSeparator(Start, End);
-      if (SepEnd != End) {
-        PosPtr TkEnd = consumeName(SepEnd, End);
-        if (TkEnd)
-          return makeState(PS_InFilenames, SepEnd, TkEnd);
-      }
-      return makeState(PS_InTrailingSep, Start, SepEnd);
-    }
-
-    case PS_InTrailingSep:
-      return makeState(PS_AtEnd);
-
-    case PS_InRootName:
-    case PS_AtEnd:
-      _LIBCPP_UNREACHABLE();
-    }
-  }
-
-  void decrement() noexcept {
-    const PosPtr REnd = getBeforeFront();
-    const PosPtr RStart = getCurrentTokenStartPos() - 1;
-    if (RStart == REnd) // we're decrementing the begin
-      return makeState(PS_BeforeBegin);
-
-    switch (State) {
-    case PS_AtEnd: {
-      // Try to consume a trailing separator or root directory first.
-      if (PosPtr SepEnd = consumeSeparator(RStart, REnd)) {
-        if (SepEnd == REnd)
-          return makeState(PS_InRootDir, Path.data(), RStart + 1);
-        return makeState(PS_InTrailingSep, SepEnd + 1, RStart + 1);
-      } else {
-        PosPtr TkStart = consumeName(RStart, REnd);
-        return makeState(PS_InFilenames, TkStart + 1, RStart + 1);
-      }
-    }
-    case PS_InTrailingSep:
-      return makeState(PS_InFilenames, consumeName(RStart, REnd) + 1,
-                       RStart + 1);
-    case PS_InFilenames: {
-      PosPtr SepEnd = consumeSeparator(RStart, REnd);
-      if (SepEnd == REnd)
-        return makeState(PS_InRootDir, Path.data(), RStart + 1);
-      PosPtr TkEnd = consumeName(SepEnd, REnd);
-      return makeState(PS_InFilenames, TkEnd + 1, SepEnd + 1);
-    }
-    case PS_InRootDir:
-      // return makeState(PS_InRootName, Path.data(), RStart + 1);
-    case PS_InRootName:
-    case PS_BeforeBegin:
-      _LIBCPP_UNREACHABLE();
-    }
-  }
-
-  /// \brief Return a view with the "preferred representation" of the current
-  ///   element. For example trailing separators are represented as a '.'
-  string_view_t operator*() const noexcept {
-    switch (State) {
-    case PS_BeforeBegin:
-    case PS_AtEnd:
-      return "";
-    case PS_InRootDir:
-      return "/";
-    case PS_InTrailingSep:
-      return "";
-    case PS_InRootName:
-    case PS_InFilenames:
-      return RawEntry;
-    }
-    _LIBCPP_UNREACHABLE();
-  }
-
-  explicit operator bool() const noexcept {
-    return State != PS_BeforeBegin && State != PS_AtEnd;
-  }
-
-  PathParser& operator++() noexcept {
-    increment();
-    return *this;
-  }
-
-  PathParser& operator--() noexcept {
-    decrement();
-    return *this;
-  }
-
-  bool atEnd() const noexcept {
-    return State == PS_AtEnd;
-  }
-
-  bool inRootDir() const noexcept {
-    return State == PS_InRootDir;
-  }
-
-  bool inRootName() const noexcept {
-    return State == PS_InRootName;
-  }
-
-  bool inRootPath() const noexcept {
-    return inRootName() || inRootDir();
-  }
-
-private:
-  void makeState(ParserState NewState, PosPtr Start, PosPtr End) noexcept {
-    State = NewState;
-    RawEntry = string_view_t(Start, End - Start);
-  }
-  void makeState(ParserState NewState) noexcept {
-    State = NewState;
-    RawEntry = {};
-  }
-
-  PosPtr getAfterBack() const noexcept { return Path.data() + Path.size(); }
-
-  PosPtr getBeforeFront() const noexcept { return Path.data() - 1; }
-
-  /// \brief Return a pointer to the first character after the currently
-  ///   lexed element.
-  PosPtr getNextTokenStartPos() const noexcept {
-    switch (State) {
-    case PS_BeforeBegin:
-      return Path.data();
-    case PS_InRootName:
-    case PS_InRootDir:
-    case PS_InFilenames:
-      return &RawEntry.back() + 1;
-    case PS_InTrailingSep:
-    case PS_AtEnd:
-      return getAfterBack();
-    }
-    _LIBCPP_UNREACHABLE();
-  }
-
-  /// \brief Return a pointer to the first character in the currently lexed
-  ///   element.
-  PosPtr getCurrentTokenStartPos() const noexcept {
-    switch (State) {
-    case PS_BeforeBegin:
-    case PS_InRootName:
-      return &Path.front();
-    case PS_InRootDir:
-    case PS_InFilenames:
-    case PS_InTrailingSep:
-      return &RawEntry.front();
-    case PS_AtEnd:
-      return &Path.back() + 1;
-    }
-    _LIBCPP_UNREACHABLE();
-  }
-
-  PosPtr consumeSeparator(PosPtr P, PosPtr End) const noexcept {
-    if (P == End || *P != '/')
-      return nullptr;
-    const int Inc = P < End ? 1 : -1;
-    P += Inc;
-    while (P != End && *P == '/')
-      P += Inc;
-    return P;
-  }
-
-  PosPtr consumeName(PosPtr P, PosPtr End) const noexcept {
-    if (P == End || *P == '/')
-      return nullptr;
-    const int Inc = P < End ? 1 : -1;
-    P += Inc;
-    while (P != End && *P != '/')
-      P += Inc;
-    return P;
-  }
-};
-
-string_view_pair separate_filename(string_view_t const& s) {
-  if (s == "." || s == ".." || s.empty())
-    return string_view_pair{s, ""};
-  auto pos = s.find_last_of('.');
-  if (pos == string_view_t::npos || pos == 0)
-    return string_view_pair{s, string_view_t{}};
-  return string_view_pair{s.substr(0, pos), s.substr(pos)};
-}
-
-string_view_t createView(PosPtr S, PosPtr E) noexcept {
-  return {S, static_cast<size_t>(E - S) + 1};
-}
-
-} // namespace parser
-} // namespace
-
-//                       POSIX HELPERS
-
-namespace detail {
-namespace {
-
-using value_type = path::value_type;
-using string_type = path::string_type;
-
-struct FileDescriptor {
-  const path& name;
-  int fd = -1;
-  StatT m_stat;
-  file_status m_status;
-
-  template <class... Args>
-  static FileDescriptor create(const path* p, error_code& ec, Args... args) {
-    ec.clear();
-    int fd;
-    if ((fd = ::open(p->c_str(), args...)) == -1) {
-      ec = capture_errno();
-      return FileDescriptor{p};
-    }
-    return FileDescriptor(p, fd);
-  }
-
-  template <class... Args>
-  static FileDescriptor create_with_status(const path* p, error_code& ec,
-                                           Args... args) {
-    FileDescriptor fd = create(p, ec, args...);
-    if (!ec)
-      fd.refresh_status(ec);
-
-    return fd;
-  }
-
-  file_status get_status() const { return m_status; }
-  StatT const& get_stat() const { return m_stat; }
-
-  bool status_known() const { return _VSTD_FS::status_known(m_status); }
-
-  file_status refresh_status(error_code& ec);
-
-  void close() noexcept {
-    if (fd != -1)
-      ::close(fd);
-    fd = -1;
-  }
-
-  FileDescriptor(FileDescriptor&& other)
-      : name(other.name), fd(other.fd), m_stat(other.m_stat),
-        m_status(other.m_status) {
-    other.fd = -1;
-    other.m_status = file_status{};
-  }
-
-  ~FileDescriptor() { close(); }
-
-  FileDescriptor(FileDescriptor const&) = delete;
-  FileDescriptor& operator=(FileDescriptor const&) = delete;
-
-private:
-  explicit FileDescriptor(const path* p, int fd = -1) : name(*p), fd(fd) {}
-};
-
-perms posix_get_perms(const StatT& st) noexcept {
-  return static_cast<perms>(st.st_mode) & perms::mask;
-}
-
-::mode_t posix_convert_perms(perms prms) {
-  return static_cast< ::mode_t>(prms & perms::mask);
-}
-
-file_status create_file_status(error_code& m_ec, path const& p,
-                               const StatT& path_stat, error_code* ec) {
-  if (ec)
-    *ec = m_ec;
-  if (m_ec && (m_ec.value() == ENOENT || m_ec.value() == ENOTDIR)) {
-    return file_status(file_type::not_found);
-  } else if (m_ec) {
-    ErrorHandler<void> err("posix_stat", ec, &p);
-    err.report(m_ec, "failed to determine attributes for the specified path");
-    return file_status(file_type::none);
-  }
-  // else
-
-  file_status fs_tmp;
-  auto const mode = path_stat.st_mode;
-  if (S_ISLNK(mode))
-    fs_tmp.type(file_type::symlink);
-  else if (S_ISREG(mode))
-    fs_tmp.type(file_type::regular);
-  else if (S_ISDIR(mode))
-    fs_tmp.type(file_type::directory);
-  else if (S_ISBLK(mode))
-    fs_tmp.type(file_type::block);
-  else if (S_ISCHR(mode))
-    fs_tmp.type(file_type::character);
-  else if (S_ISFIFO(mode))
-    fs_tmp.type(file_type::fifo);
-  else if (S_ISSOCK(mode))
-    fs_tmp.type(file_type::socket);
-  else
-    fs_tmp.type(file_type::unknown);
-
-  fs_tmp.permissions(detail::posix_get_perms(path_stat));
-  return fs_tmp;
-}
-
-file_status posix_stat(path const& p, StatT& path_stat, error_code* ec) {
-  error_code m_ec;
-  if (::stat(p.c_str(), &path_stat) == -1)
-    m_ec = detail::capture_errno();
-  return create_file_status(m_ec, p, path_stat, ec);
-}
-
-file_status posix_stat(path const& p, error_code* ec) {
-  StatT path_stat;
-  return posix_stat(p, path_stat, ec);
-}
-
-file_status posix_lstat(path const& p, StatT& path_stat, error_code* ec) {
-  error_code m_ec;
-  if (::lstat(p.c_str(), &path_stat) == -1)
-    m_ec = detail::capture_errno();
-  return create_file_status(m_ec, p, path_stat, ec);
-}
-
-file_status posix_lstat(path const& p, error_code* ec) {
-  StatT path_stat;
-  return posix_lstat(p, path_stat, ec);
-}
-
-bool posix_ftruncate(const FileDescriptor& fd, size_t to_size, error_code& ec) {
-  if (::ftruncate(fd.fd, to_size) == -1) {
-    ec = capture_errno();
-    return true;
-  }
-  ec.clear();
-  return false;
-}
-
-bool posix_fchmod(const FileDescriptor& fd, const StatT& st, error_code& ec) {
-  if (::fchmod(fd.fd, st.st_mode) == -1) {
-    ec = capture_errno();
-    return true;
-  }
-  ec.clear();
-  return false;
-}
-
-bool stat_equivalent(const StatT& st1, const StatT& st2) {
-  return (st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino);
-}
-
-file_status FileDescriptor::refresh_status(error_code& ec) {
-  // FD must be open and good.
-  m_status = file_status{};
-  m_stat = {};
-  error_code m_ec;
-  if (::fstat(fd, &m_stat) == -1)
-    m_ec = capture_errno();
-  m_status = create_file_status(m_ec, name, m_stat, &ec);
-  return m_status;
-}
-} // namespace
-} // end namespace detail
-
-using detail::capture_errno;
-using detail::ErrorHandler;
-using detail::StatT;
-using detail::TimeSpec;
-using parser::createView;
-using parser::PathParser;
-using parser::string_view_t;
-
-const bool _FilesystemClock::is_steady;
-
-_FilesystemClock::time_point _FilesystemClock::now() noexcept {
-  typedef chrono::duration<rep> __secs;
-#if defined(_LIBCPP_USE_CLOCK_GETTIME) && defined(CLOCK_REALTIME)
-  typedef chrono::duration<rep, nano> __nsecs;
-  struct timespec tp;
-  if (0 != clock_gettime(CLOCK_REALTIME, &tp))
-    __throw_system_error(errno, "clock_gettime(CLOCK_REALTIME) failed");
-  return time_point(__secs(tp.tv_sec) +
-                    chrono::duration_cast<duration>(__nsecs(tp.tv_nsec)));
-#else
-  typedef chrono::duration<rep, micro> __microsecs;
-  timeval tv;
-  gettimeofday(&tv, 0);
-  return time_point(__secs(tv.tv_sec) + __microsecs(tv.tv_usec));
-#endif // _LIBCPP_USE_CLOCK_GETTIME && CLOCK_REALTIME
-}
-
-filesystem_error::~filesystem_error() {}
-
-void filesystem_error::__create_what(int __num_paths) {
-  const char* derived_what = system_error::what();
-  __storage_->__what_ = [&]() -> string {
-    const char* p1 = path1().native().empty() ? "\"\"" : path1().c_str();
-    const char* p2 = path2().native().empty() ? "\"\"" : path2().c_str();
-    switch (__num_paths) {
-    default:
-      return detail::format_string("filesystem error: %s", derived_what);
-    case 1:
-      return detail::format_string("filesystem error: %s [%s]", derived_what,
-                                   p1);
-    case 2:
-      return detail::format_string("filesystem error: %s [%s] [%s]",
-                                   derived_what, p1, p2);
-    }
-  }();
-}
-
-static path __do_absolute(const path& p, path* cwd, error_code* ec) {
-  if (ec)
-    ec->clear();
-  if (p.is_absolute())
-    return p;
-  *cwd = __current_path(ec);
-  if (ec && *ec)
-    return {};
-  return (*cwd) / p;
-}
-
-path __absolute(const path& p, error_code* ec) {
-  path cwd;
-  return __do_absolute(p, &cwd, ec);
-}
-
-path __canonical(path const& orig_p, error_code* ec) {
-  path cwd;
-  ErrorHandler<path> err("canonical", ec, &orig_p, &cwd);
-
-  path p = __do_absolute(orig_p, &cwd, ec);
-  char buff[PATH_MAX + 1];
-  char* ret;
-  if ((ret = ::realpath(p.c_str(), buff)) == nullptr)
-    return err.report(capture_errno());
-  return {ret};
-}
-
-void __copy(const path& from, const path& to, copy_options options,
-            error_code* ec) {
-  ErrorHandler<void> err("copy", ec, &from, &to);
-
-  const bool sym_status = bool(
-      options & (copy_options::create_symlinks | copy_options::skip_symlinks));
-
-  const bool sym_status2 = bool(options & copy_options::copy_symlinks);
-
-  error_code m_ec1;
-  StatT f_st = {};
-  const file_status f = sym_status || sym_status2
-                            ? detail::posix_lstat(from, f_st, &m_ec1)
-                            : detail::posix_stat(from, f_st, &m_ec1);
-  if (m_ec1)
-    return err.report(m_ec1);
-
-  StatT t_st = {};
-  const file_status t = sym_status ? detail::posix_lstat(to, t_st, &m_ec1)
-                                   : detail::posix_stat(to, t_st, &m_ec1);
-
-  if (not status_known(t))
-    return err.report(m_ec1);
-
-  if (!exists(f) || is_other(f) || is_other(t) ||
-      (is_directory(f) && is_regular_file(t)) ||
-      detail::stat_equivalent(f_st, t_st)) {
-    return err.report(errc::function_not_supported);
-  }
-
-  if (ec)
-    ec->clear();
-
-  if (is_symlink(f)) {
-    if (bool(copy_options::skip_symlinks & options)) {
-      // do nothing
-    } else if (not exists(t)) {
-      __copy_symlink(from, to, ec);
-    } else {
-      return err.report(errc::file_exists);
-    }
-    return;
-  } else if (is_regular_file(f)) {
-    if (bool(copy_options::directories_only & options)) {
-      // do nothing
-    } else if (bool(copy_options::create_symlinks & options)) {
-      __create_symlink(from, to, ec);
-    } else if (bool(copy_options::create_hard_links & options)) {
-      __create_hard_link(from, to, ec);
-    } else if (is_directory(t)) {
-      __copy_file(from, to / from.filename(), options, ec);
-    } else {
-      __copy_file(from, to, options, ec);
-    }
-    return;
-  } else if (is_directory(f) && bool(copy_options::create_symlinks & options)) {
-    return err.report(errc::is_a_directory);
-  } else if (is_directory(f) && (bool(copy_options::recursive & options) ||
-                                 copy_options::none == options)) {
-
-    if (!exists(t)) {
-      // create directory to with attributes from 'from'.
-      __create_directory(to, from, ec);
-      if (ec && *ec) {
-        return;
-      }
-    }
-    directory_iterator it =
-        ec ? directory_iterator(from, *ec) : directory_iterator(from);
-    if (ec && *ec) {
-      return;
-    }
-    error_code m_ec2;
-    for (; it != directory_iterator(); it.increment(m_ec2)) {
-      if (m_ec2) {
-        return err.report(m_ec2);
-      }
-      __copy(it->path(), to / it->path().filename(),
-             options | copy_options::__in_recursive_copy, ec);
-      if (ec && *ec) {
-        return;
-      }
-    }
-  }
-}
-
-namespace detail {
-namespace {
-
-#ifdef _LIBCPP_USE_SENDFILE
-bool copy_file_impl_sendfile(FileDescriptor& read_fd, FileDescriptor& write_fd,
-                             error_code& ec) {
-
-  size_t count = read_fd.get_stat().st_size;
-  do {
-    ssize_t res;
-    if ((res = ::sendfile(write_fd.fd, read_fd.fd, nullptr, count)) == -1) {
-      ec = capture_errno();
-      return false;
-    }
-    count -= res;
-  } while (count > 0);
-
-  ec.clear();
-
-  return true;
-}
-#elif defined(_LIBCPP_USE_COPYFILE)
-bool copy_file_impl_copyfile(FileDescriptor& read_fd, FileDescriptor& write_fd,
-                             error_code& ec) {
-  struct CopyFileState {
-    copyfile_state_t state;
-    CopyFileState() { state = copyfile_state_alloc(); }
-    ~CopyFileState() { copyfile_state_free(state); }
-
-  private:
-    CopyFileState(CopyFileState const&) = delete;
-    CopyFileState& operator=(CopyFileState const&) = delete;
-  };
-
-  CopyFileState cfs;
-  if (fcopyfile(read_fd.fd, write_fd.fd, cfs.state, COPYFILE_DATA) < 0) {
-    ec = capture_errno();
-    return false;
-  }
-
-  ec.clear();
-  return true;
-}
-#endif
-
-// Note: This function isn't guarded by ifdef's even though it may be unused
-// in order to assure it still compiles.
-__attribute__((unused)) bool copy_file_impl_default(FileDescriptor& read_fd,
-                                                    FileDescriptor& write_fd,
-                                                    error_code& ec) {
-  ifstream in;
-  in.__open(read_fd.fd, ios::binary);
-  if (!in.is_open()) {
-    // This assumes that __open didn't reset the error code.
-    ec = capture_errno();
-    return false;
-  }
-  ofstream out;
-  out.__open(write_fd.fd, ios::binary);
-  if (!out.is_open()) {
-    ec = capture_errno();
-    return false;
-  }
-
-  if (in.good() && out.good()) {
-    using InIt = istreambuf_iterator<char>;
-    using OutIt = ostreambuf_iterator<char>;
-    InIt bin(in);
-    InIt ein;
-    OutIt bout(out);
-    copy(bin, ein, bout);
-  }
-  if (out.fail() || in.fail()) {
-    ec = make_error_code(errc::io_error);
-    return false;
-  }
-
-  ec.clear();
-  return true;
-}
-
-bool copy_file_impl(FileDescriptor& from, FileDescriptor& to, error_code& ec) {
-#if defined(_LIBCPP_USE_SENDFILE)
-  return copy_file_impl_sendfile(from, to, ec);
-#elif defined(_LIBCPP_USE_COPYFILE)
-  return copy_file_impl_copyfile(from, to, ec);
-#else
-  return copy_file_impl_default(from, to, ec);
-#endif
-}
-
-} // namespace
-} // namespace detail
-
-bool __copy_file(const path& from, const path& to, copy_options options,
-                 error_code* ec) {
-  using detail::FileDescriptor;
-  ErrorHandler<bool> err("copy_file", ec, &to, &from);
-
-  error_code m_ec;
-  FileDescriptor from_fd =
-      FileDescriptor::create_with_status(&from, m_ec, O_RDONLY | O_NONBLOCK);
-  if (m_ec)
-    return err.report(m_ec);
-
-  auto from_st = from_fd.get_status();
-  StatT const& from_stat = from_fd.get_stat();
-  if (!is_regular_file(from_st)) {
-    if (not m_ec)
-      m_ec = make_error_code(errc::not_supported);
-    return err.report(m_ec);
-  }
-
-  const bool skip_existing = bool(copy_options::skip_existing & options);
-  const bool update_existing = bool(copy_options::update_existing & options);
-  const bool overwrite_existing =
-      bool(copy_options::overwrite_existing & options);
-
-  StatT to_stat_path;
-  file_status to_st = detail::posix_stat(to, to_stat_path, &m_ec);
-  if (!status_known(to_st))
-    return err.report(m_ec);
-
-  const bool to_exists = exists(to_st);
-  if (to_exists && !is_regular_file(to_st))
-    return err.report(errc::not_supported);
-
-  if (to_exists && detail::stat_equivalent(from_stat, to_stat_path))
-    return err.report(errc::file_exists);
-
-  if (to_exists && skip_existing)
-    return false;
-
-  bool ShouldCopy = [&]() {
-    if (to_exists && update_existing) {
-      auto from_time = detail::extract_mtime(from_stat);
-      auto to_time = detail::extract_mtime(to_stat_path);
-      if (from_time.tv_sec < to_time.tv_sec)
-        return false;
-      if (from_time.tv_sec == to_time.tv_sec &&
-          from_time.tv_nsec <= to_time.tv_nsec)
-        return false;
-      return true;
-    }
-    if (!to_exists || overwrite_existing)
-      return true;
-    return err.report(errc::file_exists);
-  }();
-  if (!ShouldCopy)
-    return false;
-
-  // Don't truncate right away. We may not be opening the file we originally
-  // looked at; we'll check this later.
-  int to_open_flags = O_WRONLY;
-  if (!to_exists)
-    to_open_flags |= O_CREAT;
-  FileDescriptor to_fd = FileDescriptor::create_with_status(
-      &to, m_ec, to_open_flags, from_stat.st_mode);
-  if (m_ec)
-    return err.report(m_ec);
-
-  if (to_exists) {
-    // Check that the file we initially stat'ed is equivalent to the one
-    // we opened.
-    // FIXME: report this better.
-    if (!detail::stat_equivalent(to_stat_path, to_fd.get_stat()))
-      return err.report(errc::bad_file_descriptor);
-
-    // Set the permissions and truncate the file we opened.
-    if (detail::posix_fchmod(to_fd, from_stat, m_ec))
-      return err.report(m_ec);
-    if (detail::posix_ftruncate(to_fd, 0, m_ec))
-      return err.report(m_ec);
-  }
-
-  if (!copy_file_impl(from_fd, to_fd, m_ec)) {
-    // FIXME: Remove the dest file if we failed, and it didn't exist previously.
-    return err.report(m_ec);
-  }
-
-  return true;
-}
-
-void __copy_symlink(const path& existing_symlink, const path& new_symlink,
-                    error_code* ec) {
-  const path real_path(__read_symlink(existing_symlink, ec));
-  if (ec && *ec) {
-    return;
-  }
-  // NOTE: proposal says you should detect if you should call
-  // create_symlink or create_directory_symlink. I don't think this
-  // is needed with POSIX
-  __create_symlink(real_path, new_symlink, ec);
-}
-
-bool __create_directories(const path& p, error_code* ec) {
-  ErrorHandler<bool> err("create_directories", ec, &p);
-
-  error_code m_ec;
-  auto const st = detail::posix_stat(p, &m_ec);
-  if (!status_known(st))
-    return err.report(m_ec);
-  else if (is_directory(st))
-    return false;
-  else if (exists(st))
-    return err.report(errc::file_exists);
-
-  const path parent = p.parent_path();
-  if (!parent.empty()) {
-    const file_status parent_st = status(parent, m_ec);
-    if (not status_known(parent_st))
-      return err.report(m_ec);
-    if (not exists(parent_st)) {
-      __create_directories(parent, ec);
-      if (ec && *ec) {
-        return false;
-      }
-    }
-  }
-  return __create_directory(p, ec);
-}
-
-bool __create_directory(const path& p, error_code* ec) {
-  ErrorHandler<bool> err("create_directory", ec, &p);
-
-  if (::mkdir(p.c_str(), static_cast<int>(perms::all)) == 0)
-    return true;
-  if (errno != EEXIST)
-    err.report(capture_errno());
-  return false;
-}
-
-bool __create_directory(path const& p, path const& attributes, error_code* ec) {
-  ErrorHandler<bool> err("create_directory", ec, &p, &attributes);
-
-  StatT attr_stat;
-  error_code mec;
-  auto st = detail::posix_stat(attributes, attr_stat, &mec);
-  if (!status_known(st))
-    return err.report(mec);
-  if (!is_directory(st))
-    return err.report(errc::not_a_directory,
-                      "the specified attribute path is invalid");
-
-  if (::mkdir(p.c_str(), attr_stat.st_mode) == 0)
-    return true;
-  if (errno != EEXIST)
-    err.report(capture_errno());
-  return false;
-}
-
-void __create_directory_symlink(path const& from, path const& to,
-                                error_code* ec) {
-  ErrorHandler<void> err("create_directory_symlink", ec, &from, &to);
-  if (::symlink(from.c_str(), to.c_str()) != 0)
-    return err.report(capture_errno());
-}
-
-void __create_hard_link(const path& from, const path& to, error_code* ec) {
-  ErrorHandler<void> err("create_hard_link", ec, &from, &to);
-  if (::link(from.c_str(), to.c_str()) == -1)
-    return err.report(capture_errno());
-}
-
-void __create_symlink(path const& from, path const& to, error_code* ec) {
-  ErrorHandler<void> err("create_symlink", ec, &from, &to);
-  if (::symlink(from.c_str(), to.c_str()) == -1)
-    return err.report(capture_errno());
-}
-
-path __current_path(error_code* ec) {
-  ErrorHandler<path> err("current_path", ec);
-
-  auto size = ::pathconf(".", _PC_PATH_MAX);
-  _LIBCPP_ASSERT(size >= 0, "pathconf returned a 0 as max size");
-
-  auto buff = unique_ptr<char[]>(new char[size + 1]);
-  char* ret;
-  if ((ret = ::getcwd(buff.get(), static_cast<size_t>(size))) == nullptr)
-    return err.report(capture_errno(), "call to getcwd failed");
-
-  return {buff.get()};
-}
-
-void __current_path(const path& p, error_code* ec) {
-  ErrorHandler<void> err("current_path", ec, &p);
-  if (::chdir(p.c_str()) == -1)
-    err.report(capture_errno());
-}
-
-bool __equivalent(const path& p1, const path& p2, error_code* ec) {
-  ErrorHandler<bool> err("equivalent", ec, &p1, &p2);
-
-  error_code ec1, ec2;
-  StatT st1 = {}, st2 = {};
-  auto s1 = detail::posix_stat(p1.native(), st1, &ec1);
-  if (!exists(s1))
-    return err.report(errc::not_supported);
-  auto s2 = detail::posix_stat(p2.native(), st2, &ec2);
-  if (!exists(s2))
-    return err.report(errc::not_supported);
-
-  return detail::stat_equivalent(st1, st2);
-}
-
-uintmax_t __file_size(const path& p, error_code* ec) {
-  ErrorHandler<uintmax_t> err("file_size", ec, &p);
-
-  error_code m_ec;
-  StatT st;
-  file_status fst = detail::posix_stat(p, st, &m_ec);
-  if (!exists(fst) || !is_regular_file(fst)) {
-    errc error_kind =
-        is_directory(fst) ? errc::is_a_directory : errc::not_supported;
-    if (!m_ec)
-      m_ec = make_error_code(error_kind);
-    return err.report(m_ec);
-  }
-  // is_regular_file(p) == true
-  return static_cast<uintmax_t>(st.st_size);
-}
-
-uintmax_t __hard_link_count(const path& p, error_code* ec) {
-  ErrorHandler<uintmax_t> err("hard_link_count", ec, &p);
-
-  error_code m_ec;
-  StatT st;
-  detail::posix_stat(p, st, &m_ec);
-  if (m_ec)
-    return err.report(m_ec);
-  return static_cast<uintmax_t>(st.st_nlink);
-}
-
-bool __fs_is_empty(const path& p, error_code* ec) {
-  ErrorHandler<bool> err("is_empty", ec, &p);
-
-  error_code m_ec;
-  StatT pst;
-  auto st = detail::posix_stat(p, pst, &m_ec);
-  if (m_ec)
-    return err.report(m_ec);
-  else if (!is_directory(st) && !is_regular_file(st))
-    return err.report(errc::not_supported);
-  else if (is_directory(st)) {
-    auto it = ec ? directory_iterator(p, *ec) : directory_iterator(p);
-    if (ec && *ec)
-      return false;
-    return it == directory_iterator{};
-  } else if (is_regular_file(st))
-    return static_cast<uintmax_t>(pst.st_size) == 0;
-
-  _LIBCPP_UNREACHABLE();
-}
-
-static file_time_type __extract_last_write_time(const path& p, const StatT& st,
-                                                error_code* ec) {
-  using detail::fs_time;
-  ErrorHandler<file_time_type> err("last_write_time", ec, &p);
-
-  auto ts = detail::extract_mtime(st);
-  if (!fs_time::is_representable(ts))
-    return err.report(errc::value_too_large);
-
-  return fs_time::convert_from_timespec(ts);
-}
-
-file_time_type __last_write_time(const path& p, error_code* ec) {
-  using namespace chrono;
-  ErrorHandler<file_time_type> err("last_write_time", ec, &p);
-
-  error_code m_ec;
-  StatT st;
-  detail::posix_stat(p, st, &m_ec);
-  if (m_ec)
-    return err.report(m_ec);
-  return __extract_last_write_time(p, st, ec);
-}
-
-void __last_write_time(const path& p, file_time_type new_time, error_code* ec) {
-  using detail::fs_time;
-  ErrorHandler<void> err("last_write_time", ec, &p);
-
-  error_code m_ec;
-  array<TimeSpec, 2> tbuf;
-#if !defined(_LIBCPP_USE_UTIMENSAT)
-  // This implementation has a race condition between determining the
-  // last access time and attempting to set it to the same value using
-  // ::utimes
-  StatT st;
-  file_status fst = detail::posix_stat(p, st, &m_ec);
-  if (m_ec)
-    return err.report(m_ec);
-  tbuf[0] = detail::extract_atime(st);
-#else
-  tbuf[0].tv_sec = 0;
-  tbuf[0].tv_nsec = UTIME_OMIT;
-#endif
-  if (!fs_time::convert_to_timespec(tbuf[1], new_time))
-    return err.report(errc::value_too_large);
-
-  detail::set_file_times(p, tbuf, m_ec);
-  if (m_ec)
-    return err.report(m_ec);
-}
-
-void __permissions(const path& p, perms prms, perm_options opts,
-                   error_code* ec) {
-  ErrorHandler<void> err("permissions", ec, &p);
-
-  auto has_opt = [&](perm_options o) { return bool(o & opts); };
-  const bool resolve_symlinks = !has_opt(perm_options::nofollow);
-  const bool add_perms = has_opt(perm_options::add);
-  const bool remove_perms = has_opt(perm_options::remove);
-  _LIBCPP_ASSERT(
-      (add_perms + remove_perms + has_opt(perm_options::replace)) == 1,
-      "One and only one of the perm_options constants replace, add, or remove "
-      "is present in opts");
-
-  bool set_sym_perms = false;
-  prms &= perms::mask;
-  if (!resolve_symlinks || (add_perms || remove_perms)) {
-    error_code m_ec;
-    file_status st = resolve_symlinks ? detail::posix_stat(p, &m_ec)
-                                      : detail::posix_lstat(p, &m_ec);
-    set_sym_perms = is_symlink(st);
-    if (m_ec)
-      return err.report(m_ec);
-    _LIBCPP_ASSERT(st.permissions() != perms::unknown,
-                   "Permissions unexpectedly unknown");
-    if (add_perms)
-      prms |= st.permissions();
-    else if (remove_perms)
-      prms = st.permissions() & ~prms;
-  }
-  const auto real_perms = detail::posix_convert_perms(prms);
-
-#if defined(AT_SYMLINK_NOFOLLOW) && defined(AT_FDCWD)
-  const int flags = set_sym_perms ? AT_SYMLINK_NOFOLLOW : 0;
-  if (::fchmodat(AT_FDCWD, p.c_str(), real_perms, flags) == -1) {
-    return err.report(capture_errno());
-  }
-#else
-  if (set_sym_perms)
-    return err.report(errc::operation_not_supported);
-  if (::chmod(p.c_str(), real_perms) == -1) {
-    return err.report(capture_errno());
-  }
-#endif
-}
-
-path __read_symlink(const path& p, error_code* ec) {
-  ErrorHandler<path> err("read_symlink", ec, &p);
-
-  char buff[PATH_MAX + 1];
-  error_code m_ec;
-  ::ssize_t ret;
-  if ((ret = ::readlink(p.c_str(), buff, PATH_MAX)) == -1) {
-    return err.report(capture_errno());
-  }
-  _LIBCPP_ASSERT(ret <= PATH_MAX, "TODO");
-  _LIBCPP_ASSERT(ret > 0, "TODO");
-  buff[ret] = 0;
-  return {buff};
-}
-
-bool __remove(const path& p, error_code* ec) {
-  ErrorHandler<bool> err("remove", ec, &p);
-  if (::remove(p.c_str()) == -1) {
-    if (errno != ENOENT)
-      err.report(capture_errno());
-    return false;
-  }
-  return true;
-}
-
-namespace {
-
-uintmax_t remove_all_impl(path const& p, error_code& ec) {
-  const auto npos = static_cast<uintmax_t>(-1);
-  const file_status st = __symlink_status(p, &ec);
-  if (ec)
-    return npos;
-  uintmax_t count = 1;
-  if (is_directory(st)) {
-    for (directory_iterator it(p, ec); !ec && it != directory_iterator();
-         it.increment(ec)) {
-      auto other_count = remove_all_impl(it->path(), ec);
-      if (ec)
-        return npos;
-      count += other_count;
-    }
-    if (ec)
-      return npos;
-  }
-  if (!__remove(p, &ec))
-    return npos;
-  return count;
-}
-
-} // end namespace
-
-uintmax_t __remove_all(const path& p, error_code* ec) {
-  ErrorHandler<uintmax_t> err("remove_all", ec, &p);
-
-  error_code mec;
-  auto count = remove_all_impl(p, mec);
-  if (mec) {
-    if (mec == errc::no_such_file_or_directory)
-      return 0;
-    return err.report(mec);
-  }
-  return count;
-}
-
-void __rename(const path& from, const path& to, error_code* ec) {
-  ErrorHandler<void> err("rename", ec, &from, &to);
-  if (::rename(from.c_str(), to.c_str()) == -1)
-    err.report(capture_errno());
-}
-
-void __resize_file(const path& p, uintmax_t size, error_code* ec) {
-  ErrorHandler<void> err("resize_file", ec, &p);
-  if (::truncate(p.c_str(), static_cast< ::off_t>(size)) == -1)
-    return err.report(capture_errno());
-}
-
-space_info __space(const path& p, error_code* ec) {
-  ErrorHandler<void> err("space", ec, &p);
-  space_info si;
-  struct statvfs m_svfs = {};
-  if (::statvfs(p.c_str(), &m_svfs) == -1) {
-    err.report(capture_errno());
-    si.capacity = si.free = si.available = static_cast<uintmax_t>(-1);
-    return si;
-  }
-  // Multiply with overflow checking.
-  auto do_mult = [&](uintmax_t& out, uintmax_t other) {
-    out = other * m_svfs.f_frsize;
-    if (other == 0 || out / other != m_svfs.f_frsize)
-      out = static_cast<uintmax_t>(-1);
-  };
-  do_mult(si.capacity, m_svfs.f_blocks);
-  do_mult(si.free, m_svfs.f_bfree);
-  do_mult(si.available, m_svfs.f_bavail);
-  return si;
-}
-
-file_status __status(const path& p, error_code* ec) {
-  return detail::posix_stat(p, ec);
-}
-
-file_status __symlink_status(const path& p, error_code* ec) {
-  return detail::posix_lstat(p, ec);
-}
-
-path __temp_directory_path(error_code* ec) {
-  ErrorHandler<path> err("temp_directory_path", ec);
-
-  const char* env_paths[] = {"TMPDIR", "TMP", "TEMP", "TEMPDIR"};
-  const char* ret = nullptr;
-
-  for (auto& ep : env_paths)
-    if ((ret = getenv(ep)))
-      break;
-  if (ret == nullptr)
-    ret = "/tmp";
-
-  path p(ret);
-  error_code m_ec;
-  file_status st = detail::posix_stat(p, &m_ec);
-  if (!status_known(st))
-    return err.report(m_ec, "cannot access path \"%s\"", p);
-
-  if (!exists(st) || !is_directory(st))
-    return err.report(errc::not_a_directory, "path \"%s\" is not a directory",
-                      p);
-
-  return p;
-}
-
-path __weakly_canonical(const path& p, error_code* ec) {
-  ErrorHandler<path> err("weakly_canonical", ec, &p);
-
-  if (p.empty())
-    return __canonical("", ec);
-
-  path result;
-  path tmp;
-  tmp.__reserve(p.native().size());
-  auto PP = PathParser::CreateEnd(p.native());
-  --PP;
-  vector<string_view_t> DNEParts;
-
-  while (PP.State != PathParser::PS_BeforeBegin) {
-    tmp.assign(createView(p.native().data(), &PP.RawEntry.back()));
-    error_code m_ec;
-    file_status st = __status(tmp, &m_ec);
-    if (!status_known(st)) {
-      return err.report(m_ec);
-    } else if (exists(st)) {
-      result = __canonical(tmp, ec);
-      break;
-    }
-    DNEParts.push_back(*PP);
-    --PP;
-  }
-  if (PP.State == PathParser::PS_BeforeBegin)
-    result = __canonical("", ec);
-  if (ec)
-    ec->clear();
-  if (DNEParts.empty())
-    return result;
-  for (auto It = DNEParts.rbegin(); It != DNEParts.rend(); ++It)
-    result /= *It;
-  return result.lexically_normal();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                            path definitions
-///////////////////////////////////////////////////////////////////////////////
-
-constexpr path::value_type path::preferred_separator;
-
-path& path::replace_extension(path const& replacement) {
-  path p = extension();
-  if (not p.empty()) {
-    __pn_.erase(__pn_.size() - p.native().size());
-  }
-  if (!replacement.empty()) {
-    if (replacement.native()[0] != '.') {
-      __pn_ += ".";
-    }
-    __pn_.append(replacement.__pn_);
-  }
-  return *this;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// path.decompose
-
-string_view_t path::__root_name() const {
-  auto PP = PathParser::CreateBegin(__pn_);
-  if (PP.State == PathParser::PS_InRootName)
-    return *PP;
-  return {};
-}
-
-string_view_t path::__root_directory() const {
-  auto PP = PathParser::CreateBegin(__pn_);
-  if (PP.State == PathParser::PS_InRootName)
-    ++PP;
-  if (PP.State == PathParser::PS_InRootDir)
-    return *PP;
-  return {};
-}
-
-string_view_t path::__root_path_raw() const {
-  auto PP = PathParser::CreateBegin(__pn_);
-  if (PP.State == PathParser::PS_InRootName) {
-    auto NextCh = PP.peek();
-    if (NextCh && *NextCh == '/') {
-      ++PP;
-      return createView(__pn_.data(), &PP.RawEntry.back());
-    }
-    return PP.RawEntry;
-  }
-  if (PP.State == PathParser::PS_InRootDir)
-    return *PP;
-  return {};
-}
-
-static bool ConsumeRootName(PathParser *PP) {
-  static_assert(PathParser::PS_BeforeBegin == 1 &&
-      PathParser::PS_InRootName == 2,
-      "Values for enums are incorrect");
-  while (PP->State <= PathParser::PS_InRootName)
-    ++(*PP);
-  return PP->State == PathParser::PS_AtEnd;
-}
-
-static bool ConsumeRootDir(PathParser* PP) {
-  static_assert(PathParser::PS_BeforeBegin == 1 &&
-                PathParser::PS_InRootName == 2 &&
-                PathParser::PS_InRootDir == 3, "Values for enums are incorrect");
-  while (PP->State <= PathParser::PS_InRootDir)
-    ++(*PP);
-  return PP->State == PathParser::PS_AtEnd;
-}
-
-string_view_t path::__relative_path() const {
-  auto PP = PathParser::CreateBegin(__pn_);
-  if (ConsumeRootDir(&PP))
-    return {};
-  return createView(PP.RawEntry.data(), &__pn_.back());
-}
-
-string_view_t path::__parent_path() const {
-  if (empty())
-    return {};
-  // Determine if we have a root path but not a relative path. In that case
-  // return *this.
-  {
-    auto PP = PathParser::CreateBegin(__pn_);
-    if (ConsumeRootDir(&PP))
-      return __pn_;
-  }
-  // Otherwise remove a single element from the end of the path, and return
-  // a string representing that path
-  {
-    auto PP = PathParser::CreateEnd(__pn_);
-    --PP;
-    if (PP.RawEntry.data() == __pn_.data())
-      return {};
-    --PP;
-    return createView(__pn_.data(), &PP.RawEntry.back());
-  }
-}
-
-string_view_t path::__filename() const {
-  if (empty())
-    return {};
-  {
-    PathParser PP = PathParser::CreateBegin(__pn_);
-    if (ConsumeRootDir(&PP))
-      return {};
-  }
-  return *(--PathParser::CreateEnd(__pn_));
-}
-
-string_view_t path::__stem() const {
-  return parser::separate_filename(__filename()).first;
-}
-
-string_view_t path::__extension() const {
-  return parser::separate_filename(__filename()).second;
-}
-
-////////////////////////////////////////////////////////////////////////////
-// path.gen
-
-enum PathPartKind : unsigned char {
-  PK_None,
-  PK_RootSep,
-  PK_Filename,
-  PK_Dot,
-  PK_DotDot,
-  PK_TrailingSep
-};
-
-static PathPartKind ClassifyPathPart(string_view_t Part) {
-  if (Part.empty())
-    return PK_TrailingSep;
-  if (Part == ".")
-    return PK_Dot;
-  if (Part == "..")
-    return PK_DotDot;
-  if (Part == "/")
-    return PK_RootSep;
-  return PK_Filename;
-}
-
-path path::lexically_normal() const {
-  if (__pn_.empty())
-    return *this;
-
-  using PartKindPair = pair<string_view_t, PathPartKind>;
-  vector<PartKindPair> Parts;
-  // Guess as to how many elements the path has to avoid reallocating.
-  Parts.reserve(32);
-
-  // Track the total size of the parts as we collect them. This allows the
-  // resulting path to reserve the correct amount of memory.
-  size_t NewPathSize = 0;
-  auto AddPart = [&](PathPartKind K, string_view_t P) {
-    NewPathSize += P.size();
-    Parts.emplace_back(P, K);
-  };
-  auto LastPartKind = [&]() {
-    if (Parts.empty())
-      return PK_None;
-    return Parts.back().second;
-  };
-
-  bool MaybeNeedTrailingSep = false;
-  // Build a stack containing the remaining elements of the path, popping off
-  // elements which occur before a '..' entry.
-  for (auto PP = PathParser::CreateBegin(__pn_); PP; ++PP) {
-    auto Part = *PP;
-    PathPartKind Kind = ClassifyPathPart(Part);
-    switch (Kind) {
-    case PK_Filename:
-    case PK_RootSep: {
-      // Add all non-dot and non-dot-dot elements to the stack of elements.
-      AddPart(Kind, Part);
-      MaybeNeedTrailingSep = false;
-      break;
-    }
-    case PK_DotDot: {
-      // Only push a ".." element if there are no elements preceding the "..",
-      // or if the preceding element is itself "..".
-      auto LastKind = LastPartKind();
-      if (LastKind == PK_Filename) {
-        NewPathSize -= Parts.back().first.size();
-        Parts.pop_back();
-      } else if (LastKind != PK_RootSep)
-        AddPart(PK_DotDot, "..");
-      MaybeNeedTrailingSep = LastKind == PK_Filename;
-      break;
-    }
-    case PK_Dot:
-    case PK_TrailingSep: {
-      MaybeNeedTrailingSep = true;
-      break;
-    }
-    case PK_None:
-      _LIBCPP_UNREACHABLE();
-    }
-  }
-  // [fs.path.generic]p6.8: If the path is empty, add a dot.
-  if (Parts.empty())
-    return ".";
-
-  // [fs.path.generic]p6.7: If the last filename is dot-dot, remove any
-  // trailing directory-separator.
-  bool NeedTrailingSep = MaybeNeedTrailingSep && LastPartKind() == PK_Filename;
-
-  path Result;
-  Result.__pn_.reserve(Parts.size() + NewPathSize + NeedTrailingSep);
-  for (auto& PK : Parts)
-    Result /= PK.first;
-
-  if (NeedTrailingSep)
-    Result /= "";
-
-  return Result;
-}
-
-static int DetermineLexicalElementCount(PathParser PP) {
-  int Count = 0;
-  for (; PP; ++PP) {
-    auto Elem = *PP;
-    if (Elem == "..")
-      --Count;
-    else if (Elem != "." && Elem != "")
-      ++Count;
-  }
-  return Count;
-}
-
-path path::lexically_relative(const path& base) const {
-  { // perform root-name/root-directory mismatch checks
-    auto PP = PathParser::CreateBegin(__pn_);
-    auto PPBase = PathParser::CreateBegin(base.__pn_);
-    auto CheckIterMismatchAtBase = [&]() {
-      return PP.State != PPBase.State &&
-             (PP.inRootPath() || PPBase.inRootPath());
-    };
-    if (PP.inRootName() && PPBase.inRootName()) {
-      if (*PP != *PPBase)
-        return {};
-    } else if (CheckIterMismatchAtBase())
-      return {};
-
-    if (PP.inRootPath())
-      ++PP;
-    if (PPBase.inRootPath())
-      ++PPBase;
-    if (CheckIterMismatchAtBase())
-      return {};
-  }
-
-  // Find the first mismatching element
-  auto PP = PathParser::CreateBegin(__pn_);
-  auto PPBase = PathParser::CreateBegin(base.__pn_);
-  while (PP && PPBase && PP.State == PPBase.State && *PP == *PPBase) {
-    ++PP;
-    ++PPBase;
-  }
-
-  // If there is no mismatch, return ".".
-  if (!PP && !PPBase)
-    return ".";
-
-  // Otherwise, determine the number of elements, 'n', which are not dot or
-  // dot-dot minus the number of dot-dot elements.
-  int ElemCount = DetermineLexicalElementCount(PPBase);
-  if (ElemCount < 0)
-    return {};
-
-  // if n == 0 and (a == end() || a->empty()), returns path("."); otherwise
-  if (ElemCount == 0 && (PP.atEnd() || *PP == ""))
-    return ".";
-
-  // return a path constructed with 'n' dot-dot elements, followed by the
-  // elements of '*this' after the mismatch.
-  path Result;
-  // FIXME: Reserve enough room in Result that it won't have to re-allocate.
-  while (ElemCount--)
-    Result /= "..";
-  for (; PP; ++PP)
-    Result /= *PP;
-  return Result;
-}
-
-////////////////////////////////////////////////////////////////////////////
-// path.comparisons
-static int CompareRootName(PathParser *LHS, PathParser *RHS) {
-  if (!LHS->inRootName() && !RHS->inRootName())
-    return 0;
-
-  auto GetRootName = [](PathParser *Parser) -> string_view_t {
-    return Parser->inRootName() ? **Parser : "";
-  };
-  int res = GetRootName(LHS).compare(GetRootName(RHS));
-  ConsumeRootName(LHS);
-  ConsumeRootName(RHS);
-  return res;
-}
-
-static int CompareRootDir(PathParser *LHS, PathParser *RHS) {
-  if (!LHS->inRootDir() && RHS->inRootDir())
-    return -1;
-  else if (LHS->inRootDir() && !RHS->inRootDir())
-    return 1;
-  else {
-    ConsumeRootDir(LHS);
-    ConsumeRootDir(RHS);
-    return 0;
-  }
-}
-
-static int CompareRelative(PathParser *LHSPtr, PathParser *RHSPtr) {
-  auto &LHS = *LHSPtr;
-  auto &RHS = *RHSPtr;
-
-  int res;
-  while (LHS && RHS) {
-    if ((res = (*LHS).compare(*RHS)) != 0)
-      return res;
-    ++LHS;
-    ++RHS;
-  }
-  return 0;
-}
-
-static int CompareEndState(PathParser *LHS, PathParser *RHS) {
-  if (LHS->atEnd() && !RHS->atEnd())
-    return -1;
-  else if (!LHS->atEnd() && RHS->atEnd())
-    return 1;
-  return 0;
-}
-
-int path::__compare(string_view_t __s) const {
-  auto LHS = PathParser::CreateBegin(__pn_);
-  auto RHS = PathParser::CreateBegin(__s);
-  int res;
-
-  if ((res = CompareRootName(&LHS, &RHS)) != 0)
-    return res;
-
-  if ((res = CompareRootDir(&LHS, &RHS)) != 0)
-    return res;
-
-  if ((res = CompareRelative(&LHS, &RHS)) != 0)
-    return res;
-
-  return CompareEndState(&LHS, &RHS);
-}
-
-////////////////////////////////////////////////////////////////////////////
-// path.nonmembers
-size_t hash_value(const path& __p) noexcept {
-  auto PP = PathParser::CreateBegin(__p.native());
-  size_t hash_value = 0;
-  hash<string_view_t> hasher;
-  while (PP) {
-    hash_value = __hash_combine(hash_value, hasher(*PP));
-    ++PP;
-  }
-  return hash_value;
-}
-
-////////////////////////////////////////////////////////////////////////////
-// path.itr
-path::iterator path::begin() const {
-  auto PP = PathParser::CreateBegin(__pn_);
-  iterator it;
-  it.__path_ptr_ = this;
-  it.__state_ = static_cast<path::iterator::_ParserState>(PP.State);
-  it.__entry_ = PP.RawEntry;
-  it.__stashed_elem_.__assign_view(*PP);
-  return it;
-}
-
-path::iterator path::end() const {
-  iterator it{};
-  it.__state_ = path::iterator::_AtEnd;
-  it.__path_ptr_ = this;
-  return it;
-}
-
-path::iterator& path::iterator::__increment() {
-  PathParser PP(__path_ptr_->native(), __entry_, __state_);
-  ++PP;
-  __state_ = static_cast<_ParserState>(PP.State);
-  __entry_ = PP.RawEntry;
-  __stashed_elem_.__assign_view(*PP);
-  return *this;
-}
-
-path::iterator& path::iterator::__decrement() {
-  PathParser PP(__path_ptr_->native(), __entry_, __state_);
-  --PP;
-  __state_ = static_cast<_ParserState>(PP.State);
-  __entry_ = PP.RawEntry;
-  __stashed_elem_.__assign_view(*PP);
-  return *this;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                           directory entry definitions
-///////////////////////////////////////////////////////////////////////////////
-
-#ifndef _LIBCPP_WIN32API
-error_code directory_entry::__do_refresh() noexcept {
-  __data_.__reset();
-  error_code failure_ec;
-
-  StatT full_st;
-  file_status st = detail::posix_lstat(__p_, full_st, &failure_ec);
-  if (!status_known(st)) {
-    __data_.__reset();
-    return failure_ec;
-  }
-
-  if (!_VSTD_FS::exists(st) || !_VSTD_FS::is_symlink(st)) {
-    __data_.__cache_type_ = directory_entry::_RefreshNonSymlink;
-    __data_.__type_ = st.type();
-    __data_.__non_sym_perms_ = st.permissions();
-  } else { // we have a symlink
-    __data_.__sym_perms_ = st.permissions();
-    // Get the information about the linked entity.
-    // Ignore errors from stat, since we don't want errors regarding symlink
-    // resolution to be reported to the user.
-    error_code ignored_ec;
-    st = detail::posix_stat(__p_, full_st, &ignored_ec);
-
-    __data_.__type_ = st.type();
-    __data_.__non_sym_perms_ = st.permissions();
-
-    // If we failed to resolve the link, then only partially populate the
-    // cache.
-    if (!status_known(st)) {
-      __data_.__cache_type_ = directory_entry::_RefreshSymlinkUnresolved;
-      return error_code{};
-    }
-    // Otherwise, we resolved the link, potentially as not existing.
-    // That's OK.
-    __data_.__cache_type_ = directory_entry::_RefreshSymlink;
-  }
-
-  if (_VSTD_FS::is_regular_file(st))
-    __data_.__size_ = static_cast<uintmax_t>(full_st.st_size);
-
-  if (_VSTD_FS::exists(st)) {
-    __data_.__nlink_ = static_cast<uintmax_t>(full_st.st_nlink);
-
-    // Attempt to extract the mtime, and fail if it's not representable using
-    // file_time_type. For now we ignore the error, as we'll report it when
-    // the value is actually used.
-    error_code ignored_ec;
-    __data_.__write_time_ =
-        __extract_last_write_time(__p_, full_st, &ignored_ec);
-  }
-
-  return failure_ec;
-}
-#else
-error_code directory_entry::__do_refresh() noexcept {
-  __data_.__reset();
-  error_code failure_ec;
-
-  file_status st = _VSTD_FS::symlink_status(__p_, failure_ec);
-  if (!status_known(st)) {
-    __data_.__reset();
-    return failure_ec;
-  }
-
-  if (!_VSTD_FS::exists(st) || !_VSTD_FS::is_symlink(st)) {
-    __data_.__cache_type_ = directory_entry::_RefreshNonSymlink;
-    __data_.__type_ = st.type();
-    __data_.__non_sym_perms_ = st.permissions();
-  } else { // we have a symlink
-    __data_.__sym_perms_ = st.permissions();
-    // Get the information about the linked entity.
-    // Ignore errors from stat, since we don't want errors regarding symlink
-    // resolution to be reported to the user.
-    error_code ignored_ec;
-    st = _VSTD_FS::status(__p_, ignored_ec);
-
-    __data_.__type_ = st.type();
-    __data_.__non_sym_perms_ = st.permissions();
-
-    // If we failed to resolve the link, then only partially populate the
-    // cache.
-    if (!status_known(st)) {
-      __data_.__cache_type_ = directory_entry::_RefreshSymlinkUnresolved;
-      return error_code{};
-    }
-    __data_.__cache_type_ = directory_entry::_RefreshSymlink;
-  }
-
-  // FIXME: This is currently broken, and the implementation only a placeholder.
-  // We need to cache last_write_time, file_size, and hard_link_count here before
-  // the implementation actually works.
-
-  return failure_ec;
-}
-#endif
-
-#ifndef _LIBAUTO_UNDEF_VSTD_FS
-#pragma pop_macro("_VSTD_FS")
-#else
-#undef _VSTD
-#undef _LIBAUTO_UNDEF_VSTD_FS
-#endif
-}  // namespace android::hardware::automotive::filesystem
-/* clang-format on */
-
-#endif // defined(_LIBCPP_VERSION) && _LIBCPP_VERSION <= 8000
diff --git a/automotive/can/1.0/default/tests/fuzzer/Android.bp b/automotive/can/1.0/default/tests/fuzzer/Android.bp
index 16030d8..474b5a6 100644
--- a/automotive/can/1.0/default/tests/fuzzer/Android.bp
+++ b/automotive/can/1.0/default/tests/fuzzer/Android.bp
@@ -43,7 +43,6 @@
     ],
     static_libs: [
         "android.hardware.automotive.can@libnetdevice",
-        "android.hardware.automotive@libc++fs",
         "libnl++",
     ],
     fuzz_config: {
diff --git a/automotive/can/1.0/tools/libprotocan/include/libprotocan/MessageInjector.h b/automotive/can/1.0/tools/libprotocan/include/libprotocan/MessageInjector.h
index b0ea260..e35feee 100644
--- a/automotive/can/1.0/tools/libprotocan/include/libprotocan/MessageInjector.h
+++ b/automotive/can/1.0/tools/libprotocan/include/libprotocan/MessageInjector.h
@@ -22,6 +22,7 @@
 #include <libprotocan/MessageDef.h>
 #include <utils/Mutex.h>
 
+#include <mutex>
 #include <queue>
 
 namespace android::hardware::automotive::protocan {
diff --git a/automotive/can/aidl/default/Android.bp b/automotive/can/aidl/default/Android.bp
index d44cb91..d4e2840 100644
--- a/automotive/can/aidl/default/Android.bp
+++ b/automotive/can/aidl/default/Android.bp
@@ -44,7 +44,6 @@
     ],
     static_libs: [
         "android.hardware.automotive.can@libnetdevice",
-        "android.hardware.automotive@libc++fs",
         "libnl++",
     ],
     vintf_fragments: ["android.hardware.automotive.can.xml"],
diff --git a/automotive/can/aidl/default/CanController.cpp b/automotive/can/aidl/default/CanController.cpp
index e4b5306..1435a02 100644
--- a/automotive/can/aidl/default/CanController.cpp
+++ b/automotive/can/aidl/default/CanController.cpp
@@ -23,13 +23,13 @@
 #include <android-base/format.h>
 #include <android-base/logging.h>
 
-#include <automotive/filesystem>
+#include <filesystem>
 #include <fstream>
 #include <regex>
 
 namespace aidl::android::hardware::automotive::can {
 
-namespace fs = ::android::hardware::automotive::filesystem;
+namespace fs = ::std::filesystem;
 
 namespace fsErrors {
 static const std::error_code ok;
diff --git a/automotive/evs/aidl/impl/default/resources/evs_mock_configuration.xml b/automotive/evs/aidl/impl/default/resources/evs_mock_configuration.xml
index 6cbc18e..af5b354 100644
--- a/automotive/evs/aidl/impl/default/resources/evs_mock_configuration.xml
+++ b/automotive/evs/aidl/impl/default/resources/evs_mock_configuration.xml
@@ -55,6 +55,30 @@
                 />
             </characteristics>
         </device>
+        <device id='/dev/video11' position='front'>
+            <caps>
+                <!-- list of supported controls -->
+                <supported_controls>
+                    <control name='BRIGHTNESS' min='0' max='255'/>
+                    <control name='CONTRAST' min='0' max='255'/>
+                </supported_controls>
+
+                <stream id='0' width='640'  height='360'  format='RGBA_8888' framerate='30'/>
+            </caps>
+
+            <!-- list of parameters -->
+            <characteristics>
+                <!-- Camera intrinsic calibration matrix. See
+                     https://developer.android.com/reference/android/hardware/camera2/CameraCharacteristics.html#LENS_INTRINSIC_CALIBRATION
+                -->
+                <parameter
+                    name='LENS_INTRINSIC_CALIBRATION'
+                    type='float'
+                    size='5'
+                    value='0.0,0.0,0.0,0.0,0.0'
+                />
+            </characteristics>
+        </device>
     </camera>
     <display>
         <device id='display0' position='driver'>
diff --git a/automotive/vehicle/TEST_MAPPING b/automotive/vehicle/TEST_MAPPING
index 7306b47..77629a9 100644
--- a/automotive/vehicle/TEST_MAPPING
+++ b/automotive/vehicle/TEST_MAPPING
@@ -55,5 +55,10 @@
     {
       "name": "VehicleHalProtoMessageConverterTest"
     }
+  ],
+  "postsubmit": [
+    {
+      "name": "VehicleHalProtoMessageConverterTest"
+    }
   ]
 }
diff --git a/automotive/vehicle/aidl/impl/default_config/config/Android.bp b/automotive/vehicle/aidl/impl/default_config/config/Android.bp
index 8f1c7d1..c4f93c4 100644
--- a/automotive/vehicle/aidl/impl/default_config/config/Android.bp
+++ b/automotive/vehicle/aidl/impl/default_config/config/Android.bp
@@ -45,3 +45,24 @@
     sub_dir: "automotive/vhalconfig/",
     vendor: true,
 }
+
+prebuilt_etc_host {
+    name: "Host_Prebuilt_VehicleHalDefaultProperties_JSON",
+    filename_from_src: true,
+    src: "DefaultProperties.json",
+    relative_install_path: "automotive/vhalconfig/",
+}
+
+prebuilt_etc_host {
+    name: "Host_Prebuilt_VehicleHalTestProperties_JSON",
+    filename_from_src: true,
+    src: "TestProperties.json",
+    relative_install_path: "automotive/vhalconfig/",
+}
+
+prebuilt_etc_host {
+    name: "Host_Prebuilt_VehicleHalVendorClusterTestProperties_JSON",
+    filename_from_src: true,
+    src: "VendorClusterTestProperties.json",
+    relative_install_path: "automotive/vhalconfig/",
+}
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h b/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h
index 583e40b..79d3e77 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h
@@ -269,16 +269,6 @@
     std::string dumpInjectEvent(const std::vector<std::string>& options);
     std::string dumpSubscriptions();
 
-    template <typename T>
-    android::base::Result<T> safelyParseInt(int index, const std::string& s) {
-        T out;
-        if (!::android::base::ParseInt(s, &out)) {
-            return android::base::Error() << android::base::StringPrintf(
-                           "non-integer argument at index %d: %s\n", index, s.c_str());
-        }
-        return out;
-    }
-    android::base::Result<float> safelyParseFloat(int index, const std::string& s);
     std::vector<std::string> getOptionValues(const std::vector<std::string>& options,
                                              size_t* index);
     android::base::Result<aidl::android::hardware::automotive::vehicle::VehiclePropValue>
@@ -325,6 +315,18 @@
             const aidl::android::hardware::automotive::vehicle::VehiclePropConfig&
                     vehiclePropConfig,
             int32_t areaId);
+    template <typename T>
+    static android::base::Result<T> safelyParseInt(int index, const std::string& s) {
+        T out;
+        if (!::android::base::ParseInt(s, &out)) {
+            return android::base::Error() << android::base::StringPrintf(
+                           "non-integer argument at index %d: %s\n", index, s.c_str());
+        }
+        return out;
+    }
+    static android::base::Result<float> safelyParseFloat(int index, const std::string& s);
+    static android::base::Result<int32_t> parsePropId(const std::vector<std::string>& options,
+                                                      size_t index);
 };
 
 }  // namespace fake
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp b/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
index 9b880cd..4f060e2 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
@@ -281,6 +281,19 @@
     ifs.close();
 }
 
+inline std::string vecToStringOfHexValues(const std::vector<int32_t>& vec) {
+    std::stringstream ss;
+    ss << "[";
+    for (size_t i = 0; i < vec.size(); i++) {
+        if (i != 0) {
+            ss << ",";
+        }
+        ss << std::showbase << std::hex << vec[i];
+    }
+    ss << "]";
+    return ss.str();
+}
+
 }  // namespace
 
 void FakeVehicleHardware::storePropInitialValue(const ConfigDeclaration& config) {
@@ -1770,19 +1783,26 @@
     return "Usage: \n\n"
            "[no args]: dumps (id and value) all supported properties \n"
            "--help: shows this help\n"
-           "--list: lists the ids of all supported properties\n"
-           "--get <PROP1> [PROP2] [PROPN]: dumps the value of specific properties. \n"
-           "--getWithArg <PROP> [ValueArguments]: gets the value for a specific property with "
-           "arguments. \n"
-           "--set <PROP> [ValueArguments]: sets the value of property PROP. \n"
-           "--save-prop <prop> [-a AREA_ID]: saves the current value for PROP, integration test"
-           " that modifies prop value must call this before test and restore-prop after test. \n"
-           "--restore-prop <prop> [-a AREA_ID]: restores a previously saved property value. \n"
-           "--inject-event <PROP> [ValueArguments]: inject a property update event from car\n\n"
-           "ValueArguments are in the format of [-i INT_VALUE [INT_VALUE ...]] "
-           "[-i64 INT64_VALUE [INT64_VALUE ...]] [-f FLOAT_VALUE [FLOAT_VALUE ...]] [-s STR_VALUE] "
-           "[-b BYTES_VALUE] [-a AREA_ID].\n"
-           "Notice that the string, bytes and area value can be set just once, while the other can"
+           "--list: lists the property IDs and their supported area IDs for all supported "
+           "properties\n"
+           "--get <PROP_ID_1> [PROP_ID_2] [PROP_ID_N]: dumps the value of specific properties. \n"
+           "--getWithArg <PROP_ID> [ValueArguments]: gets the value for a specific property. "
+           "The value arguments constructs a VehiclePropValue used in the getValue request. \n"
+           "--set <PROP_ID> [ValueArguments]: sets the value of property PROP_ID, the value "
+           "arguments constructs a VehiclePropValue used in the setValue request. \n"
+           "--save-prop <PROP_ID> [-a AREA_ID]: saves the current value for PROP_ID, integration "
+           "tests that modify prop value must call this before test and restore-prop after test. \n"
+           "--restore-prop <PROP_ID> [-a AREA_ID]: restores a previously saved property value. \n"
+           "--inject-event <PROP_ID> [ValueArguments]: inject a property update event from car\n\n"
+           "ValueArguments are in the format of [-a OPTIONAL_AREA_ID] "
+           "[-i INT_VALUE_1 [INT_VALUE_2 ...]] "
+           "[-i64 INT64_VALUE_1 [INT64_VALUE_2 ...]] "
+           "[-f FLOAT_VALUE_1 [FLOAT_VALUE_2 ...]] "
+           "[-s STR_VALUE] "
+           "[-b BYTES_VALUE].\n"
+           "For example: to set property ID 0x1234, areaId 0x1 to int32 values: [1, 2, 3], "
+           "use \"--set 0x1234 -a 0x1 -i 1 2 3\"\n"
+           "Note that the string, bytes and area value can be set just once, while the other can"
            " have multiple values (so they're used in the respective array), "
            "BYTES_VALUE is in the form of 0xXXXX, e.g. 0xdeadbeef.\n" +
            genFakeDataHelp() + "Fake user HAL usage: \n" + mFakeUserHal->showDumpHelp();
@@ -1848,11 +1868,18 @@
         return "no properties to list\n";
     }
     int rowNumber = 1;
-    std::string msg = StringPrintf("listing %zu properties\n", configs.size());
+    std::stringstream ss;
+    ss << "listing " << configs.size() << " properties" << std::endl;
     for (const auto& config : configs) {
-        msg += StringPrintf("%d: %s\n", rowNumber++, PROP_ID_TO_CSTR(config.prop));
+        std::vector<int32_t> areaIds;
+        for (const auto& areaConfig : config.areaConfigs) {
+            areaIds.push_back(areaConfig.areaId);
+        }
+        ss << rowNumber++ << ": " << PROP_ID_TO_CSTR(config.prop) << ", propID: " << std::showbase
+           << std::hex << config.prop << std::noshowbase << std::dec
+           << ", areaIDs: " << vecToStringOfHexValues(areaIds) << std::endl;
     }
-    return msg;
+    return ss.str();
 }
 
 Result<void> FakeVehicleHardware::checkArgumentsSize(const std::vector<std::string>& options,
@@ -1865,6 +1892,16 @@
                                    minSize, size);
 }
 
+Result<int32_t> FakeVehicleHardware::parsePropId(const std::vector<std::string>& options,
+                                                 size_t index) {
+    const std::string& propIdStr = options[index];
+    auto result = stringToPropId(propIdStr);
+    if (result.ok()) {
+        return result;
+    }
+    return safelyParseInt<int32_t>(index, propIdStr);
+}
+
 std::string FakeVehicleHardware::dumpSpecificProperty(const std::vector<std::string>& options) {
     if (auto result = checkArgumentsSize(options, /*minSize=*/2); !result.ok()) {
         return getErrorMsg(result);
@@ -1875,7 +1912,7 @@
     size_t size = options.size();
     std::string msg = "";
     for (size_t i = 1; i < size; ++i) {
-        auto propResult = safelyParseInt<int32_t>(i, options[i]);
+        auto propResult = parsePropId(options, i);
         if (!propResult.ok()) {
             msg += getErrorMsg(propResult);
             continue;
@@ -1911,9 +1948,9 @@
     // --set/get/inject-event PROP [-f f1 f2...] [-i i1 i2...] [-i64 i1 i2...] [-s s1 s2...]
     // [-b b1 b2...] [-a a] [-t timestamp]
     size_t optionIndex = 1;
-    auto result = safelyParseInt<int32_t>(optionIndex, options[optionIndex]);
+    auto result = parsePropId(options, optionIndex);
     if (!result.ok()) {
-        return Error() << StringPrintf("Property value: \"%s\" is not a valid int: %s\n",
+        return Error() << StringPrintf("Property ID/Name: \"%s\" is not valid: %s\n",
                                        options[optionIndex].c_str(), getErrorMsg(result).c_str());
     }
     VehiclePropValue prop = {};
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/test/Android.bp b/automotive/vehicle/aidl/impl/fake_impl/hardware/test/Android.bp
index 664c877..9f002dd 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/test/Android.bp
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/test/Android.bp
@@ -56,6 +56,8 @@
     defaults: [
         "VehicleHalDefaults",
     ],
+    // Need root to use vendor lib: libgrpc++.
+    require_root: true,
     test_suites: ["device-tests"],
 }
 
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp b/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp
index cab33e1..0924360 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp
@@ -2613,6 +2613,23 @@
                                            prop1.c_str(), prop2.c_str(), prop2.c_str())));
 }
 
+TEST_F(FakeVehicleHardwareTest, testDumpSpecificPropertiesWithName) {
+    std::vector<std::string> options;
+    options.push_back("--get");
+    std::string prop1 = "INFO_FUEL_CAPACITY";
+    std::string prop2 = "TIRE_PRESSURE";
+    int prop1Int = toInt(VehicleProperty::INFO_FUEL_CAPACITY);
+    int prop2Int = toInt(VehicleProperty::TIRE_PRESSURE);
+    options.push_back(prop1);
+    options.push_back(prop2);
+    DumpResult result = getHardware()->dump(options);
+    ASSERT_FALSE(result.callerShouldDumpState);
+    ASSERT_NE(result.buffer, "");
+    ASSERT_THAT(result.buffer,
+                ContainsRegex(StringPrintf("1:.*prop: %d.*\n2-0:.*prop: %d.*\n2-1:.*prop: %d.*\n",
+                                           prop1Int, prop2Int, prop2Int)));
+}
+
 TEST_F(FakeVehicleHardwareTest, testDumpSpecificPropertiesInvalidProp) {
     std::vector<std::string> options;
     options.push_back("--get");
@@ -2766,6 +2783,7 @@
     std::string infoMakeProperty = std::to_string(toInt(VehicleProperty::INFO_MAKE));
     return {
             {"success_set_string", {"--set", infoMakeProperty, "-s", CAR_MAKE}, true},
+            {"success_set_with_name", {"--set", "INFO_MAKE", "-s", CAR_MAKE}, true},
             {"success_set_bytes", {"--set", infoMakeProperty, "-b", "0xdeadbeef"}, true},
             {"success_set_bytes_caps", {"--set", infoMakeProperty, "-b", "0xDEADBEEF"}, true},
             {"success_set_int", {"--set", infoMakeProperty, "-i", "2147483647"}, true},
@@ -2790,10 +2808,7 @@
              false,
              "No values specified"},
             {"fail_unknown_options", {"--set", infoMakeProperty, "-abcd"}, false, "Unknown option"},
-            {"fail_invalid_property",
-             {"--set", "not valid", "-s", CAR_MAKE},
-             false,
-             "not a valid int"},
+            {"fail_invalid_property", {"--set", "not_valid", "-s", CAR_MAKE}, false, "not valid"},
             {"fail_duplicate_string",
              {"--set", infoMakeProperty, "-s", CAR_MAKE, "-s", CAR_MAKE},
              false,
diff --git a/automotive/vehicle/aidl/impl/grpc/Android.bp b/automotive/vehicle/aidl/impl/grpc/Android.bp
index fd1d1ca..7a8da59 100644
--- a/automotive/vehicle/aidl/impl/grpc/Android.bp
+++ b/automotive/vehicle/aidl/impl/grpc/Android.bp
@@ -22,7 +22,7 @@
         "aprotoc",
         "protoc-gen-grpc-cpp-plugin",
     ],
-    cmd: "$(location aprotoc) -I$$(dirname $(location proto/VehicleServer.proto)) -Ihardware/interfaces/automotive/vehicle/aidl/impl/proto -Iexternal/protobuf/src --plugin=protoc-gen-grpc=$(location protoc-gen-grpc-cpp-plugin) $(location proto/VehicleServer.proto) --grpc_out=$(genDir) --cpp_out=$(genDir)",
+    cmd: "$(location aprotoc) -I$$(dirname $(location proto/VehicleServer.proto)) -Ihardware/interfaces/automotive/vehicle/aidl/impl/proto -Iexternal/protobuf/src --plugin=protoc-gen-grpc=$(location protoc-gen-grpc-cpp-plugin) $(location proto/VehicleServer.proto) --grpc_opt=generate_mock_code=true --grpc_out=$(genDir) --cpp_out=$(genDir)",
     srcs: [
         "proto/VehicleServer.proto",
         ":libprotobuf-internal-protos",
@@ -31,6 +31,7 @@
     out: [
         "VehicleServer.pb.h",
         "VehicleServer.grpc.pb.h",
+        "VehicleServer_mock.grpc.pb.h",
     ],
     visibility: ["//visibility:private"],
 }
diff --git a/automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.cpp b/automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.cpp
index 0742283..f44573a 100644
--- a/automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.cpp
+++ b/automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.cpp
@@ -39,6 +39,13 @@
       mGrpcStub(proto::VehicleServer::NewStub(mGrpcChannel)),
       mValuePollingThread([this] { ValuePollingLoop(); }) {}
 
+// Only used for unit testing.
+GRPCVehicleHardware::GRPCVehicleHardware(std::unique_ptr<proto::VehicleServer::StubInterface> stub)
+    : mServiceAddr(""),
+      mGrpcChannel(nullptr),
+      mGrpcStub(std::move(stub)),
+      mValuePollingThread([] {}) {}
+
 GRPCVehicleHardware::~GRPCVehicleHardware() {
     {
         std::lock_guard lck(mShutdownMutex);
@@ -181,6 +188,43 @@
     return static_cast<aidlvhal::StatusCode>(protoStatus.status_code());
 }
 
+aidlvhal::StatusCode GRPCVehicleHardware::subscribe(aidlvhal::SubscribeOptions options) {
+    proto::SubscribeRequest request;
+    ::grpc::ClientContext context;
+    proto::VehicleHalCallStatus protoStatus;
+    proto_msg_converter::aidlToProto(options, request.mutable_options());
+    auto grpc_status = mGrpcStub->Subscribe(&context, request, &protoStatus);
+    if (!grpc_status.ok()) {
+        if (grpc_status.error_code() == ::grpc::StatusCode::UNIMPLEMENTED) {
+            // This is a legacy sever. It should handle updateSampleRate.
+            LOG(INFO) << __func__ << ": GRPC Subscribe is not supported by the server";
+            return aidlvhal::StatusCode::OK;
+        }
+        LOG(ERROR) << __func__ << ": GRPC Subscribe Failed: " << grpc_status.error_message();
+        return aidlvhal::StatusCode::INTERNAL_ERROR;
+    }
+    return static_cast<aidlvhal::StatusCode>(protoStatus.status_code());
+}
+
+aidlvhal::StatusCode GRPCVehicleHardware::unsubscribe(int32_t propId, int32_t areaId) {
+    proto::UnsubscribeRequest request;
+    ::grpc::ClientContext context;
+    proto::VehicleHalCallStatus protoStatus;
+    request.set_prop_id(propId);
+    request.set_area_id(areaId);
+    auto grpc_status = mGrpcStub->Unsubscribe(&context, request, &protoStatus);
+    if (!grpc_status.ok()) {
+        if (grpc_status.error_code() == ::grpc::StatusCode::UNIMPLEMENTED) {
+            // This is a legacy sever. Ignore unsubscribe request.
+            LOG(INFO) << __func__ << ": GRPC Unsubscribe is not supported by the server";
+            return aidlvhal::StatusCode::OK;
+        }
+        LOG(ERROR) << __func__ << ": GRPC Unsubscribe Failed: " << grpc_status.error_message();
+        return aidlvhal::StatusCode::INTERNAL_ERROR;
+    }
+    return static_cast<aidlvhal::StatusCode>(protoStatus.status_code());
+}
+
 aidlvhal::StatusCode GRPCVehicleHardware::updateSampleRate(int32_t propId, int32_t areaId,
                                                            float sampleRate) {
     ::grpc::ClientContext context;
diff --git a/automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.h b/automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.h
index ddd620e..9750f62 100644
--- a/automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.h
+++ b/automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.h
@@ -43,6 +43,9 @@
   public:
     explicit GRPCVehicleHardware(std::string service_addr);
 
+    // Only used for unit testing.
+    explicit GRPCVehicleHardware(std::unique_ptr<proto::VehicleServer::StubInterface> stub);
+
     ~GRPCVehicleHardware();
 
     // Get all the property configs.
@@ -80,6 +83,10 @@
     aidlvhal::StatusCode updateSampleRate(int32_t propId, int32_t areaId,
                                           float sampleRate) override;
 
+    aidlvhal::StatusCode subscribe(aidlvhal::SubscribeOptions options) override;
+
+    aidlvhal::StatusCode unsubscribe(int32_t propId, int32_t areaId) override;
+
     bool waitForConnected(std::chrono::milliseconds waitTime);
 
   protected:
@@ -91,7 +98,7 @@
 
     std::string mServiceAddr;
     std::shared_ptr<::grpc::Channel> mGrpcChannel;
-    std::unique_ptr<proto::VehicleServer::Stub> mGrpcStub;
+    std::unique_ptr<proto::VehicleServer::StubInterface> mGrpcStub;
     std::thread mValuePollingThread;
 
     std::unique_ptr<const PropertySetErrorCallback> mOnSetErr;
diff --git a/automotive/vehicle/aidl/impl/grpc/GRPCVehicleProxyServer.cpp b/automotive/vehicle/aidl/impl/grpc/GRPCVehicleProxyServer.cpp
index af3dd59..a6abfa3 100644
--- a/automotive/vehicle/aidl/impl/grpc/GRPCVehicleProxyServer.cpp
+++ b/automotive/vehicle/aidl/impl/grpc/GRPCVehicleProxyServer.cpp
@@ -164,6 +164,27 @@
     return ::grpc::Status::OK;
 }
 
+::grpc::Status GrpcVehicleProxyServer::Subscribe(::grpc::ServerContext* context,
+                                                 const proto::SubscribeRequest* request,
+                                                 proto::VehicleHalCallStatus* status) {
+    const auto& protoSubscribeOptions = request->options();
+    aidlvhal::SubscribeOptions aidlSubscribeOptions = {};
+    proto_msg_converter::protoToAidl(protoSubscribeOptions, &aidlSubscribeOptions);
+    const auto status_code = mHardware->subscribe(aidlSubscribeOptions);
+    status->set_status_code(static_cast<proto::StatusCode>(status_code));
+    return ::grpc::Status::OK;
+}
+
+::grpc::Status GrpcVehicleProxyServer::Unsubscribe(::grpc::ServerContext* context,
+                                                   const proto::UnsubscribeRequest* request,
+                                                   proto::VehicleHalCallStatus* status) {
+    int32_t propId = request->prop_id();
+    int32_t areaId = request->area_id();
+    const auto status_code = mHardware->unsubscribe(propId, areaId);
+    status->set_status_code(static_cast<proto::StatusCode>(status_code));
+    return ::grpc::Status::OK;
+}
+
 ::grpc::Status GrpcVehicleProxyServer::CheckHealth(::grpc::ServerContext* context,
                                                    const ::google::protobuf::Empty*,
                                                    proto::VehicleHalCallStatus* status) {
diff --git a/automotive/vehicle/aidl/impl/grpc/GRPCVehicleProxyServer.h b/automotive/vehicle/aidl/impl/grpc/GRPCVehicleProxyServer.h
index 3596354..dd9e2aa 100644
--- a/automotive/vehicle/aidl/impl/grpc/GRPCVehicleProxyServer.h
+++ b/automotive/vehicle/aidl/impl/grpc/GRPCVehicleProxyServer.h
@@ -57,6 +57,13 @@
                                     const proto::UpdateSampleRateRequest* request,
                                     proto::VehicleHalCallStatus* status) override;
 
+    ::grpc::Status Subscribe(::grpc::ServerContext* context, const proto::SubscribeRequest* request,
+                             proto::VehicleHalCallStatus* status) override;
+
+    ::grpc::Status Unsubscribe(::grpc::ServerContext* context,
+                               const proto::UnsubscribeRequest* request,
+                               proto::VehicleHalCallStatus* status) override;
+
     ::grpc::Status CheckHealth(::grpc::ServerContext* context, const ::google::protobuf::Empty*,
                                proto::VehicleHalCallStatus* status) override;
 
diff --git a/automotive/vehicle/aidl/impl/grpc/proto/VehicleServer.proto b/automotive/vehicle/aidl/impl/grpc/proto/VehicleServer.proto
index 22b11d8..732957f 100644
--- a/automotive/vehicle/aidl/impl/grpc/proto/VehicleServer.proto
+++ b/automotive/vehicle/aidl/impl/grpc/proto/VehicleServer.proto
@@ -20,7 +20,9 @@
 
 import "android/hardware/automotive/vehicle/DumpOptions.proto";
 import "android/hardware/automotive/vehicle/DumpResult.proto";
+import "android/hardware/automotive/vehicle/SubscribeRequest.proto";
 import "android/hardware/automotive/vehicle/StatusCode.proto";
+import "android/hardware/automotive/vehicle/UnsubscribeRequest.proto";
 import "android/hardware/automotive/vehicle/VehiclePropConfig.proto";
 import "android/hardware/automotive/vehicle/VehiclePropValue.proto";
 import "android/hardware/automotive/vehicle/VehiclePropValueRequest.proto";
@@ -40,4 +42,8 @@
     rpc Dump(DumpOptions) returns (DumpResult) {}
 
     rpc StartPropertyValuesStream(google.protobuf.Empty) returns (stream VehiclePropValues) {}
+
+    rpc Subscribe(SubscribeRequest) returns (VehicleHalCallStatus) {}
+
+    rpc Unsubscribe(UnsubscribeRequest) returns (VehicleHalCallStatus) {}
 }
diff --git a/automotive/vehicle/aidl/impl/grpc/test/GRPCVehicleHardwareUnitTest.cpp b/automotive/vehicle/aidl/impl/grpc/test/GRPCVehicleHardwareUnitTest.cpp
index f578021..3bd7e0e 100644
--- a/automotive/vehicle/aidl/impl/grpc/test/GRPCVehicleHardwareUnitTest.cpp
+++ b/automotive/vehicle/aidl/impl/grpc/test/GRPCVehicleHardwareUnitTest.cpp
@@ -15,6 +15,7 @@
 #include "GRPCVehicleHardware.h"
 #include "VehicleServer.grpc.pb.h"
 #include "VehicleServer.pb.h"
+#include "VehicleServer_mock.grpc.pb.h"
 
 #include <gmock/gmock.h>
 #include <grpc++/grpc++.h>
@@ -26,6 +27,17 @@
 
 namespace android::hardware::automotive::vehicle::virtualization {
 
+namespace aidlvhal = ::aidl::android::hardware::automotive::vehicle;
+
+using ::testing::_;
+using ::testing::DoAll;
+using ::testing::NiceMock;
+using ::testing::Return;
+using ::testing::SaveArg;
+using ::testing::SetArgPointee;
+
+using proto::MockVehicleServerStub;
+
 const std::string kFakeServerAddr = "0.0.0.0:54321";
 
 class FakeVehicleServer : public proto::VehicleServer::Service {
@@ -91,4 +103,131 @@
     }
 }
 
+class GRPCVehicleHardwareMockServerUnitTest : public ::testing::Test {
+  protected:
+    NiceMock<MockVehicleServerStub>* mGrpcStub;
+    std::unique_ptr<GRPCVehicleHardware> mHardware;
+
+    void SetUp() override {
+        auto stub = std::make_unique<NiceMock<MockVehicleServerStub>>();
+        ;
+        mGrpcStub = stub.get();
+        mHardware = std::make_unique<GRPCVehicleHardware>(std::move(stub));
+    }
+
+    void TearDown() override { mHardware.reset(); }
+};
+
+MATCHER_P(RepeatedInt32Eq, expected_values, "") {
+    return std::vector<int32_t>(arg.begin(), arg.end()) == expected_values;
+}
+
+TEST_F(GRPCVehicleHardwareMockServerUnitTest, Subscribe) {
+    proto::VehicleHalCallStatus protoStatus;
+    protoStatus.set_status_code(proto::StatusCode::OK);
+    proto::SubscribeRequest actualRequest;
+
+    EXPECT_CALL(*mGrpcStub, Subscribe(_, _, _))
+            .WillOnce(DoAll(SaveArg<1>(&actualRequest), SetArgPointee<2>(protoStatus),
+                            Return(::grpc::Status::OK)));
+
+    aidlvhal::SubscribeOptions options = {.propId = 1,
+                                          .areaIds = {1, 2, 3, 4},
+                                          .sampleRate = 1.234,
+                                          .resolution = 0.01,
+                                          .enableVariableUpdateRate = true};
+    auto status = mHardware->subscribe(options);
+
+    EXPECT_EQ(status, aidlvhal::StatusCode::OK);
+    const auto& protoOptions = actualRequest.options();
+    EXPECT_EQ(protoOptions.prop_id(), 1);
+    EXPECT_THAT(protoOptions.area_ids(), RepeatedInt32Eq(std::vector<int32_t>({1, 2, 3, 4})));
+    EXPECT_FLOAT_EQ(protoOptions.sample_rate(), 1.234);
+    EXPECT_FLOAT_EQ(protoOptions.resolution(), 0.01);
+    EXPECT_EQ(protoOptions.enable_variable_update_rate(), true);
+}
+
+TEST_F(GRPCVehicleHardwareMockServerUnitTest, SubscribeLegacyServer) {
+    EXPECT_CALL(*mGrpcStub, Subscribe(_, _, _))
+            .WillOnce(Return(::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "")));
+
+    aidlvhal::SubscribeOptions options;
+    auto status = mHardware->subscribe(options);
+
+    EXPECT_EQ(status, aidlvhal::StatusCode::OK);
+}
+
+TEST_F(GRPCVehicleHardwareMockServerUnitTest, SubscribeGrpcFailure) {
+    EXPECT_CALL(*mGrpcStub, Subscribe(_, _, _))
+            .WillOnce(Return(::grpc::Status(::grpc::StatusCode::INTERNAL, "GRPC Error")));
+
+    aidlvhal::SubscribeOptions options;
+    auto status = mHardware->subscribe(options);
+
+    EXPECT_EQ(status, aidlvhal::StatusCode::INTERNAL_ERROR);
+}
+
+TEST_F(GRPCVehicleHardwareMockServerUnitTest, SubscribeProtoFailure) {
+    proto::VehicleHalCallStatus protoStatus;
+    protoStatus.set_status_code(proto::StatusCode::NOT_AVAILABLE_SPEED_LOW);
+
+    EXPECT_CALL(*mGrpcStub, Subscribe(_, _, _))
+            .WillOnce(DoAll(SetArgPointee<2>(protoStatus),  // Set the output status
+                            Return(::grpc::Status::OK)));
+
+    aidlvhal::SubscribeOptions options;
+    auto status = mHardware->subscribe(options);
+
+    EXPECT_EQ(status, aidlvhal::StatusCode::NOT_AVAILABLE_SPEED_LOW);
+}
+
+TEST_F(GRPCVehicleHardwareMockServerUnitTest, Unsubscribe) {
+    proto::VehicleHalCallStatus protoStatus;
+    protoStatus.set_status_code(proto::StatusCode::OK);
+    proto::UnsubscribeRequest actualRequest;
+
+    EXPECT_CALL(*mGrpcStub, Unsubscribe(_, _, _))
+            .WillOnce(DoAll(SaveArg<1>(&actualRequest), SetArgPointee<2>(protoStatus),
+                            Return(::grpc::Status::OK)));
+
+    int32_t propId = 1;
+    int32_t areaId = 2;
+    auto status = mHardware->unsubscribe(propId, areaId);
+
+    EXPECT_EQ(status, aidlvhal::StatusCode::OK);
+    EXPECT_EQ(actualRequest.prop_id(), propId);
+    EXPECT_EQ(actualRequest.area_id(), areaId);
+}
+
+TEST_F(GRPCVehicleHardwareMockServerUnitTest, UnsubscribeLegacyServer) {
+    EXPECT_CALL(*mGrpcStub, Unsubscribe(_, _, _))
+            .WillOnce(Return(::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "")));
+
+    auto status = mHardware->unsubscribe(1, 2);
+
+    EXPECT_EQ(status, aidlvhal::StatusCode::OK);
+}
+
+TEST_F(GRPCVehicleHardwareMockServerUnitTest, UnsubscribeGrpcFailure) {
+    EXPECT_CALL(*mGrpcStub, Unsubscribe(_, _, _))
+            .WillOnce(Return(::grpc::Status(::grpc::StatusCode::INTERNAL, "GRPC Error")));
+
+    auto status = mHardware->unsubscribe(1, 2);
+
+    EXPECT_EQ(status, aidlvhal::StatusCode::INTERNAL_ERROR);
+}
+
+TEST_F(GRPCVehicleHardwareMockServerUnitTest, UnsubscribeProtoFailure) {
+    proto::VehicleHalCallStatus protoStatus;
+    protoStatus.set_status_code(proto::StatusCode::NOT_AVAILABLE_SPEED_LOW);
+
+    EXPECT_CALL(*mGrpcStub, Unsubscribe(_, _, _))
+            .WillOnce(DoAll(SetArgPointee<2>(protoStatus),  // Set the output status
+                            Return(::grpc::Status::OK)));
+
+    auto status = mHardware->unsubscribe(1, 2);
+
+    EXPECT_EQ(status, aidlvhal::StatusCode::NOT_AVAILABLE_SPEED_LOW);
+}
+
 }  // namespace android::hardware::automotive::vehicle::virtualization
diff --git a/automotive/vehicle/aidl/impl/grpc/test/GRPCVehicleProxyServerUnitTest.cpp b/automotive/vehicle/aidl/impl/grpc/test/GRPCVehicleProxyServerUnitTest.cpp
index 49e6fc9..ca5c2d5 100644
--- a/automotive/vehicle/aidl/impl/grpc/test/GRPCVehicleProxyServerUnitTest.cpp
+++ b/automotive/vehicle/aidl/impl/grpc/test/GRPCVehicleProxyServerUnitTest.cpp
@@ -30,6 +30,13 @@
 
 namespace android::hardware::automotive::vehicle::virtualization {
 
+namespace aidlvhal = ::aidl::android::hardware::automotive::vehicle;
+
+using ::testing::_;
+using ::testing::DoAll;
+using ::testing::Return;
+using ::testing::SaveArg;
+
 const std::string kFakeServerAddr = "0.0.0.0:54321";
 
 class VehicleHardwareForTest : public IVehicleHardware {
@@ -39,38 +46,30 @@
         mOnProp = std::move(callback);
     }
 
-    void onPropertyEvent(
-            std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropValue> values) {
+    void onPropertyEvent(std::vector<aidlvhal::VehiclePropValue> values) {
         if (mOnProp) {
             (*mOnProp)(std::move(values));
         }
     }
 
     // Functions that we do not care.
-    std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropConfig>
-    getAllPropertyConfigs() const override {
-        return {};
-    }
+    std::vector<aidlvhal::VehiclePropConfig> getAllPropertyConfigs() const override { return {}; }
 
-    aidl::android::hardware::automotive::vehicle::StatusCode setValues(
+    aidlvhal::StatusCode setValues(
             std::shared_ptr<const SetValuesCallback> callback,
-            const std::vector<aidl::android::hardware::automotive::vehicle::SetValueRequest>&
-                    requests) override {
-        return aidl::android::hardware::automotive::vehicle::StatusCode::OK;
+            const std::vector<aidlvhal::SetValueRequest>& requests) override {
+        return aidlvhal::StatusCode::OK;
     }
 
-    aidl::android::hardware::automotive::vehicle::StatusCode getValues(
+    aidlvhal::StatusCode getValues(
             std::shared_ptr<const GetValuesCallback> callback,
-            const std::vector<aidl::android::hardware::automotive::vehicle::GetValueRequest>&
-                    requests) const override {
-        return aidl::android::hardware::automotive::vehicle::StatusCode::OK;
+            const std::vector<aidlvhal::GetValueRequest>& requests) const override {
+        return aidlvhal::StatusCode::OK;
     }
 
     DumpResult dump(const std::vector<std::string>& options) override { return {}; }
 
-    aidl::android::hardware::automotive::vehicle::StatusCode checkHealth() override {
-        return aidl::android::hardware::automotive::vehicle::StatusCode::OK;
-    }
+    aidlvhal::StatusCode checkHealth() override { return aidlvhal::StatusCode::OK; }
 
     void registerOnPropertySetErrorEvent(
             std::unique_ptr<const PropertySetErrorCallback> callback) override {}
@@ -79,6 +78,35 @@
     std::unique_ptr<const PropertyChangeCallback> mOnProp;
 };
 
+class MockVehicleHardware : public IVehicleHardware {
+  public:
+    // Mock methods from IVehicleHardware
+    MOCK_METHOD(std::vector<aidlvhal::VehiclePropConfig>, getAllPropertyConfigs, (),
+                (const, override));
+
+    MOCK_METHOD((aidlvhal::StatusCode), setValues,
+                (std::shared_ptr<const SetValuesCallback> callback,
+                 const std::vector<aidlvhal::SetValueRequest>& requests),
+                (override));
+
+    MOCK_METHOD((aidlvhal::StatusCode), getValues,
+                (std::shared_ptr<const GetValuesCallback> callback,
+                 const std::vector<aidlvhal::GetValueRequest>& requests),
+                (const, override));
+
+    MOCK_METHOD(DumpResult, dump, (const std::vector<std::string>& options), (override));
+    MOCK_METHOD(aidlvhal::StatusCode, checkHealth, (), (override));
+    MOCK_METHOD(void, registerOnPropertyChangeEvent,
+                (std::unique_ptr<const PropertyChangeCallback> callback), (override));
+    MOCK_METHOD(void, registerOnPropertySetErrorEvent,
+                (std::unique_ptr<const PropertySetErrorCallback> callback), (override));
+    MOCK_METHOD(std::chrono::nanoseconds, getPropertyOnChangeEventBatchingWindow, (), (override));
+    MOCK_METHOD(aidlvhal::StatusCode, subscribe, (aidlvhal::SubscribeOptions options), (override));
+    MOCK_METHOD(aidlvhal::StatusCode, unsubscribe, (int32_t propId, int32_t areaId), (override));
+    MOCK_METHOD(aidlvhal::StatusCode, updateSampleRate,
+                (int32_t propId, int32_t areaId, float sampleRate), (override));
+};
+
 TEST(GRPCVehicleProxyServerUnitTest, ClientConnectDisconnect) {
     auto testHardware = std::make_unique<VehicleHardwareForTest>();
     // HACK: manipulate the underlying hardware via raw pointer for testing.
@@ -144,4 +172,70 @@
     vehicleServer->Shutdown().Wait();
 }
 
+TEST(GRPCVehicleProxyServerUnitTest, Subscribe) {
+    auto mockHardware = std::make_unique<MockVehicleHardware>();
+    // We make sure this is alive inside the function scope.
+    MockVehicleHardware* mockHardwarePtr = mockHardware.get();
+    GrpcVehicleProxyServer server = GrpcVehicleProxyServer("", std::move(mockHardware));
+    ::grpc::ServerContext context;
+    proto::SubscribeRequest request;
+    proto::VehicleHalCallStatus returnStatus;
+    aidlvhal::SubscribeOptions aidlOptions;
+    request.mutable_options()->set_prop_id(1);
+    request.mutable_options()->add_area_ids(2);
+    request.mutable_options()->set_sample_rate(1.234);
+    request.mutable_options()->set_resolution(0.01);
+    request.mutable_options()->set_enable_variable_update_rate(true);
+
+    EXPECT_CALL(*mockHardwarePtr, subscribe(_))
+            .WillOnce(DoAll(SaveArg<0>(&aidlOptions), Return(aidlvhal::StatusCode::OK)));
+
+    auto grpcStatus = server.Subscribe(&context, &request, &returnStatus);
+
+    EXPECT_TRUE(grpcStatus.ok());
+    EXPECT_EQ(returnStatus.status_code(), proto::StatusCode::OK);
+    EXPECT_EQ(aidlOptions.propId, 1);
+    EXPECT_EQ(aidlOptions.areaIds, std::vector<int32_t>{2});
+    EXPECT_FLOAT_EQ(aidlOptions.sampleRate, 1.234);
+    EXPECT_FLOAT_EQ(aidlOptions.resolution, 0.01);
+    EXPECT_TRUE(aidlOptions.enableVariableUpdateRate);
+}
+
+TEST(GRPCVehicleProxyServerUnitTest, SubscribeNotAvailable) {
+    auto mockHardware = std::make_unique<MockVehicleHardware>();
+    // We make sure this is alive inside the function scope.
+    MockVehicleHardware* mockHardwarePtr = mockHardware.get();
+    GrpcVehicleProxyServer server = GrpcVehicleProxyServer("", std::move(mockHardware));
+    ::grpc::ServerContext context;
+    proto::SubscribeRequest request;
+    proto::VehicleHalCallStatus returnStatus;
+
+    EXPECT_CALL(*mockHardwarePtr, subscribe(_))
+            .WillOnce(Return(aidlvhal::StatusCode::NOT_AVAILABLE));
+
+    auto grpcStatus = server.Subscribe(&context, &request, &returnStatus);
+
+    EXPECT_TRUE(grpcStatus.ok());
+    EXPECT_EQ(returnStatus.status_code(), proto::StatusCode::NOT_AVAILABLE);
+}
+
+TEST(GRPCVehicleProxyServerUnitTest, Unsubscribe) {
+    auto mockHardware = std::make_unique<MockVehicleHardware>();
+    // We make sure this is alive inside the function scope.
+    MockVehicleHardware* mockHardwarePtr = mockHardware.get();
+    GrpcVehicleProxyServer server = GrpcVehicleProxyServer("", std::move(mockHardware));
+    ::grpc::ServerContext context;
+    proto::UnsubscribeRequest request;
+    proto::VehicleHalCallStatus returnStatus;
+    request.set_prop_id(1);
+    request.set_area_id(2);
+
+    EXPECT_CALL(*mockHardwarePtr, unsubscribe(1, 2)).WillOnce(Return(aidlvhal::StatusCode::OK));
+
+    auto grpcStatus = server.Unsubscribe(&context, &request, &returnStatus);
+
+    EXPECT_TRUE(grpcStatus.ok());
+    EXPECT_EQ(returnStatus.status_code(), proto::StatusCode::OK);
+}
+
 }  // namespace android::hardware::automotive::vehicle::virtualization
diff --git a/automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/Android.bp b/automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/Android.bp
index d10aa3e..94c09aa 100644
--- a/automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/Android.bp
+++ b/automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/Android.bp
@@ -42,23 +42,21 @@
     host_supported: true,
 }
 
-cc_test {
+cc_test_host {
     name: "VehicleHalProtoMessageConverterTest",
     srcs: [
         "test/*.cpp",
     ],
     vendor: true,
     defaults: ["VehicleHalDefaults"],
-    shared_libs: [
-        "libprotobuf-cpp-full",
-        "libjsoncpp",
-    ],
     static_libs: [
         "VehicleHalJsonConfigLoaderEnableTestProperties",
         "VehicleHalProtoMessageConverter",
         "VehicleHalProtos",
         "VehicleHalUtils",
         "libgtest",
+        "libprotobuf-cpp-full",
+        "libjsoncpp",
     ],
     data: [
         ":VehicleHalDefaultProperties_JSON",
diff --git a/automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/include/ProtoMessageConverter.h b/automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/include/ProtoMessageConverter.h
index 1c26fe8..25c07ef 100644
--- a/automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/include/ProtoMessageConverter.h
+++ b/automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/include/ProtoMessageConverter.h
@@ -18,6 +18,7 @@
 #define android_hardware_automotive_vehicle_aidl_impl_grpc_utils_proto_message_converter_include_ProtoMessageConverter_H_
 
 #include <VehicleHalTypes.h>
+#include <android/hardware/automotive/vehicle/SubscribeOptions.pb.h>
 #include <android/hardware/automotive/vehicle/VehicleAreaConfig.pb.h>
 #include <android/hardware/automotive/vehicle/VehiclePropConfig.pb.h>
 #include <android/hardware/automotive/vehicle/VehiclePropValue.pb.h>
@@ -46,6 +47,12 @@
 void protoToAidl(
         const ::android::hardware::automotive::vehicle::proto::VehiclePropValue& inProtoVal,
         ::aidl::android::hardware::automotive::vehicle::VehiclePropValue* outAidlVal);
+// Convert AIDL SubscribeOptions to Protobuf SubscribeOptions.
+void aidlToProto(const ::aidl::android::hardware::automotive::vehicle::SubscribeOptions& in,
+                 ::android::hardware::automotive::vehicle::proto::SubscribeOptions* out);
+// Convert Protobuf SubscribeOptions to AIDL SubscribeOptions.
+void protoToAidl(const ::android::hardware::automotive::vehicle::proto::SubscribeOptions& in,
+                 ::aidl::android::hardware::automotive::vehicle::SubscribeOptions* out);
 
 }  // namespace proto_msg_converter
 }  // namespace vehicle
diff --git a/automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/src/ProtoMessageConverter.cpp b/automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/src/ProtoMessageConverter.cpp
index 1ea0df4..c40004a 100644
--- a/automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/src/ProtoMessageConverter.cpp
+++ b/automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/src/ProtoMessageConverter.cpp
@@ -152,6 +152,24 @@
     COPY_PROTOBUF_VEC_TO_VHAL_TYPE(in, float_values, out, value.floatValues);
 }
 
+void aidlToProto(const aidl_vehicle::SubscribeOptions& in, proto::SubscribeOptions* out) {
+    out->set_prop_id(in.propId);
+    for (int areaId : in.areaIds) {
+        out->add_area_ids(areaId);
+    }
+    out->set_sample_rate(in.sampleRate);
+    out->set_resolution(in.resolution);
+    out->set_enable_variable_update_rate(in.enableVariableUpdateRate);
+}
+
+void protoToAidl(const proto::SubscribeOptions& in, aidl_vehicle::SubscribeOptions* out) {
+    out->propId = in.prop_id();
+    COPY_PROTOBUF_VEC_TO_VHAL_TYPE(in, area_ids, out, areaIds);
+    out->sampleRate = in.sample_rate();
+    out->resolution = in.resolution();
+    out->enableVariableUpdateRate = in.enable_variable_update_rate();
+}
+
 #undef COPY_PROTOBUF_VEC_TO_VHAL_TYPE
 #undef CAST_COPY_PROTOBUF_VEC_TO_VHAL_TYPE
 
diff --git a/automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/test/proto_message_converter_test.cpp b/automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/test/proto_message_converter_test.cpp
index 308be46..2efda5b 100644
--- a/automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/test/proto_message_converter_test.cpp
+++ b/automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/test/proto_message_converter_test.cpp
@@ -22,6 +22,7 @@
 
 #include <android-base/file.h>
 #include <android-base/format.h>
+#include <android/hardware/automotive/vehicle/SubscribeOptions.pb.h>
 #include <android/hardware/automotive/vehicle/VehiclePropConfig.pb.h>
 #include <android/hardware/automotive/vehicle/VehiclePropValue.pb.h>
 #include <gtest/gtest.h>
@@ -114,6 +115,21 @@
                              return ::fmt::format("property_{:d}", info.param.prop);
                          });
 
+TEST_F(PropValueConversionTest, testConvertSubscribeOption) {
+    proto::SubscribeOptions protoOptions;
+    aidl_vehicle::SubscribeOptions aidlOptions = {.propId = 1,
+                                                  .areaIds = {1, 2},
+                                                  .sampleRate = 1.234,
+                                                  .resolution = 0.01,
+                                                  .enableVariableUpdateRate = true};
+    aidl_vehicle::SubscribeOptions outputOptions;
+
+    aidlToProto(aidlOptions, &protoOptions);
+    protoToAidl(protoOptions, &outputOptions);
+
+    EXPECT_EQ(aidlOptions, outputOptions);
+}
+
 }  // namespace proto_msg_converter
 }  // namespace vehicle
 }  // namespace automotive
diff --git a/automotive/vehicle/aidl/impl/proto/Android.bp b/automotive/vehicle/aidl/impl/proto/Android.bp
index 56fad7e..b2edf75 100644
--- a/automotive/vehicle/aidl/impl/proto/Android.bp
+++ b/automotive/vehicle/aidl/impl/proto/Android.bp
@@ -50,6 +50,9 @@
         "android/hardware/automotive/vehicle/VehiclePropertyStatus.pb.h",
         "android/hardware/automotive/vehicle/VehiclePropValue.pb.h",
         "android/hardware/automotive/vehicle/VehiclePropValueRequest.pb.h",
+        "android/hardware/automotive/vehicle/SubscribeOptions.pb.h",
+        "android/hardware/automotive/vehicle/SubscribeRequest.pb.h",
+        "android/hardware/automotive/vehicle/UnsubscribeRequest.pb.h",
     ],
 }
 
@@ -74,6 +77,9 @@
         "android/hardware/automotive/vehicle/VehiclePropertyStatus.pb.cc",
         "android/hardware/automotive/vehicle/VehiclePropValue.pb.cc",
         "android/hardware/automotive/vehicle/VehiclePropValueRequest.pb.cc",
+        "android/hardware/automotive/vehicle/SubscribeOptions.pb.cc",
+        "android/hardware/automotive/vehicle/SubscribeRequest.pb.cc",
+        "android/hardware/automotive/vehicle/UnsubscribeRequest.pb.cc",
     ],
 }
 
diff --git a/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/SubscribeOptions.proto b/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/SubscribeOptions.proto
new file mode 100644
index 0000000..3fc6581
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/SubscribeOptions.proto
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto3";
+
+package android.hardware.automotive.vehicle.proto;
+
+message SubscribeOptions {
+    int32 prop_id = 1;
+    repeated int32 area_ids = 2;
+    float sample_rate = 3;
+    float resolution = 4;
+    bool enable_variable_update_rate = 5;
+}
\ No newline at end of file
diff --git a/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/SubscribeRequest.proto b/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/SubscribeRequest.proto
new file mode 100644
index 0000000..4ce6335
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/SubscribeRequest.proto
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto3";
+
+package android.hardware.automotive.vehicle.proto;
+
+import "android/hardware/automotive/vehicle/SubscribeOptions.proto";
+
+message SubscribeRequest {
+    SubscribeOptions options = 1;
+}
\ No newline at end of file
diff --git a/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/UnsubscribeRequest.proto b/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/UnsubscribeRequest.proto
new file mode 100644
index 0000000..314fbf0
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/proto/android/hardware/automotive/vehicle/UnsubscribeRequest.proto
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto3";
+
+package android.hardware.automotive.vehicle.proto;
+
+message UnsubscribeRequest {
+    int32 prop_id = 1;
+    int32 area_id = 2;
+}
\ No newline at end of file
diff --git a/automotive/vehicle/aidl/impl/utils/common/include/VehicleUtils.h b/automotive/vehicle/aidl/impl/utils/common/include/VehicleUtils.h
index aca725d..f48bb2a 100644
--- a/automotive/vehicle/aidl/impl/utils/common/include/VehicleUtils.h
+++ b/automotive/vehicle/aidl/impl/utils/common/include/VehicleUtils.h
@@ -328,11 +328,15 @@
     }
 };
 
+// This is for debug purpose only.
 inline std::string propIdToString(int32_t propId) {
     return toString(
             static_cast<aidl::android::hardware::automotive::vehicle::VehicleProperty>(propId));
 }
 
+// This is for debug purpose only.
+android::base::Result<int32_t> stringToPropId(const std::string& propName);
+
 template <typename T>
 void roundToNearestResolution(std::vector<T>& arrayToSanitize, float resolution) {
     if (resolution == 0) {
diff --git a/automotive/vehicle/aidl/impl/utils/common/src/VehicleUtils.cpp b/automotive/vehicle/aidl/impl/utils/common/src/VehicleUtils.cpp
index f85728d..4d06e4e 100644
--- a/automotive/vehicle/aidl/impl/utils/common/src/VehicleUtils.cpp
+++ b/automotive/vehicle/aidl/impl/utils/common/src/VehicleUtils.cpp
@@ -16,14 +16,18 @@
 
 #include "VehicleUtils.h"
 
+#include <unordered_map>
+
 namespace android {
 namespace hardware {
 namespace automotive {
 namespace vehicle {
 
 using ::aidl::android::hardware::automotive::vehicle::StatusCode;
+using ::aidl::android::hardware::automotive::vehicle::toString;
 using ::aidl::android::hardware::automotive::vehicle::VehicleAreaConfig;
 using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig;
+using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
 using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyGroup;
 using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType;
 using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
@@ -31,6 +35,39 @@
 using ::android::base::Result;
 using ::ndk::ScopedAStatus;
 
+namespace {
+
+class PropertyIdByNameSingleton {
+  public:
+    static PropertyIdByNameSingleton& getInstance() {
+        static PropertyIdByNameSingleton instance;
+        return instance;
+    }
+
+    Result<int32_t> getPropertyId(const std::string& name) {
+        auto it = mPropertyIdByName.find(name);
+        if (it == mPropertyIdByName.end()) {
+            return Error();
+        }
+        return it->second;
+    }
+
+    PropertyIdByNameSingleton(PropertyIdByNameSingleton const&) = delete;
+    void operator=(PropertyIdByNameSingleton const&) = delete;
+
+  private:
+    std::unordered_map<std::string, int32_t> mPropertyIdByName;
+
+    PropertyIdByNameSingleton() {
+        constexpr auto values = ndk::internal::enum_values<VehicleProperty>;
+        for (unsigned int i = 0; i < values.size(); i++) {
+            mPropertyIdByName.emplace(toString(values[i]), toInt(values[i]));
+        }
+    }
+};
+
+}  // namespace
+
 Result<void> checkPropValue(const VehiclePropValue& value, const VehiclePropConfig* config) {
     int32_t property = value.prop;
     VehiclePropertyType type = getPropType(property);
@@ -213,6 +250,10 @@
     return aidl::android::hardware::automotive::vehicle::toString(mCode);
 }
 
+Result<int32_t> stringToPropId(const std::string& propName) {
+    return PropertyIdByNameSingleton::getInstance().getPropertyId(propName);
+}
+
 }  // namespace vehicle
 }  // namespace automotive
 }  // namespace hardware
diff --git a/automotive/vehicle/aidl/impl/utils/common/test/VehicleUtilsTest.cpp b/automotive/vehicle/aidl/impl/utils/common/test/VehicleUtilsTest.cpp
index 9abb2a2..1048877 100644
--- a/automotive/vehicle/aidl/impl/utils/common/test/VehicleUtilsTest.cpp
+++ b/automotive/vehicle/aidl/impl/utils/common/test/VehicleUtilsTest.cpp
@@ -770,6 +770,23 @@
     ASSERT_EQ(result.error().message(), "error message: INVALID_ARG");
 }
 
+TEST(VehicleUtilsTest, testPropIdToString) {
+    ASSERT_EQ(propIdToString(toInt(VehicleProperty::PERF_VEHICLE_SPEED)), "PERF_VEHICLE_SPEED");
+}
+
+TEST(VehicleUtilsTest, testStringToPropId) {
+    auto result = stringToPropId("PERF_VEHICLE_SPEED");
+
+    ASSERT_TRUE(result.ok());
+    ASSERT_EQ(result.value(), toInt(VehicleProperty::PERF_VEHICLE_SPEED));
+}
+
+TEST(VehicleUtilsTest, testStringToPropId_InvalidName) {
+    auto result = stringToPropId("PERF_VEHICLE_SPEED12345");
+
+    ASSERT_FALSE(result.ok());
+}
+
 class InvalidPropValueTest : public testing::TestWithParam<InvalidPropValueTestCase> {};
 
 INSTANTIATE_TEST_SUITE_P(InvalidPropValueTests, InvalidPropValueTest,
diff --git a/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h b/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h
index 250b30c..fa2a310 100644
--- a/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h
+++ b/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h
@@ -42,10 +42,11 @@
 namespace automotive {
 namespace vehicle {
 
-class DefaultVehicleHal final : public aidl::android::hardware::automotive::vehicle::BnVehicle {
+namespace aidlvhal = ::aidl::android::hardware::automotive::vehicle;
+
+class DefaultVehicleHal final : public aidlvhal::BnVehicle {
   public:
-    using CallbackType =
-            std::shared_ptr<aidl::android::hardware::automotive::vehicle::IVehicleCallback>;
+    using CallbackType = std::shared_ptr<aidlvhal::IVehicleCallback>;
 
     explicit DefaultVehicleHal(std::unique_ptr<IVehicleHardware> hardware);
 
@@ -54,26 +55,16 @@
 
     ~DefaultVehicleHal();
 
-    ndk::ScopedAStatus getAllPropConfigs(
-            aidl::android::hardware::automotive::vehicle::VehiclePropConfigs* returnConfigs)
-            override;
-    ndk::ScopedAStatus getValues(
-            const CallbackType& callback,
-            const aidl::android::hardware::automotive::vehicle::GetValueRequests& requests)
-            override;
-    ndk::ScopedAStatus setValues(
-            const CallbackType& callback,
-            const aidl::android::hardware::automotive::vehicle::SetValueRequests& requests)
-            override;
-    ndk::ScopedAStatus getPropConfigs(
-            const std::vector<int32_t>& props,
-            aidl::android::hardware::automotive::vehicle::VehiclePropConfigs* returnConfigs)
-            override;
-    ndk::ScopedAStatus subscribe(
-            const CallbackType& callback,
-            const std::vector<aidl::android::hardware::automotive::vehicle::SubscribeOptions>&
-                    options,
-            int32_t maxSharedMemoryFileCount) override;
+    ndk::ScopedAStatus getAllPropConfigs(aidlvhal::VehiclePropConfigs* returnConfigs) override;
+    ndk::ScopedAStatus getValues(const CallbackType& callback,
+                                 const aidlvhal::GetValueRequests& requests) override;
+    ndk::ScopedAStatus setValues(const CallbackType& callback,
+                                 const aidlvhal::SetValueRequests& requests) override;
+    ndk::ScopedAStatus getPropConfigs(const std::vector<int32_t>& props,
+                                      aidlvhal::VehiclePropConfigs* returnConfigs) override;
+    ndk::ScopedAStatus subscribe(const CallbackType& callback,
+                                 const std::vector<aidlvhal::SubscribeOptions>& options,
+                                 int32_t maxSharedMemoryFileCount) override;
     ndk::ScopedAStatus unsubscribe(const CallbackType& callback,
                                    const std::vector<int32_t>& propIds) override;
     ndk::ScopedAStatus returnSharedMemory(const CallbackType& callback,
@@ -86,12 +77,8 @@
     // friend class for unit testing.
     friend class DefaultVehicleHalTest;
 
-    using GetValuesClient =
-            GetSetValuesClient<aidl::android::hardware::automotive::vehicle::GetValueResult,
-                               aidl::android::hardware::automotive::vehicle::GetValueResults>;
-    using SetValuesClient =
-            GetSetValuesClient<aidl::android::hardware::automotive::vehicle::SetValueResult,
-                               aidl::android::hardware::automotive::vehicle::SetValueResults>;
+    using GetValuesClient = GetSetValuesClient<aidlvhal::GetValueResult, aidlvhal::GetValueResults>;
+    using SetValuesClient = GetSetValuesClient<aidlvhal::SetValueResult, aidlvhal::SetValueResults>;
 
     // A wrapper for binder lifecycle operations to enable stubbing for test.
     class BinderLifecycleInterface {
@@ -137,28 +124,27 @@
     bool mShouldRefreshPropertyConfigs;
     std::unique_ptr<IVehicleHardware> mVehicleHardware;
 
-    // mConfigsByPropId and mConfigFile are only modified during initialization, so no need to
-    // lock guard them.
-    std::unordered_map<int32_t, aidl::android::hardware::automotive::vehicle::VehiclePropConfig>
-            mConfigsByPropId;
-    // Only modified in constructor, so thread-safe.
-    std::unique_ptr<ndk::ScopedFileDescriptor> mConfigFile;
     // PendingRequestPool is thread-safe.
     std::shared_ptr<PendingRequestPool> mPendingRequestPool;
     // SubscriptionManager is thread-safe.
     std::shared_ptr<SubscriptionManager> mSubscriptionManager;
     // ConcurrentQueue is thread-safe.
-    std::shared_ptr<ConcurrentQueue<aidl::android::hardware::automotive::vehicle::VehiclePropValue>>
-            mBatchedEventQueue;
+    std::shared_ptr<ConcurrentQueue<aidlvhal::VehiclePropValue>> mBatchedEventQueue;
     // BatchingConsumer is thread-safe.
-    std::shared_ptr<
-            BatchingConsumer<aidl::android::hardware::automotive::vehicle::VehiclePropValue>>
+    std::shared_ptr<BatchingConsumer<aidlvhal::VehiclePropValue>>
             mPropertyChangeEventsBatchingConsumer;
     // Only set once during initialization.
     std::chrono::nanoseconds mEventBatchingWindow;
     // Only used for testing.
     int32_t mTestInterfaceVersion = 0;
 
+    // mConfigsByPropId and mConfigFile is lazy initialized.
+    mutable std::mutex mConfigInitLock;
+    mutable bool mConfigInit GUARDED_BY(mConfigInitLock) = false;
+    mutable std::unordered_map<int32_t, aidlvhal::VehiclePropConfig> mConfigsByPropId
+            GUARDED_BY(mConfigInitLock);
+    mutable std::unique_ptr<ndk::ScopedFileDescriptor> mConfigFile GUARDED_BY(mConfigInitLock);
+
     std::mutex mLock;
     std::unordered_map<const AIBinder*, std::unique_ptr<OnBinderDiedContext>> mOnBinderDiedContexts
             GUARDED_BY(mLock);
@@ -182,32 +168,23 @@
     // A thread to handle onBinderDied or onBinderUnlinked event.
     std::thread mOnBinderDiedUnlinkedHandlerThread;
 
-    android::base::Result<void> checkProperty(
-            const aidl::android::hardware::automotive::vehicle::VehiclePropValue& propValue);
+    android::base::Result<void> checkProperty(const aidlvhal::VehiclePropValue& propValue);
 
     android::base::Result<std::vector<int64_t>> checkDuplicateRequests(
-            const std::vector<aidl::android::hardware::automotive::vehicle::GetValueRequest>&
-                    requests);
+            const std::vector<aidlvhal::GetValueRequest>& requests);
 
     android::base::Result<std::vector<int64_t>> checkDuplicateRequests(
-            const std::vector<aidl::android::hardware::automotive::vehicle::SetValueRequest>&
-                    requests);
-    VhalResult<void> checkSubscribeOptions(
-            const std::vector<aidl::android::hardware::automotive::vehicle::SubscribeOptions>&
-                    options);
+            const std::vector<aidlvhal::SetValueRequest>& requests);
+    VhalResult<void> checkSubscribeOptions(const std::vector<aidlvhal::SubscribeOptions>& options);
 
-    VhalResult<void> checkPermissionHelper(
-            const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value,
-            aidl::android::hardware::automotive::vehicle::VehiclePropertyAccess accessToTest) const;
+    VhalResult<void> checkPermissionHelper(const aidlvhal::VehiclePropValue& value,
+                                           aidlvhal::VehiclePropertyAccess accessToTest) const;
 
-    VhalResult<void> checkReadPermission(
-            const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value) const;
+    VhalResult<void> checkReadPermission(const aidlvhal::VehiclePropValue& value) const;
 
-    VhalResult<void> checkWritePermission(
-            const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value) const;
+    VhalResult<void> checkWritePermission(const aidlvhal::VehiclePropValue& value) const;
 
-    android::base::Result<const aidl::android::hardware::automotive::vehicle::VehiclePropConfig*>
-    getConfig(int32_t propId) const;
+    android::base::Result<const aidlvhal::VehiclePropConfig*> getConfig(int32_t propId) const;
 
     void onBinderDiedWithContext(const AIBinder* clientId);
 
@@ -219,7 +196,7 @@
 
     bool checkDumpPermission();
 
-    bool getAllPropConfigsFromHardware();
+    bool getAllPropConfigsFromHardwareLocked() const REQUIRES(mConfigInitLock);
 
     // The looping handler function to process all onBinderDied or onBinderUnlinked events in
     // mBinderEvents.
@@ -228,19 +205,19 @@
     size_t countSubscribeClients();
 
     // Handles the property change events in batch.
-    void handleBatchedPropertyEvents(
-            std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropValue>&&
-                    batchedEvents);
+    void handleBatchedPropertyEvents(std::vector<aidlvhal::VehiclePropValue>&& batchedEvents);
 
-    int32_t getVhalInterfaceVersion();
+    int32_t getVhalInterfaceVersion() const;
+
+    // Gets mConfigsByPropId, lazy init it if necessary.
+    const std::unordered_map<int32_t, aidlvhal::VehiclePropConfig>& getConfigsByPropId() const;
+    // Gets mConfigFile, lazy init it if necessary.
+    const ndk::ScopedFileDescriptor* getConfigFile() const;
 
     // Puts the property change events into a queue so that they can handled in batch.
     static void batchPropertyChangeEvent(
-            const std::weak_ptr<ConcurrentQueue<
-                    aidl::android::hardware::automotive::vehicle::VehiclePropValue>>&
-                    batchedEventQueue,
-            std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropValue>&&
-                    updatedValues);
+            const std::weak_ptr<ConcurrentQueue<aidlvhal::VehiclePropValue>>& batchedEventQueue,
+            std::vector<aidlvhal::VehiclePropValue>&& updatedValues);
 
     // Gets or creates a {@code T} object for the client to or from {@code clients}.
     template <class T>
@@ -248,10 +225,8 @@
             std::unordered_map<const AIBinder*, std::shared_ptr<T>>* clients,
             const CallbackType& callback, std::shared_ptr<PendingRequestPool> pendingRequestPool);
 
-    static void onPropertyChangeEvent(
-            const std::weak_ptr<SubscriptionManager>& subscriptionManager,
-            std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropValue>&&
-                    updatedValues);
+    static void onPropertyChangeEvent(const std::weak_ptr<SubscriptionManager>& subscriptionManager,
+                                      std::vector<aidlvhal::VehiclePropValue>&& updatedValues);
 
     static void onPropertySetErrorEvent(
             const std::weak_ptr<SubscriptionManager>& subscriptionManager,
diff --git a/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp b/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
index a29861f..9dc039d 100644
--- a/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
+++ b/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
@@ -24,6 +24,7 @@
 #include <VehicleUtils.h>
 #include <VersionForVehicleProperty.h>
 
+#include <android-base/logging.h>
 #include <android-base/result.h>
 #include <android-base/stringprintf.h>
 #include <android/binder_ibinder.h>
@@ -71,6 +72,7 @@
 
 using ::ndk::ScopedAIBinder_DeathRecipient;
 using ::ndk::ScopedAStatus;
+using ::ndk::ScopedFileDescriptor;
 
 std::string toString(const std::unordered_set<int64_t>& values) {
     std::string str = "";
@@ -103,10 +105,7 @@
     : mVehicleHardware(std::move(vehicleHardware)),
       mPendingRequestPool(std::make_shared<PendingRequestPool>(TIMEOUT_IN_NANO)),
       mTestInterfaceVersion(testInterfaceVersion) {
-    if (!getAllPropConfigsFromHardware()) {
-        return;
-    }
-
+    ALOGD("DefaultVehicleHal init");
     IVehicleHardware* vehicleHardwarePtr = mVehicleHardware.get();
     mSubscriptionManager = std::make_shared<SubscriptionManager>(vehicleHardwarePtr);
     mEventBatchingWindow = mVehicleHardware->getPropertyOnChangeEventBatchingWindow();
@@ -319,16 +318,18 @@
     mPendingRequestPool = std::make_unique<PendingRequestPool>(timeoutInNano);
 }
 
-int32_t DefaultVehicleHal::getVhalInterfaceVersion() {
+int32_t DefaultVehicleHal::getVhalInterfaceVersion() const {
     if (mTestInterfaceVersion != 0) {
         return mTestInterfaceVersion;
     }
     int32_t myVersion = 0;
-    getInterfaceVersion(&myVersion);
+    // getInterfaceVersion is in-reality a const method.
+    const_cast<DefaultVehicleHal*>(this)->getInterfaceVersion(&myVersion);
     return myVersion;
 }
 
-bool DefaultVehicleHal::getAllPropConfigsFromHardware() {
+bool DefaultVehicleHal::getAllPropConfigsFromHardwareLocked() const {
+    ALOGD("Get all property configs from hardware");
     auto configs = mVehicleHardware->getAllPropertyConfigs();
     std::vector<VehiclePropConfig> filteredConfigs;
     int32_t myVersion = getVhalInterfaceVersion();
@@ -373,22 +374,46 @@
     return true;
 }
 
+const ScopedFileDescriptor* DefaultVehicleHal::getConfigFile() const {
+    std::scoped_lock lockGuard(mConfigInitLock);
+    if (!mConfigInit) {
+        CHECK(getAllPropConfigsFromHardwareLocked())
+                << "Failed to get property configs from hardware";
+        mConfigInit = true;
+    }
+    return mConfigFile.get();
+}
+
+const std::unordered_map<int32_t, VehiclePropConfig>& DefaultVehicleHal::getConfigsByPropId()
+        const {
+    std::scoped_lock lockGuard(mConfigInitLock);
+    if (!mConfigInit) {
+        CHECK(getAllPropConfigsFromHardwareLocked())
+                << "Failed to get property configs from hardware";
+        mConfigInit = true;
+    }
+    return mConfigsByPropId;
+}
+
 ScopedAStatus DefaultVehicleHal::getAllPropConfigs(VehiclePropConfigs* output) {
-    if (mConfigFile != nullptr) {
+    const ScopedFileDescriptor* configFile = getConfigFile();
+    const auto& configsByPropId = getConfigsByPropId();
+    if (configFile != nullptr) {
         output->payloads.clear();
-        output->sharedMemoryFd.set(dup(mConfigFile->get()));
+        output->sharedMemoryFd.set(dup(configFile->get()));
         return ScopedAStatus::ok();
     }
-    output->payloads.reserve(mConfigsByPropId.size());
-    for (const auto& [_, config] : mConfigsByPropId) {
+    output->payloads.reserve(configsByPropId.size());
+    for (const auto& [_, config] : configsByPropId) {
         output->payloads.push_back(config);
     }
     return ScopedAStatus::ok();
 }
 
 Result<const VehiclePropConfig*> DefaultVehicleHal::getConfig(int32_t propId) const {
-    auto it = mConfigsByPropId.find(propId);
-    if (it == mConfigsByPropId.end()) {
+    const auto& configsByPropId = getConfigsByPropId();
+    auto it = configsByPropId.find(propId);
+    if (it == configsByPropId.end()) {
         return Error() << "no config for property, ID: " << propId;
     }
     return &(it->second);
@@ -634,9 +659,11 @@
 ScopedAStatus DefaultVehicleHal::getPropConfigs(const std::vector<int32_t>& props,
                                                 VehiclePropConfigs* output) {
     std::vector<VehiclePropConfig> configs;
+    const auto& configsByPropId = getConfigsByPropId();
     for (int32_t prop : props) {
-        if (mConfigsByPropId.find(prop) != mConfigsByPropId.end()) {
-            configs.push_back(mConfigsByPropId[prop]);
+        auto it = configsByPropId.find(prop);
+        if (it != configsByPropId.end()) {
+            configs.push_back(it->second);
         } else {
             return ScopedAStatus::fromServiceSpecificErrorWithMessage(
                     toInt(StatusCode::INVALID_ARG),
@@ -665,13 +692,15 @@
 
 VhalResult<void> DefaultVehicleHal::checkSubscribeOptions(
         const std::vector<SubscribeOptions>& options) {
+    const auto& configsByPropId = getConfigsByPropId();
     for (const auto& option : options) {
         int32_t propId = option.propId;
-        if (mConfigsByPropId.find(propId) == mConfigsByPropId.end()) {
+        auto it = configsByPropId.find(propId);
+        if (it == configsByPropId.end()) {
             return StatusError(StatusCode::INVALID_ARG)
                    << StringPrintf("no config for property, ID: %" PRId32, propId);
         }
-        const VehiclePropConfig& config = mConfigsByPropId[propId];
+        const VehiclePropConfig& config = it->second;
         std::vector<VehicleAreaConfig> areaConfigs;
         if (option.areaIds.empty()) {
             areaConfigs = config.areaConfigs;
@@ -744,10 +773,11 @@
     }
     std::vector<SubscribeOptions> onChangeSubscriptions;
     std::vector<SubscribeOptions> continuousSubscriptions;
+    const auto& configsByPropId = getConfigsByPropId();
     for (const auto& option : options) {
         int32_t propId = option.propId;
         // We have already validate config exists.
-        const VehiclePropConfig& config = mConfigsByPropId[propId];
+        const VehiclePropConfig& config = configsByPropId.at(propId);
 
         SubscribeOptions optionCopy = option;
         // If areaIds is empty, subscribe to all areas.
@@ -871,7 +901,7 @@
         (areaConfig == nullptr || !hasRequiredAccess(areaConfig->access, accessToTest))) {
         return StatusError(StatusCode::ACCESS_DENIED)
                << StringPrintf("Property %" PRId32 " does not have the following access: %" PRId32,
-                               propId, accessToTest);
+                               propId, static_cast<int32_t>(accessToTest));
     }
     return {};
 }
@@ -936,17 +966,19 @@
     }
     DumpResult result = mVehicleHardware->dump(options);
     if (result.refreshPropertyConfigs) {
-        getAllPropConfigsFromHardware();
+        std::scoped_lock lockGuard(mConfigInitLock);
+        getAllPropConfigsFromHardwareLocked();
     }
     dprintf(fd, "%s", (result.buffer + "\n").c_str());
     if (!result.callerShouldDumpState) {
         return STATUS_OK;
     }
     dprintf(fd, "Vehicle HAL State: \n");
+    const auto& configsByPropId = getConfigsByPropId();
     {
         std::scoped_lock<std::mutex> lockGuard(mLock);
         dprintf(fd, "Interface version: %" PRId32 "\n", getVhalInterfaceVersion());
-        dprintf(fd, "Containing %zu property configs\n", mConfigsByPropId.size());
+        dprintf(fd, "Containing %zu property configs\n", configsByPropId.size());
         dprintf(fd, "Currently have %zu getValues clients\n", mGetValuesClients.size());
         dprintf(fd, "Currently have %zu setValues clients\n", mSetValuesClients.size());
         dprintf(fd, "Currently have %zu subscribe clients\n", countSubscribeClients());
diff --git a/automotive/vehicle/aidl/impl/vhal/src/SubscriptionManager.cpp b/automotive/vehicle/aidl/impl/vhal/src/SubscriptionManager.cpp
index f1106ee..14ee707 100644
--- a/automotive/vehicle/aidl/impl/vhal/src/SubscriptionManager.cpp
+++ b/automotive/vehicle/aidl/impl/vhal/src/SubscriptionManager.cpp
@@ -40,6 +40,7 @@
 using ::android::base::StringPrintf;
 using ::ndk::ScopedAStatus;
 
+constexpr float EPSILON = 0.0000001;
 constexpr float ONE_SECOND_IN_NANOS = 1'000'000'000.;
 
 SubscribeOptions newSubscribeOptions(int32_t propId, int32_t areaId, float sampleRateHz,
@@ -88,7 +89,7 @@
     }
 
     float log = std::log10(resolution);
-    return log == (int)log;
+    return std::abs(log - std::round(log)) < EPSILON;
 }
 
 void ContSubConfigs::refreshCombinedConfig() {
@@ -433,6 +434,9 @@
         }
 
         for (const auto& [client, callback] : mClientsByPropIdAreaId[propIdAreaId]) {
+            // if propId is on-change, propIdAreaId will not exist in mContSubConfigsByPropIdArea,
+            // returning an empty ContSubConfigs value for subConfigs i.e. with resolution = 0 and
+            // enableVur = false.
             auto& subConfigs = mContSubConfigsByPropIdArea[propIdAreaId];
             // Clients must be sent different VehiclePropValues with different levels of granularity
             // as requested by the client using resolution.
diff --git a/automotive/vehicle/aidl/impl/vhal/test/SubscriptionManagerTest.cpp b/automotive/vehicle/aidl/impl/vhal/test/SubscriptionManagerTest.cpp
index f377202..440a9f9 100644
--- a/automotive/vehicle/aidl/impl/vhal/test/SubscriptionManagerTest.cpp
+++ b/automotive/vehicle/aidl/impl/vhal/test/SubscriptionManagerTest.cpp
@@ -521,6 +521,8 @@
 }
 
 TEST_F(SubscriptionManagerTest, testCheckResolutionValid) {
+    ASSERT_TRUE(SubscriptionManager::checkResolution(0.0));
+    ASSERT_TRUE(SubscriptionManager::checkResolution(0.1));
     ASSERT_TRUE(SubscriptionManager::checkResolution(1.0));
 }
 
diff --git a/biometrics/fingerprint/aidl/default/FakeFingerprintEngine.cpp b/biometrics/fingerprint/aidl/default/FakeFingerprintEngine.cpp
index 8b8d046..67eb837 100644
--- a/biometrics/fingerprint/aidl/default/FakeFingerprintEngine.cpp
+++ b/biometrics/fingerprint/aidl/default/FakeFingerprintEngine.cpp
@@ -544,6 +544,10 @@
 
 void FakeFingerprintEngine::waitForFingerDown(ISessionCallback* cb,
                                               const std::future<void>& cancel) {
+    if (mFingerIsDown) {
+        LOG(WARNING) << "waitForFingerDown: mFingerIsDown==true already!";
+    }
+
     while (!mFingerIsDown) {
         if (shouldCancel(cancel)) {
             LOG(ERROR) << "waitForFingerDown, Fail: cancel";
diff --git a/bluetooth/aidl/default/net_bluetooth_mgmt.cpp b/bluetooth/aidl/default/net_bluetooth_mgmt.cpp
index 0699781..24693ef 100644
--- a/bluetooth/aidl/default/net_bluetooth_mgmt.cpp
+++ b/bluetooth/aidl/default/net_bluetooth_mgmt.cpp
@@ -161,6 +161,16 @@
       struct mgmt_ev_read_index_list* data =
           (struct mgmt_ev_read_index_list*)ev.data;
 
+      // Prefer the exact hci_interface
+      for (int i = 0; i < data->num_controllers; i++) {
+        if (data->index[i] == hci_interface) {
+          ALOGI("hci interface %d found", data->index[i]);
+          ret = data->index[i];
+          goto end;
+        }
+      }
+
+      // Accept a larger one if we can't find the exact one
       for (int i = 0; i < data->num_controllers; i++) {
         if (data->index[i] >= hci_interface) {
           ALOGI("hci interface %d found", data->index[i]);
@@ -173,7 +183,7 @@
     // Received [Index Added] event.
     if (ev.opcode == MGMT_EV_INDEX_ADDED && ev.index == hci_interface) {
       ALOGI("hci interface %d added", hci_interface);
-      ret = 0;
+      ret = hci_interface;
       goto end;
     }
   }
@@ -253,9 +263,9 @@
   rfkill(1);
 
   // Wait for the HCI interface to complete initialization or to come online.
-  hci_interface = waitHciDev(hci_interface);
-  if (hci_interface < 0) {
-    ALOGE("hci interface not found");
+  int hci = waitHciDev(hci_interface);
+  if (hci < 0) {
+    ALOGE("hci interface %d not found", hci_interface);
     return -1;
   }
 
@@ -268,7 +278,7 @@
 
   struct sockaddr_hci hci_addr = {
       .hci_family = AF_BLUETOOTH,
-      .hci_dev = static_cast<uint16_t>(hci_interface),
+      .hci_dev = static_cast<uint16_t>(hci),
       .hci_channel = HCI_CHANNEL_USER,
   };
 
@@ -279,7 +289,7 @@
     return -1;
   }
 
-  ALOGI("hci interface %d ready", hci_interface);
+  ALOGI("hci interface %d ready", hci);
   bt_fd_ = fd;
   return fd;
 }
diff --git a/bluetooth/audio/aidl/Android.bp b/bluetooth/audio/aidl/Android.bp
index f8818fd..f273c7a 100644
--- a/bluetooth/audio/aidl/Android.bp
+++ b/bluetooth/audio/aidl/Android.bp
@@ -105,3 +105,25 @@
         latest_android_hardware_bluetooth_audio + "-ndk",
     ],
 }
+
+cc_defaults {
+    name: "latest_android_hardware_bluetooth_audio_ndk_android_shared",
+    target: {
+        android: {
+            shared_libs: [
+                latest_android_hardware_bluetooth_audio + "-ndk",
+            ],
+        },
+    },
+}
+
+cc_defaults {
+    name: "latest_android_hardware_bluetooth_audio_ndk_android_static",
+    target: {
+        android: {
+            static_libs: [
+                latest_android_hardware_bluetooth_audio + "-ndk",
+            ],
+        },
+    },
+}
diff --git a/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.cpp b/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.cpp
index dc36ac0..2a2cab0 100644
--- a/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.cpp
+++ b/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.cpp
@@ -184,12 +184,13 @@
           SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
     std::vector<CodecInfo> db_codec_info =
         BluetoothAudioCodecs::GetLeAudioOffloadCodecInfo(session_type);
-    if (!db_codec_info.empty()) {
-      auto& provider_info = _aidl_return->emplace();
-      provider_info.name = kLeAudioOffloadProviderName;
-      provider_info.codecInfos = db_codec_info;
-      return ndk::ScopedAStatus::ok();
-    }
+    // Return provider info supports without checking db_codec_info
+    // This help with various flow implementation for multidirectional support.
+    auto& provider_info = _aidl_return->emplace();
+    provider_info.supportsMultidirectionalCapabilities = true;
+    provider_info.name = kLeAudioOffloadProviderName;
+    provider_info.codecInfos = db_codec_info;
+    return ndk::ScopedAStatus::ok();
   }
 
   if (session_type == SessionType::HFP_HARDWARE_OFFLOAD_DATAPATH) {
diff --git a/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.cpp b/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.cpp
index a692d84..6783c0f 100644
--- a/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.cpp
+++ b/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.cpp
@@ -30,6 +30,8 @@
 
 constexpr uint8_t kLeAudioDirectionSink = 0x01;
 constexpr uint8_t kLeAudioDirectionSource = 0x02;
+constexpr uint8_t kIsoDataPathHci = 0x00;
+constexpr uint8_t kIsoDataPathPlatformDefault = 0x01;
 
 const std::map<CodecSpecificConfigurationLtv::SamplingFrequency, uint32_t>
     freq_to_support_bitmask_map = {
@@ -85,6 +87,7 @@
 std::map<int32_t, CodecSpecificConfigurationLtv::SamplingFrequency>
     sampling_freq_map = {
         {16000, CodecSpecificConfigurationLtv::SamplingFrequency::HZ16000},
+        {24000, CodecSpecificConfigurationLtv::SamplingFrequency::HZ24000},
         {48000, CodecSpecificConfigurationLtv::SamplingFrequency::HZ48000},
         {96000, CodecSpecificConfigurationLtv::SamplingFrequency::HZ96000},
 };
@@ -165,8 +168,8 @@
   return cfg_codec == req_codec;
 }
 
-bool LeAudioOffloadAudioProvider::isCapabilitiesMatchedContext(
-    AudioContext setting_context,
+bool LeAudioOffloadAudioProvider::filterCapabilitiesMatchedContext(
+    AudioContext& setting_context,
     const IBluetoothAudioProvider::LeAudioDeviceCapabilities& capabilities) {
   // If has no metadata, assume match
   if (!capabilities.metadata.has_value()) return true;
@@ -175,10 +178,15 @@
     if (!metadata.has_value()) continue;
     if (metadata.value().getTag() == MetadataLtv::Tag::preferredAudioContexts) {
       // Check all pref audio context to see if anything matched
-      auto& context = metadata.value()
-                          .get<MetadataLtv::Tag::preferredAudioContexts>()
-                          .values;
-      if (setting_context.bitmask & context.bitmask) return true;
+      auto& prefer_context =
+          metadata.value()
+              .get<MetadataLtv::Tag::preferredAudioContexts>()
+              .values;
+      if (setting_context.bitmask & prefer_context.bitmask) {
+        // New mask with matched capability
+        setting_context.bitmask &= prefer_context.bitmask;
+        return true;
+      }
     }
   }
 
@@ -189,8 +197,12 @@
     CodecSpecificConfigurationLtv::SamplingFrequency& cfg_freq,
     CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies&
         capability_freq) {
-  for (auto [freq, bitmask] : freq_to_support_bitmask_map)
-    if (cfg_freq == freq) return (capability_freq.bitmask & bitmask);
+  auto p = freq_to_support_bitmask_map.find(cfg_freq);
+  if (p != freq_to_support_bitmask_map.end()) {
+    if (capability_freq.bitmask & p->second) {
+      return true;
+    }
+  }
   return false;
 }
 
@@ -198,9 +210,11 @@
     CodecSpecificConfigurationLtv::FrameDuration& cfg_fduration,
     CodecSpecificCapabilitiesLtv::SupportedFrameDurations&
         capability_fduration) {
-  for (auto [fduration, bitmask] : fduration_to_support_fduration_map)
-    if (cfg_fduration == fduration)
-      return (capability_fduration.bitmask & bitmask);
+  auto p = fduration_to_support_fduration_map.find(cfg_fduration);
+  if (p != fduration_to_support_fduration_map.end())
+    if (capability_fduration.bitmask & p->second) {
+      return true;
+    }
   return false;
 }
 
@@ -209,8 +223,9 @@
     /*cfg_channel*/,
     CodecSpecificCapabilitiesLtv::SupportedAudioChannelCounts&
     /*capability_channel*/) {
+  // Simply ignore.
+  // Later can use additional capabilities to match requirement.
   bool isMatched = true;
-  // TODO: how to match?
   return isMatched;
 }
 
@@ -240,69 +255,103 @@
 
   for (auto& codec_capability : codec_capabilities) {
     auto cfg = cfg_tag_map.find(cap_to_cfg_tag_map[codec_capability.getTag()]);
-    // Cannot find tag for the capability:
-    if (cfg == cfg_tag_map.end()) return false;
+    // If capability has this tag, but our configuration doesn't
+    // Then we will assume it is matched
+    if (cfg == cfg_tag_map.end()) {
+      continue;
+    }
 
-    // Matching logic for sampling frequency
-    if (codec_capability.getTag() ==
-        CodecSpecificCapabilitiesLtv::Tag::supportedSamplingFrequencies) {
-      if (!isMatchedSamplingFreq(
-              cfg->second
-                  .get<CodecSpecificConfigurationLtv::Tag::samplingFrequency>(),
-              codec_capability.get<CodecSpecificCapabilitiesLtv::Tag::
-                                       supportedSamplingFrequencies>()))
-        return false;
-    } else if (codec_capability.getTag() ==
-               CodecSpecificCapabilitiesLtv::Tag::supportedFrameDurations) {
-      if (!isMatchedFrameDuration(
-              cfg->second
-                  .get<CodecSpecificConfigurationLtv::Tag::frameDuration>(),
-              codec_capability.get<CodecSpecificCapabilitiesLtv::Tag::
-                                       supportedFrameDurations>()))
-        return false;
-    } else if (codec_capability.getTag() ==
-               CodecSpecificCapabilitiesLtv::Tag::supportedAudioChannelCounts) {
-      if (!isMatchedAudioChannel(
-              cfg->second.get<
-                  CodecSpecificConfigurationLtv::Tag::audioChannelAllocation>(),
-              codec_capability.get<CodecSpecificCapabilitiesLtv::Tag::
-                                       supportedAudioChannelCounts>()))
-        return false;
-    } else if (codec_capability.getTag() == CodecSpecificCapabilitiesLtv::Tag::
-                                                supportedMaxCodecFramesPerSDU) {
-      if (!isMatchedCodecFramesPerSDU(
-              cfg->second.get<
-                  CodecSpecificConfigurationLtv::Tag::codecFrameBlocksPerSDU>(),
-              codec_capability.get<CodecSpecificCapabilitiesLtv::Tag::
-                                       supportedMaxCodecFramesPerSDU>()))
-        return false;
-    } else if (codec_capability.getTag() == CodecSpecificCapabilitiesLtv::Tag::
-                                                supportedOctetsPerCodecFrame) {
-      if (!isMatchedOctetsPerCodecFrame(
-              cfg->second.get<
-                  CodecSpecificConfigurationLtv::Tag::octetsPerCodecFrame>(),
-              codec_capability.get<CodecSpecificCapabilitiesLtv::Tag::
-                                       supportedOctetsPerCodecFrame>()))
-        return false;
+    switch (codec_capability.getTag()) {
+      case CodecSpecificCapabilitiesLtv::Tag::supportedSamplingFrequencies: {
+        if (!isMatchedSamplingFreq(
+                cfg->second.get<
+                    CodecSpecificConfigurationLtv::Tag::samplingFrequency>(),
+                codec_capability.get<CodecSpecificCapabilitiesLtv::Tag::
+                                         supportedSamplingFrequencies>())) {
+          return false;
+        }
+        break;
+      }
+
+      case CodecSpecificCapabilitiesLtv::Tag::supportedFrameDurations: {
+        if (!isMatchedFrameDuration(
+                cfg->second
+                    .get<CodecSpecificConfigurationLtv::Tag::frameDuration>(),
+                codec_capability.get<CodecSpecificCapabilitiesLtv::Tag::
+                                         supportedFrameDurations>())) {
+          return false;
+        }
+        break;
+      }
+
+      case CodecSpecificCapabilitiesLtv::Tag::supportedAudioChannelCounts: {
+        if (!isMatchedAudioChannel(
+                cfg->second.get<CodecSpecificConfigurationLtv::Tag::
+                                    audioChannelAllocation>(),
+                codec_capability.get<CodecSpecificCapabilitiesLtv::Tag::
+                                         supportedAudioChannelCounts>())) {
+          return false;
+        }
+        break;
+      }
+
+      case CodecSpecificCapabilitiesLtv::Tag::supportedMaxCodecFramesPerSDU: {
+        if (!isMatchedCodecFramesPerSDU(
+                cfg->second.get<CodecSpecificConfigurationLtv::Tag::
+                                    codecFrameBlocksPerSDU>(),
+                codec_capability.get<CodecSpecificCapabilitiesLtv::Tag::
+                                         supportedMaxCodecFramesPerSDU>())) {
+          return false;
+        }
+        break;
+      }
+
+      case CodecSpecificCapabilitiesLtv::Tag::supportedOctetsPerCodecFrame: {
+        if (!isMatchedOctetsPerCodecFrame(
+                cfg->second.get<
+                    CodecSpecificConfigurationLtv::Tag::octetsPerCodecFrame>(),
+                codec_capability.get<CodecSpecificCapabilitiesLtv::Tag::
+                                         supportedOctetsPerCodecFrame>())) {
+          return false;
+        }
+        break;
+      }
     }
   }
 
   return true;
 }
 
-bool LeAudioOffloadAudioProvider::isMatchedAseConfiguration(
-    LeAudioAseConfiguration setting_cfg,
-    LeAudioAseConfiguration requirement_cfg) {
+bool isMonoConfig(
+    CodecSpecificConfigurationLtv::AudioChannelAllocation allocation) {
+  auto channel_count = std::bitset<32>(allocation.bitmask);
+  return (channel_count.count() <= 1);
+}
+
+bool LeAudioOffloadAudioProvider::filterMatchedAseConfiguration(
+    LeAudioAseConfiguration& setting_cfg,
+    const LeAudioAseConfiguration& requirement_cfg) {
   // Check matching for codec configuration <=> requirement ASE codec
   // Also match if no CodecId requirement
   if (requirement_cfg.codecId.has_value()) {
     if (!setting_cfg.codecId.has_value()) return false;
     if (!isMatchedValidCodec(setting_cfg.codecId.value(),
-                             requirement_cfg.codecId.value()))
+                             requirement_cfg.codecId.value())) {
+      LOG(WARNING) << __func__ << ": Doesn't match valid codec, cfg = "
+                   << setting_cfg.codecId.value().toString()
+                   << ", req = " << requirement_cfg.codecId.value().toString();
       return false;
+    }
   }
 
-  if (setting_cfg.targetLatency != requirement_cfg.targetLatency) return false;
+  if (requirement_cfg.targetLatency !=
+          LeAudioAseConfiguration::TargetLatency::UNDEFINED &&
+      setting_cfg.targetLatency != requirement_cfg.targetLatency) {
+    LOG(WARNING) << __func__ << ": Doesn't match target latency, cfg = "
+                 << int(setting_cfg.targetLatency)
+                 << ", req = " << int(requirement_cfg.targetLatency);
+    return false;
+  }
   // Ignore PHY requirement
 
   // Check all codec configuration
@@ -314,9 +363,26 @@
   for (auto requirement_cfg : requirement_cfg.codecConfiguration) {
     // Directly compare CodecSpecificConfigurationLtv
     auto cfg = cfg_tag_map.find(requirement_cfg.getTag());
-    if (cfg == cfg_tag_map.end()) return false;
+    // Config not found for this requirement, cannot match
+    if (cfg == cfg_tag_map.end()) {
+      LOG(WARNING) << __func__ << ": Config not found for the requirement "
+                   << requirement_cfg.toString();
+      return false;
+    }
 
-    if (cfg->second != requirement_cfg) return false;
+    // Ignore matching for audio channel allocation
+    // since the rule is complicated. Match outside instead
+    if (requirement_cfg.getTag() ==
+        CodecSpecificConfigurationLtv::Tag::audioChannelAllocation)
+      continue;
+
+    if (cfg->second != requirement_cfg) {
+      LOG(WARNING) << __func__
+                   << ": Config doesn't match the requirement, cfg = "
+                   << cfg->second.toString()
+                   << ", req = " << requirement_cfg.toString();
+      return false;
+    }
   }
   // Ignore vendor configuration and metadata requirement
 
@@ -326,10 +392,13 @@
 bool LeAudioOffloadAudioProvider::isMatchedBISConfiguration(
     LeAudioBisConfiguration bis_cfg,
     const IBluetoothAudioProvider::LeAudioDeviceCapabilities& capabilities) {
-  if (!isMatchedValidCodec(bis_cfg.codecId, capabilities.codecId)) return false;
-  if (!isCapabilitiesMatchedCodecConfiguration(
-          bis_cfg.codecConfiguration, capabilities.codecSpecificCapabilities))
+  if (!isMatchedValidCodec(bis_cfg.codecId, capabilities.codecId)) {
     return false;
+  }
+  if (!isCapabilitiesMatchedCodecConfiguration(
+          bis_cfg.codecConfiguration, capabilities.codecSpecificCapabilities)) {
+    return false;
+  }
   return true;
 }
 
@@ -356,30 +425,132 @@
   }
 }
 
-void LeAudioOffloadAudioProvider::filterRequirementAseDirectionConfiguration(
-    std::vector<std::optional<AseDirectionConfiguration>>&
-        direction_configurations,
-    const std::optional<std::vector<std::optional<AseDirectionRequirement>>>&
-        requirements,
-    std::vector<std::optional<AseDirectionConfiguration>>&
-        valid_direction_configurations) {
-  for (auto direction_configuration : direction_configurations) {
-    if (!requirements.has_value()) {
-      // If there's no requirement, all are valid
-      valid_direction_configurations.push_back(direction_configuration);
-      continue;
+int getLeAudioAseConfigurationAllocationBitmask(LeAudioAseConfiguration cfg) {
+  for (auto cfg_ltv : cfg.codecConfiguration) {
+    if (cfg_ltv.getTag() ==
+        CodecSpecificConfigurationLtv::Tag::audioChannelAllocation) {
+      return cfg_ltv
+          .get<CodecSpecificConfigurationLtv::Tag::audioChannelAllocation>()
+          .bitmask;
     }
-    if (!direction_configuration.has_value()) continue;
+  }
+  return 0;
+}
 
-    for (auto& requirement : requirements.value()) {
-      if (!requirement.has_value()) continue;
-      if (!isMatchedAseConfiguration(
+int getCountFromBitmask(int bitmask) {
+  return std::bitset<32>(bitmask).count();
+}
+
+std::optional<AseDirectionConfiguration> findValidMonoConfig(
+    std::vector<AseDirectionConfiguration>& valid_direction_configurations,
+    int bitmask) {
+  for (auto& cfg : valid_direction_configurations) {
+    int cfg_bitmask =
+        getLeAudioAseConfigurationAllocationBitmask(cfg.aseConfiguration);
+    if (getCountFromBitmask(cfg_bitmask) <= 1) {
+      // Modify the bitmask to be the same as the requirement
+      for (auto& codec_cfg : cfg.aseConfiguration.codecConfiguration) {
+        if (codec_cfg.getTag() ==
+            CodecSpecificConfigurationLtv::Tag::audioChannelAllocation) {
+          codec_cfg
+              .get<CodecSpecificConfigurationLtv::Tag::audioChannelAllocation>()
+              .bitmask = bitmask;
+          return cfg;
+        }
+      }
+    }
+  }
+  return std::nullopt;
+}
+
+std::vector<AseDirectionConfiguration> getValidConfigurationsFromAllocation(
+    int req_allocation_bitmask,
+    std::vector<AseDirectionConfiguration>& valid_direction_configurations,
+    bool is_exact) {
+  // Prefer the same allocation_bitmask
+  int channel_count = getCountFromBitmask(req_allocation_bitmask);
+
+  if (is_exact) {
+    for (auto& cfg : valid_direction_configurations) {
+      int cfg_bitmask =
+          getLeAudioAseConfigurationAllocationBitmask(cfg.aseConfiguration);
+      if (cfg_bitmask == req_allocation_bitmask) {
+        LOG(DEBUG)
+            << __func__
+            << ": Found an exact match for the requirement allocation of "
+            << cfg_bitmask;
+        return {cfg};
+      }
+    }
+    return {};
+  }
+  // Not using exact match strategy
+  if (channel_count <= 1) {
+    // Mono requirement matched if cfg is a mono config
+    auto cfg = findValidMonoConfig(valid_direction_configurations,
+                                   req_allocation_bitmask);
+    if (cfg.has_value()) return {cfg.value()};
+  } else {
+    // Stereo requirement returns 2 mono configs
+    // that has a combined bitmask equal to the stereo config
+    std::vector<AseDirectionConfiguration> temp;
+    for (int bit = 0; bit < 32; ++bit)
+      if (req_allocation_bitmask & (1 << bit)) {
+        auto cfg =
+            findValidMonoConfig(valid_direction_configurations, (1 << bit));
+        if (cfg.has_value()) temp.push_back(cfg.value());
+      }
+    if (temp.size() == channel_count) return temp;
+  }
+  return {};
+}
+
+void LeAudioOffloadAudioProvider::filterRequirementAseDirectionConfiguration(
+    std::optional<std::vector<std::optional<AseDirectionConfiguration>>>&
+        direction_configurations,
+    const std::vector<std::optional<AseDirectionRequirement>>& requirements,
+    std::optional<std::vector<std::optional<AseDirectionConfiguration>>>&
+        valid_direction_configurations,
+    bool is_exact) {
+  // For every requirement, find the matched ase configuration
+  if (!direction_configurations.has_value()) return;
+
+  if (!valid_direction_configurations.has_value()) {
+    valid_direction_configurations =
+        std::vector<std::optional<AseDirectionConfiguration>>();
+  }
+
+  for (auto& requirement : requirements) {
+    if (!requirement.has_value()) continue;
+    auto req_allocation_bitmask = getLeAudioAseConfigurationAllocationBitmask(
+        requirement.value().aseConfiguration);
+    auto req_channel_count = getCountFromBitmask(req_allocation_bitmask);
+
+    auto temp = std::vector<AseDirectionConfiguration>();
+
+    for (auto direction_configuration : direction_configurations.value()) {
+      if (!direction_configuration.has_value()) continue;
+      if (!filterMatchedAseConfiguration(
               direction_configuration.value().aseConfiguration,
               requirement.value().aseConfiguration))
         continue;
       // Valid if match any requirement.
-      valid_direction_configurations.push_back(direction_configuration);
-      break;
+      temp.push_back(direction_configuration.value());
+    }
+
+    // Get the best matching config based on channel allocation
+    auto total_cfg_channel_count = 0;
+    auto req_valid_configs = getValidConfigurationsFromAllocation(
+        req_allocation_bitmask, temp, is_exact);
+    // Count and check required channel counts
+    for (auto& cfg : req_valid_configs) {
+      total_cfg_channel_count += getCountFromBitmask(
+          getLeAudioAseConfigurationAllocationBitmask(cfg.aseConfiguration));
+      valid_direction_configurations.value().push_back(cfg);
+    }
+    if (total_cfg_channel_count != req_channel_count) {
+      valid_direction_configurations = std::nullopt;
+      return;
     }
   }
 }
@@ -392,37 +563,45 @@
     IBluetoothAudioProvider::LeAudioAseConfigurationSetting& setting,
     const IBluetoothAudioProvider::LeAudioDeviceCapabilities& capabilities,
     uint8_t direction) {
-  // Try to match context in metadata.
-  if (!isCapabilitiesMatchedContext(setting.audioContext, capabilities))
-    return std::nullopt;
+  // Create a new LeAudioAseConfigurationSetting and return
+  // For other direction will contain all settings
+  LeAudioAseConfigurationSetting filtered_setting{
+      .audioContext = setting.audioContext,
+      .sinkAseConfiguration = setting.sinkAseConfiguration,
+      .sourceAseConfiguration = setting.sourceAseConfiguration,
+      .flags = setting.flags,
+      .packing = setting.packing,
+  };
 
   // Get a list of all matched AseDirectionConfiguration
   // for the input direction
   std::vector<std::optional<AseDirectionConfiguration>>*
       direction_configuration = nullptr;
   if (direction == kLeAudioDirectionSink) {
-    if (!setting.sinkAseConfiguration.has_value()) return std::nullopt;
-    direction_configuration = &setting.sinkAseConfiguration.value();
+    if (!filtered_setting.sinkAseConfiguration.has_value()) return std::nullopt;
+    direction_configuration = &filtered_setting.sinkAseConfiguration.value();
   } else {
-    if (!setting.sourceAseConfiguration.has_value()) return std::nullopt;
-    direction_configuration = &setting.sourceAseConfiguration.value();
+    if (!filtered_setting.sourceAseConfiguration.has_value())
+      return std::nullopt;
+    direction_configuration = &filtered_setting.sourceAseConfiguration.value();
   }
   std::vector<std::optional<AseDirectionConfiguration>>
       valid_direction_configuration;
   filterCapabilitiesAseDirectionConfiguration(
       *direction_configuration, capabilities, valid_direction_configuration);
-  if (valid_direction_configuration.empty()) return std::nullopt;
+
+  // No valid configuration for this direction
+  if (valid_direction_configuration.empty()) {
+    return std::nullopt;
+  }
 
   // Create a new LeAudioAseConfigurationSetting and return
-  LeAudioAseConfigurationSetting filtered_setting;
-  filtered_setting.audioContext = setting.audioContext;
-  filtered_setting.packing = setting.packing;
+  // For other direction will contain all settings
   if (direction == kLeAudioDirectionSink) {
     filtered_setting.sinkAseConfiguration = valid_direction_configuration;
   } else {
     filtered_setting.sourceAseConfiguration = valid_direction_configuration;
   }
-  filtered_setting.flags = setting.flags;
 
   return filtered_setting;
 }
@@ -433,44 +612,87 @@
 std::optional<LeAudioAseConfigurationSetting>
 LeAudioOffloadAudioProvider::getRequirementMatchedAseConfigurationSettings(
     IBluetoothAudioProvider::LeAudioAseConfigurationSetting& setting,
-    const IBluetoothAudioProvider::LeAudioConfigurationRequirement&
-        requirement) {
+    const IBluetoothAudioProvider::LeAudioConfigurationRequirement& requirement,
+    bool is_exact) {
   // Try to match context in metadata.
-  if (setting.audioContext != requirement.audioContext) return std::nullopt;
+  if ((setting.audioContext.bitmask & requirement.audioContext.bitmask) !=
+      requirement.audioContext.bitmask)
+    return std::nullopt;
 
-  // Check requirement for the correct direction
-  const std::optional<std::vector<std::optional<AseDirectionRequirement>>>*
-      direction_requirement;
-  std::vector<std::optional<AseDirectionConfiguration>>*
-      direction_configuration;
-  if (setting.sinkAseConfiguration.has_value()) {
-    direction_configuration = &setting.sinkAseConfiguration.value();
-    direction_requirement = &requirement.sinkAseRequirement;
-  } else {
-    direction_configuration = &setting.sourceAseConfiguration.value();
-    direction_requirement = &requirement.sourceAseRequirement;
+  // Further filter setting's context
+  setting.audioContext.bitmask &= requirement.audioContext.bitmask;
+
+  // Create a new LeAudioAseConfigurationSetting to return
+  LeAudioAseConfigurationSetting filtered_setting{
+      .audioContext = setting.audioContext,
+      .packing = setting.packing,
+      .flags = setting.flags,
+  };
+
+  if (requirement.sinkAseRequirement.has_value()) {
+    filterRequirementAseDirectionConfiguration(
+        setting.sinkAseConfiguration, requirement.sinkAseRequirement.value(),
+        filtered_setting.sinkAseConfiguration, is_exact);
+    if (!filtered_setting.sinkAseConfiguration.has_value()) {
+      return std::nullopt;
+    }
   }
 
-  std::vector<std::optional<AseDirectionConfiguration>>
-      valid_direction_configuration;
-  filterRequirementAseDirectionConfiguration(*direction_configuration,
-                                             *direction_requirement,
-                                             valid_direction_configuration);
-  if (valid_direction_configuration.empty()) return std::nullopt;
-
-  // Create a new LeAudioAseConfigurationSetting and return
-  LeAudioAseConfigurationSetting filtered_setting;
-  filtered_setting.audioContext = setting.audioContext;
-  filtered_setting.packing = setting.packing;
-  if (setting.sinkAseConfiguration.has_value())
-    filtered_setting.sinkAseConfiguration = valid_direction_configuration;
-  else
-    filtered_setting.sourceAseConfiguration = valid_direction_configuration;
-  filtered_setting.flags = setting.flags;
+  if (requirement.sourceAseRequirement.has_value()) {
+    filterRequirementAseDirectionConfiguration(
+        setting.sourceAseConfiguration,
+        requirement.sourceAseRequirement.value(),
+        filtered_setting.sourceAseConfiguration, is_exact);
+    if (!filtered_setting.sourceAseConfiguration.has_value()) {
+      return std::nullopt;
+    }
+  }
 
   return filtered_setting;
 }
 
+std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting>
+LeAudioOffloadAudioProvider::matchWithRequirement(
+    std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting>&
+        matched_ase_configuration_settings,
+    const std::vector<IBluetoothAudioProvider::LeAudioConfigurationRequirement>&
+        in_requirements,
+    bool is_exact) {
+  // Each requirement will match with a valid setting
+  std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting> result;
+  for (auto& requirement : in_requirements) {
+    LOG(INFO) << __func__ << ": Trying to match for the requirement "
+              << requirement.toString();
+    bool is_matched = false;
+
+    for (auto& setting : matched_ase_configuration_settings) {
+      auto filtered_ase_configuration_setting =
+          getRequirementMatchedAseConfigurationSettings(setting, requirement,
+                                                        is_exact);
+      if (filtered_ase_configuration_setting.has_value()) {
+        result.push_back(filtered_ase_configuration_setting.value());
+        LOG(INFO) << __func__ << ": Result = "
+                  << filtered_ase_configuration_setting.value().toString();
+        // Found a matched setting, ignore other settings
+        is_matched = true;
+        break;
+      }
+    }
+    if (!is_matched) {
+      // If cannot satisfy this requirement, return an empty result
+      LOG(WARNING) << __func__ << ": Cannot match the requirement "
+                   << requirement.toString();
+      result.clear();
+      break;
+    }
+  }
+  return result;
+}
+
+// For each requirement, a valid ASE configuration will satify:
+// - matched with any sink capability (if presented)
+// - OR matched with any source capability (if presented)
+// - and the setting need to pass the requirement
 ndk::ScopedAStatus LeAudioOffloadAudioProvider::getLeAudioAseConfiguration(
     const std::optional<std::vector<
         std::optional<IBluetoothAudioProvider::LeAudioDeviceCapabilities>>>&
@@ -487,48 +709,106 @@
       ase_configuration_settings =
           BluetoothAudioCodecs::GetLeAudioAseConfigurationSettings();
 
-  // Currently won't handle case where both sink and source capabilities
-  // are passed in. Only handle one of them.
-  const std::optional<std::vector<
-      std::optional<IBluetoothAudioProvider::LeAudioDeviceCapabilities>>>*
-      in_remoteAudioCapabilities;
-  uint8_t direction = 0;
-  if (in_remoteSinkAudioCapabilities.has_value()) {
-    direction = kLeAudioDirectionSink;
-    in_remoteAudioCapabilities = &in_remoteSinkAudioCapabilities;
-  } else {
-    direction = kLeAudioDirectionSource;
-    in_remoteAudioCapabilities = &in_remoteSourceAudioCapabilities;
+  if (!in_remoteSinkAudioCapabilities.has_value() &&
+      !in_remoteSourceAudioCapabilities.has_value()) {
+    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
   }
 
+  // Split out preferred and non-preferred settings based on context
+  // An example: preferred = MEDIA, available: MEDIA | CONVERSATION
+  // -> preferred list will have settings with MEDIA context
+  // -> non-preferred list will have settings with any context
+  // We want to match requirement with preferred context settings first
   std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting>
-      capability_matched_ase_configuration_settings;
-  // Matching with remote capabilities
-  for (auto& setting : ase_configuration_settings) {
-    for (auto& capability : in_remoteAudioCapabilities->value()) {
-      if (!capability.has_value()) continue;
-      auto filtered_ase_configuration_setting =
-          getCapabilitiesMatchedAseConfigurationSettings(
-              setting, capability.value(), direction);
-      if (filtered_ase_configuration_setting.has_value()) {
-        capability_matched_ase_configuration_settings.push_back(
-            filtered_ase_configuration_setting.value());
-      }
-    }
-  }
+      matched_ase_configuration_settings;
+  // Matched ASE configuration with non-preferred audio context
+  std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting>
+      non_prefer_matched_ase_configuration_settings;
 
-  // Matching with requirements
-  std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting> result;
-  for (auto& setting : capability_matched_ase_configuration_settings) {
-    for (auto& requirement : in_requirements) {
-      auto filtered_ase_configuration_setting =
-          getRequirementMatchedAseConfigurationSettings(setting, requirement);
-      if (filtered_ase_configuration_setting.has_value()) {
-        result.push_back(filtered_ase_configuration_setting.value());
+  if (in_remoteSinkAudioCapabilities.has_value())
+    // Matching each setting with any remote capabilities
+    for (auto& setting : ase_configuration_settings)
+      for (auto& capability : in_remoteSinkAudioCapabilities.value()) {
+        if (!capability.has_value()) continue;
+        auto filtered_ase_configuration_setting =
+            getCapabilitiesMatchedAseConfigurationSettings(
+                setting, capability.value(), kLeAudioDirectionSink);
+        if (filtered_ase_configuration_setting.has_value()) {
+          // Push to non-prefer first for the broadest matching possible
+          non_prefer_matched_ase_configuration_settings.push_back(
+              filtered_ase_configuration_setting.value());
+          // Try to filter out prefer context to another vector.
+          if (filterCapabilitiesMatchedContext(
+                  filtered_ase_configuration_setting.value().audioContext,
+                  capability.value())) {
+            matched_ase_configuration_settings.push_back(
+                filtered_ase_configuration_setting.value());
+          }
+        }
       }
-    }
-  }
 
+  // Combine filter every source capability
+  if (in_remoteSourceAudioCapabilities.has_value())
+    // Matching each setting with any remote capabilities
+    for (auto& setting : ase_configuration_settings)
+      for (auto& capability : in_remoteSourceAudioCapabilities.value()) {
+        if (!capability.has_value()) continue;
+        auto filtered_ase_configuration_setting =
+            getCapabilitiesMatchedAseConfigurationSettings(
+                setting, capability.value(), kLeAudioDirectionSource);
+        if (filtered_ase_configuration_setting.has_value()) {
+          // Put into the same list
+          // possibly duplicated, filtered by requirement later
+          // Push to non-prefer first for the broadest matching possible
+          non_prefer_matched_ase_configuration_settings.push_back(
+              filtered_ase_configuration_setting.value());
+          // Try to filter out prefer context to another vector.
+          if (filterCapabilitiesMatchedContext(
+                  filtered_ase_configuration_setting.value().audioContext,
+                  capability.value())) {
+            matched_ase_configuration_settings.push_back(
+                filtered_ase_configuration_setting.value());
+          }
+        }
+      }
+
+  // Matching priority list:
+  // Preferred context - exact match with allocation
+  // Any context - exact match with allocation
+  // Preferred context - loose match with allocation
+  // Any context - loose match with allocation
+
+  // A loose match will attempt to return 2 settings with the
+  // combined allocation bitmask equal the required allocation.
+  // For example, we can return 2 link (left link and right link) when
+  // the requirement required 1 (left + right) link.
+  auto result = matchWithRequirement(matched_ase_configuration_settings,
+                                     in_requirements, true);
+  if (result.empty()) {
+    LOG(WARNING)
+        << __func__
+        << ": Cannot match with preferred context settings - exact match";
+    result = matchWithRequirement(non_prefer_matched_ase_configuration_settings,
+                                  in_requirements, true);
+  }
+  if (result.empty()) {
+    LOG(WARNING)
+        << __func__
+        << ": Cannot match with non-preferred context settings - exact match";
+    result = matchWithRequirement(matched_ase_configuration_settings,
+                                  in_requirements, false);
+  }
+  if (result.empty()) {
+    LOG(WARNING) << __func__
+                 << ": Cannot match with preferred context settings - "
+                    "non-exact match";
+    result = matchWithRequirement(non_prefer_matched_ase_configuration_settings,
+                                  in_requirements, false);
+  }
+  if (result.empty())
+    LOG(ERROR) << __func__
+               << ": Cannot match with non preferred context settings - "
+                  "non-exact match";
   *_aidl_return = result;
   return ndk::ScopedAStatus::ok();
 };
@@ -537,19 +817,116 @@
     LeAudioAseQosConfiguration setting_qos,
     AseQosDirectionRequirement requirement_qos) {
   if (setting_qos.retransmissionNum !=
-      requirement_qos.preferredRetransmissionNum)
+      requirement_qos.preferredRetransmissionNum) {
     return false;
-  if (setting_qos.maxTransportLatencyMs > requirement_qos.maxTransportLatencyMs)
+  }
+  if (setting_qos.maxTransportLatencyMs >
+      requirement_qos.maxTransportLatencyMs) {
     return false;
-  // Ignore other parameters, as they are not populated in the setting_qos
+  }
   return true;
 }
 
+bool isValidQosRequirement(AseQosDirectionRequirement qosRequirement) {
+  return ((qosRequirement.maxTransportLatencyMs > 0) &&
+          (qosRequirement.presentationDelayMaxUs > 0) &&
+          (qosRequirement.presentationDelayMaxUs >=
+           qosRequirement.presentationDelayMinUs));
+}
+
+std::optional<LeAudioAseQosConfiguration>
+LeAudioOffloadAudioProvider::getDirectionQosConfiguration(
+    uint8_t direction,
+    const IBluetoothAudioProvider::LeAudioAseQosConfigurationRequirement&
+        qosRequirement,
+    std::vector<LeAudioAseConfigurationSetting>& ase_configuration_settings,
+    bool is_exact) {
+  std::optional<AseQosDirectionRequirement> direction_qos_requirement =
+      std::nullopt;
+
+  // Get the correct direction
+  if (direction == kLeAudioDirectionSink) {
+    direction_qos_requirement = qosRequirement.sinkAseQosRequirement.value();
+  } else {
+    direction_qos_requirement = qosRequirement.sourceAseQosRequirement.value();
+  }
+
+  for (auto& setting : ase_configuration_settings) {
+    // Context matching
+    if ((setting.audioContext.bitmask & qosRequirement.audioContext.bitmask) !=
+        qosRequirement.audioContext.bitmask)
+      continue;
+
+    // Match configuration flags
+    // Currently configuration flags are not populated, ignore.
+
+    // Get a list of all matched AseDirectionConfiguration
+    // for the input direction
+    std::optional<std::vector<std::optional<AseDirectionConfiguration>>>
+        direction_configuration = std::nullopt;
+    if (direction == kLeAudioDirectionSink) {
+      if (!setting.sinkAseConfiguration.has_value()) continue;
+      direction_configuration.emplace(setting.sinkAseConfiguration.value());
+    } else {
+      if (!setting.sourceAseConfiguration.has_value()) continue;
+      direction_configuration.emplace(setting.sourceAseConfiguration.value());
+    }
+
+    if (!direction_configuration.has_value()) {
+      return std::nullopt;
+    }
+
+    // Collect all valid cfg into a vector
+    // Then try to get the best match for audio allocation
+
+    auto temp = std::vector<AseDirectionConfiguration>();
+
+    for (auto& cfg : direction_configuration.value()) {
+      if (!cfg.has_value()) continue;
+      // If no requirement, return the first QoS
+      if (!direction_qos_requirement.has_value()) {
+        return cfg.value().qosConfiguration;
+      }
+
+      // If has requirement, return the first matched QoS
+      // Try to match the ASE configuration
+      // and QoS with requirement
+      if (!cfg.value().qosConfiguration.has_value()) continue;
+      if (filterMatchedAseConfiguration(
+              cfg.value().aseConfiguration,
+              direction_qos_requirement.value().aseConfiguration) &&
+          isMatchedQosRequirement(cfg.value().qosConfiguration.value(),
+                                  direction_qos_requirement.value())) {
+        temp.push_back(cfg.value());
+      }
+    }
+    LOG(WARNING) << __func__ << ": Got " << temp.size()
+                 << " configs, start matching allocation";
+
+    int qos_allocation_bitmask = getLeAudioAseConfigurationAllocationBitmask(
+        direction_qos_requirement.value().aseConfiguration);
+    // Get the best matching config based on channel allocation
+    auto req_valid_configs = getValidConfigurationsFromAllocation(
+        qos_allocation_bitmask, temp, is_exact);
+    if (req_valid_configs.empty()) {
+      LOG(WARNING) << __func__
+                   << ": Cannot find matching allocation for bitmask "
+                   << qos_allocation_bitmask;
+
+    } else {
+      return req_valid_configs[0].qosConfiguration;
+    }
+  }
+
+  return std::nullopt;
+}
+
 ndk::ScopedAStatus LeAudioOffloadAudioProvider::getLeAudioAseQosConfiguration(
     const IBluetoothAudioProvider::LeAudioAseQosConfigurationRequirement&
         in_qosRequirement,
     IBluetoothAudioProvider::LeAudioAseQosConfigurationPair* _aidl_return) {
   IBluetoothAudioProvider::LeAudioAseQosConfigurationPair result;
+
   // Get all configuration settings
   std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting>
       ase_configuration_settings =
@@ -557,67 +934,35 @@
 
   // Direction QoS matching
   // Only handle one direction input case
-  uint8_t direction = 0;
-  std::optional<AseQosDirectionRequirement> direction_qos_requirement =
-      std::nullopt;
   if (in_qosRequirement.sinkAseQosRequirement.has_value()) {
-    direction_qos_requirement = in_qosRequirement.sinkAseQosRequirement.value();
-    direction = kLeAudioDirectionSink;
-  } else if (in_qosRequirement.sourceAseQosRequirement.has_value()) {
-    direction_qos_requirement =
-        in_qosRequirement.sourceAseQosRequirement.value();
-    direction = kLeAudioDirectionSource;
-  }
-
-  for (auto& setting : ase_configuration_settings) {
-    // Context matching
-    if (setting.audioContext != in_qosRequirement.audioContext) continue;
-
-    // Match configuration flags
-    // Currently configuration flags are not populated, ignore.
-
-    // Get a list of all matched AseDirectionConfiguration
-    // for the input direction
-    std::vector<std::optional<AseDirectionConfiguration>>*
-        direction_configuration = nullptr;
-    if (direction == kLeAudioDirectionSink) {
-      if (!setting.sinkAseConfiguration.has_value()) continue;
-      direction_configuration = &setting.sinkAseConfiguration.value();
-    } else {
-      if (!setting.sourceAseConfiguration.has_value()) continue;
-      direction_configuration = &setting.sourceAseConfiguration.value();
-    }
-
-    for (auto cfg : *direction_configuration) {
-      if (!cfg.has_value()) continue;
-      // If no requirement, return the first QoS
-      if (!direction_qos_requirement.has_value()) {
-        result.sinkQosConfiguration = cfg.value().qosConfiguration;
-        result.sourceQosConfiguration = cfg.value().qosConfiguration;
-        *_aidl_return = result;
-        return ndk::ScopedAStatus::ok();
-      }
-
-      // If has requirement, return the first matched QoS
-      // Try to match the ASE configuration
-      // and QoS with requirement
-      if (!cfg.value().qosConfiguration.has_value()) continue;
-      if (isMatchedAseConfiguration(
-              cfg.value().aseConfiguration,
-              direction_qos_requirement.value().aseConfiguration) &&
-          isMatchedQosRequirement(cfg.value().qosConfiguration.value(),
-                                  direction_qos_requirement.value())) {
-        if (direction == kLeAudioDirectionSink)
-          result.sinkQosConfiguration = cfg.value().qosConfiguration;
-        else
-          result.sourceQosConfiguration = cfg.value().qosConfiguration;
-        *_aidl_return = result;
-        return ndk::ScopedAStatus::ok();
+    if (!isValidQosRequirement(in_qosRequirement.sinkAseQosRequirement.value()))
+      return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    {
+      // Try exact match first
+      result.sinkQosConfiguration =
+          getDirectionQosConfiguration(kLeAudioDirectionSink, in_qosRequirement,
+                                       ase_configuration_settings, true);
+      if (!result.sinkQosConfiguration.has_value()) {
+        result.sinkQosConfiguration = getDirectionQosConfiguration(
+            kLeAudioDirectionSink, in_qosRequirement,
+            ase_configuration_settings, false);
       }
     }
   }
+  if (in_qosRequirement.sourceAseQosRequirement.has_value()) {
+    if (!isValidQosRequirement(
+            in_qosRequirement.sourceAseQosRequirement.value()))
+      return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    result.sourceQosConfiguration =
+        getDirectionQosConfiguration(kLeAudioDirectionSource, in_qosRequirement,
+                                     ase_configuration_settings, true);
+    if (!result.sourceQosConfiguration.has_value()) {
+      result.sourceQosConfiguration = getDirectionQosConfiguration(
+          kLeAudioDirectionSource, in_qosRequirement,
+          ase_configuration_settings, false);
+    }
+  }
 
-  // No match, return empty QoS
   *_aidl_return = result;
   return ndk::ScopedAStatus::ok();
 };
@@ -640,24 +985,127 @@
   return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
 };
 
+LeAudioBroadcastConfigurationSetting getDefaultBroadcastSetting(
+    int context_bitmask, IBluetoothAudioProvider::BroadcastQuality quality) {
+  LeAudioBroadcastConfigurationSetting setting;
+  setting.retransmitionNum = 4;
+  setting.maxTransportLatencyMs = 60;
+  setting.sduIntervalUs = 10000;
+  setting.maxSduOctets = 40;
+
+  if (quality == IBluetoothAudioProvider::BroadcastQuality::HIGH) {
+    LOG(INFO) << __func__ << ": High quality, returning high quality settings";
+    setting.retransmitionNum = 4;
+    setting.maxTransportLatencyMs = 65;
+    setting.maxSduOctets = 200;
+    return setting;
+  }
+
+  // Populate other settings base on context
+  // TODO: Populate with better design
+  if (context_bitmask & (AudioContext::LIVE_AUDIO | AudioContext::GAME)) {
+    setting.retransmitionNum = 2;
+    setting.maxTransportLatencyMs = 10;
+    setting.maxSduOctets = 120;
+  } else if (context_bitmask & (AudioContext::INSTRUCTIONAL)) {
+    setting.retransmitionNum = 2;
+    setting.maxTransportLatencyMs = 10;
+    setting.maxSduOctets = 40;
+  } else if (context_bitmask &
+             (AudioContext::SOUND_EFFECTS | AudioContext::UNSPECIFIED)) {
+    setting.retransmitionNum = 4;
+    setting.maxTransportLatencyMs = 60;
+    setting.maxSduOctets = 80;
+  } else if (context_bitmask &
+             (AudioContext::ALERTS | AudioContext::NOTIFICATIONS |
+              AudioContext::EMERGENCY_ALARM)) {
+    setting.retransmitionNum = 4;
+    setting.maxTransportLatencyMs = 60;
+    setting.maxSduOctets = 40;
+  } else if (context_bitmask & AudioContext::MEDIA) {
+    setting.retransmitionNum = 4;
+    setting.maxTransportLatencyMs = 60;
+    setting.maxSduOctets = 120;
+  }
+
+  return setting;
+}
+void modifySubBISConfigAllocation(
+    IBluetoothAudioProvider::LeAudioSubgroupBisConfiguration& sub_bis_cfg,
+    int allocation_bitmask) {
+  for (auto& codec_cfg : sub_bis_cfg.bisConfiguration.codecConfiguration) {
+    if (codec_cfg.getTag() ==
+        CodecSpecificConfigurationLtv::audioChannelAllocation) {
+      codec_cfg.get<CodecSpecificConfigurationLtv::audioChannelAllocation>()
+          .bitmask = allocation_bitmask;
+      break;
+    }
+  }
+}
+void modifySubgroupConfiguration(
+    IBluetoothAudioProvider::LeAudioBroadcastSubgroupConfiguration&
+        subgroup_cfg,
+    int context_bitmask) {
+  // STEREO configs
+  // Split into 2 sub BIS config, each has numBis = 1
+  if (context_bitmask & (AudioContext::LIVE_AUDIO | AudioContext::GAME |
+                         AudioContext::SOUND_EFFECTS |
+                         AudioContext::UNSPECIFIED | AudioContext::MEDIA)) {
+    if (subgroup_cfg.bisConfigurations.size() == 1)
+      subgroup_cfg.bisConfigurations.push_back(
+          subgroup_cfg.bisConfigurations[0]);
+
+    subgroup_cfg.bisConfigurations[0].numBis = 1;
+    modifySubBISConfigAllocation(
+        subgroup_cfg.bisConfigurations[0],
+        CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_LEFT);
+
+    subgroup_cfg.bisConfigurations[1].numBis = 1;
+    modifySubBISConfigAllocation(
+        subgroup_cfg.bisConfigurations[1],
+        CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_RIGHT);
+    return;
+  }
+
+  // MONO configs
+  for (auto& sub_bis_cfg : subgroup_cfg.bisConfigurations) {
+    sub_bis_cfg.numBis = 1;
+    modifySubBISConfigAllocation(
+        sub_bis_cfg,
+        CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_CENTER);
+  }
+}
+
 void LeAudioOffloadAudioProvider::getBroadcastSettings() {
   if (!broadcast_settings.empty()) return;
 
-  LOG(INFO) << __func__ << ": Loading broadcast settings from provider info";
+  LOG(INFO) << __func__
+            << ": Loading basic broadcast settings from provider info";
 
   std::vector<CodecInfo> db_codec_info =
       BluetoothAudioCodecs::GetLeAudioOffloadCodecInfo(
           SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
+  for (auto x : db_codec_info) {
+    LOG(INFO) << __func__ << ": codec info = " << x.toString();
+  }
   broadcast_settings.clear();
+
+  // Default value population
   CodecSpecificConfigurationLtv::AudioChannelAllocation default_allocation;
   default_allocation.bitmask =
       CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_CENTER;
+  CodecSpecificConfigurationLtv::CodecFrameBlocksPerSDU default_frame;
+  default_frame.value = 1;
 
   for (auto& codec_info : db_codec_info) {
     if (codec_info.transport.getTag() != CodecInfo::Transport::leAudio)
       continue;
     auto& transport = codec_info.transport.get<CodecInfo::Transport::leAudio>();
     LeAudioBroadcastConfigurationSetting setting;
+    setting.retransmitionNum = 4;
+    setting.maxTransportLatencyMs = 60;
+    setting.sduIntervalUs = 10000;
+    setting.maxSduOctets = 40;
     // Default setting
     setting.numBis = 1;
     setting.phy = {Phy::TWO_M};
@@ -669,14 +1117,21 @@
     octets.value = transport.bitdepth[0];
 
     bis_cfg.codecConfiguration = {
-        sampling_freq_map[transport.samplingFrequencyHz[0]], octets,
-        frame_duration_map[transport.frameDurationUs[0]], default_allocation};
+        sampling_freq_map[transport.samplingFrequencyHz[0]],
+        octets,
+        frame_duration_map[transport.frameDurationUs[0]],
+        default_allocation,
+        default_frame,
+    };
+
+    // Ignore bis_cfg.metadata
 
     // Add information to structure
     IBluetoothAudioProvider::LeAudioSubgroupBisConfiguration sub_bis_cfg;
     sub_bis_cfg.numBis = 1;
     sub_bis_cfg.bisConfiguration = bis_cfg;
     IBluetoothAudioProvider::LeAudioBroadcastSubgroupConfiguration sub_cfg;
+    // Populate the same sub config
     sub_cfg.bisConfigurations = {sub_bis_cfg};
     setting.subgroupsConfigurations = {sub_cfg};
 
@@ -721,6 +1176,93 @@
   return filtered_setting;
 }
 
+std::vector<CodecSpecificConfigurationLtv> getCodecRequirementBasedOnContext(
+    int context_bitmask, IBluetoothAudioProvider::BroadcastQuality quality) {
+  // Default requirement: lc3_stereo_16_2
+  std::vector<CodecSpecificConfigurationLtv> requirement = {
+      CodecSpecificConfigurationLtv::SamplingFrequency::HZ16000,
+      CodecSpecificConfigurationLtv::FrameDuration::US10000,
+  };
+
+  if (quality == IBluetoothAudioProvider::BroadcastQuality::HIGH) {
+    LOG(INFO) << __func__
+              << ": High quality, returning high quality requirement";
+    requirement = {
+        CodecSpecificConfigurationLtv::SamplingFrequency::HZ48000,
+        CodecSpecificConfigurationLtv::FrameDuration::US10000,
+    };
+    return requirement;
+  }
+
+  if (context_bitmask & (AudioContext::LIVE_AUDIO | AudioContext::GAME)) {
+    // lc3_stereo_24_2_1
+    requirement = {
+        CodecSpecificConfigurationLtv::SamplingFrequency::HZ24000,
+        CodecSpecificConfigurationLtv::FrameDuration::US10000,
+    };
+  } else if (context_bitmask & (AudioContext::INSTRUCTIONAL)) {
+    // lc3_mono_16_2
+    requirement = {
+        CodecSpecificConfigurationLtv::SamplingFrequency::HZ16000,
+        CodecSpecificConfigurationLtv::FrameDuration::US10000,
+    };
+  } else if (context_bitmask &
+             (AudioContext::SOUND_EFFECTS | AudioContext::UNSPECIFIED)) {
+    // lc3_stereo_16_2
+    requirement = {
+        CodecSpecificConfigurationLtv::SamplingFrequency::HZ16000,
+        CodecSpecificConfigurationLtv::FrameDuration::US10000,
+    };
+  } else if (context_bitmask &
+             (AudioContext::ALERTS | AudioContext::NOTIFICATIONS |
+              AudioContext::EMERGENCY_ALARM)) {
+    // Default requirement: lc3_stereo_16_2
+    requirement = {
+        CodecSpecificConfigurationLtv::SamplingFrequency::HZ16000,
+        CodecSpecificConfigurationLtv::FrameDuration::US10000,
+    };
+  } else if (context_bitmask & AudioContext::MEDIA) {
+    // Default requirement: lc3_stereo_16_2
+    // Return the 48k requirement
+    requirement = {
+        CodecSpecificConfigurationLtv::SamplingFrequency::HZ24000,
+        CodecSpecificConfigurationLtv::FrameDuration::US10000,
+    };
+  }
+  return requirement;
+}
+
+bool LeAudioOffloadAudioProvider::isSubgroupConfigurationMatchedContext(
+    AudioContext requirement_context,
+    IBluetoothAudioProvider::BroadcastQuality quality,
+    LeAudioBroadcastSubgroupConfiguration configuration) {
+  // Find any valid context metadata in the bisConfigurations
+  // assuming the bis configuration in the same bis subgroup
+  // will have the same context metadata
+  std::optional<AudioContext> config_context = std::nullopt;
+
+  auto codec_requirement =
+      getCodecRequirementBasedOnContext(requirement_context.bitmask, quality);
+  std::map<CodecSpecificConfigurationLtv::Tag, CodecSpecificConfigurationLtv>
+      req_tag_map;
+  for (auto x : codec_requirement) req_tag_map[x.getTag()] = x;
+
+  for (auto& bis_cfg : configuration.bisConfigurations) {
+    // Check every sub_bis_cfg to see which match
+    for (auto& x : bis_cfg.bisConfiguration.codecConfiguration) {
+      auto p = req_tag_map.find(x.getTag());
+      if (p == req_tag_map.end()) continue;
+      if (p->second != x) {
+        LOG(WARNING) << __func__ << ": does not match for context "
+                     << requirement_context.toString()
+                     << ", cfg = " << x.toString();
+        return false;
+      }
+    }
+  }
+  return true;
+}
+
 ndk::ScopedAStatus
 LeAudioOffloadAudioProvider::getLeAudioBroadcastConfiguration(
     const std::optional<std::vector<
@@ -729,23 +1271,29 @@
     const IBluetoothAudioProvider::LeAudioBroadcastConfigurationRequirement&
         in_requirement,
     LeAudioBroadcastConfigurationSetting* _aidl_return) {
-  getBroadcastSettings();
-  _aidl_return = nullptr;
-
-  // Match and filter capability
-  std::vector<LeAudioBroadcastConfigurationSetting> filtered_settings;
-  if (!in_remoteSinkAudioCapabilities.has_value()) {
-    LOG(WARNING) << __func__ << ": Empty capability";
-    return ndk::ScopedAStatus::ok();
+  if (in_requirement.subgroupConfigurationRequirements.empty()) {
+    LOG(WARNING) << __func__ << ": Empty requirement";
+    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
   }
-  for (auto& setting : broadcast_settings) {
-    for (auto& capability : in_remoteSinkAudioCapabilities.value()) {
-      if (!capability.has_value()) continue;
-      auto filtered_setting =
-          getCapabilitiesMatchedBroadcastConfigurationSettings(
-              setting, capability.value());
-      if (filtered_setting.has_value())
-        filtered_settings.push_back(filtered_setting.value());
+
+  // Broadcast setting are from provider info
+  // We will allow empty capability input, match all settings with requirements.
+  getBroadcastSettings();
+  std::vector<LeAudioBroadcastConfigurationSetting> filtered_settings;
+  if (!in_remoteSinkAudioCapabilities.has_value() ||
+      in_remoteSinkAudioCapabilities.value().empty()) {
+    LOG(INFO) << __func__ << ": Empty capability, get all broadcast settings";
+    filtered_settings = broadcast_settings;
+  } else {
+    for (auto& setting : broadcast_settings) {
+      for (auto& capability : in_remoteSinkAudioCapabilities.value()) {
+        if (!capability.has_value()) continue;
+        auto filtered_setting =
+            getCapabilitiesMatchedBroadcastConfigurationSettings(
+                setting, capability.value());
+        if (filtered_setting.has_value())
+          filtered_settings.push_back(filtered_setting.value());
+      }
     }
   }
 
@@ -754,39 +1302,82 @@
     return ndk::ScopedAStatus::ok();
   }
 
-  // Match and return the first matched requirement
   if (in_requirement.subgroupConfigurationRequirements.empty()) {
     LOG(INFO) << __func__ << ": Empty requirement";
     *_aidl_return = filtered_settings[0];
     return ndk::ScopedAStatus::ok();
   }
 
-  for (auto& setting : filtered_settings) {
-    // Further filter out bis configuration
-    LeAudioBroadcastConfigurationSetting filtered_setting(setting);
-    filtered_setting.subgroupsConfigurations.clear();
-    for (auto& sub_cfg : setting.subgroupsConfigurations) {
-      bool isMatched = false;
-      for (auto& sub_req : in_requirement.subgroupConfigurationRequirements) {
-        // Matching number of BIS
-        if (sub_req.bisNumPerSubgroup != sub_cfg.bisConfigurations.size())
-          continue;
-        // Currently will ignore quality and context hint.
-        isMatched = true;
+  // For each subgroup config requirement, find a suitable subgroup config.
+  // Gather these suitable subgroup config in an array.
+  // If the setting can satisfy all requirement, we can return the setting
+  // with the filtered array.
+
+  auto context_bitmask =
+      in_requirement.subgroupConfigurationRequirements[0].audioContext.bitmask;
+  auto quality = in_requirement.subgroupConfigurationRequirements[0].quality;
+  LeAudioBroadcastConfigurationSetting return_setting =
+      getDefaultBroadcastSetting(context_bitmask, quality);
+  // Default setting
+  return_setting.numBis = 0;
+  return_setting.subgroupsConfigurations = {};
+
+  LeAudioDataPathConfiguration path;
+  path.isoDataPathConfiguration.isTransparent = true;
+  path.dataPathId = kIsoDataPathPlatformDefault;
+
+  // Each subreq, find a setting that match
+  for (auto& sub_req : in_requirement.subgroupConfigurationRequirements) {
+    bool is_setting_matched = false;
+    for (auto setting : filtered_settings) {
+      bool is_matched = true;
+      // Check if every sub BIS config satisfy
+      for (auto& sub_group_config : setting.subgroupsConfigurations) {
+        if (!isSubgroupConfigurationMatchedContext(
+                sub_req.audioContext, sub_req.quality, sub_group_config)) {
+          is_matched = false;
+          break;
+        }
+        path.isoDataPathConfiguration.codecId =
+            sub_group_config.bisConfigurations[0].bisConfiguration.codecId;
+        // Also modify the subgroup config to match the context
+        modifySubgroupConfiguration(sub_group_config, context_bitmask);
+      }
+
+      if (is_matched) {
+        is_setting_matched = true;
+        for (auto& sub_group_config : setting.subgroupsConfigurations)
+          return_setting.subgroupsConfigurations.push_back(sub_group_config);
         break;
       }
-      if (isMatched)
-        filtered_setting.subgroupsConfigurations.push_back(sub_cfg);
     }
-    // Return the first match
-    if (!filtered_setting.subgroupsConfigurations.empty()) {
-      LOG(INFO) << __func__ << ": Matched requirement";
-      *_aidl_return = filtered_setting;
+
+    if (!is_setting_matched) {
+      LOG(WARNING) << __func__
+                   << ": Cannot find a setting that match requirement "
+                   << sub_req.toString();
       return ndk::ScopedAStatus::ok();
     }
   }
 
-  LOG(WARNING) << __func__ << ": Cannot match any requirement";
+  // Populate all numBis
+  for (auto& sub_group_config : return_setting.subgroupsConfigurations) {
+    for (auto& sub_bis_config : sub_group_config.bisConfigurations) {
+      return_setting.numBis += sub_bis_config.numBis;
+    }
+  }
+  return_setting.phy = std::vector<Phy>(return_setting.numBis, Phy::TWO_M);
+  // Populate data path config
+  return_setting.dataPathConfiguration = path;
+  // TODO: Workaround for STEREO configs maxSduOctets being doubled
+  if (context_bitmask & (AudioContext::LIVE_AUDIO | AudioContext::GAME |
+                         AudioContext::SOUND_EFFECTS |
+                         AudioContext::UNSPECIFIED | AudioContext::MEDIA)) {
+    return_setting.maxSduOctets /= 2;
+  }
+  LOG(INFO) << __func__
+            << ": Combined setting that match: " << return_setting.toString();
+  *_aidl_return = return_setting;
   return ndk::ScopedAStatus::ok();
 };
 
diff --git a/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.h b/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.h
index 2785e7f..043d923 100644
--- a/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.h
+++ b/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.h
@@ -96,8 +96,8 @@
 
   // Private matching function definitions
   bool isMatchedValidCodec(CodecId cfg_codec, CodecId req_codec);
-  bool isCapabilitiesMatchedContext(
-      AudioContext setting_context,
+  bool filterCapabilitiesMatchedContext(
+      AudioContext& setting_context,
       const IBluetoothAudioProvider::LeAudioDeviceCapabilities& capabilities);
   bool isMatchedSamplingFreq(
       CodecSpecificConfigurationLtv::SamplingFrequency& cfg_freq,
@@ -122,8 +122,9 @@
   bool isCapabilitiesMatchedCodecConfiguration(
       std::vector<CodecSpecificConfigurationLtv>& codec_cfg,
       std::vector<CodecSpecificCapabilitiesLtv> codec_capabilities);
-  bool isMatchedAseConfiguration(LeAudioAseConfiguration setting_cfg,
-                                 LeAudioAseConfiguration requirement_cfg);
+  bool filterMatchedAseConfiguration(
+      LeAudioAseConfiguration& setting_cfg,
+      const LeAudioAseConfiguration& requirement_cfg);
   bool isMatchedBISConfiguration(
       LeAudioBisConfiguration bis_cfg,
       const IBluetoothAudioProvider::LeAudioDeviceCapabilities& capabilities);
@@ -134,12 +135,12 @@
       std::vector<std::optional<AseDirectionConfiguration>>&
           valid_direction_configurations);
   void filterRequirementAseDirectionConfiguration(
-      std::vector<std::optional<AseDirectionConfiguration>>&
+      std::optional<std::vector<std::optional<AseDirectionConfiguration>>>&
           direction_configurations,
-      const std::optional<std::vector<std::optional<AseDirectionRequirement>>>&
-          requirements,
-      std::vector<std::optional<AseDirectionConfiguration>>&
-          valid_direction_configurations);
+      const std::vector<std::optional<AseDirectionRequirement>>& requirements,
+      std::optional<std::vector<std::optional<AseDirectionConfiguration>>>&
+          valid_direction_configurations,
+      bool is_exact);
   std::optional<LeAudioAseConfigurationSetting>
   getCapabilitiesMatchedAseConfigurationSettings(
       IBluetoothAudioProvider::LeAudioAseConfigurationSetting& setting,
@@ -149,7 +150,8 @@
   getRequirementMatchedAseConfigurationSettings(
       IBluetoothAudioProvider::LeAudioAseConfigurationSetting& setting,
       const IBluetoothAudioProvider::LeAudioConfigurationRequirement&
-          requirement);
+          requirement,
+      bool is_exact);
   bool isMatchedQosRequirement(LeAudioAseQosConfiguration setting_qos,
                                AseQosDirectionRequirement requirement_qos);
   std::optional<LeAudioBroadcastConfigurationSetting>
@@ -157,6 +159,24 @@
       LeAudioBroadcastConfigurationSetting& setting,
       const IBluetoothAudioProvider::LeAudioDeviceCapabilities& capabilities);
   void getBroadcastSettings();
+  std::optional<LeAudioAseQosConfiguration> getDirectionQosConfiguration(
+      uint8_t direction,
+      const IBluetoothAudioProvider::LeAudioAseQosConfigurationRequirement&
+          qosRequirement,
+      std::vector<LeAudioAseConfigurationSetting>& ase_configuration_settings,
+      bool is_exact);
+  bool isSubgroupConfigurationMatchedContext(
+      AudioContext requirement_context,
+      IBluetoothAudioProvider::BroadcastQuality quality,
+      LeAudioBroadcastSubgroupConfiguration configuration);
+  std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting>
+  matchWithRequirement(
+      std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting>&
+          matched_ase_configuration_settings,
+      const std::vector<
+          IBluetoothAudioProvider::LeAudioConfigurationRequirement>&
+          in_requirements,
+      bool is_exact);
 };
 
 class LeAudioOffloadOutputAudioProvider : public LeAudioOffloadAudioProvider {
diff --git a/bluetooth/audio/aidl/vts/VtsHalBluetoothAudioTargetTest.cpp b/bluetooth/audio/aidl/vts/VtsHalBluetoothAudioTargetTest.cpp
index c313fb7..e83cb9e 100644
--- a/bluetooth/audio/aidl/vts/VtsHalBluetoothAudioTargetTest.cpp
+++ b/bluetooth/audio/aidl/vts/VtsHalBluetoothAudioTargetTest.cpp
@@ -58,6 +58,7 @@
 using aidl::android::hardware::bluetooth::audio::CodecSpecificCapabilitiesLtv;
 using aidl::android::hardware::bluetooth::audio::CodecSpecificConfigurationLtv;
 using aidl::android::hardware::bluetooth::audio::CodecType;
+using aidl::android::hardware::bluetooth::audio::ConfigurationFlags;
 using aidl::android::hardware::bluetooth::audio::HfpConfiguration;
 using aidl::android::hardware::bluetooth::audio::IBluetoothAudioPort;
 using aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider;
@@ -68,6 +69,7 @@
 using aidl::android::hardware::bluetooth::audio::LdacCapabilities;
 using aidl::android::hardware::bluetooth::audio::LdacConfiguration;
 using aidl::android::hardware::bluetooth::audio::LeAudioAseConfiguration;
+using aidl::android::hardware::bluetooth::audio::LeAudioBisConfiguration;
 using aidl::android::hardware::bluetooth::audio::LeAudioBroadcastConfiguration;
 using aidl::android::hardware::bluetooth::audio::
     LeAudioCodecCapabilitiesSetting;
@@ -105,12 +107,24 @@
     LeAudioAseConfigurationSetting::AseDirectionConfiguration;
 using AseQosDirectionRequirement = IBluetoothAudioProvider::
     LeAudioAseQosConfigurationRequirement::AseQosDirectionRequirement;
+using LeAudioAseQosConfigurationRequirement =
+    IBluetoothAudioProvider::LeAudioAseQosConfigurationRequirement;
 using LeAudioAseQosConfiguration =
     IBluetoothAudioProvider::LeAudioAseQosConfiguration;
 using LeAudioDeviceCapabilities =
     IBluetoothAudioProvider::LeAudioDeviceCapabilities;
 using LeAudioConfigurationRequirement =
     IBluetoothAudioProvider::LeAudioConfigurationRequirement;
+using LeAudioBroadcastConfigurationRequirement =
+    IBluetoothAudioProvider::LeAudioBroadcastConfigurationRequirement;
+using LeAudioBroadcastSubgroupConfiguration =
+    IBluetoothAudioProvider::LeAudioBroadcastSubgroupConfiguration;
+using LeAudioBroadcastSubgroupConfigurationRequirement =
+    IBluetoothAudioProvider::LeAudioBroadcastSubgroupConfigurationRequirement;
+using LeAudioBroadcastConfigurationSetting =
+    IBluetoothAudioProvider::LeAudioBroadcastConfigurationSetting;
+using LeAudioSubgroupBisConfiguration =
+    IBluetoothAudioProvider::LeAudioSubgroupBisConfiguration;
 
 // Constants
 
@@ -2228,6 +2242,37 @@
     BluetoothAudioProviderFactoryAidl::TearDown();
   }
 
+  bool IsMultidirectionalCapabilitiesEnabled() {
+    if (!temp_provider_info_.has_value()) return false;
+
+    return temp_provider_info_.value().supportsMultidirectionalCapabilities;
+  }
+
+  bool IsAsymmetricConfigurationAllowed() {
+    if (!temp_provider_info_.has_value()) return false;
+    if (temp_provider_info_.value().codecInfos.empty()) return false;
+
+    for (auto& codec_info : temp_provider_info_.value().codecInfos) {
+      if (codec_info.transport.getTag() != CodecInfo::Transport::leAudio) {
+        return false;
+      }
+
+      auto flags =
+          codec_info.transport.get<CodecInfo::Transport::leAudio>().flags;
+
+      if (!flags) {
+        continue;
+      }
+
+      if (flags->bitmask &
+          ConfigurationFlags::ALLOW_ASYMMETRIC_CONFIGURATIONS) {
+        return true;
+      }
+    }
+
+    return false;
+  }
+
   bool IsOffloadOutputSupported() {
     for (auto& capability : temp_provider_capabilities_) {
       if (capability.getTag() != AudioCapabilities::leAudioCapabilities) {
@@ -2284,27 +2329,31 @@
     return media_audio_context;
   }
 
-  LeAudioDeviceCapabilities GetDefaultRemoteCapability() {
+  LeAudioDeviceCapabilities GetDefaultRemoteSinkCapability() {
     // Create a capability
     LeAudioDeviceCapabilities capability;
 
     capability.codecId = CodecId::Core::LC3;
 
     auto pref_context_metadata = MetadataLtv::PreferredAudioContexts();
-    pref_context_metadata.values = GetAudioContext(AudioContext::MEDIA);
+    pref_context_metadata.values =
+        GetAudioContext(AudioContext::MEDIA | AudioContext::CONVERSATIONAL |
+                        AudioContext::GAME);
     capability.metadata = {pref_context_metadata};
 
     auto sampling_rate =
         CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies();
     sampling_rate.bitmask =
+        CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies::HZ16000 |
         CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies::HZ8000;
     auto frame_duration =
         CodecSpecificCapabilitiesLtv::SupportedFrameDurations();
     frame_duration.bitmask =
-        CodecSpecificCapabilitiesLtv::SupportedFrameDurations::US7500;
+        CodecSpecificCapabilitiesLtv::SupportedFrameDurations::US7500 |
+        CodecSpecificCapabilitiesLtv::SupportedFrameDurations::US10000;
     auto octets = CodecSpecificCapabilitiesLtv::SupportedOctetsPerCodecFrame();
     octets.min = 0;
-    octets.max = 60;
+    octets.max = 120;
     auto frames = CodecSpecificCapabilitiesLtv::SupportedMaxCodecFramesPerSDU();
     frames.value = 2;
     capability.codecSpecificCapabilities = {sampling_rate, frame_duration,
@@ -2312,29 +2361,394 @@
     return capability;
   }
 
-  LeAudioConfigurationRequirement GetDefaultRequirement(
-      bool is_source_requriement) {
+  LeAudioDeviceCapabilities GetDefaultRemoteSourceCapability() {
+    // Create a capability
+    LeAudioDeviceCapabilities capability;
+
+    capability.codecId = CodecId::Core::LC3;
+
+    auto pref_context_metadata = MetadataLtv::PreferredAudioContexts();
+    pref_context_metadata.values =
+        GetAudioContext(AudioContext::LIVE_AUDIO |
+                        AudioContext::CONVERSATIONAL | AudioContext::GAME);
+    capability.metadata = {pref_context_metadata};
+
+    auto sampling_rate =
+        CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies();
+    sampling_rate.bitmask =
+        CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies::HZ16000 |
+        CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies::HZ8000;
+    auto frame_duration =
+        CodecSpecificCapabilitiesLtv::SupportedFrameDurations();
+    frame_duration.bitmask =
+        CodecSpecificCapabilitiesLtv::SupportedFrameDurations::US7500 |
+        CodecSpecificCapabilitiesLtv::SupportedFrameDurations::US10000;
+    auto octets = CodecSpecificCapabilitiesLtv::SupportedOctetsPerCodecFrame();
+    octets.min = 0;
+    octets.max = 120;
+    auto frames = CodecSpecificCapabilitiesLtv::SupportedMaxCodecFramesPerSDU();
+    frames.value = 2;
+    capability.codecSpecificCapabilities = {sampling_rate, frame_duration,
+                                            octets, frames};
+    return capability;
+  }
+
+  std::optional<CodecSpecificConfigurationLtv> GetConfigurationLtv(
+      const std::vector<CodecSpecificConfigurationLtv>& configurationLtvs,
+      CodecSpecificConfigurationLtv::Tag tag) {
+    for (const auto ltv : configurationLtvs) {
+      if (ltv.getTag() == tag) {
+        return ltv;
+      }
+    }
+    return std::nullopt;
+  }
+
+  bool IsAseRequirementSatisfiedWithUnknownChannelCount(
+      const std::vector<std::optional<AseDirectionRequirement>>&
+          ase_requirements,
+      const std::vector<std::optional<AseDirectionConfiguration>>&
+          ase_configurations) {
+    /* This is mandatory  to match sample freq, allocation however, when in the
+     * device group there is only one device which supports left and right
+     * allocation, and channel count is hidden from the BT stack, the BT stack
+     * will send single requirement but it can receive two configurations if the
+     * channel count is 1.
+     */
+
+    int num_of_ase_requirements = 0;
+    for (const auto& ase_req : ase_requirements) {
+      auto required_allocation_ltv = GetConfigurationLtv(
+          ase_req->aseConfiguration.codecConfiguration,
+          CodecSpecificConfigurationLtv::Tag::audioChannelAllocation);
+      if (required_allocation_ltv == std::nullopt) {
+        continue;
+      }
+      int required_allocation =
+          required_allocation_ltv
+              ->get<
+                  CodecSpecificConfigurationLtv::Tag::audioChannelAllocation>()
+              .bitmask;
+      num_of_ase_requirements += std::bitset<32>(required_allocation).count();
+    }
+
+    int num_of_satisfied_ase_requirements = 0;
+    for (const auto& ase_req : ase_requirements) {
+      if (!ase_req) {
+        continue;
+      }
+      auto required_sample_freq_ltv = GetConfigurationLtv(
+          ase_req->aseConfiguration.codecConfiguration,
+          CodecSpecificConfigurationLtv::Tag::samplingFrequency);
+      auto required_allocation_ltv = GetConfigurationLtv(
+          ase_req->aseConfiguration.codecConfiguration,
+          CodecSpecificConfigurationLtv::Tag::audioChannelAllocation);
+
+      /* Allocation and sample freq shall be always in the requirement */
+      if (!required_sample_freq_ltv || !required_allocation_ltv) {
+        return false;
+      }
+
+      int required_allocation =
+          required_allocation_ltv
+              ->get<
+                  CodecSpecificConfigurationLtv::Tag::audioChannelAllocation>()
+              .bitmask;
+
+      for (const auto& ase_conf : ase_configurations) {
+        if (!ase_conf) {
+          continue;
+        }
+        auto config_sample_freq_ltv = GetConfigurationLtv(
+            ase_conf->aseConfiguration.codecConfiguration,
+            CodecSpecificConfigurationLtv::Tag::samplingFrequency);
+        auto config_allocation_ltv = GetConfigurationLtv(
+            ase_conf->aseConfiguration.codecConfiguration,
+            CodecSpecificConfigurationLtv::Tag::audioChannelAllocation);
+        if (config_sample_freq_ltv == std::nullopt ||
+            config_allocation_ltv == std::nullopt) {
+          return false;
+        }
+
+        int configured_allocation = config_allocation_ltv
+                                        ->get<CodecSpecificConfigurationLtv::
+                                                  Tag::audioChannelAllocation>()
+                                        .bitmask;
+
+        if (config_sample_freq_ltv == required_sample_freq_ltv &&
+            (required_allocation & configured_allocation)) {
+          num_of_satisfied_ase_requirements +=
+              std::bitset<32>(configured_allocation).count();
+        }
+      }
+    }
+
+    return (num_of_satisfied_ase_requirements == num_of_ase_requirements);
+  }
+
+  bool IsAseRequirementSatisfied(
+      const std::vector<std::optional<AseDirectionRequirement>>&
+          ase_requirements,
+      const std::vector<std::optional<AseDirectionConfiguration>>&
+          ase_configurations) {
+    // This is mandatory  to match sample freq, allocation
+    int num_of_satisfied_ase_requirements = 0;
+
+    int required_allocations = 0;
+    for (const auto& ase_req : ase_requirements) {
+      auto required_allocation_ltv = GetConfigurationLtv(
+          ase_req->aseConfiguration.codecConfiguration,
+          CodecSpecificConfigurationLtv::Tag::audioChannelAllocation);
+      if (required_allocation_ltv == std::nullopt) {
+        continue;
+      }
+
+      int allocations =
+          required_allocation_ltv
+              ->get<
+                  CodecSpecificConfigurationLtv::Tag::audioChannelAllocation>()
+              .bitmask;
+      required_allocations += std::bitset<32>(allocations).count();
+    }
+
+    if (ase_requirements.size() != required_allocations) {
+      /* If more than one allication is requested in the requirement, then use
+       * different verifier */
+      return IsAseRequirementSatisfiedWithUnknownChannelCount(
+          ase_requirements, ase_configurations);
+    }
+
+    for (const auto& ase_req : ase_requirements) {
+      if (!ase_req) {
+        continue;
+      }
+      auto required_sample_freq_ltv = GetConfigurationLtv(
+          ase_req->aseConfiguration.codecConfiguration,
+          CodecSpecificConfigurationLtv::Tag::samplingFrequency);
+      auto required_allocation_ltv = GetConfigurationLtv(
+          ase_req->aseConfiguration.codecConfiguration,
+          CodecSpecificConfigurationLtv::Tag::audioChannelAllocation);
+
+      /* Allocation and sample freq shall be always in the requirement */
+      if (!required_sample_freq_ltv || !required_allocation_ltv) {
+        return false;
+      }
+
+      for (const auto& ase_conf : ase_configurations) {
+        if (!ase_conf) {
+          continue;
+        }
+        auto config_sample_freq_ltv = GetConfigurationLtv(
+            ase_conf->aseConfiguration.codecConfiguration,
+            CodecSpecificConfigurationLtv::Tag::samplingFrequency);
+        auto config_allocation_ltv = GetConfigurationLtv(
+            ase_conf->aseConfiguration.codecConfiguration,
+            CodecSpecificConfigurationLtv::Tag::audioChannelAllocation);
+        if (config_sample_freq_ltv == std::nullopt ||
+            config_allocation_ltv == std::nullopt) {
+          return false;
+        }
+
+        if (config_sample_freq_ltv == required_sample_freq_ltv &&
+            config_allocation_ltv == required_allocation_ltv) {
+          num_of_satisfied_ase_requirements++;
+          break;
+        }
+      }
+    }
+
+    return (num_of_satisfied_ase_requirements == ase_requirements.size());
+  }
+
+  void VerifyIfRequirementsSatisfied(
+      const std::vector<LeAudioConfigurationRequirement>& requirements,
+      const std::vector<LeAudioAseConfigurationSetting>& configurations) {
+    if (requirements.empty() && configurations.empty()) {
+      return;
+    }
+
+    /* It might happen that vendor lib will provide same configuration for
+     * multiple contexts and it should be accepted
+     */
+
+    int num_of_requirements = 0;
+    for (const auto& req : requirements) {
+      num_of_requirements += std::bitset<32>(req.audioContext.bitmask).count();
+    }
+
+    int num_of_configurations = 0;
+    for (const auto& conf : configurations) {
+      num_of_configurations +=
+          std::bitset<32>(conf.audioContext.bitmask).count();
+    }
+
+    ASSERT_EQ(num_of_requirements, num_of_configurations);
+
+    int num_of_satisfied_requirements = 0;
+    for (const auto& req : requirements) {
+      for (const auto& conf : configurations) {
+        if ((req.audioContext.bitmask & conf.audioContext.bitmask) !=
+            req.audioContext.bitmask) {
+          continue;
+        }
+
+        if (req.sinkAseRequirement && req.sourceAseRequirement) {
+          if (!conf.sinkAseConfiguration || !conf.sourceAseConfiguration) {
+            continue;
+          }
+
+          if (!IsAseRequirementSatisfied(*req.sinkAseRequirement,
+                                         *conf.sinkAseConfiguration) ||
+              !IsAseRequirementSatisfied(*req.sourceAseRequirement,
+                                         *conf.sourceAseConfiguration)) {
+            continue;
+          }
+          num_of_satisfied_requirements +=
+              std::bitset<32>(req.audioContext.bitmask).count();
+
+          break;
+        } else if (req.sinkAseRequirement) {
+          if (!IsAseRequirementSatisfied(*req.sinkAseRequirement,
+                                         *conf.sinkAseConfiguration)) {
+            continue;
+          }
+          num_of_satisfied_requirements +=
+              std::bitset<32>(req.audioContext.bitmask).count();
+          break;
+        } else if (req.sourceAseRequirement) {
+          if (!IsAseRequirementSatisfied(*req.sourceAseRequirement,
+                                         *conf.sourceAseConfiguration)) {
+            continue;
+          }
+          num_of_satisfied_requirements +=
+              std::bitset<32>(req.audioContext.bitmask).count();
+          break;
+        }
+      }
+    }
+    ASSERT_EQ(num_of_satisfied_requirements, num_of_requirements);
+  }
+
+  LeAudioConfigurationRequirement GetUnicastDefaultRequirement(
+      int32_t context_bits, bool is_sink_requirement,
+      bool is_source_requriement,
+      CodecSpecificConfigurationLtv::SamplingFrequency freq =
+          CodecSpecificConfigurationLtv::SamplingFrequency::HZ16000) {
     // Create a requirements
     LeAudioConfigurationRequirement requirement;
-    requirement.audioContext = GetAudioContext(AudioContext::MEDIA);
+    requirement.audioContext = GetAudioContext(context_bits);
+
+    auto allocation = CodecSpecificConfigurationLtv::AudioChannelAllocation();
+    allocation.bitmask =
+        CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_LEFT |
+        CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_RIGHT;
 
     auto direction_ase_requriement = AseDirectionRequirement();
     direction_ase_requriement.aseConfiguration.codecId = CodecId::Core::LC3;
     direction_ase_requriement.aseConfiguration.targetLatency =
         LeAudioAseConfiguration::TargetLatency::BALANCED_LATENCY_RELIABILITY;
 
-    // Mismatch sampling frequency
     direction_ase_requriement.aseConfiguration.codecConfiguration = {
-        CodecSpecificConfigurationLtv::SamplingFrequency::HZ11025,
-        CodecSpecificConfigurationLtv::FrameDuration::US7500,
+        freq, CodecSpecificConfigurationLtv::FrameDuration::US10000, allocation
+
     };
+    if (is_sink_requirement)
+      requirement.sinkAseRequirement = {direction_ase_requriement};
+
     if (is_source_requriement)
       requirement.sourceAseRequirement = {direction_ase_requriement};
-    else
-      requirement.sinkAseRequirement = {direction_ase_requriement};
+
     return requirement;
   }
 
+  LeAudioConfigurationRequirement GetUnicastGameRequirement(bool asymmetric) {
+    // Create a requirements
+    LeAudioConfigurationRequirement requirement;
+    requirement.audioContext = GetAudioContext(AudioContext::GAME);
+
+    auto allocation = CodecSpecificConfigurationLtv::AudioChannelAllocation();
+    allocation.bitmask =
+        CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_LEFT |
+        CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_RIGHT;
+
+    auto sink_ase_requriement = AseDirectionRequirement();
+    sink_ase_requriement.aseConfiguration.codecId = CodecId::Core::LC3;
+    sink_ase_requriement.aseConfiguration.targetLatency =
+        LeAudioAseConfiguration::TargetLatency::BALANCED_LATENCY_RELIABILITY;
+
+    sink_ase_requriement.aseConfiguration.codecConfiguration = {
+        CodecSpecificConfigurationLtv::SamplingFrequency::HZ16000,
+        CodecSpecificConfigurationLtv::FrameDuration::US10000, allocation};
+
+    auto source_ase_requriement = AseDirectionRequirement();
+    source_ase_requriement.aseConfiguration.codecId = CodecId::Core::LC3;
+    source_ase_requriement.aseConfiguration.targetLatency =
+        LeAudioAseConfiguration::TargetLatency::BALANCED_LATENCY_RELIABILITY;
+
+    if (asymmetric) {
+      source_ase_requriement.aseConfiguration.codecConfiguration = {
+          CodecSpecificConfigurationLtv::SamplingFrequency::HZ8000,
+          CodecSpecificConfigurationLtv::FrameDuration::US10000, allocation};
+    } else {
+      source_ase_requriement.aseConfiguration.codecConfiguration = {
+          CodecSpecificConfigurationLtv::SamplingFrequency::HZ16000,
+          CodecSpecificConfigurationLtv::FrameDuration::US10000, allocation};
+    }
+
+    requirement.sinkAseRequirement = {sink_ase_requriement};
+    requirement.sourceAseRequirement = {source_ase_requriement};
+
+    return requirement;
+  }
+
+  LeAudioAseQosConfigurationRequirement GetQosRequirements(
+      bool is_sink_requirement, bool is_source_requriement, bool valid = true) {
+    LeAudioAseQosConfigurationRequirement qosRequirement;
+
+    auto allocation = CodecSpecificConfigurationLtv::AudioChannelAllocation();
+    allocation.bitmask =
+        CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_LEFT |
+        CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_RIGHT;
+
+    AseQosDirectionRequirement directionalRequirement = {
+        .framing = IBluetoothAudioProvider::Framing::UNFRAMED,
+        .preferredRetransmissionNum = 2,
+        .maxTransportLatencyMs = 10,
+        .presentationDelayMinUs = 40000,
+        .presentationDelayMaxUs = 40000,
+        .aseConfiguration =
+            {
+                .targetLatency = LeAudioAseConfiguration::TargetLatency::
+                    BALANCED_LATENCY_RELIABILITY,
+                .codecId = CodecId::Core::LC3,
+                .codecConfiguration =
+                    {CodecSpecificConfigurationLtv::SamplingFrequency::HZ16000,
+                     CodecSpecificConfigurationLtv::FrameDuration::US10000,
+                     allocation},
+            },
+    };
+
+    if (!valid) {
+      // clear some required values;
+      directionalRequirement.maxTransportLatencyMs = 0;
+      directionalRequirement.presentationDelayMaxUs = 0;
+    }
+
+    qosRequirement.sinkAseQosRequirement = directionalRequirement;
+    if (is_source_requriement && is_sink_requirement) {
+      qosRequirement.sourceAseQosRequirement = directionalRequirement;
+      qosRequirement.sinkAseQosRequirement = directionalRequirement;
+    } else if (is_source_requriement) {
+      qosRequirement.sourceAseQosRequirement = directionalRequirement;
+      qosRequirement.sinkAseQosRequirement = std::nullopt;
+    } else if (is_sink_requirement) {
+      qosRequirement.sourceAseQosRequirement = std::nullopt;
+      qosRequirement.sinkAseQosRequirement = directionalRequirement;
+    }
+
+    return qosRequirement;
+  }
+
   std::vector<Lc3Configuration> GetUnicastLc3SupportedList(bool decoding,
                                                            bool supported) {
     std::vector<Lc3Configuration> le_audio_codec_configs;
@@ -2460,6 +2874,11 @@
       AudioContext::NOTIFICATIONS, AudioContext::RINGTONE_ALERTS,
       AudioContext::ALERTS,        AudioContext::EMERGENCY_ALARM,
   };
+
+  AudioContext bidirectional_contexts = {
+      .bitmask = AudioContext::CONVERSATIONAL | AudioContext::GAME |
+                 AudioContext::VOICE_ASSISTANTS | AudioContext::LIVE_AUDIO,
+  };
 };
 
 /**
@@ -2511,6 +2930,40 @@
       BluetoothAudioHalVersion::VERSION_AIDL_V4) {
     GTEST_SKIP();
   }
+
+  if (IsMultidirectionalCapabilitiesEnabled()) {
+    GTEST_SKIP();
+  }
+
+  std::vector<std::optional<LeAudioDeviceCapabilities>> empty_capability;
+  std::vector<LeAudioConfigurationRequirement> empty_requirement;
+  std::vector<LeAudioAseConfigurationSetting> configurations;
+
+  // Check empty capability for source direction
+  auto aidl_retval = audio_provider_->getLeAudioAseConfiguration(
+      std::nullopt, empty_capability, empty_requirement, &configurations);
+
+  ASSERT_FALSE(aidl_retval.isOk());
+
+  // Check empty capability for sink direction
+  aidl_retval = audio_provider_->getLeAudioAseConfiguration(
+      empty_capability, std::nullopt, empty_requirement, &configurations);
+
+  ASSERT_TRUE(aidl_retval.isOk());
+  ASSERT_TRUE(configurations.empty());
+}
+
+TEST_P(BluetoothAudioProviderLeAudioOutputHardwareAidl,
+       GetEmptyAseConfigurationEmptyCapability_Multidirectiona) {
+  if (GetProviderFactoryInterfaceVersion() <
+      BluetoothAudioHalVersion::VERSION_AIDL_V4) {
+    GTEST_SKIP();
+  }
+
+  if (!IsMultidirectionalCapabilitiesEnabled()) {
+    GTEST_SKIP();
+  }
+
   std::vector<std::optional<LeAudioDeviceCapabilities>> empty_capability;
   std::vector<LeAudioConfigurationRequirement> empty_requirement;
   std::vector<LeAudioAseConfigurationSetting> configurations;
@@ -2536,50 +2989,388 @@
       BluetoothAudioHalVersion::VERSION_AIDL_V4) {
     GTEST_SKIP();
   }
-  std::vector<std::optional<LeAudioDeviceCapabilities>> capabilities = {
-      GetDefaultRemoteCapability()};
+  std::vector<std::optional<LeAudioDeviceCapabilities>> sink_capabilities = {
+      GetDefaultRemoteSinkCapability()};
+  std::vector<std::optional<LeAudioDeviceCapabilities>> source_capabilities = {
+      GetDefaultRemoteSourceCapability()};
+
+  auto not_supported_sampling_rate_by_remote =
+      CodecSpecificConfigurationLtv::SamplingFrequency::HZ11025;
 
   // Check empty capability for source direction
   std::vector<LeAudioAseConfigurationSetting> configurations;
   std::vector<LeAudioConfigurationRequirement> source_requirements = {
-      GetDefaultRequirement(true)};
+      GetUnicastDefaultRequirement(AudioContext::LIVE_AUDIO, false /*sink */,
+                                   true /* source */,
+                                   not_supported_sampling_rate_by_remote)};
   auto aidl_retval = audio_provider_->getLeAudioAseConfiguration(
-      std::nullopt, capabilities, source_requirements, &configurations);
+      std::nullopt, source_capabilities, source_requirements, &configurations);
 
   ASSERT_TRUE(aidl_retval.isOk());
   ASSERT_TRUE(configurations.empty());
 
   // Check empty capability for sink direction
   std::vector<LeAudioConfigurationRequirement> sink_requirements = {
-      GetDefaultRequirement(false)};
+      GetUnicastDefaultRequirement(AudioContext::MEDIA, true /*sink */,
+                                   false /* source */,
+                                   not_supported_sampling_rate_by_remote)};
   aidl_retval = audio_provider_->getLeAudioAseConfiguration(
-      capabilities, std::nullopt, source_requirements, &configurations);
+      sink_capabilities, std::nullopt, sink_requirements, &configurations);
 
   ASSERT_TRUE(aidl_retval.isOk());
   ASSERT_TRUE(configurations.empty());
 }
 
+TEST_P(BluetoothAudioProviderLeAudioOutputHardwareAidl, GetAseConfiguration) {
+  if (GetProviderFactoryInterfaceVersion() <
+      BluetoothAudioHalVersion::VERSION_AIDL_V4) {
+    GTEST_SKIP();
+  }
+
+  if (IsMultidirectionalCapabilitiesEnabled()) {
+    GTEST_SKIP();
+  }
+
+  std::vector<std::optional<LeAudioDeviceCapabilities>> sink_capabilities = {
+      GetDefaultRemoteSinkCapability()};
+  std::vector<std::optional<LeAudioDeviceCapabilities>> source_capabilities = {
+      GetDefaultRemoteSourceCapability()};
+
+  // Should not ask for Source on ENCODING session if Multidiretional not
+  // supported
+  std::vector<LeAudioAseConfigurationSetting> configurations;
+  std::vector<LeAudioConfigurationRequirement> source_requirements = {
+      GetUnicastDefaultRequirement(AudioContext::LIVE_AUDIO, false /* sink */,
+                                   true /* source */)};
+  auto aidl_retval = audio_provider_->getLeAudioAseConfiguration(
+      std::nullopt, source_capabilities, source_requirements, &configurations);
+
+  ASSERT_FALSE(aidl_retval.isOk());
+  ASSERT_TRUE(configurations.empty());
+
+  // Check capability for remote sink direction
+  std::vector<LeAudioConfigurationRequirement> sink_requirements = {
+      GetUnicastDefaultRequirement(AudioContext::MEDIA, true /* sink */,
+                                   false /* source */)};
+  aidl_retval = audio_provider_->getLeAudioAseConfiguration(
+      sink_capabilities, std::nullopt, sink_requirements, &configurations);
+
+  ASSERT_TRUE(aidl_retval.isOk());
+  ASSERT_FALSE(configurations.empty());
+  VerifyIfRequirementsSatisfied(sink_requirements, configurations);
+
+  // Check multiple capability for remote sink direction
+  std::vector<LeAudioConfigurationRequirement> multi_sink_requirements = {
+      GetUnicastDefaultRequirement(AudioContext::MEDIA, true /* sink */,
+                                   false /* source */),
+      GetUnicastDefaultRequirement(AudioContext::CONVERSATIONAL,
+                                   true /* sink */, false /* source */)};
+  aidl_retval = audio_provider_->getLeAudioAseConfiguration(
+      sink_capabilities, std::nullopt, multi_sink_requirements,
+      &configurations);
+
+  ASSERT_TRUE(aidl_retval.isOk());
+  ASSERT_FALSE(configurations.empty());
+  VerifyIfRequirementsSatisfied(multi_sink_requirements, configurations);
+
+  // Check multiple context types in a single requirement.
+  std::vector<LeAudioConfigurationRequirement> multi_context_sink_requirements =
+      {GetUnicastDefaultRequirement(
+          AudioContext::MEDIA | AudioContext::SOUND_EFFECTS, true /* sink */,
+          false /* source */)};
+  aidl_retval = audio_provider_->getLeAudioAseConfiguration(
+      sink_capabilities, std::nullopt, multi_context_sink_requirements,
+      &configurations);
+
+  ASSERT_TRUE(aidl_retval.isOk());
+  ASSERT_FALSE(configurations.empty());
+  VerifyIfRequirementsSatisfied(multi_sink_requirements, configurations);
+}
+
+TEST_P(BluetoothAudioProviderLeAudioOutputHardwareAidl,
+       GetAseConfiguration_Multidirectional) {
+  if (GetProviderFactoryInterfaceVersion() <
+      BluetoothAudioHalVersion::VERSION_AIDL_V4) {
+    GTEST_SKIP();
+  }
+
+  if (!IsMultidirectionalCapabilitiesEnabled()) {
+    GTEST_SKIP();
+  }
+
+  std::vector<std::optional<LeAudioDeviceCapabilities>> sink_capabilities = {
+      GetDefaultRemoteSinkCapability()};
+  std::vector<std::optional<LeAudioDeviceCapabilities>> source_capabilities = {
+      GetDefaultRemoteSourceCapability()};
+
+  // Verify source configuration is received
+  std::vector<LeAudioAseConfigurationSetting> configurations;
+  std::vector<LeAudioConfigurationRequirement> source_requirements = {
+      GetUnicastDefaultRequirement(AudioContext::LIVE_AUDIO, false /* sink */,
+                                   true /* source */)};
+  auto aidl_retval = audio_provider_->getLeAudioAseConfiguration(
+      std::nullopt, source_capabilities, source_requirements, &configurations);
+
+  ASSERT_TRUE(aidl_retval.isOk());
+  ASSERT_FALSE(configurations.empty());
+  VerifyIfRequirementsSatisfied(source_requirements, configurations);
+
+  // Verify sink configuration is received
+  std::vector<LeAudioConfigurationRequirement> sink_requirements = {
+      GetUnicastDefaultRequirement(AudioContext::MEDIA, true /* sink */,
+                                   false /* source */)};
+  aidl_retval = audio_provider_->getLeAudioAseConfiguration(
+      sink_capabilities, std::nullopt, sink_requirements, &configurations);
+
+  ASSERT_TRUE(aidl_retval.isOk());
+  ASSERT_FALSE(configurations.empty());
+  VerifyIfRequirementsSatisfied(sink_requirements, configurations);
+
+  std::vector<LeAudioConfigurationRequirement> combined_requirements = {
+      GetUnicastDefaultRequirement(AudioContext::LIVE_AUDIO, false /* sink */,
+                                   true /* source */),
+      GetUnicastDefaultRequirement(AudioContext::CONVERSATIONAL,
+                                   true /* sink */, true /* source */),
+      GetUnicastDefaultRequirement(AudioContext::MEDIA, true /* sink */,
+                                   false /* source */)};
+
+  aidl_retval = audio_provider_->getLeAudioAseConfiguration(
+      sink_capabilities, source_capabilities, combined_requirements,
+      &configurations);
+
+  ASSERT_TRUE(aidl_retval.isOk());
+  ASSERT_FALSE(configurations.empty());
+  VerifyIfRequirementsSatisfied(combined_requirements, configurations);
+}
+
+TEST_P(BluetoothAudioProviderLeAudioOutputHardwareAidl,
+       GetAsymmetricAseConfiguration_Multidirectional) {
+  if (GetProviderFactoryInterfaceVersion() <
+      BluetoothAudioHalVersion::VERSION_AIDL_V4) {
+    GTEST_SKIP();
+  }
+
+  if (!IsMultidirectionalCapabilitiesEnabled()) {
+    GTEST_SKIP();
+  }
+
+  if (!IsAsymmetricConfigurationAllowed()) {
+    GTEST_SKIP();
+  }
+
+  std::vector<LeAudioAseConfigurationSetting> configurations;
+  std::vector<std::optional<LeAudioDeviceCapabilities>> sink_capabilities = {
+      GetDefaultRemoteSinkCapability()};
+  std::vector<std::optional<LeAudioDeviceCapabilities>> source_capabilities = {
+      GetDefaultRemoteSourceCapability()};
+
+  std::vector<LeAudioConfigurationRequirement> asymmetric_requirements = {
+      GetUnicastGameRequirement(true /* Asymmetric */)};
+
+  auto aidl_retval = audio_provider_->getLeAudioAseConfiguration(
+      sink_capabilities, source_capabilities, asymmetric_requirements,
+      &configurations);
+
+  ASSERT_TRUE(aidl_retval.isOk());
+  ASSERT_FALSE(configurations.empty());
+  VerifyIfRequirementsSatisfied(asymmetric_requirements, configurations);
+}
+
+TEST_P(BluetoothAudioProviderLeAudioOutputHardwareAidl,
+       GetQoSConfiguration_Multidirectional) {
+  if (GetProviderFactoryInterfaceVersion() <
+      BluetoothAudioHalVersion::VERSION_AIDL_V4) {
+    GTEST_SKIP();
+  }
+
+  if (!IsMultidirectionalCapabilitiesEnabled()) {
+    GTEST_SKIP();
+  }
+
+  auto allocation = CodecSpecificConfigurationLtv::AudioChannelAllocation();
+  allocation.bitmask =
+      CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_LEFT |
+      CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_RIGHT;
+
+  LeAudioAseQosConfigurationRequirement requirement =
+      GetQosRequirements(true, true);
+
+  std::vector<IBluetoothAudioProvider::LeAudioAseQosConfiguration>
+      QoSConfigurations;
+  bool is_supported = false;
+  for (auto bitmask : all_context_bitmasks) {
+    requirement.audioContext = GetAudioContext(bitmask);
+    bool is_bidirectional = bidirectional_contexts.bitmask & bitmask;
+
+    if (is_bidirectional) {
+      requirement.sourceAseQosRequirement = requirement.sinkAseQosRequirement;
+    } else {
+      requirement.sourceAseQosRequirement = std::nullopt;
+    }
+
+    IBluetoothAudioProvider::LeAudioAseQosConfigurationPair result;
+    auto aidl_retval =
+        audio_provider_->getLeAudioAseQosConfiguration(requirement, &result);
+    if (!aidl_retval.isOk()) {
+      // If not OK, then it could be not supported, as it is an optional
+      // feature
+      ASSERT_EQ(aidl_retval.getExceptionCode(), EX_UNSUPPORTED_OPERATION);
+    }
+
+    is_supported = true;
+    if (result.sinkQosConfiguration.has_value()) {
+      if (is_bidirectional) {
+        ASSERT_TRUE(result.sourceQosConfiguration.has_value());
+      } else {
+        ASSERT_FALSE(result.sourceQosConfiguration.has_value());
+      }
+      QoSConfigurations.push_back(result.sinkQosConfiguration.value());
+    }
+  }
+  if (is_supported) {
+    // QoS Configurations should not be empty, as we searched for all contexts
+    ASSERT_FALSE(QoSConfigurations.empty());
+  }
+}
+
+TEST_P(BluetoothAudioProviderLeAudioOutputHardwareAidl,
+       GetQoSConfiguration_InvalidRequirements) {
+  if (GetProviderFactoryInterfaceVersion() <
+      BluetoothAudioHalVersion::VERSION_AIDL_V4) {
+    GTEST_SKIP();
+  }
+  auto allocation = CodecSpecificConfigurationLtv::AudioChannelAllocation();
+  allocation.bitmask =
+      CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_LEFT |
+      CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_RIGHT;
+
+  LeAudioAseQosConfigurationRequirement invalid_requirement =
+      GetQosRequirements(true /* sink */, false /* source */,
+                         false /* valid */);
+
+  std::vector<IBluetoothAudioProvider::LeAudioAseQosConfiguration>
+      QoSConfigurations;
+  for (auto bitmask : all_context_bitmasks) {
+    invalid_requirement.audioContext = GetAudioContext(bitmask);
+    IBluetoothAudioProvider::LeAudioAseQosConfigurationPair result;
+    auto aidl_retval = audio_provider_->getLeAudioAseQosConfiguration(
+        invalid_requirement, &result);
+    ASSERT_FALSE(aidl_retval.isOk());
+  }
+}
+
 TEST_P(BluetoothAudioProviderLeAudioOutputHardwareAidl, GetQoSConfiguration) {
   if (GetProviderFactoryInterfaceVersion() <
       BluetoothAudioHalVersion::VERSION_AIDL_V4) {
     GTEST_SKIP();
   }
+  auto allocation = CodecSpecificConfigurationLtv::AudioChannelAllocation();
+  allocation.bitmask =
+      CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_LEFT |
+      CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_RIGHT;
+
   IBluetoothAudioProvider::LeAudioAseQosConfigurationRequirement requirement;
+  requirement = GetQosRequirements(true /* sink */, false /* source */);
+
   std::vector<IBluetoothAudioProvider::LeAudioAseQosConfiguration>
       QoSConfigurations;
+  bool is_supported = false;
   for (auto bitmask : all_context_bitmasks) {
     requirement.audioContext = GetAudioContext(bitmask);
     IBluetoothAudioProvider::LeAudioAseQosConfigurationPair result;
     auto aidl_retval =
         audio_provider_->getLeAudioAseQosConfiguration(requirement, &result);
-    ASSERT_TRUE(aidl_retval.isOk());
-    if (result.sinkQosConfiguration.has_value())
-      QoSConfigurations.push_back(result.sinkQosConfiguration.value());
-    if (result.sourceQosConfiguration.has_value())
-      QoSConfigurations.push_back(result.sourceQosConfiguration.value());
+    if (!aidl_retval.isOk()) {
+      // If not OK, then it could be not supported, as it is an optional
+      // feature
+      ASSERT_EQ(aidl_retval.getExceptionCode(), EX_UNSUPPORTED_OPERATION);
+    } else {
+      is_supported = true;
+      if (result.sinkQosConfiguration.has_value()) {
+        QoSConfigurations.push_back(result.sinkQosConfiguration.value());
+      }
+    }
   }
-  // QoS Configurations should not be empty, as we searched for all contexts
-  ASSERT_FALSE(QoSConfigurations.empty());
+
+  if (is_supported) {
+    // QoS Configurations should not be empty, as we searched for all contexts
+    ASSERT_FALSE(QoSConfigurations.empty());
+  }
+}
+
+TEST_P(BluetoothAudioProviderLeAudioOutputHardwareAidl,
+       GetDataPathConfiguration_Multidirectional) {
+  IBluetoothAudioProvider::StreamConfig sink_requirement;
+  IBluetoothAudioProvider::StreamConfig source_requirement;
+  std::vector<IBluetoothAudioProvider::LeAudioDataPathConfiguration>
+      DataPathConfigurations;
+
+  if (!IsMultidirectionalCapabilitiesEnabled()) {
+    GTEST_SKIP();
+  }
+
+  bool is_supported = false;
+  auto allocation = CodecSpecificConfigurationLtv::AudioChannelAllocation();
+  allocation.bitmask =
+      CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_LEFT |
+      CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_RIGHT;
+
+  auto streamMap = LeAudioConfiguration::StreamMap();
+
+  // Use some mandatory configuration
+  streamMap.streamHandle = 0x0001;
+  streamMap.audioChannelAllocation = 0x03;
+  streamMap.aseConfiguration = {
+      .targetLatency =
+          LeAudioAseConfiguration::TargetLatency::BALANCED_LATENCY_RELIABILITY,
+      .codecId = CodecId::Core::LC3,
+      .codecConfiguration =
+          {CodecSpecificConfigurationLtv::SamplingFrequency::HZ16000,
+           CodecSpecificConfigurationLtv::FrameDuration::US10000, allocation},
+  };
+
+  // Bidirectional
+  sink_requirement.streamMap = {streamMap};
+  source_requirement.streamMap = {streamMap};
+
+  for (auto bitmask : all_context_bitmasks) {
+    sink_requirement.audioContext = GetAudioContext(bitmask);
+    source_requirement.audioContext = sink_requirement.audioContext;
+
+    IBluetoothAudioProvider::LeAudioDataPathConfigurationPair result;
+    ::ndk::ScopedAStatus aidl_retval;
+
+    bool is_bidirectional = bidirectional_contexts.bitmask & bitmask;
+    if (is_bidirectional) {
+      aidl_retval = audio_provider_->getLeAudioAseDatapathConfiguration(
+          sink_requirement, source_requirement, &result);
+    } else {
+      aidl_retval = audio_provider_->getLeAudioAseDatapathConfiguration(
+          sink_requirement, std::nullopt, &result);
+    }
+
+    if (!aidl_retval.isOk()) {
+      // If not OK, then it could be not supported, as it is an optional
+      // feature
+      ASSERT_EQ(aidl_retval.getExceptionCode(), EX_UNSUPPORTED_OPERATION);
+    } else {
+      is_supported = true;
+      if (result.outputConfig.has_value()) {
+        if (is_bidirectional) {
+          ASSERT_TRUE(result.inputConfig.has_value());
+        } else {
+          ASSERT_TRUE(!result.inputConfig.has_value());
+        }
+        DataPathConfigurations.push_back(result.outputConfig.value());
+      }
+    }
+  }
+
+  if (is_supported) {
+    // Datapath Configurations should not be empty, as we searched for all
+    // contexts
+    ASSERT_FALSE(DataPathConfigurations.empty());
+  }
 }
 
 TEST_P(BluetoothAudioProviderLeAudioOutputHardwareAidl,
@@ -2589,26 +3380,45 @@
     GTEST_SKIP();
   }
   IBluetoothAudioProvider::StreamConfig sink_requirement;
-  IBluetoothAudioProvider::StreamConfig source_requirement;
   std::vector<IBluetoothAudioProvider::LeAudioDataPathConfiguration>
       DataPathConfigurations;
   bool is_supported = false;
+  auto allocation = CodecSpecificConfigurationLtv::AudioChannelAllocation();
+  allocation.bitmask =
+      CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_LEFT |
+      CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_RIGHT;
+
+  auto streamMap = LeAudioConfiguration::StreamMap();
+
+  // Use some mandatory configuration
+  streamMap.streamHandle = 0x0001;
+  streamMap.audioChannelAllocation = 0x03;
+  streamMap.aseConfiguration = {
+      .targetLatency =
+          LeAudioAseConfiguration::TargetLatency::BALANCED_LATENCY_RELIABILITY,
+      .codecId = CodecId::Core::LC3,
+      .codecConfiguration =
+          {CodecSpecificConfigurationLtv::SamplingFrequency::HZ16000,
+           CodecSpecificConfigurationLtv::FrameDuration::US10000, allocation},
+  };
+
+  sink_requirement.streamMap = {streamMap};
 
   for (auto bitmask : all_context_bitmasks) {
     sink_requirement.audioContext = GetAudioContext(bitmask);
-    source_requirement.audioContext = GetAudioContext(bitmask);
     IBluetoothAudioProvider::LeAudioDataPathConfigurationPair result;
     auto aidl_retval = audio_provider_->getLeAudioAseDatapathConfiguration(
-        sink_requirement, source_requirement, &result);
+        sink_requirement, std::nullopt, &result);
+
     if (!aidl_retval.isOk()) {
-      // If not OK, then it could be not supported, as it is an optional feature
+      // If not OK, then it could be not supported, as it is an optional
+      // feature
       ASSERT_EQ(aidl_retval.getExceptionCode(), EX_UNSUPPORTED_OPERATION);
     } else {
       is_supported = true;
-      if (result.inputConfig.has_value())
-        DataPathConfigurations.push_back(result.inputConfig.value());
-      if (result.inputConfig.has_value())
-        DataPathConfigurations.push_back(result.inputConfig.value());
+      if (result.outputConfig.has_value()) {
+        DataPathConfigurations.push_back(result.outputConfig.value());
+      }
     }
   }
 
@@ -2655,10 +3465,9 @@
  * SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be started and
  * stopped with Unicast hardware encoding config
  *
- * Disabled since offload codec checking is not ready
  */
 TEST_P(BluetoothAudioProviderLeAudioOutputHardwareAidl,
-       DISABLED_StartAndEndLeAudioOutputSessionWithInvalidAudioConfiguration) {
+       StartAndEndLeAudioOutputSessionWithInvalidAudioConfiguration) {
   if (!IsOffloadOutputSupported()) {
     GTEST_SKIP();
   }
@@ -2678,8 +3487,8 @@
         audio_port_, AudioConfiguration(le_audio_config), latency_modes,
         &mq_desc);
 
-    // AIDL call should fail on invalid codec
-    ASSERT_FALSE(aidl_retval.isOk());
+    // It is OK to start session with invalid configuration
+    ASSERT_TRUE(aidl_retval.isOk());
     EXPECT_TRUE(audio_provider_->endSession().isOk());
   }
 }
@@ -2758,8 +3567,8 @@
           audio_port_, AudioConfiguration(le_audio_config), latency_modes,
           &mq_desc);
 
-      // AIDL call should fail on invalid codec
-      ASSERT_FALSE(aidl_retval.isOk());
+      // It is OK to start session with invalid configuration
+      ASSERT_TRUE(aidl_retval.isOk());
       EXPECT_TRUE(audio_provider_->endSession().isOk());
     }
   }
@@ -2879,10 +3688,9 @@
  * SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH can be started and
  * stopped with Unicast hardware encoding config
  *
- * Disabled since offload codec checking is not ready
  */
 TEST_P(BluetoothAudioProviderLeAudioInputHardwareAidl,
-       DISABLED_StartAndEndLeAudioInputSessionWithInvalidAudioConfiguration) {
+       StartAndEndLeAudioInputSessionWithInvalidAudioConfiguration) {
   if (!IsOffloadInputSupported()) {
     GTEST_SKIP();
   }
@@ -2903,12 +3711,229 @@
         audio_port_, AudioConfiguration(le_audio_config), latency_modes,
         &mq_desc);
 
-    // AIDL call should fail on invalid codec
-    ASSERT_FALSE(aidl_retval.isOk());
+    // It is OK to start with invalid configuration as it might be unknown on
+    // start
+    ASSERT_TRUE(aidl_retval.isOk());
     EXPECT_TRUE(audio_provider_->endSession().isOk());
   }
 }
 
+TEST_P(BluetoothAudioProviderLeAudioInputHardwareAidl,
+       GetEmptyAseConfigurationEmptyCapability) {
+  if (GetProviderFactoryInterfaceVersion() <
+      BluetoothAudioHalVersion::VERSION_AIDL_V4) {
+    GTEST_SKIP();
+  }
+
+  if (IsMultidirectionalCapabilitiesEnabled()) {
+    GTEST_SKIP();
+  }
+
+  std::vector<std::optional<LeAudioDeviceCapabilities>> empty_capability;
+  std::vector<LeAudioConfigurationRequirement> empty_requirement;
+  std::vector<LeAudioAseConfigurationSetting> configurations;
+
+  // Check success for source direction (Input == DecodingSession == remote
+  // source)
+  auto aidl_retval = audio_provider_->getLeAudioAseConfiguration(
+      std::nullopt, empty_capability, empty_requirement, &configurations);
+
+  ASSERT_TRUE(aidl_retval.isOk());
+  ASSERT_TRUE(configurations.empty());
+
+  // Check failure for sink direction
+  aidl_retval = audio_provider_->getLeAudioAseConfiguration(
+      empty_capability, std::nullopt, empty_requirement, &configurations);
+
+  ASSERT_FALSE(aidl_retval.isOk());
+}
+
+TEST_P(BluetoothAudioProviderLeAudioInputHardwareAidl,
+       GetEmptyAseConfigurationEmptyCapability_Multidirectional) {
+  if (GetProviderFactoryInterfaceVersion() <
+      BluetoothAudioHalVersion::VERSION_AIDL_V4) {
+    GTEST_SKIP();
+  }
+
+  if (!IsMultidirectionalCapabilitiesEnabled()) {
+    GTEST_SKIP();
+  }
+
+  std::vector<std::optional<LeAudioDeviceCapabilities>> empty_capability;
+  std::vector<LeAudioConfigurationRequirement> empty_requirement;
+  std::vector<LeAudioAseConfigurationSetting> configurations;
+
+  // Check empty capability for source direction
+  auto aidl_retval = audio_provider_->getLeAudioAseConfiguration(
+      std::nullopt, empty_capability, empty_requirement, &configurations);
+
+  ASSERT_TRUE(aidl_retval.isOk());
+  ASSERT_TRUE(configurations.empty());
+
+  // Check empty capability for sink direction
+  aidl_retval = audio_provider_->getLeAudioAseConfiguration(
+      empty_capability, std::nullopt, empty_requirement, &configurations);
+
+  ASSERT_TRUE(aidl_retval.isOk());
+  ASSERT_TRUE(configurations.empty());
+}
+
+TEST_P(BluetoothAudioProviderLeAudioInputHardwareAidl, GetAseConfiguration) {
+  if (GetProviderFactoryInterfaceVersion() <
+      BluetoothAudioHalVersion::VERSION_AIDL_V4) {
+    GTEST_SKIP();
+  }
+
+  if (IsMultidirectionalCapabilitiesEnabled()) {
+    GTEST_SKIP();
+  }
+
+  std::vector<std::optional<LeAudioDeviceCapabilities>> sink_capabilities = {
+      GetDefaultRemoteSinkCapability()};
+  std::vector<std::optional<LeAudioDeviceCapabilities>> source_capabilities = {
+      GetDefaultRemoteSourceCapability()};
+
+  // Check source configuration is received
+  std::vector<LeAudioAseConfigurationSetting> configurations;
+  std::vector<LeAudioConfigurationRequirement> source_requirements = {
+      GetUnicastDefaultRequirement(AudioContext::LIVE_AUDIO, false /* sink */,
+                                   true /* source */)};
+  auto aidl_retval = audio_provider_->getLeAudioAseConfiguration(
+      std::nullopt, source_capabilities, source_requirements, &configurations);
+
+  ASSERT_TRUE(aidl_retval.isOk());
+  ASSERT_FALSE(configurations.empty());
+
+  // Check error result when requesting sink on DECODING session
+  std::vector<LeAudioConfigurationRequirement> sink_requirements = {
+      GetUnicastDefaultRequirement(AudioContext::MEDIA, true /* sink */,
+                                   false /* source */)};
+  aidl_retval = audio_provider_->getLeAudioAseConfiguration(
+      sink_capabilities, std::nullopt, sink_requirements, &configurations);
+
+  ASSERT_FALSE(aidl_retval.isOk());
+}
+
+TEST_P(BluetoothAudioProviderLeAudioInputHardwareAidl,
+       GetAseConfiguration_Multidirectional) {
+  if (GetProviderFactoryInterfaceVersion() <
+      BluetoothAudioHalVersion::VERSION_AIDL_V4) {
+    GTEST_SKIP();
+  }
+
+  if (!IsMultidirectionalCapabilitiesEnabled()) {
+    GTEST_SKIP();
+  }
+
+  std::vector<std::optional<LeAudioDeviceCapabilities>> sink_capabilities = {
+      GetDefaultRemoteSinkCapability()};
+  std::vector<std::optional<LeAudioDeviceCapabilities>> source_capabilities = {
+      GetDefaultRemoteSourceCapability()};
+
+  // Check source configuration is received
+  std::vector<LeAudioAseConfigurationSetting> configurations;
+  std::vector<LeAudioConfigurationRequirement> source_requirements = {
+      GetUnicastDefaultRequirement(AudioContext::LIVE_AUDIO, false /* sink */,
+                                   true /* source */)};
+  auto aidl_retval = audio_provider_->getLeAudioAseConfiguration(
+      std::nullopt, source_capabilities, source_requirements, &configurations);
+
+  ASSERT_TRUE(aidl_retval.isOk());
+  ASSERT_FALSE(configurations.empty());
+  VerifyIfRequirementsSatisfied(source_requirements, configurations);
+
+  // Check empty capability for sink direction
+  std::vector<LeAudioConfigurationRequirement> sink_requirements = {
+      GetUnicastDefaultRequirement(AudioContext::MEDIA, true /* sink */,
+                                   false /* source */)};
+  aidl_retval = audio_provider_->getLeAudioAseConfiguration(
+      sink_capabilities, std::nullopt, sink_requirements, &configurations);
+
+  ASSERT_TRUE(aidl_retval.isOk());
+  ASSERT_FALSE(configurations.empty());
+  VerifyIfRequirementsSatisfied(sink_requirements, configurations);
+
+  std::vector<LeAudioConfigurationRequirement> combined_requirements = {
+      GetUnicastDefaultRequirement(AudioContext::LIVE_AUDIO, false /* sink */,
+                                   true /* source */),
+      GetUnicastDefaultRequirement(AudioContext::CONVERSATIONAL,
+                                   true /* sink */, true /* source */),
+      GetUnicastDefaultRequirement(AudioContext::MEDIA, true /* sink */,
+                                   false /* source */)};
+
+  aidl_retval = audio_provider_->getLeAudioAseConfiguration(
+      sink_capabilities, source_capabilities, combined_requirements,
+      &configurations);
+
+  ASSERT_TRUE(aidl_retval.isOk());
+  ASSERT_FALSE(configurations.empty());
+  VerifyIfRequirementsSatisfied(combined_requirements, configurations);
+}
+
+TEST_P(BluetoothAudioProviderLeAudioInputHardwareAidl,
+       GetQoSConfiguration_InvalidRequirements) {
+  if (GetProviderFactoryInterfaceVersion() <
+      BluetoothAudioHalVersion::VERSION_AIDL_V4) {
+    GTEST_SKIP();
+  }
+  auto allocation = CodecSpecificConfigurationLtv::AudioChannelAllocation();
+  allocation.bitmask =
+      CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_LEFT |
+      CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_RIGHT;
+
+  LeAudioAseQosConfigurationRequirement invalid_requirement =
+      GetQosRequirements(false /* sink */, true /* source */,
+                         false /* valid */);
+
+  std::vector<IBluetoothAudioProvider::LeAudioAseQosConfiguration>
+      QoSConfigurations;
+  for (auto bitmask : all_context_bitmasks) {
+    invalid_requirement.audioContext = GetAudioContext(bitmask);
+    IBluetoothAudioProvider::LeAudioAseQosConfigurationPair result;
+    auto aidl_retval = audio_provider_->getLeAudioAseQosConfiguration(
+        invalid_requirement, &result);
+    ASSERT_FALSE(aidl_retval.isOk());
+  }
+}
+
+TEST_P(BluetoothAudioProviderLeAudioInputHardwareAidl, GetQoSConfiguration) {
+  if (GetProviderFactoryInterfaceVersion() <
+      BluetoothAudioHalVersion::VERSION_AIDL_V4) {
+    GTEST_SKIP();
+  }
+  auto allocation = CodecSpecificConfigurationLtv::AudioChannelAllocation();
+  allocation.bitmask =
+      CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_LEFT |
+      CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_RIGHT;
+
+  IBluetoothAudioProvider::LeAudioAseQosConfigurationRequirement requirement;
+  requirement = GetQosRequirements(false /* sink */, true /* source */);
+
+  std::vector<IBluetoothAudioProvider::LeAudioAseQosConfiguration>
+      QoSConfigurations;
+  bool is_supported = false;
+  for (auto bitmask : all_context_bitmasks) {
+    requirement.audioContext = GetAudioContext(bitmask);
+    IBluetoothAudioProvider::LeAudioAseQosConfigurationPair result;
+    auto aidl_retval =
+        audio_provider_->getLeAudioAseQosConfiguration(requirement, &result);
+    if (!aidl_retval.isOk()) {
+      // If not OK, then it could be not supported, as it is an optional
+      // feature
+      ASSERT_EQ(aidl_retval.getExceptionCode(), EX_UNSUPPORTED_OPERATION);
+    } else {
+      is_supported = true;
+      if (result.sourceQosConfiguration.has_value()) {
+        QoSConfigurations.push_back(result.sourceQosConfiguration.value());
+      }
+    }
+  }
+
+  if (is_supported) {
+    // QoS Configurations should not be empty, as we searched for all contexts
+    ASSERT_FALSE(QoSConfigurations.empty());
+  }
+}
 /**
  * openProvider LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH
  */
@@ -3058,6 +4083,147 @@
     return le_audio_codec_configs;
   }
 
+  AudioContext GetAudioContext(int32_t bitmask) {
+    AudioContext media_audio_context;
+    media_audio_context.bitmask = bitmask;
+    return media_audio_context;
+  }
+
+  std::optional<CodecSpecificConfigurationLtv> GetConfigurationLtv(
+      const std::vector<CodecSpecificConfigurationLtv>& configurationLtvs,
+      CodecSpecificConfigurationLtv::Tag tag) {
+    for (const auto ltv : configurationLtvs) {
+      if (ltv.getTag() == tag) {
+        return ltv;
+      }
+    }
+    return std::nullopt;
+  }
+
+  std::optional<CodecSpecificConfigurationLtv::SamplingFrequency>
+  GetBisSampleFreq(const LeAudioBisConfiguration& bis_conf) {
+    auto sample_freq_ltv = GetConfigurationLtv(
+        bis_conf.codecConfiguration,
+        CodecSpecificConfigurationLtv::Tag::samplingFrequency);
+    if (!sample_freq_ltv) {
+      return std::nullopt;
+    }
+    return (*sample_freq_ltv)
+        .get<CodecSpecificConfigurationLtv::samplingFrequency>();
+  }
+
+  std::vector<CodecSpecificConfigurationLtv::SamplingFrequency>
+  GetSubgroupSampleFreqs(
+      const LeAudioBroadcastSubgroupConfiguration& subgroup_conf) {
+    std::vector<CodecSpecificConfigurationLtv::SamplingFrequency> result = {};
+
+    for (const auto& bis_conf : subgroup_conf.bisConfigurations) {
+      auto sample_freq = GetBisSampleFreq(bis_conf.bisConfiguration);
+      if (sample_freq) {
+        result.push_back(*sample_freq);
+      }
+    }
+    return result;
+  }
+
+  void VerifyBroadcastConfiguration(
+      const LeAudioBroadcastConfigurationRequirement& requirements,
+      const LeAudioBroadcastConfigurationSetting& configuration,
+      std::vector<CodecSpecificConfigurationLtv::SamplingFrequency>
+          expectedSampleFreqs = {}) {
+    std::vector<CodecSpecificConfigurationLtv::SamplingFrequency> sampleFreqs =
+        {};
+
+    int number_of_requested_bises = 0;
+    for (const auto& subgroup_req :
+         requirements.subgroupConfigurationRequirements) {
+      number_of_requested_bises += subgroup_req.bisNumPerSubgroup;
+    }
+
+    if (!expectedSampleFreqs.empty()) {
+      for (const auto& subgroup_conf : configuration.subgroupsConfigurations) {
+        auto result = GetSubgroupSampleFreqs(subgroup_conf);
+        sampleFreqs.insert(sampleFreqs.end(), result.begin(), result.end());
+      }
+    }
+
+    ASSERT_EQ(number_of_requested_bises, configuration.numBis);
+    ASSERT_EQ(requirements.subgroupConfigurationRequirements.size(),
+              configuration.subgroupsConfigurations.size());
+
+    if (expectedSampleFreqs.empty()) {
+      return;
+    }
+
+    std::sort(sampleFreqs.begin(), sampleFreqs.end());
+    std::sort(expectedSampleFreqs.begin(), expectedSampleFreqs.end());
+
+    ASSERT_EQ(sampleFreqs, expectedSampleFreqs);
+  }
+
+  LeAudioDeviceCapabilities GetDefaultBroadcastSinkCapability() {
+    // Create a capability
+    LeAudioDeviceCapabilities capability;
+
+    capability.codecId = CodecId::Core::LC3;
+
+    auto pref_context_metadata = MetadataLtv::PreferredAudioContexts();
+    pref_context_metadata.values =
+        GetAudioContext(AudioContext::MEDIA | AudioContext::CONVERSATIONAL |
+                        AudioContext::GAME);
+    capability.metadata = {pref_context_metadata};
+
+    auto sampling_rate =
+        CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies();
+    sampling_rate.bitmask =
+        CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies::HZ48000 |
+        CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies::HZ24000 |
+        CodecSpecificCapabilitiesLtv::SupportedSamplingFrequencies::HZ16000;
+    auto frame_duration =
+        CodecSpecificCapabilitiesLtv::SupportedFrameDurations();
+    frame_duration.bitmask =
+        CodecSpecificCapabilitiesLtv::SupportedFrameDurations::US7500 |
+        CodecSpecificCapabilitiesLtv::SupportedFrameDurations::US10000;
+    auto octets = CodecSpecificCapabilitiesLtv::SupportedOctetsPerCodecFrame();
+    octets.min = 0;
+    octets.max = 120;
+    auto frames = CodecSpecificCapabilitiesLtv::SupportedMaxCodecFramesPerSDU();
+    frames.value = 2;
+    capability.codecSpecificCapabilities = {sampling_rate, frame_duration,
+                                            octets, frames};
+    return capability;
+  }
+
+  LeAudioBroadcastConfigurationRequirement GetBroadcastRequirement(
+      bool standard_quality, bool high_quality) {
+    LeAudioBroadcastConfigurationRequirement requirement;
+
+    AudioContext media_audio_context;
+    media_audio_context.bitmask = AudioContext::MEDIA;
+
+    LeAudioBroadcastSubgroupConfigurationRequirement
+        standard_quality_requirement = {
+            .audioContext = media_audio_context,
+            .quality = IBluetoothAudioProvider::BroadcastQuality::STANDARD,
+            .bisNumPerSubgroup = 2};
+
+    LeAudioBroadcastSubgroupConfigurationRequirement high_quality_requirement =
+        {.audioContext = media_audio_context,
+         .quality = IBluetoothAudioProvider::BroadcastQuality::HIGH,
+         .bisNumPerSubgroup = 2};
+
+    if (standard_quality) {
+      requirement.subgroupConfigurationRequirements.push_back(
+          standard_quality_requirement);
+    }
+
+    if (high_quality) {
+      requirement.subgroupConfigurationRequirements.push_back(
+          high_quality_requirement);
+    }
+    return requirement;
+  }
+
   std::vector<Lc3Configuration> GetBroadcastLc3SupportedList(bool supported) {
     std::vector<Lc3Configuration> le_audio_codec_configs;
     if (!supported) {
@@ -3164,18 +4330,80 @@
       BluetoothAudioHalVersion::VERSION_AIDL_V4) {
     GTEST_SKIP();
   }
+
+  if (!IsBroadcastOffloadSupported()) {
+    GTEST_SKIP();
+  }
+
   std::vector<std::optional<LeAudioDeviceCapabilities>> empty_capability;
   IBluetoothAudioProvider::LeAudioBroadcastConfigurationRequirement
       empty_requirement;
 
-  IBluetoothAudioProvider::LeAudioBroadcastConfigurationSetting* configuration =
-      new IBluetoothAudioProvider::LeAudioBroadcastConfigurationSetting();
+  IBluetoothAudioProvider::LeAudioBroadcastConfigurationSetting configuration;
 
   // Check empty capability for source direction
   auto aidl_retval = audio_provider_->getLeAudioBroadcastConfiguration(
-      empty_capability, empty_requirement, configuration);
+      empty_capability, empty_requirement, &configuration);
+
+  ASSERT_FALSE(aidl_retval.isOk());
+}
+
+TEST_P(BluetoothAudioProviderLeAudioBroadcastHardwareAidl,
+       GetBroadcastConfigurationEmptyCapability) {
+  if (GetProviderFactoryInterfaceVersion() <
+      BluetoothAudioHalVersion::VERSION_AIDL_V4) {
+    GTEST_SKIP();
+  }
+
+  if (!IsBroadcastOffloadSupported()) {
+    GTEST_SKIP();
+  }
+
+  std::vector<std::optional<LeAudioDeviceCapabilities>> empty_capability;
+  IBluetoothAudioProvider::LeAudioBroadcastConfigurationSetting configuration;
+
+  IBluetoothAudioProvider::LeAudioBroadcastConfigurationRequirement
+      one_subgroup_requirement =
+          GetBroadcastRequirement(true /* standard*/, false /* high */);
+
+  // Check empty capability for source direction
+  auto aidl_retval = audio_provider_->getLeAudioBroadcastConfiguration(
+      empty_capability, one_subgroup_requirement, &configuration);
 
   ASSERT_TRUE(aidl_retval.isOk());
+  ASSERT_NE(configuration.numBis, 0);
+  ASSERT_FALSE(configuration.subgroupsConfigurations.empty());
+  VerifyBroadcastConfiguration(one_subgroup_requirement, configuration);
+}
+
+TEST_P(BluetoothAudioProviderLeAudioBroadcastHardwareAidl,
+       GetBroadcastConfigurationNonEmptyCapability) {
+  if (GetProviderFactoryInterfaceVersion() <
+      BluetoothAudioHalVersion::VERSION_AIDL_V4) {
+    GTEST_SKIP();
+  }
+
+  if (!IsBroadcastOffloadSupported()) {
+    GTEST_SKIP();
+  }
+
+  std::vector<std::optional<LeAudioDeviceCapabilities>> capability = {
+      GetDefaultBroadcastSinkCapability()};
+
+  IBluetoothAudioProvider::LeAudioBroadcastConfigurationRequirement
+      requirement =
+          GetBroadcastRequirement(true /* standard*/, false /* high */);
+
+  IBluetoothAudioProvider::LeAudioBroadcastConfigurationSetting configuration;
+
+  // Check empty capability for source direction
+  auto aidl_retval = audio_provider_->getLeAudioBroadcastConfiguration(
+      capability, requirement, &configuration);
+
+  ASSERT_TRUE(aidl_retval.isOk());
+  ASSERT_NE(configuration.numBis, 0);
+  ASSERT_FALSE(configuration.subgroupsConfigurations.empty());
+  VerifyBroadcastConfiguration(requirement, configuration);
 }
 
 /**
@@ -3186,7 +4414,7 @@
 TEST_P(BluetoothAudioProviderLeAudioBroadcastHardwareAidl,
        StartAndEndLeAudioBroadcastSessionWithPossibleBroadcastConfig) {
   if (!IsBroadcastOffloadSupported()) {
-    return;
+    GTEST_SKIP();
   }
 
   auto lc3_codec_configs = GetBroadcastLc3SupportedList(true /* supported */);
@@ -3225,7 +4453,7 @@
     BluetoothAudioProviderLeAudioBroadcastHardwareAidl,
     DISABLED_StartAndEndLeAudioBroadcastSessionWithInvalidAudioConfiguration) {
   if (!IsBroadcastOffloadSupported()) {
-    return;
+    GTEST_SKIP();
   }
 
   auto lc3_codec_configs = GetBroadcastLc3SupportedList(false /* supported */);
diff --git a/bluetooth/audio/flags/btaudiohal.aconfig b/bluetooth/audio/flags/btaudiohal.aconfig
index 4c1500a..13e2116 100644
--- a/bluetooth/audio/flags/btaudiohal.aconfig
+++ b/bluetooth/audio/flags/btaudiohal.aconfig
@@ -7,3 +7,10 @@
     description: "Flag for DSA Over LEA"
     bug: "270987427"
 }
+
+flag {
+    name: "leaudio_report_broadcast_ac_to_hal"
+    namespace: "pixel_bluetooth"
+    description: "Flag for reporting lea broadcast audio config to HAL"
+    bug: "321168976"
+}
\ No newline at end of file
diff --git a/bluetooth/audio/utils/Android.bp b/bluetooth/audio/utils/Android.bp
index 779a90f..1661362 100644
--- a/bluetooth/audio/utils/Android.bp
+++ b/bluetooth/audio/utils/Android.bp
@@ -90,6 +90,9 @@
 
 cc_test {
     name: "BluetoothLeAudioCodecsProviderTest",
+    defaults: [
+        "latest_android_hardware_bluetooth_audio_ndk_shared",
+    ],
     srcs: [
         "aidl_session/BluetoothLeAudioCodecsProvider.cpp",
         "aidl_session/BluetoothLeAudioCodecsProviderTest.cpp",
@@ -100,7 +103,6 @@
     shared_libs: [
         "libbase",
         "libbinder_ndk",
-        "android.hardware.bluetooth.audio-V4-ndk",
         "libxml2",
     ],
     test_suites: [
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp b/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp
index 67ba93c..d0f2a26 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp
+++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp
@@ -121,18 +121,41 @@
 
 void BluetoothAudioSession::ReportAudioConfigChanged(
     const AudioConfiguration& audio_config) {
-  if (session_type_ !=
-          SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
-      session_type_ !=
-          SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
-    return;
-  }
-
   std::lock_guard<std::recursive_mutex> guard(mutex_);
-  if (audio_config.getTag() != AudioConfiguration::leAudioConfig) {
-    LOG(ERROR) << __func__ << " invalid audio config type for SessionType ="
-               << toString(session_type_);
-    return;
+  if (com::android::btaudio::hal::flags::leaudio_report_broadcast_ac_to_hal()) {
+    if (session_type_ ==
+            SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
+        session_type_ ==
+            SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
+      if (audio_config.getTag() != AudioConfiguration::leAudioConfig) {
+        LOG(ERROR) << __func__ << " invalid audio config type for SessionType ="
+                  << toString(session_type_);
+        return;
+      }
+    } else if (session_type_ ==
+            SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
+      if (audio_config.getTag() != AudioConfiguration::leAudioBroadcastConfig) {
+        LOG(ERROR) << __func__ << " invalid audio config type for SessionType ="
+                  << toString(session_type_);
+        return;
+      }
+    } else {
+      LOG(ERROR) << __func__ << " invalid SessionType ="
+                 << toString(session_type_);
+      return;
+    }
+  } else {
+    if (session_type_ !=
+            SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
+        session_type_ !=
+            SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
+      return;
+    }
+    if (audio_config.getTag() != AudioConfiguration::leAudioConfig) {
+      LOG(ERROR) << __func__ << " invalid audio config type for SessionType ="
+                 << toString(session_type_);
+      return;
+    }
   }
 
   audio_config_ = std::make_unique<AudioConfiguration>(audio_config);
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioAseConfigurationSettingProvider.cpp b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioAseConfigurationSettingProvider.cpp
index 5429a8f..780154a 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioAseConfigurationSettingProvider.cpp
+++ b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioAseConfigurationSettingProvider.cpp
@@ -267,7 +267,7 @@
     ase_configuration_settings_.clear();
     configurations_.clear();
     auto loaded = LoadContent(kLeAudioSetConfigs, kLeAudioSetScenarios,
-                              CodecLocation::HOST);
+                              CodecLocation::ADSP);
     if (!loaded)
       LOG(ERROR) << ": Unable to load le audio set configuration files.";
   } else
@@ -371,7 +371,6 @@
       CodecSpecificConfigurationLtv::CodecFrameBlocksPerSDU();
   frame_sdu_structure.value = codec_frames_blocks_per_sdu;
   ase.codecConfiguration.push_back(frame_sdu_structure);
-  // TODO: Channel count
 }
 
 void AudioSetConfigurationProviderJson::populateAseConfiguration(
@@ -415,8 +414,53 @@
 }
 
 void AudioSetConfigurationProviderJson::populateAseQosConfiguration(
-    LeAudioAseQosConfiguration& qos,
-    const le_audio::QosConfiguration* qos_cfg) {
+    LeAudioAseQosConfiguration& qos, const le_audio::QosConfiguration* qos_cfg,
+    LeAudioAseConfiguration& ase) {
+  std::optional<CodecSpecificConfigurationLtv::CodecFrameBlocksPerSDU>
+      frameBlock = std::nullopt;
+  std::optional<CodecSpecificConfigurationLtv::FrameDuration> frameDuration =
+      std::nullopt;
+  std::optional<CodecSpecificConfigurationLtv::AudioChannelAllocation>
+      allocation = std::nullopt;
+  std::optional<CodecSpecificConfigurationLtv::OctetsPerCodecFrame> octet =
+      std::nullopt;
+
+  for (auto& cfg_ltv : ase.codecConfiguration) {
+    auto tag = cfg_ltv.getTag();
+    if (tag == CodecSpecificConfigurationLtv::codecFrameBlocksPerSDU) {
+      frameBlock =
+          cfg_ltv.get<CodecSpecificConfigurationLtv::codecFrameBlocksPerSDU>();
+    } else if (tag == CodecSpecificConfigurationLtv::frameDuration) {
+      frameDuration =
+          cfg_ltv.get<CodecSpecificConfigurationLtv::frameDuration>();
+    } else if (tag == CodecSpecificConfigurationLtv::audioChannelAllocation) {
+      allocation =
+          cfg_ltv.get<CodecSpecificConfigurationLtv::audioChannelAllocation>();
+    } else if (tag == CodecSpecificConfigurationLtv::octetsPerCodecFrame) {
+      octet = cfg_ltv.get<CodecSpecificConfigurationLtv::octetsPerCodecFrame>();
+    }
+  }
+
+  int frameBlockValue = 1;
+  if (frameBlock.has_value()) frameBlockValue = frameBlock.value().value;
+
+  // Populate maxSdu
+  if (allocation.has_value() && octet.has_value()) {
+    auto channel_count = std::bitset<32>(allocation.value().bitmask).count();
+    qos.maxSdu = channel_count * octet.value().value * frameBlockValue;
+  }
+  // Populate sduIntervalUs
+  if (frameDuration.has_value()) {
+    switch (frameDuration.value()) {
+      case CodecSpecificConfigurationLtv::FrameDuration::US7500:
+        qos.sduIntervalUs = 7500;
+        break;
+      case CodecSpecificConfigurationLtv::FrameDuration::US10000:
+        qos.sduIntervalUs = 10000;
+        break;
+    }
+    qos.sduIntervalUs *= frameBlockValue;
+  }
   qos.maxTransportLatencyMs = qos_cfg->max_transport_latency();
   qos.retransmissionNum = qos_cfg->retransmission_number();
 }
@@ -436,7 +480,7 @@
   populateAseConfiguration(ase, flat_subconfig, qos_cfg);
 
   // Translate into LeAudioAseQosConfiguration
-  populateAseQosConfiguration(qos, qos_cfg);
+  populateAseQosConfiguration(qos, qos_cfg, ase);
 
   // Translate location to data path id
   switch (location) {
@@ -453,6 +497,8 @@
       path.dataPathId = kIsoDataPathPlatformDefault;
       break;
   }
+  // Move codecId to iso data path
+  path.isoDataPathConfiguration.codecId = ase.codecId.value();
 
   direction_conf.aseConfiguration = ase;
   direction_conf.qosConfiguration = qos;
@@ -678,7 +724,8 @@
   media_context.bitmask =
       (AudioContext::ALERTS | AudioContext::INSTRUCTIONAL |
        AudioContext::NOTIFICATIONS | AudioContext::EMERGENCY_ALARM |
-       AudioContext::UNSPECIFIED | AudioContext::MEDIA);
+       AudioContext::UNSPECIFIED | AudioContext::MEDIA |
+       AudioContext::SOUND_EFFECTS);
 
   AudioContext conversational_context = AudioContext();
   conversational_context.bitmask =
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioAseConfigurationSettingProvider.h b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioAseConfigurationSettingProvider.h
index ce91fca..6639009 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioAseConfigurationSettingProvider.h
+++ b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioAseConfigurationSettingProvider.h
@@ -79,7 +79,7 @@
 
   static void populateAseQosConfiguration(
       LeAudioAseQosConfiguration& qos,
-      const le_audio::QosConfiguration* qos_cfg);
+      const le_audio::QosConfiguration* qos_cfg, LeAudioAseConfiguration& ase);
 
   static AseDirectionConfiguration SetConfigurationFromFlatSubconfig(
       const le_audio::AudioSetSubConfiguration* flat_subconfig,
diff --git a/bluetooth/finder/aidl/default/BluetoothFinder.cpp b/bluetooth/finder/aidl/default/BluetoothFinder.cpp
index 236a1f8..a43846b 100644
--- a/bluetooth/finder/aidl/default/BluetoothFinder.cpp
+++ b/bluetooth/finder/aidl/default/BluetoothFinder.cpp
@@ -19,7 +19,7 @@
 namespace aidl::android::hardware::bluetooth::finder::impl {
 
 ::ndk::ScopedAStatus BluetoothFinder::sendEids(const ::std::vector<Eid>& keys) {
-  keys_.insert(keys_.end(), keys.begin(), keys.end());
+  keys_.assign(keys.begin(), keys.end());
   return ::ndk::ScopedAStatus::ok();
 }
 
diff --git a/camera/metadata/aidl/android/hardware/camera/metadata/CameraMetadataTag.aidl b/camera/metadata/aidl/android/hardware/camera/metadata/CameraMetadataTag.aidl
index f133372..236bcaf 100644
--- a/camera/metadata/aidl/android/hardware/camera/metadata/CameraMetadataTag.aidl
+++ b/camera/metadata/aidl/android/hardware/camera/metadata/CameraMetadataTag.aidl
@@ -580,25 +580,25 @@
     /**
      * android.flash.singleStrengthMaxLevel [static, int32, public]
      *
-     * <p>Maximum flash brightness level for manual flash control in SINGLE mode.</p>
+     * <p>Maximum flash brightness level for manual flash control in <code>SINGLE</code> mode.</p>
      */
     ANDROID_FLASH_SINGLE_STRENGTH_MAX_LEVEL,
     /**
      * android.flash.singleStrengthDefaultLevel [static, int32, public]
      *
-     * <p>Default flash brightness level for manual flash control in SINGLE mode.</p>
+     * <p>Default flash brightness level for manual flash control in <code>SINGLE</code> mode.</p>
      */
     ANDROID_FLASH_SINGLE_STRENGTH_DEFAULT_LEVEL,
     /**
      * android.flash.torchStrengthMaxLevel [static, int32, public]
      *
-     * <p>Maximum flash brightness level for manual flash control in TORCH mode</p>
+     * <p>Maximum flash brightness level for manual flash control in <code>TORCH</code> mode</p>
      */
     ANDROID_FLASH_TORCH_STRENGTH_MAX_LEVEL,
     /**
      * android.flash.torchStrengthDefaultLevel [static, int32, public]
      *
-     * <p>Default flash brightness level for manual flash control in TORCH mode</p>
+     * <p>Default flash brightness level for manual flash control in <code>TORCH</code> mode</p>
      */
     ANDROID_FLASH_TORCH_STRENGTH_DEFAULT_LEVEL,
     /**
diff --git a/common/aidl/Android.bp b/common/aidl/Android.bp
index 431059b..1f5742d 100644
--- a/common/aidl/Android.bp
+++ b/common/aidl/Android.bp
@@ -13,7 +13,6 @@
     vendor_available: true,
     product_available: true,
     double_loadable: true,
-    vndk_use_version: "2",
     srcs: [
         "android/hardware/common/*.aidl",
     ],
diff --git a/compatibility_matrices/Android.bp b/compatibility_matrices/Android.bp
index 951ca85..ad42015 100644
--- a/compatibility_matrices/Android.bp
+++ b/compatibility_matrices/Android.bp
@@ -92,3 +92,25 @@
     ],
 
 }
+
+// Phony target that installs all system compatibility matrix files
+SYSTEM_MATRIX_DEPS = [
+    "framework_compatibility_matrix.5.xml",
+    "framework_compatibility_matrix.6.xml",
+    "framework_compatibility_matrix.7.xml",
+    "framework_compatibility_matrix.8.xml",
+    "framework_compatibility_matrix.202404.xml",
+    "framework_compatibility_matrix.device.xml",
+]
+
+phony {
+    name: "system_compatibility_matrix.xml",
+    required: SYSTEM_MATRIX_DEPS,
+    product_variables: {
+        release_aidl_use_unfrozen: {
+            required: [
+                "framework_compatibility_matrix.202504.xml",
+            ],
+        },
+    },
+}
diff --git a/compatibility_matrices/Android.mk b/compatibility_matrices/Android.mk
index ab57b8c..338c075 100644
--- a/compatibility_matrices/Android.mk
+++ b/compatibility_matrices/Android.mk
@@ -119,15 +119,6 @@
 my_framework_matrix_deps += \
     $(my_system_matrix_deps)
 
-# Phony target that installs all system compatibility matrix files
-include $(CLEAR_VARS)
-LOCAL_MODULE := system_compatibility_matrix.xml
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../NOTICE
-LOCAL_REQUIRED_MODULES := $(my_system_matrix_deps)
-include $(BUILD_PHONY_PACKAGE)
-
 # Phony target that installs all framework compatibility matrix files (system + product)
 include $(CLEAR_VARS)
 LOCAL_MODULE := framework_compatibility_matrix.xml
diff --git a/confirmationui/aidl/android/hardware/confirmationui/IConfirmationResultCallback.aidl b/confirmationui/aidl/android/hardware/confirmationui/IConfirmationResultCallback.aidl
index 92328a8..dcce7ef 100644
--- a/confirmationui/aidl/android/hardware/confirmationui/IConfirmationResultCallback.aidl
+++ b/confirmationui/aidl/android/hardware/confirmationui/IConfirmationResultCallback.aidl
@@ -38,15 +38,15 @@
      * prevented the TUI from being shut down gracefully.
      *
      * @param formattedMessage holds the prompt text and extra data.
-     *                         The message is CBOR (RFC 7049) encoded and has the following format:
-     *                         CBOR_MAP{ "prompt", <promptText>, "extra", <extraData> }
-     *                         The message is a CBOR encoded map (type 5) with the keys
-     *                         "prompt" and "extra". The keys are encoded as CBOR text string
-     *                         (type 3). The value <promptText> is encoded as CBOR text string
-     *                         (type 3), and the value <extraData> is encoded as CBOR byte string
-     *                         (type 2). The map must have exactly one key value pair for each of
-     *                         the keys "prompt" and "extra". Other keys are not allowed.
-     *                         The value of "prompt" is given by the proptText argument to
+     *                         The message is CBOR (RFC 7049) encoded and has the exact format
+     *                         given by the following CDDL:
+     *
+     *                         formattedMessage = {
+     *                             "prompt" : tstr,
+     *                             "extra" : bstr,
+     *                         }
+     *
+     *                         The value of "prompt" is given by the promptText argument to
      *                         IConfirmationUI::promptUserConfirmation and must not be modified
      *                         by the implementation.
      *                         The value of "extra" is given by the extraData argument to
@@ -59,8 +59,7 @@
      *                          the "", concatenated with the formatted message as returned in the
      *                          formattedMessage argument. The HMAC is keyed with a 256-bit secret
      *                          which is shared with Keymaster. In test mode the test key MUST be
-     *                          used (see TestModeCommands.aidl and
-     * IConfirmationUI::TEST_KEY_BYTE).
+     *                          used (see TestModeCommands.aidl and IConfirmationUI::TEST_KEY_BYTE)
      */
     void result(in int error, in byte[] formattedMessage, in byte[] confirmationToken);
 }
diff --git a/gnss/aidl/default/Gnss.cpp b/gnss/aidl/default/Gnss.cpp
index c31f991..94d4d00 100644
--- a/gnss/aidl/default/Gnss.cpp
+++ b/gnss/aidl/default/Gnss.cpp
@@ -162,12 +162,13 @@
     return ScopedAStatus::ok();
 }
 
-void Gnss::reportLocation(const GnssLocation& location) const {
+void Gnss::reportLocation(const GnssLocation& location) {
     std::unique_lock<std::mutex> lock(mMutex);
     if (sGnssCallback == nullptr) {
         ALOGE("%s: GnssCallback is null.", __func__);
         return;
     }
+    mLastLocation = std::make_shared<GnssLocation>(location);
     auto status = sGnssCallback->gnssLocationCb(location);
     if (!status.isOk()) {
         ALOGE("%s: Unable to invoke gnssLocationCb", __func__);
@@ -359,7 +360,6 @@
 
 ndk::ScopedAStatus Gnss::getExtensionGnssDebug(std::shared_ptr<IGnssDebug>* iGnssDebug) {
     ALOGD("Gnss::getExtensionGnssDebug");
-
     *iGnssDebug = SharedRefBase::make<GnssDebug>();
     return ndk::ScopedAStatus::ok();
 }
@@ -398,4 +398,8 @@
     mGnssMeasurementIntervalMs = intervalMs;
 }
 
+std::shared_ptr<GnssLocation> Gnss::getLastLocation() const {
+    return mLastLocation;
+}
+
 }  // namespace aidl::android::hardware::gnss
diff --git a/gnss/aidl/default/Gnss.h b/gnss/aidl/default/Gnss.h
index 245d607..73085ef 100644
--- a/gnss/aidl/default/Gnss.h
+++ b/gnss/aidl/default/Gnss.h
@@ -87,18 +87,19 @@
     void reportSvStatus() const;
     void setGnssMeasurementEnabled(const bool enabled);
     void setGnssMeasurementInterval(const long intervalMs);
+    std::shared_ptr<GnssLocation> getLastLocation() const;
     std::shared_ptr<GnssConfiguration> mGnssConfiguration;
     std::shared_ptr<GnssPowerIndication> mGnssPowerIndication;
     std::shared_ptr<GnssMeasurementInterface> mGnssMeasurementInterface;
 
   private:
-    void reportLocation(const GnssLocation&) const;
+    void reportLocation(const GnssLocation&);
     void reportSvStatus(const std::vector<IGnssCallback::GnssSvInfo>& svInfoList) const;
+    void reportGnssStatusValue(const IGnssCallback::GnssStatusValue gnssStatusValue) const;
+    void reportNmea() const;
     std::vector<IGnssCallback::GnssSvInfo> filterBlocklistedSatellites(
             std::vector<IGnssCallback::GnssSvInfo> gnssSvInfoList) const;
-    void reportGnssStatusValue(const IGnssCallback::GnssStatusValue gnssStatusValue) const;
     std::unique_ptr<GnssLocation> getLocationFromHW();
-    void reportNmea() const;
 
     static std::shared_ptr<IGnssCallback> sGnssCallback;
 
@@ -109,6 +110,7 @@
     std::atomic<bool> mIsNmeaActive;
     std::atomic<bool> mFirstFixReceived;
     std::atomic<bool> mGnssMeasurementEnabled;
+    std::shared_ptr<GnssLocation> mLastLocation;
     std::thread mThread;
     ::android::hardware::gnss::common::ThreadBlocker mThreadBlocker;
 
diff --git a/gnss/aidl/default/GnssDebug.cpp b/gnss/aidl/default/GnssDebug.cpp
index f40c0bc..5ae6edd 100644
--- a/gnss/aidl/default/GnssDebug.cpp
+++ b/gnss/aidl/default/GnssDebug.cpp
@@ -18,10 +18,15 @@
 
 #include "GnssDebug.h"
 #include <log/log.h>
+#include <utils/SystemClock.h>
+#include "Constants.h"
+#include "Gnss.h"
 #include "MockLocation.h"
 
 namespace aidl::android::hardware::gnss {
 
+using ::android::hardware::gnss::common::kMockTimestamp;
+
 ndk::ScopedAStatus GnssDebug::getDebugData(DebugData* debugData) {
     ALOGD("GnssDebug::getDebugData");
 
@@ -36,10 +41,94 @@
                                    .speedAccuracyMetersPerSecond = 1,
                                    .bearingAccuracyDegrees = 90,
                                    .ageSeconds = 0.99};
-    TimeDebug timeDebug = {.timeEstimateMs = 1519930775453L,
+    TimeDebug timeDebug = {.timeEstimateMs = static_cast<int64_t>(
+                                   kMockTimestamp + ::android::elapsedRealtimeNano() / 1e6),
                            .timeUncertaintyNs = 1000,
-                           .frequencyUncertaintyNsPerSec = 5.0e4};
-    std::vector<SatelliteData> satelliteDataArrayDebug = {};
+                           .frequencyUncertaintyNsPerSec = 800};
+    SatelliteData satelliteData1 = {
+            .svid = 3,
+            .constellation = GnssConstellationType::GPS,
+            .ephemerisType = SatelliteEphemerisType::EPHEMERIS,
+            .ephemerisSource = SatellitePvt::SatelliteEphemerisSource::SERVER_LONG_TERM,
+            .ephemerisHealth = SatelliteEphemerisHealth::GOOD,
+            .ephemerisAgeSeconds = 12,
+            .serverPredictionIsAvailable = true,
+            .serverPredictionAgeSeconds = 30};
+    SatelliteData satelliteData2 = {
+            .svid = 5,
+            .constellation = GnssConstellationType::GPS,
+            .ephemerisType = SatelliteEphemerisType::EPHEMERIS,
+            .ephemerisSource = SatellitePvt::SatelliteEphemerisSource::SERVER_LONG_TERM,
+            .ephemerisHealth = SatelliteEphemerisHealth::GOOD,
+            .ephemerisAgeSeconds = 12,
+            .serverPredictionIsAvailable = true,
+            .serverPredictionAgeSeconds = 30};
+    SatelliteData satelliteData3 = {
+            .svid = 17,
+            .constellation = GnssConstellationType::GPS,
+            .ephemerisType = SatelliteEphemerisType::EPHEMERIS,
+            .ephemerisSource = SatellitePvt::SatelliteEphemerisSource::SERVER_LONG_TERM,
+            .ephemerisHealth = SatelliteEphemerisHealth::GOOD,
+            .ephemerisAgeSeconds = 12,
+            .serverPredictionIsAvailable = true,
+            .serverPredictionAgeSeconds = 30};
+    SatelliteData satelliteData4 = {
+            .svid = 26,
+            .constellation = GnssConstellationType::GPS,
+            .ephemerisType = SatelliteEphemerisType::EPHEMERIS,
+            .ephemerisSource = SatellitePvt::SatelliteEphemerisSource::SERVER_LONG_TERM,
+            .ephemerisHealth = SatelliteEphemerisHealth::GOOD,
+            .ephemerisAgeSeconds = 12,
+            .serverPredictionIsAvailable = true,
+            .serverPredictionAgeSeconds = 30};
+    SatelliteData satelliteData5 = {
+            .svid = 5,
+            .constellation = GnssConstellationType::GLONASS,
+            .ephemerisType = SatelliteEphemerisType::EPHEMERIS,
+            .ephemerisSource = SatellitePvt::SatelliteEphemerisSource::SERVER_LONG_TERM,
+            .ephemerisHealth = SatelliteEphemerisHealth::GOOD,
+            .ephemerisAgeSeconds = 12,
+            .serverPredictionIsAvailable = true,
+            .serverPredictionAgeSeconds = 30};
+    SatelliteData satelliteData6 = {
+            .svid = 17,
+            .constellation = GnssConstellationType::GLONASS,
+            .ephemerisType = SatelliteEphemerisType::EPHEMERIS,
+            .ephemerisSource = SatellitePvt::SatelliteEphemerisSource::SERVER_LONG_TERM,
+            .ephemerisHealth = SatelliteEphemerisHealth::GOOD,
+            .ephemerisAgeSeconds = 12,
+            .serverPredictionIsAvailable = true,
+            .serverPredictionAgeSeconds = 30};
+    SatelliteData satelliteData7 = {
+            .svid = 18,
+            .constellation = GnssConstellationType::GLONASS,
+            .ephemerisType = SatelliteEphemerisType::EPHEMERIS,
+            .ephemerisSource = SatellitePvt::SatelliteEphemerisSource::SERVER_LONG_TERM,
+            .ephemerisHealth = SatelliteEphemerisHealth::GOOD,
+            .ephemerisAgeSeconds = 12,
+            .serverPredictionIsAvailable = true,
+            .serverPredictionAgeSeconds = 30};
+    SatelliteData satelliteData8 = {
+            .svid = 10,
+            .constellation = GnssConstellationType::GLONASS,
+            .ephemerisType = SatelliteEphemerisType::EPHEMERIS,
+            .ephemerisSource = SatellitePvt::SatelliteEphemerisSource::SERVER_LONG_TERM,
+            .ephemerisHealth = SatelliteEphemerisHealth::GOOD,
+            .ephemerisAgeSeconds = 12,
+            .serverPredictionIsAvailable = true,
+            .serverPredictionAgeSeconds = 30};
+    SatelliteData satelliteData9 = {
+            .svid = 3,
+            .constellation = GnssConstellationType::IRNSS,
+            .ephemerisType = SatelliteEphemerisType::EPHEMERIS,
+            .ephemerisSource = SatellitePvt::SatelliteEphemerisSource::SERVER_LONG_TERM,
+            .ephemerisHealth = SatelliteEphemerisHealth::GOOD,
+            .ephemerisAgeSeconds = 12,
+            .serverPredictionIsAvailable = true,
+            .serverPredictionAgeSeconds = 30};
+    std::vector<SatelliteData> satelliteDataArrayDebug = {
+            satelliteData1, satelliteData2, satelliteData3, satelliteData4, satelliteData5,
+            satelliteData6, satelliteData7, satelliteData8, satelliteData9};
     debugData->position = positionDebug;
     debugData->time = timeDebug;
     debugData->satelliteDataArray = satelliteDataArrayDebug;
diff --git a/gnss/aidl/default/GnssDebug.h b/gnss/aidl/default/GnssDebug.h
index 001d47c..b6844b3 100644
--- a/gnss/aidl/default/GnssDebug.h
+++ b/gnss/aidl/default/GnssDebug.h
@@ -20,6 +20,8 @@
 
 namespace aidl::android::hardware::gnss {
 
+class Gnss;
+
 struct GnssDebug : public BnGnssDebug {
   public:
     ndk::ScopedAStatus getDebugData(DebugData* debugData) override;
diff --git a/gnss/aidl/vts/gnss_hal_test_cases.cpp b/gnss/aidl/vts/gnss_hal_test_cases.cpp
index 4309187..f7408d8 100644
--- a/gnss/aidl/vts/gnss_hal_test_cases.cpp
+++ b/gnss/aidl/vts/gnss_hal_test_cases.cpp
@@ -1149,40 +1149,139 @@
     sp<IGnssDebug> iGnssDebug;
     auto status = aidl_gnss_hal_->getExtensionGnssDebug(&iGnssDebug);
     ASSERT_TRUE(status.isOk());
-
-    if (!IsAutomotiveDevice()) {
-        ASSERT_TRUE(iGnssDebug != nullptr);
-
-        IGnssDebug::DebugData data;
-        auto status = iGnssDebug->getDebugData(&data);
-        ASSERT_TRUE(status.isOk());
-
-        if (data.position.valid) {
-            ASSERT_TRUE(data.position.latitudeDegrees >= -90 &&
-                        data.position.latitudeDegrees <= 90);
-            ASSERT_TRUE(data.position.longitudeDegrees >= -180 &&
-                        data.position.longitudeDegrees <= 180);
-            ASSERT_TRUE(data.position.altitudeMeters >= -1000 &&  // Dead Sea: -414m
-                        data.position.altitudeMeters <= 20000);   // Mount Everest: 8850m
-            ASSERT_TRUE(data.position.speedMetersPerSec >= 0 &&
-                        data.position.speedMetersPerSec <= 600);
-            ASSERT_TRUE(data.position.bearingDegrees >= -360 &&
-                        data.position.bearingDegrees <= 360);
-            ASSERT_TRUE(data.position.horizontalAccuracyMeters > 0 &&
-                        data.position.horizontalAccuracyMeters <= 20000000);
-            ASSERT_TRUE(data.position.verticalAccuracyMeters > 0 &&
-                        data.position.verticalAccuracyMeters <= 20000);
-            ASSERT_TRUE(data.position.speedAccuracyMetersPerSecond > 0 &&
-                        data.position.speedAccuracyMetersPerSecond <= 500);
-            ASSERT_TRUE(data.position.bearingAccuracyDegrees > 0 &&
-                        data.position.bearingAccuracyDegrees <= 180);
-            ASSERT_TRUE(data.position.ageSeconds >= 0);
-        }
-        ASSERT_TRUE(data.time.timeEstimateMs >= 1483228800000);  // Jan 01 2017 00:00:00 GMT.
-        ASSERT_TRUE(data.time.timeUncertaintyNs > 0);
-        ASSERT_TRUE(data.time.frequencyUncertaintyNsPerSec > 0 &&
-                    data.time.frequencyUncertaintyNsPerSec <= 2.0e5);  // 200 ppm
+    if (IsAutomotiveDevice()) {
+        return;
     }
+    ASSERT_TRUE(iGnssDebug != nullptr);
+
+    IGnssDebug::DebugData data;
+    status = iGnssDebug->getDebugData(&data);
+    ASSERT_TRUE(status.isOk());
+    Utils::checkPositionDebug(data);
+
+    // Additional GnssDebug tests for AIDL version >= 4 (launched in Android 15(V)+)
+    if (aidl_gnss_hal_->getInterfaceVersion() <= 3) {
+        return;
+    }
+
+    // Start location and check the consistency between SvStatus and DebugData
+    aidl_gnss_cb_->location_cbq_.reset();
+    aidl_gnss_cb_->sv_info_list_cbq_.reset();
+    StartAndCheckLocations(/* count= */ 2);
+    int location_called_count = aidl_gnss_cb_->location_cbq_.calledCount();
+    ALOGD("Observed %d GnssSvStatus, while awaiting 2 locations (%d received)",
+          aidl_gnss_cb_->sv_info_list_cbq_.size(), location_called_count);
+
+    // Wait for up to kNumSvInfoLists events for kTimeoutSeconds for each event.
+    int kTimeoutSeconds = 2;
+    int kNumSvInfoLists = 4;
+    std::list<std::vector<IGnssCallback::GnssSvInfo>> sv_info_lists;
+    std::vector<IGnssCallback::GnssSvInfo> last_sv_info_list;
+
+    do {
+        EXPECT_GT(aidl_gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_lists, kNumSvInfoLists,
+                                                            kTimeoutSeconds),
+                  0);
+        if (!sv_info_lists.empty()) {
+            last_sv_info_list = sv_info_lists.back();
+            ALOGD("last_sv_info size = %d", (int)last_sv_info_list.size());
+        }
+    } while (!sv_info_lists.empty() && last_sv_info_list.size() == 0);
+
+    StopAndClearLocations();
+
+    status = iGnssDebug->getDebugData(&data);
+    Utils::checkPositionDebug(data);
+
+    // Validate SatelliteEphemerisType, SatelliteEphemerisSource, SatelliteEphemerisHealth
+    for (auto sv_info : last_sv_info_list) {
+        if ((sv_info.svFlag & static_cast<int>(IGnssCallback::GnssSvFlags::USED_IN_FIX)) == 0) {
+            continue;
+        }
+        ALOGD("Found usedInFix const: %d, svid: %d", static_cast<int>(sv_info.constellation),
+              sv_info.svid);
+        bool foundDebugData = false;
+        for (auto satelliteData : data.satelliteDataArray) {
+            if (satelliteData.constellation == sv_info.constellation &&
+                satelliteData.svid == sv_info.svid) {
+                foundDebugData = true;
+                ALOGD("Found GnssDebug data for this sv.");
+                EXPECT_TRUE(satelliteData.serverPredictionIsAvailable ||
+                            satelliteData.ephemerisType ==
+                                    IGnssDebug::SatelliteEphemerisType::EPHEMERIS);
+                // for satellites with ephType=0, they need ephHealth=0 if used-in-fix
+                if (satelliteData.ephemerisType == IGnssDebug::SatelliteEphemerisType::EPHEMERIS) {
+                    EXPECT_TRUE(satelliteData.ephemerisHealth ==
+                                IGnssDebug::SatelliteEphemerisHealth::GOOD);
+                }
+                break;
+            }
+        }
+        // Every Satellite where GnssStatus says it is used-in-fix has a valid ephemeris - i.e. it's
+        // it shows either a serverPredAvail: 1, or a ephType=0
+        EXPECT_TRUE(foundDebugData);
+    }
+
+    bool hasServerPredictionAvailable = false;
+    bool hasNoneZeroServerPredictionAgeSeconds = false;
+    bool hasNoneDemodEphSource = false;
+    for (auto satelliteData : data.satelliteDataArray) {
+        // for satellites with serverPredAvail: 1, the serverPredAgeSec: is not 0 for all
+        // satellites (at least not on 2 fixes in a row - it could get lucky once)
+        if (satelliteData.serverPredictionIsAvailable) {
+            hasServerPredictionAvailable = true;
+            if (satelliteData.serverPredictionAgeSeconds != 0) {
+                hasNoneZeroServerPredictionAgeSeconds = true;
+            }
+        }
+        // for satellites with ephType=0, they need ephSource 0-3
+        if (satelliteData.ephemerisType == IGnssDebug::SatelliteEphemerisType::EPHEMERIS) {
+            EXPECT_TRUE(satelliteData.ephemerisSource >=
+                                SatellitePvt::SatelliteEphemerisSource::DEMODULATED &&
+                        satelliteData.ephemerisSource <=
+                                SatellitePvt::SatelliteEphemerisSource::OTHER);
+            if (satelliteData.ephemerisSource !=
+                SatellitePvt::SatelliteEphemerisSource::DEMODULATED) {
+                hasNoneDemodEphSource = true;
+            }
+        }
+    }
+    if (hasNoneDemodEphSource && hasServerPredictionAvailable) {
+        EXPECT_TRUE(hasNoneZeroServerPredictionAgeSeconds);
+    }
+
+    /**
+    - Gnss Location Data:: should show some valid information, ideally reasonably close (+/-1km) to
+        the Location output - at least after the 2nd valid location output (maybe in general, wait
+        for 2 good Location outputs before checking this, in case they don't update the assistance
+        until after they output the Location)
+    */
+    double distanceM =
+            Utils::distanceMeters(data.position.latitudeDegrees, data.position.longitudeDegrees,
+                                  aidl_gnss_cb_->last_location_.latitudeDegrees,
+                                  aidl_gnss_cb_->last_location_.longitudeDegrees);
+    ALOGD("distance between debug position and last position: %.2lf", distanceM);
+    EXPECT_LT(distanceM, 1000.0);  // 1km
+
+    /**
+    - Gnss Time Data:: timeEstimate should be reasonably close to the current GPS time.
+    - Gnss Time Data:: timeUncertaintyNs should always be > 0 and < 5e9 (could be large due
+        to solve-for-time type solutions)
+    - Gnss Time Data:: frequencyUncertaintyNsPerSec: should always be > 0 and < 1000 (1000 ns/s
+        corresponds to roughly a 300 m/s speed error, which should be pretty rare)
+    */
+    ALOGD("debug time: %" PRId64 ", position time: %" PRId64, data.time.timeEstimateMs,
+          aidl_gnss_cb_->last_location_.timestampMillis);
+    // Allowing 5s between the last location time and the current GPS time
+    EXPECT_LT(abs(data.time.timeEstimateMs - aidl_gnss_cb_->last_location_.timestampMillis), 5000);
+
+    ALOGD("debug time uncertainty: %f ns", data.time.timeUncertaintyNs);
+    EXPECT_GT(data.time.timeUncertaintyNs, 0);
+    EXPECT_LT(data.time.timeUncertaintyNs, 5e9);
+
+    ALOGD("debug freq uncertainty: %f ns/s", data.time.frequencyUncertaintyNsPerSec);
+    EXPECT_GT(data.time.frequencyUncertaintyNsPerSec, 0);
+    EXPECT_LT(data.time.frequencyUncertaintyNsPerSec, 1000);
 }
 
 /*
diff --git a/gnss/common/utils/vts/Utils.cpp b/gnss/common/utils/vts/Utils.cpp
index 69e2b34..e3ff0f3 100644
--- a/gnss/common/utils/vts/Utils.cpp
+++ b/gnss/common/utils/vts/Utils.cpp
@@ -20,6 +20,7 @@
 #include "gtest/gtest.h"
 
 #include <cutils/properties.h>
+#include <math.h>
 #include <utils/SystemClock.h>
 
 namespace android {
@@ -58,6 +59,31 @@
     checkElapsedRealtime(location.elapsedRealtime);
 }
 
+void Utils::checkPositionDebug(android::hardware::gnss::IGnssDebug::DebugData data) {
+    if (data.position.valid) {
+        ASSERT_TRUE(data.position.latitudeDegrees >= -90 && data.position.latitudeDegrees <= 90);
+        ASSERT_TRUE(data.position.longitudeDegrees >= -180 &&
+                    data.position.longitudeDegrees <= 180);
+        ASSERT_TRUE(data.position.altitudeMeters >= -1000 &&  // Dead Sea: -414m
+                    data.position.altitudeMeters <= 20000);   // Mount Everest: 8850m
+        ASSERT_TRUE(data.position.speedMetersPerSec >= 0 && data.position.speedMetersPerSec <= 600);
+        ASSERT_TRUE(data.position.bearingDegrees >= -360 && data.position.bearingDegrees <= 360);
+        ASSERT_TRUE(data.position.horizontalAccuracyMeters > 0 &&
+                    data.position.horizontalAccuracyMeters <= 20000000);
+        ASSERT_TRUE(data.position.verticalAccuracyMeters > 0 &&
+                    data.position.verticalAccuracyMeters <= 20000);
+        ASSERT_TRUE(data.position.speedAccuracyMetersPerSecond > 0 &&
+                    data.position.speedAccuracyMetersPerSecond <= 500);
+        ASSERT_TRUE(data.position.bearingAccuracyDegrees > 0 &&
+                    data.position.bearingAccuracyDegrees <= 180);
+        ASSERT_TRUE(data.position.ageSeconds >= 0);
+    }
+    ASSERT_TRUE(data.time.timeEstimateMs >= 1483228800000);  // Jan 01 2017 00:00:00 GMT.
+    ASSERT_TRUE(data.time.timeUncertaintyNs > 0);
+    ASSERT_TRUE(data.time.frequencyUncertaintyNsPerSec > 0 &&
+                data.time.frequencyUncertaintyNsPerSec <= 2.0e5);  // 200 ppm
+}
+
 void Utils::checkElapsedRealtime(const ElapsedRealtime& elapsedRealtime) {
     ASSERT_TRUE(elapsedRealtime.flags >= 0 &&
                 elapsedRealtime.flags <= (ElapsedRealtime::HAS_TIMESTAMP_NS |
@@ -282,6 +308,17 @@
     return strncmp(buffer, "automotive", PROPERTY_VALUE_MAX) == 0;
 }
 
+double Utils::distanceMeters(double lat1, double lon1, double lat2, double lon2) {
+    double R = 6378.137;  // Radius of earth in KM
+    double dLat = lat2 * M_PI / 180 - lat1 * M_PI / 180;
+    double dLon = lon2 * M_PI / 180 - lon1 * M_PI / 180;
+    double a = sin(dLat / 2) * sin(dLat / 2) +
+               cos(lat1 * M_PI / 180) * cos(lat2 * M_PI / 180) * sin(dLon / 2) * sin(dLon / 2);
+    double c = 2 * atan2(sqrt(a), sqrt(1 - a));
+    double d = R * c;
+    return d * 1000;  // meters
+}
+
 }  // namespace common
 }  // namespace gnss
 }  // namespace hardware
diff --git a/gnss/common/utils/vts/include/Utils.h b/gnss/common/utils/vts/include/Utils.h
index 7b89078..62d409a 100644
--- a/gnss/common/utils/vts/include/Utils.h
+++ b/gnss/common/utils/vts/include/Utils.h
@@ -43,6 +43,7 @@
 
     static void checkElapsedRealtime(
             const android::hardware::gnss::ElapsedRealtime& elapsedRealtime);
+    static void checkPositionDebug(android::hardware::gnss::IGnssDebug::DebugData data);
 
     static const android::hardware::gnss::GnssLocation getMockLocation(
             double latitudeDegrees, double longitudeDegrees, double horizontalAccuracyMeters);
@@ -57,6 +58,7 @@
             V2_0::GnssConstellationType constellation);
 
     static bool isAutomotiveDevice();
+    static double distanceMeters(double lat1, double lon1, double lat2, double lon2);
 
   private:
     template <class T>
diff --git a/graphics/allocator/aidl/Android.bp b/graphics/allocator/aidl/Android.bp
index 0b916bf..7bb6b50 100644
--- a/graphics/allocator/aidl/Android.bp
+++ b/graphics/allocator/aidl/Android.bp
@@ -12,7 +12,6 @@
     name: "android.hardware.graphics.allocator",
     vendor_available: true,
     double_loadable: true,
-    vndk_use_version: "2",
     srcs: ["android/hardware/graphics/allocator/*.aidl"],
     imports: [
         "android.hardware.common-V2",
diff --git a/graphics/common/aidl/Android.bp b/graphics/common/aidl/Android.bp
index 33d0938..4f5c3d9 100644
--- a/graphics/common/aidl/Android.bp
+++ b/graphics/common/aidl/Android.bp
@@ -13,7 +13,6 @@
     host_supported: true,
     vendor_available: true,
     double_loadable: true,
-    vndk_use_version: "5",
     srcs: [
         "android/hardware/graphics/common/*.aidl",
     ],
diff --git a/graphics/composer/2.1/utils/command-buffer/include/composer-command-buffer/2.1/ComposerCommandBuffer.h b/graphics/composer/2.1/utils/command-buffer/include/composer-command-buffer/2.1/ComposerCommandBuffer.h
index 336d15d..6a45987 100644
--- a/graphics/composer/2.1/utils/command-buffer/include/composer-command-buffer/2.1/ComposerCommandBuffer.h
+++ b/graphics/composer/2.1/utils/command-buffer/include/composer-command-buffer/2.1/ComposerCommandBuffer.h
@@ -33,6 +33,7 @@
 #include <string.h>
 
 #include <android/hardware/graphics/composer/2.1/IComposer.h>
+#include <android/hardware/graphics/composer/2.1/IComposerClient.h>
 #include <fmq/MessageQueue.h>
 #include <log/log.h>
 #include <sync/sync.h>
@@ -649,7 +650,8 @@
         *outLength = static_cast<uint16_t>(val & length_mask);
 
         if (mDataRead + *outLength > mDataSize) {
-            ALOGE("command 0x%x has invalid command length %" PRIu16, *outCommand, *outLength);
+            ALOGE("command %s has invalid command length %" PRIu16,
+                  toString(*outCommand).c_str(), *outLength);
             // undo the read() above
             mDataRead--;
             return false;
diff --git a/graphics/composer/aidl/Android.bp b/graphics/composer/aidl/Android.bp
index fad70d8..c4e6878 100644
--- a/graphics/composer/aidl/Android.bp
+++ b/graphics/composer/aidl/Android.bp
@@ -30,7 +30,6 @@
     vendor_available: true,
     double_loadable: true,
     frozen: true,
-    vndk_use_version: "1",
     srcs: [
         "android/hardware/graphics/composer3/*.aidl",
     ],
diff --git a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp
index d4ce3ba..3d9253f 100644
--- a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp
+++ b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp
@@ -59,10 +59,12 @@
 
         EXPECT_TRUE(mComposerClient->setPowerMode(getPrimaryDisplayId(), PowerMode::ON).isOk());
 
+        const auto format = getHasReadbackBuffer() ? mPixelFormat : common::PixelFormat::RGBA_8888;
+
         ASSERT_NO_FATAL_FAILURE(
                 mTestRenderEngine = std::unique_ptr<TestRenderEngine>(new TestRenderEngine(
                         ::android::renderengine::RenderEngineCreationArgs::Builder()
-                                .setPixelFormat(static_cast<int>(common::PixelFormat::RGBA_8888))
+                                .setPixelFormat(static_cast<int>(format))
                                 .setImageCacheSize(TestRenderEngine::sMaxFrameBufferAcquireBuffers)
                                 .setEnableProtectedContext(false)
                                 .setPrecacheToneMapperShaderOnly(false)
diff --git a/media/bufferpool/aidl/default/Accessor.cpp b/media/bufferpool/aidl/default/Accessor.cpp
index 3d206ac..423fd84 100644
--- a/media/bufferpool/aidl/default/Accessor.cpp
+++ b/media/bufferpool/aidl/default/Accessor.cpp
@@ -16,6 +16,8 @@
 #define LOG_TAG "AidlBufferPoolAcc"
 //#define LOG_NDEBUG 0
 
+#include <android-base/no_destructor.h>
+
 #include <sys/types.h>
 #include <stdint.h>
 #include <time.h>
@@ -41,7 +43,25 @@
 #endif
 
 static constexpr uint32_t kSeqIdMax = 0x7fffffff;
-uint32_t Accessor::sSeqId = time(nullptr) & kSeqIdMax;
+
+Accessor::ConnectionIdGenerator::ConnectionIdGenerator() {
+    mSeqId = static_cast<uint32_t>(time(nullptr) & kSeqIdMax);
+    mPid = static_cast<int32_t>(getpid());
+}
+
+ConnectionId Accessor::ConnectionIdGenerator::getConnectionId() {
+    uint32_t seq;
+    {
+        std::lock_guard<std::mutex> l(mLock);
+        seq = mSeqId;
+        if (mSeqId == kSeqIdMax) {
+            mSeqId = 0;
+        } else {
+            ++mSeqId;
+        }
+    }
+    return (int64_t)mPid << 32 | seq | kSeqIdVndkBit;
+}
 
 namespace {
 // anonymous namespace
@@ -239,13 +259,14 @@
         uint32_t *pMsgId,
         StatusDescriptor* statusDescPtr,
         InvalidationDescriptor* invDescPtr) {
+    static ::android::base::NoDestructor<ConnectionIdGenerator> sConIdGenerator;
     std::shared_ptr<Connection> newConnection = ::ndk::SharedRefBase::make<Connection>();
     BufferPoolStatus status = ResultStatus::CRITICAL_ERROR;
     {
         std::lock_guard<std::mutex> lock(mBufferPool.mMutex);
         if (newConnection) {
             int32_t pid = getpid();
-            ConnectionId id = (int64_t)pid << 32 | sSeqId | kSeqIdVndkBit;
+            ConnectionId id = sConIdGenerator->getConnectionId();
             status = mBufferPool.mObserver.open(id, statusDescPtr);
             if (status == ResultStatus::OK) {
                 newConnection->initialize(ref<Accessor>(), id);
@@ -255,11 +276,6 @@
                 mBufferPool.mConnectionIds.insert(id);
                 mBufferPool.mInvalidationChannel.getDesc(invDescPtr);
                 mBufferPool.mInvalidation.onConnect(id, observer);
-                if (sSeqId == kSeqIdMax) {
-                   sSeqId = 0;
-                } else {
-                    ++sSeqId;
-                }
             }
 
         }
diff --git a/media/bufferpool/aidl/default/Accessor.h b/media/bufferpool/aidl/default/Accessor.h
index 85e2fa7..0ebe347 100644
--- a/media/bufferpool/aidl/default/Accessor.h
+++ b/media/bufferpool/aidl/default/Accessor.h
@@ -189,7 +189,14 @@
 private:
     // ConnectionId = pid : (timestamp_created + seqId)
     // in order to guarantee uniqueness for each connection
-    static uint32_t sSeqId;
+    struct ConnectionIdGenerator {
+        int32_t mPid;
+        uint32_t mSeqId;
+        std::mutex mLock;
+
+        ConnectionIdGenerator();
+        ConnectionId getConnectionId();
+    };
 
     const std::shared_ptr<BufferPoolAllocator> mAllocator;
     nsecs_t mScheduleEvictTs;
diff --git a/media/bufferpool/aidl/default/Android.bp b/media/bufferpool/aidl/default/Android.bp
index 72cd903..3c31446 100644
--- a/media/bufferpool/aidl/default/Android.bp
+++ b/media/bufferpool/aidl/default/Android.bp
@@ -29,6 +29,9 @@
     export_include_dirs: [
         "include",
     ],
+    header_libs: [
+        "libbase_headers",
+    ],
     shared_libs: [
         "libbinder_ndk",
         "libcutils",
diff --git a/radio/aidl/vts/radio_config_test.cpp b/radio/aidl/vts/radio_config_test.cpp
index 6f18d18..e7214e5 100644
--- a/radio/aidl/vts/radio_config_test.cpp
+++ b/radio/aidl/vts/radio_config_test.cpp
@@ -278,7 +278,14 @@
                     EXPECT_LT(logicalSlotId, slotPortMappingList.size());
                     if (logicalSlotId >= 0 && logicalSlotId < slotPortMappingList.size()) {
                         slotPortMappingList[logicalSlotId].physicalSlotId = i;
-                        slotPortMappingList[logicalSlotId].portId = j;
+                        if (radioRsp_config->simSlotStatus[i].supportedMepMode ==
+                                    MultipleEnabledProfilesMode::MEP_A1 ||
+                            radioRsp_config->simSlotStatus[i].supportedMepMode ==
+                                    MultipleEnabledProfilesMode::MEP_A2) {
+                            slotPortMappingList[logicalSlotId].portId = j + 1;
+                        } else {
+                            slotPortMappingList[logicalSlotId].portId = j;
+                        }
                     }
                 }
             }
diff --git a/security/keymint/aidl/vts/functional/AttestKeyTest.cpp b/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
index 7fbca36..5106561 100644
--- a/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
+++ b/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
@@ -16,7 +16,6 @@
 
 #define LOG_TAG "keymint_1_attest_key_test"
 #include <android-base/logging.h>
-#include <android-base/strings.h>
 #include <cutils/log.h>
 #include <cutils/properties.h>
 
@@ -29,66 +28,12 @@
 namespace aidl::android::hardware::security::keymint::test {
 
 namespace {
-string TELEPHONY_CMD_GET_IMEI = "cmd phone get-imei ";
 
 bool IsSelfSigned(const vector<Certificate>& chain) {
     if (chain.size() != 1) return false;
     return ChainSignaturesAreValid(chain);
 }
 
-/*
- * Run a shell command and collect the output of it. If any error, set an empty string as the
- * output.
- */
-string exec_command(string command) {
-    char buffer[128];
-    string result = "";
-
-    FILE* pipe = popen(command.c_str(), "r");
-    if (!pipe) {
-        LOG(ERROR) << "popen failed.";
-        return result;
-    }
-
-    // read till end of process:
-    while (!feof(pipe)) {
-        if (fgets(buffer, 128, pipe) != NULL) {
-            result += buffer;
-        }
-    }
-
-    pclose(pipe);
-    return result;
-}
-
-/*
- * Get IMEI using Telephony service shell command. If any error while executing the command
- * then empty string will be returned as output.
- */
-string get_imei(int slot) {
-    string cmd = TELEPHONY_CMD_GET_IMEI + std::to_string(slot);
-    string output = exec_command(cmd);
-
-    if (output.empty()) {
-        LOG(ERROR) << "Command failed. Cmd: " << cmd;
-        return "";
-    }
-
-    vector<string> out = ::android::base::Tokenize(::android::base::Trim(output), "Device IMEI:");
-
-    if (out.size() != 1) {
-        LOG(ERROR) << "Error in parsing the command output. Cmd: " << cmd;
-        return "";
-    }
-
-    string imei = ::android::base::Trim(out[0]);
-    if (imei.compare("null") == 0) {
-        LOG(WARNING) << "Failed to get IMEI from Telephony service: value is null. Cmd: " << cmd;
-        return "";
-    }
-
-    return imei;
-}
 }  // namespace
 
 class AttestKeyTest : public KeyMintAidlTestBase {
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
index 332fcd4..cef8120 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
@@ -26,6 +26,7 @@
 #include "keymint_support/keymint_tags.h"
 
 #include <android-base/logging.h>
+#include <android-base/strings.h>
 #include <android/binder_manager.h>
 #include <android/content/pm/IPackageManagerNative.h>
 #include <cppbor_parse.h>
@@ -1588,7 +1589,7 @@
     // with any other key purpose, but the original VTS tests incorrectly did exactly that.
     // This means that a device that launched prior to Android T (API level 33) may
     // accept or even require KeyPurpose::SIGN too.
-    if (property_get_int32("ro.board.first_api_level", 0) < __ANDROID_API_T__) {
+    if (get_vsr_api_level() < __ANDROID_API_T__) {
         AuthorizationSet key_desc_plus_sign = key_desc;
         key_desc_plus_sign.push_back(TAG_PURPOSE, KeyPurpose::SIGN);
 
@@ -2337,6 +2338,67 @@
     return result;
 }
 
+namespace {
+
+std::string TELEPHONY_CMD_GET_IMEI = "cmd phone get-imei ";
+
+/*
+ * Run a shell command and collect the output of it. If any error, set an empty string as the
+ * output.
+ */
+std::string exec_command(const std::string& command) {
+    char buffer[128];
+    std::string result = "";
+
+    FILE* pipe = popen(command.c_str(), "r");
+    if (!pipe) {
+        LOG(ERROR) << "popen failed.";
+        return result;
+    }
+
+    // read till end of process:
+    while (!feof(pipe)) {
+        if (fgets(buffer, 128, pipe) != NULL) {
+            result += buffer;
+        }
+    }
+
+    pclose(pipe);
+    return result;
+}
+
+}  // namespace
+
+/*
+ * Get IMEI using Telephony service shell command. If any error while executing the command
+ * then empty string will be returned as output.
+ */
+std::string get_imei(int slot) {
+    std::string cmd = TELEPHONY_CMD_GET_IMEI + std::to_string(slot);
+    std::string output = exec_command(cmd);
+
+    if (output.empty()) {
+        LOG(ERROR) << "Command failed. Cmd: " << cmd;
+        return "";
+    }
+
+    vector<std::string> out =
+            ::android::base::Tokenize(::android::base::Trim(output), "Device IMEI:");
+
+    if (out.size() != 1) {
+        LOG(ERROR) << "Error in parsing the command output. Cmd: " << cmd;
+        return "";
+    }
+
+    std::string imei = ::android::base::Trim(out[0]);
+    if (imei.compare("null") == 0) {
+        LOG(WARNING) << "Failed to get IMEI from Telephony service: value is null. Cmd: " << cmd;
+        return "";
+    }
+
+    return imei;
+}
+
 }  // namespace test
 
 }  // namespace aidl::android::hardware::security::keymint
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
index b884cc7..1bf2d9d 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
@@ -430,6 +430,7 @@
 void device_id_attestation_check_acceptable_error(Tag tag, const ErrorCode& result);
 bool check_feature(const std::string& name);
 std::optional<int32_t> keymint_feature_value(bool strongbox);
+std::string get_imei(int slot);
 
 AuthorizationSet HwEnforcedAuthorizations(const vector<KeyCharacteristics>& key_characteristics);
 AuthorizationSet SwEnforcedAuthorizations(const vector<KeyCharacteristics>& key_characteristics);
diff --git a/security/keymint/aidl/vts/functional/KeyMintTest.cpp b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
index 35e5e84..3c49a82 100644
--- a/security/keymint/aidl/vts/functional/KeyMintTest.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
@@ -2026,7 +2026,7 @@
  * NewKeyGenerationTest.EcdsaAttestationIdTags
  *
  * Verifies that creation of an attested ECDSA key includes various ID tags in the
- * attestation extension.
+ * attestation extension one by one.
  */
 TEST_P(NewKeyGenerationTest, EcdsaAttestationIdTags) {
     auto challenge = "hello";
@@ -2054,6 +2054,15 @@
     add_attestation_id(&extra_tags, TAG_ATTESTATION_ID_MANUFACTURER, "manufacturer");
     add_attestation_id(&extra_tags, TAG_ATTESTATION_ID_MODEL, "model");
     add_tag_from_prop(&extra_tags, TAG_ATTESTATION_ID_SERIAL, "ro.serialno");
+    string imei = get_imei(0);
+    if (!imei.empty()) {
+        extra_tags.Authorization(TAG_ATTESTATION_ID_IMEI, imei.data(), imei.size());
+    }
+    string second_imei = get_imei(1);
+    if (!second_imei.empty()) {
+        extra_tags.Authorization(TAG_ATTESTATION_ID_SECOND_IMEI, second_imei.data(),
+                                 second_imei.size());
+    }
 
     for (const KeyParameter& tag : extra_tags) {
         SCOPED_TRACE(testing::Message() << "tag-" << tag);
@@ -2091,6 +2100,83 @@
 }
 
 /*
+ * NewKeyGenerationTest.EcdsaAttestationIdAllTags
+ *
+ * Verifies that creation of an attested ECDSA key includes various ID tags in the
+ * attestation extension all together.
+ */
+TEST_P(NewKeyGenerationTest, EcdsaAttestationIdAllTags) {
+    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));
+    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();
+
+    // Various ATTESTATION_ID_* tags that map to fields in the attestation extension ASN.1 schema.
+    auto extra_tags = AuthorizationSetBuilder();
+    add_attestation_id(&extra_tags, TAG_ATTESTATION_ID_BRAND, "brand");
+    add_attestation_id(&extra_tags, TAG_ATTESTATION_ID_DEVICE, "device");
+    add_attestation_id(&extra_tags, TAG_ATTESTATION_ID_PRODUCT, "name");
+    add_attestation_id(&extra_tags, TAG_ATTESTATION_ID_MANUFACTURER, "manufacturer");
+    add_attestation_id(&extra_tags, TAG_ATTESTATION_ID_MODEL, "model");
+    add_tag_from_prop(&extra_tags, TAG_ATTESTATION_ID_SERIAL, "ro.serialno");
+    string imei = get_imei(0);
+    if (!imei.empty()) {
+        extra_tags.Authorization(TAG_ATTESTATION_ID_IMEI, imei.data(), imei.size());
+    }
+    string second_imei = get_imei(1);
+    if (!second_imei.empty()) {
+        extra_tags.Authorization(TAG_ATTESTATION_ID_SECOND_IMEI, second_imei.data(),
+                                 second_imei.size());
+    }
+    for (const KeyParameter& tag : extra_tags) {
+        builder.push_back(tag);
+    }
+
+    vector<uint8_t> key_blob;
+    vector<KeyCharacteristics> key_characteristics;
+    auto result = GenerateKey(builder, &key_blob, &key_characteristics);
+    if (result == ErrorCode::CANNOT_ATTEST_IDS && !isDeviceIdAttestationRequired()) {
+        // ID attestation was optional till api level 32, from api level 33 it is mandatory.
+        return;
+    }
+    ASSERT_EQ(result, ErrorCode::OK);
+    KeyBlobDeleter deleter(keymint_, key_blob);
+    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);
+
+    // 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 tags are added.
+    for (const KeyParameter& tag : extra_tags) {
+        hw_enforced.push_back(tag);
+    }
+
+    // Verifying the attestation record will check for the specific tag because
+    // it's included in the authorizations.
+    EXPECT_TRUE(verify_attestation_record(AidlVersion(), challenge, app_id, sw_enforced,
+                                          hw_enforced, SecLevel(),
+                                          cert_chain_[0].encodedCertificate))
+            << "failed to verify " << bin2hex(cert_chain_[0].encodedCertificate);
+}
+
+/*
  * NewKeyGenerationTest.EcdsaAttestationUniqueId
  *
  * Verifies that creation of an attested ECDSA key with a UNIQUE_ID included.
diff --git a/security/keymint/support/fuzzer/Android.bp b/security/keymint/support/fuzzer/Android.bp
new file mode 100644
index 0000000..1b1a580
--- /dev/null
+++ b/security/keymint/support/fuzzer/Android.bp
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_interfaces_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["hardware_interfaces_license"],
+    default_team: "trendy_team_android_hardware_backed_security",
+}
+
+cc_defaults {
+    name: "keymint_fuzzer_defaults",
+    static_libs: [
+        "libhidlbase",
+        "libkeymint_support",
+    ],
+    shared_libs: [
+        "libbase",
+        "libcrypto",
+        "libutils",
+        "libhardware",
+        "libbinder_ndk",
+        "liblog",
+    ],
+    defaults: [
+        "keymint_use_latest_hal_aidl_ndk_shared",
+    ],
+    include_dirs: [
+        "hardware/interfaces/security/keymint/support/include",
+        "frameworks/native/libs/binder/ndk/include_platform",
+    ],
+}
+
+cc_fuzz {
+    name: "keymint_attestation_fuzzer",
+    srcs: [
+        "keymint_attestation_fuzzer.cpp",
+    ],
+    defaults: [
+        "keymint_fuzzer_defaults",
+    ],
+}
+
+cc_fuzz {
+    name: "keymint_authSet_fuzzer",
+    srcs: [
+        "keymint_authSet_fuzzer.cpp",
+    ],
+    defaults: [
+        "keymint_fuzzer_defaults",
+    ],
+}
diff --git a/security/keymint/support/fuzzer/README.md b/security/keymint/support/fuzzer/README.md
new file mode 100644
index 0000000..d41af08
--- /dev/null
+++ b/security/keymint/support/fuzzer/README.md
@@ -0,0 +1,79 @@
+# Fuzzers for libkeymint_support
+
+## Plugin Design Considerations
+The fuzzer plugins for libkeymint_support are designed based on the understanding of the source code and try to achieve the following:
+
+#### Maximize code coverage
+The configuration parameters are not hardcoded, but instead selected based on incoming data. This ensures more code paths are reached by the fuzzers.
+
+#### Maximize utilization of input data
+The plugins feed the entire input data to the module. This ensures that the plugins tolerate any kind of input (empty, huge, malformed, etc) and dont `exit()` on any input and thereby increasing the chance of identifying vulnerabilities.
+
+## Table of contents
++ [keymint_attestation_fuzzer](#KeyMintAttestation)
++ [keymint_authSet_fuzzer](#KeyMintAuthSet)
+
+# <a name="KeyMintAttestation"></a> Fuzzer for KeyMintAttestation
+KeyMintAttestation supports the following parameters:
+1. PaddingMode(parameter name: "padding")
+2. Digest(parameter name: "digest")
+3. Index(parameter name: "idx")
+4. Timestamp(parameter name: "timestamp")
+5. AuthSet(parameter name: "authSet")
+6. IssuerSubjectName(parameter name: "issuerSubjectName")
+7. AttestationChallenge(parameter name: "challenge")
+8. AttestationApplicationId(parameter name: "id")
+9. EcCurve(parameter name: "ecCurve")
+10. BlockMode(parameter name: "blockmode")
+11. minMacLength(parameter name: "minMacLength")
+12. macLength(parameter name: "macLength")
+
+| Parameter| Valid Values| Configured Value|
+|------------- |--------------| -------------------- |
+|`padding`| `PaddingMode` |Value obtained from FuzzedDataProvider|
+|`digest`| `Digest` |Value obtained from FuzzedDataProvider|
+|`idx`| `size_t` |Value obtained from FuzzedDataProvider|
+|`timestamp`| `uint64_t` |Value obtained from FuzzedDataProvider|
+|`authSet`| `uint32_t` |Value obtained from FuzzedDataProvider|
+|`issuerSubjectName`| `uint8_t` |Value obtained from FuzzedDataProvider|
+|`AttestationChallenge`| `string` |Value obtained from FuzzedDataProvider|
+|`AttestationApplicationId`| `string` |Value obtained from FuzzedDataProvider|
+|`blockmode`| `BlockMode` |Value obtained from FuzzedDataProvider|
+|`minMacLength`| `uint32_t` |Value obtained from FuzzedDataProvider|
+|`macLength`| `uint32_t` |Value obtained from FuzzedDataProvider|
+
+#### Steps to run
+1. Build the fuzzer
+```
+$ mm -j$(nproc) keymint_attestation_fuzzer
+```
+2. Run on device
+```
+$ adb sync data
+$ adb shell /data/fuzz/arm64/keymint_attestation_fuzzer/keymint_attestation_fuzzer
+```
+
+# <a name="KeyMintAuthSet"></a> Fuzzer for KeyMintAuthSet
+KeyMintAuthSet supports the following parameters:
+1. AuthorizationSet(parameter name: "authSet")
+2. AuthorizationSet(parameter name: "params")
+3. KeyParameters(parameter name: "numKeyParam")
+4. Tag(parameter name: "tag")
+
+| Parameter| Valid Values| Configured Value|
+|------------- |--------------| -------------------- |
+|`authSet`| `AuthorizationSet` |Value obtained from FuzzedDataProvider|
+|`params`| `AuthorizationSet` |Value obtained from FuzzedDataProvider|
+|`numKeyParam`| `size_t` |Value obtained from FuzzedDataProvider|
+|`tag`| `Tag` |Value obtained from FuzzedDataProvider|
+
+#### Steps to run
+1. Build the fuzzer
+```
+$ mm -j$(nproc) keymint_authSet_fuzzer
+```
+2. Run on device
+```
+$ adb sync data
+$ adb shell /data/fuzz/arm64/keymint_authSet_fuzzer/keymint_authSet_fuzzer
+```
diff --git a/security/keymint/support/fuzzer/keymint_attestation_fuzzer.cpp b/security/keymint/support/fuzzer/keymint_attestation_fuzzer.cpp
new file mode 100644
index 0000000..bd781ac
--- /dev/null
+++ b/security/keymint/support/fuzzer/keymint_attestation_fuzzer.cpp
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <aidl/android/hardware/security/keymint/AttestationKey.h>
+#include <aidl/android/hardware/security/keymint/KeyCreationResult.h>
+#include <android/binder_manager.h>
+#include <keymint_common.h>
+#include <keymint_support/attestation_record.h>
+#include <keymint_support/openssl_utils.h>
+#include <utils/Log.h>
+
+namespace android::hardware::security::keymint_support::fuzzer {
+using namespace android;
+using AStatus = ::ndk::ScopedAStatus;
+std::shared_ptr<IKeyMintDevice> gKeyMint = nullptr;
+
+constexpr size_t kMaxBytes = 256;
+const std::string kServiceName = "android.hardware.security.keymint.IKeyMintDevice/default";
+
+class KeyMintAttestationFuzzer {
+  public:
+    KeyMintAttestationFuzzer(const uint8_t* data, size_t size) : mFdp(data, size){};
+    void process();
+
+  private:
+    KeyCreationResult generateKey(const AuthorizationSet& keyDesc,
+                                  const std::optional<AttestationKey>& attestKey,
+                                  vector<uint8_t>* keyBlob,
+                                  vector<KeyCharacteristics>* keyCharacteristics,
+                                  vector<Certificate>* certChain);
+    X509_Ptr parseCertificateBlob(const vector<uint8_t>& blob);
+    ASN1_OCTET_STRING* getAttestationRecord(const X509* certificate);
+    bool verifyAttestationRecord(const vector<uint8_t>& attestationCert);
+    FuzzedDataProvider mFdp;
+};
+
+KeyCreationResult KeyMintAttestationFuzzer::generateKey(
+        const AuthorizationSet& keyDesc, const std::optional<AttestationKey>& attestKey,
+        vector<uint8_t>* keyBlob, vector<KeyCharacteristics>* keyCharacteristics,
+        vector<Certificate>* certChain) {
+    KeyCreationResult creationResult;
+    AStatus result = gKeyMint->generateKey(keyDesc.vector_data(), attestKey, &creationResult);
+    if (result.isOk() && creationResult.keyBlob.size() > 0) {
+        *keyBlob = std::move(creationResult.keyBlob);
+        *keyCharacteristics = std::move(creationResult.keyCharacteristics);
+        *certChain = std::move(creationResult.certificateChain);
+    }
+    return creationResult;
+}
+
+X509_Ptr KeyMintAttestationFuzzer::parseCertificateBlob(const vector<uint8_t>& blob) {
+    const uint8_t* data = blob.data();
+    return X509_Ptr(d2i_X509(nullptr, &data, blob.size()));
+}
+
+ASN1_OCTET_STRING* KeyMintAttestationFuzzer::getAttestationRecord(const X509* certificate) {
+    ASN1_OBJECT_Ptr oid(OBJ_txt2obj(kAttestionRecordOid, 1 /* dotted string format */));
+    if (!oid.get()) {
+        return nullptr;
+    }
+
+    int32_t location = X509_get_ext_by_OBJ(certificate, oid.get(), -1 /* search from beginning */);
+    if (location == -1) {
+        return nullptr;
+    }
+
+    X509_EXTENSION* attestRecordExt = X509_get_ext(certificate, location);
+    if (!attestRecordExt) {
+        return nullptr;
+    }
+
+    ASN1_OCTET_STRING* attestRecord = X509_EXTENSION_get_data(attestRecordExt);
+    return attestRecord;
+}
+
+bool KeyMintAttestationFuzzer::verifyAttestationRecord(const vector<uint8_t>& attestationCert) {
+    X509_Ptr cert(parseCertificateBlob(attestationCert));
+    if (!cert.get()) {
+        return false;
+    }
+
+    ASN1_OCTET_STRING* attestRecord = getAttestationRecord(cert.get());
+    if (!attestRecord) {
+        return false;
+    }
+
+    AuthorizationSet attestationSwEnforced;
+    AuthorizationSet attestationHwEnforced;
+    SecurityLevel attestationSecurityLevel;
+    SecurityLevel keymintSecurityLevel;
+    vector<uint8_t> attestationChallenge;
+    vector<uint8_t> attestationUniqueId;
+    uint32_t attestationVersion;
+    uint32_t keymintVersion;
+
+    auto error = parse_attestation_record(attestRecord->data, attestRecord->length,
+                                          &attestationVersion, &attestationSecurityLevel,
+                                          &keymintVersion, &keymintSecurityLevel,
+                                          &attestationChallenge, &attestationSwEnforced,
+                                          &attestationHwEnforced, &attestationUniqueId);
+    if (error != ErrorCode::OK) {
+        return false;
+    }
+
+    VerifiedBoot verifiedBootState;
+    vector<uint8_t> verifiedBootKey;
+    vector<uint8_t> verifiedBootHash;
+    bool device_locked;
+
+    error = parse_root_of_trust(attestRecord->data, attestRecord->length, &verifiedBootKey,
+                                &verifiedBootState, &device_locked, &verifiedBootHash);
+    if (error != ErrorCode::OK) {
+        return false;
+    }
+    return true;
+}
+
+void KeyMintAttestationFuzzer::process() {
+    AttestationKey attestKey;
+    vector<Certificate> attestKeyCertChain;
+    vector<KeyCharacteristics> attestKeyCharacteristics;
+    generateKey(createAuthSetForAttestKey(&mFdp), {}, &attestKey.keyBlob, &attestKeyCharacteristics,
+                &attestKeyCertChain);
+
+    vector<Certificate> attestedKeyCertChain;
+    vector<KeyCharacteristics> attestedKeyCharacteristics;
+    vector<uint8_t> attestedKeyBlob;
+    attestKey.issuerSubjectName = mFdp.ConsumeBytes<uint8_t>(kMaxBytes);
+    generateKey(createAuthorizationSet(&mFdp), attestKey, &attestedKeyBlob,
+                &attestedKeyCharacteristics, &attestedKeyCertChain);
+
+    if (attestedKeyCertChain.size() > 0) {
+        size_t leafCert = attestedKeyCertChain.size() - 1;
+        verifyAttestationRecord(attestedKeyCertChain[leafCert].encodedCertificate);
+    }
+}
+
+extern "C" int LLVMFuzzerInitialize(int /* *argc */, char /* ***argv */) {
+    ::ndk::SpAIBinder binder(AServiceManager_waitForService(kServiceName.c_str()));
+    gKeyMint = std::move(IKeyMintDevice::fromBinder(binder));
+    LOG_ALWAYS_FATAL_IF(!gKeyMint, "Failed to get IKeyMintDevice instance.");
+    return 0;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    KeyMintAttestationFuzzer kmAttestationFuzzer(data, size);
+    kmAttestationFuzzer.process();
+    return 0;
+}
+
+}  // namespace android::hardware::security::keymint_support::fuzzer
diff --git a/security/keymint/support/fuzzer/keymint_authSet_fuzzer.cpp b/security/keymint/support/fuzzer/keymint_authSet_fuzzer.cpp
new file mode 100644
index 0000000..fcc3d91
--- /dev/null
+++ b/security/keymint/support/fuzzer/keymint_authSet_fuzzer.cpp
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+#include <keymint_common.h>
+#include <fstream>
+
+namespace android::hardware::security::keymint_support::fuzzer {
+
+constexpr size_t kMinAction = 0;
+constexpr size_t kMaxAction = 10;
+constexpr size_t kMinKeyParameter = 1;
+constexpr size_t kMaxKeyParameter = 10;
+
+constexpr Tag kTagArray[] = {Tag::INVALID,
+                             Tag::PURPOSE,
+                             Tag::ALGORITHM,
+                             Tag::KEY_SIZE,
+                             Tag::BLOCK_MODE,
+                             Tag::DIGEST,
+                             Tag::PADDING,
+                             Tag::CALLER_NONCE,
+                             Tag::MIN_MAC_LENGTH,
+                             Tag::EC_CURVE,
+                             Tag::RSA_PUBLIC_EXPONENT,
+                             Tag::INCLUDE_UNIQUE_ID,
+                             Tag::RSA_OAEP_MGF_DIGEST,
+                             Tag::BOOTLOADER_ONLY,
+                             Tag::ROLLBACK_RESISTANCE,
+                             Tag::HARDWARE_TYPE,
+                             Tag::EARLY_BOOT_ONLY,
+                             Tag::ACTIVE_DATETIME,
+                             Tag::ORIGINATION_EXPIRE_DATETIME,
+                             Tag::USAGE_EXPIRE_DATETIME,
+                             Tag::MIN_SECONDS_BETWEEN_OPS,
+                             Tag::MAX_USES_PER_BOOT,
+                             Tag::USAGE_COUNT_LIMIT,
+                             Tag::USER_ID,
+                             Tag::USER_SECURE_ID,
+                             Tag::NO_AUTH_REQUIRED,
+                             Tag::USER_AUTH_TYPE,
+                             Tag::AUTH_TIMEOUT,
+                             Tag::ALLOW_WHILE_ON_BODY,
+                             Tag::TRUSTED_USER_PRESENCE_REQUIRED,
+                             Tag::TRUSTED_CONFIRMATION_REQUIRED,
+                             Tag::UNLOCKED_DEVICE_REQUIRED,
+                             Tag::APPLICATION_ID,
+                             Tag::APPLICATION_DATA,
+                             Tag::CREATION_DATETIME,
+                             Tag::ORIGIN,
+                             Tag::ROOT_OF_TRUST,
+                             Tag::OS_VERSION,
+                             Tag::OS_PATCHLEVEL,
+                             Tag::UNIQUE_ID,
+                             Tag::ATTESTATION_CHALLENGE,
+                             Tag::ATTESTATION_APPLICATION_ID,
+                             Tag::ATTESTATION_ID_BRAND,
+                             Tag::ATTESTATION_ID_DEVICE,
+                             Tag::ATTESTATION_ID_PRODUCT,
+                             Tag::ATTESTATION_ID_SERIAL,
+                             Tag::ATTESTATION_ID_IMEI,
+                             Tag::ATTESTATION_ID_MEID,
+                             Tag::ATTESTATION_ID_MANUFACTURER,
+                             Tag::ATTESTATION_ID_MODEL,
+                             Tag::VENDOR_PATCHLEVEL,
+                             Tag::BOOT_PATCHLEVEL,
+                             Tag::DEVICE_UNIQUE_ATTESTATION,
+                             Tag::IDENTITY_CREDENTIAL_KEY,
+                             Tag::STORAGE_KEY,
+                             Tag::ASSOCIATED_DATA,
+                             Tag::NONCE,
+                             Tag::MAC_LENGTH,
+                             Tag::RESET_SINCE_ID_ROTATION,
+                             Tag::CONFIRMATION_TOKEN,
+                             Tag::CERTIFICATE_SERIAL,
+                             Tag::CERTIFICATE_SUBJECT,
+                             Tag::CERTIFICATE_NOT_BEFORE,
+                             Tag::CERTIFICATE_NOT_AFTER,
+                             Tag::MAX_BOOT_LEVEL};
+
+class KeyMintAuthSetFuzzer {
+  public:
+    KeyMintAuthSetFuzzer(const uint8_t* data, size_t size) : mFdp(data, size){};
+    void process();
+
+  private:
+    FuzzedDataProvider mFdp;
+};
+
+void KeyMintAuthSetFuzzer::process() {
+    AuthorizationSet authSet = createAuthorizationSet(&mFdp);
+    while (mFdp.remaining_bytes()) {
+        auto invokeAuthSetAPI = mFdp.PickValueInArray<const std::function<void()>>({
+                [&]() { authSet.Sort(); },
+                [&]() { authSet.Deduplicate(); },
+                [&]() { authSet.Union(createAuthorizationSet(&mFdp)); },
+                [&]() { authSet.Subtract(createAuthorizationSet(&mFdp)); },
+                [&]() {  // invoke push_back()
+                    AuthorizationSetBuilder builder = AuthorizationSetBuilder();
+                    for (const KeyParameter& tag : authSet) {
+                        builder.push_back(tag);
+                    }
+                    AuthorizationSet params = createAuthorizationSet(&mFdp);
+                    authSet.push_back(params);
+                },
+                [&]() {  // invoke copy constructor
+                    auto params = AuthorizationSetBuilder().Authorizations(authSet);
+                    authSet = params;
+                },
+                [&]() {  // invoke move constructor
+                    auto params = AuthorizationSetBuilder().Authorizations(authSet);
+                    authSet = std::move(params);
+                },
+                [&]() {  // invoke Constructor from vector<KeyParameter>
+                    vector<KeyParameter> keyParam;
+                    size_t numKeyParam =
+                            mFdp.ConsumeIntegralInRange<size_t>(kMinKeyParameter, kMaxKeyParameter);
+                    keyParam.resize(numKeyParam);
+                    for (size_t idx = 0; idx < numKeyParam - 1; ++idx) {
+                        keyParam[idx].tag = mFdp.PickValueInArray(kTagArray);
+                    }
+                    if (mFdp.ConsumeBool()) {
+                        AuthorizationSet auths(keyParam);
+                        auths.push_back(AuthorizationSet(keyParam));
+                    } else {  // invoke operator=
+                        AuthorizationSet auths = keyParam;
+                    }
+                },
+                [&]() {  // invoke 'Contains()'
+                    Tag tag = Tag::INVALID;
+                    if (authSet.size() > 0) {
+                        tag = authSet[mFdp.ConsumeIntegralInRange<size_t>(0, authSet.size() - 1)]
+                                      .tag;
+                    }
+                    authSet.Contains(mFdp.ConsumeBool() ? tag : mFdp.PickValueInArray(kTagArray));
+                },
+                [&]() {  // invoke 'GetTagCount()'
+                    Tag tag = Tag::INVALID;
+                    if (authSet.size() > 0) {
+                        tag = authSet[mFdp.ConsumeIntegralInRange<size_t>(0, authSet.size() - 1)]
+                                      .tag;
+                    }
+                    authSet.GetTagCount(mFdp.ConsumeBool() ? tag
+                                                           : mFdp.PickValueInArray(kTagArray));
+                },
+                [&]() {  // invoke 'erase()'
+                    if (authSet.size() > 0) {
+                        authSet.erase(mFdp.ConsumeIntegralInRange<size_t>(0, authSet.size() - 1));
+                    }
+                },
+        });
+        invokeAuthSetAPI();
+    }
+    authSet.Clear();
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    KeyMintAuthSetFuzzer kmAuthSetFuzzer(data, size);
+    kmAuthSetFuzzer.process();
+    return 0;
+}
+
+}  // namespace android::hardware::security::keymint_support::fuzzer
diff --git a/security/keymint/support/fuzzer/keymint_common.h b/security/keymint/support/fuzzer/keymint_common.h
new file mode 100644
index 0000000..5c30e38
--- /dev/null
+++ b/security/keymint/support/fuzzer/keymint_common.h
@@ -0,0 +1,260 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+#ifndef __KEYMINT_COMMON_H__
+#define __KEYMINT_COMMON_H__
+
+#include <aidl/android/hardware/security/keymint/BlockMode.h>
+#include <aidl/android/hardware/security/keymint/Digest.h>
+#include <aidl/android/hardware/security/keymint/EcCurve.h>
+#include <aidl/android/hardware/security/keymint/PaddingMode.h>
+#include <fuzzer/FuzzedDataProvider.h>
+#include <keymint_support/authorization_set.h>
+
+namespace android::hardware::security::keymint_support::fuzzer {
+
+using namespace aidl::android::hardware::security::keymint;
+
+constexpr uint32_t kStringSize = 64;
+constexpr uint32_t k3DesKeySize = 168;
+constexpr uint32_t kSymmKeySize = 256;
+constexpr uint32_t kRsaKeySize = 2048;
+constexpr uint32_t kPublicExponent = 65537;
+
+constexpr EcCurve kCurve[] = {EcCurve::P_224, EcCurve::P_256, EcCurve::P_384, EcCurve::P_521,
+                              EcCurve::CURVE_25519};
+
+constexpr PaddingMode kPaddingMode[] = {
+        PaddingMode::NONE,
+        PaddingMode::RSA_OAEP,
+        PaddingMode::RSA_PSS,
+        PaddingMode::RSA_PKCS1_1_5_ENCRYPT,
+        PaddingMode::RSA_PKCS1_1_5_SIGN,
+        PaddingMode::PKCS7,
+};
+
+constexpr Digest kDigest[] = {
+        Digest::NONE,      Digest::MD5,       Digest::SHA1,      Digest::SHA_2_224,
+        Digest::SHA_2_256, Digest::SHA_2_384, Digest::SHA_2_512,
+};
+
+constexpr BlockMode kBlockMode[] = {
+        BlockMode::ECB,
+        BlockMode::CBC,
+        BlockMode::CTR,
+        BlockMode::GCM,
+};
+
+enum AttestAuthSet : uint32_t {
+    RSA_ATTEST_KEY = 0u,
+    ECDSA_ATTEST_KEY,
+};
+
+enum AuthSet : uint32_t {
+    RSA_KEY = 0u,
+    RSA_SIGNING_KEY,
+    RSA_ENCRYPTION_KEY,
+    ECDSA_SIGNING_CURVE,
+    AES_ENCRYPTION_KEY,
+    TRIPLE_DES,
+    HMAC,
+    NO_DIGEST,
+    ECB_MODE,
+    GSM_MODE_MIN_MAC,
+    GSM_MODE_MAC,
+    BLOCK_MODE,
+};
+
+AuthorizationSet createAuthSetForAttestKey(FuzzedDataProvider* dataProvider) {
+    uint32_t attestAuthSet = dataProvider->ConsumeBool() ? AttestAuthSet::RSA_ATTEST_KEY
+                                                         : AttestAuthSet::ECDSA_ATTEST_KEY;
+    uint64_t timestamp = dataProvider->ConsumeIntegral<uint64_t>();
+    Digest digest = dataProvider->PickValueInArray(kDigest);
+    PaddingMode padding = dataProvider->PickValueInArray(kPaddingMode);
+    std::string challenge = dataProvider->ConsumeRandomLengthString(kStringSize);
+    std::string id = dataProvider->ConsumeRandomLengthString(kStringSize);
+    switch (attestAuthSet) {
+        case RSA_ATTEST_KEY: {
+            return AuthorizationSetBuilder()
+                    .Authorization(TAG_NO_AUTH_REQUIRED)
+                    .RsaKey(kRsaKeySize, kPublicExponent)
+                    .Digest(digest)
+                    .Padding(padding)
+                    .AttestKey()
+                    .AttestationChallenge(challenge)
+                    .AttestationApplicationId(id)
+                    .SetDefaultValidity()
+                    .Authorization(TAG_CREATION_DATETIME, timestamp)
+                    .Authorization(TAG_INCLUDE_UNIQUE_ID)
+                    .Authorization(TAG_PURPOSE, KeyPurpose::ATTEST_KEY);
+        } break;
+        case ECDSA_ATTEST_KEY: {
+            EcCurve ecCurve = dataProvider->PickValueInArray(kCurve);
+            return AuthorizationSetBuilder()
+                    .Authorization(TAG_NO_AUTH_REQUIRED)
+                    .EcdsaKey(ecCurve)
+                    .AttestKey()
+                    .Digest(digest)
+                    .AttestationChallenge(challenge)
+                    .AttestationApplicationId(id)
+                    .SetDefaultValidity()
+                    .Authorization(TAG_CREATION_DATETIME, timestamp)
+                    .Authorization(TAG_INCLUDE_UNIQUE_ID)
+                    .Authorization(TAG_PURPOSE, KeyPurpose::ATTEST_KEY);
+        } break;
+        default:
+            break;
+    };
+    return AuthorizationSetBuilder();
+}
+
+AuthorizationSet createAuthorizationSet(FuzzedDataProvider* dataProvider) {
+    uint32_t authSet =
+            dataProvider->ConsumeIntegralInRange<uint32_t>(AuthSet::RSA_KEY, AuthSet::BLOCK_MODE);
+    uint64_t timestamp = dataProvider->ConsumeIntegral<uint64_t>();
+    Digest digest = dataProvider->PickValueInArray(kDigest);
+    PaddingMode padding = dataProvider->PickValueInArray(kPaddingMode);
+    std::string challenge = dataProvider->ConsumeRandomLengthString(kStringSize);
+    std::string id = dataProvider->ConsumeRandomLengthString(kStringSize);
+    switch (authSet) {
+        case RSA_KEY: {
+            return AuthorizationSetBuilder()
+                    .Authorization(TAG_NO_AUTH_REQUIRED)
+                    .RsaKey(kRsaKeySize, kPublicExponent)
+                    .Digest(digest)
+                    .Padding(padding)
+                    .AttestKey()
+                    .AttestationChallenge(challenge)
+                    .AttestationApplicationId(id)
+                    .SetDefaultValidity()
+                    .Authorization(TAG_CREATION_DATETIME, timestamp)
+                    .Authorization(TAG_INCLUDE_UNIQUE_ID);
+        } break;
+        case RSA_SIGNING_KEY: {
+            return AuthorizationSetBuilder()
+                    .Authorization(TAG_NO_AUTH_REQUIRED)
+                    .RsaSigningKey(kRsaKeySize, kPublicExponent)
+                    .Digest(digest)
+                    .Padding(padding)
+                    .AttestationChallenge(challenge)
+                    .AttestationApplicationId(id)
+                    .SetDefaultValidity()
+                    .Authorization(TAG_CREATION_DATETIME, timestamp)
+                    .Authorization(TAG_INCLUDE_UNIQUE_ID);
+        } break;
+        case RSA_ENCRYPTION_KEY: {
+            return AuthorizationSetBuilder()
+                    .Authorization(TAG_NO_AUTH_REQUIRED)
+                    .RsaEncryptionKey(kRsaKeySize, kPublicExponent)
+                    .Digest(digest)
+                    .Padding(padding)
+                    .AttestationChallenge(challenge)
+                    .AttestationApplicationId(id)
+                    .SetDefaultValidity()
+                    .Authorization(TAG_CREATION_DATETIME, timestamp)
+                    .Authorization(TAG_INCLUDE_UNIQUE_ID);
+        } break;
+        case ECDSA_SIGNING_CURVE: {
+            EcCurve ecCurve = dataProvider->PickValueInArray(kCurve);
+            return AuthorizationSetBuilder()
+                    .Authorization(TAG_NO_AUTH_REQUIRED)
+                    .EcdsaSigningKey(ecCurve)
+                    .Digest(digest)
+                    .AttestationChallenge(challenge)
+                    .AttestationApplicationId(id)
+                    .SetDefaultValidity()
+                    .Authorization(TAG_CREATION_DATETIME, timestamp)
+                    .Authorization(TAG_INCLUDE_UNIQUE_ID);
+        } break;
+        case AES_ENCRYPTION_KEY: {
+            BlockMode blockmode = dataProvider->PickValueInArray(kBlockMode);
+            return AuthorizationSetBuilder()
+                    .Authorization(TAG_NO_AUTH_REQUIRED)
+                    .AesEncryptionKey(kSymmKeySize)
+                    .BlockMode(blockmode)
+                    .Digest(digest)
+                    .Padding(padding);
+        } break;
+        case TRIPLE_DES: {
+            BlockMode blockmode = dataProvider->PickValueInArray(kBlockMode);
+            return AuthorizationSetBuilder()
+                    .Authorization(TAG_NO_AUTH_REQUIRED)
+                    .TripleDesEncryptionKey(k3DesKeySize)
+                    .BlockMode(blockmode)
+                    .Digest(digest)
+                    .Padding(padding)
+                    .EcbMode()
+                    .SetDefaultValidity();
+        } break;
+        case HMAC: {
+            return AuthorizationSetBuilder()
+                    .Authorization(TAG_NO_AUTH_REQUIRED)
+                    .HmacKey(kSymmKeySize)
+                    .Digest(digest)
+                    .Padding(padding);
+        } break;
+        case NO_DIGEST: {
+            return AuthorizationSetBuilder()
+                    .Authorization(TAG_NO_AUTH_REQUIRED)
+                    .AesEncryptionKey(kSymmKeySize)
+                    .NoDigestOrPadding()
+                    .Digest(digest)
+                    .Padding(padding);
+        } break;
+        case ECB_MODE: {
+            return AuthorizationSetBuilder()
+                    .Authorization(TAG_NO_AUTH_REQUIRED)
+                    .AesEncryptionKey(kSymmKeySize)
+                    .EcbMode()
+                    .Digest(digest)
+                    .Padding(padding);
+        } break;
+        case GSM_MODE_MIN_MAC: {
+            uint32_t minMacLength = dataProvider->ConsumeIntegral<uint32_t>();
+            return AuthorizationSetBuilder()
+                    .Authorization(TAG_NO_AUTH_REQUIRED)
+                    .AesEncryptionKey(kSymmKeySize)
+                    .GcmModeMinMacLen(minMacLength)
+                    .Digest(digest)
+                    .Padding(padding);
+        } break;
+        case GSM_MODE_MAC: {
+            uint32_t macLength = dataProvider->ConsumeIntegral<uint32_t>();
+            return AuthorizationSetBuilder()
+                    .Authorization(TAG_NO_AUTH_REQUIRED)
+                    .AesEncryptionKey(kSymmKeySize)
+                    .GcmModeMacLen(macLength)
+                    .Digest(digest)
+                    .Padding(padding);
+        } break;
+        case BLOCK_MODE: {
+            BlockMode blockmode = dataProvider->PickValueInArray(kBlockMode);
+            return AuthorizationSetBuilder()
+                    .Authorization(TAG_NO_AUTH_REQUIRED)
+                    .AesEncryptionKey(kSymmKeySize)
+                    .BlockMode(blockmode)
+                    .Digest(digest)
+                    .Padding(padding);
+        } break;
+        default:
+            break;
+    };
+    return AuthorizationSetBuilder();
+}
+
+}  // namespace android::hardware::security::keymint_support::fuzzer
+
+#endif  // __KEYMINT_COMMON_H__
diff --git a/thermal/aidl/vts/VtsHalThermalTargetTest.cpp b/thermal/aidl/vts/VtsHalThermalTargetTest.cpp
index d36d986..7f33e2d 100644
--- a/thermal/aidl/vts/VtsHalThermalTargetTest.cpp
+++ b/thermal/aidl/vts/VtsHalThermalTargetTest.cpp
@@ -352,8 +352,8 @@
 // @VsrTest = VSR-3.2.5-002
 TEST_P(ThermalAidlTest, SkinTemperatureThresholdsTest) {
     auto apiLevel = ::android::base::GetIntProperty<int32_t>("ro.vendor.api_level", 0);
-    if (apiLevel < 35) {
-        GTEST_SKIP() << "Skipping test as the vendor level is below 35: " << apiLevel;
+    if (apiLevel < 202404) {
+        GTEST_SKIP() << "Skipping test as the vendor level is below 202404: " << apiLevel;
     }
     for (const auto& feature : kNonHandheldFeatures) {
         if (::testing::deviceSupportsFeature(feature.c_str())) {
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 d02cf4d..bb543f2 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
@@ -46,4 +46,5 @@
   NB_OF_ELEVATION_MEASUREMENTS = 0xE5,
   ENABLE_DIAGNOSTICS = 0xE8,
   DIAGRAMS_FRAME_REPORTS_FIELDS = 0xE9,
+  ANTENNA_MODE = 0xEA,
 }
diff --git a/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorSessionAppConfigTlvTypes.aidl b/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorSessionAppConfigTlvTypes.aidl
index 65bb1c9..b8b4490 100644
--- a/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorSessionAppConfigTlvTypes.aidl
+++ b/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorSessionAppConfigTlvTypes.aidl
@@ -87,4 +87,12 @@
      * b3 - b7: RFU
      */
     DIAGRAMS_FRAME_REPORTS_FIELDS = 0xE9,
+
+    /**
+     * 1 byte data
+     * 0x0: Omni mode - the ranging antenna is used for both Tx and Rx.
+     * 0x1: Directional mode - the patch antenna is used for both Tx and Rx.
+     * 0x2 - 0xFF: RFU
+     */
+    ANTENNA_MODE = 0xEA,
 }
diff --git a/uwb/aidl/default/src/uwb_chip.rs b/uwb/aidl/default/src/uwb_chip.rs
index 878aa64..956cf6c 100644
--- a/uwb/aidl/default/src/uwb_chip.rs
+++ b/uwb/aidl/default/src/uwb_chip.rs
@@ -71,7 +71,7 @@
             let packet_vec: Vec<UciControlPacketHal> = packet.into();
             for hal_packet in packet_vec.into_iter() {
                 serial
-                    .write(&hal_packet.to_vec())
+                    .write(&hal_packet.encode_to_vec().unwrap())
                     .map(|written| written as i32)
                     .map_err(|_| binder::StatusCode::UNKNOWN_ERROR)?;
             }
diff --git a/wifi/aidl/default/wifi_legacy_hal.cpp b/wifi/aidl/default/wifi_legacy_hal.cpp
index cf86120..bd92a20 100644
--- a/wifi/aidl/default/wifi_legacy_hal.cpp
+++ b/wifi/aidl/default/wifi_legacy_hal.cpp
@@ -2012,7 +2012,7 @@
 }
 
 wifi_error WifiLegacyHal::setScanMode(const std::string& iface_name, bool enable) {
-    return global_func_table_.wifi_set_scan_mode(iface_name.c_str(), enable);
+    return global_func_table_.wifi_set_scan_mode(getIfaceHandle(iface_name), enable);
 }
 
 wifi_error WifiLegacyHal::setDtimConfig(const std::string& iface_name, uint32_t multiplier) {
diff --git a/wifi/aidl/vts/functional/wifi_sta_iface_aidl_test.cpp b/wifi/aidl/vts/functional/wifi_sta_iface_aidl_test.cpp
index c87fe13..f659bf6 100644
--- a/wifi/aidl/vts/functional/wifi_sta_iface_aidl_test.cpp
+++ b/wifi/aidl/vts/functional/wifi_sta_iface_aidl_test.cpp
@@ -148,7 +148,7 @@
  * Ensures the APF packet filter is fully supported as required in VSR 14:
  * https://docs.partner.android.com/gms/policies/vsr/vsr-14
  */
-// @VsrTest = 5.3.12
+// @VsrTest = VSR-5.3.12-001|VSR-5.3.12-003|VSR-5.3.12-004|VSR-5.3.12-009
 TEST_P(WifiStaIfaceAidlTest, CheckApfIsSupported) {
     const std::string oem_key1 = getPropertyString("ro.oem.key1");
     if (isTvDevice()) {
diff --git a/wifi/legacy_headers/include/hardware_legacy/wifi_hal.h b/wifi/legacy_headers/include/hardware_legacy/wifi_hal.h
index e770777..9baa2c7 100644
--- a/wifi/legacy_headers/include/hardware_legacy/wifi_hal.h
+++ b/wifi/legacy_headers/include/hardware_legacy/wifi_hal.h
@@ -715,7 +715,7 @@
 
 /* Wi-Fi coex channel avoidance support */
 
-#define WIFI_COEX_NO_POWER_CAP (int32_t)0x7FFFFFF
+#define WIFI_COEX_NO_POWER_CAP (int32_t)0x7FFFFFFF
 
 typedef enum {
     WIFI_AWARE = 1 << 0,
@@ -1386,7 +1386,7 @@
      * @param enable true if current is scan only mode
      * @return Synchronous wifi_error
      */
-    wifi_error (*wifi_set_scan_mode)(const char * ifname, bool enable);
+    wifi_error (*wifi_set_scan_mode)(wifi_interface_handle iface, bool enable);
 
     wifi_error (*wifi_nan_pairing_end)(transaction_id id,
                                     wifi_interface_handle iface,