Merge "Update work buffer size with input/output frame size change" into main
diff --git a/audio/aidl/default/bluetooth/ModuleBluetooth.cpp b/audio/aidl/default/bluetooth/ModuleBluetooth.cpp
index 9084b30..ac375a0 100644
--- a/audio/aidl/default/bluetooth/ModuleBluetooth.cpp
+++ b/audio/aidl/default/bluetooth/ModuleBluetooth.cpp
@@ -299,7 +299,13 @@
                         : std::shared_ptr<BluetoothAudioPortAidl>(
                                   std::make_shared<BluetoothAudioPortAidlOut>());
     const auto& devicePort = audioPort.ext.get<AudioPortExt::device>();
-    if (const auto device = devicePort.device.type; !proxy.ptr->registerPort(device)) {
+    const auto device = devicePort.device.type;
+    bool registrationSuccess = false;
+    for (int i = 0; i < kCreateProxyRetries && !registrationSuccess; ++i) {
+        registrationSuccess = proxy.ptr->registerPort(device);
+        usleep(kCreateProxyRetrySleepMs * 1000);
+    }
+    if (!registrationSuccess) {
         LOG(ERROR) << __func__ << ": failed to register BT port for " << device.toString();
         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
     }
diff --git a/audio/aidl/default/include/core-impl/ModuleBluetooth.h b/audio/aidl/default/include/core-impl/ModuleBluetooth.h
index 9451411..b95b526 100644
--- a/audio/aidl/default/include/core-impl/ModuleBluetooth.h
+++ b/audio/aidl/default/include/core-impl/ModuleBluetooth.h
@@ -85,6 +85,8 @@
     ndk::ScopedAStatus findOrCreateProxy(
             const ::aidl::android::media::audio::common::AudioPort& audioPort, CachedProxy& proxy);
 
+    static constexpr int kCreateProxyRetries = 5;
+    static constexpr int kCreateProxyRetrySleepMs = 250;
     ChildInterface<BluetoothA2dp> mBluetoothA2dp;
     ChildInterface<BluetoothLe> mBluetoothLe;
     std::map<int32_t /*instantiated device port ID*/, CachedProxy> mProxies;
diff --git a/audio/aidl/vts/EffectFactoryHelper.h b/audio/aidl/vts/EffectFactoryHelper.h
index ca36655..7100431 100644
--- a/audio/aidl/vts/EffectFactoryHelper.h
+++ b/audio/aidl/vts/EffectFactoryHelper.h
@@ -24,6 +24,7 @@
 #include <aidl/Vintf.h>
 #include <android/binder_auto_utils.h>
 
+#include "AudioHalBinderServiceUtil.h"
 #include "TestUtils.h"
 
 using namespace android;
diff --git a/audio/aidl/vts/EffectHelper.h b/audio/aidl/vts/EffectHelper.h
index 9fa7f9f..0be4e50 100644
--- a/audio/aidl/vts/EffectHelper.h
+++ b/audio/aidl/vts/EffectHelper.h
@@ -35,7 +35,6 @@
 #include <system/audio_effects/aidl_effects_utils.h>
 #include <system/audio_effects/effect_uuid.h>
 
-#include "AudioHalBinderServiceUtil.h"
 #include "EffectFactoryHelper.h"
 #include "TestUtils.h"
 
diff --git a/audio/aidl/vts/VtsHalAudioEffectFactoryTargetTest.cpp b/audio/aidl/vts/VtsHalAudioEffectFactoryTargetTest.cpp
index 523f20d..adf1da7 100644
--- a/audio/aidl/vts/VtsHalAudioEffectFactoryTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioEffectFactoryTargetTest.cpp
@@ -32,7 +32,6 @@
 
 #include <aidl/android/hardware/audio/effect/IFactory.h>
 
-#include "AudioHalBinderServiceUtil.h"
 #include "EffectFactoryHelper.h"
 #include "TestUtils.h"
 
diff --git a/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp b/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp
index 01cdd81..1e6a49f 100644
--- a/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp
@@ -29,7 +29,6 @@
 #include <android/binder_process.h>
 #include <fmq/AidlMessageQueue.h>
 
-#include "AudioHalBinderServiceUtil.h"
 #include "EffectFactoryHelper.h"
 #include "EffectHelper.h"
 #include "TestUtils.h"
diff --git a/audio/aidl/vts/VtsHalEqualizerTargetTest.cpp b/audio/aidl/vts/VtsHalEqualizerTargetTest.cpp
index 76838cef..d7dbe38 100644
--- a/audio/aidl/vts/VtsHalEqualizerTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalEqualizerTargetTest.cpp
@@ -29,7 +29,6 @@
 #include <android/binder_process.h>
 #include <gtest/gtest.h>
 
-#include "AudioHalBinderServiceUtil.h"
 #include "EffectHelper.h"
 #include "TestUtils.h"
 
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecParameters.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecParameters.aidl
index 60cf82a..ac63c28 100644
--- a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecParameters.aidl
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecParameters.aidl
@@ -39,7 +39,7 @@
   int bitdepth;
   int minBitrate;
   int maxBitrate;
-  boolean lowLatency;
-  boolean lossless;
+  boolean lowLatency = false;
+  boolean lossless = false;
   byte[] vendorSpecificParameters;
 }
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioProvider.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioProvider.aidl
index 3a2dcef..8d46c01 100644
--- a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioProvider.aidl
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioProvider.aidl
@@ -41,7 +41,7 @@
   void updateAudioConfiguration(in android.hardware.bluetooth.audio.AudioConfiguration audioConfig);
   void setLowLatencyModeAllowed(in boolean allowed);
   android.hardware.bluetooth.audio.A2dpStatus parseA2dpConfiguration(in android.hardware.bluetooth.audio.CodecId codecId, in byte[] configuration, out android.hardware.bluetooth.audio.CodecParameters codecParameters);
-  @nullable android.hardware.bluetooth.audio.A2dpConfiguration getA2dpConfiguration(in List<android.hardware.bluetooth.audio.A2dpRemoteCapabilities> remoteA2dpCapabilities, in android.hardware.bluetooth.audio.A2dpConfigurationHint hint);
+  @nullable android.hardware.bluetooth.audio.A2dpConfiguration getA2dpConfiguration(in android.hardware.bluetooth.audio.A2dpRemoteCapabilities[] remoteA2dpCapabilities, in android.hardware.bluetooth.audio.A2dpConfigurationHint hint);
   void setCodecPriority(in android.hardware.bluetooth.audio.CodecId codecId, int priority);
   android.hardware.bluetooth.audio.IBluetoothAudioProvider.LeAudioAseConfigurationSetting[] getLeAudioAseConfiguration(in @nullable android.hardware.bluetooth.audio.IBluetoothAudioProvider.LeAudioDeviceCapabilities[] remoteSinkAudioCapabilities, in @nullable android.hardware.bluetooth.audio.IBluetoothAudioProvider.LeAudioDeviceCapabilities[] remoteSourceAudioCapabilities, in android.hardware.bluetooth.audio.IBluetoothAudioProvider.LeAudioConfigurationRequirement[] requirements);
   android.hardware.bluetooth.audio.IBluetoothAudioProvider.LeAudioAseQosConfigurationPair getLeAudioAseQosConfiguration(in android.hardware.bluetooth.audio.IBluetoothAudioProvider.LeAudioAseQosConfigurationRequirement qosRequirement);
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/A2dpConfiguration.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/A2dpConfiguration.aidl
index a7fd9ff..db5212f 100644
--- a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/A2dpConfiguration.aidl
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/A2dpConfiguration.aidl
@@ -26,6 +26,7 @@
 parcelable A2dpConfiguration {
     /**
      * Remote Stream Endpoint Identifier
+     * This matches `A2dpRemoteCapabilities.seid` given by the framework.
      */
     int remoteSeid;
 
@@ -35,7 +36,7 @@
      * `configuration`. Using `id.a2dp`, the format is given by the `Codec
      * Specific Information Elements` [A2DP - 4.3-6.2], and using `id.vendor`,
      * by `Vendor Specific Value` [A2DP - 4.7.2].
-     * In any case, this byte array is limited by the framework to 128 Bytes.
+     * In any case, this byte array must be limited to 128 bytes.
      */
     CodecId id;
     CodecParameters parameters;
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/A2dpRemoteCapabilities.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/A2dpRemoteCapabilities.aidl
index 87277f1..224bb60 100644
--- a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/A2dpRemoteCapabilities.aidl
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/A2dpRemoteCapabilities.aidl
@@ -25,6 +25,8 @@
 parcelable A2dpRemoteCapabilities {
     /**
      * Remote Stream Endpoint identifier
+     * Allocated by the remote device to identify a specific codec and capabilities,
+     * in the meaning of the AVDTP standard.
      */
     int seid;
 
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/A2dpStreamConfiguration.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/A2dpStreamConfiguration.aidl
index 2a0c4d8..b8521f4 100644
--- a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/A2dpStreamConfiguration.aidl
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/A2dpStreamConfiguration.aidl
@@ -21,7 +21,9 @@
 @VintfStability
 parcelable A2dpStreamConfiguration {
     /**
-     * Peer MTU (16 bits)
+     * Peer Maximum Transfer Unit (MTU), 16 bits value [Core - 3.A.5.1]
+     * It's the remote device indication of the maximum amount of data that
+     * can be received on the AVDTP Stream Channel.
      */
     int peerMtu;
 
@@ -29,6 +31,7 @@
      * Optional SCMS-T Content Protection header
      * that precedes audio content when enabled [A2DP - 3.2.1-2].
      * The content protection byte is defined by [Assigned Number - 6.3.2].
+     * When the content protection is not enabled, this field should be left `null`.
      */
     @nullable byte[1] cpHeaderScmst;
 
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecParameters.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecParameters.aidl
index b6f8a94..37f8942 100644
--- a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecParameters.aidl
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecParameters.aidl
@@ -35,24 +35,29 @@
     int bitdepth;
 
     /**
-     * Encoding parameters:
-     *
-     * - Bitrate limits on a frame basis, defined in bits per second.
-     *   The encoder bitrate mode can be encoded following this rule:
-     *     . minBitrate equals to maxBitrate for constant bitrate
-     *     . minBitrate set to 0, for VBR with peak bitrate at maxBitratre value.
-     *     . minBitrate greater than 0, for ABR, the bitrate of the stream varies
-     *       between minBitrate to maxBitrate according to link quality.
-     *   The 0 value for both means "undefined" or "don't care".
-     *
-     * - Low-latency configuration privileged
-     * - Lossless effort indication. The 'False' value can be used as "don't care"
+     * Bitrate limits on a frame basis, defined in bits per second.
+     * The encoder bitrate mode can be encoded following this rule:
+     *   . minBitrate equals to maxBitrate for constant bitrate
+     *   . minBitrate set to 0, for VBR with peak bitrate at maxBitratre value.
+     *   . minBitrate greater than 0, for ABR, the bitrate of the stream varies
+     *     between minBitrate to maxBitrate according to link quality.
+     * The 0 value for both means "undefined" or "don't care".
      */
     int minBitrate;
     int maxBitrate;
 
-    boolean lowLatency;
-    boolean lossless;
+    /**
+     * Low-latency configuration. The interpretation is vendor specific.
+     * When returned to the client, the assessment of the low latency configuration is left
+     * to the vendor's discretion. When set by the client, it indicates that we are entering
+     * a low-latency context (e.g. gaming), and such a configuration should be privileged.
+     */
+    boolean lowLatency = false;
+
+    /**
+     * Lossless effort indication. The 'False' value can be used as "don't care"
+     */
+    boolean lossless = false;
 
     /**
      * Vendor specific parameters, inserted in the Vendor Specific HCI Command
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioProvider.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioProvider.aidl
index 1424431..33af8a4 100644
--- a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioProvider.aidl
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioProvider.aidl
@@ -133,7 +133,7 @@
      *         when no suitable configuration has been found.
      */
     @nullable A2dpConfiguration getA2dpConfiguration(
-            in List<A2dpRemoteCapabilities> remoteA2dpCapabilities, in A2dpConfigurationHint hint);
+            in A2dpRemoteCapabilities[] remoteA2dpCapabilities, in A2dpConfigurationHint hint);
 
     /**
      * Predefined values for the codec priority, used by `setCodecPriority()`.
diff --git a/bluetooth/audio/aidl/default/A2dpOffloadAudioProvider.cpp b/bluetooth/audio/aidl/default/A2dpOffloadAudioProvider.cpp
index ba7a89d..c7761c5 100644
--- a/bluetooth/audio/aidl/default/A2dpOffloadAudioProvider.cpp
+++ b/bluetooth/audio/aidl/default/A2dpOffloadAudioProvider.cpp
@@ -23,7 +23,6 @@
 #include <android-base/logging.h>
 
 #include "A2dpOffloadCodecAac.h"
-#include "A2dpOffloadCodecFactory.h"
 #include "A2dpOffloadCodecSbc.h"
 
 namespace aidl {
@@ -32,17 +31,21 @@
 namespace bluetooth {
 namespace audio {
 
-A2dpOffloadEncodingAudioProvider::A2dpOffloadEncodingAudioProvider()
-    : A2dpOffloadAudioProvider() {
+A2dpOffloadEncodingAudioProvider::A2dpOffloadEncodingAudioProvider(
+    const A2dpOffloadCodecFactory& codec_factory)
+    : A2dpOffloadAudioProvider(codec_factory) {
   session_type_ = SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH;
 }
 
-A2dpOffloadDecodingAudioProvider::A2dpOffloadDecodingAudioProvider()
-    : A2dpOffloadAudioProvider() {
+A2dpOffloadDecodingAudioProvider::A2dpOffloadDecodingAudioProvider(
+    const A2dpOffloadCodecFactory& codec_factory)
+    : A2dpOffloadAudioProvider(codec_factory) {
   session_type_ = SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH;
 }
 
-A2dpOffloadAudioProvider::A2dpOffloadAudioProvider() {}
+A2dpOffloadAudioProvider::A2dpOffloadAudioProvider(
+    const A2dpOffloadCodecFactory& codec_factory)
+    : codec_factory_(codec_factory) {}
 
 bool A2dpOffloadAudioProvider::isValid(const SessionType& session_type) {
   return (session_type == session_type_);
@@ -56,17 +59,29 @@
     auto a2dp_config = audio_config.get<AudioConfiguration::Tag::a2dp>();
     A2dpStatus a2dp_status = A2dpStatus::NOT_SUPPORTED_CODEC_TYPE;
 
-    if (a2dp_config.codecId ==
-        A2dpOffloadCodecSbc::GetInstance()->GetCodecId()) {
-      SbcParameters sbc_parameters;
-      a2dp_status = A2dpOffloadCodecSbc::GetInstance()->ParseConfiguration(
-          a2dp_config.configuration, &sbc_parameters);
+    auto codec = codec_factory_.GetCodec(a2dp_config.codecId);
+    if (!codec) {
+      LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
+                << " - CodecId=" << a2dp_config.codecId.toString()
+                << " is not found";
+      return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
 
-    } else if (a2dp_config.codecId ==
-               A2dpOffloadCodecAac::GetInstance()->GetCodecId()) {
+    if (codec->info.id == CodecId(CodecId::A2dp::SBC)) {
+      SbcParameters sbc_parameters;
+
+      auto codec_sbc =
+          std::static_pointer_cast<const A2dpOffloadCodecSbc>(codec);
+      a2dp_status = codec_sbc->ParseConfiguration(a2dp_config.configuration,
+                                                  &sbc_parameters);
+
+    } else if (codec->info.id == CodecId(CodecId::A2dp::AAC)) {
       AacParameters aac_parameters;
-      a2dp_status = A2dpOffloadCodecAac::GetInstance()->ParseConfiguration(
-          a2dp_config.configuration, &aac_parameters);
+
+      auto codec_aac =
+          std::static_pointer_cast<const A2dpOffloadCodecAac>(codec);
+      a2dp_status = codec_aac->ParseConfiguration(a2dp_config.configuration,
+                                                  &aac_parameters);
     }
     if (a2dp_status != A2dpStatus::OK) {
       LOG(WARNING) << __func__ << " - Invalid Audio Configuration="
@@ -105,7 +120,7 @@
 ndk::ScopedAStatus A2dpOffloadAudioProvider::parseA2dpConfiguration(
     const CodecId& codec_id, const std::vector<uint8_t>& configuration,
     CodecParameters* codec_parameters, A2dpStatus* _aidl_return) {
-  auto codec = A2dpOffloadCodecFactory::GetInstance()->GetCodec(codec_id);
+  auto codec = codec_factory_.GetCodec(codec_id);
   if (!codec) {
     LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
               << " - CodecId=" << codec_id.toString() << " is not found";
@@ -124,8 +139,8 @@
   *_aidl_return = std::nullopt;
   A2dpConfiguration avdtp_configuration;
 
-  if (A2dpOffloadCodecFactory::GetInstance()->GetConfiguration(
-          remote_a2dp_capabilities, hint, &avdtp_configuration))
+  if (codec_factory_.GetConfiguration(remote_a2dp_capabilities, hint,
+                                      &avdtp_configuration))
     *_aidl_return =
         std::make_optional<A2dpConfiguration>(std::move(avdtp_configuration));
 
diff --git a/bluetooth/audio/aidl/default/A2dpOffloadAudioProvider.h b/bluetooth/audio/aidl/default/A2dpOffloadAudioProvider.h
index 7cc6dee..a2d03fe 100644
--- a/bluetooth/audio/aidl/default/A2dpOffloadAudioProvider.h
+++ b/bluetooth/audio/aidl/default/A2dpOffloadAudioProvider.h
@@ -16,6 +16,7 @@
 
 #pragma once
 
+#include "A2dpOffloadCodecFactory.h"
 #include "BluetoothAudioProvider.h"
 
 namespace aidl {
@@ -26,8 +27,6 @@
 
 class A2dpOffloadAudioProvider : public BluetoothAudioProvider {
  public:
-  A2dpOffloadAudioProvider();
-
   bool isValid(const SessionType& session_type) override;
 
   ndk::ScopedAStatus startSession(
@@ -45,18 +44,23 @@
       const A2dpConfigurationHint& hint,
       std::optional<audio::A2dpConfiguration>* _aidl_return) override;
 
+ protected:
+  A2dpOffloadAudioProvider(const A2dpOffloadCodecFactory&);
+
  private:
+  const A2dpOffloadCodecFactory& codec_factory_;
+
   ndk::ScopedAStatus onSessionReady(DataMQDesc* _aidl_return) override;
 };
 
 class A2dpOffloadEncodingAudioProvider : public A2dpOffloadAudioProvider {
  public:
-  A2dpOffloadEncodingAudioProvider();
+  A2dpOffloadEncodingAudioProvider(const A2dpOffloadCodecFactory&);
 };
 
 class A2dpOffloadDecodingAudioProvider : public A2dpOffloadAudioProvider {
  public:
-  A2dpOffloadDecodingAudioProvider();
+  A2dpOffloadDecodingAudioProvider(const A2dpOffloadCodecFactory&);
 };
 
 }  // namespace audio
diff --git a/bluetooth/audio/aidl/default/A2dpOffloadCodec.h b/bluetooth/audio/aidl/default/A2dpOffloadCodec.h
index 7ed5872..2f51c73 100644
--- a/bluetooth/audio/aidl/default/A2dpOffloadCodec.h
+++ b/bluetooth/audio/aidl/default/A2dpOffloadCodec.h
@@ -18,10 +18,9 @@
 
 #include <aidl/android/hardware/bluetooth/audio/A2dpStatus.h>
 #include <aidl/android/hardware/bluetooth/audio/ChannelMode.h>
+#include <aidl/android/hardware/bluetooth/audio/CodecInfo.h>
 #include <aidl/android/hardware/bluetooth/audio/CodecParameters.h>
 
-#include "BluetoothAudioProviderFactory.h"
-
 namespace aidl::android::hardware::bluetooth::audio {
 
 class A2dpOffloadCodec {
diff --git a/bluetooth/audio/aidl/default/A2dpOffloadCodecAac.cpp b/bluetooth/audio/aidl/default/A2dpOffloadCodecAac.cpp
index 0f5533a..1570cd8 100644
--- a/bluetooth/audio/aidl/default/A2dpOffloadCodecAac.cpp
+++ b/bluetooth/audio/aidl/default/A2dpOffloadCodecAac.cpp
@@ -194,11 +194,6 @@
  * AAC Class implementation
  */
 
-const A2dpOffloadCodecAac* A2dpOffloadCodecAac::GetInstance() {
-  static A2dpOffloadCodecAac instance;
-  return &instance;
-}
-
 A2dpOffloadCodecAac::A2dpOffloadCodecAac()
     : A2dpOffloadCodec(info_),
       info_({.id = CodecId(CodecId::A2dp::AAC), .name = "AAC"}) {
diff --git a/bluetooth/audio/aidl/default/A2dpOffloadCodecAac.h b/bluetooth/audio/aidl/default/A2dpOffloadCodecAac.h
index eefa89b..65e927d 100644
--- a/bluetooth/audio/aidl/default/A2dpOffloadCodecAac.h
+++ b/bluetooth/audio/aidl/default/A2dpOffloadCodecAac.h
@@ -29,14 +29,12 @@
 class A2dpOffloadCodecAac : public A2dpOffloadCodec {
   CodecInfo info_;
 
-  A2dpOffloadCodecAac();
-
   A2dpStatus ParseConfiguration(const std::vector<uint8_t>& configuration,
                                 CodecParameters* codec_parameters,
                                 AacParameters* aac_parameters) const;
 
  public:
-  static const A2dpOffloadCodecAac* GetInstance();
+  A2dpOffloadCodecAac();
 
   A2dpStatus ParseConfiguration(
       const std::vector<uint8_t>& configuration,
diff --git a/bluetooth/audio/aidl/default/A2dpOffloadCodecFactory.cpp b/bluetooth/audio/aidl/default/A2dpOffloadCodecFactory.cpp
index 73d8fb1..658073c 100644
--- a/bluetooth/audio/aidl/default/A2dpOffloadCodecFactory.cpp
+++ b/bluetooth/audio/aidl/default/A2dpOffloadCodecFactory.cpp
@@ -37,20 +37,18 @@
  * Class implementation
  */
 
-const A2dpOffloadCodecFactory* A2dpOffloadCodecFactory::GetInstance() {
-  static A2dpOffloadCodecFactory instance;
-  return &instance;
-}
-
 A2dpOffloadCodecFactory::A2dpOffloadCodecFactory()
     : name("Offload"), codecs(ranked_codecs_) {
   ranked_codecs_.reserve(kEnableAac + kEnableSbc);
 
-  if (kEnableAac) ranked_codecs_.push_back(A2dpOffloadCodecAac::GetInstance());
-  if (kEnableSbc) ranked_codecs_.push_back(A2dpOffloadCodecSbc::GetInstance());
+  if (kEnableAac)
+    ranked_codecs_.push_back(std::make_shared<A2dpOffloadCodecAac>());
+  if (kEnableSbc)
+    ranked_codecs_.push_back(std::make_shared<A2dpOffloadCodecSbc>());
 }
 
-const A2dpOffloadCodec* A2dpOffloadCodecFactory::GetCodec(CodecId id) const {
+std::shared_ptr<const A2dpOffloadCodec> A2dpOffloadCodecFactory::GetCodec(
+    CodecId id) const {
   auto codec = std::find_if(begin(ranked_codecs_), end(ranked_codecs_),
                             [&](auto c) { return id == c->info.id; });
 
diff --git a/bluetooth/audio/aidl/default/A2dpOffloadCodecFactory.h b/bluetooth/audio/aidl/default/A2dpOffloadCodecFactory.h
index 3fb5b1d..1546cc4 100644
--- a/bluetooth/audio/aidl/default/A2dpOffloadCodecFactory.h
+++ b/bluetooth/audio/aidl/default/A2dpOffloadCodecFactory.h
@@ -16,22 +16,26 @@
 
 #pragma once
 
+#include <aidl/android/hardware/bluetooth/audio/A2dpConfiguration.h>
+#include <aidl/android/hardware/bluetooth/audio/A2dpConfigurationHint.h>
+#include <aidl/android/hardware/bluetooth/audio/A2dpRemoteCapabilities.h>
+
+#include <memory>
+
 #include "A2dpOffloadCodec.h"
 
 namespace aidl::android::hardware::bluetooth::audio {
 
 class A2dpOffloadCodecFactory {
-  std::vector<const A2dpOffloadCodec*> ranked_codecs_;
-
-  A2dpOffloadCodecFactory();
+  std::vector<std::shared_ptr<const A2dpOffloadCodec>> ranked_codecs_;
 
  public:
   const std::string name;
-  const std::vector<const A2dpOffloadCodec*>& codecs;
+  const std::vector<std::shared_ptr<const A2dpOffloadCodec>>& codecs;
 
-  static const A2dpOffloadCodecFactory* GetInstance();
+  A2dpOffloadCodecFactory();
 
-  const A2dpOffloadCodec* GetCodec(CodecId id) const;
+  std::shared_ptr<const A2dpOffloadCodec> GetCodec(CodecId id) const;
 
   bool GetConfiguration(const std::vector<A2dpRemoteCapabilities>&,
                         const A2dpConfigurationHint& hint,
diff --git a/bluetooth/audio/aidl/default/A2dpOffloadCodecSbc.cpp b/bluetooth/audio/aidl/default/A2dpOffloadCodecSbc.cpp
index 36d8f72..6b9046c 100644
--- a/bluetooth/audio/aidl/default/A2dpOffloadCodecSbc.cpp
+++ b/bluetooth/audio/aidl/default/A2dpOffloadCodecSbc.cpp
@@ -257,11 +257,6 @@
  * SBC Class implementation
  */
 
-const A2dpOffloadCodecSbc* A2dpOffloadCodecSbc::GetInstance() {
-  static A2dpOffloadCodecSbc instance;
-  return &instance;
-}
-
 A2dpOffloadCodecSbc::A2dpOffloadCodecSbc()
     : A2dpOffloadCodec(info_),
       info_({.id = CodecId(CodecId::A2dp::SBC), .name = "SBC"}) {
diff --git a/bluetooth/audio/aidl/default/A2dpOffloadCodecSbc.h b/bluetooth/audio/aidl/default/A2dpOffloadCodecSbc.h
index c380850..a39d779 100644
--- a/bluetooth/audio/aidl/default/A2dpOffloadCodecSbc.h
+++ b/bluetooth/audio/aidl/default/A2dpOffloadCodecSbc.h
@@ -33,14 +33,12 @@
 class A2dpOffloadCodecSbc : public A2dpOffloadCodec {
   CodecInfo info_;
 
-  A2dpOffloadCodecSbc();
-
   A2dpStatus ParseConfiguration(const std::vector<uint8_t>& configuration,
                                 CodecParameters* codec_parameters,
                                 SbcParameters* sbc_parameters) const;
 
  public:
-  static const A2dpOffloadCodecSbc* GetInstance();
+  A2dpOffloadCodecSbc();
 
   A2dpStatus ParseConfiguration(
       const std::vector<uint8_t>& configuration,
diff --git a/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.cpp b/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.cpp
index e55a434..c7c6e6d 100644
--- a/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.cpp
+++ b/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.cpp
@@ -22,7 +22,6 @@
 #include <android-base/logging.h>
 
 #include "A2dpOffloadAudioProvider.h"
-#include "A2dpOffloadCodecFactory.h"
 #include "A2dpSoftwareAudioProvider.h"
 #include "BluetoothAudioProvider.h"
 #include "HearingAidAudioProvider.h"
@@ -53,7 +52,8 @@
       provider = ndk::SharedRefBase::make<A2dpSoftwareEncodingAudioProvider>();
       break;
     case SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
-      provider = ndk::SharedRefBase::make<A2dpOffloadEncodingAudioProvider>();
+      provider = ndk::SharedRefBase::make<A2dpOffloadEncodingAudioProvider>(
+          a2dp_offload_codec_factory_);
       break;
     case SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH:
       provider = ndk::SharedRefBase::make<HearingAidAudioProvider>();
@@ -82,7 +82,8 @@
       provider = ndk::SharedRefBase::make<A2dpSoftwareDecodingAudioProvider>();
       break;
     case SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH:
-      provider = ndk::SharedRefBase::make<A2dpOffloadDecodingAudioProvider>();
+      provider = ndk::SharedRefBase::make<A2dpOffloadDecodingAudioProvider>(
+          a2dp_offload_codec_factory_);
       break;
     case SessionType::HFP_SOFTWARE_ENCODING_DATAPATH:
       provider = ndk::SharedRefBase::make<HfpSoftwareOutputAudioProvider>();
@@ -160,8 +161,8 @@
       session_type == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
     auto& provider_info = _aidl_return->emplace();
 
-    provider_info.name = A2dpOffloadCodecFactory::GetInstance()->name;
-    for (auto codec : A2dpOffloadCodecFactory::GetInstance()->codecs)
+    provider_info.name = a2dp_offload_codec_factory_.name;
+    for (auto codec : a2dp_offload_codec_factory_.codecs)
       provider_info.codecInfos.push_back(codec->info);
   }
 
diff --git a/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.h b/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.h
index 1afae64..6931884 100644
--- a/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.h
+++ b/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.h
@@ -18,6 +18,8 @@
 
 #include <aidl/android/hardware/bluetooth/audio/BnBluetoothAudioProviderFactory.h>
 
+#include "A2dpOffloadCodecFactory.h"
+
 namespace aidl {
 namespace android {
 namespace hardware {
@@ -25,6 +27,8 @@
 namespace audio {
 
 class BluetoothAudioProviderFactory : public BnBluetoothAudioProviderFactory {
+  const A2dpOffloadCodecFactory a2dp_offload_codec_factory_;
+
  public:
   BluetoothAudioProviderFactory();
 
diff --git a/bluetooth/finder/aidl/default/service.cpp b/bluetooth/finder/aidl/default/service.cpp
index a117df8..fe8904b 100644
--- a/bluetooth/finder/aidl/default/service.cpp
+++ b/bluetooth/finder/aidl/default/service.cpp
@@ -35,12 +35,16 @@
       ndk::SharedRefBase::make<BluetoothFinder>();
   std::string instance =
       std::string() + BluetoothFinder::descriptor + "/default";
-  auto result =
-      AServiceManager_addService(service->asBinder().get(), instance.c_str());
-  if (result == STATUS_OK) {
-    ABinderProcess_joinThreadPool();
+  if (AServiceManager_isDeclared(instance.c_str())) {
+    auto result =
+        AServiceManager_addService(service->asBinder().get(), instance.c_str());
+    if (result != STATUS_OK) {
+      ALOGE("Could not register as a service!");
+    }
   } else {
-    ALOGE("Could not register as a service!");
+    ALOGE("Could not register as a service because it's not declared.");
   }
+  // Keep running
+  ABinderProcess_joinThreadPool();
   return 0;
 }
diff --git a/bluetooth/lmp_event/aidl/default/src/main.rs b/bluetooth/lmp_event/aidl/default/src/main.rs
index cbdd4d1..dfb097f 100644
--- a/bluetooth/lmp_event/aidl/default/src/main.rs
+++ b/bluetooth/lmp_event/aidl/default/src/main.rs
@@ -41,10 +41,11 @@
     let lmp_event_service = lmp_event::LmpEvent::new();
     let lmp_event_service_binder = BnBluetoothLmpEvent::new_binder(lmp_event_service, BinderFeatures::default());
 
-    binder::add_service(
-        &format!("{}/default", lmp_event::LmpEvent::get_descriptor()),
-        lmp_event_service_binder.as_binder(),
-    ).expect("Failed to register service");
-
+    let descriptor = format!("{}/default", lmp_event::LmpEvent::get_descriptor());
+    if binder::is_declared(&descriptor).expect("Failed to check if declared") {
+        binder::add_service(&descriptor, lmp_event_service_binder.as_binder()).expect("Failed to register service");
+    } else {
+        info!("{LOG_TAG}: Failed to register service. Not declared.");
+    }
     binder::ProcessState::join_thread_pool()
 }
diff --git a/bluetooth/ranging/aidl/default/service.cpp b/bluetooth/ranging/aidl/default/service.cpp
index 83e539e..35a3f55 100644
--- a/bluetooth/ranging/aidl/default/service.cpp
+++ b/bluetooth/ranging/aidl/default/service.cpp
@@ -37,12 +37,16 @@
       ndk::SharedRefBase::make<BluetoothChannelSounding>();
   std::string instance =
       std::string() + BluetoothChannelSounding::descriptor + "/default";
-  auto result =
-      AServiceManager_addService(service->asBinder().get(), instance.c_str());
-  if (result == STATUS_OK) {
-    ABinderProcess_joinThreadPool();
+  if (AServiceManager_isDeclared(instance.c_str())) {
+    auto result =
+        AServiceManager_addService(service->asBinder().get(), instance.c_str());
+    if (result != STATUS_OK) {
+      ALOGE("Could not register as a service!");
+    }
   } else {
-    ALOGE("Could not register as a service!");
+    ALOGE("Could not register as a service because it's not declared.");
   }
+  // Keep running
+  ABinderProcess_joinThreadPool();
   return 0;
 }
diff --git a/compatibility_matrices/Android.bp b/compatibility_matrices/Android.bp
index eefca39..a3e1cd4 100644
--- a/compatibility_matrices/Android.bp
+++ b/compatibility_matrices/Android.bp
@@ -94,3 +94,11 @@
         "kernel_config_v_6.6",
     ],
 }
+
+vintf_compatibility_matrix {
+    name: "framework_compatibility_matrix.tmp.xml",
+    stem: "compatibility_matrix.tmp.xml",
+    srcs: [
+        "compatibility_matrix.tmp.xml",
+    ],
+}
diff --git a/compatibility_matrices/Android.mk b/compatibility_matrices/Android.mk
index 72ead58..7abf35e 100644
--- a/compatibility_matrices/Android.mk
+++ b/compatibility_matrices/Android.mk
@@ -112,7 +112,8 @@
 # interfaces (in the `next` release configuration).
 ifeq ($(RELEASE_AIDL_USE_UNFROZEN),true)
 my_system_matrix_deps += \
-    framework_compatibility_matrix.202404.xml
+    framework_compatibility_matrix.202404.xml \
+    framework_compatibility_matrix.tmp.xml
 endif
 
 my_framework_matrix_deps += \
diff --git a/compatibility_matrices/compatibility_matrix.202404.xml b/compatibility_matrices/compatibility_matrix.202404.xml
index 490498e..b34011e 100644
--- a/compatibility_matrices/compatibility_matrix.202404.xml
+++ b/compatibility_matrices/compatibility_matrix.202404.xml
@@ -343,25 +343,6 @@
             <instance>default</instance>
         </interface>
     </hal>
-    <hal format="hidl">
-        <name>android.hardware.media.c2</name>
-        <version>1.0-2</version>
-        <interface>
-            <name>IComponentStore</name>
-            <instance>software</instance>
-            <regex-instance>default[0-9]*</regex-instance>
-            <regex-instance>vendor[0-9]*_software</regex-instance>
-        </interface>
-    </hal>
-    <hal format="hidl">
-        <name>android.hardware.media.c2</name>
-        <version>1.0</version>
-        <interface>
-            <name>IConfigurable</name>
-            <instance>default</instance>
-            <instance>software</instance>
-        </interface>
-    </hal>
     <hal format="aidl">
         <name>android.hardware.media.c2</name>
         <version>1</version>
diff --git a/compatibility_matrices/compatibility_matrix.tmp.xml b/compatibility_matrices/compatibility_matrix.tmp.xml
new file mode 100644
index 0000000..85e3c4c
--- /dev/null
+++ b/compatibility_matrices/compatibility_matrix.tmp.xml
@@ -0,0 +1,24 @@
+<compatibility-matrix version="1.0" type="framework" level="202404">
+  <!-- This file holds the HIDL media.c2 interface while it
+  is being deprecated. This will be removed after the flag ramping
+  complete. This interface is not allowed in the 202404 vendor interface -->
+    <hal format="hidl" optional="true">
+        <name>android.hardware.media.c2</name>
+        <version>1.0-2</version>
+        <interface>
+            <name>IComponentStore</name>
+            <instance>software</instance>
+            <regex-instance>default[0-9]*</regex-instance>
+            <regex-instance>vendor[0-9]*_software</regex-instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.media.c2</name>
+        <version>1.0</version>
+        <interface>
+            <name>IConfigurable</name>
+            <instance>default</instance>
+            <instance>software</instance>
+        </interface>
+    </hal>
+</compatibility-matrix>
diff --git a/contexthub/OWNERS b/contexthub/OWNERS
index d5cfc2e..ee25833 100644
--- a/contexthub/OWNERS
+++ b/contexthub/OWNERS
@@ -1,4 +1,3 @@
 # Bug component: 156070
 arthuri@google.com
 bduddie@google.com
-stange@google.com
diff --git a/security/keymint/aidl/vts/functional/BootloaderStateTest.cpp b/security/keymint/aidl/vts/functional/BootloaderStateTest.cpp
index 54f187c..808ed18 100644
--- a/security/keymint/aidl/vts/functional/BootloaderStateTest.cpp
+++ b/security/keymint/aidl/vts/functional/BootloaderStateTest.cpp
@@ -149,7 +149,9 @@
                                                  digest512.data());
 
     ASSERT_TRUE((attestedVbmetaDigest_ == digest256) || (attestedVbmetaDigest_ == digest512))
-            << "Attested digest does not match computed digest.";
+            << "Attested vbmeta digest (" << bin2hex(attestedVbmetaDigest_)
+            << ") does not match computed digest (sha256: " << bin2hex(digest256)
+            << ", sha512: " << bin2hex(digest512) << ").";
 }
 
 INSTANTIATE_KEYMINT_AIDL_TEST(BootloaderStateTest);
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
index d3f6ae3..087f763 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
@@ -64,6 +64,13 @@
 
 namespace {
 
+// Possible values for the feature version.  Assumes that future KeyMint versions
+// will continue with the 100 * AIDL_version numbering scheme.
+//
+// Must be kept in numerically increasing order.
+const int32_t kFeatureVersions[] = {10,  11,  20,  30,  40,  41,  100, 200,
+                                    300, 400, 500, 600, 700, 800, 900};
+
 // Invalid value for a patchlevel (which is of form YYYYMMDD).
 const uint32_t kInvalidPatchlevel = 99998877;
 
@@ -2278,6 +2285,43 @@
     return hasFeature;
 }
 
+// Return the numeric value associated with a feature.
+std::optional<int32_t> keymint_feature_value(bool strongbox) {
+    std::string name = strongbox ? FEATURE_STRONGBOX_KEYSTORE : FEATURE_HARDWARE_KEYSTORE;
+    ::android::String16 name16(name.c_str());
+    ::android::sp<::android::IServiceManager> sm(::android::defaultServiceManager());
+    ::android::sp<::android::IBinder> binder(
+            sm->waitForService(::android::String16("package_native")));
+    if (binder == nullptr) {
+        GTEST_LOG_(ERROR) << "waitForService package_native failed";
+        return std::nullopt;
+    }
+    ::android::sp<::android::content::pm::IPackageManagerNative> packageMgr =
+            ::android::interface_cast<::android::content::pm::IPackageManagerNative>(binder);
+    if (packageMgr == nullptr) {
+        GTEST_LOG_(ERROR) << "Cannot find package manager";
+        return std::nullopt;
+    }
+
+    // Package manager has no mechanism to retrieve the version of a feature,
+    // only to indicate whether a certain version or above is present.
+    std::optional<int32_t> result = std::nullopt;
+    for (auto version : kFeatureVersions) {
+        bool hasFeature = false;
+        auto status = packageMgr->hasSystemFeature(name16, version, &hasFeature);
+        if (!status.isOk()) {
+            GTEST_LOG_(ERROR) << "hasSystemFeature('" << name << "', " << version
+                              << ") failed: " << status;
+            return result;
+        } else if (hasFeature) {
+            result = version;
+        } else {
+            break;
+        }
+    }
+    return result;
+}
+
 }  // namespace test
 
 }  // namespace aidl::android::hardware::security::keymint
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
index 4fb711c..4ed7698 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
@@ -56,6 +56,7 @@
 
 const string FEATURE_KEYSTORE_APP_ATTEST_KEY = "android.hardware.keystore.app_attest_key";
 const string FEATURE_STRONGBOX_KEYSTORE = "android.hardware.strongbox_keystore";
+const string FEATURE_HARDWARE_KEYSTORE = "android.hardware.hardware_keystore";
 
 // RAII class to ensure that a keyblob is deleted regardless of how a test exits.
 class KeyBlobDeleter {
@@ -444,6 +445,7 @@
 void p256_pub_key(const vector<uint8_t>& coseKeyData, EVP_PKEY_Ptr* signingKey);
 void device_id_attestation_check_acceptable_error(Tag tag, const ErrorCode& result);
 bool check_feature(const std::string& name);
+std::optional<int32_t> keymint_feature_value(bool strongbox);
 
 AuthorizationSet HwEnforcedAuthorizations(const vector<KeyCharacteristics>& key_characteristics);
 AuthorizationSet SwEnforcedAuthorizations(const vector<KeyCharacteristics>& key_characteristics);
diff --git a/security/keymint/aidl/vts/functional/KeyMintTest.cpp b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
index a2e20dc..e098aca 100644
--- a/security/keymint/aidl/vts/functional/KeyMintTest.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
@@ -21,6 +21,7 @@
 
 #include <algorithm>
 #include <iostream>
+#include <map>
 
 #include <openssl/curve25519.h>
 #include <openssl/ec.h>
@@ -1027,9 +1028,9 @@
          * The KeyMint V1 spec required that CERTIFICATE_NOT_{BEFORE,AFTER} be
          * specified for asymmetric key generation. However, this was not
          * checked at the time so we can only be strict about checking this for
-         * implementations of KeyMint version 2 and above.
+         * implementations of KeyMint version 3 and above.
          */
-        GTEST_SKIP() << "Validity strict since KeyMint v2";
+        GTEST_SKIP() << "Validity strict since KeyMint v3";
     }
     // Per RFC 5280 4.1.2.5, an undefined expiration (not-after) field should be set to
     // GeneralizedTime 999912312359559, which is 253402300799000 ms from Jan 1, 1970.
@@ -8794,6 +8795,90 @@
 
 INSTANTIATE_KEYMINT_AIDL_TEST(VsrRequirementTest);
 
+class InstanceTest : public testing::Test {
+  protected:
+    static void SetUpTestSuite() {
+        auto params = ::android::getAidlHalInstanceNames(IKeyMintDevice::descriptor);
+        for (auto& param : params) {
+            ASSERT_TRUE(AServiceManager_isDeclared(param.c_str()))
+                    << "IKeyMintDevice instance " << param << " found but not declared.";
+            ::ndk::SpAIBinder binder(AServiceManager_waitForService(param.c_str()));
+            auto keymint = IKeyMintDevice::fromBinder(binder);
+            ASSERT_NE(keymint, nullptr) << "Failed to get IKeyMintDevice instance " << param;
+
+            KeyMintHardwareInfo info;
+            ASSERT_TRUE(keymint->getHardwareInfo(&info).isOk());
+            ASSERT_EQ(keymints_.count(info.securityLevel), 0)
+                    << "There must be exactly one IKeyMintDevice with security level "
+                    << info.securityLevel;
+
+            keymints_[info.securityLevel] = std::move(keymint);
+        }
+    }
+
+    int32_t AidlVersion(shared_ptr<IKeyMintDevice> keymint) {
+        int32_t version = 0;
+        auto status = keymint->getInterfaceVersion(&version);
+        if (!status.isOk()) {
+            ADD_FAILURE() << "Failed to determine interface version";
+        }
+        return version;
+    }
+
+    static std::map<SecurityLevel, shared_ptr<IKeyMintDevice>> keymints_;
+};
+
+std::map<SecurityLevel, shared_ptr<IKeyMintDevice>> InstanceTest::keymints_;
+
+// @VsrTest = VSR-3.10-017
+// Check that the AIDL version advertised by the HAL service matches
+// the value in the package manager feature version.
+TEST_F(InstanceTest, AidlVersionInFeature) {
+    if (is_gsi_image()) {
+        GTEST_SKIP() << "Versions not required to match under GSI";
+    }
+    if (keymints_.count(SecurityLevel::TRUSTED_ENVIRONMENT) == 1) {
+        auto tee = keymints_.find(SecurityLevel::TRUSTED_ENVIRONMENT)->second;
+        int32_t tee_aidl_version = AidlVersion(tee) * 100;
+        std::optional<int32_t> tee_feature_version = keymint_feature_value(/* strongbox */ false);
+        ASSERT_TRUE(tee_feature_version.has_value());
+        EXPECT_EQ(tee_aidl_version, tee_feature_version.value());
+    }
+    if (keymints_.count(SecurityLevel::STRONGBOX) == 1) {
+        auto sb = keymints_.find(SecurityLevel::STRONGBOX)->second;
+        int32_t sb_aidl_version = AidlVersion(sb) * 100;
+        std::optional<int32_t> sb_feature_version = keymint_feature_value(/* strongbox */ true);
+        ASSERT_TRUE(sb_feature_version.has_value());
+        EXPECT_EQ(sb_aidl_version, sb_feature_version.value());
+    }
+}
+
+// @VsrTest = VSR-3.10-017
+// Check that if package manager advertises support for KeyMint of a particular version, that
+// version is present as a HAL service.
+TEST_F(InstanceTest, FeatureVersionInAidl) {
+    if (is_gsi_image()) {
+        GTEST_SKIP() << "Versions not required to match under GSI";
+    }
+    std::optional<int32_t> tee_feature_version = keymint_feature_value(/* strongbox */ false);
+    if (tee_feature_version.has_value() && tee_feature_version.value() >= 100) {
+        // Feature flag advertises the existence of KeyMint; check it is present.
+        ASSERT_EQ(keymints_.count(SecurityLevel::TRUSTED_ENVIRONMENT), 1);
+        auto tee = keymints_.find(SecurityLevel::TRUSTED_ENVIRONMENT)->second;
+        int32_t tee_aidl_version = AidlVersion(tee) * 100;
+        EXPECT_EQ(tee_aidl_version, tee_feature_version.value());
+    }
+
+    std::optional<int32_t> sb_feature_version = keymint_feature_value(/* strongbox */ true);
+    if (sb_feature_version.has_value() && sb_feature_version.value() >= 100) {
+        // Feature flag advertises the existence of KeyMint; check it is present.
+        ASSERT_EQ(keymints_.count(SecurityLevel::STRONGBOX), 1);
+        auto sb = keymints_.find(SecurityLevel::STRONGBOX)->second;
+        int32_t sb_aidl_version = AidlVersion(sb) * 100;
+        EXPECT_EQ(sb_aidl_version, sb_feature_version.value());
+    }
+}
+
 }  // namespace aidl::android::hardware::security::keymint::test
 
 using aidl::android::hardware::security::keymint::test::KeyMintAidlTestBase;
diff --git a/security/secretkeeper/aidl/vts/Android.bp b/security/secretkeeper/aidl/vts/Android.bp
index 9d1701a..0061e88 100644
--- a/security/secretkeeper/aidl/vts/Android.bp
+++ b/security/secretkeeper/aidl/vts/Android.bp
@@ -50,7 +50,7 @@
         "libbinder_rs",
         "libciborium",
         "libcoset",
-        "libdice_policy",
+        "libdice_policy_builder",
         "liblog_rust",
         "libsecretkeeper_client",
         "libsecretkeeper_comm_nostd",
@@ -72,7 +72,7 @@
         "libbinder_rs",
         "libclap",
         "libcoset",
-        "libdice_policy",
+        "libdice_policy_builder",
         "libhex",
         "liblog_rust",
         "libsecretkeeper_client",
diff --git a/security/secretkeeper/aidl/vts/secretkeeper_cli.rs b/security/secretkeeper/aidl/vts/secretkeeper_cli.rs
index 5f08482..0c13811 100644
--- a/security/secretkeeper/aidl/vts/secretkeeper_cli.rs
+++ b/security/secretkeeper/aidl/vts/secretkeeper_cli.rs
@@ -24,7 +24,8 @@
 use authgraph_core::traits::Sha256;
 use clap::{Args, Parser, Subcommand};
 use coset::CborSerializable;
-use dice_policy::{ConstraintSpec, ConstraintType, DicePolicy, MissingAction};
+use dice_policy_builder::{ConstraintSpec, ConstraintType, MissingAction, policy_for_dice_chain};
+
 use secretkeeper_client::{dice::OwnedDiceArtifactsWithExplicitKey, SkSession};
 use secretkeeper_comm::data_types::{
     error::SecretkeeperError,
@@ -146,7 +147,7 @@
                 MissingAction::Ignore,
             ),
         ];
-        DicePolicy::from_dice_chain(dice, &constraint_spec)
+        policy_for_dice_chain(dice, &constraint_spec)
             .unwrap()
             .to_vec()
             .context("serialize DICE policy")
diff --git a/security/secretkeeper/aidl/vts/secretkeeper_test_client.rs b/security/secretkeeper/aidl/vts/secretkeeper_test_client.rs
index 8c33f04..483aed6 100644
--- a/security/secretkeeper/aidl/vts/secretkeeper_test_client.rs
+++ b/security/secretkeeper/aidl/vts/secretkeeper_test_client.rs
@@ -20,7 +20,7 @@
 use authgraph_boringssl as boring;
 use authgraph_core::key;
 use coset::{CborSerializable, CoseEncrypt0};
-use dice_policy::{ConstraintSpec, ConstraintType, DicePolicy, MissingAction};
+use dice_policy_builder::{ConstraintSpec, ConstraintType, MissingAction, policy_for_dice_chain};
 use rdroidtest::{ignore_if, rdroidtest};
 use secretkeeper_client::dice::OwnedDiceArtifactsWithExplicitKey;
 use secretkeeper_client::SkSession;
@@ -258,7 +258,7 @@
         ),
     ];
 
-    DicePolicy::from_dice_chain(dice, &constraint_spec).unwrap().to_vec().unwrap()
+    policy_for_dice_chain(dice, &constraint_spec).unwrap().to_vec().unwrap()
 }
 
 /// Perform AuthGraph key exchange, returning the session keys and session ID.
diff --git a/tv/tuner/aidl/vts/functional/VtsHalTvTunerTestConfigurations.h b/tv/tuner/aidl/vts/functional/VtsHalTvTunerTestConfigurations.h
index 5c13ed0..ff94639 100644
--- a/tv/tuner/aidl/vts/functional/VtsHalTvTunerTestConfigurations.h
+++ b/tv/tuner/aidl/vts/functional/VtsHalTvTunerTestConfigurations.h
@@ -731,9 +731,20 @@
     if (videoFilterIds.empty() || audioFilterIds.empty() || frontendMap.empty()) {
         return;
     }
-    if (hasSwFe && !hasHwFe && dvrMap.empty()) {
-        ALOGD("Cannot configure Live. Only software frontends and no dvr connections");
-        return;
+    if (!hasHwFe) {
+        if (hasSwFe) {
+            if (dvrMap.empty()) {
+                ALOGD("Cannot configure Live. Only software frontends and no dvr connections.");
+                return;
+            }
+            // Live is available if there is SW FE and some DVR is attached.
+        } else {
+            // We will arrive here because frontendMap won't be empty since
+            // there will be at least a default frontend declared. But the
+            // default frontend doesn't count as "hasSwFe".
+            ALOGD("Cannot configure Live. No frontend declared at all.");
+            return;
+        }
     }
     ALOGD("Can support live");
     live.hasFrontendConnection = true;