1/******************************************************************************
2 *
3 *  Copyright (C) 2009-2012 Broadcom Corporation
4 *
5 *  Licensed under the Apache License, Version 2.0 (the "License");
6 *  you may not use this file except in compliance with the License.
7 *  You may obtain a copy of the License at:
8 *
9 *  http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 *
17 ******************************************************************************/
18
19
20/*****************************************************************************
21 *
22 *  Filename:      btif_av.c
23 *
24 *  Description:   Bluedroid AV implementation
25 *
26 *****************************************************************************/
27
28#include <hardware/bluetooth.h>
29#include <system/audio.h>
30#include "hardware/bt_av.h"
31
32#define LOG_TAG "BTIF_AV"
33
34#include "btif_av.h"
35#include "btif_util.h"
36#include "btif_profile_queue.h"
37#include "bta_api.h"
38#include "btif_media.h"
39#include "bta_av_api.h"
40#include "gki.h"
41#include "bd.h"
42#include "btu.h"
43#include "bt_utils.h"
44
45/*****************************************************************************
46**  Constants & Macros
47******************************************************************************/
48#define BTIF_AV_SERVICE_NAME "Advanced Audio"
49
50#define BTIF_TIMEOUT_AV_OPEN_ON_RC_SECS  2
51
52typedef enum {
53    BTIF_AV_STATE_IDLE = 0x0,
54    BTIF_AV_STATE_OPENING,
55    BTIF_AV_STATE_OPENED,
56    BTIF_AV_STATE_STARTED,
57    BTIF_AV_STATE_CLOSING
58} btif_av_state_t;
59
60/* Should not need dedicated suspend state as actual actions are no
61   different than open state. Suspend flags are needed however to prevent
62   media task from trying to restart stream during remote suspend or while
63   we are in the process of a local suspend */
64
65#define BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING 0x1
66#define BTIF_AV_FLAG_REMOTE_SUSPEND        0x2
67#define BTIF_AV_FLAG_PENDING_START         0x4
68#define BTIF_AV_FLAG_PENDING_STOP          0x8
69
70/*****************************************************************************
71**  Local type definitions
72******************************************************************************/
73
74typedef struct
75{
76    tBTA_AV_HNDL bta_handle;
77    bt_bdaddr_t peer_bda;
78    btif_sm_handle_t sm_handle;
79    UINT8 flags;
80    tBTA_AV_EDR edr;
81    UINT8   peer_sep;  /* sep type of peer device */
82} btif_av_cb_t;
83
84typedef struct
85{
86    bt_bdaddr_t *target_bda;
87    uint16_t uuid;
88} btif_av_connect_req_t;
89
90typedef struct
91{
92    int sample_rate;
93    int channel_count;
94} btif_av_sink_config_req_t;
95
96/*****************************************************************************
97**  Static variables
98******************************************************************************/
99static btav_callbacks_t *bt_av_src_callbacks = NULL;
100static btav_callbacks_t *bt_av_sink_callbacks = NULL;
101static btif_av_cb_t btif_av_cb;
102static TIMER_LIST_ENT tle_av_open_on_rc;
103
104/* both interface and media task needs to be ready to alloc incoming request */
105#define CHECK_BTAV_INIT() if (((bt_av_src_callbacks == NULL) &&(bt_av_sink_callbacks == NULL)) \
106        || (btif_av_cb.sm_handle == NULL))\
107{\
108     BTIF_TRACE_WARNING("%s: BTAV not initialized", __FUNCTION__);\
109     return BT_STATUS_NOT_READY;\
110}\
111else\
112{\
113     BTIF_TRACE_EVENT("%s", __FUNCTION__);\
114}
115
116/* Helper macro to avoid code duplication in the state machine handlers */
117#define CHECK_RC_EVENT(e, d) \
118    case BTA_AV_RC_OPEN_EVT: \
119    case BTA_AV_RC_CLOSE_EVT: \
120    case BTA_AV_REMOTE_CMD_EVT: \
121    case BTA_AV_VENDOR_CMD_EVT: \
122    case BTA_AV_META_MSG_EVT: \
123    case BTA_AV_RC_FEAT_EVT: \
124    { \
125         btif_rc_handler(e, d);\
126    }break; \
127
128static BOOLEAN btif_av_state_idle_handler(btif_sm_event_t event, void *data);
129static BOOLEAN btif_av_state_opening_handler(btif_sm_event_t event, void *data);
130static BOOLEAN btif_av_state_opened_handler(btif_sm_event_t event, void *data);
131static BOOLEAN btif_av_state_started_handler(btif_sm_event_t event, void *data);
132static BOOLEAN btif_av_state_closing_handler(btif_sm_event_t event, void *data);
133
134static const btif_sm_handler_t btif_av_state_handlers[] =
135{
136    btif_av_state_idle_handler,
137    btif_av_state_opening_handler,
138    btif_av_state_opened_handler,
139    btif_av_state_started_handler,
140    btif_av_state_closing_handler
141};
142
143/*************************************************************************
144** Extern functions
145*************************************************************************/
146extern void btif_rc_handler(tBTA_AV_EVT event, tBTA_AV *p_data);
147extern BOOLEAN btif_rc_get_connected_peer(BD_ADDR peer_addr);
148extern void btif_rc_check_handle_pending_play (BD_ADDR peer_addr, BOOLEAN bSendToApp);
149
150/*****************************************************************************
151** Local helper functions
152******************************************************************************/
153
154const char *dump_av_sm_state_name(btif_av_state_t state)
155{
156    switch (state)
157    {
158        CASE_RETURN_STR(BTIF_AV_STATE_IDLE)
159        CASE_RETURN_STR(BTIF_AV_STATE_OPENING)
160        CASE_RETURN_STR(BTIF_AV_STATE_OPENED)
161        CASE_RETURN_STR(BTIF_AV_STATE_STARTED)
162        CASE_RETURN_STR(BTIF_AV_STATE_CLOSING)
163        default: return "UNKNOWN_STATE";
164    }
165}
166
167const char *dump_av_sm_event_name(btif_av_sm_event_t event)
168{
169    switch((int)event)
170    {
171        CASE_RETURN_STR(BTA_AV_ENABLE_EVT)
172        CASE_RETURN_STR(BTA_AV_REGISTER_EVT)
173        CASE_RETURN_STR(BTA_AV_OPEN_EVT)
174        CASE_RETURN_STR(BTA_AV_CLOSE_EVT)
175        CASE_RETURN_STR(BTA_AV_START_EVT)
176        CASE_RETURN_STR(BTA_AV_STOP_EVT)
177        CASE_RETURN_STR(BTA_AV_PROTECT_REQ_EVT)
178        CASE_RETURN_STR(BTA_AV_PROTECT_RSP_EVT)
179        CASE_RETURN_STR(BTA_AV_RC_OPEN_EVT)
180        CASE_RETURN_STR(BTA_AV_RC_CLOSE_EVT)
181        CASE_RETURN_STR(BTA_AV_REMOTE_CMD_EVT)
182        CASE_RETURN_STR(BTA_AV_REMOTE_RSP_EVT)
183        CASE_RETURN_STR(BTA_AV_VENDOR_CMD_EVT)
184        CASE_RETURN_STR(BTA_AV_VENDOR_RSP_EVT)
185        CASE_RETURN_STR(BTA_AV_RECONFIG_EVT)
186        CASE_RETURN_STR(BTA_AV_SUSPEND_EVT)
187        CASE_RETURN_STR(BTA_AV_PENDING_EVT)
188        CASE_RETURN_STR(BTA_AV_META_MSG_EVT)
189        CASE_RETURN_STR(BTA_AV_REJECT_EVT)
190        CASE_RETURN_STR(BTA_AV_RC_FEAT_EVT)
191        CASE_RETURN_STR(BTIF_SM_ENTER_EVT)
192        CASE_RETURN_STR(BTIF_SM_EXIT_EVT)
193        CASE_RETURN_STR(BTIF_AV_CONNECT_REQ_EVT)
194        CASE_RETURN_STR(BTIF_AV_DISCONNECT_REQ_EVT)
195        CASE_RETURN_STR(BTIF_AV_START_STREAM_REQ_EVT)
196        CASE_RETURN_STR(BTIF_AV_STOP_STREAM_REQ_EVT)
197        CASE_RETURN_STR(BTIF_AV_SUSPEND_STREAM_REQ_EVT)
198        CASE_RETURN_STR(BTIF_AV_SINK_CONFIG_REQ_EVT)
199        default: return "UNKNOWN_EVENT";
200   }
201}
202
203/****************************************************************************
204**  Local helper functions
205*****************************************************************************/
206/*******************************************************************************
207**
208** Function         btif_initiate_av_open_tmr_hdlr
209**
210** Description      Timer to trigger AV open if the remote headset establishes
211**                  RC connection w/o AV connection. The timer is needed to IOP
212**                  with headsets that do establish AV after RC connection.
213**
214** Returns          void
215**
216*******************************************************************************/
217static void btif_initiate_av_open_tmr_hdlr(TIMER_LIST_ENT *tle)
218{
219    BD_ADDR peer_addr;
220    UNUSED(tle);
221    btif_av_connect_req_t connect_req;
222    UNUSED(tle);
223    /* is there at least one RC connection - There should be */
224    if (btif_rc_get_connected_peer(peer_addr)) {
225       BTIF_TRACE_DEBUG("%s Issuing connect to the remote RC peer", __FUNCTION__);
226       /* In case of AVRCP connection request, we will initiate SRC connection */
227       connect_req.target_bda = (bt_bdaddr_t*)&peer_addr;
228       connect_req.uuid = UUID_SERVCLASS_AUDIO_SOURCE;
229       btif_sm_dispatch(btif_av_cb.sm_handle, BTIF_AV_CONNECT_REQ_EVT, (char*)&connect_req);
230    }
231    else
232    {
233        BTIF_TRACE_ERROR("%s No connected RC peers", __FUNCTION__);
234    }
235}
236
237/*****************************************************************************
238**  Static functions
239******************************************************************************/
240
241static void btif_report_connection_state(btav_connection_state_t state, bt_bdaddr_t *bd_addr)
242{
243    if (btif_av_cb.peer_sep == AVDT_TSEP_SRC && bt_av_sink_callbacks != NULL) {
244        HAL_CBACK(bt_av_sink_callbacks, connection_state_cb, state, bd_addr);
245    } else if (btif_av_cb.peer_sep == AVDT_TSEP_SNK && bt_av_src_callbacks != NULL) {
246        HAL_CBACK(bt_av_src_callbacks, connection_state_cb, state, bd_addr);
247    }
248}
249
250static void btif_report_audio_state(btav_audio_state_t state, bt_bdaddr_t *bd_addr)
251{
252    if (btif_av_cb.peer_sep == AVDT_TSEP_SRC && bt_av_sink_callbacks != NULL) {
253        HAL_CBACK(bt_av_sink_callbacks, audio_state_cb, state, bd_addr);
254    } else if (btif_av_cb.peer_sep == AVDT_TSEP_SNK && bt_av_src_callbacks != NULL) {
255        HAL_CBACK(bt_av_src_callbacks, audio_state_cb, state, bd_addr);
256    }
257}
258
259/*****************************************************************************
260**
261** Function     btif_av_state_idle_handler
262**
263** Description  State managing disconnected AV link
264**
265** Returns      TRUE if event was processed, FALSE otherwise
266**
267*******************************************************************************/
268
269static BOOLEAN btif_av_state_idle_handler(btif_sm_event_t event, void *p_data)
270{
271    BTIF_TRACE_DEBUG("%s event:%s flags %x", __FUNCTION__,
272                     dump_av_sm_event_name(event), btif_av_cb.flags);
273
274    switch (event)
275    {
276        case BTIF_SM_ENTER_EVT:
277            /* clear the peer_bda */
278            memset(&btif_av_cb.peer_bda, 0, sizeof(bt_bdaddr_t));
279            btif_av_cb.flags = 0;
280            btif_av_cb.edr = 0;
281            btif_a2dp_on_idle();
282            break;
283
284        case BTIF_SM_EXIT_EVT:
285            break;
286
287        case BTA_AV_ENABLE_EVT:
288            break;
289
290        case BTA_AV_REGISTER_EVT:
291            btif_av_cb.bta_handle = ((tBTA_AV*)p_data)->registr.hndl;
292            break;
293
294        case BTA_AV_PENDING_EVT:
295        case BTIF_AV_CONNECT_REQ_EVT:
296        {
297             if (event == BTIF_AV_CONNECT_REQ_EVT)
298             {
299                 memcpy(&btif_av_cb.peer_bda, ((btif_av_connect_req_t*)p_data)->target_bda,
300                                                                   sizeof(bt_bdaddr_t));
301                 BTA_AvOpen(btif_av_cb.peer_bda.address, btif_av_cb.bta_handle,
302                    TRUE, BTA_SEC_NONE, ((btif_av_connect_req_t*)p_data)->uuid);
303             }
304             else if (event == BTA_AV_PENDING_EVT)
305             {
306                  bdcpy(btif_av_cb.peer_bda.address, ((tBTA_AV*)p_data)->pend.bd_addr);
307                  BTA_AvOpen(btif_av_cb.peer_bda.address, btif_av_cb.bta_handle,
308                    TRUE, BTA_SEC_NONE, UUID_SERVCLASS_AUDIO_SOURCE);
309             }
310             btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_OPENING);
311        } break;
312
313        case BTA_AV_RC_OPEN_EVT:
314            /* IOP_FIX: Jabra 620 only does RC open without AV open whenever it connects. So
315             * as per the AV WP, an AVRC connection cannot exist without an AV connection. Therefore,
316             * we initiate an AV connection if an RC_OPEN_EVT is received when we are in AV_CLOSED state.
317             * We initiate the AV connection after a small 3s timeout to avoid any collisions from the
318             * headsets, as some headsets initiate the AVRC connection first and then
319             * immediately initiate the AV connection
320             *
321             * TODO: We may need to do this only on an AVRCP Play. FixMe
322             */
323
324            BTIF_TRACE_DEBUG("BTA_AV_RC_OPEN_EVT received w/o AV");
325            memset(&tle_av_open_on_rc, 0, sizeof(tle_av_open_on_rc));
326            tle_av_open_on_rc.param = (UINT32)btif_initiate_av_open_tmr_hdlr;
327            btu_start_timer(&tle_av_open_on_rc, BTU_TTYPE_USER_FUNC,
328                            BTIF_TIMEOUT_AV_OPEN_ON_RC_SECS);
329            btif_rc_handler(event, p_data);
330            break;
331
332        case BTA_AV_REMOTE_CMD_EVT:
333        case BTA_AV_VENDOR_CMD_EVT:
334        case BTA_AV_META_MSG_EVT:
335        case BTA_AV_RC_FEAT_EVT:
336            btif_rc_handler(event, (tBTA_AV*)p_data);
337            break;
338
339        case BTA_AV_RC_CLOSE_EVT:
340            if (tle_av_open_on_rc.in_use) {
341                BTIF_TRACE_DEBUG("BTA_AV_RC_CLOSE_EVT: Stopping AV timer.");
342                btu_stop_timer(&tle_av_open_on_rc);
343            }
344            btif_rc_handler(event, p_data);
345            break;
346
347        default:
348            BTIF_TRACE_WARNING("%s : unhandled event:%s", __FUNCTION__,
349                                dump_av_sm_event_name(event));
350            return FALSE;
351
352    }
353    return TRUE;
354}
355/*****************************************************************************
356**
357** Function        btif_av_state_opening_handler
358**
359** Description     Intermediate state managing events during establishment
360**                 of avdtp channel
361**
362** Returns         TRUE if event was processed, FALSE otherwise
363**
364*******************************************************************************/
365
366static BOOLEAN btif_av_state_opening_handler(btif_sm_event_t event, void *p_data)
367{
368    BTIF_TRACE_DEBUG("%s event:%s flags %x", __FUNCTION__,
369                     dump_av_sm_event_name(event), btif_av_cb.flags);
370
371    switch (event)
372    {
373        case BTIF_SM_ENTER_EVT:
374            /* inform the application that we are entering connecting state */
375            btif_report_connection_state(BTAV_CONNECTION_STATE_CONNECTING, &(btif_av_cb.peer_bda));
376            break;
377
378        case BTIF_SM_EXIT_EVT:
379            break;
380
381        case BTA_AV_REJECT_EVT:
382            BTIF_TRACE_DEBUG(" Received  BTA_AV_REJECT_EVT ");
383            btif_report_connection_state(BTAV_CONNECTION_STATE_DISCONNECTED, &(btif_av_cb.peer_bda));
384            btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_IDLE);
385            break;
386
387        case BTA_AV_OPEN_EVT:
388        {
389            tBTA_AV *p_bta_data = (tBTA_AV*)p_data;
390            btav_connection_state_t state;
391            btif_sm_state_t av_state;
392            BTIF_TRACE_DEBUG("status:%d, edr 0x%x",p_bta_data->open.status,
393                               p_bta_data->open.edr);
394
395            if (p_bta_data->open.status == BTA_AV_SUCCESS)
396            {
397                 state = BTAV_CONNECTION_STATE_CONNECTED;
398                 av_state = BTIF_AV_STATE_OPENED;
399                 btif_av_cb.edr = p_bta_data->open.edr;
400
401                 btif_av_cb.peer_sep = p_bta_data->open.sep;
402                 btif_a2dp_set_peer_sep(p_bta_data->open.sep);
403            }
404            else
405            {
406                BTIF_TRACE_WARNING("BTA_AV_OPEN_EVT::FAILED status: %d",
407                                     p_bta_data->open.status );
408                state = BTAV_CONNECTION_STATE_DISCONNECTED;
409                av_state  = BTIF_AV_STATE_IDLE;
410            }
411
412            /* inform the application of the event */
413            btif_report_connection_state(state, &(btif_av_cb.peer_bda));
414            /* change state to open/idle based on the status */
415            btif_sm_change_state(btif_av_cb.sm_handle, av_state);
416            if (btif_av_cb.peer_sep == AVDT_TSEP_SNK)
417            {
418                /* if queued PLAY command,  send it now */
419                btif_rc_check_handle_pending_play(p_bta_data->open.bd_addr,
420                                             (p_bta_data->open.status == BTA_AV_SUCCESS));
421            }
422            else if (btif_av_cb.peer_sep == AVDT_TSEP_SRC)
423            {
424                /* if queued PLAY command,  send it now */
425                btif_rc_check_handle_pending_play(p_bta_data->open.bd_addr, FALSE);
426                /* Bring up AVRCP connection too */
427                BTA_AvOpenRc(btif_av_cb.bta_handle);
428            }
429            btif_queue_advance();
430        } break;
431
432        case BTIF_AV_SINK_CONFIG_REQ_EVT:
433        {
434            btif_av_sink_config_req_t req;
435            // copy to avoid alignment problems
436            memcpy(&req, p_data, sizeof(req));
437
438            BTIF_TRACE_WARNING("BTIF_AV_SINK_CONFIG_REQ_EVT %d %d", req.sample_rate,
439                    req.channel_count);
440            if (btif_av_cb.peer_sep == AVDT_TSEP_SRC && bt_av_sink_callbacks != NULL) {
441                HAL_CBACK(bt_av_sink_callbacks, audio_config_cb, &(btif_av_cb.peer_bda),
442                        req.sample_rate, req.channel_count);
443            }
444        } break;
445
446        CHECK_RC_EVENT(event, p_data);
447
448        default:
449            BTIF_TRACE_WARNING("%s : unhandled event:%s", __FUNCTION__,
450                                dump_av_sm_event_name(event));
451            return FALSE;
452
453   }
454   return TRUE;
455}
456
457
458/*****************************************************************************
459**
460** Function        btif_av_state_closing_handler
461**
462** Description     Intermediate state managing events during closing
463**                 of avdtp channel
464**
465** Returns         TRUE if event was processed, FALSE otherwise
466**
467*******************************************************************************/
468
469static BOOLEAN btif_av_state_closing_handler(btif_sm_event_t event, void *p_data)
470{
471    BTIF_TRACE_DEBUG("%s event:%s flags %x", __FUNCTION__,
472                     dump_av_sm_event_name(event), btif_av_cb.flags);
473
474    switch (event)
475    {
476        case BTIF_SM_ENTER_EVT:
477            if (btif_av_cb.peer_sep == AVDT_TSEP_SNK)
478            {
479                /* immediately stop transmission of frames */
480                btif_a2dp_set_tx_flush(TRUE);
481                /* wait for audioflinger to stop a2dp */
482            }
483            if (btif_av_cb.peer_sep == AVDT_TSEP_SRC)
484            {
485                btif_a2dp_set_rx_flush(TRUE);
486            }
487            break;
488
489        case BTA_AV_STOP_EVT:
490        case BTIF_AV_STOP_STREAM_REQ_EVT:
491            if (btif_av_cb.peer_sep == AVDT_TSEP_SNK)
492            {
493              /* immediately flush any pending tx frames while suspend is pending */
494              btif_a2dp_set_tx_flush(TRUE);
495            }
496            if (btif_av_cb.peer_sep == AVDT_TSEP_SRC)
497            {
498                btif_a2dp_set_rx_flush(TRUE);
499            }
500
501            btif_a2dp_on_stopped(NULL);
502            break;
503
504        case BTIF_SM_EXIT_EVT:
505            break;
506
507        case BTA_AV_CLOSE_EVT:
508
509            /* inform the application that we are disconnecting */
510            btif_report_connection_state(BTAV_CONNECTION_STATE_DISCONNECTED, &(btif_av_cb.peer_bda));
511
512            btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_IDLE);
513            break;
514
515        /* Handle the RC_CLOSE event for the cleanup */
516        case BTA_AV_RC_CLOSE_EVT:
517            btif_rc_handler(event, (tBTA_AV*)p_data);
518            break;
519
520        default:
521            BTIF_TRACE_WARNING("%s : unhandled event:%s", __FUNCTION__,
522                                dump_av_sm_event_name(event));
523            return FALSE;
524   }
525   return TRUE;
526}
527
528
529/*****************************************************************************
530**
531** Function     btif_av_state_opened_handler
532**
533** Description  Handles AV events while AVDTP is in OPEN state
534**
535** Returns      TRUE if event was processed, FALSE otherwise
536**
537*******************************************************************************/
538
539static BOOLEAN btif_av_state_opened_handler(btif_sm_event_t event, void *p_data)
540{
541    tBTA_AV *p_av = (tBTA_AV*)p_data;
542
543    BTIF_TRACE_DEBUG("%s event:%s flags %x", __FUNCTION__,
544                     dump_av_sm_event_name(event), btif_av_cb.flags);
545
546    if ( (event == BTA_AV_REMOTE_CMD_EVT) && (btif_av_cb.flags & BTIF_AV_FLAG_REMOTE_SUSPEND) &&
547         (p_av->remote_cmd.rc_id == BTA_AV_RC_PLAY) )
548    {
549        BTIF_TRACE_EVENT("%s: Resetting remote suspend flag on RC PLAY", __FUNCTION__);
550        btif_av_cb.flags &= ~BTIF_AV_FLAG_REMOTE_SUSPEND;
551    }
552
553    switch (event)
554    {
555        case BTIF_SM_ENTER_EVT:
556            btif_av_cb.flags &= ~BTIF_AV_FLAG_PENDING_STOP;
557            btif_av_cb.flags &= ~BTIF_AV_FLAG_PENDING_START;
558            break;
559
560        case BTIF_SM_EXIT_EVT:
561            btif_av_cb.flags &= ~BTIF_AV_FLAG_PENDING_START;
562            break;
563
564        case BTIF_AV_START_STREAM_REQ_EVT:
565            if (btif_av_cb.peer_sep != AVDT_TSEP_SRC)
566                btif_a2dp_setup_codec();
567            BTA_AvStart();
568            btif_av_cb.flags |= BTIF_AV_FLAG_PENDING_START;
569            break;
570
571        case BTA_AV_START_EVT:
572        {
573            BTIF_TRACE_EVENT("BTA_AV_START_EVT status %d, suspending %d, init %d",
574                p_av->start.status, p_av->start.suspending, p_av->start.initiator);
575
576            if ((p_av->start.status == BTA_SUCCESS) && (p_av->start.suspending == TRUE))
577                return TRUE;
578
579            /*  In case peer is A2DP SRC we do not want to ack commands on UIPC*/
580            if (btif_av_cb.peer_sep == AVDT_TSEP_SNK)
581            {
582                if (btif_a2dp_on_started(&p_av->start,
583                    ((btif_av_cb.flags & BTIF_AV_FLAG_PENDING_START) != 0)))
584                {
585                    /* only clear pending flag after acknowledgement */
586                    btif_av_cb.flags &= ~BTIF_AV_FLAG_PENDING_START;
587                }
588            }
589
590            /* remain in open state if status failed */
591            if (p_av->start.status != BTA_AV_SUCCESS)
592                return FALSE;
593
594            if (btif_av_cb.peer_sep == AVDT_TSEP_SRC)
595            {
596                btif_a2dp_set_rx_flush(FALSE); /*  remove flush state, ready for streaming*/
597            }
598
599            /* change state to started, send acknowledgement if start is pending */
600            if (btif_av_cb.flags & BTIF_AV_FLAG_PENDING_START) {
601                if (btif_av_cb.peer_sep == AVDT_TSEP_SNK)
602                    btif_a2dp_on_started(NULL, TRUE);
603                /* pending start flag will be cleared when exit current state */
604            }
605            btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_STARTED);
606
607        } break;
608
609        case BTIF_AV_DISCONNECT_REQ_EVT:
610            BTA_AvClose(btif_av_cb.bta_handle);
611            if (btif_av_cb.peer_sep == AVDT_TSEP_SRC) {
612                BTA_AvCloseRc(btif_av_cb.bta_handle);
613            }
614
615            /* inform the application that we are disconnecting */
616            btif_report_connection_state(BTAV_CONNECTION_STATE_DISCONNECTING, &(btif_av_cb.peer_bda));
617            break;
618
619        case BTA_AV_CLOSE_EVT:
620             /* avdtp link is closed */
621            btif_a2dp_on_stopped(NULL);
622
623            /* inform the application that we are disconnected */
624            btif_report_connection_state(BTAV_CONNECTION_STATE_DISCONNECTED, &(btif_av_cb.peer_bda));
625
626            /* change state to idle, send acknowledgement if start is pending */
627            if (btif_av_cb.flags & BTIF_AV_FLAG_PENDING_START) {
628                btif_a2dp_ack_fail();
629                /* pending start flag will be cleared when exit current state */
630            }
631            btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_IDLE);
632            break;
633
634        case BTA_AV_RECONFIG_EVT:
635            if((btif_av_cb.flags & BTIF_AV_FLAG_PENDING_START) &&
636                (p_av->reconfig.status == BTA_AV_SUCCESS))
637            {
638               APPL_TRACE_WARNING("reconfig done BTA_AVstart()");
639               BTA_AvStart();
640            }
641            else if(btif_av_cb.flags & BTIF_AV_FLAG_PENDING_START)
642            {
643               btif_av_cb.flags &= ~BTIF_AV_FLAG_PENDING_START;
644               btif_a2dp_ack_fail();
645            }
646            break;
647
648        CHECK_RC_EVENT(event, p_data);
649
650        default:
651            BTIF_TRACE_WARNING("%s : unhandled event:%s", __FUNCTION__,
652                               dump_av_sm_event_name(event));
653            return FALSE;
654
655    }
656    return TRUE;
657}
658
659/*****************************************************************************
660**
661** Function     btif_av_state_started_handler
662**
663** Description  Handles AV events while A2DP stream is started
664**
665** Returns      TRUE if event was processed, FALSE otherwise
666**
667*******************************************************************************/
668
669static BOOLEAN btif_av_state_started_handler(btif_sm_event_t event, void *p_data)
670{
671    tBTA_AV *p_av = (tBTA_AV*)p_data;
672
673    BTIF_TRACE_DEBUG("%s event:%s flags %x", __FUNCTION__,
674                     dump_av_sm_event_name(event), btif_av_cb.flags);
675
676    switch (event)
677    {
678        case BTIF_SM_ENTER_EVT:
679
680            /* we are again in started state, clear any remote suspend flags */
681            btif_av_cb.flags &= ~BTIF_AV_FLAG_REMOTE_SUSPEND;
682
683            btif_report_audio_state(BTAV_AUDIO_STATE_STARTED, &(btif_av_cb.peer_bda));
684
685            /* increase the a2dp consumer task priority temporarily when start
686            ** audio playing, to avoid overflow the audio packet queue. */
687            adjust_priority_a2dp(TRUE);
688
689            break;
690
691        case BTIF_SM_EXIT_EVT:
692            /* restore the a2dp consumer task priority when stop audio playing. */
693            adjust_priority_a2dp(FALSE);
694
695            break;
696
697        case BTIF_AV_START_STREAM_REQ_EVT:
698            /* we were remotely started, just ack back the local request */
699            if (btif_av_cb.peer_sep == AVDT_TSEP_SNK)
700                btif_a2dp_on_started(NULL, TRUE);
701            break;
702
703        /* fixme -- use suspend = true always to work around issue with BTA AV */
704        case BTIF_AV_STOP_STREAM_REQ_EVT:
705        case BTIF_AV_SUSPEND_STREAM_REQ_EVT:
706
707            /* set pending flag to ensure btif task is not trying to restart
708               stream while suspend is in progress */
709            btif_av_cb.flags |= BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING;
710
711            /* if we were remotely suspended but suspend locally, local suspend
712               always overrides */
713            btif_av_cb.flags &= ~BTIF_AV_FLAG_REMOTE_SUSPEND;
714
715            if (btif_av_cb.peer_sep == AVDT_TSEP_SNK)
716            {
717            /* immediately stop transmission of frames while suspend is pending */
718                btif_a2dp_set_tx_flush(TRUE);
719            }
720
721            if (btif_av_cb.peer_sep == AVDT_TSEP_SRC) {
722                btif_a2dp_set_rx_flush(TRUE);
723                btif_a2dp_on_stopped(NULL);
724            }
725
726            BTA_AvStop(TRUE);
727            break;
728
729        case BTIF_AV_DISCONNECT_REQ_EVT:
730
731            /* request avdtp to close */
732            BTA_AvClose(btif_av_cb.bta_handle);
733            if (btif_av_cb.peer_sep == AVDT_TSEP_SRC) {
734                BTA_AvCloseRc(btif_av_cb.bta_handle);
735            }
736
737            /* inform the application that we are disconnecting */
738            btif_report_connection_state(BTAV_CONNECTION_STATE_DISCONNECTING, &(btif_av_cb.peer_bda));
739
740            /* wait in closing state until fully closed */
741            btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_CLOSING);
742            break;
743
744        case BTA_AV_SUSPEND_EVT:
745
746            BTIF_TRACE_EVENT("BTA_AV_SUSPEND_EVT status %d, init %d",
747                 p_av->suspend.status, p_av->suspend.initiator);
748
749            /* a2dp suspended, stop media task until resumed */
750            btif_a2dp_on_suspended(&p_av->suspend);
751
752            /* if not successful, remain in current state */
753            if (p_av->suspend.status != BTA_AV_SUCCESS)
754            {
755                btif_av_cb.flags &= ~BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING;
756
757               if (btif_av_cb.peer_sep == AVDT_TSEP_SNK)
758               {
759                /* suspend failed, reset back tx flush state */
760                    btif_a2dp_set_tx_flush(FALSE);
761               }
762                return FALSE;
763            }
764
765            if (p_av->suspend.initiator != TRUE)
766            {
767                /* remote suspend, notify HAL and await audioflinger to
768                   suspend/stop stream */
769
770                /* set remote suspend flag to block media task from restarting
771                   stream only if we did not already initiate a local suspend */
772                if ((btif_av_cb.flags & BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING) == 0)
773                    btif_av_cb.flags |= BTIF_AV_FLAG_REMOTE_SUSPEND;
774
775                btif_report_audio_state(BTAV_AUDIO_STATE_REMOTE_SUSPEND, &(btif_av_cb.peer_bda));
776            }
777            else
778            {
779                btif_report_audio_state(BTAV_AUDIO_STATE_STOPPED, &(btif_av_cb.peer_bda));
780            }
781
782            btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_OPENED);
783
784            /* suspend completed and state changed, clear pending status */
785            btif_av_cb.flags &= ~BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING;
786            break;
787
788        case BTA_AV_STOP_EVT:
789
790            btif_av_cb.flags |= BTIF_AV_FLAG_PENDING_STOP;
791            btif_a2dp_on_stopped(&p_av->suspend);
792
793            btif_report_audio_state(BTAV_AUDIO_STATE_STOPPED, &(btif_av_cb.peer_bda));
794
795            /* if stop was successful, change state to open */
796            if (p_av->suspend.status == BTA_AV_SUCCESS)
797                btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_OPENED);
798
799            break;
800
801        case BTA_AV_CLOSE_EVT:
802
803             btif_av_cb.flags |= BTIF_AV_FLAG_PENDING_STOP;
804
805            /* avdtp link is closed */
806            btif_a2dp_on_stopped(NULL);
807
808            /* inform the application that we are disconnected */
809            btif_report_connection_state(BTAV_CONNECTION_STATE_DISCONNECTED, &(btif_av_cb.peer_bda));
810
811            btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_IDLE);
812            break;
813
814        CHECK_RC_EVENT(event, p_data);
815
816        default:
817            BTIF_TRACE_WARNING("%s : unhandled event:%s", __FUNCTION__,
818                                 dump_av_sm_event_name(event));
819            return FALSE;
820
821    }
822    return TRUE;
823}
824
825/*****************************************************************************
826**  Local event handlers
827******************************************************************************/
828
829static void btif_av_handle_event(UINT16 event, char* p_param)
830{
831    btif_sm_dispatch(btif_av_cb.sm_handle, event, (void*)p_param);
832}
833
834static void bte_av_callback(tBTA_AV_EVT event, tBTA_AV *p_data)
835{
836    /* Switch to BTIF context */
837    btif_transfer_context(btif_av_handle_event, event,
838                          (char*)p_data, sizeof(tBTA_AV), NULL);
839}
840
841static void bte_av_media_callback(tBTA_AV_EVT event, tBTA_AV_MEDIA *p_data)
842{
843    btif_sm_state_t state;
844    UINT8 que_len;
845    tA2D_STATUS a2d_status;
846    tA2D_SBC_CIE sbc_cie;
847    btif_av_sink_config_req_t config_req;
848
849    if (event == BTA_AV_MEDIA_DATA_EVT)/* Switch to BTIF_MEDIA context */
850    {
851        state= btif_sm_get_state(btif_av_cb.sm_handle);
852        if ( (state == BTIF_AV_STATE_STARTED) || /* send SBC packets only in Started State */
853             (state == BTIF_AV_STATE_OPENED) )
854        {
855            que_len = btif_media_sink_enque_buf((BT_HDR *)p_data);
856            BTIF_TRACE_DEBUG(" Packets in Que %d",que_len);
857        }
858        else
859            return;
860    }
861
862    if (event == BTA_AV_MEDIA_SINK_CFG_EVT) {
863        /* send a command to BT Media Task */
864        btif_reset_decoder((UINT8*)p_data);
865
866        a2d_status = A2D_ParsSbcInfo(&sbc_cie, (UINT8 *)p_data, FALSE);
867        if (a2d_status == A2D_SUCCESS) {
868            /* Switch to BTIF context */
869            config_req.sample_rate = btif_a2dp_get_track_frequency(sbc_cie.samp_freq);
870            config_req.channel_count = btif_a2dp_get_track_channel_count(sbc_cie.ch_mode);
871            btif_transfer_context(btif_av_handle_event, BTIF_AV_SINK_CONFIG_REQ_EVT,
872                                     (char*)&config_req, sizeof(config_req), NULL);
873        } else {
874            APPL_TRACE_ERROR("ERROR dump_codec_info A2D_ParsSbcInfo fail:%d", a2d_status);
875        }
876    }
877}
878/*******************************************************************************
879**
880** Function         btif_av_init
881**
882** Description      Initializes btif AV if not already done
883**
884** Returns          bt_status_t
885**
886*******************************************************************************/
887
888bt_status_t btif_av_init()
889{
890    if (btif_av_cb.sm_handle == NULL)
891    {
892        if (btif_a2dp_start_media_task() != GKI_SUCCESS)
893            return BT_STATUS_FAIL;
894
895        btif_enable_service(BTA_A2DP_SERVICE_ID);
896
897        /* Also initialize the AV state machine */
898        btif_av_cb.sm_handle = btif_sm_init((const btif_sm_handler_t*)btif_av_state_handlers, BTIF_AV_STATE_IDLE);
899
900        btif_a2dp_on_init();
901
902       return BT_STATUS_SUCCESS;
903    }
904
905    return BT_STATUS_DONE;
906}
907
908/*******************************************************************************
909**
910** Function         init_src
911**
912** Description      Initializes the AV interface for source mode
913**
914** Returns          bt_status_t
915**
916*******************************************************************************/
917
918static bt_status_t init_src(btav_callbacks_t* callbacks)
919{
920    bt_status_t status;
921
922    BTIF_TRACE_EVENT("%s", __FUNCTION__);
923
924    if (bt_av_sink_callbacks != NULL) {
925        // already did btif_av_init()
926        status = BT_STATUS_SUCCESS;
927    } else {
928        status = btif_av_init();
929    }
930
931    if (status == BT_STATUS_SUCCESS) {
932        bt_av_src_callbacks = callbacks;
933    }
934
935    return status;
936}
937
938/*******************************************************************************
939**
940** Function         init_sink
941**
942** Description      Initializes the AV interface for sink mode
943**
944** Returns          bt_status_t
945**
946*******************************************************************************/
947
948static bt_status_t init_sink(btav_callbacks_t* callbacks)
949{
950    bt_status_t status;
951
952    BTIF_TRACE_EVENT("%s", __FUNCTION__);
953
954    if (bt_av_src_callbacks != NULL) {
955        // already did btif_av_init()
956        status = BT_STATUS_SUCCESS;
957    } else {
958        status = btif_av_init();
959    }
960
961    if (status == BT_STATUS_SUCCESS) {
962        bt_av_sink_callbacks = callbacks;
963        BTA_AvEnable_Sink(TRUE);
964    }
965
966    return status;
967}
968
969/*******************************************************************************
970**
971** Function         connect
972**
973** Description      Establishes the AV signalling channel with the remote headset
974**
975** Returns          bt_status_t
976**
977*******************************************************************************/
978
979static bt_status_t connect_int(bt_bdaddr_t *bd_addr, uint16_t uuid)
980{
981    btif_av_connect_req_t connect_req;
982    connect_req.target_bda = bd_addr;
983    connect_req.uuid = uuid;
984    BTIF_TRACE_EVENT("%s", __FUNCTION__);
985
986    btif_sm_dispatch(btif_av_cb.sm_handle, BTIF_AV_CONNECT_REQ_EVT, (char*)&connect_req);
987
988    return BT_STATUS_SUCCESS;
989}
990
991static bt_status_t src_connect_sink(bt_bdaddr_t *bd_addr)
992{
993    BTIF_TRACE_EVENT("%s", __FUNCTION__);
994    CHECK_BTAV_INIT();
995
996    return btif_queue_connect(UUID_SERVCLASS_AUDIO_SOURCE, bd_addr, connect_int);
997}
998
999static bt_status_t sink_connect_src(bt_bdaddr_t *bd_addr)
1000{
1001    BTIF_TRACE_EVENT("%s", __FUNCTION__);
1002    CHECK_BTAV_INIT();
1003
1004    return btif_queue_connect(UUID_SERVCLASS_AUDIO_SINK, bd_addr, connect_int);
1005}
1006
1007/*******************************************************************************
1008**
1009** Function         disconnect
1010**
1011** Description      Tears down the AV signalling channel with the remote headset
1012**
1013** Returns          bt_status_t
1014**
1015*******************************************************************************/
1016static bt_status_t disconnect(bt_bdaddr_t *bd_addr)
1017{
1018    BTIF_TRACE_EVENT("%s", __FUNCTION__);
1019
1020    CHECK_BTAV_INIT();
1021
1022    /* Switch to BTIF context */
1023    return btif_transfer_context(btif_av_handle_event, BTIF_AV_DISCONNECT_REQ_EVT,
1024                                 (char*)bd_addr, sizeof(bt_bdaddr_t), NULL);
1025}
1026
1027/*******************************************************************************
1028**
1029** Function         cleanup
1030**
1031** Description      Shuts down the AV interface and does the cleanup
1032**
1033** Returns          None
1034**
1035*******************************************************************************/
1036static void cleanup(void)
1037{
1038    BTIF_TRACE_EVENT("%s", __FUNCTION__);
1039
1040    btif_a2dp_stop_media_task();
1041
1042    btif_disable_service(BTA_A2DP_SERVICE_ID);
1043
1044    /* Also shut down the AV state machine */
1045    btif_sm_shutdown(btif_av_cb.sm_handle);
1046    btif_av_cb.sm_handle = NULL;
1047}
1048
1049static void cleanup_src(void) {
1050    BTIF_TRACE_EVENT("%s", __FUNCTION__);
1051
1052    if (bt_av_src_callbacks)
1053    {
1054        bt_av_src_callbacks = NULL;
1055        if (bt_av_sink_callbacks == NULL)
1056            cleanup();
1057    }
1058}
1059
1060static void cleanup_sink(void) {
1061    BTIF_TRACE_EVENT("%s", __FUNCTION__);
1062
1063    if (bt_av_sink_callbacks)
1064    {
1065        bt_av_sink_callbacks = NULL;
1066        if (bt_av_src_callbacks == NULL)
1067            cleanup();
1068    }
1069}
1070
1071static const btav_interface_t bt_av_src_interface = {
1072    sizeof(btav_interface_t),
1073    init_src,
1074    src_connect_sink,
1075    disconnect,
1076    cleanup_src,
1077};
1078
1079static const btav_interface_t bt_av_sink_interface = {
1080    sizeof(btav_interface_t),
1081    init_sink,
1082    sink_connect_src,
1083    disconnect,
1084    cleanup_sink,
1085};
1086
1087/*******************************************************************************
1088**
1089** Function         btif_av_get_sm_handle
1090**
1091** Description      Fetches current av SM handle
1092**
1093** Returns          None
1094**
1095*******************************************************************************/
1096
1097btif_sm_handle_t btif_av_get_sm_handle(void)
1098{
1099    return btif_av_cb.sm_handle;
1100}
1101
1102/*******************************************************************************
1103**
1104** Function         btif_av_stream_ready
1105**
1106** Description      Checks whether AV is ready for starting a stream
1107**
1108** Returns          None
1109**
1110*******************************************************************************/
1111
1112BOOLEAN btif_av_stream_ready(void)
1113{
1114    btif_sm_state_t state = btif_sm_get_state(btif_av_cb.sm_handle);
1115
1116    BTIF_TRACE_DEBUG("btif_av_stream_ready : sm hdl %d, state %d, flags %x",
1117                btif_av_cb.sm_handle, state, btif_av_cb.flags);
1118
1119    /* also make sure main adapter is enabled */
1120    if (btif_is_enabled() == 0)
1121    {
1122        BTIF_TRACE_EVENT("main adapter not enabled");
1123        return FALSE;
1124    }
1125
1126    /* check if we are remotely suspended or stop is pending */
1127    if (btif_av_cb.flags & (BTIF_AV_FLAG_REMOTE_SUSPEND|BTIF_AV_FLAG_PENDING_STOP))
1128        return FALSE;
1129
1130    return (state == BTIF_AV_STATE_OPENED);
1131}
1132
1133/*******************************************************************************
1134**
1135** Function         btif_av_stream_started_ready
1136**
1137** Description      Checks whether AV ready for media start in streaming state
1138**
1139** Returns          None
1140**
1141*******************************************************************************/
1142
1143BOOLEAN btif_av_stream_started_ready(void)
1144{
1145    btif_sm_state_t state = btif_sm_get_state(btif_av_cb.sm_handle);
1146
1147    BTIF_TRACE_DEBUG("btif_av_stream_started : sm hdl %d, state %d, flags %x",
1148                btif_av_cb.sm_handle, state, btif_av_cb.flags);
1149
1150    /* disallow media task to start if we have pending actions */
1151    if (btif_av_cb.flags & (BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING | BTIF_AV_FLAG_REMOTE_SUSPEND
1152        | BTIF_AV_FLAG_PENDING_STOP))
1153        return FALSE;
1154
1155    return (state == BTIF_AV_STATE_STARTED);
1156}
1157
1158/*******************************************************************************
1159**
1160** Function         btif_dispatch_sm_event
1161**
1162** Description      Send event to AV statemachine
1163**
1164** Returns          None
1165**
1166*******************************************************************************/
1167
1168/* used to pass events to AV statemachine from other tasks */
1169void btif_dispatch_sm_event(btif_av_sm_event_t event, void *p_data, int len)
1170{
1171    /* Switch to BTIF context */
1172    btif_transfer_context(btif_av_handle_event, event,
1173                          (char*)p_data, len, NULL);
1174}
1175
1176/*******************************************************************************
1177**
1178** Function         btif_av_execute_service
1179**
1180** Description      Initializes/Shuts down the service
1181**
1182** Returns          BT_STATUS_SUCCESS on success, BT_STATUS_FAIL otherwise
1183**
1184*******************************************************************************/
1185bt_status_t btif_av_execute_service(BOOLEAN b_enable)
1186{
1187     if (b_enable)
1188     {
1189         /* TODO: Removed BTA_SEC_AUTHORIZE since the Java/App does not
1190          * handle this request in order to allow incoming connections to succeed.
1191          * We need to put this back once support for this is added */
1192
1193         /* Added BTA_AV_FEAT_NO_SCO_SSPD - this ensures that the BTA does not
1194          * auto-suspend av streaming on AG events(SCO or Call). The suspend shall
1195          * be initiated by the app/audioflinger layers */
1196#if (AVRC_METADATA_INCLUDED == TRUE)
1197         BTA_AvEnable(BTA_SEC_AUTHENTICATE,
1198             BTA_AV_FEAT_RCTG|BTA_AV_FEAT_METADATA|BTA_AV_FEAT_VENDOR|BTA_AV_FEAT_NO_SCO_SSPD
1199#if (AVRC_ADV_CTRL_INCLUDED == TRUE)
1200             |BTA_AV_FEAT_RCCT
1201             |BTA_AV_FEAT_ADV_CTRL
1202#endif
1203             ,bte_av_callback);
1204#else
1205         BTA_AvEnable(BTA_SEC_AUTHENTICATE, (BTA_AV_FEAT_RCTG | BTA_AV_FEAT_NO_SCO_SSPD),
1206                      bte_av_callback);
1207#endif
1208         BTA_AvRegister(BTA_AV_CHNL_AUDIO, BTIF_AV_SERVICE_NAME, 0, bte_av_media_callback);
1209     }
1210     else {
1211         BTA_AvDeregister(btif_av_cb.bta_handle);
1212         BTA_AvDisable();
1213     }
1214     return BT_STATUS_SUCCESS;
1215}
1216
1217/*******************************************************************************
1218**
1219** Function         btif_av_get_src_interface
1220**
1221** Description      Get the AV callback interface for A2DP source profile
1222**
1223** Returns          btav_interface_t
1224**
1225*******************************************************************************/
1226const btav_interface_t *btif_av_get_src_interface(void)
1227{
1228    BTIF_TRACE_EVENT("%s", __FUNCTION__);
1229    return &bt_av_src_interface;
1230}
1231
1232/*******************************************************************************
1233**
1234** Function         btif_av_get_sink_interface
1235**
1236** Description      Get the AV callback interface for A2DP sink profile
1237**
1238** Returns          btav_interface_t
1239**
1240*******************************************************************************/
1241const btav_interface_t *btif_av_get_sink_interface(void)
1242{
1243    BTIF_TRACE_EVENT("%s", __FUNCTION__);
1244    return &bt_av_sink_interface;
1245}
1246
1247/*******************************************************************************
1248**
1249** Function         btif_av_is_connected
1250**
1251** Description      Checks if av has a connected sink
1252**
1253** Returns          BOOLEAN
1254**
1255*******************************************************************************/
1256BOOLEAN btif_av_is_connected(void)
1257{
1258    btif_sm_state_t state = btif_sm_get_state(btif_av_cb.sm_handle);
1259    return ((state == BTIF_AV_STATE_OPENED) || (state ==  BTIF_AV_STATE_STARTED));
1260}
1261
1262/*******************************************************************************
1263**
1264** Function         btif_av_is_peer_edr
1265**
1266** Description      Check if the connected a2dp device supports
1267**                  EDR or not. Only when connected this function
1268**                  will accurately provide a true capability of
1269**                  remote peer. If not connected it will always be false.
1270**
1271** Returns          TRUE if remote device is capable of EDR
1272**
1273*******************************************************************************/
1274BOOLEAN btif_av_is_peer_edr(void)
1275{
1276    ASSERTC(btif_av_is_connected(), "No active a2dp connection", 0);
1277
1278    if (btif_av_cb.edr)
1279        return TRUE;
1280    else
1281        return FALSE;
1282}
1283
1284