1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#![recursion_limit = "1024"]
use {
anyhow::{format_err, Error},
battery_client::BatteryClient,
fuchsia_component::server::ServiceFs,
fuchsia_inspect_derive::Inspect,
futures::{channel::mpsc, future, pin_mut},
tracing::{debug, error, info, warn},
};
use crate::{
audio::AudioControl, config::AudioGatewayFeatureSupport, fidl_service::run_services, hfp::Hfp,
profile::register_audio_gateway,
};
mod a2dp;
mod audio;
mod config;
mod error;
mod features;
mod fidl_service;
mod hfp;
mod inspect;
mod peer;
mod profile;
mod sco_connector;
mod service_definitions;
#[fuchsia::main(logging_tags = ["hfp-ag"])]
async fn main() -> Result<(), Error> {
let mut fs = ServiceFs::new();
let inspector = fuchsia_inspect::Inspector::default();
if let Err(e) = inspect_runtime::serve(&inspector, &mut fs) {
warn!("Couldn't serve inspect: {}", e);
}
let config = hfp_profile_config::Config::take_from_startup_handle();
let in_band_sco = config.in_band_sco;
let feature_support = AudioGatewayFeatureSupport::load_from_config(config);
debug!(?feature_support, "Starting HFP Audio Gateway");
let (profile_client, profile_svc) = register_audio_gateway(feature_support)?;
let battery_client = match BatteryClient::create() {
Err(e) => {
info!("Power integration unavailable: {:?}", e);
None
}
Ok(batt) => Some(batt),
};
let (call_manager_sender, call_manager_receiver) = mpsc::channel(1);
let (test_request_sender, test_request_receiver) = mpsc::channel(1);
let audio: Box<dyn AudioControl> = if in_band_sco {
match audio::DaiAudioControl::discover().await {
Err(e) => {
error!(?e, "Couldn't setup DAI audio");
return Err(format_err!("DAI failed"));
}
Ok(audio) => Box::new(audio),
}
} else {
match audio::InbandAudioControl::create() {
Err(e) => {
error!(?e, "Couldn't setup inband audio");
return Err(format_err!("Inband failed: {e:?}"));
}
Ok(audio) => Box::new(audio),
}
};
let mut hfp = Hfp::new(
profile_client,
profile_svc,
battery_client,
audio,
call_manager_receiver,
feature_support,
in_band_sco,
test_request_receiver,
);
if let Err(e) = hfp.iattach(&inspector.root(), "hfp") {
warn!("Couldn't attach inspect to HFP: {:?}", e);
}
let hfp = hfp.run();
pin_mut!(hfp);
let services = run_services(fs, call_manager_sender, test_request_sender);
pin_mut!(services);
info!("HFP Audio Gateway running.");
match future::select(services, hfp).await {
future::Either::Left((Ok(()), _)) => {
warn!("Service FS directory handle closed. Exiting.");
}
future::Either::Left((Err(e), _)) => {
error!("Error encountered running Service FS: {}. Exiting", e);
}
future::Either::Right((Ok(()), _)) => {
warn!("All HFP related connections to this component have been disconnected. Exiting.");
}
future::Either::Right((Err(e), _)) => {
error!("Error encountered running main HFP loop: {}. Exiting.", e);
}
}
Ok(())
}