diff --git a/system/btif/Android.bp b/system/btif/Android.bp
index 113ffd0a2ce055d79b373c3d46fe98fb840ab314..a8850a5314c2d971bd2c8ec975fb178ab28019dd 100644
--- a/system/btif/Android.bp
+++ b/system/btif/Android.bp
@@ -397,6 +397,9 @@ cc_test {
     include_dirs: btifCommonIncludes,
     srcs: [
         ":TestCommonLogMsg",
+        ":TestCommonMockFunctions",
+        ":TestMockCommon",
+        ":TestMockOsi",
         "test/btif_rc_test.cc",
     ],
     header_libs: ["libbluetooth_headers"],
@@ -411,7 +414,6 @@ cc_test {
         "libbt-protos-lite",
         "libchrome",
         "libevent",
-        "libosi",
         "libosi-AllocationTestHarness",
     ],
     target: {
diff --git a/system/btif/avrcp/avrcp_service.cc b/system/btif/avrcp/avrcp_service.cc
index a960298d163c1533b40b3711fdce66e70ea2f09b..7cf4bafaa83bb9047ab0e84d57dbb2f3cf52ef71 100644
--- a/system/btif/avrcp/avrcp_service.cc
+++ b/system/btif/avrcp/avrcp_service.cc
@@ -109,7 +109,7 @@ class AvrcpInterfaceImpl : public AvrcpInterface {
 
   uint16_t MsgReq(uint8_t handle, uint8_t label, uint8_t ctype,
                   BT_HDR* p_pkt) override {
-    return AVRC_MsgReq(handle, label, ctype, p_pkt);
+    return AVRC_MsgReq(handle, label, ctype, p_pkt, true);
   }
 
   void SaveControllerVersion(const RawAddress& bdaddr,
@@ -684,5 +684,13 @@ void AvrcpService::DebugDump(int fd) {
   dprintf(fd, "%s", stream.str().c_str());
 }
 
+/** when a2dp connected, btif will start register vol changed, so we need a
+ * interface for it. */
+void AvrcpService::RegisterVolChanged(const RawAddress& bdaddr) {
+  LOG(INFO) << ": address=" << ADDRESS_TO_LOGGABLE_STR(bdaddr);
+
+  connection_handler_->RegisterVolChanged(bdaddr);
+}
+
 }  // namespace avrcp
 }  // namespace bluetooth
diff --git a/system/btif/avrcp/avrcp_service.h b/system/btif/avrcp/avrcp_service.h
index 20a35444fba3b578feae47157ae99c0c43025185..7bd9081e00fb5f7bacfbce35c3d171556f03c69c 100644
--- a/system/btif/avrcp/avrcp_service.h
+++ b/system/btif/avrcp/avrcp_service.h
@@ -76,6 +76,10 @@ class AvrcpService : public MediaCallbacks {
   void SendPlayerSettingsChanged(std::vector<PlayerAttribute> attributes,
                                  std::vector<uint8_t> values) override;
 
+  /** when a2dp connected, btif will start register vol changed, so we need a
+   * interface for it. */
+  void RegisterVolChanged(const RawAddress& bdaddr);
+
   class ServiceInterfaceImpl : public ServiceInterface {
    public:
     void Init(MediaInterface* media_interface,
diff --git a/system/btif/include/btif_a2dp.h b/system/btif/include/btif_a2dp.h
index c4d95618b06aa775b20c8c5a5d5f43e18b414a77..d9c44d11753251681db865f5f56a546cf76f2b8f 100644
--- a/system/btif/include/btif_a2dp.h
+++ b/system/btif/include/btif_a2dp.h
@@ -26,7 +26,7 @@
 #include "types/raw_address.h"
 
 // Process 'idle' request from the BTIF state machine during initialization.
-void btif_a2dp_on_idle(void);
+void btif_a2dp_on_idle(const RawAddress& peer_addr);
 
 // Process 'start' request from the BTIF state machine to prepare for A2DP
 // streaming.
diff --git a/system/btif/include/btif_av.h b/system/btif/include/btif_av.h
index 09c0e2721c2bfe02d6daf6267d851fbe595b13ec..f85656c063a7ae6b3c4dcb568986de53df0c32b7 100644
--- a/system/btif/include/btif_av.h
+++ b/system/btif/include/btif_av.h
@@ -46,6 +46,11 @@ RawAddress btif_av_sink_active_peer(void);
  */
 bool btif_av_is_sink_enabled(void);
 
+/**
+ * Check whether A2DP Source is enabled.
+ */
+bool btif_av_is_source_enabled(void);
+
 /**
  * Start streaming.
  */
@@ -226,6 +231,14 @@ bool btif_av_is_a2dp_offload_running(void);
  */
 bool btif_av_is_peer_silenced(const RawAddress& peer_address);
 
+/**
+ * check the a2dp connect status
+ *
+ * @param address : checked device address
+ *
+ */
+bool btif_av_is_connected_addr(const RawAddress& peer_address);
+
 /**
  * Set the dynamic audio buffer size
  *
@@ -240,4 +253,16 @@ void btif_av_set_dynamic_audio_buffer_size(uint8_t dynamic_audio_buffer_size);
  */
 void btif_av_set_low_latency(bool is_low_latency);
 
+/**
+ * Check whether A2DP Source is enabled.
+ */
+extern bool btif_av_is_source_enabled(void);
+extern bool btif_av_both_enable(void);
+extern bool btif_av_src_sink_coexist_enabled(void);
+extern bool btif_av_is_sink_enabled(void);
+extern bool btif_av_is_connected_addr(const RawAddress& peer_address);
+extern bool btif_av_peer_is_connected_sink(const RawAddress& peer_address);
+extern bool btif_av_peer_is_connected_source(const RawAddress& peer_address);
+extern bool btif_av_peer_is_sink(const RawAddress& peer_address);
+extern bool btif_av_peer_is_source(const RawAddress& peer_address);
 #endif /* BTIF_AV_H */
diff --git a/system/btif/src/btif_a2dp.cc b/system/btif/src/btif_a2dp.cc
index 9e469ce14419dd2bf0f04dcb9df6369a99f87ff6..58076fa8d9490a2fdd282f64f57979e70d7a7598 100644
--- a/system/btif/src/btif_a2dp.cc
+++ b/system/btif/src/btif_a2dp.cc
@@ -38,9 +38,21 @@
 
 #include <base/logging.h>
 
-void btif_a2dp_on_idle(void) {
+void btif_a2dp_on_idle(const RawAddress& peer_addr) {
   LOG_VERBOSE("Peer stream endpoint type:%s",
               peer_stream_endpoint_text(btif_av_get_peer_sep()).c_str());
+  if (btif_av_src_sink_coexist_enabled()) {
+    bool is_sink = btif_av_peer_is_sink(peer_addr);
+    bool is_source = btif_av_peer_is_source(peer_addr);
+    LOG_INFO("## ON A2DP IDLE ## is_sink:%d is_source:%d", is_sink, is_source);
+    if (is_sink) {
+      btif_a2dp_source_on_idle();
+    } else if (is_source) {
+      btif_a2dp_sink_on_idle();
+    }
+    return;
+  }
+
   if (btif_av_get_peer_sep() == AVDT_TSEP_SNK) {
     btif_a2dp_source_on_idle();
   } else if (btif_av_get_peer_sep() == AVDT_TSEP_SRC) {
diff --git a/system/btif/src/btif_av.cc b/system/btif/src/btif_av.cc
index 019162cada29771596688d08f1c124d9ddee78cb..bfc292d20ea4c887aa54bc7db223376ec0594780 100644
--- a/system/btif/src/btif_av.cc
+++ b/system/btif/src/btif_av.cc
@@ -62,6 +62,10 @@
 #include "types/bluetooth/uuid.h"
 #include "types/raw_address.h"
 
+#ifdef OS_ANDROID
+#include <a2dp.sysprop.h>
+#endif
+
 /*****************************************************************************
  *  Constants & Macros
  *****************************************************************************/
@@ -137,6 +141,9 @@ class BtifAvEvent {
 class BtifAvPeer;
 static bt_status_t sink_set_active_device(const RawAddress& peer_address);
 
+static void btif_av_sink_delete_active_peer(void);
+static void btif_av_source_delete_active_peer(void);
+
 // Should not need dedicated Suspend state as actual actions are no
 // different than Open state. Suspend flags are needed however to prevent
 // media task from trying to restart stream during remote Suspend or while
@@ -279,6 +286,7 @@ class BtifAvPeer {
   bool IsSource() const { return (peer_sep_ == AVDT_TSEP_SRC); }
   bool IsSink() const { return (peer_sep_ == AVDT_TSEP_SNK); }
   uint8_t PeerSep() const { return peer_sep_; }
+  void SetSep(uint8_t sep_type) { peer_sep_ = sep_type; }
   /**
    * Get the local device's Service Class UUID
    *
@@ -360,7 +368,7 @@ class BtifAvPeer {
 
  private:
   const RawAddress peer_address_;
-  const uint8_t peer_sep_;  // SEP type of peer device
+  uint8_t peer_sep_;  // SEP type of peer device
   tBTA_AV_HNDL bta_handle_;
   const uint8_t peer_id_;
   BtifAvStateMachine state_machine_;
@@ -384,6 +392,7 @@ class BtifAvSource {
       : callbacks_(nullptr),
         enabled_(false),
         a2dp_offload_enabled_(false),
+        invalid_peer_check_(false),
         max_connected_peers_(kDefaultMaxConnectedAudioDevices) {}
   ~BtifAvSource();
 
@@ -396,7 +405,9 @@ class BtifAvSource {
   btav_source_callbacks_t* Callbacks() { return callbacks_; }
   bool Enabled() const { return enabled_; }
   bool A2dpOffloadEnabled() const { return a2dp_offload_enabled_; }
-
+  void SetInvalidPeerCheck(bool invalid_peer_check) {
+    invalid_peer_check_ = invalid_peer_check;
+  }
   BtifAvPeer* FindPeer(const RawAddress& peer_address);
   BtifAvPeer* FindPeerByHandle(tBTA_AV_HNDL bta_handle);
   BtifAvPeer* FindPeerByPeerId(uint8_t peer_id);
@@ -500,10 +511,15 @@ class BtifAvSource {
     if (peer_address.IsEmpty()) {
       BTIF_TRACE_EVENT("%s: peer address is empty, shutdown the Audio source",
                        __func__);
-      if (!bta_av_co_set_active_peer(peer_address)) {
-        LOG(WARNING) << __func__
-                     << ": unable to set active peer to empty in BtaAvCo";
+      if (!btif_av_src_sink_coexist_enabled() ||
+          (btif_av_src_sink_coexist_enabled() &&
+           btif_av_sink_active_peer().IsEmpty())) {
+        if (!bta_av_co_set_active_peer(peer_address)) {
+          LOG(WARNING) << __func__
+                       << ": unable to set active peer to empty in BtaAvCo";
+        }
       }
+
       btif_a2dp_source_end_session(active_peer_);
       std::promise<void> shutdown_complete_promise;
       std::future<void> shutdown_complete_future =
@@ -519,6 +535,7 @@ class BtifAvSource {
       return true;
     }
 
+    if (btif_av_src_sink_coexist_enabled()) btif_av_sink_delete_active_peer();
     BtifAvPeer* peer = FindPeer(peer_address);
     if (peer == nullptr || !peer->IsConnected()) {
       LOG(ERROR) << __func__ << ": Error setting "
@@ -537,6 +554,22 @@ class BtifAvSource {
     return true;
   }
 
+  void DeleteActivePeer(void) {
+    std::promise<void> shutdown_complete_promise;
+    BTIF_TRACE_EVENT("%s", __func__);
+    if (btif_av_sink_active_peer().IsEmpty()) {
+      if (!bta_av_co_set_active_peer(RawAddress::kEmpty)) {
+        LOG_WARN("%s : unable to set active peer to empty in BtaAvCo",
+                 __func__);
+      }
+    } else {
+      LOG_WARN("%s : there is an active peer as source role", __func__);
+    }
+    btif_a2dp_source_end_session(active_peer_);
+    btif_a2dp_source_shutdown(std::move(shutdown_complete_promise));
+    active_peer_ = RawAddress::kEmpty;
+  }
+
   /**
    * Update source codec configuration for a peer.
    *
@@ -561,6 +594,8 @@ class BtifAvSource {
   void RegisterAllBtaHandles();
   void DeregisterAllBtaHandles();
   void BtaHandleRegistered(uint8_t peer_id, tBTA_AV_HNDL bta_handle);
+  BtifAvPeer* popPeer(const RawAddress& peer_address);
+  void AddPeer(BtifAvPeer* peer);
 
  private:
   void CleanupAllPeers();
@@ -568,11 +603,15 @@ class BtifAvSource {
   btav_source_callbacks_t* callbacks_;
   bool enabled_;
   bool a2dp_offload_enabled_;
+  bool invalid_peer_check_;  // pending to check at BTA_AV_OPEN_EVT
   int max_connected_peers_;
   std::map<RawAddress, BtifAvPeer*> peers_;
   std::set<RawAddress> silenced_peers_;
   RawAddress active_peer_;
   std::map<uint8_t, tBTA_AV_HNDL> peer_id2bta_handle_;
+  std::mutex mutex_;
+  // protect for BtifAvSource::peers_
+  std::recursive_mutex btifavsource_peer_lock_;
 };
 
 class BtifAvSink {
@@ -584,6 +623,7 @@ class BtifAvSink {
   BtifAvSink()
       : callbacks_(nullptr),
         enabled_(false),
+        invalid_peer_check_(false),
         max_connected_peers_(kDefaultMaxConnectedAudioDevices) {}
   ~BtifAvSink();
 
@@ -594,6 +634,9 @@ class BtifAvSink {
   btav_sink_callbacks_t* Callbacks() { return callbacks_; }
   bool Enabled() const { return enabled_; }
 
+  void SetInvalidPeerCheck(bool invalid_peer_check) {
+    invalid_peer_check_ = invalid_peer_check;
+  }
   BtifAvPeer* FindPeer(const RawAddress& peer_address);
   BtifAvPeer* FindPeerByHandle(tBTA_AV_HNDL bta_handle);
   BtifAvPeer* FindPeerByPeerId(uint8_t peer_id);
@@ -649,10 +692,15 @@ class BtifAvSink {
     if (peer_address.IsEmpty()) {
       BTIF_TRACE_EVENT("%s: peer address is empty, shutdown the Audio sink",
                        __func__);
-      if (!bta_av_co_set_active_peer(peer_address)) {
-        LOG(WARNING) << __func__
-                     << ": unable to set active peer to empty in BtaAvCo";
+      if (!btif_av_src_sink_coexist_enabled() ||
+          (btif_av_src_sink_coexist_enabled() &&
+           btif_av_source_active_peer().IsEmpty())) {
+        if (!bta_av_co_set_active_peer(peer_address)) {
+          LOG(WARNING) << __func__
+                       << ": unable to set active peer to empty in BtaAvCo";
+        }
       }
+
       btif_a2dp_sink_end_session(active_peer_);
       btif_a2dp_sink_shutdown();
       active_peer_ = peer_address;
@@ -660,6 +708,9 @@ class BtifAvSink {
       return true;
     }
 
+    if (btif_av_src_sink_coexist_enabled()) {
+      btif_av_source_delete_active_peer();
+    }
     BtifAvPeer* peer = FindPeer(peer_address);
     if (peer == nullptr || !peer->IsConnected()) {
       LOG(ERROR) << __func__ << ": Error setting "
@@ -678,17 +729,35 @@ class BtifAvSink {
     return true;
   }
 
+  void DeleteActivePeer(void) {
+    BTIF_TRACE_EVENT("%s", __func__);
+    if (btif_av_source_active_peer().IsEmpty()) {
+      if (!bta_av_co_set_active_peer(RawAddress::kEmpty)) {
+        LOG(WARNING) << __func__
+                     << ": unable to set active peer to empty in BtaAvCo";
+      }
+    } else {
+      LOG(WARNING) << __func__ << ": there is an active peer as sink role";
+    }
+    btif_a2dp_sink_end_session(active_peer_);
+    btif_a2dp_sink_shutdown();
+    active_peer_ = RawAddress::kEmpty;
+  }
+
   const std::map<RawAddress, BtifAvPeer*>& Peers() const { return peers_; }
 
   void RegisterAllBtaHandles();
   void DeregisterAllBtaHandles();
   void BtaHandleRegistered(uint8_t peer_id, tBTA_AV_HNDL bta_handle);
+  BtifAvPeer* popPeer(const RawAddress& peer_address);
+  void AddPeer(BtifAvPeer* peer);
 
  private:
   void CleanupAllPeers();
 
   btav_sink_callbacks_t* callbacks_;
   bool enabled_;
+  bool invalid_peer_check_;  // pending to check at BTA_AV_OPEN_EVT
   int max_connected_peers_;
   std::map<RawAddress, BtifAvPeer*> peers_;
   RawAddress active_peer_;
@@ -741,6 +810,11 @@ static void btif_av_sink_initiate_av_open_timer_timeout(void* data);
 static void bta_av_sink_media_callback(const RawAddress& peer_address,
                                        tBTA_AV_EVT event,
                                        tBTA_AV_MEDIA* p_data);
+extern bool btif_av_both_enable(void);
+extern bool btif_av_is_connected_addr(const RawAddress& peer_address);
+extern bool btif_av_peer_is_sink(const RawAddress& peer_address);
+extern void btif_rc_check_pending_cmd(const RawAddress& peer_address);
+extern void btif_rc_get_addr_by_handle(uint8_t handle, RawAddress& rc_addr);
 
 static BtifAvPeer* btif_av_source_find_peer(const RawAddress& peer_address) {
   return btif_av_source.FindPeer(peer_address);
@@ -749,11 +823,27 @@ static BtifAvPeer* btif_av_sink_find_peer(const RawAddress& peer_address) {
   return btif_av_sink.FindPeer(peer_address);
 }
 static BtifAvPeer* btif_av_find_peer(const RawAddress& peer_address) {
+  if (btif_av_src_sink_coexist_enabled() && btif_av_both_enable()) {
+    BtifAvPeer* peer = nullptr;
+    peer = btif_av_source_find_peer(peer_address);
+    if (nullptr == peer) {
+      return btif_av_sink_find_peer(peer_address);
+    }
+    return peer;
+  }
   if (btif_av_source.Enabled()) return btif_av_source_find_peer(peer_address);
   if (btif_av_sink.Enabled()) return btif_av_sink_find_peer(peer_address);
   return nullptr;
 }
 static BtifAvPeer* btif_av_find_active_peer() {
+  if (btif_av_src_sink_coexist_enabled() && btif_av_both_enable()) {
+    BtifAvPeer* peer = nullptr;
+    peer = btif_av_source_find_peer(btif_av_source.ActivePeer());
+    if (nullptr == peer) {
+      return btif_av_sink_find_peer(btif_av_sink.ActivePeer());
+    }
+    return peer;
+  }
   if (btif_av_source.Enabled())
     return btif_av_source_find_peer(btif_av_source.ActivePeer());
   if (btif_av_sink.Enabled())
@@ -761,6 +851,26 @@ static BtifAvPeer* btif_av_find_active_peer() {
   return nullptr;
 }
 
+const RawAddress& btif_av_find_by_handle(tBTA_AV_HNDL bta_handle) {
+  BtifAvPeer* peer = nullptr;
+  if (btif_av_both_enable()) {
+    peer = btif_av_source.FindPeerByHandle(bta_handle);
+    if (peer == nullptr) {
+      peer = btif_av_sink.FindPeerByHandle(bta_handle);
+    }
+    if (peer == nullptr) return RawAddress::kEmpty;
+
+    return peer->PeerAddress();
+  }
+  if (btif_av_source.Enabled())
+    peer = btif_av_source.FindPeerByHandle(bta_handle);
+  if (btif_av_sink.Enabled()) peer = btif_av_sink.FindPeerByHandle(bta_handle);
+
+  if (peer == nullptr) return RawAddress::kEmpty;
+
+  return peer->PeerAddress();
+}
+
 /*****************************************************************************
  * Local helper functions
  *****************************************************************************/
@@ -985,6 +1095,18 @@ const RawAddress& BtifAvPeer::ActivePeerAddress() const {
   if (IsSink()) {
     return btif_av_source.ActivePeer();
   }
+
+  if (btif_av_src_sink_coexist_enabled() && btif_av_both_enable()) {
+    RawAddress addr = btif_av_sink.ActivePeer();
+    if (RawAddress::kEmpty == addr) {
+      LOG(WARNING) << __PRETTY_FUNCTION__ << ": A2DP peer "
+                   << btif_av_source.ActivePeer() << " is Sink";
+      return btif_av_source.ActivePeer();
+    }
+    LOG(WARNING) << __PRETTY_FUNCTION__ << ": A2DP peer "
+                 << btif_av_sink.ActivePeer() << " is Source";
+    return btif_av_sink.ActivePeer();
+  }
   LOG(FATAL) << __PRETTY_FUNCTION__ << ": A2DP peer "
              << ADDRESS_TO_LOGGABLE_STR(PeerAddress())
              << " is neither Source nor Sink";
@@ -1029,8 +1151,8 @@ bt_status_t BtifAvSource::Init(
   if (!btif_a2dp_source_init()) {
     return BT_STATUS_FAIL;
   }
-  btif_enable_service(BTA_A2DP_SOURCE_SERVICE_ID);
   enabled_ = true;
+  btif_enable_service(BTA_A2DP_SOURCE_SERVICE_ID);
   return BT_STATUS_SUCCESS;
 }
 
@@ -1083,6 +1205,7 @@ BtifAvPeer* BtifAvSource::FindPeerByPeerId(uint8_t peer_id) {
 
 BtifAvPeer* BtifAvSource::FindOrCreatePeer(const RawAddress& peer_address,
                                            tBTA_AV_HNDL bta_handle) {
+  std::unique_lock<std::mutex> lock1(mutex_);
   BTIF_TRACE_DEBUG("%s: peer_address=%s bta_handle=0x%x", __PRETTY_FUNCTION__,
                    ADDRESS_TO_LOGGABLE_CSTR(peer_address), bta_handle);
 
@@ -1092,7 +1215,14 @@ BtifAvPeer* BtifAvSource::FindOrCreatePeer(const RawAddress& peer_address,
   // Find next availabie Peer ID to use
   uint8_t peer_id;
   for (peer_id = kPeerIdMin; peer_id < kPeerIdMax; peer_id++) {
-    if (FindPeerByPeerId(peer_id) == nullptr) break;
+    /* because the peer id may be in source cb and we cannot use it */
+    if (btif_av_src_sink_coexist_enabled() && btif_av_both_enable()) {
+      if (FindPeerByPeerId(peer_id) == nullptr &&
+          btif_av_sink.FindPeerByPeerId(peer_id) == nullptr)
+        break;
+    } else {
+      if (FindPeerByPeerId(peer_id) == nullptr) break;
+    }
   }
   if (peer_id == kPeerIdMax) {
     BTIF_TRACE_ERROR(
@@ -1126,6 +1256,12 @@ BtifAvPeer* BtifAvSource::FindOrCreatePeer(const RawAddress& peer_address,
 
 bool BtifAvSource::AllowedToConnect(const RawAddress& peer_address) const {
   int connected = 0;
+  if (btif_av_src_sink_coexist_enabled() && invalid_peer_check_) {
+    LOG_INFO(
+        "invalid_peer_check_ so allow to connect here, when"
+        " BTA_AV_OPEN_EVT coming, would check again!");
+    return true;
+  }
 
   // Count peers that are in the process of connecting or already connected
   for (auto it : peers_) {
@@ -1135,6 +1271,10 @@ bool BtifAvSource::AllowedToConnect(const RawAddress& peer_address) const {
       case BtifAvStateMachine::kStateOpened:
       case BtifAvStateMachine::kStateStarted:
         if (peer->PeerAddress() == peer_address) {
+          /* we should check if another role is used */
+          if (btif_av_src_sink_coexist_enabled() && btif_av_both_enable())
+            break;
+
           return true;  // Already connected or accounted for
         }
         connected++;
@@ -1143,6 +1283,18 @@ bool BtifAvSource::AllowedToConnect(const RawAddress& peer_address) const {
         break;
     }
   }
+  if (btif_av_src_sink_coexist_enabled() && btif_av_both_enable()) {
+    LOG_INFO("%s: connected=%d, max_connected_peers_=%d, sink_peers=%d",
+             __PRETTY_FUNCTION__, connected, max_connected_peers_,
+             (int)btif_av_sink.Peers().size());
+    /* if source device connected, don't connect sink device */
+
+    if (connected >= max_connected_peers_ || !btif_av_sink.Peers().empty()) {
+      return false;
+    } else {
+      return true;
+    }
+  }
   return (connected < max_connected_peers_);
 }
 
@@ -1216,6 +1368,23 @@ void BtifAvSource::BtaHandleRegistered(uint8_t peer_id,
   }
 }
 
+BtifAvPeer* BtifAvSource::popPeer(const RawAddress& peer_address) {
+  auto it = peers_.find(peer_address);
+  if (it == peers_.end()) return nullptr;
+  BtifAvPeer* peer = it->second;
+  peers_.erase(it);
+  LOG_INFO("%s: peer_address=%s, state=%d", __PRETTY_FUNCTION__,
+           ADDRESS_TO_LOGGABLE_CSTR(peer->PeerAddress()),
+           peer->StateMachine().StateId());
+  return peer;
+}
+
+void BtifAvSource::AddPeer(BtifAvPeer* peer) {
+  LOG_INFO("%s: peer_address=%s, state=%d", __PRETTY_FUNCTION__,
+           ADDRESS_TO_LOGGABLE_CSTR(peer->PeerAddress()),
+           peer->StateMachine().StateId());
+  peers_.insert(std::make_pair(peer->PeerAddress(), peer));
+}
 BtifAvSink::~BtifAvSink() { CleanupAllPeers(); }
 
 bt_status_t BtifAvSink::Init(btav_sink_callbacks_t* callbacks,
@@ -1228,14 +1397,19 @@ bt_status_t BtifAvSink::Init(btav_sink_callbacks_t* callbacks,
   max_connected_peers_ = max_connected_audio_devices;
   callbacks_ = callbacks;
 
-  std::vector<btav_a2dp_codec_config_t> codec_priorities;  // Default priorities
-  bta_av_co_init(codec_priorities);
+  /** source will have this configuration, but sink don't have, so don't
+   * overwrite it. */
+  if (!btif_av_source.Enabled()) {
+    std::vector<btav_a2dp_codec_config_t>
+        codec_priorities;  // Default priorities
+    bta_av_co_init(codec_priorities);
+  }
 
   if (!btif_a2dp_sink_init()) {
     return BT_STATUS_FAIL;
   }
-  btif_enable_service(BTA_A2DP_SINK_SERVICE_ID);
   enabled_ = true;
+  btif_enable_service(BTA_A2DP_SINK_SERVICE_ID);
   return BT_STATUS_SUCCESS;
 }
 
@@ -1297,7 +1471,15 @@ BtifAvPeer* BtifAvSink::FindOrCreatePeer(const RawAddress& peer_address,
   // Find next availabie Peer ID to use
   uint8_t peer_id;
   for (peer_id = kPeerIdMin; peer_id < kPeerIdMax; peer_id++) {
-    if (FindPeerByPeerId(peer_id) == nullptr) break;
+    /* because the peer id may be in source cb and we cannot use it */
+    if (btif_av_both_enable()) {
+      if (FindPeerByPeerId(peer_id) == nullptr &&
+          btif_av_source.FindPeerByPeerId(peer_id) == nullptr)
+        break;
+
+    } else {
+      if (FindPeerByPeerId(peer_id) == nullptr) break;
+    }
   }
   if (peer_id == kPeerIdMax) {
     BTIF_TRACE_ERROR(
@@ -1335,6 +1517,12 @@ BtifAvPeer* BtifAvSink::FindOrCreatePeer(const RawAddress& peer_address,
 bool BtifAvSink::AllowedToConnect(const RawAddress& peer_address) const {
   int connected = 0;
 
+  if (btif_av_src_sink_coexist_enabled() && invalid_peer_check_) {
+    LOG_INFO(
+        "invalid_peer_check_ so allow to connect here, when"
+        " BTA_AV_OPEN_EVT coming, would check again!");
+    return true;
+  }
   // Count peers that are in the process of connecting or already connected
   for (auto it : peers_) {
     const BtifAvPeer* peer = it.second;
@@ -1343,6 +1531,8 @@ bool BtifAvSink::AllowedToConnect(const RawAddress& peer_address) const {
       case BtifAvStateMachine::kStateOpened:
       case BtifAvStateMachine::kStateStarted:
         if (peer->PeerAddress() == peer_address) {
+          /* we should check if another role is used */
+          if (btif_av_both_enable()) break;
           return true;  // Already connected or accounted for
         }
         connected++;
@@ -1351,6 +1541,14 @@ bool BtifAvSink::AllowedToConnect(const RawAddress& peer_address) const {
         break;
     }
   }
+  if (btif_av_both_enable()) {
+    LOG_INFO("connected=%d, max_connected_peers_=%d, source_peers=%d",
+             connected, max_connected_peers_,
+             (int)btif_av_source.Peers().size());
+    /* if source device connected, don't connect sink device */
+    return (connected < max_connected_peers_) && btif_av_source.Peers().empty();
+  }
+
   return (connected < max_connected_peers_);
 }
 
@@ -1423,6 +1621,24 @@ void BtifAvSink::BtaHandleRegistered(uint8_t peer_id, tBTA_AV_HNDL bta_handle) {
   }
 }
 
+BtifAvPeer* BtifAvSink::popPeer(const RawAddress& peer_address) {
+  auto it = peers_.find(peer_address);
+  if (it == peers_.end()) return nullptr;
+  BtifAvPeer* peer = it->second;
+  peers_.erase(it);
+  LOG_INFO("%s: peer_address=%s, state=%d", __PRETTY_FUNCTION__,
+           ADDRESS_TO_LOGGABLE_CSTR(peer->PeerAddress()),
+           peer->StateMachine().StateId());
+  return peer;
+}
+
+void BtifAvSink::AddPeer(BtifAvPeer* peer) {
+  LOG_INFO("%s: peer_address=%s, state=%d", __PRETTY_FUNCTION__,
+           ADDRESS_TO_LOGGABLE_CSTR(peer->PeerAddress()),
+           peer->StateMachine().StateId());
+  peers_.insert(std::make_pair(peer->PeerAddress(), peer));
+}
+
 void BtifAvStateMachine::StateIdle::OnEnter() {
   BTIF_TRACE_DEBUG("%s: Peer %s", __PRETTY_FUNCTION__,
                    ADDRESS_TO_LOGGABLE_CSTR(peer_.PeerAddress()));
@@ -1432,7 +1648,7 @@ void BtifAvStateMachine::StateIdle::OnEnter() {
 
   // Stop A2DP if this is the active peer
   if (peer_.IsActivePeer() || peer_.ActivePeerAddress().IsEmpty()) {
-    btif_a2dp_on_idle();
+    btif_a2dp_on_idle(peer_.PeerAddress());
   }
 
   // Reset the active peer if this was the active peer and
@@ -1551,10 +1767,20 @@ bool BtifAvStateMachine::StateIdle::ProcessEvent(uint32_t event, void* p_data) {
       // Check whether connection is allowed
       if (peer_.IsSink()) {
         can_connect = btif_av_source.AllowedToConnect(peer_.PeerAddress());
-        if (!can_connect) src_disconnect_sink(peer_.PeerAddress());
+        if (!can_connect) {
+          if (btif_av_src_sink_coexist_enabled())
+            BTA_AvCloseRc(((tBTA_AV*)p_data)->rc_open.rc_handle);
+          else
+            src_disconnect_sink(peer_.PeerAddress());
+        }
       } else if (peer_.IsSource()) {
         can_connect = btif_av_sink.AllowedToConnect(peer_.PeerAddress());
-        if (!can_connect) sink_disconnect_src(peer_.PeerAddress());
+        if (!can_connect) {
+          if (btif_av_src_sink_coexist_enabled())
+            BTA_AvCloseRc(((tBTA_AV*)p_data)->rc_open.rc_handle);
+          else
+            sink_disconnect_src(peer_.PeerAddress());
+        }
       }
       if (!can_connect) {
         BTIF_TRACE_ERROR(
@@ -1563,14 +1789,27 @@ bool BtifAvStateMachine::StateIdle::ProcessEvent(uint32_t event, void* p_data) {
             __PRETTY_FUNCTION__, ADDRESS_TO_LOGGABLE_CSTR(peer_.PeerAddress()));
         break;
       }
-      if (btif_av_source.Enabled()) {
-        alarm_set_on_mloop(
-            peer_.AvOpenOnRcTimer(), BtifAvPeer::kTimeoutAvOpenOnRcMs,
-            btif_av_source_initiate_av_open_timer_timeout, &peer_);
-      } else if (btif_av_sink.Enabled()) {
-        alarm_set_on_mloop(peer_.AvOpenOnRcTimer(),
-                           BtifAvPeer::kTimeoutAvOpenOnRcMs,
-                           btif_av_sink_initiate_av_open_timer_timeout, &peer_);
+      /* if peer is source, then start timer for sink connect to src */
+      if (btif_av_src_sink_coexist_enabled()) {
+        if (peer_.IsSource()) {
+          alarm_set_on_mloop(
+              peer_.AvOpenOnRcTimer(), BtifAvPeer::kTimeoutAvOpenOnRcMs,
+              btif_av_sink_initiate_av_open_timer_timeout, &peer_);
+        } else {
+          alarm_set_on_mloop(
+              peer_.AvOpenOnRcTimer(), BtifAvPeer::kTimeoutAvOpenOnRcMs,
+              btif_av_source_initiate_av_open_timer_timeout, &peer_);
+        }
+      } else {
+        if (btif_av_source.Enabled()) {
+          alarm_set_on_mloop(
+              peer_.AvOpenOnRcTimer(), BtifAvPeer::kTimeoutAvOpenOnRcMs,
+              btif_av_source_initiate_av_open_timer_timeout, &peer_);
+        } else if (btif_av_sink.Enabled()) {
+          alarm_set_on_mloop(
+              peer_.AvOpenOnRcTimer(), BtifAvPeer::kTimeoutAvOpenOnRcMs,
+              btif_av_sink_initiate_av_open_timer_timeout, &peer_);
+        }
       }
       if (event == BTA_AV_RC_OPEN_EVT) {
         btif_rc_handler(event, (tBTA_AV*)p_data);
@@ -1610,6 +1849,44 @@ bool BtifAvStateMachine::StateIdle::ProcessEvent(uint32_t event, void* p_data) {
 
       if (p_bta_data->open.status == BTA_AV_SUCCESS) {
         peer_.SetEdr(p_bta_data->open.edr);
+        if (btif_av_src_sink_coexist_enabled()) {
+          BTIF_TRACE_DEBUG("%s: Peer %s sep=%d, open_sep=%d",
+                           __PRETTY_FUNCTION__,
+                           ADDRESS_TO_LOGGABLE_CSTR(peer_.PeerAddress()),
+                           peer_.PeerSep(), p_bta_data->open.sep);
+          /* if peer is wrong sep type, move it to BtifAvSxxx */
+          if (peer_.PeerSep() == AVDT_TSEP_SNK) {
+            BTIF_TRACE_DEBUG("set source invalid_peer_check as false");
+            btif_av_source.SetInvalidPeerCheck(false);
+          } else {
+            BTIF_TRACE_DEBUG("set sink invalid_peer_check as false");
+            btif_av_sink.SetInvalidPeerCheck(false);
+          }
+          if (peer_.PeerSep() != p_bta_data->open.sep) {
+            BtifAvPeer* tmp_peer = nullptr;
+            if (peer_.PeerSep() == AVDT_TSEP_SNK) {
+              tmp_peer = btif_av_source.popPeer(peer_.PeerAddress());
+
+              if (peer_.PeerAddress() != tmp_peer->PeerAddress())
+                BTIF_TRACE_ERROR("error, not same peer");
+
+              btif_av_sink.AddPeer(tmp_peer);
+            } else {
+              tmp_peer = btif_av_sink.popPeer(peer_.PeerAddress());
+
+              if (peer_.PeerAddress() != tmp_peer->PeerAddress())
+                BTIF_TRACE_ERROR("error, not same peer");
+
+              btif_av_source.AddPeer(tmp_peer);
+            }
+            peer_.SetSep(p_bta_data->open.sep);
+          }
+          if (btif_rc_is_connected_peer(peer_.PeerAddress())) {
+            BTIF_TRACE_DEBUG("%s, AVRCP connected, update avrc sep", __func__);
+            BTA_AvSetPeerSep(peer_.PeerAddress(), peer_.PeerSep());
+          }
+          btif_rc_check_pending_cmd(p_bta_data->open.bd_addr);
+        }
         CHECK(peer_.PeerSep() == p_bta_data->open.sep);
 
         can_connect = peer_.IsSink()
@@ -1706,6 +1983,10 @@ void BtifAvStateMachine::StateOpening::OnEnter() {
                    ADDRESS_TO_LOGGABLE_CSTR(peer_.PeerAddress()));
 
   // Inform the application that we are entering connecting state
+  if (btif_av_both_enable()) {
+    /* if peer connect to us, don't know which role it is */
+    if (!peer_.SelfInitiatedConnection()) return;
+  }
   btif_report_connection_state(peer_.PeerAddress(),
                                BTAV_CONNECTION_STATE_CONNECTING,
                                bt_status_t::BT_STATUS_SUCCESS, BTA_AV_SUCCESS);
@@ -1781,7 +2062,63 @@ bool BtifAvStateMachine::StateOpening::ProcessEvent(uint32_t event,
       if (p_bta_data->open.status == BTA_AV_SUCCESS) {
         av_state = BtifAvStateMachine::kStateOpened;
         peer_.SetEdr(p_bta_data->open.edr);
+        if (btif_av_src_sink_coexist_enabled()) {
+          BTIF_TRACE_DEBUG("%s: Peer %s sep=%d, open_sep=%d",
+                           __PRETTY_FUNCTION__,
+                           ADDRESS_TO_LOGGABLE_CSTR(peer_.PeerAddress()),
+                           peer_.PeerSep(), p_bta_data->open.sep);
+          /* if peer is wrong sep type, move it to BtifAvSxxx */
+          if (peer_.PeerSep() == AVDT_TSEP_SNK) {
+            BTIF_TRACE_DEBUG("set source invalid_peer_check as false");
+            btif_av_source.SetInvalidPeerCheck(false);
+          } else {
+            BTIF_TRACE_DEBUG("set sink invalid_peer_check as false");
+            btif_av_sink.SetInvalidPeerCheck(false);
+          }
+          if (peer_.PeerSep() != p_bta_data->open.sep) {
+            BtifAvPeer* tmp_peer = nullptr;
+            if (peer_.PeerSep() == AVDT_TSEP_SNK) {
+              tmp_peer = btif_av_source.popPeer(peer_.PeerAddress());
+
+              if (peer_.PeerAddress() != tmp_peer->PeerAddress())
+                BTIF_TRACE_ERROR("error, not same peer");
+
+              btif_av_sink.AddPeer(tmp_peer);
+            } else {
+              tmp_peer = btif_av_sink.popPeer(peer_.PeerAddress());
+
+              if (peer_.PeerAddress() != tmp_peer->PeerAddress())
+                BTIF_TRACE_ERROR("error, not same peer");
+
+              btif_av_source.AddPeer(tmp_peer);
+            }
+            peer_.SetSep(p_bta_data->open.sep);
+          }
+          if (btif_rc_is_connected_peer(peer_.PeerAddress())) {
+            BTIF_TRACE_DEBUG("%s, AVRCP connected, update avrc sep", __func__);
+            BTA_AvSetPeerSep(peer_.PeerAddress(), peer_.PeerSep());
+          }
+          btif_rc_check_pending_cmd(p_bta_data->open.bd_addr);
+        }
         CHECK(peer_.PeerSep() == p_bta_data->open.sep);
+        /** normally it can be checked in IDLE PENDING/CONNECT_REQ, in case:
+         * 1 speacker connected to DUT and phone connect DUT, because
+         * default
+         * connect req is as SINK peer. only at here, we can know which
+         * role
+         *  it is.@{ */
+        if (btif_av_src_sink_coexist_enabled()) {
+          bool can_connect = true;
+          if (peer_.IsSink()) {
+            can_connect = btif_av_source.AllowedToConnect(peer_.PeerAddress());
+            if (!can_connect) src_disconnect_sink(peer_.PeerAddress());
+          } else if (peer_.IsSource()) {
+            can_connect = btif_av_sink.AllowedToConnect(peer_.PeerAddress());
+            if (!can_connect) sink_disconnect_src(peer_.PeerAddress());
+          }
+        }
+        /** @} */
+
         // Report the connection state to the application
         btif_report_connection_state(
             peer_.PeerAddress(), BTAV_CONNECTION_STATE_CONNECTED,
@@ -1824,7 +2161,9 @@ bool BtifAvStateMachine::StateOpening::ProcessEvent(uint32_t event,
       } else if (peer_.IsSource() &&
                  (p_bta_data->open.status == BTA_AV_SUCCESS)) {
         // Bring up AVRCP connection as well
-        BTA_AvOpenRc(peer_.BtaHandle());
+        if (btif_av_src_sink_coexist_enabled() &&
+            btif_av_sink.AllowedToConnect(peer_.PeerAddress()))
+          BTA_AvOpenRc(peer_.BtaHandle());
       }
       if (peer_.SelfInitiatedConnection()) {
         btif_queue_advance();
@@ -1834,6 +2173,13 @@ bool BtifAvStateMachine::StateOpening::ProcessEvent(uint32_t event,
     case BTIF_AV_SINK_CONFIG_REQ_EVT: {
       const btif_av_sink_config_req_t* p_config_req =
           static_cast<const btif_av_sink_config_req_t*>(p_data);
+      /* before this point, we don't know it's role, actually peer is source */
+      if (btif_av_both_enable()) {
+        btif_av_report_sink_audio_config_state(p_config_req->peer_address,
+                                               p_config_req->sample_rate,
+                                               p_config_req->channel_count);
+        break;
+      }
       if (peer_.IsSource()) {
         btif_av_report_sink_audio_config_state(p_config_req->peer_address,
                                                p_config_req->sample_rate,
@@ -2562,6 +2908,24 @@ static void btif_report_connection_state(const RawAddress& peer_address,
                                          uint8_t error_code) {
   LOG_INFO("%s: peer_address=%s state=%d", __func__,
            ADDRESS_TO_LOGGABLE_CSTR(peer_address), state);
+  if (btif_av_src_sink_coexist_enabled() && btif_av_both_enable()) {
+    BtifAvPeer* peer = btif_av_find_peer(peer_address);
+    if (peer == nullptr) {
+      LOG_ERROR("%s: peer is null", __func__);
+      return;
+    }
+
+    if (peer->IsSink()) {
+      do_in_jni_thread(
+          FROM_HERE, base::Bind(btif_av_source.Callbacks()->connection_state_cb,
+                                peer_address, state, btav_error_t{}));
+    } else if (peer->IsSource()) {
+      do_in_jni_thread(FROM_HERE,
+                       base::Bind(btif_av_sink.Callbacks()->connection_state_cb,
+                                  peer_address, state, btav_error_t{}));
+    }
+    return;
+  }
 
   if (btif_av_source.Enabled()) {
     do_in_jni_thread(
@@ -2592,6 +2956,19 @@ static void btif_report_audio_state(const RawAddress& peer_address,
   LOG_INFO("%s: peer_address=%s state=%d", __func__,
            ADDRESS_TO_LOGGABLE_CSTR(peer_address), state);
 
+  if (btif_av_both_enable()) {
+    BtifAvPeer* peer = btif_av_find_peer(peer_address);
+    if (peer->IsSink()) {
+      do_in_jni_thread(FROM_HERE,
+                       base::Bind(btif_av_source.Callbacks()->audio_state_cb,
+                                  peer_address, state));
+    } else if (peer->IsSource()) {
+      do_in_jni_thread(FROM_HERE,
+                       base::Bind(btif_av_sink.Callbacks()->audio_state_cb,
+                                  peer_address, state));
+    }
+    return;
+  }
   if (btif_av_source.Enabled()) {
     do_in_jni_thread(FROM_HERE,
                      base::Bind(btif_av_source.Callbacks()->audio_state_cb,
@@ -2693,6 +3070,84 @@ static void btif_av_query_mandatory_codec_priority(
   }
 }
 
+static BtifAvPeer* btif_av_handle_both_peer(uint8_t peer_sep,
+                                            const RawAddress& peer_address,
+                                            tBTA_AV_HNDL bta_handle) {
+  BtifAvPeer* peer = nullptr;
+
+  if (peer_address != RawAddress::kEmpty) {
+    if (btif_av_both_enable()) {
+      peer = btif_av_find_peer(peer_address);
+      /* if no this peer, default it's sink device */
+      if (peer == nullptr) {
+        if (peer_sep == AVDT_TSEP_SRC) {
+          BTIF_TRACE_DEBUG("%s: peer_sep(%d), create a new source peer",
+                           __func__, peer_sep);
+          peer = btif_av_sink.FindOrCreatePeer(peer_address, bta_handle);
+        } else if (peer_sep == AVDT_TSEP_SNK) {
+          BTIF_TRACE_DEBUG("%s: peer_sep(%d), create a new sink peer", __func__,
+                           peer_sep);
+          peer = btif_av_source.FindOrCreatePeer(peer_address, bta_handle);
+        } else {
+          btif_av_source.SetInvalidPeerCheck(true);
+          if (!btif_av_source.Peers().empty()) {
+            BTIF_TRACE_DEBUG(
+                "%s: peer_sep invalid, and already has sink peer,"
+                " so try create a new sink peer",
+                __func__);
+            peer = btif_av_source.FindOrCreatePeer(peer_address, bta_handle);
+          } else if (!btif_av_sink.Peers().empty()) {
+            BTIF_TRACE_DEBUG(
+                "%s: peer_sep invalid, and already has source peer,"
+                " so try create a new source peer",
+                __func__);
+            peer = btif_av_sink.FindOrCreatePeer(peer_address, bta_handle);
+          } else {
+            BTIF_TRACE_DEBUG(
+                "%s: peer_sep invalid, and no active peer,"
+                " so try create a new sink peer",
+                __func__);
+            peer = btif_av_source.FindOrCreatePeer(peer_address, bta_handle);
+          }
+        }
+      }
+    } else {
+      if (peer_sep == AVDT_TSEP_SNK) {
+        BTIF_TRACE_DEBUG(
+            "%s: peer_sep(%d), only init src create a new source peer",
+            __func__, peer_sep);
+        peer = btif_av_source.FindOrCreatePeer(peer_address, bta_handle);
+      } else if (peer_sep == AVDT_TSEP_SRC) {
+        BTIF_TRACE_DEBUG(
+            "%s: peer_sep(%d), only init sink create a new source peer",
+            __func__, peer_sep);
+        peer = btif_av_sink.FindOrCreatePeer(peer_address, bta_handle);
+      }
+    }
+    if (peer == NULL && bta_handle != 0) {
+      if (peer_sep == AVDT_TSEP_SNK) {
+        peer = btif_av_source.FindPeerByHandle(bta_handle);
+      } else if (peer_sep == AVDT_TSEP_SRC) {
+        peer = btif_av_sink.FindPeerByHandle(bta_handle);
+      }
+      BTIF_TRACE_DEBUG("%s:peer is check 3", __func__);
+    }
+  } else if (bta_handle != 0) {
+    if (peer_sep == AVDT_TSEP_INVALID) {
+      peer = btif_av_source.FindPeerByHandle(bta_handle);
+      /* if no this peer, default it's sink device */
+      if (peer == nullptr) {
+        peer = btif_av_sink.FindPeerByHandle(bta_handle);
+      }
+    } else if (peer_sep == AVDT_TSEP_SNK) {
+      peer = btif_av_source.FindPeerByHandle(bta_handle);
+    } else if (peer_sep == AVDT_TSEP_SRC) {
+      peer = btif_av_sink.FindPeerByHandle(bta_handle);
+    }
+  }
+  return peer;
+}
+
 /**
  * Process BTIF or BTA AV or BTA AVRCP events. The processing is done on the
  * JNI thread.
@@ -2714,17 +3169,21 @@ static void btif_av_handle_event(uint8_t peer_sep,
   BtifAvPeer* peer = nullptr;
 
   // Find the peer
-  if (peer_address != RawAddress::kEmpty) {
-    if (peer_sep == AVDT_TSEP_SNK) {
-      peer = btif_av_source.FindOrCreatePeer(peer_address, bta_handle);
-    } else if (peer_sep == AVDT_TSEP_SRC) {
-      peer = btif_av_sink.FindOrCreatePeer(peer_address, bta_handle);
-    }
-  } else if (bta_handle != kBtaHandleUnknown) {
-    if (peer_sep == AVDT_TSEP_SNK) {
-      peer = btif_av_source.FindPeerByHandle(bta_handle);
-    } else if (peer_sep == AVDT_TSEP_SRC) {
-      peer = btif_av_sink.FindPeerByHandle(bta_handle);
+  if (btif_av_src_sink_coexist_enabled()) {
+    peer = btif_av_handle_both_peer(peer_sep, peer_address, bta_handle);
+  } else {
+    if (peer_address != RawAddress::kEmpty) {
+      if (peer_sep == AVDT_TSEP_SNK) {
+        peer = btif_av_source.FindOrCreatePeer(peer_address, bta_handle);
+      } else if (peer_sep == AVDT_TSEP_SRC) {
+        peer = btif_av_sink.FindOrCreatePeer(peer_address, bta_handle);
+      }
+    } else if (bta_handle != kBtaHandleUnknown) {
+      if (peer_sep == AVDT_TSEP_SNK) {
+        peer = btif_av_source.FindPeerByHandle(bta_handle);
+      } else if (peer_sep == AVDT_TSEP_SRC) {
+        peer = btif_av_sink.FindPeerByHandle(bta_handle);
+      }
     }
   }
   if (peer == nullptr) {
@@ -2769,11 +3228,18 @@ static void btif_av_handle_bta_av_event(uint8_t peer_sep,
       return;  // Nothing to do
     }
     case BTA_AV_REGISTER_EVT: {
-      const tBTA_AV_REGISTER& registr = p_data->registr;
-      bta_handle = registr.hndl;
-      uint8_t peer_id = registr.app_id;  // The PeerId is used as AppId
-      LOG_DEBUG("Register bta_handle=0x%x app_id=%d", bta_handle,
-                registr.app_id);
+      const tBTA_AV_REGISTER& reg = p_data->reg;
+      bta_handle = reg.hndl;
+      uint8_t peer_id = reg.app_id;  // The PeerId is used as AppId
+      LOG_DEBUG("Register bta_handle=0x%x app_id=%d", bta_handle, reg.app_id);
+      if (btif_av_src_sink_coexist_enabled()) {
+        if (peer_sep == AVDT_TSEP_INVALID) {
+          if (reg.peer_sep == AVDT_TSEP_SNK)
+            peer_sep = AVDT_TSEP_SNK;
+          else
+            peer_sep = AVDT_TSEP_SRC;
+        }
+      }
       if (peer_sep == AVDT_TSEP_SNK) {
         btif_av_source.BtaHandleRegistered(peer_id, bta_handle);
       } else if (peer_sep == AVDT_TSEP_SRC) {
@@ -2841,7 +3307,26 @@ static void btif_av_handle_bta_av_event(uint8_t peer_sep,
     case BTA_AV_REMOTE_RSP_EVT:
     case BTA_AV_VENDOR_CMD_EVT:
     case BTA_AV_VENDOR_RSP_EVT:
-    case BTA_AV_META_MSG_EVT:
+    case BTA_AV_META_MSG_EVT: {
+      if (btif_av_src_sink_coexist_enabled()) {
+        if (peer_sep == AVDT_TSEP_INVALID) {
+          const tBTA_AV_REMOTE_CMD& rc_rmt_cmd = p_data->remote_cmd;
+          btif_rc_get_addr_by_handle(rc_rmt_cmd.rc_handle, peer_address);
+          if (peer_address == RawAddress::kEmpty) {
+            peer_address = btif_av_source.ActivePeer();
+            if (peer_address == RawAddress::kEmpty) {
+              peer_address = btif_av_sink.ActivePeer();
+            }
+          }
+        } else if (peer_sep == AVDT_TSEP_SNK) {
+          peer_address = btif_av_source.ActivePeer();
+        } else if (peer_sep == AVDT_TSEP_SRC) {
+          peer_address = btif_av_sink.ActivePeer();
+        }
+        break;
+      } else
+        FALLTHROUGH_INTENDED;
+    }
     case BTA_AV_OFFLOAD_START_RSP_EVT: {
       // TODO: Might be wrong - this code will be removed once those
       // events are received from the AVRCP module.
@@ -2889,6 +3374,18 @@ static void btif_av_handle_bta_av_event(uint8_t peer_sep,
   btif_av_handle_event(peer_sep, peer_address, bta_handle, btif_av_event);
 }
 
+bool btif_av_both_enable(void) {
+  return (btif_av_sink.Enabled() && btif_av_source.Enabled());
+}
+
+bool btif_av_src_sink_coexist_enabled(void) {
+#ifdef OS_ANDROID
+  return android::sysprop::bluetooth::A2dp::src_sink_coexist().value_or(false);
+#else
+  return false;
+#endif
+}
+
 static void bta_av_source_callback(tBTA_AV_EVT event, tBTA_AV* p_data) {
   BtifAvEvent btif_av_event(event, p_data, sizeof(tBTA_AV));
   BTIF_TRACE_EVENT("%s: event=%s", __func__, btif_av_event.ToString().c_str());
@@ -2905,6 +3402,22 @@ static void bta_av_sink_callback(tBTA_AV_EVT event, tBTA_AV* p_data) {
                                AVDT_TSEP_SRC /* peer_sep */, btif_av_event));
 }
 
+static void bta_av_event_callback(tBTA_AV_EVT event, tBTA_AV* p_data) {
+  if (btif_av_both_enable()) {
+    BtifAvEvent btif_av_event(event, p_data, sizeof(tBTA_AV));
+    do_in_main_thread(
+        FROM_HERE, base::Bind(&btif_av_handle_bta_av_event,
+                              AVDT_TSEP_INVALID /* peer_sep */, btif_av_event));
+    return;
+  }
+
+  if (btif_av_is_sink_enabled()) {
+    return bta_av_sink_callback(event, p_data);
+  }
+
+  return bta_av_source_callback(event, p_data);
+}
+
 // TODO: All processing should be done on the JNI thread
 static void bta_av_sink_media_callback(const RawAddress& peer_address,
                                        tBTA_AV_EVT event,
@@ -2993,6 +3506,15 @@ static void update_audio_track_gain(float gain) {
 static bt_status_t connect_int(RawAddress* peer_address, uint16_t uuid) {
   BTIF_TRACE_EVENT("%s: peer_address=%s uuid=0x%x", __func__,
                    ADDRESS_TO_LOGGABLE_CSTR(*peer_address), uuid);
+  if (btif_av_both_enable()) {
+    const RawAddress tmp = *peer_address;
+    if (uuid == UUID_SERVCLASS_AUDIO_SOURCE) {
+      btif_av_source_dispatch_sm_event(tmp, BTIF_AV_CONNECT_REQ_EVT);
+    } else if (uuid == UUID_SERVCLASS_AUDIO_SINK) {
+      btif_av_sink_dispatch_sm_event(tmp, BTIF_AV_CONNECT_REQ_EVT);
+    }
+    return BT_STATUS_SUCCESS;
+  }
 
   auto connection_task = [](RawAddress* peer_address, uint16_t uuid) {
     BtifAvPeer* peer = nullptr;
@@ -3035,16 +3557,20 @@ static void set_active_peer_int(uint8_t peer_sep,
                    ADDRESS_TO_LOGGABLE_CSTR(peer_address));
   BtifAvPeer* peer = nullptr;
   if (peer_sep == AVDT_TSEP_SNK) {
-    if (!btif_av_source.SetActivePeer(peer_address,
-                                      std::move(peer_ready_promise))) {
+    if (!btif_av_src_sink_coexist_enabled() || (btif_av_src_sink_coexist_enabled() &&
+      btif_av_both_enable() && (btif_av_sink.FindPeer(peer_address) == nullptr))) {
+      btif_av_source.SetActivePeer(peer_address,
+                                      std::move(peer_ready_promise));
       BTIF_TRACE_ERROR("%s: Error setting %s as active Sink peer", __func__,
                        ADDRESS_TO_LOGGABLE_CSTR(peer_address));
     }
     return;
   }
   if (peer_sep == AVDT_TSEP_SRC) {
-    if (!btif_av_sink.SetActivePeer(peer_address,
-                                    std::move(peer_ready_promise))) {
+    if (!btif_av_src_sink_coexist_enabled() || (btif_av_src_sink_coexist_enabled() &&
+      btif_av_both_enable() && (btif_av_source.FindPeer(peer_address) == nullptr))) {
+      btif_av_sink.SetActivePeer(peer_address,
+                                    std::move(peer_ready_promise));
       BTIF_TRACE_ERROR("%s: Error setting %s as active Source peer", __func__,
                        ADDRESS_TO_LOGGABLE_CSTR(peer_address));
     }
@@ -3246,6 +3772,8 @@ RawAddress btif_av_sink_active_peer(void) { return btif_av_sink.ActivePeer(); }
 
 bool btif_av_is_sink_enabled(void) { return btif_av_sink.Enabled(); }
 
+bool btif_av_is_source_enabled(void) { return btif_av_source.Enabled(); }
+
 void btif_av_stream_start(void) {
   LOG_INFO("%s", __func__);
   btif_av_source_dispatch_sm_event(btif_av_source_active_peer(),
@@ -3419,7 +3947,12 @@ bt_status_t btif_av_source_execute_service(bool enable) {
       features |= BTA_AV_FEAT_RCCT | BTA_AV_FEAT_ADV_CTRL | BTA_AV_FEAT_BROWSE;
     }
 
-    BTA_AvEnable(features, bta_av_source_callback);
+    if (btif_av_src_sink_coexist_enabled()) {
+      features |= BTA_AV_FEAT_SRC;
+      BTA_AvEnable(features, bta_av_event_callback);
+    } else {
+      BTA_AvEnable(features, bta_av_source_callback);
+    }
     btif_av_source.RegisterAllBtaHandles();
     return BT_STATUS_SUCCESS;
   }
@@ -3447,7 +3980,10 @@ bt_status_t btif_av_sink_execute_service(bool enable) {
       features |= BTA_AV_FEAT_DELAY_RPT;
     }
 
-    BTA_AvEnable(features, bta_av_sink_callback);
+    if (btif_av_src_sink_coexist_enabled())
+      BTA_AvEnable(features, bta_av_event_callback);
+    else
+      BTA_AvEnable(features, bta_av_sink_callback);
     btif_av_sink.RegisterAllBtaHandles();
     return BT_STATUS_SUCCESS;
   }
@@ -3563,6 +4099,18 @@ void btif_av_acl_disconnected(const RawAddress& peer_address) {
   // Inform the application that ACL is disconnected and move to idle state
   LOG_INFO("%s: Peer %s : ACL Disconnected", __func__,
            ADDRESS_TO_LOGGABLE_CSTR(peer_address));
+  if (btif_av_both_enable()) {
+    BtifAvPeer* peer = btif_av_find_peer(peer_address);
+    if (peer != nullptr) {
+      if (peer->IsSource()) {
+        btif_av_sink_dispatch_sm_event(peer_address, BTIF_AV_ACL_DISCONNECTED);
+      } else {
+        btif_av_source_dispatch_sm_event(peer_address,
+                                         BTIF_AV_ACL_DISCONNECTED);
+      }
+    }
+    return;
+  }
 
   if (btif_av_source.Enabled()) {
     btif_av_source_dispatch_sm_event(peer_address, BTIF_AV_ACL_DISCONNECTED);
@@ -3709,3 +4257,73 @@ void btif_av_set_low_latency(bool is_low_latency) {
                                           btif_av_source_active_peer(),
                                           kBtaHandleUnknown, btif_av_event));
 }
+
+static void btif_av_sink_delete_active_peer(void) {
+  btif_av_sink.DeleteActivePeer();
+}
+
+static void btif_av_source_delete_active_peer(void) {
+  btif_av_source.DeleteActivePeer();
+}
+
+bool btif_av_is_connected_addr(const RawAddress& peer_address) {
+  BtifAvPeer* peer = btif_av_find_peer(peer_address);
+  if (peer == nullptr) {
+    BTIF_TRACE_WARNING("%s: No active peer found", __func__);
+    return false;
+  }
+
+  bool connected = peer->IsConnected();
+  BTIF_TRACE_DEBUG("%s: Peer %s is %s", __func__,
+                   ADDRESS_TO_LOGGABLE_CSTR(peer->PeerAddress()),
+                   (connected) ? "connected" : "not connected");
+  return connected;
+}
+
+bool btif_av_peer_is_connected_sink(const RawAddress& peer_address) {
+  BtifAvPeer* peer = btif_av_source_find_peer(peer_address);
+  if (peer == nullptr) {
+    BTIF_TRACE_WARNING("%s: No active peer found", __func__);
+    return false;
+  }
+
+  bool connected = peer->IsConnected();
+  BTIF_TRACE_DEBUG("%s: Peer %s is %s", __func__,
+                   ADDRESS_TO_LOGGABLE_CSTR(peer->PeerAddress()),
+                   (connected) ? "connected" : "not connected");
+  return connected;
+}
+
+bool btif_av_peer_is_connected_source(const RawAddress& peer_address) {
+  BtifAvPeer* peer = btif_av_sink_find_peer(peer_address);
+  if (peer == nullptr) {
+    BTIF_TRACE_WARNING("%s: No active peer found", __func__);
+    return false;
+  }
+
+  bool connected = peer->IsConnected();
+  BTIF_TRACE_DEBUG("%s: Peer %s is %s", __func__,
+                   ADDRESS_TO_LOGGABLE_CSTR(peer->PeerAddress()),
+                   (connected) ? "connected" : "not connected");
+  return connected;
+}
+
+bool btif_av_peer_is_sink(const RawAddress& peer_address) {
+  BtifAvPeer* peer = btif_av_source_find_peer(peer_address);
+  if (peer == nullptr) {
+    BTIF_TRACE_WARNING("%s: No active peer found", __func__);
+    return false;
+  }
+
+  return true;
+}
+
+bool btif_av_peer_is_source(const RawAddress& peer_address) {
+  BtifAvPeer* peer = btif_av_sink_find_peer(peer_address);
+  if (peer == nullptr) {
+    BTIF_TRACE_WARNING("%s: No active peer found", __func__);
+    return false;
+  }
+
+  return true;
+}
diff --git a/system/btif/src/btif_rc.cc b/system/btif/src/btif_rc.cc
index e3812edc8286fcda42352e4f2442f6f5ab3174ad..c5c00eb1e16a2bdb60345be2a867e749bbf7b617 100644
--- a/system/btif/src/btif_rc.cc
+++ b/system/btif/src/btif_rc.cc
@@ -26,6 +26,7 @@
 
 #include "btif_rc.h"
 
+#include <base/logging.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <hardware/bluetooth.h>
@@ -40,6 +41,7 @@
 #include "avrc_defs.h"
 #include "bta_api.h"
 #include "bta_av_api.h"
+#include "btif/avrcp/avrcp_service.h"
 #include "btif_av.h"
 #include "btif_common.h"
 #include "btif_util.h"
@@ -54,8 +56,6 @@
 #include "stack/include/bt_hdr.h"
 #include "types/raw_address.h"
 
-#include <base/logging.h>
-
 #define RC_INVALID_TRACK_ID (0xFFFFFFFFFFFFFFFFULL)
 
 /*****************************************************************************
@@ -220,8 +220,15 @@ typedef struct {
   uint64_t rc_playing_uid;
   bool rc_procedure_complete;
   rc_transaction_set_t transaction_set;
+  tBTA_AV_FEAT peer_ct_features;
+  tBTA_AV_FEAT peer_tg_features;
+  uint8_t launch_cmd_pending; /* true: getcap/regvolume */
 } btif_rc_device_cb_t;
 
+#define RC_PENDING_ACT_GET_CAP (1 << 0)
+#define RC_PENDING_ACT_REG_VOL (1 << 1)
+#define RC_PENDING_ACT_REPORT_CONN (1 << 2)
+
 typedef struct {
   std::mutex lock;
   btif_rc_device_cb_t rc_multi_cb[BTIF_RC_NUM_CONN];
@@ -402,6 +409,23 @@ static const uint8_t media_attr_list_no_cover_art_size =
  *****************************************************************************/
 bool check_cod(const RawAddress& remote_bdaddr, uint32_t cod);
 
+void btif_rc_get_addr_by_handle(uint8_t handle, RawAddress& rc_addr) {
+  BTIF_TRACE_DEBUG("%s: handle: 0x%x", __func__, handle);
+  for (int idx = 0; idx < BTIF_RC_NUM_CONN; idx++) {
+    if ((btif_rc_cb.rc_multi_cb[idx].rc_state !=
+         BTRC_CONNECTION_STATE_DISCONNECTED) &&
+        (btif_rc_cb.rc_multi_cb[idx].rc_handle == handle)) {
+      BTIF_TRACE_DEBUG("%s: btif_rc_cb.rc_multi_cb[idx].rc_handle: 0x%x",
+                       __func__, btif_rc_cb.rc_multi_cb[idx].rc_handle);
+      rc_addr = btif_rc_cb.rc_multi_cb[idx].rc_addr;
+      return;
+    }
+  }
+  BTIF_TRACE_ERROR("%s: returning NULL", __func__);
+  rc_addr = RawAddress::kEmpty;
+  return;
+}
+
 /*****************************************************************************
  *  Functions
  *****************************************************************************/
@@ -442,6 +466,9 @@ void initialize_device(btif_rc_device_cb_t* p_dev) {
   p_dev->rc_features_processed = false;
   p_dev->rc_playing_uid = 0;
   p_dev->rc_procedure_complete = false;
+  p_dev->peer_ct_features = 0;
+  p_dev->peer_tg_features = 0;
+  p_dev->launch_cmd_pending = 0;
 
   // Leaving the value of the default constructor for the lbllock mutex is fine
   // but we still need to clear out the transaction label set
@@ -531,7 +558,79 @@ void fill_avrc_attr_entry(tAVRC_ATTR_ENTRY* attr_vals, int num_attrs,
 
 void rc_cleanup_sent_cmd(void* p_data) { BTIF_TRACE_DEBUG("%s: ", __func__); }
 
+void handle_rc_ctrl_features_all(btif_rc_device_cb_t* p_dev) {
+  if (!(p_dev->peer_tg_features & BTA_AV_FEAT_RCTG) &&
+      (!(p_dev->peer_tg_features & BTA_AV_FEAT_RCCT) ||
+       !(p_dev->peer_tg_features & BTA_AV_FEAT_ADV_CTRL))) {
+    return;
+  }
+
+  int rc_features = 0;
+
+  BTIF_TRACE_DEBUG(
+      "%s: peer_tg_features: 0x%x, rc_features_processed=%d, connected=%d, "
+      "peer_is_src:%d",
+      __func__, p_dev->peer_tg_features, p_dev->rc_features_processed,
+      btif_av_is_connected_addr(p_dev->rc_addr),
+      btif_av_peer_is_source(p_dev->rc_addr));
+
+  if ((p_dev->peer_tg_features & BTA_AV_FEAT_ADV_CTRL) &&
+      (p_dev->peer_tg_features & BTA_AV_FEAT_RCCT)) {
+    rc_features |= BTRC_FEAT_ABSOLUTE_VOLUME;
+  }
+
+  if ((p_dev->peer_tg_features & BTA_AV_FEAT_METADATA) &&
+      (p_dev->peer_tg_features & BTA_AV_FEAT_VENDOR) &&
+      (p_dev->rc_features_processed != true)) {
+    rc_features |= BTRC_FEAT_METADATA;
+
+    /* Mark rc features processed to avoid repeating
+     * the AVRCP procedure every time on receiving this
+     * update.
+     */
+    p_dev->rc_features_processed = true;
+  }
+
+  if (btif_av_is_connected_addr(p_dev->rc_addr)) {
+    if (btif_av_peer_is_source(p_dev->rc_addr)) {
+      p_dev->rc_features = p_dev->peer_tg_features;
+      if ((p_dev->peer_tg_features & BTA_AV_FEAT_METADATA) &&
+          (p_dev->peer_tg_features & BTA_AV_FEAT_VENDOR)) {
+        getcapabilities_cmd(AVRC_CAP_COMPANY_ID, p_dev);
+      }
+    }
+  } else {
+    BTIF_TRACE_DEBUG("%s: %s is not connected, pending", __func__,
+                     ADDRESS_TO_LOGGABLE_CSTR(p_dev->rc_addr));
+    p_dev->launch_cmd_pending |=
+        (RC_PENDING_ACT_GET_CAP | RC_PENDING_ACT_REG_VOL);
+  }
+
+  /* Add browsing feature capability */
+  if (p_dev->peer_tg_features & BTA_AV_FEAT_BROWSE) {
+    rc_features |= BTRC_FEAT_BROWSE;
+  }
+
+  /* Add cover art feature capability */
+  if (p_dev->peer_tg_features & BTA_AV_FEAT_COVER_ARTWORK) {
+    rc_features |= BTRC_FEAT_COVER_ARTWORK;
+  }
+
+  if (bt_rc_ctrl_callbacks != NULL) {
+    BTIF_TRACE_DEBUG("%s: Update rc features to CTRL: %d", __func__,
+                     rc_features);
+    do_in_jni_thread(FROM_HERE,
+                     base::Bind(bt_rc_ctrl_callbacks->getrcfeatures_cb,
+                                p_dev->rc_addr, rc_features));
+  }
+}
+
 void handle_rc_ctrl_features(btif_rc_device_cb_t* p_dev) {
+  if (btif_av_src_sink_coexist_enabled() && btif_av_both_enable()) {
+    handle_rc_ctrl_features_all(p_dev);
+    return;
+  }
+
   if (!(p_dev->rc_features & BTA_AV_FEAT_RCTG) &&
       (!(p_dev->rc_features & BTA_AV_FEAT_RCCT) ||
        !(p_dev->rc_features & BTA_AV_FEAT_ADV_CTRL))) {
@@ -575,14 +674,52 @@ void handle_rc_ctrl_features(btif_rc_device_cb_t* p_dev) {
   do_in_jni_thread(FROM_HERE, base::Bind(bt_rc_ctrl_callbacks->getrcfeatures_cb,
                                          p_dev->rc_addr, rc_features));
 }
+void btif_rc_check_pending_cmd(const RawAddress& peer_address) {
+  btif_rc_device_cb_t* p_dev = NULL;
+  p_dev = btif_rc_get_device_by_bda(peer_address);
+  if (p_dev == NULL) {
+    BTIF_TRACE_ERROR("%s: p_dev NULL", __func__);
+    return;
+  }
+
+  BTIF_TRACE_DEBUG(
+      "%s: launch_cmd_pending=%d, rc_connected=%d, peer_ct_features=0x%x, "
+      "peer_tg_features=0x%x",
+      __FUNCTION__, p_dev->launch_cmd_pending, p_dev->rc_connected,
+      p_dev->peer_ct_features, p_dev->peer_tg_features);
+  if (p_dev->launch_cmd_pending && p_dev->rc_connected) {
+    if ((p_dev->launch_cmd_pending & RC_PENDING_ACT_REG_VOL) &&
+        btif_av_peer_is_sink(p_dev->rc_addr)) {
+      if (bluetooth::avrcp::AvrcpService::Get() != nullptr) {
+        bluetooth::avrcp::AvrcpService::Get()->RegisterVolChanged(peer_address);
+      }
+    }
+    if ((p_dev->launch_cmd_pending & RC_PENDING_ACT_GET_CAP) &&
+        btif_av_peer_is_source(p_dev->rc_addr)) {
+      p_dev->rc_features = p_dev->peer_tg_features;
+      getcapabilities_cmd(AVRC_CAP_COMPANY_ID, p_dev);
+    }
+    if ((p_dev->launch_cmd_pending & RC_PENDING_ACT_REPORT_CONN) &&
+        btif_av_peer_is_source(p_dev->rc_addr)) {
+      if (bt_rc_ctrl_callbacks != NULL) {
+        do_in_jni_thread(FROM_HERE,
+                         base::Bind(bt_rc_ctrl_callbacks->connection_state_cb,
+                                    true, false, p_dev->rc_addr));
+      }
+    }
+  }
+  p_dev->launch_cmd_pending = 0;
+}
 
 void handle_rc_ctrl_psm(btif_rc_device_cb_t* p_dev) {
   uint16_t cover_art_psm = p_dev->rc_cover_art_psm;
   BTIF_TRACE_DEBUG("%s: Update rc cover art psm to CTRL: %d", __func__,
-      cover_art_psm);
-  do_in_jni_thread(FROM_HERE, base::Bind(
-      bt_rc_ctrl_callbacks->get_cover_art_psm_cb,
-      p_dev->rc_addr, cover_art_psm));
+                   cover_art_psm);
+  if (bt_rc_ctrl_callbacks != NULL) {
+    do_in_jni_thread(FROM_HERE,
+                     base::Bind(bt_rc_ctrl_callbacks->get_cover_art_psm_cb,
+                                p_dev->rc_addr, cover_art_psm));
+  }
 }
 
 void handle_rc_features(btif_rc_device_cb_t* p_dev) {
@@ -640,7 +777,7 @@ void handle_rc_features(btif_rc_device_cb_t* p_dev) {
 }
 
 /***************************************************************************
- *  Function       handle_rc_connect
+ *  Function       handle_rc_browse_connect
  *
  *  - Argument:    tBTA_AV_RC_OPEN  browse RC open data structure
  *
@@ -663,9 +800,22 @@ void handle_rc_browse_connect(tBTA_AV_RC_BROWSE_OPEN* p_rc_br_open) {
    * probably not preferred anyways. */
   if (p_rc_br_open->status == BTA_AV_SUCCESS) {
     p_dev->br_connected = true;
-    do_in_jni_thread(FROM_HERE,
-                     base::Bind(bt_rc_ctrl_callbacks->connection_state_cb, true,
+    if (btif_av_src_sink_coexist_enabled()) {
+      if (btif_av_peer_is_connected_source(p_dev->rc_addr)) {
+        if (bt_rc_ctrl_callbacks != NULL) {
+          do_in_jni_thread(FROM_HERE,
+                           base::Bind(bt_rc_ctrl_callbacks->connection_state_cb,
+                                      true, true, p_dev->rc_addr));
+        }
+      } else {
+        p_dev->launch_cmd_pending |= RC_PENDING_ACT_REPORT_CONN;
+        BTIF_TRACE_API("%s: pending rc browse connection event", __func__);
+      }
+    } else {
+      do_in_jni_thread(
+          FROM_HERE, base::Bind(bt_rc_ctrl_callbacks->connection_state_cb, true,
                                 true, p_dev->rc_addr));
+    }
   }
 }
 
@@ -690,6 +840,16 @@ void handle_rc_connect(tBTA_AV_RC_OPEN* p_rc_open) {
     BTIF_TRACE_ERROR("%s: Connect failed with error code: %d", __func__,
                      p_rc_open->status);
     p_dev->rc_connected = false;
+    BTA_AvCloseRc(p_rc_open->rc_handle);
+    p_dev->rc_handle = 0;
+    p_dev->rc_state = BTRC_CONNECTION_STATE_DISCONNECTED;
+    p_dev->rc_features = 0;
+    p_dev->peer_ct_features = 0;
+    p_dev->peer_tg_features = 0;
+    p_dev->launch_cmd_pending = 0;
+    p_dev->rc_vol_label = MAX_LABEL;
+    p_dev->rc_volume = MAX_VOLUME;
+    p_dev->rc_addr = RawAddress::kEmpty;
     return;
   }
 
@@ -708,24 +868,31 @@ void handle_rc_connect(tBTA_AV_RC_OPEN* p_rc_open) {
   }
   p_dev->rc_addr = p_rc_open->peer_addr;
   p_dev->rc_features = p_rc_open->peer_features;
-  BTIF_TRACE_DEBUG("%s: handle_rc_connect in features: 0x%x out features 0x%x",
-                   __func__, p_rc_open->peer_features, p_dev->rc_features);
+  p_dev->peer_ct_features = p_rc_open->peer_ct_features;
+  p_dev->peer_tg_features = p_rc_open->peer_tg_features;
   p_dev->rc_cover_art_psm = p_rc_open->cover_art_psm;
-  BTIF_TRACE_DEBUG("%s: cover art psm: 0x%x",
-                   __func__, p_dev->rc_cover_art_psm);
   p_dev->rc_vol_label = MAX_LABEL;
   p_dev->rc_volume = MAX_VOLUME;
 
+  BTIF_TRACE_DEBUG(
+      "%s: handle_rc_connect in features=%#x, out features=%#x, "
+      "ct_feature=%#x, tg_feature=%#x, cover art psm=%#x",
+      __func__, p_rc_open->peer_features, p_dev->rc_features,
+      p_dev->peer_ct_features, p_dev->peer_tg_features,
+      p_dev->rc_cover_art_psm);
+
   p_dev->rc_connected = true;
   p_dev->rc_handle = p_rc_open->rc_handle;
   p_dev->rc_state = BTRC_CONNECTION_STATE_CONNECTED;
-  /* on locally initiated connection we will get remote features as part of
-   * connect */
-  if (p_dev->rc_features != 0 && bt_rc_callbacks != NULL) {
-    handle_rc_features(p_dev);
-  }
 
   p_dev->rc_playing_uid = RC_INVALID_TRACK_ID;
+
+  if (btif_av_src_sink_coexist_enabled() &&
+      !btif_av_peer_is_connected_source(p_dev->rc_addr)) {
+    p_dev->launch_cmd_pending |= RC_PENDING_ACT_REPORT_CONN;
+    BTIF_TRACE_API("%s: pending rc connection event", __func__);
+    return;
+  }
   if (bt_rc_ctrl_callbacks != NULL) {
     do_in_jni_thread(FROM_HERE,
                      base::Bind(bt_rc_ctrl_callbacks->connection_state_cb, true,
@@ -1009,8 +1176,17 @@ void handle_rc_metamsg_cmd(tBTA_AV_META_MSG* pmeta_msg) {
           pmeta_msg->code);
       p_dev->rc_notif[event_id - 1].bNotify = true;
       p_dev->rc_notif[event_id - 1].label = pmeta_msg->label;
+      /* this is sink(tg) feature, so it should not handle here */
+      if (btif_av_both_enable() && event_id == AVRC_EVT_VOLUME_CHANGE) {
+        return;
+      }
     }
 
+    /* this is sink(tg) feature, so it should not handle here */
+    if (btif_av_both_enable() &&
+        avrc_command.cmd.pdu == AVRC_PDU_SET_ABSOLUTE_VOLUME) {
+      return;
+    }
     BTIF_TRACE_EVENT("%s: Passing received metamsg command to app. pdu: %s",
                      __func__, dump_rc_pdu(avrc_command.cmd.pdu));
 
@@ -1086,7 +1262,19 @@ void btif_rc_handler(tBTA_AV_EVT event, tBTA_AV* p_data) {
                          __func__);
         break;
       }
+      BTIF_TRACE_DEBUG("%s peer_ct_features:0x%x, peer_tg_features=0x%x",
+                       __func__, p_data->rc_feat.peer_ct_features,
+                       p_data->rc_feat.peer_tg_features);
+      if (btif_av_src_sink_coexist_enabled() &&
+          (p_dev->peer_ct_features == p_data->rc_feat.peer_ct_features) &&
+          (p_dev->peer_tg_features == p_data->rc_feat.peer_tg_features)) {
+        BTIF_TRACE_ERROR(
+            "do SDP twice, no need callback rc_feature to framework again");
+        break;
+      }
 
+      p_dev->peer_ct_features = p_data->rc_feat.peer_ct_features;
+      p_dev->peer_tg_features = p_data->rc_feat.peer_tg_features;
       p_dev->rc_features = p_data->rc_feat.peer_features;
       if (bt_rc_callbacks != NULL) {
         handle_rc_features(p_dev);
@@ -1792,6 +1980,8 @@ static bt_status_t init(btrc_callbacks_t* callbacks) {
   if (bt_rc_callbacks) return BT_STATUS_DONE;
 
   bt_rc_callbacks = callbacks;
+  if (bt_rc_ctrl_callbacks) return BT_STATUS_SUCCESS;
+
   for (int idx = 0; idx < BTIF_RC_NUM_CONN; idx++) {
     initialize_device(&btif_rc_cb.rc_multi_cb[idx]);
   }
@@ -1815,6 +2005,8 @@ static bt_status_t init_ctrl(btrc_ctrl_callbacks_t* callbacks) {
   if (bt_rc_ctrl_callbacks) return BT_STATUS_DONE;
 
   bt_rc_ctrl_callbacks = callbacks;
+  if (bt_rc_callbacks) return BT_STATUS_SUCCESS;
+
   for (int idx = 0; idx < BTIF_RC_NUM_CONN; idx++) {
     initialize_device(&btif_rc_cb.rc_multi_cb[idx]);
   }
@@ -3105,6 +3297,15 @@ static void handle_notification_response(tBTA_AV_META_MSG* pmeta_msg,
     return;
   }
 
+  if (btif_av_src_sink_coexist_enabled() &&
+      p_rsp->event_id == AVRC_EVT_VOLUME_CHANGE) {
+    BTIF_TRACE_ERROR(
+        "%s: legacy TG don't handle absolute volume change. leave it to new "
+        "avrcp",
+        __func__);
+    return;
+  }
+
   const uint32_t* attr_list = get_requested_attributes_list(p_dev);
   const uint8_t attr_list_size = get_requested_attributes_list_size(p_dev);
 
@@ -4341,6 +4542,14 @@ static void handle_avk_rc_metamsg_cmd(tBTA_AV_META_MSG* pmeta_msg) {
       BTIF_TRACE_WARNING(
           "%s: Error in parsing received metamsg command. status: 0x%02x",
           __func__, status);
+      if (true == btif_av_both_enable()) {
+        if (AVRC_PDU_GET_CAPABILITIES == avrc_cmd.pdu ||
+            AVRC_PDU_GET_ELEMENT_ATTR == avrc_cmd.pdu ||
+            AVRC_PDU_GET_PLAY_STATUS == avrc_cmd.pdu ||
+            AVRC_PDU_GET_FOLDER_ITEMS == avrc_cmd.pdu ||
+            AVRC_PDU_GET_ITEM_ATTRIBUTES == avrc_cmd.pdu)
+          return;
+      }
       send_reject_response(pmeta_msg->rc_handle, pmeta_msg->label, avrc_cmd.pdu,
                            status, pmeta_msg->p_msg->hdr.opcode);
     } else {
diff --git a/system/btif/test/btif_rc_test.cc b/system/btif/test/btif_rc_test.cc
index 48f3b748ae103b58a5065b86af82e038311b6cc8..c10cee263422173226b36b0e53797b460ba2fd4e 100644
--- a/system/btif/test/btif_rc_test.cc
+++ b/system/btif/test/btif_rc_test.cc
@@ -28,21 +28,73 @@
 #include "osi/test/AllocationTestHarness.h"
 #include "stack/include/bt_hdr.h"
 #include "stack/include/btm_api_types.h"
+#include "test/common/mock_functions.h"
+#include "test/mock/mock_osi_alarm.h"
+#include "test/mock/mock_osi_allocator.h"
+#include "test/mock/mock_osi_list.h"
 #include "types/raw_address.h"
 #undef LOG_TAG
+#include "avrcp_service.h"
 #include "btif/src/btif_rc.cc"
 
 void allocation_tracker_uninit(void);
 
+namespace bluetooth {
+namespace avrcp {
+int VolChanged = 0;
+AvrcpService* AvrcpService::instance_ = nullptr;
+
+void AvrcpService::SendMediaUpdate(bool track_changed, bool play_state,
+                                   bool queue){};
+void AvrcpService::SendFolderUpdate(bool available_players,
+                                    bool addressed_players, bool uids){};
+void AvrcpService::SendActiveDeviceChanged(const RawAddress& address){};
+void AvrcpService::SendPlayerSettingsChanged(
+    std::vector<PlayerAttribute> attributes, std::vector<uint8_t> values){};
+void AvrcpService::ServiceInterfaceImpl::Init(
+    MediaInterface* media_interface, VolumeInterface* volume_interface,
+    PlayerSettingsInterface* player_settings_interface){};
+void AvrcpService::ServiceInterfaceImpl::RegisterBipServer(int psm){};
+void AvrcpService::ServiceInterfaceImpl::UnregisterBipServer(){};
+bool AvrcpService::ServiceInterfaceImpl::ConnectDevice(
+    const RawAddress& bdaddr) {
+  return true;
+};
+bool AvrcpService::ServiceInterfaceImpl::DisconnectDevice(
+    const RawAddress& bdaddr) {
+  return true;
+};
+void AvrcpService::ServiceInterfaceImpl::SetBipClientStatus(
+    const RawAddress& bdaddr, bool connected){};
+bool AvrcpService::ServiceInterfaceImpl::Cleanup() { return true; };
+
+AvrcpService* AvrcpService::Get() {
+  CHECK(instance_ == nullptr);
+  instance_ = new AvrcpService();
+  return instance_;
+}
+
+void AvrcpService::RegisterVolChanged(const RawAddress& bdaddr) {
+  VolChanged++;
+}
+}  // namespace avrcp
+}  // namespace bluetooth
+
 namespace {
 int AVRC_BldResponse_ = 0;
+int AVRC_BldCmd_ = 0;
 }  // namespace
 
 uint8_t appl_trace_level = BT_TRACE_LEVEL_WARNING;
 uint8_t btif_trace_level = BT_TRACE_LEVEL_WARNING;
 
+const RawAddress kDeviceAddress({0x11, 0x22, 0x33, 0x44, 0x55, 0x66});
 bool avrcp_absolute_volume_is_enabled() { return true; }
-tAVRC_STS AVRC_BldCommand(tAVRC_COMMAND* p_cmd, BT_HDR** pp_pkt) { return 0; }
+
+tAVRC_STS AVRC_BldCommand(tAVRC_COMMAND* p_cmd, BT_HDR** pp_pkt) {
+  AVRC_BldCmd_++;
+  return 0;
+}
 tAVRC_STS AVRC_BldResponse(uint8_t handle, tAVRC_RESPONSE* p_rsp,
                            BT_HDR** pp_pkt) {
   AVRC_BldResponse_++;
@@ -79,8 +131,8 @@ void BTA_AvVendorCmd(uint8_t rc_handle, uint8_t label, tBTA_AV_CODE cmd_code,
 void BTA_AvVendorRsp(uint8_t rc_handle, uint8_t label, tBTA_AV_CODE rsp_code,
                      uint8_t* p_data, uint16_t len, uint32_t company_id) {}
 void btif_av_clear_remote_suspend_flag(void) {}
-bool btif_av_is_connected(void) { return false; }
-bool btif_av_is_sink_enabled(void) { return false; }
+bool btif_av_is_connected(void) { return true; }
+bool btif_av_is_sink_enabled(void) { return true; }
 RawAddress btif_av_sink_active_peer(void) { return RawAddress(); }
 RawAddress btif_av_source_active_peer(void) { return RawAddress(); }
 bool btif_av_stream_started_ready(void) { return false; }
@@ -89,12 +141,29 @@ bt_status_t btif_transfer_context(tBTIF_CBACK* p_cback, uint16_t event,
                                   tBTIF_COPY_CBACK* p_copy_cback) {
   return BT_STATUS_SUCCESS;
 }
+bool btif_av_src_sink_coexist_enabled() { return true; }
+bool btif_av_is_connected_addr(const RawAddress& peer_address) { return true; }
+bool btif_av_peer_is_connected_sink(const RawAddress& peer_address) {
+  return false;
+}
+bool btif_av_peer_is_connected_source(const RawAddress& peer_address) {
+  return true;
+}
+bool btif_av_peer_is_sink(const RawAddress& peer_address) { return false; }
+bool btif_av_peer_is_source(const RawAddress& peer_address) { return true; }
+bool btif_av_both_enable(void) { return true; }
+
 const char* dump_rc_event(uint8_t event) { return nullptr; }
 const char* dump_rc_notification_event_id(uint8_t event_id) { return nullptr; }
 const char* dump_rc_pdu(uint8_t pdu) { return nullptr; }
 const char* dump_rc_opcode(uint8_t pdu) { return nullptr; }
+static bluetooth::common::MessageLoopThread jni_thread("bt_jni_thread");
 bt_status_t do_in_jni_thread(const base::Location& from_here,
                              base::OnceClosure task) {
+  if (!jni_thread.DoInThread(from_here, std::move(task))) {
+    LOG(ERROR) << __func__ << ": Post task to task runner failed!";
+    return BT_STATUS_FAIL;
+  }
   return BT_STATUS_SUCCESS;
 }
 bluetooth::common::MessageLoopThread* get_main_thread() { return nullptr; }
@@ -133,3 +202,227 @@ TEST_F(BtifRcTest, get_element_attr_rsp) {
   CHECK(get_element_attr_rsp(bd_addr, num_attr, p_attrs) == BT_STATUS_SUCCESS);
   CHECK(AVRC_BldResponse_ == 1);
 }
+
+TEST_F(BtifRcTest, btif_rc_get_addr_by_handle) {
+  RawAddress get_bd_addr;
+
+  btif_rc_cb.rc_multi_cb[0].rc_addr = kDeviceAddress;
+  btif_rc_cb.rc_multi_cb[0].rc_state = BTRC_CONNECTION_STATE_CONNECTED;
+  btif_rc_cb.rc_multi_cb[0].rc_handle = 0;
+
+  btif_rc_get_addr_by_handle(0, get_bd_addr);
+  CHECK(kDeviceAddress == get_bd_addr);
+}
+
+static btrc_ctrl_callbacks_t btrc_ctrl_callbacks = {
+    .size = sizeof(btrc_ctrl_callbacks_t),
+    .passthrough_rsp_cb = NULL,
+    .groupnavigation_rsp_cb = NULL,
+    .connection_state_cb = NULL,
+    .getrcfeatures_cb = NULL,
+    .setplayerappsetting_rsp_cb = NULL,
+    .playerapplicationsetting_cb = NULL,
+    .playerapplicationsetting_changed_cb = NULL,
+    .setabsvol_cmd_cb = NULL,
+    .registernotification_absvol_cb = NULL,
+    .track_changed_cb = NULL,
+    .play_position_changed_cb = NULL,
+    .play_status_changed_cb = NULL,
+    .get_folder_items_cb = NULL,
+    .change_folder_path_cb = NULL,
+    .set_browsed_player_cb = NULL,
+    .set_addressed_player_cb = NULL,
+    .addressed_player_changed_cb = NULL,
+    .now_playing_contents_changed_cb = NULL,
+    .available_player_changed_cb = NULL,
+    .get_cover_art_psm_cb = NULL,
+};
+
+struct rc_connection_state_cb_t {
+  bool rc_state;
+  bool bt_state;
+  RawAddress raw_address;
+};
+
+struct rc_feature_cb_t {
+  int feature;
+  RawAddress raw_address;
+};
+
+static std::promise<rc_connection_state_cb_t> g_btrc_connection_state_promise;
+static std::promise<rc_connection_state_cb_t>
+    g_btrc_browse_connection_state_promise;
+static std::promise<rc_feature_cb_t> g_btrc_feature;
+
+class BtifRcFeatureTest : public BtifRcTest {
+ protected:
+  void SetUp() override {
+    BtifRcTest::SetUp();
+    init_ctrl(&btrc_ctrl_callbacks);
+    jni_thread.StartUp();
+    btrc_ctrl_callbacks.getrcfeatures_cb = [](const RawAddress& bd_addr,
+                                              int features) {
+      rc_feature_cb_t rc_feature = {
+          .feature = features,
+          .raw_address = bd_addr,
+      };
+      g_btrc_feature.set_value(rc_feature);
+    };
+  }
+
+  void TearDown() override {
+    bt_rc_ctrl_callbacks->getrcfeatures_cb = [](const RawAddress& bd_addr,
+                                                int features) {};
+    BtifRcTest::TearDown();
+  }
+};
+
+TEST_F(BtifRcFeatureTest, handle_rc_ctrl_features) {
+  AVRC_BldCmd_ = 0;
+  g_btrc_feature = std::promise<rc_feature_cb_t>();
+  std::future<rc_feature_cb_t> future = g_btrc_feature.get_future();
+  btif_rc_device_cb_t p_dev;
+
+  p_dev.peer_tg_features =
+      (BTA_AV_FEAT_RCTG | BTA_AV_FEAT_ADV_CTRL | BTA_AV_FEAT_RCCT |
+       BTA_AV_FEAT_METADATA | BTA_AV_FEAT_VENDOR | BTA_AV_FEAT_BROWSE |
+       BTA_AV_FEAT_COVER_ARTWORK);
+  p_dev.rc_connected = true;
+
+  handle_rc_ctrl_features(&p_dev);
+  CHECK(AVRC_BldCmd_ == 1);
+
+  CHECK(std::future_status::ready == future.wait_for(std::chrono::seconds(2)));
+  auto res = future.get();
+  LOG_INFO("FEATURES:%d", res.feature);
+  CHECK(res.feature == (BTRC_FEAT_ABSOLUTE_VOLUME | BTRC_FEAT_METADATA |
+                        BTRC_FEAT_BROWSE | BTRC_FEAT_COVER_ARTWORK));
+}
+
+class BtifRcBrowseConnectionTest : public BtifRcTest {
+ protected:
+  void SetUp() override {
+    BtifRcTest::SetUp();
+    init_ctrl(&btrc_ctrl_callbacks);
+    jni_thread.StartUp();
+    btrc_ctrl_callbacks.connection_state_cb = [](bool rc_state, bool bt_state,
+                                                 const RawAddress& bd_addr) {
+      rc_connection_state_cb_t rc_connection_state = {
+          .rc_state = rc_state,
+          .bt_state = bt_state,
+          .raw_address = bd_addr,
+      };
+      g_btrc_browse_connection_state_promise.set_value(rc_connection_state);
+    };
+  }
+
+  void TearDown() override {
+    bt_rc_ctrl_callbacks->connection_state_cb =
+        [](bool rc_state, bool bt_state, const RawAddress& bd_addr) {};
+    BtifRcTest::TearDown();
+  }
+};
+
+TEST_F(BtifRcBrowseConnectionTest, handle_rc_browse_connect) {
+  g_btrc_browse_connection_state_promise =
+      std::promise<rc_connection_state_cb_t>();
+  std::future<rc_connection_state_cb_t> future =
+      g_btrc_browse_connection_state_promise.get_future();
+
+  tBTA_AV_RC_BROWSE_OPEN browse_data = {
+      .status = BTA_AV_SUCCESS,
+      .rc_handle = 0,
+  };
+
+  btif_rc_cb.rc_multi_cb[0].rc_handle = 0;
+  btif_rc_cb.rc_multi_cb[0].rc_addr = RawAddress::kEmpty;
+  btif_rc_cb.rc_multi_cb[0].rc_state = BTRC_CONNECTION_STATE_CONNECTED;
+  btif_rc_cb.rc_multi_cb[0].rc_connected = false;
+
+  /* process unit test  handle_rc_browse_connect */
+  handle_rc_browse_connect(&browse_data);
+  CHECK(std::future_status::ready == future.wait_for(std::chrono::seconds(2)));
+  auto res = future.get();
+  CHECK(res.bt_state == true);
+}
+
+class BtifRcConnectionTest : public BtifRcTest {
+ protected:
+  void SetUp() override {
+    BtifRcTest::SetUp();
+    init_ctrl(&btrc_ctrl_callbacks);
+    jni_thread.StartUp();
+    btrc_ctrl_callbacks.connection_state_cb = [](bool rc_state, bool bt_state,
+                                                 const RawAddress& bd_addr) {
+      rc_connection_state_cb_t rc_connection_state = {
+          .rc_state = rc_state,
+          .bt_state = bt_state,
+          .raw_address = bd_addr,
+      };
+      g_btrc_connection_state_promise.set_value(rc_connection_state);
+    };
+  }
+
+  void TearDown() override {
+    bt_rc_ctrl_callbacks->connection_state_cb =
+        [](bool rc_state, bool bt_state, const RawAddress& bd_addr) {};
+    BtifRcTest::TearDown();
+  }
+};
+
+TEST_F(BtifRcConnectionTest, btif_rc_check_pending_cmd) {
+  AVRC_BldCmd_ = 0;
+  g_btrc_connection_state_promise = std::promise<rc_connection_state_cb_t>();
+  std::future<rc_connection_state_cb_t> future =
+      g_btrc_connection_state_promise.get_future();
+
+  btif_rc_cb.rc_multi_cb[0].rc_handle = 0xff;
+  btif_rc_cb.rc_multi_cb[0].rc_addr = kDeviceAddress;
+  btif_rc_cb.rc_multi_cb[0].rc_state = BTRC_CONNECTION_STATE_CONNECTED;
+  btif_rc_cb.rc_multi_cb[0].rc_connected = true;
+  btif_rc_cb.rc_multi_cb[0].launch_cmd_pending |=
+      (RC_PENDING_ACT_REG_VOL | RC_PENDING_ACT_GET_CAP |
+       RC_PENDING_ACT_REPORT_CONN);
+
+  btif_rc_check_pending_cmd(kDeviceAddress);
+  CHECK(AVRC_BldCmd_ == 1);
+
+  CHECK(std::future_status::ready == future.wait_for(std::chrono::seconds(3)));
+  auto res = future.get();
+  CHECK(res.rc_state == true);
+}
+
+TEST_F(BtifRcConnectionTest, BTA_AV_RC_OPEN_EVT) {
+  g_btrc_connection_state_promise = std::promise<rc_connection_state_cb_t>();
+  std::future<rc_connection_state_cb_t> future =
+      g_btrc_connection_state_promise.get_future();
+
+  /* handle_rc_connect  */
+  tBTA_AV data = {
+      .rc_open =
+          {
+              .rc_handle = 0,
+              .cover_art_psm = 0,
+              .peer_features = 0,
+              .peer_ct_features = 0,
+              .peer_tg_features = (BTA_AV_FEAT_METADATA | BTA_AV_FEAT_VENDOR |
+                                   BTA_AV_FEAT_RCTG | BTA_AV_FEAT_RCCT),
+              .peer_addr = kDeviceAddress,
+              .status = BTA_AV_SUCCESS,
+          },
+  };
+  btif_rc_cb.rc_multi_cb[0].rc_handle = 0;
+  btif_rc_cb.rc_multi_cb[0].rc_addr = RawAddress::kEmpty;
+  btif_rc_cb.rc_multi_cb[0].rc_state = BTRC_CONNECTION_STATE_DISCONNECTED;
+  btif_rc_cb.rc_multi_cb[0].rc_connected = false;
+
+  btif_rc_handler(BTA_AV_RC_OPEN_EVT, &data);
+
+  CHECK(btif_rc_cb.rc_multi_cb[data.rc_open.rc_handle].rc_connected == true);
+  CHECK(btif_rc_cb.rc_multi_cb[data.rc_open.rc_handle].rc_state ==
+        BTRC_CONNECTION_STATE_CONNECTED);
+
+  CHECK(std::future_status::ready == future.wait_for(std::chrono::seconds(2)));
+  auto res = future.get();
+  CHECK(res.rc_state == true);
+}
diff --git a/system/test/mock/mock_stack_avrc_api.cc b/system/test/mock/mock_stack_avrc_api.cc
index d7fb4513966dd1a5add26128cb539076bf5c0bd3..00ac4344f16f2c3be5dbddb0e76e27f604b4884c 100644
--- a/system/test/mock/mock_stack_avrc_api.cc
+++ b/system/test/mock/mock_stack_avrc_api.cc
@@ -60,7 +60,7 @@ uint16_t AVRC_GetProfileVersion() {
   return 0;
 }
 uint16_t AVRC_MsgReq(uint8_t handle, uint8_t label, uint8_t ctype,
-                     BT_HDR* p_pkt) {
+                     BT_HDR* p_pkt, bool is_new_avrcp) {
   inc_func_call_count(__func__);
   return 0;
 }
@@ -76,6 +76,11 @@ uint16_t AVRC_OpenBrowse(uint8_t handle, uint8_t conn_role) {
 void AVRC_SaveControllerVersion(const RawAddress& bdaddr, uint16_t version) {
   inc_func_call_count(__func__);
 }
+
+void AVRC_UpdateCcb(RawAddress* addr, uint32_t company_id) {
+  inc_func_call_count(__func__);
+}
+
 uint16_t AVRC_PassCmd(uint8_t handle, uint8_t label, tAVRC_MSG_PASS* p_msg) {
   inc_func_call_count(__func__);
   return 0;