bluetooth: Prevent registration of an unavailable codec at runtime
authorSanchayan Maity <sanchayan@asymptotic.io>
Fri, 1 Jan 2021 14:08:48 +0000 (19:38 +0530)
committerSanchayan Maity <sanchayan@asymptotic.io>
Tue, 19 Jan 2021 08:13:42 +0000 (13:43 +0530)
When it comes to codecs provided via GStreamer, we register all codecs
if GStreamer option is enabled for bluez5 via meson. However, the
GStreamer plugin required for the codec might not be present on the
system. This results in the codec being available for registration with
the bluez stack or selection by the user, but, trying to use the said
codec then fails.

To prevent the above, we now use the can_be_supported codec API to check
if the codec is usable and if not, we do not register the said codec and
also prevent users from switching to it.

Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/440>

src/modules/bluetooth/bluez5-util.c
src/modules/bluetooth/module-bluez5-device.c

index 76c53c2..4d0180a 100644 (file)
@@ -2101,6 +2101,9 @@ static DBusHandlerResult object_manager_handler(DBusConnection *c, DBusMessage *
             char *endpoint;
 
             a2dp_codec = pa_bluetooth_a2dp_codec_iter(i);
+            if (!a2dp_codec->can_be_supported())
+                continue;
+
             codec_id = a2dp_codec->id.codec_id;
             capabilities_size = a2dp_codec->fill_capabilities(capabilities);
             pa_assert(capabilities_size != 0);
@@ -2208,6 +2211,8 @@ pa_bluetooth_discovery* pa_bluetooth_discovery_get(pa_core *c, int headset_backe
     count = pa_bluetooth_a2dp_codec_count();
     for (i = 0; i < count; i++) {
         a2dp_codec = pa_bluetooth_a2dp_codec_iter(i);
+        if (!a2dp_codec->can_be_supported())
+            continue;
 
         endpoint = pa_sprintf_malloc("%s/%s", A2DP_SINK_ENDPOINT, a2dp_codec->name);
         endpoint_init(y, endpoint);
@@ -2296,6 +2301,9 @@ void pa_bluetooth_discovery_unref(pa_bluetooth_discovery *y) {
         for (i = 0; i < count; i++) {
             a2dp_codec = pa_bluetooth_a2dp_codec_iter(i);
 
+            if (!a2dp_codec->can_be_supported())
+                continue;
+
             endpoint = pa_sprintf_malloc("%s/%s", A2DP_SINK_ENDPOINT, a2dp_codec->name);
             endpoint_done(y, endpoint);
             pa_xfree(endpoint);
index 4ad0b95..01533fd 100644 (file)
@@ -2304,14 +2304,15 @@ static char *list_codecs(struct userdata *u) {
 
             a2dp_codec = pa_bluetooth_a2dp_codec_iter(i);
 
-            if (key->codec_id == a2dp_codec->id.codec_id && key->vendor_id == a2dp_codec->id.vendor_id
-                    && key->vendor_codec_id == a2dp_codec->id.vendor_codec_id) {
-                pa_message_params_begin_list(param);
+            if (memcmp(key, &a2dp_codec->id, sizeof(pa_a2dp_codec_id)) == 0) {
+                if (a2dp_codec->can_be_supported()) {
+                    pa_message_params_begin_list(param);
 
-                pa_message_params_write_string(param, a2dp_codec->name);
-                pa_message_params_write_string(param, a2dp_codec->description);
+                    pa_message_params_write_string(param, a2dp_codec->name);
+                    pa_message_params_write_string(param, a2dp_codec->description);
 
-                pa_message_params_end_list(param);
+                    pa_message_params_end_list(param);
+                }
             }
         }
     }
@@ -2380,6 +2381,11 @@ static int bluez5_device_message_handler(const char *object_path, const char *me
             return -PA_ERR_INVALID;
         }
 
+        if (!codec->can_be_supported()) {
+            pa_log_info("Codec not found on system");
+            return -PA_ERR_NOTSUPPORTED;
+        }
+
         is_a2dp_sink = u->profile == PA_BLUETOOTH_PROFILE_A2DP_SINK;
 
         /*