Set A2DP L2CAP socket to flushable while streaming A2DP, and set the automatic
flush timeout.
Remove the (ahead < 0) logic that was designed to skip forwards when streaming
was lagging. This logic was not working properly, and ACL flushing does its
job.
Changes made by: Jaikumar Ganesh for Bluez upgrade to 4.89
Change-Id: Ic9025be657cbea1362b0a7f1d5a30ecf55e6cad2
diff --git a/audio/Android.mk b/audio/Android.mk
index de82065..1b9beec 100755
--- a/audio/Android.mk
+++ b/audio/Android.mk
@@ -69,6 +69,8 @@
LOCAL_C_INCLUDES:= \
$(LOCAL_PATH)/../sbc \
+ ../../../../frameworks/base/include \
+ system/bluetooth/bluez-clean-headers
LOCAL_SHARED_LIBRARIES := \
libcutils
diff --git a/audio/liba2dp.c b/audio/liba2dp.c
index 7403886..bdc5992 100755
--- a/audio/liba2dp.c
+++ b/audio/liba2dp.c
@@ -39,6 +39,9 @@
#include <sys/poll.h>
#include <sys/prctl.h>
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/l2cap.h>
+
#include "ipc.h"
#include "sbc.h"
#include "rtp.h"
@@ -181,6 +184,31 @@
data->state = A2DP_STATE_NONE;
}
+static int l2cap_set_flushable(int fd, int flushable)
+{
+ int flags;
+ socklen_t len;
+
+ len = sizeof(flags);
+ if (getsockopt(fd, SOL_BLUETOOTH, BT_FLUSHABLE, &flags, &len) < 0)
+ return -errno;
+
+ if (flushable) {
+ if (flags == BT_FLUSHABLE_ON)
+ return 0;
+ flags = BT_FLUSHABLE_ON;
+ } else {
+ if (flags == BT_FLUSHABLE_OFF)
+ return 0;
+ flags = BT_FLUSHABLE_OFF;
+ }
+
+ if (setsockopt(fd, SOL_BLUETOOTH, L2CAP_LM, &flags, sizeof(flags)) < 0)
+ return -errno;
+
+ return 0;
+}
+
static int bluetooth_start(struct bluetooth_data *data)
{
char c = 'w';
@@ -219,6 +247,7 @@
err = -errno;
goto error;
}
+ l2cap_set_flushable(data->stream.fd, 1);
data->stream.events = POLLOUT;
/* set our socket buffer to the size of PACKET_BUFFER_COUNT packets */
@@ -254,6 +283,7 @@
DBG("bluetooth_stop");
data->state = A2DP_STATE_STOPPING;
+ l2cap_set_flushable(data->stream.fd, 0);
if (data->stream.fd >= 0) {
close(data->stream.fd);
data->stream.fd = -1;
@@ -649,14 +679,7 @@
} else {
data->next_write = now;
}
- if (ahead < 0) {
- /* fallen too far behind, don't try to catch up */
- VDBG("ahead < 0, resetting next_write");
- data->next_write = 0;
- } else {
- /* advance next_write by duration */
- data->next_write += duration;
- }
+ data->next_write += duration;
#ifdef ENABLE_TIMING
begin2 = get_microseconds();
diff --git a/common/android_bluez.c b/common/android_bluez.c
index 69b2ea3..81dd549 100644
--- a/common/android_bluez.c
+++ b/common/android_bluez.c
@@ -51,6 +51,31 @@
capset(&header, &cap);
}
+static int write_flush_timeout(int fd, uint16_t handle, uint16_t timeout) {
+ unsigned char hci_write_flush_cmd[] = {
+ 0x01, // HCI command packet
+ 0x28, 0x0C, // HCI_Write_Automatic_Flush_Timeout
+ 0x04, // Length
+ 0x00, 0x00, // Handle
+ 0x00, 0x00, // Timeout
+ };
+
+ hci_write_flush_cmd[4] = (uint8_t)handle;
+ hci_write_flush_cmd[5] = (uint8_t)(handle >> 8);
+ hci_write_flush_cmd[6] = (uint8_t)timeout;
+ hci_write_flush_cmd[7] = (uint8_t)(timeout >> 8);
+
+ int ret = write(fd, hci_write_flush_cmd, sizeof(hci_write_flush_cmd));
+ if (ret < 0) {
+ error("write(): %s (%d)]", strerror(errno), errno);
+ return -1;
+ } else if (ret != sizeof(hci_write_flush_cmd)) {
+ error("write(): unexpected length %d", ret);
+ return -1;
+ }
+ return 0;
+}
+
#ifdef BOARD_HAVE_BLUETOOTH_BCM
static int vendor_high_priority(int fd, uint16_t handle) {
unsigned char hci_sleep_cmd[] = {
@@ -158,6 +183,9 @@
}
ret = vendor_high_priority(fd, acl_handle);
+ if (ret < 0)
+ goto out;
+ ret = write_flush_timeout(fd, acl_handle, 0x60);
out:
close(fd);