• 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 async_helper;
7 pub mod battery_manager;
8 pub mod battery_provider_manager;
9 pub mod battery_service;
10 pub mod bluetooth;
11 pub mod bluetooth_admin;
12 pub mod bluetooth_adv;
13 pub mod bluetooth_gatt;
14 pub mod bluetooth_logging;
15 pub mod bluetooth_media;
16 pub mod bluetooth_qa;
17 pub mod callbacks;
18 pub mod dis;
19 pub mod socket_manager;
20 pub mod suspend;
21 pub mod uuid;
22 
23 use bluetooth_qa::BluetoothQA;
24 use bt_topshim::btif::BtDiscMode;
25 use log::debug;
26 use num_derive::{FromPrimitive, ToPrimitive};
27 use std::sync::{Arc, Mutex};
28 use tokio::sync::mpsc::channel;
29 use tokio::sync::mpsc::{Receiver, Sender};
30 
31 use crate::battery_manager::{BatteryManager, BatterySet};
32 use crate::battery_provider_manager::BatteryProviderManager;
33 use crate::battery_service::{BatteryService, BatteryServiceActions};
34 use crate::bluetooth::{
35     dispatch_base_callbacks, dispatch_hid_host_callbacks, dispatch_sdp_callbacks, Bluetooth,
36     BluetoothDevice, DelayedActions, IBluetooth,
37 };
38 use crate::bluetooth_admin::{BluetoothAdmin, IBluetoothAdmin};
39 use crate::bluetooth_gatt::{
40     dispatch_gatt_client_callbacks, dispatch_gatt_server_callbacks, dispatch_le_adv_callbacks,
41     dispatch_le_scanner_callbacks, dispatch_le_scanner_inband_callbacks, BluetoothGatt,
42 };
43 use crate::bluetooth_media::{BluetoothMedia, MediaActions};
44 use crate::dis::{DeviceInformation, ServiceCallbacks};
45 use crate::socket_manager::{BluetoothSocketManager, SocketActions};
46 use crate::suspend::Suspend;
47 use bt_topshim::{
48     btif::{BaseCallbacks, BtTransport},
49     profiles::{
50         a2dp::A2dpCallbacks, avrcp::AvrcpCallbacks, gatt::GattAdvCallbacks,
51         gatt::GattAdvInbandCallbacks, gatt::GattClientCallbacks, gatt::GattScannerCallbacks,
52         gatt::GattScannerInbandCallbacks, gatt::GattServerCallbacks, hfp::HfpCallbacks,
53         hid_host::HHCallbacks, sdp::SdpCallbacks,
54     },
55 };
56 
57 /// Message types that are sent to the stack main dispatch loop.
58 pub enum Message {
59     // Shuts down the stack.
60     Shutdown,
61 
62     // Adapter is enabled and ready.
63     AdapterReady,
64 
65     // Callbacks from libbluetooth
66     A2dp(A2dpCallbacks),
67     Avrcp(AvrcpCallbacks),
68     Base(BaseCallbacks),
69     GattClient(GattClientCallbacks),
70     GattServer(GattServerCallbacks),
71     LeScanner(GattScannerCallbacks),
72     LeScannerInband(GattScannerInbandCallbacks),
73     LeAdvInband(GattAdvInbandCallbacks),
74     LeAdv(GattAdvCallbacks),
75     HidHost(HHCallbacks),
76     Hfp(HfpCallbacks),
77     Sdp(SdpCallbacks),
78 
79     // Actions within the stack
80     Media(MediaActions),
81     MediaCallbackDisconnected(u32),
82 
83     // Client callback disconnections
84     AdapterCallbackDisconnected(u32),
85     ConnectionCallbackDisconnected(u32),
86 
87     // Some delayed actions for the adapter.
88     DelayedAdapterActions(DelayedActions),
89 
90     // Follows IBluetooth's on_device_(dis)connected callback but doesn't require depending on
91     // Bluetooth.
92     OnAclConnected(BluetoothDevice, BtTransport),
93     OnAclDisconnected(BluetoothDevice),
94 
95     // Suspend related
96     SuspendCallbackRegistered(u32),
97     SuspendCallbackDisconnected(u32),
98     SuspendReady(i32),
99     ResumeReady(i32),
100     AudioReconnectOnResumeComplete,
101 
102     // Scanner related
103     ScannerCallbackDisconnected(u32),
104 
105     // Advertising related
106     AdvertiserCallbackDisconnected(u32),
107 
108     SocketManagerActions(SocketActions),
109     SocketManagerCallbackDisconnected(u32),
110 
111     // Battery related
112     BatteryProviderManagerCallbackDisconnected(u32),
113     BatteryProviderManagerBatteryUpdated(String, BatterySet),
114     BatteryServiceCallbackDisconnected(u32),
115     BatteryService(BatteryServiceActions),
116     BatteryServiceRefresh,
117     BatteryManagerCallbackDisconnected(u32),
118 
119     GattClientCallbackDisconnected(u32),
120     GattServerCallbackDisconnected(u32),
121 
122     // Admin policy related
123     AdminCallbackDisconnected(u32),
124     HidHostEnable,
125     AdminPolicyChanged,
126 
127     // Dis callbacks
128     Dis(ServiceCallbacks),
129 
130     // Qualification Only
131     QaAddMediaPlayer(String, bool),
132     QaRfcommSendMsc(u8, String),
133     QaOnDiscoverableModeChanged(BtDiscMode),
134 }
135 
136 /// Represents suspend mode of a module.
137 ///
138 /// Being in suspend mode means that the module pauses some activities if required for suspend and
139 /// some subsequent API calls will be blocked with a retryable error.
140 #[derive(FromPrimitive, ToPrimitive, Debug, PartialEq, Clone)]
141 pub enum SuspendMode {
142     Normal = 0,
143     Suspending = 1,
144     Suspended = 2,
145     Resuming = 3,
146 }
147 
148 /// Umbrella class for the Bluetooth stack.
149 pub struct Stack {}
150 
151 impl Stack {
152     /// Creates an mpsc channel for passing messages to the main dispatch loop.
create_channel() -> (Sender<Message>, Receiver<Message>)153     pub fn create_channel() -> (Sender<Message>, Receiver<Message>) {
154         channel::<Message>(1)
155     }
156 
157     /// Runs the main dispatch loop.
dispatch( mut rx: Receiver<Message>, 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>>>, )158     pub async fn dispatch(
159         mut rx: Receiver<Message>,
160         bluetooth: Arc<Mutex<Box<Bluetooth>>>,
161         bluetooth_gatt: Arc<Mutex<Box<BluetoothGatt>>>,
162         battery_service: Arc<Mutex<Box<BatteryService>>>,
163         battery_manager: Arc<Mutex<Box<BatteryManager>>>,
164         battery_provider_manager: Arc<Mutex<Box<BatteryProviderManager>>>,
165         bluetooth_media: Arc<Mutex<Box<BluetoothMedia>>>,
166         suspend: Arc<Mutex<Box<Suspend>>>,
167         bluetooth_socketmgr: Arc<Mutex<Box<BluetoothSocketManager>>>,
168         bluetooth_admin: Arc<Mutex<Box<BluetoothAdmin>>>,
169         bluetooth_dis: Arc<Mutex<Box<DeviceInformation>>>,
170         bluetooth_qa: Arc<Mutex<Box<BluetoothQA>>>,
171     ) {
172         loop {
173             let m = rx.recv().await;
174 
175             if m.is_none() {
176                 eprintln!("Message dispatch loop quit");
177                 break;
178             }
179 
180             match m.unwrap() {
181                 Message::Shutdown => {
182                     bluetooth.lock().unwrap().disable();
183                 }
184 
185                 Message::AdapterReady => {
186                     // Initialize objects that need the adapter to be fully
187                     // enabled before running.
188 
189                     // Register device information service.
190                     bluetooth_dis.lock().unwrap().initialize();
191                 }
192 
193                 Message::A2dp(a) => {
194                     bluetooth_media.lock().unwrap().dispatch_a2dp_callbacks(a);
195                 }
196 
197                 Message::Avrcp(av) => {
198                     bluetooth_media.lock().unwrap().dispatch_avrcp_callbacks(av);
199                 }
200 
201                 Message::Base(b) => {
202                     dispatch_base_callbacks(bluetooth.lock().unwrap().as_mut(), b.clone());
203                     dispatch_base_callbacks(suspend.lock().unwrap().as_mut(), b);
204                 }
205 
206                 Message::GattClient(m) => {
207                     dispatch_gatt_client_callbacks(bluetooth_gatt.lock().unwrap().as_mut(), m);
208                 }
209 
210                 Message::GattServer(m) => {
211                     dispatch_gatt_server_callbacks(bluetooth_gatt.lock().unwrap().as_mut(), m);
212                 }
213 
214                 Message::LeScanner(m) => {
215                     dispatch_le_scanner_callbacks(bluetooth_gatt.lock().unwrap().as_mut(), m);
216                 }
217 
218                 Message::LeScannerInband(m) => {
219                     dispatch_le_scanner_inband_callbacks(
220                         bluetooth_gatt.lock().unwrap().as_mut(),
221                         m,
222                     );
223                 }
224 
225                 Message::LeAdvInband(m) => {
226                     debug!("Received LeAdvInband message: {:?}. This is unexpected!", m);
227                 }
228 
229                 Message::LeAdv(m) => {
230                     dispatch_le_adv_callbacks(bluetooth_gatt.lock().unwrap().as_mut(), m);
231                 }
232 
233                 Message::Hfp(hf) => {
234                     bluetooth_media.lock().unwrap().dispatch_hfp_callbacks(hf);
235                 }
236 
237                 Message::HidHost(h) => {
238                     dispatch_hid_host_callbacks(bluetooth.lock().unwrap().as_mut(), h);
239                 }
240 
241                 Message::Sdp(s) => {
242                     dispatch_sdp_callbacks(bluetooth.lock().unwrap().as_mut(), s);
243                 }
244 
245                 Message::Media(action) => {
246                     bluetooth_media.lock().unwrap().dispatch_media_actions(action);
247                 }
248 
249                 Message::MediaCallbackDisconnected(cb_id) => {
250                     bluetooth_media.lock().unwrap().remove_callback(cb_id);
251                 }
252 
253                 Message::AdapterCallbackDisconnected(id) => {
254                     bluetooth.lock().unwrap().adapter_callback_disconnected(id);
255                 }
256 
257                 Message::ConnectionCallbackDisconnected(id) => {
258                     bluetooth.lock().unwrap().connection_callback_disconnected(id);
259                 }
260 
261                 Message::DelayedAdapterActions(action) => {
262                     bluetooth.lock().unwrap().handle_delayed_actions(action);
263                 }
264 
265                 // Any service needing an updated list of devices can have an
266                 // update method triggered from here rather than needing a
267                 // reference to Bluetooth.
268                 Message::OnAclConnected(device, transport) => {
269                     battery_service
270                         .lock()
271                         .unwrap()
272                         .handle_action(BatteryServiceActions::Connect(device, transport));
273                 }
274 
275                 // For battery service, use this to clean up internal handles. GATT connection is
276                 // already dropped if ACL disconnect has occurred.
277                 Message::OnAclDisconnected(device) => {
278                     battery_service
279                         .lock()
280                         .unwrap()
281                         .handle_action(BatteryServiceActions::Disconnect(device));
282                 }
283 
284                 Message::SuspendCallbackRegistered(id) => {
285                     suspend.lock().unwrap().callback_registered(id);
286                 }
287 
288                 Message::SuspendCallbackDisconnected(id) => {
289                     suspend.lock().unwrap().remove_callback(id);
290                 }
291 
292                 Message::SuspendReady(suspend_id) => {
293                     suspend.lock().unwrap().suspend_ready(suspend_id);
294                 }
295 
296                 Message::ResumeReady(suspend_id) => {
297                     suspend.lock().unwrap().resume_ready(suspend_id);
298                 }
299 
300                 Message::AudioReconnectOnResumeComplete => {
301                     suspend.lock().unwrap().audio_reconnect_complete();
302                 }
303 
304                 Message::ScannerCallbackDisconnected(id) => {
305                     bluetooth_gatt.lock().unwrap().remove_scanner_callback(id);
306                 }
307 
308                 Message::AdvertiserCallbackDisconnected(id) => {
309                     bluetooth_gatt.lock().unwrap().remove_adv_callback(id);
310                 }
311 
312                 Message::SocketManagerActions(action) => {
313                     bluetooth_socketmgr.lock().unwrap().handle_actions(action);
314                 }
315                 Message::SocketManagerCallbackDisconnected(id) => {
316                     bluetooth_socketmgr.lock().unwrap().remove_callback(id);
317                 }
318                 Message::BatteryProviderManagerBatteryUpdated(remote_address, battery_set) => {
319                     battery_manager
320                         .lock()
321                         .unwrap()
322                         .handle_battery_updated(remote_address, battery_set);
323                 }
324                 Message::BatteryProviderManagerCallbackDisconnected(id) => {
325                     battery_provider_manager.lock().unwrap().remove_battery_provider_callback(id);
326                 }
327                 Message::BatteryServiceCallbackDisconnected(id) => {
328                     battery_service.lock().unwrap().remove_callback(id);
329                 }
330                 Message::BatteryService(action) => {
331                     battery_service.lock().unwrap().handle_action(action);
332                 }
333                 Message::BatteryServiceRefresh => {
334                     battery_service.lock().unwrap().refresh_all_devices();
335                 }
336                 Message::BatteryManagerCallbackDisconnected(id) => {
337                     battery_manager.lock().unwrap().remove_callback(id);
338                 }
339                 Message::GattClientCallbackDisconnected(id) => {
340                     bluetooth_gatt.lock().unwrap().remove_client_callback(id);
341                 }
342                 Message::GattServerCallbackDisconnected(id) => {
343                     bluetooth_gatt.lock().unwrap().remove_server_callback(id);
344                 }
345                 Message::AdminCallbackDisconnected(id) => {
346                     bluetooth_admin.lock().unwrap().unregister_admin_policy_callback(id);
347                 }
348                 Message::HidHostEnable => {
349                     bluetooth.lock().unwrap().enable_hidhost();
350                 }
351                 Message::AdminPolicyChanged => {
352                     bluetooth_socketmgr.lock().unwrap().handle_admin_policy_changed();
353                 }
354                 Message::Dis(callback) => {
355                     bluetooth_dis.lock().unwrap().handle_callbacks(&callback);
356                 }
357                 // Qualification Only
358                 Message::QaAddMediaPlayer(name, browsing_supported) => {
359                     bluetooth_media.lock().unwrap().add_player(name, browsing_supported);
360                 }
361                 Message::QaRfcommSendMsc(dlci, addr) => {
362                     bluetooth_socketmgr.lock().unwrap().rfcomm_send_msc(dlci, addr);
363                 }
364                 Message::QaOnDiscoverableModeChanged(mode) => {
365                     bluetooth_qa.lock().unwrap().handle_discoverable_mode_changed(mode);
366                 }
367             }
368         }
369     }
370 }
371 
372 /// Signifies that the object may be a proxy to a remote RPC object.
373 ///
374 /// An object that implements RPCProxy trait signifies that the object may be a proxy to a remote
375 /// RPC object. Therefore the object may be disconnected and thus should implement
376 /// `register_disconnect` to let others observe the disconnection event.
377 pub trait RPCProxy {
378     /// Registers disconnect observer that will be notified when the remote object is disconnected.
register_disconnect(&mut self, _f: Box<dyn Fn(u32) + Send>) -> u32379     fn register_disconnect(&mut self, _f: Box<dyn Fn(u32) + Send>) -> u32 {
380         0
381     }
382 
383     /// Returns the ID of the object. For example this would be an object path in D-Bus RPC.
get_object_id(&self) -> String384     fn get_object_id(&self) -> String {
385         String::from("")
386     }
387 
388     /// Unregisters callback with this id.
unregister(&mut self, _id: u32) -> bool389     fn unregister(&mut self, _id: u32) -> bool {
390         false
391     }
392 
393     /// Makes this object available for remote call.
export_for_rpc(self: Box<Self>)394     fn export_for_rpc(self: Box<Self>) {}
395 }
396