OSDN Git Service

Bluetooth: Enable A2dp Multicast.
authorAyan Ghosh <abghosh@codeaurora.org>
Mon, 25 Aug 2014 12:47:48 +0000 (18:17 +0530)
committerLinux Build Service Account <lnxbuild@localhost>
Wed, 24 Aug 2016 14:09:48 +0000 (08:09 -0600)
This feature enables the multi
streaming support on BT HOST.

Change-Id: Ic3748c32b30036abd352c9322e30a704b2103fa7

Bluetooth: A2dp MultiCast/ Soft Hands-off.

 - Trigger suspend, when new ACL is up during active
   multicast
 - Initiate suspend on both links when it is initiated by
   either connected HS
 - Clear remote suspend flag when play is initiated by either
   connected HS
 - Allocate first free SCB when remote has initiated AVRCP connection
   and we are trying to connect to other HS
 - Update Encoder when HS2 is connected during
   active streaming on HS1
Change-Id: I7ccfb81637688c23c6a2b005f849ac76cc0dbd2a

Bluetooth: Initialize RC handle with proper value.

 - Initialize rc_handle with 0xFF
 - On disconnect re-set rc_handle to invalid value.

Change-Id: Id507114451701e998f9960aa5dc961ff16f2d1bf

Bluetooth: Do not register for Volume change.

 - When absolute volume is not supported by any
   of connected HS do not register for volume change
   notification on connected HS.

Change-Id: I3b29ac5929989bc7c45b1b0f8cbe75b3082e66d3

Bluetooth: Use SCB handle for Sniff.

 - Use scb handle for making entry for sniff instead
   of audio count.With Multi A2dp audio count denotes
   number of A2dp devices connected.Due to this stale
   entries were created for AV power entries, due to
   which links did not go to sniff after max entries
   in table is reached.

Change-Id: I051017991c7d3d7d42c4822efdad2b2aa1b0e2b2

Bluetooth: Use free SCB for Incoming connections.

  - In connection race conditions, check for
    first free SCB to allocate for incoming
    connection.
  - Initiate disconnect for incoming connection when
    no free SCB is available.
  - Check for max. possible connections before initiating
    suspend for new link up-event.
  - Clear all flag on AVRCP disconnect.
Change-Id: Ic605b0470ca88aac856cefe54bf6c9ec5320bd5a

A2DP Multicast: Allow outgoing connections for scatternet

    - As there is fallback to soft handoff incase of
      scatternet scenarios, allow the outgoing
      connections in case of role switch failure for
      existing slave connection.
    - Reject the incoming connection from BTA while
      processing another incoming connection.

Change-Id: Ib8a087eea5e9845a6e2ef758757f941c1bdf7b52

A2DP Multicast: Disable multicast if BR HS is connected

    - Disable multicast if BR headset is connected
    - Use scb index for AV Busy and Idle state updates

Change-Id: If7310be4f47cbe0775eb35c0b81122d524be25f5

Dual A2DP: Avoid blocking Play key event

    - Send play key event for PLAY sent from non playing device
      to be compliant with default behavior for single connection.

Change-Id: Ie07fc10d3a946ca4e3f9643b2ae5e556358fd0b8

A2DP Multicast: Update multicast state after AV state update

    - multicast state update checks the AV state for updating
      multicast condition. Need to make sure that AV state
      is updated in OPEN state before calling the API.

Change-Id: Ifa0fd1a90ff5d8a05c37dba1590f76176d9899e0

Dual A2DP: Disconnect AVRCP only connection.

    - AVRCP only connection should be disconnected to avoid
      confusion to end user in the Dual A2DP/Multicast scenarios.
    - Proper check for RC connections before closing uinput.

Change-Id: Id515c3f29499a3ada02b8e45cc2189276152a461

Conflicts:
btif/src/btif_av.c

Dual A2DP: Allocate free SCB for incoming connection

    - SCB allocated to incoming connection should be idle.
      If not, ongoing connection handling will be affected.

Change-Id: Ideaab85b928f08b37c7a284644fd3a62926b15ec

Dual A2DP: Initiate outgoing connection only if the state is Idle

    - A2DP connection also could be triggered from remote device
      before the AVRCP timer expires. Check the state before initiating
      connection for the device.

Change-Id: Id538de6ce829a388a4c052769177319cd5c217fc

Dual A2DP: Don't suspend if stream is started for other device

    - Avoid sending suspend for remote initiated START if
      stream is started for other device. IOT issues are seen with
      specific devices if gap between SUSPEND and START is less.

Change-Id: I64d768aa8246101687bbc98b4ae0be97645bb5b1

A2DP Multicast: Update multicast state during role change

    - Role change can be triggered at any point of time
      during the connection. Update the multicast state
      upon getting role change event.

Change-Id: I60a17e955b6fdc4379d571c59d8527ec023e9531

Revert "Bluetooth: Do not register for Volume change."

This reverts commit c87e747f40b870b9a540902595524b34a5436b43.

Change-Id: I4752486979366f67e9109bd61df54dc48786f564

Dual A2DP: Set the flush only when there is no play in progress

    - When connected to two devices update the flush state only
      if there is no play on any connected device.

Change-Id: Ic13b7285625c49350334c35eed878407b6e78821

Dual A2DP: Handle connection inconstencies during stress scenarios

    - Avoid removal of connect nodes in profile connect queue
    - Dual Handoff flag cleanup during START failure
    - Reject the A2DP connection from remote device if it is
      initiated on the same endpoint where outgoing connection
      is being attempted.

CRs-Fixed: 835641
Change-Id: I4cc0d680e5cabb003dd11c8ba232d1fc70f41780

Dual A2DP: Mark the AVDTP busy during outgoing connection

    - AVDTP incoming connection cannot be handled when there is
      outgoing connection in progress as per the base design.
      Reject the incoming AVDT connection so that other
      connection can happen and A2DP connection is always
      attempted from connectOtherProfile path.

CRs-Fixed: 839392

Change-Id: Iff801a7e4f170aa85cd06278c7d62dfc81464b5a

Dual A2DP: Acknowledge the SUSPEND after both streams stop

    - Avoid on_suspended call when other stream is not yet
      suspended as it unblocks the audio process to send
      further commands.
    - Handle RC close to cleanup the BTIF RC block even if
      the current AV connections are for different devices.
      This was seen because of not getting AVCT disconnection
      response and later this event is received after getting
      ACL disconnection complete.

CRs-Fixed: 842690
Change-Id: I7eb95a9ddfc7be06af4521af1567e4e166630317

Dual A2DP: Disconnect the AVRCP only connection

AVRCP only connection has to be disconnected when it is evaluated
for A2DP connection and no free AV blocks are available in BTIF.

Change-Id: I3f6b731ed6701c739defbfd8e011bbb6a1aeb3ba

Conflicts:
btif/src/btif_rc.c

A2DP Multicast: Check for both streams for stream ready

    - Stream ready should succeed only after both streams
      are suspended during multicast, otherwise audio data
      coming will trigger inconsistent behavior for stream
      starting.

Change-Id: Ia8794dbed7dbe5f55cf7139b200fcdf2eb5ee45f

A2DP Multicast: Handle suspend for both streams

In race conditions, it is seen that ACL is established while
stream is being started for both devices for multicast.
Since the multicast state is updated after stream start when
suspend is initiated we need to check if both streams are
started and suspend them accordingly.

Change-Id: I23f64174914350b476022f7bfbfb553a55d12902

Dual A2DP: Clear the RC priority information while disconnect

RC priority information has to be cleared during disconnection
to avoid improper usage during start even after initiating
disconnection.

Change-Id: Ia52c04ea2bfecbf390aae12400073adb0f327718

Dual A2DP: Interface to query active device for handoff

During Handoff case, check the playing device and device to
start playback to provide state for given device.

CRs-Fixed: 856063
Change-Id: I3a326d9f0c6221cfc4cdcc3fad037f22a29ff90e

Dual A2DP: Connection failure handling for proper cleanup

    - Cleanup BTA AV block for the outgoing connection if
      it fails because of no resources
    - Reject the incoming connection if there is outgoing
      connection in progress

Change-Id: I44d3dd6bbff93d38c1c22260056897e42d915ffa

Conflicts:
stack/avdt/avdt_msg.c
Change-Id: Ie74102d0254fa73061b6baea9811d834fae64358

35 files changed:
audio_a2dp_hw/audio_a2dp_hw.c
audio_a2dp_hw/audio_a2dp_hw.h
bta/av/bta_av_aact.c
bta/av/bta_av_act.c
bta/av/bta_av_api.c
bta/av/bta_av_int.h
bta/av/bta_av_main.c
bta/av/bta_av_ssm.c
bta/include/bta_av_api.h
btif/co/bta_av_co.c
btif/include/btif_av.h
btif/include/btif_media.h
btif/include/btif_sm.h
btif/src/btif_av.c
btif/src/btif_dm.c
btif/src/btif_media_task.c
btif/src/btif_rc.c
btif/src/btif_sm.c
include/bt_target.h
stack/a2dp/a2d_api.c
stack/a2dp/a2d_int.h
stack/avct/avct_api.c
stack/avct/avct_int.h
stack/avct/avct_l2c.c
stack/avct/avct_lcb.c
stack/avct/avct_lcb_act.c
stack/avdt/avdt_api.c
stack/avdt/avdt_int.h
stack/avdt/avdt_l2c.c
stack/avrc/avrc_api.c
stack/avrc/avrc_bld_tg.c
stack/include/a2d_api.h
stack/include/avct_api.h
stack/include/avdt_api.h
stack/sdp/sdp_server.c

index b2d123d..3cd70cc 100644 (file)
@@ -174,6 +174,7 @@ static const char* dump_a2dp_ctrl_event(char event)
         CASE_RETURN_STR(A2DP_CTRL_CMD_START)
         CASE_RETURN_STR(A2DP_CTRL_CMD_STOP)
         CASE_RETURN_STR(A2DP_CTRL_CMD_SUSPEND)
+        CASE_RETURN_STR(A2DP_CTRL_CMD_CHECK_STREAM_STARTED)
         default:
             return "UNKNOWN MSG ID";
     }
@@ -649,6 +650,17 @@ static int suspend_audio_datapath(struct a2dp_stream_common *common, bool standb
 }
 
 
+static int check_a2dp_stream_started(struct a2dp_stream_out *out)
+{
+   if (a2dp_command(&out->common, A2DP_CTRL_CMD_CHECK_STREAM_STARTED) < 0)
+   {
+       INFO("Btif not in stream state");
+       return -1;
+   }
+   return 0;
+}
+
+
 /*****************************************************************************
 **
 **  audio output callbacks
@@ -848,8 +860,6 @@ static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
     if (!params)
       return status;
 
-    pthread_mutex_lock(&out->common.lock);
-
     /* dump params */
     hash_map_utils_dump_string_keys_string_values(params);
 
@@ -858,27 +868,42 @@ static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
     if (keyval && strcmp(keyval, "true") == 0)
     {
         DEBUG("stream closing, disallow any writes");
+            pthread_mutex_lock(&out->common.lock);
         out->common.state = AUDIO_A2DP_STATE_STOPPING;
+            pthread_mutex_unlock(&out->common.lock);
     }
 
     keyval = (char *)hash_map_get(params, "A2dpSuspended");
 
     if (keyval && strcmp(keyval, "true") == 0)
     {
+        pthread_mutex_lock(&out->common.lock);
         if (out->common.state == AUDIO_A2DP_STATE_STARTED)
             status = suspend_audio_datapath(&out->common, false);
+        else
+        {
+                if (check_a2dp_stream_started(out) == 0)
+                   /*Btif and A2dp HAL state can be out of sync
+                    *check state of btif and suspend audio.
+                    *Happens when remote initiates start.*/
+                    status = suspend_audio_datapath(&out->common, false);
+                else
+                    out->common.state = AUDIO_A2DP_STATE_SUSPENDED;
+        }
+        pthread_mutex_unlock(&out->common.lock);
     }
     else
     {
+        pthread_mutex_lock(&out->common.lock);
         /* Do not start the streaming automatically. If the phone was streaming
          * prior to being suspended, the next out_write shall trigger the
          * AVDTP start procedure */
         if (out->common.state == AUDIO_A2DP_STATE_SUSPENDED)
             out->common.state = AUDIO_A2DP_STATE_STANDBY;
         /* Irrespective of the state, return 0 */
+        pthread_mutex_unlock(&out->common.lock);
     }
 
-    pthread_mutex_unlock(&out->common.lock);
     hash_map_free(params);
 
     return status;
index 11d438a..7830c17 100644 (file)
@@ -80,6 +80,7 @@
 typedef enum {
     A2DP_CTRL_CMD_NONE,
     A2DP_CTRL_CMD_CHECK_READY,
+    A2DP_CTRL_CMD_CHECK_STREAM_STARTED,
     A2DP_CTRL_CMD_START,
     A2DP_CTRL_CMD_STOP,
     A2DP_CTRL_CMD_SUSPEND,
index 08ab78d..69b4702 100644 (file)
 #define BTA_AV_RECONFIG_RETRY       6
 #endif
 
+static const size_t SBC_MAX_BITPOOL_OFFSET = 6;
+static const size_t SBC_MAX_BITPOOL = 53;
+
 /* ACL quota we are letting FW use for A2DP Offload Tx. */
 #define BTA_AV_A2DP_OFFLOAD_XMIT_QUOTA      4
 
 static void bta_av_st_rc_timer(tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
 
-static const size_t SBC_MAX_BITPOOL_OFFSET = 6;
-static const size_t SBC_MAX_BITPOOL = 53;
-
 /* state machine states */
 enum
 {
@@ -252,10 +252,12 @@ tAVDT_CTRL_CBACK * const bta_av_dt_cback[] =
 ***********************************************/
 static UINT8 bta_av_get_scb_handle(tBTA_AV_SCB *p_scb, UINT8 local_sep)
 {
-    for (int i = 0; i < BTA_AV_MAX_SEPS; i++) {
-        if ((p_scb->seps[i].tsep == local_sep) &&
-            (p_scb->seps[i].codec_type == p_scb->codec_type))
-            return (p_scb->seps[i].av_handle);
+    UINT8 xx =0;
+    for (xx = 0; xx<BTA_AV_MAX_SEPS; xx++)
+    {
+        if ((p_scb->seps[xx].tsep == local_sep) &&
+            (p_scb->seps[xx].codec_type == p_scb->codec_type))
+            return (p_scb->seps[xx].av_handle);
     }
     APPL_TRACE_DEBUG(" bta_av_get_scb_handle appropiate sep_type not found")
     return 0; /* return invalid handle */
@@ -272,9 +274,11 @@ static UINT8 bta_av_get_scb_handle(tBTA_AV_SCB *p_scb, UINT8 local_sep)
 ***********************************************/
 static UINT8 bta_av_get_scb_sep_type(tBTA_AV_SCB *p_scb, UINT8 tavdt_handle)
 {
-    for (int i = 0; i < BTA_AV_MAX_SEPS; i++) {
-        if (p_scb->seps[i].av_handle == tavdt_handle)
-            return (p_scb->seps[i].tsep);
+    UINT8 xx =0;
+    for (xx = 0; xx<BTA_AV_MAX_SEPS; xx++)
+    {
+        if (p_scb->seps[xx].av_handle == tavdt_handle)
+            return (p_scb->seps[xx].tsep);
     }
     APPL_TRACE_DEBUG(" bta_av_get_scb_sep_type appropiate handle not found")
     return 3; /* return invalid sep type */
@@ -396,7 +400,7 @@ static BOOLEAN bta_av_next_getcap(tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
             /* we got a stream; get its capabilities */
             if (p_scb->p_cap == NULL)
                 p_scb->p_cap = (tAVDT_CFG *)osi_malloc(sizeof(tAVDT_CFG));
-            if (p_scb->avdt_version >= AVDT_VERSION_SYNC)
+            if ((p_scb->avdt_version >= AVDT_VERSION_SYNC) && (a2d_get_avdt_sdp_ver() >= AVDT_VERSION_SYNC) )
             {
                 p_req = AVDT_GetAllCapReq;
             }
@@ -435,6 +439,8 @@ static void bta_av_proc_stream_evt(UINT8 handle, BD_ADDR bd_addr, UINT8 event, t
 {
     UINT16              sec_len = 0;
     tBTA_AV_SCB         *p_scb = bta_av_cb.p_scb[index];
+    int                 xx;
+    APPL_TRACE_VERBOSE("bta_av_proc_stream_evt on the index : %d", index);
 
     if (p_data)
     {
@@ -487,7 +493,11 @@ static void bta_av_proc_stream_evt(UINT8 handle, BD_ADDR bd_addr, UINT8 event, t
              * If we already have a signalling connection with the bd_addr and the streaming
              * SST is at INIT state, change it to INCOMING state to handle the signalling
              * from the 2nd SEP.                                                                */
-            if ((bta_av_find_lcb(bd_addr, BTA_AV_LCB_FIND) != NULL) && (bta_av_is_scb_init(p_scb)))
+            /* Fix for below klockwork issue
+             * Pointer 'bd_addr' checked for NULL at line 465 may be passed to function and
+             * may be dereferenced there by passing argument 1 to function 'bta_av_find_lcb' at line 500
+             * added another null check for below condition to get rid of kw error */
+            if (bd_addr != NULL && (bta_av_find_lcb(bd_addr, BTA_AV_LCB_FIND) != NULL) && (bta_av_is_scb_init(p_scb)))
             {
                 bta_av_set_scb_sst_incoming (p_scb);
 
@@ -495,11 +505,14 @@ static void bta_av_proc_stream_evt(UINT8 handle, BD_ADDR bd_addr, UINT8 event, t
                  * Later when we receive AVDT_CONFIG_IND_EVT, we use a new p_scb and set its state to
                  * incoming which we do it above.
                  * We also have to set the old p_scb state to init to be used later             */
-                for (int i = 0; i < BTA_AV_NUM_STRS; i++) {
-                    if ((bta_av_cb.p_scb[i]) && (i != index)) {
-                        if (bta_av_cb.p_scb[i]->state == BTA_AV_INCOMING_SST) {
-                            bta_av_cb.p_scb[i]->state = BTA_AV_INIT_SST;
-                            bta_av_cb.p_scb[i]->coll_mask = 0;
+                for (xx = 0; xx < BTA_AV_NUM_STRS; xx++)
+                {
+                    if ((bta_av_cb.p_scb[xx]) && (xx != index))
+                    {
+                        if (bta_av_cb.p_scb[xx]->state == BTA_AV_INCOMING_SST)
+                        {
+                            bta_av_cb.p_scb[xx]->state = BTA_AV_INIT_SST;
+                            bta_av_cb.p_scb[xx]->coll_mask = 0;
                             break;
                         }
                     }
@@ -556,11 +569,14 @@ static void bta_av_proc_stream_evt(UINT8 handle, BD_ADDR bd_addr, UINT8 event, t
 /* coverity[var_deref_model] */
 /* false-positive: bta_av_conn_cback only processes AVDT_CONNECT_IND_EVT and AVDT_DISCONNECT_IND_EVT event
  *                 these 2 events always have associated p_data */
-    if (p_data)
+/* Fix for below klockwork issue
+ * Pointer 'bd_addr' checked for NULL at line 465 may be passed to function and may be dereferenced there
+ * by passing argument 2 to function 'bta_av_conn_cback'. */
+    if (p_data && bd_addr)
     {
         bta_av_conn_cback(handle, bd_addr, event, p_data);
     }
-    else
+    else if (!p_data)
     {
         APPL_TRACE_ERROR("%s: p_data is null", __func__);
     }
@@ -727,6 +743,9 @@ static void bta_av_a2d_sdp_cback(BOOLEAN found, tA2D_Service *p_service)
     p_msg->hdr.layer_specific = bta_av_cb.handle;
 
     bta_sys_sendmsg(p_msg);
+    if (!found)
+        APPL_TRACE_ERROR ("bta_av_a2d_sdp_cback, SDP record not found");
+    bta_sys_conn_close(BTA_ID_AV, p_scb->hdi, p_scb->peer_addr);
 }
 
 /*******************************************************************************
@@ -740,15 +759,17 @@ static void bta_av_a2d_sdp_cback(BOOLEAN found, tA2D_Service *p_service)
 *******************************************************************************/
 static void bta_av_adjust_seps_idx(tBTA_AV_SCB *p_scb, UINT8 avdt_handle)
 {
+    int xx;
     APPL_TRACE_DEBUG("bta_av_adjust_seps_idx codec_type: %d", p_scb->codec_type);
-    for (int i = 0; i < BTA_AV_MAX_SEPS; i++) {
+    for(xx=0; xx<BTA_AV_MAX_SEPS; xx++)
+    {
         APPL_TRACE_DEBUG("av_handle: %d codec_type: %d",
-            p_scb->seps[i].av_handle, p_scb->seps[i].codec_type);
-        if((p_scb->seps[i].av_handle && p_scb->codec_type == p_scb->seps[i].codec_type)
-            && (p_scb->seps[i].av_handle == avdt_handle))
+            p_scb->seps[xx].av_handle, p_scb->seps[xx].codec_type);
+        if((p_scb->seps[xx].av_handle && p_scb->codec_type == p_scb->seps[xx].codec_type)
+            && (p_scb->seps[xx].av_handle == avdt_handle))
         {
-            p_scb->sep_idx = i;
-            p_scb->avdt_handle = p_scb->seps[i].av_handle;
+            p_scb->sep_idx      = xx;
+            p_scb->avdt_handle  = p_scb->seps[xx].av_handle;
             break;
         }
     }
@@ -824,11 +845,32 @@ void bta_av_role_res (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
     BOOLEAN         initiator = FALSE;
     tBTA_AV_START   start;
     tBTA_AV_OPEN    av_open;
+    tBTA_AV_ROLE_CHANGED role_changed;
+
+    UINT8 cur_role = BTM_ROLE_UNDEFINED;
 
     APPL_TRACE_DEBUG("bta_av_role_res q_tag:%d, wait:x%x, role:x%x", p_scb->q_tag, p_scb->wait, p_scb->role);
     if (p_scb->role & BTA_AV_ROLE_START_INT)
         initiator = TRUE;
 
+    /* Multicast: update BTIF about role switch
+     * If role switch succeeded, we need to update multicast state
+     * from BTIF.
+     */
+    if (p_data->role_res.hci_status == HCI_SUCCESS)
+    {
+        APPL_TRACE_DEBUG("bta_av_role_res: Master update upper layer");
+
+        bdcpy(role_changed.bd_addr, p_scb->peer_addr);
+        role_changed.hndl = p_scb->hndl;
+
+        if (BTM_GetRole (p_scb->peer_addr, &cur_role) == BTM_SUCCESS)
+        {
+            role_changed.new_role = cur_role;
+        }
+        (*bta_av_cb.p_cback)(BTA_AV_ROLE_CHANGED_EVT, (tBTA_AV *)&role_changed);
+    }
+
     if (p_scb->q_tag == BTA_AV_Q_TAG_START)
     {
         if (p_scb->wait & BTA_AV_WAIT_ROLE_SW_STARTED)
@@ -837,7 +879,7 @@ void bta_av_role_res (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
             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, p_scb->hdi, p_scb->peer_addr);
                 /* start failed because of role switch. */
                 start.chnl   = p_scb->chnl;
                 start.status = BTA_AV_FAIL_ROLE;
@@ -866,6 +908,11 @@ void bta_av_role_res (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
                 bdcpy(av_open.bd_addr, p_scb->peer_addr);
                 av_open.chnl   = p_scb->chnl;
                 av_open.hndl   = p_scb->hndl;
+                // update Master/Slave Role for open event
+                if (BTM_GetRole (p_scb->peer_addr, &cur_role) == BTM_SUCCESS)
+                {
+                    av_open.role = cur_role;
+                }
                 start.status = BTA_AV_FAIL_ROLE;
                 if(p_scb->seps[p_scb->sep_idx].tsep == AVDT_TSEP_SRC )
                     av_open.sep = AVDT_TSEP_SNK;
@@ -996,7 +1043,7 @@ void bta_av_do_disc_a2d (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
     p_scb->sec_mask = p_data->api_open.sec_mask;
     p_scb->use_rc = p_data->api_open.use_rc;
 
-    bta_sys_conn_open(BTA_ID_AV, p_scb->app_id, p_scb->peer_addr);
+    bta_sys_conn_open(BTA_ID_AV, p_scb->hdi, p_scb->peer_addr);
 
     if (p_scb->skip_sdp == TRUE)
     {
@@ -1010,30 +1057,32 @@ void bta_av_do_disc_a2d (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
         bta_av_a2d_sdp_cback(TRUE, &a2d_ser);
         return;
     }
+    else
+    {
+        /* only one A2D find service is active at a time */
+        bta_av_cb.handle = p_scb->hndl;
 
-    /* only one A2D find service is active at a time */
-    bta_av_cb.handle = p_scb->hndl;
-
-    /* set up parameters */
-    db_params.db_len = BTA_AV_DISC_BUF_SIZE;
-    db_params.num_attr = 3;
-    db_params.p_attrs = attr_list;
-    p_scb->uuid_int = p_data->api_open.uuid;
-    p_scb->sdp_discovery_started = TRUE;
-    if (p_scb->uuid_int == UUID_SERVCLASS_AUDIO_SINK)
-        sdp_uuid = UUID_SERVCLASS_AUDIO_SOURCE;
-    else if (p_scb->uuid_int == UUID_SERVCLASS_AUDIO_SOURCE)
-        sdp_uuid = UUID_SERVCLASS_AUDIO_SINK;
+        /* set up parameters */
+        db_params.db_len = BTA_AV_DISC_BUF_SIZE;
+        db_params.num_attr = 3;
+        db_params.p_attrs = attr_list;
+        p_scb->uuid_int = p_data->api_open.uuid;
+        p_scb->sdp_discovery_started = TRUE;
+        if (p_scb->uuid_int == UUID_SERVCLASS_AUDIO_SINK)
+            sdp_uuid = UUID_SERVCLASS_AUDIO_SOURCE;
+        else if (p_scb->uuid_int == UUID_SERVCLASS_AUDIO_SOURCE)
+            sdp_uuid = UUID_SERVCLASS_AUDIO_SINK;
 
-    APPL_TRACE_DEBUG("%s: uuid_int 0x%x, Doing SDP For 0x%x", __func__,
+        APPL_TRACE_DEBUG("%s: uuid_int 0x%x, Doing SDP For 0x%x", __func__,
                     p_scb->uuid_int, sdp_uuid);
-    if (A2D_FindService(sdp_uuid, p_scb->peer_addr, &db_params,
+        if (A2D_FindService(sdp_uuid, p_scb->peer_addr, &db_params,
                     bta_av_a2d_sdp_cback) == A2D_SUCCESS)
-        return;
+            return;
 
-    /* when the code reaches here, either the DB is NULL
-     * or A2D_FindService is not successful */
-    bta_av_a2d_sdp_cback(FALSE, NULL);
+        /* when the code reaches here, either the DB is NULL
+         * or A2D_FindService is not successful */
+        bta_av_a2d_sdp_cback(FALSE, NULL);
+    }
 }
 
 /*******************************************************************************
@@ -1048,7 +1097,8 @@ void bta_av_do_disc_a2d (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
 void bta_av_cleanup(tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
 {
     tBTA_AV_CONN_CHG msg;
-    UINT8 role = BTA_AV_ROLE_AD_INT;
+    int             xx;
+    UINT8           role = BTA_AV_ROLE_AD_INT;
     UNUSED(p_data);
 
     APPL_TRACE_DEBUG("bta_av_cleanup");
@@ -1078,15 +1128,18 @@ void bta_av_cleanup(tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
         (*bta_av_cb.p_cback)(BTA_AV_OFFLOAD_START_RSP_EVT, (tBTA_AV *)&status);
     }
     p_scb->offload_start_pending = FALSE;
+    p_scb->skip_sdp = FALSE;
+    p_scb->coll_mask = 0;
 
     p_scb->skip_sdp = FALSE;
     if (p_scb->deregistring)
     {
         /* remove stream */
-        for (int i = 0; i < BTA_AV_MAX_SEPS; i++) {
-            if (p_scb->seps[i].av_handle)
-                AVDT_RemoveStream(p_scb->seps[i].av_handle);
-            p_scb->seps[i].av_handle = 0;
+        for(xx=0; xx<BTA_AV_MAX_SEPS; xx++)
+        {
+            if(p_scb->seps[xx].av_handle)
+                AVDT_RemoveStream(p_scb->seps[xx].av_handle);
+            p_scb->seps[xx].av_handle = 0;
         }
 
         bta_av_dereg_comp((tBTA_AV_DATA *) &msg);
@@ -1140,8 +1193,17 @@ void bta_av_config_ind (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
     p_scb->codec_type = p_evt_cfg->codec_info[BTA_AV_CODEC_TYPE_IDX];
     bta_av_save_addr(p_scb, p_data->str_msg.bd_addr);
 
-    /* Clear collision mask */
-    p_scb->coll_mask = 0;
+    if (p_scb->coll_mask & BTA_AV_COLL_API_CALLED)
+    {
+        APPL_TRACE_DEBUG(" bta_av_config_ind ReSetting collision mask  ");
+        /* Clear collision mask */
+        p_scb->coll_mask = 0;
+    }
+    else
+    {
+        APPL_TRACE_WARNING(" bta_av_config_ind config_ind called before Open");
+        p_scb->coll_mask |= BTA_AV_COLL_SETCONFIG_IND;
+    }
     alarm_cancel(bta_av_cb.accept_signalling_timer);
 
     /* if no codec parameters in configuration, fail */
@@ -1358,6 +1420,8 @@ void bta_av_setconfig_rsp (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
             /* Make sure UUID has been initialized... */
             if (p_scb->uuid_int == 0)
                 p_scb->uuid_int = p_scb->open_api.uuid;
+            if (p_scb->uuid_int == 0)
+                p_scb->uuid_int = UUID_SERVCLASS_AUDIO_SOURCE;
             bta_av_next_getcap(p_scb, p_data);
         }
     }
@@ -1378,6 +1442,7 @@ void bta_av_str_opened (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
     tBTA_AV_OPEN    open;
     UINT8 *p;
     UINT16 mtu;
+    UINT8 cur_role;
 
     msg.hdr.layer_specific = p_scb->hndl;
     msg.is_up = TRUE;
@@ -1396,11 +1461,11 @@ void bta_av_str_opened (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
     if(mtu == 0 || mtu > p_scb->stream_mtu)
         mtu = p_scb->stream_mtu;
 
-    /* Set the media channel as medium priority */
-    L2CA_SetTxPriority(p_scb->l2c_cid, L2CAP_CHNL_PRIORITY_MEDIUM);
+    /* Set the media channel as high priority */
+    L2CA_SetTxPriority(p_scb->l2c_cid, L2CAP_CHNL_PRIORITY_HIGH);
     L2CA_SetChnlFlushability (p_scb->l2c_cid, TRUE);
 
-    bta_sys_conn_open(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->peer_addr);
+    bta_sys_conn_open(BTA_ID_AV, p_scb->hdi, p_scb->peer_addr);
     memset(&p_scb->q_info, 0, sizeof(tBTA_AV_Q_INFO));
 
     p_scb->l2c_bufs = 0;
@@ -1423,6 +1488,11 @@ void bta_av_str_opened (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
         open.status = BTA_AV_SUCCESS;
         open.starting = bta_av_chk_start(p_scb);
         open.edr    = 0;
+        // update Master/Slave Role for start
+        if (BTM_GetRole (p_scb->peer_addr, &cur_role) == BTM_SUCCESS)
+        {
+            open.role = cur_role;
+        }
         if( NULL != (p = BTM_ReadRemoteFeatures(p_scb->peer_addr)))
         {
             if(HCI_EDR_ACL_2MPS_SUPPORTED(p))
@@ -1560,6 +1630,7 @@ void bta_av_do_close (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
 *******************************************************************************/
 void bta_av_connect_req(tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
 {
+    UINT16 result;
     UNUSED(p_data);
 
     p_scb->sdp_discovery_started = FALSE;
@@ -1571,7 +1642,17 @@ void bta_av_connect_req(tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
         return;
     }
 
-    AVDT_ConnectReq(p_scb->peer_addr, p_scb->sec_mask, bta_av_dt_cback[p_scb->hdi]);
+    result = AVDT_ConnectReq(p_scb->peer_addr, p_scb->sec_mask, bta_av_dt_cback[p_scb->hdi]);
+    if(result != AVDT_SUCCESS)
+    {
+        /* AVDT connect failed because of resource issue
+         * trigger the SDP fail event to enable the cleanup
+         * and set the stream to proper state.
+         */
+        p_scb->open_status = BTA_AV_FAIL_RESOURCES;
+        APPL_TRACE_ERROR("bta_av_connect_req: AVDT_ConnectReq failed: %d", result);
+        bta_av_ssm_execute(p_scb, BTA_AV_SDP_DISC_FAIL_EVT, NULL);
+    }
 }
 
 /*******************************************************************************
@@ -1588,7 +1669,7 @@ void bta_av_sdp_failed(tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
     if (!p_scb->open_status)
         p_scb->open_status = BTA_AV_FAIL_SDP;
 
-    p_scb->sdp_discovery_started = FALSE;
+    p_scb->sdp_discovery_started = TRUE;
     bta_av_str_closed(p_scb, p_data);
 }
 
@@ -1802,6 +1883,7 @@ void bta_av_open_failed (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
     tBTA_AV_SCB * p_opened_scb = NULL;
     UINT8 idx;
     tBTA_AV_OPEN    open;
+    UINT8 cur_role;
 
     APPL_TRACE_DEBUG("bta_av_open_failed");
     p_scb->open_status = BTA_AV_FAIL_STREAM;
@@ -1826,6 +1908,12 @@ void bta_av_open_failed (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
         open.status = BTA_AV_FAIL_GET_CAP;
         open.starting = bta_av_chk_start(p_scb);
         open.edr    = 0;
+        // update Master/Slave Role for open event
+        if (BTM_GetRole (p_scb->peer_addr, &cur_role) == BTM_SUCCESS)
+        {
+            open.role = cur_role;
+        }
+
         /* set the state back to initial state */
         bta_av_set_scb_sst_init(p_scb);
 
@@ -2031,7 +2119,7 @@ void bta_av_do_start (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
     if ((p_scb->started == FALSE) && ((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, p_scb->hdi, p_scb->peer_addr);
 
         AVDT_StartReq(&p_scb->avdt_handle, 1);
     }
@@ -2041,7 +2129,9 @@ void bta_av_do_start (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
         if ( p_scb->wait == 0 ) {
             if (p_scb->role & BTA_AV_ROLE_SUSPEND) {
                 notify_start_failed(p_scb);
-            } else {
+            }
+            else
+            {
                 bta_av_start_ok(p_scb, NULL);
             }
         }
@@ -2069,7 +2159,7 @@ void bta_av_str_stopped (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
     APPL_TRACE_ERROR("bta_av_str_stopped:audio_open_cnt=%d, p_data %x",
             bta_av_cb.audio_open_cnt, p_data);
 
-    bta_sys_idle(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->peer_addr);
+    bta_sys_idle(BTA_ID_AV, p_scb->hdi, p_scb->peer_addr);
     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);
@@ -2156,6 +2246,7 @@ void bta_av_reconfig (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
 {
     tAVDT_CFG   *p_cfg;
     tBTA_AV_API_STOP    stop;
+    tBTA_AV_RECONFIG    evt;
     tBTA_AV_API_RCFG    *p_rcfg = &p_data->api_reconfig;
 
     APPL_TRACE_DEBUG("bta_av_reconfig r:%d, s:%d idx: %d (o:%d)",
@@ -2166,7 +2257,19 @@ void bta_av_reconfig (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
     /* store the new configuration in control block */
     if (p_scb->p_cap == NULL)
         p_scb->p_cap = (tAVDT_CFG *)osi_malloc(sizeof(tAVDT_CFG));
-    p_cfg = p_scb->p_cap;
+    if((p_cfg = p_scb->p_cap) == NULL)
+    {
+        /* report failure */
+        evt.status = BTA_AV_FAIL_RESOURCES;
+        evt.chnl   = p_scb->chnl;
+        evt.hndl   = p_scb->hndl;
+        (*bta_av_cb.p_cback)(BTA_AV_RECONFIG_EVT, (tBTA_AV *)&evt);
+
+        /* this event is not possible in this state.
+         * use it to bring the SSM back to open state */
+        bta_av_ssm_execute(p_scb, BTA_AV_SDP_DISC_OK_EVT, NULL);
+        return;
+    }
 
     alarm_cancel(p_scb->avrc_ct_timer);
 
@@ -2331,7 +2434,9 @@ void bta_av_start_ok (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
     UINT8           new_role = p_scb->role;
     BT_HDR          hdr;
     UINT8           policy = HCI_ENABLE_SNIFF_MODE;
-    UINT8           cur_role;
+    /* Fix for below klockwork issue
+     * 'cur_role' might be used uninitialized in this function */
+    UINT8           cur_role = BTM_ROLE_UNDEFINED;
 
     APPL_TRACE_DEBUG("bta_av_start_ok wait:x%x, role:x%x", p_scb->wait, p_scb->role);
 
@@ -2365,7 +2470,7 @@ void bta_av_start_ok (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
         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, p_scb->hdi, p_scb->peer_addr);
             start.chnl   = p_scb->chnl;
             start.status = BTA_AV_FAIL_ROLE;
             start.hndl   = p_scb->hndl;
@@ -2404,9 +2509,9 @@ void bta_av_start_ok (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
     }
 
     /* tell role manager to check M/S role */
-    bta_sys_conn_open(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->peer_addr);
+    bta_sys_conn_open(BTA_ID_AV, p_scb->hdi, p_scb->peer_addr);
 
-    bta_sys_busy(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->peer_addr);
+    bta_sys_busy(BTA_ID_AV, p_scb->hdi, p_scb->peer_addr);
 
     if(p_scb->media_type == AVDT_MEDIA_AUDIO)
     {
@@ -2432,7 +2537,24 @@ void bta_av_start_ok (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
     }
     else if ((new_role & BTA_AV_ROLE_AD_ACP) && (new_role & BTA_AV_ROLE_SUSPEND_OPT))
     {
-        suspend = TRUE;
+
+        if (bta_av_is_multicast_enabled() == TRUE &&
+            (BTM_GetRole (p_scb->peer_addr, &cur_role) == BTM_SUCCESS)
+            && (cur_role == BTM_ROLE_MASTER))
+        {
+            /* If playing on other stream, dont suspend this. */
+            if (bta_av_chk_start(p_scb))
+            {
+                suspend = FALSE;
+                APPL_TRACE_DEBUG("cur_role: %d suspend: %d", cur_role, suspend);
+            }
+        }
+        else
+        {
+            suspend = TRUE;
+            APPL_TRACE_DEBUG("cur_role: %d suspend: %d", cur_role, suspend);
+
+        }
     }
 
     if (!suspend)
@@ -2473,6 +2595,11 @@ void bta_av_start_ok (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
         start.chnl   = p_scb->chnl;
         start.status = BTA_AV_SUCCESS;
         start.hndl   = p_scb->hndl;
+        // update Master/Slave Role for start event
+        if (BTM_GetRole (p_scb->peer_addr, &cur_role) == BTM_SUCCESS)
+        {
+            start.role = cur_role;
+        }
         (*bta_av_cb.p_cback)(BTA_AV_START_EVT, (tBTA_AV *) &start);
 
         if(suspend)
@@ -2504,7 +2631,7 @@ void bta_av_start_failed (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
 
     if(p_scb->started == FALSE && p_scb->co_started == FALSE)
     {
-        bta_sys_idle(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->peer_addr);
+        bta_sys_idle(BTA_ID_AV, p_scb->hdi, p_scb->peer_addr);
         notify_start_failed(p_scb);
     }
 
@@ -2553,7 +2680,7 @@ void bta_av_str_closed (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
         event = BTA_AV_OPEN_EVT;
         p_scb->open_status = BTA_AV_SUCCESS;
 
-        bta_sys_conn_close(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->peer_addr);
+        bta_sys_conn_close(BTA_ID_AV, p_scb->hdi, p_scb->peer_addr);
         bta_av_cleanup(p_scb, p_data);
         (*bta_av_cb.p_cback)(event, &data);
     }
@@ -2574,7 +2701,7 @@ void bta_av_str_closed (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
             data.close.hndl = p_scb->hndl;
             event = BTA_AV_CLOSE_EVT;
 
-            bta_sys_conn_close(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->peer_addr);
+            bta_sys_conn_close(BTA_ID_AV, p_scb->hdi, p_scb->peer_addr);
             bta_av_cleanup(p_scb, p_data);
             (*bta_av_cb.p_cback)(event, &data);
         }
@@ -2653,7 +2780,7 @@ void bta_av_suspend_cfm (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
         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, p_scb->hdi, p_scb->peer_addr);
     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);
@@ -3095,8 +3222,22 @@ void bta_av_open_rc (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
 *******************************************************************************/
 void bta_av_open_at_inc (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
 {
+    if (!p_scb)
+    {
+        APPL_TRACE_WARNING("scb is NULL, bailing out!");
+        return;
+    }
+
     memcpy (&(p_scb->open_api), &(p_data->api_open), sizeof(tBTA_AV_API_OPEN));
 
+    if (p_scb->coll_mask & BTA_AV_COLL_SETCONFIG_IND)
+    {
+        APPL_TRACE_WARNING(" SetConfig is already called, timer stopped");
+        /* make mask 0, timer shld have already been closed in setconfig_ind */
+        p_scb->coll_mask = 0;
+        return;
+    }
+
     if (p_scb->coll_mask & BTA_AV_COLL_INC_TMR)
     {
         p_scb->coll_mask |= BTA_AV_COLL_API_CALLED;
@@ -3108,6 +3249,7 @@ void bta_av_open_at_inc (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
     {
         /* SNK did not start signalling, API was called N seconds timeout. */
         /* We need to switch to INIT state and start opening connection. */
+        APPL_TRACE_ERROR(" bta_av_open_at_inc ReSetting collision mask  ");
         p_scb->coll_mask = 0;
         bta_av_set_scb_sst_init(p_scb);
 
index 96ff084..602b95e 100644 (file)
@@ -79,6 +79,17 @@ struct blacklist_entry
 #define AVRC_MIN_META_CMD_LEN 20
 #endif
 
+/* state machine states */
+enum
+{
+    BTA_AV_INIT_SST,
+    BTA_AV_INCOMING_SST,
+    BTA_AV_OPENING_SST,
+    BTA_AV_OPEN_SST,
+    BTA_AV_RCFG_SST,
+    BTA_AV_CLOSING_SST
+};
+
 /*******************************************************************************
 **
 ** Function         bta_av_get_rcb_by_shdl
@@ -328,13 +339,14 @@ UINT8 bta_av_rc_create(tBTA_AV_CB *p_cb, UINT8 role, UINT8 shdl, UINT8 lidx)
     tAVRC_CONN_CB ccb;
     BD_ADDR_PTR   bda = (BD_ADDR_PTR)bd_addr_any;
     UINT8         status = BTA_AV_RC_ROLE_ACP;
-    tBTA_AV_SCB  *p_scb = p_cb->p_scb[shdl - 1];
+    tBTA_AV_SCB  *p_scb;
     int i;
     UINT8   rc_handle;
     tBTA_AV_RCB *p_rcb;
 
     if (role == AVCT_INT)
     {
+        p_scb = p_cb->p_scb[shdl - 1];
         bda = p_scb->peer_addr;
         status = BTA_AV_RC_ROLE_INT;
     }
@@ -591,12 +603,16 @@ void bta_av_rc_opened(tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data)
     if (rc_open.peer_features == 0)
     {
         /* we have not done SDP on peer RC capabilities.
-         * peer must have initiated the RC connection
-         * We Don't have SDP records of Peer, so we by
-         * default will take values depending upon registered
-         * features */
-        if (p_cb->features & BTA_AV_FEAT_RCTG)
+         * peer must have initiated the RC connection */
+        /*To update default features based on the local features we support*/
+        if (bta_av_cb.features & BTA_AV_FEAT_RCTG)
+        {
             rc_open.peer_features |= BTA_AV_FEAT_RCCT;
+        }
+        if (bta_av_cb.features & BTA_AV_FEAT_RCCT)
+        {
+            rc_open.peer_features |= BTA_AV_FEAT_RCTG;
+        }
         bta_av_rc_disc(disc);
     }
     (*p_cb->p_cback)(BTA_AV_RC_OPEN_EVT, (tBTA_AV *) &rc_open);
@@ -921,8 +937,7 @@ tBTA_AV_EVT bta_av_proc_meta_cmd(tAVRC_RESPONSE  *p_rc_rsp, tBTA_AV_RC_MSG *p_ms
 tBTA_AV_EVT bta_av_proc_browse_cmd(tAVRC_RESPONSE  *p_rc_rsp, tBTA_AV_RC_MSG *p_msg)
 {
     tBTA_AV_EVT evt = BTA_AV_BROWSE_MSG_EVT;
-    UINT8       u8, pdu, *p;
-    UINT16      u16;
+    UINT8       pdu;
     tAVRC_MSG_BROWSE *p_browse = &p_msg->msg.browse;
 
     pdu = p_browse->p_browse_data[0];
@@ -1511,7 +1526,10 @@ void bta_av_disable(tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data)
 
     bta_av_close_all_rc(p_cb);
 
-    osi_free_and_reset((void **)&p_cb->p_disc_db);
+    if(p_cb->p_disc_db) {
+           (void)SDP_CancelServiceSearch (p_cb->p_disc_db);
+        osi_free_and_reset((void **)&p_cb->p_disc_db);
+    }
 
     /* disable audio/video - de-register all channels,
      * expect BTA_AV_DEREG_COMP_EVT when deregister is complete */
@@ -1566,15 +1584,48 @@ void bta_av_sig_chg(tBTA_AV_DATA *p_data)
         p_lcb = bta_av_find_lcb(p_data->str_msg.bd_addr, BTA_AV_LCB_FIND);
         if (!p_lcb)
         {
+            if (p_cb->conn_lcb > 0)
+            {
+                APPL_TRACE_DEBUG("Already connected to LCBs: 0x%x", p_cb->conn_lcb);
+            }
+            /* Check if busy processing a connection, if yes, Reject the
+             * new incoming connection.
+             * This is very rare case to happen as the timeout to start
+             * signalling procedure is just 2 sec.
+             * Also sink initiators will have retry machanism.
+             * Even though busy flag is set during outgoing connection to
+             * reject incoming connection at L2CAP connect request, there
+             * is a chance to get here if the incoming connection has passed
+             * the L2CAP connection stage.
+             */
+            if((p_data->hdr.offset == AVDT_ACP) && (AVDT_GetServiceBusyState() == TRUE))
+            {
+                APPL_TRACE_ERROR("%s Incoming conn while processing another.. Reject",
+                    __FUNCTION__);
+                AVDT_DisconnectReq (p_data->str_msg.bd_addr, NULL);
+                return;
+            }
+
             /* if the address does not have an LCB yet, alloc one */
             for(xx=0; xx<BTA_AV_NUM_LINKS; xx++)
             {
                 mask = 1 << xx;
-                APPL_TRACE_DEBUG("conn_lcb: 0x%x", p_cb->conn_lcb);
+                APPL_TRACE_DEBUG("The current conn_lcb: 0x%x", p_cb->conn_lcb);
 
                 /* look for a p_lcb with its p_scb registered */
                 if ((!(mask & p_cb->conn_lcb)) && (p_cb->p_scb[xx] != NULL))
                 {
+                    /* Check if the SCB is Free before using for
+                     * ACP connection
+                     */
+                    if ((p_data->hdr.offset == AVDT_ACP) &&
+                        (p_cb->p_scb[xx]->state != BTA_AV_INIT_SST))
+                    {
+                        APPL_TRACE_DEBUG("SCB in use %d", xx);
+                        continue;
+                    }
+
+                    APPL_TRACE_DEBUG("Found a free p_lcb : 0x%x", xx);
                     p_lcb = &p_cb->lcb[xx];
                     p_lcb->lidx = xx + 1;
                     bdcpy(p_lcb->addr, p_data->str_msg.bd_addr);
@@ -1699,6 +1750,9 @@ void bta_av_signalling_timer(tBTA_AV_DATA *p_data)
                                     BTA_AV_SIGNALLING_TIMEOUT_MS,
                                     BTA_AV_SIGNALLING_TIMER_EVT, 0);
                 bdcpy(pend.bd_addr, p_lcb->addr);
+                APPL_TRACE_DEBUG("bta_av_sig_timer on IDX = %d",xx);
+                //Copy the handle of SCB
+                pend.hndl = p_cb->p_scb[xx]->hndl;
                 (*p_cb->p_cback)(BTA_AV_PENDING_EVT, (tBTA_AV *) &pend);
             }
         }
@@ -1720,6 +1774,7 @@ static void bta_av_accept_signalling_timer_cback(void *data)
     UINT32   inx = PTR_TO_UINT(data);
     tBTA_AV_CB  *p_cb = &bta_av_cb;
     tBTA_AV_SCB *p_scb = NULL;
+
     if (inx < BTA_AV_NUM_STRS)
     {
         p_scb = p_cb->p_scb[inx];
@@ -2027,7 +2082,10 @@ void bta_av_rc_disc_done(tBTA_AV_DATA *p_data)
     else
     {
         /* Validate array index*/
-        if (((p_cb->disc & BTA_AV_HNDL_MSK) - 1) < BTA_AV_NUM_STRS)
+        /* Fix for below klockwork issue
+         * Array 'p_scb' size is 2
+         * Possible attempt to access element -1 of array 'p_scb' */
+        if ((((p_cb->disc & BTA_AV_HNDL_MSK) - 1) < BTA_AV_NUM_STRS) && (((p_cb->disc & BTA_AV_HNDL_MSK) - 1) >= 0))
         {
             p_scb = p_cb->p_scb[(p_cb->disc & BTA_AV_HNDL_MSK) - 1];
         }
@@ -2084,7 +2142,20 @@ void bta_av_rc_disc_done(tBTA_AV_DATA *p_data)
                 if (p_lcb)
                 {
                     rc_handle = bta_av_rc_create(p_cb, AVCT_INT, (UINT8)(p_scb->hdi + 1), p_lcb->lidx);
-                    p_cb->rcb[rc_handle].peer_features = peer_features;
+                    if(rc_handle != BTA_AV_RC_HANDLE_NONE)
+                    {
+                        p_cb->rcb[rc_handle].peer_features = peer_features;
+                    }
+                    else
+                    {
+                        /* cannot create valid rc_handle for current device */
+                        APPL_TRACE_ERROR(" No link resources available");
+                        p_scb->use_rc = FALSE;
+                        bdcpy(rc_open.peer_addr, p_scb->peer_addr);
+                        rc_open.peer_features = 0;
+                        rc_open.status = BTA_AV_FAIL_RESOURCES;
+                        (*p_cb->p_cback)(BTA_AV_RC_CLOSE_EVT, (tBTA_AV *) &rc_open);
+                    }
                 }
 #if (BT_USE_TRACES == TRUE || BT_TRACE_APPL == TRUE)
                 else
index 5a033c9..fb438bc 100644 (file)
@@ -223,11 +223,12 @@ void BTA_AvDisconnect(BD_ADDR bd_addr)
 ** Returns          void
 **
 *******************************************************************************/
-void BTA_AvStart(void)
+void BTA_AvStart(tBTA_AV_HNDL handle)
 {
     BT_HDR *p_buf = (BT_HDR *) osi_malloc(sizeof(BT_HDR));
 
     p_buf->event = BTA_AV_API_START_EVT;
+    p_buf->layer_specific   = handle;
 
     bta_sys_sendmsg(p_buf);
 }
@@ -305,7 +306,7 @@ void BTA_AvEnable_Sink(int enable)
 ** Returns          void
 **
 *******************************************************************************/
-void BTA_AvStop(BOOLEAN suspend)
+void BTA_AvStop(BOOLEAN suspend, tBTA_AV_HNDL handle)
 {
     tBTA_AV_API_STOP *p_buf =
         (tBTA_AV_API_STOP *)osi_malloc(sizeof(tBTA_AV_API_STOP));
@@ -313,12 +314,35 @@ void BTA_AvStop(BOOLEAN suspend)
     p_buf->hdr.event = BTA_AV_API_STOP_EVT;
     p_buf->flush = TRUE;
     p_buf->suspend = suspend;
+    p_buf->hdr.layer_specific   = handle;
 
     bta_sys_sendmsg(p_buf);
 }
 
 /*******************************************************************************
 **
+** Function         BTA_AvEnableMultiCast
+**
+** Description      Enable/Disable Avdtp MultiCast
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_AvEnableMultiCast(BOOLEAN state, tBTA_AV_HNDL handle)
+{
+    tBTA_AV_ENABLE_MULTICAST  *p_buf;
+
+    if ((p_buf = (tBTA_AV_ENABLE_MULTICAST *) osi_malloc(sizeof(tBTA_AV_ENABLE_MULTICAST))) != NULL)
+    {
+        p_buf->hdr.event = BTA_AV_ENABLE_MULTICAST_EVT;
+        p_buf->hdr.layer_specific   = handle;
+        p_buf->is_multicast_enabled = state;
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
 ** Function         BTA_AvReconfig
 **
 ** Description      Reconfigure the audio/video stream.
index dbe4c77..ea087c7 100644 (file)
@@ -106,7 +106,8 @@ enum
     BTA_AV_AVDT_RPT_CONN_EVT,
 #endif
     BTA_AV_API_START_EVT,       /* the following 2 events must be in the same order as the *AP_*EVT */
-    BTA_AV_API_STOP_EVT
+    BTA_AV_API_STOP_EVT,
+    BTA_AV_ENABLE_MULTICAST_EVT /* Event for enable and disable multicast */
 };
 
 /* events for AV control block state machine */
@@ -118,13 +119,13 @@ enum
 
 /* events that do not go through state machine */
 #define BTA_AV_FIRST_NSM_EVT    BTA_AV_API_ENABLE_EVT
-#define BTA_AV_LAST_NSM_EVT     BTA_AV_API_STOP_EVT
+#define BTA_AV_LAST_NSM_EVT     BTA_AV_ENABLE_MULTICAST_EVT
 
 /* API events passed to both SSMs (by bta_av_api_to_ssm) */
 #define BTA_AV_FIRST_A2S_API_EVT    BTA_AV_API_START_EVT
 #define BTA_AV_FIRST_A2S_SSM_EVT    BTA_AV_AP_START_EVT
 
-#define BTA_AV_LAST_EVT             BTA_AV_API_STOP_EVT
+#define BTA_AV_LAST_EVT             BTA_AV_ENABLE_MULTICAST_EVT
 
 /* maximum number of SEPS in stream discovery results */
 #define BTA_AV_NUM_SEPS         32
@@ -154,7 +155,6 @@ enum
 #define BTA_AV_MULTI_AV_SUPPORTED   0x01
 #define BTA_AV_MULTI_AV_IN_USE      0x02
 
-
 /*****************************************************************************
 **  Data types
 *****************************************************************************/
@@ -243,6 +243,13 @@ typedef struct
     BOOLEAN             flush;
 } tBTA_AV_API_STOP;
 
+/* data type for BTA_AV_ENABLE_MULTICAST_EVT */
+typedef struct
+{
+    BT_HDR              hdr;
+    BOOLEAN             is_multicast_enabled;
+} tBTA_AV_ENABLE_MULTICAST;
+
 /* data type for BTA_AV_API_DISCONNECT_EVT */
 typedef struct
 {
@@ -434,6 +441,7 @@ typedef union
     tBTA_AV_SDP_RES         sdp_res;
     tBTA_AV_API_META_RSP    api_meta_rsp;
     tBTA_AV_API_STATUS_RSP  api_status_rsp;
+    tBTA_AV_ENABLE_MULTICAST  multicast_state;
 } tBTA_AV_DATA;
 
 typedef void (tBTA_AV_VDP_DATA_ACT)(void *p_scb);
@@ -473,6 +481,7 @@ typedef union
 /* Bitmap for collision, coll_mask */
 #define BTA_AV_COLL_INC_TMR             0x01 /* Timer is running for incoming L2C connection */
 #define BTA_AV_COLL_API_CALLED          0x02 /* API open was called while incoming timer is running */
+#define BTA_AV_COLL_SETCONFIG_IND    0x04 /* SetConfig indication has been called by remote */
 
 /* type for AV stream control block */
 typedef struct
@@ -649,7 +658,7 @@ extern void bta_av_set_scb_sst_init (tBTA_AV_SCB *p_scb);
 extern BOOLEAN bta_av_is_scb_init (tBTA_AV_SCB *p_scb);
 extern void bta_av_set_scb_sst_incoming (tBTA_AV_SCB *p_scb);
 extern tBTA_AV_LCB * bta_av_find_lcb(BD_ADDR addr, UINT8 op);
-
+extern BOOLEAN bta_av_is_multicast_enabled();
 
 /* main functions */
 extern void bta_av_api_deregister(tBTA_AV_DATA *p_data);
index 1a7e2f4..5c40658 100644 (file)
@@ -123,7 +123,7 @@ static const UINT8 bta_av_st_init[][BTA_AV_NUM_COLS] =
 /* API_VENDOR_CMD_EVT */    {BTA_AV_IGNORE,         BTA_AV_INIT_ST },
 /* API_VENDOR_RSP_EVT */    {BTA_AV_IGNORE,         BTA_AV_INIT_ST },
 /* API_META_RSP_EVT */      {BTA_AV_RC_FREE_RSP,    BTA_AV_INIT_ST },
-/* API_RC_CLOSE_EVT */      {BTA_AV_IGNORE,         BTA_AV_INIT_ST },
+/* API_RC_CLOSE_EVT */      {BTA_AV_RC_CLOSE,       BTA_AV_INIT_ST },
 /* AVRC_OPEN_EVT */         {BTA_AV_RC_OPENED,      BTA_AV_OPEN_ST },
 /* AVRC_MSG_EVT */          {BTA_AV_RC_FREE_MSG,    BTA_AV_INIT_ST },
 /* AVRC_NONE_EVT */         {BTA_AV_IGNORE,         BTA_AV_INIT_ST },
@@ -170,6 +170,8 @@ static void bta_av_sco_chg_cback(tBTA_SYS_CONN_STATUS status, UINT8 id, UINT8
                                  app_id, BD_ADDR peer_addr);
 static void bta_av_sys_rs_cback (tBTA_SYS_CONN_STATUS status,UINT8 id, UINT8 app_id, BD_ADDR peer_addr);
 
+static void bta_av_api_enable_multicast(tBTA_AV_DATA *p_data);
+
 /* action functions */
 const tBTA_AV_NSM_ACT bta_av_nsm_act[] =
 {
@@ -185,13 +187,14 @@ const tBTA_AV_NSM_ACT bta_av_nsm_act[] =
     bta_av_conn_chg,        /* BTA_AV_CONN_CHG_EVT */
     bta_av_dereg_comp,      /* BTA_AV_DEREG_COMP_EVT */
 #if (BTA_AV_SINK_INCLUDED == TRUE)
-    bta_av_api_sink_enable, /* BTA_AV_API_SINK_ENABLE_EVT */
+    bta_av_api_sink_enable,         /* BTA_AV_API_SINK_ENABLE_EVT */
 #endif
 #if (AVDT_REPORTING == TRUE)
-    bta_av_rpc_conn,        /* BTA_AV_AVDT_RPT_CONN_EVT */
+    bta_av_rpc_conn,                /* BTA_AV_AVDT_RPT_CONN_EVT */
 #endif
-    bta_av_api_to_ssm,      /* BTA_AV_API_START_EVT */
-    bta_av_api_to_ssm,      /* BTA_AV_API_STOP_EVT */
+    bta_av_api_to_ssm,              /* BTA_AV_API_START_EVT */
+    bta_av_api_to_ssm,              /* BTA_AV_API_STOP_EVT */
+    bta_av_api_enable_multicast,    /* BTA_AV_ENABLE_MULTICAST_EVT */
 };
 
 /*****************************************************************************
@@ -207,6 +210,7 @@ tBTA_AV_CB  bta_av_cb;
 static char *bta_av_st_code(UINT8 state);
 #endif
 
+static BOOLEAN is_multicast_enabled = FALSE;
 /*******************************************************************************
 **
 ** Function         bta_av_api_enable
@@ -358,6 +362,7 @@ static tBTA_AV_SCB * bta_av_alloc_scb(tBTA_AV_CHNL chnl)
                 p_ret->a2d_list = list_new(NULL);
                 p_ret->avrc_ct_timer = alarm_new("bta_av.avrc_ct_timer");
                 bta_av_cb.p_scb[xx] = p_ret;
+                APPL_TRACE_EVENT("AV: Alloc success, handle is =%d", p_ret->hndl);
                 break;
             }
         }
@@ -493,6 +498,8 @@ static void bta_av_api_register(tBTA_AV_DATA *p_data)
     tBTA_AV_CODEC   codec_type;
     tBTA_UTL_COD    cod;
     UINT8           index = 0;
+    UINT8           xx;
+    UINT16          profile_initialized;
 
     memset(&cs,0,sizeof(tAVDT_CS));
 
@@ -500,8 +507,10 @@ static void bta_av_api_register(tBTA_AV_DATA *p_data)
     registr.app_id = p_data->api_reg.app_id;
     registr.chnl   = (tBTA_AV_CHNL)p_data->hdr.layer_specific;
 
-    UINT16 profile_initialized = p_data->api_reg.service_uuid;
-    if (profile_initialized == UUID_SERVCLASS_AUDIO_SINK)
+    APPL_TRACE_DEBUG("bta_av_api_register : channel %d", registr.chnl);
+
+    profile_initialized = p_data->api_reg.service_uuid;
+    if(profile_initialized == UUID_SERVCLASS_AUDIO_SINK)
     {
         p_bta_av_cfg  = (tBTA_AV_CFG *) &bta_avk_cfg;
     }
@@ -605,6 +614,7 @@ static void bta_av_api_register(tBTA_AV_DATA *p_data)
         if(registr.chnl == BTA_AV_CHNL_AUDIO)
         {
             /* set up the audio stream control block */
+            APPL_TRACE_EVENT("AV: set up the audio stream control block ");
             p_scb->p_act_tbl = (const tBTA_AV_ACT *)bta_av_a2d_action;
             p_scb->p_cos     = &bta_av_a2d_cos;
             p_scb->media_type= AVDT_MEDIA_AUDIO;
@@ -638,7 +648,7 @@ static void bta_av_api_register(tBTA_AV_DATA *p_data)
             }
 
             /* Initialize Handles to zero */
-            for (int xx=0; xx < BTA_AV_MAX_SEPS; xx++)
+            for(xx=0; xx<BTA_AV_MAX_SEPS; xx++)
             {
                 p_scb->seps[xx].av_handle = 0;
             }
@@ -683,9 +693,10 @@ static void bta_av_api_register(tBTA_AV_DATA *p_data)
                     bta_sys_add_uuid(UUID_SERVCLASS_AUDIO_SINK);
 #endif
                 }
+
                 /* start listening when A2DP is registered */
                 if (bta_av_cb.features & BTA_AV_FEAT_RCTG)
-                    bta_av_rc_create(&bta_av_cb, AVCT_ACP, 0, BTA_AV_NUM_LINKS + 1);
+                    bta_av_rc_create(&bta_av_cb, AVCT_ACP, p_scb->hdi, BTA_AV_NUM_LINKS + 1);
 
                 /* if the AV and AVK are both supported, it cannot support the CT role */
                 if (bta_av_cb.features & (BTA_AV_FEAT_RCCT))
@@ -725,7 +736,7 @@ static void bta_av_api_register(tBTA_AV_DATA *p_data)
                 }
             }
             bta_av_cb.reg_audio |= BTA_AV_HNDL_TO_MSK(p_scb->hdi);
-            APPL_TRACE_DEBUG("reg_audio: 0x%x",bta_av_cb.reg_audio);
+            APPL_TRACE_DEBUG("reg_audio: 0x%x", bta_av_cb.reg_audio);
         }
         else
         {
@@ -781,12 +792,12 @@ static void bta_av_ci_data(tBTA_AV_DATA *p_data)
     tBTA_AV_SCB *p_scb;
     int     i;
     UINT8   chnl = (UINT8)p_data->hdr.layer_specific;
-
     for( i=0; i < BTA_AV_NUM_STRS; i++ )
     {
         p_scb = bta_av_cb.p_scb[i];
-
-        if(p_scb && p_scb->chnl == chnl)
+        //Check if the Stream is in Started state before sending data
+        //in Dual Handoff mode, get SCB where START is done.
+        if(p_scb && (p_scb->chnl == chnl) && (p_scb->started))
         {
             bta_av_ssm_execute(p_scb, BTA_AV_SRC_DATA_READY_EVT, p_data);
         }
@@ -809,6 +820,20 @@ static void bta_av_rpc_conn(tBTA_AV_DATA *p_data)
 }
 #endif
 
+BOOLEAN bta_av_multiple_streams_started(void)
+{
+    int xx, stream_count = 0;
+
+    for(xx = 0; xx < BTA_AV_NUM_STRS; xx++)
+    {
+        if((bta_av_cb.p_scb[xx] != NULL) && bta_av_cb.p_scb[xx]->started == TRUE)
+        {
+            stream_count++;
+        }
+    }
+    return (stream_count > 1);
+}
+
 /*******************************************************************************
 **
 ** Function         bta_av_api_to_ssm
@@ -824,14 +849,46 @@ static void bta_av_api_to_ssm(tBTA_AV_DATA *p_data)
     int xx;
     UINT16 event = p_data->hdr.event - BTA_AV_FIRST_A2S_API_EVT + BTA_AV_FIRST_A2S_SSM_EVT;
 
-    for(xx=0; xx<BTA_AV_NUM_STRS; xx++)
+    /* Multicast: Corner case handling for multicast state getting
+     * updated for ACL connected during the stream start where both
+     * streams are not yet started. We need to take care of this
+     * during suspend to ensure we suspend both streams.
+     */
+    if ((is_multicast_enabled == TRUE) ||
+        ((event == BTA_AV_AP_STOP_EVT) && (bta_av_multiple_streams_started() == TRUE)))
+    {
+        /* Send START request to all Open Stream connections.*/
+        for(xx=0; xx<BTA_AV_NUM_STRS; xx++)
+        {
+            bta_av_ssm_execute(bta_av_cb.p_scb[xx], event, p_data);
+        }
+    }
+    else
     {
-        bta_av_ssm_execute(bta_av_cb.p_scb[xx], event, p_data);
+        /*In Dual A2dp Handoff, process this fucntion on specific handles.*/
+        APPL_TRACE_DEBUG("bta_av_api_to_ssm: on Handle 0x%x",p_data->hdr.layer_specific);
+        bta_av_ssm_execute(bta_av_hndl_to_scb(p_data->hdr.layer_specific), event, p_data);
     }
 }
 
 /*******************************************************************************
 **
+** Function         bta_av_api_enable_multicast
+**
+** Description      Enable/Disable Avdtp multicast
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_av_api_enable_multicast(tBTA_AV_DATA *p_data)
+{
+    is_multicast_enabled = p_data->multicast_state.is_multicast_enabled;
+    APPL_TRACE_DEBUG("is_multicast_enabled :%d", is_multicast_enabled);
+}
+
+/*******************************************************************************
+**
 ** Function         bta_av_chk_start
 **
 ** Description      if this is audio channel, check if more than one audio
@@ -845,7 +902,7 @@ BOOLEAN bta_av_chk_start(tBTA_AV_SCB *p_scb)
     BOOLEAN start = FALSE;
     tBTA_AV_SCB *p_scbi;
     int i;
-
+    APPL_TRACE_DEBUG("bta_av_chk_start: Audio open count: 0x%x",bta_av_cb.audio_open_cnt);
     if(p_scb->chnl == BTA_AV_CHNL_AUDIO)
     {
         if ((bta_av_cb.audio_open_cnt >= 2) &&
@@ -859,7 +916,16 @@ BOOLEAN bta_av_chk_start(tBTA_AV_SCB *p_scb)
                 p_scbi = bta_av_cb.p_scb[i];
                 if(p_scbi && p_scbi->chnl == BTA_AV_CHNL_AUDIO && p_scbi->co_started)
                 {
-                    start = TRUE;
+                    if (is_multicast_enabled == TRUE)
+                    {
+                        start = TRUE;
+                    }
+                    else
+                    {
+                        start = FALSE;
+                        APPL_TRACE_DEBUG("bta_av_chk_start: Already playing");
+                        break;
+                    }
                     /* may need to update the flush timeout of this already started stream */
                     if(p_scbi->co_started != bta_av_cb.audio_open_cnt)
                     {
@@ -967,11 +1033,17 @@ static void bta_av_sys_rs_cback (tBTA_SYS_CONN_STATUS status,UINT8 id, UINT8 app
         {
             APPL_TRACE_DEBUG ("bta_av_sys_rs_cback: rs_idx(%d), hndl:x%x q_tag: %d",
                 bta_av_cb.rs_idx, p_scb->hndl, p_scb->q_tag);
-
+            /* Multicast:
+             * As per Multicast feature implementation, fallback
+             * happens to soft hand-off when DUT is in scatternet
+             * scenario. Hence, don't fail the connection if
+             * role switch fails because of remote disallowing.
+             * Set switch_res to BTA_AV_RS_DONE on failure.
+             */
             if(HCI_SUCCESS == app_id || HCI_ERR_NO_CONNECTION == app_id)
                 p_scb->q_info.open.switch_res = BTA_AV_RS_OK;
             else
-                p_scb->q_info.open.switch_res = BTA_AV_RS_FAIL;
+                p_scb->q_info.open.switch_res = BTA_AV_RS_DONE;
 
             /* Continue av open process */
             bta_av_do_disc_a2d (p_scb, (tBTA_AV_DATA *)&(p_scb->q_info.open));
@@ -1281,6 +1353,7 @@ BOOLEAN bta_av_hdl_event(BT_HDR *p_msg)
         APPL_TRACE_VERBOSE("AV nsm event=0x%x", event);
 #endif
         /* non state machine events */
+
         (*bta_av_nsm_act[event - BTA_AV_FIRST_NSM_EVT]) ((tBTA_AV_DATA *) p_msg);
     }
     else if (event >= BTA_AV_FIRST_SM_EVT && event <= BTA_AV_LAST_SM_EVT)
@@ -1303,6 +1376,20 @@ BOOLEAN bta_av_hdl_event(BT_HDR *p_msg)
     return TRUE;
 }
 
+/*******************************************************************************
+**
+** Function         bta_av_is_multicast_enabled
+**
+** Description      return status of Avdtp multicast
+**
+**
+** Returns          BOOLEAN
+**
+*******************************************************************************/
+BOOLEAN bta_av_is_multicast_enabled()
+{
+    return is_multicast_enabled;
+}
 /*****************************************************************************
 **  Debug Functions
 *****************************************************************************/
@@ -1402,6 +1489,7 @@ char *bta_av_evt_code(UINT16 evt_code)
 #endif
     case BTA_AV_API_START_EVT: return "API_START";
     case BTA_AV_API_STOP_EVT: return "API_STOP";
+    case BTA_AV_ENABLE_MULTICAST_EVT: return "MULTICAST_ENABLE";
     default:             return "unknown";
     }
 }
index 9805de6..e60a14d 100644 (file)
@@ -172,7 +172,7 @@ static const UINT8 bta_av_sst_incoming[][BTA_AV_NUM_COLS] =
 /* STR_DISC_OK_EVT */       {BTA_AV_DISC_RES_AS_ACP,BTA_AV_SIGNORE,        BTA_AV_INCOMING_SST },
 /* STR_DISC_FAIL_EVT */     {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INCOMING_SST },
 /* STR_GETCAP_OK_EVT */     {BTA_AV_SAVE_CAPS,      BTA_AV_SIGNORE,        BTA_AV_INCOMING_SST },
-/* STR_GETCAP_FAIL_EVT */   {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INCOMING_SST },
+/* STR_GETCAP_FAIL_EVT */   {BTA_AV_OPEN_FAILED,    BTA_AV_SIGNORE,        BTA_AV_CLOSING_SST },
 /* STR_OPEN_OK_EVT */       {BTA_AV_STR_OPENED,     BTA_AV_SIGNORE,        BTA_AV_OPEN_SST },
 /* STR_OPEN_FAIL_EVT */     {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INCOMING_SST },
 /* STR_START_OK_EVT */      {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INCOMING_SST },
@@ -464,6 +464,43 @@ void bta_av_ssm_execute(tBTA_AV_SCB *p_scb, UINT16 event, tBTA_AV_DATA *p_data)
 
     event -= BTA_AV_FIRST_SSM_EVT;
 
+    if((p_scb->state != BTA_AV_OPENING_SST) &&
+        (state_table[event][BTA_AV_SNEXT_STATE] == BTA_AV_OPENING_SST))
+    {
+        AVDT_UpdateServiceBusyState(TRUE);
+    }
+    else if(AVDT_GetServiceBusyState() == TRUE)
+    {
+        BOOLEAN keep_busy = TRUE;
+
+        for (xx = 0; xx < BTA_AV_NUM_STRS; xx++)
+        {
+            if (bta_av_cb.p_scb[xx])
+            {
+                if ((bta_av_cb.p_scb[xx]->state == BTA_AV_OPENING_SST) &&
+                    (bta_av_cb.p_scb[xx] != p_scb))
+                {
+                    /* There is other SCB in opening state
+                     * keep the service state in progress
+                     */
+                    APPL_TRACE_VERBOSE("SCB in opening state. Keep Busy");
+                    keep_busy = TRUE;
+                    break;
+                }
+                else if ((bta_av_cb.p_scb[xx]->state == BTA_AV_OPENING_SST) &&
+                    (bta_av_cb.p_scb[xx] == p_scb) &&
+                    (state_table[event][BTA_AV_SNEXT_STATE] != BTA_AV_OPENING_SST))
+                {
+                    keep_busy = FALSE;
+                }
+            }
+        }
+        if (keep_busy == FALSE)
+        {
+            AVDT_UpdateServiceBusyState(FALSE);
+        }
+    }
+
     /* set next state */
     p_scb->state = state_table[event][BTA_AV_SNEXT_STATE];
 
index f0d1606..8cb96f8 100644 (file)
@@ -256,9 +256,9 @@ typedef UINT8 tBTA_AV_ERR;
 #define BTA_AV_MEDIA_DATA_EVT   21      /* sending data to Media Task */
 #define BTA_AV_OFFLOAD_START_RSP_EVT 22 /* a2dp offload start response */
 #define BTA_AV_BROWSE_MSG_EVT   23      /* Browse MSG EVT */
+#define BTA_AV_ROLE_CHANGED_EVT     24
 /* Max BTA event */
-#define BTA_AV_MAX_EVT          24
-
+#define BTA_AV_MAX_EVT          25
 
 typedef UINT8 tBTA_AV_EVT;
 
@@ -291,6 +291,7 @@ typedef struct
     BOOLEAN         starting;
     tBTA_AV_EDR     edr;        /* 0, if peer device does not support EDR */
     UINT8           sep;        /*  sep type of peer device */
+    UINT8           role;       /* 0x00 master, 0x01 slave , 0xFF unkown*/
 } tBTA_AV_OPEN;
 
 /* data associated with BTA_AV_CLOSE_EVT */
@@ -308,6 +309,7 @@ typedef struct
     tBTA_AV_STATUS  status;
     BOOLEAN         initiator; /* TRUE, if local device initiates the START */
     BOOLEAN         suspending;
+    UINT8           role;       /* 0x00 master, 0x01 slave , 0xFF unkown*/
 } tBTA_AV_START;
 
 /* data associated with BTA_AV_SUSPEND_EVT */
@@ -429,6 +431,7 @@ typedef struct
 typedef struct
 {
     BD_ADDR         bd_addr;
+    tBTA_AV_HNDL    hndl;    /* Handle associated with the stream. */
 } tBTA_AV_PEND;
 
 /* data associated with BTA_AV_REJECT_EVT */
@@ -438,6 +441,13 @@ typedef struct
     tBTA_AV_HNDL    hndl;       /* Handle associated with the stream that rejected the connection. */
 } tBTA_AV_REJECT;
 
+/* data associated with BTA_AV_ROLE_CHANGED */
+typedef struct
+{
+    BD_ADDR  bd_addr;
+    UINT8    new_role;
+    tBTA_AV_HNDL    hndl;       /* Handle associated with role change event */
+} tBTA_AV_ROLE_CHANGED;
 
 /* union of data associated with AV callback */
 typedef union
@@ -464,6 +474,7 @@ typedef union
     tBTA_AV_REJECT      reject;
     tBTA_AV_RC_FEAT     rc_feat;
     tBTA_AV_STATUS      status;
+    tBTA_AV_ROLE_CHANGED role_changed;
 } tBTA_AV;
 
 typedef struct
@@ -646,25 +657,36 @@ void BTA_AvEnable_Sink(int enable);
 **
 ** Function         BTA_AvStart
 **
-** Description      Start audio/video stream data transfer.
+** Description      Start audio/video stream data transfer on the AV handle.
 **
 ** Returns          void
 **
 *******************************************************************************/
-void BTA_AvStart(void);
+void BTA_AvStart(tBTA_AV_HNDL hndl);
 
 /*******************************************************************************
 **
 ** Function         BTA_AvStop
 **
-** Description      Stop audio/video stream data transfer.
+** Description      Stop audio/video stream data transfer on the AV handle.
 **                  If suspend is TRUE, this function sends AVDT suspend signal
 **                  to the connected peer(s).
 **
 ** Returns          void
 **
 *******************************************************************************/
-void BTA_AvStop(BOOLEAN suspend);
+void BTA_AvStop(BOOLEAN suspend, tBTA_AV_HNDL handle);
+
+/*******************************************************************************
+**
+** Function         BTA_AvEnableMultiCast
+**
+** Description      Enable/disable Avdtp MultiCast
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_AvEnableMultiCast(BOOLEAN state, tBTA_AV_HNDL handle);
 
 /*******************************************************************************
 **
index ad4e469..c7fd178 100644 (file)
@@ -1492,7 +1492,16 @@ BOOLEAN bta_av_co_audio_codec_supported(tBTIF_STATUS *p_status)
                     APPL_TRACE_DEBUG("bta_av_co_audio_codec_supported sink %d of peer %d doesn't support cp",
                             snk_index, index);
                     *p_status = BTIF_ERROR_SRV_AV_CP_NOT_SUPPORTED;
+#if defined(BTA_AV_CO_CP_SCMS_T) && (BTA_AV_CO_CP_SCMS_T == TRUE)
+                    if (!bta_av_co_audio_codec_build_config(p_sink->codec_caps, codec_cfg))
+                    {
+                        APPL_TRACE_DEBUG2("%s:index %d doesn't support codec", __FUNCTION__, index);
+                        return FALSE;
+                    }
+                    return TRUE;
+#else
                     return FALSE;
+#endif
                 }
 
                 /* Build the codec configuration for this sink */
@@ -1687,6 +1696,7 @@ BOOLEAN bta_av_co_audio_get_sbc_config(tA2D_SBC_CIE *p_sbc_config, UINT16 *p_min
                 p_peer = &bta_av_co_cb.peers[index];
                 if (p_peer->opened)
                 {
+                    APPL_TRACE_EVENT("bta_av_co_audio_get_sbc_config on index= %d", index);
                     if (p_peer->mtu < *p_minmtu)
                     {
                         *p_minmtu = p_peer->mtu;
@@ -1697,6 +1707,7 @@ BOOLEAN bta_av_co_audio_get_sbc_config(tA2D_SBC_CIE *p_sbc_config, UINT16 *p_min
                         if (p_sink->codec_type == A2D_MEDIA_CT_SBC)
                         {
                             /* Update the bitpool boundaries of the current config */
+                            APPL_TRACE_EVENT("Update the bitpool boundaries on index= %d", jndex);
                             p_sbc_config->min_bitpool =
                                BTA_AV_CO_MAX(p_sink->codec_caps[BTA_AV_CO_SBC_MIN_BITPOOL_OFF],
                                              p_sbc_config->min_bitpool);
@@ -1717,6 +1728,7 @@ BOOLEAN bta_av_co_audio_get_sbc_config(tA2D_SBC_CIE *p_sbc_config, UINT16 *p_min
     if (!result)
     {
         /* Not SBC, still return the default values */
+        APPL_TRACE_EVENT("Not SBC, still return the default values");
         *p_sbc_config = btif_av_sbc_default_config;
     }
     mutex_global_unlock();
index 99040ee..a3a5285 100644 (file)
@@ -50,6 +50,8 @@ typedef enum {
     BTIF_AV_SINK_FOCUS_REQ_EVT,
     BTIF_AV_CLEANUP_REQ_EVT,
     BTIF_AV_UPDATE_ENCODER_REQ_EVT,
+    BTIF_AV_INIT_REQ_EVT,
+       
 } btif_av_sm_event_t;
 
 
@@ -79,7 +81,7 @@ btif_sm_handle_t btif_av_get_sm_handle(void);
 **
 *******************************************************************************/
 
-bt_bdaddr_t btif_av_get_addr(void);
+bt_bdaddr_t btif_av_get_addr(BD_ADDR address);
 
 /*******************************************************************************
 ** Function         btif_av_is_sink_enabled
@@ -206,6 +208,18 @@ void btif_av_clear_remote_suspend_flag(void);
 
 /*******************************************************************************
 **
+** Function         btif_av_any_br_peer
+**
+** Description      Check if the any of connected devices is BR device.
+**
+** Returns          TRUE if connected to any BR device, FALSE otherwise.
+**
+*******************************************************************************/
+
+BOOLEAN btif_av_any_br_peer(void);
+
+/*******************************************************************************
+**
 ** Function         btif_av_peer_supports_3mbps
 **
 ** Description      Check if the connected A2DP device supports
index 1b0f58d..197f7b5 100644 (file)
@@ -272,9 +272,9 @@ extern void dump_codec_info(unsigned char *p_codec);
 
 bool btif_a2dp_start_media_task(void);
 void btif_a2dp_stop_media_task(void);
-
+bool btif_a2dp_is_media_task_stopped(void);
 void btif_a2dp_on_init(void);
-void btif_a2dp_setup_codec(void);
+tBTIF_STATUS btif_a2dp_setup_codec(void);
 void btif_a2dp_update_codec(void);
 void btif_a2dp_on_idle(void);
 void btif_a2dp_on_open(void);
index b4caf9e..b98936b 100644 (file)
@@ -45,7 +45,7 @@
 typedef UINT32 btif_sm_state_t;
 typedef UINT32 btif_sm_event_t;
 typedef void* btif_sm_handle_t;
-typedef BOOLEAN(*btif_sm_handler_t)(btif_sm_event_t event, void *data);
+typedef BOOLEAN(*btif_sm_handler_t)(btif_sm_event_t event, void *data, int index);
 
 /*****************************************************************************
 **  Functions
@@ -67,7 +67,7 @@ typedef BOOLEAN(*btif_sm_handler_t)(btif_sm_event_t event, void *data);
 **
 ******************************************************************************/
 btif_sm_handle_t btif_sm_init(const btif_sm_handler_t *p_handlers,
-                               btif_sm_state_t initial_state);
+                               btif_sm_state_t initial_state, int index);
 
 /*****************************************************************************
 **
index 83e6f96..437a2ba 100644 (file)
@@ -1,4 +1,6 @@
 /******************************************************************************
+ *  Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ *  Not a Contribution.
  *
  *  Copyright (C) 2009-2012 Broadcom Corporation
  *
@@ -35,6 +37,7 @@
 #include "btu.h"
 #include "bt_common.h"
 #include "osi/include/allocator.h"
+#include <cutils/properties.h>
 
 /*****************************************************************************
 **  Constants & Macros
 
 #define BTIF_TIMEOUT_AV_OPEN_ON_RC_MS  (2 * 1000)
 
+/* Number of BTIF-AV control blocks */
+/* Now supports Two AV connections. */
+#define BTIF_AV_NUM_CB       2
+#define HANDLE_TO_INDEX(x) ((x & BTA_AV_HNDL_MSK) - 1)
+
 typedef enum {
     BTIF_AV_STATE_IDLE = 0x0,
     BTIF_AV_STATE_OPENING,
@@ -61,6 +69,10 @@ typedef enum {
 #define BTIF_AV_FLAG_REMOTE_SUSPEND        0x2
 #define BTIF_AV_FLAG_PENDING_START         0x4
 #define BTIF_AV_FLAG_PENDING_STOP          0x8
+/* Host role defenitions */
+#define HOST_ROLE_MASTER                   0x00
+#define HOST_ROLE_SLAVE                    0x01
+#define HOST_ROLE_UNKNOWN                  0xff
 
 /*****************************************************************************
 **  Local type definitions
@@ -74,6 +86,13 @@ typedef struct
     UINT8 flags;
     tBTA_AV_EDR edr;
     UINT8 peer_sep;  /* sep type of peer device */
+    UINT8 edr_3mbps;
+    BOOLEAN dual_handoff;
+    BOOLEAN current_playing;
+    btif_sm_state_t state;
+    int service;
+    BOOLEAN is_slave;
+    BOOLEAN is_device_playing;
 } btif_av_cb_t;
 
 typedef struct
@@ -94,12 +113,18 @@ typedef struct
 ******************************************************************************/
 static btav_callbacks_t *bt_av_src_callbacks = NULL;
 static btav_callbacks_t *bt_av_sink_callbacks = NULL;
-static btif_av_cb_t btif_av_cb = {0, {{0}}, 0, 0, 0, 0};
 static alarm_t *av_open_on_rc_timer = NULL;
+static btif_av_cb_t btif_av_cb[BTIF_AV_NUM_CB];
+static btif_sm_event_t idle_rc_event;
+static tBTA_AV idle_rc_data;
+static int btif_max_av_clients = 1;
+static BOOLEAN enable_multicast = FALSE;
+static BOOLEAN is_multicast_supported = FALSE;
+static BOOLEAN multicast_disabled = FALSE;
 
 /* both interface and media task needs to be ready to alloc incoming request */
 #define CHECK_BTAV_INIT() if (((bt_av_src_callbacks == NULL) &&(bt_av_sink_callbacks == NULL)) \
-        || (btif_av_cb.sm_handle == NULL))\
+        || (btif_av_cb[0].sm_handle == NULL))\
 {\
      BTIF_TRACE_WARNING("%s: BTAV not initialized", __FUNCTION__);\
      return BT_STATUS_NOT_READY;\
@@ -111,7 +136,6 @@ else\
 
 /* Helper macro to avoid code duplication in the state machine handlers */
 #define CHECK_RC_EVENT(e, d) \
-    case BTA_AV_RC_OPEN_EVT: \
     case BTA_AV_RC_CLOSE_EVT: \
     case BTA_AV_REMOTE_CMD_EVT: \
     case BTA_AV_VENDOR_CMD_EVT: \
@@ -123,12 +147,26 @@ else\
          btif_rc_handler(e, d);\
     }break; \
 
-static BOOLEAN btif_av_state_idle_handler(btif_sm_event_t event, void *data);
-static BOOLEAN btif_av_state_opening_handler(btif_sm_event_t event, void *data);
-static BOOLEAN btif_av_state_opened_handler(btif_sm_event_t event, void *data);
-static BOOLEAN btif_av_state_started_handler(btif_sm_event_t event, void *data);
-static BOOLEAN btif_av_state_closing_handler(btif_sm_event_t event, void *data);
 
+static BOOLEAN btif_av_state_idle_handler(btif_sm_event_t event, void *data, int index);
+static BOOLEAN btif_av_state_opening_handler(btif_sm_event_t event, void *data, int index);
+static BOOLEAN btif_av_state_opened_handler(btif_sm_event_t event, void *data, int index);
+static BOOLEAN btif_av_state_started_handler(btif_sm_event_t event, void *data,int index);
+
+static BOOLEAN btif_av_state_closing_handler(btif_sm_event_t event, void *data,int index);
+
+static BOOLEAN btif_av_get_valid_idx(int idx);
+static UINT8 btif_av_idx_by_bdaddr( BD_ADDR bd_addr);
+static int btif_get_latest_playing_device_idx();
+static int btif_get_latest_device_idx_to_start();
+static int btif_av_get_valid_idx_for_rc_events(BD_ADDR bd_addr, int rc_handle);
+static int btif_get_conn_state_of_device(BD_ADDR address);
+static bt_status_t connect_int(bt_bdaddr_t *bd_addr, uint16_t uuid);
+static void btif_av_update_current_playing_device(int index);
+static void btif_av_check_rc_connection_priority(void *p_data);
+#ifdef AVK_BACKPORT
+void btif_av_request_audio_focus( BOOLEAN enable);
+#endif
 static const btif_sm_handler_t btif_av_state_handlers[] =
 {
     btif_av_state_idle_handler,
@@ -147,12 +185,27 @@ extern void btif_rc_handler(tBTA_AV_EVT event, tBTA_AV *p_data);
 extern BOOLEAN btif_rc_get_connected_peer(BD_ADDR peer_addr);
 extern UINT8 btif_rc_get_connected_peer_handle(BD_ADDR peer_addr);
 extern void btif_rc_check_handle_pending_play (BD_ADDR peer_addr, BOOLEAN bSendToApp);
+extern void btif_rc_get_playing_device(BD_ADDR address);
+extern void btif_rc_clear_playing_state(BOOLEAN play);
+extern void btif_rc_clear_priority(BD_ADDR address);
+extern void btif_rc_send_pause_command();
+extern UINT16 btif_dm_get_br_edr_links();
+extern UINT16 btif_dm_get_le_links();
+extern UINT16 btif_hf_is_call_idle();
 
 extern fixed_queue_t *btu_general_alarm_queue;
 
 /*****************************************************************************
 ** Local helper functions
 ******************************************************************************/
+void btif_av_trigger_dual_handoff(BOOLEAN handoff, BD_ADDR address);
+BOOLEAN btif_av_is_device_connected(BD_ADDR address);
+
+BOOLEAN btif_av_is_connected_on_other_idx(int current_index);
+BOOLEAN btif_av_is_playing_on_other_idx(int current_index);
+BOOLEAN btif_av_is_playing();
+void btif_av_update_multicast_state(int index);
+BOOLEAN btif_av_get_ongoing_multicast();
 
 const char *dump_av_sm_state_name(btif_av_state_t state)
 {
@@ -208,6 +261,8 @@ const char *dump_av_sm_event_name(btif_av_sm_event_t event)
         default: return "UNKNOWN_EVENT";
    }
 }
+//TODO.. We will remove this data structure
+static BD_ADDR bd_null= {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
 
 /****************************************************************************
 **  Local helper functions
@@ -226,36 +281,49 @@ const char *dump_av_sm_event_name(btif_av_sm_event_t event)
 static void btif_initiate_av_open_timer_timeout(UNUSED_ATTR void *data)
 {
     BD_ADDR peer_addr;
-    btif_av_connect_req_t connect_req;
 
     /* is there at least one RC connection - There should be */
-    if (btif_rc_get_connected_peer(peer_addr)) {
-       BTIF_TRACE_DEBUG("%s Issuing connect to the remote RC peer", __FUNCTION__);
-       btif_sm_state_t state = btif_sm_get_state(btif_av_cb.sm_handle);
-       if ((state == BTIF_AV_STATE_STARTED) || (state == BTIF_AV_STATE_OPENED) ||
-           (state == BTIF_AV_STATE_OPENING)) {
-           if(bdcmp(btif_av_cb.peer_bda.address, peer_addr))
-           {
-               BTIF_TRACE_DEBUG("%s A2DP Connection Already UP", __FUNCTION__);
-               BTA_AvCloseRc(btif_rc_get_connected_peer_handle(peer_addr));
-               BTIF_TRACE_WARNING("%s Disconnecting AVRCP", __FUNCTION__);
-               return;
-           }
-       }
-       /* In case of AVRCP connection request, we will initiate SRC connection */
-       connect_req.target_bda = (bt_bdaddr_t*)&peer_addr;
-       if(bt_av_sink_callbacks != NULL)
-           connect_req.uuid = UUID_SERVCLASS_AUDIO_SINK;
-       else if(bt_av_src_callbacks != NULL)
-           connect_req.uuid = UUID_SERVCLASS_AUDIO_SOURCE;
-       btif_sm_dispatch(btif_av_cb.sm_handle, BTIF_AV_CONNECT_REQ_EVT, (char*)&connect_req);
+    /*We have Two Connections.*/
+    if (btif_rc_get_connected_peer(peer_addr))
+    {
+        /*Check if this peer_addr is same as currently connected AV*/
+        if (btif_get_conn_state_of_device(peer_addr) == BTIF_AV_STATE_OPENED)
+        {
+            BTIF_TRACE_DEBUG("AV is already connected");
+        }
+        else
+        {
+            UINT8 rc_handle;
+            int index;
+            /* Multicast: Check if AV slot is available for connection
+             * If not available, AV got connected to different devices.
+             * Disconnect this RC connection without AV connection.
+             */
+            rc_handle = btif_rc_get_connected_peer_handle(peer_addr);
+            index = btif_av_get_valid_idx_for_rc_events(peer_addr, rc_handle);
+            if(index >= btif_max_av_clients)
+            {
+                BTIF_TRACE_ERROR("%s No slot free for AV connection, back off",
+                            __FUNCTION__);
+                return;
+            }
+            BTIF_TRACE_DEBUG("%s Issuing connect to the remote RC peer", __FUNCTION__);
+            if(bt_av_sink_callbacks != NULL)
+                btif_queue_connect(UUID_SERVCLASS_AUDIO_SINK, (bt_bdaddr_t*)&peer_addr,
+                        connect_int);
+            if(bt_av_src_callbacks != NULL)
+                btif_queue_connect(UUID_SERVCLASS_AUDIO_SOURCE, (bt_bdaddr_t*)&peer_addr,
+                        connect_int);
+        }
     }
     else
     {
         BTIF_TRACE_ERROR("%s No connected RC peers", __FUNCTION__);
     }
+
 }
 
+
 /*****************************************************************************
 **  Static functions
 ******************************************************************************/
@@ -274,7 +342,7 @@ static void btif_report_connection_state(btav_connection_state_t state, bt_bdadd
 {
     if (bt_av_sink_callbacks != NULL) {
         HAL_CBACK(bt_av_sink_callbacks, connection_state_cb, state, bd_addr);
-    } else if (bt_av_src_callbacks != NULL) {
+    } else if ( bt_av_src_callbacks != NULL) {
         HAL_CBACK(bt_av_src_callbacks, connection_state_cb, state, bd_addr);
     }
 }
@@ -311,75 +379,63 @@ static void btif_report_audio_state(btav_audio_state_t state, bt_bdaddr_t *bd_ad
 **
 *******************************************************************************/
 
-static BOOLEAN btif_av_state_idle_handler(btif_sm_event_t event, void *p_data)
+static BOOLEAN btif_av_state_idle_handler(btif_sm_event_t event, void *p_data, int index)
 {
-    BTIF_TRACE_IMP("%s event:%s flags %x", __FUNCTION__,
-                     dump_av_sm_event_name(event), btif_av_cb.flags);
+    char a2dp_role[255] = "false";
+
+    BTIF_TRACE_IMP("%s event:%s flags %x on Index = %d", __FUNCTION__,
+                     dump_av_sm_event_name(event), btif_av_cb[index].flags, index);
 
     switch (event)
     {
         case BTIF_SM_ENTER_EVT:
             /* clear the peer_bda */
-            memset(&btif_av_cb.peer_bda, 0, sizeof(bt_bdaddr_t));
-            btif_av_cb.flags = 0;
-            btif_av_cb.edr = 0;
-            btif_a2dp_on_idle();
+            BTIF_TRACE_EVENT("IDLE state for index: %d", index);
+            memset(&btif_av_cb[index].peer_bda, 0, sizeof(bt_bdaddr_t));
+            btif_av_cb[index].flags = 0;
+            btif_av_cb[index].edr_3mbps = 0;
+            btif_av_cb[index].edr = 0;
+            btif_av_cb[index].current_playing = FALSE;
+            btif_av_cb[index].is_slave = FALSE;
+            btif_av_cb[index].is_device_playing = FALSE;
+            for (int i = 0; i < btif_max_av_clients; i++)
+            {
+                btif_av_cb[i].dual_handoff = FALSE;
+            }
+            property_get("persist.service.bt.a2dp.sink", a2dp_role, "false");
+            if (!strncmp("false", a2dp_role, 5)) {
+                btif_av_cb[index].peer_sep = AVDT_TSEP_SNK;
+                btif_a2dp_set_peer_sep(AVDT_TSEP_SNK);
+            } else {
+                btif_av_cb[index].peer_sep = AVDT_TSEP_SRC;
+                btif_a2dp_set_peer_sep(AVDT_TSEP_SRC);
+            }
+            /* This API will be called twice at initialization
+            ** Idle can be moved when device is disconnected too.
+            ** Take care of other connected device here.*/
+            if (!btif_av_is_connected())
+            {
+                BTIF_TRACE_EVENT("reset A2dp states in IDLE ");
+                btif_a2dp_on_idle();
+            }
+            else
+            {
+                //There is another AV connection, update current playin
+                BTIF_TRACE_EVENT("reset A2dp states in IDLE ");
+                btif_av_update_current_playing_device(index);
+            }
             break;
 
         case BTIF_SM_EXIT_EVT:
             break;
 
         case BTA_AV_ENABLE_EVT:
+            BTIF_TRACE_EVENT("AV is enabled now for index: %d", index);
             break;
 
         case BTA_AV_REGISTER_EVT:
-            btif_av_cb.bta_handle = ((tBTA_AV*)p_data)->registr.hndl;
-            break;
-
-        case BTA_AV_PENDING_EVT:
-        case BTIF_AV_CONNECT_REQ_EVT:
-        {
-             if (event == BTIF_AV_CONNECT_REQ_EVT)
-             {
-                 memcpy(&btif_av_cb.peer_bda, ((btif_av_connect_req_t*)p_data)->target_bda,
-                                                                   sizeof(bt_bdaddr_t));
-                 BTA_AvOpen(btif_av_cb.peer_bda.address, btif_av_cb.bta_handle,
-                    TRUE, BTA_SEC_AUTHENTICATE, ((btif_av_connect_req_t*)p_data)->uuid);
-             }
-             else if (event == BTA_AV_PENDING_EVT)
-             {
-                  bdcpy(btif_av_cb.peer_bda.address, ((tBTA_AV*)p_data)->pend.bd_addr);
-                  if (bt_av_src_callbacks != NULL)
-                  {
-                      BTA_AvOpen(btif_av_cb.peer_bda.address, btif_av_cb.bta_handle,
-                        TRUE, BTA_SEC_AUTHENTICATE, UUID_SERVCLASS_AUDIO_SOURCE);
-                  }
-                  if (bt_av_sink_callbacks != NULL)
-                  {
-                      BTA_AvOpen(btif_av_cb.peer_bda.address, btif_av_cb.bta_handle,
-                                 TRUE, BTA_SEC_AUTHENTICATE, UUID_SERVCLASS_AUDIO_SINK);
-                  }
-             }
-             btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_OPENING);
-        } break;
-
-        case BTA_AV_RC_OPEN_EVT:
-            /* IOP_FIX: Jabra 620 only does RC open without AV open whenever it connects. So
-             * as per the AV WP, an AVRC connection cannot exist without an AV connection. Therefore,
-             * we initiate an AV connection if an RC_OPEN_EVT is received when we are in AV_CLOSED state.
-             * We initiate the AV connection after a small 3s timeout to avoid any collisions from the
-             * headsets, as some headsets initiate the AVRC connection first and then
-             * immediately initiate the AV connection
-             *
-             * TODO: We may need to do this only on an AVRCP Play. FixMe
-             */
-
-            BTIF_TRACE_DEBUG("BTA_AV_RC_OPEN_EVT received w/o AV");
-            alarm_set_on_queue(av_open_on_rc_timer,
-                               BTIF_TIMEOUT_AV_OPEN_ON_RC_MS,
-                               btif_initiate_av_open_timer_timeout, NULL,
-                               btu_general_alarm_queue);
-            btif_rc_handler(event, p_data);
+            BTIF_TRACE_EVENT("The AV Handle:%d", ((tBTA_AV*)p_data)->registr.hndl);
+            btif_av_cb[index].bta_handle = ((tBTA_AV*)p_data)->registr.hndl;
             break;
 
            /*
@@ -403,46 +459,148 @@ static BOOLEAN btif_av_state_idle_handler(btif_sm_event_t event, void *p_data)
             }
         } break;
 
+        case BTIF_AV_CONNECT_REQ_EVT:
+            /* For outgoing connect stack and app are in sync.
+            */
+            memcpy(&btif_av_cb[index].peer_bda, ((btif_av_connect_req_t*)p_data)->target_bda,
+                                                                        sizeof(bt_bdaddr_t));
+            BTA_AvOpen(btif_av_cb[index].peer_bda.address, btif_av_cb[index].bta_handle,
+                        TRUE, BTA_SEC_NONE, ((btif_av_connect_req_t*)p_data)->uuid);
+            btif_sm_change_state(btif_av_cb[index].sm_handle, BTIF_AV_STATE_OPENING);
+            break;
+
+        case BTA_AV_PENDING_EVT:
+        case BTA_AV_RC_OPEN_EVT:
+            /* IOP_FIX: Jabra 620 only does RC open without AV open whenever it connects. So
+             * as per the AV WP, an AVRC connection cannot exist without an AV connection. Therefore,
+             * we initiate an AV connection if an RC_OPEN_EVT is received when we are in AV_CLOSED state.
+             * We initiate the AV connection after a small 3s timeout to avoid any collisions from the
+             * headsets, as some headsets initiate the AVRC connection first and then
+             * immediately initiate the AV connection
+             *
+             * TODO: We may need to do this only on an AVRCP Play. FixMe
+             */
+            /* Check if connection allowed with this device */
+            /* In Dual A2dp case, this event can come for both the headsets.
+             * Reject second connection request as we are already checking
+             * for device priority for first device and we cannot queue
+             * incoming connections requests.
+             */
+
+            if (idle_rc_event != 0)
+            {
+                BTIF_TRACE_DEBUG("Processing another RC Event ");
+                return FALSE;
+            }
+            memcpy(&idle_rc_data, ((tBTA_AV*)p_data), sizeof(tBTA_AV));
+            if (event == BTA_AV_RC_OPEN_EVT)
+            {
+                if (((tBTA_AV*)p_data)->rc_open.status == BTA_AV_SUCCESS)
+                {
+                    bdcpy(btif_av_cb[index].peer_bda.address,
+                        ((tBTA_AV*)p_data)->rc_open.peer_addr);
+                }
+                else
+                {
+                    idle_rc_event = 0;
+                    return TRUE;
+                }
+            }
+            else
+            {
+                bdcpy(btif_av_cb[index].peer_bda.address, ((tBTA_AV*)p_data)->pend.bd_addr);
+            }
+
+            // Only for AVDTP connection request move to opening state
+            if (event == BTA_AV_PENDING_EVT)
+                btif_sm_change_state(btif_av_cb[index].sm_handle, BTIF_AV_STATE_OPENING);
+
+            if (bt_av_src_callbacks != NULL)
+            {
+                BTIF_TRACE_DEBUG("Calling connection priority callback ");
+                idle_rc_event = event;
+                HAL_CBACK(bt_av_src_callbacks, connection_priority_cb,
+                         &(btif_av_cb[index].peer_bda));
+            }
+            if (bt_av_sink_callbacks != NULL)
+            {
+                if(event == BTA_AV_PENDING_EVT)
+                {
+                    BTA_AvOpen(btif_av_cb[index].peer_bda.address, btif_av_cb[index].bta_handle,
+                       TRUE, BTA_SEC_NONE, UUID_SERVCLASS_AUDIO_SINK);
+                }
+                else if(event == BTA_AV_RC_OPEN_EVT)
+                {
+                           alarm_set_on_queue(av_open_on_rc_timer,
+                                                         BTIF_TIMEOUT_AV_OPEN_ON_RC_MS,
+                                                         btif_initiate_av_open_timer_timeout, NULL,
+                                                         btu_general_alarm_queue);
+                    btif_rc_handler(event, p_data);
+                }
+            }
+            break;
+
         case BTA_AV_OPEN_EVT:
         {
+            /* We get this event in Idle State if Signaling
+             * channel is not closed, only Streaming channel was
+             * closed earlier, and now only stream setup process is
+             * initiated.
+             */
             tBTA_AV *p_bta_data = (tBTA_AV*)p_data;
             btav_connection_state_t state;
-            btif_sm_state_t av_state;
             BTIF_TRACE_DEBUG("status:%d, edr 0x%x",p_bta_data->open.status,
                                p_bta_data->open.edr);
 
             if (p_bta_data->open.status == BTA_AV_SUCCESS)
             {
                  state = BTAV_CONNECTION_STATE_CONNECTED;
-                 av_state = BTIF_AV_STATE_OPENED;
-                 btif_av_cb.edr = p_bta_data->open.edr;
-
-                 btif_av_cb.peer_sep = p_bta_data->open.sep;
+                 btif_av_cb[index].edr = p_bta_data->open.edr;
+                 if (p_bta_data->open.role == HOST_ROLE_SLAVE)
+                 {
+                    btif_av_cb[index].is_slave = TRUE;
+                 }
+                 btif_av_cb[index].peer_sep = p_bta_data->open.sep;
                  btif_a2dp_set_peer_sep(p_bta_data->open.sep);
+
+                 if (p_bta_data->open.edr & BTA_AV_EDR_3MBPS)
+                 {
+                     BTIF_TRACE_DEBUG("remote supports 3 mbps");
+                     btif_av_cb[index].edr_3mbps = TRUE;
+                 }
+
+                 bdcpy(btif_av_cb[index].peer_bda.address, ((tBTA_AV*)p_data)->open.bd_addr);
             }
             else
             {
                 BTIF_TRACE_WARNING("BTA_AV_OPEN_EVT::FAILED status: %d",
                                      p_bta_data->open.status );
                 state = BTAV_CONNECTION_STATE_DISCONNECTED;
-                av_state  = BTIF_AV_STATE_IDLE;
             }
 
-            /* inform the application of the event */
-            btif_report_connection_state(state, &(btif_av_cb.peer_bda));
-            /* change state to open/idle based on the status */
-            btif_sm_change_state(btif_av_cb.sm_handle, av_state);
-            if (btif_av_cb.peer_sep == AVDT_TSEP_SNK)
+            /* change state to open based on the status */
+            if (p_bta_data->open.status == BTA_AV_SUCCESS)
+            {
+                /* inform the application of the event */
+                btif_report_connection_state(state, &(btif_av_cb[index].peer_bda));
+                btif_sm_change_state(btif_av_cb[index].sm_handle, BTIF_AV_STATE_OPENED);
+                /* BTIF AV State updated, now check
+                 * and update multicast state
+                 */
+                btif_av_update_multicast_state(index);
+            }
+
+            if (btif_av_cb[index].peer_sep == AVDT_TSEP_SNK)
             {
                 /* if queued PLAY command,  send it now */
                 btif_rc_check_handle_pending_play(p_bta_data->open.bd_addr,
                                              (p_bta_data->open.status == BTA_AV_SUCCESS));
             }
-            else if ((btif_av_cb.peer_sep == AVDT_TSEP_SRC) &&
+            else if ((btif_av_cb[index].peer_sep == AVDT_TSEP_SRC) &&
                     (p_bta_data->open.status == BTA_AV_SUCCESS))
             {
                 /* Bring up AVRCP connection too */
-                BTA_AvOpenRc(btif_av_cb.bta_handle);
+                BTA_AvOpenRc(btif_av_cb[index].bta_handle);
             }
             btif_queue_advance();
         } break;
@@ -487,30 +645,25 @@ static BOOLEAN btif_av_state_idle_handler(btif_sm_event_t event, void *p_data)
 **
 *******************************************************************************/
 
-static BOOLEAN btif_av_state_opening_handler(btif_sm_event_t event, void *p_data)
+static BOOLEAN btif_av_state_opening_handler(btif_sm_event_t event, void *p_data, int index)
 {
-    BTIF_TRACE_IMP("%s event:%s flags %x", __FUNCTION__,
-                     dump_av_sm_event_name(event), btif_av_cb.flags);
-
-    if (event == BTA_AV_RC_OPEN_EVT)
-    {
-        tBTA_AV *p_av = (tBTA_AV*)p_data;
-        if(bdcmp(btif_av_cb.peer_bda.address, p_av->rc_open.peer_addr))
-        {
-            BTIF_TRACE_WARNING("%s A2dp connected to other device, close this Avrcp", __FUNCTION__);
-            BTA_AvCloseRc(p_av->rc_open.rc_handle);
-        }
-        else
-        {
-            BTIF_TRACE_DEBUG("%s A2dp connected to same device, continue with Avrcp", __FUNCTION__);
-        }
-    }
-
+    int i;
+    BTIF_TRACE_IMP("%s event:%s flags %x on index = %d", __FUNCTION__,
+                     dump_av_sm_event_name(event), btif_av_cb[index].flags, index);
     switch (event)
     {
         case BTIF_SM_ENTER_EVT:
             /* inform the application that we are entering connecting state */
-            btif_report_connection_state(BTAV_CONNECTION_STATE_CONNECTING, &(btif_av_cb.peer_bda));
+            if (bt_av_sink_callbacks != NULL)
+            {
+                HAL_CBACK(bt_av_sink_callbacks, connection_state_cb,
+                         BTAV_CONNECTION_STATE_CONNECTING, &(btif_av_cb[index].peer_bda));
+            }
+            else if (bt_av_src_callbacks != NULL)
+            {
+                HAL_CBACK(bt_av_src_callbacks, connection_state_cb,
+                         BTAV_CONNECTION_STATE_CONNECTING, &(btif_av_cb[index].peer_bda));
+            }
             break;
 
         case BTIF_SM_EXIT_EVT:
@@ -518,8 +671,9 @@ static BOOLEAN btif_av_state_opening_handler(btif_sm_event_t event, void *p_data
 
         case BTA_AV_REJECT_EVT:
             BTIF_TRACE_DEBUG(" Received  BTA_AV_REJECT_EVT ");
-            btif_report_connection_state(BTAV_CONNECTION_STATE_DISCONNECTED, &(btif_av_cb.peer_bda));
-            btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_IDLE);
+            btif_report_connection_state(BTAV_CONNECTION_STATE_DISCONNECTED,
+                                        &(btif_av_cb[index].peer_bda));
+            btif_sm_change_state(btif_av_cb[index].sm_handle, BTIF_AV_STATE_IDLE);
             break;
 
         case BTA_AV_OPEN_EVT:
@@ -527,29 +681,39 @@ static BOOLEAN btif_av_state_opening_handler(btif_sm_event_t event, void *p_data
             tBTA_AV *p_bta_data = (tBTA_AV*)p_data;
             btav_connection_state_t state;
             btif_sm_state_t av_state;
-            BTIF_TRACE_DEBUG("status:%d, edr 0x%x",p_bta_data->open.status,
-                               p_bta_data->open.edr);
+            BTIF_TRACE_DEBUG("status:%d, edr 0x%x, role: 0x%x",p_bta_data->open.status,
+                             p_bta_data->open.edr, p_bta_data->open.role);
 
             if (p_bta_data->open.status == BTA_AV_SUCCESS)
             {
                  state = BTAV_CONNECTION_STATE_CONNECTED;
                  av_state = BTIF_AV_STATE_OPENED;
-                 btif_av_cb.edr = p_bta_data->open.edr;
-
-                 btif_av_cb.peer_sep = p_bta_data->open.sep;
+                 btif_av_cb[index].edr = p_bta_data->open.edr;
+                 if (p_bta_data->open.role == HOST_ROLE_SLAVE)
+                 {
+                    btif_av_cb[index].is_slave = TRUE;
+                 }
+                 btif_av_cb[index].peer_sep = p_bta_data->open.sep;
                  btif_a2dp_set_peer_sep(p_bta_data->open.sep);
+                 if (p_bta_data->open.edr & BTA_AV_EDR_3MBPS)
+                 {
+                     BTIF_TRACE_DEBUG("remote supports 3 mbps");
+                     btif_av_cb[index].edr_3mbps = TRUE;
+                 }
             }
             else
             {
                 BTIF_TRACE_WARNING("BTA_AV_OPEN_EVT::FAILED status: %d",
                                      p_bta_data->open.status );
+                /* Multicast: Check if connected to AVRC only device
+                 * disconnect when Dual A2DP/Multicast is supported.
+                 */
                 BD_ADDR peer_addr;
                 if ((btif_rc_get_connected_peer(peer_addr))
-                    &&(!bdcmp(btif_av_cb.peer_bda.address, peer_addr)))
+                    &&(!bdcmp(btif_av_cb[index].peer_bda.address, peer_addr)))
                 {
-                    /*
-                     * Disconnect AVRCP connection, if
-                     * A2DP conneciton failed, for any reason
+                    /* Disconnect AVRCP connection, if A2DP
+                     * conneciton failed, for any reason
                      */
                     BTIF_TRACE_WARNING(" Disconnecting AVRCP ");
                     BTA_AvCloseRc(btif_rc_get_connected_peer_handle(peer_addr));
@@ -559,20 +723,50 @@ static BOOLEAN btif_av_state_opening_handler(btif_sm_event_t event, void *p_data
             }
 
             /* inform the application of the event */
-            btif_report_connection_state(state, &(btif_av_cb.peer_bda));
+            btif_report_connection_state(state, &(btif_av_cb[index].peer_bda));
             /* change state to open/idle based on the status */
-            btif_sm_change_state(btif_av_cb.sm_handle, av_state);
-            if (btif_av_cb.peer_sep == AVDT_TSEP_SNK)
-            {
-                /* if queued PLAY command,  send it now */
-                btif_rc_check_handle_pending_play(p_bta_data->open.bd_addr,
-                                             (p_bta_data->open.status == BTA_AV_SUCCESS));
-            }
-            else if ((btif_av_cb.peer_sep == AVDT_TSEP_SRC) &&
-                    (p_bta_data->open.status == BTA_AV_SUCCESS))
+            btif_sm_change_state(btif_av_cb[index].sm_handle, av_state);
+            /* Check if the other connected AV is playing,
+            * If YES, trigger DUAL Handoff. */
+            if (p_bta_data->open.status == BTA_AV_SUCCESS)
             {
-                /* Bring up AVRCP connection too */
-                BTA_AvOpenRc(btif_av_cb.bta_handle);
+                /* BTIF AV State updated, now check
+                 * and update multicast state
+                 */
+                btif_av_update_multicast_state(index);
+
+                /*This device should be now ready for all next playbacks*/
+                btif_av_cb[index].current_playing = TRUE;
+                if (enable_multicast == FALSE)
+                {
+                    for (i = 0; i < btif_max_av_clients; i++)
+                    {
+                        //Other device is not current playing
+                        if (i != index)
+                            btif_av_cb[i].current_playing = FALSE;
+                    }
+                    /* In A2dp Multicast, stack will take care of starting
+                     * the stream on newly connected A2dp device. If Handoff
+                     * is supported, trigger Handoff here. */
+                    if (btif_av_is_playing())
+                    {
+                        BTIF_TRACE_DEBUG("Trigger Dual A2dp Handoff on %d", index);
+                        btif_av_trigger_dual_handoff(TRUE, btif_av_cb[index].peer_bda.address);
+                    }
+                }
+                if (btif_av_cb[index].peer_sep == AVDT_TSEP_SNK)
+                {
+                    /* if queued PLAY command,  send it now */
+                    btif_rc_check_handle_pending_play(p_bta_data->open.bd_addr,
+                                (p_bta_data->open.status == BTA_AV_SUCCESS));
+                }
+                else if (btif_av_cb[index].peer_sep == AVDT_TSEP_SRC)
+                {
+                    /* if queued PLAY command,  send it now */
+                    btif_rc_check_handle_pending_play(p_bta_data->open.bd_addr, FALSE);
+                    /* Bring up AVRCP connection too */
+                    BTA_AvOpenRc(btif_av_cb[index].bta_handle);
+                }
             }
             btif_queue_advance();
         } break;
@@ -585,16 +779,16 @@ static BOOLEAN btif_av_state_opening_handler(btif_sm_event_t event, void *p_data
 
             BTIF_TRACE_WARNING("BTIF_AV_SINK_CONFIG_REQ_EVT %d %d", req.sample_rate,
                     req.channel_count);
-            if (btif_av_cb.peer_sep == AVDT_TSEP_SRC && bt_av_sink_callbacks != NULL) {
-                HAL_CBACK(bt_av_sink_callbacks, audio_config_cb, &(btif_av_cb.peer_bda),
+            if (btif_av_cb[index].peer_sep == AVDT_TSEP_SRC && bt_av_sink_callbacks != NULL) {
+                HAL_CBACK(bt_av_sink_callbacks, audio_config_cb, &(btif_av_cb[index].peer_bda),
                         req.sample_rate, req.channel_count);
             }
         } break;
 
         case BTIF_AV_CONNECT_REQ_EVT:
             // Check for device, if same device which moved to opening then ignore callback
-            if (memcmp ((bt_bdaddr_t*)p_data, &(btif_av_cb.peer_bda),
-                sizeof(btif_av_cb.peer_bda)) == 0)
+            if (memcmp ((bt_bdaddr_t*)p_data, &(btif_av_cb[index].peer_bda),
+                sizeof(btif_av_cb[index].peer_bda)) == 0)
             {
                 BTIF_TRACE_DEBUG("%s: Same device moved to Opening state,ignore Connect Req", __func__);
                 btif_queue_advance();
@@ -610,8 +804,8 @@ static BOOLEAN btif_av_state_opening_handler(btif_sm_event_t event, void *p_data
 
         case BTA_AV_PENDING_EVT:
             // Check for device, if same device which moved to opening then ignore callback
-            if (memcmp (((tBTA_AV*)p_data)->pend.bd_addr, &(btif_av_cb.peer_bda),
-                sizeof(btif_av_cb.peer_bda)) == 0)
+            if (memcmp (((tBTA_AV*)p_data)->pend.bd_addr, &(btif_av_cb[index].peer_bda),
+                sizeof(btif_av_cb[index].peer_bda)) == 0)
             {
                 BTIF_TRACE_DEBUG("%s: Same device moved to Opening state,ignore Pending Req", __func__);
                 break;
@@ -629,18 +823,29 @@ static BOOLEAN btif_av_state_opening_handler(btif_sm_event_t event, void *p_data
             break;
 
         case BTA_AV_CLOSE_EVT:
-            btif_a2dp_on_stopped(NULL);
+            /* avdtp link is closed */
+            /* Check if any other device is playing
+            * and this is not the one.*/
+            if (!btif_av_is_playing())
+            {
+                btif_a2dp_on_stopped(NULL);
+            }
+            /* inform the application that we are disconnected */
             btif_report_connection_state(BTAV_CONNECTION_STATE_DISCONNECTED,
-                    &(btif_av_cb.peer_bda));
-            btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_IDLE);
+                    &(btif_av_cb[index].peer_bda));
+            btif_sm_change_state(btif_av_cb[index].sm_handle, BTIF_AV_STATE_IDLE);
             break;
 
         case BTIF_AV_DISCONNECT_REQ_EVT:
             btif_report_connection_state(BTAV_CONNECTION_STATE_DISCONNECTED,
-                &(btif_av_cb.peer_bda));
-            BTA_AvClose(btif_av_cb.bta_handle);
+                &(btif_av_cb[index].peer_bda));
+            BTA_AvClose(btif_av_cb[index].bta_handle);
             btif_queue_advance();
-            btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_IDLE);
+            btif_sm_change_state(btif_av_cb[index].sm_handle, BTIF_AV_STATE_IDLE);
+            break;
+
+        case BTA_AV_RC_OPEN_EVT:
+             btif_rc_handler(event, p_data);;
             break;
 
         CHECK_RC_EVENT(event, p_data);
@@ -665,21 +870,42 @@ static BOOLEAN btif_av_state_opening_handler(btif_sm_event_t event, void *p_data
 **
 *******************************************************************************/
 
-static BOOLEAN btif_av_state_closing_handler(btif_sm_event_t event, void *p_data)
+static BOOLEAN btif_av_state_closing_handler(btif_sm_event_t event, void *p_data, int index)
 {
-    BTIF_TRACE_IMP("%s event:%s flags %x", __FUNCTION__,
-                     dump_av_sm_event_name(event), btif_av_cb.flags);
+    BTIF_TRACE_IMP("%s event:%s flags %x and index = %d", __FUNCTION__,
+                     dump_av_sm_event_name(event), btif_av_cb[index].flags, index);
 
     switch (event)
     {
         case BTIF_SM_ENTER_EVT:
-            if (btif_av_cb.peer_sep == AVDT_TSEP_SNK)
+            if (btif_av_cb[index].peer_sep == AVDT_TSEP_SNK)
             {
-                /* immediately stop transmission of frames */
-                btif_a2dp_set_tx_flush(TRUE);
-                /* wait for audioflinger to stop a2dp */
+                /* Multicast/Soft Hand-off:
+                 * If MC/SHO is enabled we need to keep/start playing on
+                 * other device.
+                 */
+                if (btif_av_is_connected_on_other_idx(index))
+                {
+                    if (btif_av_is_playing())
+                    {
+                        APPL_TRACE_DEBUG("Keep playing on other device");
+                    }
+                    else
+                    {
+                        APPL_TRACE_DEBUG("Not playing on other devie: Set Flush");
+                        btif_a2dp_set_tx_flush(TRUE);
+                    }
+                }
+                else
+                {
+                    /* Single connections scenario:
+                     * Immediately stop transmission of frames
+                     * wait for audioflinger to stop a2dp
+                     */
+                    btif_a2dp_set_tx_flush(TRUE);
+                }
             }
-            if (btif_av_cb.peer_sep == AVDT_TSEP_SRC)
+            if (btif_av_cb[index].peer_sep == AVDT_TSEP_SRC)
             {
                 btif_a2dp_set_rx_flush(TRUE);
             }
@@ -687,17 +913,35 @@ static BOOLEAN btif_av_state_closing_handler(btif_sm_event_t event, void *p_data
 
         case BTA_AV_STOP_EVT:
         case BTIF_AV_STOP_STREAM_REQ_EVT:
-            if (btif_av_cb.peer_sep == AVDT_TSEP_SNK)
+            if (btif_av_cb[index].peer_sep == AVDT_TSEP_SNK)
             {
-              /* immediately flush any pending tx frames while suspend is pending */
-              btif_a2dp_set_tx_flush(TRUE);
+                /* Dont stop in DUAL A2dp connections, as
+                * UIPC will keep waiting for Audio CTRL channel
+                * to get closed which is not required in Dual A2dp.
+                * We will stop only when only single A2dp conn is present.*/
+                if (btif_av_is_connected_on_other_idx(index))
+                {
+                    if (!btif_av_is_playing())
+                    {
+                        APPL_TRACE_WARNING("Suspend the AV Data channel");
+                        //Flush and close media channel
+                        btif_a2dp_set_tx_flush(TRUE);
+                        btif_media_task_stop_aa_req();
+                    }
+                }
+                else
+                {
+                    /* immediately flush any pending tx frames while suspend is pending */
+                    APPL_TRACE_WARNING("Stop the AV Data channel");
+                    btif_a2dp_set_tx_flush(TRUE);
+                    btif_a2dp_on_stopped(NULL);
+                }
             }
-            if (btif_av_cb.peer_sep == AVDT_TSEP_SRC)
+            if (btif_av_cb[index].peer_sep == AVDT_TSEP_SRC)
             {
                 btif_a2dp_set_rx_flush(TRUE);
+                btif_a2dp_on_stopped(NULL);
             }
-
-            btif_a2dp_on_stopped(NULL);
             break;
 
         case BTIF_SM_EXIT_EVT:
@@ -706,9 +950,9 @@ static BOOLEAN btif_av_state_closing_handler(btif_sm_event_t event, void *p_data
         case BTA_AV_CLOSE_EVT:
 
             /* inform the application that we are disconnecting */
-            btif_report_connection_state(BTAV_CONNECTION_STATE_DISCONNECTED, &(btif_av_cb.peer_bda));
+            btif_report_connection_state(BTAV_CONNECTION_STATE_DISCONNECTED, &(btif_av_cb[index].peer_bda));
 
-            btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_IDLE);
+            btif_sm_change_state(btif_av_cb[index].sm_handle, BTIF_AV_STATE_IDLE);
             break;
 
         /* Handle the RC_CLOSE event for the cleanup */
@@ -739,49 +983,84 @@ static BOOLEAN btif_av_state_closing_handler(btif_sm_event_t event, void *p_data
 **
 *******************************************************************************/
 
-static BOOLEAN btif_av_state_opened_handler(btif_sm_event_t event, void *p_data)
+static BOOLEAN btif_av_state_opened_handler(btif_sm_event_t event, void *p_data, int index)
 {
     tBTA_AV *p_av = (tBTA_AV*)p_data;
 
-    BTIF_TRACE_IMP("%s event:%s flags %x", __FUNCTION__,
-                     dump_av_sm_event_name(event), btif_av_cb.flags);
+    BTIF_TRACE_IMP("%s event:%s flags %x and index = %d", __FUNCTION__,
+                     dump_av_sm_event_name(event), btif_av_cb[index].flags, index);
 
-    if ( (event == BTA_AV_REMOTE_CMD_EVT) && (btif_av_cb.flags & BTIF_AV_FLAG_REMOTE_SUSPEND) &&
+    if ((event == BTA_AV_REMOTE_CMD_EVT) &&
          (p_av->remote_cmd.rc_id == BTA_AV_RC_PLAY) )
     {
-        BTIF_TRACE_EVENT("%s: Resetting remote suspend flag on RC PLAY", __FUNCTION__);
-        btif_av_cb.flags &= ~BTIF_AV_FLAG_REMOTE_SUSPEND;
-    }
-
-    if (event == BTA_AV_RC_OPEN_EVT)
-    {
-        if(bdcmp(btif_av_cb.peer_bda.address, p_av->rc_open.peer_addr))
-        {
-            BTIF_TRACE_WARNING("%s A2dp connected to other device, close this Avrcp", __FUNCTION__);
-            BTA_AvCloseRc(p_av->rc_open.rc_handle);
-        }
-        else
+        for (int i = 0; i < btif_max_av_clients; i++)
         {
-            BTIF_TRACE_DEBUG("%s A2dp connected to same device, continue with Avrcp", __FUNCTION__);
+            if (btif_av_cb[i].flags & BTIF_AV_FLAG_REMOTE_SUSPEND)
+            {
+                BTIF_TRACE_EVENT("%s: Resetting remote suspend flag on RC PLAY",
+                        __FUNCTION__);
+                btif_av_cb[i].flags &= ~BTIF_AV_FLAG_REMOTE_SUSPEND;
+            }
         }
     }
 
     switch (event)
     {
         case BTIF_SM_ENTER_EVT:
-            btif_av_cb.flags &= ~BTIF_AV_FLAG_PENDING_STOP;
-            btif_av_cb.flags &= ~BTIF_AV_FLAG_PENDING_START;
+            btif_av_cb[index].flags &= ~BTIF_AV_FLAG_PENDING_STOP;
+            btif_av_cb[index].flags &= ~BTIF_AV_FLAG_PENDING_START;
             break;
 
         case BTIF_SM_EXIT_EVT:
-            btif_av_cb.flags &= ~BTIF_AV_FLAG_PENDING_START;
+            btif_av_cb[index].flags &= ~BTIF_AV_FLAG_PENDING_START;
             break;
 
         case BTIF_AV_START_STREAM_REQ_EVT:
-            if (btif_av_cb.peer_sep != AVDT_TSEP_SRC)
-                btif_a2dp_setup_codec();
-            BTA_AvStart();
-            btif_av_cb.flags |= BTIF_AV_FLAG_PENDING_START;
+            /* update multicast state here if new device is connected
+             * after A2dp connection. New A2dp device is connected
+             * whlie playing */
+            btif_av_update_multicast_state(index);
+            if (btif_av_cb[index].peer_sep == AVDT_TSEP_SRC)
+            {
+                BTA_AvStart(btif_av_cb[index].bta_handle);
+                btif_av_cb[index].flags |= BTIF_AV_FLAG_PENDING_START;
+                break;
+            }
+            tBTIF_STATUS status = btif_a2dp_setup_codec();
+            if (status == BTIF_SUCCESS)
+            {
+                int idx = 0;
+                BTA_AvStart(btif_av_cb[index].bta_handle);
+                if (enable_multicast == TRUE)
+                {
+                    /* In A2dp Multicast, DUT initiated stream request
+                    * should be true for all connected A2dp devices. */
+                    for (; idx < btif_max_av_clients; idx++)
+                    {
+                        btif_av_cb[idx].flags |= BTIF_AV_FLAG_PENDING_START;
+                    }
+                }
+                else
+                {
+                    btif_av_cb[index].flags |= BTIF_AV_FLAG_PENDING_START;
+                }
+            }
+            else if (status == BTIF_ERROR_SRV_AV_CP_NOT_SUPPORTED)
+            {
+#if defined(BTA_AV_DISCONNECT_IF_NO_SCMS_T) && (BTA_AV_DISCONNECT_IF_NO_SCMS_T == TRUE)
+                BTIF_TRACE_ERROR0("SCMST enabled, disconnect as remote does not support SCMST");
+                BTA_AvDisconnect(btif_av_cb[index].peer_bda.address);
+#else
+                BTIF_TRACE_WARNING("SCMST enabled, connecting to non SCMST SEP");
+                BTA_AvStart(btif_av_cb[index].bta_handle);
+                btif_av_cb[index].flags |= BTIF_AV_FLAG_PENDING_START;
+#endif
+            }
+            else
+            {
+                BTIF_TRACE_ERROR("## AV Disconnect## status : %x",status);
+                BTA_AvDisconnect(btif_av_cb[index].peer_bda.address);
+            }
             break;
 
         case BTIF_AV_UPDATE_ENCODER_REQ_EVT:
@@ -790,97 +1069,179 @@ static BOOLEAN btif_av_state_opened_handler(btif_sm_event_t event, void *p_data)
 
         case BTA_AV_START_EVT:
         {
-            BTIF_TRACE_EVENT("BTA_AV_START_EVT status %d, suspending %d, init %d",
+            BTIF_TRACE_DEBUG("BTA_AV_START_EVT status %d, suspending %d, init %d",
                 p_av->start.status, p_av->start.suspending, p_av->start.initiator);
+            BTIF_TRACE_DEBUG("BTA_AV_START_EVT role: %d", p_av->start.role);
+            if (p_av->start.role == HOST_ROLE_SLAVE)
+            {
+                btif_av_cb[index].is_slave = TRUE;
+            }
+            else
+            {
+                // update if we are master after role switch before start
+                btif_av_cb[index].is_slave = FALSE;
+            }
+            /* There can be role switch after device is connected,
+             * hence check for role before starting multicast, and
+             * disable if we are in slave role for any connection
+             */
+            btif_av_update_multicast_state(index);
 
             if ((p_av->start.status == BTA_SUCCESS) && (p_av->start.suspending == TRUE))
                 return TRUE;
 
+            /* if remote tries to start a2dp when call is in progress, suspend it right away */
+            if ((!(btif_av_cb[index].flags & BTIF_AV_FLAG_PENDING_START)) && (!btif_hf_is_call_idle())) {
+                BTIF_TRACE_EVENT("%s: trigger suspend as call is in progress!!", __FUNCTION__);
+                btif_dispatch_sm_event(BTIF_AV_SUSPEND_STREAM_REQ_EVT, NULL, 0);
+            }
+
             /* if remote tries to start a2dp when DUT is a2dp source
              * then suspend. In case a2dp is sink and call is active
              * then disconnect the AVDTP channel
              */
-            if (!(btif_av_cb.flags & BTIF_AV_FLAG_PENDING_START))
+            if (!(btif_av_cb[index].flags & BTIF_AV_FLAG_PENDING_START))
             {
-                if (btif_av_cb.peer_sep == AVDT_TSEP_SNK)
+                if (btif_av_cb[index].peer_sep == AVDT_TSEP_SNK)
                 {
-                    BTIF_TRACE_EVENT("%s: trigger suspend as remote initiated!!", __FUNCTION__);
-                    btif_dispatch_sm_event(BTIF_AV_SUSPEND_STREAM_REQ_EVT, NULL, 0);
+                    if (enable_multicast)
+                    {
+                        /* Stack will start the playback on newly connected
+                         * A2dp device, if the playback is already happening on
+                         * other connected device.*/
+                        if (btif_av_is_playing())
+                        {
+                            /* when HS2 is connected during HS1 playing, stack directly
+                             * sends start event hence update encoder so that least L2CAP
+                             *  MTU is selected.*/
+                            //btif_a2dp_update_codec();
+                            BTIF_TRACE_DEBUG("%s: A2dp Multicast playback",
+                                    __FUNCTION__);
+                        }
+                        /* initiate suspend if start is initiate by remote and multicast
+                         * is enabled.
+                         * Avoid suspend if stream is started as quick suspend-start
+                         * creates IOT issue, seen with SBH50.
+                         */
+
+                        if (!p_av->start.initiator && !btif_av_is_playing())
+                        {
+                            BTIF_TRACE_DEBUG("initiate suspend for remote start");
+                            btif_dispatch_sm_event(BTIF_AV_SUSPEND_STREAM_REQ_EVT, NULL, 0);
+                        }
+                    }
+                    else
+                    {
+                        BTIF_TRACE_DEBUG("%s: trigger suspend as remote initiated!!",
+                                __FUNCTION__);
+                        btif_dispatch_sm_event(BTIF_AV_SUSPEND_STREAM_REQ_EVT, NULL, 0);
+                    }
                 }
             }
 
             /*  In case peer is A2DP SRC we do not want to ack commands on UIPC*/
-            if (btif_av_cb.peer_sep == AVDT_TSEP_SNK)
+            if (btif_av_cb[index].peer_sep == AVDT_TSEP_SNK)
             {
                 if (btif_a2dp_on_started(&p_av->start,
-                    ((btif_av_cb.flags & BTIF_AV_FLAG_PENDING_START) != 0)))
+                    ((btif_av_cb[index].flags & BTIF_AV_FLAG_PENDING_START) != 0)))
                 {
                     /* only clear pending flag after acknowledgement */
-                    btif_av_cb.flags &= ~BTIF_AV_FLAG_PENDING_START;
+                    btif_av_cb[index].flags &= ~BTIF_AV_FLAG_PENDING_START;
                 }
             }
 
             /* remain in open state if status failed */
+            /* Multicast-soft Handoff:
+             * START failed, cleanup Handoff flag.
+             */
             if (p_av->start.status != BTA_AV_SUCCESS)
+            {
+                int i;
+
+                for (i = 0; i < btif_max_av_clients; i++)
+                {
+                    btif_av_cb[i].dual_handoff = FALSE;
+                }
                 return FALSE;
+            }
 
-            if (btif_av_cb.peer_sep == AVDT_TSEP_SRC)
+#ifndef AVK_BACKPORT
+            if (btif_av_cb[index].peer_sep == AVDT_TSEP_SRC)
             {
                 btif_a2dp_set_rx_flush(FALSE); /*  remove flush state, ready for streaming*/
             }
+#endif
 
             /* change state to started, send acknowledgement if start is pending */
-            if (btif_av_cb.flags & BTIF_AV_FLAG_PENDING_START) {
-                if (btif_av_cb.peer_sep == AVDT_TSEP_SNK)
+            if (btif_av_cb[index].flags & BTIF_AV_FLAG_PENDING_START) {
+                if (btif_av_cb[index].peer_sep == AVDT_TSEP_SNK)
                     btif_a2dp_on_started(NULL, TRUE);
                 /* pending start flag will be cleared when exit current state */
             }
-            btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_STARTED);
+            btif_sm_change_state(btif_av_cb[index].sm_handle, BTIF_AV_STATE_STARTED);
 
         } break;
 
         case BTIF_AV_DISCONNECT_REQ_EVT:
-            BTA_AvClose(btif_av_cb.bta_handle);
-            if (btif_av_cb.peer_sep == AVDT_TSEP_SRC) {
-                BTA_AvCloseRc(btif_av_cb.bta_handle);
+            BTA_AvClose(btif_av_cb[index].bta_handle);
+            if (btif_av_cb[index].peer_sep == AVDT_TSEP_SRC) {
+                BTA_AvCloseRc(btif_av_cb[index].bta_handle);
             }
 
             /* inform the application that we are disconnecting */
-            btif_report_connection_state(BTAV_CONNECTION_STATE_DISCONNECTING, &(btif_av_cb.peer_bda));
+            btif_report_connection_state(BTAV_CONNECTION_STATE_DISCONNECTING, &(btif_av_cb[index].peer_bda));
             break;
 
         case BTA_AV_CLOSE_EVT:
              /* avdtp link is closed */
-            btif_a2dp_on_stopped(NULL);
+             /*Dont close the A2dp when Dual playback is happening*/
+             if (btif_av_is_connected_on_other_idx(index))
+             {
+                 APPL_TRACE_WARNING("Conn is closing,close AV data channel");
+                 if (!btif_av_is_playing())
+                 {
+                     APPL_TRACE_WARNING("Suspend the AV Data channel");
+                     /* ensure tx frames are immediately suspended */
+                     btif_a2dp_set_tx_flush(TRUE);
+                     btif_media_task_stop_aa_req();
+                 }
+             }
+             else
+             {
+                 APPL_TRACE_WARNING("Stop the AV Data channel");
+                 btif_a2dp_on_stopped(NULL);
+             }
 
             /* inform the application that we are disconnected */
-            btif_report_connection_state(BTAV_CONNECTION_STATE_DISCONNECTED, &(btif_av_cb.peer_bda));
+            btif_report_connection_state(BTAV_CONNECTION_STATE_DISCONNECTED,
+                                        &(btif_av_cb[index].peer_bda));
 
             /* change state to idle, send acknowledgement if start is pending */
-            if (btif_av_cb.flags & BTIF_AV_FLAG_PENDING_START) {
+            if (btif_av_cb[index].flags & BTIF_AV_FLAG_PENDING_START) {
                 btif_a2dp_ack_fail();
                 /* pending start flag will be cleared when exit current state */
             }
-            btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_IDLE);
+
+            btif_sm_change_state(btif_av_cb[index].sm_handle, BTIF_AV_STATE_IDLE);
             break;
 
         case BTA_AV_RECONFIG_EVT:
-            if((btif_av_cb.flags & BTIF_AV_FLAG_PENDING_START) &&
+            if((btif_av_cb[index].flags & BTIF_AV_FLAG_PENDING_START) &&
                 (p_av->reconfig.status == BTA_AV_SUCCESS))
             {
                APPL_TRACE_WARNING("reconfig done BTA_AVstart()");
-               BTA_AvStart();
+               BTA_AvStart(btif_av_cb[index].bta_handle);
             }
-            else if(btif_av_cb.flags & BTIF_AV_FLAG_PENDING_START)
+            else if(btif_av_cb[index].flags & BTIF_AV_FLAG_PENDING_START)
             {
-               btif_av_cb.flags &= ~BTIF_AV_FLAG_PENDING_START;
+               btif_av_cb[index].flags &= ~BTIF_AV_FLAG_PENDING_START;
                btif_a2dp_ack_fail();
             }
             break;
 
         case BTIF_AV_CONNECT_REQ_EVT:
-            if (memcmp ((bt_bdaddr_t*)p_data, &(btif_av_cb.peer_bda),
-                sizeof(btif_av_cb.peer_bda)) == 0)
+            if (memcmp ((bt_bdaddr_t*)p_data, &(btif_av_cb[index].peer_bda),
+                sizeof(btif_av_cb[index].peer_bda)) == 0)
             {
                 BTIF_TRACE_DEBUG("%s: Ignore BTIF_AV_CONNECT_REQ_EVT for same device", __func__);
             }
@@ -898,6 +1259,9 @@ static BOOLEAN btif_av_state_opened_handler(btif_sm_event_t event, void *p_data)
             BTIF_TRACE_ERROR("BTIF_AV_OFFLOAD_START_REQ_EVT: Stream not Started Opened");
             break;
 
+        case BTA_AV_RC_OPEN_EVT:
+            btif_av_check_rc_connection_priority(p_data);
+            break;
         CHECK_RC_EVENT(event, p_data);
 
         default:
@@ -919,45 +1283,43 @@ static BOOLEAN btif_av_state_opened_handler(btif_sm_event_t event, void *p_data)
 **
 *******************************************************************************/
 
-static BOOLEAN btif_av_state_started_handler(btif_sm_event_t event, void *p_data)
+static BOOLEAN btif_av_state_started_handler(btif_sm_event_t event, void *p_data, int index)
 {
     tBTA_AV *p_av = (tBTA_AV*)p_data;
+    btif_sm_state_t state = BTIF_AV_STATE_IDLE;
+    int i;
 
-    BTIF_TRACE_IMP("%s event:%s flags %x", __FUNCTION__,
-                     dump_av_sm_event_name(event), btif_av_cb.flags);
-
-
-    if (event == BTA_AV_RC_OPEN_EVT)
-    {
-        if(bdcmp(btif_av_cb.peer_bda.address, p_av->rc_open.peer_addr))
-        {
-            BTIF_TRACE_WARNING("%s A2dp connected to other device, close this Avrcp", __FUNCTION__);
-            BTA_AvCloseRc(p_av->rc_open.rc_handle);
-        }
-        else
-        {
-            BTIF_TRACE_DEBUG("%s A2dp connected to same device, continue with Avrcp", __FUNCTION__);
-        }
-    }
+    BTIF_TRACE_IMP("%s event:%s flags %x  index =%d", __FUNCTION__,
+                     dump_av_sm_event_name(event), btif_av_cb[index].flags, index);
 
     switch (event)
     {
         case BTIF_SM_ENTER_EVT:
-
             /* we are again in started state, clear any remote suspend flags */
-            btif_av_cb.flags &= ~BTIF_AV_FLAG_REMOTE_SUSPEND;
+            btif_av_cb[index].flags &= ~BTIF_AV_FLAG_REMOTE_SUSPEND;
 
-            /**
-             * Report to components above that we have entered the streaming
-             * stage, this should usually be followed by focus grant.
-             * see update_audio_focus_state()
-             */
-            btif_report_audio_state(BTAV_AUDIO_STATE_STARTED, &(btif_av_cb.peer_bda));
+            btif_report_audio_state(BTAV_AUDIO_STATE_STARTED, &(btif_av_cb[index].peer_bda));
+            btif_av_cb[index].is_device_playing = TRUE;
 
             /* increase the a2dp consumer task priority temporarily when start
             ** audio playing, to avoid overflow the audio packet queue. */
             adjust_priority_a2dp(TRUE);
-
+#ifdef AVK_BACKPORT
+            if (btif_av_cb[index].peer_sep == AVDT_TSEP_SRC)
+            {
+                btif_av_request_audio_focus(TRUE);
+            }
+#endif
+            //Clear Dual Handoff for all SCBs
+            for (i = 0; i < btif_max_av_clients; i++)
+            {
+                btif_av_cb[i].dual_handoff = FALSE;
+                //Other device is not current playing
+                if (i != index)
+                    btif_av_cb[i].current_playing = FALSE;
+            }
+            //This is latest device to play now
+            btif_av_cb[index].current_playing = TRUE;
             break;
 
         case BTIF_SM_EXIT_EVT:
@@ -968,7 +1330,7 @@ static BOOLEAN btif_av_state_started_handler(btif_sm_event_t event, void *p_data
 
         case BTIF_AV_START_STREAM_REQ_EVT:
             /* we were remotely started, just ack back the local request */
-            if (btif_av_cb.peer_sep == AVDT_TSEP_SNK)
+            if (btif_av_cb[index].peer_sep == AVDT_TSEP_SNK)
                 btif_a2dp_on_started(NULL, TRUE);
             break;
 
@@ -981,56 +1343,118 @@ static BOOLEAN btif_av_state_started_handler(btif_sm_event_t event, void *p_data
         case BTIF_AV_SUSPEND_STREAM_REQ_EVT:
 
             /* set pending flag to ensure btif task is not trying to restart
-               stream while suspend is in progress */
-            btif_av_cb.flags |= BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING;
+             * stream while suspend is in progress.
+             * Multicast: If streaming is happening on both devices, we need
+             * to update flag for both connections as SUSPEND request will
+             * be sent to only one stream as internally BTA takes care of
+             * suspending both streams.
+             */
+            for(i = 0; i < btif_max_av_clients; i++)
+            {
+                state = btif_sm_get_state(btif_av_cb[i].sm_handle);
+                if (state == BTIF_AV_STATE_STARTED)
+                {
+                    btif_av_cb[i].flags |= BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING;
+                }
+            }
 
             /* if we were remotely suspended but suspend locally, local suspend
                always overrides */
-            btif_av_cb.flags &= ~BTIF_AV_FLAG_REMOTE_SUSPEND;
+            btif_av_cb[index].flags &= ~BTIF_AV_FLAG_REMOTE_SUSPEND;
 
-            if (btif_av_cb.peer_sep == AVDT_TSEP_SNK)
+            if (btif_av_cb[index].peer_sep == AVDT_TSEP_SNK)
             {
             /* immediately stop transmission of frames while suspend is pending */
                 btif_a2dp_set_tx_flush(TRUE);
             }
 
-            if (btif_av_cb.peer_sep == AVDT_TSEP_SRC) {
+            if (btif_av_cb[index].peer_sep == AVDT_TSEP_SRC) {
                 btif_a2dp_set_rx_flush(TRUE);
                 btif_a2dp_on_stopped(NULL);
             }
 
-            BTA_AvStop(TRUE);
+            BTA_AvStop(TRUE, btif_av_cb[index].bta_handle);
             break;
 
         case BTIF_AV_DISCONNECT_REQ_EVT:
 
+            //Now it is not the current playing
+            btif_av_cb[index].current_playing = FALSE;
+            btif_av_update_current_playing_device(index);
+            btif_rc_clear_priority(btif_av_cb[index].peer_bda.address);
             /* request avdtp to close */
-            BTA_AvClose(btif_av_cb.bta_handle);
-            if (btif_av_cb.peer_sep == AVDT_TSEP_SRC) {
-                BTA_AvCloseRc(btif_av_cb.bta_handle);
+            BTA_AvClose(btif_av_cb[index].bta_handle);
+            if (btif_av_cb[index].peer_sep == AVDT_TSEP_SRC) {
+                BTA_AvCloseRc(btif_av_cb[index].bta_handle);
             }
 
             /* inform the application that we are disconnecting */
-            btif_report_connection_state(BTAV_CONNECTION_STATE_DISCONNECTING, &(btif_av_cb.peer_bda));
+            btif_report_connection_state(BTAV_CONNECTION_STATE_DISCONNECTING, &(btif_av_cb[index].peer_bda));
 
             /* wait in closing state until fully closed */
-            btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_CLOSING);
+            btif_sm_change_state(btif_av_cb[index].sm_handle, BTIF_AV_STATE_CLOSING);
             break;
 
         case BTA_AV_SUSPEND_EVT:
 
             BTIF_TRACE_EVENT("BTA_AV_SUSPEND_EVT status %d, init %d",
                  p_av->suspend.status, p_av->suspend.initiator);
+            //Check if this suspend is due to DUAL_Handoff
+            if ((btif_av_cb[index].dual_handoff) &&
+                (p_av->suspend.status == BTA_AV_SUCCESS))
+            {
+                BTIF_TRACE_EVENT("BTA_AV_SUSPEND_EVT: Dual handoff");
+                btif_dispatch_sm_event(BTIF_AV_START_STREAM_REQ_EVT, NULL, 0);
+            }
+            if (p_av->suspend.initiator != TRUE)
+            {
+                /* remote suspend, notify HAL and await audioflinger to
+                 * suspend/stop stream
+                 * set remote suspend flag to block media task from restarting
+                 * stream only if we did not already initiate a local suspend
+                 * set remote suspend flag before suspending stream as in race conditions
+                 * when stream is suspended, but flag is things ge tossed up
+                 */
+                BTIF_TRACE_EVENT("Clear before suspending");
+                if ((btif_av_cb[index].flags & BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING) == 0)
+                    btif_av_cb[index].flags |= BTIF_AV_FLAG_REMOTE_SUSPEND;
+                for (int i = 0; i < btif_max_av_clients; i++)
+                {
+                    if ((i != index) && btif_av_get_ongoing_multicast())
+                    {
+                        multicast_disabled = TRUE;
+                        btif_av_update_multicast_state(index);
+                        BTIF_TRACE_EVENT("Initiate suspend for other HS also");
+                        btif_sm_dispatch(btif_av_cb[i].sm_handle,
+                                BTIF_AV_SUSPEND_STREAM_REQ_EVT, NULL);
+                    }
+                }
+            }
 
             /* a2dp suspended, stop media task until resumed */
-            btif_a2dp_on_suspended(&p_av->suspend);
+            /* Multicast: If streaming on other device, don't call onsuspended
+             * as it unblocks the audio process and audio process may send
+             * subsequent commands and create problem during the time where we
+             * still did not receive response for SUSPEND sent to other device.
+             * Keep the suspend failure handling untouched and handle
+             * only success case to check and avoid calling onsuspended.
+             */
+            if ((p_av->suspend.status != BTA_AV_SUCCESS) ||
+                !btif_av_is_playing_on_other_idx(index))
+            {
+                btif_a2dp_on_suspended(&p_av->suspend);
+            }
+            else if(btif_av_is_playing_on_other_idx(index))
+            {
+                BTIF_TRACE_DEBUG("Other device not suspended, don't ack the suspend");
+            }
 
             /* if not successful, remain in current state */
             if (p_av->suspend.status != BTA_AV_SUCCESS)
             {
-                btif_av_cb.flags &= ~BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING;
+                btif_av_cb[index].flags &= ~BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING;
 
-               if (btif_av_cb.peer_sep == AVDT_TSEP_SNK)
+               if (btif_av_cb[index].peer_sep == AVDT_TSEP_SNK)
                {
                 /* suspend failed, reset back tx flush state */
                     btif_a2dp_set_tx_flush(FALSE);
@@ -1040,59 +1464,71 @@ static BOOLEAN btif_av_state_started_handler(btif_sm_event_t event, void *p_data
 
             if (p_av->suspend.initiator != TRUE)
             {
-                /* remote suspend, notify HAL and await audioflinger to
-                   suspend/stop stream */
-
-                /* set remote suspend flag to block media task from restarting
-                   stream only if we did not already initiate a local suspend */
-                if ((btif_av_cb.flags & BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING) == 0)
-                    btif_av_cb.flags |= BTIF_AV_FLAG_REMOTE_SUSPEND;
-
-                btif_report_audio_state(BTAV_AUDIO_STATE_REMOTE_SUSPEND, &(btif_av_cb.peer_bda));
+                btif_report_audio_state(BTAV_AUDIO_STATE_REMOTE_SUSPEND, &(btif_av_cb[index].peer_bda));
             }
             else
             {
-                btif_report_audio_state(BTAV_AUDIO_STATE_STOPPED, &(btif_av_cb.peer_bda));
+                btif_report_audio_state(BTAV_AUDIO_STATE_REMOTE_SUSPEND, &(btif_av_cb[index].peer_bda));
             }
-
-            btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_OPENED);
+            btif_av_cb[index].is_device_playing = FALSE;
+            btif_sm_change_state(btif_av_cb[index].sm_handle, BTIF_AV_STATE_OPENED);
 
             /* suspend completed and state changed, clear pending status */
-            btif_av_cb.flags &= ~BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING;
+            btif_av_cb[index].flags &= ~BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING;
             break;
 
         case BTA_AV_STOP_EVT:
 
-            btif_av_cb.flags |= BTIF_AV_FLAG_PENDING_STOP;
-            btif_a2dp_on_stopped(&p_av->suspend);
+            btif_av_cb[index].flags |= BTIF_AV_FLAG_PENDING_STOP;
+            btif_av_cb[index].current_playing = FALSE;
+            if (btif_av_is_connected_on_other_idx(index))
+            {
+                if (enable_multicast == FALSE)
+                {
+                    APPL_TRACE_WARNING("other Idx is connected, move to SUSPENDED");
+                    btif_rc_send_pause_command();
+                    btif_a2dp_on_stopped(&p_av->suspend);
+                }
+            }
+            else
+            {
+                APPL_TRACE_WARNING("Stop the AV Data channel as no connection is present");
+                btif_a2dp_on_stopped(&p_av->suspend);
+            }
+            btif_av_cb[index].is_device_playing = FALSE;
 
-            btif_report_audio_state(BTAV_AUDIO_STATE_STOPPED, &(btif_av_cb.peer_bda));
 
+            btif_report_audio_state(BTAV_AUDIO_STATE_STOPPED, &(btif_av_cb[index].peer_bda));
             /* if stop was successful, change state to open */
             if (p_av->suspend.status == BTA_AV_SUCCESS)
-                btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_OPENED);
+                btif_sm_change_state(btif_av_cb[index].sm_handle, BTIF_AV_STATE_OPENED);
 
             break;
 
         case BTA_AV_CLOSE_EVT:
 
-             btif_av_cb.flags |= BTIF_AV_FLAG_PENDING_STOP;
+             btif_av_cb[index].flags |= BTIF_AV_FLAG_PENDING_STOP;
 
             /* avdtp link is closed */
+            APPL_TRACE_WARNING("Stop the AV Data channel");
             btif_a2dp_on_stopped(NULL);
 
             /* inform the application that we are disconnected */
-            btif_report_connection_state(BTAV_CONNECTION_STATE_DISCONNECTED, &(btif_av_cb.peer_bda));
+            btif_report_connection_state(BTAV_CONNECTION_STATE_DISCONNECTED,
+                                        &(btif_av_cb[index].peer_bda));
+
+            btif_sm_change_state(btif_av_cb[index].sm_handle, BTIF_AV_STATE_IDLE);
+            break;
 
-            btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_IDLE);
+        case BTA_AV_RC_OPEN_EVT:
+            btif_av_check_rc_connection_priority(p_data);
             break;
 
         case BTIF_AV_OFFLOAD_START_REQ_EVT:
-            BTA_AvOffloadStart(btif_av_cb.bta_handle);
+            BTA_AvOffloadStart(btif_av_cb[index].bta_handle);
             break;
 
         case BTA_AV_OFFLOAD_START_RSP_EVT:
-
             btif_a2dp_on_offload_started(p_av->status);
             break;
 
@@ -1107,24 +1543,6 @@ static BOOLEAN btif_av_state_started_handler(btif_sm_event_t event, void *p_data
     return TRUE;
 }
 
-/*****************************************************************************
-**  Local event handlers
-******************************************************************************/
-
-static void btif_av_handle_event(UINT16 event, char* p_param)
-{
-    switch(event)
-    {
-        case BTIF_AV_CLEANUP_REQ_EVT:
-            BTIF_TRACE_EVENT("%s: BTIF_AV_CLEANUP_REQ_EVT", __FUNCTION__);
-            btif_a2dp_stop_media_task();
-            break;
-
-        default:
-            btif_sm_dispatch(btif_av_cb.sm_handle, event, (void*)p_param);
-            btif_av_event_free_data(event, p_param);
-    }
-}
 
 void btif_av_event_deep_copy(UINT16 event, char *p_dest, char *p_src)
 {
@@ -1219,12 +1637,442 @@ static void btif_av_event_free_data(btif_sm_event_t event, void *p_data)
     }
 }
 
+/*****************************************************************************
+**  Local event handlers
+******************************************************************************/
+
+static void btif_av_handle_event(UINT16 event, char* p_param)
+{
+    int index = 0;
+    tBTA_AV *p_bta_data = (tBTA_AV*)p_param;
+    bt_bdaddr_t * bt_addr;
+    UINT8 role;
+    int uuid;
+
+    switch (event)
+    {
+        case BTIF_AV_INIT_REQ_EVT:
+            BTIF_TRACE_DEBUG("%s: BTIF_AV_INIT_REQ_EVT", __FUNCTION__);
+            if(btif_a2dp_start_media_task())
+                btif_a2dp_on_init();
+            break;
+        /*events from Upper layer and Media Task*/
+        case BTIF_AV_CLEANUP_REQ_EVT: /*Clean up to be called on default index*/
+            BTIF_TRACE_DEBUG("%s: BTIF_AV_CLEANUP_REQ_EVT", __FUNCTION__);
+            uuid = (int)*p_param;
+            if (uuid == BTA_A2DP_SOURCE_SERVICE_ID)
+            {
+                if (bt_av_src_callbacks)
+                {
+                    bt_av_src_callbacks = NULL;
+                    if (bt_av_sink_callbacks != NULL)
+                        break;
+                }
+            }
+            else
+            {
+                if (bt_av_sink_callbacks)
+                {
+                    bt_av_sink_callbacks = NULL;
+                    if (bt_av_src_callbacks != NULL)
+                        break;
+                }
+            }
+
+            btif_a2dp_stop_media_task();
+            return;
+        case BTIF_AV_CONNECT_REQ_EVT:
+            break;
+        case BTIF_AV_DISCONNECT_REQ_EVT:
+            /*Bd address passed should help us in getting the handle*/
+            bt_addr = (bt_bdaddr_t *)p_param;
+            index = btif_av_idx_by_bdaddr(bt_addr->address);
+            break;
+        case BTIF_AV_UPDATE_ENCODER_REQ_EVT:
+        case BTIF_AV_START_STREAM_REQ_EVT:
+            /* Get the last connected device on which START can be issued
+            * Get the Dual A2dp Handoff Device first, if none is present,
+            * go for lastest connected.
+            * In A2dp Multicast, the index selected can be any of the
+            * connected device. Stack will ensure to START the steaming
+            * on both the devices. */
+            index = btif_get_latest_device_idx_to_start();
+            break;
+        case BTIF_AV_STOP_STREAM_REQ_EVT:
+        case BTIF_AV_SUSPEND_STREAM_REQ_EVT:
+            /*Should be handled by current STARTED*/
+            index = btif_get_latest_playing_device_idx();
+            break;
+        /*Events from the stack, BTA*/
+        case BTA_AV_ENABLE_EVT:
+            index = 0;
+            break;
+        case BTA_AV_REGISTER_EVT:
+            index = HANDLE_TO_INDEX(p_bta_data->registr.hndl);
+            break;
+        case BTA_AV_OPEN_EVT:
+            index = HANDLE_TO_INDEX(p_bta_data->open.hndl);
+            break;
+        case BTA_AV_ROLE_CHANGED_EVT:
+            index = HANDLE_TO_INDEX(p_bta_data->role_changed.hndl);
+            role = p_bta_data->role_changed.new_role;
+            BTIF_TRACE_EVENT("Role change: 0x%x: new role: %s",
+                p_bta_data->role_changed.hndl, (role == HOST_ROLE_SLAVE) ? "Slave" : "Master");
+            if (index >= 0 && index < btif_max_av_clients)
+            {
+                btif_av_cb[index].is_slave = (role == HOST_ROLE_SLAVE) ? TRUE : FALSE;
+                btif_av_update_multicast_state(index);
+            }
+            else
+            {
+                BTIF_TRACE_ERROR("%s: Invalid index for connection", __FUNCTION__);
+            }
+            return;
+        case BTA_AV_PENDING_EVT:
+            index = HANDLE_TO_INDEX(p_bta_data->pend.hndl);
+            break;
+        case BTA_AV_REJECT_EVT:
+            index = HANDLE_TO_INDEX(p_bta_data->reject.hndl);
+            break;
+        case BTA_AV_STOP_EVT:
+            index = HANDLE_TO_INDEX(p_bta_data->suspend.hndl);
+            break;
+        case BTA_AV_CLOSE_EVT:
+            index = HANDLE_TO_INDEX(p_bta_data->close.hndl);
+            break;
+        case BTA_AV_START_EVT:
+            index = HANDLE_TO_INDEX(p_bta_data->start.hndl);
+            break;
+        case BTA_AV_RECONFIG_EVT:
+            index = HANDLE_TO_INDEX(p_bta_data->reconfig.hndl);
+            break;
+        case BTA_AV_SUSPEND_EVT:
+            index = HANDLE_TO_INDEX(p_bta_data->suspend.hndl);
+            break;
+
+        /* Handle all RC events on default index. RC handling should take
+         * care of the events. All events come with BD Address
+         * Handled well in AV Opening, opened and started state
+         * AV Idle handler needs to take care of this event properly.
+         */
+        case BTA_AV_RC_OPEN_EVT:
+            index = btif_av_get_valid_idx_for_rc_events(p_bta_data->rc_open.peer_addr,
+                    p_bta_data->rc_open.rc_handle);
+            break;
+        case BTA_AV_RC_CLOSE_EVT:
+        /* If there is no entry in the connection table
+         * RC handler has to be called for cleanup.
+         * Directly call the RC handler as we cannot
+         * associate any AV handle to it.
+         */
+            index = btif_av_idx_by_bdaddr(p_bta_data->rc_open.peer_addr);
+            if (index == btif_max_av_clients)
+            {
+                btif_rc_handler(event, p_bta_data);
+            }
+            break;
+        /* Let the RC handler decide on these passthrough cmds
+         * Use rc_handle to get the active AV device and use that mapping.
+         */
+        case BTA_AV_REMOTE_CMD_EVT:
+        case BTA_AV_VENDOR_CMD_EVT:
+        case BTA_AV_META_MSG_EVT:
+        case BTA_AV_RC_FEAT_EVT:
+        case BTA_AV_BROWSE_MSG_EVT:
+            index = 0;
+            BTIF_TRACE_EVENT("RC events: on index = %d", index);
+            break;
+        default:
+            BTIF_TRACE_ERROR("Unhandled event = %d", event);
+            break;
+    }
+    BTIF_TRACE_DEBUG("Handle the AV event = %x on index = %d", event, index);
+    if (index >= 0 && index < btif_max_av_clients)
+        btif_sm_dispatch(btif_av_cb[index].sm_handle, event, (void*)p_param);
+    else
+        BTIF_TRACE_ERROR("Unhandled Index = %d", index);
+    btif_av_event_free_data(event, p_param);
+
+}
+
+/*******************************************************************************
+**
+** Function         btif_av_get_valid_idx
+**
+** Description      Check the validity of the current index for the connection
+**
+** Returns          Boolean
+**
+*******************************************************************************/
+
+static BOOLEAN btif_av_get_valid_idx(int idx)
+{
+    btif_sm_state_t state = btif_sm_get_state(btif_av_cb[idx].sm_handle);
+    return ((state == BTIF_AV_STATE_OPENED) ||
+            (state ==  BTIF_AV_STATE_STARTED) ||
+            (state == BTIF_AV_STATE_OPENING));
+}
+
+/*******************************************************************************
+**
+** Function         btif_av_idx_by_bdaddr
+**
+** Description      Get the index corresponding to BD addr
+**
+** Returns          UNIT8
+**
+*******************************************************************************/
+
+static UINT8 btif_av_idx_by_bdaddr(BD_ADDR bd_addr)
+{
+    int i;
+    for (i = 0; i < btif_max_av_clients; i++)
+    {
+        if ((bdcmp(bd_addr,
+                  btif_av_cb[i].peer_bda.address) == 0))
+            return i;
+    }
+    return i;
+}
+
+BOOLEAN btif_av_is_current_device(BD_ADDR address)
+{
+    UINT8 index;
+
+    index = btif_av_idx_by_bdaddr(address);
+    if((index < btif_max_av_clients) && btif_av_cb[index].current_playing)
+    {
+        return TRUE;
+    }
+    return FALSE;
+}
+
+/*******************************************************************************
+**
+** Function         btif_get_latest_device_idx_to_start
+**
+** Description      Get the index of the AV where streaming is to be started
+**
+** Returns          int
+**
+*******************************************************************************/
+
+static int btif_get_latest_device_idx_to_start()
+{
+    int i, j;
+    BD_ADDR playing_address;
+
+    /* Get the device which sent PLAY command
+     * If found, START on that index.
+     */
+    memset(playing_address, 0, sizeof(BD_ADDR));
+    btif_rc_get_playing_device(playing_address);
+    if (bdcmp(playing_address, bd_addr_null) != 0)
+    {
+        /* Got some valid Playing device.
+         * Get the AV index for this device.
+         */
+        i = btif_av_idx_by_bdaddr(playing_address);
+        if (i == btif_max_av_clients)
+            return btif_max_av_clients;
+        BTIF_TRACE_EVENT("Got some valid Playing device; %d", i);
+        /*Clear the Current playing device*/
+        for (j = 0; j < btif_max_av_clients; j++)
+        {
+            if (j != i)
+              btif_av_cb[j].current_playing = FALSE;
+        }
+        /*Clear the Play command in RC*/
+        btif_rc_clear_playing_state(FALSE);
+        return i;
+    }
+
+    /*No playing device, get the latest*/
+    for (i = 0; i < btif_max_av_clients; i++)
+    {
+        if (btif_av_cb[i].current_playing)
+            break;
+    }
+    if (i == btif_max_av_clients)
+    {
+        BTIF_TRACE_ERROR("Play on default");
+        i = 0; /*play on default*/
+    }
+    return i;
+}
+
+/*******************************************************************************
+**
+** Function         btif_get_latest_playing_device_idx
+**
+** Description      Get the index of AV where streaming is happening
+**
+** Returns          int
+**
+*******************************************************************************/
+
+static int btif_get_latest_playing_device_idx()
+{
+    int i;
+    btif_sm_state_t state;
+    for (i = 0; i < btif_max_av_clients; i++)
+    {
+        state = btif_sm_get_state(btif_av_cb[i].sm_handle);
+        if (state == BTIF_AV_STATE_STARTED)
+        {
+            break;
+        }
+    }
+    return i;
+}
+
+/*******************************************************************************
+**
+** Function         btif_av_is_playing
+**
+** Description      Is AV in streaming state
+**
+** Returns          BOOLEAN
+**
+*******************************************************************************/
+
+BOOLEAN btif_av_is_playing()
+{
+    int i;
+    for (i = 0; i < btif_max_av_clients; i++)
+    {
+        btif_av_cb[i].state = btif_sm_get_state(btif_av_cb[i].sm_handle);
+        if (btif_av_cb[i].state == BTIF_AV_STATE_STARTED)
+        {
+            BTIF_TRACE_EVENT("btif_av_is_playing on index= %d", i);
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+
+/*******************************************************************************
+**
+** Function         btif_get_conn_state_of_device
+**
+** Description      Returns the state of AV scb
+**
+** Returns          int
+**
+*******************************************************************************/
+
+static int btif_get_conn_state_of_device(BD_ADDR address)
+{
+    btif_sm_state_t state = BTIF_AV_STATE_IDLE;
+    int i;
+    for (i = 0; i < btif_max_av_clients; i++)
+    {
+        if ((bdcmp(address,
+            btif_av_cb[i].peer_bda.address) == 0))
+        {
+            state = btif_sm_get_state(btif_av_cb[i].sm_handle);
+            BTIF_TRACE_EVENT("BD Found: %02X %02X %02X %02X %02X %02X :state: %s",
+                address[5], address[4], address[3],
+                address[2], address[1], address[0],
+                dump_av_sm_state_name(state));
+        }
+    }
+    return state;
+}
+
+/*******************************************************************************
+**
+** Function         btif_av_get_valid_idx_for_rc_events
+**
+** Description      gets th valid index for the RC event address
+**
+** Returns          int
+**
+*******************************************************************************/
+
+static int btif_av_get_valid_idx_for_rc_events(BD_ADDR bd_addr, int rc_handle)
+{
+    int index = 0;
+    /* First try to find if it is first event in AV IF
+    * both the handles would be in IDLE state, pick the first
+    * If we get second RC event while processing the priority
+    * for the first, reject the second connection. */
+
+    /*Get the index from connected SCBs*/
+    index = btif_av_idx_by_bdaddr(bd_addr);
+    if (index == btif_max_av_clients)
+    {
+        /* None of the SCBS matched
+        * Allocate free SCB, null address SCB*/
+        index = btif_av_idx_by_bdaddr(bd_null);
+        BTIF_TRACE_EVENT("btif_av_get_valid_idx_for_rc_events is %d", index);
+        if (index >= btif_max_av_clients)
+        {
+            BTIF_TRACE_EVENT("disconnect only AVRCP device rc_handle %d", rc_handle);
+            BTA_AvCloseRc(rc_handle);
+        }
+    }
+    return index;
+}
+
+/*******************************************************************************
+**
+** Function         btif_av_check_rc_connection_priority
+**
+** Description      Handles Priority callback for RC connections
+**
+** Returns          void
+**
+*******************************************************************************/
+
+static void btif_av_check_rc_connection_priority(void *p_data)
+{
+    bt_bdaddr_t peer_bda;
+
+    /*Check if it is for same AV device*/
+    if (btif_av_is_device_connected(((tBTA_AV*)p_data)->rc_open.peer_addr))
+    {
+        /*AV is connected */
+        BTIF_TRACE_DEBUG("AV is connected, process RC connect event");
+        btif_rc_handler(BTA_AV_RC_OPEN_EVT, (tBTA_AV*)p_data);
+        return;
+    }
+    BTIF_TRACE_DEBUG("btif_av_check_rc_connection_priority");
+    bdcpy(peer_bda.address, ((tBTA_AV*)p_data)->rc_open.peer_addr);
+
+    if (idle_rc_event != 0)
+    {
+        BTIF_TRACE_DEBUG("Processing another RC Event ");
+        return;
+    }
+    idle_rc_event = BTA_AV_RC_OPEN_EVT;
+    memcpy(&idle_rc_data, ((tBTA_AV*)p_data), sizeof(tBTA_AV));
+    if (((tBTA_AV*)p_data)->rc_open.status == BTA_AV_SUCCESS)
+    {
+        BTIF_TRACE_DEBUG("RC conn is success ");
+        if (bt_av_src_callbacks != NULL)
+        {
+            BTIF_TRACE_DEBUG(" Check Device priority");
+            HAL_CBACK(bt_av_src_callbacks, connection_priority_cb,
+                    &peer_bda);
+        }
+    }
+    else
+    {
+        idle_rc_event = 0;
+        memset(&idle_rc_data, 0, sizeof(tBTA_AV));
+    }
+    return;
+}
+
+
 static void bte_av_callback(tBTA_AV_EVT event, tBTA_AV *p_data)
 {
     btif_transfer_context(btif_av_handle_event, event,
                           (char*)p_data, sizeof(tBTA_AV), btif_av_event_deep_copy);
 }
 
+/*Called only in case of A2dp SInk, which runs on index 0*/
 static void bte_av_media_callback(tBTA_AV_EVT event, tBTA_AV_MEDIA *p_data)
 {
     btif_sm_state_t state;
@@ -1232,10 +2080,11 @@ static void bte_av_media_callback(tBTA_AV_EVT event, tBTA_AV_MEDIA *p_data)
     tA2D_STATUS a2d_status;
     tA2D_SBC_CIE sbc_cie;
     btif_av_sink_config_req_t config_req;
+    int index =0;
 
     if (event == BTA_AV_MEDIA_DATA_EVT)/* Switch to BTIF_MEDIA context */
     {
-        state= btif_sm_get_state(btif_av_cb.sm_handle);
+        state= btif_sm_get_state(btif_av_cb[index].sm_handle);
         if ( (state == BTIF_AV_STATE_STARTED) || /* send SBC packets only in Started State */
              (state == BTIF_AV_STATE_OPENED) )
         {
@@ -1275,18 +2124,27 @@ static void bte_av_media_callback(tBTA_AV_EVT event, tBTA_AV_MEDIA *p_data)
 
 bt_status_t btif_av_init(int service_id)
 {
-    if (btif_av_cb.sm_handle == NULL)
+    int i;
+    if (btif_av_cb[0].sm_handle == NULL)
     {
         alarm_free(av_open_on_rc_timer);
         av_open_on_rc_timer = alarm_new("btif_av.av_open_on_rc_timer");
-        if (!btif_a2dp_start_media_task())
+        BTIF_TRACE_DEBUG("%s", __FUNCTION__);
+        if(!btif_a2dp_is_media_task_stopped())
             return BT_STATUS_FAIL;
+        btif_av_cb[0].service = service_id;
 
         /* Also initialize the AV state machine */
-        btif_av_cb.sm_handle = btif_sm_init((const btif_sm_handler_t*)btif_av_state_handlers,
-                                                    BTIF_AV_STATE_IDLE);
+        for (i = 0; i < btif_max_av_clients; i++)
+        {
+            btif_av_cb[i].sm_handle = btif_sm_init((const btif_sm_handler_t*)btif_av_state_handlers,
+                                                    BTIF_AV_STATE_IDLE, i);
+        }
+
+        btif_transfer_context(btif_av_handle_event, BTIF_AV_INIT_REQ_EVT,
+                (char*)&service_id, sizeof(int), NULL);
+
         btif_enable_service(service_id);
-        btif_a2dp_on_init();
     }
 
     return BT_STATUS_SUCCESS;
@@ -1302,13 +2160,30 @@ bt_status_t btif_av_init(int service_id)
 **
 *******************************************************************************/
 
-static bt_status_t init_src(btav_callbacks_t* callbacks)
+static bt_status_t init_src(btav_callbacks_t* callbacks, int max_a2dp_connections,
+                            int a2dp_multicast_state)
 {
-    BTIF_TRACE_EVENT("%s()", __func__);
+    bt_status_t status;
+
+    BTIF_TRACE_EVENT("%s with max conn = %d", __FUNCTION__, max_a2dp_connections);
+
+    if (bt_av_sink_callbacks != NULL) {
+        // already did btif_av_init()
+        status = BT_STATUS_SUCCESS;
+    }
+    else
+    {
+        if (a2dp_multicast_state)
+        {
+            is_multicast_supported = TRUE;
+        }
+        btif_max_av_clients = max_a2dp_connections;
+        status = btif_av_init(BTA_A2DP_SOURCE_SERVICE_ID);
+    }
 
-    bt_status_t status = btif_av_init(BTA_A2DP_SOURCE_SERVICE_ID);
-    if (status == BT_STATUS_SUCCESS)
+    if (status == BT_STATUS_SUCCESS) {
         bt_av_src_callbacks = callbacks;
+    }
 
     return status;
 }
@@ -1323,13 +2198,33 @@ static bt_status_t init_src(btav_callbacks_t* callbacks)
 **
 *******************************************************************************/
 
-static bt_status_t init_sink(btav_callbacks_t* callbacks)
+static bt_status_t init_sink(btav_callbacks_t* callbacks, int max,
+                             int a2dp_multicast_state)
 {
-    BTIF_TRACE_EVENT("%s()", __func__);
+    bt_status_t status;
+
+    BTIF_TRACE_EVENT("%s", __FUNCTION__);
+
+    if (bt_av_src_callbacks != NULL) {
+        // already did btif_av_init()
+        status = BT_STATUS_SUCCESS;
+    }
+    else
+    {
+        enable_multicast = FALSE; // Clear multicast flag for sink
+        if (max > 1)
+        {
+            BTIF_TRACE_ERROR("Only one Sink can be initialized");
+            max = 1;
+        }
+        btif_max_av_clients = max; //Should be 1
+        status = btif_av_init(BTA_A2DP_SINK_SERVICE_ID);
+    }
 
-    bt_status_t status = btif_av_init(BTA_A2DP_SINK_SERVICE_ID);
-    if (status == BT_STATUS_SUCCESS)
+    if (status == BT_STATUS_SUCCESS) {
         bt_av_sink_callbacks = callbacks;
+        //BTA_AvEnable_Sink(TRUE);
+    }
 
     return status;
 }
@@ -1367,6 +2262,95 @@ void update_audio_track_gain(float gain)
 }
 #endif
 
+
+void btif_get_latest_playing_device(BD_ADDR address)
+{
+    int index;
+    index = btif_get_latest_playing_device_idx();
+    if (index < btif_max_av_clients)
+    {
+        //copy bdaddrsss
+        bdcpy(address, btif_av_cb[index].peer_bda.address);
+    }
+    else
+    {
+        bdcpy(address, bd_null);
+    }
+}
+
+BOOLEAN btif_av_is_device_connected(BD_ADDR address)
+{
+    btif_sm_state_t state = btif_get_conn_state_of_device(address);
+
+    if ((state == BTIF_AV_STATE_OPENED) ||
+        (state == BTIF_AV_STATE_STARTED))
+        return TRUE;
+    else
+        return FALSE;
+}
+
+/*This function will trigger remote suspend for currently
+* playing device and then initiate START on Handoff device
+* whose address is passed as an argument. */
+/*******************************************************************************
+**
+** Function         btif_av_trigger_dual_handoff
+**
+** Description      Trigger the DUAL HANDOFF
+**
+** Returns          void
+**
+*******************************************************************************/
+
+void btif_av_trigger_dual_handoff(BOOLEAN handoff, BD_ADDR address)
+{
+    int index;
+    /*Get the current playing device*/
+    BTIF_TRACE_DEBUG("%s", __FUNCTION__);
+    index = btif_get_latest_playing_device_idx();
+    if (index != btif_max_av_clients)
+    {
+        btif_av_cb[index].dual_handoff = handoff; /*Initiate Handoff*/
+        /*Initiate SUSPEND for this device*/
+        BTIF_TRACE_DEBUG("Initiate SUSPEND for this device on index = %d", index);
+        btif_sm_dispatch(btif_av_cb[index].sm_handle, BTIF_AV_SUSPEND_STREAM_REQ_EVT, NULL);
+        //btif_dispatch_sm_event(BTIF_AV_SUSPEND_STREAM_REQ_EVT, NULL, 0);
+    }
+    else
+    {
+        BTIF_TRACE_ERROR("Handoff on invalid index");
+    }
+}
+
+/*******************************************************************************
+**
+** Function         btif_av_trigger_suspend
+**
+** Description      Trigger suspend when multicast is ongoing for tuch tones
+**                  and new ACL is created.
+**
+** Returns          void
+**
+*******************************************************************************/
+
+void btif_av_trigger_suspend()
+{
+    int index;
+    /*Get the current playing device*/
+    BTIF_TRACE_DEBUG("%s", __FUNCTION__);
+    index = btif_get_latest_playing_device_idx();
+    if (index <= btif_max_av_clients)
+    {
+        /*Initiate SUSPEND for this device*/
+        BTIF_TRACE_DEBUG("Initiate SUSPEND for this device on index = %d", index);
+        btif_sm_dispatch(btif_av_cb[index].sm_handle, BTIF_AV_SUSPEND_STREAM_REQ_EVT, NULL);
+    }
+    else
+    {
+        BTIF_TRACE_ERROR("suspend on invalid index");
+    }
+}
+
 /*******************************************************************************
 **
 ** Function         connect
@@ -1380,11 +2364,47 @@ void update_audio_track_gain(float gain)
 static bt_status_t connect_int(bt_bdaddr_t *bd_addr, uint16_t uuid)
 {
     btif_av_connect_req_t connect_req;
+    int i;
     connect_req.target_bda = bd_addr;
     connect_req.uuid = uuid;
     BTIF_TRACE_EVENT("%s", __FUNCTION__);
 
-    btif_sm_dispatch(btif_av_cb.sm_handle, BTIF_AV_CONNECT_REQ_EVT, (char*)&connect_req);
+    for (i = 0; i < btif_max_av_clients;)
+    {
+        if(btif_av_get_valid_idx(i))
+        {
+            if (bdcmp(bd_addr->address, btif_av_cb[i].peer_bda.address) == 0)
+            {
+                BTIF_TRACE_ERROR("Attempting connection for non idle device.. back off ");
+                btif_queue_advance();
+                return BT_STATUS_SUCCESS;
+            }
+            i++;
+        }
+        else
+            break;
+    }
+    if (i == btif_max_av_clients)
+    {
+        UINT8 rc_handle;
+
+        BTIF_TRACE_ERROR("%s: All indexes are full", __FUNCTION__);
+
+        /* Multicast: Check if AV slot is available for connection
+         * If not available, AV got connected to different devices.
+         * Disconnect this RC connection without AV connection.
+         */
+        rc_handle = btif_rc_get_connected_peer_handle(bd_addr->address);
+        if (rc_handle != BTIF_RC_HANDLE_NONE)
+        {
+            BTA_AvCloseRc(rc_handle);
+        }
+        btif_queue_advance();
+        return BT_STATUS_FAIL;
+    }
+
+    btif_sm_dispatch(btif_av_cb[i].sm_handle, BTIF_AV_CONNECT_REQ_EVT, (char*)&connect_req);
+
 
     return BT_STATUS_SUCCESS;
 }
@@ -1436,37 +2456,80 @@ static bt_status_t disconnect(bt_bdaddr_t *bd_addr)
 *******************************************************************************/
 static void cleanup(int service_uuid)
 {
+    int i;
     BTIF_TRACE_EVENT("%s", __FUNCTION__);
 
-    btif_transfer_context(btif_av_handle_event, BTIF_AV_CLEANUP_REQ_EVT, NULL, 0, NULL);
+    btif_transfer_context(btif_av_handle_event, BTIF_AV_CLEANUP_REQ_EVT,
+            (char*)&service_uuid, sizeof(int), NULL);
 
     btif_disable_service(service_uuid);
 
     /* Also shut down the AV state machine */
-    btif_sm_shutdown(btif_av_cb.sm_handle);
-    btif_av_cb.sm_handle = NULL;
+    for (i = 0; i < btif_max_av_clients; i++ )
+    {
+        btif_sm_shutdown(btif_av_cb[i].sm_handle);
+        btif_av_cb[i].sm_handle = NULL;
+    }
 }
 
 static void cleanup_src(void) {
     BTIF_TRACE_EVENT("%s", __FUNCTION__);
+    cleanup(BTA_A2DP_SOURCE_SERVICE_ID);
+}
 
-    if (bt_av_src_callbacks)
-    {
-        bt_av_src_callbacks = NULL;
-        if (bt_av_sink_callbacks == NULL)
-            cleanup(BTA_A2DP_SOURCE_SERVICE_ID);
-    }
+static void cleanup_sink(void) {
+    BTIF_TRACE_EVENT("%s", __FUNCTION__);
+    cleanup(BTA_A2DP_SINK_SERVICE_ID);
 }
 
-static void cleanup_sink(void) {
-    BTIF_TRACE_EVENT("%s", __FUNCTION__);
+static void allow_connection(int is_valid, bt_bdaddr_t *bd_addr)
+{
+    int index = 0;
+    BTIF_TRACE_DEBUG(" %s isValid is %d event %d", __FUNCTION__,is_valid,idle_rc_event);
+    switch (idle_rc_event)
+    {
+        case BTA_AV_RC_OPEN_EVT:
+            if (is_valid)
+            {
+                BTIF_TRACE_DEBUG("allowconn for RC connection");
+                               alarm_set_on_queue(av_open_on_rc_timer,
+                                                 BTIF_TIMEOUT_AV_OPEN_ON_RC_MS,
+                                                 btif_initiate_av_open_timer_timeout, NULL,
+                                                 btu_general_alarm_queue);
+                btif_rc_handler(idle_rc_event, &idle_rc_data);
+            }
+            else
+            {
+                UINT8 rc_handle =  idle_rc_data.rc_open.rc_handle;
+                BTA_AvCloseRc(rc_handle);
+            }
+            break;
+
+        case BTA_AV_PENDING_EVT:
+            if (is_valid)
+            {
+                index = btif_av_idx_by_bdaddr(bd_addr->address);
+                if (index >= btif_max_av_clients)
+                {
+                    BTIF_TRACE_DEBUG("Invalid index for device");
+                    break;
+                }
+                BTIF_TRACE_DEBUG("The connection is allowed for the device at index = %d", index);
+                BTA_AvOpen(btif_av_cb[index].peer_bda.address, btif_av_cb[index].bta_handle,
+                       TRUE, BTA_SEC_NONE, UUID_SERVCLASS_AUDIO_SOURCE);
+            }
+            else
+            {
+                BTA_AvDisconnect(idle_rc_data.pend.bd_addr);
+            }
+            break;
 
-    if (bt_av_sink_callbacks)
-    {
-        bt_av_sink_callbacks = NULL;
-        if (bt_av_src_callbacks == NULL)
-            cleanup(BTA_A2DP_SINK_SERVICE_ID);
+        default:
+            BTIF_TRACE_DEBUG("%s : unhandled event:%s", __FUNCTION__,
+                                dump_av_sm_event_name(idle_rc_event));
     }
+    idle_rc_event = 0;
+    memset(&idle_rc_data, 0, sizeof(tBTA_AV));
 }
 
 static const btav_interface_t bt_av_src_interface = {
@@ -1477,6 +2540,7 @@ static const btav_interface_t bt_av_src_interface = {
     cleanup_src,
     NULL,
     NULL,
+    allow_connection,
 };
 
 static const btav_interface_t bt_av_sink_interface = {
@@ -1492,6 +2556,7 @@ static const btav_interface_t bt_av_sink_interface = {
     NULL,
     NULL,
 #endif
+       NULL,
 };
 
 /*******************************************************************************
@@ -1503,10 +2568,11 @@ static const btav_interface_t bt_av_sink_interface = {
 ** Returns          None
 **
 *******************************************************************************/
-
+/* Media task uses this info
+* But dont use it. */
 btif_sm_handle_t btif_av_get_sm_handle(void)
 {
-    return btif_av_cb.sm_handle;
+    return btif_av_cb[0].sm_handle;
 }
 
 /*******************************************************************************
@@ -1519,9 +2585,17 @@ btif_sm_handle_t btif_av_get_sm_handle(void)
 **
 *******************************************************************************/
 
-bt_bdaddr_t btif_av_get_addr(void)
+bt_bdaddr_t btif_av_get_addr(BD_ADDR address)
 {
-    return btif_av_cb.peer_bda;
+    int i;
+    bt_bdaddr_t not_found ;
+    memset (&not_found, 0, sizeof(bt_bdaddr_t));
+    for (i = 0; i < btif_max_av_clients; i++)
+    {
+        if (bdcmp(btif_av_cb[i].peer_bda.address, address) == 0)
+            return btif_av_cb[i].peer_bda;
+    }
+    return not_found;
 }
 
 /*******************************************************************************
@@ -1550,11 +2624,8 @@ BOOLEAN btif_av_is_sink_enabled(void)
 
 BOOLEAN btif_av_stream_ready(void)
 {
-    btif_sm_state_t state = btif_sm_get_state(btif_av_cb.sm_handle);
-
-    BTIF_TRACE_DEBUG("btif_av_stream_ready : sm hdl %d, state %d, flags %x",
-                btif_av_cb.sm_handle, state, btif_av_cb.flags);
-
+    int i;
+    BOOLEAN status = FALSE;
     /* also make sure main adapter is enabled */
     if (btif_is_enabled() == 0)
     {
@@ -1562,11 +2633,34 @@ BOOLEAN btif_av_stream_ready(void)
         return FALSE;
     }
 
-    /* check if we are remotely suspended or stop is pending */
-    if (btif_av_cb.flags & (BTIF_AV_FLAG_REMOTE_SUSPEND|BTIF_AV_FLAG_PENDING_STOP))
-        return FALSE;
-
-    return (state == BTIF_AV_STATE_OPENED);
+    for (i = 0; i < btif_max_av_clients; i++)
+    {
+        btif_av_cb[i].state = btif_sm_get_state(btif_av_cb[i].sm_handle);
+        /* Multicast:
+         * If any of the stream is in pending suspend state when
+         * we initiate start, it will result in inconsistent behavior
+         * Check the pending SUSPEND flag and return failure
+         * if suspend is in progress.
+         */
+        if (btif_av_cb[i].dual_handoff ||
+            (btif_av_cb[i].flags & BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING))
+        {
+            status = FALSE;
+            break;
+        }
+        else if (btif_av_cb[i].flags &
+            (BTIF_AV_FLAG_REMOTE_SUSPEND|BTIF_AV_FLAG_PENDING_STOP))
+        {
+            status = FALSE;
+            break;
+        }
+        else if (btif_av_cb[i].state == BTIF_AV_STATE_OPENED)
+        {
+            status = TRUE;
+        }
+    }
+    BTIF_TRACE_DEBUG("btif_av_stream_ready: %d", status);
+    return status;
 }
 
 /*******************************************************************************
@@ -1581,17 +2675,31 @@ BOOLEAN btif_av_stream_ready(void)
 
 BOOLEAN btif_av_stream_started_ready(void)
 {
-    btif_sm_state_t state = btif_sm_get_state(btif_av_cb.sm_handle);
+    int i;
+    BOOLEAN status = FALSE;
 
-    BTIF_TRACE_DEBUG("btif_av_stream_started : sm hdl %d, state %d, flags %x",
-                btif_av_cb.sm_handle, state, btif_av_cb.flags);
-
-    /* disallow media task to start if we have pending actions */
-    if (btif_av_cb.flags & (BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING | BTIF_AV_FLAG_REMOTE_SUSPEND
-        | BTIF_AV_FLAG_PENDING_STOP))
-        return FALSE;
-
-    return (state == BTIF_AV_STATE_STARTED);
+    for (i = 0; i < btif_max_av_clients; i++)
+    {
+        btif_av_cb[i].state = btif_sm_get_state(btif_av_cb[i].sm_handle);
+        if (btif_av_cb[i].dual_handoff)
+        {
+            BTIF_TRACE_ERROR("%s: Under Dual handoff ",__FUNCTION__ );
+            status = FALSE;
+            break;
+        } else if (btif_av_cb[i].flags &
+            (BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING |
+            BTIF_AV_FLAG_REMOTE_SUSPEND |
+            BTIF_AV_FLAG_PENDING_STOP))
+        {
+            status = FALSE;
+            break;
+        } else if (btif_av_cb[i].state == BTIF_AV_STATE_STARTED)
+        {
+            status = TRUE;
+        }
+    }
+    BTIF_TRACE_DEBUG("btif_av_stream_started_ready: %d", status);
+    return status;
 }
 
 /*******************************************************************************
@@ -1625,37 +2733,46 @@ void btif_dispatch_sm_event(btif_av_sm_event_t event, void *p_data, int len)
 *******************************************************************************/
 bt_status_t btif_av_execute_service(BOOLEAN b_enable)
 {
-     if (b_enable)
-     {
-         /* TODO: Removed BTA_SEC_AUTHORIZE since the Java/App does not
-          * handle this request in order to allow incoming connections to succeed.
-          * We need to put this back once support for this is added */
+    int i;
+    if (b_enable)
+    {
+        /* TODO: Removed BTA_SEC_AUTHORIZE since the Java/App does not
+        * handle this request in order to allow incoming connections to succeed.
+        * We need to put this back once support for this is added */
 
-         /* Added BTA_AV_FEAT_NO_SCO_SSPD - this ensures that the BTA does not
-          * auto-suspend av streaming on AG events(SCO or Call). The suspend shall
-          * be initiated by the app/audioflinger layers */
-         /* Support for browsing for SDP record should work only if we enable BROWSE
-          * while registering. */
+        /* Added BTA_AV_FEAT_NO_SCO_SSPD - this ensures that the BTA does not
+        * auto-suspend av streaming on AG events(SCO or Call). The suspend shall
+        * be initiated by the app/audioflinger layers */
 #if (AVRC_METADATA_INCLUDED == TRUE)
-         BTA_AvEnable(BTA_SEC_AUTHENTICATE,
-             BTA_AV_FEAT_RCTG|BTA_AV_FEAT_METADATA|BTA_AV_FEAT_VENDOR|BTA_AV_FEAT_NO_SCO_SSPD
+        BTA_AvEnable(BTA_SEC_AUTHENTICATE,
+            BTA_AV_FEAT_RCTG|BTA_AV_FEAT_METADATA|BTA_AV_FEAT_VENDOR|BTA_AV_FEAT_NO_SCO_SSPD
+            |BTA_AV_FEAT_ACP_START
 #if (AVRC_ADV_CTRL_INCLUDED == TRUE)
-             |BTA_AV_FEAT_RCCT
-             |BTA_AV_FEAT_ADV_CTRL
+            |BTA_AV_FEAT_RCCT
+            |BTA_AV_FEAT_ADV_CTRL
+                       |BTA_AV_FEAT_BROWSE
 #endif
-             ,bte_av_callback);
+            ,bte_av_callback);
 #else
-         BTA_AvEnable(BTA_SEC_AUTHENTICATE, (BTA_AV_FEAT_RCTG | BTA_AV_FEAT_NO_SCO_SSPD),
-                      bte_av_callback);
+        BTA_AvEnable(BTA_SEC_AUTHENTICATE, (BTA_AV_FEAT_RCTG | BTA_AV_FEAT_NO_SCO_SSPD
+            |BTA_AV_FEAT_ACP_START), bte_av_callback);
 #endif
-         BTA_AvRegister(BTA_AV_CHNL_AUDIO, BTIF_AV_SERVICE_NAME, 0, bte_av_media_callback,
-                                                             UUID_SERVCLASS_AUDIO_SOURCE);
-     }
-     else {
-         BTA_AvDeregister(btif_av_cb.bta_handle);
-         BTA_AvDisable();
-     }
-     return BT_STATUS_SUCCESS;
+        for (i = 0; i < btif_max_av_clients; i++)
+        {
+            BTIF_TRACE_DEBUG("%s: BTA_AvRegister : %d", __FUNCTION__, i);
+            BTA_AvRegister(BTA_AV_CHNL_AUDIO, BTIF_AV_SERVICE_NAME, 0, bte_av_media_callback,
+            UUID_SERVCLASS_AUDIO_SOURCE);
+        }
+    }
+    else
+    {
+        for (i = 0; i < btif_max_av_clients; i++)
+        {
+            BTA_AvDeregister(btif_av_cb[i].bta_handle);
+        }
+        BTA_AvDisable();
+    }
+    return BT_STATUS_SUCCESS;
 }
 
 /*******************************************************************************
@@ -1682,7 +2799,7 @@ bt_status_t btif_av_sink_execute_service(BOOLEAN b_enable)
                                                                 UUID_SERVCLASS_AUDIO_SINK);
      }
      else {
-         BTA_AvDeregister(btif_av_cb.bta_handle);
+         BTA_AvDeregister(btif_av_cb[0].bta_handle);
          BTA_AvDisable();
      }
      return BT_STATUS_SUCCESS;
@@ -1729,8 +2846,91 @@ const btav_interface_t *btif_av_get_sink_interface(void)
 *******************************************************************************/
 BOOLEAN btif_av_is_connected(void)
 {
-    btif_sm_state_t state = btif_sm_get_state(btif_av_cb.sm_handle);
-    return ((state == BTIF_AV_STATE_OPENED) || (state ==  BTIF_AV_STATE_STARTED));
+    int i;
+    BOOLEAN status = FALSE;
+    for (i = 0; i < btif_max_av_clients; i++)
+    {
+        btif_av_cb[i].state = btif_sm_get_state(btif_av_cb[i].sm_handle);
+        if ((btif_av_cb[i].state == BTIF_AV_STATE_OPENED) ||
+            (btif_av_cb[i].state ==  BTIF_AV_STATE_STARTED))
+            status = TRUE;
+    }
+    return status;
+}
+
+/*******************************************************************************
+**
+** Function         btif_av_is_connected_on_other_idx
+**
+** Description      Checks if any other AV SCB is connected
+**
+** Returns          BOOLEAN
+**
+*******************************************************************************/
+
+BOOLEAN btif_av_is_connected_on_other_idx(int current_index)
+{
+    //return true if other IDx is connected
+    btif_sm_state_t state = BTIF_AV_STATE_IDLE;
+    int i;
+    for (i = 0; i < btif_max_av_clients; i++)
+    {
+        if (i != current_index)
+        {
+            state = btif_sm_get_state(btif_av_cb[i].sm_handle);
+            if ((state == BTIF_AV_STATE_OPENED) ||
+                (state == BTIF_AV_STATE_STARTED))
+                return TRUE;
+        }
+    }
+    return FALSE;
+}
+
+/*******************************************************************************
+**
+** Function         btif_av_is_playing_on_other_idx
+**
+** Description      Checks if any other AV SCB is connected
+**
+** Returns          BOOLEAN
+**
+*******************************************************************************/
+
+BOOLEAN btif_av_is_playing_on_other_idx(int current_index)
+{
+    //return true if other IDx is playing
+    btif_sm_state_t state = BTIF_AV_STATE_IDLE;
+    int i;
+    for (i = 0; i < btif_max_av_clients; i++)
+    {
+        if (i != current_index)
+        {
+            state = btif_sm_get_state(btif_av_cb[i].sm_handle);
+            if (state == BTIF_AV_STATE_STARTED)
+                return TRUE;
+        }
+    }
+    return FALSE;
+}
+
+/*******************************************************************************
+**
+** Function         btif_av_update_current_playing_device
+**
+** Description      Update the next connected device as playing
+**
+** Returns          void
+**
+*******************************************************************************/
+
+static void btif_av_update_current_playing_device(int index)
+{
+    int i;
+    for (i = 0; i < btif_max_av_clients; i++)
+    {
+        if (i != index)
+            btif_av_cb[i].current_playing = TRUE;
+    }
 }
 
 /*******************************************************************************
@@ -1747,47 +2947,110 @@ BOOLEAN btif_av_is_connected(void)
 *******************************************************************************/
 BOOLEAN btif_av_is_peer_edr(void)
 {
+    btif_sm_state_t state;
+    BOOLEAN peer_edr = FALSE;
+
     ASSERTC(btif_av_is_connected(), "No active a2dp connection", 0);
 
-    if (btif_av_cb.edr)
-        return TRUE;
-    else
-        return FALSE;
+    /* If any of the remote in streaming state is BR
+     * return FALSE to ensure proper configuration
+     * is used. Ideally, since multicast is not supported
+     * if any of the connected device is BR device,
+     * we should not see both devices in START state.
+     */
+    for (int index = 0; index < btif_max_av_clients; index ++)
+    {
+        state = btif_sm_get_state(btif_av_cb[index].sm_handle);
+        if ((btif_av_cb[index].flags & BTIF_AV_FLAG_PENDING_START)
+            || (state == BTIF_AV_STATE_STARTED))
+        {
+            if (btif_av_cb[index].edr)
+            {
+                peer_edr = TRUE;
+            }
+            else
+            {
+                return FALSE;
+            }
+        }
+    }
+    return peer_edr;
 }
 
-/******************************************************************************
+/*******************************************************************************
 **
-** Function        btif_av_clear_remote_suspend_flag
+** Function         btif_av_any_br_peer
 **
-** Description     Clears btif_av_cd.flags if BTIF_AV_FLAG_REMOTE_SUSPEND is set
+** Description      Check if the any of connected devices is BR device.
 **
-** Returns          void
-******************************************************************************/
-void btif_av_clear_remote_suspend_flag(void)
+** Returns          TRUE if connected to any BR device, FALSE otherwise.
+**
+*******************************************************************************/
+BOOLEAN btif_av_any_br_peer(void)
 {
-    BTIF_TRACE_DEBUG("%s: flag :%x",__func__, btif_av_cb.flags);
-    btif_av_cb.flags &= ~BTIF_AV_FLAG_REMOTE_SUSPEND;
+    btif_sm_state_t state;
+    for (int index = 0; index < btif_max_av_clients; index ++)
+    {
+        state = btif_sm_get_state(btif_av_cb[index].sm_handle);
+        if (state >= BTIF_AV_STATE_OPENED)
+        {
+            if (!btif_av_cb[index].edr)
+            {
+                BTIF_TRACE_WARNING("%s : Connected to BR device :", __FUNCTION__);
+                return TRUE;
+            }
+        }
+    }
+    return FALSE;
 }
 
 /*******************************************************************************
 **
 ** Function         btif_av_peer_supports_3mbps
 **
-** Description      Check if the connected A2DP device supports
-**                  3 Mbps EDR. This function only works if connected.
-**                  If not connected it will always be false.
+** Description      check if the connected a2dp device supports
+**                  3mbps edr. Only when connected this function
+**                  will accurately provide a true capability of
+**                  remote peer. If not connected it will always be false.
 **
-** Returns          TRUE if remote device is EDR and supports 3 Mbps
+** Returns          TRUE if remote device is EDR and supports 3mbps
 **
 *******************************************************************************/
 BOOLEAN btif_av_peer_supports_3mbps(void)
 {
-    BOOLEAN is3mbps = ((btif_av_cb.edr & BTA_AV_EDR_3MBPS) != 0);
-    BTIF_TRACE_DEBUG("%s: connected %d, edr_3mbps %d", __func__,
-            btif_av_is_connected(), is3mbps);
-    return (btif_av_is_connected() && is3mbps);
+    btif_sm_state_t state;
+    ASSERTC(btif_av_is_connected(), "No active a2dp connection", 0);
+
+    for (int index = 0; index < btif_max_av_clients; index ++)
+    {
+        state = btif_sm_get_state(btif_av_cb[index].sm_handle);
+        if ((btif_av_cb[index].flags & BTIF_AV_FLAG_PENDING_START)
+            || (state == BTIF_AV_STATE_STARTED))
+        {
+            if(btif_av_cb[index].edr_3mbps)
+                return TRUE;
+        }
+    }
+    return FALSE;
 }
 
+/******************************************************************************
+**
+** Function        btif_av_clear_remote_suspend_flag
+**
+** Description     Clears btif_av_cd.flags if BTIF_AV_FLAG_REMOTE_SUSPEND is set
+**
+** Returns         void
+******************************************************************************/
+void btif_av_clear_remote_suspend_flag(void)
+{
+    int i;
+    for (i = 0; i < btif_max_av_clients; i++)
+    {
+        BTIF_TRACE_DEBUG(" flag :%x",btif_av_cb[i].flags);
+        btif_av_cb[i].flags  &= ~BTIF_AV_FLAG_REMOTE_SUSPEND;
+    }
+}
 
 /*******************************************************************************
 **
@@ -1803,16 +3066,198 @@ BOOLEAN btif_av_peer_supports_3mbps(void)
 *******************************************************************************/
 void btif_av_move_idle(bt_bdaddr_t bd_addr)
 {
+    int index =0;
     /* inform the application that ACL is disconnected and move to idle state */
-    btif_sm_state_t state = btif_sm_get_state(btif_av_cb.sm_handle);
-    BTIF_TRACE_DEBUG("%s: ACL Disconnected state %d  is same device %d", __func__,
-            state, memcmp (&bd_addr, &(btif_av_cb.peer_bda), sizeof(bd_addr)));
+    index = btif_av_idx_by_bdaddr(bd_addr.address);
+    if (index == btif_max_av_clients)
+    {
+        BTIF_TRACE_DEBUG("btif_av_move_idle: Already in IDLE");
+        return;
+    }
+    btif_sm_state_t state = btif_sm_get_state(btif_av_cb[index].sm_handle);
+    BTIF_TRACE_DEBUG("ACL Disconnected state %d  is same device %d",state,
+            memcmp (&bd_addr, &(btif_av_cb[index].peer_bda), sizeof(bd_addr)));
     if (state == BTIF_AV_STATE_OPENING &&
-            (memcmp (&bd_addr, &(btif_av_cb.peer_bda), sizeof(bd_addr)) == 0))
+            (memcmp (&bd_addr, &(btif_av_cb[index].peer_bda), sizeof(bd_addr)) == 0))
+    {
+        BTIF_TRACE_DEBUG("Moving State from Opening to Idle due to ACL disconnect");
+        btif_report_connection_state(BTAV_CONNECTION_STATE_DISCONNECTED, &(btif_av_cb[index].peer_bda));
+
+        btif_sm_change_state(btif_av_cb[index].sm_handle, BTIF_AV_STATE_IDLE);
+        btif_queue_advance();
+    }
+}
+/******************************************************************************
+**
+** Function        btif_av_get_num_playing_devices
+**
+** Description     Return number of A2dp playing devices
+**
+** Returns         int
+******************************************************************************/
+UINT16 btif_av_get_num_playing_devices(void)
+{
+    UINT16 i;
+    UINT16 playing_devices = 0;
+    for (i = 0; i < btif_max_av_clients; i++)
+    {
+        btif_av_cb[i].state = btif_sm_get_state(btif_av_cb[i].sm_handle);
+        if (btif_av_cb[i].state ==  BTIF_AV_STATE_STARTED)
+        {
+            playing_devices++;
+        }
+    }
+    BTIF_TRACE_DEBUG("AV devices playing: %d", playing_devices);
+
+    return playing_devices;
+}
+/*******************************************************************************
+**
+** Function        btif_av_get_num_connected_devices
+**
+** Description     Return number of A2dp connected devices
+**
+** Returns         int
+******************************************************************************/
+UINT16 btif_av_get_num_connected_devices(void)
+{
+    UINT16 i;
+    UINT16 connected_devies = 0;
+    for (i = 0; i < btif_max_av_clients; i++)
+    {
+        btif_av_cb[i].state = btif_sm_get_state(btif_av_cb[i].sm_handle);
+        if ((btif_av_cb[i].state == BTIF_AV_STATE_OPENED) ||
+            (btif_av_cb[i].state ==  BTIF_AV_STATE_STARTED))
+        {
+            connected_devies++;
+        }
+    }
+    BTIF_TRACE_DEBUG("AV Connection count: %d", connected_devies);
+
+    return connected_devies;
+}
+
+/******************************************************************************
+**
+** Function        btif_av_update_multicast_state
+**
+** Description     Enable Multicast only if below conditions are satisfied
+**                 1. Connected to only 2 EDR HS.
+**                 2. Connected to both HS as master.
+**                 3. Connected to 2 EDR HS and one BLE device
+**                 Multicast will fall back to soft handsoff in below conditions
+**                 1. Number of ACL links is more than 2,like connected to HID
+**                    initiating connection for HS1 and HS2.
+**                 2. Connected to BR and EDR HS.
+**                 3. Connected to more then 1 BLE device
+**
+** Returns         void
+******************************************************************************/
+void btif_av_update_multicast_state(int index)
+{
+    UINT16 num_connected_br_edr_devices = 0;
+    UINT16 num_connected_le_devices = 0;
+    UINT16 num_av_connected = 0;
+    UINT16 i = 0;
+    BOOLEAN is_slave = FALSE;
+    BOOLEAN is_br_hs_connected = FALSE;
+    BOOLEAN prev_multicast_state = enable_multicast;
+
+    if (!is_multicast_supported)
+    {
+        BTIF_TRACE_DEBUG("%s Multicast is Disabled", __FUNCTION__);
+        return;
+    }
+
+    if (multicast_disabled == TRUE)
+    {
+        multicast_disabled = FALSE;
+        enable_multicast = FALSE;
+        BTA_AvEnableMultiCast(FALSE, btif_av_cb[index].bta_handle);
+        return;
+    }
+
+    BTIF_TRACE_DEBUG("%s Multicast previous state : %s", __FUNCTION__,
+        enable_multicast ? "Enabled" : "Disabled" );
+
+    num_connected_br_edr_devices = btif_dm_get_br_edr_links();
+    num_connected_le_devices = btif_dm_get_le_links();
+    num_av_connected = btif_av_get_num_connected_devices();
+    is_br_hs_connected = btif_av_any_br_peer();
+
+    for (i = 0; i < btif_max_av_clients; i++)
+    {
+        if (btif_av_cb[i].is_slave == TRUE)
+        {
+            BTIF_TRACE_WARNING("Conected as slave");
+            is_slave = TRUE;
+            break;
+        }
+    }
+
+    if ((num_av_connected <= 2) && (is_br_hs_connected != TRUE) &&
+        (is_slave == FALSE) && ((num_connected_br_edr_devices <= 2) &&
+        (num_connected_le_devices <= 1)))
+    {
+        enable_multicast = TRUE;
+    }
+    else
     {
-        BTIF_TRACE_DEBUG("%s: Moving State from Opening to Idle due to ACL disconnect", __func__);
-        btif_report_connection_state(BTAV_CONNECTION_STATE_DISCONNECTED,
-                &(btif_av_cb.peer_bda));
-        btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_IDLE);
+        enable_multicast = FALSE;
+    }
+
+    BTIF_TRACE_DEBUG("%s Multicast current state : %s", __FUNCTION__,
+        enable_multicast ? "Enabled" : "Disabled" );
+
+    if (prev_multicast_state != enable_multicast)
+    {
+        BTA_AvEnableMultiCast(enable_multicast,
+                btif_av_cb[index].bta_handle);
+        HAL_CBACK(bt_av_src_callbacks, multicast_state_cb,
+              enable_multicast);
+    }
+}
+/******************************************************************************
+**
+** Function        btif_av_get_multicast_state
+**
+** Description     Returns TRUE if multicast is enabled else false
+**
+** Returns         BOOLEAN
+******************************************************************************/
+BOOLEAN btif_av_get_multicast_state()
+{
+    return enable_multicast;
+}
+/******************************************************************************
+**
+** Function        btif_av_get_ongoing_multicast
+**
+** Description     Returns TRUE if multicast is ongoing
+**
+** Returns         BOOLEAN
+******************************************************************************/
+BOOLEAN btif_av_get_ongoing_multicast()
+{
+    int i = 0, j = 0;
+    if (!is_multicast_supported)
+    {
+        BTIF_TRACE_DEBUG("Multicast is Disabled");
+        return FALSE;
+    }
+    for (i = 0; i < btif_max_av_clients; i++)
+    {
+        if (btif_av_cb[i].is_device_playing)
+        {
+            j++;
+        }
+    }
+    if (j == btif_max_av_clients)
+    {
+        return TRUE;
+    }
+    else
+    {
+        return FALSE;
     }
 }
index 052f785..aea496a 100644 (file)
@@ -214,6 +214,8 @@ static size_t btif_events_end_index = 0;
 ******************************************************************************/
 static btif_dm_pairing_cb_t pairing_cb;
 static btif_dm_oob_cb_t     oob_cb;
+static UINT16 num_active_br_edr_links;
+static UINT16 num_active_le_links;
 static void btif_dm_generic_evt(UINT16 event, char* p_param);
 static void btif_dm_cb_create_bond(bt_bdaddr_t *bd_addr, tBTA_TRANSPORT transport);
 static void btif_dm_cb_hid_remote_name(tBTM_REMOTE_DEV_NAME *p_remote_name);
@@ -252,6 +254,8 @@ extern bt_status_t btif_sdp_execute_service(BOOLEAN b_enable);
 extern int btif_hh_connect(bt_bdaddr_t *bd_addr);
 extern void bta_gatt_convert_uuid16_to_uuid128(UINT8 uuid_128[LEN_UUID_128], UINT16 uuid_16);
 extern void btif_av_move_idle(bt_bdaddr_t bd_addr);
+extern void btif_av_trigger_suspend();
+extern BOOLEAN btif_av_get_ongoing_multicast();
 
 /******************************************************************************
 **  Functions
@@ -1932,6 +1936,33 @@ static void btif_dm_upstreams_evt(UINT16 event, char* p_param)
             bdcpy(bd_addr.address, p_data->link_up.bd_addr);
             BTIF_TRACE_DEBUG("BTA_DM_LINK_UP_EVT. Sending BT_ACL_STATE_CONNECTED");
 
+            if(p_data->link_up.link_type == BT_TRANSPORT_LE)
+            {
+                num_active_le_links++;
+                BTIF_TRACE_DEBUG("num_active_le_links is %d ",
+                    num_active_le_links);
+            }
+
+            if(p_data->link_up.link_type == BT_TRANSPORT_BR_EDR)
+            {
+                num_active_br_edr_links++;
+                BTIF_TRACE_DEBUG("num_active_br_edr_links is %d ",
+                    num_active_br_edr_links);
+            }
+            /* When tuchtones are enabled and 2 EDR HS are connected, if new
+             * connection is initated, then tuch tones are send to both connected HS
+             * over A2dp.Stream will be suspended after 3 secs and if remote has
+             * initiated play in this duartion, multicast must not be enabled with
+             * 3 ACL's, hence trigger a2dp suspend.
+             * During active muisc streaming no new connection can happen, hence
+             * We will get this only when multistreaming is happening due to tuchtones
+             */
+            if (btif_av_get_ongoing_multicast())
+            {
+                // trigger a2dp suspend
+                btif_av_trigger_suspend();
+            }
+
             btif_update_remote_version_property(&bd_addr);
 
             HAL_CBACK(bt_hal_cbacks, acl_state_changed_cb, BT_STATUS_SUCCESS,
@@ -1940,7 +1971,23 @@ static void btif_dm_upstreams_evt(UINT16 event, char* p_param)
 
         case BTA_DM_LINK_DOWN_EVT:
             bdcpy(bd_addr.address, p_data->link_down.bd_addr);
+
             btm_set_bond_type_dev(p_data->link_down.bd_addr, BOND_TYPE_UNKNOWN);
+
+            BTIF_TRACE_DEBUG("BTA_DM_LINK_DOWN_EVT. Sending BT_ACL_STATE_DISCONNECTED");
+            if (num_active_le_links > 0 &&
+                p_data->link_down.link_type == BT_TRANSPORT_LE)
+            {
+                num_active_le_links--;
+                BTIF_TRACE_DEBUG("num_active_le_links is %d ",num_active_le_links);
+            }
+
+            if (num_active_br_edr_links > 0 &&
+                p_data->link_down.link_type == BT_TRANSPORT_BR_EDR)
+            {
+                num_active_br_edr_links--;
+                BTIF_TRACE_DEBUG("num_active_br_edr_links is %d ",num_active_br_edr_links);
+            }
             btif_av_move_idle(bd_addr);
             BTIF_TRACE_DEBUG("BTA_DM_LINK_DOWN_EVT. Sending BT_ACL_STATE_DISCONNECTED");
             HAL_CBACK(bt_hal_cbacks, acl_state_changed_cb, BT_STATUS_SUCCESS,
@@ -3578,6 +3625,10 @@ bt_status_t btif_le_test_mode(uint16_t opcode, uint8_t *buf, uint8_t len)
 
 void btif_dm_on_disable()
 {
+    /* Cleanup static variables.*/
+    num_active_br_edr_links = 0;
+    num_active_le_links = 0;
+
     /* cancel any pending pairing requests */
     if (pairing_cb.state == BT_BOND_STATE_BONDING)
     {
@@ -3724,3 +3775,34 @@ void btif_debug_bond_event_dump(int fd) {
     }
     pthread_mutex_unlock(&bond_event_lock);
 }
+
+/*******************************************************************************
+**
+** Function        btif_dm_get_br_edr_links.
+**
+** Description     Returns number of active BR/EDR links.
+**
+** Returns         UINT16
+**
+*******************************************************************************/
+UINT16 btif_dm_get_br_edr_links()
+{
+    BTIF_TRACE_DEBUG("BR/EDR Link count: %d", num_active_br_edr_links);
+    return num_active_br_edr_links;
+}
+
+/*******************************************************************************
+**
+** Function        btif_dm_get_le_links.
+**
+** Description     Returns number of active  LE links.
+**
+** Returns         UINT16
+**
+*******************************************************************************/
+UINT16 btif_dm_get_le_links()
+{
+    BTIF_TRACE_DEBUG("LE Link count: %d", num_active_le_links);
+    return num_active_le_links;
+}
+
index b5bbffc..701bfbd 100644 (file)
@@ -614,6 +614,14 @@ static void btif_recv_ctrl_data(void)
             }
             break;
 
+        case A2DP_CTRL_CMD_CHECK_STREAM_STARTED:
+
+            if((btif_av_stream_started_ready() == TRUE))
+                a2dp_cmd_acknowledge(A2DP_CTRL_ACK_SUCCESS);
+            else
+                a2dp_cmd_acknowledge(A2DP_CTRL_ACK_FAILURE);
+            break;
+
         case A2DP_CTRL_CMD_START:
             /* Don't sent START request to stack while we are in call.
                Some headsets like the Sony MW600, don't allow AVDTP START
@@ -632,7 +640,20 @@ static void btif_recv_ctrl_data(void)
                 break;
             }
 
-            if (btif_av_stream_ready() == TRUE)
+            /* In Dual A2dp, first check for started state of stream
+            * as we dont want to START again as while doing Handoff
+            * the stack state will be started, so it is not needed
+            * to send START again, just open the media socket
+            * and ACK the audio HAL.*/
+            if (btif_av_stream_started_ready())
+            {
+                /* already started, setup audio data channel listener
+                * and ack back immediately */
+                UIPC_Open(UIPC_CH_ID_AV_AUDIO, btif_a2dp_data_cb);
+
+                a2dp_cmd_acknowledge(A2DP_CTRL_ACK_SUCCESS);
+            }
+            else if (btif_av_stream_ready() == TRUE)
             {
                 /* setup audio data channel listener */
                 UIPC_Open(UIPC_CH_ID_AV_AUDIO, btif_a2dp_data_cb);
@@ -645,14 +666,6 @@ static void btif_recv_ctrl_data(void)
                     a2dp_cmd_acknowledge(A2DP_CTRL_ACK_SUCCESS);
 #endif
             }
-            else if (btif_av_stream_started_ready())
-            {
-                /* already started, setup audio data channel listener
-                   and ack back immediately */
-                UIPC_Open(UIPC_CH_ID_AV_AUDIO, btif_a2dp_data_cb);
-
-                a2dp_cmd_acknowledge(A2DP_CTRL_ACK_SUCCESS);
-            }
             else
             {
                 APPL_TRACE_WARNING("%s: A2DP command %s while AV stream is not ready",
@@ -887,6 +900,17 @@ static void btif_a2dp_encoder_update(void)
     btif_media_task_enc_update_req(&msg);
 }
 
+bool btif_a2dp_is_media_task_stopped(void)
+{
+    if (media_task_running != MEDIA_TASK_STATE_OFF)
+    {
+        APPL_TRACE_ERROR("btif_a2dp_is_media_task_stopped: %d",
+                                            media_task_running);
+        return false;
+    }
+    return true;
+}
+
 bool btif_a2dp_start_media_task(void)
 {
     if (media_task_running != MEDIA_TASK_STATE_OFF)
@@ -898,6 +922,8 @@ bool btif_a2dp_start_media_task(void)
     APPL_TRACE_IMP("## A2DP START MEDIA THREAD ##");
 
     btif_media_cmd_msg_queue = fixed_queue_new(SIZE_MAX);
+    if (btif_media_cmd_msg_queue == NULL)
+        goto error_exit;
 
     /* start a2dp media task */
     worker_thread = thread_new_sized("media_worker", MAX_MEDIA_WORKQUEUE_SEM_COUNT);
@@ -921,7 +947,15 @@ bool btif_a2dp_start_media_task(void)
 
 void btif_a2dp_stop_media_task(void)
 {
-    APPL_TRACE_IMP("## A2DP STOP MEDIA THREAD ##");
+    APPL_TRACE_DEBUG("## A2DP STOP MEDIA THREAD ##");
+    if (media_task_running != MEDIA_TASK_STATE_ON)
+    {
+        APPL_TRACE_ERROR("warning: media task cleanup state: %d",
+                                        media_task_running);
+        return;
+    }
+    /* make sure no channels are restarted while shutting down */
+    media_task_running = MEDIA_TASK_STATE_SHUTTING_DOWN;
 
     // Stop timer
     alarm_free(btif_media_cb.media_alarm);
@@ -929,10 +963,12 @@ void btif_a2dp_stop_media_task(void)
 
     // Exit thread
     fixed_queue_free(btif_media_cmd_msg_queue, NULL);
-    btif_media_cmd_msg_queue = NULL;
     thread_post(worker_thread, btif_media_thread_cleanup, NULL);
     thread_free(worker_thread);
+
     worker_thread = NULL;
+    btif_media_cmd_msg_queue = NULL;
+    APPL_TRACE_DEBUG("## A2DP MEDIA THREAD STOPPED ##");
 }
 
 /*****************************************************************************
@@ -964,7 +1000,7 @@ void btif_a2dp_on_init(void)
 **
 *******************************************************************************/
 
-void btif_a2dp_setup_codec(void)
+tBTIF_STATUS btif_a2dp_setup_codec(void)
 {
     tBTIF_AV_MEDIA_FEEDINGS media_feeding;
     tBTIF_STATUS status;
@@ -992,8 +1028,13 @@ void btif_a2dp_setup_codec(void)
         /* Send message to Media task to configure transcoding */
         btif_media_task_audio_feeding_init_req(&mfeed);
     }
+    else
+    {
+        status = BTIF_ERROR_SRV_AV_FEEDING_NOT_SUPPORTED;
+    }
 
     mutex_global_unlock();
+           return status;
 }
 
 
@@ -1333,7 +1374,8 @@ void btif_a2dp_set_audio_focus_state(btif_media_audio_focus_state state)
 
     p_buf->focus_state = state;
     p_buf->hdr.event = BTIF_MEDIA_AUDIO_SINK_SET_FOCUS_STATE;
-    fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
+    if (btif_media_cmd_msg_queue != NULL)
+        fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
 }
 
 void btif_a2dp_set_audio_track_gain(float gain)
@@ -1462,12 +1504,11 @@ static void btif_media_thread_init(UNUSED_ATTR void *context) {
 
   raise_priority_a2dp(TASK_HIGH_MEDIA);
   media_task_running = MEDIA_TASK_STATE_ON;
+  APPL_TRACE_DEBUG(" btif_media_thread_init complete");
 }
 
 static void btif_media_thread_cleanup(UNUSED_ATTR void *context) {
   APPL_TRACE_IMP(" btif_media_thread_cleanup");
-  /* make sure no channels are restarted while shutting down */
-  media_task_running = MEDIA_TASK_STATE_SHUTTING_DOWN;
 
   /* this calls blocks until uipc is fully closed */
   UIPC_Close(UIPC_CH_ID_ALL);
@@ -1481,6 +1522,7 @@ static void btif_media_thread_cleanup(UNUSED_ATTR void *context) {
 
   /* Clear media task flag */
   media_task_running = MEDIA_TASK_STATE_OFF;
+  APPL_TRACE_DEBUG(" btif_media_thread_cleanup complete");
 }
 
 /*******************************************************************************
@@ -1497,8 +1539,9 @@ BOOLEAN btif_media_task_send_cmd_evt(UINT16 Evt)
     BT_HDR *p_buf = osi_malloc(sizeof(BT_HDR));
 
     p_buf->event = Evt;
-    fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
 
+    if (btif_media_cmd_msg_queue != NULL)
+        fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
     return TRUE;
 }
 
@@ -1657,8 +1700,9 @@ BOOLEAN btif_media_task_enc_init_req(tBTIF_MEDIA_INIT_AUDIO *p_msg)
 
     memcpy(p_buf, p_msg, sizeof(tBTIF_MEDIA_INIT_AUDIO));
     p_buf->hdr.event = BTIF_MEDIA_SBC_ENC_INIT;
-    fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
 
+    if (btif_media_cmd_msg_queue != NULL)
+        fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
     return TRUE;
 }
 
@@ -1678,8 +1722,9 @@ BOOLEAN btif_media_task_enc_update_req(tBTIF_MEDIA_UPDATE_AUDIO *p_msg)
 
     memcpy(p_buf, p_msg, sizeof(tBTIF_MEDIA_UPDATE_AUDIO));
     p_buf->hdr.event = BTIF_MEDIA_SBC_ENC_UPDATE;
-    fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
 
+    if (btif_media_cmd_msg_queue != NULL)
+        fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
     return TRUE;
 }
 
@@ -1699,8 +1744,9 @@ BOOLEAN btif_media_task_audio_feeding_init_req(tBTIF_MEDIA_INIT_AUDIO_FEEDING *p
 
     memcpy(p_buf, p_msg, sizeof(tBTIF_MEDIA_INIT_AUDIO_FEEDING));
     p_buf->hdr.event = BTIF_MEDIA_AUDIO_FEEDING_INIT;
-    fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
 
+    if (btif_media_cmd_msg_queue != NULL)
+        fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
     return TRUE;
 }
 
@@ -1718,8 +1764,9 @@ BOOLEAN btif_media_task_start_aa_req(void)
     BT_HDR *p_buf = osi_malloc(sizeof(BT_HDR));
 
     p_buf->event = BTIF_MEDIA_START_AA_TX;
-    fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
 
+    if (btif_media_cmd_msg_queue != NULL)
+        fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
     return TRUE;
 }
 
@@ -1769,8 +1816,9 @@ BOOLEAN btif_media_task_aa_rx_flush_req(void)
 
     BT_HDR *p_buf = osi_malloc(sizeof(BT_HDR));
     p_buf->event = BTIF_MEDIA_FLUSH_AA_RX;
-    fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
 
+    if (btif_media_cmd_msg_queue != NULL)
+        fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
     return TRUE;
 }
 
index 21e6f94..78b943a 100644 (file)
 **  Constants & Macros
 ******************************************************************************/
 
+/* Support Two RC Handles simultaneously*/
+#define BTIF_RC_NUM_CB       2
+/* Default index*/
+#define BTIF_RC_DEFAULT_INDEX 0
 /* cod value for Headsets */
 #define COD_AV_HEADSETS        0x0404
 /* for AVRC 1.4 need to change this */
 
 #define CHECK_RC_CONNECTED                                                                  \
     BTIF_TRACE_DEBUG("## %s ##", __FUNCTION__);                                            \
-    if (btif_rc_cb.rc_connected == FALSE)                                                    \
-    {                                                                                       \
+    int clients;                                                                           \
+    int conn_status = BT_STATUS_NOT_READY;                                                      \
+    for (clients = 0; clients < btif_max_rc_clients; clients++)                            \
+    {                                                                                      \
+        if ((btif_rc_cb[clients].rc_connected == TRUE))                                    \
+            conn_status = BT_STATUS_SUCCESS;                                                    \
+    }                                                                                      \
+    if(conn_status == BT_STATUS_NOT_READY)                                                      \
+    {                                                                                      \
         BTIF_TRACE_WARNING("Function %s() called when RC is not connected", __FUNCTION__); \
-        return BT_STATUS_NOT_READY;                                                         \
+        return BT_STATUS_NOT_READY;                                                        \
     }
 
-#define FILL_PDU_QUEUE(index, ctype, label, pending)        \
+#define FILL_PDU_QUEUE(idx, ctype, label, pending, index)        \
 {                                                           \
-    btif_rc_cb.rc_pdu_info[index].ctype = ctype;            \
-    btif_rc_cb.rc_pdu_info[index].label = label;            \
-    btif_rc_cb.rc_pdu_info[index].is_rsp_pending = pending; \
+    btif_rc_cb[index].rc_pdu_info[idx].ctype = ctype;            \
+    btif_rc_cb[index].rc_pdu_info[idx].label = label;            \
+    btif_rc_cb[index].rc_pdu_info[idx].is_rsp_pending = pending; \
 }
 
-#define SEND_METAMSG_RSP(index, avrc_rsp)                                                      \
+#define SEND_METAMSG_RSP(index, avrc_rsp, idx)                                                      \
 {                                                                                              \
-    if (btif_rc_cb.rc_pdu_info[index].is_rsp_pending == FALSE)                                  \
+    if(btif_rc_cb[idx].rc_pdu_info[index].is_rsp_pending == FALSE)                                  \
     {                                                                                          \
         BTIF_TRACE_WARNING("%s Not sending response as no PDU was registered", __FUNCTION__); \
         return BT_STATUS_UNHANDLED;                                                            \
     }                                                                                          \
-    send_metamsg_rsp(btif_rc_cb.rc_handle, btif_rc_cb.rc_pdu_info[index].label,                \
-        btif_rc_cb.rc_pdu_info[index].ctype, avrc_rsp);                                        \
-    btif_rc_cb.rc_pdu_info[index].ctype = 0;                                                   \
-    btif_rc_cb.rc_pdu_info[index].label = 0;                                                   \
-    btif_rc_cb.rc_pdu_info[index].is_rsp_pending = FALSE;                                      \
+    send_metamsg_rsp(btif_rc_cb[idx].rc_handle, btif_rc_cb[idx].rc_pdu_info[index].label,                \
+        btif_rc_cb[idx].rc_pdu_info[index].ctype, avrc_rsp);                                        \
+    btif_rc_cb[idx].rc_pdu_info[index].ctype = 0;                                                   \
+    btif_rc_cb[idx].rc_pdu_info[index].label = 0;                                                   \
+    btif_rc_cb[idx].rc_pdu_info[index].is_rsp_pending = FALSE;                                      \
 }
 
-
-#define SEND_BROWSEMSG_RSP(index , avrc_rsp)                                                   \
+#define SEND_BROWSEMSG_RSP(index , avrc_rsp, rc_index)                                                   \
 {                                                                                              \
-    if(btif_rc_cb.rc_pdu_info[index].is_rsp_pending == FALSE)                                  \
+    if(btif_rc_cb[rc_index].rc_pdu_info[index].is_rsp_pending == FALSE)                                  \
     {                                                                                          \
         BTIF_TRACE_WARNING("%s Not sending response as no PDU was registered", __FUNCTION__); \
         return BT_STATUS_UNHANDLED;                                                            \
     }                                                                                          \
-    send_browsemsg_rsp(btif_rc_cb.rc_handle, btif_rc_cb.rc_pdu_info[index].label,              \
-        btif_rc_cb.rc_pdu_info[index].ctype, avrc_rsp);                                        \
-    btif_rc_cb.rc_pdu_info[index].ctype = 0;                                                   \
-    btif_rc_cb.rc_pdu_info[index].label = 0;                                                   \
-    btif_rc_cb.rc_pdu_info[index].is_rsp_pending = FALSE;                                      \
+    send_browsemsg_rsp(btif_rc_cb[rc_index].rc_handle, btif_rc_cb[rc_index].rc_pdu_info[index].label,              \
+        btif_rc_cb[rc_index].rc_pdu_info[index].ctype, avrc_rsp);                                        \
+    btif_rc_cb[rc_index].rc_pdu_info[index].ctype = 0;                                                   \
+    btif_rc_cb[rc_index].rc_pdu_info[index].label = 0;                                                   \
 }
 
 /*****************************************************************************
@@ -208,6 +217,7 @@ typedef struct {
     BOOLEAN                     rc_features_processed;
     UINT64                      rc_playing_uid;
     BOOLEAN                     rc_procedure_complete;
+    BOOLEAN                     rc_play_processed;
 } btif_rc_cb_t;
 
 typedef struct {
@@ -228,6 +238,7 @@ typedef struct
 rc_device_t device;
 
 #define MAX_UINPUT_PATHS 3
+static int btif_max_rc_clients = 1;
 static const char* uinput_dev_path[] =
                        {"/dev/uinput", "/dev/input/uinput", "/dev/misc/uinput" };
 static int uinput_fd = -1;
@@ -240,6 +251,9 @@ static int  uinput_create(char *name);
 static int  init_uinput (void);
 static void close_uinput (void);
 static void sleep_ms(period_ms_t timeout_ms);
+#if (AVRC_CTLR_INCLUDED == TRUE)
+static BOOLEAN conn_status = FALSE;
+#endif
 
 static const struct {
     const char *name;
@@ -263,7 +277,7 @@ static UINT8 opcode_from_pdu(UINT8 pdu);
 static void send_metamsg_rsp (UINT8 rc_handle, UINT8 label,
     tBTA_AV_CODE code, tAVRC_RESPONSE *pmetamsg_resp);
 #if (AVRC_ADV_CTRL_INCLUDED == TRUE)
-static void register_volumechange(UINT8 label);
+static void register_volumechange(UINT8 label, int index);
 #endif
 static void lbl_init();
 static void lbl_destroy();
@@ -300,13 +314,14 @@ static bt_status_t list_player_app_setting_attrib_cmd(void);
 static bt_status_t list_player_app_setting_value_cmd(uint8_t attrib_id);
 static bt_status_t get_player_app_setting_cmd(uint8_t num_attrib, uint8_t* attrib_ids);
 #endif
-static void btif_rc_upstreams_evt(UINT16 event, tAVRC_COMMAND* p_param, UINT8 ctype, UINT8 label);
-#if (AVRC_ADV_CTRL_INCLUDED == TRUE)
-static void btif_rc_upstreams_rsp_evt(UINT16 event, tAVRC_RESPONSE *pavrc_resp, UINT8 ctype, UINT8 label);
-#endif
 static void rc_start_play_status_timer(void);
 static bool absolute_volume_disabled(void);
-static bt_status_t set_addrplayer_rsp(btrc_status_t status_code);
+static void btif_rc_upstreams_evt(UINT16 event, tAVRC_COMMAND* p_param, UINT8 ctype, UINT8 label,
+                                    int index);
+static void btif_rc_upstreams_rsp_evt(UINT16 event, tAVRC_RESPONSE *pavrc_resp, UINT8 ctype, UINT8 label,
+                                    int index);
+static bt_status_t set_addrplayer_rsp(btrc_status_t status_code, bt_bdaddr_t *bd_addr);
+static int btif_rc_get_idx_by_addr(BD_ADDR address);
 
 /*Added for Browsing Message Response */
 static void send_browsemsg_rsp (UINT8 rc_handle, UINT8 label,
@@ -316,13 +331,15 @@ static void send_browsemsg_rsp (UINT8 rc_handle, UINT8 label,
 /*****************************************************************************
 **  Static variables
 ******************************************************************************/
-static btif_rc_cb_t btif_rc_cb;
+/* Two RC CBs needed to handle two connections*/
+static btif_rc_cb_t btif_rc_cb[BTIF_RC_NUM_CB];
 static btrc_callbacks_t *bt_rc_callbacks = NULL;
 static btrc_ctrl_callbacks_t *bt_rc_ctrl_callbacks = NULL;
 
 /*****************************************************************************
 **  Static functions
 ******************************************************************************/
+static UINT8 btif_rc_get_idx_by_rc_handle(UINT8 rc_handle);
 
 /*****************************************************************************
 **  Externs
@@ -330,8 +347,17 @@ static btrc_ctrl_callbacks_t *bt_rc_ctrl_callbacks = NULL;
 extern BOOLEAN btif_hf_call_terminated_recently();
 extern BOOLEAN check_cod(const bt_bdaddr_t *remote_bdaddr, uint32_t cod);
 
-extern fixed_queue_t *btu_general_alarm_queue;
+extern void btif_get_latest_playing_device(BD_ADDR address); //get the Playing device address
+extern BOOLEAN btif_av_is_playing();
+extern BOOLEAN btif_av_is_device_connected(BD_ADDR address);
+extern void btif_av_trigger_dual_handoff(BOOLEAN handoff, BD_ADDR address);
 extern BOOLEAN btif_hf_is_call_idle();
+extern BOOLEAN btif_av_get_multicast_state();
+extern BOOLEAN btif_av_is_current_device(BD_ADDR address);
+extern UINT16 btif_av_get_num_connected_devices(void);
+extern UINT16 btif_av_get_num_playing_devices(void);
+
+extern fixed_queue_t *btu_general_alarm_queue;
 
 /*****************************************************************************
 **  Functions
@@ -437,19 +463,27 @@ int init_uinput (void)
     char *name = "AVRCP";
 
     BTIF_TRACE_DEBUG("%s", __FUNCTION__);
-    uinput_fd = uinput_create(name);
-    if (uinput_fd < 0) {
-        BTIF_TRACE_ERROR("%s AVRCP: Failed to initialize uinput for %s (%d)",
-                          __FUNCTION__, name, uinput_fd);
-    } else {
-        BTIF_TRACE_DEBUG("%s AVRCP: Initialized uinput for %s (fd=%d)",
-                          __FUNCTION__, name, uinput_fd);
+    if (uinput_fd < 0)
+    {
+        BTIF_TRACE_DEBUG("Create Uinput device");
+        uinput_fd = uinput_create(name);
+        if (uinput_fd < 0) {
+            BTIF_TRACE_ERROR("%s AVRCP: Failed to initialize uinput for %s (%d)",
+                            __FUNCTION__, name, uinput_fd);
+        }
+        else
+        {
+            BTIF_TRACE_DEBUG("%s AVRCP: Initialized uinput for %s (fd=%d)",
+                            __FUNCTION__, name, uinput_fd);
+        }
     }
     return uinput_fd;
 }
 
 void close_uinput (void)
 {
+    //Dont close uinput untill all connections are teared down
+    // Since we support Dual AVRCP conn now.
     BTIF_TRACE_DEBUG("%s", __FUNCTION__);
     if (uinput_fd > 0) {
         ioctl(uinput_fd, UI_DEV_DESTROY);
@@ -459,6 +493,7 @@ void close_uinput (void)
     }
 }
 
+
 #if (AVRC_CTLR_INCLUDED == TRUE)
 void rc_cleanup_sent_cmd (void *p_data)
 {
@@ -466,36 +501,34 @@ void rc_cleanup_sent_cmd (void *p_data)
 
 }
 
-void handle_rc_ctrl_features(BD_ADDR bd_addr)
+void handle_rc_ctrl_features(int index)
 {
-    BTIF_TRACE_DEBUG(" %s rc_feat_processed = %d", __FUNCTION__, btif_rc_cb.rc_features_processed);
-    if (btif_rc_cb.rc_features_processed == TRUE)
-        return;
-    if ((btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG)||
-       ((btif_rc_cb.rc_features & BTA_AV_FEAT_RCCT)&&
-        (btif_rc_cb.rc_features & BTA_AV_FEAT_ADV_CTRL)))
+    if ((btif_rc_cb[index].rc_features & BTA_AV_FEAT_RCTG)||
+       ((btif_rc_cb[index].rc_features & BTA_AV_FEAT_RCCT)&&
+        (btif_rc_cb[index].rc_features & BTA_AV_FEAT_ADV_CTRL)))
     {
         bt_bdaddr_t rc_addr;
         int rc_features = 0;
-        bdcpy(rc_addr.address,bd_addr);
+        bdcpy(rc_addr.address, btif_rc_cb[index].rc_addr);
 
-        if ((btif_rc_cb.rc_features & BTA_AV_FEAT_ADV_CTRL)&&
-             (btif_rc_cb.rc_features & BTA_AV_FEAT_RCCT))
+        if ((btif_rc_cb[index].rc_features & BTA_AV_FEAT_ADV_CTRL)&&
+             (btif_rc_cb[index].rc_features & BTA_AV_FEAT_RCCT))
         {
             rc_features |= BTRC_FEAT_ABSOLUTE_VOLUME;
         }
-        if ((btif_rc_cb.rc_features & BTA_AV_FEAT_METADATA)&&
-            (btif_rc_cb.rc_features & BTA_AV_FEAT_VENDOR))
+        if ((btif_rc_cb[index].rc_features & BTA_AV_FEAT_METADATA)&&
+            (btif_rc_cb[index].rc_features & BTA_AV_FEAT_VENDOR)&&
+            (btif_rc_cb[index].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.
              */
-            if ((btif_rc_cb.rc_features_processed == FALSE) &&
+            if ((btif_rc_cb[index].rc_features_processed == FALSE) &&
                 btif_av_is_sink_enabled())
             {
-                btif_rc_cb.rc_features_processed = TRUE;
+                btif_rc_cb[index].rc_features_processed = TRUE;
                 getcapabilities_cmd (AVRC_CAP_COMPANY_ID);
             }
         }
@@ -505,83 +538,228 @@ void handle_rc_ctrl_features(BD_ADDR bd_addr)
 }
 #endif
 
-void handle_rc_features(BD_ADDR bd_addr)
+void handle_rc_features(int index)
 {
     if (bt_rc_callbacks != NULL)
     {
-    btrc_remote_features_t rc_features = BTRC_FEAT_NONE;
-    bt_bdaddr_t rc_addr;
+        btrc_remote_features_t rc_features = BTRC_FEAT_NONE;
+        bt_bdaddr_t rc_addr;
+        bt_bdaddr_t avdtp_addr;
+        bdstr_t addr1, addr2;
 
-    bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
-    bt_bdaddr_t avdtp_addr  = btif_av_get_addr();
+        bdcpy(rc_addr.address, btif_rc_cb[index].rc_addr);
+        avdtp_addr = btif_av_get_addr(btif_rc_cb[index].rc_addr);
 
-    bdstr_t addr1, addr2;
-    BTIF_TRACE_DEBUG("%s: AVDTP Address: %s AVCTP address: %s", __func__,
-                     bdaddr_to_string(&avdtp_addr, addr1, sizeof(addr1)),
-                     bdaddr_to_string(&rc_addr, addr2, sizeof(addr2)));
+        BTIF_TRACE_DEBUG("AVDTP Address : %s AVCTP address: %s",
+                         bdaddr_to_string(&avdtp_addr, addr1, sizeof(bdstr_t)),
+                         bdaddr_to_string(&rc_addr, addr2, sizeof(bdstr_t)) );
 
-    if (interop_match_addr(INTEROP_DISABLE_ABSOLUTE_VOLUME, &rc_addr)
-        || absolute_volume_disabled()
-        || bdcmp(avdtp_addr.address, rc_addr.address))
-        btif_rc_cb.rc_features &= ~BTA_AV_FEAT_ADV_CTRL;
+       //if (interop_match(INTEROP_DISABLE_ABSOLUTE_VOLUME, &rc_addr)
+       if ( absolute_volume_disabled()
+              || bdcmp(avdtp_addr.address, rc_addr.address))
+                       btif_rc_cb[index].rc_features &= ~BTA_AV_FEAT_ADV_CTRL;
 
-    if (btif_rc_cb.rc_features & BTA_AV_FEAT_BROWSE)
+        if (btif_rc_cb[index].rc_features & BTA_AV_FEAT_BROWSE)
+        {
+            rc_features |= BTRC_FEAT_BROWSE;
+        }
+        if ( (btif_rc_cb[index].rc_features & BTA_AV_FEAT_ADV_CTRL) &&
+            (btif_rc_cb[index].rc_features & BTA_AV_FEAT_RCTG))
+        {
+            rc_features |= BTRC_FEAT_ABSOLUTE_VOLUME;
+        }
+        if (btif_rc_cb[index].rc_features & BTA_AV_FEAT_METADATA)
+        {
+            rc_features |= BTRC_FEAT_METADATA;
+            /* Mark rc features processed to avoid repeating
+             * the AVRCP procedure every time on receiving this
+             * update.
+             */
+            btif_rc_cb[index].rc_features_processed = TRUE;
+            getcapabilities_cmd (AVRC_CAP_COMPANY_ID);
+        }
+        BTIF_TRACE_DEBUG("%s: rc_features=0x%x", __FUNCTION__, rc_features);
+        if (btif_rc_cb[index].rc_connected)
+        {
+            BTIF_TRACE_DEBUG("%s: update App on supported features", __FUNCTION__);
+            HAL_CBACK(bt_rc_callbacks, remote_features_cb, &rc_addr, rc_features)
+        }
+        else
+        {
+            BTIF_TRACE_DEBUG("%s: skipping feature update to App", __FUNCTION__);
+        }
+#if (AVRC_ADV_CTRL_INCLUDED == TRUE)
+        BTIF_TRACE_DEBUG("Checking for feature flags in btif_rc_handler with label %d",
+                         btif_rc_cb[index].rc_vol_label);
+        // Register for volume change on connect
+        if (btif_rc_cb[index].rc_features & BTA_AV_FEAT_ADV_CTRL &&
+            btif_rc_cb[index].rc_features & BTA_AV_FEAT_RCTG)
+        {
+            rc_transaction_t *p_transaction=NULL;
+            bt_status_t status = BT_STATUS_NOT_READY;
+            if (MAX_LABEL == btif_rc_cb[index].rc_vol_label)
+            {
+                status=get_transaction(&p_transaction);
+            }
+            else
+            {
+                p_transaction=get_transaction_by_lbl(btif_rc_cb[index].rc_vol_label);
+                if (NULL != p_transaction)
+                {
+                    BTIF_TRACE_DEBUG("register_volumechange already in progress for label %d",
+                    btif_rc_cb[index].rc_vol_label);
+                    return;
+                }
+                else
+                    status = get_transaction(&p_transaction);
+            }
+
+            if (BT_STATUS_SUCCESS == status && NULL!=p_transaction)
+            {
+                btif_rc_cb[index].rc_vol_label=p_transaction->lbl;
+                register_volumechange(btif_rc_cb[index].rc_vol_label, index);
+            }
+        }
+#endif
+    }
+    else
     {
-        rc_features |= BTRC_FEAT_BROWSE;
+        /*Disable all TG related bits if AVRCP TG feature is not enabled*/
+        BTIF_TRACE_WARNING("Avrcp TG role not enabled, disabling TG specific featuremask");
+        btif_rc_cb[index].rc_features &= ~BTA_AV_FEAT_ADV_CTRL;
+        btif_rc_cb[index].rc_features &= ~BTA_AV_FEAT_BROWSE;
+        btif_rc_cb[index].rc_features &= ~BTA_AV_FEAT_METADATA;
     }
+}
 
-#if (AVRC_ADV_CTRL_INCLUDED == TRUE)
-    if ( (btif_rc_cb.rc_features & BTA_AV_FEAT_ADV_CTRL) &&
-         (btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG))
+/***************************************************************************
+ *  Function       btif_rc_get_connection_state
+ *
+ *  - Argument:    none
+ *
+ *  - Description: Return true if any RC is in connected state
+ *
+ ***************************************************************************/
+static BOOLEAN btif_rc_get_connection_state()
+{
+    int clients;
+
+    for (clients = 0; clients < btif_max_rc_clients; clients++)
     {
-        rc_features |= BTRC_FEAT_ABSOLUTE_VOLUME;
+        if (btif_rc_cb[clients].rc_connected == TRUE)
+        {
+            return TRUE;
+        }
     }
-#endif
+    return FALSE;
+}
 
-    if (btif_rc_cb.rc_features & BTA_AV_FEAT_METADATA)
+/***************************************************************************
+ *  Function       btif_rc_get_valid_idx
+ *
+ *  - Argument:    none
+ *
+ *  - Description: Gets the index which is ready for new connection
+ *
+ ***************************************************************************/
+static int btif_rc_get_valid_idx()
+{
+    int i;
+    for (i = 0; i < btif_max_rc_clients; i++)
     {
-        rc_features |= BTRC_FEAT_METADATA;
+        if (!(btif_rc_cb[i].rc_connected))
+            break;
     }
-    if (btif_rc_cb.rc_features & BTA_AV_FEAT_AVRC_UI_UPDATE)
+    return i;
+}
+
+/***************************************************************************
+ *  Function       btif_rc_get_idx_by_rc_handle
+ *
+ *  - Argument:    rc handle
+ *
+ *  - Description: Gets the RC handle index of matching handle
+ *
+ ***************************************************************************/
+static UINT8 btif_rc_get_idx_by_rc_handle(UINT8 rc_handle)
+{
+    UINT8 i;
+
+    for (i = 0; i < btif_max_rc_clients; i++)
     {
-        rc_features |= BTRC_FEAT_AVRC_UI_UPDATE;
+        if (btif_rc_cb[i].rc_handle == rc_handle)
+            break;
     }
+    return i;
+}
 
-    BTIF_TRACE_DEBUG("%s: rc_features=0x%x", __FUNCTION__, rc_features);
-    HAL_CBACK(bt_rc_callbacks, remote_features_cb, &rc_addr, rc_features)
+/* Get the address of device on which PLAY command came
+* This address will be used in AV IF layer to determine
+* On which device to START playback. */
+/***************************************************************************
+ *  Function       btif_rc_get_playing_device
+ *
+ *  - Argument:    bd_addr
+ *
+ *  - Description: Copies the BD address of current playing device
+ *
+ ***************************************************************************/
+void btif_rc_get_playing_device(BD_ADDR address)
+{
+    int i;
+    for (i = 0; i < btif_max_rc_clients; i++)
+    {
+        if (btif_rc_cb[i].rc_play_processed)
+        {
+            //copy bd address
+            bdcpy(address, btif_rc_cb[i].rc_addr);
+        }
+    }
+}
 
-#if (AVRC_ADV_CTRL_INCLUDED == TRUE)
-     BTIF_TRACE_DEBUG("%s Checking for feature flags in btif_rc_handler with label %d",
-                        __FUNCTION__, btif_rc_cb.rc_vol_label);
-     // Register for volume change on connect
-      if (btif_rc_cb.rc_features & BTA_AV_FEAT_ADV_CTRL &&
-         btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG)
-      {
-         rc_transaction_t *p_transaction=NULL;
-         bt_status_t status = BT_STATUS_NOT_READY;
-         if (MAX_LABEL==btif_rc_cb.rc_vol_label)
-         {
-            status=get_transaction(&p_transaction);
-         }
-         else
-         {
-            p_transaction=get_transaction_by_lbl(btif_rc_cb.rc_vol_label);
-            if (NULL!=p_transaction)
-            {
-               BTIF_TRACE_DEBUG("%s register_volumechange already in progress for label %d",
-                                  __FUNCTION__, btif_rc_cb.rc_vol_label);
-               return;
-            } else {
-              status=get_transaction(&p_transaction);
-            }
-         }
-         if (BT_STATUS_SUCCESS == status && NULL!=p_transaction)
-         {
-            btif_rc_cb.rc_vol_label=p_transaction->lbl;
-            register_volumechange(btif_rc_cb.rc_vol_label);
-         }
-       }
-#endif
+/* Reset the Play trigger, once the AVDTP START is
+* sent, called from AV IF layer. */
+/***************************************************************************
+ *  Function       btif_rc_clear_playing_state
+ *
+ *  - Argument:    BOOLEAN
+ *
+ *  - Description: Clears the PLAY processed.rc_play_processed denotes
+ *                 play command has been processed for this device.
+ *
+ ***************************************************************************/
+void btif_rc_clear_playing_state(BOOLEAN state)
+{
+    int i;
+    for (i = 0; i < btif_max_rc_clients; i++)
+    {
+        if (btif_rc_cb[i].rc_play_processed)
+        {
+            btif_rc_cb[i].rc_play_processed = state;
+        }
+    }
+}
+
+/***************************************************************************
+ *  Function       btif_rc_clear_priority
+ *
+ *  - Argument:    Device address
+ *
+ *  - Description: Clears the priority information for the device
+ *                 This can be used while AV disconnection for the device.
+ *                 Setting of rc_play_processed flag could have been avoided
+ *                 looking at the stream state, but it might still leave some
+ *                 corner case of audio suspending just before the play takes
+ *                 effect.
+ ***************************************************************************/
+void btif_rc_clear_priority(BD_ADDR address)
+{
+    int index;
+
+    index = btif_rc_get_idx_by_addr(address);
+    if(index < btif_max_rc_clients)
+    {
+        btif_rc_cb[index].rc_play_processed = FALSE;
     }
 }
 
@@ -597,71 +775,73 @@ void handle_rc_connect (tBTA_AV_RC_OPEN *p_rc_open)
 {
     BTIF_TRACE_IMP("%s: rc_handle: %d", __FUNCTION__, p_rc_open->rc_handle);
     bt_status_t result = BT_STATUS_SUCCESS;
-#if (AVRC_CTLR_INCLUDED == TRUE)
     bt_bdaddr_t rc_addr;
-#endif
-
-    if (p_rc_open->status == BTA_AV_SUCCESS)
-    {
-        //check if already some RC is connected
-        if (btif_rc_cb.rc_connected)
+    int index;
+    if(p_rc_open->status == BTA_AV_SUCCESS)
+    {
+        //Check if already some RC is connected
+        /*Now we can have two RC connections
+        * Check should be here about 3rd connection too.
+        * Get the free or MAX index. Max index should be rejected. */
+        index = btif_rc_get_valid_idx();
+        if (index == btif_max_rc_clients)
         {
-            BTIF_TRACE_ERROR("%s Got RC OPEN in connected state, Connected RC: %d \
-                and Current RC: %d", __FUNCTION__, btif_rc_cb.rc_handle,p_rc_open->rc_handle );
-            if ((btif_rc_cb.rc_handle != p_rc_open->rc_handle)
-                && (bdcmp(btif_rc_cb.rc_addr, p_rc_open->peer_addr)))
-            {
-                BTIF_TRACE_DEBUG("%s Got RC connected for some other handle", __FUNCTION__);
-                BTA_AvCloseRc(p_rc_open->rc_handle);
-                return;
-            }
+            /*Reached Max, this connection must be rejected*/
+            BTIF_TRACE_ERROR("RC OPEN in MAX connected state");
+            BTA_AvCloseRc(p_rc_open->rc_handle);
+            return;
         }
-        memcpy(btif_rc_cb.rc_addr, p_rc_open->peer_addr, sizeof(BD_ADDR));
-        btif_rc_cb.rc_features = p_rc_open->peer_features;
-        btif_rc_cb.rc_vol_label=MAX_LABEL;
-        btif_rc_cb.rc_volume=MAX_VOLUME;
+        /*Use the index for this RC connection*/
+        BTIF_TRACE_DEBUG("Got RC OPEN on the index= %d", index);
+        memcpy(btif_rc_cb[index].rc_addr, p_rc_open->peer_addr, sizeof(BD_ADDR));
+        btif_rc_cb[index].rc_features = p_rc_open->peer_features;
+        btif_rc_cb[index].rc_vol_label = MAX_LABEL;
+        btif_rc_cb[index].rc_volume = MAX_VOLUME;
 
-        btif_rc_cb.rc_connected = TRUE;
-        btif_rc_cb.rc_handle = p_rc_open->rc_handle;
+        btif_rc_cb[index].rc_connected = TRUE;
+        btif_rc_cb[index].rc_handle = p_rc_open->rc_handle;
 
-        /* on locally initiated connection we will get remote features as part of connect */
-        if (btif_rc_cb.rc_features != 0)
-            handle_rc_features(btif_rc_cb.rc_addr);
         if (bt_rc_callbacks)
         {
             result = uinput_driver_check();
-            if (result == BT_STATUS_SUCCESS)
+            if(result == BT_STATUS_SUCCESS)
             {
                 init_uinput();
             }
         }
         else
         {
-            BTIF_TRACE_WARNING("%s Avrcp TG role not enabled, not initializing UInput",
-                               __FUNCTION__);
+            BTIF_TRACE_WARNING("Avrcp TG role not enabled, not initializing UInput");
         }
-        BTIF_TRACE_DEBUG("%s handle_rc_connect features %d ",__FUNCTION__, btif_rc_cb.rc_features);
+        bdcpy(rc_addr.address, btif_rc_cb[index].rc_addr);
+        if (btif_rc_cb[index].rc_features & BTA_AV_FEAT_RCCT)
+        {
+            HAL_CBACK(bt_rc_callbacks, connection_state_cb, TRUE, &rc_addr);
+        }
+        /* on locally initiated connection we will get remote features as part of connect */
+        if (btif_rc_cb[index].rc_features != 0)
+            handle_rc_features(index);
+        BTIF_TRACE_DEBUG(" handle_rc_connect features %d ",btif_rc_cb[index].rc_features);
 #if (AVRC_CTLR_INCLUDED == TRUE)
-        btif_rc_cb.rc_playing_uid = RC_INVALID_TRACK_ID;
-        bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
-        if (bt_rc_ctrl_callbacks != NULL)
+        /* report connection state if device is AVRCP target */
+        if (btif_rc_cb[index].rc_features & BTA_AV_FEAT_RCTG)
         {
             HAL_CBACK(bt_rc_ctrl_callbacks, connection_state_cb, TRUE, &rc_addr);
+            conn_status = TRUE;
         }
-        /* report connection state if remote device is AVRCP target */
-        if ((btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG)||
-           ((btif_rc_cb.rc_features & BTA_AV_FEAT_RCCT)&&
-            (btif_rc_cb.rc_features & BTA_AV_FEAT_ADV_CTRL)))
+        else
         {
-            handle_rc_ctrl_features(btif_rc_cb.rc_addr);
+            BTIF_TRACE_ERROR("RC connection state not updated to upper layer");
+            conn_status = FALSE;
         }
 #endif
+        /* on locally initiated connection we will get remote features as part of connect
+        Delay this update till connection update reaches Apps*/
     }
     else
     {
         BTIF_TRACE_ERROR("%s Connect failed with error code: %d",
             __FUNCTION__, p_rc_open->status);
-        btif_rc_cb.rc_connected = FALSE;
     }
 }
 
@@ -675,53 +855,46 @@ void handle_rc_connect (tBTA_AV_RC_OPEN *p_rc_open)
  ***************************************************************************/
 void handle_rc_disconnect (tBTA_AV_RC_CLOSE *p_rc_close)
 {
-#if (AVRC_CTLR_INCLUDED == TRUE)
     bt_bdaddr_t rc_addr;
     tBTA_AV_FEAT features;
-#endif
+    UINT8 index;
+    BOOLEAN is_connected = 0;
+
     BTIF_TRACE_IMP("%s: rc_handle: %d", __FUNCTION__, p_rc_close->rc_handle);
-    if ((p_rc_close->rc_handle != btif_rc_cb.rc_handle)
-        && (bdcmp(btif_rc_cb.rc_addr, p_rc_close->peer_addr)))
+
+    index = btif_rc_get_idx_by_rc_handle(p_rc_close->rc_handle);
+    if (index == btif_max_rc_clients)
     {
         BTIF_TRACE_ERROR("Got disconnect of unknown device");
         return;
     }
-#if (AVRC_CTLR_INCLUDED == TRUE)
-    bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
-    features = btif_rc_cb.rc_features;
-        /* Clean up AVRCP procedure flags */
-    memset(&btif_rc_cb.rc_app_settings, 0,
-        sizeof(btif_rc_player_app_settings_t));
-    btif_rc_cb.rc_features_processed = FALSE;
-    btif_rc_cb.rc_procedure_complete = FALSE;
-    rc_stop_play_status_timer();
-    /* Check and clear the notification event list */
-    if (btif_rc_cb.rc_supported_event_list != NULL)
-    {
-        list_clear(btif_rc_cb.rc_supported_event_list);
-        btif_rc_cb.rc_supported_event_list = NULL;
+    if ((p_rc_close->rc_handle != btif_rc_cb[index].rc_handle)
+        && (bdcmp(btif_rc_cb[index].rc_addr, p_rc_close->peer_addr)))
+    {
+        BTIF_TRACE_ERROR("Got disconnect of unknown device");
+        return;
     }
-#endif
-    btif_rc_cb.rc_handle = 0;
-    btif_rc_cb.rc_connected = FALSE;
-    memset(btif_rc_cb.rc_addr, 0, sizeof(BD_ADDR));
-    memset(btif_rc_cb.rc_notif, 0, sizeof(btif_rc_cb.rc_notif));
-
-    btif_rc_cb.rc_features = 0;
-    btif_rc_cb.rc_vol_label=MAX_LABEL;
-    btif_rc_cb.rc_volume=MAX_VOLUME;
-    if (device.lbllock_destroyed != TRUE)
+    btif_rc_cb[index].rc_handle = BTIF_RC_HANDLE_NONE;
+    btif_rc_cb[index].rc_connected = FALSE;
+    bdcpy(rc_addr.address, btif_rc_cb[index].rc_addr);
+    memset(btif_rc_cb[index].rc_addr, 0, sizeof(BD_ADDR));
+    memset(btif_rc_cb[index].rc_notif, 0, sizeof(btif_rc_cb[index].rc_notif));
+    features = btif_rc_cb[index].rc_features;
+    btif_rc_cb[index].rc_features = 0;
+    btif_rc_cb[index].rc_vol_label = MAX_LABEL;
+    btif_rc_cb[index].rc_volume = MAX_VOLUME;
+    btif_rc_cb[index].rc_play_processed = FALSE;
+    btif_rc_cb[index].rc_pending_play = FALSE;
+
+    //CLose Uinput only when all RCs are disconnected
+    is_connected = btif_rc_get_connection_state();
+    BTIF_TRACE_DEBUG("RC connected : %d", is_connected);
+       if (is_connected != TRUE && device.lbllock_destroyed != TRUE)
+    {
+        BTIF_TRACE_DEBUG("Clear UINPUT and transactions when zero RC left");
         init_all_transactions();
-
-    if (bt_rc_callbacks != NULL)
-    {
         close_uinput();
     }
-    else
-    {
-        BTIF_TRACE_WARNING("%s Avrcp TG role not enabled, not closing UInput", __FUNCTION__);
-    }
-
     if (!bdcmp(bd_null, rc_addr.address))
     {
         BTIF_TRACE_DEBUG("Cleanup already done");
@@ -734,6 +907,10 @@ void handle_rc_disconnect (tBTA_AV_RC_CLOSE *p_rc_close)
         HAL_CBACK(bt_rc_ctrl_callbacks, connection_state_cb, FALSE, &rc_addr);
    }
 #endif
+    if (features & BTA_AV_FEAT_RCCT)
+    {
+        HAL_CBACK(bt_rc_callbacks, connection_state_cb, FALSE, &rc_addr);
+    }
 }
 
 /***************************************************************************
@@ -745,11 +922,88 @@ void handle_rc_disconnect (tBTA_AV_RC_CLOSE *p_rc_close)
  *  - Description: Remote control command handler
  *
  ***************************************************************************/
+
+/* Rules: Only currenlty playing device's Passthrough commands
+* will be entertained.
+* While playing on Dev 1, if Dev2 sends Play, just respond it
+* without passing it to APP and in parallel start a protocol
+* suspend/pause the playback on DEV1 and Start on DEV2
+* Making sure that music is not paused and transfer happens seamless. */
 void handle_rc_passthrough_cmd ( tBTA_AV_REMOTE_CMD *p_remote_cmd)
 {
     const char *status;
     int pressed, i;
+    UINT8 index;
+    BD_ADDR address;
+    bt_bdaddr_t remote_address;
+    BOOLEAN ignore_play_processed = FALSE;
+
+    if (p_remote_cmd == NULL)
+        return;
+
+    index = btif_rc_get_idx_by_rc_handle(p_remote_cmd->rc_handle);
+    if (index == btif_max_rc_clients)
+    {
+        BTIF_TRACE_ERROR("Passthrough on invalid index");
+        return;
+    }
+    /* Multicast: Passthru command on AVRCP only device when connected
+     * to other A2DP devices, ignore it.
+     */
+    if (btif_av_is_connected() && !btif_av_is_device_connected(btif_rc_cb[index].rc_addr))
+    {
+        BTIF_TRACE_ERROR("Passthrough on AVRCP only device: Ignore..");
+        return;
+    }
 
+    /* Trigger DUAL Handoff when support single streaming */
+    if (btif_av_is_playing() &&
+        (btif_av_get_multicast_state() == FALSE))
+    {
+        /*compare the bd addr of current playing dev and this dev*/
+        btif_get_latest_playing_device(address);
+        if (bdcmp(btif_rc_cb[index].rc_addr, address) == 0)
+        {
+            APPL_TRACE_WARNING("Passthrough on the playing device");
+            if ((p_remote_cmd->rc_id == BTA_AV_RC_PLAY) &&
+                (p_remote_cmd->key_state == AVRC_STATE_PRESS))
+            {
+                APPL_TRACE_WARNING("Play again");
+                ignore_play_processed = TRUE;
+            }
+        }
+        else
+        {
+            BTIF_TRACE_DEBUG("Passthrough command on other device");
+            if (p_remote_cmd->rc_id == BTA_AV_RC_PLAY)
+            {
+                if (btif_av_is_device_connected(btif_rc_cb[index].rc_addr))
+                {
+                    /* Trigger suspend on currently playing device
+                     * Allow the Play to be sent to Music player to
+                     * address Play during Pause(Local/DUT initiated)
+                     * but SUSPEND not triggered by Audio module.
+                     */
+                    if (p_remote_cmd->key_state == AVRC_STATE_PRESS)
+                    {
+                        BTIF_TRACE_DEBUG("Trigger dual handoff for this play command");
+                        btif_rc_cb[index].rc_play_processed = TRUE;
+                        btif_av_trigger_dual_handoff(TRUE, btif_rc_cb[index].rc_addr);
+                    }
+                }
+                else
+                {
+                    APPL_TRACE_WARNING("%s: Command Invalid on %d", __FUNCTION__, index);
+                    return;
+                }
+            }
+            else
+            {
+                APPL_TRACE_WARNING("%s:Ignore all Passthrough on %d", __FUNCTION__, index);
+                return;
+            }
+        }
+    }
     BTIF_TRACE_DEBUG("%s: p_remote_cmd->rc_id=%d", __FUNCTION__, p_remote_cmd->rc_id);
 
     /* If AVRC is open and peer sends PLAY but there is no AVDT, then we queue-up this PLAY */
@@ -761,15 +1015,15 @@ void handle_rc_passthrough_cmd ( tBTA_AV_REMOTE_CMD *p_remote_cmd)
             if (p_remote_cmd->key_state == AVRC_STATE_PRESS)
             {
                 APPL_TRACE_WARNING("%s: AVDT not open, queuing the PLAY command", __FUNCTION__);
-                btif_rc_cb.rc_pending_play = TRUE;
+                btif_rc_cb[index].rc_pending_play = TRUE;
             }
             return;
         }
 
-        if ((p_remote_cmd->rc_id == BTA_AV_RC_PAUSE) && (btif_rc_cb.rc_pending_play))
+        if ((p_remote_cmd->rc_id == BTA_AV_RC_PAUSE) && (btif_rc_cb[index].rc_pending_play))
         {
             APPL_TRACE_WARNING("%s: Clear the pending PLAY on PAUSE received", __FUNCTION__);
-            btif_rc_cb.rc_pending_play = FALSE;
+            btif_rc_cb[index].rc_pending_play = FALSE;
             return;
         }
         if ((p_remote_cmd->rc_id == BTA_AV_RC_VOL_UP)||(p_remote_cmd->rc_id == BTA_AV_RC_VOL_DOWN))
@@ -781,20 +1035,35 @@ void handle_rc_passthrough_cmd ( tBTA_AV_REMOTE_CMD *p_remote_cmd)
         APPL_TRACE_WARNING("%s: Stream suspended, ignore STOP cmd",__FUNCTION__);
         return;
     }
+    if(!btif_av_is_connected())
+    {
+        APPL_TRACE_WARNING("%s: AVDT not open, discarding pass-through command: %d",
+                                                        __FUNCTION__, p_remote_cmd->rc_id);
+        return;
+    }
 
     if (p_remote_cmd->key_state == AVRC_STATE_RELEASE) {
         status = "released";
         pressed = 0;
-    } else {
+    }
+    else
+    {
         status = "pressed";
         pressed = 1;
     }
 
     if (p_remote_cmd->rc_id == BTA_AV_RC_FAST_FOR || p_remote_cmd->rc_id == BTA_AV_RC_REWIND) {
-        HAL_CBACK(bt_rc_callbacks, passthrough_cmd_cb, p_remote_cmd->rc_id, pressed);
+        bdcpy(remote_address.address, btif_rc_cb[index].rc_addr);
+        HAL_CBACK(bt_rc_callbacks, passthrough_cmd_cb, p_remote_cmd->rc_id, pressed, &remote_address);
         return;
     }
-
+    /*Update the device on which PLAY is issued*/
+    if (p_remote_cmd->rc_id == BTA_AV_RC_PLAY)
+    {
+        BTIF_TRACE_DEBUG("PLAY command on the Index: = %d", index);
+        if (p_remote_cmd->key_state == AVRC_STATE_PRESS && !ignore_play_processed)
+            btif_rc_cb[index].rc_play_processed = TRUE;
+    }
     for (i = 0; key_map[i].name != NULL; i++) {
         if (p_remote_cmd->rc_id == key_map[i].avrcp) {
             BTIF_TRACE_DEBUG("%s: %s %s", __FUNCTION__, key_map[i].name, status);
@@ -830,6 +1099,26 @@ void handle_rc_passthrough_cmd ( tBTA_AV_REMOTE_CMD *p_remote_cmd)
 }
 
 /***************************************************************************
+ *  Function       btif_rc_send_pause_command
+ *
+ *  - Argument:    None
+ *
+ *  - Description: Sends PAUSE key event to Upper layer.
+ *
+ ***************************************************************************/
+void btif_rc_send_pause_command()
+{
+    int rc_id;
+
+    rc_id = BTA_AV_RC_PAUSE;
+    BTIF_TRACE_DEBUG("Send Pause to music if playing is remotely disconnected");
+
+    send_key(uinput_fd, KEY_PAUSECD, 1);
+    sleep_ms(30); // 30ms
+    send_key(uinput_fd, KEY_PAUSECD, 0);
+}
+
+/***************************************************************************
  *  Function       handle_rc_passthrough_rsp
  *
  *  - Argument:    tBTA_AV_REMOTE_RSP passthrough command response
@@ -841,7 +1130,8 @@ void handle_rc_passthrough_rsp ( tBTA_AV_REMOTE_RSP *p_remote_rsp)
 {
 #if (AVRC_CTLR_INCLUDED == TRUE)
     const char *status;
-    if (btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG)
+    int index = BTIF_RC_DEFAULT_INDEX; // 0th index is RC
+    if (btif_rc_cb[index].rc_features & BTA_AV_FEAT_RCTG)
     {
         int key_state;
         if (p_remote_rsp->key_state == AVRC_STATE_RELEASE)
@@ -884,7 +1174,8 @@ void handle_rc_vendorunique_rsp ( tBTA_AV_REMOTE_RSP *p_remote_rsp)
 #if (AVRC_CTLR_INCLUDED == TRUE)
     const char *status;
     UINT8 vendor_id = 0;
-    if (btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG)
+    int index = BTIF_RC_DEFAULT_INDEX; // 0th index is RC
+    if (btif_rc_cb[index].rc_features & BTA_AV_FEAT_RCTG)
     {
         int key_state;
         if (p_remote_rsp->key_state == AVRC_STATE_RELEASE)
@@ -948,6 +1239,15 @@ void handle_rc_metamsg_cmd (tBTA_AV_META_MSG *pmeta_msg)
     UINT8             scratch_buf[512] = {0};
     tAVRC_COMMAND    avrc_command = {0};
     tAVRC_STS status;
+    UINT8 index;
+
+    //Get the index of RC
+    index = btif_rc_get_idx_by_rc_handle(pmeta_msg->rc_handle);
+    if (index == btif_max_rc_clients)
+    {
+        BTIF_TRACE_ERROR("%s: Invalid RC index", __FUNCTION__);
+        return;
+    }
 
     BTIF_TRACE_EVENT("+ %s", __FUNCTION__);
 
@@ -1009,8 +1309,8 @@ void handle_rc_metamsg_cmd (tBTA_AV_META_MSG *pmeta_msg)
             UINT8 event_id = avrc_command.reg_notif.event_id;
             BTIF_TRACE_EVENT("%s:New register notification received.event_id:%s,label:0x%x,code:%x",
             __FUNCTION__,dump_rc_notification_event_id(event_id), pmeta_msg->label,pmeta_msg->code);
-            btif_rc_cb.rc_notif[event_id-1].bNotify = TRUE;
-            btif_rc_cb.rc_notif[event_id-1].label = pmeta_msg->label;
+            btif_rc_cb[index].rc_notif[event_id-1].bNotify = TRUE;
+            btif_rc_cb[index].rc_notif[event_id-1].label = pmeta_msg->label;
 
             if (event_id == AVRC_EVT_UIDS_CHANGE)
             {
@@ -1027,7 +1327,7 @@ void handle_rc_metamsg_cmd (tBTA_AV_META_MSG *pmeta_msg)
             *btif context, no context switching is required. Invoke
             * btif_rc_upstreams_evt directly from here. */
         btif_rc_upstreams_evt((uint16_t)avrc_command.cmd.pdu, &avrc_command, pmeta_msg->code,
-                               pmeta_msg->label);
+                               pmeta_msg->label, index);
     }
 }
 
@@ -1053,7 +1353,7 @@ UINT8 handle_get_folder_item_mediaplyerlist_cmd (tBTA_AV_BROWSE_MSG *pbrowse_msg
     //Check length
     p_length = &pbrowse_msg->p_msg->browse.p_browse_data[1];
     BE_STREAM_TO_UINT16(length, p_length);
-    if (length != 10) //Refer to spec
+    if (length < 10)
     {
         BTIF_TRACE_ERROR("GET_FOLDER_ITEMS: length error: =%d",length);
         return TRUE;
@@ -1165,10 +1465,15 @@ void handle_rc_browsemsg_cmd (tBTA_AV_BROWSE_MSG *pbrowse_msg)
     UINT8 event;
     UINT16 length;
     tAVRC_COMMAND cmd;
-    UINT8 *start_item, *p_length, *p_data;
-    UINT8 *end_item;
+    UINT8 *p_length, *p_data;
     tAVRC_RESPONSE avrc_rsp;
     UINT8  dropmsg = TRUE;
+    UINT8 index = btif_rc_get_idx_by_rc_handle(pbrowse_msg->rc_handle);
+    if (index == btif_max_rc_clients)
+    {
+        BTIF_TRACE_ERROR("%s: Invalid RC index", __FUNCTION__);
+        return;
+    }
 
     BTIF_TRACE_EVENT("+ %s", __FUNCTION__);
     BTIF_TRACE_EVENT("pbrowse_msg PDU_ID :%x",pbrowse_msg->p_msg->browse.p_browse_data[0]);
@@ -1190,7 +1495,7 @@ void handle_rc_browsemsg_cmd (tBTA_AV_BROWSE_MSG *pbrowse_msg)
             }
             if (dropmsg == FALSE)
             {
-                btif_rc_upstreams_evt(event,&cmd,0,pbrowse_msg->label);
+                btif_rc_upstreams_evt(event,&cmd,0,pbrowse_msg->label, index);
             }
         }
         break;
@@ -1210,7 +1515,7 @@ void handle_rc_browsemsg_cmd (tBTA_AV_BROWSE_MSG *pbrowse_msg)
                 p_length = &pbrowse_msg->p_msg->browse.p_browse_data[3];
                 BE_STREAM_TO_UINT16(cmd.br_player.player_id, p_length);
                 cmd.br_player.opcode = AVRC_OP_BROWSE;
-                btif_rc_upstreams_evt(event, &cmd, 0, pbrowse_msg->label);
+                btif_rc_upstreams_evt(event, &cmd, 0, pbrowse_msg->label, index);
                 dropmsg = FALSE;
             }
         break;
@@ -1233,7 +1538,7 @@ void handle_rc_browsemsg_cmd (tBTA_AV_BROWSE_MSG *pbrowse_msg)
                 cmd.chg_path.status = AVRC_STS_NO_ERROR;
                 p_data = &pbrowse_msg->p_msg->browse.p_browse_data[6];
                 BE_STREAM_TO_UINT64(cmd.chg_path.folder_uid, p_data);
-                btif_rc_upstreams_evt(event, &cmd, 0, pbrowse_msg->label);
+                btif_rc_upstreams_evt(event, &cmd, 0, pbrowse_msg->label, index);
                 dropmsg = FALSE;
             }
         break;
@@ -1241,7 +1546,7 @@ void handle_rc_browsemsg_cmd (tBTA_AV_BROWSE_MSG *pbrowse_msg)
         case AVRC_PDU_GET_ITEM_ATTRIBUTES:
         {
             UINT16 packet_len;
-            UINT8  num_attr, index;
+            UINT8  num_attr, idx;
             event  = pbrowse_msg->p_msg->browse.p_browse_data[0] ;
             cmd.get_attrs.pdu = event;
             p_data = &pbrowse_msg->p_msg->browse.p_browse_data[1];
@@ -1265,22 +1570,22 @@ void handle_rc_browsemsg_cmd (tBTA_AV_BROWSE_MSG *pbrowse_msg)
                 if (num_attr == 0)
                 {
                     /* remote requested all Attribute ID*/
-                    for (index = 0; index < BTRC_MAX_ELEM_ATTR_SIZE; index++)
+                    for (idx = 0; idx < BTRC_MAX_ELEM_ATTR_SIZE; idx++)
                     {
-                        cmd.get_attrs.attrs[index] = index + 1;
+                        cmd.get_attrs.attrs[idx] = idx + 1;
                     }
                 }
                 else
                 {
                     p_data = &pbrowse_msg->p_msg->browse.p_browse_data[15];
                     BTIF_TRACE_ERROR("GetItemAttr num_attr: = %d", cmd.get_attrs.attr_count);
-                    for (index = 0; index < num_attr ; index++)
+                    for (idx = 0; idx < num_attr ; idx++)
                     {
-                        BE_STREAM_TO_UINT32(cmd.get_attrs.attrs[index], p_data);
-                        BTIF_TRACE_ERROR("GetItemAttr attrid: = %d", cmd.get_attrs.attrs[index]);
+                        BE_STREAM_TO_UINT32(cmd.get_attrs.attrs[idx], p_data);
+                        BTIF_TRACE_ERROR("GetItemAttr attrid: = %d", cmd.get_attrs.attrs[idx]);
                     }
                 }
-                btif_rc_upstreams_evt(event, &cmd, 0, pbrowse_msg->label);
+                btif_rc_upstreams_evt(event, &cmd, 0, pbrowse_msg->label, index);
                 dropmsg = FALSE;
             }
         }
@@ -1296,7 +1601,7 @@ void handle_rc_browsemsg_cmd (tBTA_AV_BROWSE_MSG *pbrowse_msg)
         avrc_rsp.rsp.status = AVRC_STS_BAD_CMD;
         avrc_rsp.rsp.opcode = AVRC_OP_BROWSE;
         BTIF_TRACE_ERROR("handle_rc_browsemsg_cmd: pbrowse_msg ERROR: %x", avrc_rsp.rsp.pdu);
-        send_browsemsg_rsp(btif_rc_cb.rc_handle, pbrowse_msg->label, 0, &avrc_rsp);
+        send_browsemsg_rsp(btif_rc_cb[index].rc_handle, pbrowse_msg->label, 0, &avrc_rsp);
     }
 
 }
@@ -1311,6 +1616,8 @@ void handle_rc_browsemsg_cmd (tBTA_AV_BROWSE_MSG *pbrowse_msg)
  ***************************************************************************/
 void btif_rc_handler(tBTA_AV_EVT event, tBTA_AV *p_data)
 {
+    UINT8 index;
+
     BTIF_TRACE_IMP ("%s event:%s", __FUNCTION__, dump_rc_event(event));
     switch (event)
     {
@@ -1327,28 +1634,13 @@ void btif_rc_handler(tBTA_AV_EVT event, tBTA_AV *p_data)
 
         case BTA_AV_REMOTE_CMD_EVT:
         {
-            if (bt_rc_callbacks != NULL)
-            {
-              BTIF_TRACE_DEBUG("%s rc_id:0x%x key_state:%d",
-                               __FUNCTION__, p_data->remote_cmd.rc_id,
+            BTIF_TRACE_DEBUG("rc_id:0x%x key_state:%d", p_data->remote_cmd.rc_id,
                                p_data->remote_cmd.key_state);
-                /** In race conditions just after 2nd AVRCP is connected
-                 *  remote might send pass through commands, so check for
-                 *  Rc handle before processing pass through commands
-                 **/
-                if (btif_rc_cb.rc_handle == p_data->remote_cmd.rc_handle)
-                {
-                    handle_rc_passthrough_cmd( (&p_data->remote_cmd) );
-                }
-                else
-                {
-                    BTIF_TRACE_DEBUG("%s Pass-through command for Invalid rc handle", __FUNCTION__);
-                }
-            }
-            else
-            {
-                BTIF_TRACE_ERROR("AVRCP TG role not up, drop passthrough commands");
-            }
+            /** In race conditions just after 2nd AVRCP is connected
+             *  remote might send pass through commands, so check for
+             *  Rc handle before processing pass through commands
+             **/
+            handle_rc_passthrough_cmd( (&p_data->remote_cmd) );
         }
         break;
 
@@ -1371,13 +1663,25 @@ void btif_rc_handler(tBTA_AV_EVT event, tBTA_AV *p_data)
 #endif
         case BTA_AV_RC_FEAT_EVT:
         {
-            BTIF_TRACE_DEBUG("%s Peer_features:%x", __FUNCTION__, p_data->rc_feat.peer_features);
-            btif_rc_cb.rc_features = p_data->rc_feat.peer_features;
-            handle_rc_features(p_data->rc_feat.peer_addr);
+            BTIF_TRACE_DEBUG("Peer_features:%x on RC handle: %d", p_data->rc_feat.peer_features,
+                            p_data->rc_feat.rc_handle);
+            index = btif_rc_get_idx_by_rc_handle(p_data->rc_feat.rc_handle);
+            if (index == btif_max_rc_clients)
+            {
+                BTIF_TRACE_ERROR("%s: Invalid RC index for BTA_AV_RC_FEAT_EVT", __FUNCTION__);
+                return;
+            }
+            btif_rc_cb[index].rc_features = p_data->rc_feat.peer_features;
+            handle_rc_features(index);
 #if (AVRC_CTLR_INCLUDED == TRUE)
-            if ((btif_rc_cb.rc_connected) && (bt_rc_ctrl_callbacks != NULL))
+            bt_bdaddr_t rc_addr;
+            bdcpy(rc_addr.address, btif_rc_cb[index].rc_addr);
+            if (btif_rc_cb[index].rc_features & BTA_AV_FEAT_RCTG &&
+                btif_rc_cb[index].rc_connected == TRUE && conn_status == FALSE)
             {
-                handle_rc_ctrl_features(btif_rc_cb.rc_addr);
+                BTIF_TRACE_DEBUG("Update RC Connection State");
+                HAL_CBACK(bt_rc_ctrl_callbacks, connection_state_cb, TRUE, &rc_addr);
+                conn_status = TRUE;
             }
 #endif
         }
@@ -1455,13 +1759,37 @@ void btif_rc_handler(tBTA_AV_EVT event, tBTA_AV *p_data)
  ***************************************************************************/
 BOOLEAN btif_rc_get_connected_peer(BD_ADDR peer_addr)
 {
-    if (btif_rc_cb.rc_connected == TRUE) {
-        bdcpy(peer_addr, btif_rc_cb.rc_addr);
-        return TRUE;
+    /*Find the device for which AV is not connected but RC is.*/
+    int i;
+
+    for  (i = 0; i < btif_max_rc_clients; i++)
+    {
+        if (btif_rc_cb[i].rc_connected == TRUE)
+        {
+            if (!btif_av_is_device_connected(btif_rc_cb[i].rc_addr))
+            {
+                bdcpy(peer_addr, btif_rc_cb[i].rc_addr);
+                return TRUE;
+            }
+        }
     }
     return FALSE;
 }
 
+static int btif_rc_get_idx_by_addr(BD_ADDR address)
+{
+    int i;
+
+    for (i = 0; i < btif_max_rc_clients; i++)
+    {
+        if (bdcmp(btif_rc_cb[i].rc_addr, address) == 0)
+        {
+            break;
+        }
+    }
+    return i;
+}
+
 /***************************************************************************
  **
  ** Function       btif_rc_get_connected_peer_handle
@@ -1471,9 +1799,14 @@ BOOLEAN btif_rc_get_connected_peer(BD_ADDR peer_addr)
  ***************************************************************************/
 UINT8 btif_rc_get_connected_peer_handle(BD_ADDR peer_addr)
 {
-    if (btif_rc_cb.rc_connected && !bdcmp(peer_addr, btif_rc_cb.rc_addr))
+    int i;
+    for  (i = 0; i < btif_max_rc_clients; i++)
     {
-        return btif_rc_cb.rc_handle;
+        if ((btif_rc_cb[i].rc_connected == TRUE)
+             &&(!bdcmp(peer_addr,btif_rc_cb[i].rc_addr)))
+        {
+            return btif_rc_cb[i].rc_handle;
+        }
     }
     return BTIF_RC_HANDLE_NONE;
 }
@@ -1489,10 +1822,17 @@ UINT8 btif_rc_get_connected_peer_handle(BD_ADDR peer_addr)
 /* clear the queued PLAY command. if bSend is TRUE, forward to app */
 void btif_rc_check_handle_pending_play (BD_ADDR peer_addr, BOOLEAN bSendToApp)
 {
+    int index = btif_rc_get_idx_by_addr(peer_addr);
+
+    if (index == btif_max_rc_clients)
+    {
+        BTIF_TRACE_ERROR("%s: Invalid RC index", __FUNCTION__);
+        return;
+    }
     UNUSED(peer_addr);
 
     BTIF_TRACE_DEBUG("%s: bSendToApp=%d", __FUNCTION__, bSendToApp);
-    if (btif_rc_cb.rc_pending_play)
+    if (btif_rc_cb[index].rc_pending_play)
     {
         if (bSendToApp)
         {
@@ -1500,7 +1840,7 @@ void btif_rc_check_handle_pending_play (BD_ADDR peer_addr, BOOLEAN bSendToApp)
             APPL_TRACE_DEBUG("%s: Sending queued PLAYED event to app", __FUNCTION__);
 
             memset (&remote_cmd, 0, sizeof(tBTA_AV_REMOTE_CMD));
-            remote_cmd.rc_handle  = btif_rc_cb.rc_handle;
+            remote_cmd.rc_handle  = btif_rc_cb[index].rc_handle;
             remote_cmd.rc_id      = AVRC_ID_PLAY;
             remote_cmd.hdr.ctype  = AVRC_CMD_CTRL;
             remote_cmd.hdr.opcode = AVRC_OP_PASS_THRU;
@@ -1519,7 +1859,7 @@ void btif_rc_check_handle_pending_play (BD_ADDR peer_addr, BOOLEAN bSendToApp)
             remote_cmd.key_state  = AVRC_STATE_RELEASE;
             handle_rc_passthrough_cmd( &remote_cmd );
         }
-        btif_rc_cb.rc_pending_play = FALSE;
+        btif_rc_cb[index].rc_pending_play = FALSE;
     }
 }
 
@@ -1559,7 +1899,14 @@ static void send_metamsg_rsp (UINT8 rc_handle, UINT8 label, tBTA_AV_CODE code,
     tAVRC_RESPONSE *pmetamsg_resp)
 {
     UINT8 ctype;
+    UINT8 index;
 
+    index = btif_rc_get_idx_by_rc_handle(rc_handle);
+    if (index == btif_max_rc_clients)
+    {
+        BTIF_TRACE_ERROR("%s: Invalid RC index", __FUNCTION__);
+        return;
+    }
     if (!pmetamsg_resp)
     {
         BTIF_TRACE_WARNING("%s: Invalid response received from application", __FUNCTION__);
@@ -1601,24 +1948,24 @@ static void send_metamsg_rsp (UINT8 rc_handle, UINT8 label, tBTA_AV_CODE code,
     {
         BOOLEAN bSent = FALSE;
         UINT8   event_id = pmetamsg_resp->reg_notif.event_id;
-        BOOLEAN bNotify = (btif_rc_cb.rc_connected) && (btif_rc_cb.rc_notif[event_id-1].bNotify);
+        BOOLEAN bNotify = (btif_rc_cb[index].rc_connected) && (btif_rc_cb[index].rc_notif[event_id-1].bNotify);
 
         /* de-register this notification for a CHANGED response */
-        btif_rc_cb.rc_notif[event_id-1].bNotify = FALSE;
+        btif_rc_cb[index].rc_notif[event_id-1].bNotify = FALSE;
         BTIF_TRACE_DEBUG("%s rc_handle: %d. event_id: 0x%02d bNotify:%u", __FUNCTION__,
-             btif_rc_cb.rc_handle, event_id, bNotify);
+             btif_rc_cb[index].rc_handle, event_id, bNotify);
         if (bNotify)
         {
             BT_HDR *p_msg = NULL;
             tAVRC_STS status;
 
-            if (AVRC_STS_NO_ERROR == (status = AVRC_BldResponse(btif_rc_cb.rc_handle,
+            if (AVRC_STS_NO_ERROR == (status = AVRC_BldResponse(btif_rc_cb[index].rc_handle,
                 pmetamsg_resp, &p_msg)) )
             {
                 BTIF_TRACE_DEBUG("%s Sending notification to rc_handle: %d. event_id: 0x%02d",
-                     __FUNCTION__, btif_rc_cb.rc_handle, event_id);
+                     __FUNCTION__, btif_rc_cb[index].rc_handle, event_id);
                 bSent = TRUE;
-                BTA_AvMetaRsp(btif_rc_cb.rc_handle, btif_rc_cb.rc_notif[event_id-1].label,
+                BTA_AvMetaRsp(btif_rc_cb[index].rc_handle, btif_rc_cb[index].rc_notif[event_id-1].label,
                     ctype, p_msg);
             }
             else
@@ -1730,9 +2077,9 @@ static void send_browsemsg_rsp (UINT8 rc_handle, UINT8 label, tBTA_AV_CODE code,
 * Description  -   Send Browse message
 *
 *******************************************************************************/
-int app_sendbrowsemsg(UINT8 index ,tAVRC_RESPONSE *avrc_rsp)
+int app_sendbrowsemsg(UINT8 index ,tAVRC_RESPONSE *avrc_rsp, int rc_index)
 {
-   SEND_BROWSEMSG_RSP(index ,avrc_rsp);
+   SEND_BROWSEMSG_RSP(index ,avrc_rsp, rc_index);
    return 0;
 }
 
@@ -1746,25 +2093,30 @@ int app_sendbrowsemsg(UINT8 index ,tAVRC_RESPONSE *avrc_rsp)
 ** Returns          void
 **
 *******************************************************************************/
-static void btif_rc_upstreams_evt(UINT16 event, tAVRC_COMMAND *pavrc_cmd, UINT8 ctype, UINT8 label)
+static void btif_rc_upstreams_evt(UINT16 event, tAVRC_COMMAND *pavrc_cmd, UINT8 ctype, UINT8 label,
+                                int index)
 {
+    bt_bdaddr_t remote_addr;
+    BD_ADDR address;
+
+    bdcpy(remote_addr.address, btif_rc_cb[index].rc_addr);
     BTIF_TRACE_IMP("%s pdu: %s handle: 0x%x ctype:%x label:%x", __FUNCTION__,
-        dump_rc_pdu(pavrc_cmd->pdu), btif_rc_cb.rc_handle, ctype, label);
+        dump_rc_pdu(pavrc_cmd->pdu), btif_rc_cb[index].rc_handle, ctype, label);
 
     switch (event)
     {
         case AVRC_PDU_GET_PLAY_STATUS:
         {
             BTIF_TRACE_DEBUG("AVRC_PDU_GET_PLAY_STATUS ");
-            FILL_PDU_QUEUE(IDX_GET_PLAY_STATUS_RSP, ctype, label, TRUE)
-            HAL_CBACK(bt_rc_callbacks, get_play_status_cb);
+            FILL_PDU_QUEUE(IDX_GET_PLAY_STATUS_RSP, ctype, label, TRUE, index)
+            HAL_CBACK(bt_rc_callbacks, get_play_status_cb, &remote_addr);
         }
         break;
         case AVRC_PDU_LIST_PLAYER_APP_ATTR:
         {
             BTIF_TRACE_DEBUG("AVRC_PDU_LIST_PLAYER_APP_ATTR ");
-            FILL_PDU_QUEUE(IDX_LIST_APP_ATTR_RSP, ctype, label, TRUE)
-            HAL_CBACK(bt_rc_callbacks, list_player_app_attr_cb);
+            FILL_PDU_QUEUE(IDX_LIST_APP_ATTR_RSP, ctype, label, TRUE, index)
+            HAL_CBACK(bt_rc_callbacks, list_player_app_attr_cb, &remote_addr);
         }
         break;
         case AVRC_PDU_LIST_PLAYER_APP_VALUES:
@@ -1772,11 +2124,14 @@ static void btif_rc_upstreams_evt(UINT16 event, tAVRC_COMMAND *pavrc_cmd, UINT8
             BTIF_TRACE_DEBUG("AVRC_PDU_LIST_PLAYER_APP_VALUES =%d" ,pavrc_cmd->list_app_values.attr_id);
             if (pavrc_cmd->list_app_values.attr_id == 0)
             {
-                send_reject_response (btif_rc_cb.rc_handle, label, pavrc_cmd->pdu, AVRC_STS_BAD_PARAM);
+                send_reject_response (btif_rc_cb[index].rc_handle, label, pavrc_cmd->pdu,
+                                    AVRC_STS_BAD_PARAM);
                 break;
             }
-            FILL_PDU_QUEUE(IDX_LIST_APP_VALUE_RSP, ctype, label, TRUE)
-            HAL_CBACK(bt_rc_callbacks, list_player_app_values_cb ,pavrc_cmd->list_app_values.attr_id);
+            FILL_PDU_QUEUE(IDX_LIST_APP_VALUE_RSP, ctype, label, TRUE, index)
+            HAL_CBACK(bt_rc_callbacks, list_player_app_values_cb,
+                    pavrc_cmd->list_app_values.attr_id,
+                    &remote_addr);
         }
         break;
         case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE:
@@ -1787,7 +2142,8 @@ static void btif_rc_upstreams_evt(UINT16 event, tAVRC_COMMAND *pavrc_cmd, UINT8
             if ((pavrc_cmd->get_cur_app_val.num_attr == 0) ||
                   (pavrc_cmd->get_cur_app_val.num_attr > BTRC_MAX_ELEM_ATTR_SIZE))
             {
-                send_reject_response (btif_rc_cb.rc_handle, label, pavrc_cmd->pdu, AVRC_STS_BAD_PARAM);
+                send_reject_response (btif_rc_cb[index].rc_handle, label, pavrc_cmd->pdu,
+                                    AVRC_STS_BAD_PARAM);
                 break;
             }
             memset( player_attr, 0, sizeof(player_attr));
@@ -1796,20 +2152,19 @@ static void btif_rc_upstreams_evt(UINT16 event, tAVRC_COMMAND *pavrc_cmd, UINT8
             {
                 player_attr[player_attr_num] = pavrc_cmd->get_cur_app_val.attrs[player_attr_num];
             }
-            FILL_PDU_QUEUE(IDX_GET_CURR_APP_VAL_RSP, ctype, label, TRUE)
+            FILL_PDU_QUEUE(IDX_GET_CURR_APP_VAL_RSP, ctype, label, TRUE, index)
             HAL_CBACK(bt_rc_callbacks, get_player_app_value_cb ,
-                                               pavrc_cmd->get_cur_app_val.num_attr, player_attr );
+                    pavrc_cmd->get_cur_app_val.num_attr, player_attr, &remote_addr);
         }
         break;
         case AVRC_PDU_SET_PLAYER_APP_VALUE:
         {
             btrc_player_settings_t attr;
             UINT8 count;
-            tAVRC_RESPONSE avrc_rsp;
             if ((pavrc_cmd->set_app_val.num_val== 0) ||
                               (pavrc_cmd->set_app_val.num_val > BTRC_MAX_ELEM_ATTR_SIZE))
             {
-                send_reject_response (btif_rc_cb.rc_handle, label,
+                send_reject_response (btif_rc_cb[index].rc_handle, label,
                                        pavrc_cmd->pdu, AVRC_STS_BAD_PARAM);
                 break;
             }
@@ -1821,8 +2176,8 @@ static void btif_rc_upstreams_evt(UINT16 event, tAVRC_COMMAND *pavrc_cmd, UINT8
                     attr.attr_values[count]= pavrc_cmd->set_app_val.p_vals[count].attr_val;
                 }
                 attr.num_attr  =  pavrc_cmd->set_app_val.num_val ;
-                FILL_PDU_QUEUE(IDX_SET_APP_VAL_RSP, ctype, label, TRUE)
-                HAL_CBACK(bt_rc_callbacks, set_player_app_value_cb, &attr );
+                FILL_PDU_QUEUE(IDX_SET_APP_VAL_RSP, ctype, label, TRUE, index)
+                HAL_CBACK(bt_rc_callbacks, set_player_app_value_cb, &attr, &remote_addr);
             }
         }
         break;
@@ -1833,7 +2188,7 @@ static void btif_rc_upstreams_evt(UINT16 event, tAVRC_COMMAND *pavrc_cmd, UINT8
             if ((pavrc_cmd->get_app_attr_txt.num_attr == 0) ||
                    (pavrc_cmd->get_app_attr_txt.num_attr > BTRC_MAX_ELEM_ATTR_SIZE))
             {
-                send_reject_response (btif_rc_cb.rc_handle, label, pavrc_cmd->pdu, AVRC_STS_BAD_PARAM);
+                send_reject_response (btif_rc_cb[index].rc_handle, label, pavrc_cmd->pdu, AVRC_STS_BAD_PARAM);
             }
             else
             {
@@ -1841,9 +2196,9 @@ static void btif_rc_upstreams_evt(UINT16 event, tAVRC_COMMAND *pavrc_cmd, UINT8
                 {
                     player_attr_txt[count_txt] = pavrc_cmd->get_app_attr_txt.attrs[count_txt];
                 }
-                FILL_PDU_QUEUE(IDX_GET_APP_ATTR_TXT_RSP, ctype, label, TRUE)
+                FILL_PDU_QUEUE(IDX_GET_APP_ATTR_TXT_RSP, ctype, label, TRUE, index)
                 HAL_CBACK(bt_rc_callbacks, get_player_app_attrs_text_cb,
-                            pavrc_cmd->get_app_attr_txt.num_attr, player_attr_txt );
+                            pavrc_cmd->get_app_attr_txt.num_attr, player_attr_txt, &remote_addr);
             }
         }
         break;
@@ -1852,19 +2207,19 @@ static void btif_rc_upstreams_evt(UINT16 event, tAVRC_COMMAND *pavrc_cmd, UINT8
             if (pavrc_cmd->get_app_val_txt.attr_id == 0 ||
                      pavrc_cmd->get_app_val_txt.attr_id > AVRC_PLAYER_VAL_GROUP_REPEAT)
             {
-                send_reject_response (btif_rc_cb.rc_handle, label, pavrc_cmd->pdu, AVRC_STS_BAD_PARAM);
+                send_reject_response (btif_rc_cb[index].rc_handle, label, pavrc_cmd->pdu, AVRC_STS_BAD_PARAM);
                 break;
             }
             if (pavrc_cmd->get_app_val_txt.num_val == 0)
             {
-                send_reject_response (btif_rc_cb.rc_handle, label, pavrc_cmd->pdu, AVRC_STS_BAD_PARAM);
+                send_reject_response (btif_rc_cb[index].rc_handle, label, pavrc_cmd->pdu, AVRC_STS_BAD_PARAM);
             }
             else
             {
-                FILL_PDU_QUEUE(IDX_GET_APP_VAL_TXT_RSP, ctype, label, TRUE)
+                FILL_PDU_QUEUE(IDX_GET_APP_VAL_TXT_RSP, ctype, label, TRUE, index)
                 HAL_CBACK(bt_rc_callbacks, get_player_app_values_text_cb,
                           pavrc_cmd->get_app_val_txt.attr_id, pavrc_cmd->get_app_val_txt.num_val,
-                          pavrc_cmd->get_app_val_txt.vals);
+                          pavrc_cmd->get_app_val_txt.vals, &remote_addr);
             }
         }
         break;
@@ -1886,7 +2241,7 @@ static void btif_rc_upstreams_evt(UINT16 event, tAVRC_COMMAND *pavrc_cmd, UINT8
             else if (pavrc_cmd->get_elem_attrs.num_attr == 0xFF)
             {
                 /* 0xff indicates, no attributes requested - reject */
-                send_reject_response (btif_rc_cb.rc_handle, label, pavrc_cmd->pdu,
+                send_reject_response (btif_rc_cb[index].rc_handle, label, pavrc_cmd->pdu,
                     AVRC_STS_BAD_PARAM);
                 return;
             }
@@ -1920,8 +2275,8 @@ static void btif_rc_upstreams_evt(UINT16 event, tAVRC_COMMAND *pavrc_cmd, UINT8
                     }
                 }
             }
-            FILL_PDU_QUEUE(IDX_GET_ELEMENT_ATTR_RSP, ctype, label, TRUE);
-            HAL_CBACK(bt_rc_callbacks, get_element_attr_cb, num_attr, element_attrs);
+            FILL_PDU_QUEUE(IDX_GET_ELEMENT_ATTR_RSP, ctype, label, TRUE, index);
+            HAL_CBACK(bt_rc_callbacks, get_element_attr_cb, num_attr, element_attrs, &remote_addr);
         }
         break;
         case AVRC_PDU_REGISTER_NOTIFICATION:
@@ -1931,61 +2286,58 @@ static void btif_rc_upstreams_evt(UINT16 event, tAVRC_COMMAND *pavrc_cmd, UINT8
             {
                 BTIF_TRACE_WARNING("%s Device registering position changed with illegal param 0.",
                     __FUNCTION__);
-                send_reject_response (btif_rc_cb.rc_handle, label, pavrc_cmd->pdu, AVRC_STS_BAD_PARAM);
+                send_reject_response (btif_rc_cb[index].rc_handle, label, pavrc_cmd->pdu, AVRC_STS_BAD_PARAM);
                 /* de-register this notification for a rejected response */
-                btif_rc_cb.rc_notif[BTRC_EVT_PLAY_POS_CHANGED - 1].bNotify = FALSE;
+                btif_rc_cb[index].rc_notif[BTRC_EVT_PLAY_POS_CHANGED - 1].bNotify = FALSE;
                 return;
             }
             HAL_CBACK(bt_rc_callbacks, register_notification_cb, pavrc_cmd->reg_notif.event_id,
-                pavrc_cmd->reg_notif.param);
+                pavrc_cmd->reg_notif.param, &remote_addr);
         }
         break;
         case AVRC_PDU_INFORM_DISPLAY_CHARSET:
         {
             tAVRC_RESPONSE avrc_rsp;
             BTIF_TRACE_EVENT("%s() AVRC_PDU_INFORM_DISPLAY_CHARSET", __FUNCTION__);
-            if (btif_rc_cb.rc_connected == TRUE)
+            if(btif_rc_cb[index].rc_connected == TRUE)
             {
                 memset(&(avrc_rsp.inform_charset), 0, sizeof(tAVRC_RSP));
                 avrc_rsp.inform_charset.opcode=opcode_from_pdu(AVRC_PDU_INFORM_DISPLAY_CHARSET);
                 avrc_rsp.inform_charset.pdu=AVRC_PDU_INFORM_DISPLAY_CHARSET;
                 avrc_rsp.inform_charset.status=AVRC_STS_NO_ERROR;
-                send_metamsg_rsp(btif_rc_cb.rc_handle, label, ctype, &avrc_rsp);
+                send_metamsg_rsp(btif_rc_cb[index].rc_handle, label, ctype, &avrc_rsp);
             }
         }
         break;
         case AVRC_PDU_SET_ADDRESSED_PLAYER:
         {
-            btrc_status_t status_code = AVRC_STS_NO_ERROR;
             BTIF_TRACE_EVENT("%s() AVRC_PDU_SET_ADDRESSED_PLAYER", __FUNCTION__);
             FILL_PDU_QUEUE(IDX_SET_ADDRESS_PLAYER_RSP, ctype, label, TRUE, index);
             if (!btif_hf_is_call_idle())
             {
-                set_addrplayer_rsp(ERR_PLAYER_NOT_ADDRESED); // send reject if call is in progress
+                set_addrplayer_rsp(ERR_PLAYER_NOT_ADDRESED, &remote_addr); // send reject if call is in progress
                 return;
             }
-            if (btif_rc_cb.rc_connected == TRUE)
+            if (btif_rc_cb[index].rc_connected == TRUE)
             {
-                HAL_CBACK(bt_rc_callbacks, set_addrplayer_cb, pavrc_cmd->addr_player.player_id);
+                FILL_PDU_QUEUE(IDX_SET_ADDRESS_PLAYER_RSP, ctype, label, TRUE, index);
+                HAL_CBACK(bt_rc_callbacks, set_addrplayer_cb, pavrc_cmd->addr_player.player_id, &remote_addr);
             }
         }
         break;
         case AVRC_PDU_GET_FOLDER_ITEMS:
         {
-            tAVRC_RESPONSE avrc_rsp;
             btrc_getfolderitem_t getfolder;
             btrc_browse_folderitem_t scope;
-            UINT8 player[] = "MusicPlayer1";
-            tAVRC_ITEM tem[1];
-            UINT8  index, numAttr;
+            UINT8  idx, numAttr;
             BTIF_TRACE_EVENT("%s()AVRC_PDU_GET_FOLDER_ITEMS", __FUNCTION__);
-            FILL_PDU_QUEUE(IDX_GET_FOLDER_ITEMS_RSP,ctype, label, TRUE);
-            BTIF_TRACE_EVENT("rc_connected: %d",btif_rc_cb.rc_connected);
-            if (btif_rc_cb.rc_connected == TRUE)
+            FILL_PDU_QUEUE(IDX_GET_FOLDER_ITEMS_RSP,ctype, label, TRUE, index);
+            BTIF_TRACE_EVENT("rc_connected: %d",btif_rc_cb[index].rc_connected);
+            if (btif_rc_cb[index].rc_connected == TRUE)
             {
                 getfolder.start_item = pavrc_cmd->get_items.start_item;
                 getfolder.end_item   = pavrc_cmd->get_items.end_item;
-                getfolder.size       = AVCT_GetBrowseMtu(btif_rc_cb.rc_handle);
+                getfolder.size       = AVCT_GetBrowseMtu(btif_rc_cb[index].rc_handle);
                 getfolder.attr_count = pavrc_cmd->get_items.attr_count;
                 scope                = (btrc_browse_folderitem_t)pavrc_cmd->get_items.scope;
                 if (getfolder.attr_count == 255)
@@ -1997,69 +2349,69 @@ static void btif_rc_upstreams_evt(UINT16 event, tAVRC_COMMAND *pavrc_cmd, UINT8
                     if (getfolder.attr_count == 0)
                     {
                         numAttr = 7;
-                        for (index = 0; index < BTRC_MAX_ELEM_ATTR_SIZE; index++)
+                        for (idx = 0; idx < BTRC_MAX_ELEM_ATTR_SIZE; idx++)
                         {
-                            getfolder.attrs[index] = index + 1;
+                            getfolder.attrs[idx] = idx + 1;
                         }
                     }
                     else
                     {
                         numAttr = getfolder.attr_count;
-                        for (index = 0; index < numAttr; index++)
+                        for (idx = 0; idx < numAttr; idx++)
                         {
-                            getfolder.attrs[index] = pavrc_cmd->get_items.attrs[index];
-                            BTIF_TRACE_ERROR("getfolder[%d] = %d", index, getfolder.\
-                                                                        attrs[index]);
+                            getfolder.attrs[idx] = pavrc_cmd->get_items.attrs[idx];
+                            BTIF_TRACE_ERROR("getfolder[%d] = %d", idx, getfolder.\
+                                                                        attrs[idx]);
                             BTIF_TRACE_ERROR("pavrc_cmd->get_items.attrs[%d] = %d",\
-                                            index, pavrc_cmd->get_items.attrs[index]);
+                                            idx, pavrc_cmd->get_items.attrs[idx]);
                         }
                     }
                 }
-                HAL_CBACK(bt_rc_callbacks, get_folderitems_cb, scope, &getfolder);
+                HAL_CBACK(bt_rc_callbacks, get_folderitems_cb, scope, &getfolder, &remote_addr);
             }
         }
         break;
         case AVRC_PDU_SET_BROWSED_PLAYER:
         {
             BTIF_TRACE_EVENT("%s() AVRC_PDU_SET_BROWSED_PLAYER", __FUNCTION__);
-            if (btif_rc_cb.rc_connected == TRUE)
+            if (btif_rc_cb[index].rc_connected == TRUE)
             {
-                FILL_PDU_QUEUE(IDX_SET_BROWSE_PLAYER_RSP, ctype, label, TRUE);
-                HAL_CBACK(bt_rc_callbacks, set_browsed_player_cb, pavrc_cmd->br_player.player_id);
+                FILL_PDU_QUEUE(IDX_SET_BROWSE_PLAYER_RSP, ctype, label, TRUE, index);
+                HAL_CBACK(bt_rc_callbacks, set_browsed_player_cb, pavrc_cmd->br_player.player_id, &remote_addr);
             }
         }
         break;
         case AVRC_PDU_CHANGE_PATH:
         {
             BTIF_TRACE_EVENT("%s() AVRC_PDU_CHANGE_PATH", __FUNCTION__);
-            if (btif_rc_cb.rc_connected == TRUE)
+            if (btif_rc_cb[index].rc_connected == TRUE)
             {
-                FILL_PDU_QUEUE(IDX_CHANGE_PATH_RSP, ctype, label, TRUE);
+                FILL_PDU_QUEUE(IDX_CHANGE_PATH_RSP, ctype, label, TRUE, index);
                 HAL_CBACK(bt_rc_callbacks, change_path_cb, pavrc_cmd->chg_path.direction, \
-                                                            pavrc_cmd->chg_path.folder_uid);
+                                                            pavrc_cmd->chg_path.folder_uid, &remote_addr);
             }
         }
         break;
         case AVRC_PDU_GET_ITEM_ATTRIBUTES:
         {
             UINT8 num_attr =  pavrc_cmd->get_attrs.attr_count;
-            UINT8 index, num_attr_requested = 0;
+            UINT8 idx, num_attr_requested = 0;
             BTIF_TRACE_EVENT("%s() AVRC_PDU_GET_ITEM_ATTRIBUTES", __FUNCTION__);
             btrc_media_attr_t element_attrs[BTRC_MAX_ELEM_ATTR_SIZE];
             memset(&element_attrs, 0, sizeof(element_attrs));
             if (num_attr == 0)
             {
                 /* CT requests for all attributes */
-                for (index = 0; index < BTRC_MAX_ELEM_ATTR_SIZE; index++)
+                for (idx = 0; idx < BTRC_MAX_ELEM_ATTR_SIZE; idx++)
                 {
-                    element_attrs[index] = index + 1;
+                    element_attrs[idx] = idx + 1;
                 }
-                num_attr_requested = 7; /* get all seven */
+                num_attr_requested = BTRC_MAX_ELEM_ATTR_SIZE; /* get all */
             }
             else if (num_attr == 0xFF)
             {
                 /* 0xff indicates, no attributes requested - reject */
-                send_reject_response (btif_rc_cb.rc_handle, label, pavrc_cmd->pdu,
+                send_reject_response (btif_rc_cb[index].rc_handle, label, pavrc_cmd->pdu,
                     AVRC_STS_BAD_PARAM);
                 return;
             }
@@ -2069,43 +2421,70 @@ static void btif_rc_upstreams_evt(UINT16 event, tAVRC_COMMAND *pavrc_cmd, UINT8
                  * hence HAL definition limits the attributes to BTRC_MAX_ELEM_ATTR_SIZE.
                  * Fill only valid entries.
                  */
-                for (index = 0; (index < num_attr) && (num_attr <= BTRC_MAX_ELEM_ATTR_SIZE); index++)
+                for (idx = 0; (idx < num_attr) && (num_attr <= BTRC_MAX_ELEM_ATTR_SIZE); idx++)
                 {
-                    if ((pavrc_cmd->get_attrs.attrs[index] > 0) &&
-                        (pavrc_cmd->get_attrs.attrs[index] <= BTRC_MAX_ELEM_ATTR_SIZE))
+                    if ((pavrc_cmd->get_attrs.attrs[idx] > 0) &&
+                        (pavrc_cmd->get_attrs.attrs[idx] <= BTRC_MAX_ELEM_ATTR_SIZE))
                     {
-                        element_attrs[index] = pavrc_cmd->get_attrs.attrs[index];
-                        BTIF_TRACE_ERROR("element_attrs[%d]: %d", index, element_attrs[index]);
+                        element_attrs[idx] = pavrc_cmd->get_attrs.attrs[idx];
+                        BTIF_TRACE_ERROR("element_attrs[%d]: %d", idx, element_attrs[idx]);
                     }
                 }
-                num_attr_requested = index;
+                num_attr_requested = idx;
                 BTIF_TRACE_ERROR("num_attr_requested: %d", num_attr_requested);
             }
 
-            if (btif_rc_cb.rc_connected == TRUE)
+            if (btif_rc_cb[index].rc_connected == TRUE)
             {
-                FILL_PDU_QUEUE(IDX_GET_ITEM_ATTR_RSP, ctype, label, TRUE);
+                FILL_PDU_QUEUE(IDX_GET_ITEM_ATTR_RSP, ctype, label, TRUE, index);
                 HAL_CBACK(bt_rc_callbacks, get_item_attr_cb, pavrc_cmd->get_attrs.scope,
-                        pavrc_cmd->get_attrs.uid, num_attr_requested, element_attrs);
+                        pavrc_cmd->get_attrs.uid, num_attr_requested, element_attrs, &remote_addr);
             }
         }
         break;
         case AVRC_PDU_PLAY_ITEM:
         {
             BTIF_TRACE_EVENT("%s() AVRC_PDU_PLAY_ITEM", __FUNCTION__);
-            if (btif_rc_cb.rc_connected == TRUE)
+            if (btif_rc_cb[index].rc_connected == TRUE)
             {
-                FILL_PDU_QUEUE(IDX_PLAY_ITEM_RSP, ctype, label, TRUE);
+                FILL_PDU_QUEUE(IDX_PLAY_ITEM_RSP, ctype, label, TRUE, index);
                 HAL_CBACK(bt_rc_callbacks, play_item_cb, pavrc_cmd->play_item.scope,
-                        pavrc_cmd->play_item.uid);
+                pavrc_cmd->play_item.uid, &remote_addr);
+                /*This command will trigger playback or
+                * dual a2dp handoff.. Let it play on this device. */
+                btif_rc_cb[index].rc_play_processed = TRUE;
+                /* Trigger DUAL Handoff when support single streaming */
+                if (btif_av_is_playing() &&
+                    (btif_av_get_multicast_state() == FALSE))
+                {
+                    //compare the bd addr of current playing dev and this dev
+                    btif_get_latest_playing_device(address);
+                    if (bdcmp(btif_rc_cb[index].rc_addr, address) == 0)
+                    {
+                        APPL_TRACE_WARNING("Play item on the playing device");
+                    } else
+                    {
+                        BTIF_TRACE_DEBUG("Play item on other device");
+                        if (btif_av_is_device_connected(btif_rc_cb[index].rc_addr))
+                        {
+                            //Trigger suspend on currently playing device
+                            BTIF_TRACE_DEBUG("Trigger dual handoff for this play Item command");
+                            btif_rc_cb[index].rc_play_processed = TRUE;
+                            btif_av_trigger_dual_handoff(TRUE, btif_rc_cb[index].rc_addr);
+                        } else
+                        {
+                            APPL_TRACE_WARNING("%s:Play item Invalid on %d", __FUNCTION__, index);
+                        }
+                    }
+                }
             }
         }
         break;
         default:
         {
-            send_reject_response(btif_rc_cb.rc_handle, label, pavrc_cmd->pdu,
-                 (pavrc_cmd->pdu == AVRC_PDU_SEARCH)? AVRC_STS_SEARCH_NOT_SUP:
-                                                                AVRC_STS_BAD_CMD);
+            send_reject_response (btif_rc_cb[index].rc_handle, label, pavrc_cmd->pdu,
+                    (pavrc_cmd->pdu == AVRC_PDU_SEARCH)?AVRC_STS_SEARCH_NOT_SUP:
+                                                                    AVRC_STS_BAD_CMD);
         }
         break;
     }
@@ -2125,9 +2504,9 @@ static void btif_rc_ctrl_upstreams_rsp_cmd(UINT8 event, tAVRC_COMMAND *pavrc_cmd
         UINT8 label)
 {
     BTIF_TRACE_DEBUG("%s pdu: %s handle: 0x%x", __FUNCTION__,
-        dump_rc_pdu(pavrc_cmd->pdu), btif_rc_cb.rc_handle);
+        dump_rc_pdu(pavrc_cmd->pdu), btif_rc_cb[0].rc_handle);
     bt_bdaddr_t rc_addr;
-    bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
+    bdcpy(rc_addr.address, btif_rc_cb[0].rc_addr);
 #if (AVRC_CTLR_INCLUDED == TRUE)
     switch (event)
     {
@@ -2157,28 +2536,32 @@ static void btif_rc_ctrl_upstreams_rsp_cmd(UINT8 event, tAVRC_COMMAND *pavrc_cmd
 ** Returns          void
 **
 *******************************************************************************/
-static void btif_rc_upstreams_rsp_evt(UINT16 event, tAVRC_RESPONSE *pavrc_resp, UINT8 ctype, UINT8 label)
+static void btif_rc_upstreams_rsp_evt(UINT16 event, tAVRC_RESPONSE *pavrc_resp, UINT8 ctype, UINT8 label, int index)
 {
+    bt_bdaddr_t remote_addr;
+
+    bdcpy(remote_addr.address, btif_rc_cb[index].rc_addr);
     BTIF_TRACE_IMP("%s pdu: %s handle: 0x%x ctype:%x label:%x", __FUNCTION__,
-        dump_rc_pdu(pavrc_resp->pdu), btif_rc_cb.rc_handle, ctype, label);
+        dump_rc_pdu(pavrc_resp->pdu), btif_rc_cb[index].rc_handle, ctype, label);
 
     switch (event)
     {
         case AVRC_PDU_REGISTER_NOTIFICATION:
         {
-             if (AVRC_RSP_CHANGED==ctype)
-                 btif_rc_cb.rc_volume=pavrc_resp->reg_notif.param.volume;
-             HAL_CBACK(bt_rc_callbacks, volume_change_cb, pavrc_resp->reg_notif.param.volume,ctype)
+            if(AVRC_RSP_CHANGED==ctype)
+                 btif_rc_cb[index].rc_volume=pavrc_resp->reg_notif.param.volume;
+             HAL_CBACK(bt_rc_callbacks, volume_change_cb, pavrc_resp->reg_notif.param.volume,ctype,
+                        &remote_addr)
         }
         break;
 
         case AVRC_PDU_SET_ABSOLUTE_VOLUME:
         {
-            BTIF_TRACE_DEBUG("%s Set absolute volume change event received: volume %d,ctype %d",
-                             __FUNCTION__, pavrc_resp->volume.volume,ctype);
-            if (AVRC_RSP_ACCEPT==ctype)
-                btif_rc_cb.rc_volume=pavrc_resp->volume.volume;
-            HAL_CBACK(bt_rc_callbacks,volume_change_cb,pavrc_resp->volume.volume,ctype)
+            BTIF_TRACE_DEBUG("Set absolute volume change event received: volume %d,ctype %d",
+                pavrc_resp->volume.volume,ctype);
+            if(AVRC_RSP_ACCEPT==ctype)
+                btif_rc_cb[index].rc_volume=pavrc_resp->volume.volume;
+            HAL_CBACK(bt_rc_callbacks,volume_change_cb,pavrc_resp->volume.volume,ctype, &remote_addr)
         }
         break;
 
@@ -2201,18 +2584,25 @@ static void btif_rc_upstreams_rsp_evt(UINT16 event, tAVRC_RESPONSE *pavrc_resp,
 ** Returns          bt_status_t
 **
 *******************************************************************************/
-static bt_status_t init(btrc_callbacks_t* callbacks )
+//APP can pass the max conn value here too
+static bt_status_t init(btrc_callbacks_t* callbacks, int max_connections)
 {
     BTIF_TRACE_EVENT("## %s ##", __FUNCTION__);
     bt_status_t result = BT_STATUS_SUCCESS;
+    int i;
 
     if (bt_rc_callbacks)
         return BT_STATUS_DONE;
 
     bt_rc_callbacks = callbacks;
+    btif_max_rc_clients = max_connections;
     memset (&btif_rc_cb, 0, sizeof(btif_rc_cb));
-    btif_rc_cb.rc_vol_label=MAX_LABEL;
-    btif_rc_cb.rc_volume=MAX_VOLUME;
+    for (i = 0; i < btif_max_rc_clients; i++)
+    {
+        btif_rc_cb[i].rc_vol_label=MAX_LABEL;
+        btif_rc_cb[i].rc_volume=MAX_VOLUME;
+        btif_rc_cb[i].rc_handle = BTIF_RC_HANDLE_NONE;
+    }
     lbl_init();
 
     return result;
@@ -2235,10 +2625,13 @@ static bt_status_t init_ctrl(btrc_ctrl_callbacks_t* callbacks )
     if (bt_rc_ctrl_callbacks)
         return BT_STATUS_DONE;
 
+    /* Controller is used only for Certification purposes.
+     * In normal case AVRCP controller will not be used, hence
+     * updating this is required.
+     */
     bt_rc_ctrl_callbacks = callbacks;
     memset (&btif_rc_cb, 0, sizeof(btif_rc_cb));
-    btif_rc_cb.rc_vol_label=MAX_LABEL;
-    btif_rc_cb.rc_volume=MAX_VOLUME;
+    btif_rc_cb[BTIF_RC_DEFAULT_INDEX].rc_vol_label=MAX_LABEL;
     lbl_init();
 
     return result;
@@ -2246,11 +2639,11 @@ static bt_status_t init_ctrl(btrc_ctrl_callbacks_t* callbacks )
 
 static void rc_ctrl_procedure_complete ()
 {
-    if (btif_rc_cb.rc_procedure_complete == TRUE)
+    if (btif_rc_cb[0].rc_procedure_complete == TRUE)
     {
         return;
     }
-    btif_rc_cb.rc_procedure_complete = TRUE;
+    btif_rc_cb[0].rc_procedure_complete = TRUE;
     UINT32 attr_list[] = {
             AVRC_MEDIA_ATTR_ID_TITLE,
             AVRC_MEDIA_ATTR_ID_ARTIST,
@@ -2275,10 +2668,20 @@ static void rc_ctrl_procedure_complete ()
 **
 ***************************************************************************/
 static bt_status_t get_play_status_rsp(btrc_play_status_t play_status, uint32_t song_len,
-    uint32_t song_pos)
+    uint32_t song_pos, bt_bdaddr_t *bd_addr)
 {
     tAVRC_RESPONSE avrc_rsp;
+    int rc_index;
     CHECK_RC_CONNECTED
+
+    rc_index = btif_rc_get_idx_by_addr(bd_addr->address);
+    if (rc_index == btif_max_rc_clients)
+    {
+        BTIF_TRACE_ERROR("-%s on unknown index = %d", __FUNCTION__);
+        return BT_STATUS_FAIL;
+    }
+    BTIF_TRACE_DEBUG("-%s on index = %d", __FUNCTION__, rc_index);
+
     memset(&(avrc_rsp.get_play_status), 0, sizeof(tAVRC_GET_PLAY_STATUS_RSP));
     avrc_rsp.get_play_status.song_len = song_len;
     avrc_rsp.get_play_status.song_pos = song_pos;
@@ -2288,7 +2691,7 @@ static bt_status_t get_play_status_rsp(btrc_play_status_t play_status, uint32_t
     avrc_rsp.get_play_status.opcode = opcode_from_pdu(AVRC_PDU_GET_PLAY_STATUS);
     avrc_rsp.get_play_status.status = AVRC_STS_NO_ERROR;
     /* Send the response */
-    SEND_METAMSG_RSP(IDX_GET_PLAY_STATUS_RSP, &avrc_rsp);
+    SEND_METAMSG_RSP(IDX_GET_PLAY_STATUS_RSP, &avrc_rsp, rc_index);
     return BT_STATUS_SUCCESS;
 }
 
@@ -2303,12 +2706,21 @@ static bt_status_t get_play_status_rsp(btrc_play_status_t play_status, uint32_t
 ** Returns          bt_status_t
 **
 ****************************************************************************/
-static bt_status_t  list_player_app_attr_rsp( uint8_t num_attr, btrc_player_attr_t *p_attrs)
+static bt_status_t  list_player_app_attr_rsp( uint8_t num_attr, btrc_player_attr_t *p_attrs, bt_bdaddr_t *bd_addr)
 {
     tAVRC_RESPONSE avrc_rsp;
     UINT32 i;
-
+    int rc_index;
     CHECK_RC_CONNECTED
+
+    rc_index = btif_rc_get_idx_by_addr(bd_addr->address);
+    if (rc_index == btif_max_rc_clients)
+    {
+        BTIF_TRACE_ERROR("-%s on unknown index = %d", __FUNCTION__);
+        return BT_STATUS_FAIL;
+    }
+    BTIF_TRACE_DEBUG("-%s on index = %d", __FUNCTION__, rc_index);
+
     memset(&(avrc_rsp.list_app_attr), 0, sizeof(tAVRC_LIST_APP_ATTR_RSP));
     if (num_attr == 0)
     {
@@ -2326,7 +2738,7 @@ static bt_status_t  list_player_app_attr_rsp( uint8_t num_attr, btrc_player_attr
     avrc_rsp.list_app_attr.pdu  = AVRC_PDU_LIST_PLAYER_APP_ATTR ;
     avrc_rsp.list_app_attr.opcode = opcode_from_pdu(AVRC_PDU_LIST_PLAYER_APP_ATTR);
     /* Send the response */
-    SEND_METAMSG_RSP(IDX_LIST_APP_ATTR_RSP, &avrc_rsp);
+    SEND_METAMSG_RSP(IDX_LIST_APP_ATTR_RSP, &avrc_rsp, rc_index);
     return BT_STATUS_SUCCESS;
 }
 
@@ -2337,12 +2749,21 @@ static bt_status_t  list_player_app_attr_rsp( uint8_t num_attr, btrc_player_attr
 ** Description      ListPlayerApplicationSettingValues (PDU ID: 0x12)
                     This method is called in response to PDU 0x12
 ************************************************************************/
-static bt_status_t  list_player_app_value_rsp( uint8_t num_val, uint8_t *value)
+static bt_status_t  list_player_app_value_rsp( uint8_t num_val, uint8_t *value, bt_bdaddr_t *bd_addr)
 {
     tAVRC_RESPONSE avrc_rsp;
     UINT32 i;
-
+    int rc_index;
     CHECK_RC_CONNECTED
+
+    rc_index = btif_rc_get_idx_by_addr(bd_addr->address);
+    if (rc_index == btif_max_rc_clients)
+    {
+        BTIF_TRACE_ERROR("-%s on unknown index = %d", __FUNCTION__);
+        return BT_STATUS_FAIL;
+    }
+    BTIF_TRACE_DEBUG("-%s on index = %d", __FUNCTION__, rc_index);
+
     memset(&(avrc_rsp.list_app_values), 0, sizeof(tAVRC_LIST_APP_VALUES_RSP));
     if ((num_val == 0) || (num_val > AVRC_MAX_APP_ATTR_SIZE))
     {
@@ -2360,7 +2781,7 @@ static bt_status_t  list_player_app_value_rsp( uint8_t num_val, uint8_t *value)
     avrc_rsp.list_app_values.pdu   = AVRC_PDU_LIST_PLAYER_APP_VALUES;
     avrc_rsp.list_app_attr.opcode  = opcode_from_pdu(AVRC_PDU_LIST_PLAYER_APP_VALUES);
     /* Send the response */
-    SEND_METAMSG_RSP(IDX_LIST_APP_VALUE_RSP, &avrc_rsp);
+    SEND_METAMSG_RSP(IDX_LIST_APP_VALUE_RSP, &avrc_rsp, rc_index);
     return BT_STATUS_SUCCESS;
 }
 
@@ -2372,13 +2793,22 @@ static bt_status_t  list_player_app_value_rsp( uint8_t num_val, uint8_t *value)
 ** Description  This methos is called in response to PDU ID 0x13
 **
 ***********************************************************************/
-static bt_status_t get_player_app_value_rsp(btrc_player_settings_t *p_vals)
+static bt_status_t get_player_app_value_rsp(btrc_player_settings_t *p_vals, bt_bdaddr_t *bd_addr)
 {
     tAVRC_RESPONSE avrc_rsp;
     UINT32 i;
     tAVRC_APP_SETTING app_sett[AVRC_MAX_APP_ATTR_SIZE];
-
+    int rc_index;
     CHECK_RC_CONNECTED
+
+    rc_index = btif_rc_get_idx_by_addr(bd_addr->address);
+    if (rc_index == btif_max_rc_clients)
+    {
+        BTIF_TRACE_ERROR("-%s on unknown index = %d", __FUNCTION__);
+        return BT_STATUS_FAIL;
+    }
+    BTIF_TRACE_DEBUG("-%s on index = %d", __FUNCTION__, rc_index);
+
     memset(&(avrc_rsp.get_cur_app_val) ,0 , sizeof(tAVRC_GET_CUR_APP_VALUE_RSP));
     avrc_rsp.get_cur_app_val.p_vals   = app_sett ;
     //Check for Error Condition
@@ -2405,7 +2835,7 @@ static bt_status_t get_player_app_value_rsp(btrc_player_settings_t *p_vals)
     }
     avrc_rsp.get_cur_app_val.pdu = AVRC_PDU_GET_CUR_PLAYER_APP_VALUE;
     avrc_rsp.get_cur_app_val.opcode = opcode_from_pdu(AVRC_PDU_GET_CUR_PLAYER_APP_VALUE);
-    SEND_METAMSG_RSP(IDX_GET_CURR_APP_VAL_RSP, &avrc_rsp);
+    SEND_METAMSG_RSP(IDX_GET_CURR_APP_VAL_RSP, &avrc_rsp, rc_index);
     return BT_STATUS_SUCCESS;
 }
 
@@ -2419,16 +2849,24 @@ static bt_status_t get_player_app_value_rsp(btrc_player_settings_t *p_vals)
 ** Return       bt_staus_t
 **
 *******************************************************************/
-static bt_status_t set_player_app_value_rsp (btrc_status_t rsp_status )
+static bt_status_t set_player_app_value_rsp (btrc_status_t rsp_status, bt_bdaddr_t *bd_addr )
 {
     tAVRC_RESPONSE avrc_rsp;
-    tAVRC_RSP    set_app_val;
+    int rc_index;
+
+    rc_index = btif_rc_get_idx_by_addr(bd_addr->address);
+    if (rc_index == btif_max_rc_clients)
+    {
+        BTIF_TRACE_ERROR("-%s on unknown index = %d", __FUNCTION__);
+        return BT_STATUS_FAIL;
+    }
+    BTIF_TRACE_DEBUG("-%s on index = %d", __FUNCTION__, rc_index);
 
     CHECK_RC_CONNECTED
     avrc_rsp.set_app_val.opcode = opcode_from_pdu(AVRC_PDU_SET_PLAYER_APP_VALUE);
     avrc_rsp.set_app_val.pdu    =  AVRC_PDU_SET_PLAYER_APP_VALUE ;
     avrc_rsp.set_app_val.status =  rsp_status ;
-    SEND_METAMSG_RSP(IDX_SET_APP_VAL_RSP, &avrc_rsp);
+    SEND_METAMSG_RSP(IDX_SET_APP_VAL_RSP, &avrc_rsp, rc_index);
     return BT_STATUS_SUCCESS;
 }
 
@@ -2441,13 +2879,23 @@ static bt_status_t set_player_app_value_rsp (btrc_status_t rsp_status )
 **
 **
 *******************************************************************/
-static bt_status_t get_player_app_attr_text_rsp(int num_attr, btrc_player_setting_text_t *p_attrs)
+static bt_status_t get_player_app_attr_text_rsp(int num_attr, btrc_player_setting_text_t *p_attrs,
+                                                bt_bdaddr_t *bd_addr)
 {
     tAVRC_RESPONSE avrc_rsp;
     tAVRC_APP_SETTING_TEXT attr_txt[AVRC_MAX_APP_ATTR_SIZE];
     int i;
-
+    int rc_index;
     CHECK_RC_CONNECTED
+
+    rc_index = btif_rc_get_idx_by_addr(bd_addr->address);
+    if (rc_index == btif_max_rc_clients)
+    {
+        BTIF_TRACE_ERROR("-%s on unknown index = %d", __FUNCTION__);
+        return BT_STATUS_FAIL;
+    }
+    BTIF_TRACE_DEBUG("-%s on index = %d", __FUNCTION__, rc_index);
+
     if (num_attr == 0)
     {
         avrc_rsp.get_app_attr_txt.status = AVRC_STS_BAD_PARAM;
@@ -2471,7 +2919,7 @@ static bt_status_t get_player_app_attr_text_rsp(int num_attr, btrc_player_settin
     avrc_rsp.get_app_attr_txt.pdu = AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT;
     avrc_rsp.get_app_attr_txt.opcode = opcode_from_pdu(AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT);
     /* Send the response */
-    SEND_METAMSG_RSP(IDX_GET_APP_ATTR_TXT_RSP, &avrc_rsp);
+    SEND_METAMSG_RSP(IDX_GET_APP_ATTR_TXT_RSP, &avrc_rsp, rc_index);
     return BT_STATUS_SUCCESS;
 }
 
@@ -2485,13 +2933,22 @@ static bt_status_t get_player_app_attr_text_rsp(int num_attr, btrc_player_settin
 ** Return        bt_status_t
 **
 *******************************************************************/
-static bt_status_t get_player_app_value_text_rsp(int num_attr, btrc_player_setting_text_t *p_attrs)
+static bt_status_t get_player_app_value_text_rsp(int num_attr, btrc_player_setting_text_t *p_attrs, bt_bdaddr_t *bd_addr)
 {
     tAVRC_RESPONSE avrc_rsp;
     tAVRC_APP_SETTING_TEXT attr_txt[AVRC_MAX_APP_ATTR_SIZE];
     int i;
-
+    int rc_index;
     CHECK_RC_CONNECTED
+
+    rc_index = btif_rc_get_idx_by_addr(bd_addr->address);
+    if (rc_index == btif_max_rc_clients)
+    {
+        BTIF_TRACE_ERROR("-%s on unknown index = %d", __FUNCTION__);
+        return BT_STATUS_FAIL;
+    }
+    BTIF_TRACE_DEBUG("- %s on index = %d", __FUNCTION__, rc_index);
+
     if (num_attr == 0)
     {
         avrc_rsp.get_app_val_txt.status = AVRC_STS_BAD_PARAM;
@@ -2515,7 +2972,7 @@ static bt_status_t get_player_app_value_text_rsp(int num_attr, btrc_player_setti
     avrc_rsp.get_app_val_txt.pdu = AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT;
     avrc_rsp.get_app_val_txt.opcode = opcode_from_pdu(AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT);
     /* Send the response */
-    SEND_METAMSG_RSP(IDX_GET_APP_VAL_TXT_RSP, &avrc_rsp);
+    SEND_METAMSG_RSP(IDX_GET_APP_VAL_TXT_RSP, &avrc_rsp, rc_index);
     return BT_STATUS_SUCCESS;
 }
 
@@ -2529,12 +2986,22 @@ static bt_status_t get_player_app_value_text_rsp(int num_attr, btrc_player_setti
 ** Returns          bt_status_t
 **
 ***************************************************************************/
-static bt_status_t get_element_attr_rsp(uint8_t num_attr, btrc_element_attr_val_t *p_attrs)
+static bt_status_t get_element_attr_rsp(uint8_t num_attr, btrc_element_attr_val_t *p_attrs, bt_bdaddr_t *bd_addr)
 {
     tAVRC_RESPONSE avrc_rsp;
     UINT32 i;
     tAVRC_ATTR_ENTRY element_attrs[BTRC_MAX_ELEM_ATTR_SIZE];
+    int rc_index;
     CHECK_RC_CONNECTED
+
+    rc_index = btif_rc_get_idx_by_addr(bd_addr->address);
+    if (rc_index == btif_max_rc_clients)
+    {
+        BTIF_TRACE_ERROR("-%s on unknown index = %d", __FUNCTION__);
+        return BT_STATUS_FAIL;
+    }
+    BTIF_TRACE_DEBUG("- %s on index = %d", __FUNCTION__, rc_index);
+
     memset(element_attrs, 0, sizeof(tAVRC_ATTR_ENTRY) * num_attr);
 
     if (num_attr == 0)
@@ -2561,7 +3028,7 @@ static bt_status_t get_element_attr_rsp(uint8_t num_attr, btrc_element_attr_val_
     avrc_rsp.get_elem_attrs.pdu = AVRC_PDU_GET_ELEMENT_ATTR;
     avrc_rsp.get_elem_attrs.opcode = opcode_from_pdu(AVRC_PDU_GET_ELEMENT_ATTR);
     /* Send the response */
-    SEND_METAMSG_RSP(IDX_GET_ELEMENT_ATTR_RSP, &avrc_rsp);
+    SEND_METAMSG_RSP(IDX_GET_ELEMENT_ATTR_RSP, &avrc_rsp, rc_index);
     return BT_STATUS_SUCCESS;
 }
 
@@ -2576,12 +3043,21 @@ static bt_status_t get_element_attr_rsp(uint8_t num_attr, btrc_element_attr_val_
 **
 ***************************************************************************/
 static bt_status_t register_notification_rsp(btrc_event_id_t event_id,
-    btrc_notification_type_t type, btrc_register_notification_t *p_param)
+    btrc_notification_type_t type, btrc_register_notification_t *p_param, bt_bdaddr_t *bd_addr)
 {
     tAVRC_RESPONSE avrc_rsp;
+    int index = btif_rc_get_idx_by_addr(bd_addr->address);
     CHECK_RC_CONNECTED
+
+    if (index == btif_max_rc_clients)
+    {
+        BTIF_TRACE_ERROR("%s: on unknown index", __FUNCTION__);
+        return BT_STATUS_FAIL;
+    }
+
+
     BTIF_TRACE_IMP("## %s ## event_id:%s", __FUNCTION__, dump_rc_notification_event_id(event_id));
-    if (btif_rc_cb.rc_notif[event_id-1].bNotify == FALSE)
+    if (btif_rc_cb[index].rc_notif[event_id-1].bNotify == FALSE)
     {
         BTIF_TRACE_ERROR("Avrcp Event id not registered: event_id = %x", event_id);
         return BT_STATUS_NOT_READY;
@@ -2593,6 +3069,10 @@ static bt_status_t register_notification_rsp(btrc_event_id_t event_id,
     {
         case BTRC_EVT_PLAY_STATUS_CHANGED:
             avrc_rsp.reg_notif.param.play_status = p_param->play_status;
+            /* Clear remote suspend flag, as remote device issues
+             * suspend within 3s after pause, and DUT within 3s
+             * initiates Play
+            */
             if (avrc_rsp.reg_notif.param.play_status == PLAY_STATUS_PLAYING)
                 btif_av_clear_remote_suspend_flag();
             break;
@@ -2643,7 +3123,7 @@ static bt_status_t register_notification_rsp(btrc_event_id_t event_id,
     }
 
     /* Send the response. */
-    send_metamsg_rsp(btif_rc_cb.rc_handle, btif_rc_cb.rc_notif[event_id-1].label,
+    send_metamsg_rsp(btif_rc_cb[index].rc_handle, btif_rc_cb[index].rc_notif[event_id-1].label,
         ((type == BTRC_NOTIFICATION_TYPE_INTERIM)?AVRC_CMD_NOTIF:AVRC_RSP_CHANGED), &avrc_rsp);
     return BT_STATUS_SUCCESS;
 }
@@ -2658,14 +3138,22 @@ static bt_status_t register_notification_rsp(btrc_event_id_t event_id,
 ** Returns          bt_status_t
 **
 ***************************************************************************/
-static bt_status_t get_folderitem_rsp(btrc_folder_list_entries_t *rsp)
+static bt_status_t get_folderitem_rsp(btrc_folder_list_entries_t *rsp, bt_bdaddr_t *bd_addr)
 {
     tAVRC_RESPONSE avrc_rsp;
-    CHECK_RC_CONNECTED
     tAVRC_ITEM item[MAX_FOLDER_RSP_SUPPORT]; //Number of players that could be supported
     UINT8  index, i, xx, media_attr_cnt;
     UINT8 *p_conversion;
+    int rc_index;
+    CHECK_RC_CONNECTED
+
+    rc_index = btif_rc_get_idx_by_addr(bd_addr->address);
 
+    if (rc_index == btif_max_rc_clients)
+    {
+        BTIF_TRACE_ERROR("%s: on unknown index", __FUNCTION__);
+        return BT_STATUS_FAIL;
+    }
     BTIF_TRACE_EVENT("%s() AVRC_PDU_GET_FOLDER_ITEMS", __FUNCTION__);
     index                             = IDX_GET_FOLDER_ITEMS_RSP ;
     avrc_rsp.get_items.pdu            = AVRC_PDU_GET_FOLDER_ITEMS;
@@ -2732,7 +3220,7 @@ static bt_status_t get_folderitem_rsp(btrc_folder_list_entries_t *rsp)
                 if (media_attr_cnt > 0)
                 {
                     if ((item[i].u.media.p_attr_list = \
-                    (tAVRC_ATTR_ENTRY *)GKI_getbuf((UINT16)(media_attr_cnt * \
+                    (tAVRC_ATTR_ENTRY *)osi_malloc((UINT16)(media_attr_cnt * \
                                                         sizeof(tAVRC_ATTR_ENTRY)))) != NULL)
                     {
                         for (xx = 0; xx < media_attr_cnt; xx++)
@@ -2770,7 +3258,7 @@ static bt_status_t get_folderitem_rsp(btrc_folder_list_entries_t *rsp)
         avrc_rsp.get_items.status = AVRC_STS_BAD_RANGE;
     }
     avrc_rsp.get_items.p_item_list = item;
-    app_sendbrowsemsg(IDX_GET_FOLDER_ITEMS_RSP ,&avrc_rsp);
+    app_sendbrowsemsg(IDX_GET_FOLDER_ITEMS_RSP ,&avrc_rsp, rc_index);
     BTIF_TRACE_ERROR("free attr list");
     for (i=0; (i < rsp->item_count && i < MAX_FOLDER_RSP_SUPPORT) ; ++i)
     {
@@ -2778,7 +3266,7 @@ static bt_status_t get_folderitem_rsp(btrc_folder_list_entries_t *rsp)
         {
             if (rsp->p_item_list[i].u.media.attr_count > 0)
             {
-                GKI_freebuf(item[i].u.media.p_attr_list);
+                osi_free_and_reset((void**)&item[i].u.media.p_attr_list);
             }
         }
     }
@@ -2795,15 +3283,24 @@ static bt_status_t get_folderitem_rsp(btrc_folder_list_entries_t *rsp)
 **
 *********************************************************************/
 
-static bt_status_t set_addrplayer_rsp(btrc_status_t status_code)
+static bt_status_t set_addrplayer_rsp(btrc_status_t status_code, bt_bdaddr_t *bd_addr)
 {
     tAVRC_RESPONSE avrc_rsp;
+    int rc_index;
     CHECK_RC_CONNECTED
+    rc_index = btif_rc_get_idx_by_addr(bd_addr->address);
+
+    if (rc_index == btif_max_rc_clients)
+    {
+        BTIF_TRACE_ERROR("%s: on unknown index", __FUNCTION__);
+        return BT_STATUS_FAIL;
+    }
+    BTIF_TRACE_DEBUG("- %s on index = %d", __FUNCTION__, rc_index);
     avrc_rsp.addr_player.status = status_code;
     avrc_rsp.addr_player.opcode = opcode_from_pdu(AVRC_PDU_SET_ADDRESSED_PLAYER);
     avrc_rsp.addr_player.pdu    = AVRC_PDU_SET_ADDRESSED_PLAYER;
     /* Send the response */
-    SEND_METAMSG_RSP(IDX_SET_ADDRESS_PLAYER_RSP, &avrc_rsp);
+    SEND_METAMSG_RSP(IDX_SET_ADDRESS_PLAYER_RSP, &avrc_rsp, rc_index);
     return BT_STATUS_SUCCESS;
 }
 
@@ -2817,11 +3314,19 @@ static bt_status_t set_addrplayer_rsp(btrc_status_t status_code)
 **
 *********************************************************************/
 
-static bt_status_t set_browseplayer_rsp(btrc_set_browsed_player_rsp_t *p_param)
+static bt_status_t set_browseplayer_rsp(btrc_set_browsed_player_rsp_t *p_param, bt_bdaddr_t *bd_addr)
 {
     tAVRC_RESPONSE avrc_rsp;
-
+    int rc_index = btif_rc_get_idx_by_addr(bd_addr->address);
     CHECK_RC_CONNECTED
+
+    if (rc_index == btif_max_rc_clients)
+    {
+        BTIF_TRACE_ERROR("%s: on unknown index", __FUNCTION__);
+        return BT_STATUS_FAIL;
+    }
+    BTIF_TRACE_DEBUG("- %s on index = %d", __FUNCTION__, rc_index);
+
     avrc_rsp.br_player.pdu = AVRC_PDU_SET_BROWSED_PLAYER;
     avrc_rsp.br_player.folder_depth = p_param->folder_depth;
     avrc_rsp.br_player.charset_id = p_param->charset_id;
@@ -2831,7 +3336,7 @@ static bt_status_t set_browseplayer_rsp(btrc_set_browsed_player_rsp_t *p_param)
     avrc_rsp.br_player.uid_counter = p_param->uid_counter;
     avrc_rsp.br_player.p_folders = (tAVRC_NAME*)p_param->p_folders;
     /* Send the response */
-    SEND_BROWSEMSG_RSP(IDX_SET_BROWSE_PLAYER_RSP, &avrc_rsp);
+    SEND_BROWSEMSG_RSP(IDX_SET_BROWSE_PLAYER_RSP, &avrc_rsp, rc_index);
     return BT_STATUS_SUCCESS;
 }
 
@@ -2845,17 +3350,27 @@ static bt_status_t set_browseplayer_rsp(btrc_set_browsed_player_rsp_t *p_param)
 **
 *********************************************************************/
 
-static bt_status_t changepath_rsp(uint8_t status_code, uint32_t item_count)
+static bt_status_t changepath_rsp(uint8_t status_code, uint32_t item_count, bt_bdaddr_t *bd_addr)
 {
     tAVRC_RESPONSE avrc_rsp;
-
+    int rc_index;
     CHECK_RC_CONNECTED
+
+    rc_index = btif_rc_get_idx_by_addr(bd_addr->address);
+
+    if (rc_index == btif_max_rc_clients)
+    {
+        BTIF_TRACE_ERROR("%s: on unknown index", __FUNCTION__);
+        return BT_STATUS_FAIL;
+    }
+    BTIF_TRACE_DEBUG("- %s on index = %d", __FUNCTION__, rc_index);
+
     avrc_rsp.chg_path.num_items = item_count;
     avrc_rsp.chg_path.opcode = opcode_from_pdu(AVRC_PDU_CHANGE_PATH);
     avrc_rsp.chg_path.pdu = AVRC_PDU_CHANGE_PATH;
     avrc_rsp.chg_path.status = status_code;
     /* Send the response */
-    SEND_BROWSEMSG_RSP(IDX_CHANGE_PATH_RSP, &avrc_rsp);
+    SEND_BROWSEMSG_RSP(IDX_CHANGE_PATH_RSP, &avrc_rsp, rc_index);
     return BT_STATUS_SUCCESS;
 }
 
@@ -2869,16 +3384,26 @@ static bt_status_t changepath_rsp(uint8_t status_code, uint32_t item_count)
 **
 *********************************************************************/
 
-static bt_status_t playitem_rsp(uint8_t status_code)
+static bt_status_t playitem_rsp(uint8_t status_code, bt_bdaddr_t *bd_addr)
 {
     tAVRC_RESPONSE avrc_rsp;
-
+    int rc_index;
     CHECK_RC_CONNECTED
+
+    rc_index = btif_rc_get_idx_by_addr(bd_addr->address);
+    if (rc_index == btif_max_rc_clients)
+    {
+        BTIF_TRACE_ERROR("%s: on unknown index", __FUNCTION__);
+        return BT_STATUS_FAIL;
+    }
+    BTIF_TRACE_DEBUG("- %s on index = %d", __FUNCTION__, rc_index);
+
     avrc_rsp.play_item.status = status_code;
     avrc_rsp.play_item.opcode = opcode_from_pdu(AVRC_PDU_PLAY_ITEM);
     avrc_rsp.play_item.pdu    = AVRC_PDU_PLAY_ITEM;
     /* Send the response */
-    SEND_METAMSG_RSP(IDX_PLAY_ITEM_RSP, &avrc_rsp);
+    SEND_METAMSG_RSP(IDX_PLAY_ITEM_RSP, &avrc_rsp,rc_index);
+
     return BT_STATUS_SUCCESS;
 }
 
@@ -2892,13 +3417,20 @@ static bt_status_t playitem_rsp(uint8_t status_code)
 **
 *********************************************************************/
 
-static bt_status_t get_itemattr_rsp(uint8_t num_attr, btrc_element_attr_val_t *p_attrs)
+static bt_status_t get_itemattr_rsp(uint8_t num_attr, btrc_element_attr_val_t *p_attrs, bt_bdaddr_t *bd_addr)
+
 {
     tAVRC_RESPONSE avrc_rsp;
     UINT32 i;
-    uint8_t j;
     tAVRC_ATTR_ENTRY element_attrs[BTRC_MAX_ELEM_ATTR_SIZE];
+    int rc_index = btif_rc_get_idx_by_addr(bd_addr->address);
 
+    if (rc_index == btif_max_rc_clients)
+    {
+        BTIF_TRACE_ERROR("%s: on unknown index", __FUNCTION__);
+        return BT_STATUS_FAIL;
+    }
+    BTIF_TRACE_DEBUG("- %s on index = %d", __FUNCTION__, rc_index);
     CHECK_RC_CONNECTED
     memset(element_attrs, 0, sizeof(tAVRC_ATTR_ENTRY) * num_attr);
 
@@ -2926,10 +3458,91 @@ static bt_status_t get_itemattr_rsp(uint8_t num_attr, btrc_element_attr_val_t *p
     avrc_rsp.get_attrs.pdu = AVRC_PDU_GET_ITEM_ATTRIBUTES;
     avrc_rsp.get_attrs.opcode = opcode_from_pdu(AVRC_PDU_GET_ITEM_ATTRIBUTES);
     /* Send the response */
-    SEND_BROWSEMSG_RSP(IDX_GET_ITEM_ATTR_RSP, &avrc_rsp);
+    SEND_BROWSEMSG_RSP(IDX_GET_ITEM_ATTR_RSP, &avrc_rsp, rc_index);
     return BT_STATUS_SUCCESS;
 }
 
+/**********************************************************************
+**
+** Function        is_device_active_in_handoff
+**
+** Description     Check if this is the active device during hand-off
+**                 If the multicast is disabled when connected to more
+**                 than one device and the active playing device is
+**                 different or device to start playback is different
+**                 then fail this condition.
+** Return          BT_STATUS_SUCCESS if active BT_STATUS_FAIL otherwise
+**
+*********************************************************************/
+static bt_status_t is_device_active_in_handoff(bt_bdaddr_t *bd_addr)
+{
+    BD_ADDR playing_device;
+    int rc_index;
+    UINT16 connected_devices, playing_devices;
+
+    rc_index = btif_rc_get_idx_by_addr(bd_addr->address);
+    if(rc_index >= btif_max_rc_clients)
+    {
+        return BT_STATUS_FAIL;
+    }
+    connected_devices = btif_av_get_num_connected_devices();
+    playing_devices = btif_av_get_num_playing_devices();
+
+    if((connected_devices < btif_max_rc_clients) || (playing_devices > 1))
+    {
+        return BT_STATUS_SUCCESS;
+    }
+
+    if((connected_devices > 1) && (playing_devices == 1))
+    {
+        /* One playing device, check the active device */
+        btif_get_latest_playing_device(playing_device);
+        if (bdcmp(bd_addr->address, playing_device) == 0)
+        {
+            return BT_STATUS_SUCCESS;
+        }
+        else
+        {
+            return BT_STATUS_FAIL;
+        }
+    }
+    else if (playing_devices == 0)
+    {
+        /* No Playing device, find the next playing device
+         * Play initiated from remote
+         */
+        if (btif_rc_cb[rc_index].rc_play_processed == TRUE)
+        {
+            return BT_STATUS_SUCCESS;
+        }
+        else if (btif_av_is_current_device(bd_addr->address) == TRUE)
+        {
+            /* Play initiated locally. check the current device and
+             * make sure play is not initiated from other remote
+             */
+            BD_ADDR rc_play_device = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+            btif_rc_get_playing_device(rc_play_device);
+            if(bdcmp(bd_addr->address, bd_addr_null) != 0)
+            {
+                /* some other playing device */
+                return BT_STATUS_FAIL;
+            }
+            return BT_STATUS_SUCCESS;
+        }
+        else
+        {
+            BTIF_TRACE_ERROR("%s no playing or current device ", __FUNCTION__);
+            return BT_STATUS_FAIL;
+        }
+    }
+    else
+    {
+        BTIF_TRACE_ERROR("%s unchecked state: connected devices: %d playing devices: %d",
+            __FUNCTION__, connected_devices, playing_devices);
+        return BT_STATUS_SUCCESS;
+    }
+}
+
 /***************************************************************************
 **
 ** Function         set_volume
@@ -2944,22 +3557,29 @@ static bt_status_t get_itemattr_rsp(uint8_t num_attr, btrc_element_attr_val_t *p
 ** Returns          bt_status_t
 **
 ***************************************************************************/
-static bt_status_t set_volume(uint8_t volume)
+static bt_status_t set_volume(uint8_t volume, bt_bdaddr_t *bd_addr)
 {
-    BTIF_TRACE_DEBUG("%s", __FUNCTION__);
+    int index = btif_rc_get_idx_by_addr(bd_addr->address);
+
+    if (index == btif_max_rc_clients)
+    {
+        BTIF_TRACE_ERROR("%s: on unknown index", __FUNCTION__);
+        return BT_STATUS_FAIL;
+    }
+    BTIF_TRACE_DEBUG("- %s on index = %d", __FUNCTION__, index);
     CHECK_RC_CONNECTED
     tAVRC_STS status = BT_STATUS_UNSUPPORTED;
     rc_transaction_t *p_transaction=NULL;
 
-    if (btif_rc_cb.rc_volume==volume)
+    if(btif_rc_cb[index].rc_volume==volume)
     {
         status=BT_STATUS_DONE;
         BTIF_TRACE_ERROR("%s: volume value already set earlier: 0x%02x",__FUNCTION__, volume);
         return status;
     }
 
-    if ((btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG) &&
-        (btif_rc_cb.rc_features & BTA_AV_FEAT_ADV_CTRL))
+    if ((btif_rc_cb[index].rc_features & BTA_AV_FEAT_RCTG) &&
+        (btif_rc_cb[index].rc_features & BTA_AV_FEAT_ADV_CTRL))
     {
         tAVRC_COMMAND avrc_cmd = {0};
         BT_HDR *p_msg = NULL;
@@ -2977,7 +3597,7 @@ static bt_status_t set_volume(uint8_t volume)
             {
                 BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
                                    __FUNCTION__,p_transaction->lbl);
-                BTA_AvMetaCmd(btif_rc_cb.rc_handle,p_transaction->lbl, AVRC_CMD_CTRL, p_msg);
+                BTA_AvMetaCmd(btif_rc_cb[index].rc_handle,p_transaction->lbl, AVRC_CMD_CTRL, p_msg);
                 status =  BT_STATUS_SUCCESS;
             }
             else
@@ -3011,13 +3631,12 @@ static bt_status_t set_volume(uint8_t volume)
 **
 ***************************************************************************/
 
-static void register_volumechange (UINT8 lbl)
+static void register_volumechange (UINT8 lbl, int index)
 {
     tAVRC_COMMAND avrc_cmd = {0};
     BT_HDR *p_msg = NULL;
     tAVRC_STS BldResp=AVRC_STS_BAD_CMD;
     rc_transaction_t *p_transaction=NULL;
-
     BTIF_TRACE_DEBUG("%s called with label:%d",__FUNCTION__,lbl);
 
     avrc_cmd.cmd.opcode=0x00;
@@ -3030,7 +3649,7 @@ static void register_volumechange (UINT8 lbl)
     if (AVRC_STS_NO_ERROR == BldResp && p_msg) {
         p_transaction = get_transaction_by_lbl(lbl);
         if (p_transaction != NULL) {
-            BTA_AvMetaCmd(btif_rc_cb.rc_handle, p_transaction->lbl,
+            BTA_AvMetaCmd(btif_rc_cb[index].rc_handle, p_transaction->lbl,
                           AVRC_CMD_NOTIF, p_msg);
             BTIF_TRACE_DEBUG("%s:BTA_AvMetaCmd called", __func__);
          } else {
@@ -3054,11 +3673,19 @@ static void register_volumechange (UINT8 lbl)
 ***************************************************************************/
 static void handle_rc_metamsg_rsp(tBTA_AV_META_MSG *pmeta_msg)
 {
+    UINT8 index;  /*For RC it is zero*/
     tAVRC_RESPONSE    avrc_response = {0};
     UINT8             scratch_buf[512] = {0};
     tAVRC_STS status = BT_STATUS_UNSUPPORTED;
 
-    if (AVRC_OP_VENDOR==pmeta_msg->p_msg->hdr.opcode &&(AVRC_RSP_CHANGED==pmeta_msg->code
+    index = btif_rc_get_idx_by_rc_handle(pmeta_msg->rc_handle);
+    if (index == btif_max_rc_clients)
+    {
+        BTIF_TRACE_ERROR("%s: on unknown index", __FUNCTION__);
+        return;
+    }
+
+    if(AVRC_OP_VENDOR==pmeta_msg->p_msg->hdr.opcode &&(AVRC_RSP_CHANGED==pmeta_msg->code
       || AVRC_RSP_INTERIM==pmeta_msg->code || AVRC_RSP_ACCEPT==pmeta_msg->code
       || AVRC_RSP_REJ==pmeta_msg->code || AVRC_RSP_NOT_IMPL==pmeta_msg->code))
     {
@@ -3071,10 +3698,10 @@ static void handle_rc_metamsg_rsp(tBTA_AV_META_MSG *pmeta_msg)
         {
             if (AVRC_PDU_REGISTER_NOTIFICATION==avrc_response.rsp.pdu
                 && AVRC_EVT_VOLUME_CHANGE==avrc_response.reg_notif.event_id
-                && btif_rc_cb.rc_vol_label==pmeta_msg->label)
+                && btif_rc_cb[index].rc_vol_label==pmeta_msg->label)
             {
-                btif_rc_cb.rc_vol_label=MAX_LABEL;
-                release_transaction(btif_rc_cb.rc_vol_label);
+                btif_rc_cb[index].rc_vol_label=MAX_LABEL;
+                release_transaction(btif_rc_cb[index].rc_vol_label);
             }
             else if (AVRC_PDU_SET_ABSOLUTE_VOLUME==avrc_response.rsp.pdu)
             {
@@ -3084,7 +3711,7 @@ static void handle_rc_metamsg_rsp(tBTA_AV_META_MSG *pmeta_msg)
         }
         else if (AVRC_PDU_REGISTER_NOTIFICATION==avrc_response.rsp.pdu
             && AVRC_EVT_VOLUME_CHANGE==avrc_response.reg_notif.event_id
-            && btif_rc_cb.rc_vol_label!=pmeta_msg->label)
+            && btif_rc_cb[index].rc_vol_label!=pmeta_msg->label)
             {
                 // Just discard the message, if the device sends back with an incorrect label
                 BTIF_TRACE_DEBUG("%s:Discarding register notfn in rsp.code: %d and label %d",
@@ -3105,7 +3732,7 @@ static void handle_rc_metamsg_rsp(tBTA_AV_META_MSG *pmeta_msg)
      {
          /* re-register for volume change notification */
          // Do not re-register for rejected case, as it might get into endless loop
-         register_volumechange(btif_rc_cb.rc_vol_label);
+         register_volumechange(btif_rc_cb[index].rc_vol_label, index);
      }
      else if (AVRC_PDU_SET_ABSOLUTE_VOLUME==avrc_response.rsp.pdu)
      {
@@ -3116,7 +3743,7 @@ static void handle_rc_metamsg_rsp(tBTA_AV_META_MSG *pmeta_msg)
      BTIF_TRACE_EVENT("%s: Passing received metamsg response to app. pdu: %s",
              __FUNCTION__, dump_rc_pdu(avrc_response.pdu));
      btif_rc_upstreams_rsp_evt((uint16_t)avrc_response.rsp.pdu, &avrc_response, pmeta_msg->code,
-                                pmeta_msg->label);
+                                pmeta_msg->label, index);
 }
 #endif
 
@@ -3166,7 +3793,7 @@ bool iterate_supported_event_list_for_timeout(void *data, void *cb_data)
 
     if (p_event->label == label)
     {
-        list_remove(btif_rc_cb.rc_supported_event_list, p_event);
+        list_remove(btif_rc_cb[0].rc_supported_event_list, p_event);
         return false;
     }
     return true;
@@ -3185,14 +3812,14 @@ bool iterate_supported_event_list_for_timeout(void *data, void *cb_data)
 static void rc_notification_interim_timout (UINT8 label)
 {
     list_node_t *node;
-    if (btif_rc_cb.rc_supported_event_list == NULL)
+    if (btif_rc_cb[0].rc_supported_event_list == NULL)
         return;
-    list_foreach(btif_rc_cb.rc_supported_event_list,
+    list_foreach(btif_rc_cb[0].rc_supported_event_list,
                      iterate_supported_event_list_for_timeout, &label);
     /* Timeout happened for interim response for the registered event,
      * check if there are any pending for registration
      */
-    node = list_begin(btif_rc_cb.rc_supported_event_list);
+    node = list_begin(btif_rc_cb[0].rc_supported_event_list);
     while (node != NULL)
     {
         btif_rc_supported_event_t *p_event;
@@ -3227,7 +3854,7 @@ static void btif_rc_status_cmd_timeout_handler(UNUSED_ATTR uint16_t event,
 
     p_context = (btif_rc_timer_context_t *)data;
     memset(&meta_msg, 0, sizeof(tBTA_AV_META_MSG));
-    meta_msg.rc_handle = btif_rc_cb.rc_handle;
+    meta_msg.rc_handle = btif_rc_cb[0].rc_handle;
 
     switch (p_context->rc_status_cmd.pdu_id) {
     case AVRC_PDU_REGISTER_NOTIFICATION:
@@ -3312,7 +3939,7 @@ static void btif_rc_control_cmd_timeout_handler(UNUSED_ATTR uint16_t event,
     tBTA_AV_META_MSG    meta_msg;
 
     memset(&meta_msg, 0, sizeof(tBTA_AV_META_MSG));
-    meta_msg.rc_handle = btif_rc_cb.rc_handle;
+    meta_msg.rc_handle = btif_rc_cb[0].rc_handle;
 
     switch (p_context->rc_control_cmd.pdu_id) {
     case AVRC_PDU_SET_PLAYER_APP_VALUE:
@@ -3384,12 +4011,12 @@ static void btif_rc_play_status_timer_timeout(UNUSED_ATTR void *data)
 static void rc_start_play_status_timer(void)
 {
     /* Start the Play status timer only if it is not started */
-    if (!alarm_is_scheduled(btif_rc_cb.rc_play_status_timer)) {
-        if (btif_rc_cb.rc_play_status_timer == NULL) {
-            btif_rc_cb.rc_play_status_timer =
+    if (!alarm_is_scheduled(btif_rc_cb[0].rc_play_status_timer)) {
+        if (btif_rc_cb[0].rc_play_status_timer == NULL) {
+            btif_rc_cb[0].rc_play_status_timer =
                 alarm_new("btif_rc.rc_play_status_timer");
         }
-        alarm_set_on_queue(btif_rc_cb.rc_play_status_timer,
+        alarm_set_on_queue(btif_rc_cb[0].rc_play_status_timer,
                            BTIF_TIMEOUT_RC_INTERIM_RSP_MS,
                            btif_rc_play_status_timer_timeout, NULL,
                            btu_general_alarm_queue);
@@ -3406,8 +4033,8 @@ static void rc_start_play_status_timer(void)
 ***************************************************************************/
 void rc_stop_play_status_timer()
 {
-    if (btif_rc_cb.rc_play_status_timer != NULL)
-        alarm_cancel(btif_rc_cb.rc_play_status_timer);
+    if (btif_rc_cb[0].rc_play_status_timer != NULL)
+        alarm_cancel(btif_rc_cb[0].rc_play_status_timer);
 }
 
 /***************************************************************************
@@ -3512,7 +4139,7 @@ static void handle_get_capability_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_G
         btif_rc_supported_event_t *p_event;
 
         /* Todo: Check if list can be active when we hit here */
-        btif_rc_cb.rc_supported_event_list = list_new(osi_free);
+        btif_rc_cb[0].rc_supported_event_list = list_new(osi_free);
         for (xx = 0; xx < p_rsp->count; xx++)
         {
             /* Skip registering for Play position change notification */
@@ -3523,15 +4150,15 @@ static void handle_get_capability_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_G
                 p_event = (btif_rc_supported_event_t *)osi_malloc(sizeof(btif_rc_supported_event_t));
                 p_event->event_id = p_rsp->param.event_id[xx];
                 p_event->status = eNOT_REGISTERED;
-                list_append(btif_rc_cb.rc_supported_event_list, p_event);
+                list_append(btif_rc_cb[0].rc_supported_event_list, p_event);
             }
         }
-        if (list_is_empty(btif_rc_cb.rc_supported_event_list))
+        if (list_is_empty(btif_rc_cb[0].rc_supported_event_list))
         {
             BTIF_TRACE_EVENT(" Supported event list Empty, returning");
             return;
         }
-        p_event = list_front(btif_rc_cb.rc_supported_event_list);
+        p_event = list_front(btif_rc_cb[0].rc_supported_event_list);
         if (p_event != NULL)
         {
             register_for_event_notification(p_event);
@@ -3595,7 +4222,7 @@ static void handle_notification_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_REG
         };
 
 
-    bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
+    bdcpy(rc_addr.address, btif_rc_cb[0].rc_addr);
 
     if (pmeta_msg->code == AVRC_RSP_INTERIM)
     {
@@ -3630,7 +4257,7 @@ static void handle_notification_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_REG
                     /* Update the UID for current track
                      * Attributes will be fetched after the AVRCP procedure
                      */
-                    BE_STREAM_TO_UINT64(btif_rc_cb.rc_playing_uid, p_data);
+                    BE_STREAM_TO_UINT64(btif_rc_cb[0].rc_playing_uid, p_data);
                 }
                 break;
 
@@ -3659,11 +4286,11 @@ static void handle_notification_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_REG
                     p_rsp->event_id);
                 return;
         }
-        list_foreach(btif_rc_cb.rc_supported_event_list,
+        list_foreach(btif_rc_cb[0].rc_supported_event_list,
                 iterate_supported_event_list_for_interim_rsp,
                 &p_rsp->event_id);
 
-        node = list_begin(btif_rc_cb.rc_supported_event_list);
+        node = list_begin(btif_rc_cb[0].rc_supported_event_list);
         while (node != NULL)
         {
             p_event = (btif_rc_supported_event_t *)list_node(node);
@@ -3676,13 +4303,13 @@ static void handle_notification_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_REG
             p_event = NULL;
         }
         /* Registered for all events, we can request application settings */
-        if ((p_event == NULL) && (btif_rc_cb.rc_app_settings.query_started == false))
+        if ((p_event == NULL) && (btif_rc_cb[0].rc_app_settings.query_started == false))
         {
             /* we need to do this only if remote TG supports
              * player application settings
              */
-            btif_rc_cb.rc_app_settings.query_started = TRUE;
-            if (btif_rc_cb.rc_features & BTA_AV_FEAT_APP_SETTING)
+            btif_rc_cb[0].rc_app_settings.query_started = TRUE;
+            if (btif_rc_cb[0].rc_features & BTA_AV_FEAT_APP_SETTING)
             {
                 list_player_app_setting_attrib_cmd();
             }
@@ -3701,7 +4328,7 @@ static void handle_notification_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_REG
         BTIF_TRACE_DEBUG("%s Notification completed : 0x%2X ", __FUNCTION__,
             p_rsp->event_id);
 
-        node = list_begin(btif_rc_cb.rc_supported_event_list);
+        node = list_begin(btif_rc_cb[0].rc_supported_event_list);
         while (node != NULL)
         {
             p_event = (btif_rc_supported_event_t *)list_node(node);
@@ -3738,7 +4365,7 @@ static void handle_notification_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_REG
                     break;
                 }
                 UINT8 *p_data = p_rsp->param.track;
-                BE_STREAM_TO_UINT64(btif_rc_cb.rc_playing_uid, p_data);
+                BE_STREAM_TO_UINT64(btif_rc_cb[0].rc_playing_uid, p_data);
                 get_element_attribute_cmd (AVRC_MAX_NUM_MEDIA_ATTR_ID, attr_list);
                 break;
 
@@ -3810,23 +4437,23 @@ static void handle_app_attr_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_LIST_AP
 
         if (p_rsp->attrs[xx] > AVRC_PLAYER_SETTING_LOW_MENU_EXT)
         {
-            st_index = btif_rc_cb.rc_app_settings.num_ext_attrs;
-            btif_rc_cb.rc_app_settings.ext_attrs[st_index].attr_id = p_rsp->attrs[xx];
-            btif_rc_cb.rc_app_settings.num_ext_attrs++;
+            st_index = btif_rc_cb[0].rc_app_settings.num_ext_attrs;
+            btif_rc_cb[0].rc_app_settings.ext_attrs[st_index].attr_id = p_rsp->attrs[xx];
+            btif_rc_cb[0].rc_app_settings.num_ext_attrs++;
         }
         else
         {
-            st_index = btif_rc_cb.rc_app_settings.num_attrs;
-            btif_rc_cb.rc_app_settings.attrs[st_index].attr_id = p_rsp->attrs[xx];
-            btif_rc_cb.rc_app_settings.num_attrs++;
+            st_index = btif_rc_cb[0].rc_app_settings.num_attrs;
+            btif_rc_cb[0].rc_app_settings.attrs[st_index].attr_id = p_rsp->attrs[xx];
+            btif_rc_cb[0].rc_app_settings.num_attrs++;
         }
     }
-    btif_rc_cb.rc_app_settings.attr_index = 0;
-    btif_rc_cb.rc_app_settings.ext_attr_index = 0;
-    btif_rc_cb.rc_app_settings.ext_val_index = 0;
+    btif_rc_cb[0].rc_app_settings.attr_index = 0;
+    btif_rc_cb[0].rc_app_settings.ext_attr_index = 0;
+    btif_rc_cb[0].rc_app_settings.ext_val_index = 0;
     if (p_rsp->num_attr)
     {
-        list_player_app_setting_value_cmd (btif_rc_cb.rc_app_settings.attrs[0].attr_id);
+        list_player_app_setting_value_cmd (btif_rc_cb[0].rc_app_settings.attrs[0].attr_id);
     }
     else
     {
@@ -3864,8 +4491,8 @@ static void handle_app_val_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_LIST_APP
         return;
     }
 
-    p_app_settings = &btif_rc_cb.rc_app_settings;
-    bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
+    p_app_settings = &btif_rc_cb[0].rc_app_settings;
+    bdcpy(rc_addr.address, btif_rc_cb[0].rc_addr);
 
     if (p_app_settings->attr_index < p_app_settings->num_attrs)
     {
@@ -3939,7 +4566,7 @@ static void handle_app_cur_val_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET_
         return;
     }
 
-    bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
+    bdcpy(rc_addr.address, btif_rc_cb[0].rc_addr);
 
     app_settings.num_attr = p_rsp->num_val;
     for (xx = 0; xx < app_settings.num_attr; xx++)
@@ -3974,8 +4601,8 @@ static void handle_app_attr_txt_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_GET
     btif_rc_player_app_settings_t *p_app_settings;
     bt_bdaddr_t rc_addr;
 
-    p_app_settings = &btif_rc_cb.rc_app_settings;
-    bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
+    p_app_settings = &btif_rc_cb[0].rc_app_settings;
+    bdcpy(rc_addr.address, btif_rc_cb[0].rc_addr);
 
     /* Todo: Do we need to retry on command timeout */
     if (p_rsp->status != AVRC_STS_NO_ERROR)
@@ -4048,8 +4675,8 @@ static void handle_app_attr_val_txt_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC
     btif_rc_player_app_settings_t *p_app_settings;
     bt_bdaddr_t rc_addr;
 
-    bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
-    p_app_settings = &btif_rc_cb.rc_app_settings;
+    bdcpy(rc_addr.address, btif_rc_cb[0].rc_addr);
+    p_app_settings = &btif_rc_cb[0].rc_app_settings;
 
     /* Todo: Do we need to retry on command timeout */
     if (p_rsp->status != AVRC_STS_NO_ERROR)
@@ -4166,7 +4793,7 @@ static void handle_set_app_attr_val_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC
     uint8_t accepted = 0;
     bt_bdaddr_t rc_addr;
 
-    bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
+    bdcpy(rc_addr.address, btif_rc_cb[0].rc_addr);
 
     /* For timeout pmeta_msg will be NULL, else we need to
      * check if this is accepted by TG
@@ -4196,7 +4823,7 @@ static void handle_get_elem_attr_response (tBTA_AV_META_MSG *pmeta_msg,
         btrc_element_attr_val_t *p_attr =
             (btrc_element_attr_val_t *)osi_calloc(buf_size);
 
-        bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
+        bdcpy(rc_addr.address, btif_rc_cb[0].rc_addr);
 
         for (int i = 0; i < p_rsp->num_attr; i++) {
             p_attr[i].attr_id = p_rsp->p_attrs[i].attr_id;
@@ -4244,7 +4871,7 @@ static void handle_get_playstatus_response (tBTA_AV_META_MSG *pmeta_msg, tAVRC_G
 {
     bt_bdaddr_t rc_addr;
 
-    bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
+    bdcpy(rc_addr.address, btif_rc_cb[0].rc_addr);
 
     if (p_rsp->status == AVRC_STS_NO_ERROR)
     {
@@ -4438,7 +5065,7 @@ static void cleanup()
     {
         bt_rc_callbacks = NULL;
     }
-    alarm_free(btif_rc_cb.rc_play_status_timer);
+    alarm_free(btif_rc_cb[0].rc_play_status_timer);
     lbl_destroy();
     BTIF_TRACE_EVENT("## RC: %s ## completed", __FUNCTION__);
 }
@@ -4460,7 +5087,7 @@ static void cleanup_ctrl()
     {
         bt_rc_ctrl_callbacks = NULL;
     }
-    alarm_free(btif_rc_cb.rc_play_status_timer);
+    alarm_free(btif_rc_cb[0].rc_play_status_timer);
     memset(&btif_rc_cb, 0, sizeof(btif_rc_cb_t));
     lbl_destroy();
     BTIF_TRACE_EVENT("## %s ## completed", __FUNCTION__);
@@ -4498,7 +5125,7 @@ static bt_status_t getcapabilities_cmd (uint8_t cap_id)
          UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
          BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
                             __FUNCTION__,p_transaction->lbl);
-         BTA_AvVendorCmd(btif_rc_cb.rc_handle,p_transaction->lbl,AVRC_CMD_STATUS,
+         BTA_AvVendorCmd(btif_rc_cb[0].rc_handle,p_transaction->lbl,AVRC_CMD_STATUS,
                                                           data_start, p_msg->len);
          status =  BT_STATUS_SUCCESS;
          start_status_command_timer (AVRC_PDU_GET_CAPABILITIES, p_transaction);
@@ -4546,7 +5173,7 @@ static bt_status_t list_player_app_setting_attrib_cmd(void)
          UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
          BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
                             __FUNCTION__,p_transaction->lbl);
-         BTA_AvVendorCmd(btif_rc_cb.rc_handle,p_transaction->lbl,AVRC_CMD_STATUS,
+         BTA_AvVendorCmd(btif_rc_cb[0].rc_handle,p_transaction->lbl,AVRC_CMD_STATUS,
                                                           data_start, p_msg->len);
          status =  BT_STATUS_SUCCESS;
          start_status_command_timer (AVRC_PDU_LIST_PLAYER_APP_ATTR, p_transaction);
@@ -4596,7 +5223,7 @@ static bt_status_t list_player_app_setting_value_cmd(uint8_t attrib_id)
          UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
          BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
                             __FUNCTION__,p_transaction->lbl);
-         BTA_AvVendorCmd(btif_rc_cb.rc_handle,p_transaction->lbl,AVRC_CMD_STATUS,
+         BTA_AvVendorCmd(btif_rc_cb[0].rc_handle,p_transaction->lbl,AVRC_CMD_STATUS,
                                data_start, p_msg->len);
          status =  BT_STATUS_SUCCESS;
          start_status_command_timer (AVRC_PDU_LIST_PLAYER_APP_VALUES, p_transaction);
@@ -4650,7 +5277,7 @@ static bt_status_t get_player_app_setting_cmd(uint8_t num_attrib, uint8_t* attri
          UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
          BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
                             __FUNCTION__,p_transaction->lbl);
-         BTA_AvVendorCmd(btif_rc_cb.rc_handle,p_transaction->lbl,AVRC_CMD_STATUS,
+         BTA_AvVendorCmd(btif_rc_cb[0].rc_handle,p_transaction->lbl,AVRC_CMD_STATUS,
                           data_start, p_msg->len);
          status =  BT_STATUS_SUCCESS;
          start_status_command_timer (AVRC_PDU_GET_CUR_PLAYER_APP_VALUE, p_transaction);
@@ -4707,7 +5334,7 @@ static bt_status_t change_player_app_setting(bt_bdaddr_t *bd_addr, uint8_t num_a
          UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
          BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
                             __FUNCTION__,p_transaction->lbl);
-         BTA_AvVendorCmd(btif_rc_cb.rc_handle,p_transaction->lbl,AVRC_CMD_CTRL,
+         BTA_AvVendorCmd(btif_rc_cb[0].rc_handle,p_transaction->lbl,AVRC_CMD_CTRL,
                               data_start, p_msg->len);
          status =  BT_STATUS_SUCCESS;
          start_control_command_timer (AVRC_PDU_SET_PLAYER_APP_VALUE, p_transaction);
@@ -4725,7 +5352,6 @@ static bt_status_t change_player_app_setting(bt_bdaddr_t *bd_addr, uint8_t num_a
     return status;
 }
 
-
 /***************************************************************************
 **
 ** Function         get_player_app_setting_val_text_cmd
@@ -4768,7 +5394,7 @@ static bt_status_t get_player_app_setting_value_text_cmd (UINT8 *vals, UINT8 num
                          __FUNCTION__, p_transaction->lbl);
         if (p_msg != NULL)
         {
-            BTA_AvVendorCmd(btif_rc_cb.rc_handle, p_transaction->lbl,
+            BTA_AvVendorCmd(btif_rc_cb[0].rc_handle, p_transaction->lbl,
                     AVRC_CMD_STATUS, data_start, p_msg->len);
             status =  BT_STATUS_SUCCESS;
             start_status_command_timer (AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT, p_transaction);
@@ -4820,7 +5446,7 @@ static bt_status_t register_notification_cmd (UINT8 label, UINT8 event_id, UINT3
                 __FUNCTION__, label);
         if (p_msg != NULL)
         {
-            BTA_AvVendorCmd(btif_rc_cb.rc_handle, label, AVRC_CMD_NOTIF,
+            BTA_AvVendorCmd(btif_rc_cb[0].rc_handle, label, AVRC_CMD_NOTIF,
                     data_start, p_msg->len);
             status =  BT_STATUS_SUCCESS;
         }
@@ -4881,7 +5507,7 @@ static bt_status_t get_element_attribute_cmd (uint8_t num_attribute, uint32_t *p
                 __FUNCTION__, p_transaction->lbl);
         if (p_msg != NULL)
         {
-            BTA_AvVendorCmd(btif_rc_cb.rc_handle, p_transaction->lbl,
+            BTA_AvVendorCmd(btif_rc_cb[0].rc_handle, p_transaction->lbl,
                     AVRC_CMD_STATUS, data_start, p_msg->len);
             status =  BT_STATUS_SUCCESS;
             start_status_command_timer (AVRC_PDU_GET_ELEMENT_ATTR,
@@ -4935,7 +5561,7 @@ static bt_status_t get_play_status_cmd(void)
                 __FUNCTION__, p_transaction->lbl);
         if (p_msg != NULL)
         {
-            BTA_AvVendorCmd(btif_rc_cb.rc_handle,p_transaction->lbl,
+            BTA_AvVendorCmd(btif_rc_cb[0].rc_handle,p_transaction->lbl,
                     AVRC_CMD_STATUS, data_start, p_msg->len);
             status =  BT_STATUS_SUCCESS;
             start_status_command_timer (AVRC_PDU_GET_PLAY_STATUS, p_transaction);
@@ -4977,15 +5603,15 @@ static bt_status_t set_volume_rsp(bt_bdaddr_t *bd_addr, uint8_t abs_vol, uint8_t
     avrc_rsp.volume.pdu = AVRC_PDU_SET_ABSOLUTE_VOLUME;
     avrc_rsp.volume.status = AVRC_STS_NO_ERROR;
     avrc_rsp.volume.volume = abs_vol;
-    status = AVRC_BldResponse(btif_rc_cb.rc_handle, &avrc_rsp, &p_msg);
+    status = AVRC_BldResponse(btif_rc_cb[0].rc_handle, &avrc_rsp, &p_msg);
     if (status == AVRC_STS_NO_ERROR)
     {
         UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
         BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
-                __FUNCTION__, btif_rc_cb.rc_vol_label);
+                __FUNCTION__, btif_rc_cb[0].rc_vol_label);
         if (p_msg != NULL)
         {
-            BTA_AvVendorRsp(btif_rc_cb.rc_handle, label,
+            BTA_AvVendorRsp(btif_rc_cb[0].rc_handle, label,
                     BTA_AV_RSP_ACCEPT, data_start, p_msg->len, 0);
             status =  BT_STATUS_SUCCESS;
         }
@@ -5027,12 +5653,12 @@ static bt_status_t volume_change_notification_rsp(bt_bdaddr_t *bd_addr, btrc_not
     avrc_rsp.reg_notif.param.volume = abs_vol;
     avrc_rsp.reg_notif.event_id = AVRC_EVT_VOLUME_CHANGE;
 
-    status = AVRC_BldResponse(btif_rc_cb.rc_handle, &avrc_rsp, &p_msg);
+    status = AVRC_BldResponse(btif_rc_cb[0].rc_handle, &avrc_rsp, &p_msg);
     if (status == AVRC_STS_NO_ERROR) {
         BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d",
                          __func__, label);
         UINT8* data_start = (UINT8*)(p_msg + 1) + p_msg->offset;
-        BTA_AvVendorRsp(btif_rc_cb.rc_handle, label,
+        BTA_AvVendorRsp(btif_rc_cb[0].rc_handle, label,
                         (rsp_type == BTRC_NOTIFICATION_TYPE_INTERIM) ?
                             AVRC_RSP_INTERIM : AVRC_RSP_CHANGED,
                         data_start, p_msg->len, 0);
@@ -5067,7 +5693,7 @@ static bt_status_t send_groupnavigation_cmd(bt_bdaddr_t *bd_addr, uint8_t key_co
     BTIF_TRACE_DEBUG("%s: key-code: %d, key-state: %d", __FUNCTION__,
                                                     key_code, key_state);
     CHECK_RC_CONNECTED
-    if (btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG)
+    if (btif_rc_cb[0].rc_features & BTA_AV_FEAT_RCTG)
     {
         bt_status_t tran_status = get_transaction(&p_transaction);
         if ((BT_STATUS_SUCCESS == tran_status) && (NULL != p_transaction)) {
@@ -5076,7 +5702,7 @@ static bt_status_t send_groupnavigation_cmd(bt_bdaddr_t *bd_addr, uint8_t key_co
              UINT24_TO_BE_STREAM(start, AVRC_CO_METADATA);
              *(start)++ = 0;
              UINT8_TO_BE_STREAM(start, key_code);
-             BTA_AvRemoteVendorUniqueCmd(btif_rc_cb.rc_handle,
+             BTA_AvRemoteVendorUniqueCmd(btif_rc_cb[0].rc_handle,
                                          p_transaction->lbl,
                                          (tBTA_AV_STATE)key_state, buffer,
                                          AVRC_PASS_THRU_GROUP_LEN);
@@ -5113,17 +5739,22 @@ static bt_status_t send_groupnavigation_cmd(bt_bdaddr_t *bd_addr, uint8_t key_co
 static bt_status_t send_passthrough_cmd(bt_bdaddr_t *bd_addr, uint8_t key_code, uint8_t key_state)
 {
     tAVRC_STS status = BT_STATUS_UNSUPPORTED;
+    /* Controller is used only for Certification purposes.
+     * In normal case AVRCP controller will not be used, hence
+     * updating this is required.
+     */
+    int index = BTIF_RC_DEFAULT_INDEX; //For RC it should be 0
 #if (AVRC_CTLR_INCLUDED == TRUE)
     CHECK_RC_CONNECTED
     rc_transaction_t *p_transaction=NULL;
     BTIF_TRACE_DEBUG("%s: key-code: %d, key-state: %d", __FUNCTION__,
                                                     key_code, key_state);
-    if (btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG)
+    if (btif_rc_cb[index].rc_features & BTA_AV_FEAT_RCTG)
     {
         bt_status_t tran_status = get_transaction(&p_transaction);
         if (BT_STATUS_SUCCESS == tran_status && NULL != p_transaction)
         {
-            BTA_AvRemoteCmd(btif_rc_cb.rc_handle, p_transaction->lbl,
+            BTA_AvRemoteCmd(btif_rc_cb[index].rc_handle, p_transaction->lbl,
                 (tBTA_AV_RC)key_code, (tBTA_AV_STATE)key_state);
             status =  BT_STATUS_SUCCESS;
             BTIF_TRACE_DEBUG("%s: succesfully sent passthrough command to BTA", __FUNCTION__);
@@ -5164,6 +5795,7 @@ static const btrc_interface_t bt_rc_interface = {
     changepath_rsp,
     playitem_rsp,
     get_itemattr_rsp,
+    is_device_active_in_handoff,
     cleanup,
 };
 
index aa856c5..08bcba2 100644 (file)
@@ -37,6 +37,7 @@
 ******************************************************************************/
 typedef struct {
     btif_sm_state_t         state;
+    int                     index;
     btif_sm_handler_t       *p_handlers;
 } btif_sm_cb_t;
 
@@ -57,7 +58,8 @@ typedef struct {
 **
 ******************************************************************************/
 
-btif_sm_handle_t btif_sm_init(const btif_sm_handler_t *p_handlers, btif_sm_state_t initial_state)
+btif_sm_handle_t btif_sm_init(const btif_sm_handler_t *p_handlers, btif_sm_state_t initial_state,
+                            int index)
 {
     if (p_handlers == NULL) {
         BTIF_TRACE_ERROR("%s : p_handlers is NULL", __FUNCTION__);
@@ -67,9 +69,10 @@ btif_sm_handle_t btif_sm_init(const btif_sm_handler_t *p_handlers, btif_sm_state
     btif_sm_cb_t *p_cb = (btif_sm_cb_t *)osi_malloc(sizeof(btif_sm_cb_t));
     p_cb->state = initial_state;
     p_cb->p_handlers = (btif_sm_handler_t*)p_handlers;
+    p_cb->index = index;
 
     /* Send BTIF_SM_ENTER_EVT to the initial state */
-    p_cb->p_handlers[initial_state](BTIF_SM_ENTER_EVT, NULL);
+    p_cb->p_handlers[initial_state](BTIF_SM_ENTER_EVT, NULL, index);
 
     return (btif_sm_handle_t)p_cb;
 }
@@ -107,7 +110,6 @@ void btif_sm_shutdown(btif_sm_handle_t handle)
 btif_sm_state_t btif_sm_get_state(btif_sm_handle_t handle)
 {
     btif_sm_cb_t *p_cb = (btif_sm_cb_t*)handle;
-
     if (p_cb == NULL)
     {
         BTIF_TRACE_ERROR("%s : Invalid handle", __FUNCTION__);
@@ -141,7 +143,7 @@ bt_status_t btif_sm_dispatch(btif_sm_handle_t handle, btif_sm_event_t event,
         return BT_STATUS_FAIL;
     }
 
-    if (p_cb->p_handlers[p_cb->state](event, data) == FALSE)
+    if (p_cb->p_handlers[p_cb->state](event, data, p_cb->index) == FALSE)
         return BT_STATUS_UNHANDLED;
 
     return status;
@@ -172,14 +174,14 @@ bt_status_t btif_sm_change_state(btif_sm_handle_t handle, btif_sm_state_t state)
     }
 
     /* Send exit event to the current state */
-    if (p_cb->p_handlers[p_cb->state](BTIF_SM_EXIT_EVT, NULL) == FALSE)
+    if (p_cb->p_handlers[p_cb->state](BTIF_SM_EXIT_EVT, NULL, p_cb->index) == FALSE)
         status = BT_STATUS_UNHANDLED;
 
     /* Change to the new state */
     p_cb->state = state;
 
     /* Send enter event to the new state */
-    if (p_cb->p_handlers[p_cb->state](BTIF_SM_ENTER_EVT, NULL) == FALSE)
+    if (p_cb->p_handlers[p_cb->state](BTIF_SM_ENTER_EVT, NULL, p_cb->index) == FALSE)
         status = BT_STATUS_UNHANDLED;
 
     return status;
index 7ebddb3..900e0b6 100644 (file)
 #define AVDT_NUM_LINKS              2
 #endif
 
-/* Number of simultaneous stream endpoints. */
+/* Number of simultaneous stream endpoints.
+ * Audio*2 + Video*2 + 1 Additional
+ */
 #ifndef AVDT_NUM_SEPS
-#define AVDT_NUM_SEPS               3
+#define AVDT_NUM_SEPS               5
 #endif
 
 /* Number of transport channels setup by AVDT for all media streams */
 #define AVCT_NUM_LINKS              2
 #endif
 
-/* Number of simultaneous AVCTP connections. */
+/* Number of simultaneous AVCTP connections.
+ * Audio*2 + Video*2 + 1 Additional */
 #ifndef AVCT_NUM_CONN
-#define AVCT_NUM_CONN               3
+#define AVCT_NUM_CONN               5
+#endif
+
+/* Buffer size to reassemble the SDU. */
+#ifndef AVCT_BR_USER_RX_BUF_SIZE
+#define AVCT_BR_USER_RX_BUF_SIZE    BT_DEFAULT_BUFFER_SIZE
+#endif
+
+/* Buffer size to hold the SDU. */
+#ifndef AVCT_BR_USER_TX_BUF_SIZE
+#define AVCT_BR_USER_TX_BUF_SIZE    BT_DEFAULT_BUFFER_SIZE
+#endif
+
+/*
+ * Buffer size used to hold MPS segments during SDU reassembly
+ */
+#ifndef AVCT_BR_FCR_RX_BUF_SIZE
+#define AVCT_BR_FCR_RX_BUF_SIZE     BT_DEFAULT_BUFFER_SIZE
+#endif
+
+/*
+ * Default buffer size used to hold MPS segments used in (re)transmissions.
+ * The size of each buffer must be able to hold the maximum MPS segment size
+ * passed in tL2CAP_FCR_OPTIONS plus BT_HDR (8) + HCI preamble (4) +
+ * L2CAP_MIN_OFFSET (11 - as of BT 2.1 + EDR Spec).+1452 */
+#ifndef AVCT_BR_FCR_TX_BUF_SIZE
+#define AVCT_BR_FCR_TX_BUF_SIZE     BT_DEFAULT_BUFFER_SIZE
 #endif
 
 /******************************************************************************
 #define MCA_CTRL_MTU    60
 #endif
 
+
 /* The maximum number of registered MCAP instances. */
 #ifndef MCA_NUM_REGS
 #define MCA_NUM_REGS    12
index 2f31d1b..b00055a 100644 (file)
@@ -28,6 +28,7 @@
 #include "a2d_api.h"
 #include "a2d_int.h"
 #include "avdt_api.h"
+#include "osi/include/allocator.h"
 
 /*****************************************************************************
 **  Global data
@@ -306,7 +307,7 @@ tA2D_STATUS A2D_FindService(UINT16 service_uuid, BD_ADDR bd_addr,
 
     if (result == TRUE)
     {
-        /* store service_uuid */
+        /* store service_uuid and discovery db pointer */
         a2d_cb.find.service_uuid = service_uuid;
         a2d_cb.find.p_cback = p_cback;
 
@@ -396,4 +397,17 @@ void A2D_Init(void)
     a2d_cb.trace_level  = BT_TRACE_LEVEL_NONE;
 #endif
 }
+/*******************************************************************************
+**
+** Function         a2d_get_avdt_sdp_ver
+**
+** Description      This function fetches current version of AVDT.
+**
+** Returns          Current version of AVDT
+**
+*******************************************************************************/
+int a2d_get_avdt_sdp_ver ()
+{
+    return a2d_cb.avdt_sdp_ver;
+}
 
index d4bb4c2..c65127e 100644 (file)
@@ -75,6 +75,9 @@ extern tA2D_CB *a2d_cb_ptr;
 /* Used only for conformance testing */
 extern void a2d_set_avdt_sdp_ver (UINT16 avdt_sdp_ver);
 
+/* Used to check local version of AVDTP */
+extern int a2d_get_avdt_sdp_ver ();
+
 #ifdef __cplusplus
 }
 #endif
index e3e677f..3826221 100644 (file)
 tAVCT_CB avct_cb;
 #endif
 
+
+/*******************************************************************************
+**
+** Function         AVCT_Init
+**
+** Description      This function is called to initialize the control block
+**                  for this layer.  It must be called before accessing any
+**                  other API functions for this layer.  It is typically called
+**                  once during the start up of the stack.
+**
+** Returns          void
+**
+*******************************************************************************/
+void AVCT_Init(void)
+{
+    /* initialize AVCTP data structures */
+    memset(&avct_cb, 0, sizeof(tAVCT_CB));
+
+#if defined(AVCT_INITIAL_TRACE_LEVEL)
+    avct_cb.trace_level = AVCT_INITIAL_TRACE_LEVEL;
+#else
+    avct_cb.trace_level = BT_TRACE_LEVEL_NONE;
+#endif
+}
+
 /*******************************************************************************
 **
 ** Function         AVCT_Register
@@ -80,12 +105,6 @@ void AVCT_Register(UINT16 mtu, UINT16 mtu_br, UINT8 sec_mask)
     avct_cb.mtu_br = mtu_br;
 #endif
 
-#if defined(AVCT_INITIAL_TRACE_LEVEL)
-    avct_cb.trace_level = AVCT_INITIAL_TRACE_LEVEL;
-#else
-    avct_cb.trace_level = BT_TRACE_LEVEL_NONE;
-#endif
-
     if (mtu < AVCT_MIN_CONTROL_MTU)
         mtu = AVCT_MIN_CONTROL_MTU;
     /* store mtu */
@@ -461,7 +480,13 @@ UINT16 AVCT_MsgReq(UINT8 handle, UINT8 label, UINT8 cr, BT_HDR *p_msg)
             else
             {
                 p_ccb->p_bcb = avct_bcb_by_lcb(p_ccb->p_lcb);
-                avct_bcb_event(p_ccb->p_bcb, AVCT_LCB_UL_MSG_EVT, (tAVCT_LCB_EVT *) &ul_msg);
+                if (p_ccb->p_bcb)
+                    avct_bcb_event(p_ccb->p_bcb, AVCT_LCB_UL_MSG_EVT, (tAVCT_LCB_EVT *) &ul_msg);
+                else
+                {
+                    result = AVCT_BAD_HANDLE;
+                    osi_free(p_msg);
+                }
             }
         }
         /* send msg event to lcb */
@@ -474,3 +499,32 @@ UINT16 AVCT_MsgReq(UINT8 handle, UINT8 label, UINT8 cr, BT_HDR *p_msg)
     return result;
 }
 
+/******************************************************************************
+**
+** Function         AVCT_SetTraceLevel
+**
+** Description      Sets the trace level for AVCT. If 0xff is passed, the
+**                  current trace level is returned.
+**
+**                  Input Parameters:
+**                      new_level:  The level to set the AVCT tracing to:
+**                      0xff-returns the current setting.
+**                      0-turns off tracing.
+**                      >= 1-Errors.
+**                      >= 2-Warnings.
+**                      >= 3-APIs.
+**                      >= 4-Events.
+**                      >= 5-Debug.
+**
+** Returns          The new trace level or current trace level if
+**                  the input parameter is 0xff.
+**
+******************************************************************************/
+UINT8 AVCT_SetTraceLevel (UINT8 new_level)
+{
+    if (new_level != 0xFF)
+        avct_cb.trace_level = new_level;
+
+    return (avct_cb.trace_level);
+}
+
index 2379942..4f32e21 100644 (file)
@@ -97,7 +97,7 @@ typedef struct {
     UINT8               ch_flags;       /* L2CAP configuration flags */
     BT_HDR              *p_tx_msg;      /* Message to be sent - in case the browsing channel is not open when MsgReg is called */
     UINT8               ch_close;       /* CCB index+1, if CCB initiated channel close */
-    BUFFER_Q            tx_q;           /* Transmit data buffer queue       */
+    fixed_queue_t       *tx_q;          /* Transmit data buffer queue       */
     BOOLEAN             cong;           /* TRUE, if congested */
 } tAVCT_BCB;
 
index 4b7747c..674500d 100644 (file)
@@ -230,7 +230,6 @@ void avct_l2c_br_connect_ind_cback(BD_ADDR bd_addr, UINT16 lcid, UINT16 psm, UIN
     tAVCT_BCB       *p_bcb = &avct_cb.bcb[0] ;
     tAVCT_LCB       *p_lcb = NULL;
     UINT16          result = L2CAP_CONN_OK;
-    tAVCT_CCB       *p_ccb = &avct_cb.ccb[0];
     tL2CAP_ERTM_INFO ertm_info;
     tL2CAP_ERTM_INFO *p_ertm_info = NULL;
     tL2CAP_CFG_INFO cfg;
@@ -248,6 +247,20 @@ void avct_l2c_br_connect_ind_cback(BD_ADDR bd_addr, UINT16 lcid, UINT16 psm, UIN
     }
     else
     {
+        /* We will only support one browsing connection.
+        * Second incoming BR conn is rejected.*/
+        for (index = 0; index < AVCT_NUM_LINKS; index++)
+        {
+            p_bcb = &avct_cb.bcb[index];
+            if (p_bcb && p_bcb->allocated)
+            {
+                AVCT_TRACE_ERROR("Browsing already connected to other device");
+                AVCT_TRACE_ERROR("Reject Browsing connection:%d", p_bcb->allocated);
+                result = L2CAP_CONN_NO_RESOURCES;
+                L2CA_ErtmConnectRsp (bd_addr, id, lcid, result, L2CAP_CONN_OK, &ertm_info);
+                return;
+            }
+        }
         index = (UINT8) (p_lcb - &avct_cb.lcb[0]); //calculate offset.
         AVCT_TRACE_DEBUG("index value = %d",index);
         p_bcb   = &avct_cb.bcb[index];
@@ -275,10 +288,10 @@ void avct_l2c_br_connect_ind_cback(BD_ADDR bd_addr, UINT16 lcid, UINT16 psm, UIN
             p_bcb->ch_lcid =   lcid;     /*Updadate LCID so that on config associated bcb could be found*/
             ertm_info.preferred_mode    = L2CAP_FCR_ERTM_MODE;
             ertm_info.allowed_modes     = L2CAP_FCR_CHAN_OPT_ERTM;
-            ertm_info.user_rx_pool_id   = HCI_ACL_POOL_ID;
-            ertm_info.user_tx_pool_id   = HCI_ACL_POOL_ID;
-            ertm_info.fcr_rx_pool_id    = HCI_ACL_POOL_ID;
-            ertm_info.fcr_tx_pool_id    = HCI_ACL_POOL_ID;
+            ertm_info.user_rx_buf_size   = 4096;//AVCT_BR_USER_RX_BUF_SIZE;
+            ertm_info.user_tx_buf_size   = 4096;//AVCT_BR_USER_TX_BUF_SIZE;
+            ertm_info.fcr_rx_buf_size    = 4096;//AVCT_BR_FCR_RX_BUF_SIZE;
+            ertm_info.fcr_tx_buf_size    = 4096;//AVCT_BR_FCR_TX_BUF_SIZE;
             p_ertm_info                 = &ertm_info;
             L2CA_ErtmConnectRsp (bd_addr, id, lcid, result, L2CAP_CONN_OK, p_ertm_info);
         }
@@ -823,7 +836,7 @@ void avct_l2c_br_data_ind_cback(UINT16 lcid, BT_HDR *p_buf)
     else /* prevent buffer leak */
     {
         AVCT_TRACE_WARNING("avct_l2c_br_data_ind_cback drop buffer");
-        GKI_freebuf(p_buf);
+        osi_free_and_reset((void**)&p_buf);
     }
 
 }
index 8cf5c8b..364b15b 100644 (file)
@@ -234,7 +234,7 @@ void avct_lcb_event(tAVCT_LCB *p_lcb, UINT8 event, tAVCT_LCB_EVT *p_data)
     /* execute action functions */
     for (i = 0; i < AVCT_LCB_ACTIONS; i++)
     {
-        if ((action = state_table[event][i]) != AVCT_LCB_IGNORE)
+        if ((action = state_table[event][i]) < AVCT_LCB_IGNORE)
         {
             (*avct_lcb_action[action])(p_lcb, p_data);
         }
@@ -277,7 +277,7 @@ void avct_bcb_event(tAVCT_BCB *p_bcb, UINT8 event, tAVCT_LCB_EVT *p_data)
     /* execute action functions */
     for (i = 0; i < AVCT_LCB_ACTIONS; i++)
     {
-        if ((action = state_table[event][i]) != AVCT_LCB_IGNORE)
+        if ((action = state_table[event][i]) < AVCT_LCB_IGNORE)
         {
             (*avct_bcb_action[action])(p_bcb, p_data);
         }
@@ -581,9 +581,11 @@ tAVCT_CCB *avct_lcb_has_pid(tAVCT_LCB *p_lcb, UINT16 pid)
     {
         if (p_ccb->allocated && (p_ccb->p_lcb == p_lcb) && (p_ccb->cc.pid == pid))
         {
+            AVCT_TRACE_DEBUG("avct_lcb_has_pid, found");
             return p_ccb;
         }
     }
+    AVCT_TRACE_WARNING("avct_lcb_has_pid, not found");
     return NULL;
 }
 
index aba6111..878dd82 100644 (file)
@@ -186,7 +186,6 @@ static BT_HDR *avct_bcb_msg_asmbl(tAVCT_BCB *p_bcb, BT_HDR *p_buf)
     UINT8   *p;
     UINT8   pkt_type;
     BT_HDR  *p_ret;
-    UINT16  buf_len;
 
     /* parse the message header */
     AVCT_TRACE_DEBUG("bcb_msg_asmbl peer_mtu:%x, ch_lcid:%x",p_bcb->peer_mtu, \
@@ -198,7 +197,7 @@ static BT_HDR *avct_bcb_msg_asmbl(tAVCT_BCB *p_bcb, BT_HDR *p_buf)
     /* quick sanity check on length */
     if (p_buf->len < avct_lcb_pkt_type_len[pkt_type])
     {
-        GKI_freebuf(p_buf);
+        osi_free_and_reset((void**)&p_buf);
         AVCT_TRACE_WARNING("### Bad length during reassembly");
         p_ret = NULL;
     }
@@ -214,7 +213,7 @@ static BT_HDR *avct_bcb_msg_asmbl(tAVCT_BCB *p_bcb, BT_HDR *p_buf)
     }
     else
     {
-        GKI_freebuf(p_buf);
+        osi_free_and_reset((void**)&p_buf);
         p_ret =NULL;
         AVCT_TRACE_WARNING("### Got Fragmented packet");
     }
@@ -278,7 +277,6 @@ void avct_bcb_chnl_open(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data)
 ******************************************************************************/
 void avct_close_bcb(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
 {
-    int               i;
     tAVCT_BCB        *p_bcb = NULL;
 
     AVCT_TRACE_DEBUG("avct_close_bcb");
@@ -353,8 +351,10 @@ void avct_lcb_open_ind(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
         if (p_ccb->allocated)
         {
             /* if bound to this lcb send connect confirm event */
+            AVCT_TRACE_DEBUG("avct_lcb_open_ind, %d", p_ccb->allocated);
             if (p_ccb->p_lcb == p_lcb)
             {
+                AVCT_TRACE_DEBUG("avct_lcb_open_ind, bind true");
                 bind = TRUE;
                 L2CA_SetTxPriority(p_lcb->ch_lcid, L2CAP_CHNL_PRIORITY_HIGH);
                 p_ccb->cc.p_ctrl_cback(avct_ccb_to_idx(p_ccb), AVCT_CONNECT_CFM_EVT,
@@ -365,6 +365,7 @@ void avct_lcb_open_ind(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
                      (avct_lcb_has_pid(p_lcb, p_ccb->cc.pid) == NULL))
             {
                 /* bind ccb to lcb and send connect ind event */
+                AVCT_TRACE_DEBUG("avct_lcb_open_ind, bind and update");
                 bind = TRUE;
                 p_ccb->p_lcb = p_lcb;
                 L2CA_SetTxPriority(p_lcb->ch_lcid, L2CAP_CHNL_PRIORITY_HIGH);
@@ -377,6 +378,7 @@ void avct_lcb_open_ind(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
     /* if no ccbs bound to this lcb, disconnect */
     if (bind == FALSE)
     {
+        AVCT_TRACE_DEBUG("avct_lcb_open_ind, send disconnect");
         avct_lcb_event(p_lcb, AVCT_LCB_INT_CLOSE_EVT, p_data);
     }
 }
@@ -536,7 +538,7 @@ void avct_bcb_close_ind(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data)
         {
             //set avct_cb.bcb to 0
             memset(p_ccb->p_bcb, 0 ,sizeof(tAVCT_BCB));
-            p_ccb->p_bcb == NULL;
+            p_ccb->p_bcb = NULL;
             AVCT_TRACE_DEBUG("**close_ind");
         }
     }
@@ -825,20 +827,20 @@ void avct_lcb_cong_ind(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
 *******************************************************************************/
 void avct_bcb_cong_ind(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data)
 {
-    int           i;
     UINT8         event;
     BT_HDR       *p_buf;
 
     AVCT_TRACE_DEBUG("avct_bcb_cong_ind");
     if (p_bcb != NULL)
     {
-        AVCT_TRACE_DEBUG("avct_bcb_cong_ind = %d",p_data->cong);
-        /* set event */
+        AVCT_TRACE_DEBUG("avct_bcb_cong_ind = %d", p_data->cong);
+
         event = (p_data->cong) ? AVCT_CONG_IND_EVT : AVCT_UNCONG_IND_EVT;
         p_bcb->cong = p_data->cong;
-        if (p_bcb->cong == FALSE && GKI_getfirst(&p_bcb->tx_q))
+        if (p_bcb->cong == FALSE && !fixed_queue_is_empty(p_bcb->tx_q))
         {
-            while (!p_bcb->cong && (p_buf = (BT_HDR *)GKI_dequeue(&p_bcb->tx_q)) != NULL)
+            while (!p_bcb->cong &&
+                   (p_buf = (BT_HDR *)fixed_queue_try_dequeue(p_bcb->tx_q)) != NULL)
             {
                 if (L2CA_DataWrite(p_bcb->ch_lcid, p_buf) == L2CAP_DW_CONGESTED)
                 {
@@ -886,7 +888,7 @@ void avct_lcb_discard_msg(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
 void avct_bcb_discard_msg(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data)
 {
     AVCT_TRACE_ERROR("### avct_bcb_discard_msg");
-    GKI_freebuf(p_data->ul_msg.p_buf);
+    osi_free_and_reset((void**)&p_data->ul_msg.p_buf);
 }
 #endif
 
@@ -1019,8 +1021,6 @@ void avct_bcb_send_msg(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data)
     UINT8           pkt_type;
     UINT8           *p;
     BT_HDR          *p_buf;
-    UINT8           nosp = 0; /* number of subsequent packets */
-    UINT16          buf_size = p_bcb->peer_mtu + L2CAP_MIN_OFFSET + BT_HDR_SIZE;
     /* store msg len */
     curr_msg_len = p_data->ul_msg.p_buf->len;
     AVCT_TRACE_DEBUG("avct_bcb_send_msg  length: %x",curr_msg_len);
@@ -1046,7 +1046,7 @@ void avct_bcb_send_msg(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data)
         if (p_bcb->cong == TRUE)
         {
             AVCT_TRACE_ERROR("L2CAP congestion");
-            GKI_enqueue (&p_bcb->tx_q, p_buf);
+            fixed_queue_enqueue(p_bcb->tx_q, p_buf);
         }
         else
         {
@@ -1099,7 +1099,7 @@ void avct_bcb_free_msg_ind(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data)
 {
     AVCT_TRACE_DEBUG("avct_bcb_free_msg_ind");
     if (p_data)
-        GKI_freebuf(p_data->p_buf);
+        osi_free_and_reset((void**)&p_data->p_buf);
 
 }
 #endif
@@ -1225,7 +1225,7 @@ void avct_bcb_msg_ind(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data)
     if (cr_ipid == AVCT_CR_IPID_INVALID)
     {
         AVCT_TRACE_WARNING("### Invalid cr_ipid", cr_ipid);
-        GKI_freebuf(p_data->p_buf);
+        osi_free_and_reset((void**)&p_data->p_buf);
         return;
     }
     /* parse and lookup PID */
@@ -1234,7 +1234,7 @@ void avct_bcb_msg_ind(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data)
     if (p_lcb == NULL)
     {
         AVCT_TRACE_ERROR("### Error lcb is NULL");
-        GKI_freebuf(p_data->p_buf);
+        osi_free_and_reset((void**)&p_data->p_buf);
     }
     else
     {
@@ -1260,11 +1260,11 @@ void avct_bcb_msg_ind(tAVCT_BCB *p_bcb, tAVCT_LCB_EVT *p_data)
         {
             /* PID not found; drop message */
             AVCT_TRACE_WARNING("### No ccb for PID=%x", pid);
-            GKI_freebuf(p_data->p_buf);
+            osi_free_and_reset((void**)&p_data->p_buf);
             /* if command send reject */
             if (cr_ipid == AVCT_CMD)
             {
-                if ((p_buf = (BT_HDR *) GKI_getpoolbuf(AVCT_CMD_POOL_ID)) != NULL)
+                if ((p_buf = (BT_HDR *) osi_malloc(AVCT_CMD_BUF_SIZE)) != NULL)
                 {
                     p_buf->len = AVCT_HDR_LEN_SINGLE;
                     p_buf->offset = AVCT_MSG_OFFSET - AVCT_HDR_LEN_SINGLE;
index 98ef5f7..58971cf 100644 (file)
 tAVDT_CB avdt_cb;
 #endif
 
+/*******************************************************************************
+**
+** Function         AVDT_Init
+**
+** Description      This function is called to initialize the control block
+**                  for this layer.  It must be called before accessing any
+**                  other API functions for this layer.  It is typically called
+**                  once during the start up of the stack.
+**
+** Returns          void
+**
+*******************************************************************************/
+void AVDT_Init(void)
+{
+    memset(&avdt_cb, 0, sizeof(tAVDT_CB));
+
+#if defined(AVDT_INITIAL_TRACE_LEVEL)
+    avdt_cb.trace_level = AVDT_INITIAL_TRACE_LEVEL;
+#else
+    avdt_cb.trace_level = BT_TRACE_LEVEL_NONE;
+#endif
+}
+
 void avdt_ccb_idle_ccb_timer_timeout(void *data)
 {
     tAVDT_CCB *p_ccb = (tAVDT_CCB *)data;
@@ -144,6 +167,40 @@ void AVDT_Deregister(void)
 
 /*******************************************************************************
 **
+** Function         AVDT_UpdateServiceBusyState
+**
+** Description      This function is used to set the service busy state
+**                  during outgoing connection to properly handle the
+**                  connections in upper layers.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void AVDT_UpdateServiceBusyState(BOOLEAN state)
+{
+    AVDT_TRACE_DEBUG("AVDT_UpdateServiceBusyState: %d", state);
+    avdt_cb.conn_in_progress = state;
+}
+
+/*******************************************************************************
+**
+** Function         AVDT_GetServiceBusyState
+**
+** Description      This function is used to get the service busy state
+**
+**
+** Returns          outgoing connection in progress or not
+**
+*******************************************************************************/
+BOOLEAN AVDT_GetServiceBusyState(void)
+{
+    AVDT_TRACE_DEBUG("AVDT_GetServiceBusyState: %d", avdt_cb.conn_in_progress);
+    return avdt_cb.conn_in_progress;
+}
+
+/*******************************************************************************
+**
 ** Function         AVDT_SINK_Activate
 **
 ** Description      Activate SEP of A2DP Sink. In Use parameter is adjusted.
@@ -237,16 +294,19 @@ UINT16 AVDT_CreateStream(UINT8 *p_handle, tAVDT_CS *p_cs)
     /* Verify parameters; if invalid, return failure */
     if (((p_cs->cfg.psc_mask & (~AVDT_PSC)) != 0) || (p_cs->p_ctrl_cback == NULL))
     {
+        AVDT_TRACE_ERROR("%s: bad param", __FUNCTION__);
         result = AVDT_BAD_PARAMS;
     }
     /* Allocate scb; if no scbs, return failure */
     else if ((p_scb = avdt_scb_alloc(p_cs)) == NULL)
     {
+        AVDT_TRACE_ERROR("%s: noresource", __FUNCTION__);
         result = AVDT_NO_RESOURCES;
     }
     else
     {
         *p_handle = avdt_scb_to_hdl(p_scb);
+        AVDT_TRACE_DEBUG("%s: allocated SCB", __FUNCTION__);
     }
     return result;
 }
index 1ab5f18..9f56f46 100644 (file)
@@ -552,6 +552,7 @@ typedef struct {
     tAVDT_SCB_ACTION    *p_scb_act;             /* pointer to SCB action functions */
     tAVDT_CTRL_CBACK    *p_conn_cback;          /* connection callback function */
     UINT8               trace_level;            /* trace level */
+    BOOLEAN             conn_in_progress;       /* outgoing connection in progress */
 } tAVDT_CB;
 
 
index 87c7ad9..2542015 100644 (file)
@@ -181,8 +181,17 @@ void avdt_l2c_connect_ind_cback(BD_ADDR bd_addr, UINT16 lcid, UINT16 psm, UINT8
     tBTM_STATUS rc;
     UNUSED(psm);
 
+    /* Check if outgoing connection is in progress
+     * if yes, reject incoming connection at L2CAP
+     * level itself.
+     */
+    if(avdt_cb.conn_in_progress == TRUE)
+    {
+        AVDT_TRACE_WARNING("connect_ind: outgoing conn in progress: Reject incoming conn");
+        result = L2CAP_CONN_NO_RESOURCES;
+    }
     /* do we already have a control channel for this peer? */
-    if ((p_ccb = avdt_ccb_by_bd(bd_addr)) == NULL)
+    else if ((p_ccb = avdt_ccb_by_bd(bd_addr)) == NULL)
     {
         /* no, allocate ccb */
         if ((p_ccb = avdt_ccb_alloc(bd_addr)) == NULL)
index f13c110..7838823 100644 (file)
@@ -529,7 +529,6 @@ static void avrc_msg_cback(UINT8 handle, UINT8 label, UINT8 cr,
     UINT8       opcode;
     tAVRC_MSG   msg;
     UINT8       *p_data;
-    UINT8       *browse_length;
     UINT8       *p_begin;
     BOOLEAN     drop = FALSE;
     BOOLEAN     do_free = TRUE;
@@ -591,7 +590,7 @@ static void avrc_msg_cback(UINT8 handle, UINT8 label, UINT8 cr,
                 if (cr == AVCT_CMD)
                 {
                     /* send the response to the peer */
-                    p_rsp = avrc_copy_packet(p_pkt);
+                    p_rsp = avrc_copy_packet(p_pkt, AVRC_OP_UNIT_INFO_RSP_LEN);
                     p_rsp_data = avrc_get_data_ptr(p_rsp);
                     *p_rsp_data = AVRC_RSP_IMPL_STBL;
                     /* check & set the offset. set response code, set subunit_type & subunit_id,
@@ -623,7 +622,7 @@ static void avrc_msg_cback(UINT8 handle, UINT8 label, UINT8 cr,
                 if (cr == AVCT_CMD)
                 {
                     /* send the response to the peer */
-                    p_rsp = avrc_copy_packet(p_pkt);
+                    p_rsp = avrc_copy_packet(p_pkt, AVRC_OP_SUB_UNIT_INFO_RSP_LEN);
                     p_rsp_data = avrc_get_data_ptr(p_rsp);
                     *p_rsp_data = AVRC_RSP_IMPL_STBL;
                     /* check & set the offset. set response code, set (subunit_type & subunit_id),
@@ -747,7 +746,7 @@ static void avrc_msg_cback(UINT8 handle, UINT8 label, UINT8 cr,
         if (reject)
         {
             /* reject unsupported opcode */
-            p_rsp = avrc_copy_packet(p_pkt);
+            p_rsp = avrc_copy_packet(p_pkt, AVRC_OP_REJ_MSG_LEN);
             p_rsp_data      = avrc_get_data_ptr(p_rsp);
             *p_rsp_data     = AVRC_RSP_REJ;
 #if (BT_USE_TRACES == TRUE)
index 81ba744..c379175 100644 (file)
@@ -764,57 +764,6 @@ static tAVRC_STS avrc_bld_set_absolute_volume_rsp(uint8_t abs_vol, BT_HDR *p_pkt
     return AVRC_STS_NO_ERROR;
 }
 
-/*****************************************************************************
-**
-** Function      avrc_bld_set_address_player_rsp
-**
-** Description   This function builds the set address player response
-**
-** Returns       AVRC_STS_NO_ERROR, if the response is build successfully
-**               Otherwise, the error code.
-**
-******************************************************************************/
-static tAVRC_STS avrc_bld_set_address_player_rsp(tAVRC_RSP *p_rsp, BT_HDR *p_pkt)
-{
-    UINT8   *p_data, *p_start;
-    tAVRC_STS status = AVRC_STS_NO_ERROR;
-
-    AVRC_TRACE_API(" avrc_bld_set_address_player_rsp");
-    p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
-    /* To calculate length */
-    p_data = p_start + 2;
-    /* add fixed lenth status(1) */
-    UINT16_TO_BE_STREAM(p_data, 1);
-    UINT8_TO_BE_STREAM(p_data, p_rsp->status);
-    p_pkt->len = (p_data - p_start);
-    return status;
-}
-
-/*****************************************************************************
-**
-** Function      avrc_bld_play_item_rsp
-**
-** Description   This function builds the play item response
-**
-** Returns       AVRC_STS_NO_ERROR, if the response is build successfully
-**               Otherwise, the error code.
-**
-******************************************************************************/
-static tAVRC_STS avrc_bld_play_item_rsp(tAVRC_RSP *p_rsp, BT_HDR *p_pkt)
-{
-    UINT8   *p_data, *p_start;
-    tAVRC_STS status = AVRC_STS_NO_ERROR;
-
-    AVRC_TRACE_API(" avrc_bld_play_item_rsp");
-    p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
-    /* To calculate length */
-    p_data = p_start + 2;
-    /* add fixed lenth status(1) */
-    UINT16_TO_BE_STREAM(p_data, 1);
-    UINT8_TO_BE_STREAM(p_data, p_rsp->status);
-    p_pkt->len = (p_data - p_start);
-    return status;
-}
 
 /*******************************************************************************
 **
@@ -854,9 +803,8 @@ tAVRC_STS avrc_bld_group_navigation_rsp (UINT16 navi_id, BT_HDR *p_pkt)
 static tAVRC_STS  avrc_bld_folder_item_values_rsp(tAVRC_GET_ITEMS_RSP *p_rsp, BT_HDR *p_pkt )
 {
     UINT8 *p_data, *p_start, *p_length, *p_media_element_len;
-    UINT8 *item_length;
     UINT16 itemlength, param_length;
-    UINT16 length = 0, item_numb = 0, i, xx, media_attr_count;
+    UINT16 item_numb = 0, i, xx, media_attr_count;
 
     AVRC_TRACE_DEBUG(" avrc_bld_folder_item_values_rsp offset :x%x", p_pkt->offset);
     p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
@@ -971,8 +919,6 @@ static tAVRC_STS avrc_bld_change_path_rsp (tAVRC_CHG_PATH_RSP *p_rsp, BT_HDR *p_
 {
     UINT8 *p_data, *p_start;
     UINT16 param_len; /* parameter length feild of Rsp */
-    UINT8 folder_index = 0;
-
 
     AVRC_TRACE_DEBUG("avrc_bld_change_path_rsp offset :x%x", p_pkt->offset);
 
@@ -1350,12 +1296,12 @@ static BT_HDR *avrc_bld_init_browse_rsp_buffer(tAVRC_RESPONSE *p_rsp)
 {
     UINT16 offset = AVCT_BROWSE_OFFSET;
     UINT16 chnl = AVCT_DATA_BROWSE;
-    UINT16 len  = AVRC_BROWSE_POOL_SIZE;
+    UINT16 len  = BT_DEFAULT_BUFFER_SIZE;
     BT_HDR *p_pkt = NULL;
 
     AVRC_TRACE_API("avrc_bld_init_browse_rsp_buffer ");
     /* allocate and initialize the buffer */
-    p_pkt = (BT_HDR *)GKI_getbuf(len);
+    p_pkt = (BT_HDR *)osi_malloc(len);
 
     if (p_pkt != NULL)
     {
@@ -1435,7 +1381,7 @@ tAVRC_STS AVRC_BldBrowseResponse( UINT8 handle, tAVRC_RESPONSE *p_rsp, BT_HDR **
     }
     if (alloc && (status != AVRC_STS_NO_ERROR) )
     {
-        GKI_freebuf(p_pkt);
+        osi_free_and_reset((void **)&p_pkt);
         *pp_pkt = NULL;
         AVRC_TRACE_ERROR("### error status:%d",status);
     }
index 75d2755..65da985 100644 (file)
@@ -203,6 +203,9 @@ extern tA2D_STATUS A2D_AddRecord(UINT16 service_uuid, char *p_service_name, char
 extern tA2D_STATUS A2D_FindService(UINT16 service_uuid, BD_ADDR bd_addr,
                                    tA2D_SDP_DB_PARAMS *p_db, tA2D_FIND_CBACK *p_cback);
 
+/* Used to check local version of AVDTP */
+extern int a2d_get_avdt_sdp_ver ();
+
 /******************************************************************************
 **
 ** Function         A2D_SetTraceLevel
index 5feb8c2..f8441e8 100644 (file)
@@ -127,6 +127,20 @@ extern "C"
 
 /*******************************************************************************
 **
+** Function         AVCT_Init
+**
+** Description      This function is called to initialize the control block
+**                  for this layer.  It must be called before accessing any
+**                  other API functions for this layer.  It is typically called
+**                  once during the start up of the stack.
+**
+** Returns          void
+**
+*******************************************************************************/
+void AVCT_Init(void);
+
+/*******************************************************************************
+**
 ** Function         AVCT_Register
 **
 ** Description      This is the system level registration function for the
@@ -272,6 +286,31 @@ extern UINT16 AVCT_GetPeerMtu (UINT8 handle);
 extern UINT16 AVCT_MsgReq(UINT8 handle, UINT8 label, UINT8 cr, BT_HDR *p_msg);
 
 
+
+/******************************************************************************
+**
+** Function         AVCT_SetTraceLevel
+**
+** Description      Sets the trace level for AVCT. If 0xff is passed, the
+**                  current trace level is returned.
+**
+**                  Input Parameters:
+**                      new_level:  The level to set the AVCT tracing to:
+**                      0xff-returns the current setting.
+**                      0-turns off tracing.
+**                      >= 1-Errors.
+**                      >= 2-Warnings.
+**                      >= 3-APIs.
+**                      >= 4-Events.
+**                      >= 5-Debug.
+**
+** Returns          The new trace level or current trace level if
+**                  the input parameter is 0xff.
+**
+******************************************************************************/
+UINT8 AVCT_SetTraceLevel (UINT8 new_level);
+
+
 /*******************************************************************************
 **
 ** Function         avct_get_peer_addr_by_ccb
index e10faf0..ac951c2 100644 (file)
@@ -420,6 +420,20 @@ extern "C"
 
 /*******************************************************************************
 **
+** Function         AVDT_Init
+**
+** Description      This function is called to initialize the control block
+**                  for this layer.  It must be called before accessing any
+**                  other API functions for this layer.  It is typically called
+**                  once during the start up of the stack.
+**
+** Returns          void
+**
+*******************************************************************************/
+void AVDT_Init(void);
+
+/*******************************************************************************
+**
 ** Function         AVDT_Register
 **
 ** Description      This is the system level registration function for the
@@ -452,6 +466,32 @@ extern void AVDT_Deregister(void);
 
 /*******************************************************************************
 **
+** Function         AVDT_UpdateServiceBusyState
+**
+** Description      This function is used to set the service busy state
+**                  during outgoing connection to properly handle the
+**                  connections in upper layers.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void AVDT_UpdateServiceBusyState(BOOLEAN state);
+
+/*******************************************************************************
+**
+** Function         AVDT_GetServiceBusyState
+**
+** Description      This function is used to get the service busy state
+**
+**
+** Returns          outgoing connection in progress or not
+**
+*******************************************************************************/
+BOOLEAN AVDT_GetServiceBusyState(void);
+
+/*******************************************************************************
+**
 ** Function         AVDT_SINK_Activate
 **
 ** Description      Activate SEP of A2DP Sink. In Use parameter is adjusted.
index f0f4e6e..0a378eb 100644 (file)
@@ -722,15 +722,10 @@ static void process_service_attr_req (tCONN_CB *p_ccb, UINT16 trans_num,
     }
     if (is_avrcp_fallback)
     {
-#if (defined(SDP_AVRCP_1_6) && (SDP_AVRCP_1_6 == TRUE))
-        /* Update AVRCP version back to 1.6 */
-        p_attr->value_ptr[PROFILE_VERSION_POSITION] = 0x06;
-#else
 #if (defined(SDP_AVRCP_1_5) && (SDP_AVRCP_1_5 == TRUE))
         /* Update AVRCP version back to 1.5 */
         p_attr->value_ptr[PROFILE_VERSION_POSITION] = 0x05;
 #endif
-#endif
         is_avrcp_fallback = FALSE;
     }
     if (is_avrcp_browse_bit_reset)
@@ -851,7 +846,6 @@ static void process_service_search_attr_req (tCONN_CB *p_ccb, UINT16 trans_num,
     BOOLEAN         maxxed_out = FALSE, is_cont = FALSE;
     BOOLEAN         is_avrcp_fallback = FALSE;
     BOOLEAN         is_avrcp_browse_bit_reset = FALSE;
-    BOOLEAN         is_avrcp_ca_bit_reset = FALSE;
     BOOLEAN         is_hfp_fallback = FALSE;
     UINT8           *p_seq_start;
     UINT16          seq_len, attr_len;
@@ -1025,15 +1019,10 @@ static void process_service_search_attr_req (tCONN_CB *p_ccb, UINT16 trans_num,
                 }
                 if (is_avrcp_fallback)
                 {
-#if (defined(SDP_AVRCP_1_6) && (SDP_AVRCP_1_6 == TRUE))
-                    /* Update AVRCP version back to 1.6 */
-                    p_attr->value_ptr[PROFILE_VERSION_POSITION] = 0x06;
-#else
 #if (defined(SDP_AVRCP_1_5) && (SDP_AVRCP_1_5 == TRUE))
                     /* Update AVRCP version back to 1.5 */
                     p_attr->value_ptr[PROFILE_VERSION_POSITION] = 0x05;
 #endif
-#endif
                     is_avrcp_fallback = FALSE;
                 }
                 if (is_avrcp_browse_bit_reset)
@@ -1155,7 +1144,7 @@ static void process_service_search_attr_req (tCONN_CB *p_ccb, UINT16 trans_num,
     }
 
     /* Get a buffer to use to build the response */
-    BT_HDR *p_buf = (BT_HDR *)osi_malloc(SDP_DATA_BUF_SIZE);
+    p_buf = (BT_HDR *)osi_malloc(SDP_DATA_BUF_SIZE);
     p_buf->offset = L2CAP_MIN_OFFSET;
     p_rsp = p_rsp_start = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET;