diff --git a/src/modules/bluetooth/bluez5-util.c b/src/modules/bluetooth/bluez5-util.c index 107255184a..8e50e0be7b 100644 --- a/src/modules/bluetooth/bluez5-util.c +++ b/src/modules/bluetooth/bluez5-util.c @@ -259,6 +259,9 @@ static void device_start_waiting_for_profiles(pa_bluetooth_device *device) { void pa_bluetooth_transport_set_state(pa_bluetooth_transport *t, pa_bluetooth_transport_state_t state) { bool old_any_connected; + unsigned n_disconnected_profiles; + bool new_device_appeared; + bool device_disconnected; pa_assert(t); @@ -274,26 +277,44 @@ void pa_bluetooth_transport_set_state(pa_bluetooth_transport *t, pa_bluetooth_tr pa_hook_fire(&t->device->discovery->hooks[PA_BLUETOOTH_HOOK_TRANSPORT_STATE_CHANGED], t); - if (old_any_connected != pa_bluetooth_device_any_transport_connected(t->device)) { - unsigned n_disconnected_profiles; + /* If there are profiles that are expected to get connected soon (based + * on the UUID list), we wait for a bit before announcing the new + * device, so that all profiles have time to get connected before the + * card object is created. If we didn't wait, the card would always + * have only one profile marked as available in the initial state, + * which would prevent module-card-restore from restoring the initial + * profile properly. */ - /* If there are profiles that are expected to get connected soon (based - * on the UUID list), we wait for a bit before announcing the new - * device, so that all profiles have time to get connected before the - * card object is created. If we didn't wait, the card would always - * have only one profile marked as available in the initial state, - * which would prevent module-card-restore from restoring the initial - * profile properly. */ + n_disconnected_profiles = device_count_disconnected_profiles(t->device); - n_disconnected_profiles = device_count_disconnected_profiles(t->device); + new_device_appeared = !old_any_connected && pa_bluetooth_device_any_transport_connected(t->device); + device_disconnected = old_any_connected && !pa_bluetooth_device_any_transport_connected(t->device); - if (n_disconnected_profiles == 0) - device_stop_waiting_for_profiles(t->device); - - if (!old_any_connected && n_disconnected_profiles > 0) + if (new_device_appeared) { + if (n_disconnected_profiles > 0) device_start_waiting_for_profiles(t->device); else pa_hook_fire(&t->device->discovery->hooks[PA_BLUETOOTH_HOOK_DEVICE_CONNECTION_CHANGED], t->device); + return; + } + + if (device_disconnected) { + if (t->device->wait_for_profiles_timer) { + /* If the timer is still running when the device disconnects, we + * never sent the notification of the device getting connected, so + * we don't need to send a notification about the disconnection + * either. Let's just stop the timer. */ + device_stop_waiting_for_profiles(t->device); + } else + pa_hook_fire(&t->device->discovery->hooks[PA_BLUETOOTH_HOOK_DEVICE_CONNECTION_CHANGED], t->device); + return; + } + + if (n_disconnected_profiles == 0 && t->device->wait_for_profiles_timer) { + /* All profiles are now connected, so we can stop the wait timer and + * send a notification of the new device. */ + device_stop_waiting_for_profiles(t->device); + pa_hook_fire(&t->device->discovery->hooks[PA_BLUETOOTH_HOOK_DEVICE_CONNECTION_CHANGED], t->device); } }