Merge "More canonicalization checks and canonicalize before signing"
diff --git a/audio/aidl/OWNERS b/audio/aidl/OWNERS
new file mode 100644
index 0000000..f9a2d6b
--- /dev/null
+++ b/audio/aidl/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 48436
+elaurent@google.com
+mnaganov@google.com
diff --git a/audio/common/all-versions/default/Android.bp b/audio/common/all-versions/default/Android.bp
index a25565d..9543674 100644
--- a/audio/common/all-versions/default/Android.bp
+++ b/audio/common/all-versions/default/Android.bp
@@ -211,6 +211,8 @@
     name: "android.hardware.audio.common@7.0-util_tests",
     defaults: ["android.hardware.audio.common-util_default"],
 
+    tidy_timeout_srcs: ["tests/hidlutils_tests.cpp"],
+
     srcs: ["tests/hidlutils_tests.cpp"],
 
     // Use static linking to allow running in presubmit on
@@ -241,6 +243,8 @@
     name: "android.hardware.audio.common@7.1-util_tests",
     defaults: ["android.hardware.audio.common-util_default"],
 
+    tidy_timeout_srcs: ["tests/hidlutils_tests.cpp"],
+
     srcs: ["tests/hidlutils_tests.cpp"],
 
     // Use static linking to allow running in presubmit on
diff --git a/audio/common/all-versions/default/service/Android.bp b/audio/common/all-versions/default/service/Android.bp
index 1bd6abe..9890be2 100644
--- a/audio/common/all-versions/default/service/Android.bp
+++ b/audio/common/all-versions/default/service/Android.bp
@@ -52,6 +52,7 @@
     shared_libs: [
         "libcutils",
         "libbinder",
+        "libbinder_ndk",
         "libhidlbase",
         "liblog",
         "libutils",
diff --git a/audio/common/all-versions/default/service/service.cpp b/audio/common/all-versions/default/service/service.cpp
index e26369f..fbf6165 100644
--- a/audio/common/all-versions/default/service/service.cpp
+++ b/audio/common/all-versions/default/service/service.cpp
@@ -20,8 +20,10 @@
 #include <string>
 #include <vector>
 
+#include <android/binder_process.h>
 #include <binder/ProcessState.h>
 #include <cutils/properties.h>
+#include <dlfcn.h>
 #include <hidl/HidlTransportSupport.h>
 #include <hidl/LegacySupport.h>
 #include <hwbinder/ProcessState.h>
@@ -45,6 +47,31 @@
     return false;
 }
 
+static bool registerExternalServiceImplementation(const std::string& libName,
+                                                  const std::string& funcName) {
+    constexpr int dlMode = RTLD_LAZY;
+    void* handle = nullptr;
+    dlerror();  // clear
+    auto libPath = libName + ".so";
+    handle = dlopen(libPath.c_str(), dlMode);
+    if (handle == nullptr) {
+        const char* error = dlerror();
+        ALOGE("Failed to dlopen %s: %s", libPath.c_str(),
+              error != nullptr ? error : "unknown error");
+        return false;
+    }
+    binder_status_t (*factoryFunction)();
+    *(void**)(&factoryFunction) = dlsym(handle, funcName.c_str());
+    if (!factoryFunction) {
+        const char* error = dlerror();
+        ALOGE("Factory function %s not found in libName %s: %s", funcName.c_str(), libPath.c_str(),
+              error != nullptr ? error : "unknown error");
+        dlclose(handle);
+        return false;
+    }
+    return ((*factoryFunction)() == STATUS_OK);
+}
+
 int main(int /* argc */, char* /* argv */ []) {
     signal(SIGPIPE, SIG_IGN);
 
@@ -52,6 +79,9 @@
     // start a threadpool for vndbinder interactions
     ::android::ProcessState::self()->startThreadPool();
 
+    ABinderProcess_setThreadPoolMaxThreadCount(1);
+    ABinderProcess_startThreadPool();
+
     const int32_t defaultValue = -1;
     int32_t value =
         property_get_int32("persist.vendor.audio.service.hwbinder.size_kbyte", defaultValue);
@@ -101,6 +131,13 @@
             "android.hardware.bluetooth.a2dp@1.0::IBluetoothAudioOffload"
         }
     };
+
+    const std::vector<std::pair<std::string,std::string>> optionalInterfaceSharedLibs = {
+        {
+            "android.hardware.bluetooth.audio-impl",
+            "createIBluetoothAudioProviderFactory",
+        },
+    };
     // clang-format on
 
     for (const auto& listIter : mandatoryInterfaces) {
@@ -117,5 +154,15 @@
                  "Could not register %s", interfaceFamilyName.c_str());
     }
 
+    for (const auto& interfacePair : optionalInterfaceSharedLibs) {
+        const std::string& libraryName = interfacePair.first;
+        const std::string& interfaceLoaderFuncName = interfacePair.second;
+        if (registerExternalServiceImplementation(libraryName, interfaceLoaderFuncName)) {
+            ALOGI("%s() from %s success", interfaceLoaderFuncName.c_str(), libraryName.c_str());
+        } else {
+            ALOGW("%s() from %s failed", interfaceLoaderFuncName.c_str(), libraryName.c_str());
+        }
+    }
+
     joinRpcThreadpool();
 }
diff --git a/audio/core/all-versions/vts/functional/Android.bp b/audio/core/all-versions/vts/functional/Android.bp
index 0370895..3007f01 100644
--- a/audio/core/all-versions/vts/functional/Android.bp
+++ b/audio/core/all-versions/vts/functional/Android.bp
@@ -48,6 +48,9 @@
 cc_test {
     name: "VtsHalAudioV2_0TargetTest",
     defaults: ["VtsHalAudioTargetTest_defaults"],
+    tidy_timeout_srcs: [
+        "2.0/AudioPrimaryHidlHalTest.cpp",
+    ],
     srcs: [
         "2.0/AudioPrimaryHidlHalTest.cpp",
     ],
@@ -74,6 +77,9 @@
 cc_test {
     name: "VtsHalAudioV4_0TargetTest",
     defaults: ["VtsHalAudioTargetTest_defaults"],
+    tidy_timeout_srcs: [
+        "4.0/AudioPrimaryHidlHalTest.cpp",
+    ],
     srcs: [
         "4.0/AudioPrimaryHidlHalTest.cpp",
     ],
@@ -126,6 +132,9 @@
 cc_test {
     name: "VtsHalAudioV6_0TargetTest",
     defaults: ["VtsHalAudioTargetTest_defaults"],
+    tidy_timeout_srcs: [
+        "6.0/AudioPrimaryHidlHalTest.cpp",
+    ],
     srcs: [
         "6.0/AudioPrimaryHidlHalTest.cpp",
         "6.0/Generators.cpp",
@@ -153,6 +162,9 @@
 cc_test {
     name: "VtsHalAudioV7_0TargetTest",
     defaults: ["VtsHalAudioTargetTest_defaults"],
+    tidy_timeout_srcs: [
+        "7.0/AudioPrimaryHidlHalTest.cpp",
+    ],
     srcs: [
         "7.0/AudioPrimaryHidlHalTest.cpp",
         "7.0/Generators.cpp",
diff --git a/audio/effect/all-versions/vts/functional/Android.bp b/audio/effect/all-versions/vts/functional/Android.bp
index 48d6474..3b15ed4 100644
--- a/audio/effect/all-versions/vts/functional/Android.bp
+++ b/audio/effect/all-versions/vts/functional/Android.bp
@@ -26,6 +26,9 @@
 cc_defaults {
     name: "VtsHalAudioEffectTargetTest_default",
     defaults: ["VtsHalTargetTestDefaults"],
+    tidy_timeout_srcs: [
+        "VtsHalAudioEffectTargetTest.cpp",
+    ],
     srcs: [
         "VtsHalAudioEffectTargetTest.cpp",
         "ValidateAudioEffectsConfiguration.cpp",
diff --git a/automotive/can/1.0/default/Android.bp b/automotive/can/1.0/default/Android.bp
index c0c17e2..05691d9 100644
--- a/automotive/can/1.0/default/Android.bp
+++ b/automotive/can/1.0/default/Android.bp
@@ -46,13 +46,7 @@
     vendor: true,
     relative_install_path: "hw",
     srcs: [
-        "CanBus.cpp",
-        "CanBusNative.cpp",
-        "CanBusVirtual.cpp",
-        "CanBusSlcan.cpp",
-        "CanController.cpp",
-        "CanSocket.cpp",
-        "CloseHandle.cpp",
+        ":automotiveCanV1.0_sources",
         "service.cpp",
     ],
     shared_libs: [
@@ -64,4 +58,24 @@
         "android.hardware.automotive@libc++fs",
         "libnl++",
     ],
+    vintf_fragments: ["manifest_android.hardware.automotive.can@1.0.xml"],
+}
+
+filegroup {
+    name: "automotiveCanV1.0_sources",
+    srcs: [
+        "CanBus.cpp",
+        "CanBusNative.cpp",
+        "CanBusVirtual.cpp",
+        "CanBusSlcan.cpp",
+        "CanController.cpp",
+        "CanSocket.cpp",
+        "CloseHandle.cpp",
+    ],
+}
+
+cc_library_headers {
+    name: "automotiveCanV1.0_headers",
+    vendor: true,
+    export_include_dirs: ["."],
 }
diff --git a/automotive/can/1.0/default/manifest_android.hardware.automotive.can@1.0.xml b/automotive/can/1.0/default/manifest_android.hardware.automotive.can@1.0.xml
new file mode 100644
index 0000000..2078ce5
--- /dev/null
+++ b/automotive/can/1.0/default/manifest_android.hardware.automotive.can@1.0.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 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.
+-->
+<manifest version="1.0" type="device" >
+    <hal format="hidl">
+        <name>android.hardware.automotive.can</name>
+        <transport>hwbinder</transport>
+        <fqname>@1.0::ICanController/socketcan</fqname>
+    </hal>
+</manifest>
diff --git a/automotive/can/1.0/default/tests/fuzzer/Android.bp b/automotive/can/1.0/default/tests/fuzzer/Android.bp
new file mode 100644
index 0000000..52b43b0
--- /dev/null
+++ b/automotive/can/1.0/default/tests/fuzzer/Android.bp
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package {
+    // 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"],
+}
+
+cc_fuzz {
+    name: "automotiveCanV1.0_fuzzer",
+    vendor: true,
+    defaults: ["android.hardware.automotive.can@defaults"],
+    srcs: [
+        "AutomotiveCanV1_0Fuzzer.cpp",
+        ":automotiveCanV1.0_sources",
+    ],
+    header_libs: [
+        "automotiveCanV1.0_headers",
+        "android.hardware.automotive.can@hidl-utils-lib",
+    ],
+    shared_libs: [
+        "android.hardware.automotive.can@1.0",
+        "libhidlbase",
+    ],
+    static_libs: [
+        "android.hardware.automotive.can@libnetdevice",
+        "android.hardware.automotive@libc++fs",
+        "libnl++",
+    ],
+    fuzz_config: {
+        cc: [
+            "android-media-fuzzing-reports@google.com",
+        ],
+        componentid: 533764,
+    },
+}
diff --git a/automotive/can/1.0/default/tests/fuzzer/AutomotiveCanV1_0Fuzzer.cpp b/automotive/can/1.0/default/tests/fuzzer/AutomotiveCanV1_0Fuzzer.cpp
new file mode 100644
index 0000000..96110db
--- /dev/null
+++ b/automotive/can/1.0/default/tests/fuzzer/AutomotiveCanV1_0Fuzzer.cpp
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+#include "AutomotiveCanV1_0Fuzzer.h"
+
+namespace android::hardware::automotive::can::V1_0::implementation::fuzzer {
+
+constexpr CanController::InterfaceType kInterfaceType[] = {CanController::InterfaceType::VIRTUAL,
+                                                           CanController::InterfaceType::SOCKETCAN,
+                                                           CanController::InterfaceType::SLCAN};
+constexpr FilterFlag kFilterFlag[] = {FilterFlag::DONT_CARE, FilterFlag::SET, FilterFlag::NOT_SET};
+constexpr size_t kInterfaceTypeLength = std::size(kInterfaceType);
+constexpr size_t kFilterFlagLength = std::size(kFilterFlag);
+constexpr size_t kMaxCharacters = 30;
+constexpr size_t kMaxPayloadBytes = 64;
+constexpr size_t kMaxFilters = 20;
+constexpr size_t kMaxSerialNumber = 1000;
+constexpr size_t kMaxBuses = 10;
+constexpr size_t kMaxRepeat = 5;
+
+Bus CanFuzzer::makeBus() {
+    ICanController::BusConfig config = {};
+    if (mBusNames.size() > 0 && mLastInterface < mBusNames.size()) {
+        config.name = mBusNames[mLastInterface++];
+    } else {
+        config.name = mFuzzedDataProvider->ConsumeRandomLengthString(kMaxCharacters);
+    }
+    config.interfaceId.virtualif({mFuzzedDataProvider->ConsumeRandomLengthString(kMaxCharacters)});
+    return Bus(mCanController, config);
+}
+
+void CanFuzzer::getSupportedInterfaceTypes() {
+    hidl_vec<CanController::InterfaceType> iftypesResult;
+    mCanController->getSupportedInterfaceTypes(hidl_utils::fill(&iftypesResult));
+}
+
+hidl_vec<hidl_string> CanFuzzer::getBusNames() {
+    hidl_vec<hidl_string> services = {};
+    if (auto manager = hidl::manager::V1_2::IServiceManager::getService(); manager) {
+        manager->listManifestByInterface(ICanBus::descriptor, hidl_utils::fill(&services));
+    }
+    return services;
+}
+
+void CanFuzzer::invokeUpInterface() {
+    const CanController::InterfaceType iftype =
+            kInterfaceType[mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(
+                    0, kInterfaceTypeLength - 1)];
+    std::string configName;
+
+    if (const bool shouldInvokeValidBus = mFuzzedDataProvider->ConsumeBool();
+        (shouldInvokeValidBus) && (mBusNames.size() > 0)) {
+        const size_t busNameIndex =
+                mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(0, mBusNames.size() - 1);
+        configName = mBusNames[busNameIndex];
+    } else {
+        configName = mFuzzedDataProvider->ConsumeRandomLengthString(kMaxCharacters);
+    }
+    const std::string ifname = mFuzzedDataProvider->ConsumeRandomLengthString(kMaxCharacters);
+
+    ICanController::BusConfig config = {.name = configName};
+
+    if (iftype == CanController::InterfaceType::SOCKETCAN) {
+        CanController::BusConfig::InterfaceId::Socketcan socketcan = {};
+        if (const bool shouldPassSerialSocket = mFuzzedDataProvider->ConsumeBool();
+            shouldPassSerialSocket) {
+            socketcan.serialno(
+                    {mFuzzedDataProvider->ConsumeIntegralInRange<uint32_t>(0, kMaxSerialNumber)});
+        } else {
+            socketcan.ifname(ifname);
+        }
+        config.interfaceId.socketcan(socketcan);
+    } else if (iftype == CanController::InterfaceType::SLCAN) {
+        CanController::BusConfig::InterfaceId::Slcan slcan = {};
+        if (const bool shouldPassSerialSlcan = mFuzzedDataProvider->ConsumeBool();
+            shouldPassSerialSlcan) {
+            slcan.serialno(
+                    {mFuzzedDataProvider->ConsumeIntegralInRange<uint32_t>(0, kMaxSerialNumber)});
+        } else {
+            slcan.ttyname(ifname);
+        }
+        config.interfaceId.slcan(slcan);
+    } else if (iftype == CanController::InterfaceType::VIRTUAL) {
+        config.interfaceId.virtualif({ifname});
+    }
+
+    const size_t numInvocations =
+            mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(0, kMaxRepeat);
+    for (size_t i = 0; i < numInvocations; ++i) {
+        mCanController->upInterface(config);
+    }
+}
+
+void CanFuzzer::invokeDownInterface() {
+    hidl_string configName;
+    if (const bool shouldInvokeValidBus = mFuzzedDataProvider->ConsumeBool();
+        (shouldInvokeValidBus) && (mBusNames.size() > 0)) {
+        const size_t busNameIndex =
+                mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(0, mBusNames.size() - 1);
+        configName = mBusNames[busNameIndex];
+    } else {
+        configName = mFuzzedDataProvider->ConsumeRandomLengthString(kMaxCharacters);
+    }
+
+    const size_t numInvocations =
+            mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(0, kMaxRepeat);
+    for (size_t i = 0; i < numInvocations; ++i) {
+        mCanController->downInterface(configName);
+    }
+}
+
+void CanFuzzer::invokeController() {
+    getSupportedInterfaceTypes();
+    invokeUpInterface();
+    invokeDownInterface();
+}
+
+void CanFuzzer::invokeBus() {
+    const size_t numBuses = mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(1, kMaxBuses);
+    for (size_t i = 0; i < numBuses; ++i) {
+        if (const bool shouldSendMessage = mFuzzedDataProvider->ConsumeBool(); shouldSendMessage) {
+            auto sendingBus = makeBus();
+            CanMessage msg = {.id = mFuzzedDataProvider->ConsumeIntegral<uint32_t>()};
+            uint32_t numPayloadBytes =
+                    mFuzzedDataProvider->ConsumeIntegralInRange<uint32_t>(0, kMaxPayloadBytes);
+            hidl_vec<uint8_t> payload(numPayloadBytes);
+            for (uint32_t j = 0; j < numPayloadBytes; ++j) {
+                payload[j] = mFuzzedDataProvider->ConsumeIntegral<uint32_t>();
+            }
+            msg.payload = payload;
+            msg.remoteTransmissionRequest = mFuzzedDataProvider->ConsumeBool();
+            msg.isExtendedId = mFuzzedDataProvider->ConsumeBool();
+            sendingBus.send(msg);
+        } else {
+            auto listeningBus = makeBus();
+            uint32_t numFilters =
+                    mFuzzedDataProvider->ConsumeIntegralInRange<uint32_t>(1, kMaxFilters);
+            hidl_vec<CanMessageFilter> filterVector(numFilters);
+            for (uint32_t k = 0; k < numFilters; ++k) {
+                filterVector[k].id = mFuzzedDataProvider->ConsumeIntegral<uint32_t>();
+                filterVector[k].mask = mFuzzedDataProvider->ConsumeIntegral<uint32_t>();
+                filterVector[k].rtr =
+                        kFilterFlag[mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(
+                                0, kFilterFlagLength - 1)];
+                filterVector[k].extendedFormat =
+                        kFilterFlag[mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(
+                                0, kFilterFlagLength - 1)];
+                filterVector[k].exclude = mFuzzedDataProvider->ConsumeBool();
+            }
+            auto listener = listeningBus.listen(filterVector);
+        }
+    }
+}
+
+void CanFuzzer::deInit() {
+    mCanController.clear();
+    if (mFuzzedDataProvider) {
+        delete mFuzzedDataProvider;
+    }
+    mBusNames = {};
+}
+
+void CanFuzzer::process(const uint8_t* data, size_t size) {
+    mFuzzedDataProvider = new FuzzedDataProvider(data, size);
+    invokeController();
+    invokeBus();
+}
+
+bool CanFuzzer::init() {
+    mCanController = sp<CanController>::make();
+    if (!mCanController) {
+        return false;
+    }
+    mBusNames = getBusNames();
+    return true;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    if (size < 1) {
+        return 0;
+    }
+    CanFuzzer canFuzzer;
+    if (canFuzzer.init()) {
+        canFuzzer.process(data, size);
+    }
+    return 0;
+}
+
+}  // namespace android::hardware::automotive::can::V1_0::implementation::fuzzer
diff --git a/automotive/can/1.0/default/tests/fuzzer/AutomotiveCanV1_0Fuzzer.h b/automotive/can/1.0/default/tests/fuzzer/AutomotiveCanV1_0Fuzzer.h
new file mode 100644
index 0000000..930cddd
--- /dev/null
+++ b/automotive/can/1.0/default/tests/fuzzer/AutomotiveCanV1_0Fuzzer.h
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+#ifndef __AUTOMOTIVE_CAN_V1_0_FUZZER_H__
+#define __AUTOMOTIVE_CAN_V1_0_FUZZER_H__
+#include <CanController.h>
+#include <android/hidl/manager/1.2/IServiceManager.h>
+#include <fuzzer/FuzzedDataProvider.h>
+#include <hidl-utils/hidl-utils.h>
+
+namespace android::hardware::automotive::can::V1_0::implementation::fuzzer {
+
+using ::android::sp;
+
+struct CanMessageListener : public can::V1_0::ICanMessageListener {
+    DISALLOW_COPY_AND_ASSIGN(CanMessageListener);
+
+    CanMessageListener() {}
+
+    virtual Return<void> onReceive(const can::V1_0::CanMessage& msg) override {
+        std::unique_lock<std::mutex> lock(mMessagesGuard);
+        mMessages.push_back(msg);
+        mMessagesUpdated.notify_one();
+        return {};
+    }
+
+    virtual ~CanMessageListener() {
+        if (mCloseHandle) {
+            mCloseHandle->close();
+        }
+    }
+
+    void assignCloseHandle(sp<ICloseHandle> closeHandle) { mCloseHandle = closeHandle; }
+
+  private:
+    sp<ICloseHandle> mCloseHandle;
+
+    std::mutex mMessagesGuard;
+    std::condition_variable mMessagesUpdated GUARDED_BY(mMessagesGuard);
+    std::vector<can::V1_0::CanMessage> mMessages GUARDED_BY(mMessagesGuard);
+};
+
+struct Bus {
+    DISALLOW_COPY_AND_ASSIGN(Bus);
+
+    Bus(sp<ICanController> controller, const ICanController::BusConfig& config)
+        : mIfname(config.name), mController(controller) {
+        const auto result = controller->upInterface(config);
+        const auto manager = hidl::manager::V1_2::IServiceManager::getService();
+        const auto service = manager->get(ICanBus::descriptor, config.name);
+        mBus = ICanBus::castFrom(service);
+    }
+
+    virtual ~Bus() { reset(); }
+
+    void reset() {
+        mBus.clear();
+        if (mController) {
+            mController->downInterface(mIfname);
+            mController.clear();
+        }
+    }
+
+    ICanBus* operator->() const { return mBus.get(); }
+    sp<ICanBus> get() { return mBus; }
+
+    sp<CanMessageListener> listen(const hidl_vec<CanMessageFilter>& filter) {
+        sp<CanMessageListener> listener = sp<CanMessageListener>::make();
+
+        if (!mBus) {
+            return listener;
+        }
+        Result result;
+        sp<ICloseHandle> closeHandle;
+        mBus->listen(filter, listener, hidl_utils::fill(&result, &closeHandle)).assertOk();
+        listener->assignCloseHandle(closeHandle);
+
+        return listener;
+    }
+
+    void send(const CanMessage& msg) {
+        if (!mBus) {
+            return;
+        }
+        mBus->send(msg);
+    }
+
+  private:
+    const std::string mIfname;
+    sp<ICanController> mController;
+    sp<ICanBus> mBus;
+};
+
+class CanFuzzer {
+  public:
+    ~CanFuzzer() { deInit(); }
+    bool init();
+    void process(const uint8_t* data, size_t size);
+    void deInit();
+
+  private:
+    Bus makeBus();
+    hidl_vec<hidl_string> getBusNames();
+    void getSupportedInterfaceTypes();
+    void invokeBus();
+    void invokeController();
+    void invokeUpInterface();
+    void invokeDownInterface();
+    FuzzedDataProvider* mFuzzedDataProvider = nullptr;
+    sp<CanController> mCanController = nullptr;
+    hidl_vec<hidl_string> mBusNames = {};
+    unsigned mLastInterface = 0;
+};
+}  // namespace android::hardware::automotive::can::V1_0::implementation::fuzzer
+
+#endif  // __AUTOMOTIVE_CAN_V1_0_FUZZER_H__
diff --git a/automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp b/automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp
index ad607d8..9c72acd 100644
--- a/automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp
+++ b/automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp
@@ -18,7 +18,7 @@
 
 
 // These values are called out in the EVS design doc (as of Mar 8, 2017)
-static const int kMaxStreamStartMilliseconds = 500;
+static const int kMaxStreamStartMilliseconds = 1000;
 static const int kMinimumFramesPerSecond = 10;
 
 static const int kSecondsToMilliseconds = 1000;
@@ -332,11 +332,6 @@
         printf("Measured time to first frame %0.2f ms\n", timeToFirstFrame * kNanoToMilliseconds);
         ALOGI("Measured time to first frame %0.2f ms", timeToFirstFrame * kNanoToMilliseconds);
 
-        // Check aspect ratio
-        unsigned width = 0, height = 0;
-        frameHandler->getFrameDimension(&width, &height);
-        EXPECT_GE(width, height);
-
         // Wait a bit, then ensure we get at least the required minimum number of frames
         sleep(5);
         nsecs_t end = systemTime(SYSTEM_TIME_MONOTONIC);
@@ -370,7 +365,7 @@
     ALOGI("Starting CameraStreamBuffering test");
 
     // Arbitrary constant (should be > 1 and not too big)
-    static const unsigned int kBuffersToHold = 6;
+    static const unsigned int kBuffersToHold = 2;
 
     // Get the camera list
     loadCameraList();
diff --git a/automotive/evs/1.1/vts/functional/Android.bp b/automotive/evs/1.1/vts/functional/Android.bp
index cbc2150..18687bf 100644
--- a/automotive/evs/1.1/vts/functional/Android.bp
+++ b/automotive/evs/1.1/vts/functional/Android.bp
@@ -25,6 +25,9 @@
 
 cc_test {
     name: "VtsHalEvsV1_1TargetTest",
+    tidy_timeout_srcs: [
+        "VtsHalEvsV1_1TargetTest.cpp",
+    ],
     srcs: [
         "FrameHandler.cpp",
         "FrameHandlerUltrasonics.cpp",
diff --git a/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp b/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp
index 8cc1882..d7f9ff8 100644
--- a/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp
+++ b/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp
@@ -79,19 +79,24 @@
 using IEvsDisplay_1_0 = ::android::hardware::automotive::evs::V1_0::IEvsDisplay;
 using IEvsDisplay_1_1 = ::android::hardware::automotive::evs::V1_1::IEvsDisplay;
 
+namespace {
+
 /*
  * Plese note that this is different from what is defined in
  * libhardware/modules/camera/3_4/metadata/types.h; this has one additional
  * field to store a framerate.
  */
-const size_t kStreamCfgSz = 5;
 typedef struct {
+    int32_t id;
     int32_t width;
     int32_t height;
     int32_t format;
     int32_t direction;
     int32_t framerate;
 } RawStreamConfig;
+constexpr const size_t kStreamCfgSz = sizeof(RawStreamConfig) / sizeof(int32_t);
+
+} // anonymous namespace
 
 
 // The main test class for EVS
@@ -236,6 +241,28 @@
         return physicalCameras;
     }
 
+    Stream getFirstStreamConfiguration(camera_metadata_t* metadata) {
+        Stream targetCfg = {};
+        camera_metadata_entry_t streamCfgs;
+        if (!find_camera_metadata_entry(metadata,
+                 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
+                 &streamCfgs)) {
+            // Stream configurations are found in metadata
+            RawStreamConfig *ptr = reinterpret_cast<RawStreamConfig *>(streamCfgs.data.i32);
+            for (unsigned offset = 0; offset < streamCfgs.count; offset += kStreamCfgSz) {
+                if (ptr->direction == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT &&
+                    ptr->format == HAL_PIXEL_FORMAT_RGBA_8888) {
+                    targetCfg.width = ptr->width;
+                    targetCfg.height = ptr->height;
+                    targetCfg.format = static_cast<PixelFormat>(ptr->format);
+                    break;
+                }
+                ++ptr;
+            }
+        }
+
+        return targetCfg;
+    }
 
     sp<IEvsEnumerator>              pEnumerator;   // Every test needs access to the service
     std::vector<CameraDesc>         cameraInfo;    // Empty unless/until loadCameraList() is called
@@ -265,10 +292,6 @@
     // Get the camera list
     loadCameraList();
 
-    // Using null stream configuration makes EVS uses the default resolution and
-    // output format.
-    Stream nullCfg = {};
-
     // Open and close each camera twice
     for (auto&& cam: cameraInfo) {
         bool isLogicalCam = false;
@@ -278,8 +301,14 @@
             continue;
         }
 
+        // Read a target resolution from the metadata
+        Stream targetCfg =
+            getFirstStreamConfiguration(reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+        ASSERT_GT(targetCfg.width, 0);
+        ASSERT_GT(targetCfg.height, 0);
+
         for (int pass = 0; pass < 2; pass++) {
-            sp<IEvsCamera_1_1> pCam = pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg);
+            sp<IEvsCamera_1_1> pCam = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
             ASSERT_NE(pCam, nullptr);
 
             for (auto&& devName : devices) {
@@ -343,10 +372,6 @@
     // Get the camera list
     loadCameraList();
 
-    // Using null stream configuration makes EVS uses the default resolution and
-    // output format.
-    Stream nullCfg = {};
-
     // Open and close each camera twice
     for (auto&& cam: cameraInfo) {
         bool isLogicalCam = false;
@@ -356,10 +381,14 @@
             continue;
         }
 
+        // Read a target resolution from the metadata
+        Stream targetCfg =
+            getFirstStreamConfiguration(reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+        ASSERT_GT(targetCfg.width, 0);
+        ASSERT_GT(targetCfg.height, 0);
+
         activeCameras.clear();
-        sp<IEvsCamera_1_1> pCam =
-            IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
-            .withDefault(nullptr);
+        sp<IEvsCamera_1_1> pCam = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
         ASSERT_NE(pCam, nullptr);
 
         // Store a camera handle for a clean-up
@@ -372,9 +401,7 @@
                                 }
         );
 
-        sp<IEvsCamera_1_1> pCam2 =
-            IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
-            .withDefault(nullptr);
+        sp<IEvsCamera_1_1> pCam2 = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
         ASSERT_NE(pCam2, nullptr);
 
         // Store a camera handle for a clean-up
@@ -422,10 +449,6 @@
     // Get the camera list
     loadCameraList();
 
-    // Using null stream configuration makes EVS uses the default resolution and
-    // output format.
-    Stream nullCfg = {};
-
     // Test each reported camera
     for (auto&& cam: cameraInfo) {
         bool isLogicalCam = false;
@@ -435,9 +458,13 @@
             continue;
         }
 
-        sp<IEvsCamera_1_1> pCam =
-            IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
-            .withDefault(nullptr);
+        // Read a target resolution from the metadata
+        Stream targetCfg =
+            getFirstStreamConfiguration(reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+        ASSERT_GT(targetCfg.width, 0);
+        ASSERT_GT(targetCfg.height, 0);
+
+        sp<IEvsCamera_1_1> pCam = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
         ASSERT_NE(pCam, nullptr);
 
         // Store a camera handle for a clean-up
@@ -472,11 +499,6 @@
                   << std::scientific << timeToFirstFrame * kNanoToMilliseconds
                   << " ms.";
 
-        // Check aspect ratio
-        unsigned width = 0, height = 0;
-        frameHandler->getFrameDimension(&width, &height);
-        EXPECT_GE(width, height);
-
         // Wait a bit, then ensure we get at least the required minimum number of frames
         sleep(5);
         nsecs_t end = systemTime(SYSTEM_TIME_MONOTONIC);
@@ -514,15 +536,11 @@
     LOG(INFO) << "Starting CameraStreamBuffering test";
 
     // Arbitrary constant (should be > 1 and not too big)
-    static const unsigned int kBuffersToHold = 6;
+    static const unsigned int kBuffersToHold = 2;
 
     // Get the camera list
     loadCameraList();
 
-    // Using null stream configuration makes EVS uses the default resolution and
-    // output format.
-    Stream nullCfg = {};
-
     // Test each reported camera
     for (auto&& cam: cameraInfo) {
         bool isLogicalCam = false;
@@ -532,9 +550,13 @@
             continue;
         }
 
-        sp<IEvsCamera_1_1> pCam =
-            IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
-            .withDefault(nullptr);
+        // Read a target resolution from the metadata
+        Stream targetCfg =
+            getFirstStreamConfiguration(reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+        ASSERT_GT(targetCfg.width, 0);
+        ASSERT_GT(targetCfg.height, 0);
+
+        sp<IEvsCamera_1_1> pCam = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
         ASSERT_NE(pCam, nullptr);
 
         // Store a camera handle for a clean-up
@@ -601,10 +623,6 @@
     // Get the camera list
     loadCameraList();
 
-    // Using null stream configuration makes EVS uses the default resolution and
-    // output format.
-    Stream nullCfg = {};
-
     // Request available display IDs
     uint8_t targetDisplayId = 0;
     pEnumerator->getDisplayIdList([&targetDisplayId](auto ids) {
@@ -642,9 +660,13 @@
             continue;
         }
 
-        sp<IEvsCamera_1_1> pCam =
-            IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
-            .withDefault(nullptr);
+        // Read a target resolution from the metadata
+        Stream targetCfg =
+            getFirstStreamConfiguration(reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+        ASSERT_GT(targetCfg.width, 0);
+        ASSERT_GT(targetCfg.height, 0);
+
+        sp<IEvsCamera_1_1> pCam = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
         ASSERT_NE(pCam, nullptr);
 
         // Store a camera handle for a clean-up
@@ -708,24 +730,22 @@
     // Get the camera list
     loadCameraList();
 
-    // Using null stream configuration makes EVS uses the default resolution and
-    // output format.
-    Stream nullCfg = {};
-
     // Test each reported camera
     for (auto&& cam: cameraInfo) {
+        // Read a target resolution from the metadata
+        Stream targetCfg =
+            getFirstStreamConfiguration(reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+        ASSERT_GT(targetCfg.width, 0);
+        ASSERT_GT(targetCfg.height, 0);
+
         // Create two camera clients.
-        sp<IEvsCamera_1_1> pCam0 =
-            IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
-            .withDefault(nullptr);
+        sp<IEvsCamera_1_1> pCam0 = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
         ASSERT_NE(pCam0, nullptr);
 
         // Store a camera handle for a clean-up
         activeCameras.push_back(pCam0);
 
-        sp<IEvsCamera_1_1> pCam1 =
-            IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
-            .withDefault(nullptr);
+        sp<IEvsCamera_1_1> pCam1 = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
         ASSERT_NE(pCam1, nullptr);
 
         // Store a camera handle for a clean-up
@@ -812,10 +832,6 @@
     // Get the camera list
     loadCameraList();
 
-    // Using null stream configuration makes EVS uses the default resolution and
-    // output format.
-    Stream nullCfg = {};
-
     // Test each reported camera
     Return<EvsResult> result = EvsResult::OK;
     for (auto&& cam: cameraInfo) {
@@ -828,10 +844,14 @@
             continue;
         }
 
+        // Read a target resolution from the metadata
+        Stream targetCfg =
+            getFirstStreamConfiguration(reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+        ASSERT_GT(targetCfg.width, 0);
+        ASSERT_GT(targetCfg.height, 0);
+
         // Create a camera client
-        sp<IEvsCamera_1_1> pCam =
-            IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
-            .withDefault(nullptr);
+        sp<IEvsCamera_1_1> pCam = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
         ASSERT_NE(pCam, nullptr);
 
         // Store a camera
@@ -961,10 +981,6 @@
     // Get the camera list
     loadCameraList();
 
-    // Using null stream configuration makes EVS uses the default resolution and
-    // output format.
-    Stream nullCfg = {};
-
     // Test each reported camera
     for (auto&& cam: cameraInfo) {
         bool isLogicalCam = false;
@@ -976,18 +992,20 @@
             continue;
         }
 
+        // Read a target resolution from the metadata
+        Stream targetCfg =
+            getFirstStreamConfiguration(reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+        ASSERT_GT(targetCfg.width, 0);
+        ASSERT_GT(targetCfg.height, 0);
+
         // Create two camera clients.
-        sp<IEvsCamera_1_1> pCamPrimary =
-            IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
-            .withDefault(nullptr);
+        sp<IEvsCamera_1_1> pCamPrimary = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
         ASSERT_NE(pCamPrimary, nullptr);
 
         // Store a camera handle for a clean-up
         activeCameras.push_back(pCamPrimary);
 
-        sp<IEvsCamera_1_1> pCamSecondary =
-            IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
-            .withDefault(nullptr);
+        sp<IEvsCamera_1_1> pCamSecondary = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
         ASSERT_NE(pCamSecondary, nullptr);
 
         // Store a camera handle for a clean-up
@@ -1142,10 +1160,6 @@
     // Get the camera list
     loadCameraList();
 
-    // Using null stream configuration makes EVS uses the default resolution and
-    // output format.
-    Stream nullCfg = {};
-
     // Test each reported camera
     for (auto&& cam: cameraInfo) {
         bool isLogicalCam = false;
@@ -1157,18 +1171,20 @@
             continue;
         }
 
+        // Read a target resolution from the metadata
+        Stream targetCfg =
+            getFirstStreamConfiguration(reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+        ASSERT_GT(targetCfg.width, 0);
+        ASSERT_GT(targetCfg.height, 0);
+
         // Create two camera clients.
-        sp<IEvsCamera_1_1> pCamPrimary =
-            IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
-            .withDefault(nullptr);
+        sp<IEvsCamera_1_1> pCamPrimary = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
         ASSERT_NE(pCamPrimary, nullptr);
 
         // Store a camera handle for a clean-up
         activeCameras.push_back(pCamPrimary);
 
-        sp<IEvsCamera_1_1> pCamSecondary =
-            IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
-            .withDefault(nullptr);
+        sp<IEvsCamera_1_1> pCamSecondary = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
         ASSERT_NE(pCamSecondary, nullptr);
 
         // Store a camera handle for a clean-up
@@ -1615,28 +1631,26 @@
     // Get the camera list
     loadCameraList();
 
-    // Using null stream configuration makes EVS uses the default resolution and
-    // output format.
-    Stream nullCfg = {};
-
     // Request exclusive access to the EVS display
     sp<IEvsDisplay_1_0> pDisplay = pEnumerator->openDisplay();
     ASSERT_NE(pDisplay, nullptr);
 
     // Test each reported camera
     for (auto&& cam: cameraInfo) {
+        // Read a target resolution from the metadata
+        Stream targetCfg =
+            getFirstStreamConfiguration(reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+        ASSERT_GT(targetCfg.width, 0);
+        ASSERT_GT(targetCfg.height, 0);
+
         // Create two clients
-        sp<IEvsCamera_1_1> pCam0 =
-            IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
-            .withDefault(nullptr);
+        sp<IEvsCamera_1_1> pCam0 = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
         ASSERT_NE(pCam0, nullptr);
 
         // Store a camera handle for a clean-up
         activeCameras.push_back(pCam0);
 
-        sp<IEvsCamera_1_1> pCam1 =
-            IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
-            .withDefault(nullptr);
+        sp<IEvsCamera_1_1> pCam1 = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
         ASSERT_NE(pCam1, nullptr);
 
         // Store a camera handle for a clean-up
@@ -2001,7 +2015,7 @@
                  &streamCfgs)) {
             // Stream configurations are found in metadata
             RawStreamConfig *ptr = reinterpret_cast<RawStreamConfig *>(streamCfgs.data.i32);
-            for (unsigned idx = 0; idx < streamCfgs.count; idx += kStreamCfgSz) {
+            for (unsigned offset = 0; offset < streamCfgs.count; offset += kStreamCfgSz) {
                 if (ptr->direction == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT &&
                     ptr->format == HAL_PIXEL_FORMAT_RGBA_8888) {
 
@@ -2026,9 +2040,7 @@
             continue;
         }
 
-        sp<IEvsCamera_1_1> pCam =
-            IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg))
-            .withDefault(nullptr);
+        sp<IEvsCamera_1_1> pCam = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
         ASSERT_NE(pCam, nullptr);
 
         // Store a camera handle for a clean-up
@@ -2106,7 +2118,7 @@
                  &streamCfgs)) {
             // Stream configurations are found in metadata
             RawStreamConfig *ptr = reinterpret_cast<RawStreamConfig *>(streamCfgs.data.i32);
-            for (unsigned idx = 0; idx < streamCfgs.count; idx += kStreamCfgSz) {
+            for (unsigned offset = 0; offset < streamCfgs.count; offset += kStreamCfgSz) {
                 if (ptr->direction == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT &&
                     ptr->format == HAL_PIXEL_FORMAT_RGBA_8888) {
 
@@ -2132,9 +2144,7 @@
         }
 
         // Create the first camera client with a selected stream configuration.
-        sp<IEvsCamera_1_1> pCam0 =
-            IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg))
-            .withDefault(nullptr);
+        sp<IEvsCamera_1_1> pCam0 = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
         ASSERT_NE(pCam0, nullptr);
 
         // Store a camera handle for a clean-up
@@ -2144,9 +2154,7 @@
         // configuration.
         int32_t id = targetCfg.id;
         targetCfg.id += 1;  // EVS manager sees only the stream id.
-        sp<IEvsCamera_1_1> pCam1 =
-            IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg))
-            .withDefault(nullptr);
+        sp<IEvsCamera_1_1> pCam1 = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
         ASSERT_EQ(pCam1, nullptr);
 
         // Store a camera handle for a clean-up
@@ -2154,9 +2162,7 @@
 
         // Try again with same stream configuration.
         targetCfg.id = id;
-        pCam1 =
-            IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg))
-            .withDefault(nullptr);
+        pCam1 = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
         ASSERT_NE(pCam1, nullptr);
 
         // Set up per-client frame receiver objects which will fire up its own thread
@@ -2258,52 +2264,23 @@
     LOG(INFO) << "Starting CameraStreamExternalBuffering test";
 
     // Arbitrary constant (should be > 1 and not too big)
-    static const unsigned int kBuffersToHold = 6;
+    static const unsigned int kBuffersToHold = 3;
 
     // Get the camera list
     loadCameraList();
 
-    // Using null stream configuration makes EVS uses the default resolution and
-    // output format.
-    Stream nullCfg = {};
-
     // Acquire the graphics buffer allocator
     android::GraphicBufferAllocator& alloc(android::GraphicBufferAllocator::get());
     const auto usage =
             GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_SW_READ_RARELY | GRALLOC_USAGE_SW_WRITE_OFTEN;
-    const auto format = HAL_PIXEL_FORMAT_RGBA_8888;
-    uint32_t width = 640;
-    uint32_t height = 360;
-    camera_metadata_entry_t streamCfgs;
 
     // Test each reported camera
     for (auto&& cam : cameraInfo) {
-        bool foundCfg = false;
-        if (!find_camera_metadata_entry(reinterpret_cast<camera_metadata_t*>(cam.metadata.data()),
-                                        ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
-                                        &streamCfgs)) {
-            // Stream configurations are found in metadata
-            RawStreamConfig* ptr = reinterpret_cast<RawStreamConfig*>(streamCfgs.data.i32);
-
-            LOG(DEBUG) << __LINE__ << " start searching " << streamCfgs.count;
-            for (unsigned idx = 0; idx < streamCfgs.count; idx++) {
-                LOG(DEBUG) << "ptr->direction= " << ptr->direction
-                           << " ptr->format= " << ptr->format;
-                if (ptr->direction == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT &&
-                    ptr->format == HAL_PIXEL_FORMAT_RGBA_8888) {
-                    width = ptr->width;
-                    height = ptr->height;
-                    foundCfg = true;
-                    // Always use the 1st available configuration
-                    break;
-                }
-                ++ptr;
-            }
-        }
-
-        if (!foundCfg) {
-            LOG(INFO) << "No configuration found. Use default stream configurations.";
-        }
+        // Read a target resolution from the metadata
+        Stream targetCfg =
+            getFirstStreamConfiguration(reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+        ASSERT_GT(targetCfg.width, 0);
+        ASSERT_GT(targetCfg.height, 0);
 
         // Allocate buffers to use
         hidl_vec<BufferDesc> buffers;
@@ -2312,8 +2289,11 @@
             unsigned pixelsPerLine;
             buffer_handle_t memHandle = nullptr;
             android::status_t result =
-                    alloc.allocate(width, height, format, 1, usage, &memHandle, &pixelsPerLine, 0,
-                                   "CameraStreamExternalBufferingTest");
+                    alloc.allocate(targetCfg.width, targetCfg.height,
+                                   (android::PixelFormat)targetCfg.format,
+                                   /* layerCount = */ 1, usage, &memHandle, &pixelsPerLine,
+                                   /* graphicBufferId = */ 0,
+                                   /* requestorName = */ "CameraStreamExternalBufferingTest");
             if (result != android::NO_ERROR) {
                 LOG(ERROR) << __FUNCTION__ << " failed to allocate memory.";
                 // Release previous allocated buffers
@@ -2325,10 +2305,10 @@
                 BufferDesc buf;
                 AHardwareBuffer_Desc* pDesc =
                         reinterpret_cast<AHardwareBuffer_Desc*>(&buf.buffer.description);
-                pDesc->width = width;
-                pDesc->height = height;
+                pDesc->width = targetCfg.width;
+                pDesc->height = targetCfg.height;
                 pDesc->layers = 1;
-                pDesc->format = format;
+                pDesc->format = static_cast<uint32_t>(targetCfg.format);
                 pDesc->usage = usage;
                 pDesc->stride = pixelsPerLine;
                 buf.buffer.nativeHandle = memHandle;
@@ -2340,9 +2320,7 @@
         bool isLogicalCam = false;
         getPhysicalCameraIds(cam.v1.cameraId, isLogicalCam);
 
-        sp<IEvsCamera_1_1> pCam =
-            IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
-            .withDefault(nullptr);
+        sp<IEvsCamera_1_1> pCam = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
         ASSERT_NE(pCam, nullptr);
 
         // Store a camera handle for a clean-up
@@ -2362,7 +2340,7 @@
         }
 
         EXPECT_EQ(result, EvsResult::OK);
-        EXPECT_GE(delta, 0);
+        EXPECT_GE(delta, kBuffersToHold);
 
         // Set up a frame receiver object which will fire up its own thread.
         sp<FrameHandler> frameHandler = new FrameHandler(pCam, cam,
@@ -2378,7 +2356,7 @@
         sleep(1);   // 1 second should be enough for at least 5 frames to be delivered worst case
         unsigned framesReceived = 0;
         frameHandler->getFramesCounters(&framesReceived, nullptr);
-        ASSERT_EQ(kBuffersToHold, framesReceived) << "Stream didn't stall at expected buffer limit";
+        ASSERT_LE(kBuffersToHold, framesReceived) << "Stream didn't stall at expected buffer limit";
 
 
         // Give back one buffer
@@ -2387,9 +2365,10 @@
 
         // Once we return a buffer, it shouldn't take more than 1/10 second to get a new one
         // filled since we require 10fps minimum -- but give a 10% allowance just in case.
+        unsigned framesReceivedAfter = 0;
         usleep(110 * kMillisecondsToMicroseconds);
-        frameHandler->getFramesCounters(&framesReceived, nullptr);
-        EXPECT_EQ(kBuffersToHold+1, framesReceived) << "Stream should've resumed";
+        frameHandler->getFramesCounters(&framesReceivedAfter, nullptr);
+        EXPECT_EQ(framesReceived + 1, framesReceivedAfter) << "Stream should've resumed";
 
         // Even when the camera pointer goes out of scope, the FrameHandler object will
         // keep the stream alive unless we tell it to shutdown.
diff --git a/automotive/evs/common/utils/default/test/fuzz/FormatConvertFuzzer.cpp b/automotive/evs/common/utils/default/test/fuzz/FormatConvertFuzzer.cpp
index 583a455..58423c8 100644
--- a/automotive/evs/common/utils/default/test/fuzz/FormatConvertFuzzer.cpp
+++ b/automotive/evs/common/utils/default/test/fuzz/FormatConvertFuzzer.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <fuzzer/FuzzedDataProvider.h>
 #include <cmath>
 #include <cstdlib>
 #include <cstring>
@@ -21,36 +22,43 @@
 #include "FormatConvert.h"
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, std::size_t size) {
-    if (size < 256) {
+    // 1 random value (4bytes) + min imagesize = 16*2 times bytes per pixel (worse case 2)
+    if (size < (4 + 16 * 2 * 2)) {
         return 0;
     }
+    FuzzedDataProvider fdp(data, size);
+    std::size_t image_pixel_size = size - 4;
+    image_pixel_size = (image_pixel_size & INT_MAX) / 2;
 
-    std::srand(std::time(nullptr));  // use current time as seed for random generator
-    int random_variable = std::rand() % 10;
-    int width = (int)sqrt(size);
-    int height = width * ((float)random_variable / 10.0);
+    // API have a requirement that width must be divied by 16 except yuyvtorgb
+    int min_height = 2;
+    int max_height = (image_pixel_size / 16) & ~(1);  // must be even number
+    int height = fdp.ConsumeIntegralInRange<uint32_t>(min_height, max_height);
+    int width = (image_pixel_size / height) & ~(16);  // must be divisible by 16
 
-    uint8_t* src = (uint8_t*)malloc(sizeof(uint8_t) * size);
-    memcpy(src, data, sizeof(uint8_t) * (size));
-    uint32_t* tgt = (uint32_t*)malloc(sizeof(uint32_t) * size);
+    uint8_t* src = (uint8_t*)(data + 4);
+    uint32_t* tgt = (uint32_t*)malloc(sizeof(uint32_t) * image_pixel_size);
 
 #ifdef COPY_NV21_TO_RGB32
-    android::hardware::automotive::evs::common::Utils::copyNV21toRGB32(width, height, src, tgt, 0);
+    android::hardware::automotive::evs::common::Utils::copyNV21toRGB32(width, height, src, tgt,
+                                                                       width);
 #elif COPY_NV21_TO_BGR32
-    android::hardware::automotive::evs::common::Utils::copyNV21toBGR32(width, height, src, tgt, 0);
+    android::hardware::automotive::evs::common::Utils::copyNV21toBGR32(width, height, src, tgt,
+                                                                       width);
 #elif COPY_YV12_TO_RGB32
-    android::hardware::automotive::evs::common::Utils::copyYV12toRGB32(width, height, src, tgt, 0);
+    android::hardware::automotive::evs::common::Utils::copyYV12toRGB32(width, height, src, tgt,
+                                                                       width);
 #elif COPY_YV12_TO_BGR32
-    android::hardware::automotive::evs::common::Utils::copyYV12toBGR32(width, height, src, tgt, 0);
+    android::hardware::automotive::evs::common::Utils::copyYV12toBGR32(width, height, src, tgt,
+                                                                       width);
 #elif COPY_YUYV_TO_RGB32
-    android::hardware::automotive::evs::common::Utils::copyYUYVtoRGB32(width, height, src, 0, tgt,
-                                                                       0);
+    android::hardware::automotive::evs::common::Utils::copyYUYVtoRGB32(width, height, src, width,
+                                                                       tgt, width);
 #elif COPY_YUYV_TO_BGR32
-    android::hardware::automotive::evs::common::Utils::copyYUYVtoBGR32(width, height, src, 0, tgt,
-                                                                       0);
+    android::hardware::automotive::evs::common::Utils::copyYUYVtoBGR32(width, height, src, width,
+                                                                       tgt, width);
 #endif
 
-    free(src);
     free(tgt);
 
     return 0;
diff --git a/automotive/sv/1.0/vts/functional/Android.bp b/automotive/sv/1.0/vts/functional/Android.bp
index 1ff3450..e94893c 100644
--- a/automotive/sv/1.0/vts/functional/Android.bp
+++ b/automotive/sv/1.0/vts/functional/Android.bp
@@ -25,6 +25,9 @@
 
 cc_test {
     name: "VtsHalSurroundViewV1_0TargetTest",
+    tidy_timeout_srcs: [
+        "VtsHalSurroundViewV1_0TargetTest.cpp",
+    ],
     srcs: [
         "VtsHalSurroundViewV1_0TargetTest.cpp",
         "SurroundViewStreamHandler.cpp",
diff --git a/automotive/vehicle/2.0/default/Android.bp b/automotive/vehicle/2.0/default/Android.bp
index 869c0c9..ba33098 100644
--- a/automotive/vehicle/2.0/default/Android.bp
+++ b/automotive/vehicle/2.0/default/Android.bp
@@ -172,6 +172,9 @@
     vendor: true,
     defaults: ["vhal_v2_0_target_defaults"],
     whole_static_libs: ["android.hardware.automotive.vehicle@2.0-manager-lib"],
+    tidy_timeout_srcs: [
+        "tests/VmsUtils_test.cpp",
+    ],
     srcs: [
         "tests/RecurrentTimer_test.cpp",
         "tests/SubscriptionManager_test.cpp",
@@ -182,6 +185,7 @@
     ],
     shared_libs: [
         "libbase",
+        "libcutils",
     ],
     header_libs: ["libbase_headers"],
     test_suites: ["general-tests"],
diff --git a/automotive/vehicle/2.0/default/android.hardware.automotive.vehicle@2.0-service.rc b/automotive/vehicle/2.0/default/android.hardware.automotive.vehicle@2.0-service.rc
index c8c89dc..44f9134 100644
--- a/automotive/vehicle/2.0/default/android.hardware.automotive.vehicle@2.0-service.rc
+++ b/automotive/vehicle/2.0/default/android.hardware.automotive.vehicle@2.0-service.rc
@@ -1,4 +1,4 @@
 service vendor.vehicle-hal-2.0 /vendor/bin/hw/android.hardware.automotive.vehicle@2.0-service
-    class hal
+    class early_hal
     user vehicle_network
     group system inet
diff --git a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleHalManager.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleHalManager.h
index fcfe761..6706258 100644
--- a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleHalManager.h
+++ b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleHalManager.h
@@ -76,6 +76,9 @@
     Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
 
   private:
+    // Set unit test class as friend class to test private functions.
+    friend class VehicleHalManagerTestHelper;
+
     using VehiclePropValuePtr = VehicleHal::VehiclePropValuePtr;
     // Returns true if needs to call again shortly.
     using RetriableAction = std::function<bool()>;
@@ -105,14 +108,20 @@
     void cmdDumpOneProperty(int fd, int32_t prop, int32_t areaId);
     void cmdDumpOneProperty(int fd, int rowNumber, const VehiclePropConfig& config);
 
+    bool cmdSetOneProperty(int fd, const hidl_vec<hidl_string>& options);
+
     static bool checkArgumentsSize(int fd, const hidl_vec<hidl_string>& options, size_t minSize);
     static bool checkCallerHasWritePermissions(int fd);
-    static bool safelyParseInt(int fd, int index, std::string s, int* out);
+    template <typename T>
+    static bool safelyParseInt(int fd, int index, const std::string& s, T* out);
+    static bool safelyParseFloat(int fd, int index, const std::string& s, float* out);
+    // Parses "s" as a hex string and populate "*bytes". The hex string must be in the format of
+    // valid hex format, e.g. "0xABCD".
+    static bool parseHexString(int fd, const std::string& s, std::vector<uint8_t>* bytes);
     void cmdHelp(int fd) const;
     void cmdListAllProperties(int fd) const;
     void cmdDumpAllProperties(int fd);
     void cmdDumpSpecificProperties(int fd, const hidl_vec<hidl_string>& options);
-    void cmdSetOneProperty(int fd, const hidl_vec<hidl_string>& options);
 
     static bool isSubscribable(const VehiclePropConfig& config,
                                SubscribeFlags flags);
@@ -120,7 +129,18 @@
     static float checkSampleRate(const VehiclePropConfig& config,
                                  float sampleRate);
     static ClientId getClientId(const sp<IVehicleCallback>& callback);
-private:
+
+    // Parses the cmdline options for "--set" command. "*prop" would be populated with the
+    // the properties to be set. Returns true when the cmdline options are valid, false otherwise.
+    static bool parseSetPropOptions(int fd, const hidl_vec<hidl_string>& options,
+                                    VehiclePropValue* prop);
+    // Parses the options and get the values for the current option specified by "*index". "*index"
+    // would advance to the next option field (e.g., the next "-f"). Returns a list of values for
+    // the current option.
+    static std::vector<std::string> getOptionValues(const hidl_vec<hidl_string>& options,
+                                                    size_t* index);
+
+  private:
     VehicleHal* mHal;
     std::unique_ptr<VehiclePropConfigIndex> mConfigIndex;
     SubscriptionManager mSubscriptionManager;
diff --git a/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp b/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp
index dc5d3d3..e34e692 100644
--- a/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp
+++ b/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp
@@ -20,7 +20,9 @@
 
 #include <cmath>
 #include <fstream>
+#include <unordered_set>
 
+#include <android-base/parsedouble.h>
 #include <android-base/parseint.h>
 #include <android-base/strings.h>
 #include <android/hardware/automotive/vehicle/2.0/BpHwVehicleCallback.h>
@@ -44,15 +46,34 @@
 using ::android::hardware::hidl_handle;
 using ::android::hardware::hidl_string;
 
+namespace {
+
 constexpr std::chrono::milliseconds kHalEventBatchingTimeWindow(10);
 
 const VehiclePropValue kEmptyValue{};
 
+// A list of supported options for "--set" command.
+const std::unordered_set<std::string> kSetPropOptions = {
+        // integer.
+        "-i",
+        // 64bit integer.
+        "-i64",
+        // float.
+        "-f",
+        // string.
+        "-s",
+        // bytes in hex format, e.g. 0xDEADBEEF.
+        "-b",
+        // Area id in integer.
+        "-a"};
+
+}  // namespace
+
 /**
  * Indicates what's the maximum size of hidl_vec<VehiclePropValue> we want
  * to store in reusable object pool.
  */
-constexpr auto kMaxHidlVecOfVehiclPropValuePoolSize = 20;
+constexpr auto kMaxHidlVecOfVehiclePropValuePoolSize = 20;
 
 Return<void> VehicleHalManager::getAllPropConfigs(getAllPropConfigs_cb _hidl_cb) {
     ALOGI("getAllPropConfigs called");
@@ -213,6 +234,11 @@
     } else if (EqualsIgnoreCase(option, "--get")) {
         cmdDumpSpecificProperties(fd, options);
     } else if (EqualsIgnoreCase(option, "--set")) {
+        if (!checkCallerHasWritePermissions(fd)) {
+            dprintf(fd, "Caller does not have write permission\n");
+            return;
+        }
+        // Ignore the return value for this.
         cmdSetOneProperty(fd, options);
     } else {
         dprintf(fd, "Invalid option: %s\n", option.c_str());
@@ -239,7 +265,8 @@
     return false;
 }
 
-bool VehicleHalManager::safelyParseInt(int fd, int index, std::string s, int* out) {
+template <typename T>
+bool VehicleHalManager::safelyParseInt(int fd, int index, const std::string& s, T* out) {
     if (!android::base::ParseInt(s, out)) {
         dprintf(fd, "non-integer argument at index %d: %s\n", index, s.c_str());
         return false;
@@ -247,19 +274,27 @@
     return true;
 }
 
+bool VehicleHalManager::safelyParseFloat(int fd, int index, const std::string& s, float* out) {
+    if (!android::base::ParseFloat(s, out)) {
+        dprintf(fd, "non-float argument at index %d: %s\n", index, s.c_str());
+        return false;
+    }
+    return true;
+}
+
 void VehicleHalManager::cmdHelp(int fd) const {
     dprintf(fd, "Usage: \n\n");
     dprintf(fd, "[no args]: dumps (id and value) all supported properties \n");
     dprintf(fd, "--help: shows this help\n");
     dprintf(fd, "--list: lists the ids of all supported properties\n");
     dprintf(fd, "--get <PROP1> [PROP2] [PROPN]: dumps the value of specific properties \n");
-    // TODO: support other formats (int64, float, bytes)
     dprintf(fd,
-            "--set <PROP> <i|s> <VALUE_1> [<i|s> <VALUE_N>] [a AREA_ID] : sets the value of "
-            "property PROP, using arbitrary number of key/value parameters (i for int32, "
-            "s for string) and an optional area.\n"
-            "Notice that the string value can be set just once, while the other can have multiple "
-            "values (so they're used in the respective array)\n");
+            "--set <PROP> [-i INT_VALUE [INT_VALUE ...]] [-i64 INT64_VALUE [INT64_VALUE ...]] "
+            "[-f FLOAT_VALUE [FLOAT_VALUE ...]] [-s STR_VALUE] "
+            "[-b BYTES_VALUE] [-a AREA_ID] : sets the value of property PROP. "
+            "Notice 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");
 }
 
 void VehicleHalManager::cmdListAllProperties(int fd) const {
@@ -337,102 +372,49 @@
     VehiclePropValue input;
     input.prop = prop;
     input.areaId = areaId;
-    auto callback = [&](StatusCode status, const VehiclePropValue& output) {
+    auto callback = [&fd, &prop](StatusCode status, const VehiclePropValue& output) {
         if (status == StatusCode::OK) {
             dprintf(fd, "%s\n", toString(output).c_str());
         } else {
             dprintf(fd, "Could not get property %d. Error: %s\n", prop, toString(status).c_str());
         }
     };
-    get(input, callback);
+
+    StatusCode status;
+    auto value = mHal->get(input, &status);
+    callback(status, value.get() ? *value : kEmptyValue);
 }
 
-void VehicleHalManager::cmdSetOneProperty(int fd, const hidl_vec<hidl_string>& options) {
-    if (!checkCallerHasWritePermissions(fd) || !checkArgumentsSize(fd, options, 3)) return;
-
-    size_t size = options.size();
-
-    // Syntax is --set PROP Type1 Value1 TypeN ValueN, so number of arguments must be even
-    if (size % 2 != 0) {
-        dprintf(fd, "must pass even number of arguments (passed %zu)\n", size);
-        return;
+bool VehicleHalManager::cmdSetOneProperty(int fd, const hidl_vec<hidl_string>& options) {
+    if (!checkArgumentsSize(fd, options, 4)) {
+        dprintf(fd, "Requires at least 4 options, see help\n");
+        return false;
     }
-    int numberValues = (size - 2) / 2;
 
-    VehiclePropValue prop;
-    if (!safelyParseInt(fd, 1, options[1], &prop.prop)) return;
-    prop.timestamp = elapsedRealtimeNano();
-    prop.status = VehiclePropertyStatus::AVAILABLE;
-
-    // First pass: calculate sizes
-    int sizeInt32 = 0;
-    int stringIndex = 0;
-    int areaIndex = 0;
-    for (int i = 2, kv = 1; kv <= numberValues; kv++) {
-        // iterate through the kv=1..n key/value pairs, accessing indexes i / i+1 at each step
-        std::string type = options[i];
-        std::string value = options[i + 1];
-        if (EqualsIgnoreCase(type, "i")) {
-            sizeInt32++;
-        } else if (EqualsIgnoreCase(type, "s")) {
-            if (stringIndex != 0) {
-                dprintf(fd,
-                        "defining string value (%s) again at index %d (already defined at %d=%s"
-                        ")\n",
-                        value.c_str(), i, stringIndex, options[stringIndex + 1].c_str());
-                return;
-            }
-            stringIndex = i;
-        } else if (EqualsIgnoreCase(type, "a")) {
-            if (areaIndex != 0) {
-                dprintf(fd,
-                        "defining area value (%s) again at index %d (already defined at %d=%s"
-                        ")\n",
-                        value.c_str(), i, areaIndex, options[areaIndex + 1].c_str());
-                return;
-            }
-            areaIndex = i;
-        } else {
-            dprintf(fd, "invalid (%s) type at index %d\n", type.c_str(), i);
-            return;
-        }
-        i += 2;
-    }
-    prop.value.int32Values.resize(sizeInt32);
-
-    // Second pass: populate it
-    int indexInt32 = 0;
-    for (int i = 2, kv = 1; kv <= numberValues; kv++) {
-        // iterate through the kv=1..n key/value pairs, accessing indexes i / i+1 at each step
-        int valueIndex = i + 1;
-        std::string type = options[i];
-        std::string value = options[valueIndex];
-        if (EqualsIgnoreCase(type, "i")) {
-            int safeInt;
-            if (!safelyParseInt(fd, valueIndex, value, &safeInt)) return;
-            prop.value.int32Values[indexInt32++] = safeInt;
-        } else if (EqualsIgnoreCase(type, "s")) {
-            prop.value.stringValue = value;
-        } else if (EqualsIgnoreCase(type, "a")) {
-            if (!safelyParseInt(fd, valueIndex, value, &prop.areaId)) return;
-        }
-        i += 2;
+    VehiclePropValue prop = {};
+    if (!parseSetPropOptions(fd, options, &prop)) {
+        return false;
     }
     ALOGD("Setting prop %s", toString(prop).c_str());
-    auto status = set(prop);
+
+    // Do not use VehicleHalManager::set here because we don't want to check write permission.
+    // Caller should be able to use the debug interface to set read-only properties.
+    handlePropertySetEvent(prop);
+    auto status = mHal->set(prop);
+
     if (status == StatusCode::OK) {
         dprintf(fd, "Set property %s\n", toString(prop).c_str());
-    } else {
-        dprintf(fd, "Failed to set property %s: %s\n", toString(prop).c_str(),
-                toString(status).c_str());
+        return true;
     }
+    dprintf(fd, "Failed to set property %s: %s\n", toString(prop).c_str(),
+            toString(status).c_str());
+    return false;
 }
 
 void VehicleHalManager::init() {
     ALOGI("VehicleHalManager::init");
 
-    mHidlVecOfVehiclePropValuePool.resize(kMaxHidlVecOfVehiclPropValuePoolSize);
-
+    mHidlVecOfVehiclePropValuePool.resize(kMaxHidlVecOfVehiclePropValuePoolSize);
 
     mBatchingConsumer.run(&mEventQueue,
                           kHalEventBatchingTimeWindow,
@@ -486,7 +468,7 @@
     for (const HalClientValues& cv : clientValues) {
         auto vecSize = cv.values.size();
         hidl_vec<VehiclePropValue> vec;
-        if (vecSize < kMaxHidlVecOfVehiclPropValuePoolSize) {
+        if (vecSize < kMaxHidlVecOfVehiclePropValuePoolSize) {
             vec.setToExternal(&mHidlVecOfVehiclePropValuePool[0], vecSize);
         } else {
             vec.resize(vecSize);
@@ -595,6 +577,158 @@
     }
 }
 
+std::vector<std::string> VehicleHalManager::getOptionValues(const hidl_vec<hidl_string>& options,
+                                                            size_t* index) {
+    std::vector<std::string> values;
+    while (*index < options.size()) {
+        std::string option = options[*index];
+        if (kSetPropOptions.find(option) != kSetPropOptions.end()) {
+            return std::move(values);
+        }
+        values.push_back(option);
+        (*index)++;
+    }
+    return std::move(values);
+}
+
+bool VehicleHalManager::parseSetPropOptions(int fd, const hidl_vec<hidl_string>& options,
+                                            VehiclePropValue* prop) {
+    // Options format:
+    // --set PROP [-f f1 f2...] [-i i1 i2...] [-i64 i1 i2...] [-s s1 s2...] [-b b1 b2...] [-a a]
+    size_t optionIndex = 1;
+    int propValue;
+    if (!safelyParseInt(fd, optionIndex, options[optionIndex], &propValue)) {
+        dprintf(fd, "property value: \"%s\" is not a valid int\n", options[optionIndex].c_str());
+        return false;
+    }
+    prop->prop = propValue;
+    prop->timestamp = elapsedRealtimeNano();
+    prop->status = VehiclePropertyStatus::AVAILABLE;
+    optionIndex++;
+    std::unordered_set<std::string> parsedOptions;
+
+    while (optionIndex < options.size()) {
+        std::string type = options[optionIndex];
+        optionIndex++;
+        size_t currentIndex = optionIndex;
+        std::vector<std::string> values = getOptionValues(options, &optionIndex);
+        if (parsedOptions.find(type) != parsedOptions.end()) {
+            dprintf(fd, "duplicate \"%s\" options\n", type.c_str());
+            return false;
+        }
+        parsedOptions.insert(type);
+        if (EqualsIgnoreCase(type, "-i")) {
+            if (values.size() == 0) {
+                dprintf(fd, "no values specified when using \"-i\"\n");
+                return false;
+            }
+            prop->value.int32Values.resize(values.size());
+            for (size_t i = 0; i < values.size(); i++) {
+                int32_t safeInt;
+                if (!safelyParseInt(fd, currentIndex + i, values[i], &safeInt)) {
+                    dprintf(fd, "value: \"%s\" is not a valid int\n", values[i].c_str());
+                    return false;
+                }
+                prop->value.int32Values[i] = safeInt;
+            }
+        } else if (EqualsIgnoreCase(type, "-i64")) {
+            if (values.size() == 0) {
+                dprintf(fd, "no values specified when using \"-i64\"\n");
+                return false;
+            }
+            prop->value.int64Values.resize(values.size());
+            for (size_t i = 0; i < values.size(); i++) {
+                int64_t safeInt;
+                if (!safelyParseInt(fd, currentIndex + i, values[i], &safeInt)) {
+                    dprintf(fd, "value: \"%s\" is not a valid int64\n", values[i].c_str());
+                    return false;
+                }
+                prop->value.int64Values[i] = safeInt;
+            }
+        } else if (EqualsIgnoreCase(type, "-f")) {
+            if (values.size() == 0) {
+                dprintf(fd, "no values specified when using \"-f\"\n");
+                return false;
+            }
+            prop->value.floatValues.resize(values.size());
+            for (size_t i = 0; i < values.size(); i++) {
+                float safeFloat;
+                if (!safelyParseFloat(fd, currentIndex + i, values[i], &safeFloat)) {
+                    dprintf(fd, "value: \"%s\" is not a valid float\n", values[i].c_str());
+                    return false;
+                }
+                prop->value.floatValues[i] = safeFloat;
+            }
+        } else if (EqualsIgnoreCase(type, "-s")) {
+            if (values.size() != 1) {
+                dprintf(fd, "expect exact one value when using \"-s\"\n");
+                return false;
+            }
+            prop->value.stringValue = values[0];
+        } else if (EqualsIgnoreCase(type, "-b")) {
+            if (values.size() != 1) {
+                dprintf(fd, "expect exact one value when using \"-b\"\n");
+                return false;
+            }
+            std::vector<uint8_t> bytes;
+            if (!parseHexString(fd, values[0], &bytes)) {
+                dprintf(fd, "value: \"%s\" is not a valid hex string\n", values[0].c_str());
+                return false;
+            }
+            prop->value.bytes = bytes;
+        } else if (EqualsIgnoreCase(type, "-a")) {
+            if (values.size() != 1) {
+                dprintf(fd, "expect exact one value when using \"-a\"\n");
+                return false;
+            }
+            if (!safelyParseInt(fd, currentIndex, values[0], &(prop->areaId))) {
+                dprintf(fd, "area ID: \"%s\" is not a valid int\n", values[0].c_str());
+                return false;
+            }
+        } else {
+            dprintf(fd, "unknown option: %s\n", type.c_str());
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool VehicleHalManager::parseHexString(int fd, const std::string& s, std::vector<uint8_t>* bytes) {
+    if (s.size() % 2 != 0) {
+        dprintf(fd, "invalid hex string: %s, should have even size\n", s.c_str());
+        return false;
+    }
+    if (strncmp(s.substr(0, 2).c_str(), "0x", 2)) {
+        dprintf(fd, "hex string should start with \"0x\", got %s\n", s.c_str());
+        return false;
+    }
+    std::string subs = s.substr(2);
+    std::transform(subs.begin(), subs.end(), subs.begin(),
+                   [](unsigned char c) { return std::tolower(c); });
+
+    bool highDigit = true;
+    for (size_t i = 0; i < subs.size(); i++) {
+        char c = subs[i];
+        uint8_t v;
+        if (c >= '0' && c <= '9') {
+            v = c - '0';
+        } else if (c >= 'a' && c <= 'f') {
+            v = c - 'a' + 10;
+        } else {
+            dprintf(fd, "invalid character %c in hex string %s\n", c, subs.c_str());
+            return false;
+        }
+        if (highDigit) {
+            (*bytes).push_back(v * 16);
+        } else {
+            (*bytes)[bytes->size() - 1] += v;
+        }
+        highDigit = !highDigit;
+    }
+    return true;
+}
+
 }  // namespace V2_0
 }  // namespace vehicle
 }  // namespace automotive
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
index 8ff4924..55617be 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
@@ -307,6 +307,18 @@
                          .prop = toInt(VehicleProperty::CRITICALLY_LOW_TIRE_PRESSURE),
                          .access = VehiclePropertyAccess::READ,
                          .changeMode = VehiclePropertyChangeMode::STATIC,
+                         .areaConfigs = {VehicleAreaConfig{
+                                                 .areaId = WHEEL_FRONT_LEFT,
+                                         },
+                                         VehicleAreaConfig{
+                                                 .areaId = WHEEL_FRONT_RIGHT,
+                                         },
+                                         VehicleAreaConfig{
+                                                 .areaId = WHEEL_REAR_LEFT,
+                                         },
+                                         VehicleAreaConfig{
+                                                 .areaId = WHEEL_REAR_RIGHT,
+                                         }},
                  },
          .initialAreaValues = {{WHEEL_FRONT_LEFT, {.floatValues = {137.0f}}},
                                {WHEEL_FRONT_RIGHT, {.floatValues = {137.0f}}},
@@ -1032,14 +1044,6 @@
         {
                 .config =
                         {
-                                .prop = toInt(VehicleProperty::STORAGE_ENCRYPTION_BINDING_SEED),
-                                .access = VehiclePropertyAccess::READ_WRITE,
-                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
-                        },
-        },
-        {
-                .config =
-                        {
                                 .prop = toInt(VehicleProperty::WATCHDOG_ALIVE),
                                 .access = VehiclePropertyAccess::WRITE,
                                 .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
@@ -1105,6 +1109,42 @@
                                 .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
                         },
         },
+        {
+                .config =
+                        {
+                                .prop = PLACEHOLDER_PROPERTY_INT,
+                                .access = VehiclePropertyAccess::READ_WRITE,
+                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                        },
+                .initialValue = {.int32Values = {0}},
+        },
+        {
+                .config =
+                        {
+                                .prop = PLACEHOLDER_PROPERTY_FLOAT,
+                                .access = VehiclePropertyAccess::READ_WRITE,
+                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                        },
+                .initialValue = {.floatValues = {0.0f}},
+        },
+        {
+                .config =
+                        {
+                                .prop = PLACEHOLDER_PROPERTY_BOOLEAN,
+                                .access = VehiclePropertyAccess::READ_WRITE,
+                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                        },
+                .initialValue = {.int32Values = {0 /* false */}},
+        },
+        {
+                .config =
+                        {
+                                .prop = PLACEHOLDER_PROPERTY_STRING,
+                                .access = VehiclePropertyAccess::READ_WRITE,
+                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                        },
+                .initialValue = {.stringValue = {"Test"}},
+        },
 #ifdef ENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING
         // Vendor propetry for E2E ClusterHomeService testing.
         {
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/PropertyUtils.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/PropertyUtils.h
index d5f6a18..51251a7 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/PropertyUtils.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/PropertyUtils.h
@@ -189,6 +189,19 @@
     KeyPress = 100,
 };
 
+/**
+ * These properties are placeholder properties for developers to test new features without
+ * implementing a real property.
+ */
+constexpr int32_t PLACEHOLDER_PROPERTY_INT =
+        0x2a11 | VehiclePropertyGroup::VENDOR | VehicleArea::GLOBAL | VehiclePropertyType::INT32;
+constexpr int32_t PLACEHOLDER_PROPERTY_FLOAT =
+        0x2a11 | VehiclePropertyGroup::VENDOR | VehicleArea::GLOBAL | VehiclePropertyType::FLOAT;
+constexpr int32_t PLACEHOLDER_PROPERTY_BOOLEAN =
+        0x2a11 | VehiclePropertyGroup::VENDOR | VehicleArea::GLOBAL | VehiclePropertyType::BOOLEAN;
+constexpr int32_t PLACEHOLDER_PROPERTY_STRING =
+        0x2a11 | VehiclePropertyGroup::VENDOR | VehicleArea::GLOBAL | VehiclePropertyType::STRING;
+
 const int32_t kHvacPowerProperties[] = {
     toInt(VehicleProperty::HVAC_FAN_SPEED),
     toInt(VehicleProperty::HVAC_FAN_DIRECTION),
diff --git a/automotive/vehicle/2.0/default/tests/VehicleHalManager_test.cpp b/automotive/vehicle/2.0/default/tests/VehicleHalManager_test.cpp
index 0975071..bdf46fb 100644
--- a/automotive/vehicle/2.0/default/tests/VehicleHalManager_test.cpp
+++ b/automotive/vehicle/2.0/default/tests/VehicleHalManager_test.cpp
@@ -18,6 +18,7 @@
 #include <iostream>
 
 #include <android-base/macros.h>
+#include <cutils/native_handle.h>
 #include <utils/SystemClock.h>
 
 #include <gtest/gtest.h>
@@ -32,6 +33,18 @@
 namespace vehicle {
 namespace V2_0 {
 
+// A simple helper class to expose 'cmdSetOneProperty' to the unit tests.
+class VehicleHalManagerTestHelper {
+  public:
+    VehicleHalManagerTestHelper(VehicleHalManager* manager) { mManager = manager; }
+    bool cmdSetOneProperty(int fd, const hidl_vec<hidl_string>& options) {
+        return mManager->cmdSetOneProperty(fd, options);
+    }
+
+  public:
+    VehicleHalManager* mManager;
+};
+
 namespace {
 
 using namespace std::placeholders;
@@ -57,33 +70,21 @@
         auto property = static_cast<VehicleProperty>(requestedPropValue.prop);
         int32_t areaId = requestedPropValue.areaId;
 
-        switch (property) {
-            case VehicleProperty::INFO_MAKE:
-                pValue = getValuePool()->obtainString(kCarMake);
-                break;
-            case VehicleProperty::INFO_FUEL_CAPACITY:
-                if (fuelCapacityAttemptsLeft-- > 0) {
-                    // Emulate property not ready yet.
-                    *outStatus = StatusCode::TRY_AGAIN;
-                } else {
-                    pValue = getValuePool()->obtainFloat(42.42);
-                }
-                break;
-            default:
-                if (requestedPropValue.prop == kCustomComplexProperty) {
-                    pValue = getValuePool()->obtainComplex();
-                    pValue->value.int32Values = hidl_vec<int32_t> { 10, 20 };
-                    pValue->value.int64Values = hidl_vec<int64_t> { 30, 40 };
-                    pValue->value.floatValues = hidl_vec<float_t> { 1.1, 2.2 };
-                    pValue->value.bytes = hidl_vec<uint8_t> { 1, 2, 3 };
-                    pValue->value.stringValue = kCarMake;
-                    break;
-                }
-                auto key = makeKey(toInt(property), areaId);
-                if (mValues.count(key) == 0) {
-                    ALOGW("");
-                }
-                pValue = getValuePool()->obtain(mValues[key]);
+        if (property == VehicleProperty::INFO_FUEL_CAPACITY) {
+            if (fuelCapacityAttemptsLeft-- > 0) {
+                // Emulate property not ready yet.
+                *outStatus = StatusCode::TRY_AGAIN;
+            } else {
+                pValue = getValuePool()->obtainFloat(42.42);
+            }
+        } else {
+            auto key = makeKey(requestedPropValue);
+            if (mValues.count(key) == 0) {
+                ALOGW("key not found\n");
+                *outStatus = StatusCode::INVALID_ARG;
+                return pValue;
+            }
+            pValue = getValuePool()->obtain(mValues[key]);
         }
 
         if (*outStatus == StatusCode::OK && pValue.get() != nullptr) {
@@ -100,7 +101,6 @@
                 && mirrorFoldAttemptsLeft-- > 0) {
             return StatusCode::TRY_AGAIN;
         }
-
         mValues[makeKey(propValue)] = propValue;
         return StatusCode::OK;
     }
@@ -181,6 +181,18 @@
         actualStatusCode = refStatus;
     }
 
+    MockedVehicleHal::VehiclePropValuePtr getComplexProperty() {
+        auto pValue = objectPool->obtainComplex();
+        pValue->prop = kCustomComplexProperty;
+        pValue->areaId = 0;
+        pValue->value.int32Values = hidl_vec<int32_t>{10, 20};
+        pValue->value.int64Values = hidl_vec<int64_t>{30, 40};
+        pValue->value.floatValues = hidl_vec<float_t>{1.1, 2.2};
+        pValue->value.bytes = hidl_vec<uint8_t>{1, 2, 3};
+        pValue->value.stringValue = kCarMake;
+        return pValue;
+    }
+
 public:
     VehiclePropValue actualValue;
     StatusCode actualStatusCode;
@@ -308,6 +320,8 @@
 }
 
 TEST_F(VehicleHalManagerTest, get_Complex) {
+    ASSERT_EQ(StatusCode::OK, hal->set(*getComplexProperty().get()));
+
     invokeGet(kCustomComplexProperty, 0);
 
     ASSERT_EQ(StatusCode::OK, actualStatusCode);
@@ -334,6 +348,11 @@
 }
 
 TEST_F(VehicleHalManagerTest, get_StaticString) {
+    auto pValue = objectPool->obtainString(kCarMake);
+    pValue->prop = toInt(VehicleProperty::INFO_MAKE);
+    pValue->areaId = 0;
+    ASSERT_EQ(StatusCode::OK, hal->set(*pValue.get()));
+
     invokeGet(toInt(VehicleProperty::INFO_MAKE), 0);
 
     ASSERT_EQ(StatusCode::OK, actualStatusCode);
@@ -458,6 +477,138 @@
     ASSERT_TRUE(clients.isEmpty());
 }
 
+TEST_F(VehicleHalManagerTest, debug) {
+    hidl_handle fd = {};
+    fd.setTo(native_handle_create(/*numFds=*/1, /*numInts=*/0), /*shouldOwn=*/true);
+
+    // Because debug function returns void, so no way to check return value.
+    manager->debug(fd, {});
+    manager->debug(fd, {"--help"});
+    manager->debug(fd, {"--list"});
+    manager->debug(fd, {"--get"});
+    manager->debug(fd, {"--set"});
+    manager->debug(fd, {"invalid"});
+}
+
+struct SetPropTestCase {
+    std::string test_name;
+    const hidl_vec<hidl_string> configs;
+    bool success;
+};
+
+class VehicleHalManagerSetPropTest : public VehicleHalManagerTest,
+                                     public testing::WithParamInterface<SetPropTestCase> {};
+
+TEST_P(VehicleHalManagerSetPropTest, cmdSetOneProperty) {
+    const SetPropTestCase& tc = GetParam();
+    VehicleHalManagerTestHelper helper(manager.get());
+    ASSERT_EQ(tc.success, helper.cmdSetOneProperty(STDERR_FILENO, tc.configs));
+}
+
+std::vector<SetPropTestCase> GenSetPropParams() {
+    char infoMakeProperty[100] = {};
+    snprintf(infoMakeProperty, sizeof(infoMakeProperty), "%d", toInt(VehicleProperty::INFO_MAKE));
+    return {
+            {"success_set_string", {"--set", infoMakeProperty, "-s", kCarMake}, 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},
+            {"success_set_ints",
+             {"--set", infoMakeProperty, "-i", "2147483647", "0", "-2147483648"},
+             true},
+            {"success_set_int64",
+             {"--set", infoMakeProperty, "-i64", "-9223372036854775808"},
+             true},
+            {"success_set_int64s",
+             {"--set", infoMakeProperty, "-i64", "-9223372036854775808", "0",
+              "9223372036854775807"},
+             true},
+            {"success_set_float", {"--set", infoMakeProperty, "-f", "1.175494351E-38"}, true},
+            {"success_set_floats",
+             {"--set", infoMakeProperty, "-f", "-3.402823466E+38", "0", "3.402823466E+38"},
+             true},
+            {"success_set_area", {"--set", infoMakeProperty, "-a", "2147483647"}, true},
+            {"fail_no_options", {}, false},
+            {"fail_less_than_4_options", {"--set", infoMakeProperty, "-i"}, false},
+            {"fail_unknown_options", {"--set", infoMakeProperty, "-s", kCarMake, "-abcd"}, false},
+            {"fail_invalid_property", {"--set", "not valid", "-s", kCarMake}, false},
+            {"fail_duplicate_string",
+             {"--set", infoMakeProperty, "-s", kCarMake, "-s", kCarMake},
+             false},
+            {"fail_multiple_strings", {"--set", infoMakeProperty, "-s", kCarMake, kCarMake}, false},
+            {"fail_no_string_value", {"--set", infoMakeProperty, "-s", "-a", "1234"}, false},
+            {"fail_duplicate_bytes",
+             {"--set", infoMakeProperty, "-b", "0xdeadbeef", "-b", "0xdeadbeef"},
+             false},
+            {"fail_multiple_bytes",
+             {"--set", infoMakeProperty, "-b", "0xdeadbeef", "0xdeadbeef"},
+             false},
+            {"fail_invalid_bytes", {"--set", infoMakeProperty, "-b", "0xgood"}, false},
+            {"fail_invalid_bytes_no_prefix", {"--set", infoMakeProperty, "-b", "deadbeef"}, false},
+            {"fail_invalid_int", {"--set", infoMakeProperty, "-i", "abc"}, false},
+            {"fail_int_out_of_range", {"--set", infoMakeProperty, "-i", "2147483648"}, false},
+            {"fail_no_int_value", {"--set", infoMakeProperty, "-i", "-s", kCarMake}, false},
+            {"fail_invalid_int64", {"--set", infoMakeProperty, "-i64", "abc"}, false},
+            {"fail_int64_out_of_range",
+             {"--set", infoMakeProperty, "-i64", "-9223372036854775809"},
+             false},
+            {"fail_no_int64_value", {"--set", infoMakeProperty, "-i64", "-s", kCarMake}, false},
+            {"fail_invalid_float", {"--set", infoMakeProperty, "-f", "abc"}, false},
+            {"fail_float_out_of_range",
+             {"--set", infoMakeProperty, "-f", "-3.402823466E+39"},
+             false},
+            {"fail_no_float_value", {"--set", infoMakeProperty, "-f", "-s", kCarMake}, false},
+            {"fail_multiple_areas", {"--set", infoMakeProperty, "-a", "2147483648", "0"}, false},
+            {"fail_invalid_area", {"--set", infoMakeProperty, "-a", "abc"}, false},
+            {"fail_area_out_of_range", {"--set", infoMakeProperty, "-a", "2147483648"}, false},
+            {"fail_no_area_value", {"--set", infoMakeProperty, "-a", "-s", kCarMake}, false},
+    };
+}
+
+INSTANTIATE_TEST_SUITE_P(
+        VehicleHalManagerSetPropTests, VehicleHalManagerSetPropTest,
+        testing::ValuesIn(GenSetPropParams()),
+        [](const testing::TestParamInfo<VehicleHalManagerSetPropTest::ParamType>& info) {
+            return info.param.test_name;
+        });
+
+TEST_F(VehicleHalManagerTest, SetComplexPropTest) {
+    char infoMakeProperty[100] = {};
+    snprintf(infoMakeProperty, sizeof(infoMakeProperty), "%d", toInt(VehicleProperty::INFO_MAKE));
+    VehicleHalManagerTestHelper helper(manager.get());
+    ASSERT_TRUE(helper.cmdSetOneProperty(
+            STDERR_FILENO, {"--set", infoMakeProperty,      "-s",   kCarMake,
+                            "-b",    "0xdeadbeef",          "-i",   "2147483647",
+                            "0",     "-2147483648",         "-i64", "-9223372036854775808",
+                            "0",     "9223372036854775807", "-f",   "-3.402823466E+38",
+                            "0",     "3.402823466E+38",     "-a",   "123"}));
+    StatusCode status = StatusCode::OK;
+    VehiclePropValue requestProp;
+    requestProp.prop = toInt(VehicleProperty::INFO_MAKE);
+    requestProp.areaId = 123;
+    auto value = hal->get(requestProp, &status);
+    ASSERT_EQ(StatusCode::OK, status);
+    ASSERT_EQ(value->prop, toInt(VehicleProperty::INFO_MAKE));
+    ASSERT_EQ(value->areaId, 123);
+    ASSERT_STREQ(kCarMake, value->value.stringValue.c_str());
+    uint8_t bytes[] = {0xde, 0xad, 0xbe, 0xef};
+    ASSERT_FALSE(memcmp(bytes, value->value.bytes.data(), sizeof(bytes)));
+    ASSERT_EQ(3u, value->value.int32Values.size());
+    ASSERT_EQ(2147483647, value->value.int32Values[0]);
+    ASSERT_EQ(0, value->value.int32Values[1]);
+    ASSERT_EQ(-2147483648, value->value.int32Values[2]);
+    ASSERT_EQ(3u, value->value.int64Values.size());
+    // -9223372036854775808 is not a valid literal since '-' and '9223372036854775808' would be two
+    // tokens and the later does not fit in unsigned long long.
+    ASSERT_EQ(-9223372036854775807 - 1, value->value.int64Values[0]);
+    ASSERT_EQ(0, value->value.int64Values[1]);
+    ASSERT_EQ(9223372036854775807, value->value.int64Values[2]);
+    ASSERT_EQ(3u, value->value.floatValues.size());
+    ASSERT_EQ(-3.402823466E+38f, value->value.floatValues[0]);
+    ASSERT_EQ(0.0f, value->value.floatValues[1]);
+    ASSERT_EQ(3.402823466E+38f, value->value.floatValues[2]);
+}
+
 }  // namespace anonymous
 
 }  // namespace V2_0
diff --git a/automotive/vehicle/2.0/utils/Android.bp b/automotive/vehicle/2.0/utils/Android.bp
index a75ce49..770d447 100644
--- a/automotive/vehicle/2.0/utils/Android.bp
+++ b/automotive/vehicle/2.0/utils/Android.bp
@@ -39,6 +39,9 @@
     name: "android.hardware.automotive.vehicle@2.0-utils-unit-tests",
     defaults: ["vhal_v2_0_defaults"],
     vendor: true,
+    tidy_timeout_srcs: [
+        "tests/UserHalHelper_test.cpp",
+    ],
     srcs: [
         "tests/UserHalHelper_test.cpp",
     ],
diff --git a/biometrics/fingerprint/2.1/vts/functional/Android.bp b/biometrics/fingerprint/2.1/vts/functional/Android.bp
index 0935bf6..68b3360 100644
--- a/biometrics/fingerprint/2.1/vts/functional/Android.bp
+++ b/biometrics/fingerprint/2.1/vts/functional/Android.bp
@@ -26,6 +26,7 @@
 cc_test {
     name: "VtsHalBiometricsFingerprintV2_1TargetTest",
     defaults: ["VtsHalTargetTestDefaults"],
+    tidy_timeout_srcs: ["VtsHalBiometricsFingerprintV2_1TargetTest.cpp"],
     srcs: ["VtsHalBiometricsFingerprintV2_1TargetTest.cpp"],
     static_libs: ["android.hardware.biometrics.fingerprint@2.1"],
     test_suites: ["general-tests", "vts"],
diff --git a/bluetooth/audio/2.1/vts/functional/Android.bp b/bluetooth/audio/2.1/vts/functional/Android.bp
index 3314a8a..cea7326 100644
--- a/bluetooth/audio/2.1/vts/functional/Android.bp
+++ b/bluetooth/audio/2.1/vts/functional/Android.bp
@@ -10,6 +10,7 @@
 cc_test {
     name: "VtsHalBluetoothAudioV2_1TargetTest",
     defaults: ["VtsHalTargetTestDefaults"],
+    tidy_timeout_srcs: ["VtsHalBluetoothAudioV2_1TargetTest.cpp"],
     srcs: ["VtsHalBluetoothAudioV2_1TargetTest.cpp"],
     static_libs: [
         "android.hardware.audio.common@5.0",
diff --git a/bluetooth/audio/2.2/Android.bp b/bluetooth/audio/2.2/Android.bp
deleted file mode 100644
index d66e84e..0000000
--- a/bluetooth/audio/2.2/Android.bp
+++ /dev/null
@@ -1,33 +0,0 @@
-// This file is autogenerated by hidl-gen -Landroidbp.
-
-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"],
-}
-
-hidl_interface {
-    name: "android.hardware.bluetooth.audio@2.2",
-    root: "android.hardware",
-    srcs: [
-        "types.hal",
-        "IBluetoothAudioPort.hal",
-        "IBluetoothAudioProvider.hal",
-        "IBluetoothAudioProvidersFactory.hal",
-    ],
-    interfaces: [
-        "android.hardware.audio.common@5.0",
-        "android.hardware.bluetooth.audio@2.0",
-        "android.hardware.bluetooth.audio@2.1",
-        "android.hidl.base@1.0",
-        "android.hidl.safe_union@1.0",
-    ],
-    apex_available: [
-        "//apex_available:platform",
-        "com.android.bluetooth",
-    ],
-    gen_java: false,
-}
diff --git a/bluetooth/audio/2.2/IBluetoothAudioPort.hal b/bluetooth/audio/2.2/IBluetoothAudioPort.hal
deleted file mode 100644
index 344899c..0000000
--- a/bluetooth/audio/2.2/IBluetoothAudioPort.hal
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.hardware.bluetooth.audio@2.2;
-
-import @2.0::IBluetoothAudioPort;
-import android.hardware.audio.common@5.0::SinkMetadata;
-
-interface IBluetoothAudioPort extends @2.0::IBluetoothAudioPort  {
-    /**
-     * Called when the metadata of the stream's sink has been changed.
-     *
-     * @param sinkMetadata Description of the audio that is recorded by the
-     *    clients.
-     */
-    updateSinkMetadata(SinkMetadata sinkMetadata);
-};
diff --git a/bluetooth/audio/2.2/IBluetoothAudioProvider.hal b/bluetooth/audio/2.2/IBluetoothAudioProvider.hal
deleted file mode 100644
index 7c91805..0000000
--- a/bluetooth/audio/2.2/IBluetoothAudioProvider.hal
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.hardware.bluetooth.audio@2.2;
-
-import @2.1::IBluetoothAudioProvider;
-import @2.2::IBluetoothAudioPort;
-import @2.0::Status;
-
-/**
- * HAL interface from the Bluetooth stack to the Audio HAL
- *
- * The Bluetooth stack calls methods in this interface to start and end audio
- * sessions and sends callback events to the Audio HAL.
- *
- * Note: For HIDL APIs with a "generates" statement, the callback parameter used
- * for return value must be invoked synchronously before the API call returns.
- */
-interface IBluetoothAudioProvider extends @2.1::IBluetoothAudioProvider {
-
-    /**
-     * This method indicates that the Bluetooth stack is ready to stream audio.
-     * It registers an instance of IBluetoothAudioPort with and provides the
-     * current negotiated codec to the Audio HAL. After this method is called,
-     * the Audio HAL can invoke IBluetoothAudioPort.startStream().
-     *
-     * Note: endSession() must be called to unregister this IBluetoothAudioPort
-     *
-     * @param hostIf An instance of IBluetoothAudioPort for stream control
-     * @param audioConfig The audio configuration negotiated with the remote
-     *    device. The PCM parameters are set if software based encoding,
-     *    otherwise the correct codec configuration is used for hardware
-     *    encoding.
-     *
-     * @return status One of the following
-     *    SUCCESS if this IBluetoothAudioPort was successfully registered with
-     *        the Audio HAL
-     *    UNSUPPORTED_CODEC_CONFIGURATION if the Audio HAL cannot register this
-     *        IBluetoothAudioPort with the given codec configuration
-     *    FAILURE if the Audio HAL cannot register this IBluetoothAudioPort for
-     *        any other reason
-     * @return dataMQ The fast message queue for audio data from/to this
-     *    provider. Audio data will be in PCM format as specified by the
-     *    audioConfig.pcmConfig parameter. Invalid if streaming is offloaded
-     *    from/to hardware or on failure.
-     */
-    startSession_2_2(IBluetoothAudioPort hostIf, AudioConfiguration audioConfig)
-                generates (Status status, fmq_sync<uint8_t> dataMQ);
-
-    /**
-     * Called when the audio configuration of the stream has been changed.
-     *
-     * @param audioConfig The audio configuration negotiated with the remote
-     *    device. The PCM parameters are set if software based encoding,
-     *    otherwise the correct codec configuration is used for hardware
-     *    encoding.
-     */
-    updateAudioConfiguration(AudioConfiguration audioConfig);
-
-    /**
-     * Called when the supported latency mode is updated.
-     *
-     * @param allowed If the peripheral devices can't keep up with low latency
-     * mode, the API will be called with supported is false.
-     */
-    setLowLatencyModeAllowed(bool allowed);
-};
diff --git a/bluetooth/audio/2.2/IBluetoothAudioProvidersFactory.hal b/bluetooth/audio/2.2/IBluetoothAudioProvidersFactory.hal
deleted file mode 100644
index ae9c598..0000000
--- a/bluetooth/audio/2.2/IBluetoothAudioProvidersFactory.hal
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.hardware.bluetooth.audio@2.2;
-
-import IBluetoothAudioProvider;
-import @2.1::IBluetoothAudioProvidersFactory;
-import @2.0::Status;
-import @2.1::SessionType;
-
-/**
- * This factory allows a HAL implementation to be split into multiple
- * independent providers.
- *
- * When the Bluetooth stack is ready to create an audio session, it must first
- * obtain the IBluetoothAudioProvider for that session type by calling
- * openProvider().
- *
- * Note: For HIDL APIs with a "generates" statement, the callback parameter used
- * for return value must be invoked synchronously before the API call returns.
- */
-interface IBluetoothAudioProvidersFactory extends @2.1::IBluetoothAudioProvidersFactory {
-    /**
-     * Opens an audio provider for a session type. To close the provider, it is
-     * necessary to release references to the returned provider object.
-     *
-     * @param sessionType The session type (e.g.
-     *    LE_AUDIO_SOFTWARE_ENCODING_DATAPATH).
-     *
-     * @return status One of the following
-     *    SUCCESS if the Audio HAL successfully opens the provider with the
-     *        given session type
-     *    FAILURE if the Audio HAL cannot open the provider
-     * @return provider The provider of the specified session type
-     */
-    openProvider_2_2(SessionType sessionType)
-        generates (Status status, IBluetoothAudioProvider provider);
-
-    /**
-     * Gets a list of audio capabilities for a session type.
-     *
-     * For software encoding, the PCM capabilities are returned.
-     * For hardware encoding, the supported codecs and their capabilities are
-     * returned.
-     *
-     * @param sessionType The session type (e.g.
-     *    A2DP_SOFTWARE_ENCODING_DATAPATH).
-     * @return audioCapabilities A list containing all the capabilities
-     *    supported by the sesson type. The capabilities is a list of
-     *    available options when configuring the codec for the session.
-     *    For software encoding it is the PCM data rate.
-     *    For hardware encoding it is the list of supported codecs and their
-     *    capabilities.
-     *    If a provider isn't supported, an empty list should be returned.
-     *    Note: Only one entry should exist per codec when using hardware
-     *    encoding.
-     */
-     getProviderCapabilities_2_2(SessionType sessionType)
-         generates (vec<AudioCapabilities> audioCapabilities);
-};
diff --git a/bluetooth/audio/2.2/OWNERS b/bluetooth/audio/2.2/OWNERS
deleted file mode 100644
index 84f5b1e..0000000
--- a/bluetooth/audio/2.2/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-aliceypkuo@google.com
-ugoyu@google.com
-sattiraju@google.com
diff --git a/bluetooth/audio/2.2/default/A2dpOffloadAudioProvider.cpp b/bluetooth/audio/2.2/default/A2dpOffloadAudioProvider.cpp
deleted file mode 100644
index 2a6d93a..0000000
--- a/bluetooth/audio/2.2/default/A2dpOffloadAudioProvider.cpp
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "BTAudioProviderA2dpOffload"
-
-#include "A2dpOffloadAudioProvider.h"
-
-#include <android-base/logging.h>
-#include <fmq/MessageQueue.h>
-#include <hidl/MQDescriptor.h>
-
-#include "BluetoothAudioSessionReport_2_2.h"
-#include "BluetoothAudioSupportedCodecsDB_2_1.h"
-
-namespace android {
-namespace hardware {
-namespace bluetooth {
-namespace audio {
-namespace V2_2 {
-namespace implementation {
-
-using ::android::bluetooth::audio::BluetoothAudioSessionReport_2_2;
-using ::android::hardware::kSynchronizedReadWrite;
-using ::android::hardware::MessageQueue;
-using ::android::hardware::Void;
-using ::android::hardware::bluetooth::audio::V2_0::AudioConfiguration;
-
-using DataMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
-
-A2dpOffloadAudioProvider::A2dpOffloadAudioProvider()
-    : BluetoothAudioProvider() {
-  session_type_ = V2_1::SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH;
-}
-
-bool A2dpOffloadAudioProvider::isValid(const V2_0::SessionType& sessionType) {
-  return isValid(static_cast<V2_1::SessionType>(sessionType));
-}
-
-bool A2dpOffloadAudioProvider::isValid(const V2_1::SessionType& sessionType) {
-  return (sessionType == session_type_);
-}
-
-Return<void> A2dpOffloadAudioProvider::startSession(
-    const sp<V2_0::IBluetoothAudioPort>& hostIf,
-    const AudioConfiguration& audioConfig, startSession_cb _hidl_cb) {
-  /**
-   * Initialize the audio platform if audioConfiguration is supported.
-   * Save the IBluetoothAudioPort interface, so that it can be used
-   * later to send stream control commands to the HAL client, based on
-   * interaction with Audio framework.
-   */
-  if (audioConfig.getDiscriminator() !=
-      AudioConfiguration::hidl_discriminator::codecConfig) {
-    LOG(WARNING) << __func__
-                 << " - Invalid Audio Configuration=" << toString(audioConfig);
-    _hidl_cb(BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION,
-             DataMQ::Descriptor());
-    return Void();
-  } else if (!android::bluetooth::audio::IsOffloadCodecConfigurationValid(
-                 session_type_, audioConfig.codecConfig())) {
-    _hidl_cb(BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION,
-             DataMQ::Descriptor());
-    return Void();
-  }
-
-  return BluetoothAudioProvider::startSession(hostIf, audioConfig, _hidl_cb);
-}
-
-Return<void> A2dpOffloadAudioProvider::onSessionReady(
-    startSession_cb _hidl_cb) {
-  BluetoothAudioSessionReport_2_2::OnSessionStarted(session_type_, stack_iface_,
-                                                    nullptr, audio_config_);
-  _hidl_cb(BluetoothAudioStatus::SUCCESS, DataMQ::Descriptor());
-  return Void();
-}
-
-}  // namespace implementation
-}  // namespace V2_2
-}  // namespace audio
-}  // namespace bluetooth
-}  // namespace hardware
-}  // namespace android
diff --git a/bluetooth/audio/2.2/default/A2dpOffloadAudioProvider.h b/bluetooth/audio/2.2/default/A2dpOffloadAudioProvider.h
deleted file mode 100644
index 7ccdedc..0000000
--- a/bluetooth/audio/2.2/default/A2dpOffloadAudioProvider.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include "BluetoothAudioProvider.h"
-
-namespace android {
-namespace hardware {
-namespace bluetooth {
-namespace audio {
-namespace V2_2 {
-namespace implementation {
-
-class A2dpOffloadAudioProvider : public BluetoothAudioProvider {
- public:
-  A2dpOffloadAudioProvider();
-
-  bool isValid(const V2_1::SessionType& sessionType) override;
-  bool isValid(const V2_0::SessionType& sessionType) override;
-
-  Return<void> startSession(const sp<V2_0::IBluetoothAudioPort>& hostIf,
-                            const V2_0::AudioConfiguration& audioConfig,
-                            startSession_cb _hidl_cb) override;
-
- private:
-  Return<void> onSessionReady(startSession_cb _hidl_cb) override;
-};
-
-}  // namespace implementation
-}  // namespace V2_2
-}  // namespace audio
-}  // namespace bluetooth
-}  // namespace hardware
-}  // namespace android
diff --git a/bluetooth/audio/2.2/default/A2dpSoftwareAudioProvider.cpp b/bluetooth/audio/2.2/default/A2dpSoftwareAudioProvider.cpp
deleted file mode 100644
index eb87178..0000000
--- a/bluetooth/audio/2.2/default/A2dpSoftwareAudioProvider.cpp
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "BTAudioProviderA2dpSoftware"
-
-#include "A2dpSoftwareAudioProvider.h"
-
-#include <android-base/logging.h>
-
-#include "BluetoothAudioSessionReport_2_2.h"
-#include "BluetoothAudioSupportedCodecsDB_2_2.h"
-
-namespace android {
-namespace hardware {
-namespace bluetooth {
-namespace audio {
-namespace V2_2 {
-namespace implementation {
-
-using ::android::bluetooth::audio::BluetoothAudioSessionReport_2_2;
-using ::android::hardware::Void;
-using ::android::hardware::bluetooth::audio::V2_0::AudioConfiguration;
-
-// Here the buffer size is based on SBC
-static constexpr uint32_t kPcmFrameSize = 4;  // 16 bits per sample / stereo
-// SBC is 128, and here we choose the LCM of 16, 24, and 32
-static constexpr uint32_t kPcmFrameCount = 96;
-static constexpr uint32_t kRtpFrameSize = kPcmFrameSize * kPcmFrameCount;
-// The max counts by 1 tick (20ms) for SBC is about 7. Since using 96 for the
-// PCM counts, here we just choose a greater number
-static constexpr uint32_t kRtpFrameCount = 10;
-static constexpr uint32_t kBufferSize = kRtpFrameSize * kRtpFrameCount;
-static constexpr uint32_t kBufferCount = 2;  // double buffer
-static constexpr uint32_t kDataMqSize = kBufferSize * kBufferCount;
-
-A2dpSoftwareAudioProvider::A2dpSoftwareAudioProvider()
-    : BluetoothAudioProvider(), mDataMQ(nullptr) {
-  LOG(INFO) << __func__ << " - size of audio buffer " << kDataMqSize
-            << " byte(s)";
-  std::unique_ptr<DataMQ> tempDataMQ(
-      new DataMQ(kDataMqSize, /* EventFlag */ true));
-  if (tempDataMQ && tempDataMQ->isValid()) {
-    mDataMQ = std::move(tempDataMQ);
-    session_type_ = V2_1::SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH;
-  } else {
-    ALOGE_IF(!tempDataMQ, "failed to allocate data MQ");
-    ALOGE_IF(tempDataMQ && !tempDataMQ->isValid(), "data MQ is invalid");
-  }
-}
-
-bool A2dpSoftwareAudioProvider::isValid(const V2_0::SessionType& sessionType) {
-  return isValid(static_cast<V2_1::SessionType>(sessionType));
-}
-
-bool A2dpSoftwareAudioProvider::isValid(const V2_1::SessionType& sessionType) {
-  return (sessionType == session_type_ && mDataMQ && mDataMQ->isValid());
-}
-
-Return<void> A2dpSoftwareAudioProvider::startSession(
-    const sp<V2_0::IBluetoothAudioPort>& hostIf,
-    const AudioConfiguration& audioConfig, startSession_cb _hidl_cb) {
-  /**
-   * Initialize the audio platform if audioConfiguration is supported.
-   * Save the IBluetoothAudioPort interface, so that it can be used
-   * later to send stream control commands to the HAL client, based on
-   * interaction with Audio framework.
-   */
-  if (audioConfig.getDiscriminator() !=
-      AudioConfiguration::hidl_discriminator::pcmConfig) {
-    LOG(WARNING) << __func__
-                 << " - Invalid Audio Configuration=" << toString(audioConfig);
-    _hidl_cb(BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION,
-             DataMQ::Descriptor());
-    return Void();
-  } else if (!android::bluetooth::audio::IsSoftwarePcmConfigurationValid(
-                 audioConfig.pcmConfig())) {
-    LOG(WARNING) << __func__ << " - Unsupported PCM Configuration="
-                 << toString(audioConfig.pcmConfig());
-    _hidl_cb(BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION,
-             DataMQ::Descriptor());
-    return Void();
-  }
-
-  return BluetoothAudioProvider::startSession(hostIf, audioConfig, _hidl_cb);
-}
-
-Return<void> A2dpSoftwareAudioProvider::onSessionReady(
-    startSession_cb _hidl_cb) {
-  if (mDataMQ && mDataMQ->isValid()) {
-    BluetoothAudioSessionReport_2_2::OnSessionStarted(
-        session_type_, stack_iface_, mDataMQ->getDesc(), audio_config_);
-    _hidl_cb(BluetoothAudioStatus::SUCCESS, *mDataMQ->getDesc());
-  } else {
-    _hidl_cb(BluetoothAudioStatus::FAILURE, DataMQ::Descriptor());
-  }
-  return Void();
-}
-
-}  // namespace implementation
-}  // namespace V2_2
-}  // namespace audio
-}  // namespace bluetooth
-}  // namespace hardware
-}  // namespace android
diff --git a/bluetooth/audio/2.2/default/A2dpSoftwareAudioProvider.h b/bluetooth/audio/2.2/default/A2dpSoftwareAudioProvider.h
deleted file mode 100644
index ac3aece..0000000
--- a/bluetooth/audio/2.2/default/A2dpSoftwareAudioProvider.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <fmq/MessageQueue.h>
-#include <hidl/MQDescriptor.h>
-
-#include "BluetoothAudioProvider.h"
-
-namespace android {
-namespace hardware {
-namespace bluetooth {
-namespace audio {
-namespace V2_2 {
-namespace implementation {
-
-using ::android::hardware::kSynchronizedReadWrite;
-using ::android::hardware::MessageQueue;
-
-using DataMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
-
-class A2dpSoftwareAudioProvider : public BluetoothAudioProvider {
- public:
-  A2dpSoftwareAudioProvider();
-
-  bool isValid(const V2_1::SessionType& sessionType) override;
-  bool isValid(const V2_0::SessionType& sessionType) override;
-
-  Return<void> startSession(const sp<V2_0::IBluetoothAudioPort>& hostIf,
-                            const V2_0::AudioConfiguration& audioConfig,
-                            startSession_cb _hidl_cb) override;
-
- private:
-  // audio data queue for software encoding
-  std::unique_ptr<DataMQ> mDataMQ;
-
-  Return<void> onSessionReady(startSession_cb _hidl_cb) override;
-};
-
-}  // namespace implementation
-}  // namespace V2_2
-}  // namespace audio
-}  // namespace bluetooth
-}  // namespace hardware
-}  // namespace android
diff --git a/bluetooth/audio/2.2/default/Android.bp b/bluetooth/audio/2.2/default/Android.bp
deleted file mode 100644
index 7a5ae75..0000000
--- a/bluetooth/audio/2.2/default/Android.bp
+++ /dev/null
@@ -1,37 +0,0 @@
-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"],
-}
-
-cc_library_shared {
-    name: "android.hardware.bluetooth.audio@2.2-impl",
-    defaults: ["hidl_defaults"],
-    vendor: true,
-    relative_install_path: "hw",
-    srcs: [
-        "BluetoothAudioProvidersFactory.cpp",
-        "BluetoothAudioProvider.cpp",
-        "A2dpOffloadAudioProvider.cpp",
-        "A2dpSoftwareAudioProvider.cpp",
-        "HearingAidAudioProvider.cpp",
-        "LeAudioAudioProvider.cpp",
-        "LeAudioOffloadAudioProvider.cpp",
-    ],
-    header_libs: ["libhardware_headers"],
-    shared_libs: [
-        "android.hardware.bluetooth.audio@2.0",
-        "android.hardware.bluetooth.audio@2.1",
-        "android.hardware.bluetooth.audio@2.2",
-        "libbase",
-        "libbluetooth_audio_session",
-        "libcutils",
-        "libfmq",
-        "libhidlbase",
-        "liblog",
-        "libutils",
-    ],
-}
diff --git a/bluetooth/audio/2.2/default/AudioPort_2_0_to_2_2_Wrapper.h b/bluetooth/audio/2.2/default/AudioPort_2_0_to_2_2_Wrapper.h
deleted file mode 100644
index c5613fb..0000000
--- a/bluetooth/audio/2.2/default/AudioPort_2_0_to_2_2_Wrapper.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <android/hardware/bluetooth/audio/2.2/types.h>
-
-namespace android {
-namespace hardware {
-namespace bluetooth {
-namespace audio {
-namespace V2_2 {
-namespace implementation {
-
-using ::android::sp;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-using ::android::hardware::audio::common::V5_0::SinkMetadata;
-using ::android::hardware::audio::common::V5_0::SourceMetadata;
-using ::android::hardware::bluetooth::audio::V2_2::IBluetoothAudioPort;
-
-class AudioPort_2_0_to_2_2_Wrapper : public V2_2::IBluetoothAudioPort {
- public:
-  AudioPort_2_0_to_2_2_Wrapper(const sp<V2_0::IBluetoothAudioPort>& port) {
-    this->port = port;
-  }
-
-  Return<void> startStream() override { return port->startStream(); }
-  Return<void> suspendStream() override { return port->suspendStream(); }
-  Return<void> stopStream() override { return port->stopStream(); }
-  Return<void> getPresentationPosition(
-      getPresentationPosition_cb _hidl_cb) override {
-    return port->getPresentationPosition(_hidl_cb);
-  }
-  Return<void> updateMetadata(const SourceMetadata& sourceMetadata) override {
-    return port->updateMetadata(sourceMetadata);
-  }
-  Return<void> updateSinkMetadata(const SinkMetadata&) override {
-    // DO NOTHING, 2.0 AudioPort doesn't support sink metadata updates
-    return Void();
-  }
-
-  sp<V2_0::IBluetoothAudioPort> port;
-};
-
-}  // namespace implementation
-}  // namespace V2_2
-}  // namespace audio
-}  // namespace bluetooth
-}  // namespace hardware
-}  // namespace android
\ No newline at end of file
diff --git a/bluetooth/audio/2.2/default/BluetoothAudioProvider.cpp b/bluetooth/audio/2.2/default/BluetoothAudioProvider.cpp
deleted file mode 100644
index 62511e9..0000000
--- a/bluetooth/audio/2.2/default/BluetoothAudioProvider.cpp
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "BTAudioProviderStub"
-
-#include "BluetoothAudioProvider.h"
-
-#include <android-base/logging.h>
-
-#include "AudioPort_2_0_to_2_2_Wrapper.h"
-#include "BluetoothAudioSessionReport_2_2.h"
-#include "BluetoothAudioSupportedCodecsDB_2_2.h"
-
-namespace android {
-namespace hardware {
-namespace bluetooth {
-namespace audio {
-namespace V2_2 {
-namespace implementation {
-
-using ::android::bluetooth::audio::BluetoothAudioSessionReport_2_2;
-using ::android::hardware::kSynchronizedReadWrite;
-using ::android::hardware::MessageQueue;
-using ::android::hardware::Void;
-
-using DataMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
-
-void BluetoothAudioDeathRecipient::serviceDied(
-    uint64_t cookie __unused,
-    const wp<::android::hidl::base::V1_0::IBase>& who __unused) {
-  LOG(ERROR) << "BluetoothAudioDeathRecipient::" << __func__
-             << " - BluetoothAudio Service died";
-  provider_->endSession();
-}
-
-BluetoothAudioProvider::BluetoothAudioProvider()
-    : death_recipient_(new BluetoothAudioDeathRecipient(this)),
-      session_type_(V2_1::SessionType::UNKNOWN),
-      audio_config_({}) {}
-
-Return<void> BluetoothAudioProvider::startSession(
-    const sp<V2_0::IBluetoothAudioPort>& hostIf,
-    const V2_0::AudioConfiguration& audioConfig, startSession_cb _hidl_cb) {
-  AudioConfiguration audioConfig_2_2;
-
-  if (audioConfig.getDiscriminator() ==
-      V2_0::AudioConfiguration::hidl_discriminator::pcmConfig) {
-    audioConfig_2_2.pcmConfig(
-        {.sampleRate =
-             static_cast<V2_1::SampleRate>(audioConfig.pcmConfig().sampleRate),
-         .channelMode = audioConfig.pcmConfig().channelMode,
-         .bitsPerSample = audioConfig.pcmConfig().bitsPerSample,
-         .dataIntervalUs = 0});
-  } else {
-    audioConfig_2_2.codecConfig(audioConfig.codecConfig());
-  }
-
-  sp<V2_2::IBluetoothAudioPort> hostIf_2_2 =
-      new AudioPort_2_0_to_2_2_Wrapper(hostIf);
-  return startSession_2_2(hostIf_2_2, audioConfig_2_2, _hidl_cb);
-}
-
-Return<void> BluetoothAudioProvider::startSession_2_1(
-    const sp<V2_0::IBluetoothAudioPort>& hostIf,
-    const V2_1::AudioConfiguration& audioConfig, startSession_cb _hidl_cb) {
-  AudioConfiguration audioConfig_2_2;
-  if (audioConfig.getDiscriminator() ==
-      V2_1::AudioConfiguration::hidl_discriminator::leAudioCodecConfig) {
-    audioConfig_2_2.leAudioConfig().mode = LeAudioMode::UNKNOWN;
-    audioConfig_2_2.leAudioConfig().config.unicastConfig() = {
-        .streamMap = {{
-            .streamHandle = 0xFFFF,
-            .audioChannelAllocation =
-                audioConfig.leAudioCodecConfig().audioChannelAllocation,
-        }},
-        .peerDelay = 0,
-        .lc3Config = audioConfig.leAudioCodecConfig().lc3Config};
-  } else if (audioConfig.getDiscriminator() ==
-             V2_1::AudioConfiguration::hidl_discriminator::pcmConfig) {
-    audioConfig_2_2.pcmConfig(audioConfig.pcmConfig());
-  } else {
-    audioConfig_2_2.codecConfig(audioConfig.codecConfig());
-  }
-
-  sp<V2_2::IBluetoothAudioPort> hostIf_2_2 =
-      new AudioPort_2_0_to_2_2_Wrapper(hostIf);
-  return startSession_2_2(hostIf_2_2, audioConfig_2_2, _hidl_cb);
-}
-
-Return<void> BluetoothAudioProvider::startSession_2_2(
-    const sp<V2_2::IBluetoothAudioPort>& hostIf,
-    const AudioConfiguration& audioConfig, startSession_cb _hidl_cb) {
-  if (hostIf == nullptr) {
-    _hidl_cb(BluetoothAudioStatus::FAILURE, DataMQ::Descriptor());
-    return Void();
-  }
-
-  /**
-   * Initialize the audio platform if audioConfiguration is supported.
-   * Save the IBluetoothAudioPort interface, so that it can be used
-   * later to send stream control commands to the HAL client, based on
-   * interaction with Audio framework.
-   */
-  audio_config_ = audioConfig;
-  stack_iface_ = hostIf;
-  stack_iface_->linkToDeath(death_recipient_, 0);
-
-  LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
-            << ", AudioConfiguration=[" << toString(audio_config_) << "]";
-
-  onSessionReady(_hidl_cb);
-  return Void();
-}
-
-Return<void> BluetoothAudioProvider::streamStarted(
-    BluetoothAudioStatus status) {
-  LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
-            << ", status=" << toString(status);
-
-  /**
-   * Streaming on control path has started,
-   * HAL server should start the streaming on data path.
-   */
-  if (stack_iface_) {
-    BluetoothAudioSessionReport_2_2::ReportControlStatus(session_type_, true,
-                                                         status);
-  } else {
-    LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
-                 << ", status=" << toString(status) << " has NO session";
-  }
-
-  return Void();
-}
-
-Return<void> BluetoothAudioProvider::streamSuspended(
-    BluetoothAudioStatus status) {
-  LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
-            << ", status=" << toString(status);
-
-  /**
-   * Streaming on control path has suspend,
-   * HAL server should suspend the streaming on data path.
-   */
-  if (stack_iface_) {
-    BluetoothAudioSessionReport_2_2::ReportControlStatus(session_type_, false,
-                                                         status);
-  } else {
-    LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
-                 << ", status=" << toString(status) << " has NO session";
-  }
-
-  return Void();
-}
-
-Return<void> BluetoothAudioProvider::endSession() {
-  LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_);
-
-  if (stack_iface_) {
-    BluetoothAudioSessionReport_2_2::OnSessionEnded(session_type_);
-    stack_iface_->unlinkToDeath(death_recipient_);
-  } else {
-    LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
-              << " has NO session";
-  }
-
-  /**
-   * Clean up the audio platform as remote audio device is no
-   * longer active
-   */
-  stack_iface_ = nullptr;
-  audio_config_ = {};
-
-  return Void();
-}
-
-Return<void> BluetoothAudioProvider::updateAudioConfiguration(
-    const AudioConfiguration& audioConfig) {
-  LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_);
-
-  if (stack_iface_ == nullptr) {
-    LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
-              << " has NO session";
-    return Void();
-  }
-
-  if (audioConfig.getDiscriminator() != audio_config_.getDiscriminator()) {
-    LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
-              << " audio config type is not match";
-    return Void();
-  }
-
-  audio_config_ = audioConfig;
-  BluetoothAudioSessionReport_2_2::ReportAudioConfigChanged(session_type_,
-                                                            audio_config_);
-
-  return Void();
-}
-
-Return<void> BluetoothAudioProvider::setLowLatencyModeAllowed(bool allowed) {
-  LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_);
-
-  if (stack_iface_ == nullptr) {
-    LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
-              << " has NO session";
-    return Void();
-  }
-  LOG(INFO) << __func__ << " allowed: " << allowed;
-  return Void();
-}
-
-}  // namespace implementation
-}  // namespace V2_2
-}  // namespace audio
-}  // namespace bluetooth
-}  // namespace hardware
-}  // namespace android
diff --git a/bluetooth/audio/2.2/default/BluetoothAudioProvider.h b/bluetooth/audio/2.2/default/BluetoothAudioProvider.h
deleted file mode 100644
index 90c158e..0000000
--- a/bluetooth/audio/2.2/default/BluetoothAudioProvider.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <android/hardware/bluetooth/audio/2.2/IBluetoothAudioProvider.h>
-
-namespace android {
-namespace hardware {
-namespace bluetooth {
-namespace audio {
-namespace V2_2 {
-namespace implementation {
-
-using ::android::sp;
-using ::android::hardware::bluetooth::audio::V2_2::IBluetoothAudioPort;
-
-using BluetoothAudioStatus =
-    ::android::hardware::bluetooth::audio::V2_0::Status;
-
-class BluetoothAudioDeathRecipient;
-
-class BluetoothAudioProvider : public IBluetoothAudioProvider {
- public:
-  BluetoothAudioProvider();
-  ~BluetoothAudioProvider() = default;
-
-  virtual bool isValid(const V2_1::SessionType& sessionType) = 0;
-  virtual bool isValid(const V2_0::SessionType& sessionType) = 0;
-
-  Return<void> startSession(const sp<V2_0::IBluetoothAudioPort>& hostIf,
-                            const V2_0::AudioConfiguration& audioConfig,
-                            startSession_cb _hidl_cb) override;
-  Return<void> startSession_2_1(const sp<V2_0::IBluetoothAudioPort>& hostIf,
-                                const V2_1::AudioConfiguration& audioConfig,
-                                startSession_cb _hidl_cb) override;
-  Return<void> startSession_2_2(const sp<V2_2::IBluetoothAudioPort>& hostIf,
-                                const AudioConfiguration& audioConfig,
-                                startSession_cb _hidl_cb) override;
-  Return<void> streamStarted(BluetoothAudioStatus status) override;
-  Return<void> streamSuspended(BluetoothAudioStatus status) override;
-  Return<void> endSession() override;
-  Return<void> updateAudioConfiguration(
-      const AudioConfiguration& audioConfig) override;
-
-  Return<void> setLowLatencyModeAllowed(bool allowed) override;
-
- protected:
-  sp<BluetoothAudioDeathRecipient> death_recipient_;
-
-  V2_1::SessionType session_type_;
-  AudioConfiguration audio_config_;
-  sp<V2_2::IBluetoothAudioPort> stack_iface_;
-
-  virtual Return<void> onSessionReady(startSession_cb _hidl_cb) = 0;
-};
-
-class BluetoothAudioDeathRecipient : public hidl_death_recipient {
- public:
-  BluetoothAudioDeathRecipient(const sp<BluetoothAudioProvider> provider)
-      : provider_(provider) {}
-
-  virtual void serviceDied(
-      uint64_t cookie,
-      const wp<::android::hidl::base::V1_0::IBase>& who) override;
-
- private:
-  sp<BluetoothAudioProvider> provider_;
-};
-
-}  // namespace implementation
-}  // namespace V2_2
-}  // namespace audio
-}  // namespace bluetooth
-}  // namespace hardware
-}  // namespace android
diff --git a/bluetooth/audio/2.2/default/BluetoothAudioProvidersFactory.cpp b/bluetooth/audio/2.2/default/BluetoothAudioProvidersFactory.cpp
deleted file mode 100644
index 490a436..0000000
--- a/bluetooth/audio/2.2/default/BluetoothAudioProvidersFactory.cpp
+++ /dev/null
@@ -1,269 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "BTAudioProvidersFactory"
-
-#include "BluetoothAudioProvidersFactory.h"
-
-#include <android-base/logging.h>
-
-#include "BluetoothAudioSupportedCodecsDB_2_2.h"
-
-namespace android {
-namespace hardware {
-namespace bluetooth {
-namespace audio {
-namespace V2_2 {
-namespace implementation {
-
-using ::android::hardware::hidl_vec;
-using ::android::hardware::Void;
-using ::android::hardware::bluetooth::audio::V2_0::CodecCapabilities;
-
-A2dpSoftwareAudioProvider
-    BluetoothAudioProvidersFactory::a2dp_software_provider_instance_;
-A2dpOffloadAudioProvider
-    BluetoothAudioProvidersFactory::a2dp_offload_provider_instance_;
-HearingAidAudioProvider
-    BluetoothAudioProvidersFactory::hearing_aid_provider_instance_;
-LeAudioOutputAudioProvider
-    BluetoothAudioProvidersFactory::leaudio_output_provider_instance_;
-LeAudioOffloadOutputAudioProvider
-    BluetoothAudioProvidersFactory::leaudio_offload_output_provider_instance_;
-LeAudioInputAudioProvider
-    BluetoothAudioProvidersFactory::leaudio_input_provider_instance_;
-LeAudioOffloadInputAudioProvider
-    BluetoothAudioProvidersFactory::leaudio_offload_input_provider_instance_;
-
-Return<void> BluetoothAudioProvidersFactory::openProvider(
-    const V2_0::SessionType sessionType, openProvider_cb _hidl_cb) {
-  LOG(INFO) << __func__ << " - SessionType=" << toString(sessionType);
-  BluetoothAudioStatus status = BluetoothAudioStatus::SUCCESS;
-  BluetoothAudioProvider* provider = nullptr;
-
-  switch (sessionType) {
-    case V2_0::SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH:
-      provider = &a2dp_software_provider_instance_;
-      break;
-    case V2_0::SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH:
-      provider = &a2dp_offload_provider_instance_;
-      break;
-    case V2_0::SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH:
-      provider = &hearing_aid_provider_instance_;
-      break;
-    default:
-      status = BluetoothAudioStatus::FAILURE;
-  }
-
-  if (provider == nullptr || !provider->isValid(sessionType)) {
-    provider = nullptr;
-    status = BluetoothAudioStatus::FAILURE;
-    LOG(ERROR) << __func__ << " - SessionType=" << toString(sessionType)
-               << ", status=" << toString(status);
-  }
-
-  _hidl_cb(status, provider);
-  return Void();
-}
-
-Return<void> BluetoothAudioProvidersFactory::openProvider_2_1(
-    const V2_1::SessionType sessionType, openProvider_2_1_cb _hidl_cb) {
-  LOG(INFO) << __func__ << " - SessionType=" << toString(sessionType);
-  BluetoothAudioStatus status = BluetoothAudioStatus::SUCCESS;
-  BluetoothAudioProvider* provider = nullptr;
-
-  switch (sessionType) {
-    case V2_1::SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH:
-      provider = &a2dp_software_provider_instance_;
-      break;
-    case V2_1::SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH:
-      provider = &a2dp_offload_provider_instance_;
-      break;
-    case V2_1::SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH:
-      provider = &hearing_aid_provider_instance_;
-      break;
-    case V2_1::SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH:
-      provider = &leaudio_output_provider_instance_;
-      break;
-    case V2_1::SessionType::LE_AUDIO_SOFTWARE_DECODED_DATAPATH:
-      provider = &leaudio_input_provider_instance_;
-      break;
-    default:
-      status = BluetoothAudioStatus::FAILURE;
-  }
-
-  if (provider == nullptr || !provider->isValid(sessionType)) {
-    provider = nullptr;
-    status = BluetoothAudioStatus::FAILURE;
-    LOG(ERROR) << __func__ << " - SessionType=" << toString(sessionType)
-               << ", status=" << toString(status);
-  }
-
-  _hidl_cb(status, provider);
-  return Void();
-}
-
-Return<void> BluetoothAudioProvidersFactory::openProvider_2_2(
-    const V2_1::SessionType sessionType, openProvider_2_2_cb _hidl_cb) {
-  LOG(INFO) << __func__ << " - SessionType=" << toString(sessionType);
-  BluetoothAudioStatus status = BluetoothAudioStatus::SUCCESS;
-  BluetoothAudioProvider* provider = nullptr;
-
-  switch (sessionType) {
-    case V2_1::SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH:
-      provider = &a2dp_software_provider_instance_;
-      break;
-    case V2_1::SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH:
-      provider = &a2dp_offload_provider_instance_;
-      break;
-    case V2_1::SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH:
-      provider = &hearing_aid_provider_instance_;
-      break;
-    case V2_1::SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH:
-      provider = &leaudio_output_provider_instance_;
-      break;
-    case V2_1::SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
-      provider = &leaudio_offload_output_provider_instance_;
-      break;
-    case V2_1::SessionType::LE_AUDIO_SOFTWARE_DECODED_DATAPATH:
-      provider = &leaudio_input_provider_instance_;
-      break;
-    case V2_1::SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH:
-      provider = &leaudio_offload_input_provider_instance_;
-      break;
-    default:
-      status = BluetoothAudioStatus::FAILURE;
-  }
-
-  if (provider == nullptr || !provider->isValid(sessionType)) {
-    provider = nullptr;
-    status = BluetoothAudioStatus::FAILURE;
-    LOG(ERROR) << __func__ << " - SessionType=" << toString(sessionType)
-               << ", status=" << toString(status);
-  }
-
-  _hidl_cb(status, provider);
-  return Void();
-}
-
-Return<void> BluetoothAudioProvidersFactory::getProviderCapabilities(
-    const V2_0::SessionType sessionType, getProviderCapabilities_cb _hidl_cb) {
-  hidl_vec<V2_0::AudioCapabilities> audio_capabilities =
-      hidl_vec<V2_0::AudioCapabilities>(0);
-  if (sessionType == V2_0::SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH) {
-    std::vector<CodecCapabilities> db_codec_capabilities =
-        android::bluetooth::audio::GetOffloadCodecCapabilities(sessionType);
-    if (db_codec_capabilities.size()) {
-      audio_capabilities.resize(db_codec_capabilities.size());
-      for (int i = 0; i < db_codec_capabilities.size(); ++i) {
-        audio_capabilities[i].codecCapabilities(db_codec_capabilities[i]);
-      }
-    }
-  } else if (sessionType != V2_0::SessionType::UNKNOWN) {
-    std::vector<::android::hardware::bluetooth::audio::V2_0::PcmParameters>
-        db_pcm_capabilities =
-            android::bluetooth::audio::GetSoftwarePcmCapabilities();
-    if (db_pcm_capabilities.size() == 1) {
-      audio_capabilities.resize(1);
-      audio_capabilities[0].pcmCapabilities(db_pcm_capabilities[0]);
-    }
-  }
-  LOG(INFO) << __func__ << " - SessionType=" << toString(sessionType)
-            << " supports " << audio_capabilities.size() << " codecs";
-  _hidl_cb(audio_capabilities);
-  return Void();
-}
-
-Return<void> BluetoothAudioProvidersFactory::getProviderCapabilities_2_1(
-    const V2_1::SessionType sessionType,
-    getProviderCapabilities_2_1_cb _hidl_cb) {
-  hidl_vec<V2_1::AudioCapabilities> audio_capabilities =
-      hidl_vec<V2_1::AudioCapabilities>(0);
-  if (sessionType == V2_1::SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH) {
-    std::vector<CodecCapabilities> db_codec_capabilities =
-        android::bluetooth::audio::GetOffloadCodecCapabilities(sessionType);
-    if (db_codec_capabilities.size()) {
-      audio_capabilities.resize(db_codec_capabilities.size());
-      for (int i = 0; i < db_codec_capabilities.size(); ++i) {
-        audio_capabilities[i].codecCapabilities(db_codec_capabilities[i]);
-      }
-    }
-  } else if (sessionType != V2_1::SessionType::UNKNOWN) {
-    std::vector<V2_1::PcmParameters> db_pcm_capabilities =
-        android::bluetooth::audio::GetSoftwarePcmCapabilities_2_1();
-    if (db_pcm_capabilities.size() == 1) {
-      audio_capabilities.resize(1);
-      audio_capabilities[0].pcmCapabilities(db_pcm_capabilities[0]);
-    }
-  }
-  LOG(INFO) << __func__ << " - SessionType=" << toString(sessionType)
-            << " supports " << audio_capabilities.size() << " codecs";
-  _hidl_cb(audio_capabilities);
-  return Void();
-}
-
-Return<void> BluetoothAudioProvidersFactory::getProviderCapabilities_2_2(
-    const V2_1::SessionType sessionType,
-    getProviderCapabilities_2_2_cb _hidl_cb) {
-  hidl_vec<V2_2::AudioCapabilities> audio_capabilities =
-      hidl_vec<V2_2::AudioCapabilities>(0);
-  if (sessionType == V2_1::SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH) {
-    std::vector<CodecCapabilities> db_codec_capabilities =
-        android::bluetooth::audio::GetOffloadCodecCapabilities(sessionType);
-    if (db_codec_capabilities.size()) {
-      audio_capabilities.resize(db_codec_capabilities.size());
-      for (int i = 0; i < db_codec_capabilities.size(); ++i) {
-        audio_capabilities[i].codecCapabilities(db_codec_capabilities[i]);
-      }
-    }
-  } else if (sessionType == V2_1::SessionType::
-                                LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
-             sessionType == V2_1::SessionType::
-                                LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
-    std::vector<LeAudioCodecCapabilitiesSetting> db_codec_capabilities =
-        android::bluetooth::audio::GetLeAudioOffloadCodecCapabilities(
-            sessionType);
-    if (db_codec_capabilities.size()) {
-      audio_capabilities.resize(db_codec_capabilities.size());
-      for (int i = 0; i < db_codec_capabilities.size(); ++i) {
-        audio_capabilities[i].leAudioCapabilities(db_codec_capabilities[i]);
-      }
-    }
-  } else if (sessionType != V2_1::SessionType::UNKNOWN) {
-    std::vector<V2_1::PcmParameters> db_pcm_capabilities =
-        android::bluetooth::audio::GetSoftwarePcmCapabilities_2_1();
-    if (db_pcm_capabilities.size() == 1) {
-      audio_capabilities.resize(1);
-      audio_capabilities[0].pcmCapabilities(db_pcm_capabilities[0]);
-    }
-  }
-  LOG(INFO) << __func__ << " - SessionType=" << toString(sessionType)
-            << " supports " << audio_capabilities.size() << " codecs";
-  _hidl_cb(audio_capabilities);
-  return Void();
-}
-
-IBluetoothAudioProvidersFactory* HIDL_FETCH_IBluetoothAudioProvidersFactory(
-    const char* /* name */) {
-  return new BluetoothAudioProvidersFactory();
-}
-
-}  // namespace implementation
-}  // namespace V2_2
-}  // namespace audio
-}  // namespace bluetooth
-}  // namespace hardware
-}  // namespace android
diff --git a/bluetooth/audio/2.2/default/BluetoothAudioProvidersFactory.h b/bluetooth/audio/2.2/default/BluetoothAudioProvidersFactory.h
deleted file mode 100644
index 4f549d9..0000000
--- a/bluetooth/audio/2.2/default/BluetoothAudioProvidersFactory.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <android/hardware/bluetooth/audio/2.2/IBluetoothAudioProvidersFactory.h>
-
-#include "A2dpOffloadAudioProvider.h"
-#include "A2dpSoftwareAudioProvider.h"
-#include "BluetoothAudioProvider.h"
-#include "HearingAidAudioProvider.h"
-#include "LeAudioAudioProvider.h"
-#include "LeAudioOffloadAudioProvider.h"
-
-namespace android {
-namespace hardware {
-namespace bluetooth {
-namespace audio {
-namespace V2_2 {
-namespace implementation {
-
-class BluetoothAudioProvidersFactory : public IBluetoothAudioProvidersFactory {
- public:
-  BluetoothAudioProvidersFactory() {}
-
-  Return<void> openProvider(const V2_0::SessionType sessionType,
-                            openProvider_cb _hidl_cb) override;
-
-  Return<void> getProviderCapabilities(
-      const V2_0::SessionType sessionType,
-      getProviderCapabilities_cb _hidl_cb) override;
-
-  Return<void> openProvider_2_1(const V2_1::SessionType sessionType,
-                                openProvider_2_1_cb _hidl_cb) override;
-
-  Return<void> openProvider_2_2(const V2_1::SessionType sessionType,
-                                openProvider_2_2_cb _hidl_cb) override;
-
-  Return<void> getProviderCapabilities_2_1(
-      const V2_1::SessionType sessionType,
-      getProviderCapabilities_2_1_cb _hidl_cb) override;
-
-  Return<void> getProviderCapabilities_2_2(
-      const V2_1::SessionType sessionType,
-      getProviderCapabilities_2_2_cb _hidl_cb) override;
-
- private:
-  static A2dpSoftwareAudioProvider a2dp_software_provider_instance_;
-  static A2dpOffloadAudioProvider a2dp_offload_provider_instance_;
-  static HearingAidAudioProvider hearing_aid_provider_instance_;
-  static LeAudioOutputAudioProvider leaudio_output_provider_instance_;
-  static LeAudioInputAudioProvider leaudio_input_provider_instance_;
-  static LeAudioOffloadOutputAudioProvider
-      leaudio_offload_output_provider_instance_;
-  static LeAudioOffloadInputAudioProvider
-      leaudio_offload_input_provider_instance_;
-};
-
-extern "C" IBluetoothAudioProvidersFactory*
-HIDL_FETCH_IBluetoothAudioProvidersFactory(const char* name);
-
-}  // namespace implementation
-}  // namespace V2_2
-}  // namespace audio
-}  // namespace bluetooth
-}  // namespace hardware
-}  // namespace android
diff --git a/bluetooth/audio/2.2/default/HearingAidAudioProvider.cpp b/bluetooth/audio/2.2/default/HearingAidAudioProvider.cpp
deleted file mode 100644
index 25e49a1..0000000
--- a/bluetooth/audio/2.2/default/HearingAidAudioProvider.cpp
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "BTAudioProviderHearingAid"
-
-#include "HearingAidAudioProvider.h"
-
-#include <android-base/logging.h>
-
-#include "BluetoothAudioSessionReport_2_2.h"
-#include "BluetoothAudioSupportedCodecsDB_2_2.h"
-
-namespace android {
-namespace hardware {
-namespace bluetooth {
-namespace audio {
-namespace V2_2 {
-namespace implementation {
-
-using ::android::bluetooth::audio::BluetoothAudioSessionReport_2_2;
-using ::android::hardware::Void;
-using ::android::hardware::bluetooth::audio::V2_0::AudioConfiguration;
-
-static constexpr uint32_t kPcmFrameSize = 4;  // 16 bits per sample / stereo
-static constexpr uint32_t kPcmFrameCount = 128;
-static constexpr uint32_t kRtpFrameSize = kPcmFrameSize * kPcmFrameCount;
-static constexpr uint32_t kRtpFrameCount = 7;  // max counts by 1 tick (20ms)
-static constexpr uint32_t kBufferSize = kRtpFrameSize * kRtpFrameCount;
-static constexpr uint32_t kBufferCount = 1;  // single buffer
-static constexpr uint32_t kDataMqSize = kBufferSize * kBufferCount;
-
-HearingAidAudioProvider::HearingAidAudioProvider()
-    : BluetoothAudioProvider(), mDataMQ(nullptr) {
-  LOG(INFO) << __func__ << " - size of audio buffer " << kDataMqSize
-            << " byte(s)";
-  std::unique_ptr<DataMQ> tempDataMQ(
-      new DataMQ(kDataMqSize, /* EventFlag */ true));
-  if (tempDataMQ && tempDataMQ->isValid()) {
-    mDataMQ = std::move(tempDataMQ);
-    session_type_ = V2_1::SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH;
-  } else {
-    ALOGE_IF(!tempDataMQ, "failed to allocate data MQ");
-    ALOGE_IF(tempDataMQ && !tempDataMQ->isValid(), "data MQ is invalid");
-  }
-}
-
-bool HearingAidAudioProvider::isValid(const V2_0::SessionType& sessionType) {
-  return isValid(static_cast<V2_1::SessionType>(sessionType));
-}
-
-bool HearingAidAudioProvider::isValid(const V2_1::SessionType& sessionType) {
-  return (sessionType == session_type_ && mDataMQ && mDataMQ->isValid());
-}
-
-Return<void> HearingAidAudioProvider::startSession(
-    const sp<V2_0::IBluetoothAudioPort>& hostIf,
-    const AudioConfiguration& audioConfig, startSession_cb _hidl_cb) {
-  /**
-   * Initialize the audio platform if audioConfiguration is supported.
-   * Save the IBluetoothAudioPort interface, so that it can be used
-   * later to send stream control commands to the HAL client, based on
-   * interaction with Audio framework.
-   */
-  if (audioConfig.getDiscriminator() !=
-      AudioConfiguration::hidl_discriminator::pcmConfig) {
-    LOG(WARNING) << __func__
-                 << " - Invalid Audio Configuration=" << toString(audioConfig);
-    _hidl_cb(BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION,
-             DataMQ::Descriptor());
-    return Void();
-  } else if (!android::bluetooth::audio::IsSoftwarePcmConfigurationValid(
-                 audioConfig.pcmConfig())) {
-    LOG(WARNING) << __func__ << " - Unsupported PCM Configuration="
-                 << toString(audioConfig.pcmConfig());
-    _hidl_cb(BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION,
-             DataMQ::Descriptor());
-    return Void();
-  }
-
-  return BluetoothAudioProvider::startSession(hostIf, audioConfig, _hidl_cb);
-}
-
-Return<void> HearingAidAudioProvider::onSessionReady(startSession_cb _hidl_cb) {
-  if (mDataMQ && mDataMQ->isValid()) {
-    BluetoothAudioSessionReport_2_2::OnSessionStarted(
-        session_type_, stack_iface_, mDataMQ->getDesc(), audio_config_);
-    _hidl_cb(BluetoothAudioStatus::SUCCESS, *mDataMQ->getDesc());
-  } else {
-    _hidl_cb(BluetoothAudioStatus::FAILURE, DataMQ::Descriptor());
-  }
-  return Void();
-}
-
-}  // namespace implementation
-}  // namespace V2_2
-}  // namespace audio
-}  // namespace bluetooth
-}  // namespace hardware
-}  // namespace android
diff --git a/bluetooth/audio/2.2/default/HearingAidAudioProvider.h b/bluetooth/audio/2.2/default/HearingAidAudioProvider.h
deleted file mode 100644
index 63290b5..0000000
--- a/bluetooth/audio/2.2/default/HearingAidAudioProvider.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <fmq/MessageQueue.h>
-#include <hidl/MQDescriptor.h>
-
-#include "BluetoothAudioProvider.h"
-
-namespace android {
-namespace hardware {
-namespace bluetooth {
-namespace audio {
-namespace V2_2 {
-namespace implementation {
-
-using ::android::hardware::kSynchronizedReadWrite;
-using ::android::hardware::MessageQueue;
-
-using DataMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
-
-class HearingAidAudioProvider : public BluetoothAudioProvider {
- public:
-  HearingAidAudioProvider();
-
-  bool isValid(const V2_1::SessionType& sessionType) override;
-  bool isValid(const V2_0::SessionType& sessionType) override;
-
-  Return<void> startSession(const sp<V2_0::IBluetoothAudioPort>& hostIf,
-                            const V2_0::AudioConfiguration& audioConfig,
-                            startSession_cb _hidl_cb) override;
-
- private:
-  // audio data queue for software encoding
-  std::unique_ptr<DataMQ> mDataMQ;
-
-  Return<void> onSessionReady(startSession_cb _hidl_cb) override;
-};
-
-}  // namespace implementation
-}  // namespace V2_2
-}  // namespace audio
-}  // namespace bluetooth
-}  // namespace hardware
-}  // namespace android
diff --git a/bluetooth/audio/2.2/default/LeAudioAudioProvider.cpp b/bluetooth/audio/2.2/default/LeAudioAudioProvider.cpp
deleted file mode 100644
index a7a0023..0000000
--- a/bluetooth/audio/2.2/default/LeAudioAudioProvider.cpp
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "BTAudioProviderLeAudio"
-
-#include "LeAudioAudioProvider.h"
-
-#include <android-base/logging.h>
-
-#include "AudioPort_2_0_to_2_2_Wrapper.h"
-#include "BluetoothAudioSessionReport_2_2.h"
-#include "BluetoothAudioSupportedCodecsDB_2_2.h"
-
-namespace android {
-namespace hardware {
-namespace bluetooth {
-namespace audio {
-namespace V2_2 {
-namespace implementation {
-
-using ::android::bluetooth::audio::BluetoothAudioSessionReport_2_2;
-using ::android::hardware::Void;
-using ::android::hardware::bluetooth::audio::V2_0::BitsPerSample;
-using ::android::hardware::bluetooth::audio::V2_0::ChannelMode;
-using ::android::hardware::bluetooth::audio::V2_1::SampleRate;
-
-static constexpr uint32_t kBufferOutCount = 2;  // two frame buffer
-static constexpr uint32_t kBufferInCount = 2;   // two frame buffer
-
-LeAudioOutputAudioProvider::LeAudioOutputAudioProvider()
-    : LeAudioAudioProvider() {
-  session_type_ = V2_1::SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH;
-}
-
-LeAudioInputAudioProvider::LeAudioInputAudioProvider()
-    : LeAudioAudioProvider() {
-  session_type_ = V2_1::SessionType::LE_AUDIO_SOFTWARE_DECODED_DATAPATH;
-}
-
-LeAudioAudioProvider::LeAudioAudioProvider()
-    : BluetoothAudioProvider(), mDataMQ(nullptr) {}
-
-bool LeAudioAudioProvider::isValid(const V2_0::SessionType& sessionType) {
-  LOG(ERROR) << __func__ << ", invalid session type for Le Audio provider: "
-             << toString(sessionType);
-
-  return false;
-}
-
-bool LeAudioAudioProvider::isValid(const V2_1::SessionType& sessionType) {
-  return (sessionType == session_type_);
-}
-
-Return<void> LeAudioAudioProvider::startSession_2_1(
-    const sp<V2_0::IBluetoothAudioPort>& hostIf,
-    const V2_1::AudioConfiguration& audioConfig, startSession_cb _hidl_cb) {
-  if (audioConfig.getDiscriminator() !=
-      V2_1::AudioConfiguration::hidl_discriminator::pcmConfig) {
-    LOG(WARNING) << __func__
-                 << " - Invalid Audio Configuration=" << toString(audioConfig);
-    _hidl_cb(BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION,
-             DataMQ::Descriptor());
-    return Void();
-  }
-
-  AudioConfiguration audioConfig_2_2;
-  audioConfig_2_2.pcmConfig(
-      {.sampleRate =
-           static_cast<V2_1::SampleRate>(audioConfig.pcmConfig().sampleRate),
-       .channelMode = audioConfig.pcmConfig().channelMode,
-       .bitsPerSample = audioConfig.pcmConfig().bitsPerSample,
-       .dataIntervalUs = 0});
-
-  sp<V2_2::IBluetoothAudioPort> hostIf_2_2 =
-      new AudioPort_2_0_to_2_2_Wrapper(hostIf);
-  return startSession_2_2(hostIf_2_2, audioConfig_2_2, _hidl_cb);
-}
-
-Return<void> LeAudioAudioProvider::startSession_2_2(
-    const sp<V2_2::IBluetoothAudioPort>& hostIf,
-    const AudioConfiguration& audioConfig, startSession_cb _hidl_cb) {
-  /**
-   * Initialize the audio platform if audioConfiguration is supported.
-   * Save the IBluetoothAudioPort interface, so that it can be used
-   * later to send stream control commands to the HAL client, based on
-   * interaction with Audio framework.
-   */
-  if (audioConfig.getDiscriminator() !=
-      AudioConfiguration::hidl_discriminator::pcmConfig) {
-    LOG(WARNING) << __func__
-                 << " - Invalid Audio Configuration=" << toString(audioConfig);
-    _hidl_cb(BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION,
-             DataMQ::Descriptor());
-    return Void();
-  } else if (!android::bluetooth::audio::IsSoftwarePcmConfigurationValid_2_1(
-                 audioConfig.pcmConfig())) {
-    LOG(WARNING) << __func__ << " - Unsupported PCM Configuration="
-                 << toString(audioConfig.pcmConfig());
-    _hidl_cb(BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION,
-             DataMQ::Descriptor());
-    return Void();
-  }
-
-  uint32_t kDataMqSize = 0;
-  switch (audioConfig.pcmConfig().sampleRate) {
-    case SampleRate::RATE_8000:
-      kDataMqSize = 8000;
-      break;
-    case SampleRate::RATE_16000:
-      kDataMqSize = 16000;
-      break;
-    case SampleRate::RATE_24000:
-      kDataMqSize = 24000;
-      break;
-    case SampleRate::RATE_32000:
-      kDataMqSize = 32000;
-      break;
-    case SampleRate::RATE_44100:
-      kDataMqSize = 44100;
-      break;
-    case SampleRate::RATE_48000:
-      kDataMqSize = 48000;
-      break;
-    default:
-      LOG(WARNING) << __func__ << " - Unsupported sampling frequency="
-                   << toString(audioConfig.pcmConfig());
-      _hidl_cb(BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION,
-               DataMQ::Descriptor());
-      return Void();
-  }
-
-  /* Number of samples per millisecond */
-  kDataMqSize = ceil(kDataMqSize / 1000);
-
-  switch (audioConfig.pcmConfig().channelMode) {
-    case ChannelMode::MONO:
-      break;
-    case ChannelMode::STEREO:
-      kDataMqSize *= 2;
-      break;
-    default:
-      /* This should never happen it would be caught while validating
-       * parameters.
-       */
-      break;
-  }
-
-  switch (audioConfig.pcmConfig().bitsPerSample) {
-    case BitsPerSample::BITS_16:
-      kDataMqSize *= 2;
-      break;
-    case BitsPerSample::BITS_24:
-      kDataMqSize *= 3;
-      break;
-    case BitsPerSample::BITS_32:
-      kDataMqSize *= 4;
-      break;
-    default:
-      /* This should never happen it would be caught while validating
-       * parameters.
-       */
-      break;
-  }
-
-  if (session_type_ == V2_1::SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH)
-    kDataMqSize *= kBufferOutCount;
-  else if (session_type_ ==
-           V2_1::SessionType::LE_AUDIO_SOFTWARE_DECODED_DATAPATH)
-    kDataMqSize *= kBufferInCount;
-  else
-    LOG(WARNING) << __func__ << ", default single buffer used";
-
-  kDataMqSize *= audioConfig.pcmConfig().dataIntervalUs / 1000;
-
-  LOG(INFO) << __func__ << " - size of audio buffer " << kDataMqSize
-            << " byte(s)";
-
-  std::unique_ptr<DataMQ> tempDataMQ(
-      new DataMQ(kDataMqSize, /* EventFlag */ true));
-  if (tempDataMQ && tempDataMQ->isValid()) {
-    mDataMQ = std::move(tempDataMQ);
-  } else {
-    ALOGE_IF(!tempDataMQ, "failed to allocate data MQ");
-    ALOGE_IF(tempDataMQ && !tempDataMQ->isValid(), "data MQ is invalid");
-    _hidl_cb(BluetoothAudioStatus::FAILURE, DataMQ::Descriptor());
-    return Void();
-  }
-
-  return BluetoothAudioProvider::startSession_2_2(hostIf, audioConfig,
-                                                  _hidl_cb);
-}
-
-Return<void> LeAudioAudioProvider::onSessionReady(startSession_cb _hidl_cb) {
-  if (mDataMQ && mDataMQ->isValid()) {
-    BluetoothAudioSessionReport_2_2::OnSessionStarted(
-        session_type_, stack_iface_, mDataMQ->getDesc(), audio_config_);
-    _hidl_cb(BluetoothAudioStatus::SUCCESS, *mDataMQ->getDesc());
-  } else {
-    _hidl_cb(BluetoothAudioStatus::FAILURE, DataMQ::Descriptor());
-  }
-  return Void();
-}
-
-}  // namespace implementation
-}  // namespace V2_2
-}  // namespace audio
-}  // namespace bluetooth
-}  // namespace hardware
-}  // namespace android
diff --git a/bluetooth/audio/2.2/default/LeAudioAudioProvider.h b/bluetooth/audio/2.2/default/LeAudioAudioProvider.h
deleted file mode 100644
index 3de1724..0000000
--- a/bluetooth/audio/2.2/default/LeAudioAudioProvider.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <android/hardware/bluetooth/audio/2.2/types.h>
-#include <fmq/MessageQueue.h>
-#include <hidl/MQDescriptor.h>
-
-#include "BluetoothAudioProvider.h"
-
-namespace android {
-namespace hardware {
-namespace bluetooth {
-namespace audio {
-namespace V2_2 {
-namespace implementation {
-
-using ::android::hardware::kSynchronizedReadWrite;
-using ::android::hardware::MessageQueue;
-
-using DataMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
-
-class LeAudioAudioProvider : public BluetoothAudioProvider {
- public:
-  LeAudioAudioProvider();
-
-  bool isValid(const V2_1::SessionType& sessionType) override;
-  bool isValid(const V2_0::SessionType& sessionType) override;
-
-  Return<void> startSession_2_1(const sp<V2_0::IBluetoothAudioPort>& hostIf,
-                                const V2_1::AudioConfiguration& audioConfig,
-                                startSession_cb _hidl_cb) override;
-
-  Return<void> startSession_2_2(const sp<V2_2::IBluetoothAudioPort>& hostIf,
-                                const AudioConfiguration& audioConfig,
-                                startSession_cb _hidl_cb) override;
-
- private:
-  /** queue for software encodec/decoded audio data */
-  std::unique_ptr<DataMQ> mDataMQ;
-
-  Return<void> onSessionReady(startSession_cb _hidl_cb) override;
-};
-
-class LeAudioOutputAudioProvider : public LeAudioAudioProvider {
- public:
-  LeAudioOutputAudioProvider();
-};
-
-class LeAudioInputAudioProvider : public LeAudioAudioProvider {
- public:
-  LeAudioInputAudioProvider();
-};
-
-}  // namespace implementation
-}  // namespace V2_2
-}  // namespace audio
-}  // namespace bluetooth
-}  // namespace hardware
-}  // namespace android
diff --git a/bluetooth/audio/2.2/default/LeAudioOffloadAudioProvider.cpp b/bluetooth/audio/2.2/default/LeAudioOffloadAudioProvider.cpp
deleted file mode 100644
index 2b0c02f..0000000
--- a/bluetooth/audio/2.2/default/LeAudioOffloadAudioProvider.cpp
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "BTAudioProviderLeAudioOffload"
-
-#include "LeAudioOffloadAudioProvider.h"
-
-#include <android-base/logging.h>
-
-#include "AudioPort_2_0_to_2_2_Wrapper.h"
-#include "BluetoothAudioSessionReport_2_2.h"
-#include "BluetoothAudioSupportedCodecsDB_2_2.h"
-
-namespace android {
-namespace hardware {
-namespace bluetooth {
-namespace audio {
-namespace V2_2 {
-namespace implementation {
-
-using ::android::bluetooth::audio::BluetoothAudioSessionReport_2_2;
-using ::android::hardware::Void;
-using ::android::hardware::bluetooth::audio::V2_0::BitsPerSample;
-using ::android::hardware::bluetooth::audio::V2_0::ChannelMode;
-using ::android::hardware::bluetooth::audio::V2_1::SampleRate;
-
-using DataMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
-
-LeAudioOffloadOutputAudioProvider::LeAudioOffloadOutputAudioProvider()
-    : LeAudioOffloadAudioProvider() {
-  session_type_ =
-      V2_1::SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH;
-}
-
-LeAudioOffloadInputAudioProvider::LeAudioOffloadInputAudioProvider()
-    : LeAudioOffloadAudioProvider() {
-  session_type_ =
-      V2_1::SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH;
-}
-
-LeAudioOffloadAudioProvider::LeAudioOffloadAudioProvider()
-    : BluetoothAudioProvider() {}
-
-bool LeAudioOffloadAudioProvider::isValid(
-    const V2_0::SessionType& sessionType) {
-  LOG(ERROR) << __func__
-             << ", invalid session type for Offloaded Le Audio provider: "
-             << toString(sessionType);
-
-  return false;
-}
-
-bool LeAudioOffloadAudioProvider::isValid(
-    const V2_1::SessionType& sessionType) {
-  return (sessionType == session_type_);
-}
-
-Return<void> LeAudioOffloadAudioProvider::startSession_2_1(
-    const sp<V2_0::IBluetoothAudioPort>& hostIf,
-    const V2_1::AudioConfiguration& audioConfig, startSession_cb _hidl_cb) {
-  if (audioConfig.getDiscriminator() !=
-      V2_1::AudioConfiguration::hidl_discriminator::leAudioCodecConfig) {
-    LOG(WARNING) << __func__
-                 << " - Invalid Audio Configuration=" << toString(audioConfig);
-    _hidl_cb(BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION,
-             DataMQ::Descriptor());
-    return Void();
-  }
-
-  AudioConfiguration audioConfig_2_2;
-  audioConfig_2_2.leAudioConfig().mode = LeAudioMode::UNKNOWN;
-  audioConfig_2_2.leAudioConfig().config.unicastConfig() = {
-      .streamMap = {{
-          .streamHandle = 0xFFFF,
-          .audioChannelAllocation =
-              audioConfig.leAudioCodecConfig().audioChannelAllocation,
-      }},
-      .peerDelay = 0,
-      .lc3Config = audioConfig.leAudioCodecConfig().lc3Config};
-
-  sp<V2_2::IBluetoothAudioPort> hostIf_2_2 =
-      new AudioPort_2_0_to_2_2_Wrapper(hostIf);
-  return startSession_2_2(hostIf_2_2, audioConfig_2_2, _hidl_cb);
-}
-
-Return<void> LeAudioOffloadAudioProvider::startSession_2_2(
-    const sp<V2_2::IBluetoothAudioPort>& hostIf,
-    const AudioConfiguration& audioConfig, startSession_cb _hidl_cb) {
-  /**
-   * Initialize the audio platform if audioConfiguration is supported.
-   * Save the IBluetoothAudioPort interface, so that it can be used
-   * later to send stream control commands to the HAL client, based on
-   * interaction with Audio framework.
-   */
-  if (audioConfig.getDiscriminator() !=
-      AudioConfiguration::hidl_discriminator::leAudioConfig) {
-    LOG(WARNING) << __func__
-                 << " - Invalid Audio Configuration=" << toString(audioConfig);
-    _hidl_cb(BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION,
-             DataMQ::Descriptor());
-    return Void();
-  }
-
-  if (!android::bluetooth::audio::IsOffloadLeAudioConfigurationValid(
-          session_type_, audioConfig.leAudioConfig())) {
-    LOG(WARNING) << __func__ << " - Unsupported LC3 Offloaded Configuration="
-                 << toString(audioConfig.leAudioConfig());
-    _hidl_cb(BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION,
-             DataMQ::Descriptor());
-    return Void();
-  }
-
-  return BluetoothAudioProvider::startSession_2_2(hostIf, audioConfig,
-                                                  _hidl_cb);
-}
-
-Return<void> LeAudioOffloadAudioProvider::onSessionReady(
-    startSession_cb _hidl_cb) {
-  BluetoothAudioSessionReport_2_2::OnSessionStarted(session_type_, stack_iface_,
-                                                    nullptr, audio_config_);
-  _hidl_cb(BluetoothAudioStatus::SUCCESS, DataMQ::Descriptor());
-  return Void();
-}
-
-}  // namespace implementation
-}  // namespace V2_2
-}  // namespace audio
-}  // namespace bluetooth
-}  // namespace hardware
-}  // namespace android
diff --git a/bluetooth/audio/2.2/default/LeAudioOffloadAudioProvider.h b/bluetooth/audio/2.2/default/LeAudioOffloadAudioProvider.h
deleted file mode 100644
index fe58de5..0000000
--- a/bluetooth/audio/2.2/default/LeAudioOffloadAudioProvider.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <android/hardware/bluetooth/audio/2.2/types.h>
-
-#include "BluetoothAudioProvider.h"
-
-namespace android {
-namespace hardware {
-namespace bluetooth {
-namespace audio {
-namespace V2_2 {
-namespace implementation {
-
-class LeAudioOffloadAudioProvider : public BluetoothAudioProvider {
- public:
-  LeAudioOffloadAudioProvider();
-
-  bool isValid(const V2_1::SessionType& sessionType) override;
-  bool isValid(const V2_0::SessionType& sessionType) override;
-
-  Return<void> startSession_2_1(const sp<V2_0::IBluetoothAudioPort>& hostIf,
-                                const V2_1::AudioConfiguration& audioConfig,
-                                startSession_cb _hidl_cb) override;
-
-  Return<void> startSession_2_2(const sp<V2_2::IBluetoothAudioPort>& hostIf,
-                                const AudioConfiguration& audioConfig,
-                                startSession_cb _hidl_cb) override;
-
- private:
-  Return<void> onSessionReady(startSession_cb _hidl_cb) override;
-};
-
-class LeAudioOffloadOutputAudioProvider : public LeAudioOffloadAudioProvider {
- public:
-  LeAudioOffloadOutputAudioProvider();
-};
-
-class LeAudioOffloadInputAudioProvider : public LeAudioOffloadAudioProvider {
- public:
-  LeAudioOffloadInputAudioProvider();
-};
-
-}  // namespace implementation
-}  // namespace V2_2
-}  // namespace audio
-}  // namespace bluetooth
-}  // namespace hardware
-}  // namespace android
diff --git a/bluetooth/audio/2.2/default/OWNERS b/bluetooth/audio/2.2/default/OWNERS
deleted file mode 100644
index 17ea464..0000000
--- a/bluetooth/audio/2.2/default/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-include platform/packages/modules/Bluetooth:/OWNERS
-
-cheneyni@google.com
-aliceypkuo@google.com
\ No newline at end of file
diff --git a/bluetooth/audio/2.2/types.hal b/bluetooth/audio/2.2/types.hal
deleted file mode 100644
index 6755899..0000000
--- a/bluetooth/audio/2.2/types.hal
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.hardware.bluetooth.audio@2.2;
-
-import @2.1::Lc3Parameters;
-import @2.1::PcmParameters;
-import @2.0::CodecConfiguration;
-import @2.0::CodecCapabilities;
-import @2.1::CodecType;
-
-enum LeAudioMode : uint8_t {
-    UNKNOWN = 0x00,
-    UNICAST = 0x01,
-    BROADCAST = 0x02,
-};
-
-enum AudioLocation : uint8_t {
-  UNKNOWN = 0,
-  FRONT_LEFT = 1,
-  FRONT_RIGHT = 2,
-};
-
-struct UnicastStreamMap {
-    /* The connection handle used for a unicast or a broadcast group. */
-    uint16_t streamHandle;
-    /* Audio channel allocation is  a bit field, each enabled bit means that given audio direction,
-     * i.e. "left", or "right" is used. Ordering of audio channels comes from the least significant
-     * bit to the most significant bit. */
-    uint32_t audioChannelAllocation;
-};
-
-struct BroadcastStreamMap {
-    /* The connection handle used for a unicast or a broadcast group. */
-    uint16_t streamHandle;
-    /* Audio channel allocation is  a bit field, each enabled bit means that given audio direction,
-     * i.e. "left", or "right" is used. Ordering of audio channels comes from the least significant
-     * bit to the most significant bit. */
-    uint32_t audioChannelAllocation;
-    Lc3Parameters lc3Config;
-};
-
-struct UnicastConfig {
-    vec<UnicastStreamMap> streamMap;
-    uint32_t peerDelay;
-    Lc3Parameters lc3Config;
-};
-
-struct BroadcastConfig {
-    vec<BroadcastStreamMap> streamMap;
-};
-
-struct LeAudioConfiguration {
-    /* The mode of the LE audio */
-    LeAudioMode mode;
-    safe_union CodecConfig {
-        UnicastConfig unicastConfig;
-        BroadcastConfig broadcastConfig;
-    } config;
-};
-
-/** Used to configure either a Hardware or Software Encoding session based on session type */
-safe_union AudioConfiguration {
-    PcmParameters pcmConfig;
-    CodecConfiguration codecConfig;
-    LeAudioConfiguration leAudioConfig;
-};
-
-/** Used to specify the capabilities of the different session types */
-safe_union AudioCapabilities {
-    PcmParameters pcmCapabilities;
-    CodecCapabilities codecCapabilities;
-    LeAudioCodecCapabilitiesSetting leAudioCapabilities;
-};
-
-/**
- * Used to specify the le audio capabilities for unicast and broadcast hardware offload.
- */
-struct LeAudioCodecCapabilitiesSetting{
-    UnicastCapability unicastEncodeCapability;
-    UnicastCapability unicastDecodeCapability;
-    BroadcastCapability broadcastCapability;
-};
-
-/**
- * Used to specify the le audio unicast codec capabilities for hardware offload.
- */
-struct UnicastCapability {
-    CodecType codecType;
-    AudioLocation supportedChannel;
-
-    // The number of connected device
-    uint8_t deviceCount;
-
-    // Supported channel count for each device
-    uint8_t channelCountPerDevice;
-
-    // Should use safe union when there is more than one codec
-    Lc3Parameters capabilities;
-};
-
-/**
- * Used to specify the le audio broadcast codec capabilities for hardware offload.
- */
-struct BroadcastCapability {
-    CodecType codecType;
-    AudioLocation supportedChannel;
-
-    // Supported channel count for each stream
-    uint8_t channelCountPerStream;
-
-    // Should use safe union when there is more than one codec
-    vec<Lc3Parameters> capabilities;
-};
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioPort.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioPort.aidl
index 0033fee..d364371 100644
--- a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioPort.aidl
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioPort.aidl
@@ -35,7 +35,7 @@
 @VintfStability
 interface IBluetoothAudioPort {
   android.hardware.bluetooth.audio.PresentationPosition getPresentationPosition();
-  void startStream();
+  void startStream(boolean isLowLatency);
   void stopStream();
   void suspendStream();
   void updateSourceMetadata(in android.hardware.audio.common.SourceMetadata sourceMetadata);
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioProvider.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioProvider.aidl
index 6e0bd98..267af0f 100644
--- a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioProvider.aidl
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioProvider.aidl
@@ -35,7 +35,7 @@
 @VintfStability
 interface IBluetoothAudioProvider {
   void endSession();
-  android.hardware.common.fmq.MQDescriptor<byte,android.hardware.common.fmq.SynchronizedReadWrite> startSession(in android.hardware.bluetooth.audio.IBluetoothAudioPort hostIf, in android.hardware.bluetooth.audio.AudioConfiguration audioConfig);
+  android.hardware.common.fmq.MQDescriptor<byte,android.hardware.common.fmq.SynchronizedReadWrite> startSession(in android.hardware.bluetooth.audio.IBluetoothAudioPort hostIf, in android.hardware.bluetooth.audio.AudioConfiguration audioConfig, in android.hardware.bluetooth.audio.LatencyMode[] supportedLatencyModes);
   void streamStarted(in android.hardware.bluetooth.audio.BluetoothAudioStatus status);
   void streamSuspended(in android.hardware.bluetooth.audio.BluetoothAudioStatus status);
   void updateAudioConfiguration(in android.hardware.bluetooth.audio.AudioConfiguration audioConfig);
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioPort.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioPort.aidl
index 9f8007b..4ddf645 100644
--- a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioPort.aidl
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioPort.aidl
@@ -47,8 +47,11 @@
      * This indicates that the caller of this method has opened the data path
      * and wants to start an audio stream. The caller must wait for a
      * IBluetoothAudioProvider.streamStarted(Status) call.
+     *
+     * @param isLowLatency true if the stream being started with the latency
+     * control mechanism.
      */
-    void startStream();
+    void startStream(boolean isLowLatency);
 
     /**
      * This indicates that the caller of this method wants to stop the audio
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioProvider.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioProvider.aidl
index ca6f691..d5c051e 100644
--- a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioProvider.aidl
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioProvider.aidl
@@ -19,6 +19,7 @@
 import android.hardware.bluetooth.audio.AudioConfiguration;
 import android.hardware.bluetooth.audio.BluetoothAudioStatus;
 import android.hardware.bluetooth.audio.IBluetoothAudioPort;
+import android.hardware.bluetooth.audio.LatencyMode;
 import android.hardware.common.fmq.MQDescriptor;
 import android.hardware.common.fmq.SynchronizedReadWrite;
 
@@ -50,6 +51,8 @@
      *    device. The PCM parameters are set if software based encoding,
      *    otherwise the correct codec configuration is used for hardware
      *    encoding.
+     * @param supportedLatencyModes latency modes supported by the active
+     * remote device
      *
      * @return The fast message queue for audio data from/to this
      *    provider. Audio data will be in PCM format as specified by the
@@ -57,8 +60,8 @@
      *    from/to hardware or on failure
      */
     MQDescriptor<byte, SynchronizedReadWrite> startSession(
-            in IBluetoothAudioPort hostIf, in AudioConfiguration audioConfig);
-
+            in IBluetoothAudioPort hostIf, in AudioConfiguration audioConfig,
+            in LatencyMode[] supportedLatencyModes);
     /**
      * Callback for IBluetoothAudioPort.startStream()
      *
diff --git a/bluetooth/audio/aidl/default/A2dpOffloadAudioProvider.cpp b/bluetooth/audio/aidl/default/A2dpOffloadAudioProvider.cpp
index fc8a911..4b4713d 100644
--- a/bluetooth/audio/aidl/default/A2dpOffloadAudioProvider.cpp
+++ b/bluetooth/audio/aidl/default/A2dpOffloadAudioProvider.cpp
@@ -38,7 +38,8 @@
 
 ndk::ScopedAStatus A2dpOffloadAudioProvider::startSession(
     const std::shared_ptr<IBluetoothAudioPort>& host_if,
-    const AudioConfiguration& audio_config, DataMQDesc* _aidl_return) {
+    const AudioConfiguration& audio_config,
+    const std::vector<LatencyMode>& latency_modes, DataMQDesc* _aidl_return) {
   if (audio_config.getTag() != AudioConfiguration::a2dpConfig) {
     LOG(WARNING) << __func__ << " - Invalid Audio Configuration="
                  << audio_config.toString();
@@ -52,15 +53,15 @@
     *_aidl_return = DataMQDesc();
     return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
   }
-  return BluetoothAudioProvider::startSession(host_if, audio_config,
-                                              _aidl_return);
+  return BluetoothAudioProvider::startSession(
+      host_if, audio_config, latency_modes, _aidl_return);
 }
 
 ndk::ScopedAStatus A2dpOffloadAudioProvider::onSessionReady(
     DataMQDesc* _aidl_return) {
   *_aidl_return = DataMQDesc();
-  BluetoothAudioSessionReport::OnSessionStarted(session_type_, stack_iface_,
-                                                nullptr, *audio_config_);
+  BluetoothAudioSessionReport::OnSessionStarted(
+      session_type_, stack_iface_, nullptr, *audio_config_, latency_modes_);
   return ndk::ScopedAStatus::ok();
 }
 
@@ -68,4 +69,4 @@
 }  // namespace bluetooth
 }  // namespace hardware
 }  // namespace android
-}  // namespace aidl
\ No newline at end of file
+}  // namespace aidl
diff --git a/bluetooth/audio/aidl/default/A2dpOffloadAudioProvider.h b/bluetooth/audio/aidl/default/A2dpOffloadAudioProvider.h
index 5934f5b..4621e85 100644
--- a/bluetooth/audio/aidl/default/A2dpOffloadAudioProvider.h
+++ b/bluetooth/audio/aidl/default/A2dpOffloadAudioProvider.h
@@ -32,7 +32,9 @@
 
   ndk::ScopedAStatus startSession(
       const std::shared_ptr<IBluetoothAudioPort>& host_if,
-      const AudioConfiguration& audio_config, DataMQDesc* _aidl_return);
+      const AudioConfiguration& audio_config,
+      const std::vector<LatencyMode>& latency_modes,
+      DataMQDesc* _aidl_return);
 
  private:
   ndk::ScopedAStatus onSessionReady(DataMQDesc* _aidl_return) override;
diff --git a/bluetooth/audio/aidl/default/A2dpSoftwareAudioProvider.cpp b/bluetooth/audio/aidl/default/A2dpSoftwareAudioProvider.cpp
index 5a413e0..59df3a9 100644
--- a/bluetooth/audio/aidl/default/A2dpSoftwareAudioProvider.cpp
+++ b/bluetooth/audio/aidl/default/A2dpSoftwareAudioProvider.cpp
@@ -61,7 +61,8 @@
 
 ndk::ScopedAStatus A2dpSoftwareAudioProvider::startSession(
     const std::shared_ptr<IBluetoothAudioPort>& host_if,
-    const AudioConfiguration& audio_config, DataMQDesc* _aidl_return) {
+    const AudioConfiguration& audio_config,
+    const std::vector<LatencyMode>& latency_modes, DataMQDesc* _aidl_return) {
   if (audio_config.getTag() != AudioConfiguration::pcmConfig) {
     LOG(WARNING) << __func__ << " - Invalid Audio Configuration="
                  << audio_config.toString();
@@ -77,8 +78,8 @@
     return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
   }
 
-  return BluetoothAudioProvider::startSession(host_if, audio_config,
-                                              _aidl_return);
+  return BluetoothAudioProvider::startSession(
+      host_if, audio_config, latency_modes, _aidl_return);
 }
 
 ndk::ScopedAStatus A2dpSoftwareAudioProvider::onSessionReady(
@@ -89,8 +90,8 @@
   }
   *_aidl_return = data_mq_->dupeDesc();
   auto desc = data_mq_->dupeDesc();
-  BluetoothAudioSessionReport::OnSessionStarted(session_type_, stack_iface_,
-                                                &desc, *audio_config_);
+  BluetoothAudioSessionReport::OnSessionStarted(
+      session_type_, stack_iface_, &desc, *audio_config_, latency_modes_);
   return ndk::ScopedAStatus::ok();
 }
 
@@ -98,4 +99,4 @@
 }  // namespace bluetooth
 }  // namespace hardware
 }  // namespace android
-}  // namespace aidl
\ No newline at end of file
+}  // namespace aidl
diff --git a/bluetooth/audio/aidl/default/A2dpSoftwareAudioProvider.h b/bluetooth/audio/aidl/default/A2dpSoftwareAudioProvider.h
index 3bc0a13..10f533a 100644
--- a/bluetooth/audio/aidl/default/A2dpSoftwareAudioProvider.h
+++ b/bluetooth/audio/aidl/default/A2dpSoftwareAudioProvider.h
@@ -32,7 +32,9 @@
 
   ndk::ScopedAStatus startSession(
       const std::shared_ptr<IBluetoothAudioPort>& host_if,
-      const AudioConfiguration& audio_config, DataMQDesc* _aidl_return);
+      const AudioConfiguration& audio_config,
+      const std::vector<LatencyMode>& latency_modes,
+      DataMQDesc* _aidl_return);
 
  private:
   // audio data queue for software encoding
diff --git a/bluetooth/audio/aidl/default/BluetoothAudioProvider.cpp b/bluetooth/audio/aidl/default/BluetoothAudioProvider.cpp
index 8090d26..0dd8148 100644
--- a/bluetooth/audio/aidl/default/BluetoothAudioProvider.cpp
+++ b/bluetooth/audio/aidl/default/BluetoothAudioProvider.cpp
@@ -34,11 +34,15 @@
 
 ndk::ScopedAStatus BluetoothAudioProvider::startSession(
     const std::shared_ptr<IBluetoothAudioPort>& host_if,
-    const AudioConfiguration& audio_config, DataMQDesc* _aidl_return) {
+    const AudioConfiguration& audio_config,
+    const std::vector<LatencyMode>& latencyModes,
+    DataMQDesc* _aidl_return) {
   if (host_if == nullptr) {
     *_aidl_return = DataMQDesc();
     return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
   }
+
+  latency_modes_ = latencyModes;
   audio_config_ = std::make_unique<AudioConfiguration>(audio_config);
   stack_iface_ = host_if;
 
diff --git a/bluetooth/audio/aidl/default/BluetoothAudioProvider.h b/bluetooth/audio/aidl/default/BluetoothAudioProvider.h
index 393aaba..a9f830a 100644
--- a/bluetooth/audio/aidl/default/BluetoothAudioProvider.h
+++ b/bluetooth/audio/aidl/default/BluetoothAudioProvider.h
@@ -16,6 +16,7 @@
 #pragma once
 
 #include <aidl/android/hardware/bluetooth/audio/BnBluetoothAudioProvider.h>
+#include <aidl/android/hardware/bluetooth/audio/LatencyMode.h>
 #include <aidl/android/hardware/bluetooth/audio/SessionType.h>
 #include <fmq/AidlMessageQueue.h>
 
@@ -37,10 +38,11 @@
 class BluetoothAudioProvider : public BnBluetoothAudioProvider {
  public:
   BluetoothAudioProvider();
-
   ndk::ScopedAStatus startSession(
       const std::shared_ptr<IBluetoothAudioPort>& host_if,
-      const AudioConfiguration& audio_config, DataMQDesc* _aidl_return);
+      const AudioConfiguration& audio_config,
+      const std::vector<LatencyMode>& latency_modes,
+      DataMQDesc* _aidl_return);
   ndk::ScopedAStatus endSession();
   ndk::ScopedAStatus streamStarted(BluetoothAudioStatus status);
   ndk::ScopedAStatus streamSuspended(BluetoothAudioStatus status);
@@ -59,10 +61,11 @@
   std::shared_ptr<IBluetoothAudioPort> stack_iface_;
   std::unique_ptr<AudioConfiguration> audio_config_ = nullptr;
   SessionType session_type_;
+  std::vector<LatencyMode> latency_modes_;
 };
 
 }  // namespace audio
 }  // namespace bluetooth
 }  // namespace hardware
 }  // namespace android
-}  // namespace aidl
\ No newline at end of file
+}  // namespace aidl
diff --git a/bluetooth/audio/aidl/default/HearingAidAudioProvider.cpp b/bluetooth/audio/aidl/default/HearingAidAudioProvider.cpp
index 66ce93b..e8b01ac 100644
--- a/bluetooth/audio/aidl/default/HearingAidAudioProvider.cpp
+++ b/bluetooth/audio/aidl/default/HearingAidAudioProvider.cpp
@@ -56,7 +56,8 @@
 
 ndk::ScopedAStatus HearingAidAudioProvider::startSession(
     const std::shared_ptr<IBluetoothAudioPort>& host_if,
-    const AudioConfiguration& audio_config, DataMQDesc* _aidl_return) {
+    const AudioConfiguration& audio_config,
+    const std::vector<LatencyMode>& latency_modes, DataMQDesc* _aidl_return) {
   if (audio_config.getTag() != AudioConfiguration::pcmConfig) {
     LOG(WARNING) << __func__ << " - Invalid Audio Configuration="
                  << audio_config.toString();
@@ -71,8 +72,8 @@
     return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
   }
 
-  return BluetoothAudioProvider::startSession(host_if, audio_config,
-                                              _aidl_return);
+  return BluetoothAudioProvider::startSession(
+      host_if, audio_config, latency_modes, _aidl_return);
 }
 
 ndk::ScopedAStatus HearingAidAudioProvider::onSessionReady(
@@ -83,8 +84,8 @@
   }
   *_aidl_return = data_mq_->dupeDesc();
   auto desc = data_mq_->dupeDesc();
-  BluetoothAudioSessionReport::OnSessionStarted(session_type_, stack_iface_,
-                                                &desc, *audio_config_);
+  BluetoothAudioSessionReport::OnSessionStarted(
+      session_type_, stack_iface_, &desc, *audio_config_, latency_modes_);
   return ndk::ScopedAStatus::ok();
 }
 
@@ -92,4 +93,4 @@
 }  // namespace bluetooth
 }  // namespace hardware
 }  // namespace android
-}  // namespace aidl
\ No newline at end of file
+}  // namespace aidl
diff --git a/bluetooth/audio/aidl/default/HearingAidAudioProvider.h b/bluetooth/audio/aidl/default/HearingAidAudioProvider.h
index a7e19e9..a158c86 100644
--- a/bluetooth/audio/aidl/default/HearingAidAudioProvider.h
+++ b/bluetooth/audio/aidl/default/HearingAidAudioProvider.h
@@ -32,7 +32,9 @@
 
   ndk::ScopedAStatus startSession(
       const std::shared_ptr<IBluetoothAudioPort>& host_if,
-      const AudioConfiguration& audio_config, DataMQDesc* _aidl_return);
+      const AudioConfiguration& audio_config,
+      const std::vector<LatencyMode>& latency_modes,
+      DataMQDesc* _aidl_return);
 
  private:
   // audio data queue for software encoding
diff --git a/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.cpp b/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.cpp
index 7a28513..0e22e44 100644
--- a/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.cpp
+++ b/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.cpp
@@ -53,7 +53,8 @@
 
 ndk::ScopedAStatus LeAudioOffloadAudioProvider::startSession(
     const std::shared_ptr<IBluetoothAudioPort>& host_if,
-    const AudioConfiguration& audio_config, DataMQDesc* _aidl_return) {
+    const AudioConfiguration& audio_config,
+    const std::vector<LatencyMode>& latency_modes, DataMQDesc* _aidl_return) {
   if (audio_config.getTag() != AudioConfiguration::leAudioConfig) {
     LOG(WARNING) << __func__ << " - Invalid Audio Configuration="
                  << audio_config.toString();
@@ -70,14 +71,14 @@
     return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
   }
 
-  return BluetoothAudioProvider::startSession(host_if, audio_config,
-                                              _aidl_return);
+  return BluetoothAudioProvider::startSession(
+      host_if, audio_config, latency_modes, _aidl_return);
 }
 
 ndk::ScopedAStatus LeAudioOffloadAudioProvider::onSessionReady(
     DataMQDesc* _aidl_return) {
-  BluetoothAudioSessionReport::OnSessionStarted(session_type_, stack_iface_,
-                                                nullptr, *audio_config_);
+  BluetoothAudioSessionReport::OnSessionStarted(
+      session_type_, stack_iface_, nullptr, *audio_config_, latency_modes_);
   *_aidl_return = DataMQDesc();
   return ndk::ScopedAStatus::ok();
 }
@@ -86,4 +87,4 @@
 }  // namespace bluetooth
 }  // namespace hardware
 }  // namespace android
-}  // namespace aidl
\ No newline at end of file
+}  // namespace aidl
diff --git a/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.h b/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.h
index 6509a9e..614c794 100644
--- a/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.h
+++ b/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.h
@@ -32,7 +32,9 @@
 
   ndk::ScopedAStatus startSession(
       const std::shared_ptr<IBluetoothAudioPort>& host_if,
-      const AudioConfiguration& audio_config, DataMQDesc* _aidl_return);
+      const AudioConfiguration& audio_config,
+      const std::vector<LatencyMode>& latency_modes,
+      DataMQDesc* _aidl_return);
 
  private:
   ndk::ScopedAStatus onSessionReady(DataMQDesc* _aidl_return) override;
diff --git a/bluetooth/audio/aidl/default/LeAudioSoftwareAudioProvider.cpp b/bluetooth/audio/aidl/default/LeAudioSoftwareAudioProvider.cpp
index 0fe205e..911c928 100644
--- a/bluetooth/audio/aidl/default/LeAudioSoftwareAudioProvider.cpp
+++ b/bluetooth/audio/aidl/default/LeAudioSoftwareAudioProvider.cpp
@@ -69,7 +69,8 @@
 
 ndk::ScopedAStatus LeAudioSoftwareAudioProvider::startSession(
     const std::shared_ptr<IBluetoothAudioPort>& host_if,
-    const AudioConfiguration& audio_config, DataMQDesc* _aidl_return) {
+    const AudioConfiguration& audio_config,
+    const std::vector<LatencyMode>& latency_modes, DataMQDesc* _aidl_return) {
   if (audio_config.getTag() != AudioConfiguration::pcmConfig) {
     LOG(WARNING) << __func__ << " - Invalid Audio Configuration="
                  << audio_config.toString();
@@ -119,8 +120,8 @@
   }
   data_mq_ = std::move(temp_data_mq);
 
-  return BluetoothAudioProvider::startSession(host_if, audio_config,
-                                              _aidl_return);
+  return BluetoothAudioProvider::startSession(
+      host_if, audio_config, latency_modes, _aidl_return);
 }
 
 ndk::ScopedAStatus LeAudioSoftwareAudioProvider::onSessionReady(
@@ -131,8 +132,8 @@
   }
   *_aidl_return = data_mq_->dupeDesc();
   auto desc = data_mq_->dupeDesc();
-  BluetoothAudioSessionReport::OnSessionStarted(session_type_, stack_iface_,
-                                                &desc, *audio_config_);
+  BluetoothAudioSessionReport::OnSessionStarted(
+      session_type_, stack_iface_, &desc, *audio_config_, latency_modes_);
   return ndk::ScopedAStatus::ok();
 }
 
@@ -140,4 +141,4 @@
 }  // namespace bluetooth
 }  // namespace hardware
 }  // namespace android
-}  // namespace aidl
\ No newline at end of file
+}  // namespace aidl
diff --git a/bluetooth/audio/aidl/default/LeAudioSoftwareAudioProvider.h b/bluetooth/audio/aidl/default/LeAudioSoftwareAudioProvider.h
index ace4bff..21243ff 100644
--- a/bluetooth/audio/aidl/default/LeAudioSoftwareAudioProvider.h
+++ b/bluetooth/audio/aidl/default/LeAudioSoftwareAudioProvider.h
@@ -32,7 +32,9 @@
 
   ndk::ScopedAStatus startSession(
       const std::shared_ptr<IBluetoothAudioPort>& host_if,
-      const AudioConfiguration& audio_config, DataMQDesc* _aidl_return);
+      const AudioConfiguration& audio_config,
+      const std::vector<LatencyMode>& latency_modes,
+      DataMQDesc* _aidl_return);
 
  private:
   // audio data queue for software encoding
diff --git a/bluetooth/audio/aidl/vts/Android.bp b/bluetooth/audio/aidl/vts/Android.bp
index a662aaa..feb952e 100644
--- a/bluetooth/audio/aidl/vts/Android.bp
+++ b/bluetooth/audio/aidl/vts/Android.bp
@@ -13,6 +13,7 @@
         "VtsHalTargetTestDefaults",
         "use_libaidlvintf_gtest_helper_static",
     ],
+    tidy_timeout_srcs: ["VtsHalBluetoothAudioTargetTest.cpp"],
     srcs: ["VtsHalBluetoothAudioTargetTest.cpp"],
     shared_libs: [
         "android.hardware.audio.common-V1-ndk",
diff --git a/bluetooth/audio/aidl/vts/VtsHalBluetoothAudioTargetTest.cpp b/bluetooth/audio/aidl/vts/VtsHalBluetoothAudioTargetTest.cpp
index 307403b..18352a0 100644
--- a/bluetooth/audio/aidl/vts/VtsHalBluetoothAudioTargetTest.cpp
+++ b/bluetooth/audio/aidl/vts/VtsHalBluetoothAudioTargetTest.cpp
@@ -39,6 +39,7 @@
 using aidl::android::hardware::bluetooth::audio::AudioCapabilities;
 using aidl::android::hardware::bluetooth::audio::AudioConfiguration;
 using aidl::android::hardware::bluetooth::audio::BnBluetoothAudioPort;
+using aidl::android::hardware::bluetooth::audio::BroadcastCapability;
 using aidl::android::hardware::bluetooth::audio::ChannelMode;
 using aidl::android::hardware::bluetooth::audio::CodecCapabilities;
 using aidl::android::hardware::bluetooth::audio::CodecConfiguration;
@@ -51,6 +52,7 @@
 using aidl::android::hardware::bluetooth::audio::Lc3Configuration;
 using aidl::android::hardware::bluetooth::audio::LdacCapabilities;
 using aidl::android::hardware::bluetooth::audio::LdacConfiguration;
+using aidl::android::hardware::bluetooth::audio::LeAudioBroadcastConfiguration;
 using aidl::android::hardware::bluetooth::audio::
     LeAudioCodecCapabilitiesSetting;
 using aidl::android::hardware::bluetooth::audio::LeAudioCodecConfiguration;
@@ -86,7 +88,7 @@
     CodecType::UNKNOWN, CodecType::SBC,          CodecType::AAC,
     CodecType::APTX,    CodecType::APTX_HD,      CodecType::LDAC,
     CodecType::LC3,     CodecType::APTX_ADAPTIVE};
-
+static std::vector<LatencyMode> latency_modes = {LatencyMode::FREE};
 // Helpers
 
 template <typename T>
@@ -136,7 +138,7 @@
  public:
   BluetoothAudioPort() {}
 
-  ndk::ScopedAStatus startStream() { return ScopedAStatus::ok(); }
+  ndk::ScopedAStatus startStream(bool) { return ScopedAStatus::ok(); }
 
   ndk::ScopedAStatus suspendStream() { return ScopedAStatus::ok(); }
 
@@ -379,7 +381,8 @@
         bool is_codec_config_valid = IsPcmConfigSupported(pcm_config);
         DataMQDesc mq_desc;
         auto aidl_retval = audio_provider_->startSession(
-            audio_port_, AudioConfiguration(pcm_config), &mq_desc);
+            audio_port_, AudioConfiguration(pcm_config), latency_modes,
+            &mq_desc);
         DataMQ data_mq(mq_desc);
 
         EXPECT_EQ(aidl_retval.isOk(), is_codec_config_valid);
@@ -417,7 +420,7 @@
 
   void GetA2dpOffloadCapabilityHelper(const CodecType& codec_type) {
     temp_codec_capabilities_ = nullptr;
-    for (auto codec_capability : temp_provider_capabilities_) {
+    for (auto& codec_capability : temp_provider_capabilities_) {
       auto& a2dp_capabilities =
           codec_capability.get<AudioCapabilities::a2dpCapabilities>();
       if (a2dp_capabilities.codecType != codec_type) {
@@ -671,7 +674,7 @@
     copy_codec_specific(codec_config.config, codec_specific);
     DataMQDesc mq_desc;
     auto aidl_retval = audio_provider_->startSession(
-        audio_port_, AudioConfiguration(codec_config), &mq_desc);
+        audio_port_, AudioConfiguration(codec_config), latency_modes, &mq_desc);
 
     ASSERT_TRUE(aidl_retval.isOk());
     EXPECT_TRUE(audio_provider_->endSession().isOk());
@@ -701,7 +704,7 @@
     copy_codec_specific(codec_config.config, codec_specific);
     DataMQDesc mq_desc;
     auto aidl_retval = audio_provider_->startSession(
-        audio_port_, AudioConfiguration(codec_config), &mq_desc);
+        audio_port_, AudioConfiguration(codec_config), latency_modes, &mq_desc);
 
     ASSERT_TRUE(aidl_retval.isOk());
     EXPECT_TRUE(audio_provider_->endSession().isOk());
@@ -731,7 +734,7 @@
     copy_codec_specific(codec_config.config, codec_specific);
     DataMQDesc mq_desc;
     auto aidl_retval = audio_provider_->startSession(
-        audio_port_, AudioConfiguration(codec_config), &mq_desc);
+        audio_port_, AudioConfiguration(codec_config), latency_modes, &mq_desc);
 
     ASSERT_TRUE(aidl_retval.isOk());
     EXPECT_TRUE(audio_provider_->endSession().isOk());
@@ -761,7 +764,7 @@
     copy_codec_specific(codec_config.config, codec_specific);
     DataMQDesc mq_desc;
     auto aidl_retval = audio_provider_->startSession(
-        audio_port_, AudioConfiguration(codec_config), &mq_desc);
+        audio_port_, AudioConfiguration(codec_config), latency_modes, &mq_desc);
 
     ASSERT_TRUE(aidl_retval.isOk());
     EXPECT_TRUE(audio_provider_->endSession().isOk());
@@ -795,7 +798,8 @@
       copy_codec_specific(codec_config.config, codec_specific);
       DataMQDesc mq_desc;
       auto aidl_retval = audio_provider_->startSession(
-          audio_port_, AudioConfiguration(codec_config), &mq_desc);
+          audio_port_, AudioConfiguration(codec_config), latency_modes,
+          &mq_desc);
 
       ASSERT_TRUE(aidl_retval.isOk());
       EXPECT_TRUE(audio_provider_->endSession().isOk());
@@ -856,7 +860,8 @@
       copy_codec_specific(codec_config.config, codec_specific);
       DataMQDesc mq_desc;
       auto aidl_retval = audio_provider_->startSession(
-          audio_port_, AudioConfiguration(codec_config), &mq_desc);
+          audio_port_, AudioConfiguration(codec_config), latency_modes,
+          &mq_desc);
 
       // AIDL call should fail on invalid codec
       ASSERT_FALSE(aidl_retval.isOk());
@@ -915,7 +920,8 @@
         bool is_codec_config_valid = IsPcmConfigSupported(pcm_config);
         DataMQDesc mq_desc;
         auto aidl_retval = audio_provider_->startSession(
-            audio_port_, AudioConfiguration(pcm_config), &mq_desc);
+            audio_port_, AudioConfiguration(pcm_config), latency_modes,
+            &mq_desc);
         DataMQ data_mq(mq_desc);
 
         EXPECT_EQ(aidl_retval.isOk(), is_codec_config_valid);
@@ -983,10 +989,12 @@
               .channelMode = channel_mode,
               .dataIntervalUs = data_interval_us,
           };
-          bool is_codec_config_valid = IsPcmConfigSupported(pcm_config);
+          bool is_codec_config_valid =
+              IsPcmConfigSupported(pcm_config) && pcm_config.dataIntervalUs > 0;
           DataMQDesc mq_desc;
           auto aidl_retval = audio_provider_->startSession(
-              audio_port_, AudioConfiguration(pcm_config), &mq_desc);
+              audio_port_, AudioConfiguration(pcm_config), latency_modes,
+              &mq_desc);
           DataMQ data_mq(mq_desc);
 
           EXPECT_EQ(aidl_retval.isOk(), is_codec_config_valid);
@@ -1001,7 +1009,7 @@
 }
 
 /**
- * openProvider LE_AUDIO_SOFTWARE_DECODED_DATAPATH
+ * openProvider LE_AUDIO_SOFTWARE_DECODING_DATAPATH
  */
 class BluetoothAudioProviderLeAudioInputSoftwareAidl
     : public BluetoothAudioProviderFactoryAidl {
@@ -1031,7 +1039,7 @@
 
 /**
  * Test whether each provider of type
- * SessionType::LE_AUDIO_SOFTWARE_DECODED_DATAPATH can be started and
+ * SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH can be started and
  * stopped
  */
 TEST_P(BluetoothAudioProviderLeAudioInputSoftwareAidl,
@@ -1039,7 +1047,7 @@
 
 /**
  * Test whether each provider of type
- * SessionType::LE_AUDIO_SOFTWARE_DECODED_DATAPATH can be started and
+ * SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH can be started and
  * stopped with different PCM config
  */
 TEST_P(BluetoothAudioProviderLeAudioInputSoftwareAidl,
@@ -1054,10 +1062,12 @@
               .channelMode = channel_mode,
               .dataIntervalUs = data_interval_us,
           };
-          bool is_codec_config_valid = IsPcmConfigSupported(pcm_config);
+          bool is_codec_config_valid =
+              IsPcmConfigSupported(pcm_config) && pcm_config.dataIntervalUs > 0;
           DataMQDesc mq_desc;
           auto aidl_retval = audio_provider_->startSession(
-              audio_port_, AudioConfiguration(pcm_config), &mq_desc);
+              audio_port_, AudioConfiguration(pcm_config), latency_modes,
+              &mq_desc);
           DataMQ data_mq(mq_desc);
 
           EXPECT_EQ(aidl_retval.isOk(), is_codec_config_valid);
@@ -1072,7 +1082,7 @@
 }
 
 /**
- * openProvider LE_AUDIO_HARDWARE_OFFLOAD_DECODED_DATAPATH
+ * openProvider LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH
  */
 class BluetoothAudioProviderLeAudioOutputHardwareAidl
     : public BluetoothAudioProviderFactoryAidl {
@@ -1190,7 +1200,8 @@
         .set<LeAudioCodecConfiguration::lc3Config>(lc3_config);
     DataMQDesc mq_desc;
     auto aidl_retval = audio_provider_->startSession(
-        audio_port_, AudioConfiguration(le_audio_config), &mq_desc);
+        audio_port_, AudioConfiguration(le_audio_config), latency_modes,
+        &mq_desc);
 
     ASSERT_TRUE(aidl_retval.isOk());
     EXPECT_TRUE(audio_provider_->endSession().isOk());
@@ -1222,7 +1233,8 @@
         .set<LeAudioCodecConfiguration::lc3Config>(lc3_config);
     DataMQDesc mq_desc;
     auto aidl_retval = audio_provider_->startSession(
-        audio_port_, AudioConfiguration(le_audio_config), &mq_desc);
+        audio_port_, AudioConfiguration(le_audio_config), latency_modes,
+        &mq_desc);
 
     // AIDL call should fail on invalid codec
     ASSERT_FALSE(aidl_retval.isOk());
@@ -1298,7 +1310,8 @@
         .set<LeAudioCodecConfiguration::lc3Config>(lc3_config);
     DataMQDesc mq_desc;
     auto aidl_retval = audio_provider_->startSession(
-        audio_port_, AudioConfiguration(le_audio_config), &mq_desc);
+        audio_port_, AudioConfiguration(le_audio_config), latency_modes,
+        &mq_desc);
 
     ASSERT_TRUE(aidl_retval.isOk());
     EXPECT_TRUE(audio_provider_->endSession().isOk());
@@ -1331,7 +1344,8 @@
 
     DataMQDesc mq_desc;
     auto aidl_retval = audio_provider_->startSession(
-        audio_port_, AudioConfiguration(le_audio_config), &mq_desc);
+        audio_port_, AudioConfiguration(le_audio_config), latency_modes,
+        &mq_desc);
 
     // AIDL call should fail on invalid codec
     ASSERT_FALSE(aidl_retval.isOk());
@@ -1376,7 +1390,7 @@
  * stopped
  */
 TEST_P(BluetoothAudioProviderLeAudioBroadcastSoftwareAidl,
-       DISABLED_OpenLeAudioOutputSoftwareProvider) {}
+       OpenLeAudioOutputSoftwareProvider) {}
 
 /**
  * Test whether each provider of type
@@ -1384,7 +1398,7 @@
  * stopped with different PCM config
  */
 TEST_P(BluetoothAudioProviderLeAudioBroadcastSoftwareAidl,
-       DISABLED_StartAndEndLeAudioOutputSessionWithPossiblePcmConfig) {
+       StartAndEndLeAudioOutputSessionWithPossiblePcmConfig) {
   for (auto sample_rate : le_audio_output_sample_rates_) {
     for (auto bits_per_sample : le_audio_output_bits_per_samples_) {
       for (auto channel_mode : le_audio_output_channel_modes_) {
@@ -1395,10 +1409,12 @@
               .channelMode = channel_mode,
               .dataIntervalUs = data_interval_us,
           };
-          bool is_codec_config_valid = IsPcmConfigSupported(pcm_config);
+          bool is_codec_config_valid =
+              IsPcmConfigSupported(pcm_config) && pcm_config.dataIntervalUs > 0;
           DataMQDesc mq_desc;
           auto aidl_retval = audio_provider_->startSession(
-              audio_port_, AudioConfiguration(pcm_config), &mq_desc);
+              audio_port_, AudioConfiguration(pcm_config), latency_modes,
+              &mq_desc);
           DataMQ data_mq(mq_desc);
 
           EXPECT_EQ(aidl_retval.isOk(), is_codec_config_valid);
@@ -1412,6 +1428,166 @@
   }
 }
 
+/**
+ * openProvider LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH
+ */
+class BluetoothAudioProviderLeAudioBroadcastHardwareAidl
+    : public BluetoothAudioProviderFactoryAidl {
+ public:
+  virtual void SetUp() override {
+    BluetoothAudioProviderFactoryAidl::SetUp();
+    GetProviderCapabilitiesHelper(
+        SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
+    OpenProviderHelper(
+        SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
+    ASSERT_TRUE(temp_provider_capabilities_.empty() ||
+                audio_provider_ != nullptr);
+  }
+
+  virtual void TearDown() override {
+    audio_port_ = nullptr;
+    audio_provider_ = nullptr;
+    BluetoothAudioProviderFactoryAidl::TearDown();
+  }
+
+  bool IsBroadcastOffloadSupported() {
+    for (auto& capability : temp_provider_capabilities_) {
+      if (capability.getTag() != AudioCapabilities::leAudioCapabilities) {
+        continue;
+      }
+      auto& le_audio_capability =
+          capability.get<AudioCapabilities::leAudioCapabilities>();
+      if (le_audio_capability.broadcastCapability.codecType !=
+          CodecType::UNKNOWN)
+        return true;
+    }
+    return false;
+  }
+
+  std::vector<Lc3Configuration> GetBroadcastLc3SupportedList(bool supported) {
+    std::vector<Lc3Configuration> le_audio_codec_configs;
+    if (!supported) {
+      Lc3Configuration lc3_config{.samplingFrequencyHz = 0, .pcmBitDepth = 0};
+      le_audio_codec_configs.push_back(lc3_config);
+      return le_audio_codec_configs;
+    }
+
+    // There might be more than one LeAudioCodecCapabilitiesSetting
+    std::vector<Lc3Capabilities> lc3_capabilities;
+    for (auto& capability : temp_provider_capabilities_) {
+      if (capability.getTag() != AudioCapabilities::leAudioCapabilities) {
+        continue;
+      }
+      auto& le_audio_capability =
+          capability.get<AudioCapabilities::leAudioCapabilities>();
+      auto& broadcast_capability = le_audio_capability.broadcastCapability;
+      if (broadcast_capability.codecType != CodecType::LC3) {
+        continue;
+      }
+      auto& lc3_capability = broadcast_capability.leAudioCodecCapabilities.get<
+          BroadcastCapability::LeAudioCodecCapabilities::lc3Capabilities>();
+      for (int idx = 0; idx < lc3_capability->size(); idx++)
+        lc3_capabilities.push_back(*lc3_capability->at(idx));
+    }
+
+    // Combine those parameters into one list of LeAudioCodecConfiguration
+    // This seems horrible, but usually each Lc3Capability only contains a
+    // single Lc3Configuration, which means every array has a length of 1.
+    for (auto& lc3_capability : lc3_capabilities) {
+      for (int32_t samplingFrequencyHz : lc3_capability.samplingFrequencyHz) {
+        for (int32_t frameDurationUs : lc3_capability.frameDurationUs) {
+          for (int32_t octetsPerFrame : lc3_capability.octetsPerFrame) {
+            Lc3Configuration lc3_config = {
+                .samplingFrequencyHz = samplingFrequencyHz,
+                .frameDurationUs = frameDurationUs,
+                .octetsPerFrame = octetsPerFrame,
+            };
+            le_audio_codec_configs.push_back(lc3_config);
+          }
+        }
+      }
+    }
+
+    return le_audio_codec_configs;
+  }
+
+  LeAudioCodecCapabilitiesSetting temp_le_audio_capabilities_;
+};
+
+/**
+ * Test whether each provider of type
+ * SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be
+ * started and stopped
+ */
+TEST_P(BluetoothAudioProviderLeAudioBroadcastHardwareAidl,
+       OpenLeAudioOutputHardwareProvider) {}
+
+/**
+ * Test whether each provider of type
+ * SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be
+ * started and stopped with broadcast hardware encoding config
+ */
+TEST_P(BluetoothAudioProviderLeAudioBroadcastHardwareAidl,
+       StartAndEndLeAudioBroadcastSessionWithPossibleBroadcastConfig) {
+  if (!IsBroadcastOffloadSupported()) {
+    return;
+  }
+
+  auto lc3_codec_configs = GetBroadcastLc3SupportedList(true /* supported */);
+  LeAudioBroadcastConfiguration le_audio_broadcast_config = {
+      .codecType = CodecType::LC3,
+      .streamMap = {},
+  };
+
+  for (auto& lc3_config : lc3_codec_configs) {
+    le_audio_broadcast_config.streamMap[0]
+        .leAudioCodecConfig.set<LeAudioCodecConfiguration::lc3Config>(
+            lc3_config);
+    DataMQDesc mq_desc;
+    auto aidl_retval = audio_provider_->startSession(
+        audio_port_, AudioConfiguration(le_audio_broadcast_config),
+        latency_modes, &mq_desc);
+
+    ASSERT_TRUE(aidl_retval.isOk());
+    EXPECT_TRUE(audio_provider_->endSession().isOk());
+  }
+}
+
+/**
+ * Test whether each provider of type
+ * SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be
+ * started and stopped with Broadcast hardware encoding config
+ *
+ * Disabled since offload codec checking is not ready
+ */
+TEST_P(
+    BluetoothAudioProviderLeAudioBroadcastHardwareAidl,
+    DISABLED_StartAndEndLeAudioBroadcastSessionWithInvalidAudioConfiguration) {
+  if (!IsBroadcastOffloadSupported()) {
+    return;
+  }
+
+  auto lc3_codec_configs = GetBroadcastLc3SupportedList(false /* supported */);
+  LeAudioBroadcastConfiguration le_audio_broadcast_config = {
+      .codecType = CodecType::LC3,
+      .streamMap = {},
+  };
+
+  for (auto& lc3_config : lc3_codec_configs) {
+    le_audio_broadcast_config.streamMap[0]
+        .leAudioCodecConfig.set<LeAudioCodecConfiguration::lc3Config>(
+            lc3_config);
+    DataMQDesc mq_desc;
+    auto aidl_retval = audio_provider_->startSession(
+        audio_port_, AudioConfiguration(le_audio_broadcast_config),
+        latency_modes, &mq_desc);
+
+    // AIDL call should fail on invalid codec
+    ASSERT_FALSE(aidl_retval.isOk());
+    EXPECT_TRUE(audio_provider_->endSession().isOk());
+  }
+}
+
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
     BluetoothAudioProviderFactoryAidl);
 INSTANTIATE_TEST_SUITE_P(PerInstance, BluetoothAudioProviderFactoryAidl,
@@ -1481,14 +1657,13 @@
                              IBluetoothAudioProviderFactory::descriptor)),
                          android::PrintInstanceNameToString);
 
-// TODO(219668925): Add LE Audio Broadcast VTS
-// GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
-//     BluetoothAudioProviderLeAudioBroadcastHardwareAidl);
-// INSTANTIATE_TEST_SUITE_P(PerInstance,
-//                          BluetoothAudioProviderLeAudioBroadcastHardwareAidl,
-//                          testing::ValuesIn(android::getAidlHalInstanceNames(
-//                              IBluetoothAudioProviderFactory::descriptor)),
-//                          android::PrintInstanceNameToString);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
+    BluetoothAudioProviderLeAudioBroadcastHardwareAidl);
+INSTANTIATE_TEST_SUITE_P(PerInstance,
+                         BluetoothAudioProviderLeAudioBroadcastHardwareAidl,
+                         testing::ValuesIn(android::getAidlHalInstanceNames(
+                             IBluetoothAudioProviderFactory::descriptor)),
+                         android::PrintInstanceNameToString);
 
 int main(int argc, char** argv) {
   ::testing::InitGoogleTest(&argc, argv);
diff --git a/bluetooth/audio/utils/Android.bp b/bluetooth/audio/utils/Android.bp
index 974357e..42f9455 100644
--- a/bluetooth/audio/utils/Android.bp
+++ b/bluetooth/audio/utils/Android.bp
@@ -14,10 +14,8 @@
     srcs: [
         "session/BluetoothAudioSession.cpp",
         "session/BluetoothAudioSession_2_1.cpp",
-        "session/BluetoothAudioSession_2_2.cpp",
         "session/BluetoothAudioSupportedCodecsDB.cpp",
         "session/BluetoothAudioSupportedCodecsDB_2_1.cpp",
-        "session/BluetoothAudioSupportedCodecsDB_2_2.cpp",
     ],
     export_include_dirs: ["session/"],
     header_libs: ["libhardware_headers"],
@@ -25,7 +23,6 @@
         "android.hardware.audio.common@5.0",
         "android.hardware.bluetooth.audio@2.0",
         "android.hardware.bluetooth.audio@2.1",
-        "android.hardware.bluetooth.audio@2.2",
         "libbase",
         "libcutils",
         "libfmq",
@@ -49,7 +46,6 @@
     shared_libs: [
         "android.hardware.bluetooth.audio@2.0",
         "android.hardware.bluetooth.audio@2.1",
-        "android.hardware.bluetooth.audio@2.2",
         "libbase",
         "libcutils",
         "libbinder_ndk",
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.cpp b/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.cpp
index a6fd798..8fd1ab5 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.cpp
+++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.cpp
@@ -307,7 +307,9 @@
   if (session_type !=
           SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
       session_type !=
-          SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
+          SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH &&
+      session_type !=
+          SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
     return false;
   }
   return true;
@@ -451,7 +453,9 @@
   if (session_type !=
           SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
       session_type !=
-          SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
+          SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH &&
+      session_type !=
+          SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
     return std::vector<LeAudioCodecCapabilitiesSetting>(0);
   }
 
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp b/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp
index 7187828..cdee520 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp
+++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp
@@ -46,7 +46,8 @@
 
 void BluetoothAudioSession::OnSessionStarted(
     const std::shared_ptr<IBluetoothAudioPort> stack_iface,
-    const DataMQDesc* mq_desc, const AudioConfiguration& audio_config) {
+    const DataMQDesc* mq_desc, const AudioConfiguration& audio_config,
+    const std::vector<LatencyMode>& latency_modes) {
   std::lock_guard<std::recursive_mutex> guard(mutex_);
   if (stack_iface == nullptr) {
     LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_)
@@ -61,6 +62,7 @@
     audio_config_ = nullptr;
   } else {
     stack_iface_ = stack_iface;
+    latency_modes_ = latency_modes;
     LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
               << ", AudioConfiguration=" << audio_config.toString();
     ReportSessionStatus();
@@ -191,14 +193,14 @@
  *
  ***/
 
-bool BluetoothAudioSession::StartStream() {
+bool BluetoothAudioSession::StartStream(bool is_low_latency) {
   std::lock_guard<std::recursive_mutex> guard(mutex_);
   if (!IsSessionReady()) {
     LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
                << " has NO session";
     return false;
   }
-  auto hal_retval = stack_iface_->startStream();
+  auto hal_retval = stack_iface_->startStream(is_low_latency);
   if (!hal_retval.isOk()) {
     LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
                  << toString(session_type_) << " failed";
@@ -418,6 +420,7 @@
 
 void BluetoothAudioSession::ReportLowLatencyModeAllowedChanged(bool allowed) {
   std::lock_guard<std::recursive_mutex> guard(mutex_);
+  low_latency_allowed_ = allowed;
   if (observers_.empty()) {
     LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
                  << " has NO port state observer";
@@ -428,7 +431,9 @@
     std::shared_ptr<PortStatusCallbacks> callback = observer.second;
     LOG(INFO) << __func__
               << " - allowed=" << (allowed ? " allowed" : " disallowed");
-    callback->low_latency_mode_allowed_cb_(cookie, allowed);
+    if (callback->low_latency_mode_allowed_cb_ != nullptr) {
+      callback->low_latency_mode_allowed_cb_(cookie, allowed);
+    }
   }
 }
 
@@ -530,7 +535,25 @@
   }
 }
 
-void BluetoothAudioSession::SetLatencyMode(LatencyMode latency_mode) {
+std::vector<LatencyMode> BluetoothAudioSession::GetSupportedLatencyModes() {
+  std::lock_guard<std::recursive_mutex> guard(mutex_);
+  if (!IsSessionReady()) {
+    LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
+               << " has NO session";
+    return std::vector<LatencyMode>();
+  }
+  if (low_latency_allowed_) return latency_modes_;
+  std::vector<LatencyMode> modes;
+  for (LatencyMode mode : latency_modes_) {
+    if (mode == LatencyMode::LOW_LATENCY)
+      // ignore those low latency mode if Bluetooth stack doesn't allow
+      continue;
+    modes.push_back(mode);
+  }
+  return modes;
+}
+
+void BluetoothAudioSession::SetLatencyMode(const LatencyMode& latency_mode) {
   std::lock_guard<std::recursive_mutex> guard(mutex_);
   if (!IsSessionReady()) {
     LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.h b/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.h
index 6e390cc..5bf17bd 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.h
+++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.h
@@ -27,6 +27,7 @@
 
 #include <mutex>
 #include <unordered_map>
+#include <vector>
 
 namespace aidl {
 namespace android {
@@ -120,7 +121,8 @@
    ***/
   void OnSessionStarted(const std::shared_ptr<IBluetoothAudioPort> stack_iface,
                         const DataMQDesc* mq_desc,
-                        const AudioConfiguration& audio_config);
+                        const AudioConfiguration& audio_config,
+                        const std::vector<LatencyMode>& latency_modes);
 
   /***
    * The report function is used to report that the Bluetooth stack has ended
@@ -175,13 +177,15 @@
    * Those control functions are for the bluetooth_audio module to start,
    * suspend, stop stream, to check position, and to update metadata.
    ***/
-  bool StartStream();
+  bool StartStream(bool low_latency);
   bool SuspendStream();
   void StopStream();
   bool GetPresentationPosition(PresentationPosition& presentation_position);
   void UpdateSourceMetadata(const struct source_metadata& source_metadata);
   void UpdateSinkMetadata(const struct sink_metadata& sink_metadata);
-  void SetLatencyMode(LatencyMode latency_mode);
+
+  std::vector<LatencyMode> GetSupportedLatencyModes();
+  void SetLatencyMode(const LatencyMode& latency_mode);
 
   // The control function writes stream to FMQ
   size_t OutWritePcmData(const void* buffer, size_t bytes);
@@ -202,6 +206,8 @@
   std::unique_ptr<DataMQ> data_mq_;
   // audio data configuration for both software and offloading
   std::unique_ptr<AudioConfiguration> audio_config_;
+  std::vector<LatencyMode> latency_modes_;
+  bool low_latency_allowed_ = true;
 
   // saving those registered bluetooth_audio's callbacks
   std::unordered_map<uint16_t, std::shared_ptr<struct PortStatusCallbacks>>
@@ -234,4 +240,4 @@
 }  // namespace bluetooth
 }  // namespace hardware
 }  // namespace android
-}  // namespace aidl
\ No newline at end of file
+}  // namespace aidl
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioSessionControl.h b/bluetooth/audio/utils/aidl_session/BluetoothAudioSessionControl.h
index 451a31f..5b838b0 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothAudioSessionControl.h
+++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioSessionControl.h
@@ -98,11 +98,12 @@
   stop
    * stream, to check position, and to update metadata.
   ***/
-  static bool StartStream(const SessionType& session_type) {
+  static bool StartStream(const SessionType& session_type,
+                          bool low_latency = false) {
     std::shared_ptr<BluetoothAudioSession> session_ptr =
         BluetoothAudioSessionInstance::GetSessionInstance(session_type);
     if (session_ptr != nullptr) {
-      return session_ptr->StartStream();
+      return session_ptr->StartStream(low_latency);
     }
     return false;
   }
@@ -154,6 +155,25 @@
     }
   }
 
+  static std::vector<LatencyMode> GetSupportedLatencyModes(
+      const SessionType& session_type) {
+    std::shared_ptr<BluetoothAudioSession> session_ptr =
+        BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+    if (session_ptr != nullptr) {
+      return session_ptr->GetSupportedLatencyModes();
+    }
+    return std::vector<LatencyMode>();
+  }
+
+  static void SetLatencyMode(const SessionType& session_type,
+                             const LatencyMode& latency_mode) {
+    std::shared_ptr<BluetoothAudioSession> session_ptr =
+        BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+    if (session_ptr != nullptr) {
+      session_ptr->SetLatencyMode(latency_mode);
+    }
+  }
+
   /***
    * The control API writes stream to FMQ
    ***/
@@ -185,4 +205,4 @@
 }  // namespace bluetooth
 }  // namespace hardware
 }  // namespace android
-}  // namespace aidl
\ No newline at end of file
+}  // namespace aidl
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioSessionReport.h b/bluetooth/audio/utils/aidl_session/BluetoothAudioSessionReport.h
index 03776b5..0350259 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothAudioSessionReport.h
+++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioSessionReport.h
@@ -33,11 +33,13 @@
   static void OnSessionStarted(
       const SessionType& session_type,
       const std::shared_ptr<IBluetoothAudioPort> host_iface,
-      const DataMQDesc* data_mq, const AudioConfiguration& audio_config) {
+      const DataMQDesc* data_mq, const AudioConfiguration& audio_config,
+      const std::vector<LatencyMode>& latency_modes) {
     std::shared_ptr<BluetoothAudioSession> session_ptr =
         BluetoothAudioSessionInstance::GetSessionInstance(session_type);
     if (session_ptr != nullptr) {
-      session_ptr->OnSessionStarted(host_iface, data_mq, audio_config);
+      session_ptr->OnSessionStarted(host_iface, data_mq, audio_config,
+                                    latency_modes);
     }
   }
 
@@ -96,4 +98,4 @@
 }  // namespace bluetooth
 }  // namespace hardware
 }  // namespace android
-}  // namespace aidl
\ No newline at end of file
+}  // namespace aidl
diff --git a/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware.cpp b/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware.cpp
index 1ef9365..a4664f1 100644
--- a/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware.cpp
+++ b/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware.cpp
@@ -28,7 +28,6 @@
 #include "../aidl_session/BluetoothAudioSessionControl.h"
 #include "HidlToAidlMiddleware_2_0.h"
 #include "HidlToAidlMiddleware_2_1.h"
-#include "HidlToAidlMiddleware_2_2.h"
 
 namespace aidl {
 namespace android {
@@ -82,15 +81,10 @@
 using Lc3FrameDuration_2_1 =
     ::android::hardware::bluetooth::audio::V2_1::Lc3FrameDuration;
 
-using LeAudioConfig_2_2 =
-    ::android::hardware::bluetooth::audio::V2_2::LeAudioConfiguration;
-using LeAudioMode_2_2 =
-    ::android::hardware::bluetooth::audio::V2_2::LeAudioMode;
-
 std::mutex legacy_callback_lock;
 std::unordered_map<
     SessionType,
-    std::unordered_map<uint16_t, std::shared_ptr<PortStatusCallbacks_2_2>>>
+    std::unordered_map<uint16_t, std::shared_ptr<PortStatusCallbacks_2_0>>>
     legacy_callback_table;
 
 const static std::unordered_map<SessionType_2_1, SessionType>
@@ -461,50 +455,6 @@
   return hidl_lc3_codec_config;
 }
 
-inline LeAudioConfig_2_2 to_hidl_leaudio_config_2_2(
-    const LeAudioConfiguration& unicast_config) {
-  LeAudioConfig_2_2 hidl_leaudio_config;
-  hidl_leaudio_config.mode = LeAudioMode_2_2::UNICAST;
-  ::android::hardware::bluetooth::audio::V2_2::UnicastConfig
-      hidl_unicast_config;
-  hidl_unicast_config.peerDelay =
-      static_cast<uint32_t>(unicast_config.peerDelayUs / 1000);
-
-  auto& lc3_config = unicast_config.leAudioCodecConfig
-                         .get<LeAudioCodecConfiguration::lc3Config>();
-  hidl_unicast_config.lc3Config = to_hidl_lc3_config_2_1(lc3_config);
-
-  hidl_unicast_config.streamMap.resize(unicast_config.streamMap.size());
-  for (int i = 0; i < unicast_config.streamMap.size(); i++) {
-    hidl_unicast_config.streamMap[i].audioChannelAllocation =
-        static_cast<uint32_t>(
-            unicast_config.streamMap[i].audioChannelAllocation);
-    hidl_unicast_config.streamMap[i].streamHandle =
-        static_cast<uint16_t>(unicast_config.streamMap[i].streamHandle);
-  }
-  return hidl_leaudio_config;
-}
-
-inline LeAudioConfig_2_2 to_hidl_leaudio_broadcast_config_2_2(
-    const LeAudioBroadcastConfiguration& broadcast_config) {
-  LeAudioConfig_2_2 hidl_leaudio_config;
-  hidl_leaudio_config.mode = LeAudioMode_2_2::BROADCAST;
-  ::android::hardware::bluetooth::audio::V2_2::BroadcastConfig
-      hidl_bcast_config;
-  hidl_bcast_config.streamMap.resize(broadcast_config.streamMap.size());
-  for (int i = 0; i < broadcast_config.streamMap.size(); i++) {
-    hidl_bcast_config.streamMap[i].audioChannelAllocation =
-        static_cast<uint32_t>(
-            broadcast_config.streamMap[i].audioChannelAllocation);
-    hidl_bcast_config.streamMap[i].streamHandle =
-        static_cast<uint16_t>(broadcast_config.streamMap[i].streamHandle);
-    hidl_bcast_config.streamMap[i].lc3Config = to_hidl_lc3_config_2_1(
-        broadcast_config.streamMap[i]
-            .leAudioCodecConfig.get<LeAudioCodecConfiguration::lc3Config>());
-  }
-  return hidl_leaudio_config;
-}
-
 inline AudioConfig_2_1 to_hidl_audio_config_2_1(
     const AudioConfiguration& audio_config) {
   AudioConfig_2_1 hidl_audio_config;
@@ -529,30 +479,6 @@
   return hidl_audio_config;
 }
 
-inline AudioConfig_2_2 to_hidl_audio_config_2_2(
-    const AudioConfiguration& audio_config) {
-  AudioConfig_2_2 hidl_audio_config;
-  switch (audio_config.getTag()) {
-    case AudioConfiguration::pcmConfig:
-      hidl_audio_config.pcmConfig(to_hidl_pcm_config_2_1(
-          audio_config.get<AudioConfiguration::pcmConfig>()));
-      break;
-    case AudioConfiguration::a2dpConfig:
-      hidl_audio_config.codecConfig(to_hidl_codec_config_2_0(
-          audio_config.get<AudioConfiguration::a2dpConfig>()));
-      break;
-    case AudioConfiguration::leAudioConfig:
-      hidl_audio_config.leAudioConfig(to_hidl_leaudio_config_2_2(
-          audio_config.get<AudioConfiguration::leAudioConfig>()));
-      break;
-    case AudioConfiguration::leAudioBroadcastConfig:
-      hidl_audio_config.leAudioConfig(to_hidl_leaudio_broadcast_config_2_2(
-          audio_config.get<AudioConfiguration::leAudioBroadcastConfig>()));
-      break;
-  }
-  return hidl_audio_config;
-}
-
 /***
  *
  * 2.0
@@ -568,18 +494,58 @@
 uint16_t HidlToAidlMiddleware_2_0::RegisterControlResultCback(
     const SessionType_2_0& session_type,
     const PortStatusCallbacks_2_0& cbacks) {
-  PortStatusCallbacks_2_2 callback_2_2{
-      .control_result_cb_ = cbacks.control_result_cb_,
-      .session_changed_cb_ = cbacks.session_changed_cb_,
+  LOG(INFO) << __func__ << ": " << toString(session_type);
+  auto aidl_session_type = from_session_type_2_0(session_type);
+  // Pass the exact reference to the lambda
+  auto& session_legacy_callback_table =
+      legacy_callback_table[aidl_session_type];
+  PortStatusCallbacks aidl_callbacks{};
+  if (cbacks.control_result_cb_) {
+    aidl_callbacks.control_result_cb_ =
+        [&session_legacy_callback_table](uint16_t cookie, bool start_resp,
+                                         const BluetoothAudioStatus& status) {
+          if (session_legacy_callback_table.find(cookie) ==
+              session_legacy_callback_table.end()) {
+            LOG(ERROR) << __func__ << ": Unknown callback invoked!";
+            return;
+          }
+          auto& cback = session_legacy_callback_table[cookie];
+          cback->control_result_cb_(cookie, start_resp, to_hidl_status(status));
+        };
+  }
+  if (cbacks.session_changed_cb_) {
+    aidl_callbacks.session_changed_cb_ =
+        [&session_legacy_callback_table](uint16_t cookie) {
+          if (session_legacy_callback_table.find(cookie) ==
+              session_legacy_callback_table.end()) {
+            LOG(ERROR) << __func__ << ": Unknown callback invoked!";
+            return;
+          }
+          auto& cback = session_legacy_callback_table[cookie];
+          cback->session_changed_cb_(cookie);
+        };
   };
-  return HidlToAidlMiddleware_2_2::RegisterControlResultCback(
-      static_cast<SessionType_2_1>(session_type), callback_2_2);
+  auto cookie = BluetoothAudioSessionControl::RegisterControlResultCback(
+      aidl_session_type, aidl_callbacks);
+  {
+    std::lock_guard<std::mutex> guard(legacy_callback_lock);
+    session_legacy_callback_table[cookie] =
+        std::make_shared<PortStatusCallbacks_2_0>(cbacks);
+  }
+  return cookie;
 }
 
 void HidlToAidlMiddleware_2_0::UnregisterControlResultCback(
     const SessionType_2_0& session_type, uint16_t cookie) {
-  HidlToAidlMiddleware_2_2::UnregisterControlResultCback(
-      static_cast<SessionType_2_1>(session_type), cookie);
+  LOG(INFO) << __func__ << ": " << toString(session_type);
+  auto aidl_session_type = from_session_type_2_0(session_type);
+  BluetoothAudioSessionControl::UnregisterControlResultCback(aidl_session_type,
+                                                             cookie);
+  auto& session_callback_table = legacy_callback_table[aidl_session_type];
+  if (session_callback_table.find(cookie) != session_callback_table.end()) {
+    std::lock_guard<std::mutex> guard(legacy_callback_lock);
+    session_callback_table.erase(cookie);
+  }
 }
 
 const AudioConfig_2_0 HidlToAidlMiddleware_2_0::GetAudioConfig(
@@ -659,124 +625,6 @@
       from_session_type_2_1(session_type)));
 }
 
-/***
- *
- * 2.2
- *
- ***/
-
-bool HidlToAidlMiddleware_2_2::IsSessionReady(
-    const SessionType_2_1& session_type) {
-  return BluetoothAudioSessionControl::IsSessionReady(
-      from_session_type_2_1(session_type));
-}
-
-uint16_t HidlToAidlMiddleware_2_2::RegisterControlResultCback(
-    const SessionType_2_1& session_type,
-    const PortStatusCallbacks_2_2& cbacks) {
-  LOG(INFO) << __func__ << ": " << toString(session_type);
-  auto aidl_session_type = from_session_type_2_1(session_type);
-  // Pass the exact reference to the lambda
-  auto& session_legacy_callback_table =
-      legacy_callback_table[aidl_session_type];
-  PortStatusCallbacks aidl_callbacks{};
-  if (cbacks.control_result_cb_) {
-    aidl_callbacks.control_result_cb_ =
-        [&session_legacy_callback_table](uint16_t cookie, bool start_resp,
-                                         const BluetoothAudioStatus& status) {
-          if (session_legacy_callback_table.find(cookie) ==
-              session_legacy_callback_table.end()) {
-            LOG(ERROR) << __func__ << ": Unknown callback invoked!";
-            return;
-          }
-          auto& cback = session_legacy_callback_table[cookie];
-          cback->control_result_cb_(cookie, start_resp, to_hidl_status(status));
-        };
-  }
-  if (cbacks.session_changed_cb_) {
-    aidl_callbacks.session_changed_cb_ =
-        [&session_legacy_callback_table](uint16_t cookie) {
-          if (session_legacy_callback_table.find(cookie) ==
-              session_legacy_callback_table.end()) {
-            LOG(ERROR) << __func__ << ": Unknown callback invoked!";
-            return;
-          }
-          auto& cback = session_legacy_callback_table[cookie];
-          cback->session_changed_cb_(cookie);
-        };
-  };
-  if (cbacks.audio_configuration_changed_cb_) {
-    aidl_callbacks.audio_configuration_changed_cb_ =
-        [&session_legacy_callback_table](uint16_t cookie) {
-          if (session_legacy_callback_table.find(cookie) ==
-              session_legacy_callback_table.end()) {
-            LOG(ERROR) << __func__ << ": Unknown callback invoked!";
-            return;
-          }
-          auto& cback = session_legacy_callback_table[cookie];
-          cback->audio_configuration_changed_cb_(cookie);
-        };
-  };
-  auto cookie = BluetoothAudioSessionControl::RegisterControlResultCback(
-      aidl_session_type, aidl_callbacks);
-  {
-    std::lock_guard<std::mutex> guard(legacy_callback_lock);
-    session_legacy_callback_table[cookie] =
-        std::make_shared<PortStatusCallbacks_2_2>(cbacks);
-  }
-  return cookie;
-}
-
-void HidlToAidlMiddleware_2_2::UnregisterControlResultCback(
-    const SessionType_2_1& session_type, uint16_t cookie) {
-  LOG(INFO) << __func__ << ": " << toString(session_type);
-  auto aidl_session_type = from_session_type_2_1(session_type);
-  BluetoothAudioSessionControl::UnregisterControlResultCback(aidl_session_type,
-                                                             cookie);
-  auto& session_callback_table = legacy_callback_table[aidl_session_type];
-  if (session_callback_table.find(cookie) != session_callback_table.end()) {
-    std::lock_guard<std::mutex> guard(legacy_callback_lock);
-    session_callback_table.erase(cookie);
-  }
-}
-
-const AudioConfig_2_2 HidlToAidlMiddleware_2_2::GetAudioConfig(
-    const SessionType_2_1& session_type) {
-  return to_hidl_audio_config_2_2(BluetoothAudioSessionControl::GetAudioConfig(
-      from_session_type_2_1(session_type)));
-}
-
-bool HidlToAidlMiddleware_2_2::StartStream(
-    const SessionType_2_1& session_type) {
-  return BluetoothAudioSessionControl::StartStream(
-      from_session_type_2_1(session_type));
-}
-
-bool HidlToAidlMiddleware_2_2::SuspendStream(
-    const SessionType_2_1& session_type) {
-  return BluetoothAudioSessionControl::SuspendStream(
-      from_session_type_2_1(session_type));
-}
-
-void HidlToAidlMiddleware_2_2::StopStream(const SessionType_2_1& session_type) {
-  return BluetoothAudioSessionControl::StopStream(
-      from_session_type_2_1(session_type));
-}
-
-void HidlToAidlMiddleware_2_2::UpdateTracksMetadata(
-    const SessionType_2_1& session_type,
-    const struct source_metadata* source_metadata) {
-  return BluetoothAudioSessionControl::UpdateSourceMetadata(
-      from_session_type_2_1(session_type), *source_metadata);
-}
-
-void HidlToAidlMiddleware_2_2::UpdateSinkMetadata(
-    const SessionType_2_1& session_type,
-    const struct sink_metadata* sink_metadata) {
-  return BluetoothAudioSessionControl::UpdateSinkMetadata(
-      from_session_type_2_1(session_type), *sink_metadata);
-}
-
 }  // namespace audio
 }  // namespace bluetooth
 }  // namespace hardware
diff --git a/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware_2_2.h b/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware_2_2.h
deleted file mode 100644
index f6c3e5c..0000000
--- a/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware_2_2.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <android/hardware/bluetooth/audio/2.2/types.h>
-
-#include "../session/BluetoothAudioSession.h"
-#include "../session/BluetoothAudioSession_2_2.h"
-
-namespace aidl {
-namespace android {
-namespace hardware {
-namespace bluetooth {
-namespace audio {
-
-using SessionType_2_1 =
-    ::android::hardware::bluetooth::audio::V2_1::SessionType;
-using PortStatusCallbacks_2_0 =
-    ::android::bluetooth::audio::PortStatusCallbacks;
-using PortStatusCallbacks_2_2 =
-    ::android::bluetooth::audio::PortStatusCallbacks_2_2;
-using AudioConfig_2_2 =
-    ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration;
-
-class HidlToAidlMiddleware_2_2 {
- public:
-  static bool IsSessionReady(const SessionType_2_1& session_type);
-
-  static uint16_t RegisterControlResultCback(
-      const SessionType_2_1& session_type,
-      const PortStatusCallbacks_2_2& cbacks);
-
-  static void UnregisterControlResultCback(const SessionType_2_1& session_type,
-                                           uint16_t cookie);
-
-  static const AudioConfig_2_2 GetAudioConfig(
-      const SessionType_2_1& session_type);
-
-  static bool StartStream(const SessionType_2_1& session_type);
-
-  static bool SuspendStream(const SessionType_2_1& session_type);
-
-  static void StopStream(const SessionType_2_1& session_type);
-
-  static void UpdateTracksMetadata(
-      const SessionType_2_1& session_type,
-      const struct source_metadata* source_metadata);
-
-  static void UpdateSinkMetadata(const SessionType_2_1& session_type,
-                                 const struct sink_metadata* sink_metadata);
-};
-
-}  // namespace audio
-}  // namespace bluetooth
-}  // namespace hardware
-}  // namespace android
-}  // namespace aidl
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSessionControl_2_2.h b/bluetooth/audio/utils/session/BluetoothAudioSessionControl_2_2.h
deleted file mode 100644
index c270ef0..0000000
--- a/bluetooth/audio/utils/session/BluetoothAudioSessionControl_2_2.h
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include "BluetoothAudioSession_2_2.h"
-
-namespace android {
-namespace bluetooth {
-namespace audio {
-
-class BluetoothAudioSessionControl_2_2 {
-  using SessionType_2_1 =
-      ::android::hardware::bluetooth::audio::V2_1::SessionType;
-  using AudioConfiguration_2_2 =
-      ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration;
-
- public:
-  // The control API helps to check if session is ready or not
-  // @return: true if the Bluetooth stack has started th specified session
-  static bool IsSessionReady(const SessionType_2_1& session_type) {
-    std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
-        BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
-    if (session_ptr != nullptr) {
-      return session_ptr->IsSessionReady();
-    }
-    return false;
-  }
-
-  // The control API helps the bluetooth_audio module to register
-  // PortStatusCallbacks
-  // @return: cookie - the assigned number to this bluetooth_audio output
-  static uint16_t RegisterControlResultCback(
-      const SessionType_2_1& session_type, const PortStatusCallbacks& cbacks) {
-    std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
-        BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
-    if (session_ptr != nullptr) {
-      PortStatusCallbacks_2_2 cb = {
-          .control_result_cb_ = cbacks.control_result_cb_,
-          .session_changed_cb_ = cbacks.session_changed_cb_,
-          .audio_configuration_changed_cb_ = nullptr};
-      return session_ptr->RegisterStatusCback(cb);
-    }
-    return kObserversCookieUndefined;
-  }
-
-  // The control API helps the bluetooth_audio module to register
-  // PortStatusCallbacks_2_2
-  // @return: cookie - the assigned number to this bluetooth_audio output
-  static uint16_t RegisterControlResultCback(
-      const SessionType_2_1& session_type,
-      const PortStatusCallbacks_2_2& cbacks) {
-    std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
-        BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
-    if (session_ptr != nullptr) {
-      return session_ptr->RegisterStatusCback(cbacks);
-    }
-    return kObserversCookieUndefined;
-  }
-
-  // The control API helps the bluetooth_audio module to unregister
-  // PortStatusCallbacks and PortStatusCallbacks_2_2
-  // @param: cookie - indicates which bluetooth_audio output is
-  static void UnregisterControlResultCback(const SessionType_2_1& session_type,
-                                           uint16_t cookie) {
-    std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
-        BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
-    if (session_ptr != nullptr) {
-      session_ptr->UnregisterStatusCback(cookie);
-    }
-  }
-
-  // The control API for the bluetooth_audio module to get current
-  // AudioConfiguration
-  static const AudioConfiguration_2_2 GetAudioConfig(
-      const SessionType_2_1& session_type) {
-    std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
-        BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
-    if (session_ptr != nullptr) {
-      return session_ptr->GetAudioConfig();
-    } else if (session_type ==
-               SessionType_2_1::A2DP_HARDWARE_OFFLOAD_DATAPATH) {
-      return BluetoothAudioSession_2_2::kInvalidOffloadAudioConfiguration;
-    } else if (
-        session_type ==
-            SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
-        session_type ==
-            SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
-      return BluetoothAudioSession_2_2::kInvalidLeOffloadAudioConfiguration;
-    } else {
-      return BluetoothAudioSession_2_2::kInvalidSoftwareAudioConfiguration;
-    }
-  }
-
-  // Those control APIs for the bluetooth_audio module to start / suspend / stop
-  // stream, to check position, and to update metadata.
-  static bool StartStream(const SessionType_2_1& session_type) {
-    std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
-        BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
-    if (session_ptr != nullptr) {
-      return session_ptr->StartStream();
-    }
-    return false;
-  }
-
-  static bool SuspendStream(const SessionType_2_1& session_type) {
-    std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
-        BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
-    if (session_ptr != nullptr) {
-      return session_ptr->SuspendStream();
-    }
-    return false;
-  }
-
-  static void StopStream(const SessionType_2_1& session_type) {
-    std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
-        BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
-    if (session_ptr != nullptr) {
-      session_ptr->StopStream();
-    }
-  }
-
-  static bool GetPresentationPosition(const SessionType_2_1& session_type,
-                                      uint64_t* remote_delay_report_ns,
-                                      uint64_t* total_bytes_readed,
-                                      timespec* data_position) {
-    std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
-        BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
-    if (session_ptr != nullptr) {
-      return session_ptr->GetAudioSession()->GetPresentationPosition(
-          remote_delay_report_ns, total_bytes_readed, data_position);
-    }
-    return false;
-  }
-
-  static void UpdateTracksMetadata(
-      const SessionType_2_1& session_type,
-      const struct source_metadata* source_metadata) {
-    std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
-        BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
-    if (session_ptr != nullptr) {
-      session_ptr->UpdateTracksMetadata(source_metadata);
-    }
-  }
-
-  static void UpdateSinkMetadata(const SessionType_2_1& session_type,
-                                 const struct sink_metadata* sink_metadata) {
-    std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
-        BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
-    if (session_ptr != nullptr) {
-      session_ptr->UpdateSinkMetadata(sink_metadata);
-    }
-  }
-
-  // The control API writes stream to FMQ
-  static size_t OutWritePcmData(const SessionType_2_1& session_type,
-                                const void* buffer, size_t bytes) {
-    std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
-        BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
-    if (session_ptr != nullptr) {
-      return session_ptr->GetAudioSession()->OutWritePcmData(buffer, bytes);
-    }
-    return 0;
-  }
-
-  // The control API reads stream from FMQ
-  static size_t InReadPcmData(const SessionType_2_1& session_type, void* buffer,
-                              size_t bytes) {
-    std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
-        BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
-    if (session_ptr != nullptr) {
-      return session_ptr->GetAudioSession()->InReadPcmData(buffer, bytes);
-    }
-    return 0;
-  }
-};
-
-}  // namespace audio
-}  // namespace bluetooth
-}  // namespace android
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSessionReport_2_2.h b/bluetooth/audio/utils/session/BluetoothAudioSessionReport_2_2.h
deleted file mode 100644
index 17e140e..0000000
--- a/bluetooth/audio/utils/session/BluetoothAudioSessionReport_2_2.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include "BluetoothAudioSession_2_2.h"
-
-namespace android {
-namespace bluetooth {
-namespace audio {
-
-class BluetoothAudioSessionReport_2_2 {
- public:
-  // The API reports the Bluetooth stack has started the session, and will
-  // inform registered bluetooth_audio outputs
-  static void OnSessionStarted(
-      const ::android::hardware::bluetooth::audio::V2_1::SessionType&
-          session_type,
-      const sp<IBluetoothAudioPort> host_iface,
-      const DataMQ::Descriptor* dataMQ,
-      const ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration&
-          audio_config) {
-    std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
-        BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
-    if (session_ptr != nullptr) {
-      session_ptr->OnSessionStarted(host_iface, dataMQ, audio_config);
-    }
-  }
-
-  // The API reports the Bluetooth stack has ended the session, and will
-  // inform registered bluetooth_audio outputs
-  static void OnSessionEnded(
-      const ::android::hardware::bluetooth::audio::V2_1::SessionType&
-          session_type) {
-    std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
-        BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
-    if (session_ptr != nullptr) {
-      session_ptr->OnSessionEnded();
-    }
-  }
-  // The API reports the Bluetooth stack has replied the result of startStream
-  // or suspendStream, and will inform registered bluetooth_audio outputs
-  static void ReportControlStatus(
-      const ::android::hardware::bluetooth::audio::V2_1::SessionType&
-          session_type,
-      const bool& start_resp, const BluetoothAudioStatus& status) {
-    std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
-        BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
-    if (session_ptr != nullptr) {
-      session_ptr->ReportControlStatus(start_resp, status);
-    }
-  }
-  // The API reports the Bluetooth stack has replied the changed of the audio
-  // configuration, and will inform registered bluetooth_audio outputs
-  static void ReportAudioConfigChanged(
-      const ::android::hardware::bluetooth::audio::V2_1::SessionType&
-          session_type,
-      const ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration&
-          audio_config) {
-    std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
-        BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
-    if (session_ptr != nullptr) {
-      session_ptr->ReportAudioConfigChanged(audio_config);
-    }
-  }
-};
-
-}  // namespace audio
-}  // namespace bluetooth
-}  // namespace android
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.cpp b/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.cpp
deleted file mode 100644
index ceb0662..0000000
--- a/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.cpp
+++ /dev/null
@@ -1,636 +0,0 @@
-/*
- * Copyright 2018 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.
- */
-
-#define LOG_TAG "BTAudioProviderSession_2_2"
-
-#include "BluetoothAudioSession_2_2.h"
-
-#include <android-base/logging.h>
-#include <android-base/stringprintf.h>
-#include <android/hardware/bluetooth/audio/2.2/IBluetoothAudioPort.h>
-
-#include "../aidl_session/HidlToAidlMiddleware_2_0.h"
-#include "../aidl_session/HidlToAidlMiddleware_2_2.h"
-
-namespace android {
-namespace bluetooth {
-namespace audio {
-
-using ::aidl::android::hardware::bluetooth::audio::HidlToAidlMiddleware_2_0;
-using ::aidl::android::hardware::bluetooth::audio::HidlToAidlMiddleware_2_2;
-using ::android::hardware::audio::common::V5_0::AudioContentType;
-using ::android::hardware::audio::common::V5_0::AudioSource;
-using ::android::hardware::audio::common::V5_0::AudioUsage;
-using ::android::hardware::audio::common::V5_0::PlaybackTrackMetadata;
-using ::android::hardware::audio::common::V5_0::RecordTrackMetadata;
-using ::android::hardware::audio::common::V5_0::SinkMetadata;
-using ::android::hardware::audio::common::V5_0::SourceMetadata;
-using ::android::hardware::bluetooth::audio::V2_0::BitsPerSample;
-using ::android::hardware::bluetooth::audio::V2_0::ChannelMode;
-using ::android::hardware::bluetooth::audio::V2_2::LeAudioConfiguration;
-using ::android::hardware::bluetooth::audio::V2_2::LeAudioMode;
-using PcmParameters_2_1 =
-    ::android::hardware::bluetooth::audio::V2_1::PcmParameters;
-using SampleRate_2_1 = ::android::hardware::bluetooth::audio::V2_1::SampleRate;
-
-using SessionType_2_1 =
-    ::android::hardware::bluetooth::audio::V2_1::SessionType;
-using SessionType_2_0 =
-    ::android::hardware::bluetooth::audio::V2_0::SessionType;
-
-using AudioConfiguration_2_1 =
-    ::android::hardware::bluetooth::audio::V2_1::AudioConfiguration;
-
-static constexpr PcmParameters_2_1 kInvalidPcmParameters = {
-    .sampleRate = SampleRate_2_1::RATE_UNKNOWN,
-    .channelMode = ChannelMode::UNKNOWN,
-    .bitsPerSample = BitsPerSample::BITS_UNKNOWN,
-    .dataIntervalUs = 0,
-};
-
-static LeAudioConfiguration kInvalidLeAudioConfig = {
-    .mode = LeAudioMode::UNKNOWN,
-    .config = {},
-};
-
-::android::hardware::bluetooth::audio::V2_2::AudioConfiguration
-    BluetoothAudioSession_2_2::invalidSoftwareAudioConfiguration = {};
-::android::hardware::bluetooth::audio::V2_2::AudioConfiguration
-    BluetoothAudioSession_2_2::invalidOffloadAudioConfiguration = {};
-::android::hardware::bluetooth::audio::V2_2::AudioConfiguration
-    BluetoothAudioSession_2_2::invalidLeOffloadAudioConfiguration = {};
-
-using IBluetoothAudioPort_2_2 =
-    ::android::hardware::bluetooth::audio::V2_2::IBluetoothAudioPort;
-
-namespace {
-bool is_2_0_session_type(
-    const ::android::hardware::bluetooth::audio::V2_1::SessionType&
-        session_type) {
-  if (session_type == SessionType_2_1::A2DP_SOFTWARE_ENCODING_DATAPATH ||
-      session_type == SessionType_2_1::A2DP_HARDWARE_OFFLOAD_DATAPATH ||
-      session_type == SessionType_2_1::HEARING_AID_SOFTWARE_ENCODING_DATAPATH) {
-    return true;
-  } else {
-    return false;
-  }
-}
-}  // namespace
-
-BluetoothAudioSession_2_2::BluetoothAudioSession_2_2(
-    const ::android::hardware::bluetooth::audio::V2_1::SessionType&
-        session_type)
-    : audio_session(BluetoothAudioSessionInstance::GetSessionInstance(
-          static_cast<SessionType_2_0>(session_type))),
-      audio_session_2_1(
-          BluetoothAudioSessionInstance_2_1::GetSessionInstance(session_type)) {
-  if (is_2_0_session_type(session_type)) {
-    session_type_2_1_ = (SessionType_2_1::UNKNOWN);
-  } else {
-    session_type_2_1_ = (session_type);
-  }
-  raw_session_type_ = session_type;
-  invalidSoftwareAudioConfiguration.pcmConfig(kInvalidPcmParameters);
-  invalidOffloadAudioConfiguration.codecConfig(
-      audio_session->kInvalidCodecConfiguration);
-  invalidLeOffloadAudioConfiguration.leAudioConfig(kInvalidLeAudioConfig);
-}
-
-bool BluetoothAudioSession_2_2::IsSessionReady() {
-  if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
-    return HidlToAidlMiddleware_2_2::IsSessionReady(raw_session_type_);
-  if (session_type_2_1_ !=
-          SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
-      session_type_2_1_ !=
-          SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
-    return audio_session->IsSessionReady();
-  }
-
-  std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
-  return audio_session->stack_iface_ != nullptr;
-}
-
-std::shared_ptr<BluetoothAudioSession>
-BluetoothAudioSession_2_2::GetAudioSession() {
-  return audio_session;
-}
-std::shared_ptr<BluetoothAudioSession_2_1>
-BluetoothAudioSession_2_2::GetAudioSession_2_1() {
-  return audio_session_2_1;
-}
-
-void BluetoothAudioSession_2_2::UpdateTracksMetadata(
-    const struct source_metadata* source_metadata) {
-  if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
-    return HidlToAidlMiddleware_2_2::UpdateTracksMetadata(raw_session_type_,
-                                                          source_metadata);
-  std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
-  if (!IsSessionReady()) {
-    LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_2_1_)
-               << " has NO session";
-    return;
-  }
-
-  ssize_t track_count = source_metadata->track_count;
-  LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_2_1_)
-            << ", " << track_count << " track(s)";
-
-  if (session_type_2_1_ == SessionType_2_1::UNKNOWN) {
-    audio_session->UpdateTracksMetadata(source_metadata);
-    return;
-  }
-
-  struct playback_track_metadata* track = source_metadata->tracks;
-  SourceMetadata sourceMetadata;
-  PlaybackTrackMetadata* halMetadata;
-
-  sourceMetadata.tracks.resize(track_count);
-  halMetadata = sourceMetadata.tracks.data();
-  while (track_count && track) {
-    halMetadata->usage = static_cast<AudioUsage>(track->usage);
-    halMetadata->contentType =
-        static_cast<AudioContentType>(track->content_type);
-    halMetadata->gain = track->gain;
-    LOG(VERBOSE) << __func__ << " - SessionType=" << toString(session_type_2_1_)
-                 << ", usage=" << toString(halMetadata->usage)
-                 << ", content=" << toString(halMetadata->contentType)
-                 << ", gain=" << halMetadata->gain;
-    --track_count;
-    ++track;
-    ++halMetadata;
-  }
-  auto hal_retval = audio_session->stack_iface_->updateMetadata(sourceMetadata);
-  if (!hal_retval.isOk()) {
-    LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
-                 << toString(session_type_2_1_) << " failed";
-  }
-}
-
-void BluetoothAudioSession_2_2::UpdateSinkMetadata(
-    const struct sink_metadata* sink_metadata) {
-  if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
-    return HidlToAidlMiddleware_2_2::UpdateSinkMetadata(raw_session_type_,
-                                                        sink_metadata);
-  std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
-  if (!IsSessionReady()) {
-    LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_2_1_)
-               << " has NO session";
-    return;
-  }
-
-  ssize_t track_count = sink_metadata->track_count;
-  LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_2_1_)
-            << ", " << track_count << " track(s)";
-  if (session_type_2_1_ == SessionType_2_1::A2DP_SOFTWARE_ENCODING_DATAPATH ||
-      session_type_2_1_ == SessionType_2_1::A2DP_HARDWARE_OFFLOAD_DATAPATH) {
-    return;
-  }
-
-  struct record_track_metadata* track = sink_metadata->tracks;
-  SinkMetadata sinkMetadata;
-  RecordTrackMetadata* halMetadata;
-
-  sinkMetadata.tracks.resize(track_count);
-  halMetadata = sinkMetadata.tracks.data();
-  while (track_count && track) {
-    halMetadata->source = static_cast<AudioSource>(track->source);
-    halMetadata->gain = track->gain;
-    // halMetadata->destination leave unspecified
-    LOG(INFO) << __func__
-              << " - SessionType=" << toString(GetAudioSession()->session_type_)
-              << ", source=" << track->source
-              << ", dest_device=" << track->dest_device
-              << ", gain=" << track->gain
-              << ", dest_device_address=" << track->dest_device_address;
-    --track_count;
-    ++track;
-    ++halMetadata;
-  }
-
-  /* This is called just for 2.2 sessions, so it's safe to do this casting*/
-  IBluetoothAudioPort_2_2* stack_iface_2_2_ =
-      static_cast<IBluetoothAudioPort_2_2*>(audio_session->stack_iface_.get());
-  auto hal_retval = stack_iface_2_2_->updateSinkMetadata(sinkMetadata);
-  if (!hal_retval.isOk()) {
-    LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
-                 << toString(session_type_2_1_) << " failed";
-  }
-}
-
-// The control function is for the bluetooth_audio module to get the current
-// AudioConfiguration
-const ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration
-BluetoothAudioSession_2_2::GetAudioConfig() {
-  if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
-    return HidlToAidlMiddleware_2_2::GetAudioConfig(raw_session_type_);
-  std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
-  if (IsSessionReady()) {
-    auto audio_config_discriminator = audio_config_2_2_.getDiscriminator();
-    // If session is unknown it means it should be 2.0 type
-    if (session_type_2_1_ != SessionType_2_1::UNKNOWN) {
-      if ((audio_config_discriminator ==
-               ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration::
-                   hidl_discriminator::pcmConfig &&
-           audio_config_2_2_ != kInvalidSoftwareAudioConfiguration) ||
-          (audio_config_discriminator ==
-               ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration::
-                   hidl_discriminator::leAudioConfig &&
-           audio_config_2_2_ != kInvalidLeOffloadAudioConfiguration))
-        return audio_config_2_2_;
-
-      ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration toConf;
-      const AudioConfiguration_2_1 fromConf =
-          GetAudioSession_2_1()->GetAudioConfig();
-      if (fromConf.getDiscriminator() ==
-          AudioConfiguration_2_1::hidl_discriminator::pcmConfig) {
-        toConf.pcmConfig(fromConf.pcmConfig());
-        return toConf;
-      }
-    }
-
-    ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration toConf;
-    const AudioConfiguration fromConf = GetAudioSession()->GetAudioConfig();
-    // pcmConfig only differs between 2.0 and 2.1 in AudioConfiguration
-    if (fromConf.getDiscriminator() ==
-        AudioConfiguration::hidl_discriminator::codecConfig) {
-      toConf.codecConfig(fromConf.codecConfig());
-    } else {
-      toConf.pcmConfig() = {
-          .sampleRate = static_cast<
-              ::android::hardware::bluetooth::audio::V2_1::SampleRate>(
-              fromConf.pcmConfig().sampleRate),
-          .channelMode = fromConf.pcmConfig().channelMode,
-          .bitsPerSample = fromConf.pcmConfig().bitsPerSample,
-          .dataIntervalUs = 0};
-    }
-    return toConf;
-  } else if (session_type_2_1_ ==
-                 SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
-             session_type_2_1_ ==
-                 SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
-    return kInvalidLeOffloadAudioConfiguration;
-  } else {
-    return kInvalidSoftwareAudioConfiguration;
-  }
-}
-
-// Those control functions are for the bluetooth_audio module to start, suspend,
-// stop stream, to check position, and to update metadata.
-bool BluetoothAudioSession_2_2::StartStream() {
-  if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
-    return HidlToAidlMiddleware_2_2::StartStream(raw_session_type_);
-  std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
-  if (!IsSessionReady()) {
-    LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_2_1_)
-               << " has NO session";
-    return false;
-  }
-  auto hal_retval = audio_session->stack_iface_->startStream();
-  if (!hal_retval.isOk()) {
-    LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
-                 << toString(session_type_2_1_) << " failed";
-    return false;
-  }
-  return true;
-}
-
-bool BluetoothAudioSession_2_2::SuspendStream() {
-  if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
-    return HidlToAidlMiddleware_2_2::SuspendStream(raw_session_type_);
-  std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
-  if (!IsSessionReady()) {
-    LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_2_1_)
-               << " has NO session";
-    return false;
-  }
-  auto hal_retval = audio_session->stack_iface_->suspendStream();
-  if (!hal_retval.isOk()) {
-    LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
-                 << toString(session_type_2_1_) << " failed";
-    return false;
-  }
-  return true;
-}
-
-void BluetoothAudioSession_2_2::StopStream() {
-  if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
-    return HidlToAidlMiddleware_2_2::StopStream(raw_session_type_);
-  std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
-  if (!IsSessionReady()) {
-    return;
-  }
-  auto hal_retval = audio_session->stack_iface_->stopStream();
-  if (!hal_retval.isOk()) {
-    LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
-                 << toString(session_type_2_1_) << " failed";
-  }
-}
-
-bool BluetoothAudioSession_2_2::UpdateAudioConfig(
-    const ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration&
-        audio_config) {
-  bool is_software_session =
-      (session_type_2_1_ == SessionType_2_1::A2DP_SOFTWARE_ENCODING_DATAPATH ||
-       session_type_2_1_ ==
-           SessionType_2_1::HEARING_AID_SOFTWARE_ENCODING_DATAPATH ||
-       session_type_2_1_ ==
-           SessionType_2_1::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH ||
-       session_type_2_1_ ==
-           SessionType_2_1::LE_AUDIO_SOFTWARE_DECODED_DATAPATH);
-  bool is_offload_a2dp_session =
-      (session_type_2_1_ == SessionType_2_1::A2DP_HARDWARE_OFFLOAD_DATAPATH);
-  bool is_offload_le_audio_session =
-      (session_type_2_1_ ==
-           SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
-       session_type_2_1_ ==
-           SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH);
-  auto audio_config_discriminator = audio_config.getDiscriminator();
-  bool is_software_audio_config =
-      (is_software_session &&
-       audio_config_discriminator ==
-           ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration::
-               hidl_discriminator::pcmConfig);
-  bool is_a2dp_offload_audio_config =
-      (is_offload_a2dp_session &&
-       audio_config_discriminator ==
-           ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration::
-               hidl_discriminator::codecConfig);
-  bool is_le_audio_offload_audio_config =
-      (is_offload_le_audio_session &&
-       audio_config_discriminator ==
-           ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration::
-               hidl_discriminator::leAudioConfig);
-  if (!is_software_audio_config && !is_a2dp_offload_audio_config &&
-      !is_le_audio_offload_audio_config) {
-    return false;
-  }
-  audio_config_2_2_ = audio_config;
-  return true;
-}
-
-// The report function is used to report that the Bluetooth stack has started
-// this session without any failure, and will invoke session_changed_cb_ to
-// notify those registered bluetooth_audio outputs
-void BluetoothAudioSession_2_2::OnSessionStarted(
-    const sp<IBluetoothAudioPort> stack_iface, const DataMQ::Descriptor* dataMQ,
-    const ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration&
-        audio_config) {
-  if (session_type_2_1_ == SessionType_2_1::UNKNOWN) {
-    ::android::hardware::bluetooth::audio::V2_0::AudioConfiguration config;
-    if (audio_config.getDiscriminator() ==
-        ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration::
-            hidl_discriminator::codecConfig) {
-      config.codecConfig(audio_config.codecConfig());
-    } else {
-      auto& tmpPcm = audio_config.pcmConfig();
-      config.pcmConfig(
-          ::android::hardware::bluetooth::audio::V2_0::PcmParameters{
-              .sampleRate = static_cast<SampleRate>(tmpPcm.sampleRate),
-              .channelMode = tmpPcm.channelMode,
-              .bitsPerSample = tmpPcm.bitsPerSample
-              /*dataIntervalUs is not passed to 2.0 */
-          });
-    }
-
-    audio_session->OnSessionStarted(stack_iface, dataMQ, config);
-  } else {
-    std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
-    if (stack_iface == nullptr) {
-      LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_2_1_)
-                 << ", IBluetoothAudioPort Invalid";
-    } else if (!UpdateAudioConfig(audio_config)) {
-      LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_2_1_)
-                 << ", AudioConfiguration=" << toString(audio_config)
-                 << " Invalid";
-    } else if (!audio_session->UpdateDataPath(dataMQ)) {
-      LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_2_1_)
-                 << " DataMQ Invalid";
-      audio_config_2_2_ =
-          ((session_type_2_1_ ==
-                SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
-            session_type_2_1_ ==
-                SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH)
-               ? kInvalidLeOffloadAudioConfiguration
-               : kInvalidSoftwareAudioConfiguration);
-    } else {
-      audio_session->stack_iface_ = stack_iface;
-      LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_2_1_)
-                << ", AudioConfiguration=" << toString(audio_config);
-      ReportSessionStatus();
-    };
-  }
-}
-
-// The report function is used to report that the Bluetooth stack has ended the
-// session, and will invoke session_changed_cb_ to notify registered
-// bluetooth_audio outputs
-void BluetoothAudioSession_2_2::OnSessionEnded() {
-  std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
-  bool toggled = IsSessionReady();
-  LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_2_1_);
-  if (session_type_2_1_ == SessionType_2_1::UNKNOWN) {
-    audio_session->OnSessionEnded();
-    return;
-  }
-
-  audio_config_2_2_ =
-      ((session_type_2_1_ ==
-            SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
-        session_type_2_1_ ==
-            SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH)
-           ? kInvalidLeOffloadAudioConfiguration
-           : kInvalidSoftwareAudioConfiguration);
-  audio_session->stack_iface_ = nullptr;
-  audio_session->UpdateDataPath(nullptr);
-  if (toggled) {
-    ReportSessionStatus();
-  }
-}
-
-// The control function helps the bluetooth_audio module to register
-// PortStatusCallbacks_2_2
-// @return: cookie - the assigned number to this bluetooth_audio output
-uint16_t BluetoothAudioSession_2_2::RegisterStatusCback(
-    const PortStatusCallbacks_2_2& cbacks) {
-  if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
-    return HidlToAidlMiddleware_2_2::RegisterControlResultCback(
-        raw_session_type_, cbacks);
-  if (session_type_2_1_ !=
-          SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
-      session_type_2_1_ !=
-          SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
-    PortStatusCallbacks cb = {
-        .control_result_cb_ = cbacks.control_result_cb_,
-        .session_changed_cb_ = cbacks.session_changed_cb_};
-    return audio_session->RegisterStatusCback(cb);
-  }
-
-  std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
-  uint16_t cookie = ObserversCookieGetInitValue(session_type_2_1_);
-  uint16_t cookie_upper_bound = ObserversCookieGetUpperBound(session_type_2_1_);
-
-  while (cookie < cookie_upper_bound) {
-    if (observers_.find(cookie) == observers_.end()) {
-      break;
-    }
-    ++cookie;
-  }
-  if (cookie >= cookie_upper_bound) {
-    LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_2_1_)
-               << " has " << observers_.size()
-               << " observers already (No Resource)";
-    return kObserversCookieUndefined;
-  }
-  std::shared_ptr<struct PortStatusCallbacks_2_2> cb =
-      std::make_shared<struct PortStatusCallbacks_2_2>();
-  *cb = cbacks;
-  observers_[cookie] = cb;
-  return cookie;
-}
-
-// The control function helps the bluetooth_audio module to unregister
-// PortStatusCallbacks_2_2
-// @param: cookie - indicates which bluetooth_audio output is
-void BluetoothAudioSession_2_2::UnregisterStatusCback(uint16_t cookie) {
-  if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
-    return HidlToAidlMiddleware_2_2::UnregisterControlResultCback(
-        raw_session_type_, cookie);
-  std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
-  if (session_type_2_1_ !=
-          SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
-      session_type_2_1_ !=
-          SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
-    audio_session->UnregisterStatusCback(cookie);
-    return;
-  }
-  if (observers_.erase(cookie) != 1) {
-    LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_2_1_)
-                 << " no such provider=0x"
-                 << android::base::StringPrintf("%04x", cookie);
-  }
-}
-
-// invoking the registered session_changed_cb_
-void BluetoothAudioSession_2_2::ReportSessionStatus() {
-  // This is locked already by OnSessionStarted / OnSessionEnded
-  if (session_type_2_1_ !=
-          SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
-      session_type_2_1_ !=
-          SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
-    audio_session->ReportSessionStatus();
-    return;
-  }
-  if (observers_.empty()) {
-    LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_2_1_)
-              << " has NO port state observer";
-    return;
-  }
-  for (auto& observer : observers_) {
-    uint16_t cookie = observer.first;
-    std::shared_ptr<struct PortStatusCallbacks_2_2> cb = observer.second;
-    LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_2_1_)
-              << " notify to bluetooth_audio=0x"
-              << android::base::StringPrintf("%04x", cookie);
-    cb->session_changed_cb_(cookie);
-  }
-}
-
-// The report function is used to report that the Bluetooth stack has notified
-// the result of startStream or suspendStream, and will invoke
-// control_result_cb_ to notify registered bluetooth_audio outputs
-void BluetoothAudioSession_2_2::ReportControlStatus(
-    bool start_resp, const BluetoothAudioStatus& status) {
-  if (session_type_2_1_ !=
-          SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
-      session_type_2_1_ !=
-          SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
-    audio_session->ReportControlStatus(start_resp, status);
-    return;
-  }
-  std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
-  if (observers_.empty()) {
-    LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_2_1_)
-                 << " has NO port state observer";
-    return;
-  }
-  for (auto& observer : observers_) {
-    uint16_t cookie = observer.first;
-    std::shared_ptr<struct PortStatusCallbacks_2_2> cb = observer.second;
-    LOG(INFO) << __func__ << " - status=" << toString(status)
-              << " for SessionType=" << toString(session_type_2_1_)
-              << ", bluetooth_audio=0x"
-              << android::base::StringPrintf("%04x", cookie)
-              << (start_resp ? " started" : " suspended");
-    cb->control_result_cb_(cookie, start_resp, status);
-  }
-}
-
-// The report function is used to report that the Bluetooth stack has notified
-// the result of startStream or suspendStream, and will invoke
-// control_result_cb_ to notify registered bluetooth_audio outputs
-void BluetoothAudioSession_2_2::ReportAudioConfigChanged(
-    const ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration&
-        audio_config) {
-  if (session_type_2_1_ !=
-          SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
-      session_type_2_1_ !=
-          SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
-    return;
-  }
-  std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
-  audio_config_2_2_ = audio_config;
-  if (observers_.empty()) {
-    LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_2_1_)
-                 << " has NO port state observer";
-    return;
-  }
-  for (auto& observer : observers_) {
-    uint16_t cookie = observer.first;
-    std::shared_ptr<struct PortStatusCallbacks_2_2> cb = observer.second;
-    LOG(INFO) << __func__ << " for SessionType=" << toString(session_type_2_1_)
-              << ", bluetooth_audio=0x"
-              << android::base::StringPrintf("%04x", cookie);
-    if (cb->audio_configuration_changed_cb_ != nullptr) {
-      cb->audio_configuration_changed_cb_(cookie);
-    }
-  }
-}
-
-std::unique_ptr<BluetoothAudioSessionInstance_2_2>
-    BluetoothAudioSessionInstance_2_2::instance_ptr =
-        std::unique_ptr<BluetoothAudioSessionInstance_2_2>(
-            new BluetoothAudioSessionInstance_2_2());
-
-// API to fetch the session of A2DP / Hearing Aid
-std::shared_ptr<BluetoothAudioSession_2_2>
-BluetoothAudioSessionInstance_2_2::GetSessionInstance(
-    const SessionType_2_1& session_type) {
-  std::lock_guard<std::mutex> guard(instance_ptr->mutex_);
-  if (!instance_ptr->sessions_map_.empty()) {
-    auto entry = instance_ptr->sessions_map_.find(session_type);
-    if (entry != instance_ptr->sessions_map_.end()) {
-      return entry->second;
-    }
-  }
-  std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
-      std::make_shared<BluetoothAudioSession_2_2>(session_type);
-  instance_ptr->sessions_map_[session_type] = session_ptr;
-  return session_ptr;
-}
-
-}  // namespace audio
-}  // namespace bluetooth
-}  // namespace android
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.h b/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.h
deleted file mode 100644
index e04ad80..0000000
--- a/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.h
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <android/hardware/bluetooth/audio/2.2/types.h>
-
-#include <mutex>
-#include <unordered_map>
-
-#include "BluetoothAudioSession.h"
-#include "BluetoothAudioSession_2_1.h"
-
-namespace android {
-namespace bluetooth {
-namespace audio {
-
-inline uint16_t ObserversCookieGetInitValue(
-    const ::android::hardware::bluetooth::audio::V2_1::SessionType&
-        session_type) {
-  return (static_cast<uint16_t>(session_type) << 8 & 0xff00);
-}
-inline uint16_t ObserversCookieGetUpperBound(
-    const ::android::hardware::bluetooth::audio::V2_1::SessionType&
-        session_type) {
-  return (static_cast<uint16_t>(session_type) << 8 & 0xff00) +
-         kObserversCookieSize;
-}
-
-struct PortStatusCallbacks_2_2 {
-  // control_result_cb_ - when the Bluetooth stack reports results of
-  // streamStarted or streamSuspended, the BluetoothAudioProvider will invoke
-  // this callback to report to the bluetooth_audio module.
-  // @param: cookie - indicates which bluetooth_audio output should handle
-  // @param: start_resp - this report is for startStream or not
-  // @param: status - the result of startStream
-  std::function<void(uint16_t cookie, bool start_resp,
-                     const BluetoothAudioStatus& status)>
-      control_result_cb_;
-  // session_changed_cb_ - when the Bluetooth stack start / end session, the
-  // BluetoothAudioProvider will invoke this callback to notify to the
-  // bluetooth_audio module.
-  // @param: cookie - indicates which bluetooth_audio output should handle
-  std::function<void(uint16_t cookie)> session_changed_cb_;
-  // audio_configuration_changed_cb_ - when the Bluetooth stack change the audio
-  // configuration, the BluetoothAudioProvider will invoke this callback to
-  // notify to the bluetooth_audio module.
-  // @param: cookie - indicates which bluetooth_audio output should handle
-  std::function<void(uint16_t cookie)> audio_configuration_changed_cb_;
-};
-
-class BluetoothAudioSession_2_2 {
- private:
-  std::shared_ptr<BluetoothAudioSession> audio_session;
-  std::shared_ptr<BluetoothAudioSession_2_1> audio_session_2_1;
-
-  ::android::hardware::bluetooth::audio::V2_1::SessionType session_type_2_1_;
-  ::android::hardware::bluetooth::audio::V2_1::SessionType raw_session_type_;
-
-  // audio data configuration for both software and offloading
-  ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration
-      audio_config_2_2_;
-
-  bool UpdateAudioConfig(
-      const ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration&
-          audio_config);
-
-  static ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration
-      invalidSoftwareAudioConfiguration;
-  static ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration
-      invalidOffloadAudioConfiguration;
-  static ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration
-      invalidLeOffloadAudioConfiguration;
-
-  // saving those registered bluetooth_audio's callbacks
-  std::unordered_map<uint16_t, std::shared_ptr<struct PortStatusCallbacks_2_2>>
-      observers_;
-
-  // invoking the registered session_changed_cb_
-  void ReportSessionStatus();
-
- public:
-  BluetoothAudioSession_2_2(
-      const ::android::hardware::bluetooth::audio::V2_1::SessionType&
-          session_type);
-
-  // The function helps to check if this session is ready or not
-  // @return: true if the Bluetooth stack has started the specified session
-  bool IsSessionReady();
-
-  std::shared_ptr<BluetoothAudioSession> GetAudioSession();
-  std::shared_ptr<BluetoothAudioSession_2_1> GetAudioSession_2_1();
-
-  // The report function is used to report that the Bluetooth stack has started
-  // this session without any failure, and will invoke session_changed_cb_ to
-  // notify those registered bluetooth_audio outputs
-  void OnSessionStarted(
-      const sp<IBluetoothAudioPort> stack_iface,
-      const DataMQ::Descriptor* dataMQ,
-      const ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration&
-          audio_config);
-
-  // The report function is used to report that the Bluetooth stack has ended
-  // the session, and will invoke session_changed_cb_ to notify registered
-  // bluetooth_audio outputs
-  void OnSessionEnded();
-
-  // Those control functions are for the bluetooth_audio module to start,
-  // suspend, stop stream, to check position, and to update metadata.
-  bool StartStream();
-  bool SuspendStream();
-  void StopStream();
-
-  // The control function helps the bluetooth_audio module to register
-  // PortStatusCallbacks_2_2
-  // @return: cookie - the assigned number to this bluetooth_audio output
-  uint16_t RegisterStatusCback(const PortStatusCallbacks_2_2& cbacks);
-
-  // The control function helps the bluetooth_audio module to unregister
-  // PortStatusCallbacks_2_2
-  // @param: cookie - indicates which bluetooth_audio output is
-  void UnregisterStatusCback(uint16_t cookie);
-
-  // The report function is used to report that the Bluetooth stack has notified
-  // the result of startStream or suspendStream, and will invoke
-  // control_result_cb_ to notify registered bluetooth_audio outputs
-  void ReportControlStatus(bool start_resp, const BluetoothAudioStatus& status);
-
-  // The report function is used to report that the Bluetooth stack has notified
-  // the audio configuration changed, and will invoke
-  // audio_configuration_changed_cb_ to notify registered bluetooth_audio
-  // outputs
-  void ReportAudioConfigChanged(
-      const ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration&
-          audio_config);
-
-  // The control function is for the bluetooth_audio module to get the current
-  // AudioConfiguration
-  const ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration
-  GetAudioConfig();
-
-  void UpdateTracksMetadata(const struct source_metadata* source_metadata);
-  void UpdateSinkMetadata(const struct sink_metadata* sink_metadata);
-
-  static constexpr ::android::hardware::bluetooth::audio::V2_2::
-      AudioConfiguration& kInvalidSoftwareAudioConfiguration =
-          invalidSoftwareAudioConfiguration;
-  static constexpr ::android::hardware::bluetooth::audio::V2_2::
-      AudioConfiguration& kInvalidOffloadAudioConfiguration =
-          invalidOffloadAudioConfiguration;
-  static constexpr ::android::hardware::bluetooth::audio::V2_2::
-      AudioConfiguration& kInvalidLeOffloadAudioConfiguration =
-          invalidLeOffloadAudioConfiguration;
-};
-
-class BluetoothAudioSessionInstance_2_2 {
- public:
-  // The API is to fetch the specified session of A2DP / Hearing Aid
-  static std::shared_ptr<BluetoothAudioSession_2_2> GetSessionInstance(
-      const ::android::hardware::bluetooth::audio::V2_1::SessionType&
-          session_type);
-
- private:
-  static std::unique_ptr<BluetoothAudioSessionInstance_2_2> instance_ptr;
-  std::mutex mutex_;
-  std::unordered_map<::android::hardware::bluetooth::audio::V2_1::SessionType,
-                     std::shared_ptr<BluetoothAudioSession_2_2>>
-      sessions_map_;
-};
-
-}  // namespace audio
-}  // namespace bluetooth
-}  // namespace android
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_2.cpp b/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_2.cpp
deleted file mode 100644
index decff70..0000000
--- a/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_2.cpp
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "BTAudioProviderSessionCodecsDB_2_2"
-
-#include "BluetoothAudioSupportedCodecsDB_2_2.h"
-
-#include <android-base/logging.h>
-
-namespace android {
-namespace bluetooth {
-namespace audio {
-
-using ::android::hardware::bluetooth::audio::V2_0::BitsPerSample;
-using ::android::hardware::bluetooth::audio::V2_1::CodecType;
-using ::android::hardware::bluetooth::audio::V2_1::Lc3FrameDuration;
-using ::android::hardware::bluetooth::audio::V2_1::Lc3Parameters;
-using ::android::hardware::bluetooth::audio::V2_1::SampleRate;
-using ::android::hardware::bluetooth::audio::V2_2::AudioLocation;
-using ::android::hardware::bluetooth::audio::V2_2::BroadcastCapability;
-using ::android::hardware::bluetooth::audio::V2_2::
-    LeAudioCodecCapabilitiesSetting;
-using ::android::hardware::bluetooth::audio::V2_2::UnicastCapability;
-using SessionType_2_1 =
-    ::android::hardware::bluetooth::audio::V2_1::SessionType;
-
-// Stores the list of offload supported capability
-std::vector<LeAudioCodecCapabilitiesSetting> kDefaultOffloadLeAudioCapabilities;
-
-static const UnicastCapability kInvalidUnicastCapability = {
-    .codecType = CodecType::UNKNOWN};
-
-static const BroadcastCapability kInvalidBroadcastCapability = {
-    .codecType = CodecType::UNKNOWN};
-
-// Default Supported Codecs
-// LC3 16_1: sample rate: 16 kHz, frame duration: 7.5 ms, octets per frame: 30
-static const Lc3Parameters kLc3Capability_16_1 = {
-    .samplingFrequency = SampleRate::RATE_16000,
-    .frameDuration = Lc3FrameDuration::DURATION_7500US,
-    .octetsPerFrame = 30};
-
-// Default Supported Codecs
-// LC3 16_2: sample rate: 16 kHz, frame duration: 10 ms, octets per frame: 40
-static const Lc3Parameters kLc3Capability_16_2 = {
-    .samplingFrequency = SampleRate::RATE_16000,
-    .frameDuration = Lc3FrameDuration::DURATION_10000US,
-    .octetsPerFrame = 40};
-
-// Default Supported Codecs
-// LC3 48_4: sample rate: 48 kHz, frame duration: 10 ms, octets per frame: 120
-static const Lc3Parameters kLc3Capability_48_4 = {
-    .samplingFrequency = SampleRate::RATE_48000,
-    .frameDuration = Lc3FrameDuration::DURATION_10000US,
-    .octetsPerFrame = 120};
-
-static const std::vector<Lc3Parameters> supportedLc3CapabilityList = {
-    kLc3Capability_48_4, kLc3Capability_16_2, kLc3Capability_16_1};
-
-static AudioLocation stereoAudio = static_cast<AudioLocation>(
-    AudioLocation::FRONT_LEFT | AudioLocation::FRONT_RIGHT);
-static AudioLocation monoAudio = AudioLocation::UNKNOWN;
-
-// Stores the supported setting of audio location, connected device, and the
-// channel count for each device
-std::vector<std::tuple<AudioLocation, uint8_t, uint8_t>>
-    supportedDeviceSetting = {
-        // Stereo, two connected device, one for L one for R
-        std::make_tuple(stereoAudio, 2, 1),
-        // Stereo, one connected device for both L and R
-        std::make_tuple(stereoAudio, 1, 2),
-        // Mono
-        std::make_tuple(monoAudio, 1, 1)};
-
-bool IsOffloadLeAudioConfigurationValid(
-    const ::android::hardware::bluetooth::audio::V2_1::SessionType&
-        session_type,
-    const ::android::hardware::bluetooth::audio::V2_2::LeAudioConfiguration&) {
-  if (session_type !=
-          SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
-      session_type !=
-          SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
-    return false;
-  }
-
-  // TODO: perform checks on le_audio_codec_config once we know supported
-  // parameters
-
-  return true;
-}
-
-UnicastCapability composeUnicastLc3Capability(AudioLocation audioLocation,
-                                              uint8_t deviceCnt,
-                                              uint8_t channelCount,
-                                              Lc3Parameters capability) {
-  return UnicastCapability{.codecType = CodecType::LC3,
-                           .supportedChannel = audioLocation,
-                           .deviceCount = deviceCnt,
-                           .channelCountPerDevice = channelCount,
-                           .capabilities = capability};
-}
-
-std::vector<LeAudioCodecCapabilitiesSetting> GetLeAudioOffloadCodecCapabilities(
-    const SessionType_2_1& session_type) {
-  if (session_type !=
-          SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
-      session_type !=
-          SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
-    return std::vector<LeAudioCodecCapabilitiesSetting>(0);
-  }
-
-  if (kDefaultOffloadLeAudioCapabilities.empty()) {
-    for (auto [audioLocation, deviceCnt, channelCount] :
-         supportedDeviceSetting) {
-      for (auto capability : supportedLc3CapabilityList) {
-        UnicastCapability lc3Capability = composeUnicastLc3Capability(
-            audioLocation, deviceCnt, channelCount, capability);
-        UnicastCapability lc3MonoDecodeCapability =
-            composeUnicastLc3Capability(monoAudio, 1, 1, capability);
-
-        // Adds the capability for encode only
-        kDefaultOffloadLeAudioCapabilities.push_back(
-            {.unicastEncodeCapability = lc3Capability,
-             .unicastDecodeCapability = kInvalidUnicastCapability,
-             .broadcastCapability = kInvalidBroadcastCapability});
-
-        // Adds the capability for decode only
-        kDefaultOffloadLeAudioCapabilities.push_back(
-            {.unicastEncodeCapability = kInvalidUnicastCapability,
-             .unicastDecodeCapability = lc3Capability,
-             .broadcastCapability = kInvalidBroadcastCapability});
-
-        // Adds the capability for the case that encode and decode exist at the
-        // same time
-        kDefaultOffloadLeAudioCapabilities.push_back(
-            {.unicastEncodeCapability = lc3Capability,
-             .unicastDecodeCapability = lc3MonoDecodeCapability,
-             .broadcastCapability = kInvalidBroadcastCapability});
-      }
-    }
-  }
-
-  return kDefaultOffloadLeAudioCapabilities;
-}
-
-}  // namespace audio
-}  // namespace bluetooth
-}  // namespace android
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_2.h b/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_2.h
deleted file mode 100644
index 34bba5f..0000000
--- a/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_2.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <android/hardware/bluetooth/audio/2.2/types.h>
-
-#include "BluetoothAudioSupportedCodecsDB.h"
-#include "BluetoothAudioSupportedCodecsDB_2_1.h"
-
-namespace android {
-namespace bluetooth {
-namespace audio {
-
-bool IsOffloadLeAudioConfigurationValid(
-    const ::android::hardware::bluetooth::audio::V2_1::SessionType&
-        session_type,
-    const ::android::hardware::bluetooth::audio::V2_2::LeAudioConfiguration&
-        le_audio_codec_config);
-
-std::vector<hardware::bluetooth::audio::V2_2::LeAudioCodecCapabilitiesSetting>
-GetLeAudioOffloadCodecCapabilities(
-    const ::android::hardware::bluetooth::audio::V2_1::SessionType&
-        session_type);
-}  // namespace audio
-}  // namespace bluetooth
-}  // namespace android
diff --git a/broadcastradio/1.1/vts/functional/Android.bp b/broadcastradio/1.1/vts/functional/Android.bp
index f0dfe96..0fb4eb0 100644
--- a/broadcastradio/1.1/vts/functional/Android.bp
+++ b/broadcastradio/1.1/vts/functional/Android.bp
@@ -26,6 +26,7 @@
 cc_test {
     name: "VtsHalBroadcastradioV1_1TargetTest",
     defaults: ["VtsHalTargetTestDefaults"],
+    tidy_timeout_srcs: ["VtsHalBroadcastradioV1_1TargetTest.cpp"],
     srcs: ["VtsHalBroadcastradioV1_1TargetTest.cpp"],
     static_libs: [
         "android.hardware.broadcastradio@1.0",
diff --git a/broadcastradio/2.0/default/Android.bp b/broadcastradio/2.0/default/Android.bp
index 870c944..38eeb15 100644
--- a/broadcastradio/2.0/default/Android.bp
+++ b/broadcastradio/2.0/default/Android.bp
@@ -25,6 +25,9 @@
 
 cc_binary {
     name: "android.hardware.broadcastradio@2.0-service",
+    vintf_fragments: [
+        "android.hardware.broadcastradio@2.0-service.xml",
+    ],
     init_rc: ["android.hardware.broadcastradio@2.0-service.rc"],
     vendor: true,
     relative_install_path: "hw",
@@ -41,7 +44,7 @@
         "TunerSession.cpp",
         "VirtualProgram.cpp",
         "VirtualRadio.cpp",
-        "service.cpp"
+        "service.cpp",
     ],
     static_libs: [
         "android.hardware.broadcastradio@common-utils-2x-lib",
diff --git a/broadcastradio/2.0/default/android.hardware.broadcastradio@2.0-service.rc b/broadcastradio/2.0/default/android.hardware.broadcastradio@2.0-service.rc
index dd8c9c6..d58ba53 100644
--- a/broadcastradio/2.0/default/android.hardware.broadcastradio@2.0-service.rc
+++ b/broadcastradio/2.0/default/android.hardware.broadcastradio@2.0-service.rc
@@ -1,5 +1,6 @@
 service broadcastradio-hal2 /vendor/bin/hw/android.hardware.broadcastradio@2.0-service
-    interface android.hardware.broadcastradio@2.0::IBroadcastRadio default
+    interface android.hardware.broadcastradio@2.0::IBroadcastRadio amfm
+    interface android.hardware.broadcastradio@2.0::IBroadcastRadio dab
     class hal
     user audioserver
     group audio
diff --git a/broadcastradio/2.0/default/android.hardware.broadcastradio@2.0-service.xml b/broadcastradio/2.0/default/android.hardware.broadcastradio@2.0-service.xml
new file mode 100644
index 0000000..97f2e4d
--- /dev/null
+++ b/broadcastradio/2.0/default/android.hardware.broadcastradio@2.0-service.xml
@@ -0,0 +1,12 @@
+<manifest version="1.0" type="device">
+    <hal format="hidl">
+        <name>android.hardware.broadcastradio</name>
+        <transport>hwbinder</transport>
+        <version>2.0</version>
+        <interface>
+            <name>IBroadcastRadio</name>
+            <instance>amfm</instance>
+            <instance>dab</instance>
+        </interface>
+    </hal>
+</manifest>
diff --git a/broadcastradio/2.0/vts/functional/Android.bp b/broadcastradio/2.0/vts/functional/Android.bp
index e26486d..cb50c5e 100644
--- a/broadcastradio/2.0/vts/functional/Android.bp
+++ b/broadcastradio/2.0/vts/functional/Android.bp
@@ -26,6 +26,7 @@
 cc_test {
     name: "VtsHalBroadcastradioV2_0TargetTest",
     defaults: ["VtsHalTargetTestDefaults"],
+    tidy_timeout_srcs: ["VtsHalBroadcastradioV2_0TargetTest.cpp"],
     srcs: ["VtsHalBroadcastradioV2_0TargetTest.cpp"],
     static_libs: [
         "android.hardware.broadcastradio@2.0",
diff --git a/camera/metadata/3.7/types.hal b/camera/metadata/3.7/types.hal
new file mode 100644
index 0000000..a09bdf9
--- /dev/null
+++ b/camera/metadata/3.7/types.hal
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Autogenerated from camera metadata definitions in
+ * /system/media/camera/docs/metadata_definitions.xml
+ * *** DO NOT EDIT BY HAND ***
+ */
+
+package android.hardware.camera.metadata@3.7;
+
+import android.hardware.camera.metadata@3.2;
+import android.hardware.camera.metadata@3.3;
+import android.hardware.camera.metadata@3.4;
+import android.hardware.camera.metadata@3.5;
+import android.hardware.camera.metadata@3.6;
+
+// No new metadata sections added in this revision
+
+/**
+ * Main enumeration for defining camera metadata tags added in this revision
+ *
+ * <p>Partial documentation is included for each tag; for complete documentation, reference
+ * '/system/media/camera/docs/docs.html' in the corresponding Android source tree.</p>
+ */
+enum CameraMetadataTag : @3.6::CameraMetadataTag {
+    /** android.info.deviceStateOrientations [static, int64[], ndk_public]
+     */
+    ANDROID_INFO_DEVICE_STATE_ORIENTATIONS = android.hardware.camera.metadata@3.4::CameraMetadataTag:ANDROID_INFO_END_3_4,
+
+    ANDROID_INFO_END_3_7,
+
+};
+
+/*
+ * Enumeration definitions for the various entries that need them
+ */
diff --git a/camera/provider/2.4/vts/functional/Android.bp b/camera/provider/2.4/vts/functional/Android.bp
index 8886ee1..d2f61a5 100644
--- a/camera/provider/2.4/vts/functional/Android.bp
+++ b/camera/provider/2.4/vts/functional/Android.bp
@@ -26,6 +26,7 @@
 cc_test {
     name: "VtsHalCameraProviderV2_4TargetTest",
     defaults: ["VtsHalTargetTestDefaults"],
+    tidy_timeout_srcs: ["VtsHalCameraProviderV2_4TargetTest.cpp"],
     srcs: ["VtsHalCameraProviderV2_4TargetTest.cpp"],
 
     // TODO(b/64437680): Assume these are always available on the device.
diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index 37d2973..052103d 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -882,6 +882,7 @@
             camera_metadata* oldSessionParams, camera_metadata* newSessionParams);
 
     void verifyRequestTemplate(const camera_metadata_t* metadata, RequestTemplate requestTemplate);
+    static void overrideRotateAndCrop(::android::hardware::hidl_vec<uint8_t> *settings /*in/out*/);
 
     static bool isDepthOnly(const camera_metadata_t* staticMeta);
 
@@ -935,6 +936,9 @@
             camera_metadata_ro_entry* streamConfigs,
             camera_metadata_ro_entry* maxResolutionStreamConfigs,
             const camera_metadata_t* staticMetadata);
+    void getPrivacyTestPatternModes(
+            const camera_metadata_t* staticMetadata,
+            std::unordered_set<int32_t>* privacyTestPatternModes/*out*/);
 
     static V3_2::DataspaceFlags getDataspace(PixelFormat format);
 
@@ -4659,6 +4663,7 @@
                                                            settings = req;
                                                        });
         ASSERT_TRUE(ret.isOk());
+        overrideRotateAndCrop(&settings);
 
         hidl_handle buffer_handle;
         StreamBuffer outputBuffer;
@@ -4835,6 +4840,7 @@
         settings.setToExternal(
                 reinterpret_cast<uint8_t *> (const_cast<camera_metadata_t *> (settingsBuffer)),
                 get_camera_metadata_size(settingsBuffer));
+        overrideRotateAndCrop(&settings);
 
         free_camera_metadata(staticMeta);
         ret = session->close();
@@ -4912,6 +4918,7 @@
                 reinterpret_cast<uint8_t *> (const_cast<camera_metadata_t *> (
                         filteredSettingsBuffer)),
                 get_camera_metadata_size(filteredSettingsBuffer));
+        overrideRotateAndCrop(&camSettings[0].settings);
         camSettings[0].fmqSettingsSize = 0;
         camSettings[0].physicalCameraId = physicalDeviceId;
 
@@ -5069,6 +5076,7 @@
         settings.setToExternal(
                 reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(settingsBuffer)),
                 get_camera_metadata_size(settingsBuffer));
+        overrideRotateAndCrop(&settings);
 
         free_camera_metadata(staticMeta);
         ret = session->close();
@@ -5304,6 +5312,7 @@
             camera_metadata_t *metaBuffer = requestMeta.release();
             requestSettings[i].setToExternal(reinterpret_cast<uint8_t *> (metaBuffer),
                     get_camera_metadata_size(metaBuffer), true);
+            overrideRotateAndCrop(&requestSettings[i]);
 
             requests[i] = {frameNumber + i, 0 /* fmqSettingsSize */, requestSettings[i],
                 emptyInputBuffer, {outputBuffers[i]}};
@@ -5530,6 +5539,7 @@
             camera_metadata_t *metaBuffer = requestMeta.release();
             requestSettings[i].setToExternal(reinterpret_cast<uint8_t *> (metaBuffer),
                     get_camera_metadata_size(metaBuffer), true);
+            overrideRotateAndCrop(&requestSettings[i]);
 
             requests[i] = {frameNumber + i, 0 /* fmqSettingsSize */, requestSettings[i],
                 emptyInputBuffer, {outputBuffers[i]}};
@@ -5670,6 +5680,7 @@
                                                            settings = req;
                                                        });
         ASSERT_TRUE(ret.isOk());
+        overrideRotateAndCrop(&settings);
 
         ::android::hardware::hidl_vec<StreamBuffer> emptyOutputBuffers;
         StreamBuffer emptyInputBuffer = {-1, 0, nullptr, BufferStatus::ERROR, nullptr,
@@ -5754,6 +5765,7 @@
                                                            settings = req;
                                                        });
         ASSERT_TRUE(ret.isOk());
+        overrideRotateAndCrop(&settings);
 
         hidl_handle buffer_handle;
         if (useHalBufManager) {
@@ -6617,6 +6629,25 @@
     ASSERT_TRUE(-ENOENT == retcode || 0 == retcode);
 }
 
+void CameraHidlTest::getPrivacyTestPatternModes(
+        const camera_metadata_t* staticMetadata,
+        std::unordered_set<int32_t>* privacyTestPatternModes/*out*/) {
+    ASSERT_NE(staticMetadata, nullptr);
+    ASSERT_NE(privacyTestPatternModes, nullptr);
+
+    camera_metadata_ro_entry entry;
+    int retcode = find_camera_metadata_ro_entry(
+            staticMetadata, ANDROID_SENSOR_AVAILABLE_TEST_PATTERN_MODES, &entry);
+    ASSERT_TRUE(0 == retcode);
+
+    for (auto i = 0; i < entry.count; i++) {
+        if (entry.data.i32[i] == ANDROID_SENSOR_TEST_PATTERN_MODE_SOLID_COLOR ||
+                entry.data.i32[i] == ANDROID_SENSOR_TEST_PATTERN_MODE_BLACK) {
+            privacyTestPatternModes->insert(entry.data.i32[i]);
+        }
+    }
+}
+
 // Select an appropriate dataspace given a specific pixel format.
 V3_2::DataspaceFlags CameraHidlTest::getDataspace(PixelFormat format) {
     switch (format) {
@@ -7654,6 +7685,16 @@
         ASSERT_TRUE(isUltraHighResCamera && !isMultiCamera);
         physicalIds.insert(cameraId);
     }
+
+    std::unordered_set<int32_t> physicalRequestKeyIDs;
+    rc = getSupportedKeys(const_cast<camera_metadata_t *>(metadata),
+            ANDROID_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS, &physicalRequestKeyIDs);
+    ASSERT_TRUE(Status::OK == rc);
+    bool hasTestPatternPhysicalRequestKey = physicalRequestKeyIDs.find(
+            ANDROID_SENSOR_TEST_PATTERN_MODE) != physicalRequestKeyIDs.end();
+    std::unordered_set<int32_t> privacyTestPatternModes;
+    getPrivacyTestPatternModes(metadata, &privacyTestPatternModes);
+
     // Map from image format to number of multi-resolution sizes for that format
     std::unordered_map<int32_t, size_t> multiResOutputFormatCounterMap;
     std::unordered_map<int32_t, size_t> multiResInputFormatCounterMap;
@@ -7675,6 +7716,7 @@
         camera_metadata_ro_entry physicalStreamConfigs;
         camera_metadata_ro_entry physicalMaxResolutionStreamConfigs;
         bool isUltraHighRes = false;
+        std::unordered_set<int32_t> subCameraPrivacyTestPatterns;
         if (isPublicId) {
             ::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice> subDevice;
             Return<void> ret;
@@ -7705,6 +7747,8 @@
                         &physicalMultiResStreamConfigs, &physicalStreamConfigs,
                         &physicalMaxResolutionStreamConfigs, staticMetadata);
                 isUltraHighRes = isUltraHighResolution(staticMetadata);
+
+                getPrivacyTestPatternModes(staticMetadata, &subCameraPrivacyTestPatterns);
             });
             ASSERT_TRUE(ret.isOk());
         } else {
@@ -7731,6 +7775,7 @@
                                 &physicalMultiResStreamConfigs, &physicalStreamConfigs,
                                 &physicalMaxResolutionStreamConfigs, staticMetadata);
                         isUltraHighRes = isUltraHighResolution(staticMetadata);
+                        getPrivacyTestPatternModes(staticMetadata, &subCameraPrivacyTestPatterns);
                     });
             ASSERT_TRUE(ret.isOk());
 
@@ -7747,6 +7792,10 @@
             ASSERT_TRUE(ret.isOk());
         }
 
+        if (hasTestPatternPhysicalRequestKey) {
+            ASSERT_TRUE(privacyTestPatternModes == subCameraPrivacyTestPatterns);
+        }
+
         if (physicalMultiResStreamConfigs.count > 0) {
             ASSERT_GE(deviceVersion, CAMERA_DEVICE_API_VERSION_3_7);
             ASSERT_EQ(physicalMultiResStreamConfigs.count % 4, 0);
@@ -7982,6 +8031,20 @@
                 poseReference >= ANDROID_LENS_POSE_REFERENCE_PRIMARY_CAMERA);
     }
 
+    retcode = find_camera_metadata_ro_entry(metadata,
+            ANDROID_INFO_DEVICE_STATE_ORIENTATIONS, &entry);
+    if (0 == retcode && entry.count > 0) {
+        ASSERT_TRUE((entry.count % 2) == 0);
+        uint64_t maxPublicState = ((uint64_t) provider::V2_5::DeviceState::FOLDED) << 1;
+        uint64_t vendorStateStart = 1UL << 31; // Reserved for vendor specific states
+        uint64_t stateMask = (1 << vendorStateStart) - 1;
+        stateMask &= ~((1 << maxPublicState) - 1);
+        for (int i = 0; i < entry.count; i += 2){
+            ASSERT_TRUE((entry.data.i64[i] & stateMask) == 0);
+            ASSERT_TRUE((entry.data.i64[i+1] % 90) == 0);
+        }
+    }
+
     verifyExtendedSceneModeCharacteristics(metadata);
     verifyZoomCharacteristics(metadata);
 }
@@ -8742,6 +8805,25 @@
     }
 }
 
+void CameraHidlTest::overrideRotateAndCrop(
+        ::android::hardware::hidl_vec<uint8_t> *settings /*in/out*/) {
+    if (settings == nullptr) {
+        return;
+    }
+
+    ::android::hardware::camera::common::V1_0::helper::CameraMetadata requestMeta;
+    requestMeta.append(reinterpret_cast<camera_metadata_t *> (settings->data()));
+    auto entry = requestMeta.find(ANDROID_SCALER_ROTATE_AND_CROP);
+    if ((entry.count > 0) && (entry.data.u8[0] == ANDROID_SCALER_ROTATE_AND_CROP_AUTO)) {
+        uint8_t disableRotateAndCrop = ANDROID_SCALER_ROTATE_AND_CROP_NONE;
+        requestMeta.update(ANDROID_SCALER_ROTATE_AND_CROP, &disableRotateAndCrop, 1);
+        settings->releaseData();
+        camera_metadata_t *metaBuffer = requestMeta.release();
+        settings->setToExternal(reinterpret_cast<uint8_t *> (metaBuffer),
+                get_camera_metadata_size(metaBuffer), true);
+    }
+}
+
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(CameraHidlTest);
 INSTANTIATE_TEST_SUITE_P(
         PerInstance, CameraHidlTest,
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index b65b159..6967671 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -131,14 +131,6 @@
             <instance>default</instance>
         </interface>
     </hal>
-    <hal format="hidl" optional="true">
-        <name>android.hardware.bluetooth.audio</name>
-        <version>2.0-2</version>
-        <interface>
-            <name>IBluetoothAudioProvidersFactory</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
     <hal format="aidl" optional="true">
         <name>android.hardware.bluetooth.audio</name>
         <interface>
@@ -456,6 +448,14 @@
         </interface>
     </hal>
     <hal format="aidl" optional="true">
+        <name>android.hardware.radio.config</name>
+        <version>1</version>
+        <interface>
+            <name>IRadioConfig</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="aidl" optional="true">
         <name>android.hardware.radio.data</name>
         <version>1</version>
         <interface>
@@ -517,16 +517,6 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.radio</name>
-        <version>1.6</version>
-        <interface>
-            <name>IRadio</name>
-            <instance>slot1</instance>
-            <instance>slot2</instance>
-            <instance>slot3</instance>
-        </interface>
-    </hal>
-    <hal format="hidl" optional="true">
-        <name>android.hardware.radio</name>
         <version>1.2</version>
         <interface>
             <name>ISap</name>
@@ -534,33 +524,6 @@
         </interface>
     </hal>
     <hal format="hidl" optional="true">
-        <name>android.hardware.radio.config</name>
-        <!--
-        See compatibility_matrix.4.xml on versioning of radio config HAL.
-        -->
-        <version>1.1</version>
-        <interface>
-            <name>IRadioConfig</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="aidl" optional="true">
-        <name>android.hardware.radio.config</name>
-        <version>1</version>
-        <interface>
-            <name>IRadioConfig</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="hidl" optional="true">
-        <name>android.hardware.radio.config</name>
-        <version>1.3</version>
-        <interface>
-            <name>IRadioConfig</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="hidl" optional="true">
         <name>android.hardware.renderscript</name>
         <version>1.0</version>
         <interface>
diff --git a/current.txt b/current.txt
index 7718b98..6a77e19 100644
--- a/current.txt
+++ b/current.txt
@@ -901,6 +901,9 @@
 4a087a308608d146b022ebc15633de989f5f4dfe1491a83fa41763290a82e40d android.hardware.automotive.vehicle@2.0::types
 70eb14415391f835fb218b43a1e25f5d6495f098f96fa2acaea70985e98e1ce8 android.hardware.automotive.vehicle@2.0::types
 
+# HALs released in Android SCv2
+77f6fcf3fd0dd3e424d8a0292094ebd17e4c35454bb9abbd3a6cbed1aba70765 android.hardware.camera.metadata@3.7::types
+
 # ABI preserving changes to HALs during Android T
 62ace52d9c3ff1f60f94118557a2aaf0b953513e59dcd34d5f94ae28d4c7e780 android.hardware.fastboot@1.0::IFastboot
 d0fb32f3ddeb9af7115ab32905225ea69b930d2472be8e9610f0cf136c15aefb android.hardware.keymaster@4.0::IKeymasterDevice # b/210424594
diff --git a/drm/1.0/vts/functional/Android.bp b/drm/1.0/vts/functional/Android.bp
index 5ea6ad3..8ca6a65 100644
--- a/drm/1.0/vts/functional/Android.bp
+++ b/drm/1.0/vts/functional/Android.bp
@@ -44,6 +44,10 @@
     local_include_dirs: [
         "include",
     ],
+    tidy_timeout_srcs: [
+        "drm_hal_clearkey_test.cpp",
+        "drm_hal_vendor_test.cpp",
+    ],
     srcs: [
         "drm_hal_clearkey_test.cpp",
         "drm_hal_vendor_test.cpp",
diff --git a/drm/1.1/vts/functional/Android.bp b/drm/1.1/vts/functional/Android.bp
index 656ec50..760b67e 100644
--- a/drm/1.1/vts/functional/Android.bp
+++ b/drm/1.1/vts/functional/Android.bp
@@ -32,6 +32,9 @@
     local_include_dirs: [
         "include",
     ],
+    tidy_timeout_srcs: [
+        "drm_hal_clearkey_test.cpp",
+    ],
     srcs: [
         "drm_hal_clearkey_test.cpp",
     ],
diff --git a/drm/1.2/vts/functional/Android.bp b/drm/1.2/vts/functional/Android.bp
index ca90ee9..dd22ebe 100644
--- a/drm/1.2/vts/functional/Android.bp
+++ b/drm/1.2/vts/functional/Android.bp
@@ -29,6 +29,9 @@
     local_include_dirs: [
         "include",
     ],
+    tidy_timeout_srcs: [
+        "drm_hal_test.cpp",
+    ],
     srcs: [
         "drm_hal_clearkey_module.cpp",
         "drm_hal_common.cpp",
diff --git a/drm/aidl/OWNERS b/drm/aidl/OWNERS
new file mode 100644
index 0000000..fa8fd20
--- /dev/null
+++ b/drm/aidl/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 49079
+edwinwong@google.com
+kelzhan@google.com
+robertshih@google.com
diff --git a/graphics/composer/2.1/vts/functional/Android.bp b/graphics/composer/2.1/vts/functional/Android.bp
index eb67d34..9ffd7d5 100644
--- a/graphics/composer/2.1/vts/functional/Android.bp
+++ b/graphics/composer/2.1/vts/functional/Android.bp
@@ -26,6 +26,7 @@
 cc_test {
     name: "VtsHalGraphicsComposerV2_1TargetTest",
     defaults: ["VtsHalTargetTestDefaults"],
+    tidy_timeout_srcs: ["VtsHalGraphicsComposerV2_1TargetTest.cpp"],
     srcs: ["VtsHalGraphicsComposerV2_1TargetTest.cpp"],
 
     // TODO(b/64437680): Assume these libs are always available on the device.
diff --git a/graphics/composer/2.2/vts/functional/Android.bp b/graphics/composer/2.2/vts/functional/Android.bp
index 36f3c00..e45696d 100644
--- a/graphics/composer/2.2/vts/functional/Android.bp
+++ b/graphics/composer/2.2/vts/functional/Android.bp
@@ -30,6 +30,10 @@
         // Needed for librenderengine
         "skia_deps",
     ],
+    tidy_timeout_srcs: [
+        "VtsHalGraphicsComposerV2_2ReadbackTest.cpp",
+        "VtsHalGraphicsComposerV2_2TargetTest.cpp",
+    ],
     srcs: [
         "VtsHalGraphicsComposerV2_2ReadbackTest.cpp",
         "VtsHalGraphicsComposerV2_2TargetTest.cpp",
diff --git a/graphics/composer/2.3/vts/functional/Android.bp b/graphics/composer/2.3/vts/functional/Android.bp
index d27a151..70384ac 100644
--- a/graphics/composer/2.3/vts/functional/Android.bp
+++ b/graphics/composer/2.3/vts/functional/Android.bp
@@ -26,6 +26,7 @@
 cc_test {
     name: "VtsHalGraphicsComposerV2_3TargetTest",
     defaults: ["VtsHalTargetTestDefaults"],
+    tidy_timeout_srcs: ["VtsHalGraphicsComposerV2_3TargetTest.cpp"],
     srcs: ["VtsHalGraphicsComposerV2_3TargetTest.cpp"],
 
     // TODO(b/64437680): Assume these libs are always available on the device.
diff --git a/graphics/composer/2.4/vts/functional/Android.bp b/graphics/composer/2.4/vts/functional/Android.bp
index 6089e2d..22ae7c4 100644
--- a/graphics/composer/2.4/vts/functional/Android.bp
+++ b/graphics/composer/2.4/vts/functional/Android.bp
@@ -26,6 +26,7 @@
 cc_test {
     name: "VtsHalGraphicsComposerV2_4TargetTest",
     defaults: ["VtsHalTargetTestDefaults"],
+    tidy_timeout_srcs: ["VtsHalGraphicsComposerV2_4TargetTest.cpp"],
     srcs: ["VtsHalGraphicsComposerV2_4TargetTest.cpp"],
 
     // TODO(b/64437680): Assume these libs are always available on the device.
diff --git a/health/2.0/vts/functional/Android.bp b/health/2.0/vts/functional/Android.bp
index 0fcac19..597fb50 100644
--- a/health/2.0/vts/functional/Android.bp
+++ b/health/2.0/vts/functional/Android.bp
@@ -26,6 +26,7 @@
 cc_test {
     name: "VtsHalHealthV2_0TargetTest",
     defaults: ["VtsHalTargetTestDefaults"],
+    tidy_timeout_srcs: ["VtsHalHealthV2_0TargetTest.cpp"],
     srcs: ["VtsHalHealthV2_0TargetTest.cpp"],
     static_libs: [
         "libgflags",
diff --git a/health/aidl/default/Health.cpp b/health/aidl/default/Health.cpp
index e1d1982..d41d01a 100644
--- a/health/aidl/default/Health.cpp
+++ b/health/aidl/default/Health.cpp
@@ -130,12 +130,7 @@
 ndk::ScopedAStatus Health::getHealthInfo(HealthInfo* out) {
     battery_monitor_.updateValues();
 
-    // TODO(b/177269435): BatteryMonitor should store AIDL HealthInfo instead.
-    auto health_info_2_1 = battery_monitor_.getHealthInfo_2_1();
-    if (!::android::h2a::translate(health_info_2_1, out)) {
-        return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
-                IHealth::STATUS_UNKNOWN, "Cannot translate HIDL HealthInfo to AIDL");
-    }
+    *out = battery_monitor_.getHealthInfo();
 
     // Fill in storage infos; these aren't retrieved by BatteryMonitor.
     if (auto res = getStorageInfo(&out->storageInfos); !res.isOk()) {
diff --git a/health/aidl/vts/functional/Android.bp b/health/aidl/vts/functional/Android.bp
index d315c60..f9da79f 100644
--- a/health/aidl/vts/functional/Android.bp
+++ b/health/aidl/vts/functional/Android.bp
@@ -29,6 +29,9 @@
         "VtsHalTargetTestDefaults",
         "use_libaidlvintf_gtest_helper_static",
     ],
+    tidy_timeout_srcs: [
+        "VtsHalHealthTargetTest.cpp",
+    ],
     srcs: [
         "VtsHalHealthTargetTest.cpp",
     ],
diff --git a/health/utils/libhealthshim/Android.bp b/health/utils/libhealthshim/Android.bp
index 42e4ea7..3a1415f 100644
--- a/health/utils/libhealthshim/Android.bp
+++ b/health/utils/libhealthshim/Android.bp
@@ -70,6 +70,9 @@
         "libhealthshim",
         "libgmock",
     ],
+    tidy_timeout_srcs: [
+        "test.cpp",
+    ],
     srcs: [
         "test.cpp",
     ],
diff --git a/identity/support/Android.bp b/identity/support/Android.bp
index db1a945..4e3d1f7 100644
--- a/identity/support/Android.bp
+++ b/identity/support/Android.bp
@@ -86,6 +86,9 @@
 
 cc_test {
     name: "cppbor_test",
+    tidy_timeout_srcs: [
+        "tests/cppbor_test.cpp",
+    ],
     srcs: [
         "tests/cppbor_test.cpp",
     ],
@@ -101,6 +104,9 @@
 
 cc_test_host {
     name: "cppbor_host_test",
+    tidy_timeout_srcs: [
+        "tests/cppbor_test.cpp",
+    ],
     srcs: [
         "tests/cppbor_test.cpp",
     ],
diff --git a/identity/support/include/android/hardware/identity/support/IdentityCredentialSupport.h b/identity/support/include/android/hardware/identity/support/IdentityCredentialSupport.h
index 82746d6..952b69a 100644
--- a/identity/support/include/android/hardware/identity/support/IdentityCredentialSupport.h
+++ b/identity/support/include/android/hardware/identity/support/IdentityCredentialSupport.h
@@ -407,6 +407,10 @@
 // may be smaller than |maxChunkSize|.
 vector<vector<uint8_t>> chunkVector(const vector<uint8_t>& content, size_t maxChunkSize);
 
+// Extract the issuer subject name from the leaf cert in the given chain,
+// returning it as DER-encoded bytes.
+optional<vector<uint8_t>> extractDerSubjectFromCertificate(const vector<uint8_t>& certificate);
+
 }  // namespace support
 }  // namespace identity
 }  // namespace hardware
diff --git a/identity/support/src/IdentityCredentialSupport.cpp b/identity/support/src/IdentityCredentialSupport.cpp
index 36ecdb0..4c2f186 100644
--- a/identity/support/src/IdentityCredentialSupport.cpp
+++ b/identity/support/src/IdentityCredentialSupport.cpp
@@ -209,38 +209,6 @@
     return keyPair;
 }
 
-// Extract the issuer subject name from the leaf cert in the given chain,
-// returning it as DER-encoded bytes.
-optional<vector<uint8_t>> extractDerSubjectFromCertificate(const vector<uint8_t>& certificate) {
-    const uint8_t* input = certificate.data();
-    X509_Ptr cert(d2i_X509(/*cert=*/nullptr, &input, certificate.size()));
-    if (!cert) {
-        LOG(ERROR) << "Failed to parse certificate";
-        return std::nullopt;
-    }
-
-    X509_NAME* subject = X509_get_subject_name(cert.get());
-    if (!subject) {
-        LOG(ERROR) << "Failed to retrieve subject name";
-        return std::nullopt;
-    }
-
-    int encodedSubjectLength = i2d_X509_NAME(subject, /*out=*/nullptr);
-    if (encodedSubjectLength < 0) {
-        LOG(ERROR) << "Error obtaining encoded subject name length";
-        return std::nullopt;
-    }
-
-    vector<uint8_t> encodedSubject(encodedSubjectLength);
-    uint8_t* out = encodedSubject.data();
-    if (encodedSubjectLength != i2d_X509_NAME(subject, &out)) {
-        LOG(ERROR) << "Error encoding subject name";
-        return std::nullopt;
-    }
-
-    return encodedSubject;
-}
-
 // Generates the attestation certificate with the parameters passed in.  Note
 // that the passed in |activeTimeMilliSeconds| |expireTimeMilliSeconds| are in
 // milli seconds since epoch.  We are setting them to milliseconds due to
@@ -900,7 +868,7 @@
     }
 
     optional<vector<uint8_t>> derIssuerSubject =
-            extractDerSubjectFromCertificate(attestationKeyCert);
+            support::extractDerSubjectFromCertificate(attestationKeyCert);
     if (!derIssuerSubject) {
         LOG(ERROR) << "Error error extracting issuer name from the given certificate chain";
         return std::nullopt;
@@ -2325,6 +2293,36 @@
     return testHardwareBoundKey;
 }
 
+optional<vector<uint8_t>> extractDerSubjectFromCertificate(const vector<uint8_t>& certificate) {
+    const uint8_t* input = certificate.data();
+    X509_Ptr cert(d2i_X509(/*cert=*/nullptr, &input, certificate.size()));
+    if (!cert) {
+        LOG(ERROR) << "Failed to parse certificate";
+        return std::nullopt;
+    }
+
+    X509_NAME* subject = X509_get_subject_name(cert.get());
+    if (!subject) {
+        LOG(ERROR) << "Failed to retrieve subject name";
+        return std::nullopt;
+    }
+
+    int encodedSubjectLength = i2d_X509_NAME(subject, /*out=*/nullptr);
+    if (encodedSubjectLength < 0) {
+        LOG(ERROR) << "Error obtaining encoded subject name length";
+        return std::nullopt;
+    }
+
+    vector<uint8_t> encodedSubject(encodedSubjectLength);
+    uint8_t* out = encodedSubject.data();
+    if (encodedSubjectLength != i2d_X509_NAME(subject, &out)) {
+        LOG(ERROR) << "Error encoding subject name";
+        return std::nullopt;
+    }
+
+    return encodedSubject;
+}
+
 }  // namespace support
 }  // namespace identity
 }  // namespace hardware
diff --git a/keymaster/3.0/vts/OWNERS b/keymaster/3.0/vts/OWNERS
index 376c12b..846bb84 100644
--- a/keymaster/3.0/vts/OWNERS
+++ b/keymaster/3.0/vts/OWNERS
@@ -1,3 +1,4 @@
+drysdale@google.com
 jdanis@google.com
 swillden@google.com
 yim@google.com
diff --git a/keymaster/3.0/vts/functional/Android.bp b/keymaster/3.0/vts/functional/Android.bp
index 39bec3f..fde32a7 100644
--- a/keymaster/3.0/vts/functional/Android.bp
+++ b/keymaster/3.0/vts/functional/Android.bp
@@ -26,6 +26,9 @@
 cc_test {
     name: "VtsHalKeymasterV3_0TargetTest",
     defaults: ["VtsHalTargetTestDefaults"],
+    tidy_timeout_srcs: [
+        "keymaster_hidl_hal_test.cpp",
+    ],
     srcs: [
         "authorization_set.cpp",
         "attestation_record.cpp",
diff --git a/keymaster/4.0/vts/OWNERS b/keymaster/4.0/vts/OWNERS
index abfb2e0..0d6fa6c 100644
--- a/keymaster/4.0/vts/OWNERS
+++ b/keymaster/4.0/vts/OWNERS
@@ -1,3 +1,4 @@
+drysdale@google.com
 jbires@google.com
 jdanis@google.com
 swillden@google.com
diff --git a/keymaster/4.0/vts/functional/Android.bp b/keymaster/4.0/vts/functional/Android.bp
index 8e5a0ff..f9a02ba 100644
--- a/keymaster/4.0/vts/functional/Android.bp
+++ b/keymaster/4.0/vts/functional/Android.bp
@@ -26,6 +26,9 @@
 cc_test {
     name: "VtsHalKeymasterV4_0TargetTest",
     defaults: ["VtsHalTargetTestDefaults"],
+    tidy_timeout_srcs: [
+        "keymaster_hidl_hal_test.cpp",
+    ],
     srcs: [
         "HmacKeySharingTest.cpp",
         "VerificationTokenTest.cpp",
@@ -50,6 +53,9 @@
 cc_test_library {
     name: "libkeymaster4vtstest",
     defaults: ["VtsHalTargetTestDefaults"],
+    tidy_timeout_srcs: [
+        "KeymasterHidlTest.cpp",
+    ],
     srcs: [
         "KeymasterHidlTest.cpp",
     ],
diff --git a/keymaster/4.0/vts/functional/KeymasterHidlTest.cpp b/keymaster/4.0/vts/functional/KeymasterHidlTest.cpp
index d0ad433..315a4bd 100644
--- a/keymaster/4.0/vts/functional/KeymasterHidlTest.cpp
+++ b/keymaster/4.0/vts/functional/KeymasterHidlTest.cpp
@@ -443,6 +443,101 @@
         AuthorizationSetBuilder().Digest(digest).Authorization(TAG_MAC_LENGTH, mac_length));
 }
 
+void KeymasterHidlTest::CheckAesIncrementalEncryptOperation(BlockMode block_mode,
+                                                            int message_size) {
+    auto builder = AuthorizationSetBuilder()
+                           .Authorization(TAG_NO_AUTH_REQUIRED)
+                           .AesEncryptionKey(128)
+                           .BlockMode(block_mode)
+                           .Padding(PaddingMode::NONE);
+    if (block_mode == BlockMode::GCM) {
+        builder.Authorization(TAG_MIN_MAC_LENGTH, 128);
+    }
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(builder));
+
+    for (int increment = 1; increment <= message_size; ++increment) {
+        string message(message_size, 'a');
+        auto params = AuthorizationSetBuilder()
+                              .BlockMode(block_mode)
+                              .Padding(PaddingMode::NONE)
+                              .Authorization(TAG_MAC_LENGTH, 128) /* for GCM */;
+
+        AuthorizationSet output_params;
+        EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params, &output_params));
+
+        string ciphertext;
+        size_t input_consumed;
+        string to_send;
+        for (size_t i = 0; i < message.size(); i += increment) {
+            to_send.append(message.substr(i, increment));
+            EXPECT_EQ(ErrorCode::OK, Update(to_send, &ciphertext, &input_consumed));
+            EXPECT_EQ(to_send.length(), input_consumed);
+            to_send = to_send.substr(input_consumed);
+            EXPECT_EQ(0U, to_send.length());
+
+            switch (block_mode) {
+                case BlockMode::ECB:
+                case BlockMode::CBC:
+                    // Implementations must take as many blocks as possible, leaving less than
+                    // a block.
+                    EXPECT_LE(to_send.length(), 16U);
+                    break;
+                case BlockMode::GCM:
+                case BlockMode::CTR:
+                    // Implementations must always take all the data.
+                    EXPECT_EQ(0U, to_send.length());
+                    break;
+            }
+        }
+        EXPECT_EQ(ErrorCode::OK, Finish(to_send, &ciphertext)) << "Error sending " << to_send;
+
+        switch (block_mode) {
+            case BlockMode::GCM:
+                EXPECT_EQ(message.size() + 16, ciphertext.size());
+                break;
+            case BlockMode::CTR:
+                EXPECT_EQ(message.size(), ciphertext.size());
+                break;
+            case BlockMode::CBC:
+            case BlockMode::ECB:
+                EXPECT_EQ(message.size() + message.size() % 16, ciphertext.size());
+                break;
+        }
+
+        auto iv = output_params.GetTagValue(TAG_NONCE);
+        switch (block_mode) {
+            case BlockMode::CBC:
+            case BlockMode::GCM:
+            case BlockMode::CTR:
+                ASSERT_TRUE(iv.isOk()) << "No IV for block mode " << block_mode;
+                EXPECT_EQ(block_mode == BlockMode::GCM ? 12U : 16U, iv.value().size());
+                params.push_back(TAG_NONCE, iv.value());
+                break;
+
+            case BlockMode::ECB:
+                EXPECT_FALSE(iv.isOk()) << "ECB mode should not generate IV";
+                break;
+        }
+
+        EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, params))
+                << "Decrypt begin() failed for block mode " << block_mode;
+
+        string plaintext;
+        for (size_t i = 0; i < ciphertext.size(); i += increment) {
+            to_send.append(ciphertext.substr(i, increment));
+            EXPECT_EQ(ErrorCode::OK, Update(to_send, &plaintext, &input_consumed));
+            to_send = to_send.substr(input_consumed);
+        }
+        ErrorCode error = Finish(to_send, &plaintext);
+        ASSERT_EQ(ErrorCode::OK, error) << "Decryption failed for block mode " << block_mode
+                                        << " and increment " << increment;
+        if (error == ErrorCode::OK) {
+            ASSERT_EQ(message, plaintext) << "Decryption didn't match for block mode " << block_mode
+                                          << " and increment " << increment;
+        }
+    }
+}
+
 void KeymasterHidlTest::CheckHmacTestVector(const string& key, const string& message, Digest digest,
                                             const string& expected_mac) {
     SCOPED_TRACE("CheckHmacTestVector");
diff --git a/keymaster/4.0/vts/functional/KeymasterHidlTest.h b/keymaster/4.0/vts/functional/KeymasterHidlTest.h
index 2ca7ea7..ad30aa7 100644
--- a/keymaster/4.0/vts/functional/KeymasterHidlTest.h
+++ b/keymaster/4.0/vts/functional/KeymasterHidlTest.h
@@ -166,6 +166,8 @@
 
     string MacMessage(const string& message, Digest digest, size_t mac_length);
 
+    void CheckAesIncrementalEncryptOperation(BlockMode block_mode, int message_size);
+
     void CheckHmacTestVector(const string& key, const string& message, Digest digest,
                              const string& expected_mac);
 
diff --git a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
index 2ff33b0..14c756d 100644
--- a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
+++ b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
@@ -2932,105 +2932,39 @@
 }
 
 /*
- * EncryptionOperationsTest.AesIncremental
+ * EncryptionOperationsTest.AesEcbIncremental
  *
- * Verifies that AES works, all modes, when provided data in various size increments.
+ * Verifies that AES works for ECB block mode, when provided data in various size increments.
  */
-TEST_P(EncryptionOperationsTest, AesIncremental) {
-    auto block_modes = {
-        BlockMode::ECB, BlockMode::CBC, BlockMode::CTR, BlockMode::GCM,
-    };
+TEST_P(EncryptionOperationsTest, AesEcbIncremental) {
+    CheckAesIncrementalEncryptOperation(BlockMode::ECB, 240);
+}
 
-    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
-                                             .Authorization(TAG_NO_AUTH_REQUIRED)
-                                             .AesEncryptionKey(128)
-                                             .BlockMode(block_modes)
-                                             .Padding(PaddingMode::NONE)
-                                             .Authorization(TAG_MIN_MAC_LENGTH, 128)));
+/*
+ * EncryptionOperationsTest.AesCbcIncremental
+ *
+ * Verifies that AES works for CBC block mode, when provided data in various size increments.
+ */
+TEST_P(EncryptionOperationsTest, AesCbcIncremental) {
+    CheckAesIncrementalEncryptOperation(BlockMode::CBC, 240);
+}
 
-    for (int increment = 1; increment <= 240; ++increment) {
-        for (auto block_mode : block_modes) {
-            string message(240, 'a');
-            auto params = AuthorizationSetBuilder()
-                              .BlockMode(block_mode)
-                              .Padding(PaddingMode::NONE)
-                              .Authorization(TAG_MAC_LENGTH, 128) /* for GCM */;
+/*
+ * EncryptionOperationsTest.AesCtrIncremental
+ *
+ * Verifies that AES works for CTR block mode, when provided data in various size increments.
+ */
+TEST_P(EncryptionOperationsTest, AesCtrIncremental) {
+    CheckAesIncrementalEncryptOperation(BlockMode::CTR, 240);
+}
 
-            AuthorizationSet output_params;
-            EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params, &output_params));
-
-            string ciphertext;
-            size_t input_consumed;
-            string to_send;
-            for (size_t i = 0; i < message.size(); i += increment) {
-                to_send.append(message.substr(i, increment));
-                EXPECT_EQ(ErrorCode::OK, Update(to_send, &ciphertext, &input_consumed));
-                EXPECT_EQ(to_send.length(), input_consumed);
-                to_send = to_send.substr(input_consumed);
-                EXPECT_EQ(0U, to_send.length());
-
-                switch (block_mode) {
-                    case BlockMode::ECB:
-                    case BlockMode::CBC:
-                        // Implementations must take as many blocks as possible, leaving less than
-                        // a block.
-                        EXPECT_LE(to_send.length(), 16U);
-                        break;
-                    case BlockMode::GCM:
-                    case BlockMode::CTR:
-                        // Implementations must always take all the data.
-                        EXPECT_EQ(0U, to_send.length());
-                        break;
-                }
-            }
-            EXPECT_EQ(ErrorCode::OK, Finish(to_send, &ciphertext)) << "Error sending " << to_send;
-
-            switch (block_mode) {
-                case BlockMode::GCM:
-                    EXPECT_EQ(message.size() + 16, ciphertext.size());
-                    break;
-                case BlockMode::CTR:
-                    EXPECT_EQ(message.size(), ciphertext.size());
-                    break;
-                case BlockMode::CBC:
-                case BlockMode::ECB:
-                    EXPECT_EQ(message.size() + message.size() % 16, ciphertext.size());
-                    break;
-            }
-
-            auto iv = output_params.GetTagValue(TAG_NONCE);
-            switch (block_mode) {
-                case BlockMode::CBC:
-                case BlockMode::GCM:
-                case BlockMode::CTR:
-                    ASSERT_TRUE(iv.isOk()) << "No IV for block mode " << block_mode;
-                    EXPECT_EQ(block_mode == BlockMode::GCM ? 12U : 16U, iv.value().size());
-                    params.push_back(TAG_NONCE, iv.value());
-                    break;
-
-                case BlockMode::ECB:
-                    EXPECT_FALSE(iv.isOk()) << "ECB mode should not generate IV";
-                    break;
-            }
-
-            EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, params))
-                << "Decrypt begin() failed for block mode " << block_mode;
-
-            string plaintext;
-            for (size_t i = 0; i < ciphertext.size(); i += increment) {
-                to_send.append(ciphertext.substr(i, increment));
-                EXPECT_EQ(ErrorCode::OK, Update(to_send, &plaintext, &input_consumed));
-                to_send = to_send.substr(input_consumed);
-            }
-            ErrorCode error = Finish(to_send, &plaintext);
-            ASSERT_EQ(ErrorCode::OK, error) << "Decryption failed for block mode " << block_mode
-                                            << " and increment " << increment;
-            if (error == ErrorCode::OK) {
-                ASSERT_EQ(message, plaintext) << "Decryption didn't match for block mode "
-                                              << block_mode << " and increment " << increment;
-            }
-        }
-    }
+/*
+ * EncryptionOperationsTest.AesGcmIncremental
+ *
+ * Verifies that AES works for GCM block mode, when provided data in various size increments.
+ */
+TEST_P(EncryptionOperationsTest, AesGcmIncremental) {
+    CheckAesIncrementalEncryptOperation(BlockMode::GCM, 240);
 }
 
 struct AesCtrSp80038aTestVector {
diff --git a/keymaster/4.1/vts/OWNERS b/keymaster/4.1/vts/OWNERS
index 2b2ad2a..24ed042 100644
--- a/keymaster/4.1/vts/OWNERS
+++ b/keymaster/4.1/vts/OWNERS
@@ -1,3 +1,4 @@
+drysdale@google.com
 jbires@google.com
 jdanis@google.com
 swillden@google.com
diff --git a/media/omx/1.0/vts/functional/component/Android.bp b/media/omx/1.0/vts/functional/component/Android.bp
index 9d4d092..7b8ec9d 100644
--- a/media/omx/1.0/vts/functional/component/Android.bp
+++ b/media/omx/1.0/vts/functional/component/Android.bp
@@ -26,6 +26,7 @@
 cc_test {
     name: "VtsHalMediaOmxV1_0TargetComponentTest",
     defaults: ["VtsHalMediaOmxV1_0Defaults"],
+    tidy_timeout_srcs: ["VtsHalMediaOmxV1_0TargetComponentTest.cpp"],
     srcs: ["VtsHalMediaOmxV1_0TargetComponentTest.cpp"],
     test_suites: [
         "vts",
diff --git a/media/omx/1.0/vts/functional/store/VtsHalMediaOmxV1_0TargetStoreTest.cpp b/media/omx/1.0/vts/functional/store/VtsHalMediaOmxV1_0TargetStoreTest.cpp
index 8699de3..d9a6363 100644
--- a/media/omx/1.0/vts/functional/store/VtsHalMediaOmxV1_0TargetStoreTest.cpp
+++ b/media/omx/1.0/vts/functional/store/VtsHalMediaOmxV1_0TargetStoreTest.cpp
@@ -20,7 +20,9 @@
 #endif
 
 #include <android-base/logging.h>
+#include <android-base/properties.h>
 #include <android-base/strings.h>
+#include <android/api-level.h>
 
 #include <android/hardware/media/omx/1.0/IOmx.h>
 #include <android/hardware/media/omx/1.0/IOmxNode.h>
@@ -371,6 +373,31 @@
     }
 }
 
+static int getFirstApiLevel() {
+    return android::base::GetIntProperty("ro.product.first_api_level", __ANDROID_API_T__);
+}
+
+// list components and roles.
+TEST_P(StoreHidlTest, OmxCodecAllowedTest) {
+    hidl_vec<IOmx::ComponentInfo> componentInfos = getComponentInfoList(omx);
+    for (IOmx::ComponentInfo info : componentInfos) {
+        for (std::string role : info.mRoles) {
+            if (role.find("video_decoder") != std::string::npos ||
+                role.find("video_encoder") != std::string::npos) {
+                ASSERT_LT(getFirstApiLevel(), __ANDROID_API_S__)
+                        << " Component: " << info.mName.c_str() << " Role: " << role.c_str()
+                        << " not allowed for devices launching with Android S and above";
+            }
+            if (role.find("audio_decoder") != std::string::npos ||
+                role.find("audio_encoder") != std::string::npos) {
+                ASSERT_LT(getFirstApiLevel(), __ANDROID_API_T__)
+                        << " Component: " << info.mName.c_str() << " Role: " << role.c_str()
+                        << " not allowed for devices launching with Android T and above";
+            }
+        }
+    }
+}
+
 // list components and roles.
 TEST_P(StoreHidlTest, ListNodes) {
     description("enumerate component and roles");
diff --git a/neuralnetworks/1.2/utils/Android.bp b/neuralnetworks/1.2/utils/Android.bp
index 4c5f065..e7d514f 100644
--- a/neuralnetworks/1.2/utils/Android.bp
+++ b/neuralnetworks/1.2/utils/Android.bp
@@ -45,21 +45,15 @@
             cflags: ["-DNN_DEBUGGABLE"],
         },
     },
-    target: {
-        host: {
-            cflags: [
-                "-D__INTRODUCED_IN(x)=",
-                "-D__assert(a,b,c)=",
-                // We want all the APIs to be available on the host.
-                "-D__ANDROID_API__=10000",
-            ],
-        },
-    },
 }
 
 cc_test {
     name: "neuralnetworks_utils_hal_1_2_test",
     host_supported: true,
+    tidy_timeout_srcs: [
+        "test/DeviceTest.cpp",
+        "test/PreparedModelTest.cpp",
+    ],
     srcs: ["test/*.cpp"],
     static_libs: [
         "android.hardware.neuralnetworks@1.0",
diff --git a/neuralnetworks/1.2/vts/functional/Android.bp b/neuralnetworks/1.2/vts/functional/Android.bp
index 52d51e2..2177924 100644
--- a/neuralnetworks/1.2/vts/functional/Android.bp
+++ b/neuralnetworks/1.2/vts/functional/Android.bp
@@ -44,6 +44,9 @@
 cc_test {
     name: "VtsHalNeuralnetworksV1_2TargetTest",
     defaults: ["neuralnetworks_vts_functional_defaults"],
+    tidy_timeout_srcs: [
+        "CompilationCachingTests.cpp",
+    ],
     srcs: [
         "BasicTests.cpp",
         "CompilationCachingTests.cpp",
diff --git a/neuralnetworks/1.3/utils/Android.bp b/neuralnetworks/1.3/utils/Android.bp
index c512dda..05413e6 100644
--- a/neuralnetworks/1.3/utils/Android.bp
+++ b/neuralnetworks/1.3/utils/Android.bp
@@ -42,21 +42,15 @@
         "neuralnetworks_utils_hal_1_1",
         "neuralnetworks_utils_hal_1_2",
     ],
-    target: {
-        host: {
-            cflags: [
-                "-D__INTRODUCED_IN(x)=",
-                "-D__assert(a,b,c)=",
-                // We want all the APIs to be available on the host.
-                "-D__ANDROID_API__=10000",
-            ],
-        },
-    },
 }
 
 cc_test {
     name: "neuralnetworks_utils_hal_1_3_test",
     host_supported: true,
+    tidy_timeout_srcs: [
+        "test/DeviceTest.cpp",
+        "test/PreparedModelTest.cpp",
+    ],
     srcs: ["test/*.cpp"],
     static_libs: [
         "android.hardware.neuralnetworks@1.0",
diff --git a/neuralnetworks/1.3/vts/functional/Android.bp b/neuralnetworks/1.3/vts/functional/Android.bp
index 8951760..9fa0f0a 100644
--- a/neuralnetworks/1.3/vts/functional/Android.bp
+++ b/neuralnetworks/1.3/vts/functional/Android.bp
@@ -45,6 +45,10 @@
 cc_test {
     name: "VtsHalNeuralnetworksV1_3TargetTest",
     defaults: ["neuralnetworks_vts_functional_defaults"],
+    tidy_timeout_srcs: [
+        "CompilationCachingTests.cpp",
+        "MemoryDomainTests.cpp",
+    ],
     srcs: [
         "BasicTests.cpp",
         "CompilationCachingTests.cpp",
diff --git a/neuralnetworks/aidl/utils/Android.bp b/neuralnetworks/aidl/utils/Android.bp
index 41eae85..2b7b787 100644
--- a/neuralnetworks/aidl/utils/Android.bp
+++ b/neuralnetworks/aidl/utils/Android.bp
@@ -105,6 +105,10 @@
         "neuralnetworks_use_latest_utils_hal_aidl",
         "neuralnetworks_utils_defaults",
     ],
+    tidy_timeout_srcs: [
+        "test/DeviceTest.cpp",
+        "test/PreparedModelTest.cpp",
+    ],
     srcs: [
         "test/*.cpp",
     ],
@@ -123,14 +127,6 @@
         android: {
             shared_libs: ["libnativewindow"],
         },
-        host: {
-            cflags: [
-                "-D__INTRODUCED_IN(x)=",
-                "-D__assert(a,b,c)=",
-                // We want all the APIs to be available on the host.
-                "-D__ANDROID_API__=10000",
-            ],
-        },
     },
     cflags: [
         /* GMOCK defines functions for printing all MOCK_DEVICE arguments and
diff --git a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Utils.h b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Utils.h
index beca38b..7ed5437 100644
--- a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Utils.h
+++ b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Utils.h
@@ -26,6 +26,8 @@
 #include <nnapi/Types.h>
 #include <nnapi/Validation.h>
 
+#include <type_traits>
+
 namespace aidl::android::hardware::neuralnetworks::utils {
 
 constexpr auto kDefaultPriority = Priority::MEDIUM;
@@ -80,6 +82,11 @@
     return convert(NN_TRY(nn::convert(nonCanonicalObject)));
 }
 
+template <typename Type>
+constexpr std::underlying_type_t<Type> underlyingType(Type value) {
+    return static_cast<std::underlying_type_t<Type>>(value);
+}
+
 nn::GeneralResult<Memory> clone(const Memory& memory);
 nn::GeneralResult<Request> clone(const Request& request);
 nn::GeneralResult<RequestMemoryPool> clone(const RequestMemoryPool& requestPool);
diff --git a/neuralnetworks/aidl/utils/src/Conversions.cpp b/neuralnetworks/aidl/utils/src/Conversions.cpp
index 83fda10..081e3d7 100644
--- a/neuralnetworks/aidl/utils/src/Conversions.cpp
+++ b/neuralnetworks/aidl/utils/src/Conversions.cpp
@@ -57,10 +57,6 @@
     while (UNLIKELY(value > std::numeric_limits<int32_t>::max())) return NN_ERROR()
 
 namespace {
-template <typename Type>
-constexpr std::underlying_type_t<Type> underlyingType(Type value) {
-    return static_cast<std::underlying_type_t<Type>>(value);
-}
 
 constexpr int64_t kNoTiming = -1;
 
@@ -70,6 +66,7 @@
 namespace {
 
 using ::aidl::android::hardware::common::NativeHandle;
+using ::aidl::android::hardware::neuralnetworks::utils::underlyingType;
 
 template <typename Input>
 using UnvalidatedConvertOutput =
@@ -404,7 +401,7 @@
 #endif  // __ANDROID__
         }
     }
-    return NN_ERROR() << "Unrecognized Memory::Tag: " << memory.getTag();
+    return NN_ERROR() << "Unrecognized Memory::Tag: " << underlyingType(memory.getTag());
 }
 
 GeneralResult<Timing> unvalidatedConvert(const aidl_hal::Timing& timing) {
diff --git a/neuralnetworks/aidl/utils/src/Utils.cpp b/neuralnetworks/aidl/utils/src/Utils.cpp
index 03407be..76a0b07 100644
--- a/neuralnetworks/aidl/utils/src/Utils.cpp
+++ b/neuralnetworks/aidl/utils/src/Utils.cpp
@@ -88,7 +88,7 @@
             return Memory::make<Memory::Tag::hardwareBuffer>(std::move(handle));
         }
     }
-    return (NN_ERROR() << "Unrecognized Memory::Tag: " << memory.getTag())
+    return (NN_ERROR() << "Unrecognized Memory::Tag: " << underlyingType(memory.getTag()))
             .
             operator nn::GeneralResult<Memory>();
 }
@@ -103,7 +103,7 @@
     }
     // Using explicit type conversion because std::variant inside the RequestMemoryPool confuses the
     // compiler.
-    return (NN_ERROR() << "Unrecognized request pool tag: " << requestPool.getTag())
+    return (NN_ERROR() << "Unrecognized request pool tag: " << underlyingType(requestPool.getTag()))
             .
             operator nn::GeneralResult<RequestMemoryPool>();
 }
diff --git a/neuralnetworks/aidl/vts/functional/Android.bp b/neuralnetworks/aidl/vts/functional/Android.bp
index 356cdb0..04b4a45 100644
--- a/neuralnetworks/aidl/vts/functional/Android.bp
+++ b/neuralnetworks/aidl/vts/functional/Android.bp
@@ -31,6 +31,10 @@
         "use_libaidlvintf_gtest_helper_static",
     ],
     host_supported: true,
+    tidy_timeout_srcs: [
+        "CompilationCachingTests.cpp",
+        "MemoryDomainTests.cpp",
+    ],
     srcs: [
         "BasicTests.cpp",
         "Callbacks.cpp",
diff --git a/neuralnetworks/utils/adapter/aidl/include/nnapi/hal/aidl/Adapter.h b/neuralnetworks/utils/adapter/aidl/include/nnapi/hal/aidl/Adapter.h
index 4c0b328..80ed41d 100644
--- a/neuralnetworks/utils/adapter/aidl/include/nnapi/hal/aidl/Adapter.h
+++ b/neuralnetworks/utils/adapter/aidl/include/nnapi/hal/aidl/Adapter.h
@@ -46,9 +46,6 @@
 /**
  * Adapt an NNAPI canonical interface object to a AIDL NN HAL interface object.
  *
- * The IPreparedModel object created from IDevice::prepareModel or IDevice::preparedModelFromCache
- * must return "const nn::Model*" from IPreparedModel::getUnderlyingResource().
- *
  * @param device NNAPI canonical IDevice interface object to be adapted.
  * @param executor Type-erased executor to handle executing tasks asynchronously.
  * @return AIDL NN HAL IDevice interface object.
@@ -58,9 +55,6 @@
 /**
  * Adapt an NNAPI canonical interface object to a AIDL NN HAL interface object.
  *
- * The IPreparedModel object created from IDevice::prepareModel or IDevice::preparedModelFromCache
- * must return "const nn::Model*" from IPreparedModel::getUnderlyingResource().
- *
  * This function uses a default executor, which will execute tasks from a detached thread.
  *
  * @param device NNAPI canonical IDevice interface object to be adapted.
diff --git a/neuralnetworks/utils/adapter/hidl/include/nnapi/hal/Adapter.h b/neuralnetworks/utils/adapter/hidl/include/nnapi/hal/Adapter.h
index 6fba4ab..3bd93e0 100644
--- a/neuralnetworks/utils/adapter/hidl/include/nnapi/hal/Adapter.h
+++ b/neuralnetworks/utils/adapter/hidl/include/nnapi/hal/Adapter.h
@@ -46,9 +46,6 @@
 /**
  * Adapt an NNAPI canonical interface object to a HIDL NN HAL interface object.
  *
- * The IPreparedModel object created from IDevice::prepareModel or IDevice::preparedModelFromCache
- * must return "const nn::Model*" from IPreparedModel::getUnderlyingResource().
- *
  * @param device NNAPI canonical IDevice interface object to be adapted.
  * @param executor Type-erased executor to handle executing tasks asynchronously.
  * @return HIDL NN HAL IDevice interface object.
@@ -58,9 +55,6 @@
 /**
  * Adapt an NNAPI canonical interface object to a HIDL NN HAL interface object.
  *
- * The IPreparedModel object created from IDevice::prepareModel or IDevice::preparedModelFromCache
- * must return "const nn::Model*" from IPreparedModel::getUnderlyingResource().
- *
  * This function uses a default executor, which will execute tasks from a detached thread.
  *
  * @param device NNAPI canonical IDevice interface object to be adapted.
diff --git a/neuralnetworks/utils/adapter/hidl/include/nnapi/hal/PreparedModel.h b/neuralnetworks/utils/adapter/hidl/include/nnapi/hal/PreparedModel.h
index 9482b0d..01cd4bc 100644
--- a/neuralnetworks/utils/adapter/hidl/include/nnapi/hal/PreparedModel.h
+++ b/neuralnetworks/utils/adapter/hidl/include/nnapi/hal/PreparedModel.h
@@ -39,7 +39,7 @@
 // Class that adapts nn::IPreparedModel to V1_3::IPreparedModel.
 class PreparedModel final : public V1_3::IPreparedModel {
   public:
-    PreparedModel(nn::SharedPreparedModel preparedModel, Executor executor);
+    explicit PreparedModel(nn::SharedPreparedModel preparedModel);
 
     Return<V1_0::ErrorStatus> execute(const V1_0::Request& request,
                                       const sp<V1_0::IExecutionCallback>& callback) override;
@@ -70,7 +70,6 @@
 
   private:
     const nn::SharedPreparedModel kPreparedModel;
-    const Executor kExecutor;
 };
 
 }  // namespace android::hardware::neuralnetworks::adapter
diff --git a/neuralnetworks/utils/adapter/hidl/src/Device.cpp b/neuralnetworks/utils/adapter/hidl/src/Device.cpp
index 0f44638..305a1b4 100644
--- a/neuralnetworks/utils/adapter/hidl/src/Device.cpp
+++ b/neuralnetworks/utils/adapter/hidl/src/Device.cpp
@@ -62,11 +62,11 @@
 
 using PrepareModelResult = nn::GeneralResult<nn::SharedPreparedModel>;
 
-sp<PreparedModel> adaptPreparedModel(nn::SharedPreparedModel preparedModel, Executor executor) {
+sp<PreparedModel> adaptPreparedModel(nn::SharedPreparedModel preparedModel) {
     if (preparedModel == nullptr) {
         return nullptr;
     }
-    return sp<PreparedModel>::make(std::move(preparedModel), std::move(executor));
+    return sp<PreparedModel>::make(std::move(preparedModel));
 }
 
 void notify(V1_0::IPreparedModelCallback* callback, nn::ErrorStatus status,
@@ -105,14 +105,14 @@
 }
 
 template <typename CallbackType>
-void notify(CallbackType* callback, PrepareModelResult result, Executor executor) {
+void notify(CallbackType* callback, PrepareModelResult result) {
     if (!result.has_value()) {
         const auto [message, status] = std::move(result).error();
         LOG(ERROR) << message;
         notify(callback, status, nullptr);
     } else {
         auto preparedModel = std::move(result).value();
-        auto hidlPreparedModel = adaptPreparedModel(std::move(preparedModel), std::move(executor));
+        auto hidlPreparedModel = adaptPreparedModel(std::move(preparedModel));
         notify(callback, nn::ErrorStatus::NONE, std::move(hidlPreparedModel));
     }
 }
@@ -133,10 +133,10 @@
 
     auto nnModel = NN_TRY(convertInput(model));
 
-    Task task = [device, nnModel = std::move(nnModel), executor, callback] {
+    Task task = [device, nnModel = std::move(nnModel), callback] {
         auto result = device->prepareModel(nnModel, nn::ExecutionPreference::DEFAULT,
                                            nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
-        notify(callback.get(), std::move(result), executor);
+        notify(callback.get(), std::move(result));
     };
     executor(std::move(task), {});
 
@@ -154,10 +154,10 @@
     auto nnModel = NN_TRY(convertInput(model));
     const auto nnPreference = NN_TRY(convertInput(preference));
 
-    Task task = [device, nnModel = std::move(nnModel), nnPreference, executor, callback] {
+    Task task = [device, nnModel = std::move(nnModel), nnPreference, callback] {
         auto result = device->prepareModel(nnModel, nnPreference, nn::Priority::DEFAULT, {}, {}, {},
                                            {}, {}, {});
-        notify(callback.get(), std::move(result), executor);
+        notify(callback.get(), std::move(result));
     };
     executor(std::move(task), {});
 
@@ -183,10 +183,10 @@
 
     Task task = [device, nnModel = std::move(nnModel), nnPreference,
                  nnModelCache = std::move(nnModelCache), nnDataCache = std::move(nnDataCache),
-                 nnToken, executor, callback] {
+                 nnToken, callback] {
         auto result = device->prepareModel(nnModel, nnPreference, nn::Priority::DEFAULT, {},
                                            nnModelCache, nnDataCache, nnToken, {}, {});
-        notify(callback.get(), std::move(result), executor);
+        notify(callback.get(), std::move(result));
     };
     executor(std::move(task), {});
 
@@ -213,10 +213,10 @@
 
     Task task = [device, nnModel = std::move(nnModel), nnPreference, nnPriority, nnDeadline,
                  nnModelCache = std::move(nnModelCache), nnDataCache = std::move(nnDataCache),
-                 nnToken, executor, callback] {
+                 nnToken, callback] {
         auto result = device->prepareModel(nnModel, nnPreference, nnPriority, nnDeadline,
                                            nnModelCache, nnDataCache, nnToken, {}, {});
-        notify(callback.get(), std::move(result), executor);
+        notify(callback.get(), std::move(result));
     };
     executor(std::move(task), nnDeadline);
 
@@ -238,9 +238,9 @@
     const auto nnToken = nn::CacheToken(token);
 
     Task task = [device, nnModelCache = std::move(nnModelCache),
-                 nnDataCache = std::move(nnDataCache), nnToken, executor, callback] {
+                 nnDataCache = std::move(nnDataCache), nnToken, callback] {
         auto result = device->prepareModelFromCache({}, nnModelCache, nnDataCache, nnToken);
-        notify(callback.get(), std::move(result), executor);
+        notify(callback.get(), std::move(result));
     };
     executor(std::move(task), {});
 
@@ -262,9 +262,9 @@
     const auto nnToken = nn::CacheToken(token);
 
     auto task = [device, nnDeadline, nnModelCache = std::move(nnModelCache),
-                 nnDataCache = std::move(nnDataCache), nnToken, executor, callback] {
+                 nnDataCache = std::move(nnDataCache), nnToken, callback] {
         auto result = device->prepareModelFromCache(nnDeadline, nnModelCache, nnDataCache, nnToken);
-        notify(callback.get(), std::move(result), executor);
+        notify(callback.get(), std::move(result));
     };
     executor(std::move(task), nnDeadline);
 
diff --git a/neuralnetworks/utils/adapter/hidl/src/PreparedModel.cpp b/neuralnetworks/utils/adapter/hidl/src/PreparedModel.cpp
index c6055a6..3570a74 100644
--- a/neuralnetworks/utils/adapter/hidl/src/PreparedModel.cpp
+++ b/neuralnetworks/utils/adapter/hidl/src/PreparedModel.cpp
@@ -55,15 +55,6 @@
     return result;
 }
 
-nn::GeneralResult<nn::Version> validateRequestForModel(const nn::Request& request,
-                                                       const nn::Model& model) {
-    nn::GeneralResult<nn::Version> version = nn::validateRequestForModel(request, model);
-    if (!version.ok()) {
-        version.error().code = nn::ErrorStatus::INVALID_ARGUMENT;
-    }
-    return version;
-}
-
 class FencedExecutionCallback final : public V1_3::IFencedExecutionCallback {
   public:
     explicit FencedExecutionCallback(const nn::ExecuteFencedInfoCallback& callback)
@@ -144,58 +135,48 @@
 }
 
 nn::GeneralResult<void> execute(const nn::SharedPreparedModel& preparedModel,
-                                const Executor& executor, const V1_0::Request& request,
+                                const V1_0::Request& request,
                                 const sp<V1_0::IExecutionCallback>& callback) {
     if (callback.get() == nullptr) {
         return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Invalid callback";
     }
 
-    auto nnRequest = NN_TRY(convertInput(request));
+    const auto nnRequest = NN_TRY(convertInput(request));
 
-    const std::any resource = preparedModel->getUnderlyingResource();
-    if (const auto* model = std::any_cast<const nn::Model*>(&resource)) {
-        CHECK(*model != nullptr);
-        NN_TRY(adapter::validateRequestForModel(nnRequest, **model));
+    auto result = preparedModel->execute(nnRequest, nn::MeasureTiming::NO, {}, {}, {}, {});
+
+    if (!result.ok() && result.error().code == nn::ErrorStatus::INVALID_ARGUMENT) {
+        const auto& [message, code, outputShapes] = result.error();
+        return nn::error(code) << message;
     }
 
-    Task task = [preparedModel, nnRequest = std::move(nnRequest), callback] {
-        auto result = preparedModel->execute(nnRequest, nn::MeasureTiming::NO, {}, {}, {}, {});
-        notify(callback.get(), std::move(result));
-    };
-    executor(std::move(task), {});
-
+    notify(callback.get(), std::move(result));
     return {};
 }
 
 nn::GeneralResult<void> execute_1_2(const nn::SharedPreparedModel& preparedModel,
-                                    const Executor& executor, const V1_0::Request& request,
-                                    V1_2::MeasureTiming measure,
+                                    const V1_0::Request& request, V1_2::MeasureTiming measure,
                                     const sp<V1_2::IExecutionCallback>& callback) {
     if (callback.get() == nullptr) {
         return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Invalid callback";
     }
 
-    auto nnRequest = NN_TRY(convertInput(request));
+    const auto nnRequest = NN_TRY(convertInput(request));
     const auto nnMeasure = NN_TRY(convertInput(measure));
 
-    const std::any resource = preparedModel->getUnderlyingResource();
-    if (const auto* model = std::any_cast<const nn::Model*>(&resource)) {
-        CHECK(*model != nullptr);
-        NN_TRY(adapter::validateRequestForModel(nnRequest, **model));
+    auto result = preparedModel->execute(nnRequest, nnMeasure, {}, {}, {}, {});
+
+    if (!result.ok() && result.error().code == nn::ErrorStatus::INVALID_ARGUMENT) {
+        const auto& [message, code, outputShapes] = result.error();
+        return nn::error(code) << message;
     }
 
-    Task task = [preparedModel, nnRequest = std::move(nnRequest), nnMeasure, callback] {
-        auto result = preparedModel->execute(nnRequest, nnMeasure, {}, {}, {}, {});
-        notify(callback.get(), std::move(result));
-    };
-    executor(std::move(task), {});
-
+    notify(callback.get(), std::move(result));
     return {};
 }
 
 nn::GeneralResult<void> execute_1_3(const nn::SharedPreparedModel& preparedModel,
-                                    const Executor& executor, const V1_3::Request& request,
-                                    V1_2::MeasureTiming measure,
+                                    const V1_3::Request& request, V1_2::MeasureTiming measure,
                                     const V1_3::OptionalTimePoint& deadline,
                                     const V1_3::OptionalTimeoutDuration& loopTimeoutDuration,
                                     const sp<V1_3::IExecutionCallback>& callback) {
@@ -203,25 +184,20 @@
         return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Invalid callback";
     }
 
-    auto nnRequest = NN_TRY(convertInput(request));
+    const auto nnRequest = NN_TRY(convertInput(request));
     const auto nnMeasure = NN_TRY(convertInput(measure));
     const auto nnDeadline = NN_TRY(convertInput(deadline));
     const auto nnLoopTimeoutDuration = NN_TRY(convertInput(loopTimeoutDuration));
 
-    const std::any resource = preparedModel->getUnderlyingResource();
-    if (const auto* model = std::any_cast<const nn::Model*>(&resource)) {
-        CHECK(*model != nullptr);
-        NN_TRY(adapter::validateRequestForModel(nnRequest, **model));
+    auto result =
+            preparedModel->execute(nnRequest, nnMeasure, nnDeadline, nnLoopTimeoutDuration, {}, {});
+
+    if (!result.ok() && result.error().code == nn::ErrorStatus::INVALID_ARGUMENT) {
+        const auto& [message, code, outputShapes] = result.error();
+        return nn::error(code) << message;
     }
 
-    Task task = [preparedModel, nnRequest = std::move(nnRequest), nnMeasure, nnDeadline,
-                 nnLoopTimeoutDuration, callback] {
-        auto result = preparedModel->execute(nnRequest, nnMeasure, nnDeadline,
-                                             nnLoopTimeoutDuration, {}, {});
-        notify(callback.get(), std::move(result));
-    };
-    executor(std::move(task), nnDeadline);
-
+    notify(callback.get(), std::move(result));
     return {};
 }
 
@@ -304,10 +280,9 @@
 
 }  // namespace
 
-PreparedModel::PreparedModel(nn::SharedPreparedModel preparedModel, Executor executor)
-    : kPreparedModel(std::move(preparedModel)), kExecutor(std::move(executor)) {
+PreparedModel::PreparedModel(nn::SharedPreparedModel preparedModel)
+    : kPreparedModel(std::move(preparedModel)) {
     CHECK(kPreparedModel != nullptr);
-    CHECK(kExecutor != nullptr);
 }
 
 nn::SharedPreparedModel PreparedModel::getUnderlyingPreparedModel() const {
@@ -316,7 +291,7 @@
 
 Return<V1_0::ErrorStatus> PreparedModel::execute(const V1_0::Request& request,
                                                  const sp<V1_0::IExecutionCallback>& callback) {
-    auto result = adapter::execute(kPreparedModel, kExecutor, request, callback);
+    auto result = adapter::execute(kPreparedModel, request, callback);
     if (!result.has_value()) {
         auto [message, code] = std::move(result).error();
         LOG(ERROR) << "adapter::PreparedModel::execute failed with " << code << ": " << message;
@@ -329,7 +304,7 @@
 Return<V1_0::ErrorStatus> PreparedModel::execute_1_2(const V1_0::Request& request,
                                                      V1_2::MeasureTiming measure,
                                                      const sp<V1_2::IExecutionCallback>& callback) {
-    auto result = adapter::execute_1_2(kPreparedModel, kExecutor, request, measure, callback);
+    auto result = adapter::execute_1_2(kPreparedModel, request, measure, callback);
     if (!result.has_value()) {
         auto [message, code] = std::move(result).error();
         LOG(ERROR) << "adapter::PreparedModel::execute_1_2 failed with " << code << ": " << message;
@@ -344,7 +319,7 @@
         const V1_3::OptionalTimePoint& deadline,
         const V1_3::OptionalTimeoutDuration& loopTimeoutDuration,
         const sp<V1_3::IExecutionCallback>& callback) {
-    auto result = adapter::execute_1_3(kPreparedModel, kExecutor, request, measure, deadline,
+    auto result = adapter::execute_1_3(kPreparedModel, request, measure, deadline,
                                        loopTimeoutDuration, callback);
     if (!result.has_value()) {
         auto [message, code] = std::move(result).error();
@@ -405,8 +380,8 @@
         cb(V1_2::utils::convert(code).value(), nullptr);
         return Void();
     }
-    auto burstContext = std::move(result).value();
-    cb(V1_0::ErrorStatus::NONE, std::move(burstContext));
+    const auto burstContext = std::move(result).value();
+    cb(V1_0::ErrorStatus::NONE, burstContext);
     return Void();
 }
 
diff --git a/neuralnetworks/utils/common/Android.bp b/neuralnetworks/utils/common/Android.bp
index bfba24f..91fca2f 100644
--- a/neuralnetworks/utils/common/Android.bp
+++ b/neuralnetworks/utils/common/Android.bp
@@ -36,6 +36,7 @@
 cc_test {
     name: "neuralnetworks_utils_hal_common_test",
     host_supported: true,
+    tidy_timeout_srcs: ["test/ResilientDeviceTest.cpp"],
     srcs: ["test/*.cpp"],
     static_libs: [
         "libgmock",
diff --git a/neuralnetworks/utils/service/include/nnapi/hal/Service.h b/neuralnetworks/utils/service/include/nnapi/hal/Service.h
index e8b9c10..38d2a54 100644
--- a/neuralnetworks/utils/service/include/nnapi/hal/Service.h
+++ b/neuralnetworks/utils/service/include/nnapi/hal/Service.h
@@ -24,23 +24,16 @@
 
 namespace android::hardware::neuralnetworks::service {
 
-struct SharedDeviceAndUpdatability {
-    nn::SharedDevice device;
-    bool isDeviceUpdatable = false;
-};
-
 /**
  * @brief Get the NNAPI sAIDL and HIDL services declared in the VINTF.
  *
  * @pre maxFeatureLevelAllowed >= Version::Level::FEATURE_LEVEL_5
  *
- * @param includeUpdatableDrivers Allow updatable drivers to be used.
  * @param maxFeatureLevelAllowed Maximum version of driver allowed to be used. Any driver version
  *     exceeding this must be clamped to `maxFeatureLevelAllowed`.
  * @return A list of devices and whether each device is updatable or not.
  */
-std::vector<SharedDeviceAndUpdatability> getDevices(bool includeUpdatableDrivers,
-                                                    nn::Version::Level maxFeatureLevelAllowed);
+std::vector<nn::SharedDevice> getDevices(nn::Version::Level maxFeatureLevelAllowed);
 
 }  // namespace android::hardware::neuralnetworks::service
 
diff --git a/neuralnetworks/utils/service/src/Service.cpp b/neuralnetworks/utils/service/src/Service.cpp
index e0d5f82..dd37dae 100644
--- a/neuralnetworks/utils/service/src/Service.cpp
+++ b/neuralnetworks/utils/service/src/Service.cpp
@@ -51,7 +51,7 @@
 using getDeviceFn = std::add_pointer_t<nn::GeneralResult<nn::SharedDevice>(const std::string&)>;
 
 void getHidlDevicesForVersion(const std::string& descriptor, getDeviceFn getDevice,
-                              std::vector<SharedDeviceAndUpdatability>* devices,
+                              std::vector<nn::SharedDevice>* devices,
                               std::unordered_set<std::string>* registeredDevices) {
     CHECK(devices != nullptr);
     CHECK(registeredDevices != nullptr);
@@ -63,7 +63,7 @@
             if (maybeDevice.has_value()) {
                 auto device = std::move(maybeDevice).value();
                 CHECK(device != nullptr);
-                devices->push_back({.device = std::move(device)});
+                devices->push_back(std::move(device));
             } else {
                 LOG(ERROR) << "getDevice(" << name << ") failed with " << maybeDevice.error().code
                            << ": " << maybeDevice.error().message;
@@ -72,9 +72,9 @@
     }
 }
 
-void getAidlDevices(std::vector<SharedDeviceAndUpdatability>* devices,
+void getAidlDevices(std::vector<nn::SharedDevice>* devices,
                     std::unordered_set<std::string>* registeredDevices,
-                    bool includeUpdatableDrivers, nn::Version::Level maxFeatureLevelAllowed) {
+                    nn::Version::Level maxFeatureLevelAllowed) {
     CHECK(devices != nullptr);
     CHECK(registeredDevices != nullptr);
 
@@ -91,21 +91,12 @@
     }
 
     for (const auto& name : names) {
-        bool isDeviceUpdatable = false;
-        if (__builtin_available(android __NNAPI_AIDL_MIN_ANDROID_API__, *)) {
-            const auto instance = std::string(aidl_hal::IDevice::descriptor) + '/' + name;
-            isDeviceUpdatable = AServiceManager_isUpdatableViaApex(instance.c_str());
-        }
-        if (isDeviceUpdatable && !includeUpdatableDrivers) {
-            continue;
-        }
         if (const auto [it, unregistered] = registeredDevices->insert(name); unregistered) {
             auto maybeDevice = aidl_hal::utils::getDevice(name, maxFeatureLevelAllowed);
             if (maybeDevice.has_value()) {
                 auto device = std::move(maybeDevice).value();
                 CHECK(device != nullptr);
-                devices->push_back(
-                        {.device = std::move(device), .isDeviceUpdatable = isDeviceUpdatable});
+                devices->push_back(std::move(device));
             } else {
                 LOG(ERROR) << "getDevice(" << name << ") failed with " << maybeDevice.error().code
                            << ": " << maybeDevice.error().message;
@@ -116,14 +107,13 @@
 
 }  // namespace
 
-std::vector<SharedDeviceAndUpdatability> getDevices(bool includeUpdatableDrivers,
-                                                    nn::Version::Level maxFeatureLevelAllowed) {
-    std::vector<SharedDeviceAndUpdatability> devices;
+std::vector<nn::SharedDevice> getDevices(nn::Version::Level maxFeatureLevelAllowed) {
+    std::vector<nn::SharedDevice> devices;
     std::unordered_set<std::string> registeredDevices;
 
     CHECK_GE(maxFeatureLevelAllowed, nn::Version::Level::FEATURE_LEVEL_5);
 
-    getAidlDevices(&devices, &registeredDevices, includeUpdatableDrivers, maxFeatureLevelAllowed);
+    getAidlDevices(&devices, &registeredDevices, maxFeatureLevelAllowed);
 
     getHidlDevicesForVersion(V1_3::IDevice::descriptor, &V1_3::utils::getDevice, &devices,
                              &registeredDevices);
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/ApnTypes.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/ApnTypes.aidl
index 6982d40..980b042 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/ApnTypes.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/ApnTypes.aidl
@@ -47,4 +47,7 @@
   EMERGENCY = 512,
   MCX = 1024,
   XCAP = 2048,
+  VSIM = 4096,
+  BIP = 8192,
+  ENTERPRISE = 16384,
 }
diff --git a/radio/aidl/android/hardware/radio/data/ApnTypes.aidl b/radio/aidl/android/hardware/radio/data/ApnTypes.aidl
index e780d8e..ae103fc 100644
--- a/radio/aidl/android/hardware/radio/data/ApnTypes.aidl
+++ b/radio/aidl/android/hardware/radio/data/ApnTypes.aidl
@@ -73,4 +73,16 @@
      * APN type for XCAP
      */
     XCAP = 1 << 11,
+    /**
+     * APN type for VSIM.
+     */
+    VSIM = 1 << 12,
+    /**
+     * APN type for BIP.
+     */
+    BIP = 1 << 13,
+    /**
+     * APN type for ENTERPRISE
+     */
+    ENTERPRISE = 1 << 14
 }
diff --git a/radio/aidl/compat/libradiocompat/network/RadioNetwork.cpp b/radio/aidl/compat/libradiocompat/network/RadioNetwork.cpp
index 22b9ede..d5e2a8d 100644
--- a/radio/aidl/compat/libradiocompat/network/RadioNetwork.cpp
+++ b/radio/aidl/compat/libradiocompat/network/RadioNetwork.cpp
@@ -228,7 +228,7 @@
 ScopedAStatus RadioNetwork::setNetworkSelectionModeManual(  //
         int32_t serial, const std::string& opNumeric, AccessNetwork ran) {
     LOG_CALL << serial;
-    mHal1_5->setNetworkSelectionModeManual_1_5(serial, opNumeric, V1_5::RadioAccessNetworks(ran));
+    mHal1_5->setNetworkSelectionModeManual_1_5(serial, opNumeric, toRadioAccessNetworks(ran));
     return ok();
 }
 
diff --git a/radio/aidl/compat/libradiocompat/network/structs.cpp b/radio/aidl/compat/libradiocompat/network/structs.cpp
index c1d9b35..d0b3b90 100644
--- a/radio/aidl/compat/libradiocompat/network/structs.cpp
+++ b/radio/aidl/compat/libradiocompat/network/structs.cpp
@@ -98,17 +98,56 @@
     return hidl;
 }
 
+AccessNetwork fromRadioAccessNetwork(V1_5::RadioAccessNetworks ran) {
+    switch (ran) {
+        case V1_5::RadioAccessNetworks::UNKNOWN:
+            return AccessNetwork::UNKNOWN;
+        case V1_5::RadioAccessNetworks::GERAN:
+            return AccessNetwork::GERAN;
+        case V1_5::RadioAccessNetworks::UTRAN:
+            return AccessNetwork::UTRAN;
+        case V1_5::RadioAccessNetworks::EUTRAN:
+            return AccessNetwork::EUTRAN;
+        case V1_5::RadioAccessNetworks::CDMA2000:
+            return AccessNetwork::CDMA2000;
+        case V1_5::RadioAccessNetworks::NGRAN:
+            return AccessNetwork::NGRAN;
+        default:
+            return AccessNetwork::UNKNOWN;
+    }
+}
+
 aidl::RadioAccessSpecifier toAidl(const V1_5::RadioAccessSpecifier& spec) {
     return {
-            .accessNetwork = AccessNetwork(spec.radioAccessNetwork),
+            .accessNetwork = fromRadioAccessNetwork(spec.radioAccessNetwork),
             .bands = toAidl(spec.bands),
             .channels = spec.channels,
     };
 }
 
+V1_5::RadioAccessNetworks toRadioAccessNetworks(AccessNetwork val) {
+    switch (val) {
+        case AccessNetwork::UNKNOWN:
+            return V1_5::RadioAccessNetworks::UNKNOWN;
+        case AccessNetwork::GERAN:
+            return V1_5::RadioAccessNetworks::GERAN;
+        case AccessNetwork::UTRAN:
+            return V1_5::RadioAccessNetworks::UTRAN;
+        case AccessNetwork::EUTRAN:
+            return V1_5::RadioAccessNetworks::EUTRAN;
+        case AccessNetwork::CDMA2000:
+            return V1_5::RadioAccessNetworks::CDMA2000;
+        case AccessNetwork::NGRAN:
+            return V1_5::RadioAccessNetworks::NGRAN;
+        case AccessNetwork::IWLAN:
+        default:
+            return V1_5::RadioAccessNetworks::UNKNOWN;
+    }
+}
+
 V1_5::RadioAccessSpecifier toHidl(const aidl::RadioAccessSpecifier& spec) {
     return {
-            .radioAccessNetwork = V1_5::RadioAccessNetworks{spec.accessNetwork},
+            .radioAccessNetwork = toRadioAccessNetworks(spec.accessNetwork),
             .bands = toHidl(spec.bands),
             .channels = spec.channels,
     };
diff --git a/radio/aidl/compat/libradiocompat/network/structs.h b/radio/aidl/compat/libradiocompat/network/structs.h
index aaa49a0..6a9a219 100644
--- a/radio/aidl/compat/libradiocompat/network/structs.h
+++ b/radio/aidl/compat/libradiocompat/network/structs.h
@@ -49,6 +49,8 @@
 
 ::aidl::android::hardware::radio::network::RadioAccessSpecifier  //
 toAidl(const V1_5::RadioAccessSpecifier& spec);
+V1_5::RadioAccessNetworks  //
+toRadioAccessNetworks(::aidl::android::hardware::radio::AccessNetwork val);
 V1_5::RadioAccessSpecifier  //
 toHidl(const ::aidl::android::hardware::radio::network::RadioAccessSpecifier& spec);
 
diff --git a/radio/aidl/vts/Android.bp b/radio/aidl/vts/Android.bp
index 8060e4b..8f28255 100644
--- a/radio/aidl/vts/Android.bp
+++ b/radio/aidl/vts/Android.bp
@@ -27,6 +27,12 @@
         "VtsHalTargetTestDefaults",
         "use_libaidlvintf_gtest_helper_static",
     ],
+    tidy_timeout_srcs: [
+        "radio_messaging_test.cpp",
+        "radio_network_test.cpp",
+        "radio_sim_test.cpp",
+        "radio_voice_test.cpp",
+    ],
     srcs: [
         "radio_aidl_hal_utils.cpp",
         "radio_config_indication.cpp",
diff --git a/radio/aidl/vts/AndroidTest.xml b/radio/aidl/vts/AndroidTest.xml
new file mode 100644
index 0000000..36381d1
--- /dev/null
+++ b/radio/aidl/vts/AndroidTest.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2022 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Runs VtsHalRadioTargetTest.">
+    <option name="test-suite-tag" value="apct" />
+    <option name="test-suite-tag" value="apct-native" />
+
+    <target_preparer class="com.android.tradefed.targetprep.MultiSimPreparer" />
+    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer">
+    </target_preparer>
+
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push" value="VtsHalRadioTargetTest->/data/local/tmp/VtsHalRadioTargetTest" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="native-test-timeout" value="300000" /> <!-- 5 min -->
+        <option name="module-name" value="VtsHalRadioTargetTest" />
+    </test>
+</configuration>
\ No newline at end of file
diff --git a/radio/aidl/vts/radio_aidl_hal_utils.cpp b/radio/aidl/vts/radio_aidl_hal_utils.cpp
index dc61a3c..76f15bf 100644
--- a/radio/aidl/vts/radio_aidl_hal_utils.cpp
+++ b/radio/aidl/vts/radio_aidl_hal_utils.cpp
@@ -107,7 +107,7 @@
 
 bool stringEndsWith(std::string const& string, std::string const& end) {
     if (string.size() >= end.size()) {
-        return (0 == string.compare(string.size() - end.size() - 1, end.size(), end));
+        return std::equal(end.rbegin(), end.rend(), string.rbegin());
     } else {
         return false;
     }
@@ -116,7 +116,7 @@
 bool isServiceValidForDeviceConfiguration(std::string& serviceName) {
     if (isSsSsEnabled()) {
         // Device is configured as SSSS.
-        if (stringEndsWith(serviceName, RADIO_SERVICE_SLOT1_NAME)) {
+        if (!stringEndsWith(serviceName, RADIO_SERVICE_SLOT1_NAME)) {
             ALOGI("%s instance is not valid for SSSS device.", serviceName.c_str());
             return false;
         }
diff --git a/radio/aidl/vts/radio_config_test.cpp b/radio/aidl/vts/radio_config_test.cpp
index a271b8a..43b63e8 100644
--- a/radio/aidl/vts/radio_config_test.cpp
+++ b/radio/aidl/vts/radio_config_test.cpp
@@ -24,11 +24,6 @@
 void RadioConfigTest::SetUp() {
     std::string serviceName = GetParam();
 
-    if (!isServiceValidForDeviceConfiguration(serviceName)) {
-        ALOGI("Skipped the test due to device configuration.");
-        GTEST_SKIP();
-    }
-
     radio_config = IRadioConfig::fromBinder(
             ndk::SpAIBinder(AServiceManager_waitForService(GetParam().c_str())));
     ASSERT_NE(nullptr, radio_config.get());
diff --git a/radio/aidl/vts/radio_voice_test.cpp b/radio/aidl/vts/radio_voice_test.cpp
index eec28b1..249ee63 100644
--- a/radio/aidl/vts/radio_voice_test.cpp
+++ b/radio/aidl/vts/radio_voice_test.cpp
@@ -943,3 +943,37 @@
     }
     LOG(DEBUG) << "cancelPendingUssd finished";
 }
+
+/*
+ * Test IRadioVoice.isVoNrEnabled() for the response returned.
+ */
+TEST_P(RadioVoiceTest, isVoNrEnabled) {
+    LOG(DEBUG) << "isVoNrEnabled";
+    serial = GetRandomSerialNumber();
+
+    radio_voice->isVoNrEnabled(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+    ASSERT_TRUE(CheckAnyOfErrors(radioRsp_voice->rspInfo.error,
+                                 {RadioError::REQUEST_NOT_SUPPORTED, RadioError::NONE}));
+    LOG(DEBUG) << "isVoNrEnabled finished";
+}
+
+/*
+ * Test IRadioVoice.setVoNrEnabled() for the response returned.
+ */
+TEST_P(RadioVoiceTest, setVoNrEnabled) {
+    LOG(DEBUG) << "setVoNrEnabled";
+    serial = GetRandomSerialNumber();
+
+    radio_voice->setVoNrEnabled(serial, true);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+    ASSERT_TRUE(CheckAnyOfErrors(radioRsp_voice->rspInfo.error,
+                                 {RadioError::REQUEST_NOT_SUPPORTED, RadioError::NONE}));
+    LOG(DEBUG) << "setVoNrEnabled finished";
+}
diff --git a/security/dice/aidl/default/Android.bp b/security/dice/aidl/default/Android.bp
new file mode 100644
index 0000000..b67a44a
--- /dev/null
+++ b/security/dice/aidl/default/Android.bp
@@ -0,0 +1,30 @@
+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"],
+}
+
+rust_binary {
+    name: "android.hardware.security.dice-service.non-secure-software",
+    srcs: ["service.rs"],
+    relative_install_path: "hw",
+    vendor: true,
+    rustlibs: [
+        "android.hardware.security.dice-V1-rust",
+        "libdiced_open_dice_cbor",
+        "libdiced_sample_inputs",
+        "libdiced_vendor",
+        "libandroid_logger",
+        "libanyhow",
+        "libbinder_rs",
+        "liblog_rust",
+        "libserde",
+    ],
+    init_rc: ["android.hardware.security.dice-service.non-secure-software.rc"],
+    vintf_fragments: [
+        "android.hardware.security.dice-service.non-secure-software.xml",
+    ],
+}
diff --git a/security/dice/aidl/default/android.hardware.security.dice-service.non-secure-software.rc b/security/dice/aidl/default/android.hardware.security.dice-service.non-secure-software.rc
new file mode 100644
index 0000000..28e43c3
--- /dev/null
+++ b/security/dice/aidl/default/android.hardware.security.dice-service.non-secure-software.rc
@@ -0,0 +1,9 @@
+service vendor.dice /vendor/bin/hw/android.hardware.security.dice-service.non-secure-software
+    class early_hal
+    user nobody
+    # The diced HAL cannot be allowed to restart. When it crashes for any reason.
+    # it loses security critical state. The only remedy is to restart the device.
+    # This may be implementation depended. It is safe to restart the HAL if the
+    # state change during a call to "demote" is is preserved.
+    # see android/hardware/security/dice/IDiceDevice.aidl for details on "demote".
+    oneshot
diff --git a/security/dice/aidl/default/android.hardware.security.dice-service.non-secure-software.xml b/security/dice/aidl/default/android.hardware.security.dice-service.non-secure-software.xml
new file mode 100644
index 0000000..94ef243
--- /dev/null
+++ b/security/dice/aidl/default/android.hardware.security.dice-service.non-secure-software.xml
@@ -0,0 +1,6 @@
+<manifest version="1.0" type="device">
+    <hal format="aidl">
+        <name>android.hardware.security.dice</name>
+        <fqname>IDiceDevice/default</fqname>
+    </hal>
+</manifest>
\ No newline at end of file
diff --git a/security/dice/aidl/default/service.rs b/security/dice/aidl/default/service.rs
new file mode 100644
index 0000000..eebf333
--- /dev/null
+++ b/security/dice/aidl/default/service.rs
@@ -0,0 +1,107 @@
+// Copyright 2021, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! Main entry point for the android.hardware.security.dice service.
+
+use anyhow::Result;
+use diced::{
+    dice,
+    hal_node::{DiceArtifacts, DiceDevice, ResidentHal, UpdatableDiceArtifacts},
+};
+use diced_sample_inputs::make_sample_bcc_and_cdis;
+use serde::{Deserialize, Serialize};
+use std::convert::TryInto;
+use std::panic;
+use std::sync::Arc;
+
+static DICE_HAL_SERVICE_NAME: &str = "android.hardware.security.dice.IDiceDevice/default";
+
+#[derive(Debug, Serialize, Deserialize, Clone)]
+struct InsecureSerializableArtifacts {
+    cdi_attest: [u8; dice::CDI_SIZE],
+    cdi_seal: [u8; dice::CDI_SIZE],
+    bcc: Vec<u8>,
+}
+
+impl DiceArtifacts for InsecureSerializableArtifacts {
+    fn cdi_attest(&self) -> &[u8; dice::CDI_SIZE] {
+        &self.cdi_attest
+    }
+    fn cdi_seal(&self) -> &[u8; dice::CDI_SIZE] {
+        &self.cdi_seal
+    }
+    fn bcc(&self) -> Vec<u8> {
+        self.bcc.clone()
+    }
+}
+
+impl UpdatableDiceArtifacts for InsecureSerializableArtifacts {
+    fn with_artifacts<F, T>(&self, f: F) -> Result<T>
+    where
+        F: FnOnce(&dyn DiceArtifacts) -> Result<T>,
+    {
+        f(self)
+    }
+    fn update(self, new_artifacts: &impl DiceArtifacts) -> Result<Self> {
+        Ok(Self {
+            cdi_attest: *new_artifacts.cdi_attest(),
+            cdi_seal: *new_artifacts.cdi_seal(),
+            bcc: new_artifacts.bcc(),
+        })
+    }
+}
+
+fn main() {
+    android_logger::init_once(
+        android_logger::Config::default()
+            .with_tag("android.hardware.security.dice")
+            .with_min_level(log::Level::Debug),
+    );
+    // Redirect panic messages to logcat.
+    panic::set_hook(Box::new(|panic_info| {
+        log::error!("{}", panic_info);
+    }));
+
+    // Saying hi.
+    log::info!("android.hardware.security.dice is starting.");
+
+    let (cdi_attest, cdi_seal, bcc) =
+        make_sample_bcc_and_cdis().expect("Failed to construct sample dice chain.");
+
+    let hal_impl = Arc::new(
+        unsafe {
+            // Safety: ResidentHal cannot be used in multi threaded processes.
+            // This service does not start a thread pool. The main thread is the only thread
+            // joining the thread pool, thereby keeping the process single threaded.
+            ResidentHal::new(InsecureSerializableArtifacts {
+                cdi_attest: cdi_attest[..]
+                    .try_into()
+                    .expect("Failed to convert cdi_attest to array reference."),
+                cdi_seal: cdi_seal[..]
+                    .try_into()
+                    .expect("Failed to convert cdi_seal to array reference."),
+                bcc,
+            })
+        }
+        .expect("Failed to create ResidentHal implementation."),
+    );
+
+    let hal = DiceDevice::new_as_binder(hal_impl).expect("Failed to construct hal service.");
+
+    binder::add_service(DICE_HAL_SERVICE_NAME, hal.as_binder())
+        .expect("Failed to register IDiceDevice Service");
+
+    log::info!("Joining thread pool now.");
+    binder::ProcessState::join_thread_pool();
+}
diff --git a/security/dice/aidl/vts/functional/Android.bp b/security/dice/aidl/vts/functional/Android.bp
new file mode 100644
index 0000000..f5bc949
--- /dev/null
+++ b/security/dice/aidl/vts/functional/Android.bp
@@ -0,0 +1,54 @@
+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"],
+}
+
+rust_test {
+    name: "VtsAidlDiceTargetTest",
+    srcs: [
+        "dice_test.rs",
+    ],
+    require_root: true,
+    auto_gen_config: true,
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
+
+    rustlibs: [
+        "android.hardware.security.dice-V1-rust",
+        "libanyhow",
+        "libbinder_rs",
+        "libdiced_open_dice_cbor",
+        "libdiced_sample_inputs",
+        "libdiced_utils",
+        "libkeystore2_vintf_rust",
+    ],
+}
+
+rust_test {
+    name: "VtsAidlDiceDemoteTargetTest",
+    srcs: [
+        "dice_demote_test.rs",
+    ],
+
+    test_config: "VtsAidlDiceDemoteTargetTest.xml",
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
+
+    rustlibs: [
+        "android.hardware.security.dice-V1-rust",
+        "libanyhow",
+        "libbinder_rs",
+        "libdiced_open_dice_cbor",
+        "libdiced_sample_inputs",
+        "libdiced_utils",
+        "libkeystore2_vintf_rust",
+    ],
+}
diff --git a/security/dice/aidl/vts/functional/VtsAidlDiceDemoteTargetTest.xml b/security/dice/aidl/vts/functional/VtsAidlDiceDemoteTargetTest.xml
new file mode 100644
index 0000000..2991580
--- /dev/null
+++ b/security/dice/aidl/vts/functional/VtsAidlDiceDemoteTargetTest.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<configuration description="Config to run VtsAidlDiceDemoteTargetTest device tests.">
+
+    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer">
+    </target_preparer>
+
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push" value="VtsAidlDiceDemoteTargetTest->/data/local/tmp/VtsAidlDiceDemoteTargetTest" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.rust.RustBinaryTest" >
+        <option name="test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="VtsAidlDiceDemoteTargetTest" />
+    </test>
+    <target_preparer class="com.android.tradefed.targetprep.RebootTargetPreparer" />
+
+</configuration>
\ No newline at end of file
diff --git a/security/dice/aidl/vts/functional/dice_demote_test.rs b/security/dice/aidl/vts/functional/dice_demote_test.rs
new file mode 100644
index 0000000..02ff2a4
--- /dev/null
+++ b/security/dice/aidl/vts/functional/dice_demote_test.rs
@@ -0,0 +1,67 @@
+// Copyright 2021, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+use diced_open_dice_cbor as dice;
+use diced_sample_inputs;
+use diced_utils;
+use std::convert::TryInto;
+
+mod utils;
+use utils::with_connection;
+
+// This test calls derive with an empty argument vector, then demotes the HAL using
+// a set of three input values, and then calls derive with empty argument vector again.
+// It then performs the same three derivation steps on the result of the former and compares
+// the result to the result of the latter.
+#[test]
+fn demote_test() {
+    with_connection(|device| {
+        let input_values = diced_sample_inputs::get_input_values_vector();
+        let former = device.derive(&[]).expect("Trying to call derive.");
+        device
+            .demote(&input_values)
+            .expect("Trying to call demote with input values.");
+
+        let latter = device
+            .derive(&[])
+            .expect("Trying to call derive after demote.");
+
+        let artifacts = diced_utils::ResidentArtifacts::new(
+            former.cdiAttest[..].try_into().unwrap(),
+            former.cdiSeal[..].try_into().unwrap(),
+            &former.bcc.data,
+        )
+        .unwrap();
+
+        let input_values: Vec<diced_utils::InputValues> = input_values
+            .iter()
+            .map(|v| v.into())
+            .collect();
+
+        let artifacts = artifacts
+            .execute_steps(input_values.iter().map(|v| v as &dyn dice::InputValues))
+            .unwrap();
+        let (cdi_attest, cdi_seal, bcc) = artifacts.into_tuple();
+        let from_former = diced_utils::make_bcc_handover(
+            cdi_attest[..].try_into().unwrap(),
+            cdi_seal[..].try_into().unwrap(),
+            &bcc,
+        )
+        .unwrap();
+        // TODO b/204938506 when we have a parser/verifier, check equivalence rather
+        // than bit by bit equality.
+        assert_eq!(latter, from_former);
+        Ok(())
+    })
+}
diff --git a/security/dice/aidl/vts/functional/dice_test.rs b/security/dice/aidl/vts/functional/dice_test.rs
new file mode 100644
index 0000000..574b634
--- /dev/null
+++ b/security/dice/aidl/vts/functional/dice_test.rs
@@ -0,0 +1,82 @@
+// Copyright 2021, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+use diced_open_dice_cbor as dice;
+use diced_sample_inputs;
+use diced_utils;
+use std::convert::{TryInto, Into};
+
+mod utils;
+use utils::with_connection;
+
+static TEST_MESSAGE: &[u8] = &[
+    // "My test message!"
+    0x4d, 0x79, 0x20, 0x74, 0x65, 0x73, 0x74, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x21,
+    0x0a,
+];
+
+// This test calls derive with an empty argument vector and with a set of three input values.
+// It then performs the same three derivation steps on the result of the former and compares
+// the result to the result of the latter.
+#[test]
+fn equivalence_test() {
+    with_connection(|device| {
+        let input_values = diced_sample_inputs::get_input_values_vector();
+        let former = device.derive(&[]).expect("Trying to call derive.");
+        let latter = device
+            .derive(&input_values)
+            .expect("Trying to call derive with input values.");
+        let artifacts = diced_utils::ResidentArtifacts::new(
+            former.cdiAttest[..].try_into().unwrap(),
+            former.cdiSeal[..].try_into().unwrap(),
+            &former.bcc.data,
+        )
+        .unwrap();
+
+        let input_values: Vec<diced_utils::InputValues> = input_values
+            .iter()
+            .map(|v| v.into())
+            .collect();
+
+        let artifacts = artifacts
+            .execute_steps(input_values.iter().map(|v| v as &dyn dice::InputValues))
+            .unwrap();
+        let (cdi_attest, cdi_seal, bcc) = artifacts.into_tuple();
+        let from_former = diced_utils::make_bcc_handover(
+            cdi_attest[..].try_into().unwrap(),
+            cdi_seal[..].try_into().unwrap(),
+            &bcc,
+        )
+        .unwrap();
+        // TODO b/204938506 when we have a parser/verifier, check equivalence rather
+        // than bit by bit equality.
+        assert_eq!(latter, from_former);
+        Ok(())
+    })
+}
+
+#[test]
+fn sign_and_verify() {
+    with_connection(|device| {
+        let _signature = device
+            .sign(&[], TEST_MESSAGE)
+            .expect("Trying to call sign.");
+
+        let _bcc = device
+            .getAttestationChain(&[])
+            .expect("Trying to call getAttestationChain.");
+        // TODO b/204938506 check the signature with the bcc when the verifier is available.
+        Ok(())
+    })
+}
diff --git a/security/dice/aidl/vts/functional/utils.rs b/security/dice/aidl/vts/functional/utils.rs
new file mode 100644
index 0000000..4e6708e
--- /dev/null
+++ b/security/dice/aidl/vts/functional/utils.rs
@@ -0,0 +1,53 @@
+// Copyright 2021, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+use android_hardware_security_dice::aidl::android::hardware::security::dice::IDiceDevice::IDiceDevice;
+use anyhow::Result;
+use binder::Strong;
+use keystore2_vintf::get_aidl_instances;
+use std::sync::Arc;
+
+static DICE_DEVICE_SERVICE_NAME: &str = &"android.hardware.security.dice";
+static DICE_DEVICE_INTERFACE_NAME: &str = &"IDiceDevice";
+
+/// This function iterates through all announced IDiceDevice services and runs the given test
+/// closure against connections to each of them. It also modifies the panic hook to indicate
+/// on which instance the test failed in case the test closure panics.
+pub fn with_connection<R, F>(test: F)
+where
+    F: Fn(&Strong<dyn IDiceDevice>) -> Result<R>,
+{
+    let instances = get_aidl_instances(DICE_DEVICE_SERVICE_NAME, 1, DICE_DEVICE_INTERFACE_NAME);
+    let panic_hook = Arc::new(std::panic::take_hook());
+    for i in instances.into_iter() {
+        let panic_hook_clone = panic_hook.clone();
+        let instance_clone = i.clone();
+        std::panic::set_hook(Box::new(move |v| {
+            println!("While testing instance: \"{}\"", instance_clone);
+            panic_hook_clone(v)
+        }));
+        let connection: Strong<dyn IDiceDevice> = binder::get_interface(&format!(
+            "{}.{}/{}",
+            DICE_DEVICE_SERVICE_NAME, DICE_DEVICE_INTERFACE_NAME, i
+        ))
+        .unwrap();
+        test(&connection).unwrap();
+        drop(std::panic::take_hook());
+    }
+    // Cannot call unwrap here because the panic hook is not Debug.
+    std::panic::set_hook(match Arc::try_unwrap(panic_hook) {
+        Ok(hook) => hook,
+        _ => panic!("Failed to unwrap and reset previous panic hook."),
+    })
+}
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IKeyMintDevice.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IKeyMintDevice.aidl
index fa643fc..dcc22c4 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IKeyMintDevice.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IKeyMintDevice.aidl
@@ -49,5 +49,8 @@
   void earlyBootEnded();
   byte[] convertStorageKeyToEphemeral(in byte[] storageKeyBlob);
   android.hardware.security.keymint.KeyCharacteristics[] getKeyCharacteristics(in byte[] keyBlob, in byte[] appId, in byte[] appData);
+  byte[16] getRootOfTrustChallenge();
+  byte[] getRootOfTrust(in byte[16] challenge);
+  void sendRootOfTrust(in byte[] rootOfTrust);
   const int AUTH_TOKEN_MAC_LENGTH = 32;
 }
diff --git a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
index 4b63799..da02d54 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
@@ -851,4 +851,82 @@
      */
     KeyCharacteristics[] getKeyCharacteristics(
             in byte[] keyBlob, in byte[] appId, in byte[] appData);
+
+    /**
+     * Returns a 16-byte random challenge nonce, used to prove freshness when exchanging root of
+     * trust data.
+     *
+     * This method may only be implemented by StrongBox KeyMint.  TEE KeyMint implementations must
+     * return ErrorCode::UNIMPLEMENTED.  StrongBox KeyMint implementations MAY return UNIMPLEMENTED,
+     * to indicate that they have an alternative mechanism for getting the data.  If the StrongBox
+     * implementation returns UNIMPLEMENTED, the client should not call `getRootofTrust()` or
+     * `sendRootOfTrust()`.
+     */
+    byte[16] getRootOfTrustChallenge();
+
+    /**
+     * Returns the TEE KeyMint Root of Trust data.
+     *
+     * This method is required for TEE KeyMint.  StrongBox KeyMint implementations MUST return
+     * ErrorCode::UNIMPLEMENTED.
+     *
+     * The returned data is an encoded COSE_Mac0 structure, denoted MacedRootOfTrust in the
+     * following CDDL schema.  Note that K_mac is the shared HMAC key used for auth tokens, etc.:
+     *
+     *     MacedRootOfTrust = [               ; COSE_Mac0 (untagged)
+     *         protected: bstr .cbor {
+     *             1 : 5,                     ; Algorithm : HMAC-256
+     *         },
+     *         unprotected : {},
+     *         payload : bstr .cbor RootOfTrust,
+     *         tag : bstr HMAC-256(K_mac, MAC_structure)
+     *     ]
+     *
+     *     MAC_structure = [
+     *         context : "MAC0",
+     *         protected : bstr .cbor {
+     *             1 : 5,                     ; Algorithm : HMAC-256
+     *         },
+     *         external_aad : bstr .size 16   ; Value of challenge argument
+     *         payload : bstr .cbor RootOfTrust,
+     *     ]
+     *
+     *     RootOfTrust = [
+     *         verifiedBootKey : bstr .size 32,
+     *         deviceLocked : bool,
+     *         verifiedBootState : &VerifiedBootState,
+     *         verifiedBootHash : bstr .size 32,
+     *         bootPatchLevel : int,          ; See Tag::BOOT_PATCHLEVEL
+     *     ]
+     *
+     *     VerifiedBootState = (
+     *         Verified : 0,
+     *         SelfSigned : 1,
+     *         Unverified : 2,
+     *         Failed : 3
+     *     )
+     */
+    byte[] getRootOfTrust(in byte[16] challenge);
+
+    /**
+     * Delivers the TEE KeyMint Root of Trust data to StrongBox KeyMint.  See `getRootOfTrust()`
+     * above for specification of the data format and cryptographic security structure.
+     *
+     * The implementation must verify the MAC on the RootOfTrust data.  If it is valid, and if this
+     * is the first time since reboot that StrongBox KeyMint has received this data, it must store
+     * the RoT data for use in key attestation requests, then return ErrorCode::ERROR_OK.
+     *
+     * If the MAC on the Root of Trust data and challenge is incorrect, the implementation must
+     * return ErrorCode::VERIFICATION_FAILED.
+     *
+     * If the RootOfTrust data has already been received since the last boot, the implementation
+     * must validate the data and return ErrorCode::VERIFICATION_FAILED or ErrorCode::ERROR_OK
+     * according to the result, but must not store the data for use in key attestation requests,
+     * even if verification succeeds.  On success, the challenge is invalidated and a new challenge
+     * must be requested before the RootOfTrust data may be sent again.
+     *
+     * This method is optional for StrongBox KeyMint, which MUST return ErrorCode::UNIMPLEMENTED if
+     * not implemented.  TEE KeyMint implementations must return ErrorCode::UNIMPLEMENTED.
+     */
+    void sendRootOfTrust(in byte[] rootOfTrust);
 }
diff --git a/security/keymint/aidl/default/TEST_MAPPING b/security/keymint/aidl/default/TEST_MAPPING
new file mode 100644
index 0000000..2400ccd
--- /dev/null
+++ b/security/keymint/aidl/default/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "presubmit" : [
+    {
+      "name" : "vts_treble_vintf_framework_test"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/security/keymint/aidl/default/android.hardware.hardware_keystore.xml b/security/keymint/aidl/default/android.hardware.hardware_keystore.xml
index e5a9345..2ebf1fe 100644
--- a/security/keymint/aidl/default/android.hardware.hardware_keystore.xml
+++ b/security/keymint/aidl/default/android.hardware.hardware_keystore.xml
@@ -14,5 +14,5 @@
      limitations under the License.
 -->
 <permissions>
-  <feature name="android.hardware.hardware_keystore" version="100" />
+  <feature name="android.hardware.hardware_keystore" version="200" />
 </permissions>
diff --git a/security/keymint/aidl/default/android.hardware.security.keymint-service.xml b/security/keymint/aidl/default/android.hardware.security.keymint-service.xml
index 4aa05ef..a4d0302 100644
--- a/security/keymint/aidl/default/android.hardware.security.keymint-service.xml
+++ b/security/keymint/aidl/default/android.hardware.security.keymint-service.xml
@@ -1,10 +1,12 @@
 <manifest version="1.0" type="device">
     <hal format="aidl">
         <name>android.hardware.security.keymint</name>
+        <version>2</version>
         <fqname>IKeyMintDevice/default</fqname>
     </hal>
     <hal format="aidl">
         <name>android.hardware.security.keymint</name>
+        <version>2</version>
         <fqname>IRemotelyProvisionedComponent/default</fqname>
     </hal>
 </manifest>
diff --git a/security/keymint/aidl/vts/functional/Android.bp b/security/keymint/aidl/vts/functional/Android.bp
index 91db3c8..ef5b0bd 100644
--- a/security/keymint/aidl/vts/functional/Android.bp
+++ b/security/keymint/aidl/vts/functional/Android.bp
@@ -50,10 +50,14 @@
     defaults: [
         "keymint_vts_defaults",
     ],
+    tidy_timeout_srcs: [
+        "KeyMintTest.cpp",
+    ],
     srcs: [
         "AttestKeyTest.cpp",
         "DeviceUniqueAttestationTest.cpp",
         "KeyMintTest.cpp",
+        "SecureElementProvisioningTest.cpp",
     ],
     static_libs: [
         "libkeymint_vts_test_utils",
@@ -69,6 +73,9 @@
     defaults: [
         "keymint_vts_defaults",
     ],
+    tidy_timeout_srcs: [
+        "KeyMintAidlTestBase.cpp",
+    ],
     srcs: [
         "KeyMintAidlTestBase.cpp",
     ],
diff --git a/security/keymint/aidl/vts/functional/AttestKeyTest.cpp b/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
index 727c6b7..8a26b3c 100644
--- a/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
+++ b/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
@@ -219,18 +219,22 @@
     AttestationKey attest_key;
     vector<KeyCharacteristics> attest_key_characteristics;
     vector<Certificate> attest_key_cert_chain;
-    ASSERT_EQ(ErrorCode::OK,
-              GenerateKey(AuthorizationSetBuilder()
-                                  .RsaKey(2048, 65537)
-                                  .AttestKey()
-                                  .AttestationChallenge(challenge)
-                                  .AttestationApplicationId(app_id)
-                                  .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
-                                  .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
-                                  .Authorization(TAG_NO_AUTH_REQUIRED)
-                                  .SetDefaultValidity(),
-                          {} /* attestation signing key */, &attest_key.keyBlob,
-                          &attest_key_characteristics, &attest_key_cert_chain));
+    auto result = GenerateKey(AuthorizationSetBuilder()
+                                      .RsaKey(2048, 65537)
+                                      .AttestKey()
+                                      .AttestationChallenge(challenge)
+                                      .AttestationApplicationId(app_id)
+                                      .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
+                                      .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
+                                      .Authorization(TAG_NO_AUTH_REQUIRED)
+                                      .SetDefaultValidity(),
+                              {} /* attestation signing key */, &attest_key.keyBlob,
+                              &attest_key_characteristics, &attest_key_cert_chain);
+    // Strongbox may not support factory provisioned attestation key.
+    if (SecLevel() == SecurityLevel::STRONGBOX) {
+        if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) return;
+    }
+    ASSERT_EQ(ErrorCode::OK, result);
 
     EXPECT_GT(attest_key_cert_chain.size(), 1);
     verify_subject_and_serial(attest_key_cert_chain[0], serial_int, subject, false);
@@ -319,18 +323,22 @@
             attest_key_opt = attest_key;
         }
 
-        EXPECT_EQ(ErrorCode::OK,
-                  GenerateKey(AuthorizationSetBuilder()
-                                      .RsaKey(2048, 65537)
-                                      .AttestKey()
-                                      .AttestationChallenge("foo")
-                                      .AttestationApplicationId("bar")
-                                      .Authorization(TAG_NO_AUTH_REQUIRED)
-                                      .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
-                                      .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
-                                      .SetDefaultValidity(),
-                              attest_key_opt, &key_blob_list[i], &attested_key_characteristics,
-                              &cert_chain_list[i]));
+        auto result = GenerateKey(AuthorizationSetBuilder()
+                                          .RsaKey(2048, 65537)
+                                          .AttestKey()
+                                          .AttestationChallenge("foo")
+                                          .AttestationApplicationId("bar")
+                                          .Authorization(TAG_NO_AUTH_REQUIRED)
+                                          .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
+                                          .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
+                                          .SetDefaultValidity(),
+                                  attest_key_opt, &key_blob_list[i], &attested_key_characteristics,
+                                  &cert_chain_list[i]);
+        // Strongbox may not support factory provisioned attestation key.
+        if (SecLevel() == SecurityLevel::STRONGBOX) {
+            if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) return;
+        }
+        ASSERT_EQ(ErrorCode::OK, result);
 
         AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
         AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
@@ -392,18 +400,22 @@
             attest_key_opt = attest_key;
         }
 
-        EXPECT_EQ(ErrorCode::OK,
-                  GenerateKey(AuthorizationSetBuilder()
-                                      .EcdsaKey(EcCurve::P_256)
-                                      .AttestKey()
-                                      .AttestationChallenge("foo")
-                                      .AttestationApplicationId("bar")
-                                      .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
-                                      .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
-                                      .Authorization(TAG_NO_AUTH_REQUIRED)
-                                      .SetDefaultValidity(),
-                              attest_key_opt, &key_blob_list[i], &attested_key_characteristics,
-                              &cert_chain_list[i]));
+        auto result = GenerateKey(AuthorizationSetBuilder()
+                                          .EcdsaKey(EcCurve::P_256)
+                                          .AttestKey()
+                                          .AttestationChallenge("foo")
+                                          .AttestationApplicationId("bar")
+                                          .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
+                                          .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
+                                          .Authorization(TAG_NO_AUTH_REQUIRED)
+                                          .SetDefaultValidity(),
+                                  attest_key_opt, &key_blob_list[i], &attested_key_characteristics,
+                                  &cert_chain_list[i]);
+        // Strongbox may not support factory provisioned attestation key.
+        if (SecLevel() == SecurityLevel::STRONGBOX) {
+            if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) return;
+        }
+        ASSERT_EQ(ErrorCode::OK, result);
 
         AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
         AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
@@ -484,34 +496,37 @@
             attest_key.keyBlob = key_blob_list[i - 1];
             attest_key_opt = attest_key;
         }
-
+        ErrorCode result;
         if ((i & 0x1) == 1) {
-            EXPECT_EQ(ErrorCode::OK,
-                      GenerateKey(AuthorizationSetBuilder()
-                                          .EcdsaKey(EcCurve::P_256)
-                                          .AttestKey()
-                                          .AttestationChallenge("foo")
-                                          .AttestationApplicationId("bar")
-                                          .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
-                                          .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
-                                          .Authorization(TAG_NO_AUTH_REQUIRED)
-                                          .SetDefaultValidity(),
-                                  attest_key_opt, &key_blob_list[i], &attested_key_characteristics,
-                                  &cert_chain_list[i]));
+            result = GenerateKey(AuthorizationSetBuilder()
+                                         .EcdsaKey(EcCurve::P_256)
+                                         .AttestKey()
+                                         .AttestationChallenge("foo")
+                                         .AttestationApplicationId("bar")
+                                         .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
+                                         .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
+                                         .Authorization(TAG_NO_AUTH_REQUIRED)
+                                         .SetDefaultValidity(),
+                                 attest_key_opt, &key_blob_list[i], &attested_key_characteristics,
+                                 &cert_chain_list[i]);
         } else {
-            EXPECT_EQ(ErrorCode::OK,
-                      GenerateKey(AuthorizationSetBuilder()
-                                          .RsaKey(2048, 65537)
-                                          .AttestKey()
-                                          .AttestationChallenge("foo")
-                                          .AttestationApplicationId("bar")
-                                          .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
-                                          .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
-                                          .Authorization(TAG_NO_AUTH_REQUIRED)
-                                          .SetDefaultValidity(),
-                                  attest_key_opt, &key_blob_list[i], &attested_key_characteristics,
-                                  &cert_chain_list[i]));
+            result = GenerateKey(AuthorizationSetBuilder()
+                                         .RsaKey(2048, 65537)
+                                         .AttestKey()
+                                         .AttestationChallenge("foo")
+                                         .AttestationApplicationId("bar")
+                                         .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
+                                         .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
+                                         .Authorization(TAG_NO_AUTH_REQUIRED)
+                                         .SetDefaultValidity(),
+                                 attest_key_opt, &key_blob_list[i], &attested_key_characteristics,
+                                 &cert_chain_list[i]);
         }
+        // Strongbox may not support factory provisioned attestation key.
+        if (SecLevel() == SecurityLevel::STRONGBOX) {
+            if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) return;
+        }
+        ASSERT_EQ(ErrorCode::OK, result);
 
         AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
         AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
diff --git a/security/keymint/aidl/vts/functional/DeviceUniqueAttestationTest.cpp b/security/keymint/aidl/vts/functional/DeviceUniqueAttestationTest.cpp
index d4bbd69..1dc5df3 100644
--- a/security/keymint/aidl/vts/functional/DeviceUniqueAttestationTest.cpp
+++ b/security/keymint/aidl/vts/functional/DeviceUniqueAttestationTest.cpp
@@ -80,6 +80,7 @@
                                       .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)
                                       .Authorization(TAG_INCLUDE_UNIQUE_ID)
                                       .Authorization(TAG_CREATION_DATETIME, 1619621648000)
+                                      .SetDefaultValidity()
                                       .AttestationChallenge("challenge")
                                       .AttestationApplicationId("foo")
                                       .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION),
@@ -109,6 +110,7 @@
                                       .Digest(Digest::SHA_2_256)
                                       .Authorization(TAG_INCLUDE_UNIQUE_ID)
                                       .Authorization(TAG_CREATION_DATETIME, 1619621648000)
+                                      .SetDefaultValidity()
                                       .AttestationChallenge("challenge")
                                       .AttestationApplicationId("foo")
                                       .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION),
@@ -139,6 +141,7 @@
                                       .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)
                                       .Authorization(TAG_INCLUDE_UNIQUE_ID)
                                       .Authorization(TAG_CREATION_DATETIME, 1619621648000)
+                                      .SetDefaultValidity()
                                       .AttestationChallenge("challenge")
                                       .AttestationApplicationId("foo")
                                       .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION),
@@ -197,6 +200,7 @@
                                       .Digest(Digest::SHA_2_256)
                                       .Authorization(TAG_INCLUDE_UNIQUE_ID)
                                       .Authorization(TAG_CREATION_DATETIME, 1619621648000)
+                                      .SetDefaultValidity()
                                       .AttestationChallenge("challenge")
                                       .AttestationApplicationId("foo")
                                       .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION),
@@ -264,6 +268,7 @@
                         .Digest(Digest::SHA_2_256)
                         .Authorization(TAG_INCLUDE_UNIQUE_ID)
                         .Authorization(TAG_CREATION_DATETIME, 1619621648000)
+                        .SetDefaultValidity()
                         .AttestationChallenge("challenge")
                         .AttestationApplicationId("foo")
                         .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION);
@@ -336,6 +341,7 @@
                         .Digest(Digest::SHA_2_256)
                         .Authorization(TAG_INCLUDE_UNIQUE_ID)
                         .Authorization(TAG_CREATION_DATETIME, 1619621648000)
+                        .SetDefaultValidity()
                         .AttestationChallenge("challenge")
                         .AttestationApplicationId("foo")
                         .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION);
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
index 146a527..4ab989b 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
@@ -665,6 +665,81 @@
             AuthorizationSetBuilder().Digest(digest).Authorization(TAG_MAC_LENGTH, mac_length));
 }
 
+void KeyMintAidlTestBase::CheckAesIncrementalEncryptOperation(BlockMode block_mode,
+                                                              int message_size) {
+    auto builder = AuthorizationSetBuilder()
+                           .Authorization(TAG_NO_AUTH_REQUIRED)
+                           .AesEncryptionKey(128)
+                           .BlockMode(block_mode)
+                           .Padding(PaddingMode::NONE);
+    if (block_mode == BlockMode::GCM) {
+        builder.Authorization(TAG_MIN_MAC_LENGTH, 128);
+    }
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(builder));
+
+    for (int increment = 1; increment <= message_size; ++increment) {
+        string message(message_size, 'a');
+        auto params = AuthorizationSetBuilder().BlockMode(block_mode).Padding(PaddingMode::NONE);
+        if (block_mode == BlockMode::GCM) {
+            params.Authorization(TAG_MAC_LENGTH, 128) /* for GCM */;
+        }
+
+        AuthorizationSet output_params;
+        EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params, &output_params));
+
+        string ciphertext;
+        string to_send;
+        for (size_t i = 0; i < message.size(); i += increment) {
+            EXPECT_EQ(ErrorCode::OK, Update(message.substr(i, increment), &ciphertext));
+        }
+        EXPECT_EQ(ErrorCode::OK, Finish(to_send, &ciphertext))
+                << "Error sending " << to_send << " with block mode " << block_mode;
+
+        switch (block_mode) {
+            case BlockMode::GCM:
+                EXPECT_EQ(message.size() + 16, ciphertext.size());
+                break;
+            case BlockMode::CTR:
+                EXPECT_EQ(message.size(), ciphertext.size());
+                break;
+            case BlockMode::CBC:
+            case BlockMode::ECB:
+                EXPECT_EQ(message.size() + message.size() % 16, ciphertext.size());
+                break;
+        }
+
+        auto iv = output_params.GetTagValue(TAG_NONCE);
+        switch (block_mode) {
+            case BlockMode::CBC:
+            case BlockMode::GCM:
+            case BlockMode::CTR:
+                ASSERT_TRUE(iv) << "No IV for block mode " << block_mode;
+                EXPECT_EQ(block_mode == BlockMode::GCM ? 12U : 16U, iv->get().size());
+                params.push_back(TAG_NONCE, iv->get());
+                break;
+
+            case BlockMode::ECB:
+                EXPECT_FALSE(iv) << "ECB mode should not generate IV";
+                break;
+        }
+
+        EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, params))
+                << "Decrypt begin() failed for block mode " << block_mode;
+
+        string plaintext;
+        for (size_t i = 0; i < ciphertext.size(); i += increment) {
+            EXPECT_EQ(ErrorCode::OK, Update(ciphertext.substr(i, increment), &plaintext));
+        }
+        ErrorCode error = Finish(to_send, &plaintext);
+        ASSERT_EQ(ErrorCode::OK, error) << "Decryption failed for block mode " << block_mode
+                                        << " and increment " << increment;
+        if (error == ErrorCode::OK) {
+            ASSERT_EQ(message, plaintext) << "Decryption didn't match for block mode " << block_mode
+                                          << " and increment " << increment;
+        }
+    }
+}
+
 void KeyMintAidlTestBase::CheckHmacTestVector(const string& key, const string& message,
                                               Digest digest, const string& expected_mac) {
     SCOPED_TRACE("CheckHmacTestVector");
@@ -1228,6 +1303,14 @@
     }
 }
 
+vector<uint64_t> KeyMintAidlTestBase::ValidExponents() {
+    if (SecLevel() == SecurityLevel::STRONGBOX) {
+        return {65537};
+    } else {
+        return {3, 65537};
+    }
+}
+
 vector<Digest> KeyMintAidlTestBase::ValidDigests(bool withNone, bool withMD5) {
     switch (SecLevel()) {
         case SecurityLevel::SOFTWARE:
@@ -1536,7 +1619,7 @@
         EXPECT_EQ(verified_boot_state, VerifiedBoot::FAILED);
     } else {
         EXPECT_EQ(verified_boot_state, VerifiedBoot::UNVERIFIED);
-        EXPECT_NE(0, memcmp(verified_boot_key.data(), empty_boot_key.data(),
+        EXPECT_EQ(0, memcmp(verified_boot_key.data(), empty_boot_key.data(),
                             verified_boot_key.size()));
     }
 
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
index 27cb99c..e59443c 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
@@ -169,6 +169,8 @@
 
     string MacMessage(const string& message, Digest digest, size_t mac_length);
 
+    void CheckAesIncrementalEncryptOperation(BlockMode block_mode, int message_size);
+
     void CheckHmacTestVector(const string& key, const string& message, Digest digest,
                              const string& expected_mac);
 
@@ -253,7 +255,10 @@
                                                      .SetDefaultValidity();
         tagModifier(&rsaBuilder);
         errorCode = GenerateKey(rsaBuilder, &rsaKeyData.blob, &rsaKeyData.characteristics);
-        EXPECT_EQ(expectedReturn, errorCode);
+        if (!(SecLevel() == SecurityLevel::STRONGBOX &&
+              ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED == errorCode)) {
+            EXPECT_EQ(expectedReturn, errorCode);
+        }
 
         /* ECDSA */
         KeyData ecdsaKeyData;
@@ -265,7 +270,10 @@
                                                        .SetDefaultValidity();
         tagModifier(&ecdsaBuilder);
         errorCode = GenerateKey(ecdsaBuilder, &ecdsaKeyData.blob, &ecdsaKeyData.characteristics);
-        EXPECT_EQ(expectedReturn, errorCode);
+        if (!(SecLevel() == SecurityLevel::STRONGBOX &&
+              ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED == errorCode)) {
+            EXPECT_EQ(expectedReturn, errorCode);
+        }
         return {aesKeyData, hmacKeyData, rsaKeyData, ecdsaKeyData};
     }
     bool IsSecure() const { return securityLevel_ != SecurityLevel::SOFTWARE; }
@@ -282,6 +290,7 @@
     vector<EcCurve> InvalidCurves();
 
     vector<Digest> ValidDigests(bool withNone, bool withMD5);
+    vector<uint64_t> ValidExponents();
 
     static vector<string> build_params() {
         auto params = ::android::getAidlHalInstanceNames(IKeyMintDevice::descriptor);
diff --git a/security/keymint/aidl/vts/functional/KeyMintTest.cpp b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
index 62f22bb..c734c37 100644
--- a/security/keymint/aidl/vts/functional/KeyMintTest.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
@@ -1018,6 +1018,37 @@
 }
 
 /*
+ * NewKeyGenerationTest.RsaWithMissingValidity
+ *
+ * Verifies that keymint returns an error while generating asymmetric key
+ * without providing NOT_BEFORE and NOT_AFTER parameters.
+ */
+TEST_P(NewKeyGenerationTest, RsaWithMissingValidity) {
+    // Per RFC 5280 4.1.2.5, an undefined expiration (not-after) field should be set to
+    // GeneralizedTime 999912312359559, which is 253402300799000 ms from Jan 1, 1970.
+    constexpr uint64_t kUndefinedExpirationDateTime = 253402300799000;
+
+    vector<uint8_t> key_blob;
+    vector<KeyCharacteristics> key_characteristics;
+    ASSERT_EQ(ErrorCode::MISSING_NOT_BEFORE,
+              GenerateKey(AuthorizationSetBuilder()
+                                  .RsaSigningKey(2048, 65537)
+                                  .Digest(Digest::NONE)
+                                  .Padding(PaddingMode::NONE)
+                                  .Authorization(TAG_CERTIFICATE_NOT_AFTER,
+                                                 kUndefinedExpirationDateTime),
+                          &key_blob, &key_characteristics));
+
+    ASSERT_EQ(ErrorCode::MISSING_NOT_AFTER,
+              GenerateKey(AuthorizationSetBuilder()
+                                  .RsaSigningKey(2048, 65537)
+                                  .Digest(Digest::NONE)
+                                  .Padding(PaddingMode::NONE)
+                                  .Authorization(TAG_CERTIFICATE_NOT_BEFORE, 0),
+                          &key_blob, &key_characteristics));
+}
+
+/*
  * NewKeyGenerationTest.RsaWithAttestation
  *
  * Verifies that keymint can generate all required RSA key sizes with attestation, and that the
@@ -1036,18 +1067,21 @@
     for (auto key_size : ValidKeySizes(Algorithm::RSA)) {
         vector<uint8_t> key_blob;
         vector<KeyCharacteristics> key_characteristics;
-        ASSERT_EQ(ErrorCode::OK,
-                  GenerateKey(AuthorizationSetBuilder()
-                                      .RsaSigningKey(key_size, 65537)
-                                      .Digest(Digest::NONE)
-                                      .Padding(PaddingMode::NONE)
-                                      .AttestationChallenge(challenge)
-                                      .AttestationApplicationId(app_id)
-                                      .Authorization(TAG_NO_AUTH_REQUIRED)
-                                      .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
-                                      .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
-                                      .SetDefaultValidity(),
-                              &key_blob, &key_characteristics));
+        auto result = GenerateKey(AuthorizationSetBuilder()
+                                          .RsaSigningKey(key_size, 65537)
+                                          .Digest(Digest::NONE)
+                                          .Padding(PaddingMode::NONE)
+                                          .AttestationChallenge(challenge)
+                                          .AttestationApplicationId(app_id)
+                                          .Authorization(TAG_NO_AUTH_REQUIRED)
+                                          .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
+                                          .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
+                                          .SetDefaultValidity(),
+                                  &key_blob, &key_characteristics);
+        // Strongbox may not support factory provisioned attestation key.
+        if (SecLevel() == SecurityLevel::STRONGBOX) {
+            if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) return;
+        }
 
         ASSERT_GT(key_blob.size(), 0U);
         CheckBaseParams(key_characteristics);
@@ -1169,17 +1203,21 @@
 
     vector<uint8_t> key_blob;
     vector<KeyCharacteristics> key_characteristics;
-    ASSERT_EQ(ErrorCode::OK,
-              GenerateKey(AuthorizationSetBuilder()
-                                  .RsaEncryptionKey(key_size, 65537)
-                                  .Padding(PaddingMode::NONE)
-                                  .AttestationChallenge(challenge)
-                                  .AttestationApplicationId(app_id)
-                                  .Authorization(TAG_NO_AUTH_REQUIRED)
-                                  .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
-                                  .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
-                                  .SetDefaultValidity(),
-                          &key_blob, &key_characteristics));
+    auto result = GenerateKey(AuthorizationSetBuilder()
+                                      .RsaEncryptionKey(key_size, 65537)
+                                      .Padding(PaddingMode::NONE)
+                                      .AttestationChallenge(challenge)
+                                      .AttestationApplicationId(app_id)
+                                      .Authorization(TAG_NO_AUTH_REQUIRED)
+                                      .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
+                                      .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
+                                      .SetDefaultValidity(),
+                              &key_blob, &key_characteristics);
+    // Strongbox may not support factory provisioned attestation key.
+    if (SecLevel() == SecurityLevel::STRONGBOX) {
+        if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) return;
+    }
+    ASSERT_EQ(ErrorCode::OK, result);
 
     ASSERT_GT(key_blob.size(), 0U);
     AuthorizationSet auths;
@@ -1281,15 +1319,19 @@
     vector<uint8_t> key_blob;
     vector<KeyCharacteristics> key_characteristics;
 
-    ASSERT_EQ(ErrorCode::ATTESTATION_APPLICATION_ID_MISSING,
-              GenerateKey(AuthorizationSetBuilder()
-                                  .RsaSigningKey(2048, 65537)
-                                  .Digest(Digest::NONE)
-                                  .Padding(PaddingMode::NONE)
-                                  .AttestationChallenge(challenge)
-                                  .Authorization(TAG_NO_AUTH_REQUIRED)
-                                  .SetDefaultValidity(),
-                          &key_blob, &key_characteristics));
+    auto result = GenerateKey(AuthorizationSetBuilder()
+                                      .RsaSigningKey(2048, 65537)
+                                      .Digest(Digest::NONE)
+                                      .Padding(PaddingMode::NONE)
+                                      .AttestationChallenge(challenge)
+                                      .Authorization(TAG_NO_AUTH_REQUIRED)
+                                      .SetDefaultValidity(),
+                              &key_blob, &key_characteristics);
+    // Strongbox may not support factory provisioned attestation key.
+    if (SecLevel() == SecurityLevel::STRONGBOX) {
+        if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) return;
+    }
+    ASSERT_EQ(ErrorCode::ATTESTATION_APPLICATION_ID_MISSING, result);
 }
 
 /*
@@ -1399,19 +1441,23 @@
     for (auto key_size : ValidKeySizes(Algorithm::RSA)) {
         vector<uint8_t> key_blob;
         vector<KeyCharacteristics> key_characteristics;
-        ASSERT_EQ(ErrorCode::OK,
-                  GenerateKey(AuthorizationSetBuilder()
-                                      .RsaSigningKey(key_size, 65537)
-                                      .Digest(Digest::NONE)
-                                      .Padding(PaddingMode::NONE)
-                                      .AttestationChallenge(challenge)
-                                      .AttestationApplicationId(app_id)
-                                      .Authorization(TAG_NO_AUTH_REQUIRED)
-                                      .Authorization(TAG_USAGE_COUNT_LIMIT, 1)
-                                      .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
-                                      .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
-                                      .SetDefaultValidity(),
-                              &key_blob, &key_characteristics));
+        auto result = GenerateKey(AuthorizationSetBuilder()
+                                          .RsaSigningKey(key_size, 65537)
+                                          .Digest(Digest::NONE)
+                                          .Padding(PaddingMode::NONE)
+                                          .AttestationChallenge(challenge)
+                                          .AttestationApplicationId(app_id)
+                                          .Authorization(TAG_NO_AUTH_REQUIRED)
+                                          .Authorization(TAG_USAGE_COUNT_LIMIT, 1)
+                                          .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
+                                          .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
+                                          .SetDefaultValidity(),
+                                  &key_blob, &key_characteristics);
+        // Strongbox may not support factory provisioned attestation key.
+        if (SecLevel() == SecurityLevel::STRONGBOX) {
+            if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) return;
+        }
+        ASSERT_EQ(ErrorCode::OK, result);
 
         ASSERT_GT(key_blob.size(), 0U);
         CheckBaseParams(key_characteristics);
@@ -1583,6 +1629,35 @@
 }
 
 /*
+ * NewKeyGenerationTest.EcdsaWithMissingValidity
+ *
+ * Verifies that keymint returns an error while generating asymmetric key
+ * without providing NOT_BEFORE and NOT_AFTER parameters.
+ */
+TEST_P(NewKeyGenerationTest, EcdsaWithMissingValidity) {
+    // Per RFC 5280 4.1.2.5, an undefined expiration (not-after) field should be set to
+    // GeneralizedTime 999912312359559, which is 253402300799000 ms from Jan 1, 1970.
+    constexpr uint64_t kUndefinedExpirationDateTime = 253402300799000;
+
+    vector<uint8_t> key_blob;
+    vector<KeyCharacteristics> key_characteristics;
+    ASSERT_EQ(ErrorCode::MISSING_NOT_BEFORE,
+              GenerateKey(AuthorizationSetBuilder()
+                                  .EcdsaSigningKey(EcCurve::P_256)
+                                  .Digest(Digest::NONE)
+                                  .Authorization(TAG_CERTIFICATE_NOT_AFTER,
+                                                 kUndefinedExpirationDateTime),
+                          &key_blob, &key_characteristics));
+
+    ASSERT_EQ(ErrorCode::MISSING_NOT_AFTER,
+              GenerateKey(AuthorizationSetBuilder()
+                                  .EcdsaSigningKey(EcCurve::P_256)
+                                  .Digest(Digest::NONE)
+                                  .Authorization(TAG_CERTIFICATE_NOT_BEFORE, 0),
+                          &key_blob, &key_characteristics));
+}
+
+/*
  * NewKeyGenerationTest.EcdsaAttestation
  *
  * Verifies that for all Ecdsa key sizes, if challenge and app id is provided,
@@ -1601,17 +1676,21 @@
     for (auto curve : ValidCurves()) {
         vector<uint8_t> key_blob;
         vector<KeyCharacteristics> key_characteristics;
-        ASSERT_EQ(ErrorCode::OK,
-                  GenerateKey(AuthorizationSetBuilder()
-                                      .Authorization(TAG_NO_AUTH_REQUIRED)
-                                      .EcdsaSigningKey(curve)
-                                      .Digest(Digest::NONE)
-                                      .AttestationChallenge(challenge)
-                                      .AttestationApplicationId(app_id)
-                                      .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
-                                      .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
-                                      .SetDefaultValidity(),
-                              &key_blob, &key_characteristics));
+        auto result = GenerateKey(AuthorizationSetBuilder()
+                                          .Authorization(TAG_NO_AUTH_REQUIRED)
+                                          .EcdsaSigningKey(curve)
+                                          .Digest(Digest::NONE)
+                                          .AttestationChallenge(challenge)
+                                          .AttestationApplicationId(app_id)
+                                          .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
+                                          .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
+                                          .SetDefaultValidity(),
+                                  &key_blob, &key_characteristics);
+        // Strongbox may not support factory provisioned attestation key.
+        if (SecLevel() == SecurityLevel::STRONGBOX) {
+            if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) return;
+        }
+        ASSERT_EQ(ErrorCode::OK, result);
         ASSERT_GT(key_blob.size(), 0U);
         CheckBaseParams(key_characteristics);
         CheckCharacteristics(key_blob, key_characteristics);
@@ -1745,6 +1824,10 @@
             // Tag not required to be supported by all KeyMint implementations.
             continue;
         }
+        // Strongbox may not support factory provisioned attestation key.
+        if (SecLevel() == SecurityLevel::STRONGBOX) {
+            if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) return;
+        }
         ASSERT_EQ(result, ErrorCode::OK);
         ASSERT_GT(key_blob.size(), 0U);
 
@@ -1840,6 +1923,10 @@
         AuthorizationSetBuilder builder = base_builder;
         builder.push_back(tag);
         auto result = GenerateKey(builder, &key_blob, &key_characteristics);
+        // Strongbox may not support factory provisioned attestation key.
+        if (SecLevel() == SecurityLevel::STRONGBOX) {
+            if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) return;
+        }
         if (result == ErrorCode::CANNOT_ATTEST_IDS) {
             // Device ID attestation is optional; KeyMint may not support it at all.
             continue;
@@ -1997,6 +2084,10 @@
                                       .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
                                       .SetDefaultValidity(),
                               &key_blob, &key_characteristics);
+    // Strongbox may not support factory provisioned attestation key.
+    if (SecLevel() == SecurityLevel::STRONGBOX) {
+        if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) return;
+    }
     ASSERT_EQ(result, ErrorCode::OK);
     ASSERT_GT(key_blob.size(), 0U);
 
@@ -2076,13 +2167,17 @@
     vector<uint8_t> key_blob;
     vector<KeyCharacteristics> key_characteristics;
 
-    ASSERT_EQ(ErrorCode::ATTESTATION_APPLICATION_ID_MISSING,
-              GenerateKey(AuthorizationSetBuilder()
-                                  .EcdsaSigningKey(EcCurve::P_256)
-                                  .Digest(Digest::NONE)
-                                  .AttestationChallenge(challenge)
-                                  .SetDefaultValidity(),
-                          &key_blob, &key_characteristics));
+    auto result = GenerateKey(AuthorizationSetBuilder()
+                                      .EcdsaSigningKey(EcCurve::P_256)
+                                      .Digest(Digest::NONE)
+                                      .AttestationChallenge(challenge)
+                                      .SetDefaultValidity(),
+                              &key_blob, &key_characteristics);
+    // Strongbox may not support factory provisioned attestation key.
+    if (SecLevel() == SecurityLevel::STRONGBOX) {
+        if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) return;
+    }
+    ASSERT_EQ(ErrorCode::ATTESTATION_APPLICATION_ID_MISSING, result);
 }
 
 /*
@@ -2139,14 +2234,19 @@
         const string app_id(length, 'a');
         vector<uint8_t> key_blob;
         vector<KeyCharacteristics> key_characteristics;
-        ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
-                                                     .Authorization(TAG_NO_AUTH_REQUIRED)
-                                                     .EcdsaSigningKey(EcCurve::P_256)
-                                                     .Digest(Digest::NONE)
-                                                     .AttestationChallenge(challenge)
-                                                     .AttestationApplicationId(app_id)
-                                                     .SetDefaultValidity(),
-                                             &key_blob, &key_characteristics));
+        auto result = GenerateKey(AuthorizationSetBuilder()
+                                          .Authorization(TAG_NO_AUTH_REQUIRED)
+                                          .EcdsaSigningKey(EcCurve::P_256)
+                                          .Digest(Digest::NONE)
+                                          .AttestationChallenge(challenge)
+                                          .AttestationApplicationId(app_id)
+                                          .SetDefaultValidity(),
+                                  &key_blob, &key_characteristics);
+        // Strongbox may not support factory provisioned attestation key.
+        if (SecLevel() == SecurityLevel::STRONGBOX) {
+            if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) return;
+        }
+        ASSERT_EQ(ErrorCode::OK, result);
         ASSERT_GT(key_blob.size(), 0U);
         CheckBaseParams(key_characteristics);
         CheckCharacteristics(key_blob, key_characteristics);
@@ -4646,7 +4746,7 @@
  * Verifies that raw RSA decryption works.
  */
 TEST_P(EncryptionOperationsTest, RsaNoPaddingSuccess) {
-    for (uint64_t exponent : {3, 65537}) {
+    for (uint64_t exponent : ValidExponents()) {
         ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
                                                      .Authorization(TAG_NO_AUTH_REQUIRED)
                                                      .RsaEncryptionKey(2048, exponent)
@@ -5341,89 +5441,39 @@
 }
 
 /*
- * EncryptionOperationsTest.AesIncremental
+ * EncryptionOperationsTest.AesEcbIncremental
  *
- * Verifies that AES works, all modes, when provided data in various size increments.
+ * Verifies that AES works for ECB block mode, when provided data in various size increments.
  */
-TEST_P(EncryptionOperationsTest, AesIncremental) {
-    auto block_modes = {
-            BlockMode::ECB,
-            BlockMode::CBC,
-            BlockMode::CTR,
-            BlockMode::GCM,
-    };
+TEST_P(EncryptionOperationsTest, AesEcbIncremental) {
+    CheckAesIncrementalEncryptOperation(BlockMode::ECB, 240);
+}
 
-    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
-                                                 .Authorization(TAG_NO_AUTH_REQUIRED)
-                                                 .AesEncryptionKey(128)
-                                                 .BlockMode(block_modes)
-                                                 .Padding(PaddingMode::NONE)
-                                                 .Authorization(TAG_MIN_MAC_LENGTH, 128)));
+/*
+ * EncryptionOperationsTest.AesCbcIncremental
+ *
+ * Verifies that AES works for CBC block mode, when provided data in various size increments.
+ */
+TEST_P(EncryptionOperationsTest, AesCbcIncremental) {
+    CheckAesIncrementalEncryptOperation(BlockMode::CBC, 240);
+}
 
-    for (int increment = 1; increment <= 240; ++increment) {
-        for (auto block_mode : block_modes) {
-            string message(240, 'a');
-            auto params =
-                    AuthorizationSetBuilder().BlockMode(block_mode).Padding(PaddingMode::NONE);
-            if (block_mode == BlockMode::GCM) {
-                params.Authorization(TAG_MAC_LENGTH, 128) /* for GCM */;
-            }
+/*
+ * EncryptionOperationsTest.AesCtrIncremental
+ *
+ * Verifies that AES works for CTR block mode, when provided data in various size increments.
+ */
+TEST_P(EncryptionOperationsTest, AesCtrIncremental) {
+    CheckAesIncrementalEncryptOperation(BlockMode::CTR, 240);
+}
 
-            AuthorizationSet output_params;
-            EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params, &output_params));
-
-            string ciphertext;
-            string to_send;
-            for (size_t i = 0; i < message.size(); i += increment) {
-                EXPECT_EQ(ErrorCode::OK, Update(message.substr(i, increment), &ciphertext));
-            }
-            EXPECT_EQ(ErrorCode::OK, Finish(to_send, &ciphertext))
-                    << "Error sending " << to_send << " with block mode " << block_mode;
-
-            switch (block_mode) {
-                case BlockMode::GCM:
-                    EXPECT_EQ(message.size() + 16, ciphertext.size());
-                    break;
-                case BlockMode::CTR:
-                    EXPECT_EQ(message.size(), ciphertext.size());
-                    break;
-                case BlockMode::CBC:
-                case BlockMode::ECB:
-                    EXPECT_EQ(message.size() + message.size() % 16, ciphertext.size());
-                    break;
-            }
-
-            auto iv = output_params.GetTagValue(TAG_NONCE);
-            switch (block_mode) {
-                case BlockMode::CBC:
-                case BlockMode::GCM:
-                case BlockMode::CTR:
-                    ASSERT_TRUE(iv) << "No IV for block mode " << block_mode;
-                    EXPECT_EQ(block_mode == BlockMode::GCM ? 12U : 16U, iv->get().size());
-                    params.push_back(TAG_NONCE, iv->get());
-                    break;
-
-                case BlockMode::ECB:
-                    EXPECT_FALSE(iv) << "ECB mode should not generate IV";
-                    break;
-            }
-
-            EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, params))
-                    << "Decrypt begin() failed for block mode " << block_mode;
-
-            string plaintext;
-            for (size_t i = 0; i < ciphertext.size(); i += increment) {
-                EXPECT_EQ(ErrorCode::OK, Update(ciphertext.substr(i, increment), &plaintext));
-            }
-            ErrorCode error = Finish(to_send, &plaintext);
-            ASSERT_EQ(ErrorCode::OK, error) << "Decryption failed for block mode " << block_mode
-                                            << " and increment " << increment;
-            if (error == ErrorCode::OK) {
-                ASSERT_EQ(message, plaintext) << "Decryption didn't match for block mode "
-                                              << block_mode << " and increment " << increment;
-            }
-        }
-    }
+/*
+ * EncryptionOperationsTest.AesGcmIncremental
+ *
+ * Verifies that AES works for GCM block mode, when provided data in various size increments.
+ */
+TEST_P(EncryptionOperationsTest, AesGcmIncremental) {
+    CheckAesIncrementalEncryptOperation(BlockMode::GCM, 240);
 }
 
 struct AesCtrSp80038aTestVector {
@@ -7209,7 +7259,7 @@
     size_t i;
 
     for (i = 0; i < max_operations; i++) {
-        result = Begin(KeyPurpose::ENCRYPT, key_blob_, params, &out_params, op_handles[i]);
+        result = Begin(KeyPurpose::DECRYPT, key_blob_, params, &out_params, op_handles[i]);
         if (ErrorCode::OK != result) {
             break;
         }
@@ -7217,12 +7267,12 @@
     EXPECT_EQ(ErrorCode::TOO_MANY_OPERATIONS, result);
     // Try again just in case there's a weird overflow bug
     EXPECT_EQ(ErrorCode::TOO_MANY_OPERATIONS,
-              Begin(KeyPurpose::ENCRYPT, key_blob_, params, &out_params));
+              Begin(KeyPurpose::DECRYPT, key_blob_, params, &out_params));
     for (size_t j = 0; j < i; j++) {
         EXPECT_EQ(ErrorCode::OK, Abort(op_handles[j]))
                 << "Aboort failed for i = " << j << std::endl;
     }
-    EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, key_blob_, params, &out_params));
+    EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, key_blob_, params, &out_params));
     AbortIfNeeded();
 }
 
@@ -7611,14 +7661,23 @@
             });
 
     for (const auto& keyData : {aesKeyData, hmacKeyData, rsaKeyData, ecdsaKeyData}) {
+        // Strongbox may not support factory attestation. Key creation might fail with
+        // ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED
+        if (SecLevel() == SecurityLevel::STRONGBOX && keyData.blob.size() == 0U) {
+            continue;
+        }
         ASSERT_GT(keyData.blob.size(), 0U);
         AuthorizationSet crypto_params = SecLevelAuthorizations(keyData.characteristics);
         EXPECT_TRUE(crypto_params.Contains(TAG_EARLY_BOOT_ONLY)) << crypto_params;
     }
     CheckedDeleteKey(&aesKeyData.blob);
     CheckedDeleteKey(&hmacKeyData.blob);
-    CheckedDeleteKey(&rsaKeyData.blob);
-    CheckedDeleteKey(&ecdsaKeyData.blob);
+    if (rsaKeyData.blob.size() != 0U) {
+        CheckedDeleteKey(&rsaKeyData.blob);
+    }
+    if (ecdsaKeyData.blob.size() != 0U) {
+        CheckedDeleteKey(&ecdsaKeyData.blob);
+    }
 }
 
 /*
diff --git a/security/keymint/aidl/vts/functional/SecureElementProvisioningTest.cpp b/security/keymint/aidl/vts/functional/SecureElementProvisioningTest.cpp
new file mode 100644
index 0000000..6f13867
--- /dev/null
+++ b/security/keymint/aidl/vts/functional/SecureElementProvisioningTest.cpp
@@ -0,0 +1,279 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "keymint_2_se_provisioning_test"
+
+#include <map>
+#include <memory>
+#include <vector>
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+
+#include <cppbor_parse.h>
+#include <keymaster/cppcose/cppcose.h>
+#include <keymint_support/key_param_output.h>
+
+#include "KeyMintAidlTestBase.h"
+
+namespace aidl::android::hardware::security::keymint::test {
+
+using std::array;
+using std::map;
+using std::shared_ptr;
+using std::vector;
+
+class SecureElementProvisioningTest : public testing::Test {
+  protected:
+    static void SetUpTestSuite() {
+        auto params = ::android::getAidlHalInstanceNames(IKeyMintDevice::descriptor);
+        for (auto& param : params) {
+            ASSERT_TRUE(AServiceManager_isDeclared(param.c_str()))
+                    << "IKeyMintDevice instance " << param << " found but not declared.";
+            ::ndk::SpAIBinder binder(AServiceManager_waitForService(param.c_str()));
+            auto keymint = IKeyMintDevice::fromBinder(binder);
+            ASSERT_NE(keymint, nullptr) << "Failed to get IKeyMintDevice instance " << param;
+
+            KeyMintHardwareInfo info;
+            ASSERT_TRUE(keymint->getHardwareInfo(&info).isOk());
+            ASSERT_EQ(keymints_.count(info.securityLevel), 0)
+                    << "There must be exactly one IKeyMintDevice with security level "
+                    << info.securityLevel;
+
+            keymints_[info.securityLevel] = std::move(keymint);
+        }
+    }
+
+    static map<SecurityLevel, shared_ptr<IKeyMintDevice>> keymints_;
+};
+
+map<SecurityLevel, shared_ptr<IKeyMintDevice>> SecureElementProvisioningTest::keymints_;
+
+TEST_F(SecureElementProvisioningTest, ValidConfigurations) {
+    if (keymints_.empty()) {
+        GTEST_SKIP() << "Test not applicable to device with no KeyMint devices";
+    }
+    // TEE is required
+    ASSERT_EQ(keymints_.count(SecurityLevel::TRUSTED_ENVIRONMENT), 1);
+    // StrongBox is optional
+    ASSERT_LE(keymints_.count(SecurityLevel::STRONGBOX), 1);
+}
+
+TEST_F(SecureElementProvisioningTest, TeeOnly) {
+    if (keymints_.empty()) {
+        GTEST_SKIP() << "Test not applicable to device with no KeyMint devices";
+    }
+    ASSERT_EQ(keymints_.count(SecurityLevel::TRUSTED_ENVIRONMENT), 1);
+    auto tee = keymints_.find(SecurityLevel::TRUSTED_ENVIRONMENT)->second;
+    ASSERT_NE(tee, nullptr);
+
+    array<uint8_t, 16> challenge1 = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+    array<uint8_t, 16> challenge2 = {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+    vector<uint8_t> rootOfTrust1;
+    Status result = tee->getRootOfTrust(challenge1, &rootOfTrust1);
+
+    // TODO: Remove the next line to require TEEs to succeed.
+    if (!result.isOk()) return;
+
+    ASSERT_TRUE(result.isOk());
+
+    // TODO:  Parse and validate rootOfTrust1 here
+
+    vector<uint8_t> rootOfTrust2;
+    result = tee->getRootOfTrust(challenge2, &rootOfTrust2);
+    ASSERT_TRUE(result.isOk());
+
+    // TODO:  Parse and validate rootOfTrust2 here
+
+    ASSERT_NE(rootOfTrust1, rootOfTrust2);
+
+    vector<uint8_t> rootOfTrust3;
+    result = tee->getRootOfTrust(challenge1, &rootOfTrust3);
+    ASSERT_TRUE(result.isOk());
+
+    ASSERT_EQ(rootOfTrust1, rootOfTrust3);
+
+    // TODO:  Parse and validate rootOfTrust3 here
+}
+
+TEST_F(SecureElementProvisioningTest, TeeDoesNotImplementStrongBoxMethods) {
+    if (keymints_.empty()) {
+        GTEST_SKIP() << "Test not applicable to device with no KeyMint devices";
+    }
+    ASSERT_EQ(keymints_.count(SecurityLevel::TRUSTED_ENVIRONMENT), 1);
+    auto tee = keymints_.find(SecurityLevel::TRUSTED_ENVIRONMENT)->second;
+    ASSERT_NE(tee, nullptr);
+
+    array<uint8_t, 16> challenge;
+    Status result = tee->getRootOfTrustChallenge(&challenge);
+    ASSERT_FALSE(result.isOk());
+    ASSERT_EQ(result.getExceptionCode(), EX_SERVICE_SPECIFIC);
+    ASSERT_EQ(static_cast<ErrorCode>(result.getServiceSpecificError()), ErrorCode::UNIMPLEMENTED);
+
+    result = tee->sendRootOfTrust({});
+    ASSERT_FALSE(result.isOk());
+    ASSERT_EQ(result.getExceptionCode(), EX_SERVICE_SPECIFIC);
+    ASSERT_EQ(static_cast<ErrorCode>(result.getServiceSpecificError()), ErrorCode::UNIMPLEMENTED);
+}
+
+TEST_F(SecureElementProvisioningTest, StrongBoxDoesNotImplementTeeMethods) {
+    if (keymints_.count(SecurityLevel::STRONGBOX) == 0) {
+        // Need a StrongBox to provision.
+        GTEST_SKIP() << "Test not applicable to device with no StrongBox KeyMint device";
+    }
+
+    auto sb = keymints_.find(SecurityLevel::STRONGBOX)->second;
+    ASSERT_NE(sb, nullptr);
+
+    vector<uint8_t> rootOfTrust;
+    Status result = sb->getRootOfTrust({}, &rootOfTrust);
+    ASSERT_FALSE(result.isOk());
+    ASSERT_EQ(result.getExceptionCode(), EX_SERVICE_SPECIFIC);
+    ASSERT_EQ(static_cast<ErrorCode>(result.getServiceSpecificError()), ErrorCode::UNIMPLEMENTED);
+}
+
+TEST_F(SecureElementProvisioningTest, UnimplementedTest) {
+    if (keymints_.count(SecurityLevel::STRONGBOX) == 0) {
+        // Need a StrongBox to provision.
+        GTEST_SKIP() << "Test not applicable to device with no StrongBox KeyMint device";
+    }
+
+    ASSERT_EQ(keymints_.count(SecurityLevel::TRUSTED_ENVIRONMENT), 1);
+    auto tee = keymints_.find(SecurityLevel::TRUSTED_ENVIRONMENT)->second;
+    ASSERT_NE(tee, nullptr);
+
+    ASSERT_EQ(keymints_.count(SecurityLevel::STRONGBOX), 1);
+    auto sb = keymints_.find(SecurityLevel::STRONGBOX)->second;
+    ASSERT_NE(sb, nullptr);
+
+    array<uint8_t, 16> challenge;
+    Status result = sb->getRootOfTrustChallenge(&challenge);
+    if (!result.isOk()) {
+        // Strongbox does not have to implement this feature if it has uses an alternative mechanism
+        // to provision the root of trust.  In that case it MUST return UNIMPLEMENTED, both from
+        // getRootOfTrustChallenge() and from sendRootOfTrust().
+        ASSERT_EQ(result.getExceptionCode(), EX_SERVICE_SPECIFIC);
+        ASSERT_EQ(static_cast<ErrorCode>(result.getServiceSpecificError()),
+                  ErrorCode::UNIMPLEMENTED);
+
+        result = sb->sendRootOfTrust({});
+        ASSERT_EQ(result.getExceptionCode(), EX_SERVICE_SPECIFIC);
+        ASSERT_EQ(static_cast<ErrorCode>(result.getServiceSpecificError()),
+                  ErrorCode::UNIMPLEMENTED);
+
+        SUCCEED() << "This Strongbox implementation does not use late root of trust delivery.";
+        return;
+    }
+}
+
+TEST_F(SecureElementProvisioningTest, ChallengeQualityTest) {
+    if (keymints_.count(SecurityLevel::STRONGBOX) == 0) {
+        // Need a StrongBox to provision.
+        GTEST_SKIP() << "Test not applicable to device with no StrongBox KeyMint device";
+    }
+
+    ASSERT_EQ(keymints_.count(SecurityLevel::STRONGBOX), 1);
+    auto sb = keymints_.find(SecurityLevel::STRONGBOX)->second;
+    ASSERT_NE(sb, nullptr);
+
+    array<uint8_t, 16> challenge1;
+    Status result = sb->getRootOfTrustChallenge(&challenge1);
+    if (!result.isOk()) return;
+
+    array<uint8_t, 16> challenge2;
+    result = sb->getRootOfTrustChallenge(&challenge2);
+    ASSERT_TRUE(result.isOk());
+    ASSERT_NE(challenge1, challenge2);
+
+    // TODO: When we add entropy testing in other relevant places in these tests, add it here, too,
+    // to verify that challenges appear to have adequate entropy.
+}
+
+TEST_F(SecureElementProvisioningTest, ProvisioningTest) {
+    if (keymints_.count(SecurityLevel::STRONGBOX) == 0) {
+        // Need a StrongBox to provision.
+        GTEST_SKIP() << "Test not applicable to device with no StrongBox KeyMint device";
+    }
+
+    ASSERT_EQ(keymints_.count(SecurityLevel::TRUSTED_ENVIRONMENT), 1);
+    auto tee = keymints_.find(SecurityLevel::TRUSTED_ENVIRONMENT)->second;
+    ASSERT_NE(tee, nullptr);
+
+    ASSERT_EQ(keymints_.count(SecurityLevel::STRONGBOX), 1);
+    auto sb = keymints_.find(SecurityLevel::STRONGBOX)->second;
+    ASSERT_NE(sb, nullptr);
+
+    array<uint8_t, 16> challenge;
+    Status result = sb->getRootOfTrustChallenge(&challenge);
+    if (!result.isOk()) return;
+
+    vector<uint8_t> rootOfTrust;
+    result = tee->getRootOfTrust(challenge, &rootOfTrust);
+    ASSERT_TRUE(result.isOk());
+
+    // TODO: Verify COSE_Mac0 structure and content here.
+
+    result = sb->sendRootOfTrust(rootOfTrust);
+    ASSERT_TRUE(result.isOk());
+
+    // Sending again must fail, because a new challenge is required.
+    result = sb->sendRootOfTrust(rootOfTrust);
+    ASSERT_FALSE(result.isOk());
+}
+
+TEST_F(SecureElementProvisioningTest, InvalidProvisioningTest) {
+    if (keymints_.count(SecurityLevel::STRONGBOX) == 0) {
+        // Need a StrongBox to provision.
+        GTEST_SKIP() << "Test not applicable to device with no StrongBox KeyMint device";
+    }
+
+    ASSERT_EQ(keymints_.count(SecurityLevel::TRUSTED_ENVIRONMENT), 1);
+    auto tee = keymints_.find(SecurityLevel::TRUSTED_ENVIRONMENT)->second;
+    ASSERT_NE(tee, nullptr);
+
+    ASSERT_EQ(keymints_.count(SecurityLevel::STRONGBOX), 1);
+    auto sb = keymints_.find(SecurityLevel::STRONGBOX)->second;
+    ASSERT_NE(sb, nullptr);
+
+    array<uint8_t, 16> challenge;
+    Status result = sb->getRootOfTrustChallenge(&challenge);
+    if (!result.isOk()) return;
+
+    result = sb->sendRootOfTrust({});
+    ASSERT_FALSE(result.isOk());
+    ASSERT_EQ(result.getExceptionCode(), EX_SERVICE_SPECIFIC);
+    ASSERT_EQ(static_cast<ErrorCode>(result.getServiceSpecificError()),
+              ErrorCode::VERIFICATION_FAILED);
+
+    vector<uint8_t> rootOfTrust;
+    result = tee->getRootOfTrust(challenge, &rootOfTrust);
+    ASSERT_TRUE(result.isOk());
+
+    vector<uint8_t> corruptedRootOfTrust = rootOfTrust;
+    corruptedRootOfTrust[corruptedRootOfTrust.size() / 2]++;
+    result = sb->sendRootOfTrust(corruptedRootOfTrust);
+    ASSERT_FALSE(result.isOk());
+    ASSERT_EQ(result.getExceptionCode(), EX_SERVICE_SPECIFIC);
+    ASSERT_EQ(static_cast<ErrorCode>(result.getServiceSpecificError()),
+              ErrorCode::VERIFICATION_FAILED);
+
+    // Now try the correct RoT
+    result = sb->sendRootOfTrust(rootOfTrust);
+    ASSERT_TRUE(result.isOk());
+}
+
+}  // namespace aidl::android::hardware::security::keymint::test
diff --git a/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp b/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
index 544393a..3cc11f6 100644
--- a/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
+++ b/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
@@ -185,6 +185,7 @@
             provisionable_ = IRemotelyProvisionedComponent::fromBinder(binder);
         }
         ASSERT_NE(provisionable_, nullptr);
+        ASSERT_TRUE(provisionable_->getHardwareInfo(&rpcHardwareInfo).isOk());
     }
 
     static vector<string> build_params() {
@@ -194,6 +195,7 @@
 
   protected:
     std::shared_ptr<IRemotelyProvisionedComponent> provisionable_;
+    RpcHardwareInfo rpcHardwareInfo;
 };
 
 /**
@@ -357,12 +359,11 @@
 class CertificateRequestTest : public VtsRemotelyProvisionedComponentTests {
   protected:
     CertificateRequestTest() : eekId_(string_to_bytevec("eekid")), challenge_(randomBytes(32)) {
-        generateTestEekChain(3);
     }
 
     void generateTestEekChain(size_t eekLength) {
-        auto chain = generateEekChain(eekLength, eekId_);
-        EXPECT_TRUE(chain) << chain.message();
+        auto chain = generateEekChain(rpcHardwareInfo.supportedEekCurve, eekLength, eekId_);
+        ASSERT_TRUE(chain) << chain.message();
         if (chain) testEekChain_ = chain.moveValue();
         testEekLength_ = eekLength;
     }
@@ -382,6 +383,17 @@
         }
     }
 
+    ErrMsgOr<bytevec> getSessionKey(ErrMsgOr<std::pair<bytevec, bytevec>>& senderPubkey) {
+        if (rpcHardwareInfo.supportedEekCurve == RpcHardwareInfo::CURVE_25519 ||
+            rpcHardwareInfo.supportedEekCurve == RpcHardwareInfo::CURVE_NONE) {
+            return x25519_HKDF_DeriveKey(testEekChain_.last_pubkey, testEekChain_.last_privkey,
+                                         senderPubkey->first, false /* senderIsA */);
+        } else {
+            return ECDH_HKDF_DeriveKey(testEekChain_.last_pubkey, testEekChain_.last_privkey,
+                                       senderPubkey->first, false /* senderIsA */);
+        }
+    }
+
     void checkProtectedData(const DeviceInfo& deviceInfo, const cppbor::Array& keysToSign,
                             const bytevec& keysToSignMac, const ProtectedData& protectedData,
                             std::vector<BccEntryData>* bccOutput = nullptr) {
@@ -394,9 +406,7 @@
         ASSERT_TRUE(senderPubkey) << senderPubkey.message();
         EXPECT_EQ(senderPubkey->second, eekId_);
 
-        auto sessionKey =
-                x25519_HKDF_DeriveKey(testEekChain_.last_pubkey, testEekChain_.last_privkey,
-                                      senderPubkey->first, false /* senderIsA */);
+        auto sessionKey = getSessionKey(senderPubkey);
         ASSERT_TRUE(sessionKey) << sessionKey.message();
 
         auto protectedDataPayload =
@@ -406,7 +416,8 @@
         auto [parsedPayload, __, payloadErrMsg] = cppbor::parse(*protectedDataPayload);
         ASSERT_TRUE(parsedPayload) << "Failed to parse payload: " << payloadErrMsg;
         ASSERT_TRUE(parsedPayload->asArray());
-        EXPECT_EQ(parsedPayload->asArray()->size(), 2U);
+        // Strongbox may contain additional certificate chain.
+        EXPECT_LE(parsedPayload->asArray()->size(), 3U);
 
         auto& signedMac = parsedPayload->asArray()->get(0);
         auto& bcc = parsedPayload->asArray()->get(1);
@@ -565,6 +576,7 @@
     bytevec keysToSignMac;
     DeviceInfo deviceInfo;
     ProtectedData protectedData;
+    generateTestEekChain(3);
     auto status = provisionable_->generateCertificateRequest(
             testMode, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo,
             &protectedData, &keysToSignMac);
@@ -604,8 +616,8 @@
     DeviceInfo deviceInfo;
     ProtectedData protectedData;
     auto status = provisionable_->generateCertificateRequest(
-            testMode, {} /* keysToSign */, getProdEekChain(), challenge_, &deviceInfo,
-            &protectedData, &keysToSignMac);
+            testMode, {} /* keysToSign */, getProdEekChain(rpcHardwareInfo.supportedEekCurve),
+            challenge_, &deviceInfo, &protectedData, &keysToSignMac);
     EXPECT_TRUE(status.isOk());
 }
 
@@ -645,8 +657,8 @@
     DeviceInfo deviceInfo;
     ProtectedData protectedData;
     auto status = provisionable_->generateCertificateRequest(
-            testMode, keysToSign_, getProdEekChain(), challenge_, &deviceInfo, &protectedData,
-            &keysToSignMac);
+            testMode, keysToSign_, getProdEekChain(rpcHardwareInfo.supportedEekCurve), challenge_,
+            &deviceInfo, &protectedData, &keysToSignMac);
     EXPECT_TRUE(status.isOk());
 }
 
@@ -656,11 +668,14 @@
 TEST_P(CertificateRequestTest, NonEmptyRequestCorruptMac_testMode) {
     bool testMode = true;
     generateKeys(testMode, 1 /* numKeys */);
-    MacedPublicKey keyWithCorruptMac = corrupt_maced_key(keysToSign_[0]).moveValue();
+    auto result = corrupt_maced_key(keysToSign_[0]);
+    ASSERT_TRUE(result) << result.moveMessage();
+    MacedPublicKey keyWithCorruptMac = result.moveValue();
 
     bytevec keysToSignMac;
     DeviceInfo deviceInfo;
     ProtectedData protectedData;
+    generateTestEekChain(3);
     auto status = provisionable_->generateCertificateRequest(
             testMode, {keyWithCorruptMac}, testEekChain_.chain, challenge_, &deviceInfo,
             &protectedData, &keysToSignMac);
@@ -674,14 +689,16 @@
 TEST_P(CertificateRequestTest, NonEmptyRequestCorruptMac_prodMode) {
     bool testMode = false;
     generateKeys(testMode, 1 /* numKeys */);
-    MacedPublicKey keyWithCorruptMac = corrupt_maced_key(keysToSign_[0]).moveValue();
+    auto result = corrupt_maced_key(keysToSign_[0]);
+    ASSERT_TRUE(result) << result.moveMessage();
+    MacedPublicKey keyWithCorruptMac = result.moveValue();
 
     bytevec keysToSignMac;
     DeviceInfo deviceInfo;
     ProtectedData protectedData;
     auto status = provisionable_->generateCertificateRequest(
-            testMode, {keyWithCorruptMac}, getProdEekChain(), challenge_, &deviceInfo,
-            &protectedData, &keysToSignMac);
+            testMode, {keyWithCorruptMac}, getProdEekChain(rpcHardwareInfo.supportedEekCurve),
+            challenge_, &deviceInfo, &protectedData, &keysToSignMac);
     ASSERT_FALSE(status.isOk()) << status.getMessage();
     EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_MAC);
 }
@@ -694,7 +711,7 @@
     bool testMode = false;
     generateKeys(testMode, 4 /* numKeys */);
 
-    auto prodEekChain = getProdEekChain();
+    auto prodEekChain = getProdEekChain(rpcHardwareInfo.supportedEekCurve);
     auto [parsedChain, _, parseErr] = cppbor::parse(prodEekChain);
     ASSERT_NE(parsedChain, nullptr) << parseErr;
     ASSERT_NE(parsedChain->asArray(), nullptr);
@@ -725,7 +742,7 @@
 
     // Build an EEK chain that omits the first self-signed cert.
     auto truncatedChain = cppbor::Array();
-    auto [chain, _, parseErr] = cppbor::parse(getProdEekChain());
+    auto [chain, _, parseErr] = cppbor::parse(getProdEekChain(rpcHardwareInfo.supportedEekCurve));
     ASSERT_TRUE(chain);
     auto eekChain = chain->asArray();
     ASSERT_NE(eekChain, nullptr);
@@ -753,6 +770,7 @@
     bytevec keysToSignMac;
     DeviceInfo deviceInfo;
     ProtectedData protectedData;
+    generateTestEekChain(3);
     auto status = provisionable_->generateCertificateRequest(
             true /* testMode */, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo,
             &protectedData, &keysToSignMac);
@@ -771,6 +789,7 @@
     bytevec keysToSignMac;
     DeviceInfo deviceInfo;
     ProtectedData protectedData;
+    generateTestEekChain(3);
     auto status = provisionable_->generateCertificateRequest(
             false /* testMode */, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo,
             &protectedData, &keysToSignMac);
diff --git a/security/keymint/support/Android.bp b/security/keymint/support/Android.bp
index 36969bb..bf2ab02 100644
--- a/security/keymint/support/Android.bp
+++ b/security/keymint/support/Android.bp
@@ -60,11 +60,15 @@
     export_include_dirs: [
         "include",
     ],
+    defaults: [
+        "keymint_use_latest_hal_aidl_ndk_shared",
+    ],
     shared_libs: [
         "libbase",
         "libcppbor_external",
         "libcppcose_rkp",
         "libcrypto",
+        "libkeymaster_portable",
         "libjsoncpp",
     ],
 }
@@ -76,6 +80,9 @@
         "libgmock",
         "libgtest_main",
     ],
+    defaults: [
+        "keymint_use_latest_hal_aidl_ndk_shared",
+    ],
     shared_libs: [
         "libbase",
         "libcppbor_external",
diff --git a/security/keymint/support/include/remote_prov/remote_prov_utils.h b/security/keymint/support/include/remote_prov/remote_prov_utils.h
index 406b7a9..f3b8608 100644
--- a/security/keymint/support/include/remote_prov/remote_prov_utils.h
+++ b/security/keymint/support/include/remote_prov/remote_prov_utils.h
@@ -52,6 +52,34 @@
         0x31, 0xbf, 0x6b, 0xe8, 0x1e, 0x35, 0xe2, 0xf0, 0x2d, 0xce, 0x6c, 0x2f, 0x4f, 0xf2,
         0xf5, 0x4f, 0xa5, 0xd4, 0x83, 0xad, 0x96, 0xa2, 0xf1, 0x87, 0x58, 0x04};
 
+// The Google ECDSA P256 root key for the Endpoint Encryption Key chain, encoded as COSE_Sign1
+inline constexpr uint8_t kCoseEncodedEcdsa256RootCert[] = {
+    0x84, 0x43, 0xa1, 0x01, 0x26, 0xa0, 0x58, 0x4d, 0xa5, 0x01, 0x02, 0x03, 0x26, 0x20, 0x01, 0x21,
+    0x58, 0x20, 0xf7, 0x14, 0x8a, 0xdb, 0x97, 0xf4, 0xcc, 0x53, 0xef, 0xd2, 0x64, 0x11, 0xc4, 0xe3,
+    0x75, 0x1f, 0x66, 0x1f, 0xa4, 0x71, 0x0c, 0x6c, 0xcf, 0xfa, 0x09, 0x46, 0x80, 0x74, 0x87, 0x54,
+    0xf2, 0xad, 0x22, 0x58, 0x20, 0x5e, 0x7f, 0x5b, 0xf6, 0xec, 0xe4, 0xf6, 0x19, 0xcc, 0xff, 0x13,
+    0x37, 0xfd, 0x0f, 0xa1, 0xc8, 0x93, 0xdb, 0x18, 0x06, 0x76, 0xc4, 0x5d, 0xe6, 0xd7, 0x6a, 0x77,
+    0x86, 0xc3, 0x2d, 0xaf, 0x8f, 0x58, 0x40, 0x2f, 0x97, 0x8e, 0x42, 0xfb, 0xbe, 0x07, 0x2d, 0x95,
+    0x47, 0x85, 0x47, 0x93, 0x40, 0xb0, 0x1f, 0xd4, 0x9b, 0x47, 0xa4, 0xc4, 0x44, 0xa9, 0xf2, 0xa1,
+    0x07, 0x87, 0x10, 0xc7, 0x9f, 0xcb, 0x11, 0xf4, 0xbf, 0x9f, 0xe8, 0x3b, 0xe0, 0xe7, 0x34, 0x4c,
+    0x15, 0xfc, 0x7b, 0xc3, 0x7e, 0x33, 0x05, 0xf4, 0xd1, 0x34, 0x3c, 0xed, 0x02, 0x04, 0x60, 0x7a,
+    0x15, 0xe0, 0x79, 0xd3, 0x8a, 0xff, 0x24};
+
+// The Google ECDSA P256 Endpoint Encryption Key certificate, encoded as COSE_Sign1
+inline constexpr uint8_t kCoseEncodedEcdsa256GeekCert[] = {
+    0x84, 0x43, 0xa1, 0x01, 0x26, 0xa0, 0x58, 0x71, 0xa6, 0x01, 0x02, 0x02, 0x58, 0x20, 0x35, 0x73,
+    0xb7, 0x3f, 0xa0, 0x8a, 0x80, 0x89, 0xb1, 0x26, 0x67, 0xe9, 0xcb, 0x7c, 0x75, 0xa1, 0xaf, 0x02,
+    0x61, 0xfc, 0x6e, 0x65, 0x03, 0x91, 0x3b, 0xd3, 0x4b, 0x7d, 0x14, 0x94, 0x3e, 0x46, 0x03, 0x38,
+    0x18, 0x20, 0x01, 0x21, 0x58, 0x20, 0xe0, 0x41, 0xcf, 0x2f, 0x0f, 0x34, 0x0f, 0x1c, 0x33, 0x2c,
+    0x41, 0xb0, 0xcf, 0xd7, 0x0c, 0x30, 0x55, 0x35, 0xd2, 0x1e, 0x6a, 0x47, 0x13, 0x4b, 0x2e, 0xd1,
+    0x48, 0x96, 0x7e, 0x24, 0x9c, 0x68, 0x22, 0x58, 0x20, 0x1f, 0xce, 0x45, 0xc5, 0xfb, 0x61, 0xba,
+    0x81, 0x21, 0xf9, 0xe5, 0x05, 0x9b, 0x9b, 0x39, 0x0e, 0x76, 0x86, 0x86, 0x47, 0xb8, 0x1e, 0x2f,
+    0x45, 0xf1, 0xce, 0xaf, 0xda, 0x3f, 0x80, 0x68, 0xdb, 0x58, 0x40, 0x8c, 0xb3, 0xba, 0x7e, 0x20,
+    0x3e, 0x32, 0xb0, 0x68, 0xdf, 0x60, 0xd1, 0x1d, 0x7d, 0xf0, 0xac, 0x38, 0x8e, 0x51, 0xbc, 0xff,
+    0x6c, 0xe1, 0x67, 0x3b, 0x4a, 0x79, 0xbc, 0x56, 0x78, 0xb3, 0x99, 0xd8, 0x7c, 0x8a, 0x07, 0xd8,
+    0xda, 0xb5, 0xb5, 0x7f, 0x71, 0xf4, 0xd8, 0x6b, 0xdf, 0x33, 0x27, 0x34, 0x7b, 0x65, 0xd1, 0x2a,
+    0xeb, 0x86, 0x99, 0x98, 0xab, 0x3a, 0xb4, 0x80, 0xaa, 0xbd, 0x50};
+
 /**
  * Generates random bytes.
  */
@@ -64,15 +92,15 @@
 };
 
 /**
- * Generates an X25518 EEK with the specified eekId and an Ed25519 chain of the
- * specified length. All keys are generated randomly.
+ * Based on the supportedEekCurve, Generates an X25519/ECDH with the specified eekId
+ * and an Ed25519/ECDSA chain of the specified length. All keys are generated randomly.
  */
-ErrMsgOr<EekChain> generateEekChain(size_t length, const bytevec& eekId);
+ErrMsgOr<EekChain> generateEekChain(int32_t supportedEekCurve, size_t length, const bytevec& eekId);
 
 /**
  * Returns the CBOR-encoded, production Google Endpoint Encryption Key chain.
  */
-bytevec getProdEekChain();
+bytevec getProdEekChain(int32_t supportedEekCurve);
 
 struct BccEntryData {
     bytevec pubKey;
@@ -96,17 +124,19 @@
 };
 
 /**
- * Take a given certificate request and output a JSON blob containing both the
- * build fingerprint and certificate request. This data may be serialized, then
- * later uploaded to the remote provisioning service. The input csr is not
- * validated, only encoded.
+ * Take a given instance name and certificate request, then output a JSON blob
+ * containing the name, build fingerprint and certificate request. This data may
+ * be serialized, then later uploaded to the remote provisioning service. The
+ * input csr is not validated, only encoded.
  *
  * Output format:
  *   {
  *     "build_fingerprint": <string>
  *     "csr": <base64 CBOR CSR>
+ *     "name": <string>
  *   }
  */
-JsonOutput jsonEncodeCsrWithBuild(const cppbor::Array& csr);
+JsonOutput jsonEncodeCsrWithBuild(const std::string instance_name,
+                                  const cppbor::Array& csr);
 
 }  // namespace aidl::android::hardware::security::keymint::remote_prov
diff --git a/security/keymint/support/remote_prov_utils.cpp b/security/keymint/support/remote_prov_utils.cpp
index 35cb891..0dbea5b 100644
--- a/security/keymint/support/remote_prov_utils.cpp
+++ b/security/keymint/support/remote_prov_utils.cpp
@@ -17,10 +17,16 @@
 #include <iterator>
 #include <tuple>
 
+#include <aidl/android/hardware/security/keymint/RpcHardwareInfo.h>
 #include <android-base/properties.h>
 #include <cppbor.h>
 #include <json/json.h>
+#include <keymaster/km_openssl/ec_key.h>
+#include <keymaster/km_openssl/ecdsa_operation.h>
+#include <keymaster/km_openssl/openssl_err.h>
+#include <keymaster/km_openssl/openssl_utils.h>
 #include <openssl/base64.h>
+#include <openssl/evp.h>
 #include <openssl/rand.h>
 #include <remote_prov/remote_prov_utils.h>
 
@@ -30,6 +36,166 @@
 constexpr uint32_t kBccPayloadSubject = 2;
 constexpr int32_t kBccPayloadSubjPubKey = -4670552;
 constexpr int32_t kBccPayloadKeyUsage = -4670553;
+constexpr int kP256AffinePointSize = 32;
+
+using EC_KEY_Ptr = bssl::UniquePtr<EC_KEY>;
+using EVP_PKEY_Ptr = bssl::UniquePtr<EVP_PKEY>;
+using EVP_PKEY_CTX_Ptr = bssl::UniquePtr<EVP_PKEY_CTX>;
+
+ErrMsgOr<bytevec> ecKeyGetPrivateKey(const EC_KEY* ecKey) {
+    // Extract private key.
+    const BIGNUM* bignum = EC_KEY_get0_private_key(ecKey);
+    if (bignum == nullptr) {
+        return "Error getting bignum from private key";
+    }
+    // Pad with zeros in case the length is lesser than 32.
+    bytevec privKey(32, 0);
+    BN_bn2binpad(bignum, privKey.data(), privKey.size());
+    return privKey;
+}
+
+ErrMsgOr<bytevec> ecKeyGetPublicKey(const EC_KEY* ecKey) {
+    // Extract public key.
+    auto group = EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
+    if (group.get() == nullptr) {
+        return "Error creating EC group by curve name";
+    }
+    const EC_POINT* point = EC_KEY_get0_public_key(ecKey);
+    if (point == nullptr) return "Error getting ecpoint from public key";
+
+    int size =
+        EC_POINT_point2oct(group.get(), point, POINT_CONVERSION_UNCOMPRESSED, nullptr, 0, nullptr);
+    if (size == 0) {
+        return "Error generating public key encoding";
+    }
+
+    bytevec publicKey;
+    publicKey.resize(size);
+    EC_POINT_point2oct(group.get(), point, POINT_CONVERSION_UNCOMPRESSED, publicKey.data(),
+                       publicKey.size(), nullptr);
+    return publicKey;
+}
+
+ErrMsgOr<std::tuple<bytevec, bytevec>> getAffineCoordinates(const bytevec& pubKey) {
+    auto group = EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
+    if (group.get() == nullptr) {
+        return "Error creating EC group by curve name";
+    }
+    auto point = EC_POINT_Ptr(EC_POINT_new(group.get()));
+    if (EC_POINT_oct2point(group.get(), point.get(), pubKey.data(), pubKey.size(), nullptr) != 1) {
+        return "Error decoding publicKey";
+    }
+    BIGNUM_Ptr x(BN_new());
+    BIGNUM_Ptr y(BN_new());
+    BN_CTX_Ptr ctx(BN_CTX_new());
+    if (!ctx.get()) return "Failed to create BN_CTX instance";
+
+    if (!EC_POINT_get_affine_coordinates_GFp(group.get(), point.get(), x.get(), y.get(),
+                                             ctx.get())) {
+        return "Failed to get affine coordinates from ECPoint";
+    }
+    bytevec pubX(kP256AffinePointSize);
+    bytevec pubY(kP256AffinePointSize);
+    if (BN_bn2binpad(x.get(), pubX.data(), kP256AffinePointSize) != kP256AffinePointSize) {
+        return "Error in converting absolute value of x coordinate to big-endian";
+    }
+    if (BN_bn2binpad(y.get(), pubY.data(), kP256AffinePointSize) != kP256AffinePointSize) {
+        return "Error in converting absolute value of y coordinate to big-endian";
+    }
+    return std::make_tuple(std::move(pubX), std::move(pubY));
+}
+
+ErrMsgOr<std::tuple<bytevec, bytevec>> generateEc256KeyPair() {
+    auto ec_key = EC_KEY_Ptr(EC_KEY_new());
+    if (ec_key.get() == nullptr) {
+        return "Failed to allocate ec key";
+    }
+
+    auto group = EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
+    if (group.get() == nullptr) {
+        return "Error creating EC group by curve name";
+    }
+
+    if (EC_KEY_set_group(ec_key.get(), group.get()) != 1 ||
+        EC_KEY_generate_key(ec_key.get()) != 1 || EC_KEY_check_key(ec_key.get()) < 0) {
+        return "Error generating key";
+    }
+
+    auto privKey = ecKeyGetPrivateKey(ec_key.get());
+    if (!privKey) return privKey.moveMessage();
+
+    auto pubKey = ecKeyGetPublicKey(ec_key.get());
+    if (!pubKey) return pubKey.moveMessage();
+
+    return std::make_tuple(pubKey.moveValue(), privKey.moveValue());
+}
+
+ErrMsgOr<std::tuple<bytevec, bytevec>> generateX25519KeyPair() {
+    /* Generate X25519 key pair */
+    bytevec pubKey(X25519_PUBLIC_VALUE_LEN);
+    bytevec privKey(X25519_PRIVATE_KEY_LEN);
+    X25519_keypair(pubKey.data(), privKey.data());
+    return std::make_tuple(std::move(pubKey), std::move(privKey));
+}
+
+ErrMsgOr<std::tuple<bytevec, bytevec>> generateED25519KeyPair() {
+    /* Generate ED25519 key pair */
+    bytevec pubKey(ED25519_PUBLIC_KEY_LEN);
+    bytevec privKey(ED25519_PRIVATE_KEY_LEN);
+    ED25519_keypair(pubKey.data(), privKey.data());
+    return std::make_tuple(std::move(pubKey), std::move(privKey));
+}
+
+ErrMsgOr<std::tuple<bytevec, bytevec>> generateKeyPair(int32_t supportedEekCurve, bool isEek) {
+    switch (supportedEekCurve) {
+    case RpcHardwareInfo::CURVE_25519:
+        if (isEek) {
+            return generateX25519KeyPair();
+        }
+        return generateED25519KeyPair();
+    case RpcHardwareInfo::CURVE_P256:
+        return generateEc256KeyPair();
+    default:
+        return "Unknown EEK Curve.";
+    }
+}
+
+ErrMsgOr<bytevec> constructCoseKey(int32_t supportedEekCurve, const bytevec& eekId,
+                                   const bytevec& pubKey) {
+    CoseKeyType keyType;
+    CoseKeyAlgorithm algorithm;
+    CoseKeyCurve curve;
+    bytevec pubX;
+    bytevec pubY;
+    switch (supportedEekCurve) {
+    case RpcHardwareInfo::CURVE_25519:
+        keyType = OCTET_KEY_PAIR;
+        algorithm = (eekId.empty()) ? EDDSA : ECDH_ES_HKDF_256;
+        curve = (eekId.empty()) ? ED25519 : cppcose::X25519;
+        pubX = pubKey;
+        break;
+    case RpcHardwareInfo::CURVE_P256: {
+        keyType = EC2;
+        algorithm = (eekId.empty()) ? ES256 : ECDH_ES_HKDF_256;
+        curve = P256;
+        auto affineCoordinates = getAffineCoordinates(pubKey);
+        if (!affineCoordinates) return affineCoordinates.moveMessage();
+        std::tie(pubX, pubY) = affineCoordinates.moveValue();
+    } break;
+    default:
+        return "Unknown EEK Curve.";
+    }
+    cppbor::Map coseKey = cppbor::Map()
+                              .add(CoseKey::KEY_TYPE, keyType)
+                              .add(CoseKey::ALGORITHM, algorithm)
+                              .add(CoseKey::CURVE, curve)
+                              .add(CoseKey::PUBKEY_X, pubX);
+
+    if (!pubY.empty()) coseKey.add(CoseKey::PUBKEY_Y, pubY);
+    if (!eekId.empty()) coseKey.add(CoseKey::KEY_ID, eekId);
+
+    return coseKey.canonicalize().encode();
+}
 
 bytevec kTestMacKey(32 /* count */, 0 /* byte value */);
 
@@ -39,7 +205,17 @@
     return retval;
 }
 
-ErrMsgOr<EekChain> generateEekChain(size_t length, const bytevec& eekId) {
+ErrMsgOr<cppbor::Array> constructCoseSign1(int32_t supportedEekCurve, const bytevec& key,
+                                           const bytevec& payload, const bytevec& aad) {
+    if (supportedEekCurve == RpcHardwareInfo::CURVE_P256) {
+        return constructECDSACoseSign1(key, {} /* protectedParams */, payload, aad);
+    } else {
+        return cppcose::constructCoseSign1(key, payload, aad);
+    }
+}
+
+ErrMsgOr<EekChain> generateEekChain(int32_t supportedEekCurve, size_t length,
+                                    const bytevec& eekId) {
     if (length < 2) {
         return "EEK chain must contain at least 2 certs.";
     }
@@ -48,59 +224,62 @@
 
     bytevec prev_priv_key;
     for (size_t i = 0; i < length - 1; ++i) {
-        bytevec pub_key(ED25519_PUBLIC_KEY_LEN);
-        bytevec priv_key(ED25519_PRIVATE_KEY_LEN);
-
-        ED25519_keypair(pub_key.data(), priv_key.data());
+        auto keyPair = generateKeyPair(supportedEekCurve, false);
+        if (!keyPair) return keyPair.moveMessage();
+        auto [pub_key, priv_key] = keyPair.moveValue();
 
         // The first signing key is self-signed.
         if (prev_priv_key.empty()) prev_priv_key = priv_key;
 
-        auto coseSign1 = constructCoseSign1(prev_priv_key,
-                                            cppbor::Map() /* payload CoseKey */
-                                                    .add(CoseKey::KEY_TYPE, OCTET_KEY_PAIR)
-                                                    .add(CoseKey::ALGORITHM, EDDSA)
-                                                    .add(CoseKey::CURVE, ED25519)
-                                                    .add(CoseKey::PUBKEY_X, pub_key)
-                                                    .canonicalize()
-                                                    .encode(),
-                                            {} /* AAD */);
+        auto coseKey = constructCoseKey(supportedEekCurve, {}, pub_key);
+        if (!coseKey) return coseKey.moveMessage();
+
+        auto coseSign1 =
+            constructCoseSign1(supportedEekCurve, prev_priv_key, coseKey.moveValue(), {} /* AAD */);
         if (!coseSign1) return coseSign1.moveMessage();
         eekChain.add(coseSign1.moveValue());
 
         prev_priv_key = priv_key;
     }
+    auto keyPair = generateKeyPair(supportedEekCurve, true);
+    if (!keyPair) return keyPair.moveMessage();
+    auto [pub_key, priv_key] = keyPair.moveValue();
 
-    bytevec pub_key(X25519_PUBLIC_VALUE_LEN);
-    bytevec priv_key(X25519_PRIVATE_KEY_LEN);
-    X25519_keypair(pub_key.data(), priv_key.data());
+    auto coseKey = constructCoseKey(supportedEekCurve, eekId, pub_key);
+    if (!coseKey) return coseKey.moveMessage();
 
-    auto coseSign1 = constructCoseSign1(prev_priv_key,
-                                        cppbor::Map() /* payload CoseKey */
-                                                .add(CoseKey::KEY_TYPE, OCTET_KEY_PAIR)
-                                                .add(CoseKey::KEY_ID, eekId)
-                                                .add(CoseKey::ALGORITHM, ECDH_ES_HKDF_256)
-                                                .add(CoseKey::CURVE, cppcose::X25519)
-                                                .add(CoseKey::PUBKEY_X, pub_key)
-                                                .canonicalize()
-                                                .encode(),
-                                        {} /* AAD */);
+    auto coseSign1 =
+        constructCoseSign1(supportedEekCurve, prev_priv_key, coseKey.moveValue(), {} /* AAD */);
     if (!coseSign1) return coseSign1.moveMessage();
     eekChain.add(coseSign1.moveValue());
 
+    if (supportedEekCurve == RpcHardwareInfo::CURVE_P256) {
+        // convert ec public key to x and y co-ordinates.
+        auto affineCoordinates = getAffineCoordinates(pub_key);
+        if (!affineCoordinates) return affineCoordinates.moveMessage();
+        auto [pubX, pubY] = affineCoordinates.moveValue();
+        pub_key.clear();
+        pub_key.insert(pub_key.begin(), pubX.begin(), pubX.end());
+        pub_key.insert(pub_key.end(), pubY.begin(), pubY.end());
+    }
+
     return EekChain{eekChain.encode(), pub_key, priv_key};
 }
 
-bytevec getProdEekChain() {
-    bytevec prodEek;
-    prodEek.reserve(1 + sizeof(kCoseEncodedRootCert) + sizeof(kCoseEncodedGeekCert));
-
-    // In CBOR encoding, 0x82 indicates an array of two items
-    prodEek.push_back(0x82);
-    prodEek.insert(prodEek.end(), std::begin(kCoseEncodedRootCert), std::end(kCoseEncodedRootCert));
-    prodEek.insert(prodEek.end(), std::begin(kCoseEncodedGeekCert), std::end(kCoseEncodedGeekCert));
-
-    return prodEek;
+bytevec getProdEekChain(int32_t supportedEekCurve) {
+    cppbor::Array chain;
+    if (supportedEekCurve == RpcHardwareInfo::CURVE_P256) {
+        chain.add(cppbor::EncodedItem(bytevec(std::begin(kCoseEncodedEcdsa256RootCert),
+                                              std::end(kCoseEncodedEcdsa256RootCert))));
+        chain.add(cppbor::EncodedItem(bytevec(std::begin(kCoseEncodedEcdsa256GeekCert),
+                                              std::end(kCoseEncodedEcdsa256GeekCert))));
+    } else {
+        chain.add(cppbor::EncodedItem(
+            bytevec(std::begin(kCoseEncodedRootCert), std::end(kCoseEncodedRootCert))));
+        chain.add(cppbor::EncodedItem(
+            bytevec(std::begin(kCoseEncodedGeekCert), std::end(kCoseEncodedGeekCert))));
+    }
+    return chain.encode();
 }
 
 ErrMsgOr<bytevec> validatePayloadAndFetchPubKey(const cppbor::Map* payload) {
@@ -139,7 +318,8 @@
     }
 
     auto& algorithm = parsedProtParams->asMap()->get(ALGORITHM);
-    if (!algorithm || !algorithm->asInt() || algorithm->asInt()->value() != EDDSA) {
+    if (!algorithm || !algorithm->asInt() ||
+        (algorithm->asInt()->value() != EDDSA && algorithm->asInt()->value() != ES256)) {
         return "Unsupported signature algorithm";
     }
 
@@ -152,15 +332,36 @@
     }
 
     bool selfSigned = signingCoseKey.empty();
-    auto key = CoseKey::parseEd25519(selfSigned ? *serializedKey : signingCoseKey);
-    if (!key) return "Bad signing key: " + key.moveMessage();
-
     bytevec signatureInput =
-            cppbor::Array().add("Signature1").add(*protectedParams).add(aad).add(*payload).encode();
+        cppbor::Array().add("Signature1").add(*protectedParams).add(aad).add(*payload).encode();
 
-    if (!ED25519_verify(signatureInput.data(), signatureInput.size(), signature->value().data(),
-                        key->getBstrValue(CoseKey::PUBKEY_X)->data())) {
-        return "Signature verification failed";
+    if (algorithm->asInt()->value() == EDDSA) {
+        auto key = CoseKey::parseEd25519(selfSigned ? *serializedKey : signingCoseKey);
+
+        if (!key) return "Bad signing key: " + key.moveMessage();
+
+        if (!ED25519_verify(signatureInput.data(), signatureInput.size(), signature->value().data(),
+                            key->getBstrValue(CoseKey::PUBKEY_X)->data())) {
+            return "Signature verification failed";
+        }
+    } else {  // P256
+        auto key = CoseKey::parseP256(selfSigned ? *serializedKey : signingCoseKey);
+        if (!key || key->getBstrValue(CoseKey::PUBKEY_X)->empty() ||
+            key->getBstrValue(CoseKey::PUBKEY_Y)->empty()) {
+            return "Bad signing key: " + key.moveMessage();
+        }
+        auto publicKey = key->getEcPublicKey();
+        if (!publicKey) return publicKey.moveMessage();
+
+        auto ecdsaDerSignature = ecdsaCoseSignatureToDer(signature->value());
+        if (!ecdsaDerSignature) return ecdsaDerSignature.moveMessage();
+
+        // convert public key to uncompressed form.
+        publicKey->insert(publicKey->begin(), 0x04);
+
+        if (!verifyEcdsaDigest(publicKey.moveValue(), sha256(signatureInput), *ecdsaDerSignature)) {
+            return "Signature verification failed";
+        }
     }
 
     return serializedKey.moveValue();
@@ -207,7 +408,7 @@
     return result;
 }
 
-JsonOutput jsonEncodeCsrWithBuild(const cppbor::Array& csr) {
+JsonOutput jsonEncodeCsrWithBuild(const std::string instance_name, const cppbor::Array& csr) {
     const std::string kFingerprintProp = "ro.build.fingerprint";
 
     if (!::android::base::WaitForPropertyCreation(kFingerprintProp)) {
@@ -231,6 +432,7 @@
     }
 
     Json::Value json(Json::objectValue);
+    json["name"] = instance_name;
     json["build_fingerprint"] = ::android::base::GetProperty(kFingerprintProp, /*default=*/"");
     json["csr"] = base64.data();  // Boring writes a NUL-terminated c-string
 
diff --git a/security/keymint/support/remote_prov_utils_test.cpp b/security/keymint/support/remote_prov_utils_test.cpp
index 8697c51..0250cd6 100644
--- a/security/keymint/support/remote_prov_utils_test.cpp
+++ b/security/keymint/support/remote_prov_utils_test.cpp
@@ -14,8 +14,12 @@
  * limitations under the License.
  */
 
+#include "cppbor.h"
+#include "keymaster/cppcose/cppcose.h"
+#include <aidl/android/hardware/security/keymint/RpcHardwareInfo.h>
 #include <android-base/properties.h>
 #include <cppbor_parse.h>
+#include <cstdint>
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
 #include <keymaster/android_keymaster_utils.h>
@@ -23,25 +27,120 @@
 #include <keymaster/remote_provisioning_utils.h>
 #include <openssl/curve25519.h>
 #include <remote_prov/remote_prov_utils.h>
-#include <cstdint>
-#include "cppbor.h"
-#include "keymaster/cppcose/cppcose.h"
 
 namespace aidl::android::hardware::security::keymint::remote_prov {
 namespace {
 
 using ::keymaster::KeymasterBlob;
-using ::keymaster::validateAndExtractEekPubAndId;
+using ::keymaster::kStatusFailed;
+using ::keymaster::kStatusInvalidEek;
+using ::keymaster::StatusOr;
 using ::testing::ElementsAreArray;
+using byte_view = std::basic_string_view<uint8_t>;
+
+struct KeyInfoEcdsa {
+    CoseKeyCurve curve;
+    byte_view pubKeyX;
+    byte_view pubKeyY;
+
+    bool operator==(const KeyInfoEcdsa& other) const {
+        return curve == other.curve && pubKeyX == other.pubKeyX && pubKeyY == other.pubKeyY;
+    }
+};
+
+// The production root signing key for Google ECDSA P256 Endpoint Encryption Key cert chains.
+inline constexpr uint8_t kEcdsa256GeekRootX[] = {
+    0xf7, 0x14, 0x8a, 0xdb, 0x97, 0xf4, 0xcc, 0x53, 0xef, 0xd2, 0x64, 0x11, 0xc4, 0xe3, 0x75, 0x1f,
+    0x66, 0x1f, 0xa4, 0x71, 0x0c, 0x6c, 0xcf, 0xfa, 0x09, 0x46, 0x80, 0x74, 0x87, 0x54, 0xf2, 0xad};
+
+inline constexpr uint8_t kEcdsa256GeekRootY[] = {
+    0x5e, 0x7f, 0x5b, 0xf6, 0xec, 0xe4, 0xf6, 0x19, 0xcc, 0xff, 0x13, 0x37, 0xfd, 0x0f, 0xa1, 0xc8,
+    0x93, 0xdb, 0x18, 0x06, 0x76, 0xc4, 0x5d, 0xe6, 0xd7, 0x6a, 0x77, 0x86, 0xc3, 0x2d, 0xaf, 0x8f};
+
+// Hard-coded set of acceptable public COSE_Keys that can act as roots of EEK chains.
+inline constexpr KeyInfoEcdsa kAuthorizedEcdsa256EekRoots[] = {
+    {CoseKeyCurve::P256, byte_view(kEcdsa256GeekRootX, sizeof(kEcdsa256GeekRootX)),
+     byte_view(kEcdsa256GeekRootY, sizeof(kEcdsa256GeekRootY))},
+};
+
+static ErrMsgOr<CoseKey> parseEcdh256(const bytevec& coseKey) {
+    auto key = CoseKey::parse(coseKey, EC2, ECDH_ES_HKDF_256, P256);
+    if (!key) return key;
+
+    auto& pubkey_x = key->getMap().get(cppcose::CoseKey::PUBKEY_X);
+    auto& pubkey_y = key->getMap().get(cppcose::CoseKey::PUBKEY_Y);
+    if (!pubkey_x || !pubkey_y || !pubkey_x->asBstr() || !pubkey_y->asBstr() ||
+        pubkey_x->asBstr()->value().size() != 32 || pubkey_y->asBstr()->value().size() != 32) {
+        return "Invalid P256 public key";
+    }
+
+    return key;
+}
+
+StatusOr<std::tuple<std::vector<uint8_t> /* EEK pubX */, std::vector<uint8_t> /* EEK pubY */,
+                    std::vector<uint8_t> /* EEK ID */>>
+validateAndExtractEcdsa256EekPubAndId(bool testMode,
+                                      const KeymasterBlob& endpointEncryptionCertChain) {
+    auto [item, newPos, errMsg] =
+        cppbor::parse(endpointEncryptionCertChain.begin(), endpointEncryptionCertChain.end());
+    if (!item || !item->asArray()) {
+        return kStatusFailed;
+    }
+    const cppbor::Array* certArr = item->asArray();
+    std::vector<uint8_t> lastPubKey;
+    for (size_t i = 0; i < certArr->size(); ++i) {
+        auto cosePubKey =
+            verifyAndParseCoseSign1(certArr->get(i)->asArray(), lastPubKey, {} /* AAD */);
+        if (!cosePubKey) {
+            return kStatusInvalidEek;
+        }
+        lastPubKey = *std::move(cosePubKey);
+
+        // In prod mode the first pubkey should match a well-known Google public key.
+        if (!testMode && i == 0) {
+            auto parsedPubKey = CoseKey::parse(lastPubKey);
+            if (!parsedPubKey) {
+                return kStatusFailed;
+            }
+            auto curve = parsedPubKey->getIntValue(CoseKey::CURVE);
+            if (!curve) {
+                return kStatusInvalidEek;
+            }
+            auto rawPubX = parsedPubKey->getBstrValue(CoseKey::PUBKEY_X);
+            if (!rawPubX) {
+                return kStatusInvalidEek;
+            }
+            auto rawPubY = parsedPubKey->getBstrValue(CoseKey::PUBKEY_Y);
+            if (!rawPubY) {
+                return kStatusInvalidEek;
+            }
+            KeyInfoEcdsa matcher = {static_cast<CoseKeyCurve>(*curve),
+                                    byte_view(rawPubX->data(), rawPubX->size()),
+                                    byte_view(rawPubY->data(), rawPubY->size())};
+            if (std::find(std::begin(kAuthorizedEcdsa256EekRoots),
+                          std::end(kAuthorizedEcdsa256EekRoots),
+                          matcher) == std::end(kAuthorizedEcdsa256EekRoots)) {
+                return kStatusInvalidEek;
+            }
+        }
+    }
+    auto eek = parseEcdh256(lastPubKey);
+    if (!eek) {
+        return kStatusInvalidEek;
+    }
+    return std::make_tuple(eek->getBstrValue(CoseKey::PUBKEY_X).value(),
+                           eek->getBstrValue(CoseKey::PUBKEY_Y).value(),
+                           eek->getBstrValue(CoseKey::KEY_ID).value());
+}
 
 TEST(RemoteProvUtilsTest, GenerateEekChainInvalidLength) {
-    ASSERT_FALSE(generateEekChain(1, /*eekId=*/{}));
+    ASSERT_FALSE(generateEekChain(RpcHardwareInfo::CURVE_25519, 1, /*eekId=*/{}));
 }
 
 TEST(RemoteProvUtilsTest, GenerateEekChain) {
     bytevec kTestEekId = {'t', 'e', 's', 't', 'I', 'd', 0};
     for (size_t length : {2, 3, 31}) {
-        auto get_eek_result = generateEekChain(length, kTestEekId);
+        auto get_eek_result = generateEekChain(RpcHardwareInfo::CURVE_25519, length, kTestEekId);
         ASSERT_TRUE(get_eek_result) << get_eek_result.message();
 
         auto& [chain, pubkey, privkey] = *get_eek_result;
@@ -57,7 +156,7 @@
 }
 
 TEST(RemoteProvUtilsTest, GetProdEekChain) {
-    auto chain = getProdEekChain();
+    auto chain = getProdEekChain(RpcHardwareInfo::CURVE_25519);
 
     auto validation_result = validateAndExtractEekPubAndId(
             /*testMode=*/false, KeymasterBlob(chain.data(), chain.size()));
@@ -86,16 +185,68 @@
     cppbor::Array array;
     array.add(1);
 
-    auto [json, error] = jsonEncodeCsrWithBuild(array);
+    auto [json, error] = jsonEncodeCsrWithBuild(std::string("test"), array);
 
     ASSERT_TRUE(error.empty()) << error;
 
     std::string expected = R"({"build_fingerprint":")" +
                            ::android::base::GetProperty("ro.build.fingerprint", /*default=*/"") +
-                           R"(","csr":"gQE="})";
+                           R"(","csr":"gQE=","name":"test"})";
 
     ASSERT_EQ(json, expected);
 }
 
+TEST(RemoteProvUtilsTest, GenerateEcdsaEekChainInvalidLength) {
+    ASSERT_FALSE(generateEekChain(RpcHardwareInfo::CURVE_P256, 1, /*eekId=*/{}));
+}
+
+TEST(RemoteProvUtilsTest, GenerateEcdsaEekChain) {
+    bytevec kTestEekId = {'t', 'e', 's', 't', 'I', 'd', 0};
+    for (size_t length : {2, 3, 31}) {
+        auto get_eek_result = generateEekChain(RpcHardwareInfo::CURVE_P256, length, kTestEekId);
+        ASSERT_TRUE(get_eek_result) << get_eek_result.message();
+
+        auto& [chain, pubkey, privkey] = *get_eek_result;
+
+        auto validation_result = validateAndExtractEcdsa256EekPubAndId(
+            /*testMode=*/true, KeymasterBlob(chain.data(), chain.size()));
+        ASSERT_TRUE(validation_result.isOk());
+
+        auto& [eekPubX, eekPubY, eekId] = *validation_result;
+        bytevec eekPub;
+        eekPub.insert(eekPub.begin(), eekPubX.begin(), eekPubX.end());
+        eekPub.insert(eekPub.end(), eekPubY.begin(), eekPubY.end());
+        EXPECT_THAT(eekId, ElementsAreArray(kTestEekId));
+        EXPECT_THAT(eekPub, ElementsAreArray(pubkey));
+    }
+}
+
+TEST(RemoteProvUtilsTest, GetProdEcdsaEekChain) {
+    auto chain = getProdEekChain(RpcHardwareInfo::CURVE_P256);
+
+    auto validation_result = validateAndExtractEcdsa256EekPubAndId(
+        /*testMode=*/false, KeymasterBlob(chain.data(), chain.size()));
+    ASSERT_TRUE(validation_result.isOk()) << "Error: " << validation_result.moveError();
+
+    auto& [eekPubX, eekPubY, eekId] = *validation_result;
+
+    auto [geekCert, ignoredNewPos, error] =
+        cppbor::parse(kCoseEncodedEcdsa256GeekCert, sizeof(kCoseEncodedEcdsa256GeekCert));
+    ASSERT_NE(geekCert, nullptr) << "Error: " << error;
+    ASSERT_NE(geekCert->asArray(), nullptr);
+
+    auto& encodedGeekCoseKey = geekCert->asArray()->get(kCoseSign1Payload);
+    ASSERT_NE(encodedGeekCoseKey, nullptr);
+    ASSERT_NE(encodedGeekCoseKey->asBstr(), nullptr);
+
+    auto geek = CoseKey::parse(encodedGeekCoseKey->asBstr()->value());
+    ASSERT_TRUE(geek) << "Error: " << geek.message();
+
+    const std::vector<uint8_t> empty;
+    EXPECT_THAT(eekId, ElementsAreArray(geek->getBstrValue(CoseKey::KEY_ID).value_or(empty)));
+    EXPECT_THAT(eekPubX, ElementsAreArray(geek->getBstrValue(CoseKey::PUBKEY_X).value_or(empty)));
+    EXPECT_THAT(eekPubY, ElementsAreArray(geek->getBstrValue(CoseKey::PUBKEY_Y).value_or(empty)));
+}
+
 }  // namespace
 }  // namespace aidl::android::hardware::security::keymint::remote_prov
diff --git a/sensors/1.0/vts/functional/Android.bp b/sensors/1.0/vts/functional/Android.bp
index 9a92fb3..274cfa7 100644
--- a/sensors/1.0/vts/functional/Android.bp
+++ b/sensors/1.0/vts/functional/Android.bp
@@ -27,6 +27,9 @@
     name: "VtsHalSensorsV1_0TargetTest",
     cflags: ["-DLOG_TAG=\"sensors_hidl_hal_test\""],
     defaults: ["VtsHalTargetTestDefaults"],
+    tidy_timeout_srcs: [
+        "VtsHalSensorsV1_0TargetTest.cpp",
+    ],
     srcs: [
         "SensorsHidlEnvironmentV1_0.cpp",
         "VtsHalSensorsV1_0TargetTest.cpp",
diff --git a/sensors/2.0/vts/functional/Android.bp b/sensors/2.0/vts/functional/Android.bp
index cf7c9fa..c4ec866 100644
--- a/sensors/2.0/vts/functional/Android.bp
+++ b/sensors/2.0/vts/functional/Android.bp
@@ -27,6 +27,9 @@
     name: "VtsHalSensorsV2_0TargetTest",
     cflags: ["-DLOG_TAG=\"sensors_hidl_hal_test\""],
     defaults: ["VtsHalTargetTestDefaults"],
+    tidy_timeout_srcs: [
+        "VtsHalSensorsV2_0TargetTest.cpp",
+    ],
     srcs: [
         "VtsHalSensorsV2_0TargetTest.cpp",
     ],
diff --git a/sensors/common/default/2.X/multihal/tests/Android.bp b/sensors/common/default/2.X/multihal/tests/Android.bp
index d8e7ce6..21d1d77 100644
--- a/sensors/common/default/2.X/multihal/tests/Android.bp
+++ b/sensors/common/default/2.X/multihal/tests/Android.bp
@@ -99,6 +99,9 @@
 
 cc_test {
     name: "android.hardware.sensors@2.X-halproxy-unit-tests",
+    tidy_timeout_srcs: [
+        "HalProxy_test.cpp",
+    ],
     srcs: [
         "HalProxy_test.cpp",
         "ScopedWakelock_test.cpp",
diff --git a/thermal/2.0/vts/functional/Android.bp b/thermal/2.0/vts/functional/Android.bp
index f26c1af..29dffcb 100644
--- a/thermal/2.0/vts/functional/Android.bp
+++ b/thermal/2.0/vts/functional/Android.bp
@@ -26,6 +26,7 @@
 cc_test {
     name: "VtsHalThermalV2_0TargetTest",
     defaults: ["VtsHalTargetTestDefaults"],
+    tidy_timeout_srcs: ["VtsHalThermalV2_0TargetTest.cpp"],
     srcs: ["VtsHalThermalV2_0TargetTest.cpp"],
     static_libs: [
         "android.hardware.thermal@1.0",
diff --git a/vibrator/aidl/Android.bp b/vibrator/aidl/Android.bp
index 22219b0..d4d5857 100644
--- a/vibrator/aidl/Android.bp
+++ b/vibrator/aidl/Android.bp
@@ -10,6 +10,7 @@
 aidl_interface {
     name: "android.hardware.vibrator",
     vendor_available: true,
+    host_supported: true,
     srcs: [
         "android/hardware/vibrator/*.aidl",
     ],
diff --git a/vibrator/aidl/default/Android.bp b/vibrator/aidl/default/Android.bp
index 2e12dfb..acdbdcd 100644
--- a/vibrator/aidl/default/Android.bp
+++ b/vibrator/aidl/default/Android.bp
@@ -9,7 +9,8 @@
 
 cc_library_static {
     name: "libvibratorexampleimpl",
-    vendor: true,
+    vendor_available: true,
+    host_supported: true,
     shared_libs: [
         "libbase",
         "libbinder_ndk",
@@ -24,6 +25,11 @@
         ":__subpackages__",
         "//hardware/interfaces/tests/extension/vibrator:__subpackages__",
     ],
+    target: {
+        darwin: {
+            enabled: false,
+        },
+    },
 }
 
 filegroup {
@@ -47,3 +53,40 @@
     ],
     srcs: ["main.cpp"],
 }
+
+cc_fuzz {
+    name: "android.hardware.vibrator-service.example_fuzzer",
+    host_supported: true,
+    static_libs: [
+        "android.hardware.vibrator-V2-ndk",
+        "libbase",
+        "libbinder_random_parcel",
+        "libcutils",
+        "liblog",
+        "libutils",
+        "libvibratorexampleimpl",
+    ],
+    target: {
+        android: {
+            shared_libs: [
+                "libbinder_ndk",
+                "libbinder",
+            ],
+        },
+        host: {
+            static_libs: [
+                "libbinder_ndk",
+                "libbinder",
+            ],
+        },
+        darwin: {
+            enabled: false,
+        },
+    },
+    srcs: ["fuzzer.cpp"],
+    fuzz_config: {
+        cc: [
+            "smoreland@google.com",
+        ],
+    },
+}
diff --git a/vibrator/aidl/default/fuzzer.cpp b/vibrator/aidl/default/fuzzer.cpp
new file mode 100644
index 0000000..7d52209
--- /dev/null
+++ b/vibrator/aidl/default/fuzzer.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <fuzzbinder/libbinder_ndk_driver.h>
+#include <fuzzer/FuzzedDataProvider.h>
+#include <vibrator-impl/Vibrator.h>
+#include <vibrator-impl/VibratorManager.h>
+
+using aidl::android::hardware::vibrator::Vibrator;
+using aidl::android::hardware::vibrator::VibratorManager;
+using android::fuzzService;
+using ndk::SharedRefBase;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    auto managedVib = SharedRefBase::make<Vibrator>();
+    auto vibManager = SharedRefBase::make<VibratorManager>(std::move(managedVib));
+
+    fuzzService(vibManager->asBinder().get(), FuzzedDataProvider(data, size));
+
+    return 0;
+}
diff --git a/vibrator/aidl/vts/Android.bp b/vibrator/aidl/vts/Android.bp
index 3f328fa..1261870 100644
--- a/vibrator/aidl/vts/Android.bp
+++ b/vibrator/aidl/vts/Android.bp
@@ -13,6 +13,7 @@
         "VtsHalTargetTestDefaults",
         "use_libaidlvintf_gtest_helper_static",
     ],
+    tidy_timeout_srcs: ["VtsHalVibratorTargetTest.cpp"],
     srcs: ["VtsHalVibratorTargetTest.cpp"],
     shared_libs: [
         "libbinder",
diff --git a/wifi/1.0/vts/functional/Android.bp b/wifi/1.0/vts/functional/Android.bp
index 6c0ebf7..ebfa164 100644
--- a/wifi/1.0/vts/functional/Android.bp
+++ b/wifi/1.0/vts/functional/Android.bp
@@ -48,6 +48,9 @@
 cc_test {
     name: "VtsHalWifiV1_0TargetTest",
     defaults: ["VtsHalTargetTestDefaults"],
+    tidy_timeout_srcs: [
+        "wifi_chip_hidl_test.cpp",
+    ],
     srcs: [
         "wifi_chip_hidl_test.cpp",
         "wifi_p2p_iface_hidl_test.cpp",
diff --git a/wifi/1.5/default/wifi_chip.cpp b/wifi/1.5/default/wifi_chip.cpp
index 82d794c..6bdff42 100644
--- a/wifi/1.5/default/wifi_chip.cpp
+++ b/wifi/1.5/default/wifi_chip.cpp
@@ -28,6 +28,8 @@
 #include "wifi_chip.h"
 #include "wifi_status_util.h"
 
+#define P2P_MGMT_DEVICE_PREFIX "p2p-dev-"
+
 namespace {
 using android::sp;
 using android::base::unique_fd;
@@ -126,8 +128,37 @@
 }
 
 std::string getPredefinedP2pIfaceName() {
+    std::array<char, PROPERTY_VALUE_MAX> primaryIfaceName;
+    char p2pParentIfname[100];
+    std::string p2pDevIfName = "";
     std::array<char, PROPERTY_VALUE_MAX> buffer;
     property_get("wifi.direct.interface", buffer.data(), "p2p0");
+    if (strncmp(buffer.data(), P2P_MGMT_DEVICE_PREFIX,
+                strlen(P2P_MGMT_DEVICE_PREFIX)) == 0) {
+        /* Get the p2p parent interface name from p2p device interface name set
+         * in property */
+        strncpy(p2pParentIfname, buffer.data() + strlen(P2P_MGMT_DEVICE_PREFIX),
+                strlen(buffer.data()) - strlen(P2P_MGMT_DEVICE_PREFIX));
+        if (property_get(kActiveWlanIfaceNameProperty, primaryIfaceName.data(),
+                         nullptr) == 0) {
+            return buffer.data();
+        }
+        /* Check if the parent interface derived from p2p device interface name
+         * is active */
+        if (strncmp(p2pParentIfname, primaryIfaceName.data(),
+                    strlen(buffer.data()) - strlen(P2P_MGMT_DEVICE_PREFIX)) !=
+            0) {
+            /*
+             * Update the predefined p2p device interface parent interface name
+             * with current active wlan interface
+             */
+            p2pDevIfName += P2P_MGMT_DEVICE_PREFIX;
+            p2pDevIfName += primaryIfaceName.data();
+            LOG(INFO) << "update the p2p device interface name to "
+                      << p2pDevIfName.c_str();
+            return p2pDevIfName;
+        }
+    }
     return buffer.data();
 }
 
diff --git a/wifi/hostapd/1.3/vts/functional/Android.bp b/wifi/hostapd/1.3/vts/functional/Android.bp
index 6eceadf..78cd4af 100644
--- a/wifi/hostapd/1.3/vts/functional/Android.bp
+++ b/wifi/hostapd/1.3/vts/functional/Android.bp
@@ -26,6 +26,9 @@
 cc_test {
     name: "VtsHalWifiHostapdV1_3TargetTest",
     defaults: ["VtsHalTargetTestDefaults"],
+    tidy_timeout_srcs: [
+        "hostapd_hidl_test.cpp",
+    ],
     srcs: [
         "hostapd_hidl_test.cpp",
     ],
diff --git a/wifi/supplicant/1.0/vts/functional/Android.bp b/wifi/supplicant/1.0/vts/functional/Android.bp
index 121117c..2d86822 100644
--- a/wifi/supplicant/1.0/vts/functional/Android.bp
+++ b/wifi/supplicant/1.0/vts/functional/Android.bp
@@ -44,6 +44,9 @@
 cc_test {
     name: "VtsHalWifiSupplicantV1_0TargetTest",
     defaults: ["VtsHalTargetTestDefaults"],
+    tidy_timeout_srcs: [
+        "supplicant_sta_network_hidl_test.cpp",
+    ],
     srcs: [
         "supplicant_hidl_test.cpp",
         "supplicant_sta_iface_hidl_test.cpp",
@@ -71,6 +74,9 @@
 cc_test {
     name: "VtsHalWifiSupplicantP2pV1_0TargetTest",
     defaults: ["VtsHalTargetTestDefaults"],
+    tidy_timeout_srcs: [
+        "supplicant_p2p_iface_hidl_test.cpp",
+    ],
     srcs: [
         "VtsHalWifiSupplicantP2pV1_0TargetTest.cpp",
         "supplicant_p2p_iface_hidl_test.cpp",
diff --git a/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp b/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp
index 1606b7b..086166a 100644
--- a/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp
+++ b/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp
@@ -318,7 +318,7 @@
 }
 
 bool waitForFrameworkReady() {
-    int waitCount = 10;
+    int waitCount = 15;
     do {
         // Check whether package service is ready or not.
         if (!testing::checkSubstringInCommandOutput(
diff --git a/wifi/supplicant/1.4/vts/functional/Android.bp b/wifi/supplicant/1.4/vts/functional/Android.bp
index 8cbe04f..57ee830 100644
--- a/wifi/supplicant/1.4/vts/functional/Android.bp
+++ b/wifi/supplicant/1.4/vts/functional/Android.bp
@@ -77,7 +77,6 @@
         "general-tests",
         "vts",
     ],
-    disable_framework: true,
 }
 
 cc_test {
@@ -108,5 +107,4 @@
         "general-tests",
         "vts",
     ],
-    disable_framework: true,
 }
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicant.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicant.aidl
index b4371fd..4b26ac3 100644
--- a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicant.aidl
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicant.aidl
@@ -34,11 +34,11 @@
 package android.hardware.wifi.supplicant;
 @VintfStability
 interface ISupplicant {
-  android.hardware.wifi.supplicant.ISupplicantP2pIface addP2pInterface(in String ifName);
-  android.hardware.wifi.supplicant.ISupplicantStaIface addStaInterface(in String ifName);
+  @PropagateAllowBlocking android.hardware.wifi.supplicant.ISupplicantP2pIface addP2pInterface(in String ifName);
+  @PropagateAllowBlocking android.hardware.wifi.supplicant.ISupplicantStaIface addStaInterface(in String ifName);
   android.hardware.wifi.supplicant.DebugLevel getDebugLevel();
-  android.hardware.wifi.supplicant.ISupplicantP2pIface getP2pInterface(in String ifName);
-  android.hardware.wifi.supplicant.ISupplicantStaIface getStaInterface(in String ifName);
+  @PropagateAllowBlocking android.hardware.wifi.supplicant.ISupplicantP2pIface getP2pInterface(in String ifName);
+  @PropagateAllowBlocking android.hardware.wifi.supplicant.ISupplicantStaIface getStaInterface(in String ifName);
   boolean isDebugShowKeysEnabled();
   boolean isDebugShowTimestampEnabled();
   android.hardware.wifi.supplicant.IfaceInfo[] listInterfaces();
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantP2pIface.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantP2pIface.aidl
index ca7be73..7876d86 100644
--- a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantP2pIface.aidl
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantP2pIface.aidl
@@ -37,7 +37,7 @@
   void addBonjourService(in byte[] query, in byte[] response);
   void addGroup(in boolean persistent, in int persistentNetworkId);
   void addGroupWithConfig(in byte[] ssid, in String pskPassphrase, in boolean persistent, in int freq, in byte[] peerAddress, in boolean joinExistingGroup);
-  android.hardware.wifi.supplicant.ISupplicantP2pNetwork addNetwork();
+  @PropagateAllowBlocking android.hardware.wifi.supplicant.ISupplicantP2pNetwork addNetwork();
   void addUpnpService(in int version, in String serviceName);
   void cancelConnect();
   void cancelServiceDiscovery(in long identifier);
@@ -54,7 +54,7 @@
   boolean getEdmg();
   android.hardware.wifi.supplicant.P2pGroupCapabilityMask getGroupCapability(in byte[] peerAddress);
   String getName();
-  android.hardware.wifi.supplicant.ISupplicantP2pNetwork getNetwork(in int id);
+  @PropagateAllowBlocking android.hardware.wifi.supplicant.ISupplicantP2pNetwork getNetwork(in int id);
   byte[] getSsid(in byte[] peerAddress);
   android.hardware.wifi.supplicant.IfaceType getType();
   void invite(in String groupIfName, in byte[] goDeviceAddress, in byte[] peerAddress);
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaIface.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaIface.aidl
index ca40379..20c52ac 100644
--- a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaIface.aidl
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaIface.aidl
@@ -36,7 +36,7 @@
 interface ISupplicantStaIface {
   int addDppPeerUri(in String uri);
   int addExtRadioWork(in String name, in int freqInMhz, in int timeoutInSec);
-  android.hardware.wifi.supplicant.ISupplicantStaNetwork addNetwork();
+  @PropagateAllowBlocking android.hardware.wifi.supplicant.ISupplicantStaNetwork addNetwork();
   void addRxFilter(in android.hardware.wifi.supplicant.RxFilterType type);
   void cancelWps();
   void disconnect();
@@ -48,7 +48,7 @@
   android.hardware.wifi.supplicant.KeyMgmtMask getKeyMgmtCapabilities();
   byte[] getMacAddress();
   String getName();
-  android.hardware.wifi.supplicant.ISupplicantStaNetwork getNetwork(in int id);
+  @PropagateAllowBlocking android.hardware.wifi.supplicant.ISupplicantStaNetwork getNetwork(in int id);
   android.hardware.wifi.supplicant.IfaceType getType();
   android.hardware.wifi.supplicant.WpaDriverCapabilitiesMask getWpaDriverCapabilities();
   void initiateAnqpQuery(in byte[] macAddress, in android.hardware.wifi.supplicant.AnqpInfoId[] infoElements, in android.hardware.wifi.supplicant.Hs20AnqpSubtypes[] subTypes);
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicant.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicant.aidl
index 2ac1db7..c17289d 100644
--- a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicant.aidl
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicant.aidl
@@ -46,8 +46,8 @@
      *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
      *         |SupplicantStatusCode.FAILURE_IFACE_EXISTS|
      */
-    ISupplicantP2pIface addP2pInterface(in String ifName);
-    ISupplicantStaIface addStaInterface(in String ifName);
+    @PropagateAllowBlocking ISupplicantP2pIface addP2pInterface(in String ifName);
+    @PropagateAllowBlocking ISupplicantStaIface addStaInterface(in String ifName);
 
     /**
      * Get the debug level set.
@@ -68,8 +68,8 @@
      *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
      *         |SupplicantStatusCode.FAILURE_IFACE_UNKNOWN|
      */
-    ISupplicantP2pIface getP2pInterface(in String ifName);
-    ISupplicantStaIface getStaInterface(in String ifName);
+    @PropagateAllowBlocking ISupplicantP2pIface getP2pInterface(in String ifName);
+    @PropagateAllowBlocking ISupplicantStaIface getStaInterface(in String ifName);
 
     /**
      * Get whether the keys are shown in the debug logs or not.
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantP2pIface.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantP2pIface.aidl
index 64839e7..5394f49 100644
--- a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantP2pIface.aidl
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantP2pIface.aidl
@@ -103,7 +103,7 @@
      *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
      *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
      */
-    ISupplicantP2pNetwork addNetwork();
+    @PropagateAllowBlocking ISupplicantP2pNetwork addNetwork();
 
     /**
      * This command can be used to add a UPNP service.
@@ -320,7 +320,7 @@
      *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
      *         |SupplicantStatusCode.FAILURE_NETWORK_UNKNOWN|
      */
-    ISupplicantP2pNetwork getNetwork(in int id);
+    @PropagateAllowBlocking ISupplicantP2pNetwork getNetwork(in int id);
 
     /**
      * Gets the operational SSID of the device.
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIface.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIface.aidl
index b48fa04..5cb236f 100644
--- a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIface.aidl
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIface.aidl
@@ -86,7 +86,7 @@
      *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
      *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
      */
-    ISupplicantStaNetwork addNetwork();
+    @PropagateAllowBlocking ISupplicantStaNetwork addNetwork();
 
     /**
      * Send driver command to add the specified RX filter.
@@ -231,7 +231,7 @@
      *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
      *         |SupplicantStatusCode.FAILURE_NETWORK_UNKNOWN|
      */
-    ISupplicantStaNetwork getNetwork(in int id);
+    @PropagateAllowBlocking ISupplicantStaNetwork getNetwork(in int id);
 
     /**
      * Retrieves the type of the network interface.