Skip to main content

sl4f_lib/bluetooth/
avdtp_facade.rs

1// Copyright 2019 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use anyhow::Error;
6use fidl::endpoints::create_endpoints;
7use fidl_fuchsia_bluetooth_avdtp_test::{
8    PeerControllerMarker, PeerControllerProxy, PeerManagerEvent, PeerManagerMarker,
9    PeerManagerProxy,
10};
11use fuchsia_async as fasync;
12use fuchsia_component::client;
13use fuchsia_sync::RwLock;
14use futures::stream::StreamExt;
15use log::*;
16use std::collections::HashMap;
17use std::collections::hash_map::Entry;
18use std::sync::Arc;
19
20use crate::bluetooth::types::PeerFactoryMap;
21use crate::common_utils::common::macros::{fx_err_and_bail, with_line};
22
23#[derive(Debug)]
24struct AvdtpFacadeInner {
25    /// The current Avdtp service Proxy
26    avdtp_service_proxy: Option<PeerManagerProxy>,
27
28    ///The hashmap of Peer ids to PeerControllerProxys
29    peer_map: Arc<RwLock<PeerFactoryMap>>,
30}
31
32#[derive(Debug)]
33pub struct AvdtpFacade {
34    initialized: RwLock<bool>,
35    inner: RwLock<AvdtpFacadeInner>,
36}
37
38/// Perform Bluetooth AVDTP fucntions for both Sink and Source.
39///
40/// Note this object is shared among all threads created by server.
41///
42impl AvdtpFacade {
43    pub fn new() -> AvdtpFacade {
44        AvdtpFacade {
45            initialized: RwLock::new(false),
46            inner: RwLock::new(AvdtpFacadeInner {
47                avdtp_service_proxy: None,
48                peer_map: Arc::new(RwLock::new(HashMap::new())),
49            }),
50        }
51    }
52
53    /// Creates a Peer Manager Proxy
54    async fn create_avdtp_service_proxy(&self) -> Result<PeerManagerProxy, Error> {
55        let tag = "AvdtpFacade::create_avdtp_service_proxy";
56        match self.inner.read().avdtp_service_proxy.clone() {
57            Some(avdtp_service_proxy) => {
58                info!(
59                    tag = &with_line!(tag);
60                    "Current Avdtp service proxy: {:?}", avdtp_service_proxy
61                );
62                Ok(avdtp_service_proxy)
63            }
64            None => {
65                info!(tag = &with_line!(tag); "Launching A2DP and setting new Avdtp service proxy");
66
67                let avdtp_service_proxy = client::connect_to_protocol::<PeerManagerMarker>();
68                if let Err(err) = avdtp_service_proxy {
69                    fx_err_and_bail!(
70                        &with_line!(tag),
71                        format_err!("Failed to create Avdtp service proxy: {}", err)
72                    );
73                }
74                avdtp_service_proxy
75            }
76        }
77    }
78
79    /// Initialize the Avdtp service and starts A2DP.
80    pub async fn init_avdtp_service_proxy(&self) -> Result<(), Error> {
81        if *self.initialized.read() {
82            return Ok(());
83        }
84        *self.initialized.write() = true;
85
86        let tag = "AvdtpFacade::init_avdtp_service_proxy";
87        self.inner.write().avdtp_service_proxy = Some(self.create_avdtp_service_proxy().await?);
88
89        let avdtp_svc = match &self.inner.read().avdtp_service_proxy {
90            Some(p) => p.clone(),
91            None => fx_err_and_bail!(&with_line!(tag), "No AVDTP Service proxy created"),
92        };
93
94        let avdtp_service_future =
95            AvdtpFacade::monitor_avdtp_event_stream(avdtp_svc, self.inner.write().peer_map.clone());
96
97        let fut = async move {
98            let result = avdtp_service_future.await;
99            if let Err(_err) = result {
100                error!("Failed to monitor AVDTP event stream.");
101            }
102        };
103        fasync::Task::spawn(fut).detach();
104
105        Ok(())
106    }
107
108    /// Gets the currently connected peers.
109    pub async fn get_connected_peers(&self) -> Result<Vec<u64>, Error> {
110        let tag = "AvdtpFacade::get_connected_peers";
111        let proxy_opt = self.inner.read().avdtp_service_proxy.clone();
112        let peer_ids = match proxy_opt {
113            Some(p) => {
114                let connected_peers = p.connected_peers().await?;
115                let mut peer_id_list = Vec::new();
116                for peer in connected_peers {
117                    peer_id_list.push(peer.value);
118                }
119                peer_id_list
120            }
121            None => fx_err_and_bail!(&with_line!(tag), "No AVDTP Service proxy created"),
122        };
123        Ok(peer_ids)
124    }
125
126    /// Gets the PeerController by input peer_id.
127    ///
128    /// # Arguments
129    /// * `peer_id`: The unique peer_id for the PeerController.
130    fn get_peer_controller_by_id(&self, peer_id: u64) -> Option<PeerControllerProxy> {
131        match self.inner.read().peer_map.write().get(&peer_id.to_string()) {
132            Some(p) => Some(p.clone()),
133            None => None,
134        }
135    }
136
137    /// Initiate a stream configuration procedure for the input peer_id.
138    ///
139    /// # Arguments
140    /// * `peer_id`: The peer id associated with the PeerController.
141    pub async fn set_configuration(&self, peer_id: u64) -> Result<(), Error> {
142        let tag = "AvdtpFacade::set_configuration";
143        if let Some(p) = self.get_peer_controller_by_id(peer_id) {
144            match p.set_configuration().await? {
145                Err(err) => {
146                    let err_msg = format_err!("Error: {:?}", err);
147                    fx_err_and_bail!(&with_line!(tag), err_msg)
148                }
149                Ok(()) => Ok(()),
150            }
151        } else {
152            fx_err_and_bail!(&with_line!(tag), format!("Peer id {:?} not found.", peer_id))
153        }
154    }
155
156    /// Initiate a procedure to get the configuration information of the peer stream
157    /// for the input peer_id.
158    ///
159    /// # Arguments
160    /// * `peer_id`: The peer id associated with the PeerController.
161    pub async fn get_configuration(&self, peer_id: u64) -> Result<(), Error> {
162        let tag = "AvdtpFacade::get_configuration";
163        if let Some(p) = self.get_peer_controller_by_id(peer_id) {
164            match p.get_configuration().await? {
165                Err(err) => {
166                    let err_msg = format_err!("Error: {:?}", err);
167                    fx_err_and_bail!(&with_line!(tag), err_msg)
168                }
169                Ok(()) => Ok(()),
170            }
171        } else {
172            fx_err_and_bail!(&with_line!(tag), format!("Peer id {:?} not found.", peer_id))
173        }
174    }
175
176    /// Initiate a procedure to get the capabilities for the input peer_id.
177    ///
178    /// # Arguments
179    /// * `peer_id`: The peer id associated with the PeerController.
180    pub async fn get_capabilities(&self, peer_id: u64) -> Result<(), Error> {
181        let tag = "AvdtpFacade::get_capabilities";
182        if let Some(p) = self.get_peer_controller_by_id(peer_id) {
183            let result = p.get_capabilities().await;
184            match result {
185                Ok(capabilities) => info!("{:?}", capabilities),
186                Err(e) => fx_err_and_bail!(
187                    &with_line!(tag),
188                    format_err!("Error getting capabilities: {:?}", e)
189                ),
190            };
191            Ok(())
192        } else {
193            fx_err_and_bail!(&with_line!(tag), format!("Peer id {:?} not found.", peer_id))
194        }
195    }
196
197    /// Initiate a procedure to get all the capabilities for the input peer_id.
198    ///
199    /// # Arguments
200    /// * `peer_id`: The peer id associated with the PeerController.
201    pub async fn get_all_capabilities(&self, peer_id: u64) -> Result<(), Error> {
202        let tag = "AvdtpFacade::get_all_capabilities";
203        if let Some(p) = self.get_peer_controller_by_id(peer_id) {
204            let result = p.get_all_capabilities().await;
205            match result {
206                Ok(capabilities) => info!("{:?}", capabilities),
207                Err(e) => fx_err_and_bail!(
208                    &with_line!(tag),
209                    format_err!("Error getting capabilities: {:?}", e)
210                ),
211            };
212            Ok(())
213        } else {
214            fx_err_and_bail!(&with_line!(tag), format!("Peer id {:?} not found.", peer_id))
215        }
216    }
217
218    /// Initiate a suspend request to the stream for the input peer_id.
219    /// This command will not resume nor reconfigure the stream.
220    ///
221    /// # Arguments
222    /// * `peer_id`: The peer id associated with the PeerController.
223    pub async fn reconfigure_stream(&self, peer_id: u64) -> Result<(), Error> {
224        let tag = "AvdtpFacade::reconfigure_stream";
225        if let Some(p) = self.get_peer_controller_by_id(peer_id) {
226            match p.reconfigure_stream().await? {
227                Err(err) => {
228                    let err_msg = format_err!("Error: {:?}", err);
229                    fx_err_and_bail!(&with_line!(tag), err_msg)
230                }
231                Ok(()) => Ok(()),
232            }
233        } else {
234            fx_err_and_bail!(&with_line!(tag), format!("Peer id {:?} not found.", peer_id))
235        }
236    }
237
238    /// A "chained" set of procedures on the current stream for the input peer_id.
239    /// SuspendStream() followed by ReconfigureStream().
240    /// Reconfigure() configures the stream that is currently open.
241    ///
242    /// # Arguments
243    /// * `peer_id`: The peer id associated with the PeerController.
244    pub async fn suspend_stream(&self, peer_id: u64) -> Result<(), Error> {
245        let tag = "AvdtpFacade::suspend_stream";
246        if let Some(p) = self.get_peer_controller_by_id(peer_id) {
247            match p.suspend_stream().await? {
248                Err(err) => {
249                    let err_msg = format_err!("Error: {:?}", err);
250                    fx_err_and_bail!(&with_line!(tag), err_msg)
251                }
252                Ok(()) => Ok(()),
253            }
254        } else {
255            fx_err_and_bail!(&with_line!(tag), format!("Peer id {:?} not found.", peer_id))
256        }
257    }
258
259    /// Initiate a procedure to get the capabilities for the input peer_id.
260    ///
261    /// # Arguments
262    /// * `peer_id`: The peer id associated with the PeerController.
263    pub async fn suspend_and_reconfigure(&self, peer_id: u64) -> Result<(), Error> {
264        let tag = "AvdtpFacade::suspend_and_reconfigure";
265        if let Some(p) = self.get_peer_controller_by_id(peer_id) {
266            match p.suspend_and_reconfigure().await? {
267                Err(err) => {
268                    let err_msg = format_err!("Error: {:?}", err);
269                    fx_err_and_bail!(&with_line!(tag), err_msg)
270                }
271                Ok(()) => Ok(()),
272            }
273        } else {
274            fx_err_and_bail!(&with_line!(tag), format!("Peer id {:?} not found.", peer_id))
275        }
276    }
277
278    /// Release the current stream that is owned by the input peer_id.
279    /// If the streaming channel doesn't exist, no action will be taken.
280    ///
281    /// # Arguments
282    /// * `peer_id`: The peer id associated with the PeerController.
283    pub async fn release_stream(&self, peer_id: u64) -> Result<(), Error> {
284        let tag = "AvdtpFacade::release_stream";
285        if let Some(p) = self.get_peer_controller_by_id(peer_id) {
286            match p.release_stream().await? {
287                Err(err) => {
288                    let err_msg = format_err!("Error: {:?}", err);
289                    fx_err_and_bail!(&with_line!(tag), err_msg)
290                }
291                Ok(()) => Ok(()),
292            }
293        } else {
294            fx_err_and_bail!(&with_line!(tag), format!("Peer id {:?} not found.", peer_id))
295        }
296    }
297
298    /// Initiate stream establishment for the input peer_id.
299    ///
300    /// # Arguments
301    /// * `peer_id`: The peer id associated with the PeerController.
302    pub async fn establish_stream(&self, peer_id: u64) -> Result<(), Error> {
303        let tag = "AvdtpFacade::establish_stream";
304        if let Some(p) = self.get_peer_controller_by_id(peer_id) {
305            match p.establish_stream().await? {
306                Err(err) => {
307                    let err_msg = format_err!("Error: {:?}", err);
308                    fx_err_and_bail!(&with_line!(tag), err_msg)
309                }
310                Ok(()) => Ok(()),
311            }
312        } else {
313            fx_err_and_bail!(&with_line!(tag), format!("Peer id {:?} not found.", peer_id))
314        }
315    }
316
317    /// Start stream for the input peer_id.
318    ///
319    /// # Arguments
320    /// * `peer_id`: The peer id associated with the PeerController.
321    pub async fn start_stream(&self, peer_id: u64) -> Result<(), Error> {
322        let tag = "AvdtpFacade::start_stream";
323        if let Some(p) = self.get_peer_controller_by_id(peer_id) {
324            match p.start_stream().await? {
325                Err(err) => {
326                    let err_msg = format_err!("Error: {:?}", err);
327                    fx_err_and_bail!(&with_line!(tag), err_msg)
328                }
329                Ok(()) => Ok(()),
330            }
331        } else {
332            fx_err_and_bail!(&with_line!(tag), format!("Peer id {:?} not found.", peer_id))
333        }
334    }
335
336    /// Abort stream for the input peer_id.
337    ///
338    /// # Arguments
339    /// * `peer_id`: The peer id associated with the PeerController.
340    pub async fn abort_stream(&self, peer_id: u64) -> Result<(), Error> {
341        let tag = "AvdtpFacade::abort_stream";
342        if let Some(p) = self.get_peer_controller_by_id(peer_id) {
343            match p.abort_stream().await? {
344                Err(err) => {
345                    let err_msg = format_err!("Error: {:?}", err);
346                    fx_err_and_bail!(&with_line!(tag), err_msg)
347                }
348                Ok(()) => Ok(()),
349            }
350        } else {
351            fx_err_and_bail!(&with_line!(tag), format!("Peer id {:?} not found.", peer_id))
352        }
353    }
354
355    /// A function to monitor incoming events from the Avdtp Event Stream.
356    async fn monitor_avdtp_event_stream(
357        avdtp_svc: PeerManagerProxy,
358        peer_map: Arc<RwLock<PeerFactoryMap>>,
359    ) -> Result<(), Error> {
360        let tag = "AvdtpFacade::monitor_avdtp_event_stream";
361        let mut stream = avdtp_svc.take_event_stream();
362
363        while let Some(evt) = stream.next().await {
364            match evt {
365                Ok(e) => match e {
366                    PeerManagerEvent::OnPeerConnected { peer_id } => {
367                        let (client, server) = create_endpoints::<PeerControllerMarker>();
368                        let peer = client.into_proxy();
369                        match peer_map.write().entry(peer_id.value.to_string()) {
370                            Entry::Occupied(mut entry) => {
371                                entry.insert(peer);
372                                info!("Overriding device in PeerFactoryMap");
373                            }
374                            Entry::Vacant(entry) => {
375                                entry.insert(peer);
376                                info!("Inserted device into PeerFactoryMap");
377                            }
378                        };
379                        // Establish channel with the given peer_id and server endpoint.
380                        let _ = avdtp_svc.get_peer(&peer_id, server);
381                        info!("Getting peer with peer_id: {}", peer_id.value);
382                    }
383                },
384                Err(e) => {
385                    let log_err = format_err!("Error during handling request stream: {}", e);
386                    fx_err_and_bail!(&with_line!(tag), log_err)
387                }
388            }
389        }
390        Ok(())
391    }
392
393    /// A function to remove the profile service proxy and clear connected devices.
394    fn clear(&self) {
395        self.inner.write().peer_map.write().clear();
396        self.inner.write().avdtp_service_proxy = None;
397    }
398
399    /// A function to remove the profile service proxy and clear connected devices.
400    pub async fn remove_service(&self) {
401        self.clear()
402    }
403
404    /// Cleanup any Profile Server related objects.
405    pub async fn cleanup(&self) -> Result<(), Error> {
406        self.clear();
407        Ok(())
408    }
409}