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