1 use clap::{App, AppSettings, Arg};
2 use dbus_projection::DisconnectWatcher;
3 use dbus_tokio::connection;
4 use futures::future;
5 use nix::sys::signal;
6 use std::error::Error;
7 use std::sync::{Arc, Condvar, Mutex};
8 use std::time::Duration;
9 use tokio::runtime::Builder;
10 use tokio::sync::mpsc::Sender;
11 
12 use bt_topshim::{btif::get_btinterface, topstack};
13 use btstack::{
14     battery_manager::BatteryManager,
15     battery_provider_manager::BatteryProviderManager,
16     battery_service::BatteryService,
17     bluetooth::{Bluetooth, IBluetooth, SigData},
18     bluetooth_admin::BluetoothAdmin,
19     bluetooth_gatt::BluetoothGatt,
20     bluetooth_logging::BluetoothLogging,
21     bluetooth_media::BluetoothMedia,
22     bluetooth_qa::BluetoothQA,
23     dis::DeviceInformation,
24     socket_manager::BluetoothSocketManager,
25     suspend::Suspend,
26     Message, Stack,
27 };
28 
29 mod dbus_arg;
30 mod iface_battery_manager;
31 mod iface_battery_provider_manager;
32 mod iface_bluetooth;
33 mod iface_bluetooth_admin;
34 mod iface_bluetooth_gatt;
35 mod iface_bluetooth_media;
36 mod iface_bluetooth_qa;
37 mod iface_bluetooth_telephony;
38 mod iface_logging;
39 mod interface_manager;
40 
41 const DBUS_SERVICE_NAME: &str = "org.chromium.bluetooth";
42 const ADMIN_SETTINGS_FILE_PATH: &str = "/var/lib/bluetooth/admin_policy.json";
43 // The maximum ACL disconnect timeout is 3.5s defined by BTA_DM_DISABLE_TIMER_MS
44 // and BTA_DM_DISABLE_TIMER_RETRIAL_MS
45 const STACK_TURN_OFF_TIMEOUT_MS: Duration = Duration::from_millis(4000);
46 // Time bt_stack_manager waits for cleanup
47 const STACK_CLEANUP_TIMEOUT_MS: Duration = Duration::from_millis(11000);
48 // Time bt_stack_manager waits for cleanup profiles
49 const STACK_CLEANUP_PROFILES_TIMEOUT_MS: Duration = Duration::from_millis(100);
50 // Extra time to wait before terminating the process
51 const EXTRA_WAIT_BEFORE_KILL_MS: Duration = Duration::from_millis(1000);
52 
53 const INIT_LOGGING_MAX_RETRY: u8 = 3;
54 
55 /// Runs the Bluetooth daemon serving D-Bus IPC.
main() -> Result<(), Box<dyn Error>>56 fn main() -> Result<(), Box<dyn Error>> {
57     let matches = App::new("Bluetooth Adapter Daemon")
58         .setting(AppSettings::TrailingVarArg)
59         .arg(
60             Arg::with_name("hci")
61                 .long("hci")
62                 .value_name("HCI")
63                 .takes_value(true)
64                 .help("The HCI index"),
65         )
66         .arg(
67             Arg::with_name("index")
68                 .long("index")
69                 .value_name("INDEX")
70                 .takes_value(true)
71                 .help("The Virtual index"),
72         )
73         .arg(Arg::with_name("debug").long("debug").short("d").help("Enables debug level logs"))
74         .arg(
75             Arg::with_name("verbose-debug")
76                 .long("verbose-debug")
77                 .short("v")
78                 .help("Enables VERBOSE and additional tags for debug logging. Use with --debug."),
79         )
80         .arg(
81             Arg::with_name("log-output")
82                 .long("log-output")
83                 .takes_value(true)
84                 .possible_values(&["syslog", "stderr"])
85                 .default_value("syslog")
86                 .help("Select log output"),
87         )
88         .get_matches();
89 
90     let is_debug = matches.is_present("debug");
91     let is_verbose_debug = matches.is_present("verbose-debug");
92     let log_output = matches.value_of("log-output").unwrap_or("syslog");
93 
94     let virt_index = matches.value_of("index").map_or(0, |idx| idx.parse::<i32>().unwrap_or(0));
95     let hci_index = matches.value_of("hci").map_or(0, |idx| idx.parse::<i32>().unwrap_or(0));
96 
97     let logging = Arc::new(Mutex::new(Box::new(BluetoothLogging::new(
98         is_debug,
99         is_verbose_debug,
100         log_output,
101     ))));
102     // TODO(b/307171804): Investigate why connecting to unix syslog might fail.
103     // Retry it a few times. Ignore the failure if fails too many times.
104     for _ in 0..INIT_LOGGING_MAX_RETRY {
105         match logging.lock().unwrap().initialize() {
106             Ok(_) => break,
107             Err(_) => continue,
108         }
109     }
110 
111     let (tx, rx) = Stack::create_channel();
112     let (api_tx, api_rx) = interface_manager::InterfaceManager::create_channel();
113     let sig_notifier = Arc::new(SigData {
114         enabled: Mutex::new(false),
115         enabled_notify: Condvar::new(),
116         thread_attached: Mutex::new(false),
117         thread_notify: Condvar::new(),
118     });
119 
120     // This needs to be built before any |topstack::get_runtime()| call!
121     let bt_sock_mgr_runtime = Arc::new(
122         Builder::new_multi_thread()
123             .worker_threads(1)
124             .max_blocking_threads(1)
125             .enable_all()
126             .build()
127             .expect("Failed to make socket runtime."),
128     );
129 
130     topstack::get_runtime().block_on(async {
131         // Connect to D-Bus system bus.
132         let (resource, conn) = connection::new_system_sync()?;
133 
134         // The `resource` is a task that should be spawned onto a tokio compatible
135         // reactor ASAP. If the resource ever finishes, we lost connection to D-Bus.
136         let conn_join_handle = tokio::spawn(async {
137             let err = resource.await;
138             panic!("Lost connection to D-Bus: {}", err);
139         });
140 
141         // Request a service name and quit if not able to.
142         conn.request_name(DBUS_SERVICE_NAME, false, true, false).await?;
143 
144         // Install SIGTERM handler so that we can properly shutdown
145         *SIG_DATA.lock().unwrap() = Some((tx.clone(), sig_notifier.clone()));
146         let sig_action_term = signal::SigAction::new(
147             signal::SigHandler::Handler(handle_sigterm),
148             signal::SaFlags::empty(),
149             signal::SigSet::empty(),
150         );
151         unsafe {
152             signal::sigaction(signal::SIGTERM, &sig_action_term).unwrap();
153         }
154 
155         // Construct btstack profiles.
156         let intf = Arc::new(Mutex::new(get_btinterface()));
157         let bluetooth = Arc::new(Mutex::new(Box::new(Bluetooth::new(
158             virt_index,
159             hci_index,
160             tx.clone(),
161             api_tx.clone(),
162             sig_notifier.clone(),
163             intf.clone(),
164         ))));
165         let bluetooth_qa = Arc::new(Mutex::new(Box::new(BluetoothQA::new(tx.clone()))));
166         let battery_provider_manager =
167             Arc::new(Mutex::new(Box::new(BatteryProviderManager::new(tx.clone()))));
168 
169         bluetooth.lock().unwrap().init(hci_index);
170         bluetooth.lock().unwrap().enable();
171 
172         // These constructions require |intf| to be already init-ed.
173         let bt_sock_mgr = Arc::new(Mutex::new(Box::new(BluetoothSocketManager::new(
174             tx.clone(),
175             bt_sock_mgr_runtime,
176             intf.clone(),
177             bluetooth.clone(),
178         ))));
179         let bluetooth_media = Arc::new(Mutex::new(Box::new(BluetoothMedia::new(
180             tx.clone(),
181             api_tx.clone(),
182             intf.clone(),
183             bluetooth.clone(),
184             battery_provider_manager.clone(),
185         ))));
186         let bluetooth_gatt =
187             Arc::new(Mutex::new(Box::new(BluetoothGatt::new(intf.clone(), tx.clone()))));
188 
189         // These constructions don't need |intf| to be init-ed, but just depend on those who need.
190         let bluetooth_admin = Arc::new(Mutex::new(Box::new(BluetoothAdmin::new(
191             String::from(ADMIN_SETTINGS_FILE_PATH),
192             tx.clone(),
193             bluetooth.clone(),
194             bluetooth_media.clone(),
195             bt_sock_mgr.clone(),
196         ))));
197         let suspend = Arc::new(Mutex::new(Box::new(Suspend::new(
198             bluetooth.clone(),
199             intf.clone(),
200             bluetooth_gatt.clone(),
201             bluetooth_media.clone(),
202             tx.clone(),
203         ))));
204         let battery_service = Arc::new(Mutex::new(Box::new(BatteryService::new(
205             bluetooth_gatt.clone(),
206             battery_provider_manager.clone(),
207             tx.clone(),
208             api_tx.clone(),
209         ))));
210         let battery_manager = Arc::new(Mutex::new(Box::new(BatteryManager::new(
211             battery_provider_manager.clone(),
212             tx.clone(),
213         ))));
214         let dis = Arc::new(Mutex::new(Box::new(DeviceInformation::new(
215             bluetooth_gatt.clone(),
216             tx.clone(),
217         ))));
218 
219         // Run the stack main dispatch loop.
220         topstack::get_runtime().spawn(Stack::dispatch(
221             rx,
222             tx.clone(),
223             api_tx.clone(),
224             bluetooth.clone(),
225             bluetooth_gatt.clone(),
226             battery_service.clone(),
227             battery_manager.clone(),
228             battery_provider_manager.clone(),
229             bluetooth_media.clone(),
230             suspend.clone(),
231             bt_sock_mgr.clone(),
232             bluetooth_admin.clone(),
233             dis.clone(),
234             bluetooth_qa.clone(),
235         ));
236 
237         // Set up the disconnect watcher to monitor client disconnects.
238         let mut disconnect_watcher = DisconnectWatcher::new();
239         disconnect_watcher.setup_watch(conn.clone()).await;
240         let disconnect_watcher = Arc::new(Mutex::new(disconnect_watcher));
241 
242         tokio::spawn(interface_manager::InterfaceManager::dispatch(
243             api_rx,
244             tx.clone(),
245             virt_index,
246             conn,
247             conn_join_handle,
248             disconnect_watcher.clone(),
249             bluetooth.clone(),
250             bluetooth_admin.clone(),
251             bluetooth_gatt.clone(),
252             battery_manager.clone(),
253             battery_provider_manager.clone(),
254             bluetooth_media.clone(),
255             bluetooth_qa.clone(),
256             bt_sock_mgr.clone(),
257             suspend.clone(),
258             logging.clone(),
259         ));
260 
261         // Serve clients forever.
262         future::pending::<()>().await;
263         unreachable!()
264     })
265 }
266 
267 /// Data needed for signal handling.
268 static SIG_DATA: Mutex<Option<(Sender<Message>, Arc<SigData>)>> = Mutex::new(None);
269 
handle_sigterm(_signum: i32)270 extern "C" fn handle_sigterm(_signum: i32) {
271     let guard = SIG_DATA.lock().unwrap();
272     if let Some((tx, notifier)) = guard.as_ref() {
273         log::debug!("Handling SIGTERM by disabling the adapter!");
274         let txl = tx.clone();
275         topstack::get_runtime().spawn(async move {
276             // Send the shutdown message here.
277             let _ = txl.send(Message::InterfaceShutdown).await;
278         });
279 
280         let guard = notifier.enabled.lock().unwrap();
281         if *guard {
282             log::debug!("Waiting for stack to turn off for {:?}", STACK_TURN_OFF_TIMEOUT_MS);
283             let _ = notifier.enabled_notify.wait_timeout(guard, STACK_TURN_OFF_TIMEOUT_MS);
284         }
285 
286         log::debug!("SIGTERM cleaning up the stack.");
287         let txl = tx.clone();
288         topstack::get_runtime().spawn(async move {
289             // Clean up the profiles first as some of them might require main thread to clean up.
290             let _ = txl.send(Message::CleanupProfiles).await;
291             // Currently there is no good way to know when the profile is cleaned.
292             // Simply add a small delay here.
293             tokio::time::sleep(STACK_CLEANUP_PROFILES_TIMEOUT_MS).await;
294             // Send the cleanup message to clean up the main thread.
295             let _ = txl.send(Message::Cleanup).await;
296         });
297 
298         let guard = notifier.thread_attached.lock().unwrap();
299         if *guard {
300             log::debug!("Waiting for stack to clean up for {:?}", STACK_CLEANUP_TIMEOUT_MS);
301             let _ = notifier.thread_notify.wait_timeout(guard, STACK_CLEANUP_TIMEOUT_MS);
302         }
303 
304         // Extra delay to give the rest of the cleanup processes some time to finish after
305         // finishing btif cleanup.
306         std::thread::sleep(EXTRA_WAIT_BEFORE_KILL_MS);
307     }
308 
309     log::debug!("Sigterm completed");
310     std::process::exit(0);
311 }
312