Save the AVDTP version after SDP discovery and read it on reconnect

* Save the AVDTP version discovered by SDP to the device's local
  configuration section with key string of "AvdtpVersion"
* Refactor tBTA_AV_SCB and hide the AVDTP version and peer address
  behind get/set methods:
  AvdtpVersion() / SetAvdtpVersion() / PeerAddress().
* Added new methods tBTA_AV_SCB::OnConnected() and OnDisconnected().
  The former is used to setup some of the internal state when
  connected to a peer: the peer address and read the stored AVDTP
  version from local configuration section.
  The latter is used to reset that state when disconnected
  from that peer.
* Removed field tBTA_AV_SDP_RES.avdt_version because it is never
  set / used.
* Removed duplicate re-definition of AVDT_VERSION inside avdt_api.h

Bug: 78142165
Test: Manual: connect/reconnect with Sennheiser MOMENTUM M2 AEBT headset
Change-Id: Ib9dcd95dc9899fa81f3cd927f127e5cb0f21ef60
diff --git a/bta/av/bta_av_aact.cc b/bta/av/bta_av_aact.cc
index 137e59c..af80b06 100644
--- a/bta/av/bta_av_aact.cc
+++ b/bta/av/bta_av_aact.cc
@@ -38,6 +38,7 @@
 #include "bt_utils.h"
 #include "bta_av_int.h"
 #include "btif/include/btif_av_co.h"
+#include "btif/include/btif_config.h"
 #include "btif/include/btif_storage.h"
 #include "btm_int.h"
 #include "device/include/controller.h"
@@ -267,9 +268,10 @@
 static void bta_av_save_addr(tBTA_AV_SCB* p_scb, const RawAddress& bd_addr) {
   APPL_TRACE_DEBUG("%s: r:%d, s:%d", __func__, p_scb->recfg_sup,
                    p_scb->suspend_sup);
-  if (p_scb->peer_addr != bd_addr) {
-    LOG(INFO) << __func__ << ": reset flags old_addr=" << p_scb->peer_addr
-              << ", new_addr=" << bd_addr;
+  if (p_scb->PeerAddress() != bd_addr) {
+    LOG_INFO(LOG_TAG, "%s: reset flags old_addr=%s new_addr=%s", __func__,
+             p_scb->PeerAddress().ToString().c_str(),
+             bd_addr.ToString().c_str());
     /* a new addr, reset the supported flags */
     p_scb->recfg_sup = true;
     p_scb->suspend_sup = true;
@@ -277,7 +279,7 @@
 
   /* do this copy anyway, just in case the first addr matches
    * the control block one by accident */
-  p_scb->peer_addr = bd_addr;
+  p_scb->OnConnected(bd_addr);
 }
 
 /*******************************************************************************
@@ -361,9 +363,9 @@
       p_scb->sep_info_idx = i;
 
       /* we got a stream; get its capabilities */
-      bool get_all_cap = (p_scb->avdt_version >= AVDT_VERSION_1_3) &&
+      bool get_all_cap = (p_scb->AvdtpVersion() >= AVDT_VERSION_1_3) &&
                          (A2DP_GetAvdtpVersion() >= AVDT_VERSION_1_3);
-      AVDT_GetCapReq(p_scb->peer_addr, p_scb->hdi, p_scb->sep_info[i].seid,
+      AVDT_GetCapReq(p_scb->PeerAddress(), p_scb->hdi, p_scb->sep_info[i].seid,
                      &p_scb->peer_cap, &bta_av_proc_stream_evt, get_all_cap);
       sent_cmd = true;
       break;
@@ -373,7 +375,7 @@
   /* if no streams available then stream open fails */
   if (!sent_cmd) {
     APPL_TRACE_ERROR("%s: BTA_AV_STR_GETCAP_FAIL_EVT: peer_addr=%s", __func__,
-                     p_scb->peer_addr.ToString().c_str());
+                     p_scb->PeerAddress().ToString().c_str());
     bta_av_ssm_execute(p_scb, BTA_AV_STR_GETCAP_FAIL_EVT, p_data);
   }
 
@@ -392,8 +394,9 @@
 void bta_av_proc_stream_evt(uint8_t handle, const RawAddress& bd_addr,
                             uint8_t event, tAVDT_CTRL* p_data,
                             uint8_t scb_index) {
-  uint16_t sec_len = 0;
+  CHECK_LT(scb_index, BTA_AV_NUM_STRS);
   tBTA_AV_SCB* p_scb = bta_av_cb.p_scb[scb_index];
+  uint16_t sec_len = 0;
 
   APPL_TRACE_EVENT(
       "%s: peer_address: %s avdt_handle: %d event=0x%x scb_index=%d p_scb=%p",
@@ -532,8 +535,10 @@
  * Returns          void
  *
  ******************************************************************************/
-static void bta_av_a2dp_sdp_cback(bool found, tA2DP_Service* p_service) {
-  APPL_TRACE_DEBUG("%s: found=%s", __func__, (found) ? "true" : "false");
+static void bta_av_a2dp_sdp_cback(bool found, tA2DP_Service* p_service,
+                                  const RawAddress& peer_address) {
+  APPL_TRACE_DEBUG("%s: peer %s : found=%s", __func__,
+                   peer_address.ToString().c_str(), (found) ? "true" : "false");
 
   tBTA_AV_SCB* p_scb = bta_av_hndl_to_scb(bta_av_cb.handle);
   if (p_scb == NULL) {
@@ -544,10 +549,10 @@
 
   if (!found) {
     APPL_TRACE_ERROR("%s: peer %s A2DP service discovery failed", __func__,
-                     p_scb->peer_addr.ToString().c_str());
+                     p_scb->PeerAddress().ToString().c_str());
   }
   APPL_TRACE_DEBUG("%s: peer %s found=%s", __func__,
-                   p_scb->peer_addr.ToString().c_str(),
+                   p_scb->PeerAddress().ToString().c_str(),
                    (found) ? "true" : "false");
 
   tBTA_AV_SDP_RES* p_msg =
@@ -557,12 +562,24 @@
   } else {
     p_msg->hdr.event = BTA_AV_SDP_DISC_FAIL_EVT;
     APPL_TRACE_ERROR("%s: BTA_AV_SDP_DISC_FAIL_EVT: peer_addr=%s", __func__,
-                     p_scb->peer_addr.ToString().c_str());
+                     p_scb->PeerAddress().ToString().c_str());
   }
-  if (found && (p_service != NULL))
-    p_scb->avdt_version = p_service->avdt_version;
-  else
-    p_scb->avdt_version = 0x00;
+  if (found && (p_service != NULL)) {
+    p_scb->SetAvdtpVersion(p_service->avdt_version);
+    if (p_service->avdt_version != 0) {
+      if (btif_config_set_bin(p_scb->PeerAddress().ToString(),
+                              AVDTP_VERSION_CONFIG_KEY,
+                              (const uint8_t*)&p_service->avdt_version,
+                              sizeof(p_service->avdt_version))) {
+        btif_config_save();
+      } else {
+        APPL_TRACE_WARNING("%s: Failed to store peer AVDTP version for %s",
+                           __func__, p_scb->PeerAddress().ToString().c_str());
+      }
+    }
+  } else {
+    p_scb->SetAvdtpVersion(0);
+  }
   p_msg->hdr.layer_specific = bta_av_cb.handle;
 
   bta_sys_sendmsg(p_msg);
@@ -609,7 +626,7 @@
   tBTA_AV_API_OPEN* p_buf = &p_scb->q_info.open;
 
   APPL_TRACE_DEBUG("%s: peer %s wait:0x%x", __func__,
-                   p_scb->peer_addr.ToString().c_str(), p_scb->wait);
+                   p_scb->PeerAddress().ToString().c_str(), p_scb->wait);
   if (p_scb->wait & BTA_AV_WAIT_ROLE_SW_RES_START)
     p_scb->wait |= BTA_AV_WAIT_ROLE_SW_RETRY;
 
@@ -629,7 +646,7 @@
   } else {
     /* report failure on OPEN */
     APPL_TRACE_ERROR("%s: peer %s role switch failed (wait=0x%x)", __func__,
-                     p_scb->peer_addr.ToString().c_str(), p_scb->wait);
+                     p_scb->PeerAddress().ToString().c_str(), p_scb->wait);
     switch_res = BTA_AV_RS_FAIL;
   }
 
@@ -666,7 +683,7 @@
       p_scb->wait &= ~BTA_AV_WAIT_ROLE_SW_BITS;
       if (p_data->role_res.hci_status != HCI_SUCCESS) {
         p_scb->role &= ~BTA_AV_ROLE_START_INT;
-        bta_sys_idle(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->peer_addr);
+        bta_sys_idle(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->PeerAddress());
         /* start failed because of role switch. */
         tBTA_AV_START start;
         start.chnl = p_scb->chnl;
@@ -689,7 +706,7 @@
       if (p_data->role_res.hci_status != HCI_SUCCESS) {
         /* Open failed because of role switch. */
         tBTA_AV_OPEN av_open;
-        av_open.bd_addr = p_scb->peer_addr;
+        av_open.bd_addr = p_scb->PeerAddress();
         av_open.chnl = p_scb->chnl;
         av_open.hndl = p_scb->hndl;
         av_open.status = BTA_AV_FAIL_ROLE;
@@ -729,9 +746,9 @@
  ******************************************************************************/
 void bta_av_delay_co(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) {
   APPL_TRACE_DEBUG("%s: peer %s handle:%d delay:%d", __func__,
-                   p_scb->peer_addr.ToString().c_str(), p_scb->hndl,
+                   p_scb->PeerAddress().ToString().c_str(), p_scb->hndl,
                    p_data->str_msg.msg.delay_rpt_cmd.delay);
-  p_scb->p_cos->delay(p_scb->hndl, p_scb->peer_addr,
+  p_scb->p_cos->delay(p_scb->hndl, p_scb->PeerAddress(),
                       p_data->str_msg.msg.delay_rpt_cmd.delay);
 }
 
@@ -776,7 +793,7 @@
       /* report a new failure event  */
       p_scb->open_status = BTA_AV_FAIL_ROLE;
       APPL_TRACE_ERROR("%s: BTA_AV_SDP_DISC_FAIL_EVT: peer_addr=%s", __func__,
-                       p_scb->peer_addr.ToString().c_str());
+                       p_scb->PeerAddress().ToString().c_str());
       bta_av_ssm_execute(p_scb, BTA_AV_SDP_DISC_FAIL_EVT, NULL);
       break;
 
@@ -821,7 +838,7 @@
   p_scb->sec_mask = p_data->api_open.sec_mask;
   p_scb->use_rc = p_data->api_open.use_rc;
 
-  bta_sys_app_open(BTA_ID_AV, p_scb->app_id, p_scb->peer_addr);
+  bta_sys_app_open(BTA_ID_AV, p_scb->app_id, p_scb->PeerAddress());
 
   /* only one A2DP find service is active at a time */
   bta_av_cb.handle = p_scb->hndl;
@@ -840,16 +857,17 @@
   APPL_TRACE_DEBUG(
       "%s: Initiate SDP discovery for peer %s : uuid_int=0x%x "
       "sdp_uuid=0x%x",
-      __func__, p_scb->peer_addr.ToString().c_str(), p_scb->uuid_int, sdp_uuid);
+      __func__, p_scb->PeerAddress().ToString().c_str(), p_scb->uuid_int,
+      sdp_uuid);
   tA2DP_STATUS find_service_status = A2DP_FindService(
-      sdp_uuid, p_scb->peer_addr, &db_params, bta_av_a2dp_sdp_cback);
+      sdp_uuid, p_scb->PeerAddress(), &db_params, bta_av_a2dp_sdp_cback);
   if (find_service_status != A2DP_SUCCESS) {
     APPL_TRACE_ERROR(
         "%s: A2DP_FindService() failed for peer %s uuid_int=0x%x "
         "sdp_uuid=0x%x : status=%d",
-        __func__, p_scb->peer_addr.ToString().c_str(), p_scb->uuid_int,
+        __func__, p_scb->PeerAddress().ToString().c_str(), p_scb->uuid_int,
         sdp_uuid, find_service_status);
-    bta_av_a2dp_sdp_cback(false, NULL);
+    bta_av_a2dp_sdp_cback(false, nullptr, RawAddress::kEmpty);
   }
 }
 
@@ -870,7 +888,7 @@
 
   /* free any buffers */
   p_scb->sdp_discovery_started = false;
-  p_scb->avdt_version = 0;
+  p_scb->SetAvdtpVersion(0);
 
   /* initialize some control block variables */
   p_scb->open_status = BTA_AV_SUCCESS;
@@ -910,7 +928,7 @@
   } else {
     /* report stream closed to main SM */
     msg.is_up = false;
-    msg.peer_addr = p_scb->peer_addr;
+    msg.peer_addr = p_scb->PeerAddress();
     bta_av_conn_chg((tBTA_AV_DATA*)&msg);
   }
 }
@@ -950,7 +968,8 @@
   p_scb->avdt_label = p_data->str_msg.msg.hdr.label;
 
   APPL_TRACE_DEBUG("%s: peer %s handle:%d local_sep:%d", __func__,
-                   p_scb->peer_addr.ToString().c_str(), p_scb->hndl, local_sep);
+                   p_scb->PeerAddress().ToString().c_str(), p_scb->hndl,
+                   local_sep);
   APPL_TRACE_DEBUG("%s: codec: %s", __func__,
                    A2DP_CodecInfoString(p_evt_cfg->codec_info).c_str());
 
@@ -996,15 +1015,15 @@
     /*  in case of A2DP SINK this is the first time peer data is being sent to
      * co functions */
     if (local_sep == AVDT_TSEP_SNK) {
-      p_scb->p_cos->setcfg(p_scb->hndl, p_scb->peer_addr, p_evt_cfg->codec_info,
-                           p_info->seid, p_evt_cfg->num_protect,
-                           p_evt_cfg->protect_info, AVDT_TSEP_SNK,
-                           p_msg->handle);
+      p_scb->p_cos->setcfg(p_scb->hndl, p_scb->PeerAddress(),
+                           p_evt_cfg->codec_info, p_info->seid,
+                           p_evt_cfg->num_protect, p_evt_cfg->protect_info,
+                           AVDT_TSEP_SNK, p_msg->handle);
     } else {
-      p_scb->p_cos->setcfg(p_scb->hndl, p_scb->peer_addr, p_evt_cfg->codec_info,
-                           p_info->seid, p_evt_cfg->num_protect,
-                           p_evt_cfg->protect_info, AVDT_TSEP_SRC,
-                           p_msg->handle);
+      p_scb->p_cos->setcfg(p_scb->hndl, p_scb->PeerAddress(),
+                           p_evt_cfg->codec_info, p_info->seid,
+                           p_evt_cfg->num_protect, p_evt_cfg->protect_info,
+                           AVDT_TSEP_SRC, p_msg->handle);
     }
   }
 }
@@ -1023,7 +1042,8 @@
   tBTA_AV_RCB* p_rcb;
 
   APPL_TRACE_WARNING("%s: conn_lcb: 0x%x peer_addr: %s", __func__,
-                     bta_av_cb.conn_lcb, p_scb->peer_addr.ToString().c_str());
+                     bta_av_cb.conn_lcb,
+                     p_scb->PeerAddress().ToString().c_str());
 
   alarm_cancel(bta_av_cb.link_signalling_timer);
   alarm_cancel(p_scb->avrc_ct_timer);
@@ -1031,7 +1051,7 @@
   if (bta_av_cb.conn_lcb) {
     p_rcb = bta_av_get_rcb_by_shdl((uint8_t)(p_scb->hdi + 1));
     if (p_rcb) bta_av_del_rc(p_rcb);
-    AVDT_DisconnectReq(p_scb->peer_addr, &bta_av_proc_stream_evt);
+    AVDT_DisconnectReq(p_scb->PeerAddress(), &bta_av_proc_stream_evt);
   } else {
     bta_av_ssm_execute(p_scb, BTA_AV_AVDT_DISCONNECT_EVT, NULL);
   }
@@ -1094,14 +1114,14 @@
   local_sep = bta_av_get_scb_sep_type(p_scb, avdt_handle);
   bta_av_adjust_seps_idx(p_scb, avdt_handle);
   APPL_TRACE_DEBUG("%s: peer %s handle: sep_idx: %d cur_psc_mask:0x%x",
-                   __func__, p_scb->peer_addr.ToString().c_str(),
+                   __func__, p_scb->PeerAddress().ToString().c_str(),
                    p_scb->sep_idx, p_scb->cur_psc_mask);
 
   if ((AVDT_TSEP_SNK == local_sep) &&
       (p_data->ci_setconfig.err_code == AVDT_SUCCESS) &&
       (p_scb->seps[p_scb->sep_idx].p_app_sink_data_cback != NULL)) {
     tBTA_AV_MEDIA av_sink_codec_info;
-    av_sink_codec_info.avk_config.bd_addr = p_scb->peer_addr;
+    av_sink_codec_info.avk_config.bd_addr = p_scb->PeerAddress();
     av_sink_codec_info.avk_config.codec_info = p_scb->cfg.codec_info;
     p_scb->seps[p_scb->sep_idx].p_app_sink_data_cback(BTA_AV_SINK_MEDIA_CFG_EVT,
                                                       &av_sink_codec_info);
@@ -1123,7 +1143,7 @@
     p_scb->num_seps = num;
 
     if (p_scb->cur_psc_mask & AVDT_PSC_DELAY_RPT)
-      p_scb->avdt_version = AVDT_VERSION_1_3;
+      p_scb->SetAvdtpVersion(AVDT_VERSION_1_3);
 
     if (A2DP_GetCodecType(p_scb->cfg.codec_info) == A2DP_MEDIA_CT_SBC ||
         num > 1) {
@@ -1133,7 +1153,7 @@
       /* this is called in A2DP SRC path only, In case of SINK we don't need it
        */
       if (local_sep == AVDT_TSEP_SRC)
-        p_scb->p_cos->disc_res(p_scb->hndl, p_scb->peer_addr, num, num, 0,
+        p_scb->p_cos->disc_res(p_scb->hndl, p_scb->PeerAddress(), num, num, 0,
                                UUID_SERVCLASS_AUDIO_SOURCE);
     } else {
       /* we do not know the peer device and it is using non-SBC codec
@@ -1176,11 +1196,11 @@
   uint16_t mtu;
 
   APPL_TRACE_DEBUG("%s: peer %s handle: %d", __func__,
-                   p_scb->peer_addr.ToString().c_str(), p_scb->hndl);
+                   p_scb->PeerAddress().ToString().c_str(), p_scb->hndl);
 
   msg.hdr.layer_specific = p_scb->hndl;
   msg.is_up = true;
-  msg.peer_addr = p_scb->peer_addr;
+  msg.peer_addr = p_scb->PeerAddress();
   p_scb->l2c_cid = AVDT_GetL2CapChannel(p_scb->avdt_handle);
   bta_av_conn_chg((tBTA_AV_DATA*)&msg);
   /* set the congestion flag, so AV would not send media packets by accident */
@@ -1198,11 +1218,11 @@
   L2CA_SetTxPriority(p_scb->l2c_cid, L2CAP_CHNL_PRIORITY_HIGH);
   L2CA_SetChnlFlushability(p_scb->l2c_cid, true);
 
-  bta_sys_conn_open(BTA_ID_AV, p_scb->app_id, p_scb->peer_addr);
+  bta_sys_conn_open(BTA_ID_AV, p_scb->app_id, p_scb->PeerAddress());
   memset(&p_scb->q_info, 0, sizeof(tBTA_AV_Q_INFO));
 
   p_scb->l2c_bufs = 0;
-  p_scb->p_cos->open(p_scb->hndl, p_scb->peer_addr, mtu);
+  p_scb->p_cos->open(p_scb->hndl, p_scb->PeerAddress(), mtu);
 
   {
     /* TODO check if other audio channel is open.
@@ -1216,17 +1236,18 @@
      */
     /* check if other audio channel is started. If yes, start */
     tBTA_AV_OPEN open;
-    open.bd_addr = p_scb->peer_addr;
+    open.bd_addr = p_scb->PeerAddress();
     open.chnl = p_scb->chnl;
     open.hndl = p_scb->hndl;
     open.status = BTA_AV_SUCCESS;
     open.starting = bta_av_chk_start(p_scb);
     open.edr = 0;
-    p = BTM_ReadRemoteFeatures(p_scb->peer_addr);
+    p = BTM_ReadRemoteFeatures(p_scb->PeerAddress());
     if (p != NULL) {
       if (HCI_EDR_ACL_2MPS_SUPPORTED(p)) open.edr |= BTA_AV_EDR_2MBPS;
       if (HCI_EDR_ACL_3MPS_SUPPORTED(p)) {
-        if (!interop_match_addr(INTEROP_2MBPS_LINK_ONLY, &p_scb->peer_addr)) {
+        if (!interop_match_addr(INTEROP_2MBPS_LINK_ONLY,
+                                &p_scb->PeerAddress())) {
           open.edr |= BTA_AV_EDR_3MBPS;
         }
       }
@@ -1357,7 +1378,7 @@
  ******************************************************************************/
 void bta_av_connect_req(tBTA_AV_SCB* p_scb, UNUSED_ATTR tBTA_AV_DATA* p_data) {
   APPL_TRACE_DEBUG("%s: peer %s coll_mask:0x%x", __func__,
-                   p_scb->peer_addr.ToString().c_str(), p_scb->coll_mask);
+                   p_scb->PeerAddress().ToString().c_str(), p_scb->coll_mask);
   p_scb->sdp_discovery_started = false;
   if (p_scb->coll_mask & BTA_AV_COLL_INC_TMR) {
     /* SNK initiated L2C connection while SRC was doing SDP.    */
@@ -1369,7 +1390,7 @@
     return;
   }
 
-  AVDT_ConnectReq(p_scb->peer_addr, p_scb->hdi, p_scb->sec_mask,
+  AVDT_ConnectReq(p_scb->PeerAddress(), p_scb->hdi, p_scb->sec_mask,
                   &bta_av_proc_stream_evt);
 }
 
@@ -1384,7 +1405,7 @@
  ******************************************************************************/
 void bta_av_sdp_failed(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) {
   APPL_TRACE_ERROR("%s: peer_addr=%s open_status=%d", __func__,
-                   p_scb->peer_addr.ToString().c_str(), p_scb->open_status);
+                   p_scb->PeerAddress().ToString().c_str(), p_scb->open_status);
 
   if (p_scb->open_status == BTA_AV_SUCCESS) {
     p_scb->open_status = BTA_AV_FAIL_SDP;
@@ -1411,7 +1432,8 @@
   uint16_t uuid_int = p_scb->uuid_int;
 
   APPL_TRACE_DEBUG("%s: peer %s handle: %d initiator UUID 0x%x", __func__,
-                   p_scb->peer_addr.ToString().c_str(), p_scb->hndl, uuid_int);
+                   p_scb->PeerAddress().ToString().c_str(), p_scb->hndl,
+                   uuid_int);
 
   /* store number of stream endpoints returned */
   p_scb->num_seps = p_data->str_msg.msg.discover_cfm.num_seps;
@@ -1430,7 +1452,7 @@
     }
   }
 
-  p_scb->p_cos->disc_res(p_scb->hndl, p_scb->peer_addr, p_scb->num_seps,
+  p_scb->p_cos->disc_res(p_scb->hndl, p_scb->PeerAddress(), p_scb->num_seps,
                          num_snks, num_srcs, uuid_int);
   p_scb->num_disc_snks = num_snks;
   p_scb->num_disc_srcs = num_srcs;
@@ -1446,7 +1468,7 @@
   /* else we got discover response but with no streams; we're done */
   else {
     APPL_TRACE_ERROR("%s: BTA_AV_STR_DISC_FAIL_EVT: peer_addr=%s", __func__,
-                     p_scb->peer_addr.ToString().c_str());
+                     p_scb->PeerAddress().ToString().c_str());
     bta_av_ssm_execute(p_scb, BTA_AV_STR_DISC_FAIL_EVT, p_data);
   }
 }
@@ -1466,7 +1488,7 @@
   uint8_t num_snks = 0, i;
 
   APPL_TRACE_DEBUG("%s: peer %s handle: %d", __func__,
-                   p_scb->peer_addr.ToString().c_str(), p_scb->hndl);
+                   p_scb->PeerAddress().ToString().c_str(), p_scb->hndl);
 
   /* store number of stream endpoints returned */
   p_scb->num_seps = p_data->str_msg.msg.discover_cfm.num_seps;
@@ -1479,7 +1501,7 @@
       num_snks++;
     }
   }
-  p_scb->p_cos->disc_res(p_scb->hndl, p_scb->peer_addr, p_scb->num_seps,
+  p_scb->p_cos->disc_res(p_scb->hndl, p_scb->PeerAddress(), p_scb->num_seps,
                          num_snks, 0, UUID_SERVCLASS_AUDIO_SOURCE);
   p_scb->num_disc_snks = num_snks;
   p_scb->num_disc_srcs = 0;
@@ -1495,7 +1517,7 @@
   /* else we got discover response but with no streams; we're done */
   else {
     APPL_TRACE_ERROR("%s: BTA_AV_STR_DISC_FAIL_EVT: peer_addr=%s", __func__,
-                     p_scb->peer_addr.ToString().c_str());
+                     p_scb->PeerAddress().ToString().c_str());
     bta_av_ssm_execute(p_scb, BTA_AV_STR_DISC_FAIL_EVT, p_data);
   }
 }
@@ -1517,14 +1539,14 @@
 
   APPL_TRACE_DEBUG(
       "%s: peer %s handle:%d num_seps:%d sep_info_idx:%d wait:0x%x", __func__,
-      p_scb->peer_addr.ToString().c_str(), p_scb->hndl, p_scb->num_seps,
+      p_scb->PeerAddress().ToString().c_str(), p_scb->hndl, p_scb->num_seps,
       p_scb->sep_info_idx, p_scb->wait);
   APPL_TRACE_DEBUG("%s: codec: %s", __func__,
                    A2DP_CodecInfoString(p_scb->peer_cap.codec_info).c_str());
 
   cfg = p_scb->peer_cap;
   /* let application know the capability of the SNK */
-  if (p_scb->p_cos->getcfg(p_scb->hndl, p_scb->peer_addr, cfg.codec_info,
+  if (p_scb->p_cos->getcfg(p_scb->hndl, p_scb->PeerAddress(), cfg.codec_info,
                            &p_scb->sep_info_idx, p_info->seid, &cfg.num_protect,
                            cfg.protect_info) != A2DP_SUCCESS) {
     p_scb->sep_info_idx++;
@@ -1586,11 +1608,11 @@
   uint16_t mtu;
 
   APPL_TRACE_DEBUG("%s: peer %s handle:%d", __func__,
-                   p_scb->peer_addr.ToString().c_str(), p_scb->hndl);
+                   p_scb->PeerAddress().ToString().c_str(), p_scb->hndl);
 
   mtu = bta_av_chk_mtu(p_scb, BTA_AV_MAX_A2DP_MTU);
 
-  p_scb->p_cos->close(p_scb->hndl, p_scb->peer_addr);
+  p_scb->p_cos->close(p_scb->hndl, p_scb->PeerAddress());
 }
 
 /*******************************************************************************
@@ -1608,7 +1630,7 @@
   uint8_t idx;
 
   APPL_TRACE_ERROR("%s: peer_addr=%s", __func__,
-                   p_scb->peer_addr.ToString().c_str());
+                   p_scb->PeerAddress().ToString().c_str());
   p_scb->open_status = BTA_AV_FAIL_STREAM;
   bta_av_cco_close(p_scb, p_data);
 
@@ -1617,7 +1639,7 @@
   for (idx = 0; (idx < BTA_AV_NUM_STRS) && (!is_av_opened); idx++) {
     p_opened_scb = bta_av_cb.p_scb[idx];
     if (p_opened_scb && (p_opened_scb->state == BTA_AV_OPEN_SST) &&
-        (p_opened_scb->peer_addr == p_scb->peer_addr))
+        (p_opened_scb->PeerAddress() == p_scb->PeerAddress()))
       is_av_opened = true;
   }
 
@@ -1626,7 +1648,7 @@
      BTA_AV_FAIL_GET_CAP status */
   if (is_av_opened) {
     tBTA_AV_OPEN open;
-    open.bd_addr = p_scb->peer_addr;
+    open.bd_addr = p_scb->PeerAddress();
     open.chnl = p_scb->chnl;
     open.hndl = p_scb->hndl;
     open.status = BTA_AV_FAIL_GET_CAP;
@@ -1651,7 +1673,7 @@
     bta_av_data.open = open;
     (*bta_av_cb.p_cback)(BTA_AV_OPEN_EVT, &bta_av_data);
   } else {
-    AVDT_DisconnectReq(p_scb->peer_addr, &bta_av_proc_stream_evt);
+    AVDT_DisconnectReq(p_scb->PeerAddress(), &bta_av_proc_stream_evt);
   }
 }
 
@@ -1677,7 +1699,7 @@
   memcpy(cfg.protect_info, p_scb->peer_cap.protect_info, AVDT_PROTECT_SIZE);
 
   APPL_TRACE_DEBUG("%s: peer %s handle:%d num_codec:%d psc_mask=0x%x", __func__,
-                   p_scb->peer_addr.ToString().c_str(), p_scb->hndl,
+                   p_scb->PeerAddress().ToString().c_str(), p_scb->hndl,
                    p_scb->peer_cap.num_codec, p_scb->cfg.psc_mask);
   APPL_TRACE_DEBUG("%s: media type 0x%x, 0x%x", __func__, media_type,
                    p_scb->media_type);
@@ -1686,9 +1708,10 @@
 
   /* if codec present and we get a codec configuration */
   if ((p_scb->peer_cap.num_codec != 0) && (media_type == p_scb->media_type) &&
-      (p_scb->p_cos->getcfg(
-           p_scb->hndl, p_scb->peer_addr, cfg.codec_info, &p_scb->sep_info_idx,
-           p_info->seid, &cfg.num_protect, cfg.protect_info) == A2DP_SUCCESS)) {
+      (p_scb->p_cos->getcfg(p_scb->hndl, p_scb->PeerAddress(), cfg.codec_info,
+                            &p_scb->sep_info_idx, p_info->seid,
+                            &cfg.num_protect,
+                            cfg.protect_info) == A2DP_SUCCESS)) {
     /* UUID for which connection was initiatied */
     uint16_t uuid_int = p_scb->uuid_int;
 
@@ -1714,14 +1737,14 @@
     APPL_TRACE_DEBUG(
         "%s: peer %s handle:%d sep_idx:%d sep_info_idx:%d "
         "cur_psc_mask:0x%x",
-        __func__, p_scb->peer_addr.ToString().c_str(), p_scb->hndl,
+        __func__, p_scb->PeerAddress().ToString().c_str(), p_scb->hndl,
         p_scb->sep_idx, p_scb->sep_info_idx, p_scb->cur_psc_mask);
 
     if ((uuid_int == UUID_SERVCLASS_AUDIO_SINK) &&
         (p_scb->seps[p_scb->sep_idx].p_app_sink_data_cback != NULL)) {
       APPL_TRACE_DEBUG("%s: configure decoder for Sink connection", __func__);
       tBTA_AV_MEDIA av_sink_codec_info;
-      av_sink_codec_info.avk_config.bd_addr = p_scb->peer_addr;
+      av_sink_codec_info.avk_config.bd_addr = p_scb->PeerAddress();
       av_sink_codec_info.avk_config.codec_info = p_scb->cfg.codec_info;
       p_scb->seps[p_scb->sep_idx].p_app_sink_data_cback(
           BTA_AV_SINK_MEDIA_CFG_EVT, &av_sink_codec_info);
@@ -1732,7 +1755,7 @@
     }
 
     /* open the stream */
-    AVDT_OpenReq(p_scb->seps[p_scb->sep_idx].av_handle, p_scb->peer_addr,
+    AVDT_OpenReq(p_scb->seps[p_scb->sep_idx].av_handle, p_scb->PeerAddress(),
                  p_scb->hdi, p_scb->sep_info[p_scb->sep_info_idx].seid, &cfg);
   } else {
     /* try the next stream, if any */
@@ -1778,7 +1801,7 @@
 void bta_av_discover_req(tBTA_AV_SCB* p_scb, UNUSED_ATTR tBTA_AV_DATA* p_data) {
   /* send avdtp discover request */
 
-  AVDT_DiscoverReq(p_scb->peer_addr, p_scb->hdi, p_scb->sep_info,
+  AVDT_DiscoverReq(p_scb->PeerAddress(), p_scb->hdi, p_scb->sep_info,
                    BTA_AV_NUM_SEPS, &bta_av_proc_stream_evt);
 }
 
@@ -1793,7 +1816,7 @@
  ******************************************************************************/
 void bta_av_conn_failed(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) {
   APPL_TRACE_ERROR("%s: peer_addr=%s open_status=%d", __func__,
-                   p_scb->peer_addr.ToString().c_str(), p_scb->open_status);
+                   p_scb->PeerAddress().ToString().c_str(), p_scb->open_status);
 
   p_scb->open_status = BTA_AV_FAIL_STREAM;
   bta_av_str_closed(p_scb, p_data);
@@ -1822,16 +1845,16 @@
   /* disallow role switch during streaming, only if we are the master role
    * i.e. allow role switch, if we are slave.
    * It would not hurt us, if the peer device wants us to be master */
-  if ((BTM_GetRole(p_scb->peer_addr, &cur_role) == BTM_SUCCESS) &&
+  if ((BTM_GetRole(p_scb->PeerAddress(), &cur_role) == BTM_SUCCESS) &&
       (cur_role == BTM_ROLE_MASTER)) {
     policy |= HCI_ENABLE_MASTER_SLAVE_SWITCH;
   }
 
-  bta_sys_clear_policy(BTA_ID_AV, policy, p_scb->peer_addr);
+  bta_sys_clear_policy(BTA_ID_AV, policy, p_scb->PeerAddress());
 
   if ((!p_scb->started) && ((p_scb->role & BTA_AV_ROLE_START_INT) == 0)) {
     p_scb->role |= BTA_AV_ROLE_START_INT;
-    bta_sys_busy(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->peer_addr);
+    bta_sys_busy(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->PeerAddress());
 
     AVDT_StartReq(&p_scb->avdt_handle, 1);
   } else if (p_scb->started) {
@@ -1866,14 +1889,14 @@
 
   APPL_TRACE_ERROR(
       "%s: peer %s handle:%d audio_open_cnt:%d, p_data %p start:%d", __func__,
-      p_scb->peer_addr.ToString().c_str(), p_scb->hndl,
+      p_scb->PeerAddress().ToString().c_str(), p_scb->hndl,
       bta_av_cb.audio_open_cnt, p_data, start);
 
-  bta_sys_idle(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->peer_addr);
+  bta_sys_idle(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->PeerAddress());
   if ((bta_av_cb.features & BTA_AV_FEAT_MASTER) == 0 ||
       bta_av_cb.audio_open_cnt == 1)
     policy |= HCI_ENABLE_MASTER_SLAVE_SWITCH;
-  bta_sys_set_policy(BTA_ID_AV, policy, p_scb->peer_addr);
+  bta_sys_set_policy(BTA_ID_AV, policy, p_scb->PeerAddress());
 
   if (p_scb->co_started) {
     if (p_scb->offload_started) {
@@ -1884,8 +1907,8 @@
     bta_av_stream_chg(p_scb, false);
     p_scb->co_started = false;
 
-    p_scb->p_cos->stop(p_scb->hndl, p_scb->peer_addr);
-    L2CA_SetFlushTimeout(p_scb->peer_addr, L2CAP_DEFAULT_FLUSH_TO);
+    p_scb->p_cos->stop(p_scb->hndl, p_scb->PeerAddress());
+    L2CA_SetFlushTimeout(p_scb->PeerAddress(), L2CAP_DEFAULT_FLUSH_TO);
   }
 
   /* if q_info.a2dp_list is not empty, drop it now */
@@ -2144,7 +2167,7 @@
           list_prepend(p_scb->a2dp_list, p_buf);
         } else {
           /* too many buffers in a2dp_list, drop it. */
-          bta_av_co_audio_drop(p_scb->hndl, p_scb->peer_addr);
+          bta_av_co_audio_drop(p_scb->hndl, p_scb->PeerAddress());
           osi_free(p_buf);
         }
       }
@@ -2172,15 +2195,15 @@
   uint8_t local_tsep = p_scb->seps[p_scb->sep_idx].tsep;
 
   APPL_TRACE_DEBUG("%s: peer %s handle:%d wait:0x%x role:0x%x local_tsep:%d",
-                   __func__, p_scb->peer_addr.ToString().c_str(), p_scb->hndl,
-                   p_scb->wait, p_scb->role, local_tsep);
+                   __func__, p_scb->PeerAddress().ToString().c_str(),
+                   p_scb->hndl, p_scb->wait, p_scb->role, local_tsep);
 
   p_scb->started = true;
 
   if (local_tsep == AVDT_TSEP_SRC) {
     // The RTP Header marker bit for the A2DP Source encoder
     A2dpCodecConfig* codec_config =
-        bta_av_get_a2dp_peer_current_codec(p_scb->peer_addr);
+        bta_av_get_a2dp_peer_current_codec(p_scb->PeerAddress());
     CHECK(codec_config != nullptr);
     p_scb->use_rtp_header_marker_bit = codec_config->useRtpHeaderMarkerBit();
   }
@@ -2202,20 +2225,21 @@
     /* role switch has failed */
     APPL_TRACE_ERROR(
         "%s: peer %s role switch failed: handle:%d wait:0x%x, role:0x%x",
-        __func__, p_scb->peer_addr.ToString().c_str(), p_scb->hndl, p_scb->wait,
-        p_scb->role);
+        __func__, p_scb->PeerAddress().ToString().c_str(), p_scb->hndl,
+        p_scb->wait, p_scb->role);
     p_scb->wait &= ~BTA_AV_WAIT_ROLE_SW_FAILED;
     p_data = (tBTA_AV_DATA*)&hdr;
     hdr.offset = BTA_AV_RS_FAIL;
   }
   APPL_TRACE_DEBUG("%s: peer %s wait:0x%x use_rtp_header_marker_bit:%s",
-                   __func__, p_scb->peer_addr.ToString().c_str(), p_scb->wait,
+                   __func__, p_scb->PeerAddress().ToString().c_str(),
+                   p_scb->wait,
                    (p_scb->use_rtp_header_marker_bit) ? "true" : "false");
 
   if (p_data && (p_data->hdr.offset != BTA_AV_RS_NONE)) {
     p_scb->wait &= ~BTA_AV_WAIT_ROLE_SW_BITS;
     if (p_data->hdr.offset == BTA_AV_RS_FAIL) {
-      bta_sys_idle(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->peer_addr);
+      bta_sys_idle(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->PeerAddress());
       tBTA_AV_START start;
       start.chnl = p_scb->chnl;
       start.status = BTA_AV_FAIL_ROLE;
@@ -2248,7 +2272,7 @@
 
   if (p_scb->wait) {
     APPL_TRACE_ERROR("%s: peer %s wait:0x%x q_tag:%d not started", __func__,
-                     p_scb->peer_addr.ToString().c_str(), p_scb->wait,
+                     p_scb->PeerAddress().ToString().c_str(), p_scb->wait,
                      p_scb->q_tag);
     /* Clear first bit of p_scb->wait and not to return from this point else
      * HAL layer gets blocked. And if there is delay in Get Capability response
@@ -2261,9 +2285,9 @@
   }
 
   /* tell role manager to check M/S role */
-  bta_sys_conn_open(BTA_ID_AV, p_scb->app_id, p_scb->peer_addr);
+  bta_sys_conn_open(BTA_ID_AV, p_scb->app_id, p_scb->PeerAddress());
 
-  bta_sys_busy(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->peer_addr);
+  bta_sys_busy(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->PeerAddress());
 
   if (p_scb->media_type == AVDT_MEDIA_TYPE_AUDIO) {
     /* in normal logic, conns should be bta_av_cb.audio_count - 1,
@@ -2277,7 +2301,7 @@
   } else {
     flush_to = 0;
   }
-  L2CA_SetFlushTimeout(p_scb->peer_addr, flush_to);
+  L2CA_SetFlushTimeout(p_scb->PeerAddress(), flush_to);
 
   /* clear the congestion flag */
   p_scb->cong = false;
@@ -2301,12 +2325,12 @@
        * Otherwise allow role switch, if source is slave.
        * Because it would not hurt source, if the peer device wants source to be
        * master */
-      if ((BTM_GetRole(p_scb->peer_addr, &cur_role) == BTM_SUCCESS) &&
+      if ((BTM_GetRole(p_scb->PeerAddress(), &cur_role) == BTM_SUCCESS) &&
           (cur_role == BTM_ROLE_MASTER)) {
         policy |= HCI_ENABLE_MASTER_SLAVE_SWITCH;
       }
 
-      bta_sys_clear_policy(BTA_ID_AV, policy, p_scb->peer_addr);
+      bta_sys_clear_policy(BTA_ID_AV, policy, p_scb->PeerAddress());
     }
 
     p_scb->role = new_role;
@@ -2314,13 +2338,13 @@
     p_scb->role &= ~BTA_AV_ROLE_SUSPEND_OPT;
 
     p_scb->no_rtp_header = false;
-    p_scb->p_cos->start(p_scb->hndl, p_scb->peer_addr, p_scb->cfg.codec_info,
-                        &p_scb->no_rtp_header);
+    p_scb->p_cos->start(p_scb->hndl, p_scb->PeerAddress(),
+                        p_scb->cfg.codec_info, &p_scb->no_rtp_header);
     p_scb->co_started = true;
 
     APPL_TRACE_DEBUG("%s: peer %s suspending: %d, role:0x%x, init %d", __func__,
-                     p_scb->peer_addr.ToString().c_str(), suspend, p_scb->role,
-                     initiator);
+                     p_scb->PeerAddress().ToString().c_str(), suspend,
+                     p_scb->role, initiator);
 
     tBTA_AV_START start;
     start.suspending = suspend;
@@ -2337,7 +2361,7 @@
       p_scb->role |= BTA_AV_ROLE_SUSPEND;
       p_scb->cong = true; /* do not allow the media data to go through */
       /* do not duplicate the media packets to this channel */
-      p_scb->p_cos->stop(p_scb->hndl, p_scb->peer_addr);
+      p_scb->p_cos->stop(p_scb->hndl, p_scb->PeerAddress());
       p_scb->co_started = false;
       stop.flush = false;
       stop.suspend = true;
@@ -2358,13 +2382,13 @@
  ******************************************************************************/
 void bta_av_start_failed(tBTA_AV_SCB* p_scb, UNUSED_ATTR tBTA_AV_DATA* p_data) {
   if (!p_scb->started && !p_scb->co_started) {
-    bta_sys_idle(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->peer_addr);
+    bta_sys_idle(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->PeerAddress());
     notify_start_failed(p_scb);
   }
 
   bta_sys_set_policy(BTA_ID_AV,
                      (HCI_ENABLE_SNIFF_MODE | HCI_ENABLE_MASTER_SLAVE_SWITCH),
-                     p_scb->peer_addr);
+                     p_scb->PeerAddress());
   p_scb->sco_suspend = false;
 }
 
@@ -2384,13 +2408,13 @@
 
   APPL_TRACE_WARNING(
       "%s: peer %s handle:%d open_status:%d chnl:%d co_started:%d", __func__,
-      p_scb->peer_addr.ToString().c_str(), p_scb->hndl, p_scb->open_status,
+      p_scb->PeerAddress().ToString().c_str(), p_scb->hndl, p_scb->open_status,
       p_scb->chnl, p_scb->co_started);
 
   if ((bta_av_cb.features & BTA_AV_FEAT_MASTER) == 0 ||
       bta_av_cb.audio_open_cnt == 1)
     policy |= HCI_ENABLE_MASTER_SLAVE_SWITCH;
-  bta_sys_set_policy(BTA_ID_AV, policy, p_scb->peer_addr);
+  bta_sys_set_policy(BTA_ID_AV, policy, p_scb->PeerAddress());
   if (bta_av_cb.audio_open_cnt <= 1) {
     /* last connection - restore the allow switch flag */
     L2CA_SetDesireRole(L2CAP_ROLE_ALLOW_SWITCH);
@@ -2398,7 +2422,7 @@
 
   if (p_scb->open_status != BTA_AV_SUCCESS) {
     /* must be failure when opening the stream */
-    data.open.bd_addr = p_scb->peer_addr;
+    data.open.bd_addr = p_scb->PeerAddress();
     data.open.status = p_scb->open_status;
     data.open.chnl = p_scb->chnl;
     data.open.hndl = p_scb->hndl;
@@ -2411,7 +2435,7 @@
     event = BTA_AV_OPEN_EVT;
     p_scb->open_status = BTA_AV_SUCCESS;
 
-    bta_sys_conn_close(BTA_ID_AV, p_scb->app_id, p_scb->peer_addr);
+    bta_sys_conn_close(BTA_ID_AV, p_scb->app_id, p_scb->PeerAddress());
     bta_av_cleanup(p_scb, p_data);
     (*bta_av_cb.p_cback)(event, &data);
   } else {
@@ -2421,12 +2445,12 @@
     }
 
     {
-      p_scb->p_cos->close(p_scb->hndl, p_scb->peer_addr);
+      p_scb->p_cos->close(p_scb->hndl, p_scb->PeerAddress());
       data.close.chnl = p_scb->chnl;
       data.close.hndl = p_scb->hndl;
       event = BTA_AV_CLOSE_EVT;
 
-      bta_sys_conn_close(BTA_ID_AV, p_scb->app_id, p_scb->peer_addr);
+      bta_sys_conn_close(BTA_ID_AV, p_scb->app_id, p_scb->PeerAddress());
       bta_av_cleanup(p_scb, p_data);
       (*bta_av_cb.p_cback)(event, &data);
     }
@@ -2464,8 +2488,8 @@
   uint8_t policy = HCI_ENABLE_SNIFF_MODE;
 
   APPL_TRACE_DEBUG("%s: peer %s handle:%d audio_open_cnt:%d err_code:%d",
-                   __func__, p_scb->peer_addr.ToString().c_str(), p_scb->hndl,
-                   bta_av_cb.audio_open_cnt, err_code);
+                   __func__, p_scb->PeerAddress().ToString().c_str(),
+                   p_scb->hndl, bta_av_cb.audio_open_cnt, err_code);
 
   if (!p_scb->started) {
     /* handle the condition where there is a collision of SUSPEND req from
@@ -2499,11 +2523,11 @@
     p_scb->cong = false;
   }
 
-  bta_sys_idle(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->peer_addr);
+  bta_sys_idle(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->PeerAddress());
   if ((bta_av_cb.features & BTA_AV_FEAT_MASTER) == 0 ||
       bta_av_cb.audio_open_cnt == 1)
     policy |= HCI_ENABLE_MASTER_SLAVE_SWITCH;
-  bta_sys_set_policy(BTA_ID_AV, policy, p_scb->peer_addr);
+  bta_sys_set_policy(BTA_ID_AV, policy, p_scb->PeerAddress());
 
   /* in case that we received suspend_ind, we may need to call co_stop here */
   if (p_scb->co_started) {
@@ -2515,9 +2539,9 @@
 
     {
       p_scb->co_started = false;
-      p_scb->p_cos->stop(p_scb->hndl, p_scb->peer_addr);
+      p_scb->p_cos->stop(p_scb->hndl, p_scb->PeerAddress());
     }
-    L2CA_SetFlushTimeout(p_scb->peer_addr, L2CAP_DEFAULT_FLUSH_TO);
+    L2CA_SetFlushTimeout(p_scb->PeerAddress(), L2CAP_DEFAULT_FLUSH_TO);
   }
 
   {
@@ -2542,7 +2566,7 @@
 void bta_av_rcfg_str_ok(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) {
   p_scb->l2c_cid = AVDT_GetL2CapChannel(p_scb->avdt_handle);
   APPL_TRACE_DEBUG("%s: peer %s handle:%d l2c_cid:%d", __func__,
-                   p_scb->peer_addr.ToString().c_str(), p_scb->hndl,
+                   p_scb->PeerAddress().ToString().c_str(), p_scb->hndl,
                    p_scb->l2c_cid);
 
   if (p_data != NULL) {
@@ -2553,7 +2577,7 @@
     APPL_TRACE_DEBUG("%s: l2c_cid: 0x%x stream_mtu: %d mtu: %d", __func__,
                      p_scb->l2c_cid, p_scb->stream_mtu, mtu);
     if (mtu == 0 || mtu > p_scb->stream_mtu) mtu = p_scb->stream_mtu;
-    p_scb->p_cos->update_mtu(p_scb->hndl, p_scb->peer_addr, mtu);
+    p_scb->p_cos->update_mtu(p_scb->hndl, p_scb->PeerAddress(), mtu);
   }
 
   /* rc listen */
@@ -2588,7 +2612,7 @@
 void bta_av_rcfg_failed(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) {
   APPL_TRACE_ERROR("%s: num_recfg=%d conn_lcb=0x%x peer_addr=%s", __func__,
                    p_scb->num_recfg, bta_av_cb.conn_lcb,
-                   p_scb->peer_addr.ToString().c_str());
+                   p_scb->PeerAddress().ToString().c_str());
 
   if (p_scb->num_recfg > BTA_AV_RECONFIG_RETRY) {
     bta_av_cco_close(p_scb, p_data);
@@ -2606,7 +2630,7 @@
     /* open failed. try again */
     p_scb->num_recfg++;
     if (bta_av_cb.conn_lcb) {
-      AVDT_DisconnectReq(p_scb->peer_addr, &bta_av_proc_stream_evt);
+      AVDT_DisconnectReq(p_scb->PeerAddress(), &bta_av_proc_stream_evt);
     } else {
       bta_av_connect_req(p_scb, NULL);
     }
@@ -2632,7 +2656,7 @@
     /* let bta_av_rcfg_failed report fail */
     bta_av_rcfg_failed(p_scb, NULL);
   } else {
-    AVDT_ConnectReq(p_scb->peer_addr, p_scb->hdi, p_scb->sec_mask,
+    AVDT_ConnectReq(p_scb->PeerAddress(), p_scb->hdi, p_scb->sec_mask,
                     &bta_av_proc_stream_evt);
   }
 }
@@ -2649,7 +2673,7 @@
 void bta_av_rcfg_discntd(tBTA_AV_SCB* p_scb, UNUSED_ATTR tBTA_AV_DATA* p_data) {
   APPL_TRACE_ERROR("%s: num_recfg=%d conn_lcb=0x%x peer_addr=%s", __func__,
                    p_scb->num_recfg, bta_av_cb.conn_lcb,
-                   p_scb->peer_addr.ToString().c_str());
+                   p_scb->PeerAddress().ToString().c_str());
 
   p_scb->num_recfg++;
   if (p_scb->num_recfg > BTA_AV_RECONFIG_RETRY) {
@@ -2664,7 +2688,7 @@
     /* report close event & go to init state */
     bta_av_ssm_execute(p_scb, BTA_AV_STR_DISC_FAIL_EVT, NULL);
   } else {
-    AVDT_ConnectReq(p_scb->peer_addr, p_scb->hdi, p_scb->sec_mask,
+    AVDT_ConnectReq(p_scb->PeerAddress(), p_scb->hdi, p_scb->sec_mask,
                     &bta_av_proc_stream_evt);
   }
 }
@@ -2695,7 +2719,7 @@
       bta_av_data.reconfig = reconfig;
       (*bta_av_cb.p_cback)(BTA_AV_RECONFIG_EVT, &bta_av_data);
       APPL_TRACE_ERROR("%s: BTA_AV_STR_DISC_FAIL_EVT: peer_addr=%s", __func__,
-                       p_scb->peer_addr.ToString().c_str());
+                       p_scb->PeerAddress().ToString().c_str());
       bta_av_ssm_execute(p_scb, BTA_AV_STR_DISC_FAIL_EVT, NULL);
     } else {
       APPL_TRACE_ERROR("%s: suspend rejected, try close", __func__);
@@ -2739,14 +2763,16 @@
   bool disable_avdtp_reconfigure = false;
   {
     char remote_name[BTM_MAX_REM_BD_NAME_LEN] = "";
-    if (btif_storage_get_stored_remote_name(p_scb->peer_addr, remote_name)) {
+    if (btif_storage_get_stored_remote_name(p_scb->PeerAddress(),
+                                            remote_name)) {
       if (interop_match_name(INTEROP_DISABLE_AVDTP_RECONFIGURE, remote_name) ||
           interop_match_addr(INTEROP_DISABLE_AVDTP_RECONFIGURE,
-                             (const RawAddress*)&p_scb->peer_addr)) {
+                             (const RawAddress*)&p_scb->PeerAddress())) {
         LOG_INFO(LOG_TAG,
                  "%s: disable AVDTP RECONFIGURE: interop matched "
                  "name %s address %s",
-                 __func__, remote_name, p_scb->peer_addr.ToString().c_str());
+                 __func__, remote_name,
+                 p_scb->PeerAddress().ToString().c_str());
         disable_avdtp_reconfigure = true;
       }
     }
@@ -2788,15 +2814,15 @@
  ******************************************************************************/
 void bta_av_rcfg_open(tBTA_AV_SCB* p_scb, UNUSED_ATTR tBTA_AV_DATA* p_data) {
   APPL_TRACE_DEBUG("%s: peer %s handle:%d num_disc_snks:%d", __func__,
-                   p_scb->peer_addr.ToString().c_str(), p_scb->hndl,
+                   p_scb->PeerAddress().ToString().c_str(), p_scb->hndl,
                    p_scb->num_disc_snks);
 
   if (p_scb->num_disc_snks == 0) {
     /* Need to update call-out module so that it will be ready for discover */
-    p_scb->p_cos->stop(p_scb->hndl, p_scb->peer_addr);
+    p_scb->p_cos->stop(p_scb->hndl, p_scb->PeerAddress());
 
     /* send avdtp discover request */
-    AVDT_DiscoverReq(p_scb->peer_addr, p_scb->hdi, p_scb->sep_info,
+    AVDT_DiscoverReq(p_scb->PeerAddress(), p_scb->hdi, p_scb->sep_info,
                      BTA_AV_NUM_SEPS, &bta_av_proc_stream_evt);
   } else {
     APPL_TRACE_DEBUG("%s: calling AVDT_OpenReq()", __func__);
@@ -2809,7 +2835,7 @@
 
     /* open the stream with the new config */
     p_scb->sep_info_idx = p_scb->rcfg_idx;
-    AVDT_OpenReq(p_scb->avdt_handle, p_scb->peer_addr, p_scb->hdi,
+    AVDT_OpenReq(p_scb->avdt_handle, p_scb->PeerAddress(), p_scb->hdi,
                  p_scb->sep_info[p_scb->sep_info_idx].seid, &p_scb->cfg);
   }
 }
@@ -2861,7 +2887,7 @@
           if (p_scbi->co_started != bta_av_cb.audio_open_cnt) {
             p_scbi->co_started = bta_av_cb.audio_open_cnt;
             L2CA_SetFlushTimeout(
-                p_scbi->peer_addr,
+                p_scbi->PeerAddress(),
                 p_bta_av_cfg->p_audio_flush_to[p_scbi->co_started - 1]);
           }
         }
@@ -2926,7 +2952,8 @@
       /* use main SM for AVRC SDP activities */
       if (is_new_avrcp_enabled()) {
         APPL_TRACE_WARNING("%s: Using the new AVRCP Profile", __func__);
-        bluetooth::avrcp::AvrcpService::Get()->ConnectDevice(p_scb->peer_addr);
+        bluetooth::avrcp::AvrcpService::Get()->ConnectDevice(
+            p_scb->PeerAddress());
       } else {
         bta_av_rc_disc((uint8_t)(p_scb->hdi + 1));
       }
@@ -2954,7 +2981,7 @@
   memcpy(&(p_scb->open_api), &(p_data->api_open), sizeof(tBTA_AV_API_OPEN));
 
   APPL_TRACE_DEBUG("%s: peer %s coll_mask:0x%x", __func__,
-                   p_scb->peer_addr.ToString().c_str(), p_scb->coll_mask);
+                   p_scb->PeerAddress().ToString().c_str(), p_scb->coll_mask);
 
   if (p_scb->coll_mask & BTA_AV_COLL_INC_TMR) {
     p_scb->coll_mask |= BTA_AV_COLL_API_CALLED;
@@ -3173,8 +3200,9 @@
   p_a2dp_offload->max_latency = 0;
   p_a2dp_offload->mtu = mtu;
   p_a2dp_offload->acl_hdl =
-      BTM_GetHCIConnHandle(p_scb->peer_addr, BT_TRANSPORT_BR_EDR);
-  p_a2dp_offload->scms_t_enable = p_scb->p_cos->cp_is_active(p_scb->peer_addr);
+      BTM_GetHCIConnHandle(p_scb->PeerAddress(), BT_TRANSPORT_BR_EDR);
+  p_a2dp_offload->scms_t_enable =
+      p_scb->p_cos->cp_is_active(p_scb->PeerAddress());
   APPL_TRACE_DEBUG("%s: scms_t_enable =%d", __func__,
                    p_a2dp_offload->scms_t_enable);
 
diff --git a/bta/av/bta_av_act.cc b/bta/av/bta_av_act.cc
index 8dc0b3d..df992dc 100644
--- a/bta/av/bta_av_act.cc
+++ b/bta/av/bta_av_act.cc
@@ -319,7 +319,7 @@
   tBTA_AV_RCB* p_rcb;
 
   if (role == AVCT_INT) {
-    bda = p_scb->peer_addr;
+    bda = p_scb->PeerAddress();
     status = BTA_AV_RC_ROLE_INT;
   } else {
     p_rcb = bta_av_get_rcb_by_shdl(shdl);
@@ -486,7 +486,7 @@
   /* find the SCB & stop the timer */
   for (i = 0; i < BTA_AV_NUM_STRS; i++) {
     p_scb = p_cb->p_scb[i];
-    if (p_scb && p_scb->peer_addr == p_data->rc_conn_chg.peer_addr) {
+    if (p_scb && p_scb->PeerAddress() == p_data->rc_conn_chg.peer_addr) {
       p_scb->rc_handle = p_data->rc_conn_chg.handle;
       APPL_TRACE_DEBUG("%s: shdl:%d, srch %d", __func__, i + 1,
                        p_scb->rc_handle);
@@ -1081,11 +1081,11 @@
   if (started) {
     bta_av_cb.audio_streams |= started_msk;
     /* Let L2CAP know this channel is processed with high priority */
-    L2CA_SetAclPriority(p_scb->peer_addr, L2CAP_PRIORITY_HIGH);
+    L2CA_SetAclPriority(p_scb->PeerAddress(), L2CAP_PRIORITY_HIGH);
   } else {
     bta_av_cb.audio_streams &= ~started_msk;
     /* Let L2CAP know this channel is processed with low priority */
-    L2CA_SetAclPriority(p_scb->peer_addr, L2CAP_PRIORITY_NORMAL);
+    L2CA_SetAclPriority(p_scb->PeerAddress(), L2CAP_PRIORITY_NORMAL);
   }
 }
 
@@ -1199,10 +1199,8 @@
     /* clear the conned mask for this channel */
     p_cb->conn_audio &= ~mask;
     if (p_scb) {
-      /* the stream is closed.
-       * clear the peer address, so it would not mess up the AVRCP for the next
-       * round of operation */
-      p_scb->peer_addr = RawAddress::kEmpty;
+      // The stream is closed. Clear the state.
+      p_scb->OnDisconnected();
       if (p_scb->chnl == BTA_AV_CHNL_AUDIO) {
         if (p_lcb) {
           p_lcb->conn_msk &= ~conn_msk;
@@ -1268,7 +1266,7 @@
           if (p_scbi->co_started != bta_av_cb.audio_open_cnt) {
             p_scbi->co_started = bta_av_cb.audio_open_cnt;
             L2CA_SetFlushTimeout(
-                p_scbi->peer_addr,
+                p_scbi->PeerAddress(),
                 p_bta_av_cfg->p_audio_flush_to[p_scbi->co_started - 1]);
           }
         }
@@ -1366,7 +1364,7 @@
           if (p_data->hdr.offset == AVDT_ACP) {
             APPL_TRACE_DEBUG(
                 "%s: Incoming L2CAP acquired, set state as incoming", __func__);
-            p_cb->p_scb[xx]->peer_addr = p_data->str_msg.bd_addr;
+            p_cb->p_scb[xx]->OnConnected(p_data->str_msg.bd_addr);
             p_cb->p_scb[xx]->use_rc =
                 true; /* allowing RC for incoming connection */
             bta_av_ssm_execute(p_cb->p_scb[xx], BTA_AV_ACP_CONNECT_EVT, p_data);
@@ -1382,7 +1380,7 @@
 
             APPL_TRACE_DEBUG("%s: Re-start timer for AVDTP service", __func__);
             bta_sys_conn_open(BTA_ID_AV, p_cb->p_scb[xx]->app_id,
-                              p_cb->p_scb[xx]->peer_addr);
+                              p_cb->p_scb[xx]->PeerAddress());
             /* Possible collision : need to avoid outgoing processing while the
              * timer is running */
             p_cb->p_scb[xx]->coll_mask = BTA_AV_COLL_INC_TMR;
@@ -1422,18 +1420,18 @@
       /* clean up ssm  */
       for (xx = 0; xx < BTA_AV_NUM_STRS; xx++) {
         if (p_cb->p_scb[xx] &&
-            p_cb->p_scb[xx]->peer_addr == p_data->str_msg.bd_addr) {
+            p_cb->p_scb[xx]->PeerAddress() == p_data->str_msg.bd_addr) {
           APPL_TRACE_DEBUG("%s: Closing timer for AVDTP service", __func__);
           bta_sys_conn_close(BTA_ID_AV, p_cb->p_scb[xx]->app_id,
-                             p_cb->p_scb[xx]->peer_addr);
+                             p_cb->p_scb[xx]->PeerAddress());
         }
         mask = 1 << (xx + 1);
         if (((mask & p_lcb->conn_msk) || bta_av_cb.conn_lcb) &&
             p_cb->p_scb[xx] &&
-            p_cb->p_scb[xx]->peer_addr == p_data->str_msg.bd_addr) {
+            p_cb->p_scb[xx]->PeerAddress() == p_data->str_msg.bd_addr) {
           APPL_TRACE_WARNING("%s: Sending AVDT_DISCONNECT_EVT peer_addr=%s",
                              __func__,
-                             p_cb->p_scb[xx]->peer_addr.ToString().c_str());
+                             p_cb->p_scb[xx]->PeerAddress().ToString().c_str());
           bta_av_ssm_execute(p_cb->p_scb[xx], BTA_AV_AVDT_DISCONNECT_EVT, NULL);
         }
       }
@@ -1775,7 +1773,7 @@
             (peer_features & BTA_AV_FEAT_RCTG)) ||
            ((p_cb->features & BTA_AV_FEAT_RCTG) &&
             (peer_features & BTA_AV_FEAT_RCCT)))) {
-        p_lcb = bta_av_find_lcb(p_scb->peer_addr, BTA_AV_LCB_FIND);
+        p_lcb = bta_av_find_lcb(p_scb->PeerAddress(), BTA_AV_LCB_FIND);
         if (p_lcb) {
           rc_handle = bta_av_rc_create(p_cb, AVCT_INT,
                                        (uint8_t)(p_scb->hdi + 1), p_lcb->lidx);
@@ -1787,7 +1785,7 @@
         /* can not find AVRC on peer device. report failure */
         p_scb->use_rc = false;
         tBTA_AV_RC_OPEN rc_open;
-        rc_open.peer_addr = p_scb->peer_addr;
+        rc_open.peer_addr = p_scb->PeerAddress();
         rc_open.peer_features = 0;
         rc_open.status = BTA_AV_FAIL_SDP;
         tBTA_AV bta_av_data;
@@ -1808,7 +1806,7 @@
        */
       rc_feat.peer_addr = p_cb->lcb[p_cb->rcb[rc_handle].lidx].addr;
     } else {
-      rc_feat.peer_addr = p_scb->peer_addr;
+      rc_feat.peer_addr = p_scb->PeerAddress();
     }
     tBTA_AV bta_av_data;
     bta_av_data.rc_feat = rc_feat;
@@ -1853,7 +1851,7 @@
           p_scb = bta_av_cb.p_scb[p_rcb->shdl - 1];
         }
         if (p_scb) {
-          rc_close.peer_addr = p_scb->peer_addr;
+          rc_close.peer_addr = p_scb->PeerAddress();
           if (p_scb->rc_handle == p_rcb->handle)
             p_scb->rc_handle = BTA_AV_RC_HANDLE_NONE;
           APPL_TRACE_DEBUG("%s: shdl:%d, srch:%d", __func__, p_rcb->shdl,
@@ -1971,7 +1969,7 @@
                           ATTR_ID_SUPPORTED_FEATURES};
   uint8_t hdi;
   tBTA_AV_SCB* p_scb;
-  RawAddress* p_addr = NULL;
+  RawAddress peer_addr = RawAddress::kEmpty;
   uint8_t rc_handle;
 
   APPL_TRACE_DEBUG("%s: disc: 0x%x, bta_av_cb.disc: 0x%x", __func__, disc,
@@ -1982,7 +1980,7 @@
     /* this is the rc handle/index to tBTA_AV_RCB */
     rc_handle = disc & (~BTA_AV_CHNL_MSK);
     if (p_cb->rcb[rc_handle].lidx) {
-      p_addr = &p_cb->lcb[p_cb->rcb[rc_handle].lidx - 1].addr;
+      peer_addr = p_cb->lcb[p_cb->rcb[rc_handle].lidx - 1].addr;
     }
   } else {
     hdi = (disc & BTA_AV_HNDL_MSK) - 1;
@@ -1990,11 +1988,11 @@
 
     if (p_scb) {
       APPL_TRACE_DEBUG("%s: rc_handle %d", __func__, p_scb->rc_handle);
-      p_addr = &p_scb->peer_addr;
+      peer_addr = p_scb->PeerAddress();
     }
   }
 
-  if (p_addr) {
+  if (!peer_addr.IsEmpty()) {
     /* allocate discovery database */
     if (p_cb->p_disc_db == NULL)
       p_cb->p_disc_db = (tSDP_DISCOVERY_DB*)osi_malloc(BTA_AV_DISC_BUF_SIZE);
@@ -2006,7 +2004,8 @@
     db_params.p_attrs = attr_list;
 
     /* searching for UUID_SERVCLASS_AV_REMOTE_CONTROL gets both TG and CT */
-    if (AVRC_FindService(UUID_SERVCLASS_AV_REMOTE_CONTROL, *p_addr, &db_params,
+    if (AVRC_FindService(UUID_SERVCLASS_AV_REMOTE_CONTROL, peer_addr,
+                         &db_params,
                          base::Bind(bta_av_avrc_sdp_cback)) == AVRC_SUCCESS) {
       p_cb->disc = disc;
       APPL_TRACE_DEBUG("%s: disc 0x%x", __func__, p_cb->disc);
diff --git a/bta/av/bta_av_int.h b/bta/av/bta_av_int.h
index 004552c..e5f0b5a 100644
--- a/bta/av/bta_av_int.h
+++ b/bta/av/bta_av_int.h
@@ -369,7 +369,6 @@
 /* data type for BTA_AV_SDP_DISC_OK_EVT */
 typedef struct {
   BT_HDR hdr;
-  uint16_t avdt_version; /* AVDTP protocol version */
 } tBTA_AV_SDP_RES;
 
 /* data type for BTA_AV_API_OFFLOAD_RSP_EVT */
@@ -456,7 +455,9 @@
   0x02 /* API open was called while incoming timer is running */
 
 /* type for AV stream control block */
-struct tBTA_AV_SCB {
+// TODO: This should be renamed and changed to a proper class
+struct tBTA_AV_SCB final {
+ public:
   const tBTA_AV_ACT* p_act_tbl; /* the action table for stream state machine */
   const tBTA_AV_CO_FUNCTS* p_cos; /* the associated callout functions */
   bool sdp_discovery_started; /* variable to determine whether SDP is started */
@@ -467,10 +468,8 @@
   tAVDT_SEP_INFO sep_info[BTA_AV_NUM_SEPS]; /* stream discovery results */
   AvdtpSepConfig cfg;                       /* local SEP configuration */
   alarm_t* avrc_ct_timer;                   /* delay timer for AVRC CT */
-  RawAddress peer_addr;                     /* peer BD address */
   uint16_t l2c_cid;                         /* L2CAP channel ID */
   uint16_t stream_mtu;                      /* MTU of stream */
-  uint16_t avdt_version;      /* the avdt version of peer device */
   tBTA_SEC sec_mask;          /* security mask */
   uint8_t media_type;         /* Media type: AVDT_MEDIA_TYPE_* */
   bool cong;                  /* true if AVDTP congested */
@@ -515,6 +514,40 @@
   uint16_t uuid_int; /*intended UUID of Initiator to connect to */
   bool offload_start_pending;
   bool offload_started;
+
+  /**
+   * Called to setup the state when connected to a peer.
+   *
+   * @param peer_address the peer address
+   */
+  void OnConnected(const RawAddress& peer_address);
+
+  /**
+   * Called to clear the state when disconnected from a peer.
+   *
+   */
+  void OnDisconnected();
+
+  /**
+   * Get the peer address.
+   */
+  const RawAddress& PeerAddress() const { return peer_address_; }
+
+  /**
+   * Get the AVDTP version of the peer device.
+   */
+  uint16_t AvdtpVersion() const { return avdtp_version_; }
+
+  /**
+   * Set the AVDTP version of the peer device.
+   *
+   * @param avdtp_version the AVDTP version to use
+   */
+  void SetAvdtpVersion(uint16_t avdtp_version);
+
+ private:
+  RawAddress peer_address_;  // Peer address
+  uint16_t avdtp_version_;   // The AVDTP version of the peer device
 };
 
 #define BTA_AV_RC_ROLE_MASK 0x10
diff --git a/bta/av/bta_av_main.cc b/bta/av/bta_av_main.cc
index c0d5090..da04d71 100644
--- a/bta/av/bta_av_main.cc
+++ b/bta/av/bta_av_main.cc
@@ -35,6 +35,7 @@
 #include "bta_av_co.h"
 #include "bta_av_int.h"
 #include "btif/include/btif_av_co.h"
+#include "btif/include/btif_config.h"
 #include "l2c_api.h"
 #include "l2cdefs.h"
 #include "utl.h"
@@ -267,7 +268,7 @@
 
   for (xx = 0; xx < BTA_AV_NUM_STRS; xx++) {
     if (bta_av_cb.p_scb[xx]) {
-      if (bd_addr == bta_av_cb.p_scb[xx]->peer_addr) {
+      if (bd_addr == bta_av_cb.p_scb[xx]->PeerAddress()) {
         p_scb = bta_av_cb.p_scb[xx];
         break;
       }
@@ -316,6 +317,8 @@
   for (int xx = 0; xx < BTA_AV_NUM_STRS; xx++) {
     if (bta_av_cb.p_scb[xx] != nullptr) continue;
     // Found an empty spot
+    // TODO: After tBTA_AV_SCB is changed to a proper class, the entry
+    // here should be allocated by C++ 'new' statement.
     tBTA_AV_SCB* p_ret = (tBTA_AV_SCB*)osi_calloc(sizeof(tBTA_AV_SCB));
     p_ret->rc_handle = BTA_AV_RC_HANDLE_NONE;
     p_ret->chnl = chnl;
@@ -338,9 +341,43 @@
   CHECK(p_scb == bta_av_cb.p_scb[scb_index]);
   bta_av_cb.p_scb[scb_index] = nullptr;
   alarm_free(p_scb->avrc_ct_timer);
+  // TODO: After tBTA_AV_SCB is changed to a proper class, the entry
+  // here should be de-allocated by C++ 'delete' statement.
   osi_free(p_scb);
 }
 
+void tBTA_AV_SCB::OnConnected(const RawAddress& peer_address) {
+  peer_address_ = peer_address;
+
+  if (peer_address.IsEmpty()) {
+    LOG_ERROR(LOG_TAG, "%s: Invalid peer address: %s", __func__,
+              peer_address.ToString().c_str());
+    return;
+  }
+
+  // Read and restore the AVDTP version from local storage
+  uint16_t avdtp_version = 0;
+  size_t version_value_size = sizeof(avdtp_version);
+  if (!btif_config_get_bin(peer_address_.ToString(), AVDTP_VERSION_CONFIG_KEY,
+                           (uint8_t*)&avdtp_version, &version_value_size)) {
+    LOG_WARN(LOG_TAG, "%s: Failed to read cached peer AVDTP version for %s",
+             __func__, peer_address_.ToString().c_str());
+  } else {
+    SetAvdtpVersion(avdtp_version);
+  }
+}
+
+void tBTA_AV_SCB::OnDisconnected() {
+  peer_address_ = RawAddress::kEmpty;
+  SetAvdtpVersion(0);
+}
+
+void tBTA_AV_SCB::SetAvdtpVersion(uint16_t avdtp_version) {
+  avdtp_version_ = avdtp_version;
+  LOG_DEBUG(LOG_TAG, "%s: AVDTP version for %s set to 0x%x", __func__,
+            peer_address_.ToString().c_str(), avdtp_version_);
+}
+
 /*******************************************************************************
  ******************************************************************************/
 void bta_av_conn_cback(UNUSED_ATTR uint8_t handle, const RawAddress& bd_addr,
@@ -775,7 +812,7 @@
         if (p_scbi->co_started != bta_av_cb.audio_open_cnt) {
           p_scbi->co_started = bta_av_cb.audio_open_cnt;
           L2CA_SetFlushTimeout(
-              p_scbi->peer_addr,
+              p_scbi->PeerAddress(),
               p_bta_av_cfg->p_audio_flush_to[p_scbi->co_started - 1]);
         }
       }
@@ -805,7 +842,7 @@
     if (p_cb->conn_audio == mask) {
       if (p_cb->p_scb[i]) {
         bta_sys_set_policy(BTA_ID_AV, HCI_ENABLE_MASTER_SLAVE_SWITCH,
-                           p_cb->p_scb[i]->peer_addr);
+                           p_cb->p_scb[i]->PeerAddress());
       }
       break;
     }
@@ -838,7 +875,7 @@
      * role change event */
     /* note that more than one SCB (a2dp & vdp) maybe waiting for this event */
     p_scb = bta_av_cb.p_scb[i];
-    if (p_scb && p_scb->peer_addr == peer_addr) {
+    if (p_scb && p_scb->PeerAddress() == peer_addr) {
       tBTA_AV_ROLE_RES* p_buf =
           (tBTA_AV_ROLE_RES*)osi_malloc(sizeof(tBTA_AV_ROLE_RES));
       APPL_TRACE_DEBUG(
@@ -848,7 +885,8 @@
       if ((id != BTM_ROLE_MASTER) && (app_id != HCI_SUCCESS))
       {
           bta_sys_set_policy(BTA_ID_AV,
-      (HCI_ENABLE_MASTER_SLAVE_SWITCH|HCI_ENABLE_SNIFF_MODE), p_scb->peer_addr);
+      (HCI_ENABLE_MASTER_SLAVE_SWITCH|HCI_ENABLE_SNIFF_MODE),
+      p_scb->PeerAddress());
       }
       */
       p_buf->hdr.event = BTA_AV_ROLE_CHANGE_EVT;
@@ -877,8 +915,8 @@
     }
     if (p_scb && p_scb->q_tag == BTA_AV_Q_TAG_OPEN) {
       APPL_TRACE_DEBUG("%s: peer %s rs_idx:%d, hndl:0x%x q_tag:%d", __func__,
-                       p_scb->peer_addr.ToString().c_str(), bta_av_cb.rs_idx,
-                       p_scb->hndl, p_scb->q_tag);
+                       p_scb->PeerAddress().ToString().c_str(),
+                       bta_av_cb.rs_idx, p_scb->hndl, p_scb->q_tag);
 
       if (HCI_SUCCESS == app_id || HCI_ERR_NO_CONNECTION == app_id) {
         p_scb->q_info.open.switch_res = BTA_AV_RS_OK;
@@ -887,7 +925,7 @@
             "%s: peer %s (p_scb peer %s) role switch failed: new_role:%d "
             "hci_status:0x%x",
             __func__, peer_addr.ToString().c_str(),
-            p_scb->peer_addr.ToString().c_str(), id, app_id);
+            p_scb->PeerAddress().ToString().c_str(), id, app_id);
         p_scb->q_info.open.switch_res = BTA_AV_RS_FAIL;
       }
 
@@ -978,15 +1016,15 @@
     if (p_scbi && (p_scb->hdi != i) &&   /* not the original channel */
         ((bta_av_cb.conn_audio & mask))) /* connected audio */
     {
-      BTM_GetRole(p_scbi->peer_addr, &role);
+      BTM_GetRole(p_scbi->PeerAddress(), &role);
       /* this channel is open - clear the role switch link policy for this link
        */
       if (BTM_ROLE_MASTER != role) {
         if (bta_av_cb.features & BTA_AV_FEAT_MASTER)
           bta_sys_clear_policy(BTA_ID_AV, HCI_ENABLE_MASTER_SLAVE_SWITCH,
-                               p_scbi->peer_addr);
+                               p_scbi->PeerAddress());
         if (BTM_CMD_STARTED !=
-            BTM_SwitchRole(p_scbi->peer_addr, BTM_ROLE_MASTER, NULL)) {
+            BTM_SwitchRole(p_scbi->PeerAddress(), BTM_ROLE_MASTER, NULL)) {
           /* can not switch role on SCBI
            * start the timer on SCB - because this function is ONLY called when
            * SCB gets API_OPEN */
@@ -1018,7 +1056,7 @@
   uint8_t role;
   bool is_ok = true;
 
-  if (BTM_GetRole(p_scb->peer_addr, &role) == BTM_SUCCESS) {
+  if (BTM_GetRole(p_scb->PeerAddress(), &role) == BTM_SUCCESS) {
     LOG_INFO(LOG_TAG,
              "%s: hndl:x%x role:%d conn_audio:x%x bits:%d features:x%x",
              __func__, p_scb->hndl, role, bta_av_cb.conn_audio, bits,
@@ -1028,10 +1066,10 @@
          (bta_av_cb.features & BTA_AV_FEAT_MASTER))) {
       if (bta_av_cb.features & BTA_AV_FEAT_MASTER)
         bta_sys_clear_policy(BTA_ID_AV, HCI_ENABLE_MASTER_SLAVE_SWITCH,
-                             p_scb->peer_addr);
+                             p_scb->PeerAddress());
 
       if (BTM_CMD_STARTED !=
-          BTM_SwitchRole(p_scb->peer_addr, BTM_ROLE_MASTER, NULL)) {
+          BTM_SwitchRole(p_scb->PeerAddress(), BTM_ROLE_MASTER, NULL)) {
         /* can not switch role on SCB - start the timer on SCB */
       }
       is_ok = false;
@@ -1113,7 +1151,7 @@
 
     if (list_length(p_scbi->a2dp_list) > p_bta_av_cfg->audio_mqs) {
       // Drop the oldest packet
-      bta_av_co_audio_drop(p_scbi->hndl, p_scbi->peer_addr);
+      bta_av_co_audio_drop(p_scbi->hndl, p_scbi->PeerAddress());
       BT_HDR* p_buf_drop = static_cast<BT_HDR*>(list_front(p_scbi->a2dp_list));
       list_remove(p_scbi->a2dp_list, p_buf_drop);
       osi_free(p_buf_drop);
@@ -1390,7 +1428,7 @@
       continue;
     }
     dprintf(fd, "\n  BTA ID: %zu peer: %s\n", i,
-            p_scb->peer_addr.ToString().c_str());
+            p_scb->PeerAddress().ToString().c_str());
     dprintf(fd, "    SDP discovery started: %s\n",
             p_scb->sdp_discovery_started ? "true" : "false");
     for (size_t j = 0; j < BTAV_A2DP_CODEC_INDEX_MAX; j++) {
@@ -1418,7 +1456,7 @@
     // TODO: Print p_scb->sep_info[], cfg, avrc_ct_timer, current_codec ?
     dprintf(fd, "    L2CAP Channel ID: %d\n", p_scb->l2c_cid);
     dprintf(fd, "    Stream MTU: %d\n", p_scb->stream_mtu);
-    dprintf(fd, "    AVDTP version: 0x%x\n", p_scb->avdt_version);
+    dprintf(fd, "    AVDTP version: 0x%x\n", p_scb->AvdtpVersion());
     dprintf(fd, "    Security mask: 0x%x\n", p_scb->sec_mask);
     dprintf(fd, "    Media type: %d\n", p_scb->media_type);
     dprintf(fd, "    Congested: %s\n", p_scb->cong ? "true" : "false");
diff --git a/bta/av/bta_av_ssm.cc b/bta/av/bta_av_ssm.cc
index afa78cc..6c384e0 100644
--- a/bta/av/bta_av_ssm.cc
+++ b/bta/av/bta_av_ssm.cc
@@ -488,7 +488,7 @@
 
   APPL_TRACE_VERBOSE(
       "%s: peer %s AV event(0x%x)=0x%x(%s) state=%d(%s) p_scb=%p", __func__,
-      p_scb->peer_addr.ToString().c_str(), p_scb->hndl, event,
+      p_scb->PeerAddress().ToString().c_str(), p_scb->hndl, event,
       bta_av_evt_code(event), p_scb->state, bta_av_sst_code(p_scb->state),
       p_scb);
 
@@ -500,7 +500,7 @@
   p_scb->state = state_table[event][BTA_AV_SNEXT_STATE];
 
   APPL_TRACE_VERBOSE("%s: peer %s AV next state=%d(%s) p_scb=%p", __func__,
-                     p_scb->peer_addr.ToString().c_str(), p_scb->state,
+                     p_scb->PeerAddress().ToString().c_str(), p_scb->state,
                      bta_av_sst_code(p_scb->state), p_scb);
 
   /* execute action functions */
@@ -572,9 +572,9 @@
 
   APPL_TRACE_VERBOSE(
       "%s: peer %s AV (hndl=0x%x) state=%d(%s) next state=%d(%s) p_scb=%p",
-      __func__, p_scb->peer_addr.ToString().c_str(), p_scb->hndl, p_scb->state,
-      bta_av_sst_code(p_scb->state), next_state, bta_av_sst_code(next_state),
-      p_scb);
+      __func__, p_scb->PeerAddress().ToString().c_str(), p_scb->hndl,
+      p_scb->state, bta_av_sst_code(p_scb->state), next_state,
+      bta_av_sst_code(next_state), p_scb);
 
   p_scb->state = next_state;
 }
diff --git a/stack/a2dp/a2dp_api.cc b/stack/a2dp/a2dp_api.cc
index b4563d7..cc707c4 100644
--- a/stack/a2dp/a2dp_api.cc
+++ b/stack/a2dp/a2dp_api.cc
@@ -68,6 +68,7 @@
   bool found = false;
   tA2DP_Service a2dp_svc;
   tSDP_PROTOCOL_ELEM elem;
+  RawAddress peer_address = RawAddress::kEmpty;
 
   LOG_VERBOSE(LOG_TAG, "%s: status: %d", __func__, status);
 
@@ -80,6 +81,7 @@
         break;
       }
       memset(&a2dp_svc, 0, sizeof(tA2DP_Service));
+      peer_address = p_rec->remote_bd_addr;
 
       /* get service name */
       if ((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_SERVICE_NAME)) !=
@@ -118,7 +120,7 @@
   osi_free_and_reset((void**)&a2dp_cb.find.p_db);
   /* return info from sdp record in app callback function */
   if (a2dp_cb.find.p_cback != NULL) {
-    (*a2dp_cb.find.p_cback)(found, &a2dp_svc);
+    (*a2dp_cb.find.p_cback)(found, &a2dp_svc, peer_address);
   }
 
   return;
diff --git a/stack/include/a2dp_api.h b/stack/include/a2dp_api.h
index 9aba6c7..56e259c 100644
--- a/stack/include/a2dp_api.h
+++ b/stack/include/a2dp_api.h
@@ -82,7 +82,8 @@
 } tA2DP_Service;
 
 /* This is the callback to notify the result of the SDP discovery process. */
-typedef void(tA2DP_FIND_CBACK)(bool found, tA2DP_Service* p_service);
+typedef void(tA2DP_FIND_CBACK)(bool found, tA2DP_Service* p_service,
+                               const RawAddress& peer_address);
 
 /*****************************************************************************
  *  external function declarations
diff --git a/stack/include/avdt_api.h b/stack/include/avdt_api.h
index 5d2135b..fd0721c 100644
--- a/stack/include/avdt_api.h
+++ b/stack/include/avdt_api.h
@@ -31,11 +31,10 @@
 /*****************************************************************************
  *  Constants
  ****************************************************************************/
-#ifndef AVDT_VERSION
-#define AVDT_VERSION 0x0103
-#endif
 #define AVDT_VERSION_1_3 0x0103
 
+#define AVDTP_VERSION_CONFIG_KEY "AvdtpVersion"
+
 /* Maximum size in bytes of the codec capabilities information element. */
 #define AVDT_CODEC_SIZE 20