OSDN Git Service

Add A2DP Sink Support
authorHemant Gupta <hemantg@codeaurora.org>
Thu, 24 Oct 2013 10:07:17 +0000 (15:37 +0530)
committerMike Lockwood <lockwood@google.com>
Thu, 12 Jun 2014 23:16:41 +0000 (16:16 -0700)
Change-Id: I9affefdd2d00597545e49c593ef3bddb110d4c9c

33 files changed:
Android.mk
bta/av/bta_av_aact.c
bta/av/bta_av_act.c
bta/av/bta_av_api.c
bta/av/bta_av_ci.c
bta/av/bta_av_int.h
bta/av/bta_av_main.c
bta/av/bta_av_sbc.c
bta/av/bta_av_ssm.c
bta/include/bta_av_api.h
bta/include/bta_av_ci.h
bta/include/bta_av_co.h
bta/include/bta_av_sbc.h
btif/co/bta_av_co.c
btif/include/bluetoothTrack.h [new file with mode: 0644]
btif/include/btif_av.h
btif/include/btif_av_co.h
btif/include/btif_media.h
btif/include/btif_profile_queue.h
btif/src/bluetoothTrack.cpp [new file with mode: 0644]
btif/src/btif_av.c
btif/src/btif_hf.c
btif/src/btif_hf_client.c
btif/src/btif_media_task.c
btif/src/btif_profile_queue.c
include/bt_target.h
main/Android.mk
stack/avdt/avdt_ad.c
stack/avdt/avdt_api.c
stack/avdt/avdt_int.h
stack/avdt/avdt_scb.c
stack/avdt/avdt_scb_act.c
stack/include/avdt_api.h

index 83e6bbf..dbe1b1f 100644 (file)
@@ -12,6 +12,7 @@ else
 endif
 
 bdroid_CFLAGS += -Wall -Werror
+bdroid_CFLAGS += -DBTA_AVK_INCLUDED
 
 include $(call all-subdir-makefiles)
 
index 6b1a352..25de516 100644 (file)
@@ -193,6 +193,7 @@ static const UINT16 bta_av_stream_evt_fail[] = {
     0                               /* AVDT_DELAY_REPORT_CFM_EVT */
 };
 
+void bta_av_stream_data_cback(UINT8 handle, BT_HDR *p_pkt, UINT32 time_stamp, UINT8 m_pt);
 static void bta_av_stream0_cback(UINT8 handle, BD_ADDR bd_addr, UINT8 event, tAVDT_CTRL *p_data);
 static void bta_av_stream1_cback(UINT8 handle, BD_ADDR bd_addr, UINT8 event, tAVDT_CTRL *p_data);
 #if BTA_AV_NUM_STRS > 2
@@ -225,6 +226,48 @@ tAVDT_CTRL_CBACK * const bta_av_dt_cback[] =
     ,bta_av_stream5_cback
 #endif
 };
+/***********************************************
+**
+** Function         bta_get_scb_handle
+**
+** Description      gives the registered AVDT handle.by checking with sep_type.
+**
+**
+** Returns          void
+***********************************************/
+UINT8  bta_av_get_scb_handle ( tBTA_AV_SCB *p_scb, UINT8 local_sep )
+{
+    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_DEBUG0(" bta_av_get_scb_handle appropiate sep_type not found")
+    return 0; /* return invalid handle */
+}
+
+/***********************************************
+**
+** Function         bta_av_get_scb_sep_type
+**
+** Description      gives the sep type by cross-checking with AVDT handle
+**
+**
+** Returns          void
+***********************************************/
+UINT8  bta_av_get_scb_sep_type ( tBTA_AV_SCB *p_scb, UINT8 tavdt_handle)
+{
+    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_DEBUG0(" bta_av_get_scb_sep_type appropiate handle not found")
+    return 3; /* return invalid sep type */
+}
 
 /*******************************************************************************
 **
@@ -320,12 +363,19 @@ static BOOLEAN bta_av_next_getcap(tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
     int     i;
     tAVDT_GETCAP_REQ    *p_req;
     BOOLEAN     sent_cmd = FALSE;
+    UINT16 uuid_int = p_scb->uuid_int;
+    UINT8 sep_requested = 0;
+
+    if(uuid_int == UUID_SERVCLASS_AUDIO_SOURCE)
+       sep_requested = AVDT_TSEP_SNK;
+    else if(uuid_int == UUID_SERVCLASS_AUDIO_SINK)
+       sep_requested = AVDT_TSEP_SRC;
 
     for (i = p_scb->sep_info_idx; i < p_scb->num_seps; i++)
     {
         /* steam not in use, is a sink, and is the right media type (audio/video) */
         if ((p_scb->sep_info[i].in_use == FALSE) &&
-            (p_scb->sep_info[i].tsep == AVDT_TSEP_SNK) &&
+            (p_scb->sep_info[i].tsep == sep_requested) &&
             (p_scb->sep_info[i].media_type == p_scb->media_type))
         {
             p_scb->sep_info_idx = i;
@@ -509,6 +559,39 @@ void bta_av_proc_stream_evt(UINT8 handle, BD_ADDR bd_addr, UINT8 event, tAVDT_CT
 
 /*******************************************************************************
 **
+** Function         bta_av_stream_data_cback
+**
+** Description      This is the AVDTP callback function for stream events.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_stream_data_cback(UINT8 handle, BT_HDR *p_pkt, UINT32 time_stamp, UINT8 m_pt)
+{
+    int index = 0;
+    tBTA_AV_SCB         *p_scb ;
+    APPL_TRACE_DEBUG3("bta_av_stream_data_cback avdt_handle: %d pkt_len=0x%x  ofst = 0x%x", handle,p_pkt->len,p_pkt->offset);
+    APPL_TRACE_DEBUG1(" Number of frames 0x%x",*((UINT8*)(p_pkt + 1) + p_pkt->offset));
+    APPL_TRACE_DEBUG1("Sequence Number 0x%x",p_pkt->layer_specific);
+    /* Get  SCB  and correct sep type*/
+    for(index = 0; index < BTA_AV_NUM_STRS;index ++ )
+    {
+        p_scb = bta_av_cb.p_scb[index];
+        if((p_scb->avdt_handle == handle)&&(p_scb->seps[p_scb->sep_idx].tsep == AVDT_TSEP_SNK))
+            break;
+    }
+    if(index == BTA_AV_NUM_STRS) /* cannot find correct handler */
+    {
+        GKI_freebuf(p_pkt);
+        return;
+    }
+    p_pkt->event = BTA_AV_MEDIA_DATA_EVT;
+    p_scb->seps[p_scb->sep_idx].p_app_data_cback(BTA_AV_MEDIA_DATA_EVT, (tBTA_AV_MEDIA*)p_pkt);
+    GKI_freebuf(p_pkt);  /* a copy of packet had been delivered, we free this buffer */
+}
+
+/*******************************************************************************
+**
 ** Function         bta_av_stream0_cback
 **
 ** Description      This is the AVDTP callback function for stream events.
@@ -650,16 +733,16 @@ static void bta_av_a2d_sdp_cback(BOOLEAN found, tA2D_Service *p_service)
 ** Returns
 **
 *******************************************************************************/
-static void bta_av_adjust_seps_idx(tBTA_AV_SCB *p_scb)
+static void bta_av_adjust_seps_idx(tBTA_AV_SCB *p_scb, UINT8 avdt_handle)
 {
-    int             xx;
-
+    int xx;
     APPL_TRACE_DEBUG1("bta_av_adjust_seps_idx codec_type: %d", p_scb->codec_type);
     for(xx=0; xx<BTA_AV_MAX_SEPS; xx++)
     {
         APPL_TRACE_DEBUG2("av_handle: %d codec_type: %d",
             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)
+        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      = xx;
             p_scb->avdt_handle  = p_scb->seps[xx].av_handle;
@@ -781,6 +864,10 @@ void bta_av_role_res (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
                 av_open.chnl   = p_scb->chnl;
                 av_open.hndl   = p_scb->hndl;
                 start.status = BTA_AV_FAIL_ROLE;
+                if(p_scb->seps[p_scb->sep_idx].tsep == AVDT_TSEP_SRC )
+                    av_open.sep = AVDT_TSEP_SNK;
+                else if(p_scb->seps[p_scb->sep_idx].tsep == AVDT_TSEP_SNK )
+                    av_open.sep = AVDT_TSEP_SRC;
                 (*bta_av_cb.p_cback)(BTA_AV_OPEN_EVT, (tBTA_AV *)&av_open);
             }
             else
@@ -830,6 +917,7 @@ void bta_av_do_disc_a2d (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
     UINT16              attr_list[] = {ATTR_ID_SERVICE_CLASS_ID_LIST,
                                        ATTR_ID_PROTOCOL_DESC_LIST,
                                        ATTR_ID_BT_PROFILE_DESC_LIST};
+    UINT16 sdp_uuid = 0; /* UUID for which SDP has to be done */
 
     APPL_TRACE_DEBUG3("bta_av_do_disc_a2d use_rc: %d rs:%d, oc:%d",
         p_data->api_open.use_rc, p_data->api_open.switch_res, bta_av_cb.audio_open_cnt);
@@ -922,8 +1010,14 @@ void bta_av_do_disc_a2d (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
         db_params.num_attr = 3;
         db_params.p_db = p_scb->p_disc_db;
         db_params.p_attrs = attr_list;
-
-        if(A2D_FindService(UUID_SERVCLASS_AUDIO_SINK, p_scb->peer_addr, &db_params,
+        p_scb->uuid_int = p_data->api_open.uuid;
+        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_DEBUG2("uuid_int 0x%x, Doing SDP For 0x%x", p_scb->uuid_int, sdp_uuid);
+        if(A2D_FindService(sdp_uuid, p_scb->peer_addr, &db_params,
                         bta_av_a2d_sdp_cback) == A2D_SUCCESS)
         {
             return;
@@ -1021,8 +1115,12 @@ void bta_av_config_ind (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
     tAVDT_SEP_INFO       *p_info;
     tAVDT_CFG            *p_evt_cfg = &p_data->str_msg.cfg;
     UINT8   psc_mask = (p_evt_cfg->psc_mask | p_scb->cfg.psc_mask);
+    UINT8 local_sep;    /* sep type of local handle on which connection was received */
+    UINT8 count = 0;
+    tBTA_AV_STR_MSG  *p_msg = (tBTA_AV_STR_MSG *)p_data;
     UNUSED(p_data);
 
+    local_sep = bta_av_get_scb_sep_type(p_scb, p_msg->handle);
     p_scb->avdt_label = p_data->str_msg.msg.hdr.label;
     memcpy(p_scb->cfg.codec_info, p_evt_cfg->codec_info, AVDT_CODEC_SIZE);
     p_scb->codec_type = p_evt_cfg->codec_info[BTA_AV_CODEC_TYPE_IDX];
@@ -1048,7 +1146,13 @@ void bta_av_config_ind (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
         p_info->in_use = 0;
         p_info->media_type = p_scb->media_type;
         p_info->seid = p_data->str_msg.msg.config_ind.int_seid;
-        p_info->tsep = AVDT_TSEP_SNK;
+
+        /* Sep type of Peer will be oppsite role to our local sep */
+        if (local_sep == AVDT_TSEP_SRC)
+            p_info->tsep = AVDT_TSEP_SNK;
+        else if (local_sep == AVDT_TSEP_SNK)
+            p_info->tsep = AVDT_TSEP_SRC;
+
         p_scb->role      |= BTA_AV_ROLE_AD_ACP;
         p_scb->cur_psc_mask = p_evt_cfg->psc_mask;
         if (bta_av_cb.features & BTA_AV_FEAT_RCTG)
@@ -1059,13 +1163,29 @@ void bta_av_config_ind (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
         p_scb->num_seps  = 1;
         p_scb->sep_info_idx = 0;
         APPL_TRACE_DEBUG3("bta_av_config_ind: SEID: %d use_rc: %d cur_psc_mask:0x%x", p_info->seid, p_scb->use_rc, p_scb->cur_psc_mask);
-
-        p_scb->p_cos->setcfg(p_scb->hndl, p_scb->codec_type,
+        /*  in case of A2DP SINK this is the first time peer data is being sent to co functions */
+        if (local_sep == AVDT_TSEP_SNK)
+        {
+            p_scb->p_cos->setcfg(p_scb->hndl, p_scb->codec_type,
+                             p_evt_cfg->codec_info,
+                             p_info->seid,
+                             p_scb->peer_addr,
+                             p_evt_cfg->num_protect,
+                             p_evt_cfg->protect_info,
+                             AVDT_TSEP_SNK,
+                             p_msg->handle);
+        }
+        else
+        {
+            p_scb->p_cos->setcfg(p_scb->hndl, p_scb->codec_type,
                              p_evt_cfg->codec_info,
                              p_info->seid,
                              p_scb->peer_addr,
                              p_evt_cfg->num_protect,
-                             p_evt_cfg->protect_info);
+                             p_evt_cfg->protect_info,
+                             AVDT_TSEP_SRC,
+                             p_msg->handle);
+        }
     }
 }
 
@@ -1153,12 +1273,21 @@ void bta_av_security_rsp (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
 void bta_av_setconfig_rsp (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
 {
     UINT8   num = p_data->ci_setconfig.num_seid + 1;
+    UINT8   avdt_handle = p_data->ci_setconfig.avdt_handle;
     UINT8   *p_seid = p_data->ci_setconfig.p_seid;
     int     i;
+    UINT8   local_sep;
 
     /* we like this codec_type. find the sep_idx */
-    bta_av_adjust_seps_idx(p_scb);
+    local_sep = bta_av_get_scb_sep_type(p_scb,avdt_handle);
+    bta_av_adjust_seps_idx(p_scb, avdt_handle);
     APPL_TRACE_DEBUG2("bta_av_setconfig_rsp: sep_idx: %d cur_psc_mask:0x%x", p_scb->sep_idx, p_scb->cur_psc_mask);
+    if ((AVDT_TSEP_SNK == local_sep) && (p_data->ci_setconfig.err_code == AVDT_SUCCESS) &&
+                                     (p_scb->seps[p_scb->sep_idx].p_app_data_cback != NULL))
+        p_scb->seps[p_scb->sep_idx].p_app_data_cback(BTA_AV_MEDIA_SINK_CFG_EVT,
+                                              (tBTA_AV_MEDIA*)p_scb->cfg.codec_info);
+
+
     AVDT_ConfigRsp(p_scb->avdt_handle, p_scb->avdt_label, p_data->ci_setconfig.err_code,
                    p_data->ci_setconfig.category);
 
@@ -1182,8 +1311,11 @@ void bta_av_setconfig_rsp (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
         if (p_scb->codec_type == BTA_AV_CODEC_SBC || num > 1)
         {
             /* if SBC is used by the SNK as INT, discover req is not sent in bta_av_config_ind.
-             * call disc_res now */
-            p_scb->p_cos->disc_res(p_scb->hndl, num, num, p_scb->peer_addr);
+                       * call disc_res now */
+           /* this is called in A2DP SRC path only, In case of SINK we don't need it  */
+            if (local_sep == AVDT_TSEP_SRC)
+                p_scb->p_cos->disc_res(p_scb->hndl, num, num, 0, p_scb->peer_addr,
+                                                      UUID_SERVCLASS_AUDIO_SOURCE);
         }
         else
         {
@@ -1202,7 +1334,9 @@ void bta_av_setconfig_rsp (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
             p_scb->sep_info[i].media_type = p_scb->media_type;
             p_scb->sep_info[i].seid = p_seid[i-1];
         }
-        bta_av_next_getcap(p_scb, p_data);
+        /* only in case of local sep as SRC we need to look for other SEPs, In case of SINK we don't */
+        if (local_sep == AVDT_TSEP_SRC)
+            bta_av_next_getcap(p_scb, p_data);
     }
 }
 
@@ -1275,6 +1409,11 @@ void bta_av_str_opened (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
 #if( defined BTA_AR_INCLUDED ) && (BTA_AR_INCLUDED == TRUE)
         bta_ar_avdt_conn(BTA_ID_AV, open.bd_addr);
 #endif
+        if (p_scb->seps[p_scb->sep_idx].tsep == AVDT_TSEP_SRC )
+            open.sep = AVDT_TSEP_SNK;
+        else if (p_scb->seps[p_scb->sep_idx].tsep == AVDT_TSEP_SNK )
+            open.sep = AVDT_TSEP_SRC;
+
         (*bta_av_cb.p_cback)(BTA_AV_OPEN_EVT, (tBTA_AV *) &open);
         if(open.starting)
         {
@@ -1436,8 +1575,11 @@ void bta_av_sdp_failed (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
 *******************************************************************************/
 void bta_av_disc_results (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
 {
-    UINT8 num_snks = 0, i;
+    UINT8 num_snks = 0, num_srcs =0, i;
+    /* our uuid in case we initiate connection */
+    UINT16 uuid_int = p_scb->uuid_int;
 
+    APPL_TRACE_DEBUG1(" initiator UUID 0x%x", uuid_int);
     /* store number of stream endpoints returned */
     p_scb->num_seps = p_data->str_msg.msg.discover_cfm.num_seps;
 
@@ -1445,15 +1587,23 @@ void bta_av_disc_results (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
     {
         /* steam not in use, is a sink, and is audio */
         if ((p_scb->sep_info[i].in_use == FALSE) &&
-            (p_scb->sep_info[i].tsep == AVDT_TSEP_SNK) &&
             (p_scb->sep_info[i].media_type == p_scb->media_type))
         {
-            num_snks++;
+            if((p_scb->sep_info[i].tsep == AVDT_TSEP_SNK) &&
+               (uuid_int == UUID_SERVCLASS_AUDIO_SOURCE))
+                num_snks++;
+
+            if((p_scb->sep_info[i].tsep == AVDT_TSEP_SRC) &&
+               (uuid_int == UUID_SERVCLASS_AUDIO_SINK))
+                num_srcs++;
+
         }
     }
 
-    p_scb->p_cos->disc_res(p_scb->hndl, p_scb->num_seps, num_snks, p_scb->peer_addr);
+    p_scb->p_cos->disc_res(p_scb->hndl, p_scb->num_seps, num_snks, num_srcs, p_scb->peer_addr,
+                                                                                    uuid_int);
     p_scb->num_disc_snks = num_snks;
+    p_scb->num_disc_srcs = num_srcs;
 
     /* if we got any */
     if (p_scb->num_seps > 0)
@@ -1501,9 +1651,10 @@ void bta_av_disc_res_as_acp (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
             num_snks++;
         }
     }
-
-    p_scb->p_cos->disc_res(p_scb->hndl, p_scb->num_seps, num_snks, p_scb->peer_addr);
+    p_scb->p_cos->disc_res(p_scb->hndl, p_scb->num_seps, num_snks, 0, p_scb->peer_addr,
+                                                          UUID_SERVCLASS_AUDIO_SOURCE);
     p_scb->num_disc_snks = num_snks;
+    p_scb->num_disc_srcs = 0;
 
     /* if we got any */
     if (p_scb->num_seps > 0)
@@ -1648,6 +1799,11 @@ void bta_av_open_failed (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
         /* set the state back to initial state */
         bta_av_set_scb_sst_init(p_scb);
 
+        if (p_scb->seps[p_scb->sep_idx].tsep == AVDT_TSEP_SRC )
+            open.sep = AVDT_TSEP_SNK;
+        else if (p_scb->seps[p_scb->sep_idx].tsep == AVDT_TSEP_SNK )
+            open.sep = AVDT_TSEP_SRC;
+
         (*bta_av_cb.p_cback)(BTA_AV_OPEN_EVT, (tBTA_AV *) &open);
 
     }
@@ -1674,6 +1830,7 @@ void bta_av_getcap_results (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
     tAVDT_CFG   cfg;
     UINT8       media_type;
     tAVDT_SEP_INFO  *p_info = &p_scb->sep_info[p_scb->sep_info_idx];
+    UINT16 uuid_int; /* UUID for which connection was initiatied */
 
     memcpy(&cfg, &p_scb->cfg, sizeof(tAVDT_CFG));
     cfg.num_codec = 1;
@@ -1702,11 +1859,26 @@ void bta_av_getcap_results (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
         /* save copy of codec type and configuration */
         p_scb->codec_type = cfg.codec_info[BTA_AV_CODEC_TYPE_IDX];
         memcpy(&p_scb->cfg, &cfg, sizeof(tAVDT_CFG));
-        bta_av_adjust_seps_idx(p_scb);
+
+        uuid_int = p_scb->uuid_int;
+        APPL_TRACE_DEBUG1(" initiator UUID = 0x%x ", uuid_int);
+        if (uuid_int == UUID_SERVCLASS_AUDIO_SOURCE)
+            bta_av_adjust_seps_idx(p_scb, bta_av_get_scb_handle(p_scb, AVDT_TSEP_SRC));
+        else if (uuid_int == UUID_SERVCLASS_AUDIO_SINK)
+            bta_av_adjust_seps_idx(p_scb, bta_av_get_scb_handle(p_scb, AVDT_TSEP_SNK));
+
         /* use only the services peer supports */
         cfg.psc_mask &= p_scb->p_cap->psc_mask;
         p_scb->cur_psc_mask = cfg.psc_mask;
 
+        if ((uuid_int == UUID_SERVCLASS_AUDIO_SINK) &&
+            (p_scb->seps[p_scb->sep_idx].p_app_data_cback != NULL))
+        {
+            APPL_TRACE_DEBUG0(" Configure Deoder for Sink Connection ");
+            p_scb->seps[p_scb->sep_idx].p_app_data_cback(BTA_AV_MEDIA_SINK_CFG_EVT,
+                     (tBTA_AV_MEDIA*)p_scb->cfg.codec_info);
+        }
+
         /* open the stream */
         AVDT_OpenReq(p_scb->seps[p_scb->sep_idx].av_handle, p_scb->peer_addr,
                      p_scb->sep_info[p_scb->sep_info_idx].seid, &cfg);
@@ -1738,9 +1910,12 @@ void bta_av_getcap_results (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
 void bta_av_setconfig_rej (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
 {
     tBTA_AV_REJECT reject;
+    UINT8   avdt_handle = p_data->ci_setconfig.avdt_handle;
+
+    bta_av_adjust_seps_idx(p_scb, avdt_handle);
+    APPL_TRACE_DEBUG1("bta_av_setconfig_rej: sep_idx: %d",p_scb->sep_idx);
+    AVDT_ConfigRsp(p_scb->avdt_handle, p_scb->avdt_label, AVDT_ERR_UNSUP_CFG, 0);
 
-    APPL_TRACE_DEBUG0("bta_av_setconfig_rej");
-    AVDT_ConfigRsp(p_data->str_msg.handle, p_data->str_msg.msg.hdr.label, AVDT_ERR_BAD_STATE, 0);
     bdcpy(reject.bd_addr, p_data->str_msg.bd_addr);
     reject.hndl = p_scb->hndl;
     (*bta_av_cb.p_cback)(BTA_AV_REJECT_EVT, (tBTA_AV *) &reject);
@@ -2129,6 +2304,13 @@ void bta_av_start_ok (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
     if (new_role & BTA_AV_ROLE_START_INT)
         initiator = TRUE;
 
+    /* for A2DP SINK we do not send get_caps */
+    if ((p_scb->avdt_handle == p_scb->seps[p_scb->sep_idx].av_handle)
+         &&(p_scb->seps[p_scb->sep_idx].tsep == AVDT_TSEP_SNK))
+    {
+        p_scb->wait &= ~(BTA_AV_WAIT_ACP_CAPS_ON);
+        APPL_TRACE_DEBUG1(" Local SEP type is SNK  new wait is 0x%x",p_scb->wait);
+    }
     if (p_scb->wait & BTA_AV_WAIT_ROLE_SW_FAILED)
     {
         /* role switch has failed */
@@ -2322,6 +2504,12 @@ void bta_av_str_closed (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
         data.open.status = p_scb->open_status;
         data.open.chnl   = p_scb->chnl;
         data.open.hndl   = p_scb->hndl;
+
+        if (p_scb->seps[p_scb->sep_idx].tsep == AVDT_TSEP_SRC )
+            data.open.sep = AVDT_TSEP_SNK;
+        else if (p_scb->seps[p_scb->sep_idx].tsep == AVDT_TSEP_SNK )
+            data.open.sep = AVDT_TSEP_SRC;
+
         event = BTA_AV_OPEN_EVT;
         p_scb->open_status = BTA_AV_SUCCESS;
 
@@ -2683,7 +2871,7 @@ void bta_av_rcfg_open (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
 {
     UNUSED(p_data);
 
-    APPL_TRACE_DEBUG1("bta_av_rcfg_open, num_disc_snks = %d", p_scb->num_disc_snks);
+       APPL_TRACE_DEBUG1("bta_av_rcfg_open, num_disc_snks = %d", p_scb->num_disc_snks);
 
     if (p_scb->num_disc_snks == 0)
     {
@@ -2699,7 +2887,7 @@ void bta_av_rcfg_open (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
         memcpy(p_scb->cfg.codec_info, p_scb->p_cap->codec_info, AVDT_CODEC_SIZE);
         /* we may choose to use a different SEP at reconfig.
          * adjust the sep_idx now */
-        bta_av_adjust_seps_idx(p_scb);
+        bta_av_adjust_seps_idx(p_scb, bta_av_get_scb_handle(p_scb, AVDT_TSEP_SRC));
 
         /* open the stream with the new config */
         p_scb->sep_info_idx = p_scb->rcfg_idx;
index 1637adc..54e7aba 100644 (file)
@@ -1996,6 +1996,11 @@ void bta_av_dereg_comp(tBTA_AV_DATA *p_data)
 #endif
                 bta_av_del_sdp_rec(&p_cb->sdp_a2d_handle);
                 bta_sys_remove_uuid(UUID_SERVCLASS_AUDIO_SOURCE);
+
+#ifdef BTA_AVK_INCLUDED
+                bta_av_del_sdp_rec(&p_cb->sdp_a2d_snk_handle);
+                bta_sys_remove_uuid(UUID_SERVCLASS_AUDIO_SINK);
+#endif
             }
         }
         else
index 9b07399..47cc2aa 100644 (file)
@@ -109,7 +109,7 @@ void BTA_AvDisable(void)
 ** Returns          void
 **
 *******************************************************************************/
-void BTA_AvRegister(tBTA_AV_CHNL chnl, const char *p_service_name, UINT8 app_id)
+void BTA_AvRegister(tBTA_AV_CHNL chnl, const char *p_service_name, UINT8 app_id, tBTA_AV_DATA_CBACK  *p_data_cback)
 {
     tBTA_AV_API_REG  *p_buf;
 
@@ -128,6 +128,7 @@ void BTA_AvRegister(tBTA_AV_CHNL chnl, const char *p_service_name, UINT8 app_id)
             p_buf->p_service_name[0] = 0;
         }
         p_buf->app_id = app_id;
+        p_buf->p_app_data_cback = p_data_cback;
         bta_sys_sendmsg(p_buf);
     }
 }
@@ -164,7 +165,8 @@ void BTA_AvDeregister(tBTA_AV_HNDL hndl)
 ** Returns          void
 **
 *******************************************************************************/
-void BTA_AvOpen(BD_ADDR bd_addr, tBTA_AV_HNDL handle, BOOLEAN use_rc, tBTA_SEC sec_mask)
+void BTA_AvOpen(BD_ADDR bd_addr, tBTA_AV_HNDL handle, BOOLEAN use_rc, tBTA_SEC sec_mask,
+                                                                             UINT16 uuid)
 {
     tBTA_AV_API_OPEN  *p_buf;
 
@@ -176,6 +178,7 @@ void BTA_AvOpen(BD_ADDR bd_addr, tBTA_AV_HNDL handle, BOOLEAN use_rc, tBTA_SEC s
         p_buf->use_rc = use_rc;
         p_buf->sec_mask = sec_mask;
         p_buf->switch_res = BTA_AV_RS_NONE;
+        p_buf->uuid = uuid;
         bta_sys_sendmsg(p_buf);
     }
 }
@@ -244,6 +247,31 @@ void BTA_AvStart(void)
 
 /*******************************************************************************
 **
+** Function         BTA_AvEnable_Sink
+**
+** Description      Enable/Disable A2DP Sink..
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_AvEnable_Sink(int enable)
+{
+    BT_HDR  *p_buf;
+
+#ifdef BTA_AVK_INCLUDED
+    if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+    {
+        p_buf->event = BTA_AV_API_SINK_ENABLE_EVT;
+        p_buf->layer_specific = enable;
+        bta_sys_sendmsg(p_buf);
+    }
+#else
+    return;
+#endif
+}
+
+/*******************************************************************************
+**
 ** Function         BTA_AvStop
 **
 ** Description      Stop audio/video stream data transfer.
index a1c2ac0..2da1d97 100644 (file)
@@ -68,7 +68,7 @@ void bta_av_ci_src_data_ready(tBTA_AV_CHNL chnl)
 **
 *******************************************************************************/
 void bta_av_ci_setconfig(tBTA_AV_HNDL hndl, UINT8 err_code, UINT8 category,
-                         UINT8 num_seid, UINT8 *p_seid, BOOLEAN recfg_needed)
+                         UINT8 num_seid, UINT8 *p_seid, BOOLEAN recfg_needed, UINT8 avdt_handle)
 {
     tBTA_AV_CI_SETCONFIG  *p_buf;
 
@@ -81,6 +81,7 @@ void bta_av_ci_setconfig(tBTA_AV_HNDL hndl, UINT8 err_code, UINT8 category,
         p_buf->category = category;
         p_buf->recfg_needed = recfg_needed;
         p_buf->num_seid = num_seid;
+        p_buf->avdt_handle= avdt_handle;
         if(p_seid && num_seid)
         {
             p_buf->p_seid   = (UINT8 *)(p_buf + 1);
index cd22bcb..bbef8c5 100644 (file)
@@ -96,6 +96,9 @@ enum
     BTA_AV_AVRC_CLOSE_EVT,
     BTA_AV_CONN_CHG_EVT,
     BTA_AV_DEREG_COMP_EVT,
+#ifdef BTA_AVK_INCLUDED
+    BTA_AV_API_SINK_ENABLE_EVT,
+#endif
 #if (AVDT_REPORTING == TRUE)
     BTA_AV_AVDT_RPT_CONN_EVT,
 #endif
@@ -156,16 +159,15 @@ enum
 /* function types for call-out functions */
 typedef BOOLEAN (*tBTA_AV_CO_INIT) (UINT8 *p_codec_type, UINT8 *p_codec_info,
                                    UINT8 *p_num_protect, UINT8 *p_protect_info, UINT8 index);
-
 typedef void (*tBTA_AV_CO_DISC_RES) (tBTA_AV_HNDL hndl, UINT8 num_seps,
-                                     UINT8 num_snk, BD_ADDR addr);
-
+                                     UINT8 num_snk, UINT8 num_src, BD_ADDR addr, UINT16 uuid_local);
 typedef UINT8 (*tBTA_AV_CO_GETCFG) (tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type,
                                      UINT8 *p_codec_info, UINT8 *p_sep_info_idx, UINT8 seid,
                                      UINT8 *p_num_protect, UINT8 *p_protect_info);
 typedef void (*tBTA_AV_CO_SETCFG) (tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type,
-                                    UINT8 *p_codec_info, UINT8 seid, BD_ADDR addr,
-                                    UINT8 num_protect, UINT8 *p_protect_info);
+                                     UINT8 *p_codec_info, UINT8 seid, BD_ADDR addr,
+                                     UINT8 num_protect, UINT8 *p_protect_info,
+                                     UINT8 t_local_sep, UINT8 avdt_handle);
 typedef void (*tBTA_AV_CO_OPEN) (tBTA_AV_HNDL hndl,
                                  tBTA_AV_CODEC codec_type, UINT8 *p_codec_info,
                                    UINT16 mtu);
@@ -206,6 +208,7 @@ typedef struct
     BT_HDR              hdr;
     char                p_service_name[BTA_SERVICE_NAME_LEN+1];
     UINT8               app_id;
+    tBTA_AV_DATA_CBACK       *p_app_data_cback;
 } tBTA_AV_API_REG;
 
 
@@ -225,6 +228,7 @@ typedef struct
     BOOLEAN             use_rc;
     tBTA_SEC            sec_mask;
     tBTA_AV_RS_RES      switch_res;
+    UINT16              uuid;  /* uuid of initiator */
 } tBTA_AV_API_OPEN;
 
 /* data type for BTA_AV_API_STOP_EVT */
@@ -319,6 +323,7 @@ typedef struct
     UINT8               num_seid;
     UINT8               *p_seid;
     BOOLEAN             recfg_needed;
+    UINT8               avdt_handle;  /* local sep type for which this stream will be set up */
 } tBTA_AV_CI_SETCONFIG;
 
 /* data type for all stream events from AVDTP */
@@ -376,8 +381,10 @@ typedef struct
 /* type for SEP control block */
 typedef struct
 {
-    UINT8               av_handle;      /* AVDTP handle */
-    tBTA_AV_CODEC       codec_type;     /* codec type */
+    UINT8               av_handle;         /* AVDTP handle */
+    tBTA_AV_CODEC       codec_type;        /* codec type */
+    UINT8               tsep;              /* SEP type of local SEP */
+    tBTA_AV_DATA_CBACK  *p_app_data_cback; /* Application callback for media packets */
 } tBTA_AV_SEP;
 
 
@@ -483,6 +490,7 @@ typedef struct
     UINT8               hdi;            /* the index to SCB[] */
     UINT8               num_seps;       /* number of seps returned by stream discovery */
     UINT8               num_disc_snks;  /* number of discovered snks */
+    UINT8               num_disc_srcs;  /* number of discovered srcs */
     UINT8               sep_info_idx;   /* current index into sep_info */
     UINT8               sep_idx;        /* current index into local seps[] */
     UINT8               rcfg_idx;       /* reconfig requested index into sep_info */
@@ -505,6 +513,7 @@ typedef struct
     UINT8               wait;           /* set 0x1, when getting Caps as ACP, set 0x2, when started */
     UINT8               q_tag;          /* identify the associated q_info union member */
     BOOLEAN             no_rtp_hdr;     /* TRUE if add no RTP header*/
+    UINT16              uuid_int;       /*intended UUID of Initiator to connect to */
 } tBTA_AV_SCB;
 
 #define BTA_AV_RC_ROLE_MASK     0x10
@@ -554,6 +563,9 @@ typedef struct
     TIMER_LIST_ENT      sig_tmr;        /* link timer */
     TIMER_LIST_ENT      acp_sig_tmr;    /* timer to monitor signalling when accepting */
     UINT32              sdp_a2d_handle; /* SDP record handle for audio src */
+#ifdef BTA_AVK_INCLUDED
+    UINT32              sdp_a2d_snk_handle; /* SDP record handle for audio snk */
+#endif
     UINT32              sdp_vdp_handle; /* SDP record handle for video src */
     tBTA_AV_FEAT        features;       /* features mask */
     tBTA_SEC            sec_mask;       /* security mask */
@@ -601,6 +613,7 @@ extern const tBTA_AV_SACT bta_av_a2d_action[];
 extern const tBTA_AV_CO_FUNCTS bta_av_a2d_cos;
 extern const tBTA_AV_SACT bta_av_vdp_action[];
 extern tAVDT_CTRL_CBACK * const bta_av_dt_cback[];
+extern void bta_av_stream_data_cback(UINT8 handle, BT_HDR *p_pkt, UINT32 time_stamp, UINT8 m_pt);
 
 /*****************************************************************************
 **  Function prototypes
index 25c40a5..20ed161 100644 (file)
@@ -41,6 +41,8 @@
 *****************************************************************************/
 
 /* AVDTP protocol timeout values */
+#define BTIF_AVK_SERVICE_NAME "Advanced Audio Sink"
+
 #ifndef BTA_AV_RET_TOUT
 #define BTA_AV_RET_TOUT     4
 #endif
@@ -150,6 +152,9 @@ static const tBTA_AV_ST_TBL bta_av_st_tbl[] =
 typedef void (*tBTA_AV_NSM_ACT)(tBTA_AV_DATA *p_data);
 static void bta_av_api_enable(tBTA_AV_DATA *p_data);
 static void bta_av_api_register(tBTA_AV_DATA *p_data);
+#ifdef BTA_AVK_INCLUDED
+static void bta_av_api_sink_enable(tBTA_AV_DATA *p_data);
+#endif
 static void bta_av_ci_data(tBTA_AV_DATA *p_data);
 #if (AVDT_REPORTING == TRUE)
 static void bta_av_rpc_conn(tBTA_AV_DATA *p_data);
@@ -175,6 +180,9 @@ const tBTA_AV_NSM_ACT bta_av_nsm_act[] =
     bta_av_rc_closed,       /* BTA_AV_AVRC_CLOSE_EVT */
     bta_av_conn_chg,        /* BTA_AV_CONN_CHG_EVT */
     bta_av_dereg_comp,      /* BTA_AV_DEREG_COMP_EVT */
+#ifdef BTA_AVK_INCLUDED
+    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 */
 #endif
@@ -459,6 +467,49 @@ static void bta_av_a2dp_report_cback(UINT8 handle, AVDT_REPORT_TYPE type,
 }
 #endif
 
+#ifdef BTA_AVK_INCLUDED
+/*******************************************************************************
+**
+** Function         bta_av_api_sink_enable
+**
+** Description      activate, deactive A2DP Sink,
+**
+** Returns          void
+**
+*******************************************************************************/
+
+static void bta_av_api_sink_enable(tBTA_AV_DATA *p_data)
+{
+    UINT16 activate_sink = 0;
+    activate_sink = p_data->hdr.layer_specific;
+    APPL_TRACE_DEBUG1("bta_av_api_sink_enable %d ", activate_sink)
+    char p_service_name[BTA_SERVICE_NAME_LEN+1];
+    BCM_STRNCPY_S(p_service_name, sizeof(p_service_name),
+            BTIF_AVK_SERVICE_NAME, BTA_SERVICE_NAME_LEN);
+
+    if(activate_sink)
+    {
+        AVDT_SINK_Activate();
+        if (bta_av_cb.sdp_a2d_snk_handle == 0)
+        {
+            bta_av_cb.sdp_a2d_snk_handle = SDP_CreateRecord();
+            A2D_AddRecord(UUID_SERVCLASS_AUDIO_SINK, p_service_name, NULL,
+                          A2D_SUPF_PLAYER, bta_av_cb.sdp_a2d_snk_handle);
+            bta_sys_add_uuid(UUID_SERVCLASS_AUDIO_SINK);
+        }
+    }
+    else
+    {
+        AVDT_SINK_Deactivate();
+        if (bta_av_cb.sdp_a2d_snk_handle != 0)
+        {
+            SDP_DeleteRecord(bta_av_cb.sdp_a2d_snk_handle);
+            bta_av_cb.sdp_a2d_snk_handle = 0;
+            bta_sys_remove_uuid(UUID_SERVCLASS_AUDIO_SINK);
+        }
+    }
+}
+#endif
 /*******************************************************************************
 **
 ** Function         bta_av_api_register
@@ -480,6 +531,8 @@ static void bta_av_api_register(tBTA_AV_DATA *p_data)
     tBTA_AV_CODEC   codec_type;
     tBTA_UTL_COD    cod;
     UINT8           index = 0;
+    char p_avk_service_name[BTA_SERVICE_NAME_LEN+1];
+    BCM_STRNCPY_S(p_avk_service_name, sizeof(p_avk_service_name), BTIF_AVK_SERVICE_NAME, BTA_SERVICE_NAME_LEN);
 
     memset(&cs,0,sizeof(tAVDT_CS));
 
@@ -534,7 +587,11 @@ static void bta_av_api_register(tBTA_AV_DATA *p_data)
             }
 
             /* Set the Capturing service class bit */
+#ifdef BTA_AVK_INCLUDED
+            cod.service = BTM_COD_SERVICE_CAPTURING | BTM_COD_SERVICE_RENDERING;
+#else
             cod.service = BTM_COD_SERVICE_CAPTURING;
+#endif
             utl_set_device_class(&cod, BTA_UTL_SET_COD_SERVICE_CLASS);
         } /* if 1st channel */
 
@@ -594,9 +651,27 @@ static void bta_av_api_register(tBTA_AV_DATA *p_data)
                 (*bta_av_a2d_cos.init)(&codec_type, cs.cfg.codec_info,
                 &cs.cfg.num_protect, cs.cfg.protect_info, index) == TRUE)
             {
+
+#ifdef BTA_AVK_INCLUDED
+            if(index == 1)
+            {
+                cs.tsep = AVDT_TSEP_SNK;
+                cs.p_data_cback = bta_av_stream_data_cback;
+            }
+                APPL_TRACE_DEBUG1(" SEP Type = %d",cs.tsep);
+#endif
                 if(AVDT_CreateStream(&p_scb->seps[index].av_handle, &cs) == AVDT_SUCCESS)
                 {
                     p_scb->seps[index].codec_type = codec_type;
+
+#ifdef BTA_AVK_INCLUDED
+                    p_scb->seps[index].tsep = cs.tsep;
+                    if(cs.tsep == AVDT_TSEP_SNK)
+                        p_scb->seps[index].p_app_data_cback = p_data->api_reg.p_app_data_cback;
+                    else
+                        p_scb->seps[index].p_app_data_cback = NULL; /* In case of A2DP SOURCE we don't need a callback to handle media packets */
+#endif
+
                     APPL_TRACE_DEBUG3("audio[%d] av_handle: %d codec_type: %d",
                         index, p_scb->seps[index].av_handle, p_scb->seps[index].codec_type);
                     index++;
@@ -613,6 +688,12 @@ static void bta_av_api_register(tBTA_AV_DATA *p_data)
                                   A2D_SUPF_PLAYER, bta_av_cb.sdp_a2d_handle);
                 bta_sys_add_uuid(UUID_SERVCLASS_AUDIO_SOURCE);
 
+#ifdef BTA_AVK_INCLUDED
+                bta_av_cb.sdp_a2d_snk_handle = SDP_CreateRecord();
+                A2D_AddRecord(UUID_SERVCLASS_AUDIO_SINK, p_avk_service_name, NULL,
+                                  A2D_SUPF_PLAYER, bta_av_cb.sdp_a2d_snk_handle);
+                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);
@@ -1318,6 +1399,9 @@ char *bta_av_evt_code(UINT16 evt_code)
     case BTA_AV_AVRC_CLOSE_EVT: return "AVRC_CLOSE";
     case BTA_AV_CONN_CHG_EVT: return "CONN_CHG";
     case BTA_AV_DEREG_COMP_EVT: return "DEREG_COMP";
+#ifdef BTA_AVK_INCLUDED
+    case BTA_AV_API_SINK_ENABLE_EVT: return "SINK_ENABLE";
+#endif
 #if (AVDT_REPORTING == TRUE)
     case BTA_AV_AVDT_RPT_CONN_EVT: return "RPT_CONN";
 #endif
index a570375..af1b3ec 100644 (file)
@@ -511,6 +511,78 @@ UINT8 bta_av_sbc_cfg_for_cap(UINT8 *p_peer, tA2D_SBC_CIE *p_cap, tA2D_SBC_CIE *p
 
 /*******************************************************************************
 **
+** Function         bta_av_sbc_cfg_matches_cap
+**
+** Description      This function checks whether an SBC codec configuration
+**                  matched with capabilities. Here we check subset.
+**
+** Returns          0 if ok, nonzero if error.
+**
+*******************************************************************************/
+UINT8 bta_av_sbc_cfg_matches_cap(UINT8 *p_cfg, tA2D_SBC_CIE *p_cap)
+{
+    UINT8           status = 0;
+    tA2D_SBC_CIE    cfg_cie;
+
+    /* parse configuration */
+    if ((status = A2D_ParsSbcInfo(&cfg_cie, p_cfg, TRUE)) != 0)
+    {
+        APPL_TRACE_ERROR1(" bta_av_sbc_cfg_matches_cap Parsing Failed %d", status);
+        return status;
+    }
+
+    /* verify that each parameter is in range */
+
+    APPL_TRACE_DEBUG2(" FREQ peer: 0%x, capability  0%x", cfg_cie.samp_freq, p_cap->samp_freq);
+    APPL_TRACE_DEBUG2(" CH_MODE peer: 0%x, capability  0%x", cfg_cie.ch_mode, p_cap->ch_mode);
+    APPL_TRACE_DEBUG2(" BLOCK_LEN peer: 0%x, capability  0%x", cfg_cie.block_len, p_cap->block_len);
+    APPL_TRACE_DEBUG2(" SUB_BAND peer: 0%x, capability  0%x", cfg_cie.num_subbands, p_cap->num_subbands);
+    APPL_TRACE_DEBUG2(" ALLOC_MTHD peer: 0%x, capability  0%x", cfg_cie.alloc_mthd, p_cap->alloc_mthd);
+    APPL_TRACE_DEBUG2(" MAX_BitPool peer: 0%x, capability  0%x", cfg_cie.max_bitpool, p_cap->max_bitpool);
+    APPL_TRACE_DEBUG2(" Min_bitpool peer: 0%x, capability  0%x", cfg_cie.min_bitpool, p_cap->min_bitpool);
+
+    /* sampling frequency */
+    if ((cfg_cie.samp_freq & p_cap->samp_freq) == 0)
+    {
+        status = A2D_NS_SAMP_FREQ;
+    }
+    /* channel mode */
+    else if ((cfg_cie.ch_mode & p_cap->ch_mode) == 0)
+    {
+        status = A2D_NS_CH_MODE;
+    }
+    /* block length */
+    else if ((cfg_cie.block_len & p_cap->block_len) == 0)
+    {
+        status = A2D_BAD_BLOCK_LEN;
+    }
+    /* subbands */
+    else if ((cfg_cie.num_subbands & p_cap->num_subbands) == 0)
+    {
+        status = A2D_NS_SUBBANDS;
+    }
+    /* allocation method */
+    else if ((cfg_cie.alloc_mthd & p_cap->alloc_mthd) == 0)
+    {
+        status = A2D_NS_ALLOC_MTHD;
+    }
+    /* max bitpool */
+    else if (cfg_cie.max_bitpool > p_cap->max_bitpool)
+    {
+        status = A2D_NS_MAX_BITPOOL;
+    }
+    /* min bitpool */
+    else if (cfg_cie.min_bitpool < p_cap->min_bitpool)
+    {
+        status = A2D_NS_MIN_BITPOOL;
+    }
+
+    return status;
+}
+
+
+/*******************************************************************************
+**
 ** Function         bta_av_sbc_cfg_in_cap
 **
 ** Description      This function checks whether an SBC codec configuration
@@ -532,6 +604,7 @@ UINT8 bta_av_sbc_cfg_in_cap(UINT8 *p_cfg, tA2D_SBC_CIE *p_cap)
 
     /* verify that each parameter is in range */
 
+
     /* sampling frequency */
     if ((cfg_cie.samp_freq & p_cap->samp_freq) == 0)
     {
index 407146e..5756c88 100644 (file)
@@ -162,7 +162,7 @@ static const UINT8 bta_av_sst_incoming[][BTA_AV_NUM_COLS] =
 /* API_RC_OPEN_EVT  */      {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INCOMING_SST },
 /* SRC_DATA_READY_EVT */    {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INCOMING_SST },
 /* CI_SETCONFIG_OK_EVT */   {BTA_AV_SETCONFIG_RSP,  BTA_AV_ST_RC_TIMER,    BTA_AV_INCOMING_SST },
-/* CI_SETCONFIG_FAIL_EVT */ {BTA_AV_SETCONFIG_RSP,  BTA_AV_CLEANUP,        BTA_AV_INIT_SST },
+/* CI_SETCONFIG_FAIL_EVT */ {BTA_AV_SETCONFIG_REJ,  BTA_AV_CLEANUP,        BTA_AV_INIT_SST },
 /* SDP_DISC_OK_EVT */       {BTA_AV_FREE_SDB,       BTA_AV_SIGNORE,        BTA_AV_INCOMING_SST },
 /* SDP_DISC_FAIL_EVT */     {BTA_AV_FREE_SDB,       BTA_AV_SIGNORE,        BTA_AV_INCOMING_SST },
 /* STR_DISC_OK_EVT */       {BTA_AV_DISC_RES_AS_ACP,BTA_AV_SIGNORE,        BTA_AV_INCOMING_SST },
index 1ea570c..22ee91c 100644 (file)
@@ -249,8 +249,11 @@ typedef UINT8 tBTA_AV_ERR;
 #define BTA_AV_META_MSG_EVT     17      /* metadata messages */
 #define BTA_AV_REJECT_EVT       18      /* incoming connection rejected */
 #define BTA_AV_RC_FEAT_EVT      19      /* remote control channel peer supported features update */
+#define BTA_AV_MEDIA_SINK_CFG_EVT    20      /* command to configure codec */
+#define BTA_AV_MEDIA_DATA_EVT   21      /* sending data to Media Task */
 /* Max BTA event */
-#define BTA_AV_MAX_EVT          20
+#define BTA_AV_MAX_EVT          22
+
 
 typedef UINT8 tBTA_AV_EVT;
 
@@ -282,6 +285,7 @@ typedef struct
     tBTA_AV_STATUS  status;
     BOOLEAN         starting;
     tBTA_AV_EDR     edr;        /* 0, if peer device does not support EDR */
+    UINT8           sep;        /*  sep type of peer device */
 } tBTA_AV_OPEN;
 
 /* data associated with BTA_AV_CLOSE_EVT */
@@ -446,6 +450,13 @@ typedef union
     tBTA_AV_RC_FEAT     rc_feat;
 } tBTA_AV;
 
+/* union of data associated with AV Media callback */
+typedef union
+{
+    BT_HDR     *p_data;
+    UINT8      *codec_info;
+} tBTA_AV_MEDIA;
+
 
 #define BTA_AVC_PACKET_LEN                  AVRC_PACKET_LEN
 #define BTA_VENDOR_DATA_OFFSET              6
@@ -464,6 +475,7 @@ typedef union
 
 /* AV callback */
 typedef void (tBTA_AV_CBACK)(tBTA_AV_EVT event, tBTA_AV *p_data);
+typedef void (tBTA_AV_DATA_CBACK)(tBTA_AV_EVT event, tBTA_AV_MEDIA *p_data);
 
 /* type for stream state machine action functions */
 typedef void (*tBTA_AV_ACT)(void *p_cb, void *p_data);
@@ -548,7 +560,7 @@ BTA_API void BTA_AvDisable(void);
 **
 *******************************************************************************/
 BTA_API void BTA_AvRegister(tBTA_AV_CHNL chnl, const char *p_service_name,
-                            UINT8 app_id);
+                            UINT8 app_id, tBTA_AV_DATA_CBACK  *p_data_cback);
 
 /*******************************************************************************
 **
@@ -573,7 +585,7 @@ BTA_API void BTA_AvDeregister(tBTA_AV_HNDL hndl);
 **
 *******************************************************************************/
 BTA_API void BTA_AvOpen(BD_ADDR bd_addr, tBTA_AV_HNDL handle,
-                        BOOLEAN use_rc, tBTA_SEC sec_mask);
+                        BOOLEAN use_rc, tBTA_SEC sec_mask, UINT16 uuid);
 
 /*******************************************************************************
 **
@@ -599,6 +611,17 @@ BTA_API void BTA_AvDisconnect(BD_ADDR bd_addr);
 
 /*******************************************************************************
 **
+** Function         BTA_AvEnable_Sink
+**
+** Description      Enable/Disable A2DP Sink.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_AvEnable_Sink(int enable);
+
+/*******************************************************************************
+**
 ** Function         BTA_AvStart
 **
 ** Description      Start audio/video stream data transfer.
index 63668a9..faad260 100644 (file)
@@ -63,7 +63,7 @@ BTA_API extern void bta_av_ci_src_data_ready(tBTA_AV_CHNL chnl);
 *******************************************************************************/
 BTA_API extern void bta_av_ci_setconfig(tBTA_AV_HNDL hndl, UINT8 err_code,
                                         UINT8 category, UINT8 num_seid, UINT8 *p_seid,
-                                        BOOLEAN recfg_needed);
+                                        BOOLEAN recfg_needed, UINT8 avdt_handle);
 
 
 #ifdef __cplusplus
index 862ac5e..ed11c50 100644 (file)
@@ -100,7 +100,7 @@ BTA_API extern BOOLEAN bta_av_co_audio_init(UINT8 *p_codec_type, UINT8 *p_codec_
 **
 *******************************************************************************/
 BTA_API extern void bta_av_co_audio_disc_res(tBTA_AV_HNDL hndl, UINT8 num_seps,
-                                             UINT8 num_snk, BD_ADDR addr);
+                    UINT8 num_snk, UINT8 num_src, BD_ADDR addr, UINT16 uuid_local);
 
 /*******************************************************************************
 **
@@ -162,7 +162,7 @@ BTA_API extern UINT8 bta_av_co_video_getconfig(tBTA_AV_HNDL hndl, tBTA_AV_CODEC
 *******************************************************************************/
 BTA_API extern void bta_av_co_audio_setconfig(tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type,
                                         UINT8 *p_codec_info, UINT8 seid, BD_ADDR addr,
-                                        UINT8 num_protect, UINT8 *p_protect_info);
+                                        UINT8 num_protect, UINT8 *p_protect_info,UINT8 t_local_sep, UINT8 avdt_handle);
 
 /*******************************************************************************
 **
index 98eb6ae..d7cfa89 100644 (file)
@@ -194,6 +194,18 @@ extern UINT8 bta_av_sbc_cfg_in_cap(UINT8 *p_cfg, tA2D_SBC_CIE *p_cap);
 
 /*******************************************************************************
 **
+** Function         bta_av_sbc_cfg_matches_cap
+**
+** Description      This function checks whether an SBC codec configuration
+**                  matched with capabilities. Here we check subset.
+**
+** Returns          0 if ok, nonzero if error.
+**
+*******************************************************************************/
+extern UINT8 bta_av_sbc_cfg_matches_cap(UINT8 *p_cfg, tA2D_SBC_CIE *p_cap);
+
+/*******************************************************************************
+**
 ** Function         bta_av_sbc_bld_hdr
 **
 ** Description      This function builds the packet header for MPF1.
index fecf621..a0cc344 100644 (file)
@@ -67,7 +67,7 @@
 /* SCMS-T protect info */
 const UINT8 bta_av_co_cp_scmst[BTA_AV_CP_INFO_LEN] = "\x02\x02\x00";
 
-/* SBC codec capabilities */
+/* SBC SRC codec capabilities */
 const tA2D_SBC_CIE bta_av_co_sbc_caps =
 {
     (A2D_SBC_IE_SAMP_FREQ_44), /* samp_freq */
@@ -79,6 +79,18 @@ const tA2D_SBC_CIE bta_av_co_sbc_caps =
     A2D_SBC_IE_MIN_BITPOOL /* min_bitpool */
 };
 
+/* SBC SINK codec capabilities */
+const tA2D_SBC_CIE bta_av_co_sbc_sink_caps =
+{
+    (A2D_SBC_IE_SAMP_FREQ_48 | A2D_SBC_IE_SAMP_FREQ_44), /* samp_freq */
+    (A2D_SBC_IE_CH_MD_MONO | A2D_SBC_IE_CH_MD_STEREO | A2D_SBC_IE_CH_MD_JOINT | A2D_SBC_IE_CH_MD_DUAL), /* ch_mode */
+    (A2D_SBC_IE_BLOCKS_16 | A2D_SBC_IE_BLOCKS_12 | A2D_SBC_IE_BLOCKS_8 | A2D_SBC_IE_BLOCKS_4), /* block_len */
+    (A2D_SBC_IE_SUBBAND_4 | A2D_SBC_IE_SUBBAND_8), /* num_subbands */
+    (A2D_SBC_IE_ALLOC_MD_L | A2D_SBC_IE_ALLOC_MD_S), /* alloc_mthd */
+    A2D_SBC_IE_MAX_BITPOOL, /* max_bitpool */
+    A2D_SBC_IE_MIN_BITPOOL /* min_bitpool */
+};
+
 #if !defined(BTIF_AV_SBC_DEFAULT_SAMP_FREQ)
 #define BTIF_AV_SBC_DEFAULT_SAMP_FREQ A2D_SBC_IE_SAMP_FREQ_44
 #endif
@@ -113,17 +125,23 @@ typedef struct
 {
     BD_ADDR         addr;               /* address of audio/video peer */
     tBTA_AV_CO_SINK snks[BTIF_SV_AV_AA_SEP_INDEX]; /* array of supported sinks */
+    tBTA_AV_CO_SINK srcs[BTIF_SV_AV_AA_SEP_INDEX]; /* array of supported srcs */
     UINT8           num_snks;           /* total number of sinks at peer */
+    UINT8           num_srcs;           /* total number of srcs at peer */
     UINT8           num_seps;           /* total number of seids at peer */
     UINT8           num_rx_snks;        /* number of received sinks */
+    UINT8           num_rx_srcs;        /* number of received srcs */
     UINT8           num_sup_snks;       /* number of supported sinks in the snks array */
+    UINT8           num_sup_srcs;       /* number of supported srcs in the srcs array */
     tBTA_AV_CO_SINK *p_snk;             /* currently selected sink */
+    tBTA_AV_CO_SINK *p_src;             /* currently selected src */
     UINT8           codec_cfg[AVDT_CODEC_SIZE]; /* current codec configuration */
     BOOLEAN         cp_active;          /* current CP configuration */
     BOOLEAN         acp;                /* acceptor */
     BOOLEAN         recfg_needed;       /* reconfiguration is needed */
     BOOLEAN         opened;             /* opened */
     UINT16          mtu;                /* maximum transmit unit size */
+    UINT16          uuid_to_connect;    /* uuid of peer device */
 } tBTA_AV_CO_PEER;
 
 typedef struct
@@ -152,7 +170,8 @@ static BOOLEAN bta_av_co_cp_is_scmst(const UINT8 *p_protectinfo);
 static BOOLEAN bta_av_co_audio_sink_has_scmst(const tBTA_AV_CO_SINK *p_sink);
 static BOOLEAN bta_av_co_audio_peer_supports_codec(tBTA_AV_CO_PEER *p_peer, UINT8 *p_snk_index);
 static BOOLEAN bta_av_co_audio_media_supports_config(UINT8 codec_type, const UINT8 *p_codec_cfg);
-
+static BOOLEAN bta_av_co_audio_sink_supports_config(UINT8 codec_type, const UINT8 *p_codec_cfg);
+static BOOLEAN bta_av_co_audio_peer_src_supports_codec(tBTA_AV_CO_PEER *p_peer, UINT8 *p_src_index);
 
 
 
@@ -284,7 +303,7 @@ BOOLEAN bta_av_co_audio_init(UINT8 *p_codec_type, UINT8 *p_codec_info, UINT8 *p_
     switch (index)
     {
     case BTIF_SV_AV_AA_SBC_INDEX:
-        /* Set up for SBC codec */
+        /* Set up for SBC codec  for SRC*/
         *p_codec_type = BTA_AV_CODEC_SBC;
 
         /* This should not fail because we are using constants for parameters */
@@ -292,8 +311,16 @@ BOOLEAN bta_av_co_audio_init(UINT8 *p_codec_type, UINT8 *p_codec_info, UINT8 *p_
 
         /* Codec is valid */
         return TRUE;
+#ifdef BTA_AVK_INCLUDED
+    case BTIF_SV_AV_AA_SBC_SINK_INDEX:
+        *p_codec_type = BTA_AV_CODEC_SBC;
 
+        /* This should not fail because we are using constants for parameters */
+        A2D_BldSbcInfo(AVDT_MEDIA_AUDIO, (tA2D_SBC_CIE *) &bta_av_co_sbc_sink_caps, p_codec_info);
 
+        /* Codec is valid */
+        return TRUE;
+#endif
     default:
         /* Not valid */
         return FALSE;
@@ -313,14 +340,14 @@ BOOLEAN bta_av_co_audio_init(UINT8 *p_codec_type, UINT8 *p_codec_info, UINT8 *p_
  **
  *******************************************************************************/
 BTA_API void bta_av_co_audio_disc_res(tBTA_AV_HNDL hndl, UINT8 num_seps, UINT8 num_snk,
-        BD_ADDR addr)
+        UINT8 num_src, BD_ADDR addr, UINT16 uuid_local)
 {
     tBTA_AV_CO_PEER *p_peer;
 
     FUNC_TRACE();
 
-    APPL_TRACE_DEBUG3("bta_av_co_audio_disc_res h:x%x num_seps:%d num_snk:%d",
-            hndl, num_seps, num_snk);
+    APPL_TRACE_DEBUG4("bta_av_co_audio_disc_res h:x%x num_seps:%d num_snk:%d num_src:%d",
+            hndl, num_seps, num_snk, num_src);
 
     /* Find the peer info */
     p_peer = bta_av_co_get_peer(hndl);
@@ -339,13 +366,220 @@ BTA_API void bta_av_co_audio_disc_res(tBTA_AV_HNDL hndl, UINT8 num_seps, UINT8 n
     /* Copy the discovery results */
     bdcpy(p_peer->addr, addr);
     p_peer->num_snks = num_snk;
+    p_peer->num_srcs = num_src;
     p_peer->num_seps = num_seps;
     p_peer->num_rx_snks = 0;
+    p_peer->num_rx_srcs = 0;
     p_peer->num_sup_snks = 0;
+    if (uuid_local == UUID_SERVCLASS_AUDIO_SINK)
+        p_peer->uuid_to_connect = UUID_SERVCLASS_AUDIO_SOURCE;
+    else if (uuid_local == UUID_SERVCLASS_AUDIO_SOURCE)
+        p_peer->uuid_to_connect = UUID_SERVCLASS_AUDIO_SINK;
 }
 
 /*******************************************************************************
  **
+ ** Function         bta_av_build_src_cfg
+ **
+ ** Description      This function will build preferred config from src capabilities
+ **
+ **
+ ** Returns          Pass or Fail for current getconfig.
+ **
+ *******************************************************************************/
+void bta_av_build_src_cfg (UINT8 *p_pref_cfg, UINT8 *p_src_cap)
+{
+    tA2D_SBC_CIE    src_cap;
+    tA2D_SBC_CIE    pref_cap;
+    UINT8           status = 0;
+
+    /* initialize it to default SBC configuration */
+    A2D_BldSbcInfo(AVDT_MEDIA_AUDIO, (tA2D_SBC_CIE *) &btif_av_sbc_default_config, p_pref_cfg);
+    /* now try to build a preferred one */
+    /* parse configuration */
+    if ((status = A2D_ParsSbcInfo(&src_cap, p_src_cap, TRUE)) != 0)
+    {
+         APPL_TRACE_DEBUG1(" Cant parse src cap ret = %d", status);
+         return ;
+    }
+
+    if (src_cap.samp_freq & A2D_SBC_IE_SAMP_FREQ_48)
+        pref_cap.samp_freq = A2D_SBC_IE_SAMP_FREQ_48;
+    else if (src_cap.samp_freq & A2D_SBC_IE_SAMP_FREQ_44)
+        pref_cap.samp_freq = A2D_SBC_IE_SAMP_FREQ_44;
+
+    if (src_cap.ch_mode & A2D_SBC_IE_CH_MD_JOINT)
+        pref_cap.ch_mode = A2D_SBC_IE_CH_MD_JOINT;
+    else if (src_cap.ch_mode & A2D_SBC_IE_CH_MD_STEREO)
+        pref_cap.ch_mode = A2D_SBC_IE_CH_MD_STEREO;
+    else if (src_cap.ch_mode & A2D_SBC_IE_CH_MD_DUAL)
+        pref_cap.ch_mode = A2D_SBC_IE_CH_MD_DUAL;
+    else if (src_cap.ch_mode & A2D_SBC_IE_CH_MD_MONO)
+        pref_cap.ch_mode = A2D_SBC_IE_CH_MD_MONO;
+
+    if (src_cap.block_len & A2D_SBC_IE_BLOCKS_16)
+        pref_cap.block_len = A2D_SBC_IE_BLOCKS_16;
+    else if (src_cap.block_len & A2D_SBC_IE_BLOCKS_12)
+        pref_cap.block_len = A2D_SBC_IE_BLOCKS_12;
+    else if (src_cap.block_len & A2D_SBC_IE_BLOCKS_8)
+        pref_cap.block_len = A2D_SBC_IE_BLOCKS_8;
+    else if (src_cap.block_len & A2D_SBC_IE_BLOCKS_4)
+        pref_cap.block_len = A2D_SBC_IE_BLOCKS_4;
+
+    if (src_cap.num_subbands & A2D_SBC_IE_SUBBAND_8)
+        pref_cap.num_subbands = A2D_SBC_IE_SUBBAND_8;
+    else if(src_cap.num_subbands & A2D_SBC_IE_SUBBAND_4)
+        pref_cap.num_subbands = A2D_SBC_IE_SUBBAND_4;
+
+    if (src_cap.alloc_mthd & A2D_SBC_IE_ALLOC_MD_L)
+        pref_cap.alloc_mthd = A2D_SBC_IE_ALLOC_MD_L;
+    else if(src_cap.alloc_mthd & A2D_SBC_IE_ALLOC_MD_S)
+        pref_cap.alloc_mthd = A2D_SBC_IE_ALLOC_MD_S;
+
+    pref_cap.max_bitpool = src_cap.max_bitpool;
+    pref_cap.min_bitpool = src_cap.min_bitpool;
+
+    A2D_BldSbcInfo(AVDT_MEDIA_AUDIO, (tA2D_SBC_CIE *) &pref_cap, p_pref_cfg);
+}
+
+/*******************************************************************************
+ **
+ ** Function         bta_av_audio_sink_getconfig
+ **
+ ** Description      This callout function is executed by AV to retrieve the
+ **                  desired codec and content protection configuration for the
+ **                  A2DP Sink audio stream in Initiator.
+ **
+ **
+ ** Returns          Pass or Fail for current getconfig.
+ **
+ *******************************************************************************/
+UINT8 bta_av_audio_sink_getconfig(tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type,
+        UINT8 *p_codec_info, UINT8 *p_sep_info_idx, UINT8 seid, UINT8 *p_num_protect,
+        UINT8 *p_protect_info)
+{
+
+    UINT8 result = A2D_FAIL;
+    BOOLEAN supported;
+    tBTA_AV_CO_PEER *p_peer;
+    tBTA_AV_CO_SINK *p_src;
+    UINT8 codec_cfg[AVDT_CODEC_SIZE];
+    UINT8 pref_cfg[AVDT_CODEC_SIZE];
+    UINT8 index;
+
+    FUNC_TRACE();
+
+    APPL_TRACE_DEBUG3("bta_av_audio_sink_getconfig handle:0x%x codec_type:%d seid:%d",
+                                                               hndl, codec_type, seid);
+    APPL_TRACE_DEBUG4("num_protect:0x%02x protect_info:0x%02x%02x%02x",
+        *p_num_protect, p_protect_info[0], p_protect_info[1], p_protect_info[2]);
+
+    /* Retrieve the peer info */
+    p_peer = bta_av_co_get_peer(hndl);
+    if (p_peer == NULL)
+    {
+        APPL_TRACE_ERROR0("bta_av_audio_sink_getconfig could not find peer entry");
+        return A2D_FAIL;
+    }
+
+    APPL_TRACE_DEBUG4("bta_av_audio_sink_getconfig peer(o=%d,n_snks=%d,n_rx_snks=%d,n_sup_snks=%d)",
+            p_peer->opened, p_peer->num_srcs, p_peer->num_rx_srcs, p_peer->num_sup_srcs);
+
+    p_peer->num_rx_srcs++;
+
+    /* Check if this is a supported configuration */
+    supported = FALSE;
+    switch (codec_type)
+    {
+        case BTA_AV_CODEC_SBC:
+            supported = TRUE;
+            break;
+
+        default:
+            break;
+    }
+
+    if (supported)
+    {
+        /* If there is room for a new one */
+        if (p_peer->num_sup_srcs < BTA_AV_CO_NUM_ELEMENTS(p_peer->srcs))
+        {
+            p_src = &p_peer->srcs[p_peer->num_sup_srcs++];
+
+            APPL_TRACE_DEBUG6("bta_av_audio_sink_getconfig saved caps[%x:%x:%x:%x:%x:%x]",
+                    p_codec_info[1], p_codec_info[2], p_codec_info[3],
+                    p_codec_info[4], p_codec_info[5], p_codec_info[6]);
+
+            memcpy(p_src->codec_caps, p_codec_info, AVDT_CODEC_SIZE);
+            p_src->codec_type = codec_type;
+            p_src->sep_info_idx = *p_sep_info_idx;
+            p_src->seid = seid;
+            p_src->num_protect = *p_num_protect;
+            memcpy(p_src->protect_info, p_protect_info, BTA_AV_CP_INFO_LEN);
+        }
+        else
+        {
+            APPL_TRACE_ERROR0("bta_av_audio_sink_getconfig no more room for SRC info");
+        }
+    }
+
+    /* If last SNK get capabilities or all supported codec caps retrieved */
+    if ((p_peer->num_rx_srcs == p_peer->num_srcs) ||
+        (p_peer->num_sup_srcs == BTA_AV_CO_NUM_ELEMENTS(p_peer->srcs)))
+    {
+        APPL_TRACE_DEBUG0("bta_av_audio_sink_getconfig last SRC reached");
+
+        /* Protect access to bta_av_co_cb.codec_cfg */
+        GKI_disable();
+
+        /* Find a src that matches the codec config */
+        if (bta_av_co_audio_peer_src_supports_codec(p_peer, &index))
+        {
+            APPL_TRACE_DEBUG0(" Codec Supported ");
+            p_src = &p_peer->srcs[index];
+
+            /* Build the codec configuration for this sink */
+            {
+                /* Save the new configuration */
+                p_peer->p_src = p_src;
+                /* get preferred config from src_caps */
+                bta_av_build_src_cfg(pref_cfg, p_src->codec_caps);
+                memcpy(p_peer->codec_cfg, pref_cfg, AVDT_CODEC_SIZE);
+
+                APPL_TRACE_DEBUG6("bta_av_audio_sink_getconfig  p_codec_info[%x:%x:%x:%x:%x:%x]",
+                        p_peer->codec_cfg[1], p_peer->codec_cfg[2], p_peer->codec_cfg[3],
+                        p_peer->codec_cfg[4], p_peer->codec_cfg[5], p_peer->codec_cfg[6]);
+                /* By default, no content protection */
+                *p_num_protect = 0;
+
+#if defined(BTA_AV_CO_CP_SCMS_T) && (BTA_AV_CO_CP_SCMS_T == TRUE)
+                /* Check if this sink supports SCMS */
+                if (bta_av_co_audio_sink_has_scmst(p_sink))
+                {
+                    p_peer->cp_active = TRUE;
+                    bta_av_co_cb.cp.active = TRUE;
+                    *p_num_protect = BTA_AV_CP_INFO_LEN;
+                    memcpy(p_protect_info, bta_av_co_cp_scmst, BTA_AV_CP_INFO_LEN);
+                }
+                else
+                {
+                    p_peer->cp_active = FALSE;
+                    bta_av_co_cb.cp.active = FALSE;
+                }
+#endif
+
+                    *p_sep_info_idx = p_src->sep_info_idx;
+                    memcpy(p_codec_info, p_peer->codec_cfg, AVDT_CODEC_SIZE);
+                result =  A2D_SUCCESS;
+            }
+        }
+        /* Protect access to bta_av_co_cb.codec_cfg */
+        GKI_enable();
+    }
+    return result;
+}
+/*******************************************************************************
+ **
  ** Function         bta_av_co_audio_getconfig
  **
  ** Description      This callout function is executed by AV to retrieve the
@@ -370,10 +604,6 @@ BTA_API UINT8 bta_av_co_audio_getconfig(tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_t
 
     FUNC_TRACE();
 
-    APPL_TRACE_DEBUG3("bta_av_co_audio_getconfig handle:0x%x codec_type:%d seid:%d", hndl, codec_type, seid);
-    APPL_TRACE_DEBUG4("num_protect:0x%02x protect_info:0x%02x%02x%02x",
-        *p_num_protect, p_protect_info[0], p_protect_info[1], p_protect_info[2]);
-
     /* Retrieve the peer info */
     p_peer = bta_av_co_get_peer(hndl);
     if (p_peer == NULL)
@@ -382,10 +612,20 @@ BTA_API UINT8 bta_av_co_audio_getconfig(tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_t
         return A2D_FAIL;
     }
 
+    if (p_peer->uuid_to_connect == UUID_SERVCLASS_AUDIO_SOURCE)
+    {
+        result = bta_av_audio_sink_getconfig(hndl, codec_type, p_codec_info, p_sep_info_idx,
+                                             seid, p_num_protect, p_protect_info);
+        return result;
+    }
+    APPL_TRACE_DEBUG3("bta_av_co_audio_getconfig handle:0x%x codec_type:%d seid:%d",
+                                                              hndl, codec_type, seid);
+    APPL_TRACE_DEBUG4("num_protect:0x%02x protect_info:0x%02x%02x%02x",
+        *p_num_protect, p_protect_info[0], p_protect_info[1], p_protect_info[2]);
+
     APPL_TRACE_DEBUG4("bta_av_co_audio_getconfig peer(o=%d,n_snks=%d,n_rx_snks=%d,n_sup_snks=%d)",
             p_peer->opened, p_peer->num_snks, p_peer->num_rx_snks, p_peer->num_sup_snks);
 
-    /* Increment the number of received sinks capabilities */
     p_peer->num_rx_snks++;
 
     /* Check if this is a supported configuration */
@@ -510,13 +750,15 @@ BTA_API UINT8 bta_av_co_audio_getconfig(tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_t
  **
  *******************************************************************************/
 BTA_API void bta_av_co_audio_setconfig(tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type,
-        UINT8 *p_codec_info, UINT8 seid, BD_ADDR addr, UINT8 num_protect, UINT8 *p_protect_info)
+        UINT8 *p_codec_info, UINT8 seid, BD_ADDR addr, UINT8 num_protect, UINT8 *p_protect_info,
+        UINT8 t_local_sep, UINT8 avdt_handle)
 
 {
     tBTA_AV_CO_PEER *p_peer;
     UINT8 status = A2D_SUCCESS;
     UINT8 category = A2D_SUCCESS;
     BOOLEAN recfg_needed = FALSE;
+    BOOLEAN codec_cfg_supported = FALSE;
     UNUSED(seid);
     UNUSED(addr);
 
@@ -535,9 +777,11 @@ BTA_API void bta_av_co_audio_setconfig(tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_ty
         APPL_TRACE_ERROR0("bta_av_co_audio_setconfig could not find peer entry");
 
         /* Call call-in rejecting the configuration */
-        bta_av_ci_setconfig(hndl, A2D_BUSY, AVDT_ASC_CODEC, 0, NULL, FALSE);
+        bta_av_ci_setconfig(hndl, A2D_BUSY, AVDT_ASC_CODEC, 0, NULL, FALSE, avdt_handle);
         return;
     }
+    APPL_TRACE_DEBUG4("bta_av_co_audio_setconfig peer(o=%d,n_snks=%d,n_rx_snks=%d,n_sup_snks=%d)",
+            p_peer->opened, p_peer->num_snks, p_peer->num_rx_snks, p_peer->num_sup_snks);
 
     /* Sanity check: should not be opened at this point */
     if (p_peer->opened)
@@ -568,9 +812,20 @@ BTA_API void bta_av_co_audio_setconfig(tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_ty
 #endif
     if (status == A2D_SUCCESS)
     {
+        if(AVDT_TSEP_SNK == t_local_sep)
+        {
+            codec_cfg_supported = bta_av_co_audio_sink_supports_config(codec_type, p_codec_info);
+            APPL_TRACE_DEBUG0(" Peer is  A2DP SRC ");
+        }
+        if(AVDT_TSEP_SRC == t_local_sep)
+        {
+            codec_cfg_supported = bta_av_co_audio_media_supports_config(codec_type, p_codec_info);
+            APPL_TRACE_DEBUG0(" Peer is A2DP SINK ");
+        }
         /* Check if codec configuration is supported */
-        if (bta_av_co_audio_media_supports_config(codec_type, p_codec_info))
+        if (codec_cfg_supported)
         {
+
             /* Protect access to bta_av_co_cb.codec_cfg */
             GKI_disable();
 
@@ -595,6 +850,13 @@ BTA_API void bta_av_co_audio_setconfig(tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_ty
 
                 bta_av_co_cb.codec_cfg_setconfig.id = BTIF_AV_CODEC_SBC;
                 memcpy(bta_av_co_cb.codec_cfg_setconfig.info, p_codec_info, AVDT_CODEC_SIZE);
+                if(AVDT_TSEP_SNK == t_local_sep)
+                {
+                    /* If Peer is SRC, and our cfg subset matches with what is requested by peer, then
+                                         just accept what peer wants */
+                    memcpy(bta_av_co_cb.codec_cfg.info, p_codec_info, AVDT_CODEC_SIZE);
+                    recfg_needed = FALSE;
+                }
                 break;
 
 
@@ -618,7 +880,7 @@ BTA_API void bta_av_co_audio_setconfig(tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_ty
         APPL_TRACE_DEBUG2("bta_av_co_audio_setconfig reject s=%d c=%d", status, category);
 
         /* Call call-in rejecting the configuration */
-        bta_av_ci_setconfig(hndl, status, category, 0, NULL, FALSE);
+        bta_av_ci_setconfig(hndl, status, category, 0, NULL, FALSE, avdt_handle);
     }
     else
     {
@@ -629,7 +891,7 @@ BTA_API void bta_av_co_audio_setconfig(tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_ty
         APPL_TRACE_DEBUG1("bta_av_co_audio_setconfig accept reconf=%d", recfg_needed);
 
         /* Call call-in accepting the configuration */
-        bta_av_ci_setconfig(hndl, A2D_SUCCESS, A2D_SUCCESS, 0, NULL, recfg_needed);
+        bta_av_ci_setconfig(hndl, A2D_SUCCESS, A2D_SUCCESS, 0, NULL, recfg_needed, avdt_handle);
     }
 }
 
@@ -1094,13 +1356,89 @@ static BOOLEAN bta_av_co_audio_peer_supports_codec(tBTA_AV_CO_PEER *p_peer, UINT
 
 /*******************************************************************************
  **
- ** Function         bta_av_co_audio_media_supports_config
+ ** Function         bta_av_co_audio_peer_src_supports_codec
+ **
+ ** Description      Check if a peer acting as src supports codec config
+ **
+ ** Returns          TRUE if the connection supports this codec, FALSE otherwise
+ **
+ *******************************************************************************/
+static BOOLEAN bta_av_co_audio_peer_src_supports_codec(tBTA_AV_CO_PEER *p_peer, UINT8 *p_src_index)
+{
+    int index;
+    UINT8 codec_type;
+    FUNC_TRACE();
+
+    /* Configure the codec type to look for */
+    codec_type = bta_av_co_cb.codec_cfg.id;
+
+
+    for (index = 0; index < p_peer->num_sup_srcs; index++)
+    {
+        if (p_peer->srcs[index].codec_type == codec_type)
+        {
+            switch (bta_av_co_cb.codec_cfg.id)
+            {
+            case BTIF_AV_CODEC_SBC:
+                if (p_src_index) *p_src_index = index;
+                if (0 ==  bta_av_sbc_cfg_matches_cap((UINT8 *)p_peer->srcs[index].codec_caps,
+                                                     (tA2D_SBC_CIE *)&bta_av_co_sbc_sink_caps))
+                {
+                    return TRUE;
+                }
+                break;
+
+            default:
+                APPL_TRACE_ERROR1("peer_src_supports_codec: unsupported codec id %d",
+                                                            bta_av_co_cb.codec_cfg.id);
+                return FALSE;
+                break;
+            }
+        }
+    }
+    return FALSE;
+}
+
+/*******************************************************************************
+ **
+ ** Function         bta_av_co_audio_sink_supports_config
  **
  ** Description      Check if the media source supports a given configuration
  **
  ** Returns          TRUE if the media source supports this config, FALSE otherwise
  **
  *******************************************************************************/
+static BOOLEAN bta_av_co_audio_sink_supports_config(UINT8 codec_type, const UINT8 *p_codec_cfg)
+{
+    FUNC_TRACE();
+
+    switch (codec_type)
+    {
+    case BTA_AV_CODEC_SBC:
+        if (bta_av_sbc_cfg_in_cap((UINT8 *)p_codec_cfg, (tA2D_SBC_CIE *)&bta_av_co_sbc_sink_caps))
+        {
+            return FALSE;
+        }
+        break;
+
+
+    default:
+        APPL_TRACE_ERROR1("bta_av_co_audio_media_supports_config unsupported codec type %d", codec_type);
+        return FALSE;
+        break;
+    }
+    return TRUE;
+}
+
+/*******************************************************************************
+ **
+ ** Function         bta_av_co_audio_media_supports_config
+ **
+ ** Description      Check if the media sink supports a given configuration
+ **
+ ** Returns          TRUE if the media source supports this config, FALSE otherwise
+ **
+ *******************************************************************************/
 static BOOLEAN bta_av_co_audio_media_supports_config(UINT8 codec_type, const UINT8 *p_codec_cfg)
 {
     FUNC_TRACE();
diff --git a/btif/include/bluetoothTrack.h b/btif/include/bluetoothTrack.h
new file mode 100644 (file)
index 0000000..e4e1660
--- /dev/null
@@ -0,0 +1,32 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2014 The Android Open Source Project
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at:
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ ******************************************************************************/
+
+#if defined (__cplusplus) || (cplusplus)
+extern "C" {
+#endif
+
+int btCreateTrack(int trackFreq, int channelType);
+void btDeleteTrack();
+void btStopTrack();
+void btStartTrack();
+void btPauseTrack();
+int btWriteData(void *audioBuffer, int bufferlen);
+
+#if defined (__cplusplus) || (cplusplus)
+}
+#endif
index 9e537cd..eda9c18 100644 (file)
@@ -45,6 +45,8 @@ typedef enum {
     BTIF_AV_STOP_STREAM_REQ_EVT,
     BTIF_AV_SUSPEND_STREAM_REQ_EVT,
     BTIF_AV_RECONFIGURE_REQ_EVT,
+    BTIF_AV_REQUEST_AUDIO_FOCUS_EVT,
+    BTIF_AV_REQUEST_ACTIVATE_SINK_EVT,
 } btif_av_sm_event_t;
 
 
index 20e9a1e..a6a5bfa 100644 (file)
@@ -28,6 +28,7 @@
 enum
 {
     BTIF_SV_AV_AA_SBC_INDEX = 0,
+    BTIF_SV_AV_AA_SBC_SINK_INDEX,
     BTIF_SV_AV_AA_SEP_INDEX  /* Last index */
 };
 
index 4cdbb8c..a785d34 100644 (file)
@@ -90,8 +90,20 @@ typedef struct
         tBTIF_AV_FEEDING_MODE feeding_mode;
         tBTIF_AV_MEDIA_FEEDINGS feeding;
 } tBTIF_MEDIA_INIT_AUDIO_FEEDING;
+
+typedef struct
+{
+        BT_HDR hdr;
+        UINT8 codec_info[AVDT_CODEC_SIZE];
+} tBTIF_MEDIA_SINK_CFG_UPDATE;
 #endif
 
+typedef enum {
+    BTIF_MEDIA_AUDIOFOCUS_LOSS = 0,
+    BTIF_MEDIA_AUDIOFOCUS_GAIN,
+    BTIF_MEDIA_AUDIOFOCUS_LOSS_TRANSIENT
+} btif_media_AudioFocus_state;
+
 
 /*******************************************************************************
  **  Public functions
@@ -154,7 +166,16 @@ extern BOOLEAN btif_media_task_start_aa_req(void);
  *******************************************************************************/
 extern BOOLEAN btif_media_task_stop_aa_req(void);
 
-
+/*******************************************************************************
+ **
+ ** Function         btif_media_task_aa_rx_flush_req
+ **
+ ** Description      Request to flush audio decoding pipe
+ **
+ ** Returns          TRUE is success
+ **
+ *******************************************************************************/
+extern BOOLEAN btif_media_task_aa_rx_flush_req(void);
 /*******************************************************************************
  **
  ** Function         btif_media_task_aa_tx_flush_req
@@ -179,6 +200,19 @@ extern BT_HDR *btif_media_aa_readbuf(void);
 
 /*******************************************************************************
  **
+ ** Function         btif_media_sink_enque_buf
+ **
+ ** Description      This function is called by the av_co to fill A2DP Sink Queue
+ **
+ **
+ ** Returns          size of the queue
+ *******************************************************************************/
+ UINT8 btif_media_sink_enque_buf(BT_HDR *p_buf);
+
+
+
+/*******************************************************************************
+ **
  ** Function         btif_media_aa_writebuf
  **
  ** Description      Enqueue a Advance Audio media GKI buffer to be processed by btif media task.
@@ -243,5 +277,10 @@ void btif_a2dp_on_stopped(tBTA_AV_SUSPEND *p_av);
 void btif_a2dp_on_suspend(void);
 void btif_a2dp_on_suspended(tBTA_AV_SUSPEND *p_av);
 void btif_a2dp_set_tx_flush(BOOLEAN enable);
+void btif_a2dp_set_rx_flush(BOOLEAN enable);
+void btif_media_check_iop_exceptions(UINT8 *peer_bda);
+void btif_reset_decoder(UINT8 *p_av);
+BOOLEAN btif_media_task_start_decoding_req(void);
+void btif_a2dp_set_audio_focus_state(btif_media_AudioFocus_state state);
 
 #endif
index e05c97a..b586575 100644 (file)
@@ -27,7 +27,7 @@
 #ifndef BTIF_PROFILE_QUEUE_H
 #define BTIF_PROFILE_QUEUE_H
 
-typedef bt_status_t (*btif_connect_cb_t)(bt_bdaddr_t *bda);
+typedef bt_status_t (*btif_connect_cb_t) (bt_bdaddr_t *bda, uint16_t uuid);
 
 bt_status_t btif_queue_connect(uint16_t uuid, const bt_bdaddr_t *bda, btif_connect_cb_t connect_cb);
 void btif_queue_advance();
diff --git a/btif/src/bluetoothTrack.cpp b/btif/src/bluetoothTrack.cpp
new file mode 100644 (file)
index 0000000..685780e
--- /dev/null
@@ -0,0 +1,122 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2014 The Android Open Source Project
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at:
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ ******************************************************************************/
+
+#include "bluetoothTrack.h"
+#include <media/AudioTrack.h>
+
+//#define DUMP_PCM_DATA TRUE
+#if (defined(DUMP_PCM_DATA) && (DUMP_PCM_DATA == TRUE))
+FILE *outputPcmSampleFile;
+char outputFilename [50] = "/data/misc/bluedroid/output_sample.pcm";
+#endif
+
+struct BluetoothTrack {
+    android::sp<android::AudioTrack> mTrack;
+};
+
+typedef struct BluetoothTrack BluetoothTrack;
+
+BluetoothTrack *track = NULL;
+
+int btCreateTrack(int trackFreq, int channelType)
+{
+    int ret = -1;
+    if (track == NULL)
+        track = new BluetoothTrack;
+    track->mTrack = NULL;
+    track->mTrack = new android::AudioTrack(AUDIO_STREAM_MUSIC, trackFreq, AUDIO_FORMAT_PCM_16_BIT,
+            channelType, (int)0, (audio_output_flags_t)AUDIO_OUTPUT_FLAG_FAST, NULL, NULL, 0, 0, android::AudioTrack::TRANSFER_SYNC);
+    if (track->mTrack == NULL)
+    {
+        delete track;
+        track = NULL;
+        return ret;
+    }
+    if (track->mTrack->initCheck() != 0)
+    {
+        delete track;
+        track = NULL;
+        return ret;
+    }
+#if (defined(DUMP_PCM_DATA) && (DUMP_PCM_DATA == TRUE))
+    outputPcmSampleFile = fopen(outputFilename, "ab");
+#endif
+    ret = 0;
+    track->mTrack->setVolume(1, 1);
+    return ret;
+}
+
+void btStartTrack()
+{
+    if ((track != NULL) && (track->mTrack.get() != NULL))
+    {
+        track->mTrack->start();
+    }
+}
+
+
+void btDeleteTrack()
+{
+    if ((track != NULL) && (track->mTrack.get() != NULL))
+    {
+        track->mTrack.clear();
+        delete track;
+        track = NULL;
+    }
+#if (defined(DUMP_PCM_DATA) && (DUMP_PCM_DATA == TRUE))
+    if (outputPcmSampleFile)
+    {
+        fclose(outputPcmSampleFile);
+    }
+    outputPcmSampleFile = NULL;
+#endif
+}
+
+void btPauseTrack()
+{
+    if ((track != NULL) && (track->mTrack.get() != NULL))
+    {
+        track->mTrack->pause();
+        track->mTrack->flush();
+    }
+}
+
+void btStopTrack()
+{
+    if ((track != NULL) && (track->mTrack.get() != NULL))
+    {
+        track->mTrack->stop();
+    }
+}
+
+int btWriteData(void *audioBuffer, int bufferlen)
+{
+    int retval = -1;
+    if ((track != NULL) && (track->mTrack.get() != NULL))
+    {
+#if (defined(DUMP_PCM_DATA) && (DUMP_PCM_DATA == TRUE))
+        if (outputPcmSampleFile)
+        {
+            fwrite ((audioBuffer), 1, (size_t)bufferlen, outputPcmSampleFile);
+        }
+#endif
+        retval = track->mTrack->write(audioBuffer, (size_t)bufferlen);
+    }
+    return retval;
+}
+
index f893c9e..0b7b9d7 100644 (file)
@@ -69,6 +69,12 @@ typedef enum {
 /*****************************************************************************
 **  Local type definitions
 ******************************************************************************/
+typedef enum
+{
+    SEP_SRC = 0x0,
+    SEP_SNK,
+    SEP_NOT_OPENED
+}tbtif_AV_SEP_TYPE;
 
 typedef struct
 {
@@ -77,8 +83,14 @@ typedef struct
     btif_sm_handle_t sm_handle;
     UINT8 flags;
     tBTA_AV_EDR edr;
+    tbtif_AV_SEP_TYPE   sep;  /* sep type of peer device */
 } btif_av_cb_t;
 
+typedef struct
+{
+    bt_bdaddr_t *target_bda;
+    uint16_t uuid;
+} btif_av_connect_req_t;
 /*****************************************************************************
 **  Static variables
 ******************************************************************************/
@@ -180,11 +192,38 @@ const char *dump_av_sm_event_name(btif_av_sm_event_t event)
         CASE_RETURN_STR(BTIF_AV_STOP_STREAM_REQ_EVT)
         CASE_RETURN_STR(BTIF_AV_SUSPEND_STREAM_REQ_EVT)
         CASE_RETURN_STR(BTIF_AV_RECONFIGURE_REQ_EVT)
-
+        CASE_RETURN_STR(BTIF_AV_REQUEST_AUDIO_FOCUS_EVT)
+        CASE_RETURN_STR(BTIF_AV_REQUEST_ACTIVATE_SINK_EVT)
         default: return "UNKNOWN_EVENT";
    }
 }
 
+/*******************************************************************************
+**
+** Function         btif_av_request_audio_focus
+**
+** Description      send request to gain audio focus
+**
+** Returns          void
+**
+*******************************************************************************/
+void btif_av_request_audio_focus( BOOLEAN enable)
+{
+    btif_sm_state_t state;
+    state= btif_sm_get_state(btif_av_cb.sm_handle);
+    /* We shld be in started state */
+    if (state != BTIF_AV_STATE_STARTED)
+        return;
+    /* If we are in started state, suspend shld not have been initiated */
+    if ((btif_av_cb.flags & BTIF_AV_FLAG_REMOTE_SUSPEND )||
+        (btif_av_cb.flags & BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING))
+        return;
+    if(enable)
+    {
+         btif_dispatch_sm_event(BTIF_AV_REQUEST_AUDIO_FOCUS_EVT, NULL, 0);
+    }
+}
+
 /****************************************************************************
 **  Local helper functions
 *****************************************************************************/
@@ -203,11 +242,15 @@ static void btif_initiate_av_open_tmr_hdlr(TIMER_LIST_ENT *tle)
 {
     BD_ADDR peer_addr;
     UNUSED(tle);
-
+    btif_av_connect_req_t connect_req;
+    UNUSED(tle);
     /* is there at least one RC connection - There should be */
     if (btif_rc_get_connected_peer(peer_addr)) {
        BTIF_TRACE_DEBUG1("%s Issuing connect to the remote RC peer", __FUNCTION__);
-       btif_sm_dispatch(btif_av_cb.sm_handle, BTIF_AV_CONNECT_REQ_EVT, (void*)&peer_addr);
+       /* In case of AVRCP connection request, we will initiate SRC connection */
+       connect_req.target_bda = (bt_bdaddr_t*)&peer_addr;
+       connect_req.uuid = UUID_SERVCLASS_AUDIO_SOURCE;
+       btif_sm_dispatch(btif_av_cb.sm_handle, BTIF_AV_CONNECT_REQ_EVT, (char*)&connect_req);
     }
     else
     {
@@ -221,7 +264,7 @@ static void btif_initiate_av_open_tmr_hdlr(TIMER_LIST_ENT *tle)
 
 /*****************************************************************************
 **
-** Function            btif_av_state_idle_handler
+** Function     btif_av_state_idle_handler
 **
 ** Description  State managing disconnected AV link
 **
@@ -241,6 +284,7 @@ static BOOLEAN btif_av_state_idle_handler(btif_sm_event_t event, void *p_data)
             memset(&btif_av_cb.peer_bda, 0, sizeof(bt_bdaddr_t));
             btif_av_cb.flags = 0;
             btif_av_cb.edr = 0;
+            btif_av_cb.sep = SEP_NOT_OPENED;
             btif_a2dp_on_idle();
             break;
 
@@ -250,6 +294,14 @@ static BOOLEAN btif_av_state_idle_handler(btif_sm_event_t event, void *p_data)
         case BTA_AV_ENABLE_EVT:
             break;
 
+        case BTIF_AV_REQUEST_ACTIVATE_SINK_EVT:
+        {
+            int enable = *((int*)p_data);
+            BTIF_TRACE_DEBUG1(" Active_Sink enable %d", enable)
+            BTA_AvEnable_Sink(enable);
+        }
+            break;
+
         case BTA_AV_REGISTER_EVT:
             btif_av_cb.bta_handle = ((tBTA_AV*)p_data)->registr.hndl;
             break;
@@ -259,14 +311,17 @@ static BOOLEAN btif_av_state_idle_handler(btif_sm_event_t event, void *p_data)
         {
              if (event == BTIF_AV_CONNECT_REQ_EVT)
              {
-                 memcpy(&btif_av_cb.peer_bda, (bt_bdaddr_t*)p_data, sizeof(bt_bdaddr_t));
+                 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_NONE, ((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);
+                  BTA_AvOpen(btif_av_cb.peer_bda.address, btif_av_cb.bta_handle,
+                    TRUE, BTA_SEC_NONE, UUID_SERVCLASS_AUDIO_SOURCE);
              }
-             BTA_AvOpen(btif_av_cb.peer_bda.address, btif_av_cb.bta_handle,
-                    TRUE, BTA_SEC_NONE);
              btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_OPENING);
         } break;
 
@@ -339,6 +394,13 @@ static BOOLEAN btif_av_state_opening_handler(btif_sm_event_t event, void *p_data
         case BTIF_SM_EXIT_EVT:
             break;
 
+        case BTA_AV_REJECT_EVT:
+            BTIF_TRACE_DEBUG0(" Received  BTA_AV_REJECT_EVT ");
+            HAL_CBACK(bt_av_callbacks, connection_state_cb,
+                BTAV_CONNECTION_STATE_DISCONNECTED, &(btif_av_cb.peer_bda));
+            btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_IDLE);
+            break;
+
         case BTA_AV_OPEN_EVT:
         {
             tBTA_AV *p_bta_data = (tBTA_AV*)p_data;
@@ -352,6 +414,11 @@ static BOOLEAN btif_av_state_opening_handler(btif_sm_event_t event, void *p_data
                  state = BTAV_CONNECTION_STATE_CONNECTED;
                  av_state = BTIF_AV_STATE_OPENED;
                  btif_av_cb.edr = p_bta_data->open.edr;
+
+                 if (p_bta_data->open.sep == AVDT_TSEP_SRC)
+                    btif_av_cb.sep = SEP_SRC;
+                 else if (p_bta_data->open.sep == AVDT_TSEP_SNK)
+                     btif_av_cb.sep = SEP_SNK;
             }
             else
             {
@@ -366,9 +433,17 @@ static BOOLEAN btif_av_state_opening_handler(btif_sm_event_t event, void *p_data
                              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 queued PLAY command,  send it now */
-            btif_rc_check_handle_pending_play(p_bta_data->open.bd_addr,
+            if (btif_av_cb.sep == SEP_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.sep == SEP_SRC)
+            {
+                /* if queued PLAY command,  send it now */
+                btif_rc_check_handle_pending_play(p_bta_data->open.bd_addr, FALSE);
+            }
             btif_queue_advance();
         } break;
 
@@ -403,19 +478,31 @@ static BOOLEAN btif_av_state_closing_handler(btif_sm_event_t event, void *p_data
     switch (event)
     {
         case BTIF_SM_ENTER_EVT:
-
-            /* immediately stop transmission of frames */
-            btif_a2dp_set_tx_flush(TRUE);
-            /* wait for audioflinger to stop a2dp */
+            if (btif_av_cb.sep == SEP_SNK)
+            {
+                /* immediately stop transmission of frames */
+                btif_a2dp_set_tx_flush(TRUE);
+                /* wait for audioflinger to stop a2dp */
+            }
+            if (btif_av_cb.sep == SEP_SRC)
+            {
+                btif_a2dp_set_rx_flush(TRUE);
+            }
             break;
 
         case BTA_AV_STOP_EVT:
         case BTIF_AV_STOP_STREAM_REQ_EVT:
+            if (btif_av_cb.sep == SEP_SNK)
+            {
               /* immediately flush any pending tx frames while suspend is pending */
               btif_a2dp_set_tx_flush(TRUE);
+            }
+            if (btif_av_cb.sep == SEP_SRC)
+            {
+                btif_a2dp_set_rx_flush(TRUE);
+            }
 
-              btif_a2dp_on_stopped(NULL);
-
+            btif_a2dp_on_stopped(NULL);
               break;
 
         case BTIF_SM_EXIT_EVT:
@@ -480,6 +567,12 @@ static BOOLEAN btif_av_state_opened_handler(btif_sm_event_t event, void *p_data)
             break;
 
         case BTIF_AV_START_STREAM_REQ_EVT:
+            if (btif_av_cb.sep == SEP_SRC)
+            {
+                BTA_AvStart();
+                btif_av_cb.flags |= BTIF_AV_FLAG_PENDING_START;
+                break;
+            }
             btif_a2dp_setup_codec();
             BTA_AvStart();
             btif_av_cb.flags |= BTIF_AV_FLAG_PENDING_START;
@@ -493,19 +586,30 @@ static BOOLEAN btif_av_state_opened_handler(btif_sm_event_t event, void *p_data)
             if ((p_av->start.status == BTA_SUCCESS) && (p_av->start.suspending == TRUE))
                 return TRUE;
 
-            if (btif_a2dp_on_started(&p_av->start,
-                ((btif_av_cb.flags & BTIF_AV_FLAG_PENDING_START) != 0))) {
-                /* only clear pending flag after acknowledgement */
-                btif_av_cb.flags &= ~BTIF_AV_FLAG_PENDING_START;
+            /*  In case peer is A2DP SRC we do not want to ack commands on UIPC*/
+            if (btif_av_cb.sep == SEP_SNK)
+            {
+                if (btif_a2dp_on_started(&p_av->start,
+                    ((btif_av_cb.flags & BTIF_AV_FLAG_PENDING_START) != 0)))
+                {
+                    /* only clear pending flag after acknowledgement */
+                    btif_av_cb.flags &= ~BTIF_AV_FLAG_PENDING_START;
+                }
             }
 
             /* remain in open state if status failed */
             if (p_av->start.status != BTA_AV_SUCCESS)
                 return FALSE;
 
+            if (btif_av_cb.sep == SEP_SRC)
+            {
+                btif_a2dp_set_rx_flush(FALSE); /*  remove flush state, ready for streaming*/
+            }
+
             /* change state to started, send acknowledgement if start is pending */
             if (btif_av_cb.flags & BTIF_AV_FLAG_PENDING_START) {
-                btif_a2dp_on_started(NULL, TRUE);
+                if (btif_av_cb.sep == SEP_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);
@@ -521,8 +625,7 @@ static BOOLEAN btif_av_state_opened_handler(btif_sm_event_t event, void *p_data)
             break;
 
         case BTA_AV_CLOSE_EVT:
-
-            /* avdtp link is closed */
+             /* avdtp link is closed */
             btif_a2dp_on_stopped(NULL);
 
             /* inform the application that we are disconnected */
@@ -603,7 +706,8 @@ 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 */
-            btif_a2dp_on_started(NULL, TRUE);
+            if (btif_av_cb.sep == SEP_SNK)
+                btif_a2dp_on_started(NULL, TRUE);
             break;
 
         /* fixme -- use suspend = true always to work around issue with BTA AV */
@@ -618,8 +722,14 @@ static BOOLEAN btif_av_state_started_handler(btif_sm_event_t event, void *p_data
                always overrides */
             btif_av_cb.flags &= ~BTIF_AV_FLAG_REMOTE_SUSPEND;
 
+            if (btif_av_cb.sep == SEP_SNK)
+            {
             /* immediately stop transmission of frames while suspend is pending */
-            btif_a2dp_set_tx_flush(TRUE);
+                btif_a2dp_set_tx_flush(TRUE);
+            }
+
+            if (btif_av_cb.sep == SEP_SRC)
+                btif_a2dp_set_rx_flush(TRUE);
 
             BTA_AvStop(TRUE);
             break;
@@ -650,8 +760,11 @@ static BOOLEAN btif_av_state_started_handler(btif_sm_event_t event, void *p_data
             {
                 btif_av_cb.flags &= ~BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING;
 
+               if (btif_av_cb.sep == SEP_SNK)
+               {
                 /* suspend failed, reset back tx flush state */
-                btif_a2dp_set_tx_flush(FALSE);
+                    btif_a2dp_set_tx_flush(FALSE);
+               }
                 return FALSE;
             }
 
@@ -683,7 +796,6 @@ static BOOLEAN btif_av_state_started_handler(btif_sm_event_t event, void *p_data
         case BTA_AV_STOP_EVT:
 
             btif_av_cb.flags |= BTIF_AV_FLAG_PENDING_STOP;
-
             btif_a2dp_on_stopped(&p_av->suspend);
 
             HAL_CBACK(bt_av_callbacks, audio_state_cb,
@@ -695,12 +807,16 @@ static BOOLEAN btif_av_state_started_handler(btif_sm_event_t event, void *p_data
 
             break;
 
+            case BTIF_AV_REQUEST_AUDIO_FOCUS_EVT:
+                HAL_CBACK(bt_av_callbacks, audio_focus_request_cb,
+                                       1, &(btif_av_cb.peer_bda));
+                break;
+
         case BTA_AV_CLOSE_EVT:
 
              btif_av_cb.flags |= BTIF_AV_FLAG_PENDING_STOP;
 
             /* avdtp link is closed */
-
             btif_a2dp_on_stopped(NULL);
 
             /* inform the application that we are disconnected */
@@ -737,6 +853,27 @@ static void bte_av_callback(tBTA_AV_EVT event, tBTA_AV *p_data)
                           (char*)p_data, sizeof(tBTA_AV), NULL);
 }
 
+static void bte_av_media_callback(tBTA_AV_EVT event, tBTA_AV_MEDIA *p_data)
+{
+    btif_sm_state_t state;
+    UINT8 que_len;
+
+    if (event == BTA_AV_MEDIA_DATA_EVT)/* Switch to BTIF_MEDIA context */
+    {
+        state= btif_sm_get_state(btif_av_cb.sm_handle);
+        if ( (state == BTIF_AV_STATE_STARTED) || /* send SBC packets only in Started State */
+             (state == BTIF_AV_STATE_OPENED) )
+        {
+            que_len = btif_media_sink_enque_buf((BT_HDR *)p_data);
+            BTIF_TRACE_DEBUG1(" Packets in Que %d",que_len);
+        }
+        else
+            return;
+    }
+
+    if (event == BTA_AV_MEDIA_SINK_CFG_EVT) /* send a command to BT Media Task */
+        btif_reset_decoder((UINT8*)p_data);
+}
 /*******************************************************************************
 **
 ** Function         btif_av_init
@@ -802,16 +939,27 @@ static bt_status_t init(btav_callbacks_t* callbacks )
 **
 *******************************************************************************/
 
-static bt_status_t connect_int(bt_bdaddr_t *bd_addr)
+static bt_status_t connect_int(bt_bdaddr_t *bd_addr, uint16_t uuid)
 {
+    btif_av_connect_req_t connect_req;
+    connect_req.target_bda = bd_addr;
+    connect_req.uuid = uuid;
     BTIF_TRACE_EVENT1("%s", __FUNCTION__);
 
-    btif_sm_dispatch(btif_av_cb.sm_handle, BTIF_AV_CONNECT_REQ_EVT, (char*)bd_addr);
+    btif_sm_dispatch(btif_av_cb.sm_handle, BTIF_AV_CONNECT_REQ_EVT, (char*)&connect_req);
 
     return BT_STATUS_SUCCESS;
 }
 
-static bt_status_t connect(bt_bdaddr_t *bd_addr)
+static bt_status_t connect_sink(bt_bdaddr_t *bd_addr)
+{
+    BTIF_TRACE_EVENT1("%s", __FUNCTION__);
+    CHECK_BTAV_INIT();
+    return btif_queue_connect(UUID_SERVCLASS_AUDIO_SINK, bd_addr,
+                                 connect_int);
+}
+
+static bt_status_t connect_src(bt_bdaddr_t *bd_addr)
 {
     BTIF_TRACE_EVENT1("%s", __FUNCTION__);
     CHECK_BTAV_INIT();
@@ -866,12 +1014,110 @@ static void cleanup(void)
     return;
 }
 
+/*******************************************************************************
+**
+** Function         is_src
+**
+** Description      Checks if peer device is A2DP SRC
+**
+** Returns          Success in case peer is A2DP Src, FAIL otherwise
+**
+*******************************************************************************/
+bt_status_t is_src( bt_bdaddr_t *bd_addr )
+{
+    BTIF_TRACE_DEBUG0(" isSrc:  Check if peer device with bd_addr is audio src or sink");
+    if (btif_av_cb.sep == SEP_SRC)
+    {
+        BTIF_TRACE_DEBUG0(" Current Peer is SRC");
+        return BT_STATUS_SUCCESS;
+    }
+    else if (btif_av_cb.sep == SEP_SNK)
+    {
+        BTIF_TRACE_DEBUG0(" Current Peer is SNK");
+        return BT_STATUS_FAIL;
+    }
+    else
+    {
+        BTIF_TRACE_DEBUG0(" Stream not opened till now");
+        return BT_STATUS_NOT_READY;
+    }
+}
+
+/*******************************************************************************
+**
+** Function         activate_sink
+**
+** Description      Activates/Deactivates A2DP Sink
+**
+** Returns          None
+**
+*******************************************************************************/
+void activate_sink(int enable)
+{
+    BTIF_TRACE_DEBUG1(" Activate Sink %d", enable);
+    btif_dispatch_sm_event(BTIF_AV_REQUEST_ACTIVATE_SINK_EVT, (char*)&enable, sizeof(int));
+}
+
+/*******************************************************************************
+**
+** Function         suspend_sink
+**
+** Description      Suspends stream  in case of A2DP Sink
+**
+** Returns          None
+**
+*******************************************************************************/
+void suspend_sink()
+{
+    BTIF_TRACE_DEBUG0(" suspend Stream Suspend called");
+    if (btif_av_cb.sep == SEP_SRC)
+        btif_dispatch_sm_event(BTIF_AV_SUSPEND_STREAM_REQ_EVT, NULL, 0);
+}
+
+/*******************************************************************************
+**
+** Function         resume_sink
+**
+** Description      Resumes stream  in case of A2DP Sink
+**
+** Returns          None
+**
+*******************************************************************************/
+void resume_sink()
+{
+    BTIF_TRACE_DEBUG0(" resume Stream called");
+    if (btif_av_cb.sep == SEP_SRC)
+        btif_dispatch_sm_event(BTIF_AV_START_STREAM_REQ_EVT, NULL, 0);
+}
+
+/*******************************************************************************
+**
+** Function         audio_focus_status
+**
+** Description      Updates audio focus state
+**
+** Returns          None
+**
+*******************************************************************************/
+static void audio_focus_status(int state)
+{
+    BTIF_TRACE_DEBUG1(" Audio Focus granted %d",state);
+
+    btif_a2dp_set_audio_focus_state(state);
+}
+
 static const btav_interface_t bt_av_interface = {
     sizeof(btav_interface_t),
     init,
-    connect,
+    connect_src,
+    connect_sink,
     disconnect,
     cleanup,
+    is_src,
+    suspend_sink,
+    resume_sink,
+    audio_focus_status,
+    activate_sink,
 };
 
 /*******************************************************************************
@@ -995,7 +1241,7 @@ bt_status_t btif_av_execute_service(BOOLEAN b_enable)
          BTA_AvEnable(BTA_SEC_AUTHENTICATE, (BTA_AV_FEAT_RCTG | BTA_AV_FEAT_NO_SCO_SSPD),
                       bte_av_callback);
 #endif
-         BTA_AvRegister(BTA_AV_CHNL_AUDIO, BTIF_AV_SERVICE_NAME, 0);
+         BTA_AvRegister(BTA_AV_CHNL_AUDIO, BTIF_AV_SERVICE_NAME, 0, bte_av_media_callback);
      }
      else {
          BTA_AvDeregister(btif_av_cb.bta_handle);
index d2e8354..1b826ae 100644 (file)
@@ -675,7 +675,7 @@ static bt_status_t init( bthf_callbacks_t* callbacks, int max_hf_clients)
 ** Returns         bt_status_t
 **
 *******************************************************************************/
-static bt_status_t connect_int( bt_bdaddr_t *bd_addr )
+static bt_status_t connect_int(bt_bdaddr_t *bd_addr, uint16_t uuid)
 {
     CHECK_BTHF_INIT();
     int i;
index f1eb374..98a73d8 100644 (file)
@@ -211,7 +211,7 @@ static bt_status_t init( bthf_client_callbacks_t* callbacks )
 ** Returns         bt_status_t
 **
 *******************************************************************************/
-static bt_status_t connect_int( bt_bdaddr_t *bd_addr )
+static bt_status_t connect_int( bt_bdaddr_t *bd_addr, uint16_t uuid )
 {
     if (is_connected(bd_addr))
         return BT_STATUS_BUSY;
index 26bda41..aa2d3c8 100644 (file)
 #include "btif_av.h"
 #include "btif_sm.h"
 #include "btif_util.h"
+#ifdef BTA_AVK_INCLUDED
+#include "oi_codec_sbc.h"
+#include "oi_status.h"
+#endif
+#include "stdio.h"
+#include <dlfcn.h>
+#include "bluetoothTrack.h"
+
+//#define DEBUG_MEDIA_AV_FLOW TRUE
+
+#ifdef BTA_AVK_INCLUDED
+OI_CODEC_SBC_DECODER_CONTEXT context;
+OI_UINT32 contextData[CODEC_DATA_WORDS(2, SBC_CODEC_FAST_FILTER_BUFFERS)];
+OI_INT16 pcmData[15*SBC_MAX_SAMPLES_PER_FRAME*SBC_MAX_CHANNELS];
+void *dlhandle = NULL;
+oi_sbc_decoder_vendor_interface_t *oi_sbc_decode_vnd_if = NULL;
+#endif
 
 /*****************************************************************************
  **  Constants
  *****************************************************************************/
 
-//#define DEBUG_MEDIA_AV_FLOW TRUE
+#ifndef AUDIO_CHANNEL_OUT_MONO
+#define AUDIO_CHANNEL_OUT_MONO 0x01
+#endif
+
+#ifndef AUDIO_CHANNEL_OUT_STEREO
+#define AUDIO_CHANNEL_OUT_STEREO 0x03
+#endif
 
 /* BTIF media task gki event definition */
 #define BTIF_MEDIA_TASK_CMD TASK_MBOX_0_EVT_MASK
 
 #define BTIF_MEDIA_AA_TASK_TIMER_ID TIMER_0
 #define BTIF_MEDIA_AV_TASK_TIMER_ID TIMER_1
+#define BTIF_MEDIA_AVK_TASK_TIMER_ID TIMER_2
+
 #define BTIF_MEDIA_AA_TASK_TIMER TIMER_0_EVT_MASK
 #define BTIF_MEDIA_AV_TASK_TIMER TIMER_1_EVT_MASK
+#define BTIF_MEDIA_AVK_TASK_TIMER TIMER_2_EVT_MASK
+
 
 #define BTIF_MEDIA_TASK_CMD_MBOX        TASK_MBOX_0     /* cmd mailbox  */
 #define BTIF_MEDIA_TASK_DATA_MBOX       TASK_MBOX_1     /* data mailbox  */
@@ -102,7 +129,11 @@ enum
     BTIF_MEDIA_FLUSH_AA_TX,
     BTIF_MEDIA_FLUSH_AA_RX,
     BTIF_MEDIA_AUDIO_FEEDING_INIT,
-    BTIF_MEDIA_AUDIO_RECEIVING_INIT
+    BTIF_MEDIA_AUDIO_RECEIVING_INIT,
+    BTIF_MEDIA_AUDIO_SINK_CFG_UPDATE,
+    BTIF_MEDIA_AUDIO_SINK_START_DECODING,
+    BTIF_MEDIA_AUDIO_SINK_STOP_DECODING,
+    BTIF_MEDIA_AUDIO_SINK_CLEAR_TRACK
 };
 
 enum {
@@ -121,6 +152,8 @@ enum {
 
 #define BTIF_MEDIA_TIME_TICK                     (20 * BTIF_MEDIA_NUM_TICK)
 #define A2DP_DATA_READ_POLL_MS    (BTIF_MEDIA_TIME_TICK / 2)
+#define BTIF_SINK_MEDIA_TIME_TICK                (20 * BTIF_MEDIA_NUM_TICK)
+
 
 /* buffer pool */
 #define BTIF_MEDIA_AA_POOL_ID GKI_POOL_ID_3
@@ -183,6 +216,13 @@ static UINT32 a2dp_media_task_stack[(A2DP_MEDIA_TASK_STACK_SIZE + 3) / 4];
 #define RESET_RATE_COUNTER_THRESHOLD_MS    2000
 
 //#define BTIF_MEDIA_VERBOSE_ENABLED
+/* In case of A2DP SINK, we will delay start by 5 AVDTP Packets*/
+#define MAX_A2DP_DELAYED_START_FRAME_COUNT 5
+#define PACKET_PLAYED_PER_TICK_48 8
+#define PACKET_PLAYED_PER_TICK_44 7
+#define PACKET_PLAYED_PER_TICK_32 5
+#define PACKET_PLAYED_PER_TICK_16 3
+
 
 #ifdef BTIF_MEDIA_VERBOSE_ENABLED
 #define VERBOSE(fmt, ...) \
@@ -195,6 +235,13 @@ static UINT32 a2dp_media_task_stack[(A2DP_MEDIA_TASK_STACK_SIZE + 3) / 4];
 /*****************************************************************************
  **  Data types
  *****************************************************************************/
+typedef struct
+{
+    UINT16 num_frames_to_be_processed;
+    UINT16 len;
+    UINT16 offset;
+    UINT16 layer_specific;
+} tBT_SBC_HDR;
 
 typedef struct
 {
@@ -219,7 +266,9 @@ typedef struct
 {
 #if (BTA_AV_INCLUDED == TRUE)
     BUFFER_Q TxAaQ;
+    BUFFER_Q RxSbcQ;
     BOOLEAN is_tx_timer;
+    BOOLEAN is_rx_timer;
     UINT16 TxAaMtuSize;
     UINT32 timestamp;
     UINT8 TxTranscoding;
@@ -231,6 +280,10 @@ typedef struct
     void* av_sm_hdl;
     UINT8 a2dp_cmd_pending; /* we can have max one command pending */
     BOOLEAN tx_flush; /* discards any outgoing data when true */
+    BOOLEAN rx_flush; /* discards any incoming data when true */
+    BOOLEAN is_source;
+    UINT8   frames_to_process;
+    BOOLEAN rx_audio_focus_gained;
 #endif
 
 } tBTIF_MEDIA_CB;
@@ -259,13 +312,24 @@ static void btif_a2dp_data_cb(tUIPC_CH_ID ch_id, tUIPC_EVENT event);
 static void btif_a2dp_ctrl_cb(tUIPC_CH_ID ch_id, tUIPC_EVENT event);
 static void btif_a2dp_encoder_update(void);
 const char* dump_media_event(UINT16 event);
+#ifdef BTA_AVK_INCLUDED
+void btif_load_decoder_library();
+#endif
+static void btif_media_flush_q(BUFFER_Q *p_q);
+static void btif_media_task_aa_handle_stop_decoding(void );
+static void btif_media_task_aa_rx_flush(void);
+static BOOLEAN btif_media_task_stop_decoding_req(void);
 
 /*****************************************************************************
  **  Externs
  *****************************************************************************/
 
 static void btif_media_task_handle_cmd(BT_HDR *p_msg);
-static void btif_media_task_handle_media(BT_HDR *p_msg);
+static void btif_media_task_handle_media(BT_HDR*p_msg);
+/* Handle incoming media packets A2DP SINK streaming*/
+#ifdef BTA_AVK_INCLUDED
+static void btif_media_task_handle_inc_media(tBT_SBC_HDR*p_msg);
+#endif
 
 #if (BTA_AV_INCLUDED == TRUE)
 static void btif_media_send_aa_frame(void);
@@ -277,9 +341,15 @@ static void btif_media_task_enc_update(BT_HDR *p_msg);
 static void btif_media_task_audio_feeding_init(BT_HDR *p_msg);
 static void btif_media_task_aa_tx_flush(BT_HDR *p_msg);
 static void btif_media_aa_prep_2_send(UINT8 nb_frame);
+#ifdef BTA_AVK_INCLUDED
+static void btif_media_task_aa_handle_decoder_reset(BT_HDR *p_msg);
+static void btif_media_task_aa_handle_clear_track(void);
 #endif
-
-
+static void btif_media_task_aa_handle_start_decoding(void );
+#endif
+extern void btif_av_request_audio_focus(BOOLEAN enable);
+BOOLEAN btif_media_task_start_decoding_req(void);
+BOOLEAN btif_media_task_clear_track(void);
 /*****************************************************************************
  **  Misc helper functions
  *****************************************************************************/
@@ -318,6 +388,10 @@ const char* dump_media_event(UINT16 event)
         CASE_RETURN_STR(BTIF_MEDIA_FLUSH_AA_RX)
         CASE_RETURN_STR(BTIF_MEDIA_AUDIO_FEEDING_INIT)
         CASE_RETURN_STR(BTIF_MEDIA_AUDIO_RECEIVING_INIT)
+        CASE_RETURN_STR(BTIF_MEDIA_AUDIO_SINK_CFG_UPDATE)
+        CASE_RETURN_STR(BTIF_MEDIA_AUDIO_SINK_START_DECODING)
+        CASE_RETURN_STR(BTIF_MEDIA_AUDIO_SINK_STOP_DECODING)
+        CASE_RETURN_STR(BTIF_MEDIA_AUDIO_SINK_CLEAR_TRACK)
 
         default:
             return "UNKNOWN MEDIA EVENT";
@@ -381,7 +455,6 @@ static void btif_recv_ctrl_data(void)
 {
     UINT8 cmd = 0;
     int n;
-
     n = UIPC_Read(UIPC_CH_ID_AV_CTRL, NULL, &cmd, 1);
 
     /* detach on ctrl channel means audioflinger process was terminated */
@@ -779,11 +852,26 @@ void btif_a2dp_setup_codec(void)
 void btif_a2dp_on_idle(void)
 {
     APPL_TRACE_EVENT0("## ON A2DP IDLE ##");
-
-    /* Make sure media task is stopped */
-    btif_media_task_stop_aa_req();
+    if(btif_media_cb.is_source)
+    {
+        /* Make sure media task is stopped */
+        btif_media_task_stop_aa_req();
+    }
 
     bta_av_co_init();
+#ifdef BTA_AVK_INCLUDED
+    if (!btif_media_cb.is_source)
+    {
+        btif_media_cb.rx_flush = TRUE;
+        btif_media_task_aa_rx_flush_req();
+        btif_media_task_stop_decoding_req();
+        btif_media_task_clear_track();
+        APPL_TRACE_DEBUG0("Stopped BT track");
+        APPL_TRACE_DEBUG0("Reset to Source role");
+        btif_media_cb.is_source = TRUE;
+        btif_media_cb.rx_audio_focus_gained = BTIF_MEDIA_AUDIOFOCUS_LOSS;
+    }
+#endif
 }
 
 /*****************************************************************************
@@ -804,6 +892,113 @@ void btif_a2dp_on_open(void)
     UIPC_Open(UIPC_CH_ID_AV_AUDIO, btif_a2dp_data_cb);
 }
 
+/*******************************************************************************
+ **
+ ** Function         btif_media_task_clear_track
+ **
+ ** Description
+ **
+ ** Returns          TRUE is success
+ **
+ *******************************************************************************/
+BOOLEAN btif_media_task_clear_track(void)
+{
+    BT_HDR *p_buf;
+
+    if (NULL == (p_buf = GKI_getbuf(sizeof(BT_HDR))))
+    {
+        return FALSE;
+    }
+
+    p_buf->event = BTIF_MEDIA_AUDIO_SINK_CLEAR_TRACK;
+
+    GKI_send_msg(BT_MEDIA_TASK, BTIF_MEDIA_TASK_CMD_MBOX, p_buf);
+    return TRUE;
+}
+/*******************************************************************************
+ **
+ ** Function         btif_media_task_stop_decoding_req
+ **
+ ** Description
+ **
+ ** Returns          TRUE is success
+ **
+ *******************************************************************************/
+BOOLEAN btif_media_task_stop_decoding_req(void)
+{
+    BT_HDR *p_buf;
+
+    if (!btif_media_cb.is_rx_timer)
+        return TRUE;   /*  if timer is not running no need to send message */
+
+    if (NULL == (p_buf = GKI_getbuf(sizeof(BT_HDR))))
+    {
+        return FALSE;
+    }
+
+    p_buf->event = BTIF_MEDIA_AUDIO_SINK_STOP_DECODING;
+
+    GKI_send_msg(BT_MEDIA_TASK, BTIF_MEDIA_TASK_CMD_MBOX, p_buf);
+    return TRUE;
+}
+
+/*******************************************************************************
+ **
+ ** Function         btif_media_task_start_decoding_req
+ **
+ ** Description
+ **
+ ** Returns          TRUE is success
+ **
+ *******************************************************************************/
+BOOLEAN btif_media_task_start_decoding_req(void)
+{
+    BT_HDR *p_buf;
+
+    if(btif_media_cb.is_rx_timer)
+        return FALSE;   /*  if timer is already running no need to send message */
+
+    if (NULL == (p_buf = GKI_getbuf(sizeof(BT_HDR))))
+    {
+        return FALSE;
+    }
+
+    p_buf->event = BTIF_MEDIA_AUDIO_SINK_START_DECODING;
+
+    GKI_send_msg(BT_MEDIA_TASK, BTIF_MEDIA_TASK_CMD_MBOX, p_buf);
+    return TRUE;
+}
+
+/*****************************************************************************
+**
+** Function        btif_reset_decoder
+**
+** Description
+**
+** Returns
+**
+*******************************************************************************/
+
+void btif_reset_decoder(UINT8 *p_av)
+{
+    APPL_TRACE_EVENT0("btif_reset_decoder");
+    APPL_TRACE_DEBUG6("btif_reset_decoder p_codec_info[%x:%x:%x:%x:%x:%x]",
+            p_av[1], p_av[2], p_av[3],
+            p_av[4], p_av[5], p_av[6]);
+
+    tBTIF_MEDIA_SINK_CFG_UPDATE *p_buf;
+    if (NULL == (p_buf = GKI_getbuf(sizeof(tBTIF_MEDIA_SINK_CFG_UPDATE))))
+    {
+        APPL_TRACE_EVENT0("btif_reset_decoder No Buffer ");
+        return;
+    }
+
+    memcpy(p_buf->codec_info,p_av, AVDT_CODEC_SIZE);
+    p_buf->hdr.event = BTIF_MEDIA_AUDIO_SINK_CFG_UPDATE;
+
+    GKI_send_msg(BT_MEDIA_TASK, BTIF_MEDIA_TASK_CMD_MBOX, p_buf);
+}
+
 /*****************************************************************************
 **
 ** Function        btif_a2dp_on_started
@@ -889,7 +1084,13 @@ void btif_a2dp_ack_fail(void)
 void btif_a2dp_on_stopped(tBTA_AV_SUSPEND *p_av)
 {
     APPL_TRACE_EVENT0("## ON A2DP STOPPED ##");
-
+    if ((!btif_media_cb.is_source)) /*  Handling for A2DP SINK cases*/
+    {
+        btif_media_cb.rx_flush = TRUE;
+        btif_media_task_aa_rx_flush_req();
+        btif_media_task_stop_decoding_req();
+        return;
+    }
     /* allow using this api for other than suspend */
     if (p_av != NULL)
     {
@@ -927,6 +1128,13 @@ void btif_a2dp_on_stopped(tBTA_AV_SUSPEND *p_av)
 void btif_a2dp_on_suspended(tBTA_AV_SUSPEND *p_av)
 {
     APPL_TRACE_EVENT0("## ON A2DP SUSPENDED ##");
+    if ((!btif_media_cb.is_source))
+    {
+        btif_media_cb.rx_flush = TRUE;
+        btif_media_task_aa_rx_flush_req();
+        btif_media_task_stop_decoding_req();
+        return;
+    }
 
     /* check for status failures */
     if (p_av->status != BTA_AV_SUCCESS)
@@ -944,6 +1152,13 @@ void btif_a2dp_on_suspended(tBTA_AV_SUSPEND *p_av)
     btif_media_task_stop_aa_req();
 }
 
+/* when true media task discards any rx frames */
+void btif_a2dp_set_rx_flush(BOOLEAN enable)
+{
+    APPL_TRACE_EVENT1("## DROP RX %d ##", enable);
+    btif_media_cb.rx_flush = enable;
+}
+
 /* when true media task discards any tx frames */
 void btif_a2dp_set_tx_flush(BOOLEAN enable)
 {
@@ -951,6 +1166,94 @@ void btif_a2dp_set_tx_flush(BOOLEAN enable)
     btif_media_cb.tx_flush = enable;
 }
 
+/* when true media task discards any rx frames */
+void btif_a2dp_set_audio_focus_state(btif_media_AudioFocus_state state)
+{
+    APPL_TRACE_EVENT1("## Audio_focus_state Rx %d ##", state);
+    btif_media_cb.rx_audio_focus_gained = state;
+}
+
+#ifdef BTA_AVK_INCLUDED
+/*******************************************************************************
+ **
+ ** Function         btif_media_task_avk_handle_timer
+ **
+ ** Description
+ **
+ ** Returns          void
+ **
+ *******************************************************************************/
+static void btif_media_task_avk_handle_timer ( void )
+{
+    UINT8 count;
+    tBT_SBC_HDR *p_msg;
+    int num_sbc_frames;
+    int num_frames_to_process;
+
+    count = btif_media_cb.RxSbcQ.count;
+    if (0 == count)
+    {
+        APPL_TRACE_DEBUG0("  QUE  EMPTY ");
+    }
+    else
+    {
+        if (btif_media_cb.rx_flush == TRUE)
+        {
+            btif_media_flush_q(&(btif_media_cb.RxSbcQ));
+            return;
+        }
+        if (btif_media_cb.rx_audio_focus_gained == BTIF_MEDIA_AUDIOFOCUS_LOSS_TRANSIENT)
+        {
+            APPL_TRACE_DEBUG0("Received Transient Focus Loss, Ignoring");
+            return;
+        }
+
+        if (btif_media_cb.rx_audio_focus_gained == BTIF_MEDIA_AUDIOFOCUS_LOSS)
+        {
+            /* Send a Audio Focus Request */
+            btif_av_request_audio_focus(TRUE);
+            return;
+        }
+        num_frames_to_process = btif_media_cb.frames_to_process;
+        APPL_TRACE_DEBUG0(" Process Frames + ");
+
+        do
+        {
+            p_msg = (tBT_SBC_HDR *)GKI_getfirst(&(btif_media_cb.RxSbcQ));
+            if (p_msg == NULL)
+                return;
+            num_sbc_frames  = p_msg->num_frames_to_be_processed; /* num of frames in Que Packets */
+            APPL_TRACE_DEBUG1(" Frames left in topmost packet %d", num_sbc_frames);
+            APPL_TRACE_DEBUG1(" Remaining frames to process in tick %d", num_frames_to_process);
+            APPL_TRACE_DEBUG1(" Num of Packets in Que %d", btif_media_cb.RxSbcQ.count);
+
+            if ( num_sbc_frames > num_frames_to_process) /*  Que Packet has more frames*/
+            {
+                 p_msg->num_frames_to_be_processed= num_frames_to_process;
+                 btif_media_task_handle_inc_media(p_msg);
+                 p_msg->num_frames_to_be_processed = num_sbc_frames - num_frames_to_process;
+                 num_frames_to_process = 0;
+                 break;
+            }
+            else                                        /*  Que packet has less frames */
+            {
+                btif_media_task_handle_inc_media(p_msg);
+                p_msg = (tBT_SBC_HDR *)GKI_dequeue(&(btif_media_cb.RxSbcQ));
+                if( p_msg == NULL )
+                {
+                     APPL_TRACE_ERROR0("Insufficient data in que ");
+                     break;
+                }
+                num_frames_to_process = num_frames_to_process - p_msg->num_frames_to_be_processed;
+                GKI_freebuf(p_msg);
+            }
+        }while(num_frames_to_process > 0);
+
+        APPL_TRACE_DEBUG0(" Process Frames - ");
+    }
+}
+#endif
+
 /*******************************************************************************
  **
  ** Function         btif_media_task_aa_handle_timer
@@ -1027,8 +1330,8 @@ void btif_media_task_init(void)
 #if (BTA_AV_INCLUDED == TRUE)
     UIPC_Open(UIPC_CH_ID_AV_CTRL , btif_a2dp_ctrl_cb);
 #endif
-
-
+    btif_media_cb.is_source = TRUE;
+    APPL_TRACE_DEBUG0("Reset to Source role");
 }
 /*******************************************************************************
  **
@@ -1075,6 +1378,7 @@ int btif_media_task(void *p)
 
         if (event & BTIF_MEDIA_TASK_DATA)
         {
+            VERBOSE("================= Received Media Packets %d ===============", event);
             /* Process all messages in the queue */
             while ((p_msg = (BT_HDR *) GKI_read_mbox(BTIF_MEDIA_TASK_DATA_MBOX)) != NULL)
             {
@@ -1088,6 +1392,15 @@ int btif_media_task(void *p)
             btif_media_task_aa_handle_timer();
         }
 
+        if (event & BTIF_MEDIA_AVK_TASK_TIMER)
+        {
+#ifdef BTA_AVK_INCLUDED
+            /* advance audio timer expiration for a2dp sink */
+            btif_media_task_avk_handle_timer();
+#endif
+        }
+
+
 
         VERBOSE("=============== MEDIA TASK EVENT %d DONE ============", event);
 
@@ -1146,7 +1459,7 @@ BOOLEAN btif_media_task_send_cmd_evt(UINT16 Evt)
  *******************************************************************************/
 static void btif_media_flush_q(BUFFER_Q *p_q)
 {
-    while (GKI_IS_QUEUE_EMPTY(p_q) == FALSE)
+    while (GKI_queue_is_empty(p_q) == FALSE)
     {
         GKI_freebuf(GKI_dequeue(p_q));
     }
@@ -1191,6 +1504,25 @@ static void btif_media_task_handle_cmd(BT_HDR *p_msg)
     case BTIF_MEDIA_UIPC_RX_RDY:
         btif_media_task_aa_handle_uipc_rx_rdy();
         break;
+    case BTIF_MEDIA_AUDIO_SINK_CFG_UPDATE:
+#ifdef BTA_AVK_INCLUDED
+        btif_media_task_aa_handle_decoder_reset(p_msg);
+#endif
+        break;
+    case BTIF_MEDIA_AUDIO_SINK_START_DECODING:
+        btif_media_task_aa_handle_start_decoding();
+        break;
+    case BTIF_MEDIA_AUDIO_SINK_CLEAR_TRACK:
+#ifdef BTA_AVK_INCLUDED
+        btif_media_task_aa_handle_clear_track();
+#endif
+        break;
+    case BTIF_MEDIA_AUDIO_SINK_STOP_DECODING:
+        btif_media_task_aa_handle_stop_decoding();
+        break;
+     case BTIF_MEDIA_FLUSH_AA_RX:
+        btif_media_task_aa_rx_flush();
+        break;
 #endif
     default:
         APPL_TRACE_ERROR1("ERROR in btif_media_task_handle_cmd unknown event %d", p_msg->event);
@@ -1199,25 +1531,68 @@ static void btif_media_task_handle_cmd(BT_HDR *p_msg)
     VERBOSE("btif_media_task_handle_cmd : %s DONE", dump_media_event(p_msg->event));
 }
 
+#ifdef BTA_AVK_INCLUDED
 /*******************************************************************************
  **
- ** Function         btif_media_task_handle_media
+ ** Function         btif_media_task_handle_inc_media
  **
  ** Description
  **
  ** Returns          void
  **
  *******************************************************************************/
-static void btif_media_task_handle_media(BT_HDR *p_msg)
+static void btif_media_task_handle_inc_media(tBT_SBC_HDR*p_msg)
 {
-    APPL_TRACE_ERROR0("ERROR btif_media_task_handle_media: not in use");
-
-    GKI_freebuf(p_msg);
-}
-
+    UINT8 *sbc_start_frame = ((UINT8*)(p_msg + 1) + p_msg->offset + 1);
+    int count;
+    UINT32 pcmBytes, availPcmBytes;
+    OI_INT16 *pcmDataPointer = pcmData; /*Will be overwritten on next packet receipt*/
+    OI_STATUS status;
+    int num_sbc_frames = p_msg->num_frames_to_be_processed;
+    UINT32 sbc_frame_len = p_msg->len - 1;
+    int retwriteAudioTrack = 0;
+    availPcmBytes = 2*sizeof(pcmData);
+
+    if ((btif_media_cb.is_source) || (btif_media_cb.rx_flush))
+    {
+        APPL_TRACE_DEBUG0(" State Changed happened in this tick ");
+        return;
+    }
+    APPL_TRACE_DEBUG2("Number of sbc frames %d, frame_len %d", num_sbc_frames, sbc_frame_len);
 
+    for(count = 0; count < num_sbc_frames && sbc_frame_len != 0; count ++)
+    {
+        pcmBytes = availPcmBytes;
+        status = oi_sbc_decode_vnd_if->OI_CODEC_SBC_DecodeFrame(&context, (const OI_BYTE**)&sbc_start_frame,
+                                                        &sbc_frame_len, pcmDataPointer, &pcmBytes);
+        if (!OI_SUCCESS(status)) {
+            APPL_TRACE_ERROR1("Decoding failure: %d\n", status);
+            break;
+        }
+        availPcmBytes -= pcmBytes;
+        pcmDataPointer += pcmBytes/2;
+        p_msg->offset += (p_msg->len - 1) - sbc_frame_len;
+        p_msg->len = sbc_frame_len + 1;
+    }
 
+    retwriteAudioTrack = btWriteData((void*)pcmData, (2*sizeof(pcmData) - availPcmBytes));
+}
+#endif
 
+/*******************************************************************************
+ **
+ ** Function         btif_media_task_handle_media
+ **
+ ** Description
+ **
+ ** Returns          void
+ **
+ *******************************************************************************/
+static void btif_media_task_handle_media(BT_HDR*p_msg)
+{
+    APPL_TRACE_DEBUG0(" btif_media_task_handle_media ");
+    GKI_freebuf(p_msg);
+}
 #if (BTA_AV_INCLUDED == TRUE)
 /*******************************************************************************
  **
@@ -1337,6 +1712,32 @@ BOOLEAN btif_media_task_stop_aa_req(void)
     GKI_send_msg(BT_MEDIA_TASK, BTIF_MEDIA_TASK_CMD_MBOX, p_buf);
     return TRUE;
 }
+/*******************************************************************************
+ **
+ ** Function         btif_media_task_aa_rx_flush_req
+ **
+ ** Description
+ **
+ ** Returns          TRUE is success
+ **
+ *******************************************************************************/
+BOOLEAN btif_media_task_aa_rx_flush_req(void)
+{
+    BT_HDR *p_buf;
+
+    if (GKI_queue_is_empty(&(btif_media_cb.RxSbcQ))== TRUE) /*  Que is already empty */
+        return TRUE;
+
+    if (NULL == (p_buf = GKI_getbuf(sizeof(BT_HDR))))
+    {
+        return FALSE;
+    }
+
+    p_buf->event = BTIF_MEDIA_FLUSH_AA_RX;
+
+    GKI_send_msg(BT_MEDIA_TASK, BTIF_MEDIA_TASK_CMD_MBOX, p_buf);
+    return TRUE;
+}
 
 /*******************************************************************************
  **
@@ -1360,6 +1761,23 @@ BOOLEAN btif_media_task_aa_tx_flush_req(void)
     GKI_send_msg(BT_MEDIA_TASK, BTIF_MEDIA_TASK_CMD_MBOX, p_buf);
     return TRUE;
 }
+/*******************************************************************************
+ **
+ ** Function         btif_media_task_aa_rx_flush
+ **
+ ** Description
+ **
+ ** Returns          void
+ **
+ *******************************************************************************/
+static void btif_media_task_aa_rx_flush(void)
+{
+    /* Flush all enqueued GKI SBC  buffers (encoded) */
+    APPL_TRACE_DEBUG0("btif_media_task_aa_rx_flush");
+
+    btif_media_flush_q(&(btif_media_cb.RxSbcQ));
+}
+
 
 /*******************************************************************************
  **
@@ -1679,6 +2097,234 @@ static void btif_media_task_audio_feeding_init(BT_HDR *p_msg)
     }
 }
 
+int a2dp_get_track_frequency(UINT8 frequency) {
+    int freq = 48000;
+    switch (frequency) {
+        case A2D_SBC_IE_SAMP_FREQ_16:
+            freq = 16000;
+            break;
+        case A2D_SBC_IE_SAMP_FREQ_32:
+            freq = 32000;
+            break;
+        case A2D_SBC_IE_SAMP_FREQ_44:
+            freq = 44100;
+            break;
+        case A2D_SBC_IE_SAMP_FREQ_48:
+            freq = 48000;
+            break;
+    }
+    return freq;
+}
+
+int a2dp_get_track_channel_type(UINT8 channeltype) {
+    int channel = AUDIO_CHANNEL_OUT_MONO;
+    switch (channeltype) {
+        case A2D_SBC_IE_CH_MD_MONO:
+            channel = AUDIO_CHANNEL_OUT_MONO;
+            break;
+        case A2D_SBC_IE_CH_MD_DUAL:
+        case A2D_SBC_IE_CH_MD_STEREO:
+        case A2D_SBC_IE_CH_MD_JOINT:
+            channel = AUDIO_CHANNEL_OUT_STEREO;
+            break;
+    }
+    return channel;
+}
+
+/*******************************************************************************
+ **
+ ** Function         btif_media_task_aa_handle_stop_decoding
+ **
+ ** Description
+ **
+ ** Returns          void
+ **
+ *******************************************************************************/
+static void btif_media_task_aa_handle_stop_decoding(void )
+{
+    btif_media_cb.is_rx_timer = FALSE;
+    GKI_stop_timer(BTIF_MEDIA_AVK_TASK_TIMER_ID);
+    btPauseTrack();
+}
+
+/*******************************************************************************
+ **
+ ** Function         btif_media_task_aa_handle_start_decoding
+ **
+ ** Description
+ **
+ ** Returns          void
+ **
+ *******************************************************************************/
+static void btif_media_task_aa_handle_start_decoding(void )
+{
+    if(btif_media_cb.is_rx_timer == TRUE)
+        return;
+    btStartTrack();
+    btif_media_cb.is_rx_timer = TRUE;
+    GKI_start_timer(BTIF_MEDIA_AVK_TASK_TIMER_ID, GKI_MS_TO_TICKS(BTIF_SINK_MEDIA_TIME_TICK), TRUE);
+}
+
+#ifdef BTA_AVK_INCLUDED
+
+static void btif_media_task_aa_handle_clear_track (void)
+{
+    APPL_TRACE_DEBUG0("btif_media_task_aa_handle_clear_track");
+    btStopTrack();
+    btDeleteTrack();
+    if (dlhandle)
+    {
+        APPL_TRACE_DEBUG0("Unload Decoder lib");
+        dlclose(dlhandle);
+        dlhandle = NULL;
+        oi_sbc_decode_vnd_if = NULL;
+    }
+}
+
+/*******************************************************************************
+ **
+ ** Function         btif_media_task_aa_handle_decoder_reset
+ **
+ ** Description
+ **
+ ** Returns          void
+ **
+ *******************************************************************************/
+static void btif_media_task_aa_handle_decoder_reset(BT_HDR *p_msg)
+{
+    tBTIF_MEDIA_SINK_CFG_UPDATE *p_buf = (tBTIF_MEDIA_SINK_CFG_UPDATE*) p_msg;
+    tA2D_STATUS a2d_status;
+    tA2D_SBC_CIE sbc_cie;
+    OI_STATUS       status;
+    UINT32          freq_multiple; /* frequency multiple for 20ms of data */
+    UINT32          num_blocks;
+    UINT32          num_subbands;
+    UINT32          num_channel;
+
+    APPL_TRACE_DEBUG6("btif_media_task_aa_handle_decoder_reset p_codec_info[%x:%x:%x:%x:%x:%x]",
+            p_buf->codec_info[1], p_buf->codec_info[2], p_buf->codec_info[3],
+            p_buf->codec_info[4], p_buf->codec_info[5], p_buf->codec_info[6]);
+
+    a2d_status = A2D_ParsSbcInfo(&sbc_cie, p_buf->codec_info, FALSE);
+    if (a2d_status != A2D_SUCCESS)
+    {
+        APPL_TRACE_ERROR1("ERROR dump_codec_info A2D_ParsSbcInfo fail:%d", a2d_status);
+        return;
+    }
+    btif_media_cb.is_source = FALSE;
+    btif_media_cb.rx_flush = FALSE;
+    APPL_TRACE_DEBUG0("Reset to sink role");
+    btif_load_decoder_library();
+    status = oi_sbc_decode_vnd_if->OI_CODEC_SBC_DecoderReset(&context, contextData, sizeof(contextData), 2, 2, FALSE);
+    if (!OI_SUCCESS(status)) {
+        APPL_TRACE_ERROR1("OI_CODEC_SBC_DecoderReset failed with error code %d\n", status);
+    }
+    APPL_TRACE_DEBUG0("A2dpSink: Crate Track");
+    if (btCreateTrack(a2dp_get_track_frequency(sbc_cie.samp_freq), a2dp_get_track_channel_type(sbc_cie.ch_mode)) == -1) {
+        APPL_TRACE_ERROR0("A2dpSink: Track creation fails!!!");
+        return;
+    }
+
+    switch(sbc_cie.samp_freq)
+    {
+        case A2D_SBC_IE_SAMP_FREQ_16:
+            APPL_TRACE_DEBUG1("\tsamp_freq:%d (16000)", sbc_cie.samp_freq);
+            freq_multiple = 16*20;
+            break;
+        case A2D_SBC_IE_SAMP_FREQ_32:
+            APPL_TRACE_DEBUG1("\tsamp_freq:%d (32000)", sbc_cie.samp_freq);
+            freq_multiple = 32*20;
+            break;
+        case A2D_SBC_IE_SAMP_FREQ_44:
+            APPL_TRACE_DEBUG1("\tsamp_freq:%d (44100)", sbc_cie.samp_freq);
+            freq_multiple = 441*2;
+            break;
+        case A2D_SBC_IE_SAMP_FREQ_48:
+            APPL_TRACE_DEBUG1("\tsamp_freq:%d (48000)", sbc_cie.samp_freq);
+            freq_multiple = 48*20;
+            break;
+        default:
+            APPL_TRACE_DEBUG0(" Unknown Frequency ");
+            break;
+    }
+
+    switch(sbc_cie.ch_mode)
+    {
+        case A2D_SBC_IE_CH_MD_MONO:
+            APPL_TRACE_DEBUG1("\tch_mode:%d (Mono)", sbc_cie.ch_mode);
+            break;
+        case A2D_SBC_IE_CH_MD_DUAL:
+            APPL_TRACE_DEBUG1("\tch_mode:%d (DUAL)", sbc_cie.ch_mode);
+            break;
+        case A2D_SBC_IE_CH_MD_STEREO:
+            APPL_TRACE_DEBUG1("\tch_mode:%d (STEREO)", sbc_cie.ch_mode);
+            break;
+        case A2D_SBC_IE_CH_MD_JOINT:
+            APPL_TRACE_DEBUG1("\tch_mode:%d (JOINT)", sbc_cie.ch_mode);
+            break;
+        default:
+            APPL_TRACE_DEBUG0(" Unknown Mode ");
+            break;
+    }
+
+    switch(sbc_cie.block_len)
+    {
+        case A2D_SBC_IE_BLOCKS_4:
+            APPL_TRACE_DEBUG1("\tblock_len:%d (4)", sbc_cie.block_len);
+            num_blocks = 4;
+            break;
+        case A2D_SBC_IE_BLOCKS_8:
+            APPL_TRACE_DEBUG1("\tblock_len:%d (8)", sbc_cie.block_len);
+            num_blocks = 8;
+            break;
+        case A2D_SBC_IE_BLOCKS_12:
+            APPL_TRACE_DEBUG1("\tblock_len:%d (12)", sbc_cie.block_len);
+            num_blocks = 12;
+            break;
+        case A2D_SBC_IE_BLOCKS_16:
+            APPL_TRACE_DEBUG1("\tblock_len:%d (16)", sbc_cie.block_len);
+            num_blocks = 16;
+            break;
+        default:
+            APPL_TRACE_DEBUG0(" Unknown BlockLen ");
+            break;
+    }
+
+    switch(sbc_cie.num_subbands)
+    {
+        case A2D_SBC_IE_SUBBAND_4:
+            APPL_TRACE_DEBUG1("\tnum_subbands:%d (4)", sbc_cie.num_subbands);
+            num_subbands = 4;
+            break;
+        case A2D_SBC_IE_SUBBAND_8:
+            APPL_TRACE_DEBUG1("\tnum_subbands:%d (8)", sbc_cie.num_subbands);
+            num_subbands = 8;
+            break;
+        default:
+            APPL_TRACE_DEBUG0(" Unknown SubBands ");
+            break;
+    }
+
+    switch(sbc_cie.alloc_mthd)
+    {
+        case A2D_SBC_IE_ALLOC_MD_S:
+            APPL_TRACE_DEBUG1("\talloc_mthd:%d (SNR)", sbc_cie.alloc_mthd);
+            break;
+        case A2D_SBC_IE_ALLOC_MD_L:
+            APPL_TRACE_DEBUG1("\talloc_mthd:%d (Loudness)", sbc_cie.alloc_mthd);
+            break;
+        default:
+            APPL_TRACE_DEBUG0(" Unknown Allocation Method");
+            break;
+    }
+
+    APPL_TRACE_DEBUG2("\tBit pool Min:%d Max:%d", sbc_cie.min_bitpool, sbc_cie.max_bitpool);
+
+    btif_media_cb.frames_to_process = ((freq_multiple)/(num_blocks*num_subbands)) + 1;
+    APPL_TRACE_DEBUG1(" Frames to be processed in 20 ms %d",btif_media_cb.frames_to_process);
+}
+#endif
+
 /*******************************************************************************
  **
  ** Function         btif_media_task_feeding_state_reset
@@ -1826,6 +2472,49 @@ static UINT8 btif_get_num_aa_frame(void)
 
 /*******************************************************************************
  **
+ ** Function         btif_media_sink_enque_buf
+ **
+ ** Description      This function is called by the av_co to fill A2DP Sink Queue
+ **
+ **
+ ** Returns          size of the queue
+ *******************************************************************************/
+UINT8 btif_media_sink_enque_buf(BT_HDR *p_pkt)
+{
+    tBT_SBC_HDR *p_msg;
+
+    if(btif_media_cb.rx_flush == TRUE) /* Flush enabled, do not enque*/
+        return btif_media_cb.RxSbcQ.count;
+    if(btif_media_cb.RxSbcQ.count == MAX_OUTPUT_A2DP_FRAME_QUEUE_SZ)
+    {
+        GKI_freebuf(GKI_dequeue(&(btif_media_cb.RxSbcQ)));
+    }
+
+    BTIF_TRACE_VERBOSE0("btif_media_sink_enque_buf + ");
+    /* allocate and Queue this buffer */
+    if ((p_msg = (tBT_SBC_HDR *) GKI_getbuf(sizeof(tBT_SBC_HDR) +
+                        p_pkt->offset+ p_pkt->len)) != NULL)
+    {
+        memcpy(p_msg, p_pkt, (sizeof(BT_HDR) + p_pkt->offset + p_pkt->len));
+        p_msg->num_frames_to_be_processed = (*((UINT8*)(p_msg + 1) + p_msg->offset)) & 0x0f;
+        BTIF_TRACE_VERBOSE1("btif_media_sink_enque_buf + ", p_msg->num_frames_to_be_processed);
+        GKI_enqueue(&(btif_media_cb.RxSbcQ), p_msg);
+        if(btif_media_cb.RxSbcQ.count == MAX_A2DP_DELAYED_START_FRAME_COUNT)
+        {
+            BTIF_TRACE_DEBUG0(" Initiate Decoding ");
+            btif_media_task_start_decoding_req();
+        }
+    }
+    else
+    {
+        /* let caller deal with a failed allocation */
+        BTIF_TRACE_VERBOSE0("btif_media_sink_enque_buf No Buffer left - ");
+    }
+    return btif_media_cb.RxSbcQ.count;
+}
+
+/*******************************************************************************
+ **
  ** Function         btif_media_aa_readbuf
  **
  ** Description      This function is called by the av_co to get the next buffer to send
@@ -2280,3 +2969,23 @@ void dump_codec_info(unsigned char *p_codec)
     APPL_TRACE_DEBUG2("\tBit pool Min:%d Max:%d", sbc_cie.min_bitpool, sbc_cie.max_bitpool);
 
 }
+
+#ifdef BTA_AVK_INCLUDED
+void btif_load_decoder_library()
+{
+    dlhandle = dlopen("liboi_sbc_decoder.so", RTLD_NOW);
+    APPL_TRACE_DEBUG0("Load decoder library");
+    if (!dlhandle)
+    {
+        APPL_TRACE_ERROR0("!!! Failed to load oi_sbc_decoder.so !!!");
+        return;
+    }
+
+    oi_sbc_decode_vnd_if = (oi_sbc_decoder_vendor_interface_t *) dlsym(dlhandle, "OI_SBC_DECODER_VENDOR_LIB_INTERFACE");
+    if (!oi_sbc_decode_vnd_if)
+    {
+        APPL_TRACE_ERROR0("!!! Failed to get oi sbc decode vendor interface !!!");
+        return;
+    }
+}
+#endif
index b9bbe17..12cec2e 100644 (file)
@@ -89,7 +89,7 @@ static bt_status_t queue_int_connect_next() {
         return BT_STATUS_SUCCESS;
 
     p_head->busy = true;
-    return p_head->connect_cb(&p_head->bda);
+    return p_head->connect_cb(&p_head->bda, p_head->uuid);
 }
 
 static void queue_int_handle_evt(UINT16 event, char *p_param) {
index 7cccf36..39bdd9f 100644 (file)
 #define BTA_GATT_INCLUDED TRUE
 #endif
 
+/* defined BTA_AVK_INCLUDED in Android.mk file based on target selected*/
+
 #ifndef BTA_DISABLE_DELAY
 #define BTA_DISABLE_DELAY 200 /* in milliseconds */
 #endif
index 07afe1b..7add8f7 100644 (file)
@@ -46,7 +46,8 @@ LOCAL_SRC_FILES += \
     ../btif/src/btif_gatt_test.c \
     ../btif/src/btif_config.c \
     ../btif/src/btif_config_util.cpp \
-    ../btif/src/btif_profile_queue.c
+    ../btif/src/btif_profile_queue.c \
+    ../btif/src/bluetoothTrack.cpp
 
 # callouts
 LOCAL_SRC_FILES+= \
@@ -100,6 +101,7 @@ LOCAL_C_INCLUDES+= . \
        $(LOCAL_PATH)/../audio_a2dp_hw \
        $(LOCAL_PATH)/../utils/include \
        $(bdroid_C_INCLUDES) \
+       $(TOP)/frameworks/av/include/media \
        external/tinyxml2
 
 LOCAL_CFLAGS += -DBUILDCFG $(bdroid_CFLAGS) -Werror -Wno-error=maybe-uninitialized -Wno-error=uninitialized -Wno-error=unused-parameter
index 7fe665c..5f9e60a 100644 (file)
@@ -482,7 +482,10 @@ void avdt_ad_tc_data_ind(tAVDT_TC_TBL *p_tbl, BT_HDR *p_buf)
             avdt_scb_event(p_scb, AVDT_SCB_TC_DATA_EVT, (tAVDT_SCB_EVT *) &p_buf);
         }
         else
+        {
             GKI_freebuf(p_buf);
+            AVDT_TRACE_ERROR0(" avdt_ad_tc_data_ind buffer freed");
+        }
     }
 }
 
index 855f17e..5e5ea2b 100644 (file)
@@ -176,6 +176,68 @@ void AVDT_Deregister(void)
 
 /*******************************************************************************
 **
+** Function         AVDT_SINK_Activate
+**
+** Description      Activate SEP of A2DP Sink. In Use parameter is adjusted.
+**                  In Use will be made false in case of activation. A2DP SRC
+**                  will receive in_use as false and can open A2DP Sink
+**                  connection
+**
+** Returns          void.
+**
+*******************************************************************************/
+void AVDT_SINK_Activate()
+{
+    tAVDT_SCB           *p_scb = &avdt_cb.scb[0];
+    int                 i;
+    AVDT_TRACE_DEBUG0("AVDT_SINK_Activate");
+    /* for all allocated scbs */
+    for (i = 0; i < AVDT_NUM_SEPS; i++, p_scb++)
+    {
+        if ((p_scb->allocated) && (p_scb->cs.tsep == AVDT_TSEP_SNK))
+        {
+            AVDT_TRACE_DEBUG0("AVDT_SINK_Activate found scb");
+            p_scb->sink_activated = TRUE;
+            /* update in_use */
+            p_scb->in_use = FALSE;
+            break;
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         AVDT_SINK_Deactivate
+**
+** Description      Deactivate SEP of A2DP Sink. In Use parameter is adjusted.
+**                  In Use will be made TRUE in case of activation. A2DP SRC
+**                  will receive in_use as true and will not open A2DP Sink
+**                  connection
+**
+** Returns          void.
+**
+*******************************************************************************/
+void AVDT_SINK_Deactivate()
+{
+    tAVDT_SCB           *p_scb = &avdt_cb.scb[0];
+    int                 i;
+    AVDT_TRACE_DEBUG0("AVDT_SINK_Deactivate");
+    /* for all allocated scbs */
+    for (i = 0; i < AVDT_NUM_SEPS; i++, p_scb++)
+    {
+        if ((p_scb->allocated) && (p_scb->cs.tsep == AVDT_TSEP_SNK))
+        {
+            AVDT_TRACE_DEBUG0("AVDT_SINK_Deactivate, found scb");
+            p_scb->sink_activated = FALSE;
+            /* update in_use */
+            p_scb->in_use = TRUE;
+            break;
+        }
+    }
+}
+
+/*******************************************************************************
+**
 ** Function         AVDT_CreateStream
 **
 ** Description      Create a stream endpoint.  After a stream endpoint is
index 04968a6..e9752c2 100644 (file)
@@ -491,6 +491,7 @@ typedef struct {
     UINT16          media_seq;      /* media packet sequence number */
     BOOLEAN         allocated;      /* whether scb is allocated or unused */
     BOOLEAN         in_use;         /* whether stream being used by peer */
+    BOOLEAN         sink_activated; /* A2DP Sink activated/de-activated from Application */
     UINT8           role;           /* initiator/acceptor role in current procedure */
     BOOLEAN         remove;         /* whether CB is marked for removal */
     UINT8           state;          /* state machine state */
index d0c9e0f..f509240 100644 (file)
@@ -601,6 +601,13 @@ tAVDT_SCB *avdt_scb_alloc(tAVDT_CS *p_cs)
             memset(p_scb,0,sizeof(tAVDT_SCB));
             p_scb->allocated = TRUE;
             p_scb->p_ccb = NULL;
+
+            /* initialize sink as activated */
+            if (p_cs->tsep == AVDT_TSEP_SNK)
+            {
+                p_scb->sink_activated = TRUE;
+            }
+
             memcpy(&p_scb->cs, p_cs, sizeof(tAVDT_CS));
 #if AVDT_MULTIPLEXING == TRUE
             /* initialize fragments gueue */
index 8175b96..87cc61f 100644 (file)
@@ -678,7 +678,7 @@ void avdt_scb_drop_pkt(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
     UNUSED(p_scb);
 
     GKI_freebuf(p_data->p_pkt);
-    AVDT_TRACE_WARNING0("Dropped incoming media packet");
+    AVDT_TRACE_ERROR0(" avdt_scb_drop_pkt Dropped incoming media packet");
 }
 
 /*******************************************************************************
@@ -826,7 +826,7 @@ void avdt_scb_hdl_setconfig_cmd(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
             p_scb->peer_seid = p_data->msg.config_cmd.int_seid;
             memcpy(&p_scb->req_cfg, p_cfg, sizeof(tAVDT_CFG));
             /* call app callback */
-            (*p_scb->cs.p_ctrl_cback)(avdt_scb_to_hdl(p_scb),
+            (*p_scb->cs.p_ctrl_cback)(avdt_scb_to_hdl(p_scb), /* handle of scb- which is same as sep handle of bta_av_cb.p_scb*/
                                       p_scb->p_ccb ? p_scb->p_ccb->peer_addr : NULL,
                                       AVDT_CONFIG_IND_EVT,
                                       (tAVDT_CTRL *) &p_data->msg.config_cmd);
@@ -2054,7 +2054,14 @@ void avdt_scb_clr_vars(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data)
 {
     UNUSED(p_data);
 
-    p_scb->in_use = FALSE;
+    if ((p_scb->cs.tsep == AVDT_TSEP_SNK) && (!p_scb->sink_activated))
+    {
+        p_scb->in_use = TRUE;
+    }
+    else
+    {
+        p_scb->in_use = FALSE;
+    }
     p_scb->p_ccb = NULL;
     p_scb->peer_seid = 0;
 }
index beaecf6..93ed6ae 100644 (file)
@@ -454,6 +454,35 @@ AVDT_API extern void AVDT_Register(tAVDT_REG *p_reg, tAVDT_CTRL_CBACK *p_cback);
 *******************************************************************************/
 AVDT_API extern void AVDT_Deregister(void);
 
+
+/*******************************************************************************
+**
+** Function         AVDT_SINK_Activate
+**
+** Description      Activate SEP of A2DP Sink. In Use parameter is adjusted.
+**                  In Use will be made false in case of activation. A2DP SRC
+**                  will receive in_use as false and can open A2DP Sink
+**                  connection
+**
+** Returns          void
+**
+*******************************************************************************/
+AVDT_API extern void AVDT_SINK_Activate(void);
+
+/*******************************************************************************
+**
+** Function         AVDT_SINK_Deactivate
+**
+** Description      Deactivate SEP of A2DP Sink. In Use parameter is adjusted.
+**                  In Use will be made TRUE in case of activation. A2DP SRC
+**                  will receive in_use as true and will not open A2DP Sink
+**                  connection
+**
+** Returns          void.
+**
+*******************************************************************************/
+AVDT_API extern void AVDT_SINK_Deactivate(void);
+
 /*******************************************************************************
 **
 ** Function         AVDT_CreateStream