1 use btstack::bluetooth_qa::BluetoothQA;
2 use clap::{App, AppSettings, Arg};
3 use dbus::{channel::MatchingReceiver, message::MatchRule};
4 use dbus_crossroads::Crossroads;
5 use dbus_tokio::connection;
6 use futures::future;
7 use lazy_static::lazy_static;
8 use nix::sys::signal;
9 use std::error::Error;
10 use std::sync::{Arc, Condvar, Mutex};
11 use std::time::Duration;
12 use tokio::time;
13
14 // Necessary to link right entries.
15 #[allow(unused_imports)]
16 use bt_shim;
17
18 use bt_topshim::{btif::get_btinterface, topstack};
19 use btstack::{
20 battery_manager::BatteryManager,
21 battery_provider_manager::BatteryProviderManager,
22 battery_service::BatteryService,
23 bluetooth::{get_bt_dispatcher, Bluetooth, IBluetooth},
24 bluetooth_admin::BluetoothAdmin,
25 bluetooth_gatt::BluetoothGatt,
26 bluetooth_logging::BluetoothLogging,
27 bluetooth_media::BluetoothMedia,
28 dis::DeviceInformation,
29 socket_manager::BluetoothSocketManager,
30 suspend::Suspend,
31 Message, Stack,
32 };
33 use dbus_projection::DisconnectWatcher;
34 use tokio::sync::mpsc::Sender;
35
36 mod dbus_arg;
37 mod iface_battery_manager;
38 mod iface_battery_provider_manager;
39 mod iface_bluetooth;
40 mod iface_bluetooth_admin;
41 mod iface_bluetooth_gatt;
42 mod iface_bluetooth_media;
43 mod iface_bluetooth_qa;
44 mod iface_bluetooth_telephony;
45 mod iface_logging;
46
47 const DBUS_SERVICE_NAME: &str = "org.chromium.bluetooth";
48 const ADMIN_SETTINGS_FILE_PATH: &str = "/var/lib/bluetooth/admin_policy.json";
49 // The maximum ACL disconnect timeout is 3.5s defined by BTA_DM_DISABLE_TIMER_MS
50 // and BTA_DM_DISABLE_TIMER_RETRIAL_MS
51 const STACK_TURN_OFF_TIMEOUT_MS: Duration = Duration::from_millis(4000);
52
53 const VERBOSE_ONLY_LOG_TAGS: &[&str] = &[
54 "bt_bta_av", // AV apis
55 "btm_sco", // SCO data path logs
56 "l2c_csm", // L2CAP state machine
57 "l2c_link", // L2CAP link layer logs
58 "sco_hci", // SCO over HCI
59 "uipc", // Userspace IPC implementation
60 ];
61
make_object_name(idx: i32, name: &str) -> String62 fn make_object_name(idx: i32, name: &str) -> String {
63 String::from(format!("/org/chromium/bluetooth/hci{}/{}", idx, name))
64 }
65
66 /// Runs the Bluetooth daemon serving D-Bus IPC.
main() -> Result<(), Box<dyn Error>>67 fn main() -> Result<(), Box<dyn Error>> {
68 let matches = App::new("Bluetooth Adapter Daemon")
69 // Allows multiple INIT_ flags to be given at the end of the arguments.
70 .setting(AppSettings::TrailingVarArg)
71 .arg(
72 Arg::with_name("hci")
73 .long("hci")
74 .value_name("HCI")
75 .takes_value(true)
76 .help("The HCI index"),
77 )
78 .arg(
79 Arg::with_name("index")
80 .long("index")
81 .value_name("INDEX")
82 .takes_value(true)
83 .help("The Virtual index"),
84 )
85 .arg(Arg::with_name("debug").long("debug").short("d").help("Enables debug level logs"))
86 .arg(
87 Arg::with_name("verbose-debug")
88 .long("verbose-debug")
89 .short("v")
90 .help("Enables VERBOSE and additional tags for debug logging. Use with --debug."),
91 )
92 .arg(Arg::from_usage("[init-flags] 'Fluoride INIT_ flags'").multiple(true))
93 .arg(
94 Arg::with_name("log-output")
95 .long("log-output")
96 .takes_value(true)
97 .possible_values(&["syslog", "stderr"])
98 .default_value("syslog")
99 .help("Select log output"),
100 )
101 .get_matches();
102
103 let is_debug = matches.is_present("debug");
104 let is_verbose_debug = matches.is_present("verbose-debug");
105 let log_output = matches.value_of("log-output").unwrap_or("syslog");
106
107 let adapter_index = matches.value_of("index").map_or(0, |idx| idx.parse::<i32>().unwrap_or(0));
108 let hci_index = matches.value_of("hci").map_or(0, |idx| idx.parse::<i32>().unwrap_or(0));
109
110 // The remaining flags are passed down to Fluoride as is.
111 let mut init_flags: Vec<String> = match matches.values_of("init-flags") {
112 Some(args) => args.map(|s| String::from(s)).collect(),
113 None => vec![],
114 };
115
116 // Set GD debug flag if debug is enabled.
117 if is_debug {
118 // Limit tags if verbose debug logging isn't enabled.
119 if !is_verbose_debug {
120 init_flags.push(format!(
121 "INIT_logging_debug_disabled_for_tags={}",
122 VERBOSE_ONLY_LOG_TAGS.join(",")
123 ));
124 init_flags.push(String::from("INIT_default_log_level_str=LOG_DEBUG"));
125 } else {
126 init_flags.push(String::from("INIT_default_log_level_str=LOG_VERBOSE"));
127 }
128 }
129
130 // Forward --hci to Fluoride.
131 init_flags.push(format!("--hci={}", hci_index));
132 let logging = Arc::new(Mutex::new(Box::new(BluetoothLogging::new(is_debug, log_output))));
133
134 // Always treat discovery as classic only
135 init_flags.push(String::from("INIT_classic_discovery_only=true"));
136
137 let (tx, rx) = Stack::create_channel();
138 let sig_notifier = Arc::new((Mutex::new(false), Condvar::new()));
139
140 let intf = Arc::new(Mutex::new(get_btinterface().unwrap()));
141 let bluetooth_gatt =
142 Arc::new(Mutex::new(Box::new(BluetoothGatt::new(intf.clone(), tx.clone()))));
143 let battery_provider_manager =
144 Arc::new(Mutex::new(Box::new(BatteryProviderManager::new(tx.clone()))));
145 let battery_service = Arc::new(Mutex::new(Box::new(BatteryService::new(
146 bluetooth_gatt.clone(),
147 battery_provider_manager.clone(),
148 tx.clone(),
149 ))));
150 let battery_manager = Arc::new(Mutex::new(Box::new(BatteryManager::new(
151 battery_provider_manager.clone(),
152 tx.clone(),
153 ))));
154 let bluetooth_media = Arc::new(Mutex::new(Box::new(BluetoothMedia::new(
155 tx.clone(),
156 intf.clone(),
157 battery_provider_manager.clone(),
158 ))));
159 let bluetooth_admin = Arc::new(Mutex::new(Box::new(BluetoothAdmin::new(
160 String::from(ADMIN_SETTINGS_FILE_PATH),
161 tx.clone(),
162 ))));
163 let bluetooth = Arc::new(Mutex::new(Box::new(Bluetooth::new(
164 adapter_index,
165 tx.clone(),
166 sig_notifier.clone(),
167 intf.clone(),
168 bluetooth_admin.clone(),
169 bluetooth_gatt.clone(),
170 bluetooth_media.clone(),
171 ))));
172 let suspend = Arc::new(Mutex::new(Box::new(Suspend::new(
173 bluetooth.clone(),
174 intf.clone(),
175 bluetooth_gatt.clone(),
176 bluetooth_media.clone(),
177 tx.clone(),
178 ))));
179 let bt_sock_mgr = Arc::new(Mutex::new(Box::new(BluetoothSocketManager::new(
180 tx.clone(),
181 bluetooth_admin.clone(),
182 ))));
183 let bluetooth_qa = Arc::new(Mutex::new(Box::new(BluetoothQA::new(tx.clone()))));
184
185 let dis =
186 Arc::new(Mutex::new(Box::new(DeviceInformation::new(bluetooth_gatt.clone(), tx.clone()))));
187
188 topstack::get_runtime().block_on(async {
189 // Connect to D-Bus system bus.
190 let (resource, conn) = connection::new_system_sync()?;
191
192 // The `resource` is a task that should be spawned onto a tokio compatible
193 // reactor ASAP. If the resource ever finishes, we lost connection to D-Bus.
194 tokio::spawn(async {
195 let err = resource.await;
196 panic!("Lost connection to D-Bus: {}", err);
197 });
198
199 // Request a service name and quit if not able to.
200 conn.request_name(DBUS_SERVICE_NAME, false, true, false).await?;
201
202 // Prepare D-Bus interfaces.
203 let cr = Arc::new(Mutex::new(Crossroads::new()));
204 cr.lock().unwrap().set_async_support(Some((
205 conn.clone(),
206 Box::new(|x| {
207 tokio::spawn(x);
208 }),
209 )));
210
211 // Announce the exported adapter objects so that clients can properly detect the readiness
212 // of the adapter APIs.
213 cr.lock().unwrap().set_object_manager_support(Some(conn.clone()));
214 let object_manager = cr.lock().unwrap().object_manager();
215 cr.lock().unwrap().insert("/", &[object_manager], {});
216
217 // Run the stack main dispatch loop.
218 topstack::get_runtime().spawn(Stack::dispatch(
219 rx,
220 bluetooth.clone(),
221 bluetooth_gatt.clone(),
222 battery_service.clone(),
223 battery_manager.clone(),
224 battery_provider_manager.clone(),
225 bluetooth_media.clone(),
226 suspend.clone(),
227 bt_sock_mgr.clone(),
228 bluetooth_admin.clone(),
229 dis.clone(),
230 bluetooth_qa.clone(),
231 ));
232
233 // Set up the disconnect watcher to monitor client disconnects.
234 let disconnect_watcher = Arc::new(Mutex::new(DisconnectWatcher::new()));
235 disconnect_watcher.lock().unwrap().setup_watch(conn.clone()).await;
236
237 // Set up handling of D-Bus methods. This must be done before exporting interfaces so that
238 // clients that rely on InterfacesAdded signal can rely on us being ready to handle methods
239 // on those exported interfaces.
240 let cr_clone = cr.clone();
241 conn.start_receive(
242 MatchRule::new_method_call(),
243 Box::new(move |msg, conn| {
244 cr_clone.lock().unwrap().handle_message(msg, conn).unwrap();
245 true
246 }),
247 );
248
249 // Register D-Bus method handlers of IBluetooth.
250 let adapter_iface = iface_bluetooth::export_bluetooth_dbus_intf(
251 conn.clone(),
252 &mut cr.lock().unwrap(),
253 disconnect_watcher.clone(),
254 );
255 let qa_iface = iface_bluetooth_qa::export_bluetooth_qa_dbus_intf(
256 conn.clone(),
257 &mut cr.lock().unwrap(),
258 disconnect_watcher.clone(),
259 );
260 let qa_legacy_iface = iface_bluetooth::export_bluetooth_qa_legacy_dbus_intf(
261 conn.clone(),
262 &mut cr.lock().unwrap(),
263 disconnect_watcher.clone(),
264 );
265 let socket_mgr_iface = iface_bluetooth::export_socket_mgr_intf(
266 conn.clone(),
267 &mut cr.lock().unwrap(),
268 disconnect_watcher.clone(),
269 );
270 let suspend_iface = iface_bluetooth::export_suspend_dbus_intf(
271 conn.clone(),
272 &mut cr.lock().unwrap(),
273 disconnect_watcher.clone(),
274 );
275 let logging_iface = iface_logging::export_bluetooth_logging_dbus_intf(
276 conn.clone(),
277 &mut cr.lock().unwrap(),
278 disconnect_watcher.clone(),
279 );
280
281 // Register D-Bus method handlers of IBluetoothGatt.
282 let gatt_iface = iface_bluetooth_gatt::export_bluetooth_gatt_dbus_intf(
283 conn.clone(),
284 &mut cr.lock().unwrap(),
285 disconnect_watcher.clone(),
286 );
287
288 let media_iface = iface_bluetooth_media::export_bluetooth_media_dbus_intf(
289 conn.clone(),
290 &mut cr.lock().unwrap(),
291 disconnect_watcher.clone(),
292 );
293
294 let telephony_iface = iface_bluetooth_telephony::export_bluetooth_telephony_dbus_intf(
295 conn.clone(),
296 &mut cr.lock().unwrap(),
297 disconnect_watcher.clone(),
298 );
299
300 let battery_provider_manager_iface =
301 iface_battery_provider_manager::export_battery_provider_manager_dbus_intf(
302 conn.clone(),
303 &mut cr.lock().unwrap(),
304 disconnect_watcher.clone(),
305 );
306
307 let battery_manager_iface = iface_battery_manager::export_battery_manager_dbus_intf(
308 conn.clone(),
309 &mut cr.lock().unwrap(),
310 disconnect_watcher.clone(),
311 );
312
313 let admin_iface = iface_bluetooth_admin::export_bluetooth_admin_dbus_intf(
314 conn.clone(),
315 &mut cr.lock().unwrap(),
316 disconnect_watcher.clone(),
317 );
318
319 // Create mixin object for Bluetooth + Suspend interfaces.
320 let mixin = Box::new(iface_bluetooth::BluetoothMixin {
321 adapter: bluetooth.clone(),
322 qa: bluetooth.clone(),
323 suspend: suspend.clone(),
324 socket_mgr: bt_sock_mgr.clone(),
325 });
326
327 cr.lock().unwrap().insert(
328 make_object_name(adapter_index, "adapter"),
329 &[adapter_iface, qa_legacy_iface, socket_mgr_iface, suspend_iface],
330 mixin,
331 );
332
333 cr.lock().unwrap().insert(
334 make_object_name(adapter_index, "gatt"),
335 &[gatt_iface],
336 bluetooth_gatt.clone(),
337 );
338
339 cr.lock().unwrap().insert(
340 make_object_name(adapter_index, "media"),
341 &[media_iface],
342 bluetooth_media.clone(),
343 );
344
345 cr.lock().unwrap().insert(
346 make_object_name(adapter_index, "telephony"),
347 &[telephony_iface],
348 bluetooth_media.clone(),
349 );
350
351 cr.lock().unwrap().insert(
352 make_object_name(adapter_index, "battery_provider_manager"),
353 &[battery_provider_manager_iface],
354 battery_provider_manager.clone(),
355 );
356
357 cr.lock().unwrap().insert(
358 make_object_name(adapter_index, "battery_manager"),
359 &[battery_manager_iface],
360 battery_manager.clone(),
361 );
362
363 cr.lock().unwrap().insert(
364 make_object_name(adapter_index, "admin"),
365 &[admin_iface],
366 bluetooth_admin.clone(),
367 );
368
369 cr.lock().unwrap().insert(
370 make_object_name(adapter_index, "logging"),
371 &[logging_iface],
372 logging.clone(),
373 );
374
375 cr.lock().unwrap().insert(
376 make_object_name(adapter_index, "qa"),
377 &[qa_iface],
378 bluetooth_qa.clone(),
379 );
380
381 // Hold locks and initialize all interfaces. This must be done AFTER DBus is
382 // initialized so DBus can properly enforce user policies.
383 {
384 intf.lock().unwrap().initialize(get_bt_dispatcher(tx.clone()), init_flags);
385
386 let adapter = bluetooth.clone();
387 bluetooth_media.lock().unwrap().set_adapter(adapter.clone());
388 bluetooth_admin.lock().unwrap().set_adapter(adapter.clone());
389
390 let mut bluetooth = bluetooth.lock().unwrap();
391 bluetooth.init_profiles();
392 bluetooth.enable();
393
394 bluetooth_gatt.lock().unwrap().init_profiles(tx.clone(), adapter.clone());
395 // TODO(b/247093293): Gatt topshim api is only usable some
396 // time after init. Investigate why this delay is needed
397 // and make it a blocking part of init before removing
398 // this.
399 tokio::spawn(async move {
400 time::sleep(Duration::from_millis(500)).await;
401 battery_service.lock().unwrap().init();
402 });
403 bt_sock_mgr.lock().unwrap().initialize(intf.clone());
404
405 // Install SIGTERM handler so that we can properly shutdown
406 *SIG_DATA.lock().unwrap() = Some((tx.clone(), sig_notifier.clone()));
407
408 let sig_action = signal::SigAction::new(
409 signal::SigHandler::Handler(handle_sigterm),
410 signal::SaFlags::empty(),
411 signal::SigSet::empty(),
412 );
413
414 unsafe {
415 signal::sigaction(signal::SIGTERM, &sig_action).unwrap();
416 }
417 }
418
419 // Initialize the bluetooth_qa
420 bluetooth.lock().unwrap().cache_discoverable_mode_into_qa();
421
422 // Serve clients forever.
423 future::pending::<()>().await;
424 unreachable!()
425 })
426 }
427
428 lazy_static! {
429 /// Data needed for signal handling.
430 static ref SIG_DATA: Mutex<Option<(Sender<Message>, Arc<(Mutex<bool>, Condvar)>)>> = Mutex::new(None);
431 }
432
handle_sigterm(_signum: i32)433 extern "C" fn handle_sigterm(_signum: i32) {
434 let guard = SIG_DATA.lock().unwrap();
435 if let Some((tx, notifier)) = guard.as_ref() {
436 log::debug!("Handling SIGTERM by disabling the adapter!");
437 let txl = tx.clone();
438 tokio::spawn(async move {
439 // Send the shutdown message here.
440 let _ = txl.send(Message::Shutdown).await;
441 });
442
443 let guard = notifier.0.lock().unwrap();
444 if *guard {
445 log::debug!("Waiting for stack to turn off for {:?}", STACK_TURN_OFF_TIMEOUT_MS);
446 let _ = notifier.1.wait_timeout(guard, STACK_TURN_OFF_TIMEOUT_MS);
447 }
448 }
449
450 log::debug!("Sigterm completed");
451 std::process::exit(0);
452 }
453