From 65cff269a3e12fb145206aeeaa656d910f27b439 Mon Sep 17 00:00:00 2001 From: AnubhavGupta Date: Wed, 6 Apr 2016 11:47:05 +0530 Subject: Do not request AVRC_CAP_COMPANY_ID if A2DP Sink is not enabled Also fixed AVRC_PDU_GET_PLAY_STATUS timeout response. Bug: 28177785 Change-Id: Icde64a5c1806453850abe101f9707fff61566566 (cherry picked from commit 1c512b851d76deac860fce1232e4a1fa1a097f1c) --- btif/include/btif_av.h | 11 +++++++++++ btif/src/btif_av.c | 14 ++++++++++++++ btif/src/btif_rc.c | 8 +++++--- 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/btif/include/btif_av.h b/btif/include/btif_av.h index eaf856e..1fc7cfe 100644 --- a/btif/include/btif_av.h +++ b/btif/include/btif_av.h @@ -80,6 +80,17 @@ btif_sm_handle_t btif_av_get_sm_handle(void); bt_bdaddr_t btif_av_get_addr(void); /******************************************************************************* +** Function btif_av_is_sink_enabled +** +** Description Checks if A2DP Sink is enabled or not +** +** Returns TRUE if A2DP Sink is enabled, false otherwise +** +*******************************************************************************/ + +BOOLEAN btif_av_is_sink_enabled(void); + +/******************************************************************************* ** ** Function btif_av_stream_ready ** diff --git a/btif/src/btif_av.c b/btif/src/btif_av.c index 0f7af6c..03ba842 100644 --- a/btif/src/btif_av.c +++ b/btif/src/btif_av.c @@ -1427,6 +1427,20 @@ bt_bdaddr_t btif_av_get_addr(void) } /******************************************************************************* +** Function btif_av_is_sink_enabled +** +** Description Checks if A2DP Sink is enabled or not +** +** Returns TRUE if A2DP Sink is enabled, false otherwise +** +*******************************************************************************/ + +BOOLEAN btif_av_is_sink_enabled(void) +{ + return (bt_av_sink_callbacks != NULL) ? TRUE : FALSE; +} + +/******************************************************************************* ** ** Function btif_av_stream_ready ** diff --git a/btif/src/btif_rc.c b/btif/src/btif_rc.c index 763809b..8805f4f 100644 --- a/btif/src/btif_rc.c +++ b/btif/src/btif_rc.c @@ -457,7 +457,9 @@ void handle_rc_ctrl_features(BD_ADDR bd_addr) * update. */ btif_rc_cb.rc_features_processed = TRUE; - getcapabilities_cmd (AVRC_CAP_COMPANY_ID); + + if (btif_av_is_sink_enabled()) + getcapabilities_cmd (AVRC_CAP_COMPANY_ID); } BTIF_TRACE_DEBUG("%s Update rc features to CTRL %d", __FUNCTION__, rc_features); HAL_CBACK(bt_rc_ctrl_callbacks, getrcfeatures_cb, &rc_addr, rc_features); @@ -2090,8 +2092,8 @@ static void btif_rc_status_cmd_timeout_handler(UNUSED_ATTR uint16_t event, break; case AVRC_PDU_GET_PLAY_STATUS: - avrc_response.get_caps.status = BTIF_RC_STS_TIMEOUT; - handle_get_capability_response(&meta_msg, &avrc_response.get_caps); + avrc_response.get_play_status.status = BTIF_RC_STS_TIMEOUT; + handle_get_playstatus_response(&meta_msg, &avrc_response.get_play_status); break; } release_transaction(p_context->rc_status_cmd.label); -- cgit v1.1 From 939fd540855c48a930b20cd99642715d15376a9c Mon Sep 17 00:00:00 2001 From: Ayan Ghosh Date: Fri, 22 Jul 2016 15:11:11 +0530 Subject: Proper handling of AV connection collision Use case: 1. Pair to Remote 2. Turn OFF/ON BT on DUT 3. After DUT's BT is turned ON, Remote would reconnect to DUT Failure: Bluetooth settings UI continues to display Connecting when BT was Turned OFF and ON. Root cause: - This is a connection collision case where remote is not responding to DUT initiated SDP attribute fetch request for AV. AV holds outgoing connection for sometime and meanwhile remote starts AV connection from its end. Then DUT disconnects the SDP channel after a second without waiting to fetch requested info, and this confuses DUT's AV state machine. The outgoing connection could not proceed as incoming AV L2CAP connects, because DUT's AV state machine is not equipped with handling this scenario. On incoming connection timer expiry, it does not start AV media channel as it finds AV Open has not been done from upper layer after incoming L2CAP got connected. - When the incoming path 2s timer expires, the DUT checks whether Open has been called after incoming state is set. This is not the case here, because Open was triggered earlier as as part of the outgoing connection. As a result, A2DP cannot connect at all. Fix: - Properly set collision flags for handling AV connection collision. - Update BTA AV handle even when BTIF AV state machine is yet to be built. Bug: 30362987 Change-Id: I02a3adb62479b0f762bc792a5727d06e11eaaa52 (cherry picked from commit db1e3a5fbb41cd1faf572c5f89ec9212c5ff2986) --- bta/av/bta_av_aact.c | 5 ++++- bta/av/bta_av_act.c | 3 +++ btif/src/btif_av.c | 10 +++++++++- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/bta/av/bta_av_aact.c b/bta/av/bta_av_aact.c index 6c5d874..1e73fa6 100644 --- a/bta/av/bta_av_aact.c +++ b/bta/av/bta_av_aact.c @@ -1567,7 +1567,10 @@ void bta_av_connect_req(tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data) { /* SNK initiated L2C connection while SRC was doing SDP. */ /* Wait until timeout to check if SNK starts signalling. */ - APPL_TRACE_EVENT("bta_av_connect_req: coll_mask = 0x%2X", p_scb->coll_mask); + APPL_TRACE_EVENT("%s: coll_mask = 0x%2X", __func__, p_scb->coll_mask); + p_scb->coll_mask |= BTA_AV_COLL_API_CALLED; + APPL_TRACE_EVENT("%s: updated coll_mask = 0x%2X", __func__, + p_scb->coll_mask); return; } diff --git a/bta/av/bta_av_act.c b/bta/av/bta_av_act.c index 5857dd6..9cc802f 100644 --- a/bta/av/bta_av_act.c +++ b/bta/av/bta_av_act.c @@ -1613,6 +1613,8 @@ static void bta_av_accept_signalling_timer_cback(void *data) if (bta_av_is_scb_opening(p_scb)) { + APPL_TRACE_DEBUG("%s: stream state opening: SDP started = %d", + __func__, p_scb->sdp_discovery_started); if (p_scb->sdp_discovery_started) { /* We are still doing SDP. Run the timer again. */ @@ -1634,6 +1636,7 @@ static void bta_av_accept_signalling_timer_cback(void *data) { /* Stay in incoming state if SNK does not start signalling */ + APPL_TRACE_DEBUG("%s: stream state incoming", __func__); /* API open was called right after SNK opened L2C connection. */ if (p_scb->coll_mask & BTA_AV_COLL_API_CALLED) { diff --git a/btif/src/btif_av.c b/btif/src/btif_av.c index 03ba842..f852d48 100644 --- a/btif/src/btif_av.c +++ b/btif/src/btif_av.c @@ -1044,13 +1044,21 @@ static BOOLEAN btif_av_state_started_handler(btif_sm_event_t event, void *p_data static void btif_av_handle_event(UINT16 event, char* p_param) { + BTIF_TRACE_EVENT("%s event:%s", __func__, + dump_av_sm_event_name((btif_av_sm_event_t)event)); switch(event) { case BTIF_AV_CLEANUP_REQ_EVT: - BTIF_TRACE_EVENT("%s: BTIF_AV_CLEANUP_REQ_EVT", __FUNCTION__); btif_a2dp_stop_media_task(); break; + case BTA_AV_REGISTER_EVT: + if (btif_av_cb.sm_handle == NULL) + { + btif_av_cb.bta_handle = ((tBTA_AV*)p_param)->registr.hndl; + BTIF_TRACE_DEBUG("%s: BTA AV Handle updated", __func__); + } + /* FALLTHROUGH */ default: btif_sm_dispatch(btif_av_cb.sm_handle, event, (void*)p_param); btif_av_event_free_data(event, p_param); -- cgit v1.1 From b1f51a346bebb47bd723ad7ca69b9cedc1337f71 Mon Sep 17 00:00:00 2001 From: Andy Hung Date: Thu, 28 Jul 2016 10:45:54 -0700 Subject: audio_a2dp_hw: Always update frame counter in out_write Required now that we always return success. Bug: 30025777 Change-Id: I7db51321672c128039545cc0fb604c615f169bc3 --- audio_a2dp_hw/audio_a2dp_hw.c | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/audio_a2dp_hw/audio_a2dp_hw.c b/audio_a2dp_hw/audio_a2dp_hw.c index 20c7335..fdd05e4 100644 --- a/audio_a2dp_hw/audio_a2dp_hw.c +++ b/audio_a2dp_hw/audio_a2dp_hw.c @@ -586,8 +586,7 @@ static ssize_t out_write(struct audio_stream_out *stream, const void* buffer, size_t bytes) { struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream; - int sent; - int us_delay; + int sent = -1; DEBUG("write %zu bytes (fd %d)", bytes, out->common.audio_fd); @@ -595,7 +594,7 @@ static ssize_t out_write(struct audio_stream_out *stream, const void* buffer, if (out->common.state == AUDIO_A2DP_STATE_SUSPENDED || out->common.state == AUDIO_A2DP_STATE_STOPPING) { DEBUG("stream suspended or closing"); - goto error; + goto finish; } /* only allow autostarting if we are in stopped or standby */ @@ -604,13 +603,13 @@ static ssize_t out_write(struct audio_stream_out *stream, const void* buffer, { if (start_audio_datapath(&out->common) < 0) { - goto error; + goto finish; } } else if (out->common.state != AUDIO_A2DP_STATE_STARTED) { ERROR("stream not in stopped or standby"); - goto error; + goto finish; } pthread_mutex_unlock(&out->common.lock); @@ -626,26 +625,24 @@ static ssize_t out_write(struct audio_stream_out *stream, const void* buffer, } else { ERROR("write failed : stream suspended, avoid resetting state"); } - goto error; + goto finish; } +finish: ; const size_t frames = bytes / audio_stream_out_frame_size(stream); out->frames_rendered += frames; out->frames_presented += frames; pthread_mutex_unlock(&out->common.lock); - return bytes; - -error: - pthread_mutex_unlock(&out->common.lock); - us_delay = calc_audiotime(out->common.cfg, bytes); - DEBUG("emulate a2dp write delay (%d us)", us_delay); - - usleep(us_delay); + // If send didn't work out, sleep to emulate write delay. + if (sent == -1) { + const int us_delay = calc_audiotime(out->common.cfg, bytes); + DEBUG("emulate a2dp write delay (%d us)", us_delay); + usleep(us_delay); + } return bytes; } - static uint32_t out_get_sample_rate(const struct audio_stream *stream) { struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream; -- cgit v1.1 From 9ef3ce8fb8b275fcd372ec673b4b496461e6b6a5 Mon Sep 17 00:00:00 2001 From: Pavlin Radoslavov Date: Wed, 14 Sep 2016 16:39:02 -0700 Subject: Add BT_HCI_UNKNOWN_MESSAGE_TYPE log event If the received HCI type is unknown, then log an event and abort. The most likely reason for that to happen is if the UART stream is corrupted. We cannot recover from that, and there is not much else we can do. Also, fixed a bug in an HCI-related unit test that was exposed by the above change. Bug: 31432127 Change-Id: Ia888c485f177af4962268bf8f593b27fd7a4b080 (cherry picked from commit 27ec0c7824cf67b8a36bf5391734e6d2fc6207e2) (cherry picked from commit e1c8ed17c7a35510f00997ca329687f73cd193d8) --- EventLogTags.logtags | 1 + hci/src/hci_hal_h4.c | 7 ++++++- hci/test/hci_hal_h4_test.cpp | 25 ++++++++++++++----------- 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/EventLogTags.logtags b/EventLogTags.logtags index 32493d8..dc1d239 100644 --- a/EventLogTags.logtags +++ b/EventLogTags.logtags @@ -35,3 +35,4 @@ 1010000 bt_hci_timeout (opcode|1) 1010001 bt_config_source (opcode|1) +1010002 bt_hci_unknown_type (hci_type|1) diff --git a/hci/src/hci_hal_h4.c b/hci/src/hci_hal_h4.c index 062b6c0..9c7afe5 100644 --- a/hci/src/hci_hal_h4.c +++ b/hci/src/hci_hal_h4.c @@ -38,6 +38,8 @@ // when streaming time sensitive data (A2DP). #define HCI_THREAD_PRIORITY -19 +#define BT_HCI_UNKNOWN_MESSAGE_TYPE_NUM 1010002 + // Our interface and modules we import static const hci_hal_t interface; static const hci_hal_callbacks_t *callbacks; @@ -233,7 +235,10 @@ static void event_uart_has_bytes(eager_reader_t *reader, UNUSED_ATTR void *conte return; if (type_byte < DATA_TYPE_ACL || type_byte > DATA_TYPE_EVENT) { - LOG_ERROR(LOG_TAG, "%s Unknown HCI message type. Dropping this byte 0x%x, min %x, max %x", __func__, type_byte, DATA_TYPE_ACL, DATA_TYPE_EVENT); + LOG_ERROR(LOG_TAG, "%s Unknown HCI message type 0x%x (min=0x%x max=0x%x). Aborting...", + __func__, type_byte, DATA_TYPE_ACL, DATA_TYPE_EVENT); + LOG_EVENT_INT(BT_HCI_UNKNOWN_MESSAGE_TYPE_NUM, type_byte); + assert(false && "Unknown HCI message type"); return; } diff --git a/hci/test/hci_hal_h4_test.cpp b/hci/test/hci_hal_h4_test.cpp index bf62405..1b861a0 100644 --- a/hci/test/hci_hal_h4_test.cpp +++ b/hci/test/hci_hal_h4_test.cpp @@ -192,17 +192,18 @@ static void expect_socket_data(int fd, char first_byte, char *data) { } } -static void write_packet(int fd, char first_byte, char *data) { +static void write_packet(int fd, char first_byte, const void *data, + size_t datalen) { write(fd, &first_byte, 1); - write(fd, data, strlen(data)); + write(fd, data, datalen); } -static void write_packet_reentry(int fd, char first_byte, char *data) { +static void write_packet_reentry(int fd, char first_byte, const void *data, + size_t datalen) { write(fd, &first_byte, 1); - int length = strlen(data); - for (int i = 0; i < length; i++) { - write(fd, &data[i], 1); + for (size_t i = 0; i < datalen; i++) { + write(fd, static_cast(data) + i, 1); semaphore_wait(reentry_semaphore); } } @@ -226,10 +227,11 @@ TEST_F(HciHalH4Test, test_transmit) { TEST_F(HciHalH4Test, test_read_synchronous) { reset_for(read_synchronous); - write_packet(sockfd[1], DATA_TYPE_ACL, acl_data); - write_packet(sockfd[1], HCI_BLE_EVENT, corrupted_data); - write_packet(sockfd[1], DATA_TYPE_SCO, sco_data); - write_packet(sockfd[1], DATA_TYPE_EVENT, event_data); + write_packet(sockfd[1], DATA_TYPE_ACL, acl_data, strlen(acl_data)); + write_packet(sockfd[1], HCI_BLE_EVENT, corrupted_data, + sizeof(corrupted_data)); + write_packet(sockfd[1], DATA_TYPE_SCO, sco_data, strlen(sco_data)); + write_packet(sockfd[1], DATA_TYPE_EVENT, event_data, strlen(event_data)); // Wait for all data to be received before calling the test good semaphore_wait(done); @@ -242,7 +244,8 @@ TEST_F(HciHalH4Test, test_read_async_reentry) { reentry_semaphore = semaphore_new(0); reentry_i = 0; - write_packet_reentry(sockfd[1], DATA_TYPE_ACL, sample_data3); + write_packet_reentry(sockfd[1], DATA_TYPE_ACL, sample_data3, + strlen(sample_data3)); // write_packet_reentry ensures the data has been received semaphore_free(reentry_semaphore); -- cgit v1.1