diff --git a/system/btif/co/bta_av_co.cc b/system/btif/co/bta_av_co.cc
index de9f0dea0faf4c2754090346c14277722923c859..f703a8764722a1c8014e91ce307877fe4e12b459 100644
--- a/system/btif/co/bta_av_co.cc
+++ b/system/btif/co/bta_av_co.cc
@@ -132,6 +132,8 @@ static const tBTA_AV_CO_SINK* bta_av_co_find_peer_src_supports_codec(
 static tBTA_AV_CO_SINK* bta_av_co_audio_set_codec(tBTA_AV_CO_PEER* p_peer);
 static tBTA_AV_CO_SINK* bta_av_co_audio_codec_selected(
     A2dpCodecConfig& codec_config, tBTA_AV_CO_PEER* p_peer);
+static bool bta_av_co_audio_update_selectable_codec(
+    A2dpCodecConfig& codec_config, const tBTA_AV_CO_PEER* p_peer);
 static void bta_av_co_save_new_codec_config(tBTA_AV_CO_PEER* p_peer,
                                             const uint8_t* new_codec_config,
                                             uint8_t num_protect,
@@ -848,21 +850,39 @@ static const tBTA_AV_CO_SINK* bta_av_co_find_peer_src_supports_codec(
 
 //
 // Select the current codec configuration based on peer codec support.
-// Return true on success, otherwise false.
+// Furthermore, the local state for the remaining non-selected codecs is
+// updated to reflect whether the codec is selectable.
+// Return a pointer to the corresponding |tBTA_AV_CO_SINK| sink entry
+// on success, otherwise NULL.
 //
 static tBTA_AV_CO_SINK* bta_av_co_audio_set_codec(tBTA_AV_CO_PEER* p_peer) {
+  tBTA_AV_CO_SINK* p_sink = NULL;
+
+  // Update all selectable codecs.
+  // This is needed to update the selectable parameters for each codec.
+  // NOTE: The selectable codec info is used only for informational purpose.
+  for (const auto& iter : bta_av_co_cb.codecs->orderedSourceCodecs()) {
+    APPL_TRACE_DEBUG("%s: updating selectable codec %s", __func__,
+                     iter->name().c_str());
+    bta_av_co_audio_update_selectable_codec(*iter, p_peer);
+  }
+
+  // Select the codec
   for (const auto& iter : bta_av_co_cb.codecs->orderedSourceCodecs()) {
     APPL_TRACE_DEBUG("%s: trying codec %s", __func__, iter->name().c_str());
-    // Try to select an open device for the codec
-    tBTA_AV_CO_SINK* p_sink = bta_av_co_audio_codec_selected(*iter, p_peer);
+    p_sink = bta_av_co_audio_codec_selected(*iter, p_peer);
     if (p_sink != NULL) {
       APPL_TRACE_DEBUG("%s: selected codec %s", __func__, iter->name().c_str());
-      return p_sink;
+      break;
     }
     APPL_TRACE_DEBUG("%s: cannot use codec %s", __func__, iter->name().c_str());
   }
 
-  return NULL;
+  // NOTE: Unconditionally dispatch the event to make sure a callback with
+  // the most recent codec info is generated.
+  btif_dispatch_sm_event(BTIF_AV_SOURCE_CONFIG_UPDATED_EVT, NULL, 0);
+
+  return p_sink;
 }
 
 // Select an open device for the preferred codec specified by |codec_config|.
@@ -896,8 +916,9 @@ static tBTA_AV_CO_SINK* bta_av_co_audio_codec_selected(
                      codec_config.name().c_str());
     return NULL;
   }
-  if (!bta_av_co_cb.codecs->setCodecConfig(p_sink->codec_caps, true,
-                                           new_codec_config)) {
+  if (!bta_av_co_cb.codecs->setCodecConfig(
+          p_sink->codec_caps, true /* is_capability */, new_codec_config,
+          true /* select_current_codec */)) {
     APPL_TRACE_DEBUG("%s: cannot set source codec %s", __func__,
                      codec_config.name().c_str());
     return NULL;
@@ -906,11 +927,52 @@ static tBTA_AV_CO_SINK* bta_av_co_audio_codec_selected(
 
   bta_av_co_save_new_codec_config(p_peer, new_codec_config, p_sink->num_protect,
                                   p_sink->protect_info);
-  btif_dispatch_sm_event(BTIF_AV_SOURCE_CONFIG_UPDATED_EVT, NULL, 0);
+  // NOTE: Event BTIF_AV_SOURCE_CONFIG_UPDATED_EVT is dispatched by the caller
 
   return p_sink;
 }
 
+// Update a selectable codec |codec_config| with the corresponding codec
+// information from a peer device |p_peer|.
+// Returns true if the codec is updated, otherwise false.
+static bool bta_av_co_audio_update_selectable_codec(
+    A2dpCodecConfig& codec_config, const tBTA_AV_CO_PEER* p_peer) {
+  uint8_t new_codec_config[AVDT_CODEC_SIZE];
+
+  APPL_TRACE_DEBUG("%s", __func__);
+
+  // Find the peer sink for the codec
+  const tBTA_AV_CO_SINK* p_sink = NULL;
+  for (size_t index = 0; index < p_peer->num_sup_sinks; index++) {
+    btav_a2dp_codec_index_t peer_codec_index =
+        A2DP_SourceCodecIndex(p_peer->sinks[index].codec_caps);
+    if (peer_codec_index != codec_config.codecIndex()) {
+      continue;
+    }
+    if (!bta_av_co_audio_sink_supports_cp(&p_peer->sinks[index])) {
+      APPL_TRACE_DEBUG(
+          "%s: peer sink for codec %s does not support "
+          "Copy Protection",
+          __func__, codec_config.name().c_str());
+      continue;
+    }
+    p_sink = &p_peer->sinks[index];
+    break;
+  }
+  if (p_sink == NULL) {
+    // The peer sink device does not support this codec
+    return false;
+  }
+  if (!bta_av_co_cb.codecs->setCodecConfig(
+          p_sink->codec_caps, true /* is_capability */, new_codec_config,
+          false /* select_current_codec */)) {
+    APPL_TRACE_DEBUG("%s: cannot update source codec %s", __func__,
+                     codec_config.name().c_str());
+    return false;
+  }
+  return true;
+}
+
 static void bta_av_co_save_new_codec_config(tBTA_AV_CO_PEER* p_peer,
                                             const uint8_t* new_codec_config,
                                             uint8_t num_protect,
@@ -973,9 +1035,11 @@ const tA2DP_ENCODER_INTERFACE* bta_av_co_get_encoder_interface(void) {
 bool bta_av_co_set_codec_user_config(
     const btav_a2dp_codec_config_t& codec_user_config) {
   uint8_t result_codec_config[AVDT_CODEC_SIZE];
+  const tBTA_AV_CO_SINK* p_sink = nullptr;
   bool restart_input = false;
   bool restart_output = false;
   bool config_updated = false;
+  bool success = true;
 
   // Find the peer that is currently open
   tBTA_AV_CO_PEER* p_peer = nullptr;
@@ -988,11 +1052,11 @@ bool bta_av_co_set_codec_user_config(
   }
   if (p_peer == nullptr) {
     APPL_TRACE_ERROR("%s: no open peer to configure", __func__);
-    return false;
+    success = false;
+    goto done;
   }
 
   // Find the peer SEP codec to use
-  const tBTA_AV_CO_SINK* p_sink = nullptr;
   if (codec_user_config.codec_type < BTAV_A2DP_CODEC_INDEX_MAX) {
     for (size_t index = 0; index < p_peer->num_sup_sinks; index++) {
       btav_a2dp_codec_index_t peer_codec_index =
@@ -1008,7 +1072,8 @@ bool bta_av_co_set_codec_user_config(
   }
   if (p_sink == nullptr) {
     APPL_TRACE_ERROR("%s: cannot find peer SEP to configure", __func__);
-    return false;
+    success = false;
+    goto done;
   }
 
   tA2DP_ENCODER_INIT_PEER_PARAMS peer_params;
@@ -1017,7 +1082,8 @@ bool bta_av_co_set_codec_user_config(
           codec_user_config, &peer_params, p_sink->codec_caps,
           result_codec_config, &restart_input, &restart_output,
           &config_updated)) {
-    return false;
+    success = false;
+    goto done;
   }
 
   if (restart_output) {
@@ -1034,13 +1100,15 @@ bool bta_av_co_set_codec_user_config(
                    p_peer->codec_config, num_protect, bta_av_co_cp_scmst);
   }
 
-  if (restart_input || config_updated) {
-    // NOTE: Currently, the input is restarted by sending an upcall
-    // and informing the Media Framework about the change.
-    btif_dispatch_sm_event(BTIF_AV_SOURCE_CONFIG_UPDATED_EVT, NULL, 0);
-  }
+done:
+  // NOTE: We uncoditionally send the upcall even if there is no change
+  // or the user config failed. Thus, the caller would always know whether the
+  // request succeeded or failed.
+  // NOTE: Currently, the input is restarted by sending an upcall
+  // and informing the Media Framework about the change.
+  btif_dispatch_sm_event(BTIF_AV_SOURCE_CONFIG_UPDATED_EVT, NULL, 0);
 
-  return true;
+  return success;
 }
 
 // Sets the Over-The-Air preferred codec configuration.
@@ -1211,4 +1279,8 @@ void bta_av_co_init(void) {
   bta_av_co_cb.codecs->init();
   A2DP_InitDefaultCodec(bta_av_co_cb.codec_config);
   mutex_global_unlock();
+
+  // NOTE: Unconditionally dispatch the event to make sure a callback with
+  // the most recent codec info is generated.
+  btif_dispatch_sm_event(BTIF_AV_SOURCE_CONFIG_UPDATED_EVT, NULL, 0);
 }
diff --git a/system/btif/src/btif_av.cc b/system/btif/src/btif_av.cc
index bcfcbc4cb7b2b34b2717ea24a08eb3d4e85b5a4d..6428754479cde46b80de62ba4fa8af6aac7921c9 100644
--- a/system/btif/src/btif_av.cc
+++ b/system/btif/src/btif_av.cc
@@ -296,12 +296,14 @@ static void btif_update_source_codec(void* p_data) {
 
 static void btif_report_source_codec_state(UNUSED_ATTR void* p_data) {
   btav_a2dp_codec_config_t codec_config;
-  std::vector<btav_a2dp_codec_config_t> codec_capabilities;
+  std::vector<btav_a2dp_codec_config_t> codecs_local_capabilities;
+  std::vector<btav_a2dp_codec_config_t> codecs_selectable_capabilities;
 
   A2dpCodecs* a2dp_codecs = bta_av_get_a2dp_codecs();
   if (a2dp_codecs == nullptr) return;
-  if (!a2dp_codecs->getCodecConfigAndCapabilities(&codec_config,
-                                                  &codec_capabilities)) {
+  if (!a2dp_codecs->getCodecConfigAndCapabilities(
+          &codec_config, &codecs_local_capabilities,
+          &codecs_selectable_capabilities)) {
     BTIF_TRACE_WARNING(
         "BTIF_AV_SOURCE_CONFIG_UPDATED_EVT failed: "
         "cannot get codec config and capabilities");
@@ -309,7 +311,7 @@ static void btif_report_source_codec_state(UNUSED_ATTR void* p_data) {
   }
   if (bt_av_src_callbacks != NULL) {
     HAL_CBACK(bt_av_src_callbacks, audio_config_cb, codec_config,
-              codec_capabilities);
+              codecs_local_capabilities, codecs_selectable_capabilities);
   }
 }
 
diff --git a/system/stack/a2dp/a2dp_aac.cc b/system/stack/a2dp/a2dp_aac.cc
index 23207d04e42eee938621c18526c1e80bbdb64b2f..a8b09b35484af19f650e50603bed111f80635498 100644
--- a/system/stack/a2dp/a2dp_aac.cc
+++ b/system/stack/a2dp/a2dp_aac.cc
@@ -650,7 +650,28 @@ UNUSED_ATTR static void build_codec_config(const tA2DP_AAC_CIE& config_cie,
 }
 
 A2dpCodecConfigAac::A2dpCodecConfigAac()
-    : A2dpCodecConfig(BTAV_A2DP_CODEC_INDEX_SOURCE_AAC, "AAC") {}
+    : A2dpCodecConfig(BTAV_A2DP_CODEC_INDEX_SOURCE_AAC, "AAC") {
+  // Compute the local capability
+  if (a2dp_aac_caps.sampleRate & A2DP_AAC_SAMPLING_FREQ_44100) {
+    codec_local_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_44100;
+  }
+  if (a2dp_aac_caps.sampleRate & A2DP_AAC_SAMPLING_FREQ_48000) {
+    codec_local_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_48000;
+  }
+  if (a2dp_aac_caps.sampleRate & A2DP_AAC_SAMPLING_FREQ_88200) {
+    codec_local_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_88200;
+  }
+  if (a2dp_aac_caps.sampleRate & A2DP_AAC_SAMPLING_FREQ_96000) {
+    codec_local_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_96000;
+  }
+  codec_local_capability_.bits_per_sample = a2dp_aac_caps.bits_per_sample;
+  if (a2dp_aac_caps.channelMode & A2DP_AAC_CHANNEL_MODE_MONO) {
+    codec_local_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_MONO;
+  }
+  if (a2dp_aac_caps.channelMode & A2DP_AAC_CHANNEL_MODE_STEREO) {
+    codec_local_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
+  }
+}
 
 A2dpCodecConfigAac::~A2dpCodecConfigAac() {}
 
@@ -873,6 +894,8 @@ bool A2dpCodecConfigAac::setCodecConfig(const uint8_t* p_peer_codec_info,
   // Save the internal state
   btav_a2dp_codec_config_t saved_codec_config = codec_config_;
   btav_a2dp_codec_config_t saved_codec_capability = codec_capability_;
+  btav_a2dp_codec_config_t saved_codec_selectable_capability =
+      codec_selectable_capability_;
   btav_a2dp_codec_config_t saved_codec_user_config = codec_user_config_;
   btav_a2dp_codec_config_t saved_codec_audio_config = codec_audio_config_;
   uint8_t saved_ota_codec_config[AVDT_CODEC_SIZE];
@@ -953,6 +976,24 @@ bool A2dpCodecConfigAac::setCodecConfig(const uint8_t* p_peer_codec_info,
 
   // Select the sample frequency if there is no user preference
   do {
+    // Compute the selectable capability
+    if (sampleRate & A2DP_AAC_SAMPLING_FREQ_44100) {
+      codec_selectable_capability_.sample_rate |=
+          BTAV_A2DP_CODEC_SAMPLE_RATE_44100;
+    }
+    if (sampleRate & A2DP_AAC_SAMPLING_FREQ_48000) {
+      codec_selectable_capability_.sample_rate |=
+          BTAV_A2DP_CODEC_SAMPLE_RATE_48000;
+    }
+    if (sampleRate & A2DP_AAC_SAMPLING_FREQ_88200) {
+      codec_selectable_capability_.sample_rate |=
+          BTAV_A2DP_CODEC_SAMPLE_RATE_88200;
+    }
+    if (sampleRate & A2DP_AAC_SAMPLING_FREQ_96000) {
+      codec_selectable_capability_.sample_rate |=
+          BTAV_A2DP_CODEC_SAMPLE_RATE_96000;
+    }
+
     if (codec_config_.sample_rate != BTAV_A2DP_CODEC_SAMPLE_RATE_NONE) break;
 
     // Compute the common capability
@@ -1030,6 +1071,10 @@ bool A2dpCodecConfigAac::setCodecConfig(const uint8_t* p_peer_codec_info,
 
   // Select the bits per sample if there is no user preference
   do {
+    // Compute the selectable capability
+    codec_selectable_capability_.bits_per_sample =
+        a2dp_aac_caps.bits_per_sample;
+
     if (codec_config_.bits_per_sample != BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE)
       break;
 
@@ -1092,6 +1137,16 @@ bool A2dpCodecConfigAac::setCodecConfig(const uint8_t* p_peer_codec_info,
 
   // Select the channel mode if there is no user preference
   do {
+    // Compute the selectable capability
+    if (channelMode & A2DP_AAC_CHANNEL_MODE_MONO) {
+      codec_selectable_capability_.channel_mode |=
+          BTAV_A2DP_CODEC_CHANNEL_MODE_MONO;
+    }
+    if (channelMode & A2DP_AAC_CHANNEL_MODE_STEREO) {
+      codec_selectable_capability_.channel_mode |=
+          BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
+    }
+
     if (codec_config_.channel_mode != BTAV_A2DP_CODEC_CHANNEL_MODE_NONE) break;
 
     // Compute the common capability
@@ -1164,6 +1219,7 @@ fail:
   // Restore the internal state
   codec_config_ = saved_codec_config;
   codec_capability_ = saved_codec_capability;
+  codec_selectable_capability_ = saved_codec_selectable_capability;
   codec_user_config_ = saved_codec_user_config;
   codec_audio_config_ = saved_codec_audio_config;
   memcpy(ota_codec_config_, saved_ota_codec_config, sizeof(ota_codec_config_));
diff --git a/system/stack/a2dp/a2dp_codec_config.cc b/system/stack/a2dp/a2dp_codec_config.cc
index fb86eeee1a68ba7efb77cdba28e0ada290a49a36..f4440e6982d0af164c325fd8b5ee9c71d5059e5f 100644
--- a/system/stack/a2dp/a2dp_codec_config.cc
+++ b/system/stack/a2dp/a2dp_codec_config.cc
@@ -35,22 +35,34 @@
 /* The Media Type offset within the codec info byte array */
 #define A2DP_MEDIA_TYPE_OFFSET 1
 
+// Initializes the codec config.
+// |codec_config| is the codec config to initialize.
+// |codec_index| and |codec_priority| are the codec type and priority to use
+// for the initialization.
+static void init_btav_a2dp_codec_config(
+    btav_a2dp_codec_config_t* codec_config, btav_a2dp_codec_index_t codec_index,
+    btav_a2dp_codec_priority_t codec_priority) {
+  memset(codec_config, 0, sizeof(btav_a2dp_codec_config_t));
+  codec_config->codec_type = codec_index;
+  codec_config->codec_priority = codec_priority;
+}
+
 A2dpCodecConfig::A2dpCodecConfig(btav_a2dp_codec_index_t codec_index,
                                  const std::string& name)
     : codec_index_(codec_index), name_(name) {
   setDefaultCodecPriority();
 
-  memset(&codec_config_, 0, sizeof(codec_config_));
-  codec_config_.codec_type = codec_index_;
-
-  memset(&codec_capability_, 0, sizeof(codec_capability_));
-  codec_capability_.codec_type = codec_index_;
-
-  memset(&codec_user_config_, 0, sizeof(codec_user_config_));
-  codec_user_config_.codec_type = codec_index_;
-
-  memset(&codec_audio_config_, 0, sizeof(codec_audio_config_));
-  codec_audio_config_.codec_type = codec_index_;
+  init_btav_a2dp_codec_config(&codec_config_, codec_index_, codecPriority());
+  init_btav_a2dp_codec_config(&codec_capability_, codec_index_,
+                              codecPriority());
+  init_btav_a2dp_codec_config(&codec_local_capability_, codec_index_,
+                              codecPriority());
+  init_btav_a2dp_codec_config(&codec_selectable_capability_, codec_index_,
+                              codecPriority());
+  init_btav_a2dp_codec_config(&codec_user_config_, codec_index_,
+                              BTAV_A2DP_CODEC_PRIORITY_DEFAULT);
+  init_btav_a2dp_codec_config(&codec_audio_config_, codec_index_,
+                              BTAV_A2DP_CODEC_PRIORITY_DEFAULT);
 
   memset(ota_codec_config_, 0, sizeof(ota_codec_config_));
   memset(ota_codec_peer_capability_, 0, sizeof(ota_codec_peer_capability_));
@@ -61,7 +73,7 @@ A2dpCodecConfig::~A2dpCodecConfig() {}
 
 void A2dpCodecConfig::setCodecPriority(
     btav_a2dp_codec_priority_t codec_priority) {
-  if (codec_priority == 0) {
+  if (codec_priority == BTAV_A2DP_CODEC_PRIORITY_DEFAULT) {
     // Compute the default codec priority
     setDefaultCodecPriority();
   } else {
@@ -71,7 +83,8 @@ void A2dpCodecConfig::setCodecPriority(
 
 void A2dpCodecConfig::setDefaultCodecPriority() {
   // Compute the default codec priority
-  codec_priority_ = 1000 * codec_index_ + 1;
+  uint32_t priority = 1000 * codec_index_ + 1;
+  codec_priority_ = static_cast<btav_a2dp_codec_priority_t>(priority);
 }
 
 A2dpCodecConfig* A2dpCodecConfig::createCodec(
@@ -141,6 +154,20 @@ btav_a2dp_codec_config_t A2dpCodecConfig::getCodecCapability() {
   return codec_capability_;
 }
 
+btav_a2dp_codec_config_t A2dpCodecConfig::getCodecLocalCapability() {
+  std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
+
+  // TODO: We should check whether the codec capability is valid
+  return codec_local_capability_;
+}
+
+btav_a2dp_codec_config_t A2dpCodecConfig::getCodecSelectableCapability() {
+  std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
+
+  // TODO: We should check whether the codec capability is valid
+  return codec_selectable_capability_;
+}
+
 btav_a2dp_codec_config_t A2dpCodecConfig::getCodecUserConfig() {
   std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
 
@@ -172,7 +199,7 @@ uint8_t A2dpCodecConfig::getAudioBitsPerSample() {
 bool A2dpCodecConfig::isCodecConfigEmpty(
     const btav_a2dp_codec_config_t& codec_config) {
   return (
-      (codec_config.codec_priority == 0) &&
+      (codec_config.codec_priority == BTAV_A2DP_CODEC_PRIORITY_DEFAULT) &&
       (codec_config.sample_rate == BTAV_A2DP_CODEC_SAMPLE_RATE_NONE) &&
       (codec_config.bits_per_sample == BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE) &&
       (codec_config.channel_mode == BTAV_A2DP_CODEC_CHANNEL_MODE_NONE) &&
@@ -324,7 +351,8 @@ A2dpCodecConfig* A2dpCodecs::findSourceCodecConfig(
 
 bool A2dpCodecs::setCodecConfig(const uint8_t* p_peer_codec_info,
                                 bool is_capability,
-                                uint8_t* p_result_codec_config) {
+                                uint8_t* p_result_codec_config,
+                                bool select_current_codec) {
   std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
   A2dpCodecConfig* a2dp_codec_config = findSourceCodecConfig(p_peer_codec_info);
   if (a2dp_codec_config == nullptr) return false;
@@ -332,7 +360,9 @@ bool A2dpCodecs::setCodecConfig(const uint8_t* p_peer_codec_info,
                                          p_result_codec_config)) {
     return false;
   }
-  current_codec_config_ = a2dp_codec_config;
+  if (select_current_codec) {
+    current_codec_config_ = a2dp_codec_config;
+  }
   return true;
 }
 
@@ -522,7 +552,8 @@ fail:
 
 bool A2dpCodecs::getCodecConfigAndCapabilities(
     btav_a2dp_codec_config_t* p_codec_config,
-    std::vector<btav_a2dp_codec_config_t>* p_codec_capabilities) {
+    std::vector<btav_a2dp_codec_config_t>* p_codecs_local_capabilities,
+    std::vector<btav_a2dp_codec_config_t>* p_codecs_selectable_capabilities) {
   std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
 
   if (current_codec_config_ != nullptr) {
@@ -533,11 +564,26 @@ bool A2dpCodecs::getCodecConfigAndCapabilities(
     *p_codec_config = codec_config;
   }
 
-  std::vector<btav_a2dp_codec_config_t> codec_capabilities;
+  std::vector<btav_a2dp_codec_config_t> codecs_capabilities;
   for (auto codec : orderedSourceCodecs()) {
-    codec_capabilities.push_back(codec->getCodecCapability());
+    codecs_capabilities.push_back(codec->getCodecLocalCapability());
+  }
+  *p_codecs_local_capabilities = codecs_capabilities;
+
+  codecs_capabilities.clear();
+  for (auto codec : orderedSourceCodecs()) {
+    btav_a2dp_codec_config_t codec_capability =
+        codec->getCodecSelectableCapability();
+    // Don't add entries that cannot be used
+    if ((codec_capability.sample_rate == BTAV_A2DP_CODEC_SAMPLE_RATE_NONE) ||
+        (codec_capability.bits_per_sample ==
+         BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE) ||
+        (codec_capability.channel_mode == BTAV_A2DP_CODEC_CHANNEL_MODE_NONE)) {
+      continue;
+    }
+    codecs_capabilities.push_back(codec_capability);
   }
-  *p_codec_capabilities = codec_capabilities;
+  *p_codecs_selectable_capabilities = codecs_capabilities;
 
   return true;
 }
diff --git a/system/stack/a2dp/a2dp_sbc.cc b/system/stack/a2dp/a2dp_sbc.cc
index e8ab36a5965e37bdbad995053a3e711b51f9149b..1b09a8db1370fefdf7a0c5dfcc210c40832075a6 100644
--- a/system/stack/a2dp/a2dp_sbc.cc
+++ b/system/stack/a2dp/a2dp_sbc.cc
@@ -49,17 +49,19 @@ typedef struct {
   uint8_t alloc_method; /* Allocation method */
   uint8_t min_bitpool;  /* Minimum bitpool */
   uint8_t max_bitpool;  /* Maximum bitpool */
+  btav_a2dp_codec_bits_per_sample_t bits_per_sample;
 } tA2DP_SBC_CIE;
 
 /* SBC SRC codec capabilities */
 static const tA2DP_SBC_CIE a2dp_sbc_caps = {
-    A2DP_SBC_IE_SAMP_FREQ_44, /* samp_freq */
-    A2DP_SBC_IE_CH_MD_JOINT,  /* ch_mode */
-    A2DP_SBC_IE_BLOCKS_16,    /* block_len */
-    A2DP_SBC_IE_SUBBAND_8,    /* num_subbands */
-    A2DP_SBC_IE_ALLOC_MD_L,   /* alloc_method */
-    A2DP_SBC_IE_MIN_BITPOOL,  /* min_bitpool */
-    A2DP_SBC_MAX_BITPOOL      /* max_bitpool */
+    A2DP_SBC_IE_SAMP_FREQ_44,          /* samp_freq */
+    A2DP_SBC_IE_CH_MD_JOINT,           /* ch_mode */
+    A2DP_SBC_IE_BLOCKS_16,             /* block_len */
+    A2DP_SBC_IE_SUBBAND_8,             /* num_subbands */
+    A2DP_SBC_IE_ALLOC_MD_L,            /* alloc_method */
+    A2DP_SBC_IE_MIN_BITPOOL,           /* min_bitpool */
+    A2DP_SBC_MAX_BITPOOL,              /* max_bitpool */
+    BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16 /* bits_per_sample */
 };
 
 /* SBC SINK codec capabilities */
@@ -72,18 +74,20 @@ static const tA2DP_SBC_CIE a2dp_sbc_sink_caps = {
     (A2DP_SBC_IE_SUBBAND_4 | A2DP_SBC_IE_SUBBAND_8),   /* num_subbands */
     (A2DP_SBC_IE_ALLOC_MD_L | A2DP_SBC_IE_ALLOC_MD_S), /* alloc_method */
     A2DP_SBC_IE_MIN_BITPOOL,                           /* min_bitpool */
-    A2DP_SBC_MAX_BITPOOL                               /* max_bitpool */
+    A2DP_SBC_MAX_BITPOOL,                              /* max_bitpool */
+    BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16                 /* bits_per_sample */
 };
 
 /* Default SBC codec configuration */
 const tA2DP_SBC_CIE a2dp_sbc_default_config = {
-    A2DP_SBC_IE_SAMP_FREQ_44, /* samp_freq */
-    A2DP_SBC_IE_CH_MD_JOINT,  /* ch_mode */
-    A2DP_SBC_IE_BLOCKS_16,    /* block_len */
-    A2DP_SBC_IE_SUBBAND_8,    /* num_subbands */
-    A2DP_SBC_IE_ALLOC_MD_L,   /* alloc_method */
-    A2DP_SBC_IE_MIN_BITPOOL,  /* min_bitpool */
-    A2DP_SBC_MAX_BITPOOL      /* max_bitpool */
+    A2DP_SBC_IE_SAMP_FREQ_44,          /* samp_freq */
+    A2DP_SBC_IE_CH_MD_JOINT,           /* ch_mode */
+    A2DP_SBC_IE_BLOCKS_16,             /* block_len */
+    A2DP_SBC_IE_SUBBAND_8,             /* num_subbands */
+    A2DP_SBC_IE_ALLOC_MD_L,            /* alloc_method */
+    A2DP_SBC_IE_MIN_BITPOOL,           /* min_bitpool */
+    A2DP_SBC_MAX_BITPOOL,              /* max_bitpool */
+    BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16 /* bits_per_sample */
 };
 
 static const tA2DP_ENCODER_INTERFACE a2dp_encoder_interface_sbc = {
@@ -1014,7 +1018,7 @@ UNUSED_ATTR static void build_codec_config(const tA2DP_SBC_CIE& config_cie,
   if (config_cie.samp_freq & A2DP_SBC_IE_SAMP_FREQ_48)
     result->sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_48000;
 
-  result->bits_per_sample = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16;
+  result->bits_per_sample = config_cie.bits_per_sample;
 
   if (config_cie.ch_mode & A2DP_SBC_IE_CH_MD_MONO)
     result->channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_MONO;
@@ -1026,7 +1030,28 @@ UNUSED_ATTR static void build_codec_config(const tA2DP_SBC_CIE& config_cie,
 }
 
 A2dpCodecConfigSbc::A2dpCodecConfigSbc()
-    : A2dpCodecConfig(BTAV_A2DP_CODEC_INDEX_SOURCE_SBC, "SBC") {}
+    : A2dpCodecConfig(BTAV_A2DP_CODEC_INDEX_SOURCE_SBC, "SBC") {
+  // Compute the local capability
+  if (a2dp_sbc_caps.samp_freq & A2DP_SBC_IE_SAMP_FREQ_44) {
+    codec_local_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_44100;
+  }
+  if (a2dp_sbc_caps.samp_freq & A2DP_SBC_IE_SAMP_FREQ_48) {
+    codec_local_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_48000;
+  }
+  codec_local_capability_.bits_per_sample = a2dp_sbc_caps.bits_per_sample;
+  if (a2dp_sbc_caps.ch_mode & A2DP_SBC_IE_CH_MD_MONO) {
+    codec_local_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_MONO;
+  }
+  if (a2dp_sbc_caps.ch_mode & A2DP_SBC_IE_CH_MD_JOINT) {
+    codec_local_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
+  }
+  if (a2dp_sbc_caps.ch_mode & A2DP_SBC_IE_CH_MD_STEREO) {
+    codec_local_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
+  }
+  if (a2dp_sbc_caps.ch_mode & A2DP_SBC_IE_CH_MD_DUAL) {
+    codec_local_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
+  }
+}
 
 A2dpCodecConfigSbc::~A2dpCodecConfigSbc() {}
 
@@ -1214,6 +1239,8 @@ bool A2dpCodecConfigSbc::setCodecConfig(const uint8_t* p_peer_codec_info,
   // Save the internal state
   btav_a2dp_codec_config_t saved_codec_config = codec_config_;
   btav_a2dp_codec_config_t saved_codec_capability = codec_capability_;
+  btav_a2dp_codec_config_t saved_codec_selectable_capability =
+      codec_selectable_capability_;
   btav_a2dp_codec_config_t saved_codec_user_config = codec_user_config_;
   btav_a2dp_codec_config_t saved_codec_audio_config = codec_audio_config_;
   uint8_t saved_ota_codec_config[AVDT_CODEC_SIZE];
@@ -1270,6 +1297,16 @@ bool A2dpCodecConfigSbc::setCodecConfig(const uint8_t* p_peer_codec_info,
 
   // Select the sample frequency if there is no user preference
   do {
+    // Compute the selectable capability
+    if (samp_freq & A2DP_SBC_IE_SAMP_FREQ_44) {
+      codec_selectable_capability_.sample_rate |=
+          BTAV_A2DP_CODEC_SAMPLE_RATE_44100;
+    }
+    if (samp_freq & A2DP_SBC_IE_SAMP_FREQ_48) {
+      codec_selectable_capability_.sample_rate |=
+          BTAV_A2DP_CODEC_SAMPLE_RATE_48000;
+    }
+
     if (codec_config_.sample_rate != BTAV_A2DP_CODEC_SAMPLE_RATE_NONE) break;
 
     // Compute the common capability
@@ -1326,6 +1363,10 @@ bool A2dpCodecConfigSbc::setCodecConfig(const uint8_t* p_peer_codec_info,
 
   // Select the bits per sample if there is no user preference
   do {
+    // Compute the selectable capability
+    codec_selectable_capability_.bits_per_sample =
+        a2dp_sbc_caps.bits_per_sample;
+
     if (codec_config_.bits_per_sample != BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE)
       break;
 
@@ -1396,6 +1437,24 @@ bool A2dpCodecConfigSbc::setCodecConfig(const uint8_t* p_peer_codec_info,
 
   // Select the channel mode if there is no user preference
   do {
+    // Compute the selectable capability
+    if (ch_mode & A2DP_SBC_IE_CH_MD_MONO) {
+      codec_selectable_capability_.channel_mode |=
+          BTAV_A2DP_CODEC_CHANNEL_MODE_MONO;
+    }
+    if (ch_mode & A2DP_SBC_IE_CH_MD_JOINT) {
+      codec_selectable_capability_.channel_mode |=
+          BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
+    }
+    if (ch_mode & A2DP_SBC_IE_CH_MD_STEREO) {
+      codec_selectable_capability_.channel_mode |=
+          BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
+    }
+    if (ch_mode & A2DP_SBC_IE_CH_MD_DUAL) {
+      codec_selectable_capability_.channel_mode |=
+          BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
+    }
+
     if (codec_config_.channel_mode != BTAV_A2DP_CODEC_CHANNEL_MODE_NONE) break;
 
     // Compute the common capability
@@ -1538,6 +1597,7 @@ fail:
   // Restore the internal state
   codec_config_ = saved_codec_config;
   codec_capability_ = saved_codec_capability;
+  codec_selectable_capability_ = saved_codec_selectable_capability;
   codec_user_config_ = saved_codec_user_config;
   codec_audio_config_ = saved_codec_audio_config;
   memcpy(ota_codec_config_, saved_ota_codec_config, sizeof(ota_codec_config_));
diff --git a/system/stack/a2dp/a2dp_vendor_aptx.cc b/system/stack/a2dp/a2dp_vendor_aptx.cc
index 8de13eda38fb81fd07f51013ed7cb6c7d02d794b..812e05a69775892dc0c273533f7bf982ff03f639 100644
--- a/system/stack/a2dp/a2dp_vendor_aptx.cc
+++ b/system/stack/a2dp/a2dp_vendor_aptx.cc
@@ -416,7 +416,22 @@ bool A2DP_VendorInitCodecConfigAptx(tAVDT_CFG* p_cfg) {
 }
 
 A2dpCodecConfigAptx::A2dpCodecConfigAptx()
-    : A2dpCodecConfig(BTAV_A2DP_CODEC_INDEX_SOURCE_APTX, "aptX") {}
+    : A2dpCodecConfig(BTAV_A2DP_CODEC_INDEX_SOURCE_APTX, "aptX") {
+  // Compute the local capability
+  if (a2dp_aptx_caps.sampleRate & A2DP_APTX_SAMPLERATE_44100) {
+    codec_local_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_44100;
+  }
+  if (a2dp_aptx_caps.sampleRate & A2DP_APTX_SAMPLERATE_48000) {
+    codec_local_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_48000;
+  }
+  codec_local_capability_.bits_per_sample = a2dp_aptx_caps.bits_per_sample;
+  if (a2dp_aptx_caps.channelMode & A2DP_APTX_CHANNELS_MONO) {
+    codec_local_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_MONO;
+  }
+  if (a2dp_aptx_caps.channelMode & A2DP_APTX_CHANNELS_STEREO) {
+    codec_local_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
+  }
+}
 
 A2dpCodecConfigAptx::~A2dpCodecConfigAptx() {}
 
@@ -582,6 +597,8 @@ bool A2dpCodecConfigAptx::setCodecConfig(const uint8_t* p_peer_codec_info,
   // Save the internal state
   btav_a2dp_codec_config_t saved_codec_config = codec_config_;
   btav_a2dp_codec_config_t saved_codec_capability = codec_capability_;
+  btav_a2dp_codec_config_t saved_codec_selectable_capability =
+      codec_selectable_capability_;
   btav_a2dp_codec_config_t saved_codec_user_config = codec_user_config_;
   btav_a2dp_codec_config_t saved_codec_audio_config = codec_audio_config_;
   uint8_t saved_ota_codec_config[AVDT_CODEC_SIZE];
@@ -640,6 +657,16 @@ bool A2dpCodecConfigAptx::setCodecConfig(const uint8_t* p_peer_codec_info,
 
   // Select the sample frequency if there is no user preference
   do {
+    // Compute the selectable capability
+    if (sampleRate & A2DP_APTX_SAMPLERATE_44100) {
+      codec_selectable_capability_.sample_rate |=
+          BTAV_A2DP_CODEC_SAMPLE_RATE_44100;
+    }
+    if (sampleRate & A2DP_APTX_SAMPLERATE_48000) {
+      codec_selectable_capability_.sample_rate |=
+          BTAV_A2DP_CODEC_SAMPLE_RATE_48000;
+    }
+
     if (codec_config_.sample_rate != BTAV_A2DP_CODEC_SAMPLE_RATE_NONE) break;
 
     // Compute the common capability
@@ -696,6 +723,10 @@ bool A2dpCodecConfigAptx::setCodecConfig(const uint8_t* p_peer_codec_info,
 
   // Select the bits per sample if there is no user preference
   do {
+    // Compute the selectable capability
+    codec_selectable_capability_.bits_per_sample =
+        a2dp_aptx_caps.bits_per_sample;
+
     if (codec_config_.bits_per_sample != BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE)
       break;
 
@@ -753,6 +784,16 @@ bool A2dpCodecConfigAptx::setCodecConfig(const uint8_t* p_peer_codec_info,
 
   // Select the channel mode if there is no user preference
   do {
+    // Compute the selectable capability
+    if (channelMode & A2DP_APTX_CHANNELS_MONO) {
+      codec_selectable_capability_.channel_mode |=
+          BTAV_A2DP_CODEC_CHANNEL_MODE_MONO;
+    }
+    if (channelMode & A2DP_APTX_CHANNELS_STEREO) {
+      codec_selectable_capability_.channel_mode |=
+          BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
+    }
+
     if (codec_config_.channel_mode != BTAV_A2DP_CODEC_CHANNEL_MODE_NONE) break;
 
     // Compute the common capability
@@ -831,6 +872,7 @@ fail:
   // Restore the internal state
   codec_config_ = saved_codec_config;
   codec_capability_ = saved_codec_capability;
+  codec_selectable_capability_ = saved_codec_selectable_capability;
   codec_user_config_ = saved_codec_user_config;
   codec_audio_config_ = saved_codec_audio_config;
   memcpy(ota_codec_config_, saved_ota_codec_config, sizeof(ota_codec_config_));
diff --git a/system/stack/a2dp/a2dp_vendor_aptx_hd.cc b/system/stack/a2dp/a2dp_vendor_aptx_hd.cc
index c31486dc59e70745d22759c6ac057166cdad7c91..5bb4ddf5bf58d64f2f23191e5d0f9a8821ef470f 100644
--- a/system/stack/a2dp/a2dp_vendor_aptx_hd.cc
+++ b/system/stack/a2dp/a2dp_vendor_aptx_hd.cc
@@ -434,7 +434,22 @@ bool A2DP_VendorInitCodecConfigAptxHd(tAVDT_CFG* p_cfg) {
 }
 
 A2dpCodecConfigAptxHd::A2dpCodecConfigAptxHd()
-    : A2dpCodecConfig(BTAV_A2DP_CODEC_INDEX_SOURCE_APTX_HD, "aptX-HD") {}
+    : A2dpCodecConfig(BTAV_A2DP_CODEC_INDEX_SOURCE_APTX_HD, "aptX-HD") {
+  // Compute the local capability
+  if (a2dp_aptx_hd_caps.sampleRate & A2DP_APTX_HD_SAMPLERATE_44100) {
+    codec_local_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_44100;
+  }
+  if (a2dp_aptx_hd_caps.sampleRate & A2DP_APTX_HD_SAMPLERATE_48000) {
+    codec_local_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_48000;
+  }
+  codec_local_capability_.bits_per_sample = a2dp_aptx_hd_caps.bits_per_sample;
+  if (a2dp_aptx_hd_caps.channelMode & A2DP_APTX_HD_CHANNELS_MONO) {
+    codec_local_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_MONO;
+  }
+  if (a2dp_aptx_hd_caps.channelMode & A2DP_APTX_HD_CHANNELS_STEREO) {
+    codec_local_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
+  }
+}
 
 A2dpCodecConfigAptxHd::~A2dpCodecConfigAptxHd() {}
 
@@ -600,6 +615,8 @@ bool A2dpCodecConfigAptxHd::setCodecConfig(const uint8_t* p_peer_codec_info,
   // Save the internal state
   btav_a2dp_codec_config_t saved_codec_config = codec_config_;
   btav_a2dp_codec_config_t saved_codec_capability = codec_capability_;
+  btav_a2dp_codec_config_t saved_codec_selectable_capability =
+      codec_selectable_capability_;
   btav_a2dp_codec_config_t saved_codec_user_config = codec_user_config_;
   btav_a2dp_codec_config_t saved_codec_audio_config = codec_audio_config_;
   uint8_t saved_ota_codec_config[AVDT_CODEC_SIZE];
@@ -658,6 +675,16 @@ bool A2dpCodecConfigAptxHd::setCodecConfig(const uint8_t* p_peer_codec_info,
 
   // Select the sample frequency if there is no user preference
   do {
+    // Compute the selectable capability
+    if (sampleRate & A2DP_APTX_HD_SAMPLERATE_44100) {
+      codec_selectable_capability_.sample_rate |=
+          BTAV_A2DP_CODEC_SAMPLE_RATE_44100;
+    }
+    if (sampleRate & A2DP_APTX_HD_SAMPLERATE_48000) {
+      codec_selectable_capability_.sample_rate |=
+          BTAV_A2DP_CODEC_SAMPLE_RATE_48000;
+    }
+
     if (codec_config_.sample_rate != BTAV_A2DP_CODEC_SAMPLE_RATE_NONE) break;
 
     // Compute the common capability
@@ -714,6 +741,10 @@ bool A2dpCodecConfigAptxHd::setCodecConfig(const uint8_t* p_peer_codec_info,
 
   // Select the bits per sample if there is no user preference
   do {
+    // Compute the selectable capability
+    codec_selectable_capability_.bits_per_sample =
+        a2dp_aptx_hd_caps.bits_per_sample;
+
     if (codec_config_.bits_per_sample != BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE)
       break;
 
@@ -771,6 +802,16 @@ bool A2dpCodecConfigAptxHd::setCodecConfig(const uint8_t* p_peer_codec_info,
 
   // Select the channel mode if there is no user preference
   do {
+    // Compute the selectable capability
+    if (channelMode & A2DP_APTX_HD_CHANNELS_MONO) {
+      codec_selectable_capability_.channel_mode |=
+          BTAV_A2DP_CODEC_CHANNEL_MODE_MONO;
+    }
+    if (channelMode & A2DP_APTX_HD_CHANNELS_STEREO) {
+      codec_selectable_capability_.channel_mode |=
+          BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
+    }
+
     if (codec_config_.channel_mode != BTAV_A2DP_CODEC_CHANNEL_MODE_NONE) break;
 
     // Compute the common capability
@@ -859,6 +900,7 @@ fail:
   // Restore the internal state
   codec_config_ = saved_codec_config;
   codec_capability_ = saved_codec_capability;
+  codec_selectable_capability_ = saved_codec_selectable_capability;
   codec_user_config_ = saved_codec_user_config;
   codec_audio_config_ = saved_codec_audio_config;
   memcpy(ota_codec_config_, saved_ota_codec_config, sizeof(ota_codec_config_));
diff --git a/system/stack/a2dp/a2dp_vendor_ldac.cc b/system/stack/a2dp/a2dp_vendor_ldac.cc
index 0f3ae23546517fac1c3313545a24e1d7157404e7..66fa570d8b83c747cee3fa8fee5c232c6ef6cee1 100644
--- a/system/stack/a2dp/a2dp_vendor_ldac.cc
+++ b/system/stack/a2dp/a2dp_vendor_ldac.cc
@@ -518,6 +518,10 @@ UNUSED_ATTR static void build_codec_config(const tA2DP_LDAC_CIE& config_cie,
     result->sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_88200;
   if (config_cie.sampleRate & A2DP_LDAC_SAMPLING_FREQ_96000)
     result->sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_96000;
+  if (config_cie.sampleRate & A2DP_LDAC_SAMPLING_FREQ_176400)
+    result->sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_176400;
+  if (config_cie.sampleRate & A2DP_LDAC_SAMPLING_FREQ_192000)
+    result->sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_192000;
 
   result->bits_per_sample = config_cie.bits_per_sample;
 
@@ -530,7 +534,37 @@ UNUSED_ATTR static void build_codec_config(const tA2DP_LDAC_CIE& config_cie,
 }
 
 A2dpCodecConfigLdac::A2dpCodecConfigLdac()
-    : A2dpCodecConfig(BTAV_A2DP_CODEC_INDEX_SOURCE_LDAC, "LDAC") {}
+    : A2dpCodecConfig(BTAV_A2DP_CODEC_INDEX_SOURCE_LDAC, "LDAC") {
+  // Compute the local capability
+  if (a2dp_ldac_caps.sampleRate & A2DP_LDAC_SAMPLING_FREQ_44100) {
+    codec_local_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_44100;
+  }
+  if (a2dp_ldac_caps.sampleRate & A2DP_LDAC_SAMPLING_FREQ_48000) {
+    codec_local_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_48000;
+  }
+  if (a2dp_ldac_caps.sampleRate & A2DP_LDAC_SAMPLING_FREQ_88200) {
+    codec_local_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_88200;
+  }
+  if (a2dp_ldac_caps.sampleRate & A2DP_LDAC_SAMPLING_FREQ_96000) {
+    codec_local_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_96000;
+  }
+  if (a2dp_ldac_caps.sampleRate & A2DP_LDAC_SAMPLING_FREQ_176400) {
+    codec_local_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_176400;
+  }
+  if (a2dp_ldac_caps.sampleRate & A2DP_LDAC_SAMPLING_FREQ_192000) {
+    codec_local_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_192000;
+  }
+  codec_local_capability_.bits_per_sample = a2dp_ldac_caps.bits_per_sample;
+  if (a2dp_ldac_caps.channelMode & A2DP_LDAC_CHANNEL_MODE_MONO) {
+    codec_local_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_MONO;
+  }
+  if (a2dp_ldac_caps.channelMode & A2DP_LDAC_CHANNEL_MODE_STEREO) {
+    codec_local_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
+  }
+  if (a2dp_ldac_caps.channelMode & A2DP_LDAC_CHANNEL_MODE_DUAL) {
+    codec_local_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
+  }
+}
 
 A2dpCodecConfigLdac::~A2dpCodecConfigLdac() {}
 
@@ -785,6 +819,8 @@ bool A2dpCodecConfigLdac::setCodecConfig(const uint8_t* p_peer_codec_info,
   // Save the internal state
   btav_a2dp_codec_config_t saved_codec_config = codec_config_;
   btav_a2dp_codec_config_t saved_codec_capability = codec_capability_;
+  btav_a2dp_codec_config_t saved_codec_selectable_capability =
+      codec_selectable_capability_;
   btav_a2dp_codec_config_t saved_codec_user_config = codec_user_config_;
   btav_a2dp_codec_config_t saved_codec_audio_config = codec_audio_config_;
   uint8_t saved_ota_codec_config[AVDT_CODEC_SIZE];
@@ -866,6 +902,32 @@ bool A2dpCodecConfigLdac::setCodecConfig(const uint8_t* p_peer_codec_info,
 
   // Select the sample frequency if there is no user preference
   do {
+    // Compute the selectable capability
+    if (sampleRate & A2DP_LDAC_SAMPLING_FREQ_44100) {
+      codec_selectable_capability_.sample_rate |=
+          BTAV_A2DP_CODEC_SAMPLE_RATE_44100;
+    }
+    if (sampleRate & A2DP_LDAC_SAMPLING_FREQ_48000) {
+      codec_selectable_capability_.sample_rate |=
+          BTAV_A2DP_CODEC_SAMPLE_RATE_48000;
+    }
+    if (sampleRate & A2DP_LDAC_SAMPLING_FREQ_88200) {
+      codec_selectable_capability_.sample_rate |=
+          BTAV_A2DP_CODEC_SAMPLE_RATE_88200;
+    }
+    if (sampleRate & A2DP_LDAC_SAMPLING_FREQ_96000) {
+      codec_selectable_capability_.sample_rate |=
+          BTAV_A2DP_CODEC_SAMPLE_RATE_96000;
+    }
+    if (sampleRate & A2DP_LDAC_SAMPLING_FREQ_176400) {
+      codec_selectable_capability_.sample_rate |=
+          BTAV_A2DP_CODEC_SAMPLE_RATE_176400;
+    }
+    if (sampleRate & A2DP_LDAC_SAMPLING_FREQ_192000) {
+      codec_selectable_capability_.sample_rate |=
+          BTAV_A2DP_CODEC_SAMPLE_RATE_192000;
+    }
+
     if (codec_config_.sample_rate != BTAV_A2DP_CODEC_SAMPLE_RATE_NONE) break;
 
     // Compute the common capability
@@ -947,6 +1009,10 @@ bool A2dpCodecConfigLdac::setCodecConfig(const uint8_t* p_peer_codec_info,
 
   // Select the bits per sample if there is no user preference
   do {
+    // Compute the selectable capability
+    codec_selectable_capability_.bits_per_sample =
+        a2dp_ldac_caps.bits_per_sample;
+
     if (codec_config_.bits_per_sample != BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE)
       break;
 
@@ -1016,6 +1082,20 @@ bool A2dpCodecConfigLdac::setCodecConfig(const uint8_t* p_peer_codec_info,
 
   // Select the channel mode if there is no user preference
   do {
+    // Compute the selectable capability
+    if (channelMode & A2DP_LDAC_CHANNEL_MODE_MONO) {
+      codec_selectable_capability_.channel_mode |=
+          BTAV_A2DP_CODEC_CHANNEL_MODE_MONO;
+    }
+    if (channelMode & A2DP_LDAC_CHANNEL_MODE_STEREO) {
+      codec_selectable_capability_.channel_mode |=
+          BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
+    }
+    if (channelMode & A2DP_LDAC_CHANNEL_MODE_DUAL) {
+      codec_selectable_capability_.channel_mode |=
+          BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
+    }
+
     if (codec_config_.channel_mode != BTAV_A2DP_CODEC_CHANNEL_MODE_NONE) break;
 
     // Compute the common capability
@@ -1089,6 +1169,7 @@ fail:
   // Restore the internal state
   codec_config_ = saved_codec_config;
   codec_capability_ = saved_codec_capability;
+  codec_selectable_capability_ = saved_codec_selectable_capability;
   codec_user_config_ = saved_codec_user_config;
   codec_audio_config_ = saved_codec_audio_config;
   memcpy(ota_codec_config_, saved_ota_codec_config, sizeof(ota_codec_config_));
diff --git a/system/stack/include/a2dp_codec_api.h b/system/stack/include/a2dp_codec_api.h
index 80e4eec0af27c46635c974a0fbe2825a0f4babd6..63049eda95b2ea8abd980d839fe6d812bd9f5d4d 100644
--- a/system/stack/include/a2dp_codec_api.h
+++ b/system/stack/include/a2dp_codec_api.h
@@ -81,6 +81,17 @@ class A2dpCodecConfig {
   // Returns a copy of the current codec capability.
   btav_a2dp_codec_config_t getCodecCapability();
 
+  // Gets the codec local capability.
+  // Returns a copy of the codec local capability.
+  btav_a2dp_codec_config_t getCodecLocalCapability();
+
+  // Gets the codec selectable capability.
+  // The capability is computed by intersecting the local codec's capability
+  // and the peer's codec capability. Any explicit user configuration is
+  // not included in the result.
+  // Returns a copy of the codec selectable capability.
+  btav_a2dp_codec_config_t getCodecSelectableCapability();
+
   // Gets the current codec user configuration.
   // Returns a copy of the current codec user configuration.
   btav_a2dp_codec_config_t getCodecUserConfig();
@@ -99,7 +110,8 @@ class A2dpCodecConfig {
 
  protected:
   // Sets the current priority of the codec to |codec_priority|.
-  // If |codec_priority| is 0, the priority is reset to its default value.
+  // If |codec_priority| is BTAV_A2DP_CODEC_PRIORITY_DEFAULT, the priority is
+  // reset to its default value.
   void setCodecPriority(btav_a2dp_codec_priority_t codec_priority);
 
   // Sets the current priority of the codec to its default value.
@@ -175,6 +187,8 @@ class A2dpCodecConfig {
 
   btav_a2dp_codec_config_t codec_config_;
   btav_a2dp_codec_config_t codec_capability_;
+  btav_a2dp_codec_config_t codec_local_capability_;
+  btav_a2dp_codec_config_t codec_selectable_capability_;
 
   // The optional user configuration. The values (if set) are used
   // as a preference when there is a choice. If a particular value
@@ -227,6 +241,8 @@ class A2dpCodecs {
   // to use. If |is_capability| is true, then |p_peer_codec_info| contains the
   // peer's A2DP Sink codec capability, otherwise it contains the peer's
   // preferred A2DP codec configuration to use.
+  // If the codec can be used and |select_current_codec| is true, then
+  // this codec is selected as the current one.
   //
   // The codec configuration is built by considering the optional user
   // configuration, the local codec capabilities, the peer's codec
@@ -255,7 +271,8 @@ class A2dpCodecs {
   // The result codec configuration is stored in |p_result_codec_config|.
   // Returns true on success, othewise false.
   bool setCodecConfig(const uint8_t* p_peer_codec_info, bool is_capability,
-                      uint8_t* p_result_codec_config);
+                      uint8_t* p_result_codec_config,
+                      bool select_current_codec);
 
   // Sets the user prefered codec configuration.
   // |codec_user_config| contains the preferred codec configuration.
@@ -318,12 +335,16 @@ class A2dpCodecs {
 
   // Gets the current codec configuration and the capabilities of
   // all configured codecs.
-  // The codec configuration is stored in |p_codec_config|.
-  // The codecs capabilities are stored in |p_codec_capabilities|.
+  // The current codec configuration is stored in |p_codec_config|.
+  // Local device's codecs capabilities are stored in
+  // |p_codecs_local_capabilities|.
+  // The codecs capabilities that can be used between the local device
+  // and the remote device are stored in |p_codecs_selectable_capabilities|.
   // Returns true on success, otherwise false.
   bool getCodecConfigAndCapabilities(
       btav_a2dp_codec_config_t* p_codec_config,
-      std::vector<btav_a2dp_codec_config_t>* p_codec_capabilities);
+      std::vector<btav_a2dp_codec_config_t>* p_codecs_local_capabilities,
+      std::vector<btav_a2dp_codec_config_t>* p_codecs_selectable_capabilities);
 
  private:
   struct CompareBtBdaddr
diff --git a/system/stack/test/stack_a2dp_test.cc b/system/stack/test/stack_a2dp_test.cc
index 305a240dfc448541b86406674b5d2656f7fdc908..d3e40568a9b17801eb87ab3a7787882feba18668 100644
--- a/system/stack/test/stack_a2dp_test.cc
+++ b/system/stack/test/stack_a2dp_test.cc
@@ -835,8 +835,9 @@ TEST_F(A2dpCodecConfigTest, setCodecConfig) {
   codec_config =
       a2dp_codecs->findSourceCodecConfig(codec_info_sbc_sink_capability);
   EXPECT_NE(codec_config, nullptr);
-  EXPECT_TRUE(a2dp_codecs->setCodecConfig(codec_info_sbc_sink_capability, true,
-                                          codec_info_result));
+  EXPECT_TRUE(a2dp_codecs->setCodecConfig(
+      codec_info_sbc_sink_capability, true /* is_capability */,
+      codec_info_result, true /* select_current_codec */));
   EXPECT_EQ(a2dp_codecs->getCurrentCodecConfig(), codec_config);
   // Compare the result codec with the local test codec info
   for (size_t i = 0; i < codec_info_sbc[0] + 1; i++) {
@@ -850,8 +851,9 @@ TEST_F(A2dpCodecConfigTest, setCodecConfig) {
   codec_config =
       a2dp_codecs->findSourceCodecConfig(codec_info_aac_sink_capability);
   EXPECT_NE(codec_config, nullptr);
-  EXPECT_TRUE(a2dp_codecs->setCodecConfig(codec_info_aac_sink_capability, true,
-                                          codec_info_result));
+  EXPECT_TRUE(a2dp_codecs->setCodecConfig(
+      codec_info_aac_sink_capability, true /* is_capability */,
+      codec_info_result, true /* select_current_codec */));
   EXPECT_EQ(a2dp_codecs->getCurrentCodecConfig(), codec_config);
   // Compare the result codec with the local test codec info
   for (size_t i = 0; i < codec_info_aac[0] + 1; i++) {
@@ -864,8 +866,9 @@ TEST_F(A2dpCodecConfigTest, setCodecConfig) {
   EXPECT_NE(peer_codec_index, BTAV_A2DP_CODEC_INDEX_MAX);
   codec_config = a2dp_codecs->findSourceCodecConfig(codec_info_sbc);
   EXPECT_NE(codec_config, nullptr);
-  EXPECT_TRUE(
-      a2dp_codecs->setCodecConfig(codec_info_sbc, false, codec_info_result));
+  EXPECT_TRUE(a2dp_codecs->setCodecConfig(
+      codec_info_sbc, false /* is_capability */, codec_info_result,
+      true /* select_current_codec */));
   EXPECT_EQ(a2dp_codecs->getCurrentCodecConfig(), codec_config);
   // Compare the result codec with the local test codec info
   for (size_t i = 0; i < codec_info_sbc[0] + 1; i++) {
@@ -878,8 +881,9 @@ TEST_F(A2dpCodecConfigTest, setCodecConfig) {
   EXPECT_NE(peer_codec_index, BTAV_A2DP_CODEC_INDEX_MAX);
   codec_config = a2dp_codecs->findSourceCodecConfig(codec_info_aac);
   EXPECT_NE(codec_config, nullptr);
-  EXPECT_TRUE(
-      a2dp_codecs->setCodecConfig(codec_info_aac, false, codec_info_result));
+  EXPECT_TRUE(a2dp_codecs->setCodecConfig(
+      codec_info_aac, false /* is_capability */, codec_info_result,
+      true /* select_current_codec */));
   EXPECT_EQ(a2dp_codecs->getCurrentCodecConfig(), codec_config);
   // Compare the result codec with the local test codec info
   for (size_t i = 0; i < codec_info_aac[0] + 1; i++) {
@@ -890,8 +894,9 @@ TEST_F(A2dpCodecConfigTest, setCodecConfig) {
   uint8_t codec_info_sbc_test1[AVDT_CODEC_SIZE];
   memset(codec_info_result, 0, sizeof(codec_info_result));
   memset(codec_info_sbc_test1, 0, sizeof(codec_info_sbc_test1));
-  EXPECT_FALSE(a2dp_codecs->setCodecConfig(codec_info_sbc_test1, true,
-                                           codec_info_result));
+  EXPECT_FALSE(a2dp_codecs->setCodecConfig(
+      codec_info_sbc_test1, true /* is_capability */, codec_info_result,
+      true /* select_current_codec */));
   delete a2dp_codecs;
 }