Coverage Report

Created: 2026-04-09 06:45

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/adhd/cras/src/server/cras_bt_manager.c
Line
Count
Source
1
/* Copyright 2013 The ChromiumOS Authors
2
 * Use of this source code is governed by a BSD-style license that can be
3
 * found in the LICENSE file.
4
 */
5
6
#include "cras/src/server/cras_bt_manager.h"
7
8
#include <dbus/dbus.h>
9
#include <errno.h>
10
#include <stdlib.h>
11
#include <string.h>
12
#include <syslog.h>
13
14
#include "cras/src/common/cras_string.h"
15
#include "cras/src/server/cras_a2dp_endpoint.h"
16
#include "cras/src/server/cras_bt_adapter.h"
17
#include "cras/src/server/cras_bt_battery_provider.h"
18
#include "cras/src/server/cras_bt_constants.h"
19
#include "cras/src/server/cras_bt_device.h"
20
#include "cras/src/server/cras_bt_endpoint.h"
21
#include "cras/src/server/cras_bt_log.h"
22
#include "cras/src/server/cras_bt_player.h"
23
#include "cras/src/server/cras_bt_policy.h"
24
#include "cras/src/server/cras_bt_profile.h"
25
#include "cras/src/server/cras_bt_transport.h"
26
#include "cras/src/server/cras_hfp_ag_profile.h"
27
#include "cras/src/server/cras_telephony.h"
28
#include "cras_types.h"
29
30
static void cras_bt_start_bluez(struct bt_stack* s);
31
static void cras_bt_stop_bluez(struct bt_stack* s);
32
33
static struct bt_stack default_stack = {
34
    .conn = NULL,
35
    .start = cras_bt_start_bluez,
36
    .stop = cras_bt_stop_bluez,
37
};
38
static struct bt_stack* current = &default_stack;
39
40
static void cras_bt_interface_added(DBusConnection* conn,
41
                                    const char* object_path,
42
                                    const char* interface_name,
43
0
                                    DBusMessageIter* properties_array_iter) {
44
0
  if (strcmp(interface_name, BLUEZ_INTERFACE_ADAPTER) == 0) {
45
0
    struct cras_bt_adapter* adapter;
46
47
0
    adapter = cras_bt_adapter_get(object_path);
48
0
    if (adapter) {
49
0
      cras_bt_adapter_update_properties(adapter, properties_array_iter, NULL);
50
0
    } else {
51
0
      BTLOG(btlog, BT_ADAPTER_ADDED, 0, 0);
52
0
      adapter = cras_bt_adapter_create(conn, object_path);
53
0
      if (adapter) {
54
0
        cras_bt_adapter_update_properties(adapter, properties_array_iter, NULL);
55
56
0
        syslog(LOG_DEBUG, "Bluetooth Adapter: %s added",
57
0
               cras_bt_adapter_address(adapter));
58
0
      } else {
59
0
        syslog(LOG_WARNING, "Failed to create Bluetooth Adapter: %s",
60
0
               object_path);
61
0
      }
62
0
    }
63
64
0
  } else if (strcmp(interface_name, BLUEZ_INTERFACE_MEDIA) == 0) {
65
0
    struct cras_bt_adapter* adapter;
66
67
0
    adapter = cras_bt_adapter_get(object_path);
68
0
    if (adapter) {
69
0
      cras_bt_register_endpoints(conn, adapter);
70
0
      cras_bt_register_player(conn, adapter);
71
72
0
      syslog(LOG_DEBUG, "Bluetooth Endpoint and/or Player: %s added",
73
0
             cras_bt_adapter_address(adapter));
74
0
    } else {
75
0
      syslog(LOG_WARNING,
76
0
             "Failed to create Bluetooth Endpoint and/or Player: %s",
77
0
             object_path);
78
0
    }
79
80
0
  } else if (strcmp(interface_name, BLUEZ_PROFILE_MGMT_INTERFACE) == 0) {
81
0
    cras_bt_register_profiles(conn);
82
83
0
    syslog(LOG_DEBUG, "Bluetooth Profile Manager added");
84
85
0
  } else if (strcmp(interface_name, BLUEZ_INTERFACE_DEVICE) == 0) {
86
0
    struct cras_bt_device* device;
87
88
0
    device = cras_bt_device_get(object_path);
89
0
    if (device) {
90
0
      cras_bt_device_update_properties(device, properties_array_iter, NULL);
91
0
    } else {
92
0
      device = cras_bt_device_create(conn, object_path);
93
0
      if (device) {
94
0
        cras_bt_device_update_properties(device, properties_array_iter, NULL);
95
96
0
        syslog(LOG_DEBUG, "Bluetooth Device: %s added",
97
0
               cras_bt_device_address(device));
98
0
      } else {
99
0
        syslog(LOG_WARNING, "Failed to create Bluetooth Device: %s",
100
0
               object_path);
101
0
      }
102
0
    }
103
104
0
  } else if (strcmp(interface_name, BLUEZ_INTERFACE_MEDIA_TRANSPORT) == 0) {
105
0
    struct cras_bt_transport* transport;
106
107
0
    transport = cras_bt_transport_get(object_path);
108
0
    if (transport) {
109
0
      cras_bt_transport_update_properties(transport, properties_array_iter,
110
0
                                          NULL);
111
0
    } else {
112
0
      transport = cras_bt_transport_create(conn, object_path);
113
0
      if (transport) {
114
0
        cras_bt_transport_update_properties(transport, properties_array_iter,
115
0
                                            NULL);
116
117
0
        syslog(LOG_DEBUG, "Bluetooth Transport: %s added",
118
0
               cras_bt_transport_object_path(transport));
119
0
      } else {
120
0
        syslog(LOG_WARNING,
121
0
               "Failed to create Bluetooth Transport: "
122
0
               "%s",
123
0
               object_path);
124
0
      }
125
0
    }
126
0
  } else if (strcmp(interface_name, BLUEZ_INTERFACE_BATTERY_PROVIDER_MANAGER) ==
127
0
             0) {
128
0
    struct cras_bt_adapter* adapter;
129
0
    int ret;
130
131
0
    syslog(LOG_DEBUG, "Bluetooth Battery Provider Manager available");
132
133
0
    adapter = cras_bt_adapter_get(object_path);
134
0
    if (adapter) {
135
0
      syslog(LOG_DEBUG, "Registering Battery Provider for adapter %s",
136
0
             cras_bt_adapter_address(adapter));
137
0
      ret = cras_bt_register_battery_provider(conn, adapter);
138
0
      if (ret != 0) {
139
0
        syslog(LOG_WARNING,
140
0
               "Error registering Battery Provider "
141
0
               "for adapter %s: %s",
142
0
               cras_bt_adapter_address(adapter), cras_strerror(-ret));
143
0
      }
144
0
    } else {
145
0
      syslog(LOG_WARNING,
146
0
             "Adapter not available when trying to create "
147
0
             "Battery Provider");
148
0
    }
149
0
  }
150
0
}
151
152
static void cras_bt_interface_removed(DBusConnection* conn,
153
                                      const char* object_path,
154
0
                                      const char* interface_name) {
155
0
  if (strcmp(interface_name, BLUEZ_INTERFACE_ADAPTER) == 0) {
156
0
    struct cras_bt_adapter* adapter;
157
158
0
    BTLOG(btlog, BT_ADAPTER_REMOVED, 0, 0);
159
0
    adapter = cras_bt_adapter_get(object_path);
160
0
    if (adapter) {
161
0
      syslog(LOG_WARNING, "Bluetooth Adapter: %s removed",
162
0
             cras_bt_adapter_address(adapter));
163
0
      cras_bt_adapter_destroy(adapter);
164
0
    }
165
166
0
  } else if (strcmp(interface_name, BLUEZ_INTERFACE_DEVICE) == 0) {
167
0
    struct cras_bt_device* device;
168
169
0
    device = cras_bt_device_get(object_path);
170
0
    if (device) {
171
0
      if (device->profiles & CRAS_SUPPORTED_PROFILES) {
172
0
        syslog(LOG_WARNING, "Bluetooth Device: %s removed",
173
0
               cras_bt_device_address(device));
174
0
      }
175
0
      cras_bt_device_remove(device);
176
0
    }
177
178
0
  } else if (strcmp(interface_name, BLUEZ_INTERFACE_MEDIA_TRANSPORT) == 0) {
179
0
    struct cras_bt_transport* transport;
180
181
0
    transport = cras_bt_transport_get(object_path);
182
0
    if (transport) {
183
0
      syslog(LOG_WARNING, "Bluetooth Transport: %s removed",
184
0
             cras_bt_transport_object_path(transport));
185
0
      cras_bt_transport_remove(transport);
186
0
    }
187
0
  } else if (strcmp(interface_name, BLUEZ_INTERFACE_BATTERY_PROVIDER_MANAGER) ==
188
0
             0) {
189
0
    syslog(LOG_WARNING, "Bluetooth Battery Provider Manager removed");
190
0
    cras_bt_battery_provider_reset();
191
0
  }
192
0
}
193
194
static void cras_bt_update_properties(DBusConnection* conn,
195
                                      const char* object_path,
196
                                      const char* interface_name,
197
                                      DBusMessageIter* properties_array_iter,
198
0
                                      DBusMessageIter* invalidated_array_iter) {
199
0
  if (strcmp(interface_name, BLUEZ_INTERFACE_ADAPTER) == 0) {
200
0
    struct cras_bt_adapter* adapter;
201
202
0
    adapter = cras_bt_adapter_get(object_path);
203
0
    if (adapter) {
204
0
      cras_bt_adapter_update_properties(adapter, properties_array_iter,
205
0
                                        invalidated_array_iter);
206
0
    }
207
208
0
  } else if (strcmp(interface_name, BLUEZ_INTERFACE_DEVICE) == 0) {
209
0
    struct cras_bt_device* device;
210
211
0
    device = cras_bt_device_get(object_path);
212
0
    if (device) {
213
0
      cras_bt_device_update_properties(device, properties_array_iter,
214
0
                                       invalidated_array_iter);
215
0
    }
216
217
0
  } else if (strcmp(interface_name, BLUEZ_INTERFACE_MEDIA_TRANSPORT) == 0) {
218
0
    struct cras_bt_transport* transport;
219
220
0
    transport = cras_bt_transport_get(object_path);
221
0
    if (transport) {
222
0
      cras_bt_transport_update_properties(transport, properties_array_iter,
223
0
                                          invalidated_array_iter);
224
0
    }
225
0
  }
226
0
}
227
228
/* Destroys all bt related stuff. The reset functions must be called in
229
 * reverse order of the adapter -> device -> profile(s) hierarchy.
230
 */
231
0
static void cras_bt_reset() {
232
0
  BTLOG(btlog, BT_RESET, 0, 0);
233
0
  cras_bt_endpoint_reset();
234
0
  cras_bt_transport_reset();
235
0
  cras_bt_profile_reset();
236
0
  cras_bt_device_reset();
237
0
  cras_bt_adapter_reset();
238
0
}
239
240
static void cras_bt_on_get_managed_objects(DBusPendingCall* pending_call,
241
0
                                           void* data) {
242
0
  DBusConnection* conn = (DBusConnection*)data;
243
0
  DBusMessage* reply;
244
0
  DBusMessageIter message_iter, object_array_iter;
245
246
0
  reply = dbus_pending_call_steal_reply(pending_call);
247
0
  dbus_pending_call_unref(pending_call);
248
249
0
  if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) {
250
0
    syslog(LOG_WARNING, "GetManagedObjects returned error: %s",
251
0
           dbus_message_get_error_name(reply));
252
0
    dbus_message_unref(reply);
253
0
    return;
254
0
  }
255
256
0
  if (!dbus_message_has_signature(reply, "a{oa{sa{sv}}}")) {
257
0
    syslog(LOG_WARNING, "Bad GetManagedObjects reply received");
258
0
    dbus_message_unref(reply);
259
0
    return;
260
0
  }
261
262
0
  dbus_message_iter_init(reply, &message_iter);
263
0
  dbus_message_iter_recurse(&message_iter, &object_array_iter);
264
265
0
  while (dbus_message_iter_get_arg_type(&object_array_iter) !=
266
0
         DBUS_TYPE_INVALID) {
267
0
    DBusMessageIter object_dict_iter, interface_array_iter;
268
0
    const char* object_path;
269
270
0
    dbus_message_iter_recurse(&object_array_iter, &object_dict_iter);
271
272
0
    dbus_message_iter_get_basic(&object_dict_iter, &object_path);
273
0
    dbus_message_iter_next(&object_dict_iter);
274
275
0
    dbus_message_iter_recurse(&object_dict_iter, &interface_array_iter);
276
277
0
    while (dbus_message_iter_get_arg_type(&interface_array_iter) !=
278
0
           DBUS_TYPE_INVALID) {
279
0
      DBusMessageIter interface_dict_iter;
280
0
      DBusMessageIter properties_array_iter;
281
0
      const char* interface_name;
282
283
0
      dbus_message_iter_recurse(&interface_array_iter, &interface_dict_iter);
284
285
0
      dbus_message_iter_get_basic(&interface_dict_iter, &interface_name);
286
0
      dbus_message_iter_next(&interface_dict_iter);
287
288
0
      dbus_message_iter_recurse(&interface_dict_iter, &properties_array_iter);
289
290
0
      cras_bt_interface_added(conn, object_path, interface_name,
291
0
                              &properties_array_iter);
292
293
0
      dbus_message_iter_next(&interface_array_iter);
294
0
    }
295
296
0
    dbus_message_iter_next(&object_array_iter);
297
0
  }
298
299
0
  dbus_message_unref(reply);
300
0
}
301
302
0
static int cras_bt_get_managed_objects(DBusConnection* conn) {
303
0
  DBusMessage* method_call;
304
0
  DBusPendingCall* pending_call;
305
306
0
  method_call = dbus_message_new_method_call(
307
0
      BLUEZ_SERVICE, "/", DBUS_INTERFACE_OBJECT_MANAGER, "GetManagedObjects");
308
0
  if (!method_call) {
309
0
    return -ENOMEM;
310
0
  }
311
312
0
  pending_call = NULL;
313
0
  if (!dbus_connection_send_with_reply(conn, method_call, &pending_call,
314
0
                                       DBUS_TIMEOUT_USE_DEFAULT)) {
315
0
    dbus_message_unref(method_call);
316
0
    return -ENOMEM;
317
0
  }
318
319
0
  dbus_message_unref(method_call);
320
0
  if (!pending_call) {
321
0
    return -EIO;
322
0
  }
323
324
0
  if (!dbus_pending_call_set_notify(
325
0
          pending_call, cras_bt_on_get_managed_objects, conn, NULL)) {
326
0
    dbus_pending_call_cancel(pending_call);
327
0
    dbus_pending_call_unref(pending_call);
328
0
    return -ENOMEM;
329
0
  }
330
331
0
  return 0;
332
0
}
333
334
static DBusHandlerResult cras_bt_handle_name_owner_changed(DBusConnection* conn,
335
                                                           DBusMessage* message,
336
0
                                                           void* arg) {
337
0
  DBusError dbus_error;
338
0
  const char *service_name, *old_owner, *new_owner;
339
340
0
  if (!dbus_message_is_signal(message, DBUS_INTERFACE_DBUS,
341
0
                              "NameOwnerChanged")) {
342
0
    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
343
0
  }
344
345
0
  dbus_error_init(&dbus_error);
346
0
  if (!dbus_message_get_args(message, &dbus_error, DBUS_TYPE_STRING,
347
0
                             &service_name, DBUS_TYPE_STRING, &old_owner,
348
0
                             DBUS_TYPE_STRING, &new_owner, DBUS_TYPE_INVALID)) {
349
0
    syslog(LOG_WARNING, "Bad NameOwnerChanged signal received: %s",
350
0
           dbus_error.message);
351
0
    dbus_error_free(&dbus_error);
352
0
    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
353
0
  }
354
355
0
  syslog(LOG_DEBUG, "Bluetooth daemon disconnected from the bus.");
356
0
  cras_bt_reset();
357
358
0
  if (strlen(new_owner) > 0) {
359
0
    cras_bt_get_managed_objects(conn);
360
0
  }
361
362
0
  return DBUS_HANDLER_RESULT_HANDLED;
363
0
}
364
365
static DBusHandlerResult cras_bt_handle_interfaces_added(DBusConnection* conn,
366
                                                         DBusMessage* message,
367
0
                                                         void* arg) {
368
0
  DBusMessageIter message_iter, interface_array_iter;
369
0
  const char* object_path;
370
371
0
  if (!dbus_message_is_signal(message, DBUS_INTERFACE_OBJECT_MANAGER,
372
0
                              "InterfacesAdded")) {
373
0
    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
374
0
  }
375
376
0
  if (!dbus_message_has_signature(message, "oa{sa{sv}}")) {
377
0
    syslog(LOG_WARNING, "Bad InterfacesAdded signal received");
378
0
    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
379
0
  }
380
381
0
  dbus_message_iter_init(message, &message_iter);
382
383
0
  dbus_message_iter_get_basic(&message_iter, &object_path);
384
0
  dbus_message_iter_next(&message_iter);
385
386
0
  dbus_message_iter_recurse(&message_iter, &interface_array_iter);
387
388
0
  while (dbus_message_iter_get_arg_type(&interface_array_iter) !=
389
0
         DBUS_TYPE_INVALID) {
390
0
    DBusMessageIter interface_dict_iter, properties_array_iter;
391
0
    const char* interface_name;
392
393
0
    dbus_message_iter_recurse(&interface_array_iter, &interface_dict_iter);
394
395
0
    dbus_message_iter_get_basic(&interface_dict_iter, &interface_name);
396
0
    dbus_message_iter_next(&interface_dict_iter);
397
398
0
    dbus_message_iter_recurse(&interface_dict_iter, &properties_array_iter);
399
400
0
    cras_bt_interface_added(conn, object_path, interface_name,
401
0
                            &properties_array_iter);
402
403
0
    dbus_message_iter_next(&interface_array_iter);
404
0
  }
405
406
0
  return DBUS_HANDLER_RESULT_HANDLED;
407
0
}
408
409
static DBusHandlerResult cras_bt_handle_interfaces_removed(DBusConnection* conn,
410
                                                           DBusMessage* message,
411
0
                                                           void* arg) {
412
0
  DBusMessageIter message_iter, interface_array_iter;
413
0
  const char* object_path;
414
415
0
  if (!dbus_message_is_signal(message, DBUS_INTERFACE_OBJECT_MANAGER,
416
0
                              "InterfacesRemoved")) {
417
0
    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
418
0
  }
419
420
0
  if (!dbus_message_has_signature(message, "oas")) {
421
0
    syslog(LOG_WARNING, "Bad InterfacesRemoved signal received");
422
0
    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
423
0
  }
424
425
0
  dbus_message_iter_init(message, &message_iter);
426
427
0
  dbus_message_iter_get_basic(&message_iter, &object_path);
428
0
  dbus_message_iter_next(&message_iter);
429
430
0
  dbus_message_iter_recurse(&message_iter, &interface_array_iter);
431
432
0
  while (dbus_message_iter_get_arg_type(&interface_array_iter) !=
433
0
         DBUS_TYPE_INVALID) {
434
0
    const char* interface_name;
435
436
0
    dbus_message_iter_get_basic(&interface_array_iter, &interface_name);
437
438
0
    cras_bt_interface_removed(conn, object_path, interface_name);
439
440
0
    dbus_message_iter_next(&interface_array_iter);
441
0
  }
442
443
0
  return DBUS_HANDLER_RESULT_HANDLED;
444
0
}
445
446
static DBusHandlerResult cras_bt_handle_properties_changed(DBusConnection* conn,
447
                                                           DBusMessage* message,
448
0
                                                           void* arg) {
449
0
  DBusMessageIter message_iter, properties_array_iter;
450
0
  DBusMessageIter invalidated_array_iter;
451
0
  const char *object_path, *interface_name;
452
453
0
  if (!dbus_message_is_signal(message, DBUS_INTERFACE_PROPERTIES,
454
0
                              "PropertiesChanged")) {
455
0
    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
456
0
  }
457
458
0
  if (!dbus_message_has_signature(message, "sa{sv}as")) {
459
0
    syslog(LOG_WARNING, "Bad PropertiesChanged signal received");
460
0
    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
461
0
  }
462
463
0
  object_path = dbus_message_get_path(message);
464
465
0
  dbus_message_iter_init(message, &message_iter);
466
467
0
  dbus_message_iter_get_basic(&message_iter, &interface_name);
468
0
  dbus_message_iter_next(&message_iter);
469
470
0
  dbus_message_iter_recurse(&message_iter, &properties_array_iter);
471
0
  dbus_message_iter_next(&message_iter);
472
473
0
  dbus_message_iter_recurse(&message_iter, &invalidated_array_iter);
474
475
0
  cras_bt_update_properties(conn, object_path, interface_name,
476
0
                            &properties_array_iter, &invalidated_array_iter);
477
478
0
  return DBUS_HANDLER_RESULT_HANDLED;
479
0
}
480
481
0
static void cras_bt_start_bluez(struct bt_stack* s) {
482
0
  DBusConnection* conn = s->conn;
483
0
  DBusError dbus_error;
484
485
0
  cras_bt_policy_start();
486
487
0
  dbus_error_init(&dbus_error);
488
489
  // Inform the bus daemon which signals we wish to receive.
490
0
  dbus_bus_add_match(conn,
491
0
                     "type='signal',"
492
0
                     "sender='" DBUS_SERVICE_DBUS
493
0
                     "',"
494
0
                     "interface='" DBUS_INTERFACE_DBUS
495
0
                     "',"
496
0
                     "member='NameOwnerChanged',"
497
0
                     "arg0='" BLUEZ_SERVICE "'",
498
0
                     &dbus_error);
499
0
  if (dbus_error_is_set(&dbus_error)) {
500
0
    goto add_match_error;
501
0
  }
502
503
0
  dbus_bus_add_match(conn,
504
0
                     "type='signal',"
505
0
                     "sender='" BLUEZ_SERVICE
506
0
                     "',"
507
0
                     "interface='" DBUS_INTERFACE_OBJECT_MANAGER
508
0
                     "',"
509
0
                     "member='InterfacesAdded'",
510
0
                     &dbus_error);
511
0
  if (dbus_error_is_set(&dbus_error)) {
512
0
    goto add_match_error;
513
0
  }
514
515
0
  dbus_bus_add_match(conn,
516
0
                     "type='signal',"
517
0
                     "sender='" BLUEZ_SERVICE
518
0
                     "',"
519
0
                     "interface='" DBUS_INTERFACE_OBJECT_MANAGER
520
0
                     "',"
521
0
                     "member='InterfacesRemoved'",
522
0
                     &dbus_error);
523
0
  if (dbus_error_is_set(&dbus_error)) {
524
0
    goto add_match_error;
525
0
  }
526
527
0
  dbus_bus_add_match(conn,
528
0
                     "type='signal',"
529
0
                     "sender='" BLUEZ_SERVICE
530
0
                     "',"
531
0
                     "interface='" DBUS_INTERFACE_PROPERTIES
532
0
                     "',"
533
0
                     "member='PropertiesChanged'",
534
0
                     &dbus_error);
535
0
  if (dbus_error_is_set(&dbus_error)) {
536
0
    goto add_match_error;
537
0
  }
538
539
  // Install filter functions to handle the signals we receive.
540
0
  if (!dbus_connection_add_filter(conn, cras_bt_handle_name_owner_changed, NULL,
541
0
                                  NULL)) {
542
0
    goto add_filter_error;
543
0
  }
544
545
0
  if (!dbus_connection_add_filter(conn, cras_bt_handle_interfaces_added, NULL,
546
0
                                  NULL)) {
547
0
    goto add_filter_error;
548
0
  }
549
550
0
  if (!dbus_connection_add_filter(conn, cras_bt_handle_interfaces_removed, NULL,
551
0
                                  NULL)) {
552
0
    goto add_filter_error;
553
0
  }
554
555
0
  if (!dbus_connection_add_filter(conn, cras_bt_handle_properties_changed, NULL,
556
0
                                  NULL)) {
557
0
    goto add_filter_error;
558
0
  }
559
560
0
  cras_bt_get_managed_objects(conn);
561
562
  /*
563
   * At this point we successfully registered for BlueZ interfaces added
564
   * events.  Let's add the profile implementations locally so they can be
565
   * registered to corresponding interfaces later.
566
   */
567
0
  if (!(s->profile_disable_mask & CRAS_BT_PROFILE_MASK_HFP)) {
568
0
    cras_hfp_ag_profile_create(conn);
569
0
  }
570
0
  cras_telephony_start(conn);
571
0
  if (!(s->profile_disable_mask & CRAS_BT_PROFILE_MASK_A2DP)) {
572
0
    cras_a2dp_endpoint_create(conn);
573
0
  }
574
0
  cras_bt_player_create(conn);
575
576
0
  return;
577
578
0
add_match_error:
579
0
  syslog(LOG_WARNING, "Couldn't setup Bluetooth device monitoring: %s",
580
0
         dbus_error.message);
581
0
  dbus_error_free(&dbus_error);
582
0
  cras_bt_stop(conn);
583
0
  return;
584
585
0
add_filter_error:
586
0
  syslog(LOG_WARNING, "Couldn't setup Bluetooth device monitoring: %s",
587
0
         cras_strerror(ENOMEM));
588
0
  cras_bt_stop(conn);
589
0
  return;
590
0
}
591
592
0
static void cras_bt_stop_bluez(struct bt_stack* s) {
593
0
  DBusConnection* conn = s->conn;
594
0
  cras_bt_policy_stop();
595
596
0
  dbus_bus_remove_match(conn,
597
0
                        "type='signal',"
598
0
                        "sender='" DBUS_SERVICE_DBUS
599
0
                        "',"
600
0
                        "interface='" DBUS_INTERFACE_DBUS
601
0
                        "',"
602
0
                        "member='NameOwnerChanged',"
603
0
                        "arg0='" BLUEZ_SERVICE "'",
604
0
                        NULL);
605
0
  dbus_bus_remove_match(conn,
606
0
                        "type='signal',"
607
0
                        "sender='" BLUEZ_SERVICE
608
0
                        "',"
609
0
                        "interface='" DBUS_INTERFACE_OBJECT_MANAGER
610
0
                        "',"
611
0
                        "member='InterfacesAdded'",
612
0
                        NULL);
613
0
  dbus_bus_remove_match(conn,
614
0
                        "type='signal',"
615
0
                        "sender='" BLUEZ_SERVICE
616
0
                        "',"
617
0
                        "interface='" DBUS_INTERFACE_OBJECT_MANAGER
618
0
                        "',"
619
0
                        "member='InterfacesRemoved'",
620
0
                        NULL);
621
0
  dbus_bus_remove_match(conn,
622
0
                        "type='signal',"
623
0
                        "sender='" BLUEZ_SERVICE
624
0
                        "',"
625
0
                        "interface='" DBUS_INTERFACE_PROPERTIES
626
0
                        "',"
627
0
                        "member='PropertiesChanged'",
628
0
                        NULL);
629
630
0
  dbus_connection_remove_filter(conn, cras_bt_handle_name_owner_changed, NULL);
631
0
  dbus_connection_remove_filter(conn, cras_bt_handle_interfaces_added, NULL);
632
0
  dbus_connection_remove_filter(conn, cras_bt_handle_interfaces_removed, NULL);
633
0
  dbus_connection_remove_filter(conn, cras_bt_handle_properties_changed, NULL);
634
635
  // Unregister all objects we've registered.
636
0
  cras_telephony_stop();
637
0
  cras_bt_player_destroy(conn);
638
0
  cras_bt_unregister_battery_provider(conn);
639
640
  // Clean up the cached objects bluetoothd has told us.
641
0
  cras_bt_reset();
642
643
0
  if (!(s->profile_disable_mask & CRAS_BT_PROFILE_MASK_HFP)) {
644
0
    cras_hfp_ag_profile_destroy(conn);
645
0
  }
646
0
  if (!(s->profile_disable_mask & CRAS_BT_PROFILE_MASK_A2DP)) {
647
0
    cras_a2dp_endpoint_destroy(conn);
648
0
  }
649
0
}
650
651
0
void cras_bt_start(DBusConnection* conn, unsigned profile_disable_mask) {
652
0
  if (btlog == NULL) {
653
0
    btlog = cras_bt_event_log_init();
654
0
  }
655
656
  // Configure the current stack and start it.
657
0
  current->profile_disable_mask = profile_disable_mask;
658
0
  current->conn = conn;
659
0
  current->start(current);
660
0
}
661
0
void cras_bt_stop(DBusConnection* conn) {
662
0
  current->stop(current);
663
0
}
664
665
0
void cras_bt_switch_stack(struct bt_stack* target) {
666
0
  if (!target) {
667
0
    return;
668
0
  }
669
0
  if (current == target) {
670
0
    return;
671
0
  }
672
673
0
  current->stop(current);
674
675
0
  if (btlog) {
676
0
    cras_bt_event_log_deinit(btlog);
677
0
    btlog = cras_bt_event_log_init();
678
0
  }
679
680
  // Inherit the same configuration, swap current then start.
681
0
  target->profile_disable_mask = current->profile_disable_mask;
682
0
  target->conn = current->conn;
683
0
  current = target;
684
0
  current->start(current);
685
0
}
686
687
0
void cras_bt_switch_default_stack() {
688
0
  if (current == &default_stack) {
689
0
    return;
690
0
  }
691
0
  cras_bt_switch_stack(&default_stack);
692
0
}