Fix authorization when the audio profiles are slow to connect
Incoming audio connections should be automatically authorized if either
HFP/HSP or A2DP is already connected for the same device.
diff --git a/audio/avdtp.c b/audio/avdtp.c
index 71a8da2..0ee81c0 100644
--- a/audio/avdtp.c
+++ b/audio/avdtp.c
@@ -1028,6 +1028,8 @@
if (session->ref == 1) {
if (session->state == AVDTP_SESSION_STATE_CONNECTING &&
session->io) {
+ btd_cancel_authorization(&session->server->src,
+ &session->dst);
g_io_channel_shutdown(session->io, TRUE, NULL);
g_io_channel_unref(session->io);
session->io = NULL;
@@ -2136,6 +2138,7 @@
session->io_id = g_io_add_watch(chan, G_IO_ERR | G_IO_HUP | G_IO_NVAL,
(GIOFunc) session_cb, session);
+
perr = audio_device_request_authorization(dev, ADVANCED_AUDIO_UUID,
auth_cb, session);
if (perr < 0) {
diff --git a/audio/control.c b/audio/control.c
index e49c229..d7161c0 100644
--- a/audio/control.c
+++ b/audio/control.c
@@ -710,12 +710,8 @@
avctp_set_state(control, AVCTP_STATE_CONNECTING);
control->io = g_io_channel_ref(chan);
- if (avdtp_is_connected(&src, &dst)) {
- if (!bt_io_accept(chan, avctp_connect_cb, dev->control,
- NULL, NULL))
- goto drop;
- } else if (audio_device_request_authorization(dev, AVRCP_TARGET_UUID,
- auth_cb, dev->control) < 0)
+ if (audio_device_request_authorization(dev, AVRCP_TARGET_UUID,
+ auth_cb, dev->control) < 0)
goto drop;
return;
diff --git a/audio/device.c b/audio/device.c
index 85a6a78..27d2bdb 100644
--- a/audio/device.c
+++ b/audio/device.c
@@ -683,6 +683,42 @@
}
}
+static gboolean auth_idle_cb(gpointer user_data)
+{
+ auth_cb(NULL, user_data);
+ return FALSE;
+}
+
+static gboolean audio_device_is_connected(struct audio_device *dev)
+{
+ if (dev->headset) {
+ headset_state_t state = headset_get_state(dev);
+
+ if (state == HEADSET_STATE_CONNECTED ||
+ state == HEADSET_STATE_PLAY_IN_PROGRESS ||
+ state == HEADSET_STATE_PLAYING)
+ return TRUE;
+ }
+
+ if (dev->sink) {
+ sink_state_t state = sink_get_state(dev);
+
+ if (state == SINK_STATE_CONNECTED ||
+ state == SINK_STATE_PLAYING)
+ return TRUE;
+ }
+
+ if (dev->source) {
+ source_state_t state = source_get_state(dev);
+
+ if (state == SOURCE_STATE_CONNECTED ||
+ state == SOURCE_STATE_PLAYING)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
int audio_device_request_authorization(struct audio_device *dev,
const char *uuid, service_auth_cb cb,
void *user_data)
@@ -702,6 +738,11 @@
if (g_slist_length(priv->auths) > 1)
return 0;
+ if (audio_device_is_connected(dev)) {
+ g_idle_add(auth_idle_cb, dev);
+ return 0;
+ }
+
err = btd_request_authorization(&dev->src, &dev->dst, uuid, auth_cb,
dev);
if (err < 0) {