1 //! Floss Bluetooth stack.
2 //!
3 //! This crate provides the API implementation of the Fluoride/GD Bluetooth
4 //! stack, independent of any RPC projection.
5 
6 pub mod battery_manager;
7 pub mod battery_provider_manager;
8 pub mod battery_service;
9 pub mod bluetooth;
10 pub mod bluetooth_admin;
11 pub mod bluetooth_adv;
12 pub mod bluetooth_gatt;
13 pub mod bluetooth_logging;
14 pub mod bluetooth_media;
15 pub mod bluetooth_qa;
16 pub mod callbacks;
17 pub mod dis;
18 pub mod socket_manager;
19 pub mod suspend;
20 pub mod uuid;
21 
22 use bluetooth_qa::{BluetoothQA, IBluetoothQA};
23 use log::{debug, info};
24 use num_derive::{FromPrimitive, ToPrimitive};
25 use std::sync::{Arc, Mutex};
26 use tokio::sync::mpsc::channel;
27 use tokio::sync::mpsc::{Receiver, Sender};
28 use tokio::time::{sleep, Duration};
29 
30 use crate::battery_manager::{BatteryManager, BatterySet};
31 use crate::battery_provider_manager::BatteryProviderManager;
32 use crate::battery_service::{
33     BatteryService, BatteryServiceActions, BATTERY_SERVICE_GATT_CLIENT_APP_ID,
34 };
35 use crate::bluetooth::{
36     dispatch_base_callbacks, dispatch_hid_host_callbacks, dispatch_sdp_callbacks, AdapterActions,
37     Bluetooth, BluetoothDevice, IBluetooth,
38 };
39 use crate::bluetooth_admin::{AdminActions, BluetoothAdmin, IBluetoothAdmin};
40 use crate::bluetooth_adv::{dispatch_le_adv_callbacks, AdvertiserActions};
41 use crate::bluetooth_gatt::{
42     dispatch_gatt_client_callbacks, dispatch_gatt_server_callbacks, dispatch_le_scanner_callbacks,
43     dispatch_le_scanner_inband_callbacks, BluetoothGatt, GattActions,
44 };
45 use crate::bluetooth_media::{BluetoothMedia, IBluetoothMedia, MediaActions};
46 use crate::dis::{DeviceInformation, ServiceCallbacks};
47 use crate::socket_manager::{BluetoothSocketManager, SocketActions};
48 use crate::suspend::Suspend;
49 use bt_topshim::{
50     btif::{BaseCallbacks, BtAclState, BtBondState, BtTransport, DisplayAddress, RawAddress, Uuid},
51     profiles::{
52         a2dp::A2dpCallbacks,
53         avrcp::AvrcpCallbacks,
54         csis::CsisClientCallbacks,
55         gatt::GattAdvCallbacks,
56         gatt::GattAdvInbandCallbacks,
57         gatt::GattClientCallbacks,
58         gatt::GattScannerCallbacks,
59         gatt::GattScannerInbandCallbacks,
60         gatt::GattServerCallbacks,
61         hfp::HfpCallbacks,
62         hid_host::{BthhReportType, HHCallbacks},
63         le_audio::LeAudioClientCallbacks,
64         sdp::SdpCallbacks,
65         vc::VolumeControlCallbacks,
66     },
67 };
68 
69 /// Message types that are sent to the stack main dispatch loop.
70 pub enum Message {
71     /// Remove the DBus API. Call it before other AdapterShutdown.
72     InterfaceShutdown,
73     /// Disable the adapter by calling btif disable.
74     AdapterShutdown,
75     /// Clean up the adapter by calling btif cleanup.
76     Cleanup,
77     /// Clean up the media by calling profile cleanup.
78     CleanupProfiles,
79 
80     // Adapter is enabled and ready.
81     AdapterReady,
82 
83     // Callbacks from libbluetooth
84     A2dp(A2dpCallbacks),
85     Avrcp(AvrcpCallbacks),
86     Base(BaseCallbacks),
87     GattClient(GattClientCallbacks),
88     GattServer(GattServerCallbacks),
89     LeAudioClient(LeAudioClientCallbacks),
90     LeScanner(GattScannerCallbacks),
91     LeScannerInband(GattScannerInbandCallbacks),
92     LeAdvInband(GattAdvInbandCallbacks),
93     LeAdv(GattAdvCallbacks),
94     HidHost(HHCallbacks),
95     Hfp(HfpCallbacks),
96     Sdp(SdpCallbacks),
97     VolumeControl(VolumeControlCallbacks),
98     CsisClient(CsisClientCallbacks),
99     CreateBondWithRetry(BluetoothDevice, BtTransport, u32, Duration),
100 
101     // Actions within the stack
102     Media(MediaActions),
103     MediaCallbackDisconnected(u32),
104     TelephonyCallbackDisconnected(u32),
105 
106     // Client callback disconnections
107     AdapterCallbackDisconnected(u32),
108     ConnectionCallbackDisconnected(u32),
109 
110     AdapterActions(AdapterActions),
111 
112     // Follows IBluetooth's on_device_(dis)connected and bond_state callbacks
113     // but doesn't require depending on Bluetooth.
114     // Params: Address, BR/EDR ACL state, BLE ACL state, bond state, transport
115     OnDeviceConnectionOrBondStateChanged(
116         RawAddress,
117         BtAclState,
118         BtAclState,
119         BtBondState,
120         BtTransport,
121     ),
122 
123     // Suspend related
124     SuspendCallbackRegistered(u32),
125     SuspendCallbackDisconnected(u32),
126     SuspendReady(i32),
127     ResumeReady(i32),
128     AudioReconnectOnResumeComplete,
129 
130     // Scanner related
131     ScannerCallbackDisconnected(u32),
132 
133     // Advertising related
134     AdvertiserCallbackDisconnected(u32),
135     AdvertiserActions(AdvertiserActions),
136 
137     SocketManagerActions(SocketActions),
138     SocketManagerCallbackDisconnected(u32),
139 
140     // Battery related
141     BatteryProviderManagerCallbackDisconnected(u32),
142     BatteryProviderManagerBatteryUpdated(RawAddress, BatterySet),
143     BatteryServiceCallbackDisconnected(u32),
144     BatteryService(BatteryServiceActions),
145     BatteryServiceRefresh,
146     BatteryManagerCallbackDisconnected(u32),
147 
148     GattActions(GattActions),
149     GattClientCallbackDisconnected(u32),
150     GattServerCallbackDisconnected(u32),
151 
152     // Admin policy related
153     AdminCallbackDisconnected(u32),
154     AdminActions(AdminActions),
155     HidHostEnable,
156 
157     // Dis callbacks
158     Dis(ServiceCallbacks),
159 
160     // Device removal
161     DisconnectDevice(BluetoothDevice),
162 
163     // Qualification Only
164     QaCallbackDisconnected(u32),
165     QaAddMediaPlayer(String, bool),
166     QaRfcommSendMsc(u8, RawAddress),
167     QaFetchDiscoverableMode,
168     QaFetchConnectable,
169     QaSetConnectable(bool),
170     QaFetchAlias,
171     QaGetHidReport(RawAddress, BthhReportType, u8),
172     QaSetHidReport(RawAddress, BthhReportType, String),
173     QaSendHidData(RawAddress, String),
174     QaSendHidVirtualUnplug(RawAddress),
175 
176     // UHid callbacks
177     UHidHfpOutputCallback(RawAddress, u8, u8),
178     UHidTelephonyUseCallback(RawAddress, bool),
179 
180     // This message is sent when either HID, media, or GATT client, is disconnected.
181     // Note that meida sends this when the profiles are disconnected as a whole, that is, it will
182     // not be called when AVRCP is disconnected but not A2DP, as an example.
183     ProfileDisconnected(RawAddress),
184 }
185 
186 /// Returns a callable object that dispatches a BTIF callback to Message
187 ///
188 /// The returned object would make sure the order of how the callbacks arrive the same as how they
189 /// goes to Message.
190 ///
191 /// Example
192 /// ```ignore
193 /// // Create a dispatcher in btstack
194 /// let gatt_client_callbacks_dispatcher = topshim::gatt::GattClientCallbacksDispatcher {
195 ///     dispatch: make_message_dispatcher(tx.clone(), Message::GattClient),
196 /// };
197 ///
198 /// // Register the dispatcher to topshim
199 /// bt_topshim::topstack::get_dispatchers()
200 ///     .lock()
201 ///     .unwrap()
202 ///     .set::<topshim::gatt::GattClientCb>(Arc::new(Mutex::new(gatt_client_callbacks_dispatcher)))
203 /// ```
make_message_dispatcher<F, Cb>(tx: Sender<Message>, f: F) -> Box<dyn Fn(Cb) + Send> where Cb: Send + 'static, F: Fn(Cb) -> Message + Send + Copy + 'static,204 pub(crate) fn make_message_dispatcher<F, Cb>(tx: Sender<Message>, f: F) -> Box<dyn Fn(Cb) + Send>
205 where
206     Cb: Send + 'static,
207     F: Fn(Cb) -> Message + Send + Copy + 'static,
208 {
209     let async_mutex = Arc::new(tokio::sync::Mutex::new(()));
210     let dispatch_queue = Arc::new(Mutex::new(std::collections::VecDeque::new()));
211 
212     Box::new(move |cb| {
213         let tx = tx.clone();
214         let async_mutex = async_mutex.clone();
215         let dispatch_queue = dispatch_queue.clone();
216         // Enqueue the callbacks at the synchronized block to ensure the order.
217         dispatch_queue.lock().unwrap().push_back(cb);
218         bt_topshim::topstack::get_runtime().spawn(async move {
219             // Acquire the lock first to ensure |pop_front| and |tx.send| not
220             // interrupted by the other async threads.
221             let _guard = async_mutex.lock().await;
222             // Consume exactly one callback.
223             let cb = dispatch_queue.lock().unwrap().pop_front().unwrap();
224             let _ = tx.send(f(cb)).await;
225         });
226     })
227 }
228 
229 pub enum BluetoothAPI {
230     Adapter,
231     Admin,
232     Battery,
233     Media,
234     Gatt,
235 }
236 
237 /// Message types that are sent to the InterfaceManager's dispatch loop.
238 pub enum APIMessage {
239     /// Indicates a subcomponent is ready to receive DBus messages.
240     IsReady(BluetoothAPI),
241     /// Indicates bluetooth is shutting down, so we remove all DBus endpoints.
242     ShutDown,
243 }
244 
245 /// Represents suspend mode of a module.
246 ///
247 /// Being in suspend mode means that the module pauses some activities if required for suspend and
248 /// some subsequent API calls will be blocked with a retryable error.
249 #[derive(FromPrimitive, ToPrimitive, Debug, PartialEq, Clone)]
250 pub enum SuspendMode {
251     Normal = 0,
252     Suspending = 1,
253     Suspended = 2,
254     Resuming = 3,
255 }
256 
257 /// Umbrella class for the Bluetooth stack.
258 pub struct Stack {}
259 
260 impl Stack {
261     /// Creates an mpsc channel for passing messages to the main dispatch loop.
create_channel() -> (Sender<Message>, Receiver<Message>)262     pub fn create_channel() -> (Sender<Message>, Receiver<Message>) {
263         channel::<Message>(1)
264     }
265 
266     /// Runs the main dispatch loop.
dispatch( mut rx: Receiver<Message>, tx: Sender<Message>, api_tx: Sender<APIMessage>, bluetooth: Arc<Mutex<Box<Bluetooth>>>, bluetooth_gatt: Arc<Mutex<Box<BluetoothGatt>>>, battery_service: Arc<Mutex<Box<BatteryService>>>, battery_manager: Arc<Mutex<Box<BatteryManager>>>, battery_provider_manager: Arc<Mutex<Box<BatteryProviderManager>>>, bluetooth_media: Arc<Mutex<Box<BluetoothMedia>>>, suspend: Arc<Mutex<Box<Suspend>>>, bluetooth_socketmgr: Arc<Mutex<Box<BluetoothSocketManager>>>, bluetooth_admin: Arc<Mutex<Box<BluetoothAdmin>>>, bluetooth_dis: Arc<Mutex<Box<DeviceInformation>>>, bluetooth_qa: Arc<Mutex<Box<BluetoothQA>>>, )267     pub async fn dispatch(
268         mut rx: Receiver<Message>,
269         tx: Sender<Message>,
270         api_tx: Sender<APIMessage>,
271         bluetooth: Arc<Mutex<Box<Bluetooth>>>,
272         bluetooth_gatt: Arc<Mutex<Box<BluetoothGatt>>>,
273         battery_service: Arc<Mutex<Box<BatteryService>>>,
274         battery_manager: Arc<Mutex<Box<BatteryManager>>>,
275         battery_provider_manager: Arc<Mutex<Box<BatteryProviderManager>>>,
276         bluetooth_media: Arc<Mutex<Box<BluetoothMedia>>>,
277         suspend: Arc<Mutex<Box<Suspend>>>,
278         bluetooth_socketmgr: Arc<Mutex<Box<BluetoothSocketManager>>>,
279         bluetooth_admin: Arc<Mutex<Box<BluetoothAdmin>>>,
280         bluetooth_dis: Arc<Mutex<Box<DeviceInformation>>>,
281         bluetooth_qa: Arc<Mutex<Box<BluetoothQA>>>,
282     ) {
283         loop {
284             let m = rx.recv().await;
285 
286             if m.is_none() {
287                 eprintln!("Message dispatch loop quit");
288                 break;
289             }
290 
291             match m.unwrap() {
292                 Message::InterfaceShutdown => {
293                     let txl = api_tx.clone();
294                     tokio::spawn(async move {
295                         let _ = txl.send(APIMessage::ShutDown).await;
296                     });
297                 }
298 
299                 Message::AdapterShutdown => {
300                     bluetooth_gatt.lock().unwrap().enable(false);
301                     bluetooth.lock().unwrap().disable();
302                 }
303 
304                 Message::Cleanup => {
305                     bluetooth.lock().unwrap().cleanup();
306                 }
307 
308                 Message::CleanupProfiles => {
309                     bluetooth_media.lock().unwrap().cleanup();
310                 }
311 
312                 Message::AdapterReady => {
313                     // Initialize objects that need the adapter to be fully
314                     // enabled before running.
315 
316                     // Init Media and pass it to Bluetooth.
317                     bluetooth_media.lock().unwrap().initialize();
318                     bluetooth.lock().unwrap().set_media(bluetooth_media.clone());
319                     // Init Gatt and pass it to Bluetooth.
320                     bluetooth_gatt.lock().unwrap().init_profiles(api_tx.clone());
321                     bluetooth_gatt.lock().unwrap().enable(true);
322                     bluetooth.lock().unwrap().set_gatt_and_init_scanner(bluetooth_gatt.clone());
323                     // Init AdvertiseManager. It selects the stack per is_le_ext_adv_supported
324                     // so it can only be done after Adapter is ready.
325                     bluetooth_gatt.lock().unwrap().init_adv_manager(bluetooth.clone());
326                     // Battery service and device information service are on top of Gatt.
327                     // Only initialize them after GATT is ready.
328                     bluetooth_dis.lock().unwrap().initialize();
329                     battery_service.lock().unwrap().init();
330                     // Initialize Admin. This toggles the enabled profiles.
331                     bluetooth_admin.lock().unwrap().initialize(api_tx.clone());
332                 }
333 
334                 Message::A2dp(a) => {
335                     bluetooth_media.lock().unwrap().dispatch_a2dp_callbacks(a);
336                 }
337 
338                 Message::Avrcp(av) => {
339                     bluetooth_media.lock().unwrap().dispatch_avrcp_callbacks(av);
340                 }
341 
342                 Message::Base(b) => {
343                     dispatch_base_callbacks(bluetooth.lock().unwrap().as_mut(), b.clone());
344                     dispatch_base_callbacks(suspend.lock().unwrap().as_mut(), b);
345                 }
346 
347                 // When pairing is busy for any reason, the bond cannot be created.
348                 // Allow retries until it is ready for bonding.
349                 Message::CreateBondWithRetry(device, bt_transport, num_attempts, retry_delay) => {
350                     if num_attempts == 0 {
351                         continue;
352                     }
353 
354                     let mut bt = bluetooth.lock().unwrap();
355                     if !bt.is_pairing_busy() {
356                         bt.create_bond(device, bt_transport);
357                         continue;
358                     }
359 
360                     let txl = tx.clone();
361                     tokio::spawn(async move {
362                         sleep(retry_delay).await;
363                         let _ = txl
364                             .send(Message::CreateBondWithRetry(
365                                 device,
366                                 bt_transport,
367                                 num_attempts - 1,
368                                 retry_delay,
369                             ))
370                             .await;
371                     });
372                 }
373 
374                 Message::GattClient(m) => {
375                     dispatch_gatt_client_callbacks(bluetooth_gatt.lock().unwrap().as_mut(), m);
376                 }
377 
378                 Message::GattServer(m) => {
379                     dispatch_gatt_server_callbacks(bluetooth_gatt.lock().unwrap().as_mut(), m);
380                 }
381 
382                 Message::LeAudioClient(a) => {
383                     bluetooth_media.lock().unwrap().dispatch_le_audio_callbacks(a);
384                 }
385 
386                 Message::VolumeControl(a) => {
387                     bluetooth_media.lock().unwrap().dispatch_vc_callbacks(a);
388                 }
389 
390                 Message::CsisClient(a) => {
391                     bluetooth_media.lock().unwrap().dispatch_csis_callbacks(a);
392                 }
393 
394                 Message::LeScanner(m) => {
395                     dispatch_le_scanner_callbacks(bluetooth_gatt.lock().unwrap().as_mut(), m);
396                 }
397 
398                 Message::LeScannerInband(m) => {
399                     dispatch_le_scanner_inband_callbacks(
400                         bluetooth_gatt.lock().unwrap().as_mut(),
401                         m,
402                     );
403                 }
404 
405                 Message::LeAdvInband(m) => {
406                     debug!("Received LeAdvInband message: {:?}. This is unexpected!", m);
407                 }
408 
409                 Message::LeAdv(m) => {
410                     dispatch_le_adv_callbacks(bluetooth_gatt.lock().unwrap().as_mut(), m);
411                 }
412 
413                 Message::Hfp(hf) => {
414                     bluetooth_media.lock().unwrap().dispatch_hfp_callbacks(hf);
415                 }
416 
417                 Message::HidHost(h) => {
418                     dispatch_hid_host_callbacks(bluetooth.lock().unwrap().as_mut(), h);
419                 }
420 
421                 Message::Sdp(s) => {
422                     dispatch_sdp_callbacks(bluetooth.lock().unwrap().as_mut(), s);
423                 }
424 
425                 Message::Media(action) => {
426                     bluetooth_media.lock().unwrap().dispatch_media_actions(action);
427                 }
428 
429                 Message::MediaCallbackDisconnected(cb_id) => {
430                     bluetooth_media.lock().unwrap().remove_callback(cb_id);
431                 }
432 
433                 Message::TelephonyCallbackDisconnected(cb_id) => {
434                     bluetooth_media.lock().unwrap().remove_telephony_callback(cb_id);
435                 }
436 
437                 Message::AdapterCallbackDisconnected(id) => {
438                     bluetooth.lock().unwrap().adapter_callback_disconnected(id);
439                 }
440 
441                 Message::ConnectionCallbackDisconnected(id) => {
442                     bluetooth.lock().unwrap().connection_callback_disconnected(id);
443                 }
444 
445                 Message::AdapterActions(action) => {
446                     bluetooth.lock().unwrap().handle_actions(action);
447                 }
448 
449                 // Any service needing an updated list of devices can have an update method
450                 // triggered from here rather than needing a reference to Bluetooth.
451                 Message::OnDeviceConnectionOrBondStateChanged(
452                     addr,
453                     _bredr_acl_state,
454                     ble_acl_state,
455                     bond_state,
456                     _transport,
457                 ) => {
458                     if ble_acl_state == BtAclState::Connected && bond_state == BtBondState::Bonded {
459                         info!("BAS: Connecting to {}", DisplayAddress(&addr));
460                         battery_service.lock().unwrap().init_device(addr);
461                     }
462                 }
463 
464                 Message::SuspendCallbackRegistered(id) => {
465                     suspend.lock().unwrap().callback_registered(id);
466                 }
467 
468                 Message::SuspendCallbackDisconnected(id) => {
469                     suspend.lock().unwrap().remove_callback(id);
470                 }
471 
472                 Message::SuspendReady(suspend_id) => {
473                     suspend.lock().unwrap().suspend_ready(suspend_id);
474                 }
475 
476                 Message::ResumeReady(suspend_id) => {
477                     suspend.lock().unwrap().resume_ready(suspend_id);
478                 }
479 
480                 Message::AudioReconnectOnResumeComplete => {
481                     suspend.lock().unwrap().audio_reconnect_complete();
482                 }
483 
484                 Message::ScannerCallbackDisconnected(id) => {
485                     bluetooth_gatt.lock().unwrap().remove_scanner_callback(id);
486                 }
487 
488                 Message::AdvertiserCallbackDisconnected(id) => {
489                     bluetooth_gatt.lock().unwrap().remove_adv_callback(id);
490                 }
491 
492                 Message::AdvertiserActions(action) => {
493                     bluetooth_gatt.lock().unwrap().handle_adv_action(action);
494                 }
495 
496                 Message::SocketManagerActions(action) => {
497                     bluetooth_socketmgr.lock().unwrap().handle_actions(action);
498                 }
499                 Message::SocketManagerCallbackDisconnected(id) => {
500                     bluetooth_socketmgr.lock().unwrap().remove_callback(id);
501                 }
502                 Message::BatteryProviderManagerBatteryUpdated(remote_address, battery_set) => {
503                     battery_manager
504                         .lock()
505                         .unwrap()
506                         .handle_battery_updated(remote_address, battery_set);
507                 }
508                 Message::BatteryProviderManagerCallbackDisconnected(id) => {
509                     battery_provider_manager.lock().unwrap().remove_battery_provider_callback(id);
510                 }
511                 Message::BatteryServiceCallbackDisconnected(id) => {
512                     battery_service.lock().unwrap().remove_callback(id);
513                 }
514                 Message::BatteryService(action) => {
515                     battery_service.lock().unwrap().handle_action(action);
516                 }
517                 Message::BatteryServiceRefresh => {
518                     battery_service.lock().unwrap().refresh_all_devices();
519                 }
520                 Message::BatteryManagerCallbackDisconnected(id) => {
521                     battery_manager.lock().unwrap().remove_callback(id);
522                 }
523                 Message::GattActions(action) => {
524                     bluetooth_gatt.lock().unwrap().handle_action(action);
525                 }
526                 Message::GattClientCallbackDisconnected(id) => {
527                     bluetooth_gatt.lock().unwrap().remove_client_callback(id);
528                 }
529                 Message::GattServerCallbackDisconnected(id) => {
530                     bluetooth_gatt.lock().unwrap().remove_server_callback(id);
531                 }
532                 Message::AdminCallbackDisconnected(id) => {
533                     bluetooth_admin.lock().unwrap().unregister_admin_policy_callback(id);
534                 }
535                 Message::AdminActions(action) => {
536                     bluetooth_admin.lock().unwrap().handle_action(action);
537                 }
538                 Message::HidHostEnable => {
539                     bluetooth.lock().unwrap().enable_hidhost();
540                 }
541                 Message::Dis(callback) => {
542                     bluetooth_dis.lock().unwrap().handle_callbacks(&callback);
543                 }
544                 Message::DisconnectDevice(addr) => {
545                     bluetooth.lock().unwrap().disconnect_all_enabled_profiles(addr);
546                 }
547                 // Qualification Only
548                 Message::QaAddMediaPlayer(name, browsing_supported) => {
549                     bluetooth_media.lock().unwrap().add_player(name, browsing_supported);
550                 }
551                 Message::QaRfcommSendMsc(dlci, addr) => {
552                     bluetooth_socketmgr.lock().unwrap().rfcomm_send_msc(dlci, addr);
553                 }
554                 Message::QaCallbackDisconnected(id) => {
555                     bluetooth_qa.lock().unwrap().unregister_qa_callback(id);
556                 }
557                 Message::QaFetchDiscoverableMode => {
558                     let mode = bluetooth.lock().unwrap().get_discoverable_mode_internal();
559                     bluetooth_qa.lock().unwrap().on_fetch_discoverable_mode_completed(mode);
560                 }
561                 Message::QaFetchConnectable => {
562                     let connectable = bluetooth.lock().unwrap().get_connectable_internal();
563                     bluetooth_qa.lock().unwrap().on_fetch_connectable_completed(connectable);
564                 }
565                 Message::QaSetConnectable(mode) => {
566                     let succeed = bluetooth.lock().unwrap().set_connectable_internal(mode);
567                     bluetooth_qa.lock().unwrap().on_set_connectable_completed(succeed);
568                 }
569                 Message::QaFetchAlias => {
570                     let alias = bluetooth.lock().unwrap().get_alias_internal();
571                     bluetooth_qa.lock().unwrap().on_fetch_alias_completed(alias);
572                 }
573                 Message::QaGetHidReport(addr, report_type, report_id) => {
574                     let status = bluetooth.lock().unwrap().get_hid_report_internal(
575                         addr,
576                         report_type,
577                         report_id,
578                     );
579                     bluetooth_qa.lock().unwrap().on_get_hid_report_completed(status);
580                 }
581                 Message::QaSetHidReport(addr, report_type, report) => {
582                     let status = bluetooth.lock().unwrap().set_hid_report_internal(
583                         addr,
584                         report_type,
585                         report,
586                     );
587                     bluetooth_qa.lock().unwrap().on_set_hid_report_completed(status);
588                 }
589                 Message::QaSendHidData(addr, data) => {
590                     let status = bluetooth.lock().unwrap().send_hid_data_internal(addr, data);
591                     bluetooth_qa.lock().unwrap().on_send_hid_data_completed(status);
592                 }
593                 Message::QaSendHidVirtualUnplug(addr) => {
594                     let status = bluetooth.lock().unwrap().send_hid_virtual_unplug_internal(addr);
595                     bluetooth_qa.lock().unwrap().on_send_hid_virtual_unplug_completed(status);
596                 }
597 
598                 // UHid callbacks
599                 Message::UHidHfpOutputCallback(addr, id, data) => {
600                     bluetooth_media
601                         .lock()
602                         .unwrap()
603                         .dispatch_uhid_hfp_output_callback(addr, id, data);
604                 }
605 
606                 Message::UHidTelephonyUseCallback(addr, state) => {
607                     bluetooth_media
608                         .lock()
609                         .unwrap()
610                         .dispatch_uhid_telephony_use_callback(addr, state);
611                 }
612 
613                 Message::ProfileDisconnected(addr) => {
614                     let bas_app_uuid =
615                         Uuid::from_string(String::from(BATTERY_SERVICE_GATT_CLIENT_APP_ID))
616                             .expect("BAS Uuid failed to be parsed");
617                     // Ideally we would also check that there are no open sockets for this device
618                     // but Floss does not manage socket state so there is no reasonable way for us
619                     // to know whether a socket is open or not.
620                     if bluetooth_gatt.lock().unwrap().get_connected_applications(&addr)
621                         == vec![bas_app_uuid]
622                         && !bluetooth.lock().unwrap().is_hh_connected(&addr)
623                         && bluetooth_media.lock().unwrap().get_connected_profiles(&addr).is_empty()
624                     {
625                         info!(
626                             "BAS: Disconnecting from {} since it's the last active profile",
627                             DisplayAddress(&addr)
628                         );
629                         battery_service.lock().unwrap().drop_device(addr);
630                     }
631                 }
632             }
633         }
634     }
635 }
636 
637 /// Signifies that the object may be a proxy to a remote RPC object.
638 ///
639 /// An object that implements RPCProxy trait signifies that the object may be a proxy to a remote
640 /// RPC object. Therefore the object may be disconnected and thus should implement
641 /// `register_disconnect` to let others observe the disconnection event.
642 pub trait RPCProxy {
643     /// Registers disconnect observer that will be notified when the remote object is disconnected.
register_disconnect(&mut self, _f: Box<dyn Fn(u32) + Send>) -> u32644     fn register_disconnect(&mut self, _f: Box<dyn Fn(u32) + Send>) -> u32 {
645         0
646     }
647 
648     /// Returns the ID of the object. For example this would be an object path in D-Bus RPC.
get_object_id(&self) -> String649     fn get_object_id(&self) -> String {
650         String::from("")
651     }
652 
653     /// Unregisters callback with this id.
unregister(&mut self, _id: u32) -> bool654     fn unregister(&mut self, _id: u32) -> bool {
655         false
656     }
657 
658     /// Makes this object available for remote call.
export_for_rpc(self: Box<Self>)659     fn export_for_rpc(self: Box<Self>) {}
660 }
661