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);