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