Merge "wifi: Support for Wi-Fi Direct R2" into main
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/Android.bp b/audio/aidl/Android.bp
index 4902497..1e6df46 100644
--- a/audio/aidl/Android.bp
+++ b/audio/aidl/Android.bp
@@ -303,6 +303,7 @@
         "android.hardware.audio_defaults",
         "latest_android_hardware_audio_common_import_interface",
         "latest_android_media_audio_common_types_import_interface",
+        "latest_android_media_audio_eraser_types_import_interface",
     ],
     srcs: [
         "android/hardware/audio/effect/AcousticEchoCanceler.aidl",
@@ -317,6 +318,7 @@
         "android/hardware/audio/effect/DynamicsProcessing.aidl",
         "android/hardware/audio/effect/EnvironmentalReverb.aidl",
         "android/hardware/audio/effect/Equalizer.aidl",
+        "android/hardware/audio/effect/Eraser.aidl",
         "android/hardware/audio/effect/Flags.aidl",
         "android/hardware/audio/effect/HapticGenerator.aidl",
         "android/hardware/audio/effect/IEffect.aidl",
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Descriptor.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Descriptor.aidl
index 115da1d..36f22ae 100644
--- a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Descriptor.aidl
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Descriptor.aidl
@@ -44,6 +44,7 @@
   const String EFFECT_TYPE_UUID_DYNAMICS_PROCESSING = "7261676f-6d75-7369-6364-28e2fd3ac39e";
   const String EFFECT_TYPE_UUID_ENV_REVERB = "c2e5d5f0-94bd-4763-9cac-4e234d06839e";
   const String EFFECT_TYPE_UUID_EQUALIZER = "0bed4300-ddd6-11db-8f34-0002a5d5c51b";
+  const String EFFECT_TYPE_UUID_ERASER = "fa81a9ac-588b-11ed-9b6a-0242ac120002";
   const String EFFECT_TYPE_UUID_HAPTIC_GENERATOR = "1411e6d6-aecd-4021-a1cf-a6aceb0d71e5";
   const String EFFECT_TYPE_UUID_LOUDNESS_ENHANCER = "fe3199be-aed0-413f-87bb-11260eb63cf1";
   const String EFFECT_TYPE_UUID_NS = "58b4b260-8e06-11e0-aa8e-0002a5d5c51b";
diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Eraser.aidl
similarity index 81%
copy from vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl
copy to audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Eraser.aidl
index a5eda52..5d8abd5 100644
--- a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Eraser.aidl
@@ -31,9 +31,15 @@
 // 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.audio.effect;
 @VintfStability
-parcelable PwleV2OutputMapEntry {
-  float frequencyHz;
-  float maxOutputAccelerationGs;
+union Eraser {
+  android.hardware.audio.effect.VendorExtension vendor;
+  android.media.audio.eraser.Capability capability;
+  android.media.audio.eraser.Configuration configuration;
+  @VintfStability
+  union Id {
+    android.hardware.audio.effect.VendorExtension vendorExtensionTag;
+    android.hardware.audio.effect.Eraser.Tag commonTag;
+  }
 }
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Parameter.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Parameter.aidl
index ff33c42..40a49de 100644
--- a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Parameter.aidl
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Parameter.aidl
@@ -63,6 +63,7 @@
     android.hardware.audio.effect.Volume.Id volumeTag;
     android.hardware.audio.effect.Parameter.Tag commonTag;
     android.hardware.audio.effect.Spatializer.Id spatializerTag;
+    android.hardware.audio.effect.Eraser.Id eraserTag;
   }
   @VintfStability
   parcelable Common {
@@ -95,5 +96,6 @@
     android.hardware.audio.effect.Visualizer visualizer;
     android.hardware.audio.effect.Volume volume;
     android.hardware.audio.effect.Spatializer spatializer;
+    android.hardware.audio.effect.Eraser eraser;
   }
 }
diff --git a/audio/aidl/android/hardware/audio/effect/Descriptor.aidl b/audio/aidl/android/hardware/audio/effect/Descriptor.aidl
index b152f76..62e9bd4 100644
--- a/audio/aidl/android/hardware/audio/effect/Descriptor.aidl
+++ b/audio/aidl/android/hardware/audio/effect/Descriptor.aidl
@@ -70,6 +70,10 @@
      */
     const String EFFECT_TYPE_UUID_EQUALIZER = "0bed4300-ddd6-11db-8f34-0002a5d5c51b";
     /**
+     * UUID for Audio eraser effect type.
+     */
+    const String EFFECT_TYPE_UUID_ERASER = "fa81a9ac-588b-11ed-9b6a-0242ac120002";
+    /**
      * UUID for Haptic Generator type.
      */
     const String EFFECT_TYPE_UUID_HAPTIC_GENERATOR = "1411e6d6-aecd-4021-a1cf-a6aceb0d71e5";
diff --git a/audio/aidl/android/hardware/audio/effect/Eraser.aidl b/audio/aidl/android/hardware/audio/effect/Eraser.aidl
new file mode 100644
index 0000000..990c6c0
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/effect/Eraser.aidl
@@ -0,0 +1,93 @@
+/*
+ * 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.audio.effect;
+
+import android.hardware.audio.effect.VendorExtension;
+import android.media.audio.eraser.Capability;
+import android.media.audio.eraser.Configuration;
+import android.media.audio.eraser.Mode;
+
+/**
+ * The Audio Eraser Effect is an audio effect that combines multiple capabilities to manipulate and
+ * enhance audio streams.
+ *
+ * The Audio Eraser Effect integrates three primary components:
+ *
+ * Sound Separator: Detects and splits the input audio into multiple sound sources.
+ * Sound Classifier: Classifies each separated sound source into predefined categories based on the
+ * AudioSet ontology.
+ * Remixer: Adjusts the gain factor (volume) of each classified sound source according to specified
+ * configurations, then recombines them into a single output audio stream.
+ *
+ * The Audio Eraser Effect operates in different modes, each leveraging a subset of these
+ * components to achieve specific functionalities as defined in `android.media.audio.eraser.Mode`.
+ *
+ * Flow Diagrams for each operation mode as below.
+ *
+ * ERASER:
+ *                                                  +-----------------+
+ *                                              +-->| Sound Classifier|---+
+ *                                              |   +-----------------+   |
+ *                                              |                         |
+ *+----------------+       +----------------+   |   +-----------------+   |   +----------------+
+ *|   Input Audio  |------>| Sound Separator|---+-->| Sound Classifier|---+-->|    Remixer     |
+ *+----------------+       +----------------+   |   +-----------------+   |   +--------+-------+
+ *                                              |                         |            |
+ *                                              |   +-----------------+   |            |
+ *                                              +-->| Sound Classifier|---+            |
+ *                                                  +-----------------+                |
+ *                                                            |                        v
+ *                                                            v               +----------------+
+ *                                               {Classification Metadata}    |  Output Audio  |
+ *                                                                            +----------------+
+ *
+ * CLASSIFIER:
+ *+----------------+       +-----------------+       +-----------------+
+ *|   Input Audio  |------>| Sound Classifier|------>| Original Audio  |
+ *+----------------+       +-----------------+       +-----------------+
+ *                                  |
+ *                                  v
+ *                       {Classification Metadata}
+ *
+ */
+@VintfStability
+union Eraser {
+    /**
+     * Parameter Id with union tag to identify the parameters for getParameter().
+     */
+    @VintfStability
+    union Id {
+        VendorExtension vendorExtensionTag;
+        Eraser.Tag commonTag;
+    }
+
+    /**
+     * Vendor extension parameters which can be customized.
+     */
+    VendorExtension vendor;
+
+    /**
+     * Eraser capability, defines supported input/output data formats, available work modes, and
+     * the specific capabilities of the sound classifier and separator
+     */
+    Capability capability;
+
+    /**
+     * Eraser configuration, contains the list of configurations for the eraser effect.
+     */
+    Configuration configuration;
+}
diff --git a/audio/aidl/android/hardware/audio/effect/Parameter.aidl b/audio/aidl/android/hardware/audio/effect/Parameter.aidl
index 6fd9161..d57e67d 100644
--- a/audio/aidl/android/hardware/audio/effect/Parameter.aidl
+++ b/audio/aidl/android/hardware/audio/effect/Parameter.aidl
@@ -26,6 +26,7 @@
 import android.hardware.audio.effect.DynamicsProcessing;
 import android.hardware.audio.effect.EnvironmentalReverb;
 import android.hardware.audio.effect.Equalizer;
+import android.hardware.audio.effect.Eraser;
 import android.hardware.audio.effect.HapticGenerator;
 import android.hardware.audio.effect.LoudnessEnhancer;
 import android.hardware.audio.effect.NoiseSuppression;
@@ -111,6 +112,10 @@
          * Parameter tag defined for Spatializer parameters.
          */
         Spatializer.Id spatializerTag;
+        /**
+         * Parameter tag defined for eraser parameters.
+         */
+        Eraser.Id eraserTag;
     }
 
     /**
@@ -198,6 +203,8 @@
         Visualizer visualizer;
         Volume volume;
         Spatializer spatializer;
+        // Eraser added at android.hardware.audio.effect.V3
+        Eraser eraser;
     }
     Specific specific;
 
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/audio_effects_config.xml b/audio/aidl/default/audio_effects_config.xml
index a54f4db..2cef9eb 100644
--- a/audio/aidl/default/audio_effects_config.xml
+++ b/audio/aidl/default/audio_effects_config.xml
@@ -36,6 +36,7 @@
         <library name="downmix" path="libdownmixaidl.so"/>
         <library name="dynamics_processing" path="libdynamicsprocessingaidl.so"/>
         <library name="equalizersw" path="libequalizersw.so"/>
+        <library name="erasersw" path="liberasersw.so"/>
         <library name="haptic_generator" path="libhapticgeneratoraidl.so"/>
         <library name="loudness_enhancer" path="libloudnessenhanceraidl.so"/>
         <library name="nssw" path="libnssw.so"/>
diff --git a/audio/aidl/default/eraser/Android.bp b/audio/aidl/default/eraser/Android.bp
new file mode 100644
index 0000000..c495d8e
--- /dev/null
+++ b/audio/aidl/default/eraser/Android.bp
@@ -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 {
+    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"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_library_shared {
+    name: "liberasersw",
+    defaults: [
+        "aidlaudioeffectservice_defaults",
+    ],
+    srcs: [
+        "Eraser.cpp",
+        ":effectCommonFile",
+    ],
+    relative_install_path: "soundfx",
+    visibility: [
+        "//hardware/interfaces/audio/aidl/default:__subpackages__",
+    ],
+}
diff --git a/audio/aidl/default/eraser/Eraser.cpp b/audio/aidl/default/eraser/Eraser.cpp
new file mode 100644
index 0000000..157ec79
--- /dev/null
+++ b/audio/aidl/default/eraser/Eraser.cpp
@@ -0,0 +1,187 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "AHAL_Eraser"
+
+#include "Eraser.h"
+
+#include <android-base/logging.h>
+#include <system/audio_effects/effect_uuid.h>
+
+#include <optional>
+
+using aidl::android::hardware::audio::common::getChannelCount;
+using aidl::android::hardware::audio::effect::Descriptor;
+using aidl::android::hardware::audio::effect::EraserSw;
+using aidl::android::hardware::audio::effect::getEffectImplUuidEraserSw;
+using aidl::android::hardware::audio::effect::getEffectTypeUuidEraser;
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::State;
+using aidl::android::media::audio::common::AudioChannelLayout;
+using aidl::android::media::audio::common::AudioUuid;
+
+extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
+                                           std::shared_ptr<IEffect>* instanceSpp) {
+    if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidEraserSw()) {
+        LOG(ERROR) << __func__ << "uuid not supported";
+        return EX_ILLEGAL_ARGUMENT;
+    }
+    if (!instanceSpp) {
+        LOG(ERROR) << __func__ << " invalid input parameter!";
+        return EX_ILLEGAL_ARGUMENT;
+    }
+
+    *instanceSpp = ndk::SharedRefBase::make<EraserSw>();
+    LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
+    return EX_NONE;
+}
+
+extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
+    if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidEraserSw()) {
+        LOG(ERROR) << __func__ << "uuid not supported";
+        return EX_ILLEGAL_ARGUMENT;
+    }
+    *_aidl_return = EraserSw::kDescriptor;
+    return EX_NONE;
+}
+
+namespace aidl::android::hardware::audio::effect {
+
+const std::string EraserSw::kEffectName = "EraserSw";
+const Descriptor EraserSw::kDescriptor = {
+        .common = {.id = {.type = getEffectTypeUuidEraser(), .uuid = getEffectImplUuidEraserSw()},
+                   .flags = {.type = Flags::Type::INSERT,
+                             .insert = Flags::Insert::FIRST,
+                             .hwAcceleratorMode = Flags::HardwareAccelerator::NONE},
+                   .name = EraserSw::kEffectName,
+                   .implementor = "The Android Open Source Project"}};
+
+ndk::ScopedAStatus EraserSw::getDescriptor(Descriptor* _aidl_return) {
+    LOG(DEBUG) << __func__ << kDescriptor.toString();
+    *_aidl_return = kDescriptor;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EraserSw::setParameterSpecific(const Parameter::Specific& specific) {
+    RETURN_IF(Parameter::Specific::eraser != specific.getTag(), EX_ILLEGAL_ARGUMENT,
+              "EffectNotSupported");
+    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+    auto& param = specific.get<Parameter::Specific::eraser>();
+    return mContext->setParam(param.getTag(), param);
+}
+
+ndk::ScopedAStatus EraserSw::getParameterSpecific(const Parameter::Id& id,
+                                                  Parameter::Specific* specific) {
+    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+    auto tag = id.getTag();
+    RETURN_IF(Parameter::Id::eraserTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
+    auto eraserId = id.get<Parameter::Id::eraserTag>();
+    auto eraserTag = eraserId.getTag();
+    switch (eraserTag) {
+        case Eraser::Id::commonTag: {
+            auto specificTag = eraserId.get<Eraser::Id::commonTag>();
+            std::optional<Eraser> param = mContext->getParam(specificTag);
+            if (!param.has_value()) {
+                return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                        "EraserTagNotSupported");
+            }
+            specific->set<Parameter::Specific::eraser>(param.value());
+            break;
+        }
+        default: {
+            LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                    "EraserTagNotSupported");
+        }
+    }
+    return ndk::ScopedAStatus::ok();
+}
+
+std::shared_ptr<EffectContext> EraserSw::createContext(const Parameter::Common& common) {
+    if (mContext) {
+        LOG(DEBUG) << __func__ << " context already exist";
+    } else {
+        mContext = std::make_shared<EraserSwContext>(1 /* statusFmqDepth */, common);
+    }
+    return mContext;
+}
+
+RetCode EraserSw::releaseContext() {
+    if (mContext) {
+        mContext.reset();
+    }
+    return RetCode::SUCCESS;
+}
+
+EraserSw::~EraserSw() {
+    cleanUp();
+    LOG(DEBUG) << __func__;
+}
+
+// Processing method running in EffectWorker thread.
+IEffect::Status EraserSw::effectProcessImpl(float* in, float* out, int samples) {
+    RETURN_VALUE_IF(!mContext, (IEffect::Status{EX_NULL_POINTER, 0, 0}), "nullContext");
+    return mContext->process(in, out, samples);
+}
+
+EraserSwContext::EraserSwContext(int statusDepth, const Parameter::Common& common)
+    : EffectContext(statusDepth, common) {
+    LOG(DEBUG) << __func__;
+}
+
+EraserSwContext::~EraserSwContext() {
+    LOG(DEBUG) << __func__;
+}
+
+template <typename TAG>
+std::optional<Eraser> EraserSwContext::getParam(TAG tag) {
+    if (mParamsMap.find(tag) != mParamsMap.end()) {
+        return mParamsMap.at(tag);
+    }
+    return std::nullopt;
+}
+
+template <typename TAG>
+ndk::ScopedAStatus EraserSwContext::setParam(TAG tag, Eraser eraser) {
+    mParamsMap[tag] = eraser;
+    return ndk::ScopedAStatus::ok();
+}
+
+IEffect::Status EraserSwContext::process(float* in, float* out, int samples) {
+    LOG(DEBUG) << __func__ << " in " << in << " out " << out << " samples " << samples;
+    IEffect::Status status = {EX_ILLEGAL_ARGUMENT, 0, 0};
+
+    const auto inputChannelCount = getChannelCount(mCommon.input.base.channelMask);
+    const auto outputChannelCount = getChannelCount(mCommon.output.base.channelMask);
+    if (inputChannelCount < outputChannelCount) {
+        LOG(ERROR) << __func__ << " invalid channel count, in: " << inputChannelCount
+                   << " out: " << outputChannelCount;
+        return status;
+    }
+
+    int iFrames = samples / inputChannelCount;
+    for (int i = 0; i < iFrames; i++) {
+        std::memcpy(out, in, outputChannelCount);
+        in += inputChannelCount;
+        out += outputChannelCount;
+    }
+    return {STATUS_OK, static_cast<int32_t>(iFrames * inputChannelCount),
+            static_cast<int32_t>(iFrames * outputChannelCount)};
+}
+
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/eraser/Eraser.h b/audio/aidl/default/eraser/Eraser.h
new file mode 100644
index 0000000..0d4eb8f
--- /dev/null
+++ b/audio/aidl/default/eraser/Eraser.h
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include "effect-impl/EffectContext.h"
+#include "effect-impl/EffectImpl.h"
+
+#include <fmq/AidlMessageQueue.h>
+
+#include <unordered_map>
+#include <vector>
+
+namespace aidl::android::hardware::audio::effect {
+
+class EraserSwContext final : public EffectContext {
+  public:
+    EraserSwContext(int statusDepth, const Parameter::Common& common);
+    ~EraserSwContext() final;
+
+    template <typename TAG>
+    std::optional<Eraser> getParam(TAG tag);
+    template <typename TAG>
+    ndk::ScopedAStatus setParam(TAG tag, Eraser eraser);
+
+    IEffect::Status process(float* in, float* out, int samples);
+
+  private:
+    std::unordered_map<Eraser::Tag, Eraser> mParamsMap;
+};
+
+class EraserSw final : public EffectImpl {
+  public:
+    static const std::string kEffectName;
+    static const Capability kCapability;
+    static const Descriptor kDescriptor;
+    ~EraserSw() final;
+
+    ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) final;
+    ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific)
+            REQUIRES(mImplMutex) final;
+    ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id, Parameter::Specific* specific)
+            REQUIRES(mImplMutex) final;
+
+    std::shared_ptr<EffectContext> createContext(const Parameter::Common& common)
+            REQUIRES(mImplMutex) final;
+    RetCode releaseContext() REQUIRES(mImplMutex) final;
+
+    std::string getEffectName() final { return kEffectName; };
+    IEffect::Status effectProcessImpl(float* in, float* out, int samples)
+            REQUIRES(mImplMutex) final;
+
+  private:
+    static const std::vector<Range::SpatializerRange> kRanges;
+    std::shared_ptr<EraserSwContext> mContext GUARDED_BY(mImplMutex);
+};
+}  // namespace aidl::android::hardware::audio::effect
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 c1c1f03..46e384e 100644
--- a/audio/aidl/default/primary/StreamPrimary.cpp
+++ b/audio/aidl/default/primary/StreamPrimary.cpp
@@ -218,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);
 }
 
@@ -241,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();
 }
 
@@ -254,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);
 }
 
@@ -272,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/audio/aidl/vts/Android.bp b/audio/aidl/vts/Android.bp
index 85d400e..9ebe518 100644
--- a/audio/aidl/vts/Android.bp
+++ b/audio/aidl/vts/Android.bp
@@ -14,6 +14,7 @@
         "latest_android_hardware_audio_common_ndk_static",
         "latest_android_hardware_audio_effect_ndk_static",
         "latest_android_media_audio_common_types_ndk_static",
+        "latest_android_media_audio_eraser_types_ndk_static",
         "use_libaidlvintf_gtest_helper_static",
         "VtsHalTargetTestDefaults",
     ],
diff --git a/audio/aidl/vts/VtsHalVisualizerTargetTest.cpp b/audio/aidl/vts/VtsHalVisualizerTargetTest.cpp
index f89cb40..a0e43bc 100644
--- a/audio/aidl/vts/VtsHalVisualizerTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalVisualizerTargetTest.cpp
@@ -48,27 +48,23 @@
         std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int, Visualizer::ScalingMode,
                    Visualizer::MeasurementMode, int>;
 
-class VisualizerParamTest : public ::testing::TestWithParam<VisualizerParamTestParam>,
-                            public EffectHelper {
+class VisualizerTestHelper : public EffectHelper {
   public:
-    VisualizerParamTest()
-        : mCaptureSize(std::get<PARAM_CAPTURE_SIZE>(GetParam())),
-          mScalingMode(std::get<PARAM_SCALING_MODE>(GetParam())),
-          mMeasurementMode(std::get<PARAM_MEASUREMENT_MODE>(GetParam())),
-          mLatency(std::get<PARAM_LATENCY>(GetParam())) {
-        std::tie(mFactory, mDescriptor) = std::get<PARAM_INSTANCE_NAME>(GetParam());
-
-        size_t channelCount =
-                getChannelCount(AudioChannelLayout::make<AudioChannelLayout::layoutMask>(
-                        AudioChannelLayout::LAYOUT_STEREO));
-        mBufferSizeInFrames = kInputFrameCount * channelCount;
-        mInputBuffer.resize(mBufferSizeInFrames);
-        generateInputBuffer(mInputBuffer, 0, true, channelCount, kMaxAudioSampleValue);
-
-        mOutputBuffer.resize(mBufferSizeInFrames);
+    VisualizerTestHelper(
+            std::pair<std::shared_ptr<IFactory>, Descriptor> descPair = {}, int captureSize = 128,
+            int latency = 0,
+            Visualizer::ScalingMode scalingMode = Visualizer::ScalingMode::NORMALIZED,
+            Visualizer::MeasurementMode measurementMode = Visualizer::MeasurementMode::NONE)
+        : mCaptureSize(captureSize),
+          mLatency(latency),
+          mScalingMode(scalingMode),
+          mMeasurementMode(measurementMode),
+          mInputBuffer(mBufferSizeInFrames),
+          mOutputBuffer(mBufferSizeInFrames) {
+        std::tie(mFactory, mDescriptor) = descPair;
     }
 
-    void SetUp() override {
+    void SetUpVisualizer() {
         ASSERT_NE(nullptr, mFactory);
         ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
 
@@ -80,28 +76,14 @@
         mVersion = EffectFactoryHelper::getHalVersion(mFactory);
     }
 
-    void TearDown() override {
+    void TearDownVisualizer() {
         ASSERT_NO_FATAL_FAILURE(close(mEffect));
         ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
         mOpenEffectReturn = IEffect::OpenEffectReturn{};
     }
 
-    static const long kInputFrameCount = 0x100, kOutputFrameCount = 0x100;
-    std::shared_ptr<IFactory> mFactory;
-    std::shared_ptr<IEffect> mEffect;
-    Descriptor mDescriptor;
-    int mCaptureSize;
-    Visualizer::ScalingMode mScalingMode = Visualizer::ScalingMode::NORMALIZED;
-    Visualizer::MeasurementMode mMeasurementMode = Visualizer::MeasurementMode::NONE;
-    int mLatency = 0;
-    int mVersion = 0;
-    std::vector<float> mInputBuffer;
-    std::vector<float> mOutputBuffer;
-    size_t mBufferSizeInFrames;
-    IEffect::OpenEffectReturn mOpenEffectReturn;
-    bool mAllParamsValid = true;
-
-    void SetAndGetParameters() {
+    void SetAndGetParameters(bool* allParamsValid = nullptr) {
+        if (allParamsValid != nullptr) *allParamsValid = true;
         for (auto& it : mCommonTags) {
             auto& tag = it.first;
             auto& vs = it.second;
@@ -111,7 +93,9 @@
             ASSERT_STATUS(EX_NONE, mEffect->getDescriptor(&desc));
             const bool valid = isParameterValid<Visualizer, Range::visualizer>(vs, desc);
             const binder_exception_t expected = valid ? EX_NONE : EX_ILLEGAL_ARGUMENT;
-            if (expected == EX_ILLEGAL_ARGUMENT) mAllParamsValid = false;
+            if (expected == EX_ILLEGAL_ARGUMENT && allParamsValid != nullptr) {
+                *allParamsValid = false;
+            }
 
             // set parameter
             Parameter expectParam;
@@ -155,6 +139,44 @@
                 {Visualizer::latencyMs, Visualizer::make<Visualizer::latencyMs>(latency)});
     }
 
+    static constexpr long kInputFrameCount = 0x100, kOutputFrameCount = 0x100;
+    const size_t mChannelCount =
+            getChannelCount(AudioChannelLayout::make<AudioChannelLayout::layoutMask>(
+                    AudioChannelLayout::LAYOUT_STEREO));
+    const size_t mBufferSizeInFrames = kInputFrameCount * mChannelCount;
+    const int mCaptureSize;
+    const int mLatency;
+    const Visualizer::ScalingMode mScalingMode;
+    const Visualizer::MeasurementMode mMeasurementMode;
+    int mVersion;
+    std::vector<float> mInputBuffer;
+    std::vector<float> mOutputBuffer;
+    std::shared_ptr<IEffect> mEffect;
+    std::shared_ptr<IFactory> mFactory;
+    Descriptor mDescriptor;
+    IEffect::OpenEffectReturn mOpenEffectReturn;
+
+  private:
+    std::vector<std::pair<Visualizer::Tag, Visualizer>> mCommonTags;
+    void CleanUp() { mCommonTags.clear(); }
+};
+
+class VisualizerParamTest : public ::testing::TestWithParam<VisualizerParamTestParam>,
+                            public VisualizerTestHelper {
+  public:
+    VisualizerParamTest()
+        : VisualizerTestHelper(std::get<PARAM_INSTANCE_NAME>(GetParam()),
+                               std::get<PARAM_CAPTURE_SIZE>(GetParam()),
+                               std::get<PARAM_LATENCY>(GetParam()),
+                               std::get<PARAM_SCALING_MODE>(GetParam()),
+                               std::get<PARAM_MEASUREMENT_MODE>(GetParam())) {
+        generateInputBuffer(mInputBuffer, 0, true, mChannelCount, kMaxAudioSampleValue);
+    }
+
+    void SetUp() override { SetUpVisualizer(); }
+
+    void TearDown() override { TearDownVisualizer(); }
+
     static std::unordered_set<Visualizer::MeasurementMode> getMeasurementModeValues() {
         return {ndk::enum_range<Visualizer::MeasurementMode>().begin(),
                 ndk::enum_range<Visualizer::MeasurementMode>().end()};
@@ -164,10 +186,6 @@
         return {ndk::enum_range<Visualizer::ScalingMode>().begin(),
                 ndk::enum_range<Visualizer::ScalingMode>().end()};
     }
-
-  private:
-    std::vector<std::pair<Visualizer::Tag, Visualizer>> mCommonTags;
-    void CleanUp() { mCommonTags.clear(); }
 };
 
 TEST_P(VisualizerParamTest, SetAndGetCaptureSize) {
@@ -192,11 +210,13 @@
 
 TEST_P(VisualizerParamTest, testCaptureSampleBufferSizeAndOutput) {
     SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags);
+
+    bool allParamsValid = true;
     ASSERT_NO_FATAL_FAILURE(addCaptureSizeParam(mCaptureSize));
     ASSERT_NO_FATAL_FAILURE(addScalingModeParam(mScalingMode));
     ASSERT_NO_FATAL_FAILURE(addMeasurementModeParam(mMeasurementMode));
     ASSERT_NO_FATAL_FAILURE(addLatencyParam(mLatency));
-    ASSERT_NO_FATAL_FAILURE(SetAndGetParameters());
+    ASSERT_NO_FATAL_FAILURE(SetAndGetParameters(&allParamsValid));
 
     Parameter getParam;
     Parameter::Id id;
@@ -209,7 +229,7 @@
                                                     &mOpenEffectReturn, mVersion));
     ASSERT_EQ(mInputBuffer, mOutputBuffer);
 
-    if (mAllParamsValid) {
+    if (allParamsValid) {
         std::vector<uint8_t> captureBuffer = getParam.get<Parameter::specific>()
                                                      .get<Parameter::Specific::visualizer>()
                                                      .get<Visualizer::captureSampleBuffer>();
diff --git a/audio/aidl/vts/VtsHalVolumeTargetTest.cpp b/audio/aidl/vts/VtsHalVolumeTargetTest.cpp
index 2c21d2e..4300801 100644
--- a/audio/aidl/vts/VtsHalVolumeTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalVolumeTargetTest.cpp
@@ -108,16 +108,13 @@
  * Here we focus on specific parameter checking, general IEffect interfaces testing performed in
  * VtsAudioEffectTargetTest.
  */
-enum ParamName { PARAM_INSTANCE_NAME, PARAM_LEVEL, PARAM_MUTE };
-using VolumeParamTestParam =
-        std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int, bool>;
+enum VolumeLevelParamName { PARAM_INSTANCE_NAME, PARAM_LEVEL };
+using VolumeLevelTestParam = std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, int>;
 
-class VolumeParamTest : public ::testing::TestWithParam<VolumeParamTestParam>,
-                        public VolumeControlHelper {
+class VolumeLevelParamTest : public ::testing::TestWithParam<VolumeLevelTestParam>,
+                             public VolumeControlHelper {
   public:
-    VolumeParamTest()
-        : mParamLevel(std::get<PARAM_LEVEL>(GetParam())),
-          mParamMute(std::get<PARAM_MUTE>(GetParam())) {
+    VolumeLevelParamTest() : mParamLevel(std::get<PARAM_LEVEL>(GetParam())) {
         std::tie(mFactory, mDescriptor) = std::get<PARAM_INSTANCE_NAME>(GetParam());
     }
 
@@ -125,13 +122,31 @@
     void TearDown() override { TearDownVolumeControl(); }
 
     int mParamLevel = 0;
-    bool mParamMute = false;
 };
 
-TEST_P(VolumeParamTest, SetAndGetParams) {
+TEST_P(VolumeLevelParamTest, SetAndGetParams) {
     ASSERT_NO_FATAL_FAILURE(
             setAndVerifyParameters(Volume::levelDb, mParamLevel,
                                    isLevelValid(mParamLevel) ? EX_NONE : EX_ILLEGAL_ARGUMENT));
+}
+
+enum VolumeMuteParamName { MUTE_PARAM_INSTANCE_NAME, PARAM_MUTE };
+using VolumeMuteTestParam = std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>, bool>;
+
+class VolumeMuteParamTest : public ::testing::TestWithParam<VolumeMuteTestParam>,
+                            public VolumeControlHelper {
+  public:
+    VolumeMuteParamTest() : mParamMute(std::get<PARAM_MUTE>(GetParam())) {
+        std::tie(mFactory, mDescriptor) = std::get<MUTE_PARAM_INSTANCE_NAME>(GetParam());
+    }
+
+    void SetUp() override { ASSERT_NO_FATAL_FAILURE(SetUpVolumeControl()); }
+    void TearDown() override { TearDownVolumeControl(); }
+
+    bool mParamMute = false;
+};
+
+TEST_P(VolumeMuteParamTest, SetAndGetParams) {
     ASSERT_NO_FATAL_FAILURE(setAndVerifyParameters(Volume::mute, mParamMute, EX_NONE));
 }
 
@@ -298,25 +313,40 @@
 
 std::vector<std::pair<std::shared_ptr<IFactory>, Descriptor>> kDescPair;
 INSTANTIATE_TEST_SUITE_P(
-        VolumeTest, VolumeParamTest,
+        VolumeTest, VolumeLevelParamTest,
         ::testing::Combine(
                 testing::ValuesIn(kDescPair = EffectFactoryHelper::getAllEffectDescriptors(
                                           IFactory::descriptor, getEffectTypeUuidVolume())),
                 testing::ValuesIn(
                         EffectHelper::getTestValueSet<Volume, int, Range::volume, Volume::levelDb>(
-                                kDescPair, EffectHelper::expandTestValueBasic<int>)),
-                testing::Bool() /* mute */),
-        [](const testing::TestParamInfo<VolumeParamTest::ParamType>& info) {
+                                kDescPair, EffectHelper::expandTestValueBasic<int>))),
+        [](const testing::TestParamInfo<VolumeLevelParamTest::ParamType>& info) {
             auto descriptor = std::get<PARAM_INSTANCE_NAME>(info.param).second;
             std::string level = std::to_string(std::get<PARAM_LEVEL>(info.param));
-            std::string mute = std::to_string(std::get<PARAM_MUTE>(info.param));
-            std::string name = getPrefix(descriptor) + "_level" + level + "_mute" + mute;
+            std::string name = getPrefix(descriptor) + "_level" + level;
             std::replace_if(
                     name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
             return name;
         });
 
-GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VolumeParamTest);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VolumeLevelParamTest);
+
+INSTANTIATE_TEST_SUITE_P(
+        VolumeTest, VolumeMuteParamTest,
+        ::testing::Combine(
+                testing::ValuesIn(kDescPair = EffectFactoryHelper::getAllEffectDescriptors(
+                                          IFactory::descriptor, getEffectTypeUuidVolume())),
+                testing::Bool() /* mute */),
+        [](const testing::TestParamInfo<VolumeMuteParamTest::ParamType>& info) {
+            auto descriptor = std::get<MUTE_PARAM_INSTANCE_NAME>(info.param).second;
+            std::string mute = std::to_string(std::get<PARAM_MUTE>(info.param));
+            std::string name = getPrefix(descriptor) + "_mute" + mute;
+            std::replace_if(
+                    name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
+            return name;
+        });
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VolumeMuteParamTest);
 
 INSTANTIATE_TEST_SUITE_P(VolumeTest, VolumeDataTest,
                          testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
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/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/1.0/vts/functional/Android.bp b/automotive/evs/1.0/vts/functional/Android.bp
index f1b57d7..bad193b 100644
--- a/automotive/evs/1.0/vts/functional/Android.bp
+++ b/automotive/evs/1.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_perception_virtualization",
     // 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/1.1/vts/functional/Android.bp b/automotive/evs/1.1/vts/functional/Android.bp
index 18687bf..8f9d5c7 100644
--- a/automotive/evs/1.1/vts/functional/Android.bp
+++ b/automotive/evs/1.1/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_perception_virtualization",
     // 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/vts/Android.bp b/automotive/evs/aidl/vts/Android.bp
index e50c913..79905fa 100644
--- a/automotive/evs/aidl/vts/Android.bp
+++ b/automotive/evs/aidl/vts/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_perception_virtualization",
     // 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/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/sv/1.0/vts/functional/Android.bp b/automotive/sv/1.0/vts/functional/Android.bp
index e94893c..4ea5aff 100644
--- a/automotive/sv/1.0/vts/functional/Android.bp
+++ b/automotive/sv/1.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_perception_virtualization",
     // 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"
@@ -45,7 +46,10 @@
         "android.hidl.memory@1.0",
         "libhidlmemory",
     ],
-    test_suites: ["general-tests", "vts"],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
     cflags: [
         "-O0",
         "-g",
diff --git a/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp b/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp
index 4891bf5..ad34a4c 100644
--- a/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp
+++ b/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp
@@ -1849,6 +1849,12 @@
     std::this_thread::sleep_for(std::chrono::seconds(3));
 
     auto maybeResults = getCallback()->nextOnPropertyEventResults();
+    size_t retryCount = 0;
+    // Add a 1s (100ms * 10) buffer time.
+    while (!maybeResults.has_value() && retryCount < 10) {
+        retryCount++;
+        std::this_thread::sleep_for(std::chrono::milliseconds(100));
+    }
     ASSERT_TRUE(maybeResults.has_value()) << "no results in callback";
     ASSERT_EQ(maybeResults.value().payloads.size(), static_cast<size_t>(1));
     VehiclePropValue gotValue = maybeResults.value().payloads[0];
diff --git a/automotive/vehicle/tools/translate_aidl_enums.py b/automotive/vehicle/tools/translate_aidl_enums.py
index a7c1808..53afef3 100644
--- a/automotive/vehicle/tools/translate_aidl_enums.py
+++ b/automotive/vehicle/tools/translate_aidl_enums.py
@@ -21,14 +21,16 @@
    ENUM_NAMETest.java files in cts/tests/tests/car/src/android/car/cts and
    packages/services/Car/tests/android_car_api_test/src/android/car/apitest
 
+   Also needs a flag name e.g. FLAG_ANDROID_VIC_VEHICLE_PROPERTIES
+
    Usage:
-   $ python translate_aidl_enums.py ENUM_NAME.aidl
+   $ python translate_aidl_enums.py ENUM_NAME.aidl FLAG_NAME
 """
 import os
 import sys
 
 LICENSE = """/*
- * Copyright (C) 2023 The Android Open Source Project
+ * 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.
@@ -45,15 +47,20 @@
 """
 
 class EnumParser:
-    def __init__(self, file_path, file_name):
+    def __init__(self, file_path, file_name, flag_name):
         self.filePath = file_path
         self.fileName = file_name
+        self.flagName = flag_name
         self.lowerFileName = self.fileName[0].lower() + self.fileName[1:]
+        self.enumNames = []
         self.enums = []
         self.outputMsg = []
         self.outputMsg.append(LICENSE)
         self.outputMsg.append("\npackage android.car.hardware.property;\n")
         self.outputMsg.append("""
+import static android.car.feature.Flags.{};
+
+import android.annotation.FlaggedApi;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 
@@ -61,26 +68,61 @@
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
-""")
+""".format(self.flagName))
+
+        comment_block = []
+        in_comment = False
 
         with open(self.filePath, 'r') as f:
-            for line in f.readlines()[16:]:
-                if line in ["package android.hardware.automotive.vehicle;\n",
-                            "@VintfStability\n",
-                            '@Backing(type="int")\n']:
+            lines = f.readlines()
+            for line in lines:
+                line = line.rstrip('\n')
+                if line.strip() in ["package android.hardware.automotive.vehicle;",
+                                    "@VintfStability",
+                                    '@Backing(type="int")']:
                     continue
 
-                msg = line
+                if line.strip().startswith('/**') or line.strip().startswith('/*'):
+                    in_comment = True
+                    comment_block.append(line + '\n')
+                    continue
+                elif in_comment:
+                    comment_block.append(line + '\n')
+                    if line.strip().endswith('*/'):
+                        in_comment = False
+                    continue
+                elif line.strip().startswith('*'):
+                    comment_block.append(line + '\n')
+                    continue
+
+                msg = line + '\n'
                 msgSplit = msg.strip().split()
                 if len(msgSplit) > 0 and msgSplit[0] == "enum":
+                    if comment_block:
+                        self.outputMsg.extend(comment_block)
+                        comment_block = []
+                    self.outputMsg.append("@FlaggedApi({})\n".format(self.flagName))
                     msgSplit[0] = "public final class"
                     msg = " ".join(msgSplit) + "\n"
+                    self.outputMsg.append(msg)
                 elif len(msgSplit) > 1 and msgSplit[1] == '=':
+                    if comment_block:
+                        indented_comment_block = [line for line in comment_block]
+                        self.outputMsg.extend(indented_comment_block)
+                        comment_block = []
                     msgSplit.insert(0, "    public static final int")
-                    self.enums.append(msgSplit[1])
-                    msgSplit[-1] = msgSplit[-1][:-1] + ";\n"
-                    msg = " ".join(msgSplit)
-                elif msg == "}\n":
+                    enum_name = msgSplit[1].strip()
+                    self.enumNames.append(enum_name)
+                    enum = msgSplit[3].strip(",")
+                    self.enums.append(enum)
+                    if msgSplit[-1].endswith(','):
+                        msgSplit[-1] = msgSplit[-1][:-1] + ";"
+                    msg = " ".join(msgSplit) + "\n"
+                    self.outputMsg.append(msg)
+                elif line.strip() == '}':
+                    if comment_block:
+                        self.outputMsg.extend(comment_block)
+                        comment_block = []
                     self.outputMsg.append("""
     private {2}() {{}}
 
@@ -101,17 +143,23 @@
     @Retention(RetentionPolicy.SOURCE)
     public @interface {2}Int {{}}\n""".format(self.lowerFileName, "{" + ", ".join(self.enums) + "}",
                                               self.fileName))
-                self.outputMsg.append(msg)
-        self.outputMsg.append("TODO: delete this line and manually update this file with app-facing documentation and necessary tags.\n")
+        self.outputMsg.append("}")
 
         self.outputMsgApiTest = []
         self.outputMsgApiTest.append(LICENSE)
         self.outputMsgApiTest.append("""package android.car.apitest;
 
+import static android.car.feature.Flags.{1};
+
 import static com.google.common.truth.Truth.assertWithMessage;
 
+import android.platform.test.annotations.RequiresFlagsEnabled;
+import android.platform.test.flag.junit.CheckFlagsRule;
+import android.platform.test.flag.junit.DeviceFlagsValueProvider;
+
 import androidx.test.filters.SmallTest;
 
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -122,6 +170,8 @@
 @SmallTest
 @RunWith(Parameterized.class)
 public class {0}Test {{
+    @Rule
+    public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
     private final int mJavaConstantValue;
     private final int mHalConstantValue;
 
@@ -133,56 +183,68 @@
     @Parameterized.Parameters
     public static Collection constantValues() {{
         return Arrays.asList(
-                new Object[][] {{""".format(self.fileName))
-        for enum in self.enums:
+                new Object[][] {{""".format(self.fileName, self.flagName))
+        for enum in self.enumNames:
             self.outputMsgApiTest.append("""
                         {{
                                 android.car.hardware.property.{0}.{1},
                                 android.hardware.automotive.vehicle.{0}.{1}
                         }},""".format(self.fileName, enum))
         self.outputMsgApiTest.append("""
-                });
-    }
+                }});
+    }}
 
     @Test
-    public void testMatchWithVehicleHal() {
+    @RequiresFlagsEnabled({})
+    public void testMatchWithVehicleHal() {{
         assertWithMessage("Java constant")
                 .that(mJavaConstantValue)
                 .isEqualTo(mHalConstantValue);
-    }
-}
-""")
+    }}
+}}
+""".format(self.flagName))
 
         self.outputMsgCtsTest = []
         self.outputMsgCtsTest.append(LICENSE)
         self.outputMsgCtsTest.append("""
 package android.car.cts;
 
+import static android.car.feature.Flags.{1};
+
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.common.truth.Truth.assertWithMessage;
 
 import android.car.cts.utils.VehiclePropertyUtils;
 import android.car.hardware.property.{0};
+import android.platform.test.annotations.RequiresFlagsEnabled;
+import android.platform.test.flag.junit.CheckFlagsRule;
+import android.platform.test.flag.junit.DeviceFlagsValueProvider;
 
+import org.junit.Rule;
 import org.junit.Test;
 
 import java.util.List;
 
 public class {0}Test {{
+    @Rule
+    public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
 
     @Test
-    public void testToString() {{""".format(self.fileName))
-        for enum in self.enums:
+    @RequiresFlagsEnabled({1})
+    public void testToString() {{""".format(self.fileName, self.flagName))
+        for enum in self.enumNames:
             self.outputMsgCtsTest.append("""
         assertThat({0}.toString(
                 {0}.{1}))
                 .isEqualTo("{1}");""".format(self.fileName, enum))
+        max_enum_value = len(self.enums)
         self.outputMsgCtsTest.append("""
         assertThat({0}.toString({1})).isEqualTo("{2}");
         assertThat({0}.toString(12)).isEqualTo("0xc");
     }}
 
     @Test
+    @RequiresFlagsEnabled({4})
     public void testAll{0}sAreMappedInToString() {{
         List<Integer> {3}s =
                 VehiclePropertyUtils.getIntegersFromDataEnums({0}.class);
@@ -194,11 +256,11 @@
         }}
     }}
 }}
-""".format(self.fileName, len(self.enums), hex(len(self.enums)), self.lowerFileName))
+""".format(self.fileName, len(self.enums), hex(len(self.enums)), self.lowerFileName, self.flagName))
 
 def main():
-    if len(sys.argv) != 2:
-        print("Usage: {} enum_aidl_file".format(sys.argv[0]))
+    if len(sys.argv) != 3:
+        print("Usage: {} enum_aidl_file ALL_CAPS_FLAG_NAME".format(sys.argv[0]))
         sys.exit(1)
     print("WARNING: This file only generates the base enum values in the framework layer. The "
           + "generated files must be reviewed by you and edited if any additional changes are "
@@ -207,12 +269,14 @@
           + "the new property is system API")
     file_path = sys.argv[1]
     file_name = file_path.split('/')[-1][:-5]
-    parser = EnumParser(file_path, file_name)
+    flag_name = sys.argv[2]
+    parser = EnumParser(file_path, file_name, flag_name)
 
     android_top = os.environ['ANDROID_BUILD_TOP']
     if not android_top:
         print('ANDROID_BUILD_TOP is not in environmental variable, please run source and lunch '
               + 'at the android root')
+        sys.exit(1)
 
     with open(android_top + "/packages/services/Car/car-lib/src/android/car/hardware/property/"
               + file_name + ".java", 'w') as f:
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/biometrics/face/1.0/vts/functional/Android.bp b/biometrics/face/1.0/vts/functional/Android.bp
index 259c4ec..4c06121 100644
--- a/biometrics/face/1.0/vts/functional/Android.bp
+++ b/biometrics/face/1.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_biometrics_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/biometrics/fingerprint/2.1/vts/functional/Android.bp b/biometrics/fingerprint/2.1/vts/functional/Android.bp
index 68b3360..819feb4 100644
--- a/biometrics/fingerprint/2.1/vts/functional/Android.bp
+++ b/biometrics/fingerprint/2.1/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_biometrics_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/biometrics/fingerprint/2.2/vts/functional/Android.bp b/biometrics/fingerprint/2.2/vts/functional/Android.bp
index 02f833a..11315fa 100644
--- a/biometrics/fingerprint/2.2/vts/functional/Android.bp
+++ b/biometrics/fingerprint/2.2/vts/functional/Android.bp
@@ -15,6 +15,7 @@
  */
 
 package {
+    default_team: "trendy_team_biometrics_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/1.0/vts/functional/Android.bp b/bluetooth/1.0/vts/functional/Android.bp
index 768142c..7d76b89 100644
--- a/bluetooth/1.0/vts/functional/Android.bp
+++ b/bluetooth/1.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_bluetooth",
     // 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/1.1/vts/functional/Android.bp b/bluetooth/1.1/vts/functional/Android.bp
index 7f56647..6b3a3e7 100644
--- a/bluetooth/1.1/vts/functional/Android.bp
+++ b/bluetooth/1.1/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_bluetooth",
     // 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/Android.bp b/bluetooth/aidl/vts/Android.bp
index c69ced4..a08bdfc 100644
--- a/bluetooth/aidl/vts/Android.bp
+++ b/bluetooth/aidl/vts/Android.bp
@@ -1,4 +1,5 @@
 package {
+    default_team: "trendy_team_bluetooth",
     // 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/bluetooth/audio/2.0/vts/functional/Android.bp b/bluetooth/audio/2.0/vts/functional/Android.bp
index f5cb956..65ad8d0 100644
--- a/bluetooth/audio/2.0/vts/functional/Android.bp
+++ b/bluetooth/audio/2.0/vts/functional/Android.bp
@@ -1,4 +1,5 @@
 package {
+    default_team: "trendy_team_bluetooth",
     // 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/audio/2.1/vts/functional/Android.bp b/bluetooth/audio/2.1/vts/functional/Android.bp
index cea7326..de858fc 100644
--- a/bluetooth/audio/2.1/vts/functional/Android.bp
+++ b/bluetooth/audio/2.1/vts/functional/Android.bp
@@ -1,4 +1,5 @@
 package {
+    default_team: "trendy_team_bluetooth",
     // 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/audio/aidl/vts/Android.bp b/bluetooth/audio/aidl/vts/Android.bp
index 884062a..b0b095d 100644
--- a/bluetooth/audio/aidl/vts/Android.bp
+++ b/bluetooth/audio/aidl/vts/Android.bp
@@ -1,4 +1,5 @@
 package {
+    default_team: "trendy_team_bluetooth",
     // 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/finder/aidl/vts/Android.bp b/bluetooth/finder/aidl/vts/Android.bp
index 6b0285e..49d2d45 100644
--- a/bluetooth/finder/aidl/vts/Android.bp
+++ b/bluetooth/finder/aidl/vts/Android.bp
@@ -13,6 +13,7 @@
 // limitations under the License.
 
 package {
+    default_team: "trendy_team_bluetooth",
     default_applicable_licenses: ["hardware_interfaces_license"],
 }
 
diff --git a/bluetooth/lmp_event/aidl/vts/Android.bp b/bluetooth/lmp_event/aidl/vts/Android.bp
index b89351e..a137434 100644
--- a/bluetooth/lmp_event/aidl/vts/Android.bp
+++ b/bluetooth/lmp_event/aidl/vts/Android.bp
@@ -1,5 +1,6 @@
 cc_test {
     name: "VtsHalLmpEventTargetTest",
+    team: "trendy_team_bluetooth",
     defaults: [
         "VtsHalTargetTestDefaults",
         "use_libaidlvintf_gtest_helper_static",
diff --git a/bluetooth/ranging/aidl/vts/Android.bp b/bluetooth/ranging/aidl/vts/Android.bp
index ead9992..9984ce8 100644
--- a/bluetooth/ranging/aidl/vts/Android.bp
+++ b/bluetooth/ranging/aidl/vts/Android.bp
@@ -1,4 +1,5 @@
 package {
+    default_team: "trendy_team_bluetooth",
     default_applicable_licenses: ["hardware_interfaces_license"],
 }
 
diff --git a/boot/1.0/vts/functional/Android.bp b/boot/1.0/vts/functional/Android.bp
index 90ee9cb..b49772c 100644
--- a/boot/1.0/vts/functional/Android.bp
+++ b/boot/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/boot/1.1/vts/functional/Android.bp b/boot/1.1/vts/functional/Android.bp
index 3a36046..6e44996 100644
--- a/boot/1.1/vts/functional/Android.bp
+++ b/boot/1.1/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/boot/1.2/vts/functional/Android.bp b/boot/1.2/vts/functional/Android.bp
index 7d546ed..ba186bf 100644
--- a/boot/1.2/vts/functional/Android.bp
+++ b/boot/1.2/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/boot/aidl/client/BootControlClient.cpp b/boot/aidl/client/BootControlClient.cpp
index 10f0ffe..5cca183 100644
--- a/boot/aidl/client/BootControlClient.cpp
+++ b/boot/aidl/client/BootControlClient.cpp
@@ -37,6 +37,17 @@
 
 using aidl::android::hardware::boot::MergeStatus;
 
+#define TEST_OP(_x, _y, op)                                                            \
+    do {                                                                               \
+        const auto& x = _x;                                                            \
+        const auto& y = _y;                                                            \
+        if (!(x op y)) {                                                               \
+            LOG(ERROR) << #_x " " #op " " #_y << " failed: " << x << " " #op " " << y; \
+            return {};                                                                 \
+        }                                                                              \
+    } while (0)
+#define TEST_NE(_x, _y) TEST_OP(_x, _y, !=)
+
 std::ostream& operator<<(std::ostream& os, MergeStatus status) {
     switch (status) {
         case MergeStatus::NONE:
@@ -79,31 +90,64 @@
 
     BootControlVersion GetVersion() const override { return BootControlVersion::BOOTCTL_AIDL; }
 
-    ~BootControlClientAidl() {
-        if (boot_control_death_recipient) {
-            AIBinder_unlinkToDeath(module_->asBinder().get(), boot_control_death_recipient, this);
+    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;
         }
     }
 
-    void onBootControlServiceDied() { LOG(ERROR) << "boot control service AIDL died"; }
-
     int32_t GetNumSlots() const override {
         int32_t ret = -1;
+        if (!module_) {
+            LOG(ERROR) << "bootctl module not set";
+            return ret;
+        }
         LOG_NDK_STATUS(module_->getNumberSlots(&ret));
         return ret;
     }
 
     int32_t GetCurrentSlot() const override {
         int32_t ret = -1;
+        if (!module_) {
+            LOG(ERROR) << "bootctl module not set";
+            return ret;
+        }
         LOG_NDK_STATUS(module_->getCurrentSlot(&ret));
         return ret;
     }
+
     MergeStatus getSnapshotMergeStatus() const override {
         MergeStatus status = MergeStatus::UNKNOWN;
+        if (!module_) {
+            LOG(ERROR) << "bootctl module not set";
+            return status;
+        }
         LOG_NDK_STATUS(module_->getSnapshotMergeStatus(&status));
         return status;
     }
+
     std::string GetSuffix(int32_t slot) const override {
+        TEST_NE(module_, nullptr);
         std::string ret;
         const auto status = module_->getSuffix(slot, &ret);
         if (!status.isOk()) {
@@ -115,6 +159,7 @@
     }
 
     std::optional<bool> IsSlotBootable(int32_t slot) const override {
+        TEST_NE(module_, nullptr);
         bool ret = false;
         const auto status = module_->isSlotBootable(slot, &ret);
         if (!status.isOk()) {
@@ -126,6 +171,7 @@
     }
 
     CommandResult MarkSlotUnbootable(int32_t slot) override {
+        TEST_NE(module_, nullptr);
         const auto status = module_->setSlotAsUnbootable(slot);
         if (!status.isOk()) {
             LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed "
@@ -135,6 +181,7 @@
     }
 
     CommandResult SetActiveBootSlot(int slot) override {
+        TEST_NE(module_, nullptr);
         const auto status = module_->setActiveBootSlot(slot);
         if (!status.isOk()) {
             LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed "
@@ -142,14 +189,20 @@
         }
         return {.success = status.isOk(), .errMsg = status.getDescription()};
     }
+
     int GetActiveBootSlot() const {
         int ret = -1;
+        if (!module_) {
+            LOG(ERROR) << "bootctl module not set";
+            return ret;
+        }
         LOG_NDK_STATUS(module_->getActiveBootSlot(&ret));
         return ret;
     }
 
     // Check if |slot| is marked boot successfully.
     std::optional<bool> IsSlotMarkedSuccessful(int slot) const override {
+        TEST_NE(module_, nullptr);
         bool ret = false;
         const auto status = module_->isSlotMarkedSuccessful(slot, &ret);
         if (!status.isOk()) {
@@ -161,6 +214,7 @@
     }
 
     CommandResult MarkBootSuccessful() override {
+        TEST_NE(module_, nullptr);
         const auto status = module_->markBootSuccessful();
         if (!status.isOk()) {
             LOG(ERROR) << __FUNCTION__ << " failed " << status.getDescription();
@@ -170,6 +224,7 @@
 
     CommandResult SetSnapshotMergeStatus(
             aidl::android::hardware::boot::MergeStatus merge_status) override {
+        TEST_NE(module_, nullptr);
         const auto status = module_->setSnapshotMergeStatus(merge_status);
         if (!status.isOk()) {
             LOG(ERROR) << __FUNCTION__ << "(" << merge_status << ")" << " failed "
@@ -179,7 +234,7 @@
     }
 
   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);
diff --git a/boot/aidl/vts/functional/Android.bp b/boot/aidl/vts/functional/Android.bp
index e46cbef..0310716 100644
--- a/boot/aidl/vts/functional/Android.bp
+++ b/boot/aidl/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/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/default/BroadcastRadio.cpp b/broadcastradio/aidl/default/BroadcastRadio.cpp
index 4d6d81d..015cae0 100644
--- a/broadcastradio/aidl/default/BroadcastRadio.cpp
+++ b/broadcastradio/aidl/default/BroadcastRadio.cpp
@@ -17,11 +17,9 @@
 #include "BroadcastRadio.h"
 #include <broadcastradio-utils-aidl/Utils.h>
 #include <broadcastradio-utils-aidl/UtilsV2.h>
+#include <broadcastradio-utils-aidl/UtilsV3.h>
 #include "resources.h"
 
-#include <aidl/android/hardware/broadcastradio/IdentifierType.h>
-#include <aidl/android/hardware/broadcastradio/Result.h>
-
 #include <android-base/logging.h>
 #include <android-base/strings.h>
 
@@ -47,6 +45,8 @@
 inline constexpr std::chrono::milliseconds kTuneDelayTimeMs = 150ms;
 inline constexpr std::chrono::seconds kListDelayTimeS = 1s;
 
+const string kAlertAreaDelimiter = "+";
+const string kAlertCoordinateGeocodeDelimiter = ",";
 // clang-format off
 const AmFmBandRange kFmFullBandRange = {65000, 108000, 10, 0};
 const AmFmBandRange kAmFullBandRange = {150, 30000, 1, 0};
@@ -142,6 +142,30 @@
     return info;
 }
 
+static Alert createSampleAlert() {
+    Polygon polygon = {{{-38.47, -120.14},
+                        {38.34, -119.95},
+                        {38.52, -119.74},
+                        {38.62, -119.89},
+                        {-38.47, -120.14}}};
+    AlertArea alertArea1 = {{polygon}, {{"SAME", "006109"}, {"SAME", "006209"}}};
+    AlertArea alertArea2 = {{}, {{"SAME", "006009"}}};
+    AlertInfo alertInfo;
+    alertInfo.categoryArray = {AlertCategory::GEO, AlertCategory::TRANSPORT};
+    alertInfo.urgency = AlertUrgency::FUTURE;
+    alertInfo.severity = AlertSeverity::SEVERE;
+    alertInfo.certainty = AlertCertainty::POSSIBLE;
+    alertInfo.description = "Sample radio alert.";
+    alertInfo.language = "en-US";
+    alertInfo.areas.push_back(alertArea1);
+    alertInfo.areas.push_back(alertArea2);
+    Alert alert;
+    alert.status = AlertStatus::ACTUAL;
+    alert.messageType = AlertMessageType::ALERT;
+    alert.infoArray.push_back(alertInfo);
+    return alert;
+}
+
 static bool checkDumpCallerHasWritePermissions(int fd) {
     uid_t uid = AIBinder_getCallingUid();
     if (uid == AID_ROOT || uid == AID_SHELL || uid == AID_SYSTEM) {
@@ -151,6 +175,87 @@
     return false;
 }
 
+static bool parseGeocode(int fd, const string& geocodeString, Geocode& parsedGeocode) {
+    vector<string> geocodeStringPair =
+            ::android::base::Split(geocodeString, kAlertCoordinateGeocodeDelimiter);
+    if (geocodeStringPair.size() != 2) {
+        dprintf(fd, "Geocode is not of \"VALUE_NAME,VALUE\" format: %s\n", geocodeString.c_str());
+        return false;
+    }
+    parsedGeocode.valueName = geocodeStringPair[0];
+    parsedGeocode.value = geocodeStringPair[1];
+    return true;
+}
+
+static bool parsePolygon(int fd, const string& polygonString, Polygon& parsedPolygon) {
+    vector<Coordinate> coordinates;
+    vector<string> coordinateStrings =
+            ::android::base::Split(polygonString, kAlertCoordinateGeocodeDelimiter);
+    if (coordinateStrings.size() % 2) {
+        dprintf(fd, "Incomplete \"LATITUDE,LONGITUDE\" coordinate pairs separated by \",\": %s\n",
+                polygonString.c_str());
+        return false;
+    }
+    for (size_t i = 0; i < coordinateStrings.size(); i += 2) {
+        double latitude;
+        double longitude;
+        if (!utils::parseArgDouble(coordinateStrings[i], &latitude) ||
+            !utils::parseArgDouble(coordinateStrings[i + 1], &longitude)) {
+            dprintf(fd, "Value of \"LATITUDE,LONGITUDE\" coordinate pair is not double-type: %s\n",
+                    coordinateStrings[i].c_str());
+            return false;
+        }
+        coordinates.push_back(Coordinate(latitude, longitude));
+    }
+    parsedPolygon.coordinates = coordinates;
+    return true;
+}
+
+static bool parseAreaString(int fd, const string& areaString, AlertArea& parsedAlertArea) {
+    vector<string> areaEntryStrings = ::android::base::Split(areaString, "_");
+    for (const auto& areaEntryString : areaEntryStrings) {
+        vector<string> areaTypeValuePair = ::android::base::Split(areaEntryString, ":");
+        if (areaTypeValuePair.size() != 2) {
+            dprintf(fd, "Area is not of \"<TYPE>:<VALUE>\" format: %s\n", areaEntryString.c_str());
+            return false;
+        }
+        if (EqualsIgnoreCase(areaTypeValuePair[0], "polygon")) {
+            Polygon parsedPolygon;
+            if (!parsePolygon(fd, areaTypeValuePair[1], parsedPolygon)) {
+                return false;
+            }
+            parsedAlertArea.polygons.push_back(parsedPolygon);
+        } else if (EqualsIgnoreCase(areaTypeValuePair[0], "geocode")) {
+            Geocode parsedGeocode;
+            if (!parseGeocode(fd, areaTypeValuePair[1], parsedGeocode)) {
+                return false;
+            }
+            parsedAlertArea.geocodes.push_back(parsedGeocode);
+        } else {
+            dprintf(fd, "Invalid area <TYPE> other than \"polygon\" and \"geocode\": %s\n",
+                    areaTypeValuePair[0].c_str());
+            return false;
+        }
+    }
+    return true;
+}
+
+static bool parseAreaListString(int fd, const string& areaListString,
+                                vector<AlertArea>& parsedAlertAreas) {
+    if (EqualsIgnoreCase(areaListString, kAlertAreaDelimiter)) {
+        return true;
+    }
+    vector<string> areaStrings = ::android::base::Split(areaListString, kAlertAreaDelimiter);
+    for (const auto& areaString : areaStrings) {
+        AlertArea parsedArea;
+        if (!parseAreaString(fd, areaString, parsedArea)) {
+            return false;
+        }
+        parsedAlertAreas.push_back(parsedArea);
+    }
+    return true;
+}
+
 }  // namespace
 
 BroadcastRadio::BroadcastRadio(const VirtualRadio& virtualRadio)
@@ -162,9 +267,9 @@
         ProgramSelector sel = utils::makeSelectorAmfm(ranges[0].lowerBound);
         VirtualProgram virtualProgram = {};
         if (mVirtualRadio.getProgram(sel, &virtualProgram)) {
-            mCurrentProgram = virtualProgram.selector;
+            mCurrentProgramSelector = virtualProgram.selector;
         } else {
-            mCurrentProgram = sel;
+            mCurrentProgramSelector = sel;
         }
         adjustAmFmRangeLocked();
     }
@@ -230,13 +335,13 @@
             isDigitalProgramAllowed(sel, isConfigFlagSetLocked(ConfigFlag::FORCE_ANALOG_FM),
                                     isConfigFlagSetLocked(ConfigFlag::FORCE_ANALOG_AM));
     if (isProgramAllowed && mVirtualRadio.getProgram(sel, &virtualProgram)) {
-        mCurrentProgram = virtualProgram.selector;
+        mCurrentProgramSelector = virtualProgram.selector;
         programInfo = virtualProgram;
     } else {
         if (!isProgramAllowed) {
-            mCurrentProgram = utils::makeSelectorAmfm(utils::getAmFmFrequency(sel));
+            mCurrentProgramSelector = utils::makeSelectorAmfm(utils::getAmFmFrequency(sel));
         } else {
-            mCurrentProgram = sel;
+            mCurrentProgramSelector = sel;
         }
         programInfo = makeSampleProgramInfo(sel);
     }
@@ -277,6 +382,10 @@
 void BroadcastRadio::handleProgramInfoUpdateRadioCallback(
         ProgramInfo programInfo, const std::shared_ptr<ITunerCallback>& callback) {
     callback->onCurrentProgramInfoChanged(programInfo);
+    {
+        lock_guard<mutex> lk(mMutex);
+        mCurrentProgramInfo = programInfo;
+    }
     if (programInfo.selector.primaryId.type != IdentifierType::HD_STATION_ID_EXT) {
         return;
     }
@@ -285,12 +394,14 @@
     programInfo.infoFlags |= ProgramInfo::FLAG_HD_SIS_ACQUISITION;
     auto sisAcquiredTask = [this, callback, programInfo, cancelTask]() {
         callback->onCurrentProgramInfoChanged(programInfo);
+        mCurrentProgramInfo = programInfo;
         auto audioAcquiredTask = [this, callback, programInfo]() {
             ProgramInfo hdProgramInfoWithAudio = programInfo;
             hdProgramInfoWithAudio.infoFlags |= ProgramInfo::FLAG_HD_AUDIO_ACQUISITION;
             callback->onCurrentProgramInfoChanged(hdProgramInfoWithAudio);
             lock_guard<mutex> lk(mMutex);
             mIsTuneCompleted = true;
+            mCurrentProgramInfo = hdProgramInfoWithAudio;
         };
         lock_guard<mutex> lk(mMutex);
         mTuningThread->schedule(audioAcquiredTask, cancelTask, kTuneDelayTimeMs);
@@ -481,7 +592,8 @@
     auto cancelTask = [callback]() { callback->onTuneFailed(Result::CANCELED, {}); };
 
     VirtualProgram nextProgram = {};
-    bool foundNext = findNextLocked(mCurrentProgram, directionUp, skipSubChannel, &nextProgram);
+    bool foundNext =
+            findNextLocked(mCurrentProgramSelector, directionUp, skipSubChannel, &nextProgram);
     mIsTuneCompleted = false;
     if (!foundNext) {
         auto task = [callback]() {
@@ -520,10 +632,10 @@
     cancelLocked();
 
     int64_t stepTo;
-    if (utils::hasId(mCurrentProgram, IdentifierType::AMFM_FREQUENCY_KHZ)) {
-        stepTo = utils::getId(mCurrentProgram, IdentifierType::AMFM_FREQUENCY_KHZ);
-    } else if (mCurrentProgram.primaryId.type == IdentifierType::HD_STATION_ID_EXT) {
-        stepTo = utils::getHdFrequency(mCurrentProgram);
+    if (utils::hasId(mCurrentProgramSelector, IdentifierType::AMFM_FREQUENCY_KHZ)) {
+        stepTo = utils::getId(mCurrentProgramSelector, IdentifierType::AMFM_FREQUENCY_KHZ);
+    } else if (mCurrentProgramSelector.primaryId.type == IdentifierType::HD_STATION_ID_EXT) {
+        stepTo = utils::getHdFrequency(mCurrentProgramSelector);
     } else {
         LOG(WARNING) << __func__ << ": can't step in anything else than AM/FM";
         return ScopedAStatus::fromServiceSpecificErrorWithMessage(
@@ -568,7 +680,7 @@
     LOG(DEBUG) << __func__ << ": cancelling current tuning operations...";
 
     mTuningThread->cancelAll();
-    if (mCurrentProgram.primaryId.type != IdentifierType::INVALID) {
+    if (mCurrentProgramSelector.primaryId.type != IdentifierType::INVALID) {
         mIsTuneCompleted = true;
     }
 }
@@ -692,13 +804,13 @@
 
 bool BroadcastRadio::adjustAmFmRangeLocked() {
     bool hasBandBefore = mCurrentAmFmBandRange.has_value();
-    if (!utils::hasAmFmFrequency(mCurrentProgram)) {
+    if (!utils::hasAmFmFrequency(mCurrentProgramSelector)) {
         LOG(WARNING) << __func__ << ": current program does not has AMFM_FREQUENCY_KHZ identifier";
         mCurrentAmFmBandRange.reset();
         return hasBandBefore;
     }
 
-    int32_t freq = static_cast<int32_t>(utils::getAmFmFrequency(mCurrentProgram));
+    int32_t freq = static_cast<int32_t>(utils::getAmFmFrequency(mCurrentProgramSelector));
     for (const auto& range : mAmFmConfig.ranges) {
         if (range.lowerBound <= freq && range.upperBound >= freq) {
             bool isBandChanged = hasBandBefore ? *mCurrentAmFmBandRange != range : true;
@@ -711,6 +823,24 @@
     return !hasBandBefore;
 }
 
+void BroadcastRadio::updateCurrentProgramInfoWithAlert(std::optional<Alert>& alert) {
+    std::shared_ptr<ITunerCallback> callback;
+    ProgramInfo currentProgramInfo;
+    {
+        lock_guard<mutex> lk(mMutex);
+        if (mCallback == nullptr) {
+            return;
+        }
+        if (mCurrentProgramInfo.selector.primaryId.type == IdentifierType::INVALID) {
+            return;
+        }
+        callback = mCallback;
+        currentProgramInfo = mCurrentProgramInfo;
+    }
+    currentProgramInfo.emergencyAlert = alert.value();
+    callback->onCurrentProgramInfoChanged(currentProgramInfo);
+}
+
 ScopedAStatus BroadcastRadio::registerAnnouncementListener(
         [[maybe_unused]] const std::shared_ptr<IAnnouncementListener>& listener,
         const vector<AnnouncementType>& enabled, std::shared_ptr<ICloseHandle>* returnCloseHandle) {
@@ -745,6 +875,8 @@
         return cmdStartProgramListUpdates(fd, args, numArgs);
     } else if (EqualsIgnoreCase(option, "--stopProgramListUpdates")) {
         return cmdStopProgramListUpdates(fd, numArgs);
+    } else if (EqualsIgnoreCase(option, "--simulateAlert")) {
+        return cmdSimulateAlert(fd, args, numArgs);
     }
     dprintf(fd, "Invalid option: %s\n", option.c_str());
     return STATUS_BAD_VALUE;
@@ -767,7 +899,7 @@
     } else {
         dprintf(fd, "ITunerCallback registered\n");
     }
-    dprintf(fd, "CurrentProgram: %s \n", mCurrentProgram.toString().c_str());
+    dprintf(fd, "CurrentProgram: %s \n", mCurrentProgramSelector.toString().c_str());
     return STATUS_OK;
 }
 
@@ -798,13 +930,41 @@
             "excludeModifications (string, should be either \"true\" or \"false\")\n");
     dprintf(fd, "--stopProgramListUpdates: stop current pending program list updates\n");
     dprintf(fd,
-            "Note on <TYPE> for --startProgramList command: it is int for identifier type. "
+            "\t<TYPE>: it is int for identifier type. "
             "Please see broadcastradio/aidl/android/hardware/broadcastradio/IdentifierType.aidl "
             "for its definition.\n");
     dprintf(fd,
-            "Note on <VALUE> for --startProgramList command: it is long type for identifier value. "
+            "\t<VALUE>: it is long type for identifier value. "
             "Please see broadcastradio/aidl/android/hardware/broadcastradio/IdentifierType.aidl "
             "for its value.\n");
+    dprintf(fd,
+            "--simulateAlert <STATUS> <MESSAGE_TYPE> <CATEGORIES> <URGENCY> <SEVERITY> "
+            "<CERTAINTY> <DESCRIPTION> <LANGUAGE> <AREAS>: simulate emergency alert on current "
+            "program; if no arguments following \"--simulateAlert\", the default alert message"
+            "is applied.\n");
+    dprintf(fd, "\t<STATUS>: string representation of alert scope.\n");
+    dprintf(fd, "\t<MESSAGE_TYPE>: string representation of alert message type.\n");
+    dprintf(fd,
+            "\t<CATEGORIES>: string representation of alert categories separated by "
+            "\",\".\n");
+    dprintf(fd, "\t<URGENCY>: string representation of alert urgency type.\n");
+    dprintf(fd, "\t<SEVERITY>: string representation of alert severity type.\n");
+    dprintf(fd, "\t<CERTAINTY>: string representation of alert certainty type.\n");
+    dprintf(fd, "\t<DESCRIPTION>: description of alert message within quotation mark(\"\").\n");
+    dprintf(fd, "\t<LANGUAGE>: language code of alert message, \"null\" if unspecified.\n");
+    dprintf(fd,
+            "\t<AREAS>: <TYPE>:<VALUE>_<TYPE>:<VALUE>_...+<TYPE>:<VALUE>_<TYPE>:<VALUE>_... "
+            "which represents list of affected areas of the alert separated by \"|\". "
+            "If no area, this field should be: |\n"
+            "Each area may contains multiple entries separated by \";\" where "
+            "<TYPE> can be either \"polygon\" or \"geocode\". If <TYPE> is polygon, <VALUE> is a "
+            "series of coordinates of \"LATITUDE,LONGITUDE\" format separated by \",\"; if "
+            "<TYPE> is geocode, <VALUE> is of \"VALUE_NAME,VALUE\" format.\n");
+    dprintf(fd,
+            "Example: --simulateAlert actual alert geo,transport future severe"
+            " possible \"alert message for testing\" en-US geocode:SAME,006109_geocode:SAME,006209"
+            "_polygon:-38.47,-120.14,38.34,-119.95,38.52,-119.74,38.62,-119.89,-38.47,-120.14"
+            "+geocode:SAME,006009\n");
 
     return STATUS_OK;
 }
@@ -1038,4 +1198,71 @@
     return STATUS_OK;
 }
 
+binder_status_t BroadcastRadio::cmdSimulateAlert(int fd, const char** args, uint32_t numArgs) {
+    if (!checkDumpCallerHasWritePermissions(fd)) {
+        return STATUS_PERMISSION_DENIED;
+    }
+    std::optional<Alert> alertOpt;
+    if (numArgs == 1) {
+        alertOpt.emplace(createSampleAlert());
+        updateCurrentProgramInfoWithAlert(alertOpt);
+        return STATUS_OK;
+    }
+    if (numArgs != 10) {
+        dprintf(fd,
+                "Invalid number of arguments: please provide --simulateAlert "
+                "<STATUS> <MESSAGE_TYPE> <CATEGORIES> <URGENCY> "
+                "<SEVERITY> <CERTAINTY> <DESCRIPTION> <LANGUAGE> <AREAS>, provided: %d\n",
+                numArgs);
+        return STATUS_BAD_VALUE;
+    }
+    Alert parsedAlert;
+    if (!utils::parseAlertStatus(args[1], parsedAlert.status)) {
+        dprintf(fd, "Unknown alert status type: %s\n", args[2]);
+        return STATUS_BAD_VALUE;
+    }
+    if (!utils::parseAlertMessageType(args[2], parsedAlert.messageType)) {
+        dprintf(fd, "Unknown alert message type: %s\n", args[3]);
+        return STATUS_BAD_VALUE;
+    }
+    AlertInfo parsedAlertInfo;
+    vector<string> categoryStrings = ::android::base::Split(args[3], ",");
+    for (const auto& categoryString : categoryStrings) {
+        AlertCategory category;
+        if (!utils::parseAlertCategory(categoryString, category)) {
+            dprintf(fd, "Unknown alert category type: %s\n", args[3]);
+            return STATUS_BAD_VALUE;
+        }
+        parsedAlertInfo.categoryArray.push_back(category);
+    }
+    if (!utils::parseAlertUrgency(args[4], parsedAlertInfo.urgency)) {
+        dprintf(fd, "Unknown alert urgency type: %s\n", args[4]);
+        return STATUS_BAD_VALUE;
+    }
+    if (!utils::parseAlertSeverity(args[5], parsedAlertInfo.severity)) {
+        dprintf(fd, "Unknown alert severity type: %s\n", args[5]);
+        return STATUS_BAD_VALUE;
+    }
+    if (!utils::parseAlertCertainty(args[6], parsedAlertInfo.certainty)) {
+        dprintf(fd, "Unknown alert certainty type: %s\n", args[6]);
+        return STATUS_BAD_VALUE;
+    }
+    parsedAlertInfo.description = string(args[7]);
+    string languageStr = string(args[8]);
+    if (!EqualsIgnoreCase(languageStr, "null")) {
+        parsedAlertInfo.language.emplace(languageStr);
+    }
+    string areaListString = string(args[9]);
+    vector<AlertArea> areaList;
+    if (!parseAreaListString(fd, areaListString, areaList)) {
+        return STATUS_BAD_VALUE;
+    }
+    parsedAlertInfo.areas = areaList;
+    parsedAlert.infoArray = {parsedAlertInfo};
+    LOG(INFO) << "Simulate alert: " << parsedAlert.toString().c_str();
+    alertOpt.emplace(parsedAlert);
+    updateCurrentProgramInfoWithAlert(alertOpt);
+    return STATUS_OK;
+}
+
 }  // namespace aidl::android::hardware::broadcastradio
diff --git a/broadcastradio/aidl/default/BroadcastRadio.h b/broadcastradio/aidl/default/BroadcastRadio.h
index 60ea907..a4cba3b 100644
--- a/broadcastradio/aidl/default/BroadcastRadio.h
+++ b/broadcastradio/aidl/default/BroadcastRadio.h
@@ -78,7 +78,8 @@
             std::unique_ptr<::android::WorkerThread>(new ::android::WorkerThread());
     bool mIsTuneCompleted GUARDED_BY(mMutex) = true;
     Properties mProperties GUARDED_BY(mMutex);
-    ProgramSelector mCurrentProgram GUARDED_BY(mMutex) = {};
+    ProgramSelector mCurrentProgramSelector GUARDED_BY(mMutex) = {};
+    ProgramInfo mCurrentProgramInfo GUARDED_BY(mMutex) = {};
     std::vector<VirtualProgram> mProgramList GUARDED_BY(mMutex) = {};
     std::optional<AmFmBandRange> mCurrentAmFmBandRange GUARDED_BY(mMutex);
     std::shared_ptr<ITunerCallback> mCallback GUARDED_BY(mMutex);
@@ -99,6 +100,7 @@
     void jumpToFirstSubChannelLocked(std::vector<VirtualProgram>::const_iterator& it) const
             REQUIRES(mMutex);
     bool isConfigFlagSetLocked(ConfigFlag flag) const REQUIRES(mMutex);
+    void updateCurrentProgramInfoWithAlert(std::optional<Alert>& alert);
 
     binder_status_t cmdHelp(int fd) const;
     binder_status_t cmdTune(int fd, const char** args, uint32_t numArgs);
@@ -107,6 +109,7 @@
     binder_status_t cmdCancel(int fd, uint32_t numArgs);
     binder_status_t cmdStartProgramListUpdates(int fd, const char** args, uint32_t numArgs);
     binder_status_t cmdStopProgramListUpdates(int fd, uint32_t numArgs);
+    binder_status_t cmdSimulateAlert(int fd, const char** args, uint32_t numArgs);
 
     binder_status_t dumpsys(int fd) EXCLUDES(mMutex);
 };
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/broadcastradio/common/utilsaidl/Android.bp b/broadcastradio/common/utilsaidl/Android.bp
index d88081f..2245492 100644
--- a/broadcastradio/common/utilsaidl/Android.bp
+++ b/broadcastradio/common/utilsaidl/Android.bp
@@ -24,7 +24,7 @@
     default_applicable_licenses: ["hardware_interfaces_license"],
 }
 
-cc_library_static {
+cc_library {
     name: "android.hardware.broadcastradio@common-utils-aidl-lib",
     defaults: [
         "BroadcastRadioUtilsDefaults",
@@ -34,7 +34,7 @@
     ],
 }
 
-cc_library_static {
+cc_library {
     name: "android.hardware.broadcastradio@common-utils-aidl-lib-V2",
     defaults: [
         "BroadcastRadioUtilsDefaults",
@@ -47,7 +47,21 @@
     ],
 }
 
-cc_library_static {
+cc_library {
+    name: "android.hardware.broadcastradio@common-utils-aidl-lib-V3",
+    defaults: [
+        "BroadcastRadioUtilsDefaults",
+    ],
+    srcs: [
+        "src/UtilsV2.cpp",
+        "src/UtilsV3.cpp",
+    ],
+    shared_libs: [
+        "android.hardware.broadcastradio-V3-ndk",
+    ],
+}
+
+cc_library {
     name: "android.hardware.broadcastradio@common-utils-aidl-lib-latest",
     defaults: [
         "BroadcastRadioUtilsDefaults",
@@ -55,6 +69,7 @@
     ],
     srcs: [
         "src/UtilsV2.cpp",
+        "src/UtilsV3.cpp",
     ],
 }
 
diff --git a/broadcastradio/common/utilsaidl/include/broadcastradio-utils-aidl/Utils.h b/broadcastradio/common/utilsaidl/include/broadcastradio-utils-aidl/Utils.h
index a34ee10..f5b71b2 100644
--- a/broadcastradio/common/utilsaidl/include/broadcastradio-utils-aidl/Utils.h
+++ b/broadcastradio/common/utilsaidl/include/broadcastradio-utils-aidl/Utils.h
@@ -197,6 +197,8 @@
 
 bool parseArgLong(const std::string& s, long* out);
 
+bool parseArgDouble(const std::string& s, double* out);
+
 bool parseArgBool(const std::string& s, bool* out);
 
 bool parseArgDirection(const std::string& s, bool* out);
diff --git a/broadcastradio/common/utilsaidl/include/broadcastradio-utils-aidl/UtilsV3.h b/broadcastradio/common/utilsaidl/include/broadcastradio-utils-aidl/UtilsV3.h
new file mode 100644
index 0000000..250e217
--- /dev/null
+++ b/broadcastradio/common/utilsaidl/include/broadcastradio-utils-aidl/UtilsV3.h
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/broadcastradio/ProgramInfo.h>
+
+namespace aidl::android::hardware::broadcastradio {
+
+namespace utils {
+
+bool parseAlertStatus(const std::string& s, AlertStatus& out);
+
+bool parseAlertMessageType(const std::string& s, AlertMessageType& out);
+
+bool parseAlertCategory(const std::string& s, AlertCategory& out);
+
+bool parseAlertUrgency(const std::string& s, AlertUrgency& out);
+
+bool parseAlertSeverity(const std::string& s, AlertSeverity& out);
+
+bool parseAlertCertainty(const std::string& s, AlertCertainty& out);
+}  // namespace utils
+}  // namespace aidl::android::hardware::broadcastradio
\ No newline at end of file
diff --git a/broadcastradio/common/utilsaidl/src/Utils.cpp b/broadcastradio/common/utilsaidl/src/Utils.cpp
index 3de1866..bfa93a5 100644
--- a/broadcastradio/common/utilsaidl/src/Utils.cpp
+++ b/broadcastradio/common/utilsaidl/src/Utils.cpp
@@ -19,6 +19,7 @@
 #include "broadcastradio-utils-aidl/Utils.h"
 
 #include <android-base/logging.h>
+#include <android-base/parsedouble.h>
 #include <android-base/parseint.h>
 #include <android-base/strings.h>
 
@@ -631,6 +632,10 @@
     return ::android::base::ParseInt(s, out);
 }
 
+bool parseArgDouble(const std::string& s, double* out) {
+    return ::android::base::ParseDouble(s, out);
+}
+
 bool parseArgBool(const std::string& s, bool* out) {
     if (EqualsIgnoreCase(s, "true")) {
         *out = true;
diff --git a/broadcastradio/common/utilsaidl/src/UtilsV3.cpp b/broadcastradio/common/utilsaidl/src/UtilsV3.cpp
new file mode 100644
index 0000000..bf694da
--- /dev/null
+++ b/broadcastradio/common/utilsaidl/src/UtilsV3.cpp
@@ -0,0 +1,142 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "BcRadioAidlDef.utilsV3"
+
+#include "broadcastradio-utils-aidl/Utils.h"
+
+#include <android-base/strings.h>
+
+namespace aidl::android::hardware::broadcastradio {
+
+namespace utils {
+
+namespace {
+
+using ::android::base::EqualsIgnoreCase;
+using ::std::vector;
+}  // namespace
+
+bool parseAlertStatus(const std::string& s, AlertStatus& out) {
+    if (EqualsIgnoreCase(s, toString(AlertStatus::ACTUAL))) {
+        out = AlertStatus::ACTUAL;
+    } else if (EqualsIgnoreCase(s, toString(AlertStatus::EXERCISE))) {
+        out = AlertStatus::EXERCISE;
+    } else if (EqualsIgnoreCase(s, toString(AlertStatus::TEST))) {
+        out = AlertStatus::TEST;
+    } else {
+        return false;
+    }
+    return true;
+}
+
+bool parseAlertMessageType(const std::string& s, AlertMessageType& out) {
+    if (EqualsIgnoreCase(s, toString(AlertMessageType::ALERT))) {
+        out = AlertMessageType::ALERT;
+    } else if (EqualsIgnoreCase(s, toString(AlertMessageType::UPDATE))) {
+        out = AlertMessageType::UPDATE;
+    } else if (EqualsIgnoreCase(s, toString(AlertMessageType::CANCEL))) {
+        out = AlertMessageType::CANCEL;
+    } else {
+        return false;
+    }
+    return true;
+}
+
+bool parseAlertCategory(const std::string& s, AlertCategory& out) {
+    if (EqualsIgnoreCase(s, toString(AlertCategory::GEO))) {
+        out = AlertCategory::GEO;
+    } else if (EqualsIgnoreCase(s, toString(AlertCategory::MET))) {
+        out = AlertCategory::MET;
+    } else if (EqualsIgnoreCase(s, toString(AlertCategory::SAFETY))) {
+        out = AlertCategory::SAFETY;
+    } else if (EqualsIgnoreCase(s, toString(AlertCategory::SECURITY))) {
+        out = AlertCategory::SECURITY;
+    } else if (EqualsIgnoreCase(s, toString(AlertCategory::RESCUE))) {
+        out = AlertCategory::RESCUE;
+    } else if (EqualsIgnoreCase(s, toString(AlertCategory::FIRE))) {
+        out = AlertCategory::FIRE;
+    } else if (EqualsIgnoreCase(s, toString(AlertCategory::HEALTH))) {
+        out = AlertCategory::HEALTH;
+    } else if (EqualsIgnoreCase(s, toString(AlertCategory::ENV))) {
+        out = AlertCategory::ENV;
+    } else if (EqualsIgnoreCase(s, toString(AlertCategory::TRANSPORT))) {
+        out = AlertCategory::TRANSPORT;
+    } else if (EqualsIgnoreCase(s, toString(AlertCategory::INFRA))) {
+        out = AlertCategory::INFRA;
+    } else if (EqualsIgnoreCase(s, toString(AlertCategory::CBRNE))) {
+        out = AlertCategory::CBRNE;
+    } else if (EqualsIgnoreCase(s, toString(AlertCategory::OTHER))) {
+        out = AlertCategory::OTHER;
+    } else {
+        return false;
+    }
+    return true;
+}
+
+bool parseAlertUrgency(const std::string& s, AlertUrgency& out) {
+    if (EqualsIgnoreCase(s, toString(AlertUrgency::IMMEDIATE))) {
+        out = AlertUrgency::IMMEDIATE;
+    } else if (EqualsIgnoreCase(s, toString(AlertUrgency::EXPECTED))) {
+        out = AlertUrgency::EXPECTED;
+    } else if (EqualsIgnoreCase(s, toString(AlertUrgency::FUTURE))) {
+        out = AlertUrgency::FUTURE;
+    } else if (EqualsIgnoreCase(s, toString(AlertUrgency::PAST))) {
+        out = AlertUrgency::PAST;
+    } else if (EqualsIgnoreCase(s, toString(AlertUrgency::UNKNOWN))) {
+        out = AlertUrgency::UNKNOWN;
+    } else {
+        return false;
+    }
+    return true;
+}
+
+bool parseAlertSeverity(const std::string& s, AlertSeverity& out) {
+    if (EqualsIgnoreCase(s, toString(AlertSeverity::EXTREME))) {
+        out = AlertSeverity::EXTREME;
+    } else if (EqualsIgnoreCase(s, toString(AlertSeverity::SEVERE))) {
+        out = AlertSeverity::SEVERE;
+    } else if (EqualsIgnoreCase(s, toString(AlertSeverity::MODERATE))) {
+        out = AlertSeverity::MODERATE;
+    } else if (EqualsIgnoreCase(s, toString(AlertSeverity::MINOR))) {
+        out = AlertSeverity::MINOR;
+    } else if (EqualsIgnoreCase(s, toString(AlertSeverity::UNKNOWN))) {
+        out = AlertSeverity::UNKNOWN;
+    } else {
+        return false;
+    }
+    return true;
+}
+
+bool parseAlertCertainty(const std::string& s, AlertCertainty& out) {
+    if (EqualsIgnoreCase(s, toString(AlertCertainty::OBSERVED))) {
+        out = AlertCertainty::OBSERVED;
+    } else if (EqualsIgnoreCase(s, toString(AlertCertainty::LIKELY))) {
+        out = AlertCertainty::LIKELY;
+    } else if (EqualsIgnoreCase(s, toString(AlertCertainty::POSSIBLE))) {
+        out = AlertCertainty::POSSIBLE;
+    } else if (EqualsIgnoreCase(s, toString(AlertCertainty::UNLIKELY))) {
+        out = AlertCertainty::UNLIKELY;
+    } else if (EqualsIgnoreCase(s, toString(AlertCertainty::UNKNOWN))) {
+        out = AlertCertainty::UNKNOWN;
+    } else {
+        return false;
+    }
+    return true;
+}
+
+}  // namespace utils
+}  // namespace aidl::android::hardware::broadcastradio
diff --git a/cas/1.0/vts/functional/Android.bp b/cas/1.0/vts/functional/Android.bp
index 6d06cab..1817371 100644
--- a/cas/1.0/vts/functional/Android.bp
+++ b/cas/1.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_tv_os",
     // 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/cas/1.1/vts/functional/Android.bp b/cas/1.1/vts/functional/Android.bp
index a598554..f95f9b3 100644
--- a/cas/1.1/vts/functional/Android.bp
+++ b/cas/1.1/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_tv_os",
     // 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/cas/1.2/vts/functional/Android.bp b/cas/1.2/vts/functional/Android.bp
index 21f791b..3b1cfb1 100644
--- a/cas/1.2/vts/functional/Android.bp
+++ b/cas/1.2/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_tv_os",
     // 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/cas/aidl/vts/functional/Android.bp b/cas/aidl/vts/functional/Android.bp
index 295ae7c..390c713 100644
--- a/cas/aidl/vts/functional/Android.bp
+++ b/cas/aidl/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_media_codec_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/compatibility_matrices/Android.bp b/compatibility_matrices/Android.bp
index df5e5b1..825c931 100644
--- a/compatibility_matrices/Android.bp
+++ b/compatibility_matrices/Android.bp
@@ -147,6 +147,6 @@
     stem: "compatibility_matrix.202504.xml",
     srcs: ["compatibility_matrix.202504.xml"],
     kernel_configs: [
-        "kernel_config_w_6.next",
+        "kernel_config_w_6.12",
     ],
 }
diff --git a/compatibility_matrices/compatibility_matrix.202504.xml b/compatibility_matrices/compatibility_matrix.202504.xml
index 616a701..10f73f1 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>
@@ -396,7 +396,7 @@
     </hal>
     <hal format="aidl">
         <name>android.hardware.radio.data</name>
-        <version>3</version>
+        <version>3-4</version>
         <interface>
             <name>IRadioData</name>
             <instance>slot1</instance>
@@ -476,7 +476,7 @@
     </hal>
     <hal format="aidl">
         <name>android.hardware.radio.ims.media</name>
-        <version>2</version>
+        <version>2-3</version>
         <interface>
             <name>IImsMedia</name>
             <instance>default</instance>
@@ -551,7 +551,7 @@
     </hal>
     <hal format="aidl">
         <name>android.hardware.thermal</name>
-        <version>2</version>
+        <version>3</version>
         <interface>
             <name>IThermal</name>
             <instance>default</instance>
diff --git a/configstore/1.0/vts/functional/Android.bp b/configstore/1.0/vts/functional/Android.bp
index 27c66fd..388c565 100644
--- a/configstore/1.0/vts/functional/Android.bp
+++ b/configstore/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/confirmationui/1.0/vts/functional/Android.bp b/confirmationui/1.0/vts/functional/Android.bp
index 6c6488b..2fbd851 100644
--- a/confirmationui/1.0/vts/functional/Android.bp
+++ b/confirmationui/1.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_platform_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/confirmationui/aidl/vts/functional/Android.bp b/confirmationui/aidl/vts/functional/Android.bp
index ac2d53a..2403185 100644
--- a/confirmationui/aidl/vts/functional/Android.bp
+++ b/confirmationui/aidl/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_platform_security",
     // See: http://go/android-license-faq
     default_applicable_licenses: ["hardware_interfaces_license"],
 }
diff --git a/contexthub/1.0/vts/functional/Android.bp b/contexthub/1.0/vts/functional/Android.bp
index 5949f8d..3bc3597 100644
--- a/contexthub/1.0/vts/functional/Android.bp
+++ b/contexthub/1.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_context_hub",
     // 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/contexthub/1.1/vts/functional/Android.bp b/contexthub/1.1/vts/functional/Android.bp
index b2961c4..5e0779d 100644
--- a/contexthub/1.1/vts/functional/Android.bp
+++ b/contexthub/1.1/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_context_hub",
     // 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/contexthub/1.2/vts/functional/Android.bp b/contexthub/1.2/vts/functional/Android.bp
index c923f42..cdf348f 100644
--- a/contexthub/1.2/vts/functional/Android.bp
+++ b/contexthub/1.2/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_context_hub",
     // 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.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/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/1.0/vts/functional/Android.bp b/dumpstate/1.0/vts/functional/Android.bp
index cc0a9cd..a7ee2d8 100644
--- a/dumpstate/1.0/vts/functional/Android.bp
+++ b/dumpstate/1.0/vts/functional/Android.bp
@@ -14,6 +14,7 @@
 // limitations under the License.
 
 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/dumpstate/1.1/vts/functional/Android.bp b/dumpstate/1.1/vts/functional/Android.bp
index 17b412e..b2692f6 100644
--- a/dumpstate/1.1/vts/functional/Android.bp
+++ b/dumpstate/1.1/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/dumpstate/aidl/vts/functional/Android.bp b/dumpstate/aidl/vts/functional/Android.bp
index 5e516cf..9aa62e0 100644
--- a/dumpstate/aidl/vts/functional/Android.bp
+++ b/dumpstate/aidl/vts/functional/Android.bp
@@ -13,6 +13,7 @@
 // limitations under the License.
 
 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/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/common/aidl/android/hardware/graphics/common/StandardMetadataType.aidl b/graphics/common/aidl/android/hardware/graphics/common/StandardMetadataType.aidl
index 8cfdae6..e4da890 100644
--- a/graphics/common/aidl/android/hardware/graphics/common/StandardMetadataType.aidl
+++ b/graphics/common/aidl/android/hardware/graphics/common/StandardMetadataType.aidl
@@ -282,7 +282,7 @@
      * When it is encoded into a byte stream, the total number of Rects is written using
      * 8 bytes in little endian. It is followed by each Rect.
      *
-     * To encode a Rect, write the following fields in this order each as 8 bytes in little endian:
+     * To encode a Rect, write the following fields in this order each as 4 bytes in little endian:
      * left, top, right and bottom.
      */
     CROP = 16,
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayLuts.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayLuts.aidl
index 327e84c..4263140 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayLuts.aidl
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayLuts.aidl
@@ -38,6 +38,6 @@
   android.hardware.graphics.composer3.DisplayLuts.LayerLut[] layerLuts;
   parcelable LayerLut {
     long layer;
-    android.hardware.graphics.composer3.Lut lut;
+    android.hardware.graphics.composer3.Luts luts;
   }
 }
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/LayerCommand.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/LayerCommand.aidl
index 8b2b13c..87c0e1e 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/LayerCommand.aidl
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/LayerCommand.aidl
@@ -57,5 +57,5 @@
   @nullable int[] bufferSlotsToClear;
   android.hardware.graphics.composer3.LayerLifecycleBatchCommandType layerLifecycleBatchCommandType;
   int newBufferSlotCount;
-  @nullable android.hardware.graphics.composer3.Lut[] luts;
+  @nullable android.hardware.graphics.composer3.Luts luts;
 }
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/LutProperties.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/LutProperties.aidl
index 5edceb5..6a4593a 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/LutProperties.aidl
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/LutProperties.aidl
@@ -35,7 +35,7 @@
 @VintfStability
 parcelable LutProperties {
   android.hardware.graphics.composer3.LutProperties.Dimension dimension;
-  long size;
+  int size;
   android.hardware.graphics.composer3.LutProperties.SamplingKey[] samplingKeys;
   @VintfStability
   enum Dimension {
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/Lut.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/Luts.aidl
similarity index 93%
rename from graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/Lut.aidl
rename to graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/Luts.aidl
index 5fae35b..2890365 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/Lut.aidl
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/Luts.aidl
@@ -33,7 +33,8 @@
 
 package android.hardware.graphics.composer3;
 @VintfStability
-parcelable Lut {
+parcelable Luts {
   @nullable ParcelFileDescriptor pfd;
-  android.hardware.graphics.composer3.LutProperties lutProperties;
+  @nullable int[] offsets;
+  android.hardware.graphics.composer3.LutProperties[] lutProperties;
 }
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayLuts.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayLuts.aidl
index ac0a606..6b59a6f 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayLuts.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayLuts.aidl
@@ -16,7 +16,7 @@
 
 package android.hardware.graphics.composer3;
 
-import android.hardware.graphics.composer3.Lut;
+import android.hardware.graphics.composer3.Luts;
 
 /**
  * LUT (Look-Up Table) Interface for Color Transformation.
@@ -37,9 +37,9 @@
          */
         long layer;
         /**
-         * A Lut specified by the HWC for given HDR layers that don't have Luts provided.
+         * Lut(s) specified by the HWC for given HDR layers that don't have Luts provided.
          */
-        Lut lut;
+        Luts luts;
     }
 
     LayerLut[] layerLuts;
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/LayerCommand.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/LayerCommand.aidl
index bf4f504..c89887d 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/LayerCommand.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/LayerCommand.aidl
@@ -24,7 +24,7 @@
 import android.hardware.graphics.composer3.Color;
 import android.hardware.graphics.composer3.LayerBrightness;
 import android.hardware.graphics.composer3.LayerLifecycleBatchCommandType;
-import android.hardware.graphics.composer3.Lut;
+import android.hardware.graphics.composer3.Luts;
 import android.hardware.graphics.composer3.ParcelableBlendMode;
 import android.hardware.graphics.composer3.ParcelableComposition;
 import android.hardware.graphics.composer3.ParcelableDataspace;
@@ -284,5 +284,5 @@
     /**
      * Sets the lut(s) for the layer.
      */
-    @nullable Lut[] luts;
+    @nullable Luts luts;
 }
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/LutProperties.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/LutProperties.aidl
index 47ec390..1c6fd18 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/LutProperties.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/LutProperties.aidl
@@ -32,7 +32,7 @@
      * The size of the Lut.
      * This refers to the length of a 1D Lut, or the grid size of a 3D one.
      */
-    long size;
+    int size;
 
     /**
      * SamplingKey is about how a Lut can be sampled.
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/Lut.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/Luts.aidl
similarity index 81%
rename from graphics/composer/aidl/android/hardware/graphics/composer3/Lut.aidl
rename to graphics/composer/aidl/android/hardware/graphics/composer3/Luts.aidl
index abfeb14..5f55f1c 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/Lut.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/Luts.aidl
@@ -26,13 +26,13 @@
  */
 
 @VintfStability
-parcelable Lut {
+parcelable Luts {
     /**
      * A handle to a memory region.
      * If the file descriptor is not set, this means that the HWC doesn't specify a Lut.
      *
      * When specifying a Lut, the HWC is required to follow the instructions as below:
-     * 1. use `memfd_create` to create a shared memory segment
+     * 1. use `ashmem_create_region` to create a shared memory segment
      *    with the size specified in lutProperties.
      * 2. use `mmap` to map the shared memory segment into its own virtual address space.
      *    PROT_READ/PROT_WRITE recommended for prot argument.
@@ -40,6 +40,7 @@
      * For data precision, 32-bit float is used to specify a Lut by both the HWC and
      * the platform.
      *
+     *
      * For unflattening/flattening 3D Lut(s), the algorithm below should be observed
      * by both the HWC and the platform.
      * Assuming that we have a 3D array `ORIGINAL[WIDTH, HEIGHT, DEPTH]`, we would turn it into
@@ -50,7 +51,15 @@
     @nullable ParcelFileDescriptor pfd;
 
     /**
-     * The properties of the Lut.
+     * The offsets store the starting point of each Lut memory of the Lut buffer.
+     *
+     * Multiple Luts can be packed into one same `pfd`, and `offsets` is used to pinpoint
+     * the starting point of each Lut.
      */
-    LutProperties lutProperties;
+    @nullable int[] offsets;
+
+    /**
+     * The properties list of the Luts.
+     */
+    LutProperties[] lutProperties;
 }
diff --git a/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientReader.h b/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientReader.h
index 331d717..07c9c6d 100644
--- a/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientReader.h
+++ b/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientReader.h
@@ -247,11 +247,11 @@
     void parseSetDisplayLuts(DisplayLuts&& displayLuts) {
         LOG_ALWAYS_FATAL_IF(mDisplay && displayLuts.display != *mDisplay);
         auto& data = mReturnData[displayLuts.display];
-        for (auto& layerLut : displayLuts.layerLuts) {
-            if (layerLut.lut.pfd.get() >= 0) {
+        for (auto& [layerId, luts] : displayLuts.layerLuts) {
+            if (luts.pfd.get() >= 0) {
                 data.layerLuts.push_back(
-                        {layerLut.layer, Lut{ndk::ScopedFileDescriptor(layerLut.lut.pfd.release()),
-                                             layerLut.lut.lutProperties}});
+                        {layerId, Luts{ndk::ScopedFileDescriptor(luts.pfd.release()), luts.offsets,
+                                       luts.lutProperties}});
             }
         }
     }
diff --git a/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientWriter.h b/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientWriter.h
index 02fb3aa..036460e 100644
--- a/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientWriter.h
+++ b/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientWriter.h
@@ -30,7 +30,7 @@
 #include <aidl/android/hardware/graphics/composer3/DisplayBrightness.h>
 #include <aidl/android/hardware/graphics/composer3/LayerBrightness.h>
 #include <aidl/android/hardware/graphics/composer3/LayerLifecycleBatchCommandType.h>
-#include <aidl/android/hardware/graphics/composer3/Lut.h>
+#include <aidl/android/hardware/graphics/composer3/Luts.h>
 #include <aidl/android/hardware/graphics/composer3/PerFrameMetadata.h>
 #include <aidl/android/hardware/graphics/composer3/PerFrameMetadataBlob.h>
 
@@ -246,13 +246,8 @@
         getLayerCommand(display, layer).blockingRegion.emplace(blocking.begin(), blocking.end());
     }
 
-    void setLayerLuts(int64_t display, int64_t layer, std::vector<Lut>& luts) {
-        std::vector<std::optional<Lut>> currentLuts;
-        for (auto& lut : luts) {
-            currentLuts.push_back(std::make_optional<Lut>(
-                    {ndk::ScopedFileDescriptor(lut.pfd.release()), lut.lutProperties}));
-        }
-        getLayerCommand(display, layer).luts.emplace(std::move(currentLuts));
+    void setLayerLuts(int64_t display, int64_t layer, Luts& luts) {
+        getLayerCommand(display, layer).luts.emplace(std::move(luts));
     }
 
     std::vector<DisplayCommand> takePendingCommands() {
diff --git a/graphics/composer/aidl/vts/RenderEngineVts.h b/graphics/composer/aidl/vts/RenderEngineVts.h
index bbe508f..6553720 100644
--- a/graphics/composer/aidl/vts/RenderEngineVts.h
+++ b/graphics/composer/aidl/vts/RenderEngineVts.h
@@ -51,9 +51,10 @@
 
   private:
     common::PixelFormat mFormat;
-    std::vector<::android::renderengine::LayerSettings> mCompositionLayers;
     std::unique_ptr<::android::renderengine::RenderEngine> mRenderEngine;
-    std::vector<::android::renderengine::LayerSettings> mRenderLayers;
+    // Delete RenderEngine layers before RenderEngine -- ExternalTexture holds a reference to
+    // RenderEngine.
+    std::vector<::android::renderengine::LayerSettings> mCompositionLayers;
     ::android::sp<::android::GraphicBuffer> mGraphicBuffer;
 
     DisplaySettings mDisplaySettings;
diff --git a/graphics/mapper/stable-c/vts/VtsHalGraphicsMapperStableC_TargetTest.cpp b/graphics/mapper/stable-c/vts/VtsHalGraphicsMapperStableC_TargetTest.cpp
index bdbe4d0..3e2f2ac 100644
--- a/graphics/mapper/stable-c/vts/VtsHalGraphicsMapperStableC_TargetTest.cpp
+++ b/graphics/mapper/stable-c/vts/VtsHalGraphicsMapperStableC_TargetTest.cpp
@@ -753,7 +753,7 @@
  * Test IMapper::lock and IMapper::unlock with no CPU usage requested.
  */
 TEST_P(GraphicsMapperStableCTests, LockUnlockNoCPUUsage) {
-    constexpr auto usage = BufferUsage::CPU_READ_NEVER | BufferUsage::CPU_WRITE_NEVER;
+    constexpr auto usage = BufferUsage::CPU_READ_RARELY | BufferUsage::CPU_WRITE_NEVER;
     auto buffer = allocate({
             .name = {"VTS_TEMP"},
             .width = 64,
@@ -771,15 +771,12 @@
     auto handle = buffer->import();
     uint8_t* data = nullptr;
 
-    EXPECT_EQ(AIMAPPER_ERROR_BAD_VALUE,
-              mapper()->v5.lock(*handle, static_cast<int64_t>(info.usage),
-                                region, -1,(void**)&data))
-              << "Locking with 0 access succeeded";
+    EXPECT_EQ(AIMAPPER_ERROR_BAD_VALUE, mapper()->v5.lock(*handle, 0, region, -1, (void**)&data))
+            << "Locking with 0 access succeeded";
 
     int releaseFence = -1;
-    EXPECT_EQ(AIMAPPER_ERROR_BAD_BUFFER,
-              mapper()->v5.unlock(*handle, &releaseFence))
-              << "Unlocking not locked buffer succeeded";
+    EXPECT_EQ(AIMAPPER_ERROR_BAD_BUFFER, mapper()->v5.unlock(*handle, &releaseFence))
+            << "Unlocking not locked buffer succeeded";
     if (releaseFence != -1) {
         close(releaseFence);
     }
diff --git a/health/utils/libhealthloop/Android.bp b/health/utils/libhealthloop/Android.bp
index 4ebc575..08b3180 100644
--- a/health/utils/libhealthloop/Android.bp
+++ b/health/utils/libhealthloop/Android.bp
@@ -22,6 +22,12 @@
 }
 
 bpf {
+    name: "filterPowerSupplyEvents.o_non_vendor",
+    srcs: ["filterPowerSupplyEvents.c"],
+    visibility: ["//visibility:private"],
+}
+
+bpf {
     name: "filterPowerSupplyEvents.o",
     srcs: ["filterPowerSupplyEvents.c"],
     // "vendor: true" because all binaries that use this BPF filter are vendor
@@ -55,10 +61,10 @@
     ],
 }
 
-genrule {
+cc_genrule {
     name: "filterPowerSupplyEvents.h",
     out: ["filterPowerSupplyEvents.h"],
-    srcs: [":filterPowerSupplyEvents.o"],
+    srcs: [":filterPowerSupplyEvents.o_non_vendor"],
     cmd: "cat $(in) | od -v -tx1 | cut -c9- | grep -v '^$$' | sed 's/^/0x/;s/ /, 0x/g;s/^, //;s/$$/,/' > $(out)",
 }
 
@@ -76,8 +82,10 @@
         "libgmock",
     ],
     generated_headers: [
-        "filterPowerSupplyEvents.h",
         "libbpf_headers",
     ],
+    device_first_generated_headers: [
+        "filterPowerSupplyEvents.h",
+    ],
     compile_multilib: "64",
 }
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/ir/1.0/vts/functional/Android.bp b/ir/1.0/vts/functional/Android.bp
index 983f2a4..7c23f03 100644
--- a/ir/1.0/vts/functional/Android.bp
+++ b/ir/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/ir/aidl/vts/Android.bp b/ir/aidl/vts/Android.bp
index c2491b8..d42a7f4 100644
--- a/ir/aidl/vts/Android.bp
+++ b/ir/aidl/vts/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/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.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/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/memtrack/1.0/vts/functional/Android.bp b/memtrack/1.0/vts/functional/Android.bp
index 852cd15..924fc27 100644
--- a/memtrack/1.0/vts/functional/Android.bp
+++ b/memtrack/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/memtrack/aidl/vts/Android.bp b/memtrack/aidl/vts/Android.bp
index f54388a..523c903 100644
--- a/memtrack/aidl/vts/Android.bp
+++ b/memtrack/aidl/vts/Android.bp
@@ -1,4 +1,5 @@
 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/neuralnetworks/1.3/vts/functional/Android.bp b/neuralnetworks/1.3/vts/functional/Android.bp
index 07071cc..ab2d4a1 100644
--- a/neuralnetworks/1.3/vts/functional/Android.bp
+++ b/neuralnetworks/1.3/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_renderscript_nnapi",
     // 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/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/IPower.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/IPower.aidl
index 8acdaf2..8d8fb88 100644
--- a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/IPower.aidl
+++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/IPower.aidl
@@ -43,4 +43,5 @@
   android.hardware.power.IPowerHintSession createHintSessionWithConfig(in int tgid, in int uid, in int[] threadIds, in long durationNanos, in android.hardware.power.SessionTag tag, out android.hardware.power.SessionConfig config);
   android.hardware.power.ChannelConfig getSessionChannel(in int tgid, in int uid);
   oneway void closeSessionChannel(in int tgid, in int uid);
+  android.hardware.power.SupportInfo getSupportInfo();
 }
diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/SupportInfo.aidl
similarity index 90%
copy from vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl
copy to power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/SupportInfo.aidl
index a5eda52..85da2fc 100644
--- a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl
+++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/SupportInfo.aidl
@@ -31,9 +31,13 @@
 // 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.power;
 @VintfStability
-parcelable PwleV2OutputMapEntry {
-  float frequencyHz;
-  float maxOutputAccelerationGs;
+parcelable SupportInfo {
+  boolean usesSessions;
+  long boosts;
+  long modes;
+  long sessionHints;
+  long sessionModes;
+  long sessionTags;
 }
diff --git a/power/aidl/android/hardware/power/IPower.aidl b/power/aidl/android/hardware/power/IPower.aidl
index e25714f..2f15648 100644
--- a/power/aidl/android/hardware/power/IPower.aidl
+++ b/power/aidl/android/hardware/power/IPower.aidl
@@ -22,6 +22,7 @@
 import android.hardware.power.Mode;
 import android.hardware.power.SessionConfig;
 import android.hardware.power.SessionTag;
+import android.hardware.power.SupportInfo;
 
 @VintfStability
 interface IPower {
@@ -144,4 +145,14 @@
      * @param   uid The UID to be associated with this channel.
      */
     oneway void closeSessionChannel(in int tgid, in int uid);
+
+    /**
+     * Called to get detailed information on the support status of various PowerHAL
+     * features, such as hint sessions and specific boosts.
+     *
+     * @return  a SupportInfo giving detailed support information, or
+     *          EX_UNSUPPORTED_OPERATION if detailed support checking is itself
+     *          not supported.
+     */
+    SupportInfo getSupportInfo();
 }
diff --git a/power/aidl/android/hardware/power/SupportInfo.aidl b/power/aidl/android/hardware/power/SupportInfo.aidl
new file mode 100644
index 0000000..46bcdd3
--- /dev/null
+++ b/power/aidl/android/hardware/power/SupportInfo.aidl
@@ -0,0 +1,73 @@
+/*
+ * 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.power;
+
+import android.hardware.power.Boost;
+import android.hardware.power.Mode;
+import android.hardware.power.SessionHint;
+import android.hardware.power.SessionMode;
+
+/**
+ * Tells clients the status of various PowerHAL features in a single call.
+ * SupportInfo consists of several bitsets, where each bit from the left
+ * corresponds to the support status of that same value of that enum index.
+ *
+ * For "Boost", having the first bit set would mean "INTERACTION"
+ * boost is supported, having the second bit set would mean
+ * "DISPLAY_UPDATE_IMMINENT" is supported, and so on. The expectation
+ * is that a client should be able to index the bitset like
+ * "(supportInfo.boosts >> Boost::AUDIO_LAUNCH) % 2" and it should return
+ * the support value of Boost::AUDIO_LAUNCH. This pattern is the same for
+ * all four support bitsets.
+ */
+@VintfStability
+parcelable SupportInfo {
+    /**
+     * Boolean representing whether hint sessions are supported on this device
+     */
+    boolean usesSessions;
+
+    /**
+     * The set of "Boost" enum values that are supported by this device
+     * Each bit should correspond to a value of the "Boost.aidl" enum
+     */
+    long boosts;
+
+    /**
+     * The set of "Mode" enum values that are supported by this device
+     * Each bit should correspond to a value of the "Mode.aidl" enum
+     */
+    long modes;
+
+    /**
+     * The set of "SessionHint" enum values that are supported by this device
+     * Each bit should correspond to a value of the "SessionHint.aidl" enum
+     */
+    long sessionHints;
+
+    /**
+     * The set of "SessionMode" enum values that are supported by this device
+     * Each bit should correspond to a value of the "SessionMode.aidl" enum
+     */
+    long sessionModes;
+
+    /**
+     * The set of "SessionTag" enum values that are supported by this device
+     * Each bit should correspond to a value of the "SessionTag.aidl" enum
+     */
+    long sessionTags;
+}
diff --git a/power/aidl/default/Android.bp b/power/aidl/default/Android.bp
index 4926b91..e934bc5 100644
--- a/power/aidl/default/Android.bp
+++ b/power/aidl/default/Android.bp
@@ -26,7 +26,7 @@
     defaults: ["android.hardware.power-ndk_shared"],
     relative_install_path: "hw",
     init_rc: [":android.hardware.power.rc"],
-    vintf_fragments: [":android.hardware.power.xml"],
+    vintf_fragments: ["power-default.xml"],
     vendor: true,
     shared_libs: [
         "android.hardware.common-V2-ndk",
diff --git a/power/aidl/default/Power.cpp b/power/aidl/default/Power.cpp
index 64294e5..36d0055 100644
--- a/power/aidl/default/Power.cpp
+++ b/power/aidl/default/Power.cpp
@@ -41,6 +41,11 @@
                                      ndk::enum_range<Boost>().end()};
 const std::vector<Mode> MODE_RANGE{ndk::enum_range<Mode>().begin(), ndk::enum_range<Mode>().end()};
 
+template <class T>
+constexpr size_t enum_size() {
+    return static_cast<size_t>(*(ndk::enum_range<T>().end() - 1)) + 1;
+}
+
 ScopedAStatus Power::setMode(Mode type, bool enabled) {
     LOG(VERBOSE) << "Power setMode: " << static_cast<int32_t>(type) << " to: " << enabled;
     return ScopedAStatus::ok();
@@ -105,11 +110,30 @@
     return ndk::ScopedAStatus::ok();
 }
 
-ScopedAStatus Power::getHintSessionPreferredRate(int64_t* outNanoseconds) {
+ndk::ScopedAStatus Power::getHintSessionPreferredRate(int64_t* outNanoseconds) {
     *outNanoseconds = std::chrono::nanoseconds(1ms).count();
     return ScopedAStatus::ok();
 }
 
+template <class E>
+int64_t bitsForEnum() {
+    return static_cast<int64_t>(std::bitset<enum_size<E>()>().set().to_ullong());
+}
+
+ndk::ScopedAStatus Power::getSupportInfo(SupportInfo* _aidl_return) {
+    static SupportInfo supportInfo = {
+            .usesSessions = false,
+            .modes = bitsForEnum<Mode>(),
+            .boosts = bitsForEnum<Boost>(),
+            .sessionHints = 0,
+            .sessionModes = 0,
+            .sessionTags = 0,
+    };
+    // Copy the support object into the binder
+    *_aidl_return = supportInfo;
+    return ndk::ScopedAStatus::ok();
+}
+
 }  // namespace example
 }  // namespace impl
 }  // namespace power
diff --git a/power/aidl/default/Power.h b/power/aidl/default/Power.h
index baabaa7..ef524e1 100644
--- a/power/aidl/default/Power.h
+++ b/power/aidl/default/Power.h
@@ -44,6 +44,7 @@
     ndk::ScopedAStatus getSessionChannel(int32_t tgid, int32_t uid,
                                          ChannelConfig* _aidl_return) override;
     ndk::ScopedAStatus closeSessionChannel(int32_t tgid, int32_t uid) override;
+    ndk::ScopedAStatus getSupportInfo(SupportInfo* _aidl_return) override;
 
   private:
     std::vector<std::shared_ptr<IPowerHintSession>> mPowerHintSessions;
diff --git a/power/aidl/vts/VtsHalPowerTargetTest.cpp b/power/aidl/vts/VtsHalPowerTargetTest.cpp
index 272674f..9684c38 100644
--- a/power/aidl/vts/VtsHalPowerTargetTest.cpp
+++ b/power/aidl/vts/VtsHalPowerTargetTest.cpp
@@ -45,6 +45,7 @@
 using android::hardware::power::Mode;
 using android::hardware::power::SessionHint;
 using android::hardware::power::SessionMode;
+using android::hardware::power::SupportInfo;
 using android::hardware::power::WorkDuration;
 using ChannelMessageContents = ChannelMessage::ChannelMessageContents;
 using ModeSetter = ChannelMessage::ChannelMessageContents::SessionModeSetter;
@@ -83,6 +84,16 @@
         static_cast<SessionMode>(static_cast<int32_t>(kSessionModes.back()) + 1),
 };
 
+template <class T>
+constexpr size_t enum_size() {
+    return static_cast<size_t>(*(ndk::enum_range<T>().end() - 1)) + 1;
+}
+
+template <class E>
+bool supportFromBitset(int64_t& supportInt, E type) {
+    return (supportInt >> static_cast<int>(type)) % 2;
+}
+
 class DurationWrapper : public WorkDuration {
   public:
     DurationWrapper(int64_t dur, int64_t time) {
@@ -288,6 +299,21 @@
     ASSERT_TRUE(supported);
 }
 
+TEST_P(PowerAidl, hasSupportInfo) {
+    SupportInfo config;
+    ASSERT_TRUE(power->getSupportInfo(&config).isOk());
+    for (Mode mode : kModes) {
+        bool supported;
+        power->isModeSupported(mode, &supported);
+        ASSERT_EQ(supported, supportFromBitset(config.modes, mode));
+    }
+    for (Boost boost : kBoosts) {
+        bool supported;
+        power->isBoostSupported(boost, &supported);
+        ASSERT_EQ(supported, supportFromBitset(config.boosts, boost));
+    }
+}
+
 TEST_P(HintSessionAidl, createAndCloseHintSession) {
     if (!mSessionSupport) {
         GTEST_SKIP() << "DEVICE not support Hint Session.";
diff --git a/power/stats/aidl/default/Android.bp b/power/stats/aidl/default/Android.bp
index cc0fbf6..4c59d98 100644
--- a/power/stats/aidl/default/Android.bp
+++ b/power/stats/aidl/default/Android.bp
@@ -25,7 +25,7 @@
     name: "android.hardware.power.stats-service.example",
     relative_install_path: "hw",
     init_rc: [":android.hardware.power.stats.rc"],
-    vintf_fragments: [":android.hardware.power.stats.xml"],
+    vintf_fragments: ["power.stats-default.xml"],
     vendor: true,
     shared_libs: [
         "libbase",
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.bp b/radio/aidl/Android.bp
index f60c484..517ad86 100644
--- a/radio/aidl/Android.bp
+++ b/radio/aidl/Android.bp
@@ -105,7 +105,7 @@
         },
 
     ],
-    frozen: true,
+    frozen: false,
 }
 
 aidl_interface {
@@ -320,7 +320,7 @@
     stability: "vintf",
     imports: [
         "android.hardware.radio-V3",
-        "android.hardware.radio.data-V3",
+        "android.hardware.radio.data-V4",
     ],
     backend: {
         cpp: {
@@ -347,7 +347,7 @@
         },
 
     ],
-    frozen: true,
+    frozen: false,
 }
 
 aidl_interface {
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/ApnTypes.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/ApnTypes.aidl
index 782dbbf..27561b9 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/ApnTypes.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/ApnTypes.aidl
@@ -52,4 +52,6 @@
   BIP = (1 << 13) /* 8192 */,
   ENTERPRISE = (1 << 14) /* 16384 */,
   RCS = (1 << 15) /* 32768 */,
+  OEM_PAID = (1 << 16) /* 65536 */,
+  OEM_PRIVATE = (1 << 17) /* 131072 */,
 }
diff --git a/radio/aidl/android/hardware/radio/data/ApnTypes.aidl b/radio/aidl/android/hardware/radio/data/ApnTypes.aidl
index 2a0c263..bea8bcf 100644
--- a/radio/aidl/android/hardware/radio/data/ApnTypes.aidl
+++ b/radio/aidl/android/hardware/radio/data/ApnTypes.aidl
@@ -91,16 +91,12 @@
      * APN type for RCS (Rich Communication Services)
      */
     RCS = 1 << 15,
-
     /**
      * APN type for OEM_PAID networks (Automotive PANS)
      */
-    // TODO(b/366194627): enable once HAL unfreezes
-    // OEM_PAID = 1 << 16,
-
+    OEM_PAID = 1 << 16,
     /**
      * APN type for OEM_PRIVATE networks (Automotive PANS)
      */
-    // TODO(b/366194627): enable once HAL unfreezes
-    // OEM_PRIVATE = 1 << 17,
+    OEM_PRIVATE = 1 << 17,
 }
diff --git a/radio/aidl/compat/libradiocompat/Android.bp b/radio/aidl/compat/libradiocompat/Android.bp
index d78455e..3fbd398 100644
--- a/radio/aidl/compat/libradiocompat/Android.bp
+++ b/radio/aidl/compat/libradiocompat/Android.bp
@@ -22,8 +22,25 @@
     default_applicable_licenses: ["hardware_interfaces_license"],
 }
 
+cc_defaults {
+    name: "android.hardware.radio-library.aidl_deps",
+    shared_libs: [
+        "android.hardware.radio.config-V3-ndk",
+        "android.hardware.radio.data-V4-ndk",
+        "android.hardware.radio.ims-V2-ndk",
+        "android.hardware.radio.ims.media-V3-ndk",
+        "android.hardware.radio.messaging-V3-ndk",
+        "android.hardware.radio.modem-V3-ndk",
+        "android.hardware.radio.network-V3-ndk",
+        "android.hardware.radio.sap-V1-ndk",
+        "android.hardware.radio.sim-V3-ndk",
+        "android.hardware.radio.voice-V3-ndk",
+    ],
+}
+
 cc_library {
     name: "android.hardware.radio-library.compat",
+    defaults: ["android.hardware.radio-library.aidl_deps"],
     relative_install_path: "hw",
     vendor: true,
     cflags: [
@@ -32,20 +49,10 @@
         "-DANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION",
     ],
     shared_libs: [
-        "android.hardware.radio.config-V3-ndk",
         "android.hardware.radio.config@1.0",
         "android.hardware.radio.config@1.1",
         "android.hardware.radio.config@1.2",
         "android.hardware.radio.config@1.3",
-        "android.hardware.radio.data-V3-ndk",
-        "android.hardware.radio.ims-V2-ndk",
-        "android.hardware.radio.ims.media-V2-ndk",
-        "android.hardware.radio.messaging-V3-ndk",
-        "android.hardware.radio.modem-V3-ndk",
-        "android.hardware.radio.network-V3-ndk",
-        "android.hardware.radio.sap-V1-ndk",
-        "android.hardware.radio.sim-V3-ndk",
-        "android.hardware.radio.voice-V3-ndk",
         "android.hardware.radio@1.0",
         "android.hardware.radio@1.1",
         "android.hardware.radio@1.2",
diff --git a/radio/aidl/compat/service/Android.bp b/radio/aidl/compat/service/Android.bp
index c8bbd4c..3d46d4f 100644
--- a/radio/aidl/compat/service/Android.bp
+++ b/radio/aidl/compat/service/Android.bp
@@ -24,6 +24,7 @@
 
 cc_binary {
     name: "android.hardware.radio-service.compat",
+    defaults: ["android.hardware.radio-library.aidl_deps"],
     relative_install_path: "hw",
     init_rc: ["radio-compat.rc"],
     vintf_fragments: ["radio-compat.xml"],
@@ -35,20 +36,10 @@
     ],
     shared_libs: [
         "android.hardware.radio-library.compat",
-        "android.hardware.radio.config-V3-ndk",
         "android.hardware.radio.config@1.0",
         "android.hardware.radio.config@1.1",
         "android.hardware.radio.config@1.2",
         "android.hardware.radio.config@1.3",
-        "android.hardware.radio.data-V3-ndk",
-        "android.hardware.radio.ims-V2-ndk",
-        "android.hardware.radio.ims.media-V2-ndk",
-        "android.hardware.radio.messaging-V3-ndk",
-        "android.hardware.radio.modem-V3-ndk",
-        "android.hardware.radio.network-V3-ndk",
-        "android.hardware.radio.sap-V1-ndk",
-        "android.hardware.radio.sim-V3-ndk",
-        "android.hardware.radio.voice-V3-ndk",
         "android.hardware.radio@1.0",
         "android.hardware.radio@1.1",
         "android.hardware.radio@1.2",
diff --git a/radio/aidl/vts/Android.bp b/radio/aidl/vts/Android.bp
index 9521068..37e0ba8 100644
--- a/radio/aidl/vts/Android.bp
+++ b/radio/aidl/vts/Android.bp
@@ -79,9 +79,9 @@
     static_libs: [
         "android.hardware.radio-V3-ndk",
         "android.hardware.radio.config-V3-ndk",
-        "android.hardware.radio.data-V3-ndk",
+        "android.hardware.radio.data-V4-ndk",
         "android.hardware.radio.ims-V2-ndk",
-        "android.hardware.radio.ims.media-V2-ndk",
+        "android.hardware.radio.ims.media-V3-ndk",
         "android.hardware.radio.messaging-V3-ndk",
         "android.hardware.radio.modem-V3-ndk",
         "android.hardware.radio.network-V3-ndk",
diff --git a/rebootescrow/aidl/vts/functional/Android.bp b/rebootescrow/aidl/vts/functional/Android.bp
index 76b6784..ba15cca 100644
--- a/rebootescrow/aidl/vts/functional/Android.bp
+++ b/rebootescrow/aidl/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_platform_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/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/support/Android.bp b/security/keymint/support/Android.bp
index 608d328..f313cf3 100644
--- a/security/keymint/support/Android.bp
+++ b/security/keymint/support/Android.bp
@@ -55,6 +55,35 @@
 }
 
 cc_library {
+    name: "libkeymint_support_V3",
+    vendor_available: true,
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+    ],
+    srcs: [
+        "attestation_record.cpp",
+        "authorization_set.cpp",
+        "keymint_utils.cpp",
+        "key_param_output.cpp",
+    ],
+    export_include_dirs: [
+        "include",
+    ],
+    header_libs: [
+        "libhardware_headers",
+    ],
+    shared_libs: [
+        "android.hardware.security.keymint-V3-ndk",
+        "libbase",
+        "libcrypto",
+        "libutils",
+        "libhardware",
+    ],
+}
+
+cc_library {
     name: "libkeymint_remote_prov_support",
     vendor_available: true,
     srcs: [
@@ -97,6 +126,7 @@
     ],
     shared_libs: [
         "libbase",
+        "libbinder_ndk",
         "libcppbor",
         "libcppcose_rkp",
         "libcrypto",
diff --git a/security/keymint/support/include/remote_prov/MockIRemotelyProvisionedComponent.h b/security/keymint/support/include/remote_prov/MockIRemotelyProvisionedComponent.h
new file mode 100644
index 0000000..4fa39c2
--- /dev/null
+++ b/security/keymint/support/include/remote_prov/MockIRemotelyProvisionedComponent.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright 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.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.h>
+#include <aidl/android/hardware/security/keymint/RpcHardwareInfo.h>
+#include <android-base/properties.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include <cstdint>
+
+namespace aidl::android::hardware::security::keymint::remote_prov {
+
+using ::ndk::ScopedAStatus;
+
+class MockIRemotelyProvisionedComponent : public IRemotelyProvisionedComponentDefault {
+  public:
+    MOCK_METHOD(ScopedAStatus, getHardwareInfo, (RpcHardwareInfo * _aidl_return), (override));
+    MOCK_METHOD(ScopedAStatus, generateEcdsaP256KeyPair,
+                (bool in_testMode, MacedPublicKey* out_macedPublicKey,
+                 std::vector<uint8_t>* _aidl_return),
+                (override));
+    MOCK_METHOD(ScopedAStatus, generateCertificateRequest,
+                (bool in_testMode, const std::vector<MacedPublicKey>& in_keysToSign,
+                 const std::vector<uint8_t>& in_endpointEncryptionCertChain,
+                 const std::vector<uint8_t>& in_challenge, DeviceInfo* out_deviceInfo,
+                 ProtectedData* out_protectedData, std::vector<uint8_t>* _aidl_return),
+                (override));
+    MOCK_METHOD(ScopedAStatus, generateCertificateRequestV2,
+                (const std::vector<MacedPublicKey>& in_keysToSign,
+                 const std::vector<uint8_t>& in_challenge, std::vector<uint8_t>* _aidl_return),
+                (override));
+    MOCK_METHOD(ScopedAStatus, getInterfaceVersion, (int32_t* _aidl_return), (override));
+    MOCK_METHOD(ScopedAStatus, getInterfaceHash, (std::string * _aidl_return), (override));
+};
+
+}  // namespace aidl::android::hardware::security::keymint::remote_prov
\ No newline at end of file
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 b56c90a..caeb7ff 100644
--- a/security/keymint/support/include/remote_prov/remote_prov_utils.h
+++ b/security/keymint/support/include/remote_prov/remote_prov_utils.h
@@ -94,6 +94,13 @@
 const std::string RKPVM_INSTANCE_NAME =
         "android.hardware.security.keymint.IRemotelyProvisionedComponent/avf";
 
+/**
+ * Returns the portion of an instance name after the /
+ * e.g. for "android.hardware.security.keymint.IRemotelyProvisionedComponent/avf",
+ * it returns "avf".
+ */
+std::string deviceSuffix(const std::string& name);
+
 struct EekChain {
     bytevec chain;
     bytevec last_pubkey;
@@ -184,7 +191,9 @@
 ErrMsgOr<std::unique_ptr<cppbor::Array>> verifyFactoryCsr(
         const cppbor::Array& keysToSign, const std::vector<uint8_t>& csr,
         IRemotelyProvisionedComponent* provisionable, const std::string& instanceName,
-        const std::vector<uint8_t>& challenge, bool allowDegenerate = true);
+        const std::vector<uint8_t>& challenge, bool allowDegenerate = true,
+        bool requireUdsCerts = false);
+
 /**
  * Verify the CSR as if the device is a final production sample.
  */
diff --git a/security/keymint/support/remote_prov_utils.cpp b/security/keymint/support/remote_prov_utils.cpp
index 497f478..464d912 100644
--- a/security/keymint/support/remote_prov_utils.cpp
+++ b/security/keymint/support/remote_prov_utils.cpp
@@ -52,8 +52,8 @@
 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('/');
+std::string deviceSuffix(const std::string& name) {
+    size_t pos = name.rfind('/');
     if (pos == std::string::npos) {
         return name;
     }
@@ -344,15 +344,18 @@
     }
 
     auto chain =
-            hwtrust::DiceChain::Verify(encodedBcc, kind, allowAnyMode, device_suffix(instanceName));
-    if (!chain.ok()) return chain.error().message();
-
+            hwtrust::DiceChain::Verify(encodedBcc, kind, allowAnyMode, deviceSuffix(instanceName));
+    if (!chain.ok()) {
+        return chain.error().message();
+    }
     if (!allowDegenerate && !chain->IsProper()) {
         return "DICE chain is degenerate";
     }
 
     auto keys = chain->CosePublicKeys();
-    if (!keys.ok()) return keys.error().message();
+    if (!keys.ok()) {
+        return keys.error().message();
+    }
     std::vector<BccEntryData> result;
     for (auto& key : *keys) {
         result.push_back({std::move(key)});
@@ -857,7 +860,8 @@
     return rawPubKey;
 }
 
-std::string validateUdsCerts(const cppbor::Map& udsCerts, const bytevec& udsCoseKeyBytes) {
+std::optional<std::string> validateUdsCerts(const cppbor::Map& udsCerts,
+                                            const bytevec& udsCoseKeyBytes) {
     for (const auto& [signerName, udsCertChain] : udsCerts) {
         if (!signerName || !signerName->asTstr()) {
             return "Signer Name must be a Tstr.";
@@ -874,8 +878,9 @@
             return leafPubKey.message();
         }
         auto coseKey = CoseKey::parse(udsCoseKeyBytes);
-        if (!coseKey) return coseKey.moveMessage();
-
+        if (!coseKey) {
+            return coseKey.moveMessage();
+        }
         auto curve = coseKey->getIntValue(CoseKey::CURVE);
         if (!curve) {
             return "CoseKey must contain curve.";
@@ -883,7 +888,9 @@
         bytevec udsPub;
         if (curve == CoseKeyCurve::P256 || curve == CoseKeyCurve::P384) {
             auto pubKey = coseKey->getEcPublicKey();
-            if (!pubKey) return pubKey.moveMessage();
+            if (!pubKey) {
+                return pubKey.moveMessage();
+            }
             // convert public key to uncompressed form by prepending 0x04 at begin.
             pubKey->insert(pubKey->begin(), 0x04);
             udsPub = pubKey.moveValue();
@@ -900,7 +907,7 @@
             return "Leaf public key in UDS certificate chain doesn't match UDS public key.";
         }
     }
-    return "";
+    return std::nullopt;
 }
 
 ErrMsgOr<std::unique_ptr<cppbor::Array>> parseAndValidateCsrPayload(
@@ -1016,7 +1023,8 @@
                                                        const std::vector<uint8_t>& challenge,
                                                        const std::string& instanceName,
                                                        bool allowAnyMode = false,
-                                                       bool allowDegenerate = true) {
+                                                       bool allowDegenerate = true,
+                                                       bool requireUdsCerts = false) {
     auto [parsedRequest, _, csrErrMsg] = cppbor::parse(request);
     if (!parsedRequest) {
         return csrErrMsg;
@@ -1038,8 +1046,12 @@
     if (!version || version->value() != 1U) {
         return "AuthenticatedRequest version must be an unsigned integer and must be equal to 1.";
     }
+
     if (!udsCerts) {
-        return "AuthenticatedRequest UdsCerts must be an Map.";
+        return "AuthenticatedRequest UdsCerts must be a Map.";
+    }
+    if (requireUdsCerts && udsCerts->size() == 0) {
+        return "AuthenticatedRequest UdsCerts must not be empty.";
     }
     if (!diceCertChain) {
         return "AuthenticatedRequest DiceCertChain must be an Array.";
@@ -1060,15 +1072,20 @@
         return diceContents.message() + "\n" + prettyPrint(diceCertChain);
     }
 
+    if (!diceCertChain->get(0)->asMap()) {
+        return "AuthenticatedRequest The first entry in DiceCertChain must be a Map.";
+    }
     auto udsPub = diceCertChain->get(0)->asMap()->encode();
-    auto& kmDiceKey = diceContents->back().pubKey;
-
     auto error = validateUdsCerts(*udsCerts, udsPub);
-    if (!error.empty()) {
-        return error;
+    if (error) {
+        return *error;
     }
 
-    auto signedPayload = verifyAndParseCoseSign1(signedData, kmDiceKey, {} /* aad */);
+    if (diceContents->empty()) {
+        return "AuthenticatedRequest DiceContents must not be empty.";
+    }
+    auto& kmDiceKey = diceContents->back().pubKey;
+    auto signedPayload = verifyAndParseCoseSign1(signedData, kmDiceKey, /*aad=*/{});
     if (!signedPayload) {
         return signedPayload.message();
     }
@@ -1081,13 +1098,11 @@
     return payload;
 }
 
-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) {
+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, bool requireUdsCerts = false) {
     RpcHardwareInfo info;
     provisionable->getHardwareInfo(&info);
     if (info.versionNumber != 3) {
@@ -1095,8 +1110,9 @@
                ") does not match expected version (3).";
     }
 
-    auto csrPayload = parseAndValidateAuthenticatedRequest(csr, challenge, instanceName,
-                                                           allowAnyMode, allowDegenerate);
+    auto csrPayload = parseAndValidateAuthenticatedRequest(
+            csr, challenge, instanceName, allowAnyMode, allowDegenerate, requireUdsCerts);
+
     if (!csrPayload) {
         return csrPayload.message();
     }
@@ -1107,9 +1123,9 @@
 ErrMsgOr<std::unique_ptr<cppbor::Array>> verifyFactoryCsr(
         const cppbor::Array& keysToSign, const std::vector<uint8_t>& csr,
         IRemotelyProvisionedComponent* provisionable, const std::string& instanceName,
-        const std::vector<uint8_t>& challenge, bool allowDegenerate) {
+        const std::vector<uint8_t>& challenge, bool allowDegenerate, bool requireUdsCerts) {
     return verifyCsr(keysToSign, csr, provisionable, instanceName, challenge, /*isFactory=*/true,
-                     /*allowAnyMode=*/false, allowDegenerate);
+                     /*allowAnyMode=*/false, allowDegenerate, requireUdsCerts);
 }
 
 ErrMsgOr<std::unique_ptr<cppbor::Array>> verifyProductionCsr(
@@ -1153,7 +1169,7 @@
 
     auto encodedDiceChain = diceCertChain->encode();
     auto chain = hwtrust::DiceChain::Verify(encodedDiceChain, *diceChainKind,
-                                            /*allowAnyMode=*/false, device_suffix(instanceName));
+                                            /*allowAnyMode=*/false, deviceSuffix(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 8b18b29..8ffb149 100644
--- a/security/keymint/support/remote_prov_utils_test.cpp
+++ b/security/keymint/support/remote_prov_utils_test.cpp
@@ -25,6 +25,7 @@
 #include <keymaster/logger.h>
 #include <keymaster/remote_provisioning_utils.h>
 #include <openssl/curve25519.h>
+#include <remote_prov/MockIRemotelyProvisionedComponent.h>
 #include <remote_prov/remote_prov_utils.h>
 
 #include <algorithm>
@@ -41,6 +42,11 @@
 using ::testing::ElementsAreArray;
 using byte_view = std::span<const uint8_t>;
 
+using ::cppbor::Array;
+using ::cppbor::parse;
+using ::ndk::SharedRefBase;
+using ::testing::NotNull;
+
 inline const std::vector<uint8_t> kDegenerateBcc{
         0x82, 0xa5, 0x01, 0x01, 0x03, 0x27, 0x04, 0x81, 0x02, 0x20, 0x06, 0x21, 0x58, 0x20, 0xf5,
         0x5a, 0xfb, 0x28, 0x06, 0x48, 0x68, 0xea, 0x49, 0x3e, 0x47, 0x80, 0x1d, 0xfe, 0x1f, 0xfc,
@@ -76,6 +82,252 @@
         0x50, 0x12, 0x82, 0x37, 0xfe, 0xa4, 0x07, 0xc3, 0xd5, 0xc3, 0x78, 0xcc, 0xf9, 0xef, 0xe1,
         0x95, 0x38, 0x9f, 0xb0, 0x79, 0x16, 0x4c, 0x4a, 0x23, 0xc4, 0xdc, 0x35, 0x4e, 0x0f};
 
+// The challenge that is in kKeysToSignForCsrWithUdsCerts and kCsrWithUdsCerts
+inline const std::vector<uint8_t> kChallenge{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+                                             0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
+                                             0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
+                                             0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20};
+
+inline const std::vector<uint8_t> kKeysToSignForCsrWithUdsCerts{
+        0x82, 0xa6, 0x01, 0x02, 0x03, 0x26, 0x20, 0x01, 0x21, 0x58, 0x20, 0x35, 0xeb, 0x56, 0xed,
+        0x62, 0x13, 0x6a, 0x41, 0x89, 0xf6, 0x72, 0xa6, 0xf1, 0x5c, 0xd1, 0xf6, 0x34, 0xbd, 0x81,
+        0xdb, 0x2e, 0x0b, 0x4d, 0xf6, 0x69, 0x6f, 0xa6, 0xf3, 0xce, 0x27, 0x2c, 0x78, 0x22, 0x58,
+        0x20, 0xac, 0xa9, 0x9f, 0x62, 0x81, 0x58, 0xc7, 0x10, 0xd7, 0xb5, 0xa8, 0xa0, 0x7b, 0x11,
+        0xf5, 0x75, 0xdb, 0xd9, 0xa2, 0x1d, 0x86, 0x34, 0xc6, 0xf4, 0x23, 0x79, 0xcc, 0x8a, 0x87,
+        0x3c, 0xb2, 0xd0, 0x23, 0x58, 0x20, 0x0f, 0x2c, 0x5a, 0xb7, 0xe1, 0x3b, 0x24, 0xa3, 0x4f,
+        0xaa, 0x49, 0x51, 0xfc, 0x8c, 0xd0, 0x35, 0x43, 0x7c, 0x21, 0xfa, 0x7d, 0x56, 0x97, 0x69,
+        0xe1, 0x81, 0xf5, 0x88, 0x15, 0x33, 0xa0, 0x7f, 0xa6, 0x01, 0x02, 0x03, 0x26, 0x20, 0x01,
+        0x21, 0x58, 0x20, 0xb5, 0xcc, 0xd9, 0x4f, 0x7a, 0xe2, 0xca, 0xac, 0xfe, 0xa5, 0x65, 0x0c,
+        0x6a, 0xa8, 0x16, 0x45, 0x40, 0x41, 0x1c, 0xb2, 0x64, 0xcd, 0x34, 0xe8, 0x37, 0x88, 0xb9,
+        0x9a, 0xb3, 0xc3, 0xfd, 0x6a, 0x22, 0x58, 0x20, 0x5e, 0xbe, 0xff, 0x98, 0x60, 0x6e, 0x1d,
+        0x6b, 0x42, 0x60, 0x59, 0xe9, 0x42, 0x95, 0xc8, 0x2e, 0xc5, 0xb6, 0x66, 0x4a, 0x53, 0xf1,
+        0x73, 0x02, 0xcb, 0x89, 0x8a, 0x2a, 0xc9, 0xa5, 0xa3, 0x39, 0x23, 0x58, 0x21, 0x00, 0xdb,
+        0xda, 0x3c, 0x3e, 0x27, 0x71, 0x5e, 0xd0, 0x2b, 0x09, 0xb8, 0x6f, 0xe2, 0x2c, 0xdd, 0x0a,
+        0xbf, 0x1d, 0x94, 0x36, 0xd2, 0x33, 0x88, 0x6e, 0x66, 0x05, 0x21, 0x92, 0x64, 0x79, 0xa9,
+        0x10};
+
+inline const std::vector<uint8_t> kCsrWithUdsCerts{
+        0x84, 0x01, 0xa1, 0x70, 0x74, 0x65, 0x73, 0x74, 0x2d, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72,
+        0x2d, 0x6e, 0x61, 0x6d, 0x65, 0x82, 0x59, 0x01, 0x6c, 0x30, 0x82, 0x01, 0x68, 0x30, 0x82,
+        0x01, 0x1a, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x7b, 0x30, 0x05, 0x06, 0x03, 0x2b,
+        0x65, 0x70, 0x30, 0x2b, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0c,
+        0x46, 0x61, 0x6b, 0x65, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x31, 0x12, 0x30,
+        0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x09, 0x46, 0x61, 0x6b, 0x65, 0x20, 0x52, 0x6f,
+        0x6f, 0x74, 0x30, 0x1e, 0x17, 0x0d, 0x32, 0x34, 0x31, 0x30, 0x31, 0x37, 0x31, 0x39, 0x32,
+        0x33, 0x30, 0x39, 0x5a, 0x17, 0x0d, 0x32, 0x34, 0x31, 0x31, 0x31, 0x36, 0x31, 0x39, 0x32,
+        0x33, 0x30, 0x39, 0x5a, 0x30, 0x2b, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0a,
+        0x13, 0x0c, 0x46, 0x61, 0x6b, 0x65, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x31,
+        0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x09, 0x46, 0x61, 0x6b, 0x65, 0x20,
+        0x52, 0x6f, 0x6f, 0x74, 0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x70, 0x03, 0x21,
+        0x00, 0x20, 0xc5, 0xfa, 0x42, 0xe9, 0x23, 0xd3, 0x72, 0x83, 0x96, 0xc5, 0x73, 0x1e, 0xec,
+        0x07, 0x39, 0x4f, 0xc8, 0xb7, 0xd1, 0x9f, 0x77, 0xb6, 0x0b, 0x59, 0x9e, 0x62, 0xc0, 0xec,
+        0x06, 0x06, 0xad, 0xa3, 0x63, 0x30, 0x61, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04,
+        0x16, 0x04, 0x14, 0xec, 0x36, 0x07, 0x83, 0xf0, 0xda, 0x23, 0xfc, 0x0f, 0xb1, 0x08, 0xd0,
+        0x60, 0x97, 0xc1, 0x9a, 0x14, 0x54, 0xbf, 0x63, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23,
+        0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xec, 0x36, 0x07, 0x83, 0xf0, 0xda, 0x23, 0xfc, 0x0f,
+        0xb1, 0x08, 0xd0, 0x60, 0x97, 0xc1, 0x9a, 0x14, 0x54, 0xbf, 0x63, 0x30, 0x0f, 0x06, 0x03,
+        0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0e,
+        0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x02, 0x04, 0x30,
+        0x05, 0x06, 0x03, 0x2b, 0x65, 0x70, 0x03, 0x41, 0x00, 0x41, 0xfa, 0x27, 0xfd, 0xe3, 0x42,
+        0x89, 0x43, 0x68, 0x92, 0x48, 0x39, 0xb1, 0x93, 0x93, 0x8b, 0x69, 0x16, 0x50, 0xbe, 0xc0,
+        0xc5, 0x83, 0xd6, 0x1e, 0x4b, 0x2f, 0x6e, 0x18, 0x32, 0x78, 0xfe, 0x35, 0x78, 0xed, 0x6d,
+        0xc8, 0x36, 0xb2, 0x4e, 0x0d, 0x10, 0x23, 0xab, 0x28, 0x32, 0xa1, 0xfc, 0x83, 0x2a, 0xa3,
+        0xca, 0xe1, 0xca, 0x82, 0xd2, 0x5f, 0xf1, 0x7f, 0xf2, 0xba, 0xbe, 0x86, 0x0b, 0x59, 0x01,
+        0x70, 0x30, 0x82, 0x01, 0x6c, 0x30, 0x82, 0x01, 0x1e, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
+        0x02, 0x01, 0xc8, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x70, 0x30, 0x2b, 0x31, 0x15, 0x30,
+        0x13, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0c, 0x46, 0x61, 0x6b, 0x65, 0x20, 0x43, 0x6f,
+        0x6d, 0x70, 0x61, 0x6e, 0x79, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
+        0x09, 0x46, 0x61, 0x6b, 0x65, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x30, 0x1e, 0x17, 0x0d, 0x32,
+        0x34, 0x31, 0x30, 0x31, 0x37, 0x31, 0x39, 0x32, 0x33, 0x30, 0x39, 0x5a, 0x17, 0x0d, 0x32,
+        0x34, 0x31, 0x31, 0x31, 0x36, 0x31, 0x39, 0x32, 0x33, 0x30, 0x39, 0x5a, 0x30, 0x2e, 0x31,
+        0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0c, 0x46, 0x61, 0x6b, 0x65, 0x20,
+        0x43, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04,
+        0x03, 0x13, 0x0c, 0x46, 0x61, 0x6b, 0x65, 0x20, 0x43, 0x68, 0x69, 0x70, 0x73, 0x65, 0x74,
+        0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x70, 0x03, 0x21, 0x00, 0x14, 0xf4, 0x4a,
+        0x88, 0x56, 0x9f, 0xc0, 0xf5, 0x1f, 0xe5, 0xef, 0xfb, 0xf4, 0x06, 0xbc, 0xb1, 0xe4, 0x4a,
+        0x37, 0xe5, 0x07, 0xf8, 0x65, 0x95, 0x55, 0x54, 0xfd, 0x90, 0xf9, 0x8b, 0xa7, 0xc6, 0xa3,
+        0x63, 0x30, 0x61, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xef,
+        0x05, 0x40, 0x0a, 0x1b, 0x74, 0x3e, 0x4d, 0x2e, 0x22, 0xf5, 0x66, 0x0c, 0xd7, 0xf9, 0xb8,
+        0x8e, 0x81, 0x3d, 0xab, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16,
+        0x80, 0x14, 0xec, 0x36, 0x07, 0x83, 0xf0, 0xda, 0x23, 0xfc, 0x0f, 0xb1, 0x08, 0xd0, 0x60,
+        0x97, 0xc1, 0x9a, 0x14, 0x54, 0xbf, 0x63, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
+        0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d,
+        0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x02, 0x04, 0x30, 0x05, 0x06, 0x03, 0x2b,
+        0x65, 0x70, 0x03, 0x41, 0x00, 0x64, 0x32, 0x42, 0x06, 0xa7, 0x11, 0xb0, 0x67, 0x81, 0x73,
+        0x19, 0x70, 0xb6, 0x60, 0x1c, 0xd2, 0x43, 0xde, 0x42, 0xec, 0x71, 0x4d, 0x6e, 0xa8, 0xed,
+        0x6f, 0xe2, 0x59, 0x3e, 0xa3, 0x45, 0x82, 0x8b, 0x25, 0x25, 0xf9, 0xc6, 0xb3, 0xf5, 0xb5,
+        0x3d, 0x11, 0x7d, 0xcf, 0xf2, 0x50, 0x22, 0xff, 0x2b, 0xc5, 0x14, 0x94, 0x64, 0xbf, 0xbf,
+        0x52, 0x69, 0xb1, 0xfe, 0x07, 0x81, 0x83, 0xb3, 0x0d, 0x82, 0xa5, 0x01, 0x01, 0x03, 0x27,
+        0x20, 0x06, 0x21, 0x58, 0x20, 0x14, 0xf4, 0x4a, 0x88, 0x56, 0x9f, 0xc0, 0xf5, 0x1f, 0xe5,
+        0xef, 0xfb, 0xf4, 0x06, 0xbc, 0xb1, 0xe4, 0x4a, 0x37, 0xe5, 0x07, 0xf8, 0x65, 0x95, 0x55,
+        0x54, 0xfd, 0x90, 0xf9, 0x8b, 0xa7, 0xc6, 0x23, 0x58, 0x20, 0x8d, 0x38, 0x0d, 0x38, 0xcb,
+        0x76, 0x73, 0xef, 0x13, 0xd1, 0x08, 0x02, 0xa5, 0x0e, 0xd2, 0x16, 0xd4, 0x0f, 0x2c, 0x29,
+        0xf8, 0xd0, 0x20, 0xb8, 0x6a, 0x7f, 0xa2, 0xd1, 0x1e, 0xeb, 0xd1, 0x5c, 0x84, 0x43, 0xa1,
+        0x01, 0x27, 0xa0, 0x59, 0x01, 0x27, 0xa9, 0x01, 0x66, 0x69, 0x73, 0x73, 0x75, 0x65, 0x72,
+        0x02, 0x67, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3a, 0x00, 0x47, 0x44, 0x50, 0x58,
+        0x20, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+        0x55, 0x55, 0x55, 0x3a, 0x00, 0x47, 0x44, 0x52, 0x58, 0x20, 0xb8, 0x96, 0x54, 0xe2, 0x2c,
+        0xa4, 0xd2, 0x4a, 0x9c, 0x0e, 0x45, 0x11, 0xc8, 0xf2, 0x63, 0xf0, 0x66, 0x0d, 0x2e, 0x20,
+        0x48, 0x96, 0x90, 0x14, 0xf4, 0x54, 0x63, 0xc4, 0xf4, 0x39, 0x30, 0x38, 0x3a, 0x00, 0x47,
+        0x44, 0x53, 0x55, 0xa1, 0x3a, 0x00, 0x01, 0x11, 0x71, 0x6e, 0x63, 0x6f, 0x6d, 0x70, 0x6f,
+        0x6e, 0x65, 0x6e, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x3a, 0x00, 0x47, 0x44, 0x54, 0x58,
+        0x20, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+        0x55, 0x55, 0x55, 0x3a, 0x00, 0x47, 0x44, 0x56, 0x41, 0x01, 0x3a, 0x00, 0x47, 0x44, 0x57,
+        0x58, 0x70, 0xa6, 0x01, 0x02, 0x03, 0x26, 0x20, 0x01, 0x21, 0x58, 0x20, 0x76, 0x82, 0x58,
+        0xce, 0x99, 0x1c, 0x29, 0xa1, 0x81, 0x3e, 0x22, 0xe3, 0x02, 0x13, 0xea, 0x2a, 0x25, 0x2e,
+        0x20, 0x14, 0xeb, 0x45, 0x0d, 0xb8, 0xdb, 0x8c, 0x38, 0xef, 0xeb, 0x25, 0xd6, 0x31, 0x22,
+        0x58, 0x20, 0xbe, 0x55, 0xba, 0x87, 0x17, 0xc2, 0x5b, 0xb6, 0x56, 0xff, 0x4b, 0xf0, 0x8a,
+        0x98, 0x57, 0x86, 0xa4, 0x36, 0x0a, 0x90, 0x38, 0xce, 0x66, 0xec, 0xcb, 0x25, 0x30, 0x29,
+        0x83, 0x02, 0x02, 0xc0, 0x23, 0x58, 0x20, 0x73, 0xdf, 0xc3, 0x4a, 0xe4, 0x2e, 0xbd, 0x04,
+        0x09, 0xec, 0x91, 0xc7, 0xe7, 0xf1, 0xec, 0x55, 0x10, 0x7e, 0xd1, 0x36, 0x5e, 0x9d, 0x11,
+        0x71, 0x27, 0xee, 0x30, 0x7b, 0x04, 0x45, 0x5f, 0x95, 0x3a, 0x00, 0x47, 0x44, 0x58, 0x41,
+        0x20, 0x58, 0x40, 0x44, 0x7f, 0x1a, 0x67, 0x16, 0xa0, 0x49, 0xfe, 0x2c, 0xde, 0x87, 0x38,
+        0xef, 0xb9, 0xe0, 0x19, 0x25, 0x7d, 0xcc, 0x39, 0x53, 0x27, 0xbd, 0x2c, 0x04, 0x6c, 0xe3,
+        0x5c, 0x5e, 0xd6, 0x27, 0x09, 0xb9, 0xf7, 0x8c, 0x2b, 0xd2, 0x68, 0xc3, 0xf1, 0x23, 0xcf,
+        0xc6, 0xfc, 0x21, 0xb3, 0x52, 0x48, 0xe6, 0x8a, 0x89, 0x3e, 0x37, 0x24, 0x13, 0x23, 0x80,
+        0xb2, 0xc7, 0xa7, 0xc6, 0xf1, 0xec, 0x04, 0x84, 0x43, 0xa1, 0x01, 0x26, 0xa0, 0x59, 0x02,
+        0x0f, 0x82, 0x58, 0x20, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
+        0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a,
+        0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x59, 0x01, 0xe9, 0x84, 0x03, 0x67, 0x6b, 0x65, 0x79,
+        0x6d, 0x69, 0x6e, 0x74, 0xae, 0x65, 0x62, 0x72, 0x61, 0x6e, 0x64, 0x66, 0x47, 0x6f, 0x6f,
+        0x67, 0x6c, 0x65, 0x65, 0x66, 0x75, 0x73, 0x65, 0x64, 0x01, 0x65, 0x6d, 0x6f, 0x64, 0x65,
+        0x6c, 0x65, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x66, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x66,
+        0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x67, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x65,
+        0x70, 0x69, 0x78, 0x65, 0x6c, 0x68, 0x76, 0x62, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x65,
+        0x67, 0x72, 0x65, 0x65, 0x6e, 0x6a, 0x6f, 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f,
+        0x6e, 0x62, 0x31, 0x32, 0x6c, 0x6d, 0x61, 0x6e, 0x75, 0x66, 0x61, 0x63, 0x74, 0x75, 0x72,
+        0x65, 0x72, 0x66, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x6d, 0x76, 0x62, 0x6d, 0x65, 0x74,
+        0x61, 0x5f, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x4f, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66,
+        0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72,
+        0x69, 0x74, 0x79, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x63, 0x74, 0x65, 0x65, 0x70, 0x62,
+        0x6f, 0x6f, 0x74, 0x5f, 0x70, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c,
+        0x1a, 0x01, 0x34, 0x8c, 0x62, 0x70, 0x62, 0x6f, 0x6f, 0x74, 0x6c, 0x6f, 0x61, 0x64, 0x65,
+        0x72, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x66, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x72,
+        0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x5f, 0x70, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x6c, 0x65,
+        0x76, 0x65, 0x6c, 0x1a, 0x01, 0x34, 0x8c, 0x61, 0x72, 0x76, 0x65, 0x6e, 0x64, 0x6f, 0x72,
+        0x5f, 0x70, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x1a, 0x01, 0x34,
+        0x8c, 0x63, 0x82, 0xa6, 0x01, 0x02, 0x03, 0x26, 0x20, 0x01, 0x21, 0x58, 0x20, 0x35, 0xeb,
+        0x56, 0xed, 0x62, 0x13, 0x6a, 0x41, 0x89, 0xf6, 0x72, 0xa6, 0xf1, 0x5c, 0xd1, 0xf6, 0x34,
+        0xbd, 0x81, 0xdb, 0x2e, 0x0b, 0x4d, 0xf6, 0x69, 0x6f, 0xa6, 0xf3, 0xce, 0x27, 0x2c, 0x78,
+        0x22, 0x58, 0x20, 0xac, 0xa9, 0x9f, 0x62, 0x81, 0x58, 0xc7, 0x10, 0xd7, 0xb5, 0xa8, 0xa0,
+        0x7b, 0x11, 0xf5, 0x75, 0xdb, 0xd9, 0xa2, 0x1d, 0x86, 0x34, 0xc6, 0xf4, 0x23, 0x79, 0xcc,
+        0x8a, 0x87, 0x3c, 0xb2, 0xd0, 0x23, 0x58, 0x20, 0x0f, 0x2c, 0x5a, 0xb7, 0xe1, 0x3b, 0x24,
+        0xa3, 0x4f, 0xaa, 0x49, 0x51, 0xfc, 0x8c, 0xd0, 0x35, 0x43, 0x7c, 0x21, 0xfa, 0x7d, 0x56,
+        0x97, 0x69, 0xe1, 0x81, 0xf5, 0x88, 0x15, 0x33, 0xa0, 0x7f, 0xa6, 0x01, 0x02, 0x03, 0x26,
+        0x20, 0x01, 0x21, 0x58, 0x20, 0xb5, 0xcc, 0xd9, 0x4f, 0x7a, 0xe2, 0xca, 0xac, 0xfe, 0xa5,
+        0x65, 0x0c, 0x6a, 0xa8, 0x16, 0x45, 0x40, 0x41, 0x1c, 0xb2, 0x64, 0xcd, 0x34, 0xe8, 0x37,
+        0x88, 0xb9, 0x9a, 0xb3, 0xc3, 0xfd, 0x6a, 0x22, 0x58, 0x20, 0x5e, 0xbe, 0xff, 0x98, 0x60,
+        0x6e, 0x1d, 0x6b, 0x42, 0x60, 0x59, 0xe9, 0x42, 0x95, 0xc8, 0x2e, 0xc5, 0xb6, 0x66, 0x4a,
+        0x53, 0xf1, 0x73, 0x02, 0xcb, 0x89, 0x8a, 0x2a, 0xc9, 0xa5, 0xa3, 0x39, 0x23, 0x58, 0x21,
+        0x00, 0xdb, 0xda, 0x3c, 0x3e, 0x27, 0x71, 0x5e, 0xd0, 0x2b, 0x09, 0xb8, 0x6f, 0xe2, 0x2c,
+        0xdd, 0x0a, 0xbf, 0x1d, 0x94, 0x36, 0xd2, 0x33, 0x88, 0x6e, 0x66, 0x05, 0x21, 0x92, 0x64,
+        0x79, 0xa9, 0x10, 0x58, 0x40, 0x87, 0xcf, 0xaa, 0x82, 0x6a, 0xba, 0x25, 0x8b, 0x81, 0xd8,
+        0x14, 0xca, 0xbd, 0xf4, 0x67, 0xdf, 0xc8, 0x2c, 0xa1, 0x04, 0x57, 0x99, 0xa0, 0x54, 0xe7,
+        0x9b, 0xb2, 0xd0, 0xaf, 0xdd, 0x07, 0x46, 0x0a, 0xd7, 0xbd, 0xa7, 0xf9, 0xa8, 0x0c, 0x08,
+        0x1e, 0x9c, 0xae, 0x73, 0x4c, 0x22, 0x6e, 0x56, 0x8b, 0xe4, 0x91, 0x54, 0xa4, 0x7a, 0xb0,
+        0xf5, 0xe4, 0x5d, 0xa9, 0x8f, 0xae, 0x43, 0x95, 0x7a};
+
+inline const std::vector<uint8_t> kKeysToSignForCsrWithoutUdsCerts = {
+        0x82, 0xa6, 0x01, 0x02, 0x03, 0x26, 0x20, 0x01, 0x21, 0x58, 0x20, 0x50, 0x43, 0xb4, 0xf1,
+        0xc1, 0x7f, 0x17, 0xc6, 0x3b, 0x56, 0x27, 0x63, 0x03, 0x18, 0x78, 0x9d, 0x63, 0x93, 0x3b,
+        0x98, 0xed, 0x55, 0x8c, 0x87, 0x1b, 0xd7, 0x89, 0xb6, 0x81, 0x92, 0x5f, 0x24, 0x22, 0x58,
+        0x20, 0xd5, 0x24, 0x93, 0xda, 0x3e, 0x32, 0x17, 0xfa, 0xe8, 0x8d, 0x1e, 0xa9, 0xe0, 0x84,
+        0x4e, 0x1c, 0x6a, 0xef, 0x9a, 0xe3, 0xbe, 0x1d, 0xf1, 0x14, 0xe0, 0x9e, 0x82, 0xc8, 0x92,
+        0x1a, 0x3a, 0x69, 0x23, 0x58, 0x20, 0x29, 0xcb, 0x16, 0x78, 0x61, 0x35, 0x92, 0x3f, 0x71,
+        0xc4, 0x66, 0x61, 0xd4, 0xd4, 0x20, 0x8a, 0x86, 0x1e, 0xb0, 0x2b, 0x2f, 0x4f, 0x13, 0xb4,
+        0x0d, 0x89, 0x60, 0x87, 0x77, 0xac, 0x1a, 0x0f, 0xa6, 0x01, 0x02, 0x03, 0x26, 0x20, 0x01,
+        0x21, 0x58, 0x20, 0x4b, 0xcc, 0x7a, 0x09, 0x99, 0x76, 0xe7, 0xfa, 0x06, 0xb9, 0x19, 0x22,
+        0x15, 0x3b, 0x9f, 0xa8, 0x34, 0x77, 0x24, 0x27, 0x8c, 0x8a, 0x97, 0x61, 0xf3, 0x6f, 0x29,
+        0x74, 0x4e, 0x9a, 0x66, 0x23, 0x22, 0x58, 0x20, 0x8f, 0xa8, 0xaf, 0x2b, 0x02, 0x3a, 0xd4,
+        0x8a, 0xa2, 0x9d, 0x25, 0xa8, 0x01, 0xe7, 0xbd, 0x61, 0x25, 0x88, 0xb4, 0xc9, 0xce, 0x05,
+        0x43, 0xcc, 0x0d, 0x38, 0x7d, 0xe2, 0xda, 0x03, 0xb3, 0x33, 0x23, 0x58, 0x21, 0x00, 0xc8,
+        0x67, 0xb8, 0xbe, 0xc4, 0x1c, 0xca, 0x3c, 0x73, 0x3c, 0xbf, 0x52, 0xb2, 0x5a, 0x64, 0x9e,
+        0x9f, 0xae, 0xc6, 0x9f, 0x02, 0x2f, 0xee, 0x92, 0x1d, 0xdb, 0x01, 0x77, 0x27, 0x12, 0x84,
+        0x14};
+
+inline const std::vector<uint8_t> kCsrWithoutUdsCerts{
+        0x84, 0x01, 0xa0, 0x82, 0xa6, 0x01, 0x02, 0x03, 0x38, 0x22, 0x20, 0x02, 0x21, 0x58, 0x30,
+        0x21, 0x09, 0x81, 0xb2, 0x4c, 0x8e, 0x23, 0x63, 0x46, 0xe5, 0x32, 0x1e, 0x1b, 0xa3, 0x39,
+        0x47, 0xd1, 0x19, 0x91, 0xc5, 0xe1, 0xd0, 0x51, 0xa4, 0x4e, 0x6d, 0xfd, 0x21, 0x46, 0xf3,
+        0x65, 0x6b, 0xd3, 0xec, 0x20, 0x21, 0xf8, 0xef, 0x39, 0x50, 0x0a, 0xfc, 0x6d, 0x18, 0xf8,
+        0x90, 0x1c, 0xc8, 0x22, 0x58, 0x30, 0x80, 0x1f, 0xd8, 0xe3, 0x64, 0x51, 0x48, 0x66, 0xa5,
+        0xad, 0x05, 0xcb, 0xe4, 0xee, 0x0f, 0x20, 0xc1, 0xca, 0x84, 0xc2, 0xe0, 0xcc, 0x22, 0x06,
+        0x7c, 0x5e, 0x2c, 0xb3, 0x3b, 0x52, 0xd4, 0xe7, 0xc1, 0xe2, 0x57, 0x9d, 0x8a, 0xa6, 0x5c,
+        0x08, 0xbb, 0x77, 0x07, 0xa8, 0x39, 0xba, 0x9f, 0x5f, 0x23, 0x58, 0x31, 0x00, 0xff, 0x5f,
+        0xa3, 0x03, 0x87, 0x70, 0xe5, 0xf0, 0x69, 0xcd, 0x0a, 0x32, 0x9e, 0x4a, 0xe8, 0x07, 0x1f,
+        0x26, 0xb9, 0x8a, 0x01, 0x83, 0xfe, 0xb9, 0x21, 0x22, 0x49, 0x9d, 0x9f, 0x78, 0x48, 0xf4,
+        0x24, 0x87, 0xe8, 0x4d, 0xab, 0xd5, 0xe9, 0xd6, 0x90, 0x49, 0x4b, 0x42, 0xb4, 0x68, 0xac,
+        0xf1, 0x84, 0x44, 0xa1, 0x01, 0x38, 0x22, 0xa0, 0x59, 0x01, 0x28, 0xa9, 0x01, 0x66, 0x69,
+        0x73, 0x73, 0x75, 0x65, 0x72, 0x02, 0x67, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3a,
+        0x00, 0x47, 0x44, 0x50, 0x58, 0x20, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x3a, 0x00, 0x47, 0x44, 0x52, 0x58, 0x20,
+        0xb8, 0x96, 0x54, 0xe2, 0x2c, 0xa4, 0xd2, 0x4a, 0x9c, 0x0e, 0x45, 0x11, 0xc8, 0xf2, 0x63,
+        0xf0, 0x66, 0x0d, 0x2e, 0x20, 0x48, 0x96, 0x90, 0x14, 0xf4, 0x54, 0x63, 0xc4, 0xf4, 0x39,
+        0x30, 0x38, 0x3a, 0x00, 0x47, 0x44, 0x53, 0x55, 0xa1, 0x3a, 0x00, 0x01, 0x11, 0x71, 0x6e,
+        0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x3a,
+        0x00, 0x47, 0x44, 0x54, 0x58, 0x20, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x3a, 0x00, 0x47, 0x44, 0x56, 0x41, 0x01,
+        0x3a, 0x00, 0x47, 0x44, 0x57, 0x58, 0x71, 0xa6, 0x01, 0x02, 0x03, 0x26, 0x20, 0x01, 0x21,
+        0x58, 0x20, 0x2d, 0x41, 0x43, 0x19, 0xf2, 0x91, 0x58, 0x12, 0x65, 0x2e, 0x96, 0xb5, 0x9d,
+        0x12, 0x18, 0x58, 0x54, 0x11, 0xed, 0x41, 0x30, 0xef, 0xa4, 0xee, 0x69, 0x8f, 0x0c, 0x6e,
+        0xe6, 0x27, 0xc5, 0x20, 0x22, 0x58, 0x20, 0x21, 0x0e, 0x8f, 0x83, 0xe5, 0xeb, 0x40, 0x89,
+        0xc2, 0x0a, 0x43, 0x6c, 0x9f, 0xa8, 0x4e, 0xe0, 0xba, 0x9e, 0xba, 0x4f, 0xe3, 0x27, 0xc4,
+        0xbd, 0x41, 0xa0, 0xd6, 0xe9, 0x55, 0x54, 0x17, 0x78, 0x23, 0x58, 0x21, 0x00, 0xb6, 0x33,
+        0x44, 0x98, 0xa7, 0x1c, 0x90, 0x13, 0xcc, 0x42, 0x71, 0x43, 0x29, 0xe5, 0xe1, 0x57, 0x89,
+        0x7a, 0x39, 0x17, 0x7c, 0xcc, 0x03, 0xac, 0xd3, 0x1b, 0xd2, 0xae, 0x29, 0x5f, 0xd6, 0xf8,
+        0x3a, 0x00, 0x47, 0x44, 0x58, 0x41, 0x20, 0x58, 0x60, 0xc4, 0x54, 0xad, 0x40, 0xa2, 0x07,
+        0xc7, 0x80, 0xbd, 0x41, 0x77, 0x5d, 0xa7, 0xa2, 0xef, 0xef, 0x92, 0x67, 0x24, 0xab, 0xa1,
+        0x4a, 0x5e, 0x4f, 0x73, 0xfb, 0x5c, 0x1f, 0xe6, 0x46, 0x2f, 0xb9, 0x1b, 0x71, 0x86, 0x87,
+        0x29, 0xc4, 0x66, 0xb7, 0x3e, 0x85, 0x13, 0x9a, 0xa3, 0xf8, 0xfc, 0x63, 0x26, 0xe0, 0xba,
+        0x0b, 0xe0, 0x9b, 0x2e, 0x7d, 0x06, 0x06, 0xb8, 0x2f, 0xdd, 0x0c, 0xa5, 0x90, 0x1c, 0x10,
+        0x1c, 0x55, 0xf9, 0x65, 0xf6, 0x26, 0x40, 0x41, 0xaf, 0x5c, 0x16, 0x03, 0xf3, 0xee, 0x8d,
+        0x72, 0x2c, 0x6b, 0x1e, 0xb3, 0x1f, 0x96, 0x97, 0x34, 0x61, 0x0d, 0x5c, 0xe4, 0x94, 0x6a,
+        0x84, 0x43, 0xa1, 0x01, 0x26, 0xa0, 0x59, 0x02, 0x0f, 0x82, 0x58, 0x20, 0x01, 0x02, 0x03,
+        0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12,
+        0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x59,
+        0x01, 0xe9, 0x84, 0x03, 0x67, 0x6b, 0x65, 0x79, 0x6d, 0x69, 0x6e, 0x74, 0xae, 0x65, 0x62,
+        0x72, 0x61, 0x6e, 0x64, 0x66, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x65, 0x66, 0x75, 0x73,
+        0x65, 0x64, 0x01, 0x65, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x65, 0x6d, 0x6f, 0x64, 0x65, 0x6c,
+        0x66, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x66, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x67,
+        0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x65, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x68, 0x76,
+        0x62, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x65, 0x67, 0x72, 0x65, 0x65, 0x6e, 0x6a, 0x6f,
+        0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x62, 0x31, 0x32, 0x6c, 0x6d, 0x61,
+        0x6e, 0x75, 0x66, 0x61, 0x63, 0x74, 0x75, 0x72, 0x65, 0x72, 0x66, 0x47, 0x6f, 0x6f, 0x67,
+        0x6c, 0x65, 0x6d, 0x76, 0x62, 0x6d, 0x65, 0x74, 0x61, 0x5f, 0x64, 0x69, 0x67, 0x65, 0x73,
+        0x74, 0x4f, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd,
+        0xee, 0xff, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x5f, 0x6c, 0x65, 0x76,
+        0x65, 0x6c, 0x63, 0x74, 0x65, 0x65, 0x70, 0x62, 0x6f, 0x6f, 0x74, 0x5f, 0x70, 0x61, 0x74,
+        0x63, 0x68, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x1a, 0x01, 0x34, 0x8c, 0x62, 0x70, 0x62,
+        0x6f, 0x6f, 0x74, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65,
+        0x66, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x72, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x5f,
+        0x70, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x1a, 0x01, 0x34, 0x8c,
+        0x61, 0x72, 0x76, 0x65, 0x6e, 0x64, 0x6f, 0x72, 0x5f, 0x70, 0x61, 0x74, 0x63, 0x68, 0x5f,
+        0x6c, 0x65, 0x76, 0x65, 0x6c, 0x1a, 0x01, 0x34, 0x8c, 0x63, 0x82, 0xa6, 0x01, 0x02, 0x03,
+        0x26, 0x20, 0x01, 0x21, 0x58, 0x20, 0x50, 0x43, 0xb4, 0xf1, 0xc1, 0x7f, 0x17, 0xc6, 0x3b,
+        0x56, 0x27, 0x63, 0x03, 0x18, 0x78, 0x9d, 0x63, 0x93, 0x3b, 0x98, 0xed, 0x55, 0x8c, 0x87,
+        0x1b, 0xd7, 0x89, 0xb6, 0x81, 0x92, 0x5f, 0x24, 0x22, 0x58, 0x20, 0xd5, 0x24, 0x93, 0xda,
+        0x3e, 0x32, 0x17, 0xfa, 0xe8, 0x8d, 0x1e, 0xa9, 0xe0, 0x84, 0x4e, 0x1c, 0x6a, 0xef, 0x9a,
+        0xe3, 0xbe, 0x1d, 0xf1, 0x14, 0xe0, 0x9e, 0x82, 0xc8, 0x92, 0x1a, 0x3a, 0x69, 0x23, 0x58,
+        0x20, 0x29, 0xcb, 0x16, 0x78, 0x61, 0x35, 0x92, 0x3f, 0x71, 0xc4, 0x66, 0x61, 0xd4, 0xd4,
+        0x20, 0x8a, 0x86, 0x1e, 0xb0, 0x2b, 0x2f, 0x4f, 0x13, 0xb4, 0x0d, 0x89, 0x60, 0x87, 0x77,
+        0xac, 0x1a, 0x0f, 0xa6, 0x01, 0x02, 0x03, 0x26, 0x20, 0x01, 0x21, 0x58, 0x20, 0x4b, 0xcc,
+        0x7a, 0x09, 0x99, 0x76, 0xe7, 0xfa, 0x06, 0xb9, 0x19, 0x22, 0x15, 0x3b, 0x9f, 0xa8, 0x34,
+        0x77, 0x24, 0x27, 0x8c, 0x8a, 0x97, 0x61, 0xf3, 0x6f, 0x29, 0x74, 0x4e, 0x9a, 0x66, 0x23,
+        0x22, 0x58, 0x20, 0x8f, 0xa8, 0xaf, 0x2b, 0x02, 0x3a, 0xd4, 0x8a, 0xa2, 0x9d, 0x25, 0xa8,
+        0x01, 0xe7, 0xbd, 0x61, 0x25, 0x88, 0xb4, 0xc9, 0xce, 0x05, 0x43, 0xcc, 0x0d, 0x38, 0x7d,
+        0xe2, 0xda, 0x03, 0xb3, 0x33, 0x23, 0x58, 0x21, 0x00, 0xc8, 0x67, 0xb8, 0xbe, 0xc4, 0x1c,
+        0xca, 0x3c, 0x73, 0x3c, 0xbf, 0x52, 0xb2, 0x5a, 0x64, 0x9e, 0x9f, 0xae, 0xc6, 0x9f, 0x02,
+        0x2f, 0xee, 0x92, 0x1d, 0xdb, 0x01, 0x77, 0x27, 0x12, 0x84, 0x14, 0x58, 0x40, 0x6c, 0xd5,
+        0x66, 0x0a, 0x99, 0xdd, 0x32, 0x47, 0x50, 0x1f, 0x5d, 0x46, 0x40, 0x8a, 0x60, 0x25, 0xa0,
+        0x1b, 0x3c, 0x2a, 0xcf, 0xa1, 0x92, 0x1a, 0xdc, 0x81, 0xaa, 0xb0, 0x0f, 0xf2, 0xe6, 0x94,
+        0xce, 0x3d, 0xff, 0xac, 0x25, 0x44, 0xea, 0xf7, 0x0a, 0x89, 0x9d, 0xc4, 0x7e, 0xe5, 0x02,
+        0xa7, 0xb6, 0xc2, 0x40, 0x06, 0x65, 0xc5, 0xff, 0x19, 0xc5, 0xcd, 0x1c, 0xd5, 0x78, 0x01,
+        0xd4, 0xb8};
+
 inline bool equal_byte_views(const byte_view& view1, const byte_view& view2) {
     return std::equal(view1.begin(), view1.end(), view2.begin(), view2.end());
 }
@@ -304,5 +556,79 @@
                              /*allowAnyMode=*/false, /*allowDegenerate=*/false,
                              DEFAULT_INSTANCE_NAME));
 }
+
+TEST(RemoteProvUtilsTest, requireUdsCertsWhenPresent) {
+    auto [keysToSignPtr, _, errMsg] = cppbor::parse(kKeysToSignForCsrWithUdsCerts);
+    ASSERT_TRUE(keysToSignPtr) << "Error: " << errMsg;
+
+    auto mockRpc = SharedRefBase::make<MockIRemotelyProvisionedComponent>();
+    EXPECT_CALL(*mockRpc, getHardwareInfo(NotNull())).WillRepeatedly([](RpcHardwareInfo* hwInfo) {
+        hwInfo->versionNumber = 3;
+        return ScopedAStatus::ok();
+    });
+
+    const auto keysToSign = keysToSignPtr->asArray();
+    auto csr = verifyFactoryCsr(*keysToSign, kCsrWithUdsCerts, mockRpc.get(), "default", kChallenge,
+                                /*allowDegenerate=*/false, /*requireUdsCerts=*/true);
+    ASSERT_TRUE(csr) << csr.message();
+}
+
+TEST(RemoteProvUtilsTest, dontRequireUdsCertsWhenPresent) {
+    auto [keysToSignPtr, _, errMsg] = cppbor::parse(kKeysToSignForCsrWithUdsCerts);
+    ASSERT_TRUE(keysToSignPtr) << "Error: " << errMsg;
+
+    auto mockRpc = SharedRefBase::make<MockIRemotelyProvisionedComponent>();
+    EXPECT_CALL(*mockRpc, getHardwareInfo(NotNull())).WillRepeatedly([](RpcHardwareInfo* hwInfo) {
+        hwInfo->versionNumber = 3;
+        return ScopedAStatus::ok();
+    });
+
+    const auto* keysToSign = keysToSignPtr->asArray();
+    auto csr = verifyFactoryCsr(*keysToSign, kCsrWithUdsCerts, mockRpc.get(), DEFAULT_INSTANCE_NAME,
+                                kChallenge,
+                                /*allowDegenerate=*/false, /*requireUdsCerts=*/false);
+    ASSERT_TRUE(csr) << csr.message();
+}
+
+TEST(RemoteProvUtilsTest, requireUdsCertsWhenNotPresent) {
+    auto mockRpc = SharedRefBase::make<MockIRemotelyProvisionedComponent>();
+    EXPECT_CALL(*mockRpc, getHardwareInfo(NotNull())).WillRepeatedly([](RpcHardwareInfo* hwInfo) {
+        hwInfo->versionNumber = 3;
+        return ScopedAStatus::ok();
+    });
+
+    auto csr = verifyFactoryCsr(/*keysToSign=*/Array(), kCsrWithoutUdsCerts, mockRpc.get(),
+                                DEFAULT_INSTANCE_NAME, kChallenge, /*allowDegenerate=*/false,
+                                /*requireUdsCerts=*/true);
+    ASSERT_FALSE(csr);
+    ASSERT_THAT(csr.message(), testing::HasSubstr("UdsCerts must not be empty"));
+}
+
+TEST(RemoteProvUtilsTest, dontRequireUdsCertsWhenNotPresent) {
+    auto [keysToSignPtr, _, errMsg] = cppbor::parse(
+            kKeysToSignForCsrWithoutUdsCerts.data(),
+            kKeysToSignForCsrWithoutUdsCerts.data() + kKeysToSignForCsrWithoutUdsCerts.size());
+    ASSERT_TRUE(keysToSignPtr) << "Error: " << errMsg;
+
+    auto mockRpc = SharedRefBase::make<MockIRemotelyProvisionedComponent>();
+    EXPECT_CALL(*mockRpc, getHardwareInfo(NotNull())).WillRepeatedly([](RpcHardwareInfo* hwInfo) {
+        hwInfo->versionNumber = 3;
+        return ScopedAStatus::ok();
+    });
+
+    const auto* keysToSign = keysToSignPtr->asArray();
+    auto csr = verifyFactoryCsr(*keysToSign, kCsrWithoutUdsCerts, mockRpc.get(),
+                                DEFAULT_INSTANCE_NAME, kChallenge,
+                                /*allowDegenerate=*/false, /*requireUdsCerts=*/false);
+    ASSERT_TRUE(csr) << csr.message();
+}
+
+TEST(RemoteProvUtilsTest, parseFullyQualifiedInstanceNames) {
+    ASSERT_EQ(deviceSuffix(RKPVM_INSTANCE_NAME), "avf");
+    ASSERT_EQ(deviceSuffix(DEFAULT_INSTANCE_NAME), "default");
+    ASSERT_EQ(deviceSuffix("default"), "default");
+    ASSERT_EQ(deviceSuffix("//the/last/one"), "one");
+}
+
 }  // 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/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/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/sensors/1.0/vts/functional/Android.bp b/sensors/1.0/vts/functional/Android.bp
index d53179a..b042907 100644
--- a/sensors/1.0/vts/functional/Android.bp
+++ b/sensors/1.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_sensors",
     // 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/sensors/2.0/vts/functional/Android.bp b/sensors/2.0/vts/functional/Android.bp
index 62eaf6b..a62a0e7 100644
--- a/sensors/2.0/vts/functional/Android.bp
+++ b/sensors/2.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_sensors",
     // 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/sensors/2.1/vts/functional/Android.bp b/sensors/2.1/vts/functional/Android.bp
index 61cfd14..e8777e5 100644
--- a/sensors/2.1/vts/functional/Android.bp
+++ b/sensors/2.1/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_android_sensors",
     // 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/thermal/aidl/Android.bp b/thermal/aidl/Android.bp
index 597a166..db77783 100644
--- a/thermal/aidl/Android.bp
+++ b/thermal/aidl/Android.bp
@@ -48,8 +48,7 @@
             version: "2",
             imports: [],
         },
-
     ],
-    frozen: true,
+    frozen: false,
 
 }
diff --git a/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/IThermalChangedCallback.aidl b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/IThermalChangedCallback.aidl
index 5e1d753..779544b 100644
--- a/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/IThermalChangedCallback.aidl
+++ b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/IThermalChangedCallback.aidl
@@ -36,4 +36,5 @@
 @VintfStability
 interface IThermalChangedCallback {
   oneway void notifyThrottling(in android.hardware.thermal.Temperature temperature);
+  oneway void notifyThresholdChanged(in android.hardware.thermal.TemperatureThreshold threshold);
 }
diff --git a/thermal/aidl/android/hardware/thermal/IThermalChangedCallback.aidl b/thermal/aidl/android/hardware/thermal/IThermalChangedCallback.aidl
index 105f085..1ff4b7a 100644
--- a/thermal/aidl/android/hardware/thermal/IThermalChangedCallback.aidl
+++ b/thermal/aidl/android/hardware/thermal/IThermalChangedCallback.aidl
@@ -17,6 +17,7 @@
 package android.hardware.thermal;
 
 import android.hardware.thermal.Temperature;
+import android.hardware.thermal.TemperatureThreshold;
 
 /**
  * IThermalChangedCallback send throttling notification to clients.
@@ -25,11 +26,19 @@
 @VintfStability
 interface IThermalChangedCallback {
     /**
-     * Send a thermal throttling event to all ThermalHAL
+     * Send a thermal throttling event to all Thermal HAL
      * thermal event listeners.
      *
      * @param temperature The temperature associated with the
      *    throttling event.
      */
     oneway void notifyThrottling(in Temperature temperature);
+
+    /**
+     * Send a thermal threshold change event to all Thermal HAL
+     * thermal event listeners.
+     *
+     * @param threshold The temperature threshold that changed.
+     */
+    oneway void notifyThresholdChanged(in TemperatureThreshold threshold);
 }
diff --git a/thermal/aidl/default/Android.bp b/thermal/aidl/default/Android.bp
index 9fe62ce..9d89903 100644
--- a/thermal/aidl/default/Android.bp
+++ b/thermal/aidl/default/Android.bp
@@ -27,7 +27,7 @@
     vendor: true,
     stl: "c++_static",
     static_libs: [
-        "android.hardware.thermal-V2-ndk",
+        "android.hardware.thermal-V3-ndk",
         "libbase",
     ],
     shared_libs: [
diff --git a/thermal/aidl/default/thermal-example.xml b/thermal/aidl/default/thermal-example.xml
index 08dc68c..148ddbf 100644
--- a/thermal/aidl/default/thermal-example.xml
+++ b/thermal/aidl/default/thermal-example.xml
@@ -1,7 +1,7 @@
 <manifest version="1.0" type="device">
     <hal format="aidl">
         <name>android.hardware.thermal</name>
-        <version>2</version>
+        <version>3</version>
         <fqname>IThermal/default</fqname>
     </hal>
 </manifest>
diff --git a/thermal/aidl/vts/Android.bp b/thermal/aidl/vts/Android.bp
index 0812811..8235be2 100644
--- a/thermal/aidl/vts/Android.bp
+++ b/thermal/aidl/vts/Android.bp
@@ -32,7 +32,7 @@
         "libbinder_ndk",
     ],
     static_libs: [
-        "android.hardware.thermal-V2-ndk",
+        "android.hardware.thermal-V3-ndk",
     ],
     test_suites: [
         "vts",
diff --git a/thermal/aidl/vts/VtsHalThermalTargetTest.cpp b/thermal/aidl/vts/VtsHalThermalTargetTest.cpp
index 7f33e2d..066e773 100644
--- a/thermal/aidl/vts/VtsHalThermalTargetTest.cpp
+++ b/thermal/aidl/vts/VtsHalThermalTargetTest.cpp
@@ -93,6 +93,10 @@
         return ndk::ScopedAStatus::ok();
     }
 
+    ndk::ScopedAStatus notifyThresholdChanged(const TemperatureThreshold&) {
+        return ndk::ScopedAStatus::ok();
+    }
+
     template <typename R, typename P>
     [[nodiscard]] bool waitForCallback(std::chrono::duration<R, P> duration) {
         std::unique_lock<std::mutex> lock(mMutex);
diff --git a/threadnetwork/aidl/vts/Android.bp b/threadnetwork/aidl/vts/Android.bp
index 931081b..f489039 100644
--- a/threadnetwork/aidl/vts/Android.bp
+++ b/threadnetwork/aidl/vts/Android.bp
@@ -16,6 +16,7 @@
 
 cc_test {
     name: "VtsHalThreadNetworkTargetTest",
+    team: "trendy_team_fwk_thread_network",
     defaults: [
         "VtsHalTargetTestDefaults",
         "use_libaidlvintf_gtest_helper_static",
diff --git a/tv/input/1.0/vts/functional/Android.bp b/tv/input/1.0/vts/functional/Android.bp
index fad1c90..57d81e2 100644
--- a/tv/input/1.0/vts/functional/Android.bp
+++ b/tv/input/1.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_interactive_tv",
     // 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/tv/tuner/1.0/vts/functional/Android.bp b/tv/tuner/1.0/vts/functional/Android.bp
index 6187c73..9f3466a 100644
--- a/tv/tuner/1.0/vts/functional/Android.bp
+++ b/tv/tuner/1.0/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_interactive_tv",
     // 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/tv/tuner/1.1/vts/functional/Android.bp b/tv/tuner/1.1/vts/functional/Android.bp
index ac835a4..90b2494 100644
--- a/tv/tuner/1.1/vts/functional/Android.bp
+++ b/tv/tuner/1.1/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_interactive_tv",
     // 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/tv/tuner/aidl/Android.bp b/tv/tuner/aidl/Android.bp
index 7ffc8bb..e53e84d 100644
--- a/tv/tuner/aidl/Android.bp
+++ b/tv/tuner/aidl/Android.bp
@@ -40,5 +40,6 @@
             ],
         },
     ],
+    frozen: false,
 
 }
diff --git a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendStandardExt.aidl
similarity index 80%
copy from vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl
copy to tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendStandardExt.aidl
index a5eda52..88637db 100644
--- a/vibrator/aidl/aidl_api/android.hardware.vibrator/current/android/hardware/vibrator/PwleV2OutputMapEntry.aidl
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendStandardExt.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2024 The Android Open Source Project
+ * Copyright 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.
@@ -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.tv.tuner;
+/* @hide */
 @VintfStability
-parcelable PwleV2OutputMapEntry {
-  float frequencyHz;
-  float maxOutputAccelerationGs;
+union FrontendStandardExt {
+  android.hardware.tv.tuner.FrontendDvbsStandard dvbsStandardExt = android.hardware.tv.tuner.FrontendDvbsStandard.UNDEFINED;
+  android.hardware.tv.tuner.FrontendDvbtStandard dvbtStandardExt = android.hardware.tv.tuner.FrontendDvbtStandard.UNDEFINED;
 }
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendStatus.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendStatus.aidl
index b991ab6..e79eba6 100644
--- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendStatus.aidl
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendStatus.aidl
@@ -82,4 +82,5 @@
   long iptvPacketsLost;
   int iptvWorstJitterMs;
   int iptvAverageJitterMs;
+  android.hardware.tv.tuner.FrontendStandardExt standardExt;
 }
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendStatusType.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendStatusType.aidl
index 9f34e8d..bfd2145 100644
--- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendStatusType.aidl
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/FrontendStatusType.aidl
@@ -82,4 +82,5 @@
   IPTV_PACKETS_RECEIVED,
   IPTV_WORST_JITTER_MS,
   IPTV_AVERAGE_JITTER_MS,
+  STANDARD_EXT,
 }
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendStandardExt.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendStandardExt.aidl
new file mode 100644
index 0000000..0b68e89
--- /dev/null
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendStandardExt.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright 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.tv.tuner;
+
+import android.hardware.tv.tuner.FrontendDvbsStandard;
+import android.hardware.tv.tuner.FrontendDvbtStandard;
+
+/**
+ * @hide
+ */
+@VintfStability
+union FrontendStandardExt {
+    /**
+     * The DVB-S standard extension after standard transition.
+     */
+    FrontendDvbsStandard dvbsStandardExt = FrontendDvbsStandard.UNDEFINED;
+
+    /**
+     * The DVB-T standard extension after standard transition.
+     */
+    FrontendDvbtStandard dvbtStandardExt = FrontendDvbtStandard.UNDEFINED;
+}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendStatus.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendStatus.aidl
index 391f29b..a3902df 100644
--- a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendStatus.aidl
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendStatus.aidl
@@ -28,6 +28,7 @@
 import android.hardware.tv.tuner.FrontendRollOff;
 import android.hardware.tv.tuner.FrontendScanAtsc3PlpInfo;
 import android.hardware.tv.tuner.FrontendSpectralInversion;
+import android.hardware.tv.tuner.FrontendStandardExt;
 import android.hardware.tv.tuner.FrontendStatusAtsc3PlpInfo;
 import android.hardware.tv.tuner.FrontendTransmissionMode;
 import android.hardware.tv.tuner.LnbVoltage;
@@ -272,4 +273,13 @@
      * Average jitter (milliseconds).
      */
     int iptvAverageJitterMs;
+
+    /**
+     * Standard extension.
+     *
+     * DVB-T and DVB-S can transition to another standard within the same standard series. For
+     * example, DVB-T can transition to DVB-T2 and back. This attribute represents the standard
+     * extension. Valid values include FrontendDvbtStandard.T or FrontendDvbsStandard.S2 etc.
+     */
+    FrontendStandardExt standardExt;
 }
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendStatusType.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendStatusType.aidl
index 6804b2d..3225c42 100644
--- a/tv/tuner/aidl/android/hardware/tv/tuner/FrontendStatusType.aidl
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/FrontendStatusType.aidl
@@ -259,4 +259,9 @@
      * Average jitter (milliseconds).
      */
     IPTV_AVERAGE_JITTER_MS,
+
+    /**
+     * Standard extension.
+     */
+    STANDARD_EXT,
 }
diff --git a/tv/tuner/aidl/default/Frontend.cpp b/tv/tuner/aidl/default/Frontend.cpp
index 1031604..bba004a 100644
--- a/tv/tuner/aidl/default/Frontend.cpp
+++ b/tv/tuner/aidl/default/Frontend.cpp
@@ -81,6 +81,7 @@
                     FrontendStatusType::SIGNAL_STRENGTH, FrontendStatusType::SYMBOL_RATE,
                     FrontendStatusType::MODULATION,      FrontendStatusType::MODULATIONS,
                     FrontendStatusType::ROLL_OFF,        FrontendStatusType::IS_MISO,
+                    FrontendStatusType::STANDARD_EXT,
             };
             break;
         }
@@ -96,6 +97,7 @@
                     FrontendStatusType::TRANSMISSION_MODE,
                     FrontendStatusType::T2_SYSTEM_ID,
                     FrontendStatusType::DVBT_CELL_IDS,
+                    FrontendStatusType::STANDARD_EXT,
             };
             break;
         }
@@ -985,6 +987,17 @@
                 status.set<FrontendStatus::iptvAverageJitterMs>(5);
                 break;
             }
+            case FrontendStatusType::STANDARD_EXT: {
+                FrontendStandardExt standardExt;
+                if (mType == FrontendType::DVBS) {
+                    standardExt.set<FrontendStandardExt::dvbsStandardExt>(
+                            FrontendDvbsStandard::S2X);
+                } else if (mType == FrontendType::DVBT) {
+                    standardExt.set<FrontendStandardExt::dvbtStandardExt>(FrontendDvbtStandard::T2);
+                }
+                status.set<FrontendStatus::standardExt>(standardExt);
+                break;
+            }
             default: {
                 continue;
             }
diff --git a/tv/tuner/aidl/vts/functional/Android.bp b/tv/tuner/aidl/vts/functional/Android.bp
index 0057b6f..4c961ad 100644
--- a/tv/tuner/aidl/vts/functional/Android.bp
+++ b/tv/tuner/aidl/vts/functional/Android.bp
@@ -15,6 +15,7 @@
 //
 
 package {
+    default_team: "trendy_team_interactive_tv",
     // 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/tv/tuner/aidl/vts/functional/FrontendTests.cpp b/tv/tuner/aidl/vts/functional/FrontendTests.cpp
index 85d0496..99c0283 100644
--- a/tv/tuner/aidl/vts/functional/FrontendTests.cpp
+++ b/tv/tuner/aidl/vts/functional/FrontendTests.cpp
@@ -636,7 +636,7 @@
     ASSERT_TRUE(tuneFrontend(frontendConf, false /*testWithDemux*/));
 
     // TODO: find a better way to push all frontend status types
-    for (int32_t i = 0; i <= static_cast<int32_t>(FrontendStatusType::ATSC3_ALL_PLP_INFO); i++) {
+    for (int32_t i = 0; i <= static_cast<int32_t>(FrontendStatusType::STANDARD_EXT); i++) {
         allTypes.push_back(static_cast<FrontendStatusType>(i));
     }
 
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/Android.bp b/vibrator/aidl/default/Android.bp
index 0ac5bc0..de228cd 100644
--- a/vibrator/aidl/default/Android.bp
+++ b/vibrator/aidl/default/Android.bp
@@ -45,7 +45,7 @@
     name: "android.hardware.vibrator-service.example",
     relative_install_path: "hw",
     init_rc: ["vibrator-default.rc"],
-    vintf_fragments: [":android.hardware.vibrator.xml"],
+    vintf_fragments: ["android.hardware.vibrator.xml"],
     vendor: true,
     shared_libs: [
         "libbase",
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/vr/1.0/vts/functional/Android.bp b/vr/1.0/vts/functional/Android.bp
index 8e23f4f..267a1cc 100644
--- a/vr/1.0/vts/functional/Android.bp
+++ b/vr/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/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/wifi/aidl/Android.bp b/wifi/aidl/Android.bp
index b77e935..4b7e372 100644
--- a/wifi/aidl/Android.bp
+++ b/wifi/aidl/Android.bp
@@ -29,7 +29,7 @@
         "android/hardware/wifi/*.aidl",
     ],
     imports: [
-        "android.hardware.wifi.common-V1",
+        "android.hardware.wifi.common-V2",
     ],
     stability: "vintf",
     backend: {
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/Akm.aidl
similarity index 79%
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/Akm.aidl
index a5eda52..5baf2e8 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/Akm.aidl
@@ -31,9 +31,16 @@
 // 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 Akm {
+  const long NONE = 0;
+  const long PASN = (1 << 0) /* 1 */;
+  const long SAE = (1 << 1) /* 2 */;
+  const long FT_EAP_SHA256 = (1 << 2) /* 4 */;
+  const long FT_PSK_SHA256 = (1 << 3) /* 8 */;
+  const long FT_EAP_SHA384 = (1 << 4) /* 16 */;
+  const long FT_PSK_SHA384 = (1 << 5) /* 32 */;
+  const long FILS_EAP_SHA256 = (1 << 6) /* 64 */;
+  const long FILS_EAP_SHA384 = (1 << 7) /* 128 */;
 }
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/CipherSuite.aidl
similarity index 86%
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/CipherSuite.aidl
index a5eda52..32fb5ba 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/CipherSuite.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;
+package android.hardware.wifi;
 @VintfStability
-parcelable PwleV2OutputMapEntry {
-  float frequencyHz;
-  float maxOutputAccelerationGs;
+parcelable CipherSuite {
+  const long NONE = 0;
+  const long CCMP_128 = (1 << 0) /* 1 */;
+  const long CCMP_256 = (1 << 1) /* 2 */;
+  const long GCMP_128 = (1 << 2) /* 4 */;
+  const long GCMP_256 = (1 << 3) /* 8 */;
 }
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/PasnConfig.aidl
similarity index 91%
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/PasnConfig.aidl
index a5eda52..9b26c97 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/PasnConfig.aidl
@@ -31,9 +31,11 @@
 // 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 PasnConfig {
+  long baseAkm;
+  long cipherSuite;
+  @nullable byte[] passphrase;
+  @nullable byte[] pmkid;
 }
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttCapabilities.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttCapabilities.aidl
index 6c64084..6197585 100644
--- a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttCapabilities.aidl
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttCapabilities.aidl
@@ -47,4 +47,8 @@
   boolean ntbInitiatorSupported;
   boolean ntbResponderSupported;
   @nullable android.hardware.wifi.common.OuiKeyedData[] vendorData;
+  long akmsSupported;
+  long cipherSuitesSupported;
+  boolean secureHeLtfSupported;
+  boolean rangingFrameProtectionSupported;
 }
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttConfig.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttConfig.aidl
index 3613616..5507280 100644
--- a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttConfig.aidl
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttConfig.aidl
@@ -51,4 +51,5 @@
   long ntbMinMeasurementTime;
   long ntbMaxMeasurementTime;
   @nullable android.hardware.wifi.common.OuiKeyedData[] vendorData;
+  @nullable android.hardware.wifi.RttSecureConfig secureConfig;
 }
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttResult.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttResult.aidl
index 13202ba..87257be 100644
--- a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttResult.aidl
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttResult.aidl
@@ -66,4 +66,9 @@
   byte numTxSpatialStreams;
   byte numRxSpatialStreams;
   @nullable android.hardware.wifi.common.OuiKeyedData[] vendorData;
+  boolean isRangingFrameProtectionEnabled;
+  boolean isSecureLtfEnabled;
+  long baseAkm;
+  long cipherSuite;
+  int secureHeLtfProtocolVersion;
 }
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/RttSecureConfig.aidl
similarity index 89%
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/RttSecureConfig.aidl
index a5eda52..c2d7866 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/RttSecureConfig.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 RttSecureConfig {
+  android.hardware.wifi.PasnConfig pasnConfig;
+  boolean enableSecureHeLtf;
+  boolean enableRangingFrameProtection;
 }
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttStatus.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttStatus.aidl
index 2817497..08bca77 100644
--- a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttStatus.aidl
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttStatus.aidl
@@ -52,4 +52,9 @@
   FAIL_FTM_PARAM_OVERRIDE = 15,
   NAN_RANGING_PROTOCOL_FAILURE = 16,
   NAN_RANGING_CONCURRENCY_NOT_SUPPORTED = 17,
+  SECURE_RANGING_FAILURE_INVALID_AKM = 18,
+  SECURE_RANGING_FAILURE_INVALID_CIPHER = 19,
+  SECURE_RANGING_FAILURE_INVALID_CONFIG = 20,
+  SECURE_RANGING_FAILURE_REJECTED = 21,
+  SECURE_RANGING_FAILURE_UNKNOWN = 22,
 }
diff --git a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttType.aidl b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttType.aidl
index cb25673..8545d73 100644
--- a/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttType.aidl
+++ b/wifi/aidl/aidl_api/android.hardware.wifi/current/android/hardware/wifi/RttType.aidl
@@ -38,4 +38,5 @@
   TWO_SIDED = 2,
   TWO_SIDED_11MC = TWO_SIDED /* 2 */,
   TWO_SIDED_11AZ_NTB = 3,
+  TWO_SIDED_11AZ_NTB_SECURE = 4,
 }
diff --git a/wifi/aidl/android/hardware/wifi/Akm.aidl b/wifi/aidl/android/hardware/wifi/Akm.aidl
new file mode 100644
index 0000000..e3a913b
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/Akm.aidl
@@ -0,0 +1,33 @@
+/*
+ * 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;
+
+/**
+ * Authentication and Key Management types.
+ */
+@VintfStability
+parcelable Akm {
+    const long NONE = 0;
+    const long PASN = 1 << 0;
+    const long SAE = 1 << 1;
+    const long FT_EAP_SHA256 = 1 << 2;
+    const long FT_PSK_SHA256 = 1 << 3;
+    const long FT_EAP_SHA384 = 1 << 4;
+    const long FT_PSK_SHA384 = 1 << 5;
+    const long FILS_EAP_SHA256 = 1 << 6;
+    const long FILS_EAP_SHA384 = 1 << 7;
+}
diff --git a/wifi/aidl/android/hardware/wifi/CipherSuite.aidl b/wifi/aidl/android/hardware/wifi/CipherSuite.aidl
new file mode 100644
index 0000000..02b62e8
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/CipherSuite.aidl
@@ -0,0 +1,29 @@
+/*
+ * 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;
+
+/**
+ * Cipher Suite types.
+ */
+@VintfStability
+parcelable CipherSuite {
+    const long NONE = 0;
+    const long CCMP_128 = 1 << 0;
+    const long CCMP_256 = 1 << 1;
+    const long GCMP_128 = 1 << 2;
+    const long GCMP_256 = 1 << 3;
+}
diff --git a/wifi/aidl/android/hardware/wifi/PasnConfig.aidl b/wifi/aidl/android/hardware/wifi/PasnConfig.aidl
new file mode 100644
index 0000000..4c6b5bf
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/PasnConfig.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.wifi;
+
+/**
+ * Pre-Association Security Negotiation (PASN) configuration.
+ */
+@VintfStability
+parcelable PasnConfig {
+    /**
+     * Base Authentication and Key Management (AKM) protocol used for PASN as defined in |Akm|.
+     */
+    long baseAkm;
+    /**
+     * Pairwise cipher suite used for the PTKSA (Pairwise Transient Key Security Association)
+     * as defined in |CipherSuite|
+     */
+    long cipherSuite;
+    /**
+     * Passphrase for the base AKM. This can be null based on the AKM type.
+     */
+    @nullable byte[] passphrase;
+    /**
+     * PMKID corresponding to the cached PMK from the base AKM. PMKID can be null if no cached PMK
+     * is present.
+     */
+    @nullable byte[] pmkid;
+}
diff --git a/wifi/aidl/android/hardware/wifi/RttCapabilities.aidl b/wifi/aidl/android/hardware/wifi/RttCapabilities.aidl
index c193924..0cf048d 100644
--- a/wifi/aidl/android/hardware/wifi/RttCapabilities.aidl
+++ b/wifi/aidl/android/hardware/wifi/RttCapabilities.aidl
@@ -84,4 +84,20 @@
      * that no vendor data is provided.
      */
     @nullable OuiKeyedData[] vendorData;
+    /**
+     * Bitmap of |Akm| values indicating the set of supported AKMs.
+     */
+    long akmsSupported;
+    /**
+     * Bitmap of |CipherSuite| values indicating the set of supported pairwise cipher suites.
+     */
+    long cipherSuitesSupported;
+    /**
+     * Whether secure HE-LTF is supported.
+     */
+    boolean secureHeLtfSupported;
+    /**
+     * Whether frame protection for ranging is supported.
+     */
+    boolean rangingFrameProtectionSupported;
 }
diff --git a/wifi/aidl/android/hardware/wifi/RttConfig.aidl b/wifi/aidl/android/hardware/wifi/RttConfig.aidl
index 496ffd2..8dfbea8 100644
--- a/wifi/aidl/android/hardware/wifi/RttConfig.aidl
+++ b/wifi/aidl/android/hardware/wifi/RttConfig.aidl
@@ -19,6 +19,7 @@
 import android.hardware.wifi.RttBw;
 import android.hardware.wifi.RttPeerType;
 import android.hardware.wifi.RttPreamble;
+import android.hardware.wifi.RttSecureConfig;
 import android.hardware.wifi.RttType;
 import android.hardware.wifi.WifiChannelInfo;
 import android.hardware.wifi.common.OuiKeyedData;
@@ -140,4 +141,8 @@
      * that no vendor data is provided.
      */
     @nullable OuiKeyedData[] vendorData;
+    /**
+     * Secure Ranging configuration
+     */
+    @nullable RttSecureConfig secureConfig;
 }
diff --git a/wifi/aidl/android/hardware/wifi/RttResult.aidl b/wifi/aidl/android/hardware/wifi/RttResult.aidl
index 2f9aefe..dd41868 100644
--- a/wifi/aidl/android/hardware/wifi/RttResult.aidl
+++ b/wifi/aidl/android/hardware/wifi/RttResult.aidl
@@ -213,4 +213,25 @@
      * that no vendor data is provided.
      */
     @nullable OuiKeyedData[] vendorData;
+    /**
+     * Whether ranging frame protection is enabled.
+     */
+    boolean isRangingFrameProtectionEnabled;
+    /**
+     * Whether Secure HE-LTF is enabled.
+     */
+    boolean isSecureLtfEnabled;
+    /**
+     * Base Authentication and Key Management (AKM) protocol used for PASN as defined in |Akm|.
+     */
+    long baseAkm;
+    /**
+     * Pairwise cipher suite used for the PTKSA (Pairwise Transient Key Security Association)
+     * as defined in |CipherSuite|
+     */
+    long cipherSuite;
+    /**
+     * Secure HE-LTF protocol version used.
+     */
+    int secureHeLtfProtocolVersion;
 }
diff --git a/wifi/aidl/android/hardware/wifi/RttSecureConfig.aidl b/wifi/aidl/android/hardware/wifi/RttSecureConfig.aidl
new file mode 100644
index 0000000..c10e6b5
--- /dev/null
+++ b/wifi/aidl/android/hardware/wifi/RttSecureConfig.aidl
@@ -0,0 +1,38 @@
+/*
+ * 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.PasnConfig;
+
+/**
+ * RTT secure configuration.
+ */
+@VintfStability
+parcelable RttSecureConfig {
+    /**
+     * Pre-Association Security Negotiation (PASN) configuration.
+     */
+    PasnConfig pasnConfig;
+    /**
+     * Enable secure HE-LTF (High Efficiency Long Training Field).
+     */
+    boolean enableSecureHeLtf;
+    /**
+     * Enable Ranging frame protection.
+     */
+    boolean enableRangingFrameProtection;
+}
diff --git a/wifi/aidl/android/hardware/wifi/RttStatus.aidl b/wifi/aidl/android/hardware/wifi/RttStatus.aidl
index 600165c..94bc9e3 100644
--- a/wifi/aidl/android/hardware/wifi/RttStatus.aidl
+++ b/wifi/aidl/android/hardware/wifi/RttStatus.aidl
@@ -88,4 +88,24 @@
      * NAN concurrency not supported (NDP + RTT).
      */
     NAN_RANGING_CONCURRENCY_NOT_SUPPORTED = 17,
+    /**
+     * Secure Ranging failed due to invalid AKM (Authentication and Key Management)
+     */
+    SECURE_RANGING_FAILURE_INVALID_AKM = 18,
+    /**
+     * Secure Ranging failed due to invalid Cipher.
+     */
+    SECURE_RANGING_FAILURE_INVALID_CIPHER = 19,
+    /**
+     * Secure Ranging failed due to invalid configuration.
+     */
+    SECURE_RANGING_FAILURE_INVALID_CONFIG = 20,
+    /**
+     * Secure ranging rejected by the AP.
+     */
+    SECURE_RANGING_FAILURE_REJECTED = 21,
+    /**
+     * Secure ranging failure unknown.
+     */
+    SECURE_RANGING_FAILURE_UNKNOWN = 22,
 }
diff --git a/wifi/aidl/android/hardware/wifi/RttType.aidl b/wifi/aidl/android/hardware/wifi/RttType.aidl
index 3f1a2f1..d7cf9fe 100644
--- a/wifi/aidl/android/hardware/wifi/RttType.aidl
+++ b/wifi/aidl/android/hardware/wifi/RttType.aidl
@@ -37,4 +37,8 @@
      * Two-sided RTT 11az non trigger based (non-TB) type.
      */
     TWO_SIDED_11AZ_NTB = 3,
+    /**
+     * Two-sided RTT 11az non trigger based (non-TB) secure type.
+     */
+    TWO_SIDED_11AZ_NTB_SECURE = 4,
 }
diff --git a/wifi/aidl/default/Android.bp b/wifi/aidl/default/Android.bp
index 0711bde..c2e8541 100644
--- a/wifi/aidl/default/Android.bp
+++ b/wifi/aidl/default/Android.bp
@@ -200,7 +200,7 @@
         "libgmock",
         "libgtest",
         "android.hardware.wifi-V3-ndk",
-        "android.hardware.wifi.common-V1-ndk",
+        "android.hardware.wifi.common-V2-ndk",
         "android.hardware.wifi-service-lib",
     ],
     shared_libs: [
diff --git a/wifi/aidl/default/aidl_struct_util.cpp b/wifi/aidl/default/aidl_struct_util.cpp
index 0455be7..bf6c206 100644
--- a/wifi/aidl/default/aidl_struct_util.cpp
+++ b/wifi/aidl/default/aidl_struct_util.cpp
@@ -2478,6 +2478,8 @@
             return legacy_hal::RTT_TYPE_2_SIDED_11MC;
         case RttType::TWO_SIDED_11AZ_NTB:
             return legacy_hal::RTT_TYPE_2_SIDED_11AZ_NTB;
+        case RttType::TWO_SIDED_11AZ_NTB_SECURE:
+            return legacy_hal::RTT_TYPE_2_SIDED_11AZ_NTB_SECURE;
     };
     CHECK(false);
 }
@@ -2491,6 +2493,8 @@
             return RttType::TWO_SIDED_11MC;
         case legacy_hal::RTT_TYPE_2_SIDED_11AZ_NTB:
             return RttType::TWO_SIDED_11AZ_NTB;
+        case legacy_hal::RTT_TYPE_2_SIDED_11AZ_NTB_SECURE:
+            return RttType::TWO_SIDED_11AZ_NTB_SECURE;
     };
     CHECK(false) << "Unknown legacy type: " << type;
 }
@@ -2723,6 +2727,16 @@
             return RttStatus::NAN_RANGING_PROTOCOL_FAILURE;
         case legacy_hal::RTT_STATUS_NAN_RANGING_CONCURRENCY_NOT_SUPPORTED:
             return RttStatus::NAN_RANGING_CONCURRENCY_NOT_SUPPORTED;
+        case legacy_hal::RTT_STATUS_SECURE_RANGING_FAILURE_INVALID_AKM:
+            return RttStatus::SECURE_RANGING_FAILURE_INVALID_AKM;
+        case legacy_hal::RTT_STATUS_SECURE_RANGING_FAILURE_INVALID_CIPHER:
+            return RttStatus::SECURE_RANGING_FAILURE_INVALID_CIPHER;
+        case legacy_hal::RTT_STATUS_SECURE_RANGING_FAILURE_INVALID_CONFIG:
+            return RttStatus::SECURE_RANGING_FAILURE_INVALID_CONFIG;
+        case legacy_hal::RTT_STATUS_SECURE_RANGING_FAILURE_REJECTED:
+            return RttStatus::SECURE_RANGING_FAILURE_REJECTED;
+        case legacy_hal::RTT_STATUS_SECURE_RANGING_FAILURE_UNKNOWN:
+            return RttStatus::SECURE_RANGING_FAILURE_UNKNOWN;
     };
     CHECK(false) << "Unknown legacy status: " << status;
 }
diff --git a/wifi/aidl/default/wifi_legacy_hal.h b/wifi/aidl/default/wifi_legacy_hal.h
index 3fd567b..aa563cb 100644
--- a/wifi/aidl/default/wifi_legacy_hal.h
+++ b/wifi/aidl/default/wifi_legacy_hal.h
@@ -212,10 +212,16 @@
 using ::RTT_STATUS_NAN_RANGING_CONCURRENCY_NOT_SUPPORTED;
 using ::RTT_STATUS_NAN_RANGING_PROTOCOL_FAILURE;
 using ::RTT_STATUS_NO_WIFI;
+using ::RTT_STATUS_SECURE_RANGING_FAILURE_INVALID_AKM;
+using ::RTT_STATUS_SECURE_RANGING_FAILURE_INVALID_CIPHER;
+using ::RTT_STATUS_SECURE_RANGING_FAILURE_INVALID_CONFIG;
+using ::RTT_STATUS_SECURE_RANGING_FAILURE_REJECTED;
+using ::RTT_STATUS_SECURE_RANGING_FAILURE_UNKNOWN;
 using ::RTT_STATUS_SUCCESS;
 using ::RTT_TYPE_1_SIDED;
 using ::RTT_TYPE_2_SIDED;
 using ::RTT_TYPE_2_SIDED_11AZ_NTB;
+using ::RTT_TYPE_2_SIDED_11AZ_NTB_SECURE;
 using ::RTT_TYPE_2_SIDED_11MC;
 using ::RX_PKT_FATE_DRV_DROP_FILTER;
 using ::RX_PKT_FATE_DRV_DROP_INVALID;
diff --git a/wifi/aidl/vts/functional/Android.bp b/wifi/aidl/vts/functional/Android.bp
index 66eb970..429c0c5 100644
--- a/wifi/aidl/vts/functional/Android.bp
+++ b/wifi/aidl/vts/functional/Android.bp
@@ -40,7 +40,7 @@
     ],
     static_libs: [
         "VtsHalWifiTargetTestUtil",
-        "android.hardware.wifi.common-V1-ndk",
+        "android.hardware.wifi.common-V2-ndk",
         "android.hardware.wifi-V3-ndk",
         "libwifi-system-iface",
     ],
@@ -66,7 +66,7 @@
     ],
     static_libs: [
         "VtsHalWifiTargetTestUtil",
-        "android.hardware.wifi.common-V1-ndk",
+        "android.hardware.wifi.common-V2-ndk",
         "android.hardware.wifi-V3-ndk",
         "libwifi-system-iface",
     ],
@@ -92,7 +92,7 @@
     ],
     static_libs: [
         "VtsHalWifiTargetTestUtil",
-        "android.hardware.wifi.common-V1-ndk",
+        "android.hardware.wifi.common-V2-ndk",
         "android.hardware.wifi-V3-ndk",
         "libwifi-system-iface",
     ],
@@ -118,7 +118,7 @@
     ],
     static_libs: [
         "VtsHalWifiTargetTestUtil",
-        "android.hardware.wifi.common-V1-ndk",
+        "android.hardware.wifi.common-V2-ndk",
         "android.hardware.wifi-V3-ndk",
         "libwifi-system-iface",
     ],
@@ -144,7 +144,7 @@
     ],
     static_libs: [
         "VtsHalWifiTargetTestUtil",
-        "android.hardware.wifi.common-V1-ndk",
+        "android.hardware.wifi.common-V2-ndk",
         "android.hardware.wifi-V3-ndk",
         "libwifi-system-iface",
     ],
@@ -169,7 +169,7 @@
         "libnativehelper",
     ],
     static_libs: [
-        "android.hardware.wifi.common-V1-ndk",
+        "android.hardware.wifi.common-V2-ndk",
         "android.hardware.wifi-V3-ndk",
         "libwifi-system-iface",
     ],
diff --git a/wifi/common/aidl/Android.bp b/wifi/common/aidl/Android.bp
index 0920a55..8ea54be 100644
--- a/wifi/common/aidl/Android.bp
+++ b/wifi/common/aidl/Android.bp
@@ -54,6 +54,6 @@
             imports: [],
         },
     ],
-    frozen: true,
+    frozen: false,
 
 }
diff --git a/wifi/common/aidl/aidl_api/android.hardware.wifi.common/current/android/hardware/wifi/common/DeauthenticationReasonCode.aidl b/wifi/common/aidl/aidl_api/android.hardware.wifi.common/current/android/hardware/wifi/common/DeauthenticationReasonCode.aidl
new file mode 100644
index 0000000..2404b2c
--- /dev/null
+++ b/wifi/common/aidl/aidl_api/android.hardware.wifi.common/current/android/hardware/wifi/common/DeauthenticationReasonCode.aidl
@@ -0,0 +1,99 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// 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.wifi.common;
+@Backing(type="int") @VintfStability
+enum DeauthenticationReasonCode {
+  HOSTAPD_NO_REASON = 0,
+  UNSPECIFIED = 1,
+  PREV_AUTH_NOT_VALID = 2,
+  DEAUTH_LEAVING = 3,
+  DISASSOC_DUE_TO_INACTIVITY = 4,
+  DISASSOC_AP_BUSY = 5,
+  CLASS2_FRAME_FROM_NONAUTH_STA = 6,
+  CLASS3_FRAME_FROM_NONASSOC_STA = 7,
+  DISASSOC_STA_HAS_LEFT = 8,
+  STA_REQ_ASSOC_WITHOUT_AUTH = 9,
+  PWR_CAPABILITY_NOT_VALID = 10,
+  SUPPORTED_CHANNEL_NOT_VALID = 11,
+  BSS_TRANSITION_DISASSOC = 12,
+  INVALID_IE = 13,
+  MICHAEL_MIC_FAILURE = 14,
+  FOURWAY_HANDSHAKE_TIMEOUT = 15,
+  GROUP_KEY_UPDATE_TIMEOUT = 16,
+  IE_IN_4WAY_DIFFERS = 17,
+  GROUP_CIPHER_NOT_VALID = 18,
+  PAIRWISE_CIPHER_NOT_VALID = 19,
+  AKMP_NOT_VALID = 20,
+  UNSUPPORTED_RSN_IE_VERSION = 21,
+  INVALID_RSN_IE_CAPAB = 22,
+  IEEE_802_1X_AUTH_FAILED = 23,
+  CIPHER_SUITE_REJECTED = 24,
+  TDLS_TEARDOWN_UNREACHABLE = 25,
+  TDLS_TEARDOWN_UNSPECIFIED = 26,
+  SSP_REQUESTED_DISASSOC = 27,
+  NO_SSP_ROAMING_AGREEMENT = 28,
+  BAD_CIPHER_OR_AKM = 29,
+  NOT_AUTHORIZED_THIS_LOCATION = 30,
+  SERVICE_CHANGE_PRECLUDES_TS = 31,
+  UNSPECIFIED_QOS_REASON = 32,
+  NOT_ENOUGH_BANDWIDTH = 33,
+  DISASSOC_LOW_ACK = 34,
+  EXCEEDED_TXOP = 35,
+  STA_LEAVING = 36,
+  END_TS_BA_DLS = 37,
+  UNKNOWN_TS_BA = 38,
+  TIMEOUT = 39,
+  PEERKEY_MISMATCH = 45,
+  AUTHORIZED_ACCESS_LIMIT_REACHED = 46,
+  EXTERNAL_SERVICE_REQUIREMENTS = 47,
+  INVALID_FT_ACTION_FRAME_COUNT = 48,
+  INVALID_PMKID = 49,
+  INVALID_MDE = 50,
+  INVALID_FTE = 51,
+  MESH_PEERING_CANCELLED = 52,
+  MESH_MAX_PEERS = 53,
+  MESH_CONFIG_POLICY_VIOLATION = 54,
+  MESH_CLOSE_RCVD = 55,
+  MESH_MAX_RETRIES = 56,
+  MESH_CONFIRM_TIMEOUT = 57,
+  MESH_INVALID_GTK = 58,
+  MESH_INCONSISTENT_PARAMS = 59,
+  MESH_INVALID_SECURITY_CAP = 60,
+  MESH_PATH_ERROR_NO_PROXY_INFO = 61,
+  MESH_PATH_ERROR_NO_FORWARDING_INFO = 62,
+  MESH_PATH_ERROR_DEST_UNREACHABLE = 63,
+  MAC_ADDRESS_ALREADY_EXISTS_IN_MBSS = 64,
+  MESH_CHANNEL_SWITCH_REGULATORY_REQ = 65,
+  MESH_CHANNEL_SWITCH_UNSPECIFIED = 66,
+}
diff --git a/wifi/common/aidl/android/hardware/wifi/common/DeauthenticationReasonCode.aidl b/wifi/common/aidl/android/hardware/wifi/common/DeauthenticationReasonCode.aidl
new file mode 100644
index 0000000..95eb31d
--- /dev/null
+++ b/wifi/common/aidl/android/hardware/wifi/common/DeauthenticationReasonCode.aidl
@@ -0,0 +1,90 @@
+/*
+ * 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.common;
+
+/**
+ * Reason codes (IEEE Std 802.11-2016, 9.4.1.7, Table 9-45).
+ *
+ * Note: HOSTAPD_NO_REASON is the default return from hostapd, even though it
+ * does not appear in the IEEE spec.
+ */
+@VintfStability
+@Backing(type="int")
+enum DeauthenticationReasonCode {
+    HOSTAPD_NO_REASON = 0,
+    UNSPECIFIED = 1,
+    PREV_AUTH_NOT_VALID = 2,
+    DEAUTH_LEAVING = 3,
+    DISASSOC_DUE_TO_INACTIVITY = 4,
+    DISASSOC_AP_BUSY = 5,
+    CLASS2_FRAME_FROM_NONAUTH_STA = 6,
+    CLASS3_FRAME_FROM_NONASSOC_STA = 7,
+    DISASSOC_STA_HAS_LEFT = 8,
+    STA_REQ_ASSOC_WITHOUT_AUTH = 9,
+    PWR_CAPABILITY_NOT_VALID = 10,
+    SUPPORTED_CHANNEL_NOT_VALID = 11,
+    BSS_TRANSITION_DISASSOC = 12,
+    INVALID_IE = 13,
+    MICHAEL_MIC_FAILURE = 14,
+    FOURWAY_HANDSHAKE_TIMEOUT = 15,
+    GROUP_KEY_UPDATE_TIMEOUT = 16,
+    IE_IN_4WAY_DIFFERS = 17,
+    GROUP_CIPHER_NOT_VALID = 18,
+    PAIRWISE_CIPHER_NOT_VALID = 19,
+    AKMP_NOT_VALID = 20,
+    UNSUPPORTED_RSN_IE_VERSION = 21,
+    INVALID_RSN_IE_CAPAB = 22,
+    IEEE_802_1X_AUTH_FAILED = 23,
+    CIPHER_SUITE_REJECTED = 24,
+    TDLS_TEARDOWN_UNREACHABLE = 25,
+    TDLS_TEARDOWN_UNSPECIFIED = 26,
+    SSP_REQUESTED_DISASSOC = 27,
+    NO_SSP_ROAMING_AGREEMENT = 28,
+    BAD_CIPHER_OR_AKM = 29,
+    NOT_AUTHORIZED_THIS_LOCATION = 30,
+    SERVICE_CHANGE_PRECLUDES_TS = 31,
+    UNSPECIFIED_QOS_REASON = 32,
+    NOT_ENOUGH_BANDWIDTH = 33,
+    DISASSOC_LOW_ACK = 34,
+    EXCEEDED_TXOP = 35,
+    STA_LEAVING = 36,
+    END_TS_BA_DLS = 37,
+    UNKNOWN_TS_BA = 38,
+    TIMEOUT = 39,
+    PEERKEY_MISMATCH = 45,
+    AUTHORIZED_ACCESS_LIMIT_REACHED = 46,
+    EXTERNAL_SERVICE_REQUIREMENTS = 47,
+    INVALID_FT_ACTION_FRAME_COUNT = 48,
+    INVALID_PMKID = 49,
+    INVALID_MDE = 50,
+    INVALID_FTE = 51,
+    MESH_PEERING_CANCELLED = 52,
+    MESH_MAX_PEERS = 53,
+    MESH_CONFIG_POLICY_VIOLATION = 54,
+    MESH_CLOSE_RCVD = 55,
+    MESH_MAX_RETRIES = 56,
+    MESH_CONFIRM_TIMEOUT = 57,
+    MESH_INVALID_GTK = 58,
+    MESH_INCONSISTENT_PARAMS = 59,
+    MESH_INVALID_SECURITY_CAP = 60,
+    MESH_PATH_ERROR_NO_PROXY_INFO = 61,
+    MESH_PATH_ERROR_NO_FORWARDING_INFO = 62,
+    MESH_PATH_ERROR_DEST_UNREACHABLE = 63,
+    MAC_ADDRESS_ALREADY_EXISTS_IN_MBSS = 64,
+    MESH_CHANNEL_SWITCH_REGULATORY_REQ = 65,
+    MESH_CHANNEL_SWITCH_UNSPECIFIED = 66,
+}
diff --git a/wifi/hostapd/aidl/Android.bp b/wifi/hostapd/aidl/Android.bp
index 88f4ef2..e580573 100644
--- a/wifi/hostapd/aidl/Android.bp
+++ b/wifi/hostapd/aidl/Android.bp
@@ -29,7 +29,7 @@
         "android/hardware/wifi/hostapd/*.aidl",
     ],
     imports: [
-        "android.hardware.wifi.common-V1",
+        "android.hardware.wifi.common-V2",
     ],
     stability: "vintf",
     backend: {
diff --git a/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/ClientInfo.aidl b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/ClientInfo.aidl
index c4d62b6..c4db789 100644
--- a/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/ClientInfo.aidl
+++ b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/ClientInfo.aidl
@@ -38,4 +38,5 @@
   String apIfaceInstance;
   byte[] clientAddress;
   boolean isConnected;
+  android.hardware.wifi.common.DeauthenticationReasonCode disconnectReasonCode;
 }
diff --git a/wifi/hostapd/aidl/android/hardware/wifi/hostapd/ClientInfo.aidl b/wifi/hostapd/aidl/android/hardware/wifi/hostapd/ClientInfo.aidl
index 7bed658..a7ca1ec 100644
--- a/wifi/hostapd/aidl/android/hardware/wifi/hostapd/ClientInfo.aidl
+++ b/wifi/hostapd/aidl/android/hardware/wifi/hostapd/ClientInfo.aidl
@@ -16,6 +16,8 @@
 
 package android.hardware.wifi.hostapd;
 
+import android.hardware.wifi.common.DeauthenticationReasonCode;
+
 /**
  * Parameters to control the channel selection for the interface.
  */
@@ -42,4 +44,9 @@
      * True when client connected, false when client disconnected.
      */
     boolean isConnected;
+
+    /**
+     * Reason for client disconnect from soft ap.
+     */
+    DeauthenticationReasonCode disconnectReasonCode;
 }
diff --git a/wifi/hostapd/aidl/vts/functional/Android.bp b/wifi/hostapd/aidl/vts/functional/Android.bp
index b1c9c5d..de31e14 100644
--- a/wifi/hostapd/aidl/vts/functional/Android.bp
+++ b/wifi/hostapd/aidl/vts/functional/Android.bp
@@ -37,7 +37,7 @@
         "android.hardware.wifi@1.4",
         "android.hardware.wifi@1.5",
         "android.hardware.wifi@1.6",
-        "android.hardware.wifi.common-V1-ndk",
+        "android.hardware.wifi.common-V2-ndk",
         "android.hardware.wifi-V3-ndk",
         "libwifi-system",
         "libwifi-system-iface",
diff --git a/wifi/legacy_headers/include/hardware_legacy/rtt.h b/wifi/legacy_headers/include/hardware_legacy/rtt.h
index 426abe0..631821d 100644
--- a/wifi/legacy_headers/include/hardware_legacy/rtt.h
+++ b/wifi/legacy_headers/include/hardware_legacy/rtt.h
@@ -7,24 +7,33 @@
 
 /* Ranging status */
 typedef enum {
-    RTT_STATUS_SUCCESS       = 0,
-    RTT_STATUS_FAILURE       = 1,           // general failure status
-    RTT_STATUS_FAIL_NO_RSP   = 2,           // target STA does not respond to request
-    RTT_STATUS_FAIL_REJECTED = 3,           // request rejected. Applies to 2-sided RTT only
-    RTT_STATUS_FAIL_NOT_SCHEDULED_YET  = 4,
-    RTT_STATUS_FAIL_TM_TIMEOUT         = 5, // timing measurement times out
-    RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL = 6, // Target on different channel, cannot range
-    RTT_STATUS_FAIL_NO_CAPABILITY  = 7,     // ranging not supported
-    RTT_STATUS_ABORTED             = 8,     // request aborted for unknown reason
-    RTT_STATUS_FAIL_INVALID_TS     = 9,     // Invalid T1-T4 timestamp
-    RTT_STATUS_FAIL_PROTOCOL       = 10,    // 11mc protocol failed
-    RTT_STATUS_FAIL_SCHEDULE       = 11,    // request could not be scheduled
-    RTT_STATUS_FAIL_BUSY_TRY_LATER = 12,    // responder cannot collaborate at time of request
-    RTT_STATUS_INVALID_REQ         = 13,    // bad request args
-    RTT_STATUS_NO_WIFI             = 14,    // WiFi not enabled
-    RTT_STATUS_FAIL_FTM_PARAM_OVERRIDE = 15, // Responder overrides param info, cannot range with new params
-    RTT_STATUS_NAN_RANGING_PROTOCOL_FAILURE =16, //Negotiation failure
-    RTT_STATUS_NAN_RANGING_CONCURRENCY_NOT_SUPPORTED=17, //concurrency not supported (NDP+RTT)
+    RTT_STATUS_SUCCESS = 0,
+    RTT_STATUS_FAILURE = 1,        // general failure status
+    RTT_STATUS_FAIL_NO_RSP = 2,    // target STA does not respond to request
+    RTT_STATUS_FAIL_REJECTED = 3,  // request rejected. Applies to 2-sided RTT only
+    RTT_STATUS_FAIL_NOT_SCHEDULED_YET = 4,
+    RTT_STATUS_FAIL_TM_TIMEOUT = 5,          // timing measurement times out
+    RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL = 6,  // Target on different channel, cannot range
+    RTT_STATUS_FAIL_NO_CAPABILITY = 7,       // ranging not supported
+    RTT_STATUS_ABORTED = 8,                  // request aborted for unknown reason
+    RTT_STATUS_FAIL_INVALID_TS = 9,          // Invalid T1-T4 timestamp
+    RTT_STATUS_FAIL_PROTOCOL = 10,           // 11mc protocol failed
+    RTT_STATUS_FAIL_SCHEDULE = 11,           // request could not be scheduled
+    RTT_STATUS_FAIL_BUSY_TRY_LATER = 12,     // responder cannot collaborate at time of request
+    RTT_STATUS_INVALID_REQ = 13,             // bad request args
+    RTT_STATUS_NO_WIFI = 14,                 // WiFi not enabled
+    RTT_STATUS_FAIL_FTM_PARAM_OVERRIDE =
+            15,  // Responder overrides param info, cannot range with new params
+    RTT_STATUS_NAN_RANGING_PROTOCOL_FAILURE = 16,           // Negotiation failure
+    RTT_STATUS_NAN_RANGING_CONCURRENCY_NOT_SUPPORTED = 17,  // concurrency not supported (NDP+RTT)
+    RTT_STATUS_SECURE_RANGING_FAILURE_INVALID_AKM = 18,  // Secure Ranging failed due to invalid AKM
+                                                         // (Authentication and Key Management)
+    RTT_STATUS_SECURE_RANGING_FAILURE_INVALID_CIPHER = 19,  // Secure Ranging failed due to invalid
+                                                            // Cipher
+    RTT_STATUS_SECURE_RANGING_FAILURE_INVALID_CONFIG = 20,  // Secure Ranging failed due to invalid
+                                                            // configuration
+    RTT_STATUS_SECURE_RANGING_FAILURE_REJECTED = 21,        // Secure ranging rejected by the AP.2
+    RTT_STATUS_SECURE_RANGING_FAILURE_UNKNOWN = 22,         // Secure ranging failure unknown
 } wifi_rtt_status;
 
 /* RTT peer type */
@@ -60,14 +69,57 @@
 
 /* RTT Type */
 typedef enum {
-    RTT_TYPE_1_SIDED          = 0x1,
+    RTT_TYPE_1_SIDED = 0x1,
     /* Deprecated. Use RTT_TYPE_2_SIDED_11MC instead. */
-    RTT_TYPE_2_SIDED          = 0x2,
-    RTT_TYPE_2_SIDED_11MC     = RTT_TYPE_2_SIDED,
+    RTT_TYPE_2_SIDED = 0x2,
+    RTT_TYPE_2_SIDED_11MC = RTT_TYPE_2_SIDED,
     RTT_TYPE_2_SIDED_11AZ_NTB = 0x3,
-
+    RTT_TYPE_2_SIDED_11AZ_NTB_SECURE = 0x4,
 } wifi_rtt_type;
 
+/* RTT AKM type */
+typedef enum {
+    WPA_KEY_MGMT_NONE = 0x0,
+    WPA_KEY_MGMT_PASN = 0x1,
+    WPA_KEY_MGMT_SAE = 0x2,
+    WPA_KEY_MGMT_EAP_FT_SHA256 = 0x4,
+    WPA_KEY_MGMT_FT_PSK_SHA256 = 0x8,
+    WPA_KEY_MGMT_EAP_FT_SHA384 = 0x10,
+    WPA_KEY_MGMT_FT_PSK_SHA384 = 0x20,
+    WPA_KEY_MGMT_EAP_FILS_SHA256 = 0x40,
+    WPA_KEY_MGMT_EAP_FILS_SHA384 = 0x80
+} wifi_rtt_akm;
+
+typedef enum {
+    WPA_CIPHER_NONE = 0x0,
+    WPA_CIPHER_CCMP_128 = 0x1,
+    WPA_CIPHER_CCMP_256 = 0x2,
+    WPA_CIPHER_GCMP_128 = 0x4,
+    WPA_CIPHER_GCMP_256 = 0x8,
+} wifi_rtt_cipher_suite;
+
+#define RTT_SECURITY_MAX_PASSPHRASE_LEN 63
+#define PMKID_LEN 16
+
+typedef struct {
+    wifi_rtt_akm base_akm;  // Base Authentication and Key Management (AKM) protocol used for PASN
+    wifi_rtt_cipher_suite pairwise_cipher_suite;  // Pairwise cipher suite used for the PTKSA
+                                                  // (Pairwise Transient Key Security Association)
+    u32 passphrase_len;
+    u8 passphrase[RTT_SECURITY_MAX_PASSPHRASE_LEN];  // Passphrase for the base AKM. This can be
+                                                     // empty based on the AKM type.
+    u32 pmkid_len;
+    u8 pmkid[PMKID_LEN];  // PMKID corresponding to the cached PMK from the base AKM. PMKID can be
+                          // null if no cached PMK is present.
+
+} wifi_rtt_pasn_config;
+
+typedef struct {
+    wifi_rtt_pasn_config pasn_config;
+    bool enable_secure_he_ltf;
+    bool enable_ranging_frame_protection;
+} wifi_rtt_secure_config;
+
 /* RTT configuration */
 typedef struct {
     mac_addr addr;                 // peer device mac address
@@ -127,6 +179,11 @@
                                   // units of 10 milliseconds
 } wifi_rtt_config_v3;
 
+typedef struct {
+    wifi_rtt_config_v3 rtt_config;
+    wifi_rtt_secure_config rtt_secure_config;
+} wifi_rtt_config_v4;
+
 /* RTT results */
 typedef struct {
     mac_addr addr;                // device mac address
@@ -197,6 +254,14 @@
   byte num_rx_sts;                 // Number of receive space-time streams used.
 } wifi_rtt_result_v3;
 
+typedef struct {
+    wifi_rtt_result_v3 rtt_result_v3;
+    bool is_ranging_protection_enabled;
+    bool is_secure_ltf_enabled;
+    wifi_rtt_akm base_akm;
+    wifi_rtt_cipher_suite cipher_suite;
+    int secure_he_ltf_protocol_version;
+} wifi_rtt_result_v4;
 
 /* RTT result callbacks */
 typedef struct {
@@ -234,6 +299,15 @@
                                wifi_rtt_result_v3 *rtt_result_v3[]);
 } wifi_rtt_event_handler_v3;
 
+/* RTT result v4 callback (secure ranging support) */
+typedef struct {
+    /*
+     * Called when vendor implementation supports sending RTT results version 4 (Added support for
+     * secure 11az ranging)
+     */
+    void (*on_rtt_results_v4)(wifi_request_id id, unsigned num_results,
+                              wifi_rtt_result_v4* rtt_result_v4[]);
+} wifi_rtt_event_handler_v4;
 
 /* v3 API to request RTT measurement(11az support).  */
 wifi_error wifi_rtt_range_request_v3(wifi_request_id id,
@@ -242,6 +316,11 @@
                                      wifi_rtt_config_v3 rtt_config_v3[],
                                      wifi_rtt_event_handler_v3 handler);
 
+/* v4 API to request RTT measurement(11az security support). */
+wifi_error wifi_rtt_range_request_v4(wifi_request_id id, wifi_interface_handle iface,
+                                     unsigned num_rtt_config, wifi_rtt_config_v4 rtt_config_v4[],
+                                     wifi_rtt_event_handler_v4 handler);
+
 /* API to cancel RTT measurements */
 wifi_error wifi_rtt_range_cancel(wifi_request_id id,  wifi_interface_handle iface,
         unsigned num_devices, mac_addr addr[]);
@@ -313,10 +392,26 @@
     byte ntb_responder_supported;   // if 11az non-TB responder is supported
 } wifi_rtt_capabilities_v3;
 
+/* RTT Capabilities v4 (11az secure support) */
+typedef struct {
+    wifi_rtt_capabilities_v3 rtt_capab_v3;
+    bool secure_ltf_supported;
+    bool ranging_fame_protection_supported;
+    wifi_rtt_akm supported_akms;  // Bitmap of wifi_rtt_akm values indicating the set of supported
+                                  // AKMs.
+    wifi_rtt_cipher_suite
+            supported_cipher_suites;  // Bitmap of wifi_rtt_cipher_suite values
+                                      // indicating the set of supported pairwise cipher suites.
+} wifi_rtt_capabilities_v4;
+
 /*  RTT capabilities v3 of the device (11az support) */
 wifi_error wifi_get_rtt_capabilities_v3(wifi_interface_handle iface,
                                         wifi_rtt_capabilities_v3 *capabilities);
 
+/*  RTT capabilities v4 of the device (11az secure support) */
+wifi_error wifi_get_rtt_capabilities_v4(wifi_interface_handle iface,
+                                        wifi_rtt_capabilities_v4* capabilities);
+
 /* debugging definitions */
 enum {
     RTT_DEBUG_DISABLE,
diff --git a/wifi/supplicant/aidl/Android.bp b/wifi/supplicant/aidl/Android.bp
index 8d16cb7..1fbe8e9 100644
--- a/wifi/supplicant/aidl/Android.bp
+++ b/wifi/supplicant/aidl/Android.bp
@@ -29,7 +29,7 @@
         "android/hardware/wifi/supplicant/*.aidl",
     ],
     imports: [
-        "android.hardware.wifi.common-V1",
+        "android.hardware.wifi.common-V2",
     ],
     stability: "vintf",
     backend: {
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl
index 9fa8f56..b617c57 100644
--- a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl
@@ -86,5 +86,6 @@
   enum MloLinkInfoChangeReason {
     TID_TO_LINK_MAP = 0,
     MULTI_LINK_RECONFIG_AP_REMOVAL = 1,
+    MULTI_LINK_RECONFIG_AP_ADDITION = 2,
   }
 }
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/PmkSaCacheData.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/PmkSaCacheData.aidl
index c31b167..b1269ba 100644
--- a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/PmkSaCacheData.aidl
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/PmkSaCacheData.aidl
@@ -37,4 +37,5 @@
   byte[6] bssid;
   long expirationTimeInSec;
   byte[] serializedEntry;
+  @nullable byte[] pmkid;
 }
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl
index 172fcda..8740ad0 100644
--- a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl
@@ -338,11 +338,19 @@
         /**
          * Multi-link reconfiguration - AP removal as described in
          * IEEE 802.11be spec, section 35.3.6. This is a mandatory feature for
-         * station.
+         * station according to Wi-Fi 7 R1 MRD.
          *
          * Removed link will not be present in |ISupplicantStaIface.getConnectionMloLinksInfo|.
          */
         MULTI_LINK_RECONFIG_AP_REMOVAL = 1,
+        /**
+         * Multi-link reconfiguration - Adding affiliated AP(s) as described in
+         * IEEE 802.11be spec, section 35.3.6. This is an optional feature for
+         * station according to Wi-Fi 7 R2 MRD.
+         *
+         * Added link will be present in |ISupplicantStaIface.getConnectionMloLinksInfo|.
+         */
+        MULTI_LINK_RECONFIG_AP_ADDITION = 2,
     }
 
     /**
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/PmkSaCacheData.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/PmkSaCacheData.aidl
index e0f1d31..4071179 100644
--- a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/PmkSaCacheData.aidl
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/PmkSaCacheData.aidl
@@ -34,4 +34,9 @@
      * The content is opaque for the framework and depends on the native implementation.
      */
     byte[] serializedEntry;
+    /**
+     * Pairwise Master Key Identifier (PMKID), which is a unique key identifier used by AP to
+     * track PMK used (Pairwise Master Key) for a station.
+     */
+    @nullable byte[] pmkid;
 }
diff --git a/wifi/supplicant/aidl/vts/functional/Android.bp b/wifi/supplicant/aidl/vts/functional/Android.bp
index 8bfe805..f94eb46 100644
--- a/wifi/supplicant/aidl/vts/functional/Android.bp
+++ b/wifi/supplicant/aidl/vts/functional/Android.bp
@@ -43,7 +43,7 @@
         "android.hardware.wifi@1.3",
         "android.hardware.wifi@1.4",
         "android.hardware.wifi@1.5",
-        "android.hardware.wifi.common-V1-ndk",
+        "android.hardware.wifi.common-V2-ndk",
         "android.hardware.wifi.supplicant@1.0",
         "android.hardware.wifi.supplicant@1.1",
         "android.hardware.wifi.supplicant-V4-ndk",
@@ -52,7 +52,7 @@
         "VtsHalWifiV1_0TargetTestUtil",
         "VtsHalWifiV1_5TargetTestUtil",
         "VtsHalWifiSupplicantV1_0TargetTestUtil",
-        "android.hardware.wifi.common-V1-ndk",
+        "android.hardware.wifi.common-V2-ndk",
         "android.hardware.wifi-V3-ndk",
         "VtsHalWifiTargetTestUtil",
     ],
@@ -81,7 +81,7 @@
         "android.hardware.wifi@1.3",
         "android.hardware.wifi@1.4",
         "android.hardware.wifi@1.5",
-        "android.hardware.wifi.common-V1-ndk",
+        "android.hardware.wifi.common-V2-ndk",
         "android.hardware.wifi.supplicant@1.0",
         "android.hardware.wifi.supplicant@1.1",
         "android.hardware.wifi.supplicant-V4-ndk",
@@ -90,7 +90,7 @@
         "VtsHalWifiV1_0TargetTestUtil",
         "VtsHalWifiV1_5TargetTestUtil",
         "VtsHalWifiSupplicantV1_0TargetTestUtil",
-        "android.hardware.wifi.common-V1-ndk",
+        "android.hardware.wifi.common-V2-ndk",
         "android.hardware.wifi-V3-ndk",
         "VtsHalWifiTargetTestUtil",
     ],
@@ -119,7 +119,7 @@
         "android.hardware.wifi@1.3",
         "android.hardware.wifi@1.4",
         "android.hardware.wifi@1.5",
-        "android.hardware.wifi.common-V1-ndk",
+        "android.hardware.wifi.common-V2-ndk",
         "android.hardware.wifi.supplicant@1.0",
         "android.hardware.wifi.supplicant@1.1",
         "android.hardware.wifi.supplicant-V4-ndk",
@@ -128,7 +128,7 @@
         "VtsHalWifiV1_0TargetTestUtil",
         "VtsHalWifiV1_5TargetTestUtil",
         "VtsHalWifiSupplicantV1_0TargetTestUtil",
-        "android.hardware.wifi.common-V1-ndk",
+        "android.hardware.wifi.common-V2-ndk",
         "android.hardware.wifi-V3-ndk",
         "VtsHalWifiTargetTestUtil",
     ],