Merge "Support standard extension frontend status" into main
diff --git a/Android.bp b/Android.bp
index baf3291..68115aa 100644
--- a/Android.bp
+++ b/Android.bp
@@ -86,3 +86,9 @@
         "VtsHalHidlTargetTestBase",
     ],
 }
+
+dirgroup {
+    name: "trusty_dirgroup_hardware_interfaces",
+    dirs: ["."],
+    visibility: ["//trusty/vendor/google/aosp/scripts"],
+}
diff --git a/atrace/1.0/vts/functional/Android.bp b/atrace/1.0/vts/functional/Android.bp
index 9681aa2..16fbaa2 100644
--- a/atrace/1.0/vts/functional/Android.bp
+++ b/atrace/1.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_kernel",
     // 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"
diff --git a/audio/aidl/default/Android.bp b/audio/aidl/default/Android.bp
index d47b0b1..73d7626 100644
--- a/audio/aidl/default/Android.bp
+++ b/audio/aidl/default/Android.bp
@@ -62,7 +62,6 @@
         "ModulePrimary.cpp",
         "SoundDose.cpp",
         "Stream.cpp",
-        "StreamSwitcher.cpp",
         "Telephony.cpp",
         "XsdcConversion.cpp",
         "alsa/Mixer.cpp",
@@ -72,6 +71,7 @@
         "bluetooth/DevicePortProxy.cpp",
         "bluetooth/ModuleBluetooth.cpp",
         "bluetooth/StreamBluetooth.cpp",
+        "deprecated/StreamSwitcher.cpp",
         "primary/PrimaryMixer.cpp",
         "primary/StreamPrimary.cpp",
         "r_submix/ModuleRemoteSubmix.cpp",
diff --git a/audio/aidl/default/Stream.cpp b/audio/aidl/default/Stream.cpp
index de66293..3d7f30c 100644
--- a/audio/aidl/default/Stream.cpp
+++ b/audio/aidl/default/Stream.cpp
@@ -937,9 +937,12 @@
 }
 
 StreamInHwGainHelper::StreamInHwGainHelper(const StreamContext* context)
-    : mChannelCount(getChannelCount(context->getChannelLayout())), mHwGains(mChannelCount, 0.0f) {}
+    : mChannelCount(getChannelCount(context->getChannelLayout())) {}
 
 ndk::ScopedAStatus StreamInHwGainHelper::getHwGainImpl(std::vector<float>* _aidl_return) {
+    if (mHwGains.empty()) {
+        mHwGains.resize(mChannelCount, 0.0f);
+    }
     *_aidl_return = mHwGains;
     LOG(DEBUG) << __func__ << ": returning " << ::android::internal::ToString(*_aidl_return);
     return ndk::ScopedAStatus::ok();
@@ -1068,10 +1071,12 @@
 }
 
 StreamOutHwVolumeHelper::StreamOutHwVolumeHelper(const StreamContext* context)
-    : mChannelCount(getChannelCount(context->getChannelLayout())),
-      mHwVolumes(mChannelCount, 0.0f) {}
+    : mChannelCount(getChannelCount(context->getChannelLayout())) {}
 
 ndk::ScopedAStatus StreamOutHwVolumeHelper::getHwVolumeImpl(std::vector<float>* _aidl_return) {
+    if (mHwVolumes.empty()) {
+        mHwVolumes.resize(mChannelCount, 0.0f);
+    }
     *_aidl_return = mHwVolumes;
     LOG(DEBUG) << __func__ << ": returning " << ::android::internal::ToString(*_aidl_return);
     return ndk::ScopedAStatus::ok();
diff --git a/audio/aidl/default/StreamSwitcher.cpp b/audio/aidl/default/deprecated/StreamSwitcher.cpp
similarity index 98%
rename from audio/aidl/default/StreamSwitcher.cpp
rename to audio/aidl/default/deprecated/StreamSwitcher.cpp
index 0052889..f1e0f52 100644
--- a/audio/aidl/default/StreamSwitcher.cpp
+++ b/audio/aidl/default/deprecated/StreamSwitcher.cpp
@@ -23,12 +23,12 @@
 #include <error/expected_utils.h>
 
 #include "core-impl/StreamStub.h"
-#include "core-impl/StreamSwitcher.h"
+#include "deprecated/StreamSwitcher.h"
 
 using aidl::android::hardware::audio::effect::IEffect;
 using aidl::android::media::audio::common::AudioDevice;
 
-namespace aidl::android::hardware::audio::core {
+namespace aidl::android::hardware::audio::core::deprecated {
 
 StreamSwitcher::StreamSwitcher(StreamContext* context, const Metadata& metadata)
     : mContext(context),
@@ -268,4 +268,4 @@
     return mStream->setGain(gain);
 }
 
-}  // namespace aidl::android::hardware::audio::core
+}  // namespace aidl::android::hardware::audio::core::deprecated
diff --git a/audio/aidl/default/include/core-impl/StreamSwitcher.h b/audio/aidl/default/deprecated/StreamSwitcher.h
similarity index 96%
rename from audio/aidl/default/include/core-impl/StreamSwitcher.h
rename to audio/aidl/default/deprecated/StreamSwitcher.h
index 2d75e85..56fdd23 100644
--- a/audio/aidl/default/include/core-impl/StreamSwitcher.h
+++ b/audio/aidl/default/deprecated/StreamSwitcher.h
@@ -14,11 +14,18 @@
  * limitations under the License.
  */
 
+/**
+ ** This class is deprecated because its use causes threading issues
+ ** with the FMQ due to change of threads reading and writing into FMQ.
+ **
+ ** DO NOT USE. These files will be removed.
+ **/
+
 #pragma once
 
-#include "Stream.h"
+#include "core-impl/Stream.h"
 
-namespace aidl::android::hardware::audio::core {
+namespace aidl::android::hardware::audio::core::deprecated {
 
 // 'StreamSwitcher' is an implementation of 'StreamCommonInterface' which allows
 // dynamically switching the underlying stream implementation based on currently
@@ -192,4 +199,4 @@
     bool mBluetoothParametersUpdated = false;
 };
 
-}  // namespace aidl::android::hardware::audio::core
+}  // namespace aidl::android::hardware::audio::core::deprecated
diff --git a/audio/aidl/default/include/core-impl/StreamRemoteSubmix.h b/audio/aidl/default/include/core-impl/StreamRemoteSubmix.h
index e78e8b7..5e52ad0 100644
--- a/audio/aidl/default/include/core-impl/StreamRemoteSubmix.h
+++ b/audio/aidl/default/include/core-impl/StreamRemoteSubmix.h
@@ -16,18 +16,19 @@
 
 #pragma once
 
-#include <atomic>
-#include <mutex>
 #include <vector>
 
 #include "core-impl/Stream.h"
+#include "deprecated/StreamSwitcher.h"
 #include "r_submix/SubmixRoute.h"
 
 namespace aidl::android::hardware::audio::core {
 
 class StreamRemoteSubmix : public StreamCommonImpl {
   public:
-    StreamRemoteSubmix(StreamContext* context, const Metadata& metadata);
+    StreamRemoteSubmix(
+            StreamContext* context, const Metadata& metadata,
+            const ::aidl::android::media::audio::common::AudioDeviceAddress& deviceAddress);
     ~StreamRemoteSubmix();
 
     // Methods of 'DriverInterface'.
@@ -44,18 +45,17 @@
 
     // Overridden methods of 'StreamCommonImpl', called on a Binder thread.
     ndk::ScopedAStatus prepareToClose() override;
-    ndk::ScopedAStatus setConnectedDevices(const ConnectedDevices& devices) override;
 
   private:
     long getDelayInUsForFrameCount(size_t frameCount);
-    ::aidl::android::media::audio::common::AudioDeviceAddress getDeviceAddress() const {
-        std::lock_guard guard(mLock);
-        return mDeviceAddress;
-    }
     size_t getStreamPipeSizeInFrames();
-    ::android::status_t inRead(void* buffer, size_t frameCount, size_t* actualFrameCount);
     ::android::status_t outWrite(void* buffer, size_t frameCount, size_t* actualFrameCount);
-    ::android::status_t setCurrentRoute();
+    ::android::status_t inRead(void* buffer, size_t frameCount, size_t* actualFrameCount);
+
+    const ::aidl::android::media::audio::common::AudioDeviceAddress mDeviceAddress;
+    const bool mIsInput;
+    r_submix::AudioConfig mStreamConfig;
+    std::shared_ptr<r_submix::SubmixRoute> mCurrentRoute = nullptr;
 
     // Limit for the number of error log entries to avoid spamming the logs.
     static constexpr int kMaxErrorLogs = 5;
@@ -66,15 +66,6 @@
     // 5ms between two read attempts when pipe is empty
     static constexpr int kReadAttemptSleepUs = 5000;
 
-    const bool mIsInput;
-    const r_submix::AudioConfig mStreamConfig;
-
-    mutable std::mutex mLock;
-    ::aidl::android::media::audio::common::AudioDeviceAddress mDeviceAddress GUARDED_BY(mLock);
-    std::atomic<bool> mDeviceAddressUpdated = false;
-
-    // Used by the worker thread only.
-    std::shared_ptr<r_submix::SubmixRoute> mCurrentRoute = nullptr;
     int64_t mStartTimeNs = 0;
     long mFramesSinceStart = 0;
     int mReadErrorCount = 0;
@@ -82,7 +73,7 @@
     int mWriteShutdownCount = 0;
 };
 
-class StreamInRemoteSubmix final : public StreamIn, public StreamRemoteSubmix {
+class StreamInRemoteSubmix final : public StreamIn, public deprecated::StreamSwitcher {
   public:
     friend class ndk::SharedRefBase;
     StreamInRemoteSubmix(
@@ -91,13 +82,19 @@
             const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones);
 
   private:
+    DeviceSwitchBehavior switchCurrentStream(
+            const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices)
+            override;
+    std::unique_ptr<deprecated::StreamCommonInterfaceEx> createNewStream(
+            const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices,
+            StreamContext* context, const Metadata& metadata) override;
     void onClose(StreamDescriptor::State) override { defaultOnClose(); }
     ndk::ScopedAStatus getActiveMicrophones(
             std::vector<::aidl::android::media::audio::common::MicrophoneDynamicInfo>* _aidl_return)
             override;
 };
 
-class StreamOutRemoteSubmix final : public StreamOut, public StreamRemoteSubmix {
+class StreamOutRemoteSubmix final : public StreamOut, public deprecated::StreamSwitcher {
   public:
     friend class ndk::SharedRefBase;
     StreamOutRemoteSubmix(
@@ -107,6 +104,12 @@
                     offloadInfo);
 
   private:
+    DeviceSwitchBehavior switchCurrentStream(
+            const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices)
+            override;
+    std::unique_ptr<deprecated::StreamCommonInterfaceEx> createNewStream(
+            const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices,
+            StreamContext* context, const Metadata& metadata) override;
     void onClose(StreamDescriptor::State) override { defaultOnClose(); }
 };
 
diff --git a/audio/aidl/default/primary/StreamPrimary.cpp b/audio/aidl/default/primary/StreamPrimary.cpp
index 1176d05..46e384e 100644
--- a/audio/aidl/default/primary/StreamPrimary.cpp
+++ b/audio/aidl/default/primary/StreamPrimary.cpp
@@ -56,7 +56,9 @@
 }
 
 ::android::status_t StreamPrimary::flush() {
-    return isStubStreamOnWorker() ? mStubDriver.flush() : StreamAlsa::flush();
+    RETURN_STATUS_IF_ERROR(isStubStreamOnWorker() ? mStubDriver.flush() : StreamAlsa::flush());
+    // TODO(b/372951987): consider if this needs to be done from 'StreamInWorkerLogic::cycle'.
+    return mIsInput ? standby() : ::android::OK;
 }
 
 ::android::status_t StreamPrimary::pause() {
@@ -216,11 +218,12 @@
     if (isStubStream()) {
         return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
     }
-    float gain;
-    RETURN_STATUS_IF_ERROR(primary::PrimaryMixer::getInstance().getMicGain(&gain));
-    _aidl_return->resize(0);
-    _aidl_return->resize(mChannelCount, gain);
-    RETURN_STATUS_IF_ERROR(setHwGainImpl(*_aidl_return));
+    if (mHwGains.empty()) {
+        float gain;
+        RETURN_STATUS_IF_ERROR(primary::PrimaryMixer::getInstance().getMicGain(&gain));
+        _aidl_return->resize(mChannelCount, gain);
+        RETURN_STATUS_IF_ERROR(setHwGainImpl(*_aidl_return));
+    }
     return getHwGainImpl(_aidl_return);
 }
 
@@ -239,6 +242,14 @@
         mHwGains = currentGains;
         return status;
     }
+    float gain;
+    RETURN_STATUS_IF_ERROR(primary::PrimaryMixer::getInstance().getMicGain(&gain));
+    // Due to rounding errors, round trip conversions between percents and indexed values may not
+    // match.
+    if (gain != in_channelGains[0]) {
+        LOG(WARNING) << __func__ << ": unmatched gain: set: " << in_channelGains[0]
+                     << ", from mixer: " << gain;
+    }
     return ndk::ScopedAStatus::ok();
 }
 
@@ -252,9 +263,11 @@
     if (isStubStream()) {
         return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
     }
-    RETURN_STATUS_IF_ERROR(primary::PrimaryMixer::getInstance().getVolumes(_aidl_return));
-    _aidl_return->resize(mChannelCount);
-    RETURN_STATUS_IF_ERROR(setHwVolumeImpl(*_aidl_return));
+    if (mHwVolumes.empty()) {
+        RETURN_STATUS_IF_ERROR(primary::PrimaryMixer::getInstance().getVolumes(_aidl_return));
+        _aidl_return->resize(mChannelCount);
+        RETURN_STATUS_IF_ERROR(setHwVolumeImpl(*_aidl_return));
+    }
     return getHwVolumeImpl(_aidl_return);
 }
 
@@ -270,6 +283,15 @@
         mHwVolumes = currentVolumes;
         return status;
     }
+    std::vector<float> volumes;
+    RETURN_STATUS_IF_ERROR(primary::PrimaryMixer::getInstance().getVolumes(&volumes));
+    // Due to rounding errors, round trip conversions between percents and indexed values may not
+    // match.
+    if (volumes != in_channelVolumes) {
+        LOG(WARNING) << __func__ << ": unmatched volumes: set: "
+                     << ::android::internal::ToString(in_channelVolumes)
+                     << ", from mixer: " << ::android::internal::ToString(volumes);
+    }
     return ndk::ScopedAStatus::ok();
 }
 
diff --git a/audio/aidl/default/r_submix/StreamRemoteSubmix.cpp b/audio/aidl/default/r_submix/StreamRemoteSubmix.cpp
index 93fe028..ea59771 100644
--- a/audio/aidl/default/r_submix/StreamRemoteSubmix.cpp
+++ b/audio/aidl/default/r_submix/StreamRemoteSubmix.cpp
@@ -26,106 +26,132 @@
 using aidl::android::hardware::audio::common::SourceMetadata;
 using aidl::android::hardware::audio::core::r_submix::SubmixRoute;
 using aidl::android::media::audio::common::AudioDeviceAddress;
-using aidl::android::media::audio::common::AudioDeviceType;
 using aidl::android::media::audio::common::AudioOffloadInfo;
 using aidl::android::media::audio::common::MicrophoneDynamicInfo;
 using aidl::android::media::audio::common::MicrophoneInfo;
 
 namespace aidl::android::hardware::audio::core {
 
-StreamRemoteSubmix::StreamRemoteSubmix(StreamContext* context, const Metadata& metadata)
+using deprecated::InnerStreamWrapper;
+using deprecated::StreamCommonInterfaceEx;
+using deprecated::StreamSwitcher;
+
+StreamRemoteSubmix::StreamRemoteSubmix(StreamContext* context, const Metadata& metadata,
+                                       const AudioDeviceAddress& deviceAddress)
     : StreamCommonImpl(context, metadata),
-      mIsInput(isInput(metadata)),
-      mStreamConfig{.sampleRate = context->getSampleRate(),
-                    .format = context->getFormat(),
-                    .channelLayout = context->getChannelLayout(),
-                    .frameSize = context->getFrameSize()} {}
+      mDeviceAddress(deviceAddress),
+      mIsInput(isInput(metadata)) {
+    mStreamConfig.frameSize = context->getFrameSize();
+    mStreamConfig.format = context->getFormat();
+    mStreamConfig.channelLayout = context->getChannelLayout();
+    mStreamConfig.sampleRate = context->getSampleRate();
+}
 
 StreamRemoteSubmix::~StreamRemoteSubmix() {
     cleanupWorker();
 }
 
 ::android::status_t StreamRemoteSubmix::init() {
+    mCurrentRoute = SubmixRoute::findOrCreateRoute(mDeviceAddress, mStreamConfig);
+    if (mCurrentRoute == nullptr) {
+        return ::android::NO_INIT;
+    }
+    if (!mCurrentRoute->isStreamConfigValid(mIsInput, mStreamConfig)) {
+        LOG(ERROR) << __func__ << ": invalid stream config";
+        return ::android::NO_INIT;
+    }
+    sp<MonoPipe> sink = mCurrentRoute->getSink();
+    if (sink == nullptr) {
+        LOG(ERROR) << __func__ << ": nullptr sink when opening stream";
+        return ::android::NO_INIT;
+    }
+    if ((!mIsInput || mCurrentRoute->isStreamInOpen()) && sink->isShutdown()) {
+        LOG(DEBUG) << __func__ << ": Shut down sink when opening stream";
+        if (::android::OK != mCurrentRoute->resetPipe()) {
+            LOG(ERROR) << __func__ << ": reset pipe failed";
+            return ::android::NO_INIT;
+        }
+    }
+    mCurrentRoute->openStream(mIsInput);
     return ::android::OK;
 }
 
 ::android::status_t StreamRemoteSubmix::drain(StreamDescriptor::DrainMode) {
+    usleep(1000);
     return ::android::OK;
 }
 
 ::android::status_t StreamRemoteSubmix::flush() {
+    usleep(1000);
     return ::android::OK;
 }
 
 ::android::status_t StreamRemoteSubmix::pause() {
+    usleep(1000);
     return ::android::OK;
 }
 
 ::android::status_t StreamRemoteSubmix::standby() {
-    if (mCurrentRoute) mCurrentRoute->standby(mIsInput);
+    mCurrentRoute->standby(mIsInput);
     return ::android::OK;
 }
 
 ::android::status_t StreamRemoteSubmix::start() {
-    if (mDeviceAddressUpdated.load(std::memory_order_acquire)) {
-        LOG(DEBUG) << __func__ << ": device address updated, reset current route";
-        shutdown();
-        mDeviceAddressUpdated.store(false, std::memory_order_release);
-    }
-    if (!mCurrentRoute) {
-        RETURN_STATUS_IF_ERROR(setCurrentRoute());
-        LOG(DEBUG) << __func__ << ": have current route? " << (mCurrentRoute != nullptr);
-    }
-    if (mCurrentRoute) mCurrentRoute->exitStandby(mIsInput);
+    mCurrentRoute->exitStandby(mIsInput);
     mStartTimeNs = ::android::uptimeNanos();
     mFramesSinceStart = 0;
     return ::android::OK;
 }
 
+ndk::ScopedAStatus StreamRemoteSubmix::prepareToClose() {
+    if (!mIsInput) {
+        std::shared_ptr<SubmixRoute> route = SubmixRoute::findRoute(mDeviceAddress);
+        if (route != nullptr) {
+            sp<MonoPipe> sink = route->getSink();
+            if (sink == nullptr) {
+                ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+            }
+            LOG(DEBUG) << __func__ << ": shutting down MonoPipe sink";
+
+            sink->shutdown(true);
+            // The client already considers this stream as closed, release the output end.
+            route->closeStream(mIsInput);
+        } else {
+            LOG(DEBUG) << __func__ << ": stream already closed.";
+            ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+        }
+    }
+    return ndk::ScopedAStatus::ok();
+}
+
 // Remove references to the specified input and output streams.  When the device no longer
 // references input and output streams destroy the associated pipe.
 void StreamRemoteSubmix::shutdown() {
-    if (!mCurrentRoute) return;
     mCurrentRoute->closeStream(mIsInput);
     // If all stream instances are closed, we can remove route information for this port.
     if (!mCurrentRoute->hasAtleastOneStreamOpen()) {
         mCurrentRoute->releasePipe();
         LOG(DEBUG) << __func__ << ": pipe destroyed";
-        SubmixRoute::removeRoute(getDeviceAddress());
+        SubmixRoute::removeRoute(mDeviceAddress);
     }
     mCurrentRoute.reset();
 }
 
 ::android::status_t StreamRemoteSubmix::transfer(void* buffer, size_t frameCount,
                                                  size_t* actualFrameCount, int32_t* latencyMs) {
-    if (mDeviceAddressUpdated.load(std::memory_order_acquire)) {
-        // 'setConnectedDevices' was called. I/O will be restarted.
-        return ::android::OK;
-    }
-
     *latencyMs = getDelayInUsForFrameCount(getStreamPipeSizeInFrames()) / 1000;
     LOG(VERBOSE) << __func__ << ": Latency " << *latencyMs << "ms";
-    ::android::status_t status = ::android::OK;
-    if (mCurrentRoute) {
-        mCurrentRoute->exitStandby(mIsInput);
-        status = mIsInput ? inRead(buffer, frameCount, actualFrameCount)
-                          : outWrite(buffer, frameCount, actualFrameCount);
-        if ((status != ::android::OK && mIsInput) ||
-            ((status != ::android::OK && status != ::android::DEAD_OBJECT) && !mIsInput)) {
-            return status;
-        }
-    } else {
-        LOG(WARNING) << __func__ << ": no current route";
-        if (mIsInput) {
-            memset(buffer, 0, mStreamConfig.frameSize * frameCount);
-        }
-        *actualFrameCount = frameCount;
+    mCurrentRoute->exitStandby(mIsInput);
+    ::android::status_t status = mIsInput ? inRead(buffer, frameCount, actualFrameCount)
+                                          : outWrite(buffer, frameCount, actualFrameCount);
+    if ((status != ::android::OK && mIsInput) ||
+        ((status != ::android::OK && status != ::android::DEAD_OBJECT) && !mIsInput)) {
+        return status;
     }
     mFramesSinceStart += *actualFrameCount;
-    // If there is no route, always block, otherwise:
-    //  - Input streams always need to block, output streams need to block when there is no sink.
-    //  - When the sink exists, more sophisticated blocking algorithm is implemented by MonoPipe.
-    if (mCurrentRoute && !mIsInput && status != ::android::DEAD_OBJECT) return ::android::OK;
+    if (!mIsInput && status != ::android::DEAD_OBJECT) return ::android::OK;
+    // Input streams always need to block, output streams need to block when there is no sink.
+    // When the sink exists, more sophisticated blocking algorithm is implemented by MonoPipe.
     const long bufferDurationUs =
             (*actualFrameCount) * MICROS_PER_SECOND / mContext.getSampleRate();
     const auto totalDurationUs = (::android::uptimeNanos() - mStartTimeNs) / NANOS_PER_MICROSECOND;
@@ -141,10 +167,6 @@
 }
 
 ::android::status_t StreamRemoteSubmix::refinePosition(StreamDescriptor::Position* position) {
-    if (!mCurrentRoute) {
-        RETURN_STATUS_IF_ERROR(setCurrentRoute());
-        if (!mCurrentRoute) return ::android::OK;
-    }
     sp<MonoPipeReader> source = mCurrentRoute->getSource();
     if (source == nullptr) {
         return ::android::NO_INIT;
@@ -168,7 +190,6 @@
 
 // Calculate the maximum size of the pipe buffer in frames for the specified stream.
 size_t StreamRemoteSubmix::getStreamPipeSizeInFrames() {
-    if (!mCurrentRoute) return r_submix::kDefaultPipeSizeInFrames;
     auto pipeConfig = mCurrentRoute->getPipeConfig();
     const size_t maxFrameSize = std::max(mStreamConfig.frameSize, pipeConfig.frameSize);
     return (pipeConfig.frameCount * pipeConfig.frameSize) / maxFrameSize;
@@ -192,7 +213,7 @@
     }
     mWriteShutdownCount = 0;
 
-    LOG(VERBOSE) << __func__ << ": " << getDeviceAddress().toString() << ", " << frameCount
+    LOG(VERBOSE) << __func__ << ": " << mDeviceAddress.toString() << ", " << frameCount
                  << " frames";
 
     const bool shouldBlockWrite = mCurrentRoute->shouldBlockWrite();
@@ -266,9 +287,8 @@
     }
     mReadErrorCount = 0;
 
-    LOG(VERBOSE) << __func__ << ": " << getDeviceAddress().toString() << ", " << frameCount
+    LOG(VERBOSE) << __func__ << ": " << mDeviceAddress.toString() << ", " << frameCount
                  << " frames";
-
     // read the data from the pipe
     char* buff = (char*)buffer;
     size_t actuallyRead = 0;
@@ -308,91 +328,10 @@
     return ::android::OK;
 }
 
-::android::status_t StreamRemoteSubmix::setCurrentRoute() {
-    const auto address = getDeviceAddress();
-    if (address == AudioDeviceAddress{}) {
-        return ::android::OK;
-    }
-    mCurrentRoute = SubmixRoute::findOrCreateRoute(address, mStreamConfig);
-    if (mCurrentRoute == nullptr) {
-        return ::android::NO_INIT;
-    }
-    if (!mCurrentRoute->isStreamConfigValid(mIsInput, mStreamConfig)) {
-        LOG(ERROR) << __func__ << ": invalid stream config";
-        return ::android::NO_INIT;
-    }
-    sp<MonoPipe> sink = mCurrentRoute->getSink();
-    if (sink == nullptr) {
-        LOG(ERROR) << __func__ << ": nullptr sink when opening stream";
-        return ::android::NO_INIT;
-    }
-    if ((!mIsInput || mCurrentRoute->isStreamInOpen()) && sink->isShutdown()) {
-        LOG(DEBUG) << __func__ << ": Shut down sink when opening stream";
-        if (::android::OK != mCurrentRoute->resetPipe()) {
-            LOG(ERROR) << __func__ << ": reset pipe failed";
-            return ::android::NO_INIT;
-        }
-    }
-    mCurrentRoute->openStream(mIsInput);
-    return ::android::OK;
-}
-
-ndk::ScopedAStatus StreamRemoteSubmix::prepareToClose() {
-    if (!mIsInput) {
-        const auto address = getDeviceAddress();
-        if (address == AudioDeviceAddress{}) return ndk::ScopedAStatus::ok();
-        std::shared_ptr<SubmixRoute> route = SubmixRoute::findRoute(address);
-        if (route != nullptr) {
-            sp<MonoPipe> sink = route->getSink();
-            if (sink == nullptr) {
-                ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
-            }
-            LOG(DEBUG) << __func__ << ": shutting down MonoPipe sink";
-
-            sink->shutdown(true);
-            // The client already considers this stream as closed, release the output end.
-            route->closeStream(mIsInput);
-        } else {
-            LOG(DEBUG) << __func__ << ": stream already closed.";
-            ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
-        }
-    }
-    return ndk::ScopedAStatus::ok();
-}
-
-ndk::ScopedAStatus StreamRemoteSubmix::setConnectedDevices(const ConnectedDevices& devices) {
-    if (devices.size() > 1) {
-        LOG(ERROR) << __func__ << ": Only single device supported, got " << devices.size();
-        return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
-    }
-    AudioDeviceAddress newAddress;
-    if (!devices.empty()) {
-        if (auto deviceDesc = devices.front().type;
-            (mIsInput && deviceDesc.type != AudioDeviceType::IN_SUBMIX) ||
-            (!mIsInput && deviceDesc.type != AudioDeviceType::OUT_SUBMIX)) {
-            LOG(ERROR) << __func__ << ": Device type " << toString(deviceDesc.type)
-                       << " not supported";
-            return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
-        }
-        newAddress = devices.front().address;
-        LOG(DEBUG) << __func__ << ": connected to " << newAddress.toString();
-    } else {
-        LOG(DEBUG) << __func__ << ": disconnected";
-    }
-    RETURN_STATUS_IF_ERROR(StreamCommonImpl::setConnectedDevices(devices));
-    std::lock_guard guard(mLock);
-    if (mDeviceAddress != newAddress) {
-        mDeviceAddress = newAddress;
-        mDeviceAddressUpdated.store(true, std::memory_order_release);
-    }
-    return ndk::ScopedAStatus::ok();
-}
-
 StreamInRemoteSubmix::StreamInRemoteSubmix(StreamContext&& context,
                                            const SinkMetadata& sinkMetadata,
                                            const std::vector<MicrophoneInfo>& microphones)
-    : StreamIn(std::move(context), microphones),
-      StreamRemoteSubmix(&mContextInstance, sinkMetadata) {}
+    : StreamIn(std::move(context), microphones), StreamSwitcher(&mContextInstance, sinkMetadata) {}
 
 ndk::ScopedAStatus StreamInRemoteSubmix::getActiveMicrophones(
         std::vector<MicrophoneDynamicInfo>* _aidl_return) {
@@ -401,10 +340,66 @@
     return ndk::ScopedAStatus::ok();
 }
 
+StreamSwitcher::DeviceSwitchBehavior StreamInRemoteSubmix::switchCurrentStream(
+        const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices) {
+    // This implementation effectively postpones stream creation until
+    // receiving the first call to 'setConnectedDevices' with a non-empty list.
+    if (isStubStream()) {
+        if (devices.size() == 1) {
+            auto deviceDesc = devices.front().type;
+            if (deviceDesc.type ==
+                ::aidl::android::media::audio::common::AudioDeviceType::IN_SUBMIX) {
+                return DeviceSwitchBehavior::CREATE_NEW_STREAM;
+            }
+            LOG(ERROR) << __func__ << ": Device type " << toString(deviceDesc.type)
+                       << " not supported";
+        } else {
+            LOG(ERROR) << __func__ << ": Only single device supported.";
+        }
+        return DeviceSwitchBehavior::UNSUPPORTED_DEVICES;
+    }
+    return DeviceSwitchBehavior::USE_CURRENT_STREAM;
+}
+
+std::unique_ptr<StreamCommonInterfaceEx> StreamInRemoteSubmix::createNewStream(
+        const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices,
+        StreamContext* context, const Metadata& metadata) {
+    return std::unique_ptr<StreamCommonInterfaceEx>(
+            new InnerStreamWrapper<StreamRemoteSubmix>(context, metadata, devices.front().address));
+}
+
 StreamOutRemoteSubmix::StreamOutRemoteSubmix(StreamContext&& context,
                                              const SourceMetadata& sourceMetadata,
                                              const std::optional<AudioOffloadInfo>& offloadInfo)
     : StreamOut(std::move(context), offloadInfo),
-      StreamRemoteSubmix(&mContextInstance, sourceMetadata) {}
+      StreamSwitcher(&mContextInstance, sourceMetadata) {}
+
+StreamSwitcher::DeviceSwitchBehavior StreamOutRemoteSubmix::switchCurrentStream(
+        const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices) {
+    // This implementation effectively postpones stream creation until
+    // receiving the first call to 'setConnectedDevices' with a non-empty list.
+    if (isStubStream()) {
+        if (devices.size() == 1) {
+            auto deviceDesc = devices.front().type;
+            if (deviceDesc.type ==
+                ::aidl::android::media::audio::common::AudioDeviceType::OUT_SUBMIX) {
+                return DeviceSwitchBehavior::CREATE_NEW_STREAM;
+            }
+            LOG(ERROR) << __func__ << ": Device type " << toString(deviceDesc.type)
+                       << " not supported";
+        } else {
+            LOG(ERROR) << __func__ << ": Only single device supported.";
+        }
+        return DeviceSwitchBehavior::UNSUPPORTED_DEVICES;
+    }
+    return DeviceSwitchBehavior::USE_CURRENT_STREAM;
+}
+
+std::unique_ptr<StreamCommonInterfaceEx> StreamOutRemoteSubmix::createNewStream(
+        const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices,
+        StreamContext* context, const Metadata& metadata) {
+    return std::unique_ptr<StreamCommonInterfaceEx>(
+            new InnerStreamWrapper<StreamRemoteSubmix>(context, metadata, devices.front().address));
+}
 
 }  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/r_submix/SubmixRoute.h b/audio/aidl/default/r_submix/SubmixRoute.h
index 0097f39..5425f12 100644
--- a/audio/aidl/default/r_submix/SubmixRoute.h
+++ b/audio/aidl/default/r_submix/SubmixRoute.h
@@ -25,12 +25,10 @@
 #include <media/nbaio/MonoPipe.h>
 #include <media/nbaio/MonoPipeReader.h>
 
-#include <Utils.h>
 #include <aidl/android/media/audio/common/AudioChannelLayout.h>
 #include <aidl/android/media/audio/common/AudioDeviceAddress.h>
 #include <aidl/android/media/audio/common/AudioFormatDescription.h>
 
-using aidl::android::hardware::audio::common::getFrameSizeInBytes;
 using aidl::android::media::audio::common::AudioChannelLayout;
 using aidl::android::media::audio::common::AudioFormatDescription;
 using aidl::android::media::audio::common::AudioFormatType;
@@ -58,8 +56,8 @@
     AudioChannelLayout channelLayout =
             AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
                     AudioChannelLayout::LAYOUT_STEREO);
-    size_t frameSize = getFrameSizeInBytes(format, channelLayout);
-    size_t frameCount = 0;
+    size_t frameSize;
+    size_t frameCount;
 };
 
 class SubmixRoute {
diff --git a/authsecret/aidl/Android.bp b/authsecret/aidl/Android.bp
index 90e128d..b5e4e3d 100644
--- a/authsecret/aidl/Android.bp
+++ b/authsecret/aidl/Android.bp
@@ -10,6 +10,7 @@
 aidl_interface {
     name: "android.hardware.authsecret",
     vendor_available: true,
+    frozen: true,
     srcs: ["android/hardware/authsecret/*.aidl"],
     stability: "vintf",
     backend: {
diff --git a/automotive/audiocontrol/1.0/vts/functional/Android.bp b/automotive/audiocontrol/1.0/vts/functional/Android.bp
index 15c480a..fe5be81 100644
--- a/automotive/audiocontrol/1.0/vts/functional/Android.bp
+++ b/automotive/audiocontrol/1.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_automotive",
     // 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"
diff --git a/automotive/audiocontrol/2.0/vts/functional/Android.bp b/automotive/audiocontrol/2.0/vts/functional/Android.bp
index cb7a54d..597aaa3 100644
--- a/automotive/audiocontrol/2.0/vts/functional/Android.bp
+++ b/automotive/audiocontrol/2.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_automotive",
     // 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"
diff --git a/automotive/can/1.0/default/libnetdevice/Android.bp b/automotive/can/1.0/default/libnetdevice/Android.bp
index 653e773..affbeee 100644
--- a/automotive/can/1.0/default/libnetdevice/Android.bp
+++ b/automotive/can/1.0/default/libnetdevice/Android.bp
@@ -26,6 +26,7 @@
 cc_library_static {
     name: "android.hardware.automotive.can@libnetdevice",
     defaults: ["android.hardware.automotive.can@defaults"],
+    host_supported: true,
     vendor_available: true,
     srcs: [
         "can.cpp",
diff --git a/automotive/can/1.0/default/libnetdevice/can.cpp b/automotive/can/1.0/default/libnetdevice/can.cpp
index 2a0545a..9cf0253 100644
--- a/automotive/can/1.0/default/libnetdevice/can.cpp
+++ b/automotive/can/1.0/default/libnetdevice/can.cpp
@@ -33,7 +33,7 @@
 
 static constexpr can_err_mask_t kErrMask = CAN_ERR_MASK;
 
-base::unique_fd socket(const std::string& ifname) {
+base::unique_fd socket(std::string_view ifname) {
     sockaddr_can addr = {};
     addr.can_family = AF_CAN;
     addr.can_ifindex = nametoindex(ifname);
@@ -66,11 +66,11 @@
     return sock;
 }
 
-bool setBitrate(std::string ifname, uint32_t bitrate) {
+bool setBitrate(std::string_view ifname, uint32_t bitrate) {
     can_bittiming bt = {};
     bt.bitrate = bitrate;
 
-    nl::MessageFactory<ifinfomsg> req(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_ACK);
+    nl::MessageFactory<ifinfomsg> req(RTM_NEWLINK);
 
     req->ifi_index = nametoindex(ifname);
     if (req->ifi_index == 0) {
diff --git a/automotive/can/1.0/default/libnetdevice/common.cpp b/automotive/can/1.0/default/libnetdevice/common.cpp
index 28e50af..22add65 100644
--- a/automotive/can/1.0/default/libnetdevice/common.cpp
+++ b/automotive/can/1.0/default/libnetdevice/common.cpp
@@ -22,8 +22,8 @@
 
 namespace android::netdevice {
 
-unsigned int nametoindex(const std::string& ifname) {
-    const auto ifidx = if_nametoindex(ifname.c_str());
+unsigned int nametoindex(std::string_view ifname) {
+    const auto ifidx = if_nametoindex(std::string(ifname).c_str());
     if (ifidx != 0) return ifidx;
 
     if (errno != ENODEV) {
diff --git a/automotive/can/1.0/default/libnetdevice/common.h b/automotive/can/1.0/default/libnetdevice/common.h
index 661e3f8..e73c581 100644
--- a/automotive/can/1.0/default/libnetdevice/common.h
+++ b/automotive/can/1.0/default/libnetdevice/common.h
@@ -32,6 +32,6 @@
  * \param ifname Interface to check
  * \return Interface index, or 0 if the interface doesn't exist
  */
-unsigned int nametoindex(const std::string& ifname);
+unsigned int nametoindex(std::string_view ifname);
 
 }  // namespace android::netdevice
diff --git a/automotive/can/1.0/default/libnetdevice/ethtool.cpp b/automotive/can/1.0/default/libnetdevice/ethtool.cpp
index 762ef5c..b0f88c7 100644
--- a/automotive/can/1.0/default/libnetdevice/ethtool.cpp
+++ b/automotive/can/1.0/default/libnetdevice/ethtool.cpp
@@ -19,27 +19,28 @@
 #include "ifreqs.h"
 
 #include <linux/ethtool.h>
+#include <linux/sockios.h>
 
 namespace android::netdevice::ethtool {
 
-std::optional<uint32_t> getValue(const std::string& ifname, uint32_t command) {
+std::optional<uint32_t> getValue(std::string_view ifname, uint32_t command) {
     struct ethtool_value valueop = {};
     valueop.cmd = command;
 
     auto ifr = ifreqs::fromName(ifname);
-    ifr.ifr_data = &valueop;
+    ifr.ifr_data = reinterpret_cast<caddr_t>(&valueop);
 
     if (!ifreqs::send(SIOCETHTOOL, ifr)) return std::nullopt;
     return valueop.data;
 }
 
-bool setValue(const std::string& ifname, uint32_t command, uint32_t value) {
+bool setValue(std::string_view ifname, uint32_t command, uint32_t value) {
     struct ethtool_value valueop = {};
     valueop.cmd = command;
     valueop.data = value;
 
     auto ifr = ifreqs::fromName(ifname);
-    ifr.ifr_data = &valueop;
+    ifr.ifr_data = reinterpret_cast<caddr_t>(&valueop);
 
     return ifreqs::send(SIOCETHTOOL, ifr);
 }
diff --git a/automotive/can/1.0/default/libnetdevice/ifreqs.cpp b/automotive/can/1.0/default/libnetdevice/ifreqs.cpp
index 8471173..2e6ad41 100644
--- a/automotive/can/1.0/default/libnetdevice/ifreqs.cpp
+++ b/automotive/can/1.0/default/libnetdevice/ifreqs.cpp
@@ -21,6 +21,8 @@
 #include <android-base/logging.h>
 #include <android-base/unique_fd.h>
 
+#include <sys/ioctl.h>
+
 #include <map>
 
 namespace android::netdevice::ifreqs {
@@ -68,9 +70,11 @@
     return true;
 }
 
-struct ifreq fromName(const std::string& ifname) {
+struct ifreq fromName(std::string_view ifname) {
     struct ifreq ifr = {};
-    strlcpy(ifr.ifr_name, ifname.c_str(), IF_NAMESIZE);
+    // memcpy: last \0 initialized with ifreq above
+    memcpy(ifr.ifr_name, ifname.data(),
+           std::min(ifname.size(), static_cast<size_t>(IF_NAMESIZE - 1)));
     return ifr;
 }
 
diff --git a/automotive/can/1.0/default/libnetdevice/ifreqs.h b/automotive/can/1.0/default/libnetdevice/ifreqs.h
index aa7030b..f9d8d3b 100644
--- a/automotive/can/1.0/default/libnetdevice/ifreqs.h
+++ b/automotive/can/1.0/default/libnetdevice/ifreqs.h
@@ -52,6 +52,6 @@
  * \param ifname Interface to initialize request with
  * \return Interface request with ifr_name field set to ifname
  */
-struct ifreq fromName(const std::string& ifname);
+struct ifreq fromName(std::string_view ifname);
 
 }  // namespace android::netdevice::ifreqs
diff --git a/automotive/can/1.0/default/libnetdevice/include/libnetdevice/can.h b/automotive/can/1.0/default/libnetdevice/include/libnetdevice/can.h
index 3886acf..6045733 100644
--- a/automotive/can/1.0/default/libnetdevice/include/libnetdevice/can.h
+++ b/automotive/can/1.0/default/libnetdevice/include/libnetdevice/can.h
@@ -28,7 +28,7 @@
  * \param ifname Interface to open a socket against
  * \return Socket's FD or -1 in case of failure
  */
-base::unique_fd socket(const std::string& ifname);
+base::unique_fd socket(std::string_view ifname);
 
 /**
  * Sets CAN interface bitrate.
@@ -36,6 +36,6 @@
  * \param ifname Interface for which the bitrate is to be set
  * \return true on success, false on failure
  */
-bool setBitrate(std::string ifname, uint32_t bitrate);
+bool setBitrate(std::string_view ifname, uint32_t bitrate);
 
 }  // namespace android::netdevice::can
diff --git a/automotive/can/1.0/default/libnetdevice/include/libnetdevice/ethtool.h b/automotive/can/1.0/default/libnetdevice/include/libnetdevice/ethtool.h
index 26bfdce..416108f 100644
--- a/automotive/can/1.0/default/libnetdevice/include/libnetdevice/ethtool.h
+++ b/automotive/can/1.0/default/libnetdevice/include/libnetdevice/ethtool.h
@@ -29,7 +29,7 @@
  * \param command Fetch command (ETHTOOL_G*)
  * \return value, or nullopt if fetch failed
  */
-std::optional<uint32_t> getValue(const std::string& ifname, uint32_t command);
+std::optional<uint32_t> getValue(std::string_view ifname, uint32_t command);
 
 /**
  * Set a single value with ethtool_value.
@@ -40,6 +40,6 @@
  * \param value New value
  * \return true if succeeded, false otherwise
  */
-bool setValue(const std::string& ifname, uint32_t command, uint32_t value);
+bool setValue(std::string_view ifname, uint32_t command, uint32_t value);
 
 }  // namespace android::netdevice::ethtool
diff --git a/automotive/can/1.0/default/libnetdevice/include/libnetdevice/libnetdevice.h b/automotive/can/1.0/default/libnetdevice/include/libnetdevice/libnetdevice.h
index 657f9b2..75655d5 100644
--- a/automotive/can/1.0/default/libnetdevice/include/libnetdevice/libnetdevice.h
+++ b/automotive/can/1.0/default/libnetdevice/include/libnetdevice/libnetdevice.h
@@ -43,7 +43,7 @@
  * \param ifname Interface to check
  * \return true if it exists, false otherwise
  */
-bool exists(std::string ifname);
+bool exists(std::string_view ifname);
 
 /**
  * Checks if network interface is up.
@@ -51,7 +51,7 @@
  * \param ifname Interface to check
  * \return true/false if the check succeeded, nullopt otherwise
  */
-std::optional<bool> isUp(std::string ifname);
+std::optional<bool> isUp(std::string_view ifname);
 
 /**
  * Interface condition to wait for.
@@ -101,7 +101,7 @@
  * \param ifname Interface to bring up
  * \return true in case of success, false otherwise
  */
-bool up(std::string ifname);
+bool up(std::string_view ifname);
 
 /**
  * Brings network interface down.
@@ -109,7 +109,38 @@
  * \param ifname Interface to bring down
  * \return true in case of success, false otherwise
  */
-bool down(std::string ifname);
+bool down(std::string_view ifname);
+
+/**
+ * Retrieves all IPv4 addresses of a given interface.
+ *
+ * \param ifname Interface to query
+ * \return list of IPv4 addresses of this interface
+ */
+std::set<std::string> getAllAddr4(std::string_view ifname);
+
+/**
+ * Set IPv4 address on a given interface.
+ *
+ * This function will overwrite any other existing IPv4 addresses.
+ *
+ * \param ifname Interface to modify
+ * \param addr IPv4 address to set
+ * \return true in case of success, false otherwise
+ */
+bool setAddr4(std::string_view ifname, std::string_view addr);
+
+/**
+ * Add new IPv4 address to a given interface.
+ *
+ * Please note this doesn't remove existing IPv4 addresses.
+ *
+ * \param ifname Interface to modify
+ * \param addr IPv4 address to add
+ * \param prefixlen IPv4 netmask length
+ * \return true in case of success, false otherwise
+ */
+bool addAddr4(std::string_view ifname, std::string_view addr, uint8_t prefixlen = 24);
 
 /**
  * Adds virtual link.
@@ -118,7 +149,7 @@
  * \param type the type of the new device
  * \return true in case of success, false otherwise
  */
-bool add(std::string dev, std::string type);
+bool add(std::string_view dev, std::string_view type);
 
 /**
  * Deletes virtual link.
@@ -126,7 +157,7 @@
  * \param dev the name of the device to remove
  * \return true in case of success, false otherwise
  */
-bool del(std::string dev);
+bool del(std::string_view dev);
 
 /**
  * Fetches interface's hardware address.
@@ -134,7 +165,7 @@
  * \param ifname Interface name
  * \return Hardware address (MAC address) or nullopt if the lookup failed
  */
-std::optional<hwaddr_t> getHwAddr(const std::string& ifname);
+std::optional<hwaddr_t> getHwAddr(std::string_view ifname);
 
 /**
  * Changes interface's hardware address.
@@ -142,7 +173,7 @@
  * \param ifname Interface name
  * \param hwaddr New hardware address to set
  */
-bool setHwAddr(const std::string& ifname, hwaddr_t hwaddr);
+bool setHwAddr(std::string_view ifname, hwaddr_t hwaddr);
 
 }  // namespace android::netdevice
 
diff --git a/automotive/can/1.0/default/libnetdevice/include/libnetdevice/vlan.h b/automotive/can/1.0/default/libnetdevice/include/libnetdevice/vlan.h
index 3e1b736..884b704 100644
--- a/automotive/can/1.0/default/libnetdevice/include/libnetdevice/vlan.h
+++ b/automotive/can/1.0/default/libnetdevice/include/libnetdevice/vlan.h
@@ -20,6 +20,6 @@
 
 namespace android::netdevice::vlan {
 
-bool add(const std::string& eth, const std::string& vlan, uint16_t id);
+bool add(std::string_view eth, std::string_view vlan, uint16_t id);
 
 }  // namespace android::netdevice::vlan
diff --git a/automotive/can/1.0/default/libnetdevice/libnetdevice.cpp b/automotive/can/1.0/default/libnetdevice/libnetdevice.cpp
index 413b4b1..1830633 100644
--- a/automotive/can/1.0/default/libnetdevice/libnetdevice.cpp
+++ b/automotive/can/1.0/default/libnetdevice/libnetdevice.cpp
@@ -23,9 +23,13 @@
 #include <libnl++/MessageFactory.h>
 #include <libnl++/Socket.h>
 
+#include <arpa/inet.h>
+#include <ifaddrs.h>
 #include <linux/can.h>
 #include <linux/rtnetlink.h>
 #include <net/if.h>
+#include <netdb.h>
+#include <sys/ioctl.h>
 
 #include <algorithm>
 #include <iterator>
@@ -37,27 +41,85 @@
     ifreqs::socketDomain = domain;
 }
 
-bool exists(std::string ifname) {
+bool exists(std::string_view ifname) {
     return nametoindex(ifname) != 0;
 }
 
-bool up(std::string ifname) {
+bool up(std::string_view ifname) {
     auto ifr = ifreqs::fromName(ifname);
     if (!ifreqs::send(SIOCGIFFLAGS, ifr)) return false;
+    if (ifr.ifr_flags & IFF_UP) return true;
     ifr.ifr_flags |= IFF_UP;
     return ifreqs::send(SIOCSIFFLAGS, ifr);
 }
 
-bool down(std::string ifname) {
+bool down(std::string_view ifname) {
     auto ifr = ifreqs::fromName(ifname);
     if (!ifreqs::send(SIOCGIFFLAGS, ifr)) return false;
+    if (!(ifr.ifr_flags & IFF_UP)) return true;
     ifr.ifr_flags &= ~IFF_UP;
     return ifreqs::send(SIOCSIFFLAGS, ifr);
 }
 
-bool add(std::string dev, std::string type) {
-    nl::MessageFactory<ifinfomsg> req(RTM_NEWLINK,
-                                      NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL | NLM_F_ACK);
+static std::string toString(const sockaddr* addr) {
+    char host[NI_MAXHOST];
+    socklen_t addrlen = (addr->sa_family == AF_INET) ? sizeof(sockaddr_in) : sizeof(sockaddr_in6);
+    auto res = getnameinfo(addr, addrlen, host, sizeof(host), nullptr, 0, NI_NUMERICHOST);
+    CHECK(res == 0) << "getnameinfo failed: " << gai_strerror(res);
+    return host;
+}
+
+static std::unique_ptr<ifaddrs, decltype(&freeifaddrs)> getifaddrs() {
+    ifaddrs* addrs = nullptr;
+    CHECK(getifaddrs(&addrs) == 0) << "getifaddrs failed: " << strerror(errno);
+    return {addrs, freeifaddrs};
+}
+
+std::set<std::string> getAllAddr4(std::string_view ifname) {
+    std::set<std::string> addresses;
+    auto addrs = getifaddrs();
+    for (ifaddrs* addr = addrs.get(); addr != nullptr; addr = addr->ifa_next) {
+        if (ifname != addr->ifa_name) continue;
+        if (addr->ifa_addr == nullptr) continue;
+        if (addr->ifa_addr->sa_family != AF_INET) continue;
+        addresses.insert(toString(addr->ifa_addr));
+    }
+    return addresses;
+}
+
+static in_addr_t inetAddr(std::string_view addr) {
+    auto addrn = inet_addr(std::string(addr).c_str());
+    CHECK(addrn != INADDR_NONE) << "Invalid address " << addr;
+    return addrn;
+}
+
+bool setAddr4(std::string_view ifname, std::string_view addr) {
+    auto ifr = ifreqs::fromName(ifname);
+
+    struct sockaddr_in* ifrAddr = reinterpret_cast<sockaddr_in*>(&ifr.ifr_addr);
+    ifrAddr->sin_family = AF_INET;
+    ifrAddr->sin_addr.s_addr = inetAddr(addr);
+
+    return ifreqs::send(SIOCSIFADDR, ifr);
+}
+
+bool addAddr4(std::string_view ifname, std::string_view addr, uint8_t prefixlen) {
+    nl::MessageFactory<ifaddrmsg> req(RTM_NEWADDR, nl::kCreateFlags);
+    req->ifa_family = AF_INET;
+    req->ifa_prefixlen = prefixlen;
+    req->ifa_flags = IFA_F_SECONDARY;
+    req->ifa_index = nametoindex(ifname);
+
+    auto addrn = inetAddr(addr);
+    req.add(IFLA_ADDRESS, addrn);
+    req.add(IFLA_BROADCAST, addrn);
+
+    nl::Socket sock(NETLINK_ROUTE);
+    return sock.send(req) && sock.receiveAck(req);
+}
+
+bool add(std::string_view dev, std::string_view type) {
+    nl::MessageFactory<ifinfomsg> req(RTM_NEWLINK, nl::kCreateFlags);
     req.add(IFLA_IFNAME, dev);
 
     {
@@ -69,15 +131,15 @@
     return sock.send(req) && sock.receiveAck(req);
 }
 
-bool del(std::string dev) {
-    nl::MessageFactory<ifinfomsg> req(RTM_DELLINK, NLM_F_REQUEST | NLM_F_ACK);
+bool del(std::string_view dev) {
+    nl::MessageFactory<ifinfomsg> req(RTM_DELLINK);
     req.add(IFLA_IFNAME, dev);
 
     nl::Socket sock(NETLINK_ROUTE);
     return sock.send(req) && sock.receiveAck(req);
 }
 
-std::optional<hwaddr_t> getHwAddr(const std::string& ifname) {
+std::optional<hwaddr_t> getHwAddr(std::string_view ifname) {
     auto ifr = ifreqs::fromName(ifname);
     if (!ifreqs::send(SIOCGIFHWADDR, ifr)) return std::nullopt;
 
@@ -86,7 +148,7 @@
     return hwaddr;
 }
 
-bool setHwAddr(const std::string& ifname, hwaddr_t hwaddr) {
+bool setHwAddr(std::string_view ifname, hwaddr_t hwaddr) {
     auto ifr = ifreqs::fromName(ifname);
 
     // fetch sa_family
@@ -96,13 +158,13 @@
     return ifreqs::send(SIOCSIFHWADDR, ifr);
 }
 
-std::optional<bool> isUp(std::string ifname) {
+std::optional<bool> isUp(std::string_view ifname) {
     auto ifr = ifreqs::fromName(ifname);
     if (!ifreqs::send(SIOCGIFFLAGS, ifr)) return std::nullopt;
     return ifr.ifr_flags & IFF_UP;
 }
 
-static bool hasIpv4(std::string ifname) {
+static bool hasIpv4(std::string_view ifname) {
     auto ifr = ifreqs::fromName(ifname);
     switch (ifreqs::trySend(SIOCGIFADDR, ifr)) {
         case 0:
diff --git a/automotive/can/1.0/default/libnetdevice/vlan.cpp b/automotive/can/1.0/default/libnetdevice/vlan.cpp
index 35b21b8..e5b5a61 100644
--- a/automotive/can/1.0/default/libnetdevice/vlan.cpp
+++ b/automotive/can/1.0/default/libnetdevice/vlan.cpp
@@ -26,15 +26,14 @@
 
 namespace android::netdevice::vlan {
 
-bool add(const std::string& eth, const std::string& vlan, uint16_t id) {
+bool add(std::string_view eth, std::string_view vlan, uint16_t id) {
     const auto ethidx = nametoindex(eth);
     if (ethidx == 0) {
         LOG(ERROR) << "Ethernet interface " << eth << " doesn't exist";
         return false;
     }
 
-    nl::MessageFactory<ifinfomsg> req(RTM_NEWLINK,
-                                      NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL | NLM_F_ACK);
+    nl::MessageFactory<ifinfomsg> req(RTM_NEWLINK, nl::kCreateFlags);
     req.add(IFLA_IFNAME, vlan);
     req.add<uint32_t>(IFLA_LINK, ethidx);
 
diff --git a/automotive/can/1.0/default/libnl++/Android.bp b/automotive/can/1.0/default/libnl++/Android.bp
index 01c1e55..5e3168a 100644
--- a/automotive/can/1.0/default/libnl++/Android.bp
+++ b/automotive/can/1.0/default/libnl++/Android.bp
@@ -26,6 +26,7 @@
 cc_library_static {
     name: "libnl++",
     defaults: ["android.hardware.automotive.can@defaults"],
+    host_supported: true,
     vendor_available: true,
     srcs: [
         "protocols/common/Empty.cpp",
diff --git a/automotive/can/1.0/default/libnl++/Socket.cpp b/automotive/can/1.0/default/libnl++/Socket.cpp
index 221063d..a5a782c 100644
--- a/automotive/can/1.0/default/libnl++/Socket.cpp
+++ b/automotive/can/1.0/default/libnl++/Socket.cpp
@@ -20,6 +20,9 @@
 
 #include <android-base/logging.h>
 
+// Should be in sys/socket.h or linux/socket.h
+#define SOL_NETLINK 270
+
 namespace android::nl {
 
 /**
diff --git a/automotive/can/1.0/default/libnl++/include/libnl++/MessageFactory.h b/automotive/can/1.0/default/libnl++/include/libnl++/MessageFactory.h
index a5a425e..f65f055 100644
--- a/automotive/can/1.0/default/libnl++/include/libnl++/MessageFactory.h
+++ b/automotive/can/1.0/default/libnl++/include/libnl++/MessageFactory.h
@@ -26,6 +26,9 @@
 
 namespace android::nl {
 
+static constexpr uint16_t kDefaultFlags = NLM_F_REQUEST | NLM_F_ACK;
+static constexpr uint16_t kCreateFlags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL | NLM_F_ACK;
+
 class MessageFactoryBase {
   protected:
     static nlattr* add(nlmsghdr* msg, size_t maxLen, nlattrtype_t type, const void* data,
@@ -54,7 +57,7 @@
      * \param type Message type (such as RTM_NEWLINK).
      * \param flags Message flags (such as NLM_F_REQUEST).
      */
-    MessageFactory(nlmsgtype_t type, uint16_t flags)
+    MessageFactory(nlmsgtype_t type, uint16_t flags = kDefaultFlags)
         : header(mMessage.header), data(mMessage.data) {
         mMessage.header.nlmsg_len = offsetof(Message, attributesBuffer);
         mMessage.header.nlmsg_type = type;
diff --git a/automotive/can/1.0/default/libnl++/printer.cpp b/automotive/can/1.0/default/libnl++/printer.cpp
index d540482..8c7c476 100644
--- a/automotive/can/1.0/default/libnl++/printer.cpp
+++ b/automotive/can/1.0/default/libnl++/printer.cpp
@@ -26,6 +26,12 @@
 #include <iomanip>
 #include <sstream>
 
+// should be in linux/netlink.h
+#define NLM_F_DUMP_FILTERED 0x20
+#define NLM_F_NONREC 0x100
+#define NLM_F_CAPPED 0x100
+#define NLM_F_ACK_TLVS 0x200
+
 namespace android::nl {
 
 static void flagsToStream(std::stringstream& ss, __u16 nlmsg_flags, protocols::MessageGenre genre) {
diff --git a/automotive/can/1.0/default/libnl++/protocols/common/Error.cpp b/automotive/can/1.0/default/libnl++/protocols/common/Error.cpp
index 77451ed..277f19d 100644
--- a/automotive/can/1.0/default/libnl++/protocols/common/Error.cpp
+++ b/automotive/can/1.0/default/libnl++/protocols/common/Error.cpp
@@ -22,6 +22,17 @@
 
 #include <map>
 
+#include <linux/netlink.h>
+#ifndef _UAPI__LINUX_NETLINK_H
+// linux_glibc (host) includes source headers instead of uapi headers
+enum nlmsgerr_attrs {
+    NLMSGERR_ATTR_UNUSED,
+    NLMSGERR_ATTR_MSG,
+    NLMSGERR_ATTR_OFFS,
+    NLMSGERR_ATTR_COOKIE,
+};
+#endif
+
 namespace android::nl::protocols::base {
 
 using DataType = AttributeDefinition::DataType;
diff --git a/automotive/can/1.0/default/libnl++/protocols/generic/FamilyTracker.cpp b/automotive/can/1.0/default/libnl++/protocols/generic/FamilyTracker.cpp
index 3ad101e..eebd1f1 100644
--- a/automotive/can/1.0/default/libnl++/protocols/generic/FamilyTracker.cpp
+++ b/automotive/can/1.0/default/libnl++/protocols/generic/FamilyTracker.cpp
@@ -18,6 +18,9 @@
 
 #include <android-base/logging.h>
 
+// should be in linux/genetlink.h
+#define GENL_START_ALLOC (NLMSG_MIN_TYPE + 3)
+
 namespace android::nl::generic {
 
 bool FamilyTracker::track(const Buffer<nlmsghdr>& buffer) {
diff --git a/automotive/can/1.0/default/libnl++/protocols/route/Addr.cpp b/automotive/can/1.0/default/libnl++/protocols/route/Addr.cpp
index 024d389..5bd6262 100644
--- a/automotive/can/1.0/default/libnl++/protocols/route/Addr.cpp
+++ b/automotive/can/1.0/default/libnl++/protocols/route/Addr.cpp
@@ -20,6 +20,12 @@
 #include "attributes.h"
 #include "structs.h"
 
+// should be in linux/if_addr.h
+#define IFA_F_MANAGETEMPADDR 0x100
+#define IFA_F_NOPREFIXROUTE 0x200
+#define IFA_F_MCAUTOJOIN 0x400
+#define IFA_F_STABLE_PRIVACY 0x800
+
 namespace android::nl::protocols::route {
 
 using DataType = AttributeDefinition::DataType;
diff --git a/automotive/can/1.0/default/libnl++/protocols/route/attributes.cpp b/automotive/can/1.0/default/libnl++/protocols/route/attributes.cpp
index 69d9b81..c81ee27 100644
--- a/automotive/can/1.0/default/libnl++/protocols/route/attributes.cpp
+++ b/automotive/can/1.0/default/libnl++/protocols/route/attributes.cpp
@@ -22,6 +22,54 @@
 #include <linux/rtnetlink.h>
 #include <net/if.h>
 
+#include <linux/if_link.h>
+#ifndef _UAPI_LINUX_IF_LINK_H
+enum {
+    IFLA_INFO_SLAVE_KIND = IFLA_INFO_XSTATS + 1,
+    IFLA_INFO_SLAVE_DATA,
+};
+enum {
+    IFLA_INET6_TOKEN = IFLA_INET6_ICMP6STATS + 1,
+    IFLA_INET6_ADDR_GEN_MODE,
+    IFLA_INET6_RA_MTU,
+};
+enum {
+    IFLA_CARRIER = IFLA_NUM_RX_QUEUES + 1,
+    IFLA_PHYS_PORT_ID,
+    IFLA_CARRIER_CHANGES,
+    IFLA_PHYS_SWITCH_ID,
+    IFLA_LINK_NETNSID,
+    IFLA_PHYS_PORT_NAME,
+    IFLA_PROTO_DOWN,
+    IFLA_GSO_MAX_SEGS,
+    IFLA_GSO_MAX_SIZE,
+    IFLA_PAD,
+    IFLA_XDP,
+    IFLA_EVENT,
+    IFLA_NEW_NETNSID,
+    IFLA_TARGET_NETNSID,
+    IFLA_CARRIER_UP_COUNT,
+    IFLA_CARRIER_DOWN_COUNT,
+    IFLA_NEW_IFINDEX,
+    IFLA_MIN_MTU,
+    IFLA_MAX_MTU,
+    IFLA_PROP_LIST,
+    IFLA_ALT_IFNAME,
+    IFLA_PERM_ADDRESS,
+    IFLA_PROTO_DOWN_REASON,
+    IFLA_PARENT_DEV_NAME,
+    IFLA_PARENT_DEV_BUS_NAME,
+    IFLA_GRO_MAX_SIZE,
+    IFLA_TSO_MAX_SIZE,
+    IFLA_TSO_MAX_SEGS,
+    IFLA_ALLMULTI,
+    IFLA_DEVLINK_PORT,
+    IFLA_GSO_IPV4_MAX_SIZE,
+    IFLA_GRO_IPV4_MAX_SIZE,
+    IFLA_DPLL_PIN,
+};
+#endif
+
 namespace android::nl::protocols::route {
 
 using DataType = AttributeDefinition::DataType;
diff --git a/automotive/can/1.0/default/libnl++/protocols/route/structs.h b/automotive/can/1.0/default/libnl++/protocols/route/structs.h
index c969a6c..410c42e 100644
--- a/automotive/can/1.0/default/libnl++/protocols/route/structs.h
+++ b/automotive/can/1.0/default/libnl++/protocols/route/structs.h
@@ -64,8 +64,8 @@
        << data.tx_heartbeat_errors << ','  //
        << data.tx_window_errors << ','     //
        << data.rx_compressed << ','        //
-       << data.tx_compressed << ','        //
-       << data.rx_nohandler << '}';
+       << data.tx_compressed << '}';
+    // Not printed (due to portability): rx_nohandler, rx_otherhost_dropped
 }
 
 }  // namespace android::nl::protocols::route
diff --git a/automotive/can/1.0/vts/functional/Android.bp b/automotive/can/1.0/vts/functional/Android.bp
index 1d51492..b13ec3b 100644
--- a/automotive/can/1.0/vts/functional/Android.bp
+++ b/automotive/can/1.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_connectivity_telemetry",
     // 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"
diff --git a/automotive/can/aidl/vts/functional/Android.bp b/automotive/can/aidl/vts/functional/Android.bp
index b816a49..d90164c 100644
--- a/automotive/can/aidl/vts/functional/Android.bp
+++ b/automotive/can/aidl/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_connectivity_telemetry",
     // 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"
diff --git a/automotive/evs/aidl/Android.bp b/automotive/evs/aidl/Android.bp
index 5b2f82f..75eb924 100644
--- a/automotive/evs/aidl/Android.bp
+++ b/automotive/evs/aidl/Android.bp
@@ -28,9 +28,11 @@
         "android/hardware/automotive/evs/*.aidl",
     ],
     stability: "vintf",
+    defaults: [
+        "android.hardware.graphics.common-latest",
+    ],
     imports: [
         "android.hardware.common-V2",
-        "android.hardware.graphics.common-V5",
     ],
     backend: {
         java: {
diff --git a/automotive/occupant_awareness/aidl/Android.bp b/automotive/occupant_awareness/aidl/Android.bp
index 1a8124c..33406ba 100644
--- a/automotive/occupant_awareness/aidl/Android.bp
+++ b/automotive/occupant_awareness/aidl/Android.bp
@@ -14,6 +14,7 @@
         "android/hardware/automotive/occupant_awareness/*.aidl",
     ],
     stability: "vintf",
+    frozen: true,
     backend: {
         java: {
             sdk_version: "module_current",
diff --git a/automotive/remoteaccess/vts/Android.bp b/automotive/remoteaccess/vts/Android.bp
index 8acd6a1..043cafa 100644
--- a/automotive/remoteaccess/vts/Android.bp
+++ b/automotive/remoteaccess/vts/Android.bp
@@ -15,6 +15,7 @@
  */
 
 package {
+    default_team: "trendy_team_aaos_framework",
     // 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"
diff --git a/automotive/vehicle/vts/Android.bp b/automotive/vehicle/vts/Android.bp
index 433ac41..d55dc33 100644
--- a/automotive/vehicle/vts/Android.bp
+++ b/automotive/vehicle/vts/Android.bp
@@ -15,6 +15,7 @@
  */
 
 package {
+    default_team: "trendy_team_aaos_framework",
     // 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"
diff --git a/bluetooth/aidl/vts/VtsHalBluetoothTargetTest.cpp b/bluetooth/aidl/vts/VtsHalBluetoothTargetTest.cpp
index fcf1649..4d90058 100644
--- a/bluetooth/aidl/vts/VtsHalBluetoothTargetTest.cpp
+++ b/bluetooth/aidl/vts/VtsHalBluetoothTargetTest.cpp
@@ -72,11 +72,9 @@
 static constexpr uint8_t kMinLeResolvingListForBt5 = 8;
 
 static constexpr size_t kNumHciCommandsBandwidth = 100;
-static constexpr size_t kNumScoPacketsBandwidth = 100;
 static constexpr size_t kNumAclPacketsBandwidth = 100;
 static constexpr std::chrono::milliseconds kWaitForInitTimeout(2000);
 static constexpr std::chrono::milliseconds kWaitForHciEventTimeout(2000);
-static constexpr std::chrono::milliseconds kWaitForScoDataTimeout(1000);
 static constexpr std::chrono::milliseconds kWaitForAclDataTimeout(1000);
 static constexpr std::chrono::milliseconds kInterfaceCloseDelayMs(200);
 
@@ -216,7 +214,6 @@
 
   // Functions called from within tests in loopback mode
   void sendAndCheckHci(int num_packets);
-  void sendAndCheckSco(int num_packets, size_t size, uint16_t handle);
   void sendAndCheckAcl(int num_packets, size_t size, uint16_t handle);
 
   // Helper functions to try to get a handle on verbosity
@@ -563,38 +560,6 @@
   logger.setTotalBytes(command_size * num_packets * 2);
 }
 
-// Send a SCO data packet (in Loopback mode) and check the response.
-void BluetoothAidlTest::sendAndCheckSco(int num_packets, size_t size,
-                                        uint16_t handle) {
-  ThroughputLogger logger{__func__};
-  for (int n = 0; n < num_packets; n++) {
-    // Send a SCO packet
-    std::vector<uint8_t> sco_packet;
-    std::vector<uint8_t> payload;
-    for (size_t i = 0; i < size; i++) {
-      payload.push_back(static_cast<uint8_t>(i + n));
-    }
-    ::bluetooth::packet::BitInserter bi{sco_packet};
-    ::bluetooth::hci::ScoBuilder::Create(
-        handle, ::bluetooth::hci::PacketStatusFlag::CORRECTLY_RECEIVED, payload)
-        ->Serialize(bi);
-    hci->sendScoData(sco_packet);
-
-    // Check the loopback of the SCO packet
-    std::vector<uint8_t> sco_loopback;
-    ASSERT_TRUE(
-        sco_queue.tryPopWithTimeout(sco_loopback, kWaitForScoDataTimeout));
-
-    if (sco_loopback.size() < size) {
-      // The packets may have been split for USB. Reassemble before checking.
-      reassemble_sco_loopback_pkt(sco_loopback, size);
-    }
-
-    ASSERT_EQ(sco_packet, sco_loopback);
-  }
-  logger.setTotalBytes(num_packets * size * 2);
-}
-
 // Send an ACL data packet (in Loopback mode) and check the response.
 void BluetoothAidlTest::sendAndCheckAcl(int num_packets, size_t size,
                                         uint16_t handle) {
@@ -724,22 +689,6 @@
       wait_for_command_complete_event(view.GetOpCode(), cmd_complete));
 }
 
-// Handle the loopback packet.
-void BluetoothAidlTest::reassemble_sco_loopback_pkt(std::vector<uint8_t>& scoPackets,
-        size_t size) {
-    std::vector<uint8_t> sco_packet_whole;
-    sco_packet_whole.assign(scoPackets.begin(), scoPackets.end());
-    while (size + 3 > sco_packet_whole.size()) {
-      std::vector<uint8_t> sco_packets;
-      ASSERT_TRUE(
-      sco_queue.tryPopWithTimeout(sco_packets, kWaitForScoDataTimeout));
-      sco_packet_whole.insert(sco_packet_whole.end(), sco_packets.begin() + 3,
-          sco_packets.end());
-    }
-    scoPackets.assign(sco_packet_whole.begin(), sco_packet_whole.end());
-    scoPackets[2] = size;
-}
-
 // Empty test: Initialize()/Close() are called in SetUp()/TearDown().
 TEST_P(BluetoothAidlTest, InitializeAndClose) {}
 
@@ -829,26 +778,6 @@
   sendAndCheckHci(1);
 }
 
-// Enter loopback mode and send a single SCO packet.
-TEST_P(BluetoothAidlTest, LoopbackModeSingleSco) {
-  setBufferSizes();
-  setSynchronousFlowControlEnable();
-
-  enterLoopbackMode();
-
-  if (!sco_connection_handles.empty()) {
-    ASSERT_LT(0, max_sco_data_packet_length);
-    sendAndCheckSco(1, max_sco_data_packet_length, sco_connection_handles[0]);
-    int sco_packets_sent = 1;
-    int completed_packets =
-        wait_for_completed_packets_event(sco_connection_handles[0]);
-    if (sco_packets_sent != completed_packets) {
-      ALOGW("%s: packets_sent (%d) != completed_packets (%d)", __func__,
-            sco_packets_sent, completed_packets);
-    }
-  }
-}
-
 // Enter loopback mode and send a single ACL packet.
 TEST_P(BluetoothAidlTest, LoopbackModeSingleAcl) {
   setBufferSizes();
@@ -879,27 +808,6 @@
   sendAndCheckHci(kNumHciCommandsBandwidth);
 }
 
-// Enter loopback mode and send SCO packets for bandwidth measurements.
-TEST_P(BluetoothAidlTest, LoopbackModeScoBandwidth) {
-  setBufferSizes();
-  setSynchronousFlowControlEnable();
-
-  enterLoopbackMode();
-
-  if (!sco_connection_handles.empty()) {
-    ASSERT_LT(0, max_sco_data_packet_length);
-    sendAndCheckSco(kNumScoPacketsBandwidth, max_sco_data_packet_length,
-                    sco_connection_handles[0]);
-    int sco_packets_sent = kNumScoPacketsBandwidth;
-    int completed_packets =
-        wait_for_completed_packets_event(sco_connection_handles[0]);
-    if (sco_packets_sent != completed_packets) {
-      ALOGW("%s: packets_sent (%d) != completed_packets (%d)", __func__,
-            sco_packets_sent, completed_packets);
-    }
-  }
-}
-
 // Enter loopback mode and send packets for ACL bandwidth measurements.
 TEST_P(BluetoothAidlTest, LoopbackModeAclBandwidth) {
   setBufferSizes();
diff --git a/boot/aidl/client/BootControlClient.cpp b/boot/aidl/client/BootControlClient.cpp
index 89258d2..090d624 100644
--- a/boot/aidl/client/BootControlClient.cpp
+++ b/boot/aidl/client/BootControlClient.cpp
@@ -18,6 +18,7 @@
 
 #include <aidl/android/hardware/boot/IBootControl.h>
 #include <android-base/logging.h>
+#include <android/binder_ibinder.h>
 #include <android/binder_manager.h>
 #include <android/hardware/boot/1.0/IBootControl.h>
 #include <android/hardware/boot/1.1/IBootControl.h>
@@ -65,63 +66,97 @@
     using IBootControl = ::aidl::android::hardware::boot::IBootControl;
 
   public:
-    BootControlClientAidl(std::shared_ptr<IBootControl> module) : module_(module) {}
+    explicit BootControlClientAidl(std::shared_ptr<IBootControl> module)
+        : module_(module),
+          boot_control_death_recipient(AIBinder_DeathRecipient_new(onBootControlServiceDied)) {
+        binder_status_t status =
+                AIBinder_linkToDeath(module->asBinder().get(), boot_control_death_recipient, this);
+        if (status != STATUS_OK) {
+            LOG(ERROR) << "Could not link to binder death";
+            return;
+        }
+    }
 
     BootControlVersion GetVersion() const override { return BootControlVersion::BOOTCTL_AIDL; }
 
-    ~BootControlClientAidl() = default;
-    virtual int32_t GetNumSlots() const {
+    void onBootControlServiceDied() {
+        LOG(ERROR) << "boot control service AIDL died. Attempting to reconnect...";
+        const auto instance_name =
+                std::string(::aidl::android::hardware::boot::IBootControl::descriptor) + "/default";
+        if (AServiceManager_isDeclared(instance_name.c_str())) {
+            module_ = ::aidl::android::hardware::boot::IBootControl::fromBinder(
+                    ndk::SpAIBinder(AServiceManager_waitForService(instance_name.c_str())));
+            if (module_ == nullptr) {
+                LOG(ERROR) << "AIDL " << instance_name
+                           << " is declared but waitForService returned nullptr when trying to "
+                              "reconnect boot control service";
+                return;
+            }
+            LOG(INFO) << "Reconnected to AIDL version of IBootControl";
+            binder_status_t status = AIBinder_linkToDeath(module_->asBinder().get(),
+                                                          boot_control_death_recipient, this);
+            if (status != STATUS_OK) {
+                LOG(ERROR) << "Could not link to binder death";
+                return;
+            }
+
+        } else {
+            LOG(ERROR) << "Failed to get service manager for: " << instance_name;
+        }
+    }
+
+    int32_t GetNumSlots() const override {
         int32_t ret = -1;
         LOG_NDK_STATUS(module_->getNumberSlots(&ret));
         return ret;
     }
 
-    int32_t GetCurrentSlot() const {
+    int32_t GetCurrentSlot() const override {
         int32_t ret = -1;
         LOG_NDK_STATUS(module_->getCurrentSlot(&ret));
         return ret;
     }
-    MergeStatus getSnapshotMergeStatus() const {
+    MergeStatus getSnapshotMergeStatus() const override {
         MergeStatus status = MergeStatus::UNKNOWN;
         LOG_NDK_STATUS(module_->getSnapshotMergeStatus(&status));
         return status;
     }
-    std::string GetSuffix(int32_t slot) const {
+    std::string GetSuffix(int32_t slot) const override {
         std::string ret;
         const auto status = module_->getSuffix(slot, &ret);
         if (!status.isOk()) {
-            LOG(ERROR) << __FUNCTION__ << "(" << slot << ")"
-                       << " failed " << status.getDescription();
+            LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed "
+                       << status.getDescription();
             return {};
         }
         return ret;
     }
 
-    std::optional<bool> IsSlotBootable(int32_t slot) const {
+    std::optional<bool> IsSlotBootable(int32_t slot) const override {
         bool ret = false;
         const auto status = module_->isSlotBootable(slot, &ret);
         if (!status.isOk()) {
-            LOG(ERROR) << __FUNCTION__ << "(" << slot << ")"
-                       << " failed " << status.getDescription();
+            LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed "
+                       << status.getDescription();
             return {};
         }
         return ret;
     }
 
-    CommandResult MarkSlotUnbootable(int32_t slot) {
+    CommandResult MarkSlotUnbootable(int32_t slot) override {
         const auto status = module_->setSlotAsUnbootable(slot);
         if (!status.isOk()) {
-            LOG(ERROR) << __FUNCTION__ << "(" << slot << ")"
-                       << " failed " << status.getDescription();
+            LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed "
+                       << status.getDescription();
         }
         return {.success = status.isOk(), .errMsg = status.getDescription()};
     }
 
-    CommandResult SetActiveBootSlot(int slot) {
+    CommandResult SetActiveBootSlot(int slot) override {
         const auto status = module_->setActiveBootSlot(slot);
         if (!status.isOk()) {
-            LOG(ERROR) << __FUNCTION__ << "(" << slot << ")"
-                       << " failed " << status.getDescription();
+            LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed "
+                       << status.getDescription();
         }
         return {.success = status.isOk(), .errMsg = status.getDescription()};
     }
@@ -132,18 +167,18 @@
     }
 
     // Check if |slot| is marked boot successfully.
-    std::optional<bool> IsSlotMarkedSuccessful(int slot) const {
+    std::optional<bool> IsSlotMarkedSuccessful(int slot) const override {
         bool ret = false;
         const auto status = module_->isSlotMarkedSuccessful(slot, &ret);
         if (!status.isOk()) {
-            LOG(ERROR) << __FUNCTION__ << "(" << slot << ")"
-                       << " failed " << status.getDescription();
+            LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed "
+                       << status.getDescription();
             return {};
         }
         return ret;
     }
 
-    CommandResult MarkBootSuccessful() {
+    CommandResult MarkBootSuccessful() override {
         const auto status = module_->markBootSuccessful();
         if (!status.isOk()) {
             LOG(ERROR) << __FUNCTION__ << " failed " << status.getDescription();
@@ -151,17 +186,23 @@
         return {.success = status.isOk(), .errMsg = status.getDescription()};
     }
 
-    CommandResult SetSnapshotMergeStatus(aidl::android::hardware::boot::MergeStatus merge_status) {
+    CommandResult SetSnapshotMergeStatus(
+            aidl::android::hardware::boot::MergeStatus merge_status) override {
         const auto status = module_->setSnapshotMergeStatus(merge_status);
         if (!status.isOk()) {
-            LOG(ERROR) << __FUNCTION__ << "(" << merge_status << ")"
-                       << " failed " << status.getDescription();
+            LOG(ERROR) << __FUNCTION__ << "(" << merge_status << ")" << " failed "
+                       << status.getDescription();
         }
         return {.success = status.isOk(), .errMsg = status.getDescription()};
     }
 
   private:
-    const std::shared_ptr<IBootControl> module_;
+    std::shared_ptr<IBootControl> module_;
+    AIBinder_DeathRecipient* boot_control_death_recipient;
+    static void onBootControlServiceDied(void* client) {
+        BootControlClientAidl* self = static_cast<BootControlClientAidl*>(client);
+        self->onBootControlServiceDied();
+    }
 };
 
 using namespace android::hardware::boot;
@@ -183,7 +224,7 @@
             return BootControlVersion::BOOTCTL_V1_0;
         }
     }
-    int32_t GetNumSlots() const {
+    int32_t GetNumSlots() const override {
         const auto ret = module_v1_->getNumberSlots();
         if (!ret.isOk()) {
             LOG(ERROR) << __FUNCTION__ << " failed " << ret.description();
@@ -191,7 +232,7 @@
         return ret.withDefault(-1);
     }
 
-    int32_t GetCurrentSlot() const {
+    int32_t GetCurrentSlot() const override {
         const auto ret = module_v1_->getCurrentSlot();
         if (!ret.isOk()) {
             LOG(ERROR) << __FUNCTION__ << " failed " << ret.description();
@@ -199,23 +240,21 @@
         return ret.withDefault(-1);
     }
 
-    std::string GetSuffix(int32_t slot) const {
+    std::string GetSuffix(int32_t slot) const override {
         std::string suffix;
         const auto ret = module_v1_->getSuffix(
                 slot,
                 [&](const ::android::hardware::hidl_string& slotSuffix) { suffix = slotSuffix; });
         if (!ret.isOk()) {
-            LOG(ERROR) << __FUNCTION__ << "(" << slot << ")"
-                       << " failed " << ret.description();
+            LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed " << ret.description();
         }
         return suffix;
     }
 
-    std::optional<bool> IsSlotBootable(int32_t slot) const {
+    std::optional<bool> IsSlotBootable(int32_t slot) const override {
         const auto ret = module_v1_->isSlotBootable(slot);
         if (!ret.isOk()) {
-            LOG(ERROR) << __FUNCTION__ << "(" << slot << ")"
-                       << " failed " << ret.description();
+            LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed " << ret.description();
             return {};
         }
         const auto bool_result = ret.withDefault(V1_0::BoolResult::INVALID_SLOT);
@@ -225,7 +264,7 @@
         return bool_result == V1_0::BoolResult::TRUE;
     }
 
-    CommandResult MarkSlotUnbootable(int32_t slot) {
+    CommandResult MarkSlotUnbootable(int32_t slot) override {
         CommandResult result;
         const auto ret =
                 module_v1_->setSlotAsUnbootable(slot, [&](const V1_0::CommandResult& error) {
@@ -233,26 +272,24 @@
                     result.errMsg = error.errMsg;
                 });
         if (!ret.isOk()) {
-            LOG(ERROR) << __FUNCTION__ << "(" << slot << ")"
-                       << " failed " << ret.description();
+            LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed " << ret.description();
         }
         return result;
     }
 
-    CommandResult SetActiveBootSlot(int32_t slot) {
+    CommandResult SetActiveBootSlot(int32_t slot) override {
         CommandResult result;
         const auto ret = module_v1_->setActiveBootSlot(slot, [&](const V1_0::CommandResult& error) {
             result.success = error.success;
             result.errMsg = error.errMsg;
         });
         if (!ret.isOk()) {
-            LOG(ERROR) << __FUNCTION__ << "(" << slot << ")"
-                       << " failed " << ret.description();
+            LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed " << ret.description();
         }
         return result;
     }
 
-    CommandResult MarkBootSuccessful() {
+    CommandResult MarkBootSuccessful() override {
         CommandResult result;
         const auto ret = module_v1_->markBootSuccessful([&](const V1_0::CommandResult& error) {
             result.success = error.success;
@@ -264,11 +301,10 @@
         return result;
     }
 
-    std::optional<bool> IsSlotMarkedSuccessful(int32_t slot) const {
+    std::optional<bool> IsSlotMarkedSuccessful(int32_t slot) const override {
         const auto ret = module_v1_->isSlotMarkedSuccessful(slot);
         if (!ret.isOk()) {
-            LOG(ERROR) << __FUNCTION__ << "(" << slot << ")"
-                       << " failed " << ret.description();
+            LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed " << ret.description();
             return {};
         }
         const auto bool_result = ret.withDefault(V1_0::BoolResult::INVALID_SLOT);
@@ -278,7 +314,7 @@
         return bool_result == V1_0::BoolResult::TRUE;
     }
 
-    MergeStatus getSnapshotMergeStatus() const {
+    MergeStatus getSnapshotMergeStatus() const override {
         if (module_v1_1_ == nullptr) {
             LOG(ERROR) << __FUNCTION__ << " is unsupported, requires at least boot v1.1";
             return MergeStatus::UNKNOWN;
@@ -291,7 +327,7 @@
                 ret.withDefault(static_cast<V1_1::MergeStatus>(MergeStatus::UNKNOWN)));
     }
 
-    CommandResult SetSnapshotMergeStatus(MergeStatus merge_status) {
+    CommandResult SetSnapshotMergeStatus(MergeStatus merge_status) override {
         if (module_v1_1_ == nullptr) {
             return {.success = false,
                     .errMsg = "setSnapshotMergeStatus is unsupported, requires at least boot v1.1"};
@@ -299,13 +335,13 @@
         const auto ret =
                 module_v1_1_->setSnapshotMergeStatus(static_cast<V1_1::MergeStatus>(merge_status));
         if (!ret.isOk()) {
-            LOG(ERROR) << __FUNCTION__ << "(" << merge_status << ")"
-                       << " failed " << ret.description();
+            LOG(ERROR) << __FUNCTION__ << "(" << merge_status << ")" << " failed "
+                       << ret.description();
         }
         return {.success = ret.isOk(), .errMsg = ret.description()};
     }
 
-    int32_t GetActiveBootSlot() const {
+    int32_t GetActiveBootSlot() const override {
         if (module_v1_2_ == nullptr) {
             LOG(ERROR) << __FUNCTION__ << " is unsupported, requires at least boot v1.2";
             return -1;
@@ -326,7 +362,6 @@
 std::unique_ptr<BootControlClient> BootControlClient::WaitForService() {
     const auto instance_name =
             std::string(::aidl::android::hardware::boot::IBootControl::descriptor) + "/default";
-
     if (AServiceManager_isDeclared(instance_name.c_str())) {
         auto module = ::aidl::android::hardware::boot::IBootControl::fromBinder(
                 ndk::SpAIBinder(AServiceManager_waitForService(instance_name.c_str())));
diff --git a/broadcastradio/1.0/vts/functional/Android.bp b/broadcastradio/1.0/vts/functional/Android.bp
index 623ff78..5a42fe4 100644
--- a/broadcastradio/1.0/vts/functional/Android.bp
+++ b/broadcastradio/1.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_aaos_framework",
     // 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"
diff --git a/broadcastradio/1.1/vts/functional/Android.bp b/broadcastradio/1.1/vts/functional/Android.bp
index 0fb4eb0..9d3db88 100644
--- a/broadcastradio/1.1/vts/functional/Android.bp
+++ b/broadcastradio/1.1/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_aaos_framework",
     // 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"
diff --git a/broadcastradio/2.0/vts/functional/Android.bp b/broadcastradio/2.0/vts/functional/Android.bp
index cb50c5e..03bec77 100644
--- a/broadcastradio/2.0/vts/functional/Android.bp
+++ b/broadcastradio/2.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_aaos_framework",
     // 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"
diff --git a/broadcastradio/aidl/Android.bp b/broadcastradio/aidl/Android.bp
index 82ee949..081bae3 100644
--- a/broadcastradio/aidl/Android.bp
+++ b/broadcastradio/aidl/Android.bp
@@ -51,12 +51,12 @@
         },
 
     ],
-    frozen: true,
+    frozen: false,
 
 }
 
 // Note: This should always be one version ahead of the last frozen version
-latest_android_hardware_broadcastradio = "android.hardware.broadcastradio-V2"
+latest_android_hardware_broadcastradio = "android.hardware.broadcastradio-V3"
 
 cc_defaults {
     name: "latest_android_hardware_broadcastradio_ndk_static",
diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl b/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/Alert.aidl
similarity index 84%
copy from vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl
copy to broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/Alert.aidl
index a5eda52..7e02f70 100644
--- a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl
+++ b/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/Alert.aidl
@@ -31,9 +31,10 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.vibrator;
-@VintfStability
-parcelable PwleV2OutputMapEntry {
-  float frequencyHz;
-  float maxOutputAccelerationGs;
+package android.hardware.broadcastradio;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable Alert {
+  android.hardware.broadcastradio.AlertStatus status;
+  android.hardware.broadcastradio.AlertMessageType messageType;
+  android.hardware.broadcastradio.AlertInfo[] infoArray;
 }
diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl b/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/AlertArea.aidl
similarity index 87%
copy from vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl
copy to broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/AlertArea.aidl
index a5eda52..aa828d0 100644
--- a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl
+++ b/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/AlertArea.aidl
@@ -31,9 +31,9 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.vibrator;
-@VintfStability
-parcelable PwleV2OutputMapEntry {
-  float frequencyHz;
-  float maxOutputAccelerationGs;
+package android.hardware.broadcastradio;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable AlertArea {
+  android.hardware.broadcastradio.Polygon[] polygons;
+  android.hardware.broadcastradio.Geocode[] geocodes;
 }
diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl b/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/AlertCategory.aidl
similarity index 86%
copy from vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl
copy to broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/AlertCategory.aidl
index a5eda52..f493e75 100644
--- a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl
+++ b/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/AlertCategory.aidl
@@ -31,9 +31,19 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.vibrator;
-@VintfStability
-parcelable PwleV2OutputMapEntry {
-  float frequencyHz;
-  float maxOutputAccelerationGs;
+package android.hardware.broadcastradio;
+@Backing(type="int") @JavaDerive(equals=true, toString=true) @VintfStability
+enum AlertCategory {
+  GEO,
+  MET,
+  SAFETY,
+  SECURITY,
+  RESCUE,
+  FIRE,
+  HEALTH,
+  ENV,
+  TRANSPORT,
+  INFRA,
+  CBRNE,
+  OTHER,
 }
diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl b/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/AlertCertainty.aidl
similarity index 88%
copy from vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl
copy to broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/AlertCertainty.aidl
index a5eda52..dcf283a 100644
--- a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl
+++ b/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/AlertCertainty.aidl
@@ -31,9 +31,12 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.vibrator;
-@VintfStability
-parcelable PwleV2OutputMapEntry {
-  float frequencyHz;
-  float maxOutputAccelerationGs;
+package android.hardware.broadcastradio;
+@Backing(type="int") @JavaDerive(equals=true, toString=true) @VintfStability
+enum AlertCertainty {
+  OBSERVED,
+  LIKELY,
+  POSSIBLE,
+  UNLIKELY,
+  UNKNOWN,
 }
diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl b/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/AlertInfo.aidl
similarity index 77%
copy from vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl
copy to broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/AlertInfo.aidl
index a5eda52..da08c9a 100644
--- a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl
+++ b/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/AlertInfo.aidl
@@ -31,9 +31,14 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.vibrator;
-@VintfStability
-parcelable PwleV2OutputMapEntry {
-  float frequencyHz;
-  float maxOutputAccelerationGs;
+package android.hardware.broadcastradio;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable AlertInfo {
+  android.hardware.broadcastradio.AlertCategory[] categoryArray;
+  android.hardware.broadcastradio.AlertUrgency urgency;
+  android.hardware.broadcastradio.AlertSeverity severity;
+  android.hardware.broadcastradio.AlertCertainty certainty;
+  String description;
+  android.hardware.broadcastradio.AlertArea[] areas;
+  @nullable String language;
 }
diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl b/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/AlertMessageType.aidl
similarity index 90%
copy from vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl
copy to broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/AlertMessageType.aidl
index a5eda52..2b89c92 100644
--- a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl
+++ b/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/AlertMessageType.aidl
@@ -31,9 +31,10 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.vibrator;
-@VintfStability
-parcelable PwleV2OutputMapEntry {
-  float frequencyHz;
-  float maxOutputAccelerationGs;
+package android.hardware.broadcastradio;
+@Backing(type="int") @JavaDerive(equals=true, toString=true) @VintfStability
+enum AlertMessageType {
+  ALERT,
+  UPDATE,
+  CANCEL,
 }
diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl b/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/AlertSeverity.aidl
similarity index 89%
copy from vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl
copy to broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/AlertSeverity.aidl
index a5eda52..5c91abd 100644
--- a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl
+++ b/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/AlertSeverity.aidl
@@ -31,9 +31,12 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.vibrator;
-@VintfStability
-parcelable PwleV2OutputMapEntry {
-  float frequencyHz;
-  float maxOutputAccelerationGs;
+package android.hardware.broadcastradio;
+@Backing(type="int") @JavaDerive(equals=true, toString=true) @VintfStability
+enum AlertSeverity {
+  EXTREME,
+  SEVERE,
+  MODERATE,
+  MINOR,
+  UNKNOWN,
 }
diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl b/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/AlertStatus.aidl
similarity index 90%
copy from vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl
copy to broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/AlertStatus.aidl
index a5eda52..8ce69b5 100644
--- a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl
+++ b/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/AlertStatus.aidl
@@ -31,9 +31,10 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.vibrator;
-@VintfStability
-parcelable PwleV2OutputMapEntry {
-  float frequencyHz;
-  float maxOutputAccelerationGs;
+package android.hardware.broadcastradio;
+@Backing(type="int") @JavaDerive(equals=true, toString=true) @VintfStability
+enum AlertStatus {
+  ACTUAL,
+  EXERCISE,
+  TEST,
 }
diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl b/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/AlertUrgency.aidl
similarity index 89%
copy from vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl
copy to broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/AlertUrgency.aidl
index a5eda52..fd0491d 100644
--- a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl
+++ b/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/AlertUrgency.aidl
@@ -31,9 +31,12 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.vibrator;
-@VintfStability
-parcelable PwleV2OutputMapEntry {
-  float frequencyHz;
-  float maxOutputAccelerationGs;
+package android.hardware.broadcastradio;
+@Backing(type="int") @JavaDerive(equals=true, toString=true) @VintfStability
+enum AlertUrgency {
+  IMMEDIATE,
+  EXPECTED,
+  FUTURE,
+  PAST,
+  UNKNOWN,
 }
diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl b/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/Coordinate.aidl
similarity index 90%
copy from vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl
copy to broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/Coordinate.aidl
index a5eda52..b303986 100644
--- a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl
+++ b/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/Coordinate.aidl
@@ -31,9 +31,9 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.vibrator;
-@VintfStability
-parcelable PwleV2OutputMapEntry {
-  float frequencyHz;
-  float maxOutputAccelerationGs;
+package android.hardware.broadcastradio;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable Coordinate {
+  double latitude;
+  double longitude;
 }
diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl b/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/Geocode.aidl
similarity index 90%
copy from vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl
copy to broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/Geocode.aidl
index a5eda52..a07e1c0 100644
--- a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl
+++ b/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/Geocode.aidl
@@ -31,9 +31,9 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.vibrator;
-@VintfStability
-parcelable PwleV2OutputMapEntry {
-  float frequencyHz;
-  float maxOutputAccelerationGs;
+package android.hardware.broadcastradio;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable Geocode {
+  String valueName;
+  String value;
 }
diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl b/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/Polygon.aidl
similarity index 89%
copy from vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl
copy to broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/Polygon.aidl
index a5eda52..4d4d78d 100644
--- a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl
+++ b/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/Polygon.aidl
@@ -31,9 +31,8 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.vibrator;
-@VintfStability
-parcelable PwleV2OutputMapEntry {
-  float frequencyHz;
-  float maxOutputAccelerationGs;
+package android.hardware.broadcastradio;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable Polygon {
+  android.hardware.broadcastradio.Coordinate[] coordinates;
 }
diff --git a/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/ProgramInfo.aidl b/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/ProgramInfo.aidl
index 997cdd7..dd57901 100644
--- a/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/ProgramInfo.aidl
+++ b/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/ProgramInfo.aidl
@@ -42,6 +42,7 @@
   int signalQuality;
   android.hardware.broadcastradio.Metadata[] metadata;
   android.hardware.broadcastradio.VendorKeyValue[] vendorInfo;
+  @nullable android.hardware.broadcastradio.Alert emergencyAlert;
   const int FLAG_LIVE = (1 << 0) /* 1 */;
   const int FLAG_MUTED = (1 << 1) /* 2 */;
   const int FLAG_TRAFFIC_PROGRAM = (1 << 2) /* 4 */;
diff --git a/broadcastradio/aidl/android/hardware/broadcastradio/Alert.aidl b/broadcastradio/aidl/android/hardware/broadcastradio/Alert.aidl
new file mode 100644
index 0000000..a307ccc
--- /dev/null
+++ b/broadcastradio/aidl/android/hardware/broadcastradio/Alert.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.broadcastradio;
+
+import android.hardware.broadcastradio.AlertInfo;
+import android.hardware.broadcastradio.AlertMessageType;
+import android.hardware.broadcastradio.AlertStatus;
+
+/**
+ * Emergency Alert Message.
+ *
+ * <p>Alert message can be sent from a radio station of technologies such as HD radio to
+ * the radio users for some emergency events (see ITU-T X.1303 bis for more info).
+ */
+@VintfStability
+@JavaDerive(equals=true, toString=true)
+parcelable Alert {
+    /**
+     * The status of the alert message.
+     */
+    AlertStatus status;
+
+    /**
+     * The message type of the alert message.
+     */
+    AlertMessageType messageType;
+
+    /**
+     * Array of alert information.
+     */
+    AlertInfo[] infoArray;
+}
diff --git a/broadcastradio/aidl/android/hardware/broadcastradio/AlertArea.aidl b/broadcastradio/aidl/android/hardware/broadcastradio/AlertArea.aidl
new file mode 100644
index 0000000..b3f07b3
--- /dev/null
+++ b/broadcastradio/aidl/android/hardware/broadcastradio/AlertArea.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.broadcastradio;
+
+import android.hardware.broadcastradio.Geocode;
+import android.hardware.broadcastradio.Polygon;
+
+/**
+ * The geographic area that delineates the affected area of the alert message
+ *
+ * <p>(see ITU-T X.1303 bis for more info).
+ */
+@VintfStability
+@JavaDerive(equals=true, toString=true)
+parcelable AlertArea {
+    /**
+     * Polygons that delineate the affected area of the alert message.
+     */
+    Polygon[] polygons;
+
+    /**
+     * Geographic code delineating the affected area of the alert message.
+     */
+    Geocode[] geocodes;
+}
diff --git a/broadcastradio/aidl/android/hardware/broadcastradio/AlertCategory.aidl b/broadcastradio/aidl/android/hardware/broadcastradio/AlertCategory.aidl
new file mode 100644
index 0000000..a24361a
--- /dev/null
+++ b/broadcastradio/aidl/android/hardware/broadcastradio/AlertCategory.aidl
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.broadcastradio;
+
+/**
+ * The category of the subject event of the emergency alert message.
+ *
+ * <p>(see ITU-T X.1303 bis for more info).
+ */
+@VintfStability
+@Backing(type="int")
+@JavaDerive(equals=true, toString=true)
+enum AlertCategory {
+    /**
+     * Alert category related to geophysical (inc. landslide).
+     */
+    GEO,
+
+    /**
+     * Alert category related to meteorological (inc. flood).
+     */
+    MET,
+
+    /**
+     * Alert category related to general emergency and public safety.
+     */
+    SAFETY,
+
+    /**
+     * Alert category related to law enforcement, military, homeland and local/private security.
+     */
+    SECURITY,
+
+    /**
+     * Alert category related to rescue and recovery.
+     */
+    RESCUE,
+
+    /**
+     * Alert category related to fire suppression and rescue.
+     */
+    FIRE,
+
+    /**
+     * Alert category related to medical and public health.
+     */
+    HEALTH,
+
+    /**
+     * Alert category related to pollution and other environmental.
+     */
+    ENV,
+
+    /**
+     * Alert category related to public and private transportation.
+     */
+    TRANSPORT,
+
+    /**
+     * Utility, telecommunication, other non-transport infrastructure.
+     */
+    INFRA,
+
+    /**
+     * Alert category related to chemical, biological, radiological, nuclear or high-yield
+     * explosive threat or attack.
+     */
+    CBRNE,
+
+    /**
+     * Alert category related to other events.
+     */
+    OTHER,
+}
diff --git a/broadcastradio/aidl/android/hardware/broadcastradio/AlertCertainty.aidl b/broadcastradio/aidl/android/hardware/broadcastradio/AlertCertainty.aidl
new file mode 100644
index 0000000..11f069e
--- /dev/null
+++ b/broadcastradio/aidl/android/hardware/broadcastradio/AlertCertainty.aidl
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.broadcastradio;
+
+/**
+ * The certainty of the subject event of the emergency alert message
+ *
+ * <p>(see ITU-T X.1303 bis for more info).
+ */
+@VintfStability
+@Backing(type="int")
+@JavaDerive(equals=true, toString=true)
+enum AlertCertainty {
+    /**
+     * Certainty indicating that the event is determined to have occurred or to be ongoing.
+     */
+    OBSERVED,
+
+    /**
+     * Certainty indicating that the event is likely (probability > ~50%).
+     */
+    LIKELY,
+
+    /**
+     * Certainty indicating that the event is possible but not likely (probability <= ~50%).
+     */
+    POSSIBLE,
+
+    /**
+     * Certainty indicating that the event is not expected to occur (probability ~ 0).
+     */
+    UNLIKELY,
+
+    /**
+     * Unknown certainty.
+     */
+    UNKNOWN,
+}
diff --git a/broadcastradio/aidl/android/hardware/broadcastradio/AlertInfo.aidl b/broadcastradio/aidl/android/hardware/broadcastradio/AlertInfo.aidl
new file mode 100644
index 0000000..ab2e6f7
--- /dev/null
+++ b/broadcastradio/aidl/android/hardware/broadcastradio/AlertInfo.aidl
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.broadcastradio;
+
+import android.hardware.broadcastradio.AlertArea;
+import android.hardware.broadcastradio.AlertCategory;
+import android.hardware.broadcastradio.AlertCertainty;
+import android.hardware.broadcastradio.AlertSeverity;
+import android.hardware.broadcastradio.AlertUrgency;
+
+/**
+ * Alert information.
+ *
+ * <p>(see ITU-T X.1303 bis for more info).
+ */
+@VintfStability
+@JavaDerive(equals=true, toString=true)
+parcelable AlertInfo {
+    /**
+     * Array of categories of the subject event of the alert info.
+     *
+     * <p>According to ITU-T X.1303, a single alert info block may contains multiple categories.
+     */
+    AlertCategory[] categoryArray;
+
+    /**
+     * The urgency of the subject event of the alert info.
+     *
+     * <p>Urgency represents the time available to prepare for the alert.
+     */
+    AlertUrgency urgency;
+
+    /**
+     * The severity of the subject event of the alert info.
+     *
+     * <p>Severity represents the intensity of impact.
+     */
+    AlertSeverity severity;
+
+    /**
+     * The certainty of the subject event of the alert info.
+     *
+     * <p>Certainty represents confidence in the observation or prediction.
+     */
+    AlertCertainty certainty;
+
+    /**
+     * Textual descriptions of the subject event.
+     */
+    String description;
+
+    /**
+     * The array of geographic areas to which the alert info segment in which it appears applies.
+     */
+    AlertArea[] areas;
+
+    /**
+     * The IETF RFC 3066 language code donating the language of the alert message.
+     *
+     * <p>This field is optional.
+     */
+    @nullable String language;
+}
diff --git a/broadcastradio/aidl/android/hardware/broadcastradio/AlertMessageType.aidl b/broadcastradio/aidl/android/hardware/broadcastradio/AlertMessageType.aidl
new file mode 100644
index 0000000..1dd4e2b
--- /dev/null
+++ b/broadcastradio/aidl/android/hardware/broadcastradio/AlertMessageType.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.broadcastradio;
+
+/**
+ * The emergency alert message type
+ *
+ * <p>The message type indicates the emergency alert message nature.
+ * (see ITU-T X.1303 bis for more info).
+ */
+@VintfStability
+@Backing(type="int")
+@JavaDerive(equals=true, toString=true)
+enum AlertMessageType {
+    /**
+     * Initial information requiring attention by targeted recipients.
+     */
+    ALERT,
+
+    /**
+     * Updates and supersedes the earlier message(s).
+     */
+    UPDATE,
+
+    /**
+     * Cancels the earlier message(s).
+     */
+    CANCEL,
+}
diff --git a/broadcastradio/aidl/android/hardware/broadcastradio/AlertSeverity.aidl b/broadcastradio/aidl/android/hardware/broadcastradio/AlertSeverity.aidl
new file mode 100644
index 0000000..acc11c4
--- /dev/null
+++ b/broadcastradio/aidl/android/hardware/broadcastradio/AlertSeverity.aidl
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.broadcastradio;
+
+/**
+ * The severity of the subject event of the emergency alert message
+ *
+ * <p>(see ITU-T X.1303 bis for more info).
+ */
+@VintfStability
+@Backing(type="int")
+@JavaDerive(equals=true, toString=true)
+enum AlertSeverity {
+    /**
+     * Severity indicating extraordinary threat to life or property.
+     */
+    EXTREME,
+
+    /**
+     * Severity indicating significant threat to life or property.
+     */
+    SEVERE,
+
+    /**
+     * Severity indicating possible threat to life or property.
+     */
+    MODERATE,
+
+    /**
+     * Severity indicating minimal to no known threat to life or property.
+     */
+    MINOR,
+
+    /**
+     * Unknown severity.
+     */
+    UNKNOWN,
+}
diff --git a/broadcastradio/aidl/android/hardware/broadcastradio/AlertStatus.aidl b/broadcastradio/aidl/android/hardware/broadcastradio/AlertStatus.aidl
new file mode 100644
index 0000000..8b0c917
--- /dev/null
+++ b/broadcastradio/aidl/android/hardware/broadcastradio/AlertStatus.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.broadcastradio;
+
+/**
+ * The status of the alert message
+ *
+ * <p>Status is the appropriate handling of the alert message (see ITU-T X.1303 bis for more info).
+ */
+@VintfStability
+@Backing(type="int")
+@JavaDerive(equals=true, toString=true)
+enum AlertStatus {
+    /**
+     * Actionable by all targeted recipients.
+     */
+    ACTUAL,
+
+    /**
+     * Actionable only by designated exercise participants.
+     */
+    EXERCISE,
+
+    /**
+     * Technical testing only, all recipients disregard.
+     */
+    TEST,
+}
diff --git a/broadcastradio/aidl/android/hardware/broadcastradio/AlertUrgency.aidl b/broadcastradio/aidl/android/hardware/broadcastradio/AlertUrgency.aidl
new file mode 100644
index 0000000..a0ef4a9
--- /dev/null
+++ b/broadcastradio/aidl/android/hardware/broadcastradio/AlertUrgency.aidl
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.broadcastradio;
+
+/**
+ * The severity of the subject event of the emergency alert message.
+ *
+ * <p>(see ITU-T X.1303 bis for more info).
+ */
+@VintfStability
+@Backing(type="int")
+@JavaDerive(equals=true, toString=true)
+enum AlertUrgency {
+    /**
+     * Urgency indicating that responsive action should be taken immediately.
+     */
+    IMMEDIATE,
+
+    /**
+     * Urgency indicating that responsive action should be taken soon.
+     */
+    EXPECTED,
+
+    /**
+     * Urgency indicating that responsive action should be taken in the near future.
+     */
+    FUTURE,
+
+    /**
+     * Urgency indicating that responsive action is no longer required.
+     */
+    PAST,
+
+    /**
+     * Unknown rgency.
+     */
+    UNKNOWN,
+}
diff --git a/broadcastradio/aidl/android/hardware/broadcastradio/Coordinate.aidl b/broadcastradio/aidl/android/hardware/broadcastradio/Coordinate.aidl
new file mode 100644
index 0000000..b881534
--- /dev/null
+++ b/broadcastradio/aidl/android/hardware/broadcastradio/Coordinate.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.broadcastradio;
+
+/**
+ * Coordinate reprensenting the geographic location in alert message
+ *
+ * <p>(see ITU-T X.1303 bis for more info).
+ */
+@VintfStability
+@JavaDerive(equals=true, toString=true)
+parcelable Coordinate {
+    /**
+     * Latitude of the cooridinate.
+     *
+     * <p>Latitude is in the range of -90 to 90.
+     */
+    double latitude;
+
+    /**
+     * Longitude of the cooridinate.
+     *
+     * <p>Longitude is in the range of -90 to 90.
+     */
+    double longitude;
+}
diff --git a/broadcastradio/aidl/android/hardware/broadcastradio/Geocode.aidl b/broadcastradio/aidl/android/hardware/broadcastradio/Geocode.aidl
new file mode 100644
index 0000000..f0162ca
--- /dev/null
+++ b/broadcastradio/aidl/android/hardware/broadcastradio/Geocode.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.broadcastradio;
+
+/**
+ * Geographic code reprensenting location in alert message
+ *
+ * <p>(see ITU-T X.1303 bis for more info).
+ */
+@VintfStability
+@JavaDerive(equals=true, toString=true)
+parcelable Geocode {
+    /**
+     * Value name of a geographic code.
+     *
+     * <p>Value name are acronyms should be represented in all capital
+     * letters without periods (e.g., SAME, FIPS, ZIP).
+     */
+    String valueName;
+
+    /**
+     * Value of a geographic code.
+     */
+    String value;
+}
diff --git a/broadcastradio/aidl/android/hardware/broadcastradio/Polygon.aidl b/broadcastradio/aidl/android/hardware/broadcastradio/Polygon.aidl
new file mode 100644
index 0000000..12bd2cd
--- /dev/null
+++ b/broadcastradio/aidl/android/hardware/broadcastradio/Polygon.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.broadcastradio;
+
+import android.hardware.broadcastradio.Coordinate;
+
+/**
+ * The array of coordinates defining a polygon
+ *
+ * <p>(see ITU-T X.1303 bis for more info).
+ */
+@VintfStability
+@JavaDerive(equals=true, toString=true)
+parcelable Polygon {
+    /**
+     * Cooridinates of points defining a polygon.
+     *
+     * <p>A minimum of 4 coordinates MUST be present and the first and last
+     * coordinates must be the same. See WGS 84 for more information.
+     */
+    Coordinate[] coordinates;
+}
diff --git a/broadcastradio/aidl/android/hardware/broadcastradio/ProgramInfo.aidl b/broadcastradio/aidl/android/hardware/broadcastradio/ProgramInfo.aidl
index d4ccd01..0b5abe2 100644
--- a/broadcastradio/aidl/android/hardware/broadcastradio/ProgramInfo.aidl
+++ b/broadcastradio/aidl/android/hardware/broadcastradio/ProgramInfo.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.broadcastradio;
 
+import android.hardware.broadcastradio.Alert;
 import android.hardware.broadcastradio.Metadata;
 import android.hardware.broadcastradio.ProgramIdentifier;
 import android.hardware.broadcastradio.ProgramSelector;
@@ -192,4 +193,12 @@
      * for example: paid-service=true; bitrate=320kbps.
      */
     VendorKeyValue[] vendorInfo;
+
+    /**
+     * Emergency alert message.
+     *
+     * <p>Alert message can be sent from a radio station of technologies such as HD radio to
+     * the radio users for some emergency events.
+     */
+    @nullable Alert emergencyAlert;
 }
diff --git a/broadcastradio/aidl/vts/src/VtsHalBroadcastradioAidlTargetTest.cpp b/broadcastradio/aidl/vts/src/VtsHalBroadcastradioAidlTargetTest.cpp
index ee0c639..7e9e458 100644
--- a/broadcastradio/aidl/vts/src/VtsHalBroadcastradioAidlTargetTest.cpp
+++ b/broadcastradio/aidl/vts/src/VtsHalBroadcastradioAidlTargetTest.cpp
@@ -16,6 +16,7 @@
 
 #define EGMOCK_VERBOSE 1
 
+#include <aidl/android/hardware/broadcastradio/Alert.h>
 #include <aidl/android/hardware/broadcastradio/BnAnnouncementListener.h>
 #include <aidl/android/hardware/broadcastradio/BnTunerCallback.h>
 #include <aidl/android/hardware/broadcastradio/ConfigFlag.h>
@@ -76,12 +77,13 @@
 
 constexpr int32_t kAidlVersion1 = 1;
 constexpr int32_t kAidlVersion2 = 2;
+constexpr int32_t kAidlVersion3 = 3;
 
 bool isValidAmFmFreq(int64_t freq, int aidlVersion) {
     ProgramIdentifier id = bcutils::makeIdentifier(IdentifierType::AMFM_FREQUENCY_KHZ, freq);
     if (aidlVersion == kAidlVersion1) {
         return bcutils::isValid(id);
-    } else if (aidlVersion == kAidlVersion2) {
+    } else if (aidlVersion >= kAidlVersion2) {
         return bcutils::isValidV2(id);
     }
     LOG(ERROR) << "Unknown AIDL version " << aidlVersion;
@@ -105,6 +107,41 @@
     return false;
 }
 
+void validateMetadata(const ProgramInfo& info, int32_t aidlVersion) {
+    for (const auto& metadataItem : info.metadata) {
+        bool validMetadata = false;
+        if (aidlVersion == kAidlVersion1) {
+            validMetadata = bcutils::isValidMetadata(metadataItem);
+        } else {
+            validMetadata = bcutils::isValidMetadataV2(metadataItem);
+        }
+        EXPECT_TRUE(validMetadata) << "Invalid metadata " << metadataItem.toString().c_str();
+    }
+}
+
+void validateAlert(const ProgramInfo& info, int32_t aidlVersion) {
+    if (aidlVersion < kAidlVersion3 || !info.emergencyAlert.has_value()) {
+        return;
+    }
+    Alert alert = info.emergencyAlert.value();
+    ASSERT_FALSE(alert.infoArray.empty());
+    for (const auto& alertInfo : alert.infoArray) {
+        ASSERT_FALSE(alertInfo.categoryArray.empty());
+        if (alertInfo.areas.empty()) {
+            continue;
+        }
+        for (const auto& area : alertInfo.areas) {
+            if (area.polygons.empty()) {
+                continue;
+            }
+            for (const auto& polygon : area.polygons) {
+                ASSERT_GE(polygon.coordinates.size(), 4);
+                EXPECT_EQ(polygon.coordinates.front(), polygon.coordinates.back());
+            }
+        }
+    }
+}
+
 }  // namespace
 
 class CallbackFlag final {
@@ -250,15 +287,9 @@
         }
     }
 
-    for (const auto& metadataItem : info.metadata) {
-        bool validMetadata = false;
-        if (mCallbackAidlVersion == kAidlVersion1) {
-            validMetadata = bcutils::isValidMetadata(metadataItem);
-        } else {
-            validMetadata = bcutils::isValidMetadataV2(metadataItem);
-        }
-        EXPECT_TRUE(validMetadata) << "Invalid metadata " << metadataItem.toString().c_str();
-    }
+    validateMetadata(info, mCallbackAidlVersion);
+
+    validateAlert(info, mCallbackAidlVersion);
 
     {
         std::lock_guard<std::mutex> lk(mLock);
@@ -349,7 +380,7 @@
     // get AIDL HAL version
     ASSERT_TRUE(mModule->getInterfaceVersion(&mAidlVersion).isOk());
     EXPECT_GE(mAidlVersion, kAidlVersion1);
-    EXPECT_LE(mAidlVersion, kAidlVersion2);
+    EXPECT_LE(mAidlVersion, kAidlVersion3);
 
     // set callback
     mCallback = SharedRefBase::make<TunerCallbackImpl>(mAidlVersion);
@@ -1122,12 +1153,22 @@
  * Verifies that:
  * - startProgramListUpdates either succeeds or returns NOT_SUPPORTED;
  * - the complete list is fetched within kProgramListScanTimeoutMs;
- * - stopProgramListUpdates does not crash.
+ * - stopProgramListUpdates does not crash;
+ * - metadata of program info in the program list is valid;
+ * - alert message is valid if it exists in the program list.
  */
 TEST_P(BroadcastRadioHalTest, GetProgramListFromEmptyFilter) {
     LOG(DEBUG) << "GetProgramListFromEmptyFilter Test";
 
-    getProgramList();
+    std::optional<bcutils::ProgramInfoSet> completeList = getProgramList();
+
+    if (!completeList || mAidlVersion < kAidlVersion3) {
+        return;
+    }
+    for (const auto& program : *completeList) {
+        validateMetadata(program, mAidlVersion);
+        validateAlert(program, mAidlVersion);
+    }
 }
 
 /**
diff --git a/camera/device/aidl/Android.bp b/camera/device/aidl/Android.bp
index 125f14c..48ae34e 100644
--- a/camera/device/aidl/Android.bp
+++ b/camera/device/aidl/Android.bp
@@ -15,12 +15,14 @@
     srcs: ["android/hardware/camera/device/*.aidl"],
     frozen: true,
     stability: "vintf",
+    defaults: [
+        "android.hardware.graphics.common-latest",
+    ],
     imports: [
         "android.hardware.common-V2",
         "android.hardware.common.fmq-V1",
         "android.hardware.camera.common-V1",
         "android.hardware.camera.metadata-V3",
-        "android.hardware.graphics.common-V5",
     ],
     backend: {
         cpp: {
diff --git a/camera/device/default/ExternalCameraDeviceSession.cpp b/camera/device/default/ExternalCameraDeviceSession.cpp
index 91196d4..abd5d7e 100644
--- a/camera/device/default/ExternalCameraDeviceSession.cpp
+++ b/camera/device/default/ExternalCameraDeviceSession.cpp
@@ -1136,6 +1136,11 @@
 
     uint32_t v4lBufferCount = (fps >= kDefaultFps) ? mCfg.numVideoBuffers : mCfg.numStillBuffers;
 
+    // Double the max lag in theory.
+    mMaxLagNs = v4lBufferCount * 1000000000LL * 2 / fps;
+    ALOGI("%s: set mMaxLagNs to %" PRIu64 " ns, v4lBufferCount %u", __FUNCTION__, mMaxLagNs,
+          v4lBufferCount);
+
     // VIDIOC_REQBUFS: create buffers
     v4l2_requestbuffers req_buffers{};
     req_buffers.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
@@ -1232,40 +1237,67 @@
         }
     }
 
-    ATRACE_BEGIN("VIDIOC_DQBUF");
+    uint64_t lagNs = 0;
     v4l2_buffer buffer{};
-    buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-    buffer.memory = V4L2_MEMORY_MMAP;
-    if (TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_DQBUF, &buffer)) < 0) {
-        ALOGE("%s: DQBUF fails: %s", __FUNCTION__, strerror(errno));
-        return ret;
-    }
-    ATRACE_END();
+    do {
+        ATRACE_BEGIN("VIDIOC_DQBUF");
+        buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+        buffer.memory = V4L2_MEMORY_MMAP;
+        if (TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_DQBUF, &buffer)) < 0) {
+            ALOGE("%s: DQBUF fails: %s", __FUNCTION__, strerror(errno));
+            return ret;
+        }
+        ATRACE_END();
 
-    if (buffer.index >= mV4L2BufferCount) {
-        ALOGE("%s: Invalid buffer id: %d", __FUNCTION__, buffer.index);
-        return ret;
-    }
+        if (buffer.index >= mV4L2BufferCount) {
+            ALOGE("%s: Invalid buffer id: %d", __FUNCTION__, buffer.index);
+            return ret;
+        }
 
-    if (buffer.flags & V4L2_BUF_FLAG_ERROR) {
-        ALOGE("%s: v4l2 buf error! buf flag 0x%x", __FUNCTION__, buffer.flags);
-        // TODO: try to dequeue again
-    }
+        if (buffer.flags & V4L2_BUF_FLAG_ERROR) {
+            ALOGE("%s: v4l2 buf error! buf flag 0x%x", __FUNCTION__, buffer.flags);
+            // TODO: try to dequeue again
+        }
 
-    if (buffer.bytesused > mMaxV4L2BufferSize) {
-        ALOGE("%s: v4l2 buffer bytes used: %u maximum %u", __FUNCTION__, buffer.bytesused,
-              mMaxV4L2BufferSize);
-        return ret;
-    }
+        if (buffer.bytesused > mMaxV4L2BufferSize) {
+            ALOGE("%s: v4l2 buffer bytes used: %u maximum %u", __FUNCTION__, buffer.bytesused,
+                  mMaxV4L2BufferSize);
+            return ret;
+        }
 
-    if (buffer.flags & V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC) {
-        // Ideally we should also check for V4L2_BUF_FLAG_TSTAMP_SRC_SOE, but
-        // even V4L2_BUF_FLAG_TSTAMP_SRC_EOF is better than capture a timestamp now
-        *shutterTs = static_cast<nsecs_t>(buffer.timestamp.tv_sec) * 1000000000LL +
-                     buffer.timestamp.tv_usec * 1000LL;
-    } else {
-        *shutterTs = systemTime(SYSTEM_TIME_MONOTONIC);
-    }
+        nsecs_t curTimeNs = systemTime(SYSTEM_TIME_MONOTONIC);
+
+        if (buffer.flags & V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC) {
+            // Ideally we should also check for V4L2_BUF_FLAG_TSTAMP_SRC_SOE, but
+            // even V4L2_BUF_FLAG_TSTAMP_SRC_EOF is better than capture a timestamp now
+            *shutterTs = static_cast<nsecs_t>(buffer.timestamp.tv_sec) * 1000000000LL +
+                         buffer.timestamp.tv_usec * 1000LL;
+        } else {
+            *shutterTs = curTimeNs;
+        }
+
+        // The tactic only takes effect on v4l2 buffers with flag V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC.
+        // Most USB cameras should have the feature.
+        if (curTimeNs < *shutterTs) {
+            lagNs = 0;
+            ALOGW("%s: should not happen, the monotonic clock has issue, shutterTs is in the "
+                  "future, curTimeNs %" PRId64 "  < "
+                  "shutterTs %" PRId64 "",
+                  __func__, curTimeNs, *shutterTs);
+        } else {
+            lagNs = curTimeNs - *shutterTs;
+        }
+
+        if (lagNs > mMaxLagNs) {
+            ALOGI("%s: drop too old buffer, index %d, lag %" PRIu64 " ns > max %" PRIu64 " ns", __FUNCTION__,
+                  buffer.index, lagNs, mMaxLagNs);
+            int retVal = ioctl(mV4l2Fd.get(), VIDIOC_QBUF, &buffer);
+            if (retVal) {
+                ALOGE("%s: unexpected VIDIOC_QBUF failed, retVal %d", __FUNCTION__, retVal);
+                return ret;
+            }
+        }
+    } while (lagNs > mMaxLagNs);
 
     {
         std::lock_guard<std::mutex> lk(mV4l2BufferLock);
diff --git a/camera/device/default/ExternalCameraDeviceSession.h b/camera/device/default/ExternalCameraDeviceSession.h
index 795b589..1c6ed06 100644
--- a/camera/device/default/ExternalCameraDeviceSession.h
+++ b/camera/device/default/ExternalCameraDeviceSession.h
@@ -382,6 +382,9 @@
     std::string mExifMake;
     std::string mExifModel;
     /* End of members not changed after initialize() */
+
+    // The max tolerant lag between the dequeued v4l2 buffer and current capture request.
+    uint64_t mMaxLagNs;
 };
 
 }  // namespace implementation
diff --git a/cas/1.2/default/Android.bp b/cas/1.2/default/Android.bp
index 38561fd..5bc8bad 100644
--- a/cas/1.2/default/Android.bp
+++ b/cas/1.2/default/Android.bp
@@ -46,6 +46,7 @@
     vintf_fragments: ["android.hardware.cas@1.2-service.xml"],
     defaults: ["cas_service_defaults@1.2"],
     init_rc: ["android.hardware.cas@1.2-service.rc"],
+    overrides: ["com.android.hardware.cas"],
 }
 
 cc_binary {
diff --git a/compatibility_matrices/Android.bp b/compatibility_matrices/Android.bp
index 6a3fa32..825c931 100644
--- a/compatibility_matrices/Android.bp
+++ b/compatibility_matrices/Android.bp
@@ -21,6 +21,65 @@
     default_applicable_licenses: ["hardware_interfaces_license"],
 }
 
+// Device framework compatibility matrix (common to all FCM versions)
+// Reference: https://source.android.com/docs/core/architecture/vintf/comp-matrices
+vintf_compatibility_matrix {
+    name: "framework_compatibility_matrix.device.xml",
+    stem: "compatibility_matrix.device.xml",
+    type: "device_fcm",
+}
+
+// Phony target that installs all system compatibility matrix files
+SYSTEM_MATRIX_DEPS = [
+    "framework_compatibility_matrix.5.xml",
+    "framework_compatibility_matrix.6.xml",
+    "framework_compatibility_matrix.7.xml",
+    "framework_compatibility_matrix.8.xml",
+    "framework_compatibility_matrix.202404.xml",
+    "framework_compatibility_matrix.device.xml",
+]
+
+phony {
+    name: "system_compatibility_matrix.xml",
+    required: SYSTEM_MATRIX_DEPS,
+    product_variables: {
+        release_aidl_use_unfrozen: {
+            required: [
+                "framework_compatibility_matrix.202504.xml",
+            ],
+        },
+    },
+}
+
+// Product Compatibility Matrix
+vintf_compatibility_matrix {
+    name: "product_compatibility_matrix.xml",
+    stem: "compatibility_matrix.xml",
+    product_specific: true,
+    type: "product_fcm",
+}
+
+// Phony target that installs all framework compatibility matrix files (system + product)
+FRAMEWORK_MATRIX_DEPS = SYSTEM_MATRIX_DEPS + ["product_compatibility_matrix.xml"]
+
+phony {
+    name: "framework_compatibility_matrix.xml",
+    required: FRAMEWORK_MATRIX_DEPS,
+    product_variables: {
+        release_aidl_use_unfrozen: {
+            required: [
+                "framework_compatibility_matrix.202504.xml",
+            ],
+        },
+    },
+}
+
+////////////////////////////////////////////
+// AUTO GENERATED MODULES
+// DO NOT ADD MORE MODULES BELOW THIS LINE
+////////////////////////////////////////////
+
+// System compatibility matrices
 vintf_compatibility_matrix {
     name: "framework_compatibility_matrix.5.xml",
     stem: "compatibility_matrix.5.xml",
@@ -88,60 +147,6 @@
     stem: "compatibility_matrix.202504.xml",
     srcs: ["compatibility_matrix.202504.xml"],
     kernel_configs: [
-        "kernel_config_w_6.next",
+        "kernel_config_w_6.12",
     ],
-
-}
-
-// Device framework compatibility matrix (common to all FCM versions)
-// Reference: https://source.android.com/docs/core/architecture/vintf/comp-matrices
-vintf_compatibility_matrix {
-    name: "framework_compatibility_matrix.device.xml",
-    stem: "compatibility_matrix.device.xml",
-    type: "device_fcm",
-}
-
-// Phony target that installs all system compatibility matrix files
-SYSTEM_MATRIX_DEPS = [
-    "framework_compatibility_matrix.5.xml",
-    "framework_compatibility_matrix.6.xml",
-    "framework_compatibility_matrix.7.xml",
-    "framework_compatibility_matrix.8.xml",
-    "framework_compatibility_matrix.202404.xml",
-    "framework_compatibility_matrix.device.xml",
-]
-
-phony {
-    name: "system_compatibility_matrix.xml",
-    required: SYSTEM_MATRIX_DEPS,
-    product_variables: {
-        release_aidl_use_unfrozen: {
-            required: [
-                "framework_compatibility_matrix.202504.xml",
-            ],
-        },
-    },
-}
-
-// Product Compatibility Matrix
-vintf_compatibility_matrix {
-    name: "product_compatibility_matrix.xml",
-    stem: "compatibility_matrix.xml",
-    product_specific: true,
-    type: "product_fcm",
-}
-
-// Phony target that installs all framework compatibility matrix files (system + product)
-FRAMEWORK_MATRIX_DEPS = SYSTEM_MATRIX_DEPS + ["product_compatibility_matrix.xml"]
-
-phony {
-    name: "framework_compatibility_matrix.xml",
-    required: FRAMEWORK_MATRIX_DEPS,
-    product_variables: {
-        release_aidl_use_unfrozen: {
-            required: [
-                "framework_compatibility_matrix.202504.xml",
-            ],
-        },
-    },
 }
diff --git a/compatibility_matrices/bump.py b/compatibility_matrices/bump.py
index 4e3ceaa..ee2fa88 100755
--- a/compatibility_matrices/bump.py
+++ b/compatibility_matrices/bump.py
@@ -58,7 +58,6 @@
         self.bump_kernel_configs()
         self.copy_matrix()
         self.edit_android_bp()
-        self.edit_android_mk()
         self.bump_libvintf()
 
     def bump_kernel_configs(self):
@@ -127,28 +126,6 @@
         with open(android_bp, "w") as f:
             f.write("".join(lines))
 
-
-    # This Android.mk file may be deprecated soon and the functionality is
-    # replaced by the soong phony module system_compatibility_matrix.xml.
-    def edit_android_mk(self):
-        android_mk = self.interfaces_dir / "compatibility_matrices/Android.mk"
-        lines = []
-        with open(android_mk) as f:
-            if self.next_module_name in f.read():
-                return
-            f.seek(0)
-            for line in f:
-              if f"    {self.device_module_name} \\\n" in line:
-                  lines.append(f"    {self.current_module_name} \\\n")
-
-              if self.current_module_name in line:
-                  lines.append(f"    {self.next_module_name} \\\n")
-              else:
-                  lines.append(line)
-
-        with open(android_mk, "w") as f:
-            f.write("".join(lines))
-
     def bump_libvintf(self):
         if not self.current_version:
             print("Skip libvintf update...")
diff --git a/compatibility_matrices/compatibility_matrix.202504.xml b/compatibility_matrices/compatibility_matrix.202504.xml
index 349496a..63e6061 100644
--- a/compatibility_matrices/compatibility_matrix.202504.xml
+++ b/compatibility_matrices/compatibility_matrix.202504.xml
@@ -163,7 +163,7 @@
     </hal>
     <hal format="aidl">
         <name>android.hardware.broadcastradio</name>
-        <version>1-2</version>
+        <version>1-3</version>
         <interface>
             <name>IBroadcastRadio</name>
             <regex-instance>.*</regex-instance>
@@ -372,7 +372,7 @@
     </hal>
     <hal format="aidl">
         <name>android.hardware.power</name>
-        <version>5</version>
+        <version>5-6</version>
         <interface>
             <name>IPower</name>
             <instance>default</instance>
diff --git a/drm/1.0/vts/functional/Android.bp b/drm/1.0/vts/functional/Android.bp
index e0c6fa5..73612df 100644
--- a/drm/1.0/vts/functional/Android.bp
+++ b/drm/1.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_media_drm",
     // 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"
diff --git a/drm/1.1/vts/functional/Android.bp b/drm/1.1/vts/functional/Android.bp
index b539fa2..aeb0443 100644
--- a/drm/1.1/vts/functional/Android.bp
+++ b/drm/1.1/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_media_drm",
     // 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"
diff --git a/drm/1.2/vts/functional/Android.bp b/drm/1.2/vts/functional/Android.bp
index 9ceb1a3..f6fb528 100644
--- a/drm/1.2/vts/functional/Android.bp
+++ b/drm/1.2/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_media_drm",
     // 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"
diff --git a/drm/1.3/vts/functional/Android.bp b/drm/1.3/vts/functional/Android.bp
index 3db23e3..a9ebd80 100644
--- a/drm/1.3/vts/functional/Android.bp
+++ b/drm/1.3/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_media_drm",
     // 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"
diff --git a/drm/1.4/vts/functional/Android.bp b/drm/1.4/vts/functional/Android.bp
index 89edab7..0662a0f 100644
--- a/drm/1.4/vts/functional/Android.bp
+++ b/drm/1.4/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_media_drm",
     // 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"
diff --git a/drm/aidl/Android.bp b/drm/aidl/Android.bp
index 99780dc..827621c 100644
--- a/drm/aidl/Android.bp
+++ b/drm/aidl/Android.bp
@@ -12,6 +12,7 @@
     vendor_available: true,
     srcs: ["android/hardware/drm/*.aidl"],
     stability: "vintf",
+    frozen: true,
     imports: [
         "android.hardware.common-V2",
         "android.hardware.drm.common-V1",
diff --git a/drm/aidl/vts/Android.bp b/drm/aidl/vts/Android.bp
index 27ce0d7..1fe0972 100644
--- a/drm/aidl/vts/Android.bp
+++ b/drm/aidl/vts/Android.bp
@@ -14,6 +14,7 @@
 // limitations under the License.
 //
 package {
+    default_team: "trendy_team_android_media_drm",
     // 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"
diff --git a/dumpstate/aidl/Android.bp b/dumpstate/aidl/Android.bp
index 1eb8b32..45c992a 100644
--- a/dumpstate/aidl/Android.bp
+++ b/dumpstate/aidl/Android.bp
@@ -26,6 +26,7 @@
     vendor_available: true,
     srcs: ["android/hardware/dumpstate/*.aidl"],
     stability: "vintf",
+    frozen: true,
     backend: {
         cpp: {
             enabled: false,
diff --git a/gatekeeper/1.0/vts/functional/Android.bp b/gatekeeper/1.0/vts/functional/Android.bp
index 64b3505..16e2970 100644
--- a/gatekeeper/1.0/vts/functional/Android.bp
+++ b/gatekeeper/1.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_hardware_backed_security",
     // 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"
diff --git a/gatekeeper/aidl/software/file_contexts b/gatekeeper/aidl/software/file_contexts
index 23a62ea..cc4180e 100644
--- a/gatekeeper/aidl/software/file_contexts
+++ b/gatekeeper/aidl/software/file_contexts
@@ -1,3 +1,3 @@
 (/.*)?                                                          u:object_r:vendor_file:s0
 /etc(/.*)?                                                      u:object_r:vendor_configs_file:s0
-/bin/hw/android\.hardware\.gatekeeper-service\.nonsecure        u:object_r:hal_gatekeeper_remote_exec:s0
+/bin/hw/android\.hardware\.gatekeeper-service\.nonsecure        u:object_r:hal_gatekeeper_default_exec:s0
diff --git a/gatekeeper/aidl/vts/functional/Android.bp b/gatekeeper/aidl/vts/functional/Android.bp
index 008f25c..801ee56 100644
--- a/gatekeeper/aidl/vts/functional/Android.bp
+++ b/gatekeeper/aidl/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_hardware_backed_security",
     // See: http://go/android-license-faq
     default_applicable_licenses: ["hardware_interfaces_license"],
 }
diff --git a/gnss/1.0/vts/functional/Android.bp b/gnss/1.0/vts/functional/Android.bp
index f27732a..b1093a6 100644
--- a/gnss/1.0/vts/functional/Android.bp
+++ b/gnss/1.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_location_time",
     // 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"
diff --git a/gnss/1.1/vts/functional/Android.bp b/gnss/1.1/vts/functional/Android.bp
index f9fcbf1..65c752c 100644
--- a/gnss/1.1/vts/functional/Android.bp
+++ b/gnss/1.1/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_location_time",
     // 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"
diff --git a/gnss/2.0/vts/functional/Android.bp b/gnss/2.0/vts/functional/Android.bp
index 0b54308..4ca3063 100644
--- a/gnss/2.0/vts/functional/Android.bp
+++ b/gnss/2.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_location_time",
     // 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"
diff --git a/gnss/2.1/vts/functional/Android.bp b/gnss/2.1/vts/functional/Android.bp
index 9906b27..af66037 100644
--- a/gnss/2.1/vts/functional/Android.bp
+++ b/gnss/2.1/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_location_time",
     // 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"
diff --git a/gnss/aidl/vts/Android.bp b/gnss/aidl/vts/Android.bp
index fd1d853..2bd6f07 100644
--- a/gnss/aidl/vts/Android.bp
+++ b/gnss/aidl/vts/Android.bp
@@ -13,6 +13,7 @@
 // limitations under the License.
 
 package {
+    default_team: "trendy_team_location_time",
     // 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"
diff --git a/graphics/Android.bp b/graphics/Android.bp
index c33f7ff..d768ecf 100644
--- a/graphics/Android.bp
+++ b/graphics/Android.bp
@@ -16,11 +16,32 @@
     default_applicable_licenses: ["hardware_interfaces_license"],
 }
 
+aidl_interface_defaults {
+    name: "android.hardware.graphics.allocator-latest",
+    imports: [
+        "android.hardware.graphics.allocator-V2",
+    ],
+}
+
+rust_defaults {
+    name: "android.hardware.graphics.allocator-latest-rust",
+    rustlibs: [
+        "android.hardware.graphics.allocator-V2-rust",
+    ],
+    defaults: [
+        "android.hardware.graphics.common-latest-rust",
+    ],
+}
+
 cc_defaults {
     name: "android.hardware.graphics.allocator-ndk_static",
-    static_libs: [
-        "android.hardware.graphics.allocator-V2-ndk",
-    ],
+    target: {
+        linux: {
+            static_libs: [
+                "android.hardware.graphics.allocator-V2-ndk",
+            ],
+        },
+    },
     defaults: [
         "android.hardware.graphics.common-ndk_static",
     ],
@@ -28,40 +49,81 @@
 
 cc_defaults {
     name: "android.hardware.graphics.allocator-ndk_shared",
-    shared_libs: [
-        "android.hardware.graphics.allocator-V2-ndk",
-    ],
+    target: {
+        linux: {
+            shared_libs: [
+                "android.hardware.graphics.allocator-V2-ndk",
+            ],
+        },
+    },
     defaults: [
         "android.hardware.graphics.common-ndk_shared",
     ],
 }
 
-cc_defaults {
-    name: "android.hardware.graphics.common-ndk_static",
-    static_libs: [
-        "android.hardware.graphics.common-V5-ndk",
+aidl_interface_defaults {
+    name: "android.hardware.graphics.common-latest",
+    imports: [
+        "android.hardware.graphics.common-V5",
+    ],
+}
+
+rust_defaults {
+    name: "android.hardware.graphics.common-latest-rust",
+    rustlibs: [
+        "android.hardware.graphics.common-V5-rust",
     ],
 }
 
 cc_defaults {
+    name: "android.hardware.graphics.common-ndk_static",
+    target: {
+        linux: {
+            static_libs: [
+                "android.hardware.graphics.common-V5-ndk",
+            ],
+        },
+    },
+}
+
+cc_defaults {
     name: "android.hardware.graphics.common-ndk_shared",
-    shared_libs: [
-        "android.hardware.graphics.common-V5-ndk",
+    target: {
+        linux: {
+            shared_libs: [
+                "android.hardware.graphics.common-V5-ndk",
+            ],
+        },
+    },
+}
+
+aidl_interface_defaults {
+    name: "android.hardware.graphics.composer3-latest",
+    imports: [
+        "android.hardware.graphics.composer3-V4",
     ],
 }
 
 cc_defaults {
     name: "android.hardware.graphics.composer3-ndk_static",
-    static_libs: [
-        "android.hardware.drm.common-V1-ndk",
-        "android.hardware.graphics.composer3-V4-ndk",
-    ],
+    target: {
+        linux: {
+            static_libs: [
+                "android.hardware.drm.common-V1-ndk",
+                "android.hardware.graphics.composer3-V4-ndk",
+            ],
+        },
+    },
 }
 
 cc_defaults {
     name: "android.hardware.graphics.composer3-ndk_shared",
-    shared_libs: [
-        "android.hardware.drm.common-V1-ndk",
-        "android.hardware.graphics.composer3-V4-ndk",
-    ],
+    target: {
+        linux: {
+            shared_libs: [
+                "android.hardware.drm.common-V1-ndk",
+                "android.hardware.graphics.composer3-V4-ndk",
+            ],
+        },
+    },
 }
diff --git a/graphics/allocator/aidl/Android.bp b/graphics/allocator/aidl/Android.bp
index 7bb6b50..30b341c 100644
--- a/graphics/allocator/aidl/Android.bp
+++ b/graphics/allocator/aidl/Android.bp
@@ -13,9 +13,11 @@
     vendor_available: true,
     double_loadable: true,
     srcs: ["android/hardware/graphics/allocator/*.aidl"],
+    defaults: [
+        "android.hardware.graphics.common-latest",
+    ],
     imports: [
         "android.hardware.common-V2",
-        "android.hardware.graphics.common-V5",
     ],
     stability: "vintf",
     backend: {
diff --git a/graphics/common/aidl/Android.bp b/graphics/common/aidl/Android.bp
index c28da4c..3c75d7b 100644
--- a/graphics/common/aidl/Android.bp
+++ b/graphics/common/aidl/Android.bp
@@ -43,7 +43,7 @@
             enabled: true,
         },
     },
-    frozen: true,
+    frozen: false,
     versions_with_info: [
         {
             version: "1",
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/PixelFormat.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/PixelFormat.aidl
index ed84a44..54a9d8d 100644
--- a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/PixelFormat.aidl
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/PixelFormat.aidl
@@ -68,4 +68,5 @@
   R_16_UINT = 0x39,
   RG_1616_UINT = 0x3a,
   RGBA_10101010 = 0x3b,
+  YCBCR_P210 = 0x3c,
 }
diff --git a/graphics/common/aidl/android/hardware/graphics/common/PixelFormat.aidl b/graphics/common/aidl/android/hardware/graphics/common/PixelFormat.aidl
index 1117504..55be4d2 100644
--- a/graphics/common/aidl/android/hardware/graphics/common/PixelFormat.aidl
+++ b/graphics/common/aidl/android/hardware/graphics/common/PixelFormat.aidl
@@ -531,4 +531,26 @@
      * interpretation is defined by the dataspace.
      */
     RGBA_10101010 = 0x3b,
+
+    /**
+     * YCBCR_P210 is a 4:2:2 YCbCr semiplanar format comprised of a WxH Y plane
+     * followed by a WxH CbCr plane. Each sample is represented by a 16-bit
+     * little-endian value, with the lower 6 bits set to zero.
+     *
+     * This format must be accepted by the allocator when used with the
+     * following usage flags:
+     *
+     *    - BufferUsage::VIDEO_*
+     *    - BufferUsage::CPU_*
+     *    - BufferUsage::GPU_TEXTURE
+     *
+     * The component values are unsigned normalized to the range [0, 1], whose
+     * interpretation is defined by the dataspace.
+     *
+     * This format is appropriate for 10bit video content.
+     *
+     * Buffers with this format must be locked with IMapper::lockYCbCr
+     * or with IMapper::lock.
+     */
+    YCBCR_P210 = 0x3c,
 }
diff --git a/graphics/composer/aidl/Android.bp b/graphics/composer/aidl/Android.bp
index 1728f78..bba41da 100644
--- a/graphics/composer/aidl/Android.bp
+++ b/graphics/composer/aidl/Android.bp
@@ -34,8 +34,10 @@
         "android/hardware/graphics/composer3/*.aidl",
     ],
     stability: "vintf",
+    defaults: [
+        "android.hardware.graphics.common-latest",
+    ],
     imports: [
-        "android.hardware.graphics.common-V5",
         "android.hardware.common-V2",
         "android.hardware.drm.common-V1",
     ],
diff --git a/graphics/mapper/stable-c/Android.bp b/graphics/mapper/stable-c/Android.bp
index 82306be..f4196b9 100644
--- a/graphics/mapper/stable-c/Android.bp
+++ b/graphics/mapper/stable-c/Android.bp
@@ -111,7 +111,7 @@
         "VtsHalTargetTestDefaults",
         "use_libaidlvintf_gtest_helper_static",
         "android.hardware.graphics.allocator-ndk_shared",
-        "android.hardware.graphics.common-ndk_shared",
+        "android.hardware.graphics.common-ndk_static",
     ],
     srcs: [
         "vts/VtsHalGraphicsMapperStableC_TargetTest.cpp",
diff --git a/health/storage/OWNERS b/health/storage/OWNERS
index 7af8d99..ec1fd8f 100644
--- a/health/storage/OWNERS
+++ b/health/storage/OWNERS
@@ -1,6 +1,9 @@
 # Bug component: 30545
 
+# Don't inherit owners from hardware/interfaces/health/
 set noparent
+# But inherit from hardware/interfaces
+include platform/hardware/interfaces:/OWNERS
 
 jaegeuk@google.com
 elsk@google.com
diff --git a/health/storage/aidl/Android.bp b/health/storage/aidl/Android.bp
index c614efb..44484d6 100644
--- a/health/storage/aidl/Android.bp
+++ b/health/storage/aidl/Android.bp
@@ -26,6 +26,7 @@
     vendor_available: true,
     srcs: ["android/hardware/health/storage/*.aidl"],
     stability: "vintf",
+    frozen: true,
     backend: {
         cpp: {
             enabled: false,
diff --git a/identity/aidl/vts/Android.bp b/identity/aidl/vts/Android.bp
index 8ff2382..1ce4f0c 100644
--- a/identity/aidl/vts/Android.bp
+++ b/identity/aidl/vts/Android.bp
@@ -1,4 +1,5 @@
 package {
+    default_team: "trendy_team_android_hardware_backed_security",
     // 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"
diff --git a/input/common/aidl/Android.bp b/input/common/aidl/Android.bp
index 0759d2e..8721e5d 100644
--- a/input/common/aidl/Android.bp
+++ b/input/common/aidl/Android.bp
@@ -14,6 +14,7 @@
     vendor_available: true,
     srcs: ["android/hardware/input/common/*.aidl"],
     stability: "vintf",
+    frozen: true,
     backend: {
         cpp: {
             enabled: false,
diff --git a/input/processor/aidl/Android.bp b/input/processor/aidl/Android.bp
index 68adf32..6855b08 100644
--- a/input/processor/aidl/Android.bp
+++ b/input/processor/aidl/Android.bp
@@ -12,6 +12,7 @@
     name: "android.hardware.input.processor",
     host_supported: true,
     vendor_available: true,
+    frozen: true,
     srcs: ["android/hardware/input/processor/*.aidl"],
     imports: [
         "android.hardware.input.common-V1",
diff --git a/ir/aidl/Android.bp b/ir/aidl/Android.bp
index 25f6c8f..c561c52 100644
--- a/ir/aidl/Android.bp
+++ b/ir/aidl/Android.bp
@@ -26,6 +26,7 @@
     vendor_available: true,
     srcs: ["android/hardware/ir/*.aidl"],
     stability: "vintf",
+    frozen: true,
     backend: {
         cpp: {
             enabled: false,
diff --git a/keymaster/3.0/vts/functional/Android.bp b/keymaster/3.0/vts/functional/Android.bp
index fde32a7..4aa0692 100644
--- a/keymaster/3.0/vts/functional/Android.bp
+++ b/keymaster/3.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_hardware_backed_security",
     // 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"
diff --git a/keymaster/4.0/vts/functional/Android.bp b/keymaster/4.0/vts/functional/Android.bp
index e1dfcfc..cd12319 100644
--- a/keymaster/4.0/vts/functional/Android.bp
+++ b/keymaster/4.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_hardware_backed_security",
     // 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"
diff --git a/keymaster/4.0/vts/performance/Android.bp b/keymaster/4.0/vts/performance/Android.bp
index d7342ad..8f26871 100644
--- a/keymaster/4.0/vts/performance/Android.bp
+++ b/keymaster/4.0/vts/performance/Android.bp
@@ -33,6 +33,5 @@
         "android.hardware.keymaster@4.0",
         "libkeymaster4support",
         "libsoftkeymasterdevice",
-        "libchrome"
     ],
 }
diff --git a/keymaster/4.0/vts/performance/Benchmark.cpp b/keymaster/4.0/vts/performance/Benchmark.cpp
index e5fdff2..723b543 100644
--- a/keymaster/4.0/vts/performance/Benchmark.cpp
+++ b/keymaster/4.0/vts/performance/Benchmark.cpp
@@ -16,6 +16,8 @@
 
 #define LOG_TAG "keymaster_benchmark"
 
+#include <getopt.h>
+
 #include <android/hardware/keymaster/4.0/IKeymasterDevice.h>
 #include <android/hardware/keymaster/4.0/types.h>
 #include <keymaster/keymaster_configuration.h>
@@ -36,8 +38,6 @@
 #include <benchmark/benchmark.h>
 #include <hidl/Status.h>
 
-#include <base/command_line.h>
-
 namespace android {
 namespace hardware {
 namespace keymaster {
@@ -700,14 +700,26 @@
 }  // namespace hardware
 }  // namespace android
 
+namespace {
+
+std::string ParseCommandLineFlags(int argc, char** argv) {
+    std::string service_name = "default";
+    static struct option long_options[] = {{"service_name", required_argument, 0, 's'},
+                                           {0, 0, 0, 0}};
+    int opt;
+    while ((opt = getopt_long(argc, argv, "s:", long_options, nullptr)) != -1) {
+        if (opt == 's') {
+            service_name = optarg;
+        }
+    }
+    return service_name;
+}
+
+}  // namespace
+
 int main(int argc, char** argv) {
     ::benchmark::Initialize(&argc, argv);
-    base::CommandLine::Init(argc, argv);
-    base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
-    auto service_name = command_line->GetSwitchValueASCII("service_name");
-    if (service_name.empty()) {
-        service_name = "default";
-    }
+    std::string service_name = ParseCommandLineFlags(argc, argv);
     android::hardware::keymaster::V4_0::test::keymaster =
             android::hardware::keymaster::V4_0::test::KeymasterWrapper::newInstance(service_name);
     if (!android::hardware::keymaster::V4_0::test::keymaster) {
diff --git a/keymaster/4.1/vts/functional/Android.bp b/keymaster/4.1/vts/functional/Android.bp
index 547ce38..04fc2d3 100644
--- a/keymaster/4.1/vts/functional/Android.bp
+++ b/keymaster/4.1/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_hardware_backed_security",
     // 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"
diff --git a/light/aidl/Android.bp b/light/aidl/Android.bp
index c9fba95..142be6d 100644
--- a/light/aidl/Android.bp
+++ b/light/aidl/Android.bp
@@ -14,6 +14,7 @@
         "android/hardware/light/*.aidl",
     ],
     stability: "vintf",
+    frozen: true,
     backend: {
         java: {
             sdk_version: "module_current",
diff --git a/macsec/aidl/vts/functional/Android.bp b/macsec/aidl/vts/functional/Android.bp
index 0c8f43d..faf0d15 100644
--- a/macsec/aidl/vts/functional/Android.bp
+++ b/macsec/aidl/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_aaos_security",
     // 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"
diff --git a/neuralnetworks/aidl/Android.bp b/neuralnetworks/aidl/Android.bp
index 145604c..9589750 100644
--- a/neuralnetworks/aidl/Android.bp
+++ b/neuralnetworks/aidl/Android.bp
@@ -11,13 +11,16 @@
     name: "android.hardware.neuralnetworks",
     host_supported: true,
     vendor_available: true,
+    frozen: true,
     srcs: [
         "android/hardware/neuralnetworks/*.aidl",
     ],
     stability: "vintf",
+    defaults: [
+        "android.hardware.graphics.common-latest",
+    ],
     imports: [
         "android.hardware.common-V2",
-        "android.hardware.graphics.common-V5",
     ],
     backend: {
         java: {
diff --git a/nfc/aidl/Android.bp b/nfc/aidl/Android.bp
index ae68f17..b34e4f2 100644
--- a/nfc/aidl/Android.bp
+++ b/nfc/aidl/Android.bp
@@ -27,6 +27,7 @@
     vendor_available: true,
     srcs: ["android/hardware/nfc/*.aidl"],
     stability: "vintf",
+    frozen: false,
     backend: {
         cpp: {
             enabled: false,
diff --git a/oemlock/aidl/Android.bp b/oemlock/aidl/Android.bp
index 1c19bb1..f4533ed 100644
--- a/oemlock/aidl/Android.bp
+++ b/oemlock/aidl/Android.bp
@@ -10,6 +10,7 @@
 aidl_interface {
     name: "android.hardware.oemlock",
     vendor_available: true,
+    frozen: true,
     srcs: ["android/hardware/oemlock/*.aidl"],
     stability: "vintf",
     backend: {
diff --git a/power/aidl/Android.bp b/power/aidl/Android.bp
index dc57613..2c80aab 100644
--- a/power/aidl/Android.bp
+++ b/power/aidl/Android.bp
@@ -69,46 +69,53 @@
                 "android.hardware.common-V2",
             ],
         },
-
     ],
-    frozen: true,
-
+    frozen: false,
 }
 
+power_version = "android.hardware.power-V6"
+
 cc_defaults {
     name: "android.hardware.power-ndk_shared",
     shared_libs: [
-        "android.hardware.power-V5-ndk",
+        power_version + "-ndk",
     ],
 }
 
 cc_defaults {
     name: "android.hardware.power-ndk_export_shared",
     shared_libs: [
-        "android.hardware.power-V5-ndk",
+        power_version + "-ndk",
     ],
     export_shared_lib_headers: [
-        "android.hardware.power-V5-ndk",
+        power_version + "-ndk",
     ],
 }
 
 cc_defaults {
     name: "android.hardware.power-ndk_static",
     static_libs: [
-        "android.hardware.power-V5-ndk",
+        power_version + "-ndk",
     ],
 }
 
 java_defaults {
     name: "android.hardware.power-java_shared",
     libs: [
-        "android.hardware.power-V5-java",
+        power_version + "-java",
     ],
 }
 
 java_defaults {
     name: "android.hardware.power-java_static",
     static_libs: [
-        "android.hardware.power-V5-java",
+        power_version + "-java",
+    ],
+}
+
+aidl_interface_defaults {
+    name: "android.hardware.power-aidl",
+    imports: [
+        power_version,
     ],
 }
diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/SessionTag.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/SessionTag.aidl
index 862fbc5..71da2d4 100644
--- a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/SessionTag.aidl
+++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/SessionTag.aidl
@@ -39,4 +39,5 @@
   HWUI,
   GAME,
   APP,
+  SYSUI,
 }
diff --git a/power/aidl/android/hardware/power/SessionTag.aidl b/power/aidl/android/hardware/power/SessionTag.aidl
index 27bf3e3..e98cc77 100644
--- a/power/aidl/android/hardware/power/SessionTag.aidl
+++ b/power/aidl/android/hardware/power/SessionTag.aidl
@@ -46,4 +46,9 @@
      * instead.
      */
     APP,
+
+    /**
+     * This tag is used to mark hint sessions created by the system UI.
+     */
+    SYSUI,
 }
diff --git a/power/aidl/default/power-default.xml b/power/aidl/default/power-default.xml
index 418fb83..1bb73f3 100644
--- a/power/aidl/default/power-default.xml
+++ b/power/aidl/default/power-default.xml
@@ -1,7 +1,7 @@
 <manifest version="1.0" type="device">
     <hal format="aidl">
         <name>android.hardware.power</name>
-        <version>5</version>
+        <version>6</version>
         <fqname>IPower/default</fqname>
     </hal>
 </manifest>
diff --git a/radio/1.0/vts/functional/Android.bp b/radio/1.0/vts/functional/Android.bp
index 2c0e70a..4ff5c2c 100644
--- a/radio/1.0/vts/functional/Android.bp
+++ b/radio/1.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_fwk_telephony",
     // 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"
diff --git a/radio/1.1/vts/functional/Android.bp b/radio/1.1/vts/functional/Android.bp
index b3def8e..dc50cfb 100644
--- a/radio/1.1/vts/functional/Android.bp
+++ b/radio/1.1/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_fwk_telephony",
     // 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"
diff --git a/radio/1.2/vts/functional/Android.bp b/radio/1.2/vts/functional/Android.bp
index a62000f..6bc0594 100644
--- a/radio/1.2/vts/functional/Android.bp
+++ b/radio/1.2/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_fwk_telephony",
     // 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"
diff --git a/radio/1.3/vts/functional/Android.bp b/radio/1.3/vts/functional/Android.bp
index d96d391..9a0996b 100644
--- a/radio/1.3/vts/functional/Android.bp
+++ b/radio/1.3/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_fwk_telephony",
     // 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"
diff --git a/radio/1.4/vts/functional/Android.bp b/radio/1.4/vts/functional/Android.bp
index 167dec8..de2ed2c 100644
--- a/radio/1.4/vts/functional/Android.bp
+++ b/radio/1.4/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_fwk_telephony",
     // 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"
diff --git a/radio/1.5/vts/functional/Android.bp b/radio/1.5/vts/functional/Android.bp
index 4549d3c..83a2568 100644
--- a/radio/1.5/vts/functional/Android.bp
+++ b/radio/1.5/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_fwk_telephony",
     // 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"
diff --git a/radio/1.6/vts/functional/Android.bp b/radio/1.6/vts/functional/Android.bp
index 2bc6af3..b78330e 100644
--- a/radio/1.6/vts/functional/Android.bp
+++ b/radio/1.6/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_fwk_telephony",
     // 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"
diff --git a/radio/aidl/android/hardware/radio/sim/IRadioSimResponse.aidl b/radio/aidl/android/hardware/radio/sim/IRadioSimResponse.aidl
index 91b5729..63134c1 100644
--- a/radio/aidl/android/hardware/radio/sim/IRadioSimResponse.aidl
+++ b/radio/aidl/android/hardware/radio/sim/IRadioSimResponse.aidl
@@ -378,6 +378,7 @@
      *   RadioError:INVALID_MODEM_STATE
      *   RadioError:SIM_ERR
      *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:REQUEST_NOT_SUPPORTED
      */
     void requestIccSimAuthenticationResponse(in RadioResponseInfo info, in IccIoResult result);
 
diff --git a/radio/aidl/vts/radio_network_test.cpp b/radio/aidl/vts/radio_network_test.cpp
index 914cad0..3d24165 100644
--- a/radio/aidl/vts/radio_network_test.cpp
+++ b/radio/aidl/vts/radio_network_test.cpp
@@ -609,6 +609,11 @@
         }
     }
 
+    if (!deviceSupportsFeature(FEATURE_TELEPHONY_CDMA)) {
+        GTEST_SKIP() << "Skipping setSignalStrengthReportingCriteria_Cdma2000 "
+                        "due to undefined FEATURE_TELEPHONY_CDMA";
+    }
+
     serial = GetRandomSerialNumber();
 
     SignalThresholdInfo signalThresholdInfo;
@@ -824,9 +829,12 @@
     signalThresholdInfoNgran.isEnabled = true;
     signalThresholdInfoNgran.ran = AccessNetwork::NGRAN;
 
-    const static std::vector<SignalThresholdInfo> candidateSignalThresholdInfos = {
+    std::vector<SignalThresholdInfo> candidateSignalThresholdInfos = {
             signalThresholdInfoGeran, signalThresholdInfoUtran, signalThresholdInfoEutran,
-            signalThresholdInfoCdma2000, signalThresholdInfoNgran};
+            signalThresholdInfoNgran};
+    if (deviceSupportsFeature(FEATURE_TELEPHONY_CDMA)) {
+        candidateSignalThresholdInfos.push_back(signalThresholdInfoCdma2000);
+    }
 
     std::vector<SignalThresholdInfo> supportedSignalThresholdInfos;
     for (size_t i = 0; i < candidateSignalThresholdInfos.size(); i++) {
diff --git a/rebootescrow/aidl/Android.bp b/rebootescrow/aidl/Android.bp
index 39aaa07..3d5b827 100644
--- a/rebootescrow/aidl/Android.bp
+++ b/rebootescrow/aidl/Android.bp
@@ -10,6 +10,7 @@
 aidl_interface {
     name: "android.hardware.rebootescrow",
     vendor_available: true,
+    frozen: true,
     srcs: [
         "android/hardware/rebootescrow/IRebootEscrow.aidl",
     ],
diff --git a/secure_element/1.0/vts/functional/Android.bp b/secure_element/1.0/vts/functional/Android.bp
index 735d7c9..25ce050 100644
--- a/secure_element/1.0/vts/functional/Android.bp
+++ b/secure_element/1.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_pixel_connectivity_nfc",
     // 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"
diff --git a/secure_element/1.1/vts/functional/Android.bp b/secure_element/1.1/vts/functional/Android.bp
index d63e7c4..ad7f97c 100644
--- a/secure_element/1.1/vts/functional/Android.bp
+++ b/secure_element/1.1/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_pixel_connectivity_nfc",
     // 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"
diff --git a/secure_element/1.2/vts/functional/Android.bp b/secure_element/1.2/vts/functional/Android.bp
index 63a0a19..5a01851 100644
--- a/secure_element/1.2/vts/functional/Android.bp
+++ b/secure_element/1.2/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_pixel_connectivity_nfc",
     // 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"
diff --git a/secure_element/aidl/Android.bp b/secure_element/aidl/Android.bp
index 655487d..1145305 100644
--- a/secure_element/aidl/Android.bp
+++ b/secure_element/aidl/Android.bp
@@ -1,4 +1,5 @@
 package {
+    default_team: "trendy_team_pixel_connectivity_nfc",
     // 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"
diff --git a/security/authgraph/aidl/vts/functional/Android.bp b/security/authgraph/aidl/vts/functional/Android.bp
index 28a70e2..e40525c 100644
--- a/security/authgraph/aidl/vts/functional/Android.bp
+++ b/security/authgraph/aidl/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_hardware_backed_security",
     // 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"
diff --git a/security/keymint/aidl/default/file_contexts b/security/keymint/aidl/default/file_contexts
index dce7e3c..41b02d5 100644
--- a/security/keymint/aidl/default/file_contexts
+++ b/security/keymint/aidl/default/file_contexts
@@ -1,3 +1,3 @@
 (/.*)?                                                           u:object_r:vendor_file:s0
 /etc(/.*)?                                                       u:object_r:vendor_configs_file:s0
-/bin/hw/android\.hardware\.security\.keymint-service\.nonsecure  u:object_r:hal_keymint_rust_exec:s0
+/bin/hw/android\.hardware\.security\.keymint-service\.nonsecure  u:object_r:hal_keymint_default_exec:s0
diff --git a/security/keymint/aidl/vts/functional/Android.bp b/security/keymint/aidl/vts/functional/Android.bp
index 7a135e1..1414220 100644
--- a/security/keymint/aidl/vts/functional/Android.bp
+++ b/security/keymint/aidl/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_hardware_backed_security",
     // 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"
diff --git a/security/keymint/aidl/vts/functional/DeviceUniqueAttestationTest.cpp b/security/keymint/aidl/vts/functional/DeviceUniqueAttestationTest.cpp
index f669110..9e3e159 100644
--- a/security/keymint/aidl/vts/functional/DeviceUniqueAttestationTest.cpp
+++ b/security/keymint/aidl/vts/functional/DeviceUniqueAttestationTest.cpp
@@ -253,39 +253,14 @@
 
     // Collection of valid attestation ID tags.
     auto attestation_id_tags = AuthorizationSetBuilder();
-    // Use ro.product.brand_for_attestation property for attestation if it is present else fallback
-    // to ro.product.brand
-    std::string prop_value =
-            ::android::base::GetProperty("ro.product.brand_for_attestation", /* default= */ "");
-    if (!prop_value.empty()) {
-        add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_BRAND,
-                          "ro.product.brand_for_attestation");
-    } else {
-        add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_BRAND, "ro.product.brand");
-    }
-    add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_DEVICE, "ro.product.device");
-    // Use ro.product.name_for_attestation property for attestation if it is present else fallback
-    // to ro.product.name
-    prop_value = ::android::base::GetProperty("ro.product.name_for_attestation", /* default= */ "");
-    if (!prop_value.empty()) {
-        add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_PRODUCT,
-                          "ro.product.name_for_attestation");
-    } else {
-        add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_PRODUCT, "ro.product.name");
-    }
+
+    add_attestation_id(&attestation_id_tags, TAG_ATTESTATION_ID_BRAND, "brand");
+    add_attestation_id(&attestation_id_tags, TAG_ATTESTATION_ID_DEVICE, "device");
+    add_attestation_id(&attestation_id_tags, TAG_ATTESTATION_ID_PRODUCT, "name");
     add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_SERIAL, "ro.serialno");
-    add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_MANUFACTURER,
-                      "ro.product.manufacturer");
-    // Use ro.product.model_for_attestation property for attestation if it is present else fallback
-    // to ro.product.model
-    prop_value =
-            ::android::base::GetProperty("ro.product.model_for_attestation", /* default= */ "");
-    if (!prop_value.empty()) {
-        add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_MODEL,
-                          "ro.product.model_for_attestation");
-    } else {
-        add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_MODEL, "ro.product.model");
-    }
+    add_attestation_id(&attestation_id_tags, TAG_ATTESTATION_ID_MANUFACTURER, "manufacturer");
+    add_attestation_id(&attestation_id_tags, TAG_ATTESTATION_ID_MODEL, "model");
+
     vector<uint8_t> key_blob;
     vector<KeyCharacteristics> key_characteristics;
 
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
index c19ab11..cfe9fa7 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
@@ -2400,6 +2400,43 @@
     return imei;
 }
 
+std::optional<std::string> get_attestation_id(const char* prop) {
+    // The frameworks code (in AndroidKeyStoreKeyPairGeneratorSpi.java) populates device ID
+    // values from one of 3 places, so the same logic needs to be reproduced here so the tests
+    // check what's expected correctly.
+    //
+    // In order of preference, the properties checked are:
+    //
+    // 1) `ro.product.<device-id>_for_attestation`: This should only be set in special cases; in
+    //     particular, AOSP builds for reference devices use a different value than the normal
+    //     builds for the same device (e.g. model of "aosp_raven" instead of "raven").
+    ::android::String8 prop_name =
+            ::android::String8::format("ro.product.%s_for_attestation", prop);
+    std::string prop_value = ::android::base::GetProperty(prop_name.c_str(), /* default= */ "");
+    if (!prop_value.empty()) {
+        return prop_value;
+    }
+
+    // 2) `ro.product.vendor.<device-id>`: This property refers to the vendor code, and so is
+    //    retained even in a GSI environment.
+    prop_name = ::android::String8::format("ro.product.vendor.%s", prop);
+    prop_value = ::android::base::GetProperty(prop_name.c_str(), /* default= */ "");
+    if (!prop_value.empty()) {
+        return prop_value;
+    }
+
+    // 3) `ro.product.<device-id>`: Note that this property is replaced by a default value when
+    //    running a GSI environment, and so will *not* match the value expected/used by the
+    //    vendor code on the device.
+    prop_name = ::android::String8::format("ro.product.%s", prop);
+    prop_value = ::android::base::GetProperty(prop_name.c_str(), /* default= */ "");
+    if (!prop_value.empty()) {
+        return prop_value;
+    }
+
+    return std::nullopt;
+}
+
 }  // namespace test
 
 }  // namespace aidl::android::hardware::security::keymint
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
index 0368bba..85ae93d 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
@@ -17,6 +17,7 @@
 #pragma once
 
 #include <functional>
+#include <optional>
 #include <string_view>
 
 #include <aidl/Gtest.h>
@@ -384,14 +385,20 @@
                                     const string& plaintext, const string& exp_cipher_text);
 };
 
+// If the given string is non-empty, add it to the tag set under the given tag ID.
+template <Tag tag>
+void add_tag(AuthorizationSetBuilder* tags, TypedTag<TagType::BYTES, tag> ttag,
+             const std::string& prop_value) {
+    if (!prop_value.empty()) {
+        tags->Authorization(ttag, prop_value.data(), prop_value.size());
+    }
+}
+
 // If the given property is available, add it to the tag set under the given tag ID.
 template <Tag tag>
 void add_tag_from_prop(AuthorizationSetBuilder* tags, TypedTag<TagType::BYTES, tag> ttag,
                        const char* prop) {
-    std::string prop_value = ::android::base::GetProperty(prop, /* default= */ "");
-    if (!prop_value.empty()) {
-        tags->Authorization(ttag, prop_value.data(), prop_value.size());
-    }
+    add_tag(tags, ttag, ::android::base::GetProperty(prop, /* default= */ ""));
 }
 
 // Return the VSR API level for this device.
@@ -431,6 +438,20 @@
 std::optional<int32_t> keymint_feature_value(bool strongbox);
 std::string get_imei(int slot);
 
+// Retrieve a device ID property value, to match what is expected in attestations.
+std::optional<std::string> get_attestation_id(const char* prop);
+
+// Add the appropriate attestation device ID tag value to the provided `AuthorizationSetBuilder`,
+// if found.
+template <Tag tag>
+void add_attestation_id(AuthorizationSetBuilder* attestation_id_tags,
+                        TypedTag<TagType::BYTES, tag> tag_type, const char* prop) {
+    auto prop_value = get_attestation_id(prop);
+    if (prop_value.has_value()) {
+        add_tag(attestation_id_tags, tag_type, prop_value.value());
+    }
+}
+
 AuthorizationSet HwEnforcedAuthorizations(const vector<KeyCharacteristics>& key_characteristics);
 AuthorizationSet SwEnforcedAuthorizations(const vector<KeyCharacteristics>& key_characteristics);
 ::testing::AssertionResult ChainSignaturesAreValid(const vector<Certificate>& chain,
@@ -444,29 +465,6 @@
                              ::android::PrintInstanceNameToString);                  \
     GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(name);
 
-// Use `ro.product.<property>_for_attestation` property for attestation if it is present else
-// fallback to use `ro.product.vendor.<property>` if it is present else fallback to
-// `ro.product.<property>`. Similar logic can be seen in Java method `getVendorDeviceIdProperty`
-// in frameworks/base/core/java/android/os/Build.java.
-template <Tag tag>
-void add_attestation_id(AuthorizationSetBuilder* attestation_id_tags,
-                        TypedTag<TagType::BYTES, tag> tag_type, const char* prop) {
-    ::android::String8 prop_name =
-            ::android::String8::format("ro.product.%s_for_attestation", prop);
-    std::string prop_value = ::android::base::GetProperty(prop_name.c_str(), /* default= */ "");
-    if (!prop_value.empty()) {
-        add_tag_from_prop(attestation_id_tags, tag_type, prop_name.c_str());
-    } else {
-        prop_name = ::android::String8::format("ro.product.vendor.%s", prop);
-        prop_value = ::android::base::GetProperty(prop_name.c_str(), /* default= */ "");
-        if (!prop_value.empty()) {
-            add_tag_from_prop(attestation_id_tags, tag_type, prop_name.c_str());
-        } else {
-            prop_name = ::android::String8::format("ro.product.%s", prop);
-            add_tag_from_prop(attestation_id_tags, tag_type, prop_name.c_str());
-        }
-    }
-}
 }  // namespace test
 
 }  // namespace aidl::android::hardware::security::keymint
diff --git a/security/keymint/support/fuzzer/keymint_remote_prov_fuzzer.cpp b/security/keymint/support/fuzzer/keymint_remote_prov_fuzzer.cpp
index 6bd986c..9b74fbb 100644
--- a/security/keymint/support/fuzzer/keymint_remote_prov_fuzzer.cpp
+++ b/security/keymint/support/fuzzer/keymint_remote_prov_fuzzer.cpp
@@ -79,9 +79,13 @@
 
     while (mFdp.remaining_bytes()) {
         auto invokeProvAPI = mFdp.PickValueInArray<const std::function<void()>>({
-                [&]() { verifyFactoryCsr(cborKeysToSign, csr, gRPC.get(), challenge); },
-                [&]() { verifyProductionCsr(cborKeysToSign, csr, gRPC.get(), challenge); },
-                [&]() { isCsrWithProperDiceChain(csr); },
+                [&]() {
+                    verifyFactoryCsr(cborKeysToSign, csr, gRPC.get(), kServiceName, challenge);
+                },
+                [&]() {
+                    verifyProductionCsr(cborKeysToSign, csr, gRPC.get(), kServiceName, challenge);
+                },
+                [&]() { isCsrWithProperDiceChain(csr, kServiceName); },
         });
         invokeProvAPI();
     }
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 141f243..b56c90a 100644
--- a/security/keymint/support/include/remote_prov/remote_prov_utils.h
+++ b/security/keymint/support/include/remote_prov/remote_prov_utils.h
@@ -89,6 +89,11 @@
  */
 bytevec randomBytes(size_t numBytes);
 
+const std::string DEFAULT_INSTANCE_NAME =
+        "android.hardware.security.keymint.IRemotelyProvisionedComponent/default";
+const std::string RKPVM_INSTANCE_NAME =
+        "android.hardware.security.keymint.IRemotelyProvisionedComponent/avf";
+
 struct EekChain {
     bytevec chain;
     bytevec last_pubkey;
@@ -160,7 +165,8 @@
         const DeviceInfo& deviceInfo, const cppbor::Array& keysToSign,
         const std::vector<uint8_t>& keysToSignMac, const ProtectedData& protectedData,
         const EekChain& eekChain, const std::vector<uint8_t>& eekId, int32_t supportedEekCurve,
-        IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge);
+        IRemotelyProvisionedComponent* provisionable, const std::string& instanceName,
+        const std::vector<uint8_t>& challenge);
 /**
  * Verify the protected data as if the device is a final production sample.
  */
@@ -168,8 +174,8 @@
         const DeviceInfo& deviceInfo, const cppbor::Array& keysToSign,
         const std::vector<uint8_t>& keysToSignMac, const ProtectedData& protectedData,
         const EekChain& eekChain, const std::vector<uint8_t>& eekId, int32_t supportedEekCurve,
-        IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge,
-        bool allowAnyMode = false);
+        IRemotelyProvisionedComponent* provisionable, const std::string& instanceName,
+        const std::vector<uint8_t>& challenge, bool allowAnyMode = false);
 
 /**
  * Verify the CSR as if the device is still early in the factory process and may not
@@ -177,22 +183,24 @@
  */
 ErrMsgOr<std::unique_ptr<cppbor::Array>> verifyFactoryCsr(
         const cppbor::Array& keysToSign, const std::vector<uint8_t>& csr,
-        IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge,
-        bool allowDegenerate = true);
+        IRemotelyProvisionedComponent* provisionable, const std::string& instanceName,
+        const std::vector<uint8_t>& challenge, bool allowDegenerate = true);
 /**
  * Verify the CSR as if the device is a final production sample.
  */
 ErrMsgOr<std::unique_ptr<cppbor::Array>> verifyProductionCsr(
         const cppbor::Array& keysToSign, const std::vector<uint8_t>& csr,
-        IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge,
-        bool allowAnyMode = false);
+        IRemotelyProvisionedComponent* provisionable, const std::string& instanceName,
+        const std::vector<uint8_t>& challenge, bool allowAnyMode = false);
 
 /** Checks whether the CSR has a proper DICE chain. */
-ErrMsgOr<bool> isCsrWithProperDiceChain(const std::vector<uint8_t>& csr);
+ErrMsgOr<bool> isCsrWithProperDiceChain(const std::vector<uint8_t>& csr,
+                                        const std::string& instanceName);
 
 /** Verify the DICE chain. */
 ErrMsgOr<std::vector<BccEntryData>> validateBcc(const cppbor::Array* bcc,
                                                 hwtrust::DiceChain::Kind kind, bool allowAnyMode,
-                                                bool allowDegenerate);
+                                                bool allowDegenerate,
+                                                const std::string& instanceName);
 
 }  // 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 a679340..497f478 100644
--- a/security/keymint/support/remote_prov_utils.cpp
+++ b/security/keymint/support/remote_prov_utils.cpp
@@ -52,6 +52,14 @@
 using X509_Ptr = bssl::UniquePtr<X509>;
 using CRYPTO_BUFFER_Ptr = bssl::UniquePtr<CRYPTO_BUFFER>;
 
+std::string device_suffix(const std::string& name) {
+    size_t pos = name.find('/');
+    if (pos == std::string::npos) {
+        return name;
+    }
+    return name.substr(pos + 1);
+}
+
 ErrMsgOr<bytevec> ecKeyGetPrivateKey(const EC_KEY* ecKey) {
     // Extract private key.
     const BIGNUM* bignum = EC_KEY_get0_private_key(ecKey);
@@ -325,7 +333,8 @@
 
 ErrMsgOr<std::vector<BccEntryData>> validateBcc(const cppbor::Array* bcc,
                                                 hwtrust::DiceChain::Kind kind, bool allowAnyMode,
-                                                bool allowDegenerate) {
+                                                bool allowDegenerate,
+                                                const std::string& instanceName) {
     auto encodedBcc = bcc->encode();
 
     // Use ro.build.type instead of ro.debuggable because ro.debuggable=1 for VTS testing
@@ -334,7 +343,8 @@
         allowAnyMode = true;
     }
 
-    auto chain = hwtrust::DiceChain::Verify(encodedBcc, kind, allowAnyMode);
+    auto chain =
+            hwtrust::DiceChain::Verify(encodedBcc, kind, allowAnyMode, device_suffix(instanceName));
     if (!chain.ok()) return chain.error().message();
 
     if (!allowDegenerate && !chain->IsProper()) {
@@ -649,8 +659,8 @@
         const DeviceInfo& deviceInfo, const cppbor::Array& keysToSign,
         const std::vector<uint8_t>& keysToSignMac, const ProtectedData& protectedData,
         const EekChain& eekChain, const std::vector<uint8_t>& eekId, int32_t supportedEekCurve,
-        IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge,
-        bool isFactory, bool allowAnyMode = false) {
+        IRemotelyProvisionedComponent* provisionable, const std::string& instanceName,
+        const std::vector<uint8_t>& challenge, bool isFactory, bool allowAnyMode = false) {
     auto [parsedProtectedData, _, protDataErrMsg] = cppbor::parse(protectedData.protectedData);
     if (!parsedProtectedData) {
         return protDataErrMsg;
@@ -707,7 +717,7 @@
 
     // BCC is [ pubkey, + BccEntry]
     auto bccContents = validateBcc(bcc->asArray(), hwtrust::DiceChain::Kind::kVsr13, allowAnyMode,
-                                   /*allowDegenerate=*/true);
+                                   /*allowDegenerate=*/true, instanceName);
     if (!bccContents) {
         return bccContents.message() + "\n" + prettyPrint(bcc.get());
     }
@@ -750,9 +760,10 @@
         const DeviceInfo& deviceInfo, const cppbor::Array& keysToSign,
         const std::vector<uint8_t>& keysToSignMac, const ProtectedData& protectedData,
         const EekChain& eekChain, const std::vector<uint8_t>& eekId, int32_t supportedEekCurve,
-        IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge) {
+        IRemotelyProvisionedComponent* provisionable, const std::string& instanceName,
+        const std::vector<uint8_t>& challenge) {
     return verifyProtectedData(deviceInfo, keysToSign, keysToSignMac, protectedData, eekChain,
-                               eekId, supportedEekCurve, provisionable, challenge,
+                               eekId, supportedEekCurve, provisionable, instanceName, challenge,
                                /*isFactory=*/true);
 }
 
@@ -760,10 +771,10 @@
         const DeviceInfo& deviceInfo, const cppbor::Array& keysToSign,
         const std::vector<uint8_t>& keysToSignMac, const ProtectedData& protectedData,
         const EekChain& eekChain, const std::vector<uint8_t>& eekId, int32_t supportedEekCurve,
-        IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge,
-        bool allowAnyMode) {
+        IRemotelyProvisionedComponent* provisionable, const std::string& instanceName,
+        const std::vector<uint8_t>& challenge, bool allowAnyMode) {
     return verifyProtectedData(deviceInfo, keysToSign, keysToSignMac, protectedData, eekChain,
-                               eekId, supportedEekCurve, provisionable, challenge,
+                               eekId, supportedEekCurve, provisionable, instanceName, challenge,
                                /*isFactory=*/false, allowAnyMode);
 }
 
@@ -1003,6 +1014,7 @@
 
 ErrMsgOr<bytevec> parseAndValidateAuthenticatedRequest(const std::vector<uint8_t>& request,
                                                        const std::vector<uint8_t>& challenge,
+                                                       const std::string& instanceName,
                                                        bool allowAnyMode = false,
                                                        bool allowDegenerate = true) {
     auto [parsedRequest, _, csrErrMsg] = cppbor::parse(request);
@@ -1042,7 +1054,8 @@
         return diceChainKind.message();
     }
 
-    auto diceContents = validateBcc(diceCertChain, *diceChainKind, allowAnyMode, allowDegenerate);
+    auto diceContents =
+            validateBcc(diceCertChain, *diceChainKind, allowAnyMode, allowDegenerate, instanceName);
     if (!diceContents) {
         return diceContents.message() + "\n" + prettyPrint(diceCertChain);
     }
@@ -1071,6 +1084,7 @@
 ErrMsgOr<std::unique_ptr<cppbor::Array>> verifyCsr(const cppbor::Array& keysToSign,
                                                    const std::vector<uint8_t>& csr,
                                                    IRemotelyProvisionedComponent* provisionable,
+                                                   const std::string& instanceName,
                                                    const std::vector<uint8_t>& challenge,
                                                    bool isFactory, bool allowAnyMode = false,
                                                    bool allowDegenerate = true) {
@@ -1081,8 +1095,8 @@
                ") does not match expected version (3).";
     }
 
-    auto csrPayload =
-            parseAndValidateAuthenticatedRequest(csr, challenge, allowAnyMode, allowDegenerate);
+    auto csrPayload = parseAndValidateAuthenticatedRequest(csr, challenge, instanceName,
+                                                           allowAnyMode, allowDegenerate);
     if (!csrPayload) {
         return csrPayload.message();
     }
@@ -1092,20 +1106,22 @@
 
 ErrMsgOr<std::unique_ptr<cppbor::Array>> verifyFactoryCsr(
         const cppbor::Array& keysToSign, const std::vector<uint8_t>& csr,
-        IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge,
-        bool allowDegenerate) {
-    return verifyCsr(keysToSign, csr, provisionable, challenge, /*isFactory=*/true,
+        IRemotelyProvisionedComponent* provisionable, const std::string& instanceName,
+        const std::vector<uint8_t>& challenge, bool allowDegenerate) {
+    return verifyCsr(keysToSign, csr, provisionable, instanceName, challenge, /*isFactory=*/true,
                      /*allowAnyMode=*/false, allowDegenerate);
 }
 
 ErrMsgOr<std::unique_ptr<cppbor::Array>> verifyProductionCsr(
         const cppbor::Array& keysToSign, const std::vector<uint8_t>& csr,
-        IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge,
-        bool allowAnyMode) {
-    return verifyCsr(keysToSign, csr, provisionable, challenge, /*isFactory=*/false, allowAnyMode);
+        IRemotelyProvisionedComponent* provisionable, const std::string& instanceName,
+        const std::vector<uint8_t>& challenge, bool allowAnyMode) {
+    return verifyCsr(keysToSign, csr, provisionable, instanceName, challenge, /*isFactory=*/false,
+                     allowAnyMode);
 }
 
-ErrMsgOr<bool> isCsrWithProperDiceChain(const std::vector<uint8_t>& csr) {
+ErrMsgOr<bool> isCsrWithProperDiceChain(const std::vector<uint8_t>& csr,
+                                        const std::string& instanceName) {
     auto [parsedRequest, _, csrErrMsg] = cppbor::parse(csr);
     if (!parsedRequest) {
         return csrErrMsg;
@@ -1136,8 +1152,8 @@
     }
 
     auto encodedDiceChain = diceCertChain->encode();
-    auto chain =
-            hwtrust::DiceChain::Verify(encodedDiceChain, *diceChainKind, /*allowAnyMode=*/false);
+    auto chain = hwtrust::DiceChain::Verify(encodedDiceChain, *diceChainKind,
+                                            /*allowAnyMode=*/false, device_suffix(instanceName));
     if (!chain.ok()) return chain.error().message();
     return chain->IsProper();
 }
diff --git a/security/keymint/support/remote_prov_utils_test.cpp b/security/keymint/support/remote_prov_utils_test.cpp
index 82121cb..8b18b29 100644
--- a/security/keymint/support/remote_prov_utils_test.cpp
+++ b/security/keymint/support/remote_prov_utils_test.cpp
@@ -298,9 +298,11 @@
     ASSERT_TRUE(bcc) << "Error: " << errMsg;
 
     EXPECT_TRUE(validateBcc(bcc->asArray(), hwtrust::DiceChain::Kind::kVsr16,
-                            /*allowAnyMode=*/false, /*allowDegenerate=*/true));
+                            /*allowAnyMode=*/false, /*allowDegenerate=*/true,
+                            DEFAULT_INSTANCE_NAME));
     EXPECT_FALSE(validateBcc(bcc->asArray(), hwtrust::DiceChain::Kind::kVsr16,
-                             /*allowAnyMode=*/false, /*allowDegenerate=*/false));
+                             /*allowAnyMode=*/false, /*allowDegenerate=*/false,
+                             DEFAULT_INSTANCE_NAME));
 }
 }  // namespace
 }  // namespace aidl::android::hardware::security::keymint::remote_prov
diff --git a/security/rkp/README.md b/security/rkp/README.md
index 67cf72e..43a00fb 100644
--- a/security/rkp/README.md
+++ b/security/rkp/README.md
@@ -31,12 +31,13 @@
 1.  (Preferred, recommended) The device OEM extracts the UDS\_pub from each
     device they manufacture and uploads the public keys to a backend server.
 
-1.  The device OEM signs the UDS\_pub and stores the certificates on the device
-    rather than uploading a UDS\_pub for every device immediately. However,
-    there are many disadvantages and costs associated with this option as the
-    OEM will need to pass a security audit of their factory's physical security,
-    CA and HSM configuration, and incident response processes before the OEM's
-    public key is registered with the provisioning server.
+1.  The device OEM certifies the UDS\_pub using an x.509 certificate chain
+    then stores the chain on the device rather than uploading a UDS\_pub for
+    every device immediately. However, there are many disadvantages and costs
+    associated with this option as the OEM will need to pass a security audit
+    of their factory's physical security, CA and HSM configuration, and
+    incident response processes before the OEM's public key is registered with
+    the provisioning server.
 
 Note that in the full elaboration of this plan, UDS\_pub is not the key used to
 sign certificate requests. Instead, UDS\_pub is just the first public key in a
@@ -124,6 +125,53 @@
 choice for algorithm implies the implementor should also choose the P256 public
 key group further down in the COSE structure.
 
+## UDS certificates
+
+As noted in the section [General approach](#general-approach), the UDS\_pub may
+be authenticated by an OEM using an x.509 certificate chain. Additionally,
+[RKP Phase 3](#phases) depends on the chip vendor signing the UDS\_pub and
+issuing an x.509 certificate chain. This section describes the requirements for
+both the signing keys and the resulting certificate chain.
+
+### X.509 Certificates
+
+X.509v3 public key certificates are the only supported mechanism for
+authenticating a UDS\_pub. Certificates must be formatted according to
+[RFC 5280](https://datatracker.ietf.org/doc/html/rfc5280), and certificate
+chains must satisfy the certificate path validation described in the RFC. RFC
+5280 covers most requirements for the chain, but this specification has some
+additional requirements that must be met for the certificates:
+
+*   [`BasicConstraints`](https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.9)
+    *   All CA certificates must include this as a critical extension.
+    *   `pathLenConstraint` must be set correctly in each CA certificate to
+        limit the maximum chain length.
+    *   `cA` must be set to true for all certificates except the leaf
+        certificate.
+    *   `BasicConstraints` must be absent for the leaf/UDS certificate.
+    *   Consider the chain `root -> intermediate -> UDS_pub`. In such a chain,
+        `BasicConstraints` must be:
+        *   `{ cA: TRUE, pathLenConstraint: 1}` for the root certificate
+        *   `{ cA: TRUE, pathLenConstraint: 0}` for the intermediate certificate
+        *   Absent for the UDS certificate
+*   [`KeyUsage`](https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.3)
+    *   All certificates in a UDS certificate chain must include this as a
+        critical extension.
+    *   CA certificates must set `KeyUsage` to only `keyCertSign`.
+    *   The UDS certificate must set `KeyUsage` to only `digitalSignature`.
+
+### Supported Algorithms
+
+UDS certificates must be signed using one of the following allowed algorithms:
+
+*   `ecdsa-with-SHA256`
+    ([RFC 5758](https://www.rfc-editor.org/rfc/rfc5758#section-3.2))
+    *   Note: this algorithm is only usable with ECDSA P-256 keys
+*   `ecdsa-with-SHA384`
+    ([RFC 5758](https://www.rfc-editor.org/rfc/rfc5758#section-3.2))
+    *   Note: this algorithm is only usable with ECDSA P-384 keys
+*   `id-Ed25519` ([RFC 8410](https://www.rfc-editor.org/rfc/rfc8410#section-3))
+
 ## Design
 
 ### Certificate provisioning flow
diff --git a/security/rkp/aidl/android/hardware/security/keymint/generateCertificateRequestV2.cddl b/security/rkp/aidl/android/hardware/security/keymint/generateCertificateRequestV2.cddl
index 7a02ff5..c519086 100644
--- a/security/rkp/aidl/android/hardware/security/keymint/generateCertificateRequestV2.cddl
+++ b/security/rkp/aidl/android/hardware/security/keymint/generateCertificateRequestV2.cddl
@@ -52,7 +52,8 @@
 ; example, this could be provided by the hardware vendor, who certifies all of their chips.
 ; The SignerName is a free-form string describing who generated the signature. The root
 ; certificate will need to be communicated to the verifier out of band, along with the
-; SignerName that is expected for the given root certificate.
+; SignerName that is expected for the given root certificate. UDS certificate
+; requirements are defined in https://android.googlesource.com/platform/hardware/interfaces/+/main/security/rkp/README.md#uds-certificates.
 UdsCerts = {
     * SignerName => UdsCertChain
 }
diff --git a/security/rkp/aidl/vts/functional/Android.bp b/security/rkp/aidl/vts/functional/Android.bp
index 2cce8db..3bc8c9e 100644
--- a/security/rkp/aidl/vts/functional/Android.bp
+++ b/security/rkp/aidl/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_hardware_backed_security",
     // See: http://go/android-license-faq
     default_applicable_licenses: ["hardware_interfaces_license"],
 }
diff --git a/security/rkp/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp b/security/rkp/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
index f68ff91..8f918af 100644
--- a/security/rkp/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
+++ b/security/rkp/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
@@ -55,10 +55,7 @@
 
 constexpr uint8_t MIN_CHALLENGE_SIZE = 0;
 constexpr uint8_t MAX_CHALLENGE_SIZE = 64;
-const string DEFAULT_INSTANCE_NAME =
-        "android.hardware.security.keymint.IRemotelyProvisionedComponent/default";
-const string RKP_VM_INSTANCE_NAME =
-        "android.hardware.security.keymint.IRemotelyProvisionedComponent/avf";
+
 const string KEYMINT_STRONGBOX_INSTANCE_NAME =
         "android.hardware.security.keymint.IKeyMintDevice/strongbox";
 
@@ -188,7 +185,7 @@
         }
         ASSERT_NE(provisionable_, nullptr);
         auto status = provisionable_->getHardwareInfo(&rpcHardwareInfo);
-        isRkpVmInstance_ = GetParam() == RKP_VM_INSTANCE_NAME;
+        isRkpVmInstance_ = GetParam() == RKPVM_INSTANCE_NAME;
         if (isRkpVmInstance_) {
             if (status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
                 GTEST_SKIP() << "The RKP VM is not supported on this system.";
@@ -227,7 +224,7 @@
 
         RpcHardwareInfo hwInfo;
         auto status = rpc->getHardwareInfo(&hwInfo);
-        if (hal == RKP_VM_INSTANCE_NAME && status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
+        if (hal == RKPVM_INSTANCE_NAME && status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
             GTEST_SKIP() << "The RKP VM is not supported on this system.";
         }
         ASSERT_TRUE(status.isOk());
@@ -268,7 +265,7 @@
     auto status = rpc->generateCertificateRequestV2({} /* keysToSign */, challenge, &csr);
     EXPECT_TRUE(status.isOk()) << status.getDescription();
 
-    auto result = isCsrWithProperDiceChain(csr);
+    auto result = isCsrWithProperDiceChain(csr, DEFAULT_INSTANCE_NAME);
     ASSERT_TRUE(result) << result.message();
     ASSERT_TRUE(*result);
 }
@@ -494,7 +491,7 @@
 
         auto result = verifyProductionProtectedData(
                 deviceInfo, cppbor::Array(), keysToSignMac, protectedData, testEekChain_, eekId_,
-                rpcHardwareInfo.supportedEekCurve, provisionable_.get(), challenge_);
+                rpcHardwareInfo.supportedEekCurve, provisionable_.get(), GetParam(), challenge_);
         ASSERT_TRUE(result) << result.message();
     }
 }
@@ -517,9 +514,10 @@
             &protectedData, &keysToSignMac);
     ASSERT_TRUE(status.isOk()) << status.getDescription();
 
-    auto firstBcc = verifyProductionProtectedData(
-            deviceInfo, /*keysToSign=*/cppbor::Array(), keysToSignMac, protectedData, testEekChain_,
-            eekId_, rpcHardwareInfo.supportedEekCurve, provisionable_.get(), challenge_);
+    auto firstBcc = verifyProductionProtectedData(deviceInfo, /*keysToSign=*/cppbor::Array(),
+                                                  keysToSignMac, protectedData, testEekChain_,
+                                                  eekId_, rpcHardwareInfo.supportedEekCurve,
+                                                  provisionable_.get(), GetParam(), challenge_);
     ASSERT_TRUE(firstBcc) << firstBcc.message();
 
     status = provisionable_->generateCertificateRequest(
@@ -527,9 +525,10 @@
             &protectedData, &keysToSignMac);
     ASSERT_TRUE(status.isOk()) << status.getDescription();
 
-    auto secondBcc = verifyProductionProtectedData(
-            deviceInfo, /*keysToSign=*/cppbor::Array(), keysToSignMac, protectedData, testEekChain_,
-            eekId_, rpcHardwareInfo.supportedEekCurve, provisionable_.get(), challenge_);
+    auto secondBcc = verifyProductionProtectedData(deviceInfo, /*keysToSign=*/cppbor::Array(),
+                                                   keysToSignMac, protectedData, testEekChain_,
+                                                   eekId_, rpcHardwareInfo.supportedEekCurve,
+                                                   provisionable_.get(), GetParam(), challenge_);
     ASSERT_TRUE(secondBcc) << secondBcc.message();
 
     // Verify that none of the keys in the first BCC are repeated in the second one.
@@ -579,7 +578,7 @@
 
         auto result = verifyProductionProtectedData(
                 deviceInfo, cborKeysToSign_, keysToSignMac, protectedData, testEekChain_, eekId_,
-                rpcHardwareInfo.supportedEekCurve, provisionable_.get(), challenge_);
+                rpcHardwareInfo.supportedEekCurve, provisionable_.get(), GetParam(), challenge_);
         ASSERT_TRUE(result) << result.message();
     }
 }
@@ -767,8 +766,8 @@
                 provisionable_->generateCertificateRequestV2({} /* keysToSign */, challenge, &csr);
         ASSERT_TRUE(status.isOk()) << status.getDescription();
 
-        auto result = verifyProductionCsr(cppbor::Array(), csr, provisionable_.get(), challenge,
-                                          isRkpVmInstance_);
+        auto result = verifyProductionCsr(cppbor::Array(), csr, provisionable_.get(), GetParam(),
+                                          challenge, isRkpVmInstance_);
         ASSERT_TRUE(result) << result.message();
     }
 }
@@ -789,8 +788,8 @@
         auto status = provisionable_->generateCertificateRequestV2(keysToSign_, challenge, &csr);
         ASSERT_TRUE(status.isOk()) << status.getDescription();
 
-        auto result = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), challenge,
-                                          isRkpVmInstance_);
+        auto result = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), GetParam(),
+                                          challenge, isRkpVmInstance_);
         ASSERT_TRUE(result) << result.message();
     }
 }
@@ -820,15 +819,15 @@
     auto status = provisionable_->generateCertificateRequestV2(keysToSign_, challenge_, &csr);
     ASSERT_TRUE(status.isOk()) << status.getDescription();
 
-    auto firstCsr = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), challenge_,
-                                        isRkpVmInstance_);
+    auto firstCsr = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), GetParam(),
+                                        challenge_, isRkpVmInstance_);
     ASSERT_TRUE(firstCsr) << firstCsr.message();
 
     status = provisionable_->generateCertificateRequestV2(keysToSign_, challenge_, &csr);
     ASSERT_TRUE(status.isOk()) << status.getDescription();
 
-    auto secondCsr = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), challenge_,
-                                         isRkpVmInstance_);
+    auto secondCsr = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), GetParam(),
+                                         challenge_, isRkpVmInstance_);
     ASSERT_TRUE(secondCsr) << secondCsr.message();
 
     ASSERT_EQ(**firstCsr, **secondCsr);
@@ -846,8 +845,8 @@
     auto status = provisionable_->generateCertificateRequestV2(keysToSign_, challenge_, &csr);
     ASSERT_TRUE(status.isOk()) << status.getDescription();
 
-    auto result = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), challenge_,
-                                      isRkpVmInstance_);
+    auto result = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), GetParam(),
+                                      challenge_, isRkpVmInstance_);
     ASSERT_TRUE(result) << result.message();
 }
 
@@ -977,7 +976,8 @@
             provisionable_->generateCertificateRequestV2({} /* keysToSign */, challenge_, &csr);
     ASSERT_TRUE(irpcStatus.isOk()) << irpcStatus.getDescription();
 
-    auto result = verifyProductionCsr(cppbor::Array(), csr, provisionable_.get(), challenge_);
+    auto result =
+            verifyProductionCsr(cppbor::Array(), csr, provisionable_.get(), GetParam(), challenge_);
     ASSERT_TRUE(result) << result.message();
 
     std::unique_ptr<cppbor::Array> csrPayload = std::move(*result);
diff --git a/security/secureclock/aidl/Android.bp b/security/secureclock/aidl/Android.bp
index 853ad89..d7e7b43 100644
--- a/security/secureclock/aidl/Android.bp
+++ b/security/secureclock/aidl/Android.bp
@@ -10,6 +10,7 @@
 aidl_interface {
     name: "android.hardware.security.secureclock",
     vendor_available: true,
+    frozen: true,
     srcs: [
         "android/hardware/security/secureclock/*.aidl",
     ],
diff --git a/security/secureclock/aidl/vts/functional/Android.bp b/security/secureclock/aidl/vts/functional/Android.bp
index a34668b..4e54561 100644
--- a/security/secureclock/aidl/vts/functional/Android.bp
+++ b/security/secureclock/aidl/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_hardware_backed_security",
     // 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"
diff --git a/security/sharedsecret/aidl/Android.bp b/security/sharedsecret/aidl/Android.bp
index fe77c10..adf33d3 100644
--- a/security/sharedsecret/aidl/Android.bp
+++ b/security/sharedsecret/aidl/Android.bp
@@ -10,6 +10,7 @@
 aidl_interface {
     name: "android.hardware.security.sharedsecret",
     vendor_available: true,
+    frozen: true,
     srcs: [
         "android/hardware/security/sharedsecret/*.aidl",
     ],
diff --git a/security/sharedsecret/aidl/vts/functional/Android.bp b/security/sharedsecret/aidl/vts/functional/Android.bp
index 1f0f6a6..eedd325 100644
--- a/security/sharedsecret/aidl/vts/functional/Android.bp
+++ b/security/sharedsecret/aidl/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_hardware_backed_security",
     // 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"
diff --git a/soundtrigger/2.0/vts/functional/Android.bp b/soundtrigger/2.0/vts/functional/Android.bp
index 403fa9b..dde1aa1 100644
--- a/soundtrigger/2.0/vts/functional/Android.bp
+++ b/soundtrigger/2.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_media_audio_framework",
     // 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"
diff --git a/soundtrigger/2.1/vts/functional/Android.bp b/soundtrigger/2.1/vts/functional/Android.bp
index b013350..3e475e6 100644
--- a/soundtrigger/2.1/vts/functional/Android.bp
+++ b/soundtrigger/2.1/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_media_audio_framework",
     // 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"
diff --git a/soundtrigger/2.2/vts/functional/Android.bp b/soundtrigger/2.2/vts/functional/Android.bp
index faf6d58..3502545 100644
--- a/soundtrigger/2.2/vts/functional/Android.bp
+++ b/soundtrigger/2.2/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_media_audio_framework",
     // 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"
diff --git a/soundtrigger/2.3/vts/functional/Android.bp b/soundtrigger/2.3/vts/functional/Android.bp
index e613db5..23cbe85 100644
--- a/soundtrigger/2.3/vts/functional/Android.bp
+++ b/soundtrigger/2.3/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_media_audio_framework",
     // 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"
diff --git a/tests/libhwbinder/aidl/android/tests/binder/IBenchmark.aidl b/tests/libhwbinder/aidl/android/tests/binder/IBenchmark.aidl
index be91fb9..bc44e95 100644
--- a/tests/libhwbinder/aidl/android/tests/binder/IBenchmark.aidl
+++ b/tests/libhwbinder/aidl/android/tests/binder/IBenchmark.aidl
@@ -1,5 +1,6 @@
 package android.tests.binder;
 
 interface IBenchmark {
-  byte[] sendVec(in byte[] data);
-}
\ No newline at end of file
+    byte[] sendVec(in byte[] data);
+    IBinder[] sendBinderVec(in IBinder[] data);
+}
diff --git a/threadnetwork/aidl/vts/VtsHalThreadNetworkTargetTest.xml b/threadnetwork/aidl/vts/VtsHalThreadNetworkTargetTest.xml
index 0525876..b5eb843 100644
--- a/threadnetwork/aidl/vts/VtsHalThreadNetworkTargetTest.xml
+++ b/threadnetwork/aidl/vts/VtsHalThreadNetworkTargetTest.xml
@@ -13,11 +13,12 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
+
 <configuration description="Runs VtsHalThreadNetworkTargetTest.">
     <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
-        <option name="run-command" value="cmd thread_network force-stop-ot-daemon enabled" />
+        <option name="run-command" value="if pm list features |grep 'android.hardware.thread_network'; then cmd thread_network force-stop-ot-daemon enabled; fi" />
         <option name="run-command" value="cmd bluetooth_manager enable" />
-        <option name="teardown-command" value="cmd thread_network force-stop-ot-daemon disabled" />
+        <option name="teardown-command" value="if pm list features |grep 'android.hardware.thread_network'; then cmd thread_network force-stop-ot-daemon disabled; fi" />
     </target_preparer>
     <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
         <option name="cleanup" value="true" />
diff --git a/uwb/aidl/Android.bp b/uwb/aidl/Android.bp
index abd6a23..655d8a2 100755
--- a/uwb/aidl/Android.bp
+++ b/uwb/aidl/Android.bp
@@ -16,6 +16,7 @@
     srcs: ["android/hardware/uwb/*.aidl"],
     stability: "vintf",
     host_supported: true,
+    frozen: true,
     backend: {
         java: {
             sdk_version: "module_Tiramisu",
@@ -56,6 +57,7 @@
     vendor_available: true,
     srcs: ["android/hardware/uwb/fira_android/*.aidl"],
     stability: "vintf",
+    frozen: false,
     backend: {
         java: {
             sdk_version: "module_Tiramisu",
diff --git a/vibrator/1.0/vts/functional/Android.bp b/vibrator/1.0/vts/functional/Android.bp
index 83377e7..c62dc42 100644
--- a/vibrator/1.0/vts/functional/Android.bp
+++ b/vibrator/1.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_haptics_framework",
     // 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"
diff --git a/vibrator/1.1/vts/functional/Android.bp b/vibrator/1.1/vts/functional/Android.bp
index f97a343..c7dadc5 100644
--- a/vibrator/1.1/vts/functional/Android.bp
+++ b/vibrator/1.1/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_haptics_framework",
     // 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"
diff --git a/vibrator/1.2/vts/functional/Android.bp b/vibrator/1.2/vts/functional/Android.bp
index 40171ae..4d5de1f 100644
--- a/vibrator/1.2/vts/functional/Android.bp
+++ b/vibrator/1.2/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_haptics_framework",
     // 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"
diff --git a/vibrator/1.3/vts/functional/Android.bp b/vibrator/1.3/vts/functional/Android.bp
index 0fcbf07..3221fa2 100644
--- a/vibrator/1.3/vts/functional/Android.bp
+++ b/vibrator/1.3/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_haptics_framework",
     // 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"
diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/CompositePwleV2.aidl
similarity index 94%
copy from vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl
copy to vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/CompositePwleV2.aidl
index a5eda52..de0bdb5 100644
--- a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl
+++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/CompositePwleV2.aidl
@@ -33,7 +33,6 @@
 
 package android.hardware.vibrator;
 @VintfStability
-parcelable PwleV2OutputMapEntry {
-  float frequencyHz;
-  float maxOutputAccelerationGs;
+parcelable CompositePwleV2 {
+  android.hardware.vibrator.PwleV2Primitive[] pwlePrimitives;
 }
diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/FrequencyAccelerationMapEntry.aidl
similarity index 97%
rename from vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl
rename to vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/FrequencyAccelerationMapEntry.aidl
index a5eda52..e6743f9 100644
--- a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl
+++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/FrequencyAccelerationMapEntry.aidl
@@ -33,7 +33,7 @@
 
 package android.hardware.vibrator;
 @VintfStability
-parcelable PwleV2OutputMapEntry {
+parcelable FrequencyAccelerationMapEntry {
   float frequencyHz;
   float maxOutputAccelerationGs;
 }
diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibrator.aidl b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibrator.aidl
index 0dcc657..9fad952 100644
--- a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibrator.aidl
+++ b/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/IVibrator.aidl
@@ -51,19 +51,40 @@
   void alwaysOnDisable(in int id);
   float getResonantFrequency();
   float getQFactor();
+  /**
+   * @deprecated This method is deprecated from AIDL v3 and is no longer required to be implemented even if CAP_FREQUENCY_CONTROL capability is reported.
+   */
   float getFrequencyResolution();
+  /**
+   * @deprecated This method is deprecated from AIDL v3 and is no longer required to be implemented even if CAP_FREQUENCY_CONTROL capability is reported.
+   */
   float getFrequencyMinimum();
+  /**
+   * @deprecated This method is deprecated from AIDL v3 and is no longer required to be implemented even if CAP_FREQUENCY_CONTROL capability is reported.
+   */
   float[] getBandwidthAmplitudeMap();
+  /**
+   * @deprecated This method is deprecated from AIDL v3 and is no longer required to be implemented. Use `IVibrator.getPwleV2PrimitiveDurationMaxMillis` instead.
+   */
   int getPwlePrimitiveDurationMax();
+  /**
+   * @deprecated This method is deprecated from AIDL v3 and is no longer required to be implemented. Use `IVibrator.getPwleV2CompositionSizeMax` instead.
+   */
   int getPwleCompositionSizeMax();
+  /**
+   * @deprecated This method is deprecated from AIDL v3 and is no longer required to be implemented.
+   */
   android.hardware.vibrator.Braking[] getSupportedBraking();
+  /**
+   * @deprecated This method is deprecated from AIDL v3 and is no longer required to be implemented. Use `IVibrator.composePwleV2` instead.
+   */
   void composePwle(in android.hardware.vibrator.PrimitivePwle[] composite, in android.hardware.vibrator.IVibratorCallback callback);
   void performVendorEffect(in android.hardware.vibrator.VendorEffect vendorEffect, in android.hardware.vibrator.IVibratorCallback callback);
-  List<android.hardware.vibrator.PwleV2OutputMapEntry> getPwleV2FrequencyToOutputAccelerationMap();
+  List<android.hardware.vibrator.FrequencyAccelerationMapEntry> getFrequencyToOutputAccelerationMap();
   int getPwleV2PrimitiveDurationMaxMillis();
   int getPwleV2CompositionSizeMax();
   int getPwleV2PrimitiveDurationMinMillis();
-  void composePwleV2(in android.hardware.vibrator.PwleV2Primitive[] composite, in android.hardware.vibrator.IVibratorCallback callback);
+  void composePwleV2(in android.hardware.vibrator.CompositePwleV2 composite, in android.hardware.vibrator.IVibratorCallback callback);
   const int CAP_ON_CALLBACK = (1 << 0) /* 1 */;
   const int CAP_PERFORM_CALLBACK = (1 << 1) /* 2 */;
   const int CAP_AMPLITUDE_CONTROL = (1 << 2) /* 4 */;
diff --git a/vibrator/aidl/android/hardware/vibrator/CompositePwleV2.aidl b/vibrator/aidl/android/hardware/vibrator/CompositePwleV2.aidl
new file mode 100644
index 0000000..9662ca0
--- /dev/null
+++ b/vibrator/aidl/android/hardware/vibrator/CompositePwleV2.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.vibrator;
+
+import android.hardware.vibrator.PwleV2Primitive;
+
+@VintfStability
+parcelable CompositePwleV2 {
+    /**
+     * An array of primitives that represents the PWLE effect
+     */
+    PwleV2Primitive[] pwlePrimitives;
+}
diff --git a/vibrator/aidl/android/hardware/vibrator/PwleV2OutputMapEntry.aidl b/vibrator/aidl/android/hardware/vibrator/FrequencyAccelerationMapEntry.aidl
similarity index 96%
rename from vibrator/aidl/android/hardware/vibrator/PwleV2OutputMapEntry.aidl
rename to vibrator/aidl/android/hardware/vibrator/FrequencyAccelerationMapEntry.aidl
index a8db87c..470dc80 100644
--- a/vibrator/aidl/android/hardware/vibrator/PwleV2OutputMapEntry.aidl
+++ b/vibrator/aidl/android/hardware/vibrator/FrequencyAccelerationMapEntry.aidl
@@ -17,7 +17,7 @@
 package android.hardware.vibrator;
 
 @VintfStability
-parcelable PwleV2OutputMapEntry {
+parcelable FrequencyAccelerationMapEntry {
     /**
      * Absolute frequency point in the units of hertz
      *
diff --git a/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl b/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl
index 11f36ba..a2f0017 100644
--- a/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl
+++ b/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl
@@ -19,12 +19,12 @@
 import android.hardware.vibrator.Braking;
 import android.hardware.vibrator.CompositeEffect;
 import android.hardware.vibrator.CompositePrimitive;
+import android.hardware.vibrator.CompositePwleV2;
 import android.hardware.vibrator.Effect;
 import android.hardware.vibrator.EffectStrength;
+import android.hardware.vibrator.FrequencyAccelerationMapEntry;
 import android.hardware.vibrator.IVibratorCallback;
 import android.hardware.vibrator.PrimitivePwle;
-import android.hardware.vibrator.PwleV2OutputMapEntry;
-import android.hardware.vibrator.PwleV2Primitive;
 import android.hardware.vibrator.VendorEffect;
 
 @VintfStability
@@ -290,6 +290,8 @@
      *
      * @return The frequency resolution of the bandwidth amplitude map.
      *         Non-zero value if supported, or value should be ignored if not supported.
+     * @deprecated This method is deprecated from AIDL v3 and is no longer required to be
+     * implemented even if CAP_FREQUENCY_CONTROL capability is reported.
      */
     float getFrequencyResolution();
 
@@ -301,6 +303,8 @@
      *
      * @return The minimum frequency allowed. Non-zero value if supported,
      *         or value should be ignored if not supported.
+     * @deprecated This method is deprecated from AIDL v3 and is no longer required to be
+     * implemented even if CAP_FREQUENCY_CONTROL capability is reported.
      */
     float getFrequencyMinimum();
 
@@ -322,6 +326,8 @@
      *
      * @return The maximum output acceleration amplitude for each supported frequency,
      *         starting at getMinimumFrequency()
+     * @deprecated This method is deprecated from AIDL v3 and is no longer required to be
+     * implemented even if CAP_FREQUENCY_CONTROL capability is reported.
      */
     float[] getBandwidthAmplitudeMap();
 
@@ -333,6 +339,8 @@
      *
      * @return The maximum duration allowed for a single PrimitivePwle.
      *         Non-zero value if supported, or value should be ignored if not supported.
+     * @deprecated This method is deprecated from AIDL v3 and is no longer required to be
+     * implemented. Use `IVibrator.getPwleV2PrimitiveDurationMaxMillis` instead.
      */
     int getPwlePrimitiveDurationMax();
 
@@ -344,6 +352,8 @@
      *
      * @return The maximum count allowed. Non-zero value if supported,
      *         or value should be ignored if not supported.
+     * @deprecated This method is deprecated from AIDL v3 and is no longer required to be
+     * implemented. Use `IVibrator.getPwleV2CompositionSizeMax` instead.
      */
     int getPwleCompositionSizeMax();
 
@@ -355,6 +365,8 @@
      * Implementations are optional but encouraged if available.
      *
      * @return The braking mechanisms which are supported by the composePwle API.
+     * @deprecated This method is deprecated from AIDL v3 and is no longer required to be
+     * implemented.
      */
     Braking[] getSupportedBraking();
 
@@ -368,6 +380,8 @@
      * explicitly call off. IVibratorCallback.onComplete() support is required for this API.
      *
      * @param composite Array of PWLEs.
+     * @deprecated This method is deprecated from AIDL v3 and is no longer required to be
+     * implemented. Use `IVibrator.composePwleV2` instead.
      */
     void composePwle(in PrimitivePwle[] composite, in IVibratorCallback callback);
 
@@ -396,12 +410,12 @@
      * Retrieves a mapping of vibration frequency (Hz) to the maximum achievable output
      * acceleration (Gs) the device can reach at that frequency.
      *
-     * The map, represented as a list of `PwleV2OutputMapEntry` (frequency, output acceleration)
-     * pairs, defines the device's frequency response. The platform uses the minimum and maximum
-     * frequency values to determine the supported input range for `IVibrator.composePwleV2`.
-     * Output acceleration values are used to identify a frequency range suitable to safely play
-     * perceivable vibrations with a simple API. The map is also exposed for developers using an
-     * advanced API.
+     * The map, represented as a list of `FrequencyAccelerationMapEntry` (frequency, output
+     * acceleration) pairs, defines the device's frequency response. The platform uses the minimum
+     * and maximum frequency values to determine the supported input range for
+     * `IVibrator.composePwleV2`. Output acceleration values are used to identify a frequency range
+     * suitable to safely play perceivable vibrations with a simple API. The map is also exposed for
+     * developers using an advanced API.
      *
      * The platform does not impose specific requirements on map resolution which can vary
      * depending on the shape of device output curve. The values will be linearly interpolated
@@ -410,7 +424,7 @@
      *
      *
      * This may not be supported and this support is reflected in getCapabilities
-     * (CAP_COMPOSE_PWLE_EFFECTS_V2). If this is supported, it's expected to be non-empty and
+     * (CAP_FREQUENCY_CONTROL). If this is supported, it's expected to be non-empty and
      * describe a valid non-empty frequency range where the simple API can be defined
      * (i.e. a range where the output acceleration is always above 10 db SL).
      *
@@ -418,7 +432,7 @@
      *         mapping.
      * @throws EX_UNSUPPORTED_OPERATION if unsupported, as reflected by getCapabilities.
      */
-    List<PwleV2OutputMapEntry> getPwleV2FrequencyToOutputAccelerationMap();
+    List<FrequencyAccelerationMapEntry> getFrequencyToOutputAccelerationMap();
 
     /**
      * Retrieve the maximum duration allowed for any primitive PWLE in units of
@@ -436,8 +450,8 @@
      * Retrieve the maximum number of PWLE primitives input supported by IVibrator.composePwleV2.
      *
      * This may not be supported and this support is reflected in
-     * getCapabilities (CAP_COMPOSE_PWLE_EFFECTS_V2). Devices supporting PWLE effects must
-     * support effects with at least 16 PwleV2Primitive.
+     * getCapabilities (CAP_COMPOSE_PWLE_EFFECTS_V2). Devices supporting
+     * PWLE effects must support effects with at least 16 PwleV2Primitive.
      *
      * @return The maximum count allowed. Non-zero value if supported.
      * @throws EX_UNSUPPORTED_OPERATION if unsupported, as reflected by getCapabilities.
@@ -463,10 +477,14 @@
      * This may not be supported and this support is reflected in
      * getCapabilities (CAP_COMPOSE_PWLE_EFFECTS_V2).
      *
+     * Note: Devices reporting CAP_COMPOSE_PWLE_EFFECTS_V2 support MUST also have the
+     * CAP_FREQUENCY_CONTROL capability and provide a valid frequency to output acceleration map.
+     *
      * Doing this operation while the vibrator is already on is undefined behavior. Clients should
      * explicitly call off. IVibratorCallback.onComplete() support is required for this API.
      *
-     * @param composite An array of primitives that represents a PWLE (Piecewise-Linear Envelope).
+     * @param composite A CompositePwleV2 representing a composite vibration effect, composed of an
+     *                  array of primitives that define the PWLE (Piecewise-Linear Envelope).
      */
-    void composePwleV2(in PwleV2Primitive[] composite, in IVibratorCallback callback);
+    void composePwleV2(in CompositePwleV2 composite, in IVibratorCallback callback);
 }
diff --git a/vibrator/aidl/android/hardware/vibrator/PwleV2Primitive.aidl b/vibrator/aidl/android/hardware/vibrator/PwleV2Primitive.aidl
index bd7bec6..1ad1a9f 100644
--- a/vibrator/aidl/android/hardware/vibrator/PwleV2Primitive.aidl
+++ b/vibrator/aidl/android/hardware/vibrator/PwleV2Primitive.aidl
@@ -21,7 +21,7 @@
     /**
      * Input amplitude ranges from 0.0 (inclusive) to 1.0 (inclusive), representing the relative
      * input value. Actual output acceleration depends on frequency and device response curve
-     * (see IVibrator.getPwleV2FrequencyToOutputAccelerationMap for max values).
+     * (see IVibrator.getFrequencyToOutputAccelerationMap for max values).
      *
      * Input amplitude linearly maps to output acceleration (e.g., 0.5 amplitude yields half the
      * max acceleration for that frequency).
@@ -36,7 +36,7 @@
      * Absolute frequency point in the units of hertz
      *
      * Values are within the continuous inclusive frequency range defined by
-     * IVibrator#getPwleV2FrequencyToOutputAccelerationMap.
+     * IVibrator#getFrequencyToOutputAccelerationMap.
      */
     float frequencyHz;
 
diff --git a/vibrator/aidl/default/Vibrator.cpp b/vibrator/aidl/default/Vibrator.cpp
index 34be008..165a3bf 100644
--- a/vibrator/aidl/default/Vibrator.cpp
+++ b/vibrator/aidl/default/Vibrator.cpp
@@ -494,9 +494,17 @@
     return ndk::ScopedAStatus::ok();
 }
 
-ndk::ScopedAStatus Vibrator::getPwleV2FrequencyToOutputAccelerationMap(
-        std::vector<PwleV2OutputMapEntry>* _aidl_return) {
-    std::vector<PwleV2OutputMapEntry> frequencyToOutputAccelerationMap;
+ndk::ScopedAStatus Vibrator::getFrequencyToOutputAccelerationMap(
+        std::vector<FrequencyAccelerationMapEntry>* _aidl_return) {
+    int32_t capabilities = 0;
+    if (!getCapabilities(&capabilities).isOk()) {
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+    }
+    if (!(capabilities & IVibrator::CAP_FREQUENCY_CONTROL)) {
+        return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
+    }
+
+    std::vector<FrequencyAccelerationMapEntry> frequencyToOutputAccelerationMap;
 
     std::vector<std::pair<float, float>> frequencyToOutputAccelerationData = {
             {30.0f, 0.01f},  {46.0f, 0.09f},  {50.0f, 0.1f},   {55.0f, 0.12f},  {62.0f, 0.66f},
@@ -507,8 +515,8 @@
             {263.0f, 1.39f}, {65.0f, 1.38f},  {278.0f, 1.37f}, {294.0f, 1.35f}, {300.0f, 1.34f}};
     for (const auto& entry : frequencyToOutputAccelerationData) {
         frequencyToOutputAccelerationMap.push_back(
-                PwleV2OutputMapEntry(/*frequency=*/entry.first,
-                                     /*maxOutputAcceleration=*/entry.second));
+                FrequencyAccelerationMapEntry(/*frequency=*/entry.first,
+                                              /*maxOutputAcceleration=*/entry.second));
     }
 
     *_aidl_return = frequencyToOutputAccelerationMap;
@@ -531,7 +539,8 @@
     return ndk::ScopedAStatus::ok();
 }
 
-float getPwleV2FrequencyMinHz(std::vector<PwleV2OutputMapEntry> frequencyToOutputAccelerationMap) {
+float getPwleV2FrequencyMinHz(
+        std::vector<FrequencyAccelerationMapEntry> frequencyToOutputAccelerationMap) {
     if (frequencyToOutputAccelerationMap.empty()) {
         return 0.0f;
     }
@@ -547,7 +556,8 @@
     return minFrequency;
 }
 
-float getPwleV2FrequencyMaxHz(std::vector<PwleV2OutputMapEntry> frequencyToOutputAccelerationMap) {
+float getPwleV2FrequencyMaxHz(
+        std::vector<FrequencyAccelerationMapEntry> frequencyToOutputAccelerationMap) {
     if (frequencyToOutputAccelerationMap.empty()) {
         return 0.0f;
     }
@@ -563,30 +573,31 @@
     return maxFrequency;
 }
 
-ndk::ScopedAStatus Vibrator::composePwleV2(const std::vector<PwleV2Primitive>& composite,
+ndk::ScopedAStatus Vibrator::composePwleV2(const CompositePwleV2& composite,
                                            const std::shared_ptr<IVibratorCallback>& callback) {
     LOG(VERBOSE) << "Vibrator compose PWLE V2";
     int32_t capabilities = 0;
     if (!getCapabilities(&capabilities).isOk()) {
         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
     }
-    if ((capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS_V2) == 0) {
+    if (!(capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS_V2) ||
+        !(capabilities & IVibrator::CAP_FREQUENCY_CONTROL)) {
         return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
     }
 
     int compositionSizeMax;
     getPwleV2CompositionSizeMax(&compositionSizeMax);
-    if (composite.size() <= 0 || composite.size() > compositionSizeMax) {
+    if (composite.pwlePrimitives.empty() || composite.pwlePrimitives.size() > compositionSizeMax) {
         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
     }
 
     int32_t totalEffectDuration = 0;
-    std::vector<PwleV2OutputMapEntry> frequencyToOutputAccelerationMap;
-    getPwleV2FrequencyToOutputAccelerationMap(&frequencyToOutputAccelerationMap);
+    std::vector<FrequencyAccelerationMapEntry> frequencyToOutputAccelerationMap;
+    getFrequencyToOutputAccelerationMap(&frequencyToOutputAccelerationMap);
     float minFrequency = getPwleV2FrequencyMinHz(frequencyToOutputAccelerationMap);
     float maxFrequency = getPwleV2FrequencyMaxHz(frequencyToOutputAccelerationMap);
 
-    for (auto& e : composite) {
+    for (auto& e : composite.pwlePrimitives) {
         if (e.timeMillis < 0.0f || e.timeMillis > COMPOSE_PWLE_V2_PRIMITIVE_DURATION_MAX_MS) {
             return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
         }
diff --git a/vibrator/aidl/default/include/vibrator-impl/Vibrator.h b/vibrator/aidl/default/include/vibrator-impl/Vibrator.h
index 4637c5a..354ba46 100644
--- a/vibrator/aidl/default/include/vibrator-impl/Vibrator.h
+++ b/vibrator/aidl/default/include/vibrator-impl/Vibrator.h
@@ -59,12 +59,12 @@
     ndk::ScopedAStatus getSupportedBraking(std::vector<Braking>* supported) override;
     ndk::ScopedAStatus composePwle(const std::vector<PrimitivePwle> &composite,
                                    const std::shared_ptr<IVibratorCallback> &callback) override;
-    ndk::ScopedAStatus getPwleV2FrequencyToOutputAccelerationMap(
-            std::vector<PwleV2OutputMapEntry>* _aidl_return) override;
+    ndk::ScopedAStatus getFrequencyToOutputAccelerationMap(
+            std::vector<FrequencyAccelerationMapEntry>* _aidl_return) override;
     ndk::ScopedAStatus getPwleV2PrimitiveDurationMaxMillis(int32_t* maxDurationMs) override;
     ndk::ScopedAStatus getPwleV2PrimitiveDurationMinMillis(int32_t* minDurationMs) override;
     ndk::ScopedAStatus getPwleV2CompositionSizeMax(int32_t* maxSize) override;
-    ndk::ScopedAStatus composePwleV2(const std::vector<PwleV2Primitive>& composite,
+    ndk::ScopedAStatus composePwleV2(const CompositePwleV2& composite,
                                      const std::shared_ptr<IVibratorCallback>& callback) override;
 
     void setGlobalVibrationCallback(const std::shared_ptr<IVibratorCallback>& callback);
diff --git a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
index bc017ae..03ecb1a 100644
--- a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
+++ b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
@@ -41,12 +41,13 @@
 using aidl::android::hardware::vibrator::BrakingPwle;
 using aidl::android::hardware::vibrator::CompositeEffect;
 using aidl::android::hardware::vibrator::CompositePrimitive;
+using aidl::android::hardware::vibrator::CompositePwleV2;
 using aidl::android::hardware::vibrator::Effect;
 using aidl::android::hardware::vibrator::EffectStrength;
+using aidl::android::hardware::vibrator::FrequencyAccelerationMapEntry;
 using aidl::android::hardware::vibrator::IVibrator;
 using aidl::android::hardware::vibrator::IVibratorManager;
 using aidl::android::hardware::vibrator::PrimitivePwle;
-using aidl::android::hardware::vibrator::PwleV2OutputMapEntry;
 using aidl::android::hardware::vibrator::PwleV2Primitive;
 using aidl::android::hardware::vibrator::VendorEffect;
 using aidl::android::os::PersistableBundle;
@@ -175,11 +176,23 @@
     return resonantFrequencyHz;
 }
 
+static bool shouldValidateLegacyFrequencyControlResult(int32_t capabilities, int32_t version,
+                                                       ndk::ScopedAStatus& status) {
+    bool hasFrequencyControl = capabilities & IVibrator::CAP_FREQUENCY_CONTROL;
+    // Legacy frequency control APIs deprecated with PWLE V2 feature.
+    bool isDeprecated = version >= PWLE_V2_MIN_VERSION;
+    bool isUnknownOrUnsupported = status.getExceptionCode() == EX_UNSUPPORTED_OPERATION ||
+                                  status.getStatus() == STATUS_UNKNOWN_TRANSACTION;
+
+    // Validate if older HAL or if result is provided, even after deprecation.
+    return hasFrequencyControl && (!isDeprecated || !isUnknownOrUnsupported);
+}
+
 static float getFrequencyResolutionHz(const std::shared_ptr<IVibrator>& vibrator,
-                                      int32_t capabilities) {
-    float freqResolutionHz;
+                                      int32_t capabilities, int32_t version) {
+    float freqResolutionHz = -1;
     ndk::ScopedAStatus status = vibrator->getFrequencyResolution(&freqResolutionHz);
-    if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) {
+    if (shouldValidateLegacyFrequencyControlResult(capabilities, version, status)) {
         EXPECT_OK(std::move(status));
         EXPECT_GT(freqResolutionHz, 0);
     } else {
@@ -188,11 +201,11 @@
     return freqResolutionHz;
 }
 
-static float getFrequencyMinimumHz(const std::shared_ptr<IVibrator>& vibrator,
-                                   int32_t capabilities) {
+static float getFrequencyMinimumHz(const std::shared_ptr<IVibrator>& vibrator, int32_t capabilities,
+                                   int32_t version) {
     float freqMinimumHz;
     ndk::ScopedAStatus status = vibrator->getFrequencyMinimum(&freqMinimumHz);
-    if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) {
+    if (shouldValidateLegacyFrequencyControlResult(capabilities, version, status)) {
         EXPECT_OK(std::move(status));
 
         float resonantFrequencyHz = getResonantFrequencyHz(vibrator, capabilities);
@@ -205,19 +218,19 @@
     return freqMinimumHz;
 }
 
-static float getFrequencyMaximumHz(const std::shared_ptr<IVibrator>& vibrator,
-                                   int32_t capabilities) {
+static float getFrequencyMaximumHz(const std::shared_ptr<IVibrator>& vibrator, int32_t capabilities,
+                                   int32_t version) {
     std::vector<float> bandwidthAmplitudeMap;
     ndk::ScopedAStatus status = vibrator->getBandwidthAmplitudeMap(&bandwidthAmplitudeMap);
-    if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) {
+    if (shouldValidateLegacyFrequencyControlResult(capabilities, version, status)) {
         EXPECT_OK(std::move(status));
     } else {
         EXPECT_UNKNOWN_OR_UNSUPPORTED(std::move(status));
     }
 
     float freqMaximumHz = ((bandwidthAmplitudeMap.size() - 1) *
-                           getFrequencyResolutionHz(vibrator, capabilities)) +
-                          getFrequencyMinimumHz(vibrator, capabilities);
+                           getFrequencyResolutionHz(vibrator, capabilities, version)) +
+                          getFrequencyMinimumHz(vibrator, capabilities, version);
     return freqMaximumHz;
 }
 
@@ -230,12 +243,16 @@
 }
 
 static ActivePwle composeValidActivePwle(const std::shared_ptr<IVibrator>& vibrator,
-                                         int32_t capabilities) {
+                                         int32_t capabilities, int32_t version) {
     float frequencyHz;
     if (capabilities & IVibrator::CAP_GET_RESONANT_FREQUENCY) {
         frequencyHz = getResonantFrequencyHz(vibrator, capabilities);
     } else if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) {
-        frequencyHz = getFrequencyMinimumHz(vibrator, capabilities);
+        if (version < PWLE_V2_MIN_VERSION) {
+            frequencyHz = getFrequencyMinimumHz(vibrator, capabilities, version);
+        } else {
+            frequencyHz = pwle_v2_utils::getPwleV2FrequencyMinHz(vibrator);
+        }
     } else {
         frequencyHz = 150.0;  // default value commonly used
     }
@@ -846,23 +863,24 @@
 }
 
 TEST_P(VibratorAidl, GetFrequencyResolution) {
-    getFrequencyResolutionHz(vibrator, capabilities);
+    getFrequencyResolutionHz(vibrator, capabilities, version);
 }
 
 TEST_P(VibratorAidl, GetFrequencyMinimum) {
-    getFrequencyMinimumHz(vibrator, capabilities);
+    getFrequencyMinimumHz(vibrator, capabilities, version);
 }
 
 TEST_P(VibratorAidl, GetBandwidthAmplitudeMap) {
     std::vector<float> bandwidthAmplitudeMap;
     ndk::ScopedAStatus status = vibrator->getBandwidthAmplitudeMap(&bandwidthAmplitudeMap);
-    if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) {
+
+    if (shouldValidateLegacyFrequencyControlResult(capabilities, version, status)) {
         EXPECT_OK(std::move(status));
         ASSERT_FALSE(bandwidthAmplitudeMap.empty());
 
         int minMapSize = (getResonantFrequencyHz(vibrator, capabilities) -
-                          getFrequencyMinimumHz(vibrator, capabilities)) /
-                         getFrequencyResolutionHz(vibrator, capabilities);
+                          getFrequencyMinimumHz(vibrator, capabilities, version)) /
+                         getFrequencyResolutionHz(vibrator, capabilities, version);
         ASSERT_GT(bandwidthAmplitudeMap.size(), minMapSize);
 
         for (float e : bandwidthAmplitudeMap) {
@@ -911,7 +929,7 @@
 
 TEST_P(VibratorAidl, ComposeValidPwle) {
     if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) {
-        ActivePwle firstActive = composeValidActivePwle(vibrator, capabilities);
+        ActivePwle firstActive = composeValidActivePwle(vibrator, capabilities, version);
 
         std::vector<Braking> supported;
         EXPECT_OK(vibrator->getSupportedBraking(&supported));
@@ -921,13 +939,17 @@
         firstBraking.braking = isClabSupported ? Braking::CLAB : Braking::NONE;
         firstBraking.duration = 100;
 
-        ActivePwle secondActive = composeValidActivePwle(vibrator, capabilities);
+        ActivePwle secondActive = composeValidActivePwle(vibrator, capabilities, version);
         if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) {
-            float minFrequencyHz = getFrequencyMinimumHz(vibrator, capabilities);
-            float maxFrequencyHz = getFrequencyMaximumHz(vibrator, capabilities);
-            float freqResolutionHz = getFrequencyResolutionHz(vibrator, capabilities);
-            secondActive.startFrequency = minFrequencyHz + (freqResolutionHz / 2.0f);
-            secondActive.endFrequency = maxFrequencyHz - (freqResolutionHz / 3.0f);
+            float minFrequencyHz = getFrequencyMinimumHz(vibrator, capabilities, version);
+            float maxFrequencyHz = getFrequencyMaximumHz(vibrator, capabilities, version);
+            float freqResolutionHz = getFrequencyResolutionHz(vibrator, capabilities, version);
+            // As of API 16 these APIs are deprecated and no longer required to be implemented
+            //  with frequency control capability.
+            if (minFrequencyHz >= 0 && maxFrequencyHz >= 0 && freqResolutionHz >= 0) {
+                secondActive.startFrequency = minFrequencyHz + (freqResolutionHz / 2.0f);
+                secondActive.endFrequency = maxFrequencyHz - (freqResolutionHz / 3.0f);
+            }
         }
         BrakingPwle secondBraking;
         secondBraking.braking = Braking::NONE;
@@ -955,7 +977,7 @@
     uint32_t durationMs = segmentDurationMaxMs * 2 + 100;  // Sum of 2 active and 1 braking below
     auto timeout = std::chrono::milliseconds(durationMs) + VIBRATION_CALLBACK_TIMEOUT;
 
-    ActivePwle active = composeValidActivePwle(vibrator, capabilities);
+    ActivePwle active = composeValidActivePwle(vibrator, capabilities, version);
 
     std::vector<Braking> supported;
     EXPECT_OK(vibrator->getSupportedBraking(&supported));
@@ -978,7 +1000,7 @@
         // test empty queue
         EXPECT_ILLEGAL_ARGUMENT(vibrator->composePwle(pwleQueue, nullptr));
 
-        ActivePwle active = composeValidActivePwle(vibrator, capabilities);
+        ActivePwle active = composeValidActivePwle(vibrator, capabilities, version);
 
         PrimitivePwle pwle;
         pwle = active;
@@ -996,7 +1018,7 @@
 
 TEST_P(VibratorAidl, ComposePwleAmplitudeParameterBoundary) {
     if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) {
-        ActivePwle active = composeValidActivePwle(vibrator, capabilities);
+        ActivePwle active = composeValidActivePwle(vibrator, capabilities, version);
         active.startAmplitude = getAmplitudeMax() + 1.0;  // Amplitude greater than allowed
         active.endAmplitude = getAmplitudeMax() + 1.0;    // Amplitude greater than allowed
 
@@ -1016,11 +1038,18 @@
 TEST_P(VibratorAidl, ComposePwleFrequencyParameterBoundary) {
     if ((capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) &&
         (capabilities & IVibrator::CAP_FREQUENCY_CONTROL)) {
-        float freqMinimumHz = getFrequencyMinimumHz(vibrator, capabilities);
-        float freqMaximumHz = getFrequencyMaximumHz(vibrator, capabilities);
-        float freqResolutionHz = getFrequencyResolutionHz(vibrator, capabilities);
+        float freqMinimumHz = getFrequencyMinimumHz(vibrator, capabilities, version);
+        float freqMaximumHz = getFrequencyMaximumHz(vibrator, capabilities, version);
+        float freqResolutionHz = getFrequencyResolutionHz(vibrator, capabilities, version);
 
-        ActivePwle active = composeValidActivePwle(vibrator, capabilities);
+        // As of API 16 these APIs are deprecated and no longer required to be implemented with
+        // frequency control capability.
+        if (freqMinimumHz < 0 || freqMaximumHz < 0 || freqResolutionHz < 0) {
+            GTEST_SKIP() << "PWLE V1 is not supported, skipping test";
+            return;
+        }
+
+        ActivePwle active = composeValidActivePwle(vibrator, capabilities, version);
         active.startFrequency =
             freqMaximumHz + freqResolutionHz;                    // Frequency greater than allowed
         active.endFrequency = freqMaximumHz + freqResolutionHz;  // Frequency greater than allowed
@@ -1040,7 +1069,7 @@
 
 TEST_P(VibratorAidl, ComposePwleSegmentDurationBoundary) {
     if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) {
-        ActivePwle active = composeValidActivePwle(vibrator, capabilities);
+        ActivePwle active = composeValidActivePwle(vibrator, capabilities, version);
 
         int32_t segmentDurationMaxMs;
         vibrator->getPwlePrimitiveDurationMax(&segmentDurationMaxMs);
@@ -1052,15 +1081,15 @@
     }
 }
 
-TEST_P(VibratorAidl, PwleV2FrequencyToOutputAccelerationMapHasValidFrequencyRange) {
-    if (!(capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS_V2)) {
-        GTEST_SKIP() << "PWLE V2 not supported, skipping test";
+TEST_P(VibratorAidl, FrequencyToOutputAccelerationMapHasValidFrequencyRange) {
+    if (version < PWLE_V2_MIN_VERSION || !(capabilities & IVibrator::CAP_FREQUENCY_CONTROL)) {
+        GTEST_SKIP() << "Frequency control is not supported, skipping test";
         return;
     }
 
-    std::vector<PwleV2OutputMapEntry> frequencyToOutputAccelerationMap;
+    std::vector<FrequencyAccelerationMapEntry> frequencyToOutputAccelerationMap;
     ndk::ScopedAStatus status =
-            vibrator->getPwleV2FrequencyToOutputAccelerationMap(&frequencyToOutputAccelerationMap);
+            vibrator->getFrequencyToOutputAccelerationMap(&frequencyToOutputAccelerationMap);
     EXPECT_OK(std::move(status));
     ASSERT_FALSE(frequencyToOutputAccelerationMap.empty());
     auto sharpnessRange =
@@ -1072,6 +1101,15 @@
     ASSERT_TRUE(sharpnessRange.first < sharpnessRange.second);
 }
 
+TEST_P(VibratorAidl, FrequencyToOutputAccelerationMapUnsupported) {
+    if ((capabilities & IVibrator::CAP_FREQUENCY_CONTROL)) return;
+
+    std::vector<FrequencyAccelerationMapEntry> frequencyToOutputAccelerationMap;
+
+    EXPECT_UNKNOWN_OR_UNSUPPORTED(
+            vibrator->getFrequencyToOutputAccelerationMap(&frequencyToOutputAccelerationMap));
+}
+
 TEST_P(VibratorAidl, GetPwleV2PrimitiveDurationMaxMillis) {
     if (!(capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS_V2)) {
         GTEST_SKIP() << "PWLE V2 not supported, skipping test";
@@ -1111,6 +1149,17 @@
     ASSERT_LE(durationMs, pwle_v2_utils::COMPOSE_PWLE_V2_MAX_ALLOWED_PRIMITIVE_MIN_DURATION_MS);
 }
 
+TEST_P(VibratorAidl, ValidatePwleV2DependencyOnFrequencyControl) {
+    if (!(capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS_V2)) {
+        GTEST_SKIP() << "PWLE V2 not supported, skipping test";
+        return;
+    }
+
+    // Check if frequency control is supported
+    bool hasFrequencyControl = (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) != 0;
+    ASSERT_TRUE(hasFrequencyControl) << "Frequency control MUST be supported when PWLE V2 is.";
+}
+
 TEST_P(VibratorAidl, ComposeValidPwleV2Effect) {
     if (!(capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS_V2)) {
         GTEST_SKIP() << "PWLE V2 not supported, skipping test";
@@ -1126,12 +1175,13 @@
         EXPECT_EQ(capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS_V2, 0)
                 << "Vibrator version " << version << " should not report PWLE V2 capability.";
     }
-    if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS_V2) return;
+    if ((capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS_V2)) return;
 
-    std::vector<PwleV2Primitive> pwleEffect{
-            PwleV2Primitive(/*amplitude=*/1.0f, /*frequencyHz=*/100.0f, /*timeMillis=*/50)};
+    CompositePwleV2 composite;
+    composite.pwlePrimitives.emplace_back(/*amplitude=*/1.0f, /*frequencyHz=*/100.0f,
+                                          /*timeMillis=*/50);
 
-    EXPECT_UNKNOWN_OR_UNSUPPORTED(vibrator->composePwleV2(pwleEffect, nullptr));
+    EXPECT_UNKNOWN_OR_UNSUPPORTED(vibrator->composePwleV2(composite, nullptr));
 }
 
 TEST_P(VibratorAidl, ComposeValidPwleV2EffectWithCallback) {
@@ -1150,8 +1200,10 @@
     auto timeout = std::chrono::milliseconds(minDuration) + VIBRATION_CALLBACK_TIMEOUT;
     float minFrequency = pwle_v2_utils::getPwleV2FrequencyMinHz(vibrator);
 
-    EXPECT_OK(vibrator->composePwleV2(
-            {PwleV2Primitive(/*amplitude=*/0.5, minFrequency, minDuration)}, callback));
+    CompositePwleV2 composite;
+    composite.pwlePrimitives.emplace_back(/*amplitude=*/0.5, minFrequency, minDuration);
+
+    EXPECT_OK(vibrator->composePwleV2(composite, callback));
     EXPECT_EQ(completionFuture.wait_for(timeout), std::future_status::ready);
     EXPECT_OK(vibrator->off());
 }
@@ -1177,43 +1229,48 @@
     EXPECT_OK(vibrator->getPwleV2PrimitiveDurationMinMillis(&minDurationMs));
     EXPECT_OK(vibrator->getPwleV2PrimitiveDurationMaxMillis(&maxDurationMs));
 
-    std::vector<PwleV2Primitive> composePwle;
+    CompositePwleV2 composePwle;
 
     // Negative amplitude
-    composePwle.push_back(PwleV2Primitive(/*amplitude=*/-0.8f, /*frequency=*/100, minDurationMs));
+    composePwle.pwlePrimitives.push_back(
+            PwleV2Primitive(/*amplitude=*/-0.8f, /*frequency=*/100, minDurationMs));
     EXPECT_ILLEGAL_ARGUMENT(vibrator->composePwleV2(composePwle, nullptr))
             << "Composing PWLE V2 effect with negative amplitude should fail";
-    composePwle.clear();
+    composePwle.pwlePrimitives.clear();
 
     // Amplitude exceeding 1.0
-    composePwle.push_back(PwleV2Primitive(/*amplitude=*/1.2f, /*frequency=*/100, minDurationMs));
+    composePwle.pwlePrimitives.push_back(
+            PwleV2Primitive(/*amplitude=*/1.2f, /*frequency=*/100, minDurationMs));
     EXPECT_ILLEGAL_ARGUMENT(vibrator->composePwleV2(composePwle, nullptr))
             << "Composing PWLE V2 effect with amplitude greater than 1.0 should fail";
-    composePwle.clear();
+    composePwle.pwlePrimitives.clear();
 
     // Duration exceeding maximum
-    composePwle.push_back(
+    composePwle.pwlePrimitives.push_back(
             PwleV2Primitive(/*amplitude=*/0.2f, /*frequency=*/100, maxDurationMs + 10));
     EXPECT_ILLEGAL_ARGUMENT(vibrator->composePwleV2(composePwle, nullptr))
             << "Composing PWLE V2 effect with duration exceeding maximum should fail";
-    composePwle.clear();
+    composePwle.pwlePrimitives.clear();
 
     // Negative duration
-    composePwle.push_back(PwleV2Primitive(/*amplitude=*/0.2f, /*frequency=*/100, /*time=*/-1));
+    composePwle.pwlePrimitives.push_back(
+            PwleV2Primitive(/*amplitude=*/0.2f, /*frequency=*/100, /*time=*/-1));
     EXPECT_ILLEGAL_ARGUMENT(vibrator->composePwleV2(composePwle, nullptr))
             << "Composing PWLE V2 effect with negative duration should fail";
-    composePwle.clear();
+    composePwle.pwlePrimitives.clear();
 
     // Frequency below minimum
     float minFrequency = pwle_v2_utils::getPwleV2FrequencyMinHz(vibrator);
-    composePwle.push_back(PwleV2Primitive(/*amplitude=*/0.2f, minFrequency - 1, minDurationMs));
+    composePwle.pwlePrimitives.push_back(
+            PwleV2Primitive(/*amplitude=*/0.2f, minFrequency - 1, minDurationMs));
     EXPECT_ILLEGAL_ARGUMENT(vibrator->composePwleV2(composePwle, nullptr))
             << "Composing PWLE V2 effect with frequency below minimum should fail";
-    composePwle.clear();
+    composePwle.pwlePrimitives.clear();
 
     // Frequency above maximum
     float maxFrequency = pwle_v2_utils::getPwleV2FrequencyMaxHz(vibrator);
-    composePwle.push_back(PwleV2Primitive(/*amplitude=*/0.2f, maxFrequency + 1, minDurationMs));
+    composePwle.pwlePrimitives.push_back(
+            PwleV2Primitive(/*amplitude=*/0.2f, maxFrequency + 1, minDurationMs));
     EXPECT_ILLEGAL_ARGUMENT(vibrator->composePwleV2(composePwle, nullptr))
             << "Composing PWLE V2 effect with frequency above maximum should fail";
 }
diff --git a/vibrator/aidl/vts/pwle_v2_utils.h b/vibrator/aidl/vts/pwle_v2_utils.h
index 2163908..eaa024c 100644
--- a/vibrator/aidl/vts/pwle_v2_utils.h
+++ b/vibrator/aidl/vts/pwle_v2_utils.h
@@ -20,8 +20,8 @@
 #include <aidl/android/hardware/vibrator/IVibrator.h>
 #include "test_utils.h"
 
+using aidl::android::hardware::vibrator::FrequencyAccelerationMapEntry;
 using aidl::android::hardware::vibrator::IVibrator;
-using aidl::android::hardware::vibrator::PwleV2OutputMapEntry;
 using aidl::android::hardware::vibrator::PwleV2Primitive;
 
 namespace aidl {
@@ -116,9 +116,8 @@
 }
 
 static float getPwleV2FrequencyMinHz(const std::shared_ptr<IVibrator>& vibrator) {
-    std::vector<PwleV2OutputMapEntry> frequencyToOutputAccelerationMap;
-    EXPECT_OK(
-            vibrator->getPwleV2FrequencyToOutputAccelerationMap(&frequencyToOutputAccelerationMap));
+    std::vector<FrequencyAccelerationMapEntry> frequencyToOutputAccelerationMap;
+    EXPECT_OK(vibrator->getFrequencyToOutputAccelerationMap(&frequencyToOutputAccelerationMap));
     EXPECT_TRUE(!frequencyToOutputAccelerationMap.empty());
     // We can't use ASSERT_TRUE() above because this is a non-void function,
     // but we need to return to assure we don't crash from a null dereference.
@@ -134,9 +133,8 @@
 }
 
 static float getPwleV2FrequencyMaxHz(const std::shared_ptr<IVibrator>& vibrator) {
-    std::vector<PwleV2OutputMapEntry> frequencyToOutputAccelerationMap;
-    EXPECT_OK(
-            vibrator->getPwleV2FrequencyToOutputAccelerationMap(&frequencyToOutputAccelerationMap));
+    std::vector<FrequencyAccelerationMapEntry> frequencyToOutputAccelerationMap;
+    EXPECT_OK(vibrator->getFrequencyToOutputAccelerationMap(&frequencyToOutputAccelerationMap));
     EXPECT_TRUE(!frequencyToOutputAccelerationMap.empty());
     // We can't use ASSERT_TRUE() above because this is a non-void function,
     // but we need to return to assure we don't crash from a null dereference.
@@ -151,8 +149,7 @@
     return entry->frequencyHz;
 }
 
-static std::vector<PwleV2Primitive> composeValidPwleV2Effect(
-        const std::shared_ptr<IVibrator>& vibrator) {
+static CompositePwleV2 composeValidPwleV2Effect(const std::shared_ptr<IVibrator>& vibrator) {
     int32_t minDurationMs;
     EXPECT_OK(vibrator->getPwleV2PrimitiveDurationMinMillis(&minDurationMs));
     int32_t maxDurationMs;
@@ -162,20 +159,20 @@
     int32_t maxCompositionSize;
     EXPECT_OK(vibrator->getPwleV2CompositionSizeMax(&maxCompositionSize));
 
-    std::vector<PwleV2Primitive> pwleEffect;
+    CompositePwleV2 composite;
 
-    pwleEffect.emplace_back(0.1f, minFrequency, minDurationMs);
-    pwleEffect.emplace_back(0.5f, maxFrequency, maxDurationMs);
+    composite.pwlePrimitives.emplace_back(0.1f, minFrequency, minDurationMs);
+    composite.pwlePrimitives.emplace_back(0.5f, maxFrequency, maxDurationMs);
 
     float variedFrequency = (minFrequency + maxFrequency) / 2.0f;
     for (int i = 0; i < maxCompositionSize - 2; i++) {
-        pwleEffect.emplace_back(0.7f, variedFrequency, minDurationMs);
+        composite.pwlePrimitives.emplace_back(0.7f, variedFrequency, minDurationMs);
     }
 
-    return pwleEffect;
+    return composite;
 }
 
-static std::vector<PwleV2Primitive> composePwleV2EffectWithTooManyPoints(
+static CompositePwleV2 composePwleV2EffectWithTooManyPoints(
         const std::shared_ptr<IVibrator>& vibrator) {
     int32_t minDurationMs, maxCompositionSize;
     EXPECT_OK(vibrator->getPwleV2PrimitiveDurationMinMillis(&minDurationMs));
@@ -187,12 +184,15 @@
     std::fill(pwleEffect.begin(), pwleEffect.end(),
               PwleV2Primitive(/*amplitude=*/0.2f, maxFrequency, minDurationMs));
 
-    return pwleEffect;
+    CompositePwleV2 composite;
+    composite.pwlePrimitives = pwleEffect;
+
+    return composite;
 }
 
 static std::pair<float, float> getPwleV2SharpnessRange(
         const std::shared_ptr<IVibrator>& vibrator,
-        std::vector<PwleV2OutputMapEntry> freqToOutputAccelerationMap) {
+        std::vector<FrequencyAccelerationMapEntry> freqToOutputAccelerationMap) {
     std::pair<float, float> sharpnessRange = {-1, -1};
 
     // Sort the entries by frequency in ascending order
diff --git a/wifi/1.0/vts/functional/Android.bp b/wifi/1.0/vts/functional/Android.bp
index ebfa164..e3c269d 100644
--- a/wifi/1.0/vts/functional/Android.bp
+++ b/wifi/1.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_fwk_wifi_hal",
     // 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"
diff --git a/wifi/1.1/vts/functional/Android.bp b/wifi/1.1/vts/functional/Android.bp
index a8f3470..123c8a3 100644
--- a/wifi/1.1/vts/functional/Android.bp
+++ b/wifi/1.1/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_fwk_wifi_hal",
     // 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"
diff --git a/wifi/1.2/vts/functional/Android.bp b/wifi/1.2/vts/functional/Android.bp
index f43892b..2b85d0c 100644
--- a/wifi/1.2/vts/functional/Android.bp
+++ b/wifi/1.2/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_fwk_wifi_hal",
     // 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"
diff --git a/wifi/1.3/vts/functional/Android.bp b/wifi/1.3/vts/functional/Android.bp
index 16f84ef..a171ba8 100644
--- a/wifi/1.3/vts/functional/Android.bp
+++ b/wifi/1.3/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_fwk_wifi_hal",
     // 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"
diff --git a/wifi/1.4/vts/functional/Android.bp b/wifi/1.4/vts/functional/Android.bp
index cac8c0b..a1be952 100644
--- a/wifi/1.4/vts/functional/Android.bp
+++ b/wifi/1.4/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_fwk_wifi_hal",
     // 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"
diff --git a/wifi/1.5/vts/functional/Android.bp b/wifi/1.5/vts/functional/Android.bp
index d906d06..9dba217 100644
--- a/wifi/1.5/vts/functional/Android.bp
+++ b/wifi/1.5/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_fwk_wifi_hal",
     // 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"
diff --git a/wifi/1.6/vts/functional/Android.bp b/wifi/1.6/vts/functional/Android.bp
index 92e6d13..188c67c 100644
--- a/wifi/1.6/vts/functional/Android.bp
+++ b/wifi/1.6/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_fwk_wifi_hal",
     // 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"
diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/ApIfaceParams.aidl
similarity index 88%
copy from vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl
copy to wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/ApIfaceParams.aidl
index a5eda52..50e1bbb 100644
--- a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/ApIfaceParams.aidl
@@ -31,9 +31,10 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.vibrator;
+package android.hardware.wifi;
 @VintfStability
-parcelable PwleV2OutputMapEntry {
-  float frequencyHz;
-  float maxOutputAccelerationGs;
+parcelable ApIfaceParams {
+  android.hardware.wifi.IfaceConcurrencyType ifaceType;
+  boolean usesMlo;
+  @nullable android.hardware.wifi.common.OuiKeyedData[] vendorData;
 }
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiApIface.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiApIface.aidl
index e71dde4..af95bee 100644
--- a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiApIface.aidl
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiApIface.aidl
@@ -40,4 +40,5 @@
   void setCountryCode(in byte[2] code);
   void resetToFactoryMacAddress();
   void setMacAddress(in byte[6] mac);
+  boolean usesMlo();
 }
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiChip.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiChip.aidl
index 5fe7c53..1af0d65 100644
--- a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiChip.aidl
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/IWifiChip.aidl
@@ -35,7 +35,13 @@
 @VintfStability
 interface IWifiChip {
   void configureChip(in int modeId);
+  /**
+   * @deprecated This method is deprecated from AIDL v3, newer HALs should use createApOrBridgedApIfaceWithParams.
+   */
   @PropagateAllowBlocking android.hardware.wifi.IWifiApIface createApIface();
+  /**
+   * @deprecated This method is deprecated from AIDL v3, newer HALs should use createApOrBridgedApIfaceWithParams.
+   */
   @PropagateAllowBlocking android.hardware.wifi.IWifiApIface createBridgedApIface();
   @PropagateAllowBlocking android.hardware.wifi.IWifiNanIface createNanIface();
   @PropagateAllowBlocking android.hardware.wifi.IWifiP2pIface createP2pIface();
@@ -83,8 +89,12 @@
   void triggerSubsystemRestart();
   void enableStaChannelForPeerNetwork(in int channelCategoryEnableFlag);
   void setMloMode(in android.hardware.wifi.IWifiChip.ChipMloMode mode);
+  /**
+   * @deprecated This method is deprecated from AIDL v3, newer HALs should use createApOrBridgedApIfaceWithParams.
+   */
   @PropagateAllowBlocking android.hardware.wifi.IWifiApIface createApOrBridgedApIface(in android.hardware.wifi.IfaceConcurrencyType iface, in android.hardware.wifi.common.OuiKeyedData[] vendorData);
   void setVoipMode(in android.hardware.wifi.IWifiChip.VoipMode mode);
+  @PropagateAllowBlocking android.hardware.wifi.IWifiApIface createApOrBridgedApIfaceWithParams(in android.hardware.wifi.ApIfaceParams params);
   const int NO_POWER_CAP_CONSTANT = 0x7FFFFFFF;
   @Backing(type="int") @VintfStability
   enum FeatureSetMask {
diff --git a/wifi/aidl/android/hardware/wifi/ApIfaceParams.aidl b/wifi/aidl/android/hardware/wifi/ApIfaceParams.aidl
new file mode 100644
index 0000000..f075b72
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/ApIfaceParams.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi;
+
+import android.hardware.wifi.IfaceConcurrencyType;
+import android.hardware.wifi.common.OuiKeyedData;
+
+/**
+ * Parameters to use for setting up the access point interfaces.
+ */
+@VintfStability
+parcelable ApIfaceParams {
+    /**
+     * IfaceConcurrencyType to be created. Takes one of
+     * |IfaceConcurrencyType.AP| or |IfaceConcurrencyType.AP_BRIDGED|
+     */
+    IfaceConcurrencyType ifaceType;
+    /**
+     * Whether the current iface will be operated on Multi-links on the one MLD device (MLO).
+     */
+    boolean usesMlo;
+    /**
+     * Optional vendor-specific configuration parameters.
+     */
+    @nullable OuiKeyedData[] vendorData;
+}
diff --git a/wifi/aidl/android/hardware/wifi/IWifiApIface.aidl b/wifi/aidl/android/hardware/wifi/IWifiApIface.aidl
index b14a800..a350e52 100644
--- a/wifi/aidl/android/hardware/wifi/IWifiApIface.aidl
+++ b/wifi/aidl/android/hardware/wifi/IWifiApIface.aidl
@@ -85,4 +85,11 @@
      *         |WifiStatusCode.ERROR_UNKNOWN|
      */
     void setMacAddress(in byte[6] mac);
+
+    /**
+     * Check if ApIface is for an AP using Multi-Link Operation
+     *
+     * @return true if it is MLO iface, false otherwise.
+     */
+    boolean usesMlo();
 }
diff --git a/wifi/aidl/android/hardware/wifi/IWifiChip.aidl b/wifi/aidl/android/hardware/wifi/IWifiChip.aidl
index 4e418d8..04f31d2 100644
--- a/wifi/aidl/android/hardware/wifi/IWifiChip.aidl
+++ b/wifi/aidl/android/hardware/wifi/IWifiChip.aidl
@@ -17,6 +17,7 @@
 package android.hardware.wifi;
 
 import android.hardware.wifi.AfcChannelAllowance;
+import android.hardware.wifi.ApIfaceParams;
 import android.hardware.wifi.IWifiApIface;
 import android.hardware.wifi.IWifiChipEventCallback;
 import android.hardware.wifi.IWifiNanIface;
@@ -433,6 +434,9 @@
      * reached the maximum allowed (specified in |ChipIfaceCombination|) number
      * of ifaces of the AP type.
      *
+     * @deprecated This method is deprecated from AIDL v3, newer HALs should use
+     * createApOrBridgedApIfaceWithParams.
+     *
      * @return AIDL interface object representing the iface if
      *         successful, null otherwise.
      * @throws ServiceSpecificException with one of the following values:
@@ -450,6 +454,9 @@
      * reached the maximum allowed (specified in |ChipIfaceCombination|) number
      * of ifaces of the AP type.
      *
+     * @deprecated This method is deprecated from AIDL v3, newer HALs should use
+     * createApOrBridgedApIfaceWithParams.
+     *
      * @return AIDL interface object representing the iface if
      *         successful, null otherwise.
      * @throws ServiceSpecificException with one of the following values:
@@ -1177,6 +1184,9 @@
      * reached the maximum allowed (specified in |ChipIfaceCombination|) number
      * of ifaces of the AP or AP_BRIDGED type.
      *
+     * @deprecated This method is deprecated from AIDL v3, newer HALs should use
+     * createApOrBridgedApIfaceWithParams.
+     *
      * @param  iface IfaceConcurrencyType to be created. Takes one of
                |IfaceConcurrencyType.AP| or |IfaceConcurrencyType.AP_BRIDGED|
      * @param  vendorData Vendor-provided configuration data as a list of |OuiKeyedData|.
@@ -1210,4 +1220,22 @@
      *         |WifiStatusCode.ERROR_UNKNOWN|
      */
     void setVoipMode(in VoipMode mode);
+
+    /**
+     * Create an AP or bridged AP iface on the chip based on ApIfaceParamss.
+     *
+     * Depending on the mode the chip is configured in, the interface creation
+     * may fail (code: |WifiStatusCode.ERROR_NOT_AVAILABLE|) if we've already
+     * reached the maximum allowed (specified in |ChipIfaceCombination|) number
+     * of ifaces of the AP type.
+     *
+     * @return AIDL interface object representing the iface if
+     *         successful, null otherwise.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|,
+     *         |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+     *         |WifiStatusCode.ERROR_NOT_AVAILABLE|
+     */
+    @PropagateAllowBlocking
+    IWifiApIface createApOrBridgedApIfaceWithParams(in ApIfaceParams params);
 }
diff --git a/wifi/aidl/default/wifi_ap_iface.cpp b/wifi/aidl/default/wifi_ap_iface.cpp
index 7779750..6a73cc8 100644
--- a/wifi/aidl/default/wifi_ap_iface.cpp
+++ b/wifi/aidl/default/wifi_ap_iface.cpp
@@ -28,10 +28,12 @@
 namespace wifi {
 using aidl_return_util::validateAndCall;
 
-WifiApIface::WifiApIface(const std::string& ifname, const std::vector<std::string>& instances,
+WifiApIface::WifiApIface(const std::string& ifname, const bool usesMlo,
+                         const std::vector<std::string>& instances,
                          const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
                          const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util)
     : ifname_(ifname),
+      uses_mlo_(usesMlo),
       instances_(instances),
       legacy_hal_(legacy_hal),
       iface_util_(iface_util),
@@ -50,6 +52,10 @@
     return ifname_;
 }
 
+bool WifiApIface::usesMlo() {
+    return uses_mlo_;
+}
+
 void WifiApIface::removeInstance(std::string instance) {
     instances_.erase(std::remove(instances_.begin(), instances_.end(), instance), instances_.end());
 }
@@ -72,7 +78,7 @@
 ndk::ScopedAStatus WifiApIface::getFactoryMacAddress(std::array<uint8_t, 6>* _aidl_return) {
     return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
                            &WifiApIface::getFactoryMacAddressInternal, _aidl_return,
-                           instances_.size() > 0 ? instances_[0] : ifname_);
+                           getOperatingInstanceName());
 }
 
 ndk::ScopedAStatus WifiApIface::resetToFactoryMacAddress() {
@@ -90,14 +96,14 @@
 }
 
 ndk::ScopedAStatus WifiApIface::setCountryCodeInternal(const std::array<uint8_t, 2>& code) {
-    legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->setCountryCode(
-            instances_.size() > 0 ? instances_[0] : ifname_, code);
+    legacy_hal::wifi_error legacy_status =
+            legacy_hal_.lock()->setCountryCode(getOperatingInstanceName(), code);
     return createWifiStatusFromLegacyError(legacy_status);
 }
 
 ndk::ScopedAStatus WifiApIface::setMacAddressInternal(const std::array<uint8_t, 6>& mac) {
     // Support random MAC up to 2 interfaces
-    if (instances_.size() == 2) {
+    if (instances_.size() == 2 && !uses_mlo_) {
         int rbyte = 1;
         for (auto const& intf : instances_) {
             std::array<uint8_t, 6> rmac = mac;
@@ -131,7 +137,7 @@
 
 ndk::ScopedAStatus WifiApIface::resetToFactoryMacAddressInternal() {
     std::pair<std::array<uint8_t, 6>, ndk::ScopedAStatus> getMacResult;
-    if (instances_.size() == 2) {
+    if (instances_.size() == 2 && !uses_mlo_) {
         for (auto const& intf : instances_) {
             getMacResult = getFactoryMacAddressInternal(intf);
             LOG(DEBUG) << "Reset MAC to factory MAC on " << intf;
@@ -166,6 +172,11 @@
     return {instances_, ndk::ScopedAStatus::ok()};
 }
 
+ndk::ScopedAStatus WifiApIface::usesMlo(bool* _aidl_return) {
+    *_aidl_return = uses_mlo_;
+    return ndk::ScopedAStatus::ok();
+}
+
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/aidl/default/wifi_ap_iface.h b/wifi/aidl/default/wifi_ap_iface.h
index 7378f98..e07154d 100644
--- a/wifi/aidl/default/wifi_ap_iface.h
+++ b/wifi/aidl/default/wifi_ap_iface.h
@@ -33,13 +33,15 @@
  */
 class WifiApIface : public BnWifiApIface {
   public:
-    WifiApIface(const std::string& ifname, const std::vector<std::string>& instances,
+    WifiApIface(const std::string& ifname, const bool usesMlo,
+                const std::vector<std::string>& instances,
                 const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
                 const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util);
     // Refer to |WifiChip::invalidate()|.
     void invalidate();
     bool isValid();
     std::string getName();
+    bool usesMlo();
     void removeInstance(std::string instance);
 
     // AIDL methods exposed.
@@ -49,6 +51,7 @@
     ndk::ScopedAStatus getFactoryMacAddress(std::array<uint8_t, 6>* _aidl_return) override;
     ndk::ScopedAStatus resetToFactoryMacAddress() override;
     ndk::ScopedAStatus getBridgedInstances(std::vector<std::string>* _aidl_return) override;
+    ndk::ScopedAStatus usesMlo(bool* _aidl_return) override;
 
   private:
     // Corresponding worker functions for the AIDL methods.
@@ -61,11 +64,18 @@
     std::pair<std::vector<std::string>, ndk::ScopedAStatus> getBridgedInstancesInternal();
 
     std::string ifname_;
+    bool uses_mlo_;
     std::vector<std::string> instances_;
     std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
     std::weak_ptr<iface_util::WifiIfaceUtil> iface_util_;
     bool is_valid_;
 
+    // The mlo is using one interface but owning two link instances.
+    // The operating should be based on interface.
+    inline std::string getOperatingInstanceName() {
+        return (instances_.size() > 0 && !uses_mlo_) ? instances_[0] : ifname_;
+    };
+
     DISALLOW_COPY_AND_ASSIGN(WifiApIface);
 };
 
diff --git a/wifi/aidl/default/wifi_chip.cpp b/wifi/aidl/default/wifi_chip.cpp
index fccfc15..045e07d 100644
--- a/wifi/aidl/default/wifi_chip.cpp
+++ b/wifi/aidl/default/wifi_chip.cpp
@@ -369,7 +369,7 @@
 
 ndk::ScopedAStatus WifiChip::createBridgedApIface(std::shared_ptr<IWifiApIface>* _aidl_return) {
     return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                           &WifiChip::createBridgedApIfaceInternal, _aidl_return);
+                           &WifiChip::createBridgedApIfaceInternal, _aidl_return, false);
 }
 
 ndk::ScopedAStatus WifiChip::createApOrBridgedApIface(
@@ -613,6 +613,13 @@
                            &WifiChip::setVoipModeInternal, in_mode);
 }
 
+ndk::ScopedAStatus WifiChip::createApOrBridgedApIfaceWithParams(
+        const ApIfaceParams& in_params, std::shared_ptr<IWifiApIface>* _aidl_return) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+                           &WifiChip::createApOrBridgedApIfaceWithParamsInternal, _aidl_return,
+                           in_params);
+}
+
 void WifiChip::invalidateAndRemoveAllIfaces() {
     invalidateAndClearBridgedApAll();
     invalidateAndClearAll(ap_ifaces_);
@@ -797,15 +804,15 @@
     return ndk::ScopedAStatus::ok();
 }
 
-std::shared_ptr<WifiApIface> WifiChip::newWifiApIface(std::string& ifname) {
+std::shared_ptr<WifiApIface> WifiChip::newWifiApIface(std::string& ifname, bool usesMlo) {
     std::vector<std::string> ap_instances;
     for (auto const& it : br_ifaces_ap_instances_) {
         if (it.first == ifname) {
             ap_instances = it.second;
         }
     }
-    std::shared_ptr<WifiApIface> iface =
-            ndk::SharedRefBase::make<WifiApIface>(ifname, ap_instances, legacy_hal_, iface_util_);
+    std::shared_ptr<WifiApIface> iface = ndk::SharedRefBase::make<WifiApIface>(
+            ifname, usesMlo, ap_instances, legacy_hal_, iface_util_);
     ap_ifaces_.push_back(iface);
     for (const auto& callback : event_cb_handler_.getCallbacks()) {
         if (!callback->onIfaceAdded(IfaceType::AP, ifname).isOk()) {
@@ -826,47 +833,60 @@
     if (!status.isOk()) {
         return {std::shared_ptr<WifiApIface>(), std::move(status)};
     }
-    std::shared_ptr<WifiApIface> iface = newWifiApIface(ifname);
+    std::shared_ptr<WifiApIface> iface = newWifiApIface(ifname, false);
     return {iface, ndk::ScopedAStatus::ok()};
 }
 
-std::pair<std::shared_ptr<IWifiApIface>, ndk::ScopedAStatus>
-WifiChip::createBridgedApIfaceInternal() {
+std::pair<std::shared_ptr<IWifiApIface>, ndk::ScopedAStatus> WifiChip::createBridgedApIfaceInternal(
+        bool usesMlo) {
     if (!canCurrentModeSupportConcurrencyTypeWithCurrentTypes(IfaceConcurrencyType::AP_BRIDGED)) {
         return {nullptr, createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE)};
     }
-    std::vector<std::string> ap_instances = allocateBridgedApInstanceNames();
+    std::string br_ifname;
+    std::vector<std::string> ap_instances = allocateBridgedApInstanceNames(usesMlo);
     if (ap_instances.size() < 2) {
         LOG(ERROR) << "Fail to allocate two instances";
         return {nullptr, createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE)};
     }
-    std::string br_ifname = kApBridgeIfacePrefix + ap_instances[0];
-    for (int i = 0; i < 2; i++) {
-        ndk::ScopedAStatus status = createVirtualApInterface(ap_instances[i]);
-        if (!status.isOk()) {
-            if (i != 0) {  // The failure happened when creating second virtual
-                           // iface.
-                legacy_hal_.lock()->deleteVirtualInterface(
-                        ap_instances.front());  // Remove the first virtual iface.
+    if (usesMlo) {
+        // MLO SoftAp is using single interface with two links. So only need to create 1 interface.
+        br_ifname = allocateApIfaceName();
+    } else {
+        br_ifname = kApBridgeIfacePrefix + ap_instances[0];
+        for (int i = 0; i < 2; i++) {
+            ndk::ScopedAStatus status = createVirtualApInterface(ap_instances[i]);
+            if (!status.isOk()) {
+                if (i != 0) {  // The failure happened when creating second virtual
+                               // iface.
+                    legacy_hal_.lock()->deleteVirtualInterface(
+                            ap_instances.front());  // Remove the first virtual iface.
+                }
+                return {nullptr, std::move(status)};
             }
-            return {nullptr, std::move(status)};
         }
     }
     br_ifaces_ap_instances_[br_ifname] = ap_instances;
-    if (!iface_util_->createBridge(br_ifname)) {
-        LOG(ERROR) << "Failed createBridge - br_name=" << br_ifname.c_str();
-        deleteApIface(br_ifname);
-        return {nullptr, createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE)};
-    }
-    for (auto const& instance : ap_instances) {
-        // Bind ap instance interface to AP bridge
-        if (!iface_util_->addIfaceToBridge(br_ifname, instance)) {
-            LOG(ERROR) << "Failed add if to Bridge - if_name=" << instance.c_str();
+    if (usesMlo) {
+        ndk::ScopedAStatus status = createVirtualApInterface(br_ifname);
+        if (!status.isOk()) {
+            return {nullptr, std::move(status)};
+        }
+    } else {
+        if (!iface_util_->createBridge(br_ifname)) {
+            LOG(ERROR) << "Failed createBridge - br_name=" << br_ifname.c_str();
             deleteApIface(br_ifname);
             return {nullptr, createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE)};
         }
+        for (auto const& instance : ap_instances) {
+            // Bind ap instance interface to AP bridge
+            if (!iface_util_->addIfaceToBridge(br_ifname, instance)) {
+                LOG(ERROR) << "Failed add if to Bridge - if_name=" << instance.c_str();
+                deleteApIface(br_ifname);
+                return {nullptr, createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE)};
+            }
+        }
     }
-    std::shared_ptr<WifiApIface> iface = newWifiApIface(br_ifname);
+    std::shared_ptr<WifiApIface> iface = newWifiApIface(br_ifname, usesMlo);
     return {iface, ndk::ScopedAStatus::ok()};
 }
 
@@ -876,7 +896,18 @@
     if (ifaceType == IfaceConcurrencyType::AP) {
         return createApIfaceInternal();
     } else if (ifaceType == IfaceConcurrencyType::AP_BRIDGED) {
-        return createBridgedApIfaceInternal();
+        return createBridgedApIfaceInternal(false);
+    } else {
+        return {nullptr, createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS)};
+    }
+}
+
+std::pair<std::shared_ptr<IWifiApIface>, ndk::ScopedAStatus>
+WifiChip::createApOrBridgedApIfaceWithParamsInternal(const ApIfaceParams& params) {
+    if (params.ifaceType == IfaceConcurrencyType::AP) {
+        return createApIfaceInternal();
+    } else if (params.ifaceType == IfaceConcurrencyType::AP_BRIDGED) {
+        return createBridgedApIfaceInternal(params.usesMlo);
     } else {
         return {nullptr, createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS)};
     }
@@ -925,23 +956,28 @@
     if (!iface.get() || ifInstanceName.empty()) {
         return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
     }
+
     // Requires to remove one of the instance in bridge mode
     for (auto const& it : br_ifaces_ap_instances_) {
         if (it.first == ifname) {
             std::vector<std::string> ap_instances = it.second;
-            for (auto const& iface : ap_instances) {
-                if (iface == ifInstanceName) {
-                    if (!iface_util_->removeIfaceFromBridge(it.first, iface)) {
-                        LOG(ERROR) << "Failed to remove interface: " << ifInstanceName << " from "
-                                   << ifname;
-                        return createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE);
-                    }
-                    legacy_hal::wifi_error legacy_status =
-                            legacy_hal_.lock()->deleteVirtualInterface(iface);
-                    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
-                        LOG(ERROR) << "Failed to del interface: " << iface << " "
-                                   << legacyErrorToString(legacy_status);
-                        return createWifiStatusFromLegacyError(legacy_status);
+            for (auto const& instance : ap_instances) {
+                if (instance == ifInstanceName) {
+                    if (iface->usesMlo()) {
+                        LOG(INFO) << "Remove Link " << ifInstanceName << " from " << ifname;
+                    } else {
+                        if (!iface_util_->removeIfaceFromBridge(it.first, instance)) {
+                            LOG(ERROR) << "Failed to remove interface: " << ifInstanceName
+                                       << " from " << ifname;
+                            return createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE);
+                        }
+                        legacy_hal::wifi_error legacy_status =
+                                legacy_hal_.lock()->deleteVirtualInterface(instance);
+                        if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+                            LOG(ERROR) << "Failed to del interface: " << instance << " "
+                                       << legacyErrorToString(legacy_status);
+                            return createWifiStatusFromLegacyError(legacy_status);
+                        }
                     }
                     ap_instances.erase(
                             std::remove(ap_instances.begin(), ap_instances.end(), ifInstanceName),
@@ -1729,7 +1765,7 @@
         // If the first active wlan iface is bridged iface.
         // Return first instance name.
         for (auto const& it : br_ifaces_ap_instances_) {
-            if (it.first == ap_ifaces_[0]->getName()) {
+            if (it.first == ap_ifaces_[0]->getName() && !ap_ifaces_[0]->usesMlo()) {
                 return it.second[0];
             }
         }
@@ -1782,9 +1818,19 @@
     return allocateApOrStaIfaceName(IfaceType::AP, startIdxOfApIface());
 }
 
-std::vector<std::string> WifiChip::allocateBridgedApInstanceNames() {
-    // Check if we have a dedicated iface for AP.
-    std::vector<std::string> instances = getPredefinedApIfaceNames(true);
+std::vector<std::string> WifiChip::allocateBridgedApInstanceNames(bool usesMlo) {
+    std::vector<std::string> instances;
+    if (usesMlo) {
+        // For MLO AP, the instances are MLO links and it will be maintained in hostapd.
+        // The hostapd will use 0 as an initial link id and 1 as the next.
+        // Considering Android didn't support link reconfiguration. Forcing to use 0 & 1
+        // should work.
+        instances.push_back("0");
+        instances.push_back("1");
+    } else {
+        // Check if we have a dedicated iface for AP.
+        instances = getPredefinedApIfaceNames(true);
+    }
     if (instances.size() == 2) {
         return instances;
     } else {
@@ -1856,11 +1902,14 @@
 
 void WifiChip::invalidateAndClearBridgedApAll() {
     for (auto const& it : br_ifaces_ap_instances_) {
-        for (auto const& iface : it.second) {
-            iface_util_->removeIfaceFromBridge(it.first, iface);
-            legacy_hal_.lock()->deleteVirtualInterface(iface);
+        const auto iface = findUsingName(ap_ifaces_, it.first);
+        if (!iface->usesMlo()) {
+            for (auto const& iface : it.second) {
+                iface_util_->removeIfaceFromBridge(it.first, iface);
+                legacy_hal_.lock()->deleteVirtualInterface(iface);
+            }
+            iface_util_->deleteBridge(it.first);
         }
-        iface_util_->deleteBridge(it.first);
     }
     br_ifaces_ap_instances_.clear();
 }
@@ -1868,16 +1917,19 @@
 void WifiChip::deleteApIface(const std::string& if_name) {
     if (if_name.empty()) return;
     // delete bridged interfaces if any
-    for (auto const& it : br_ifaces_ap_instances_) {
-        if (it.first == if_name) {
-            for (auto const& iface : it.second) {
-                iface_util_->removeIfaceFromBridge(if_name, iface);
-                legacy_hal_.lock()->deleteVirtualInterface(iface);
+    const auto iface = findUsingName(ap_ifaces_, if_name);
+    if (!iface->usesMlo()) {
+        for (auto const& it : br_ifaces_ap_instances_) {
+            if (it.first == if_name) {
+                for (auto const& instance : it.second) {
+                    iface_util_->removeIfaceFromBridge(if_name, instance);
+                    legacy_hal_.lock()->deleteVirtualInterface(instance);
+                }
+                iface_util_->deleteBridge(if_name);
+                br_ifaces_ap_instances_.erase(if_name);
+                // ifname is bridged AP, return here.
+                return;
             }
-            iface_util_->deleteBridge(if_name);
-            br_ifaces_ap_instances_.erase(if_name);
-            // ifname is bridged AP, return here.
-            return;
         }
     }
 
diff --git a/wifi/aidl/default/wifi_chip.h b/wifi/aidl/default/wifi_chip.h
index ffd507f..24dd00d 100644
--- a/wifi/aidl/default/wifi_chip.h
+++ b/wifi/aidl/default/wifi_chip.h
@@ -159,6 +159,8 @@
     binder_status_t dump(int fd, const char** args, uint32_t numArgs) override;
     ndk::ScopedAStatus setMloMode(const ChipMloMode in_mode) override;
     ndk::ScopedAStatus setVoipMode(const VoipMode in_mode) override;
+    ndk::ScopedAStatus createApOrBridgedApIfaceWithParams(
+            const ApIfaceParams& in_params, std::shared_ptr<IWifiApIface>* _aidl_return) override;
 
   private:
     void invalidateAndRemoveAllIfaces();
@@ -178,12 +180,15 @@
     std::pair<IWifiChip::ChipDebugInfo, ndk::ScopedAStatus> requestChipDebugInfoInternal();
     std::pair<std::vector<uint8_t>, ndk::ScopedAStatus> requestDriverDebugDumpInternal();
     std::pair<std::vector<uint8_t>, ndk::ScopedAStatus> requestFirmwareDebugDumpInternal();
-    std::shared_ptr<WifiApIface> newWifiApIface(std::string& ifname);
+    std::shared_ptr<WifiApIface> newWifiApIface(std::string& ifname, bool usesMlo);
     ndk::ScopedAStatus createVirtualApInterface(const std::string& apVirtIf);
     std::pair<std::shared_ptr<IWifiApIface>, ndk::ScopedAStatus> createApIfaceInternal();
-    std::pair<std::shared_ptr<IWifiApIface>, ndk::ScopedAStatus> createBridgedApIfaceInternal();
+    std::pair<std::shared_ptr<IWifiApIface>, ndk::ScopedAStatus> createBridgedApIfaceInternal(
+            bool usesMlo);
     std::pair<std::shared_ptr<IWifiApIface>, ndk::ScopedAStatus> createApOrBridgedApIfaceInternal(
             IfaceConcurrencyType ifaceType, const std::vector<common::OuiKeyedData>& vendorData);
+    std::pair<std::shared_ptr<IWifiApIface>, ndk::ScopedAStatus>
+    createApOrBridgedApIfaceWithParamsInternal(const ApIfaceParams& params);
     std::pair<std::vector<std::string>, ndk::ScopedAStatus> getApIfaceNamesInternal();
     std::pair<std::shared_ptr<IWifiApIface>, ndk::ScopedAStatus> getApIfaceInternal(
             const std::string& ifname);
@@ -258,7 +263,7 @@
     std::string getFirstActiveWlanIfaceName();
     std::string allocateApOrStaIfaceName(IfaceType type, uint32_t start_idx);
     std::string allocateApIfaceName();
-    std::vector<std::string> allocateBridgedApInstanceNames();
+    std::vector<std::string> allocateBridgedApInstanceNames(bool usesMlo);
     std::string allocateStaIfaceName();
     bool writeRingbufferFilesInternal();
     std::string getWlanIfaceNameWithType(IfaceType type, unsigned idx);
diff --git a/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/IfaceParams.aidl b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/IfaceParams.aidl
index 8da3441..7b67102 100644
--- a/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/IfaceParams.aidl
+++ b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/IfaceParams.aidl
@@ -39,5 +39,5 @@
   android.hardware.wifi.hostapd.ChannelParams[] channelParams;
   @nullable android.hardware.wifi.common.OuiKeyedData[] vendorData;
   @nullable String[] instanceIdentities;
-  boolean isMlo;
+  boolean usesMlo;
 }
diff --git a/wifi/hostapd/aidl/android/hardware/wifi/hostapd/IfaceParams.aidl b/wifi/hostapd/aidl/android/hardware/wifi/hostapd/IfaceParams.aidl
index bb646e3..f4e4647 100644
--- a/wifi/hostapd/aidl/android/hardware/wifi/hostapd/IfaceParams.aidl
+++ b/wifi/hostapd/aidl/android/hardware/wifi/hostapd/IfaceParams.aidl
@@ -46,7 +46,7 @@
      */
     @nullable String[] instanceIdentities;
     /**
-     * Whether the current iface is MLO.
+     * Whether the current iface is using multi-link operation.
      */
-    boolean isMlo;
+    boolean usesMlo;
 }
diff --git a/wifi/netlinkinterceptor/aidl/Android.bp b/wifi/netlinkinterceptor/aidl/Android.bp
index 8c04e31..bc02125 100644
--- a/wifi/netlinkinterceptor/aidl/Android.bp
+++ b/wifi/netlinkinterceptor/aidl/Android.bp
@@ -29,6 +29,7 @@
     vendor_available: true,
     srcs: ["android/hardware/net/nlinterceptor/*.aidl"],
     stability: "vintf",
+    frozen: true,
     backend: {
         java: {
             enabled: false,