bt_hfp/audio/
partial_offload.rs1use fidl_fuchsia_media as media;
6use fuchsia_bluetooth::types::PeerId;
7use futures::StreamExt;
8use futures::stream::BoxStream;
9use std::collections::{HashMap, HashSet};
10
11use crate::codec_id::CodecId;
12use crate::sco;
13
14use super::dai::DaiControl;
15use super::inband::InbandControl;
16use super::{Control, ControlEvent, Error};
17
18pub struct PartialOffloadControl {
22 offload_codecids: HashSet<CodecId>,
23 offload: Box<dyn Control>,
25 inband: InbandControl,
27 started: HashMap<PeerId, bool>,
29}
30
31impl PartialOffloadControl {
32 pub async fn setup_audio_core(
33 audio_proxy: media::AudioDeviceEnumeratorProxy,
34 offload_supported: HashSet<CodecId>,
35 ) -> Result<Self, Error> {
36 let dai = DaiControl::discover(audio_proxy.clone()).await?;
37 let inband = InbandControl::create(audio_proxy)?;
38 Ok(Self {
39 offload_codecids: offload_supported,
40 offload: Box::new(dai),
41 inband,
42 started: Default::default(),
43 })
44 }
45}
46
47impl Control for PartialOffloadControl {
48 fn start(
49 &mut self,
50 id: PeerId,
51 connection: sco::Connection,
52 codec: CodecId,
53 ) -> Result<(), Error> {
54 if self.started.contains_key(&id) {
55 return Err(Error::AlreadyStarted);
56 }
57 let result = if self.offload_codecids.contains(&codec) {
58 self.offload.start(id, connection, codec)
59 } else {
60 self.inband.start(id, connection, codec)
61 };
62 if result.is_ok() {
63 let _ = self.started.insert(id, self.offload_codecids.contains(&codec));
64 }
65 result
66 }
67
68 fn stop(&mut self, id: PeerId) -> Result<(), Error> {
69 let stop_result = match self.started.get(&id) {
70 None => return Err(Error::NotStarted),
71 Some(true) => self.offload.stop(id),
72 Some(false) => self.inband.stop(id),
73 };
74 if stop_result.is_ok() {
75 let _ = self.started.remove(&id);
76 }
77 stop_result
78 }
79
80 fn connect(&mut self, id: PeerId, supported_codecs: &[CodecId]) {
81 self.inband.connect(id, supported_codecs);
84 if supported_codecs.iter().any(|i| self.offload_codecids.contains(i)) {
85 self.offload.connect(id, supported_codecs);
86 }
87 }
88
89 fn disconnect(&mut self, id: PeerId) {
90 self.inband.disconnect(id);
91 self.offload.disconnect(id);
92 }
93
94 fn take_events(&self) -> BoxStream<'static, ControlEvent> {
95 let inband_events = self.inband.take_events();
96 let controller_events = self.offload.take_events();
97 futures::stream::select_all([inband_events, controller_events]).boxed()
98 }
99
100 fn failed_request(&self, request: ControlEvent, error: Error) {
101 self.offload.failed_request(request, error);
104 }
105}