1use anyhow::{bail, format_err, Error};
6use async_utils::hanging_get::client::HangingGetStream;
7use derivative::Derivative;
8use fidl_fuchsia_bluetooth::PeerId;
9use fidl_fuchsia_bluetooth_hfp::{
10 CallAction, CallDirection, CallManagerMarker, CallManagerRequest, CallManagerRequestStream,
11 CallMarker, CallRequest, CallRequestStream, CallState as FidlCallState,
12 CallWatchStateResponder, DtmfCode, HeadsetGainProxy, HfpMarker, HfpProxy, NetworkInformation,
13 NextCall, PeerHandlerRequest, PeerHandlerRequestStream,
14 PeerHandlerWatchNetworkInformationResponder, PeerHandlerWatchNextCallResponder, SignalStrength,
15};
16use fidl_fuchsia_bluetooth_hfp_test::{ConnectionBehavior, HfpTestMarker, HfpTestProxy};
17use fuchsia_async as fasync;
18use fuchsia_component::client;
19use futures::lock::Mutex;
20use futures::stream::StreamExt;
21use futures::{FutureExt, TryStreamExt};
22use log::*;
23use serde::Serialize;
24use std::collections::{HashMap, VecDeque};
25use std::sync::Arc;
26
27type CallId = u64;
28type Number = String;
29type Memory = String;
30
31#[derive(Debug, Default, Clone)]
33struct Dialer {
34 last_dialed: Option<Number>,
36 address_book: HashMap<Memory, Number>,
38 dial_result: HashMap<Number, zx::Status>,
40}
41
42impl Dialer {
43 pub fn dial(&mut self, action: CallAction) -> Result<Number, zx::Status> {
51 let number = match &action {
52 CallAction::TransferActive(_) => panic!("TransferActive action passed to dial"),
53 CallAction::DialFromNumber(number) => Ok(number),
54 CallAction::DialFromLocation(location) => {
55 self.address_book.get(location).ok_or(zx::Status::NOT_FOUND)
56 }
57 CallAction::RedialLast(_) => self.last_dialed.as_ref().ok_or(zx::Status::NOT_FOUND),
58 }?
59 .to_owned();
60
61 let result = self.dial_result.get(&number).cloned().unwrap_or(zx::Status::NOT_FOUND);
62 info!("Dial action result: {:?} - {:?}", action, result);
63 if result == zx::Status::OK {
64 self.last_dialed = Some(number.clone());
65 Ok(number)
66 } else {
67 Err(result)
68 }
69 }
70}
71
72#[derive(Derivative)]
73#[derivative(Debug)]
74struct ManagerState {
76 #[derivative(Debug = "ignore")]
77 peer_watcher: Option<fasync::Task<()>>,
78 network: NetworkInformation,
79 operator: String,
80 subscriber_numbers: Vec<String>,
81 nrec_support: bool,
82 battery_level: Option<u8>,
83 dialer: Dialer,
84}
85
86impl Default for ManagerState {
87 fn default() -> Self {
88 Self {
89 peer_watcher: None,
90 network: NetworkInformation::default(),
91 operator: String::new(),
92 subscriber_numbers: vec![],
93 nrec_support: true,
94 battery_level: None,
95 dialer: Dialer::default(),
96 }
97 }
98}
99
100#[derive(Derivative)]
102#[derivative(Debug, Default)]
103struct PeerState {
104 reported_network: Option<NetworkInformation>,
105 network_responder: Option<PeerHandlerWatchNetworkInformationResponder>,
106 #[derivative(Default(value = "true"))]
108 nrec_enabled: bool,
109 battery_level: u8,
110 speaker_gain: u8,
111 requested_speaker_gain: Option<u8>,
112 microphone_gain: u8,
113 requested_microphone_gain: Option<u8>,
114 #[derivative(Debug = "ignore")]
115 gain_control_watcher: Option<fasync::Task<()>>,
116 gain_control: Option<HeadsetGainProxy>,
117 call_responder: Option<PeerHandlerWatchNextCallResponder>,
118 #[derivative(Debug = "ignore")]
121 call_tasks: HashMap<CallId, fasync::Task<()>>,
122}
123
124#[derive(Derivative)]
126#[derivative(Debug)]
127struct CallState {
128 remote: String,
129 peer_id: Option<PeerId>,
130 responder: Option<CallWatchStateResponder>,
131 state: FidlCallState,
132 direction: CallDirection,
133 reported_state: Option<FidlCallState>,
134 dtmf_codes: Vec<DtmfCode>,
135}
136
137impl CallState {
138 pub fn update_state(&mut self, state: FidlCallState) -> Result<(), Error> {
141 self.state = state;
142 if self.reported_state != Some(state) && self.responder.is_some() {
143 let responder =
144 self.responder.take().expect("responder must be some after checking for presence");
145 responder.send(state)?;
146 self.reported_state = Some(state);
147 }
148 Ok(())
149 }
150}
151
152#[derive(Serialize)]
153pub struct StateSer {
154 manager: ManagerStateSer,
155 peers: HashMap<u64, PeerStateSer>,
156 calls: HashMap<CallId, CallStateSer>,
157}
158
159#[derive(Serialize)]
160pub struct ManagerStateSer {
161 network: NetworkInformationSer,
162 operator: String,
163 subscriber_numbers: Vec<String>,
164 nrec_support: bool,
165 battery_level: Option<u8>,
166 dialer: DialerSer,
167}
168
169#[derive(Serialize)]
170pub struct NetworkInformationSer {
171 service_available: Option<bool>,
172 signal_strength: Option<u8>,
173 roaming: Option<bool>,
174}
175
176impl From<NetworkInformation> for NetworkInformationSer {
177 fn from(info: NetworkInformation) -> Self {
178 let signal_strength = info.signal_strength.map(|strength| match strength {
179 SignalStrength::None => 0,
180 SignalStrength::VeryLow => 1,
181 SignalStrength::Low => 2,
182 SignalStrength::Medium => 3,
183 SignalStrength::High => 4,
184 SignalStrength::VeryHigh => 5,
185 });
186 Self { service_available: info.service_available, signal_strength, roaming: info.roaming }
187 }
188}
189
190impl From<&ManagerState> for ManagerStateSer {
191 fn from(state: &ManagerState) -> Self {
192 Self {
193 network: state.network.clone().into(),
194 operator: state.operator.clone(),
195 subscriber_numbers: state.subscriber_numbers.clone(),
196 nrec_support: state.nrec_support.clone(),
197 battery_level: state.battery_level.clone(),
198 dialer: state.dialer.clone().into(),
199 }
200 }
201}
202
203#[derive(Serialize)]
204struct PeerStateSer {
205 reported_network: Option<NetworkInformationSer>,
206 nrec_enabled: bool,
207 battery_level: u8,
208 speaker_gain: u8,
209 requested_speaker_gain: Option<u8>,
210 microphone_gain: u8,
211 requested_microphone_gain: Option<u8>,
212}
213
214impl From<&PeerState> for PeerStateSer {
215 fn from(state: &PeerState) -> Self {
216 Self {
217 reported_network: state.reported_network.clone().map(Into::into),
218 nrec_enabled: state.nrec_enabled,
219 battery_level: state.battery_level,
220 speaker_gain: state.speaker_gain,
221 requested_speaker_gain: state.requested_speaker_gain,
222 microphone_gain: state.microphone_gain,
223 requested_microphone_gain: state.requested_microphone_gain,
224 }
225 }
226}
227
228#[derive(Serialize)]
229struct CallStateSer {
230 remote: String,
231 direction: String,
232 state: String,
233 reported_state: Option<String>,
234 dtmf_codes: Vec<String>,
235}
236
237impl From<&CallState> for CallStateSer {
238 fn from(state: &CallState) -> Self {
239 Self {
240 remote: state.remote.clone(),
241 direction: format!("{:?}", state.direction),
242 state: format!("{:?}", state.state),
243 reported_state: state.reported_state.clone().map(|s| format!("{:?}", s)),
244 dtmf_codes: state.dtmf_codes.iter().map(|code| format!("{:?}", code)).collect(),
245 }
246 }
247}
248
249#[derive(Serialize)]
250struct DialerSer {
251 last_dialed: Option<Number>,
253 address_book: HashMap<Memory, Number>,
255 dial_result: HashMap<Number, String>,
257}
258
259impl From<Dialer> for DialerSer {
260 fn from(dialer: Dialer) -> Self {
261 Self {
262 last_dialed: dialer.last_dialed,
263 address_book: dialer.address_book,
264 dial_result: dialer
265 .dial_result
266 .into_iter()
267 .map(|(k, v)| (k, format!("{:?}", v)))
268 .collect(),
269 }
270 }
271}
272
273#[derive(Derivative, Default)]
274#[derivative(Debug)]
275struct TestCallManagerInner {
276 #[derivative(Debug = "ignore")]
278 test_proxy: Option<HfpTestProxy>,
279 manager: ManagerState,
281 active_peer: Option<PeerId>,
283 peers: HashMap<PeerId, PeerState>,
285 next_call_id: CallId,
287 #[derivative(Debug = "ignore")]
289 calls: HashMap<CallId, CallState>,
290 unreported_calls: VecDeque<CallId>,
292}
293
294impl TestCallManagerInner {
295 pub fn remove_peer(&mut self, id: PeerId) {
297 let _ = self.peers.remove(&id);
298
299 for call in self.calls.values_mut() {
300 if call.peer_id == Some(id) {
301 call.peer_id = None;
302 }
303 }
304
305 if self.active_peer == Some(id) {
306 self.active_peer = None;
307 }
308 }
309
310 pub fn active_peer_mut(&mut self) -> Option<&mut PeerState> {
311 if let Some(id) = &self.active_peer {
312 Some(self.peers.get_mut(id).expect("Active peer must exist in peers map"))
313 } else {
314 None
315 }
316 }
317}
318
319#[derive(Debug, Clone)]
320pub struct TestCallManager {
321 inner: Arc<Mutex<TestCallManagerInner>>,
322}
323
324impl TestCallManager {
327 pub fn new() -> TestCallManager {
328 TestCallManager { inner: Arc::new(Mutex::new(TestCallManagerInner::default())) }
329 }
330
331 pub async fn set_request_stream(&self, stream: CallManagerRequestStream) {
332 let task =
333 fasync::Task::spawn(self.clone().watch_for_peers(stream).map(|f| f.unwrap_or({})));
334 self.inner.lock().await.manager.peer_watcher = Some(task);
335 }
336
337 pub async fn register_manager(&self, proxy: HfpProxy) -> Result<(), Error> {
338 let (client_end, stream) = fidl::endpoints::create_request_stream::<CallManagerMarker>();
339 proxy.register(client_end)?;
340 self.set_request_stream(stream).await;
341 Ok(())
342 }
343
344 pub async fn init_hfp_service(&self) -> Result<(), Error> {
346 let mut inner = self.inner.lock().await;
347
348 if inner.manager.peer_watcher.is_none() {
349 info!("Connecting to HFP and setting new service proxy");
350
351 let hfp_service_proxy = client::connect_to_protocol::<HfpMarker>()
352 .map_err(|err| format_err!("Failed to create HFP service proxy: {}", err))?;
353
354 inner.test_proxy =
355 Some(client::connect_to_protocol::<HfpTestMarker>().map_err(|err| {
356 format_err!("Failed to create HFP Test service proxy: {}", err)
357 })?);
358
359 let (client_end, stream) =
360 fidl::endpoints::create_request_stream::<CallManagerMarker>();
361 hfp_service_proxy.register(client_end)?;
362
363 let task =
364 fasync::Task::spawn(self.clone().watch_for_peers(stream).map(|f| f.unwrap_or({})));
365
366 inner.manager.peer_watcher = Some(task);
367 }
368 Ok(())
369 }
370
371 pub async fn list_calls(&self) -> Result<Vec<(u64, String)>, Error> {
373 let inner = self.inner.lock().await;
374 Ok(inner.calls.iter().map(|(&id, state)| (id, state.remote.clone())).collect())
375 }
376
377 pub async fn new_call(
385 &self,
386 remote: &str,
387 fidl_state: FidlCallState,
388 direction: CallDirection,
389 ) -> Result<CallId, Error> {
390 let remote = remote.to_string();
391 let mut inner = self.inner.lock().await;
392 let call_id = inner.next_call_id;
393 inner.next_call_id += 1;
394 let mut state = CallState {
395 remote: remote.clone(),
396 peer_id: None,
397 responder: None,
398 state: fidl_state,
399 direction,
400 reported_state: None,
401 dtmf_codes: vec![],
402 };
403
404 if let Some(peer_id) = inner.active_peer.clone() {
405 let peer = inner.peers.get_mut(&peer_id).expect("Active peer must exist in peers map");
406
407 let (client_end, stream) = fidl::endpoints::create_request_stream::<CallMarker>();
408 let responder = peer
410 .call_responder
411 .take()
412 .ok_or_else(|| format_err!("No peer call responder for {:?}", peer_id))?;
413 let next_call = NextCall {
414 call: Some(client_end),
415 remote: Some(remote),
416 state: Some(fidl_state),
417 direction: Some(direction),
418 ..Default::default()
419 };
420 if let Ok(()) = responder.send(next_call) {
421 let task = fasync::Task::local(self.clone().manage_call(peer_id, call_id, stream));
422 let _ = peer.call_tasks.insert(call_id, task);
423 state.peer_id = Some(peer_id);
424 }
425 } else {
426 inner.unreported_calls.push_back(call_id);
427 }
428
429 let _ = inner.calls.insert(call_id, state);
430 Ok(call_id)
431 }
432
433 pub async fn incoming_ringing_call(&self, remote: &str) -> Result<CallId, Error> {
440 self.new_call(remote, FidlCallState::IncomingRinging, CallDirection::MobileTerminated).await
441 }
442
443 pub async fn incoming_waiting_call(&self, remote: &str) -> Result<CallId, Error> {
450 self.new_call(remote, FidlCallState::IncomingWaiting, CallDirection::MobileTerminated).await
451 }
452
453 pub async fn outgoing_call(&self, remote: &str) -> Result<CallId, Error> {
460 self.new_call(remote, FidlCallState::OutgoingDialing, CallDirection::MobileOriginated).await
461 }
462
463 async fn update_call(&self, call_id: CallId, fidl_state: FidlCallState) -> Result<(), Error> {
469 self.inner
471 .lock()
472 .await
473 .calls
474 .get_mut(&call_id)
475 .ok_or_else(|| format_err!("Unknown Call Id {}", call_id))
476 .and_then(|call| call.update_state(fidl_state))
477 }
478
479 pub async fn set_call_active(&self, call_id: CallId) -> Result<(), Error> {
484 match self.update_call(call_id, FidlCallState::OngoingActive).await {
485 Ok(()) => Ok(()),
486 Err(e) => Err(format_err!("Failed to set call active: {}", e)),
487 }
488 }
489
490 pub async fn set_call_held(&self, call_id: CallId) -> Result<(), Error> {
495 match self.update_call(call_id, FidlCallState::OngoingHeld).await {
496 Ok(()) => Ok(()),
497 Err(e) => Err(format_err!("Failed to set call active: {}", e)),
498 }
499 }
500
501 pub async fn set_call_terminated(&self, call_id: CallId) -> Result<(), Error> {
506 match self.update_call(call_id, FidlCallState::Terminated).await {
507 Ok(()) => Ok(()),
508 Err(e) => Err(format_err!("Failed to terminate call: {}", e)),
509 }
510 }
511
512 pub async fn set_call_transferred_to_ag(&self, call_id: CallId) -> Result<(), Error> {
517 match self.update_call(call_id, FidlCallState::TransferredToAg).await {
518 Ok(()) => Ok(()),
519 Err(e) => Err(format_err!("Failed to transfer call to ag: {}", e)),
520 }
521 }
522
523 pub async fn list_peers(&self) -> Result<Vec<(u64, bool)>, Error> {
526 let inner = self.inner.lock().await;
527 Ok(inner
528 .peers
529 .keys()
530 .map(|&id| (id.value, inner.active_peer.map(|active| active == id).unwrap_or(false)))
531 .collect())
532 }
533
534 pub async fn set_active_peer(&self, id: u64) -> Result<(), Error> {
540 let id = PeerId { value: id };
541 let mut inner = self.inner.lock().await;
542 if inner.peers.contains_key(&id) {
543 inner.active_peer = Some(id);
544 Ok(())
545 } else {
546 Err(format_err!("Peer {:?} not connected", id))
547 }
548 }
549
550 fn report_calls(
553 self,
554 id: PeerId,
555 mut inner: futures::lock::MutexGuard<'_, TestCallManagerInner>,
556 ) -> Result<(), Error> {
557 while let Some(cid) = inner.unreported_calls.pop_front() {
560 if let Some(call) = inner.calls.get(&cid) {
561 let remote = call.remote.clone();
562 let state = call.state;
563 let direction = call.direction;
564 let (client_end, stream) = fidl::endpoints::create_request_stream::<CallMarker>();
565 let peer = inner.peers.get_mut(&id).expect("peer just added");
566 let next_call = NextCall {
567 call: Some(client_end),
568 remote: Some(remote),
569 state: Some(state),
570 direction: Some(direction),
571 ..Default::default()
572 };
573 let res = peer.call_responder.take().expect("just put here").send(next_call);
574 if let Ok(()) = res {
575 let task = fasync::Task::local(self.manage_call(id, cid, stream));
576 let _ = peer.call_tasks.insert(cid, task);
577 inner.calls.get_mut(&cid).expect("still here").peer_id = Some(id);
578 }
579 break;
580 }
581 }
582 Ok(())
583 }
584
585 async fn handle_peer_request(
592 &mut self,
593 id: PeerId,
594 request: PeerHandlerRequest,
595 ) -> Result<(), Error> {
596 info!("Received Peer Handler request for {:?}: {:?}", id, request);
597 match request {
598 PeerHandlerRequest::WatchNetworkInformation { responder, .. } => {
599 let mut inner = self.inner.lock().await;
600 let current_network = inner.manager.network.clone();
601 let peer = inner
602 .peers
603 .get_mut(&id)
604 .ok_or_else(|| format_err!("peer removed: {:?}", id))?;
605
606 if Some(¤t_network) == peer.reported_network.as_ref() {
607 peer.network_responder = Some(responder);
608 } else {
609 responder.send(¤t_network)?;
610 peer.reported_network = Some(current_network);
611 }
612 }
613 PeerHandlerRequest::WatchNextCall { responder, .. } => {
614 let this = self.clone();
615 let mut inner = self.inner.lock().await;
616 let peer = inner
617 .peers
618 .get_mut(&id)
619 .ok_or_else(|| format_err!("peer removed: {:?}", id))?;
620 if peer.call_responder.is_none() {
621 peer.call_responder = Some(responder);
622 this.report_calls(id, inner)?;
623 } else {
624 let err = format_err!("double hanging get call on PeerHandler::WatchNextCall");
625 error!(err:%; "");
626 *inner = TestCallManagerInner::default();
627 return Err(err);
628 }
629 }
630 PeerHandlerRequest::RequestOutgoingCall { action, responder } => {
631 if let CallAction::TransferActive(_) = action {
632 let inner = self.inner.lock().await;
633 match inner
634 .calls
635 .iter()
636 .find(|(_, call)| call.state == FidlCallState::OngoingActive)
637 {
638 Some((&id, _)) => {
639 drop(inner);
640 let _ = self.update_call(id, FidlCallState::TransferredToAg).await;
642 }
643 None => drop(responder.send(Err(zx::Status::NOT_FOUND.into_raw()))),
644 };
645 } else {
646 let result = match {
649 let mut inner = self.inner.lock().await;
653 inner.manager.dialer.dial(action)
654 } {
655 Ok(number) => match self.outgoing_call(&number).await {
656 Ok(id) => {
657 info!(CallId = id; "Initiated outgoing call to {}", number);
658 Ok(())
659 }
660 Err(e) => {
661 error!("Could not initiate outgoing call action: {}", e);
662 Err(zx::Status::INTERNAL.into_raw())
663 }
664 },
665 Err(status) => Err(status.into_raw()),
666 };
667 info!("sending result to peer: {:?}", result);
668
669 let _ = responder.send(result);
671 }
672 }
673 PeerHandlerRequest::QueryOperator { responder, .. } => {
674 responder.send(Some(&self.inner.lock().await.manager.operator))?;
675 }
676 PeerHandlerRequest::SubscriberNumberInformation { responder, .. } => {
677 responder.send(&self.inner.lock().await.manager.subscriber_numbers)?;
678 }
679 PeerHandlerRequest::SetNrecMode { enabled, responder, .. } => {
680 let mut inner = self.inner.lock().await;
681 if inner.manager.nrec_support {
682 let peer = inner
683 .peers
684 .get_mut(&id)
685 .ok_or_else(|| format_err!("peer removed: {:?}", id))?;
686 peer.nrec_enabled = enabled;
687 responder.send(Ok(()))?;
688 } else {
689 responder.send(Err(zx::Status::NOT_SUPPORTED.into_raw()))?;
690 }
691 }
692 PeerHandlerRequest::ReportHeadsetBatteryLevel { level, .. } => {
693 self.inner
694 .lock()
695 .await
696 .peers
697 .get_mut(&id)
698 .ok_or_else(|| format_err!("peer removed: {:?}", id))?
699 .battery_level = level;
700 }
701 PeerHandlerRequest::GainControl { control, .. } => {
702 let this = self.clone();
703 let proxy = control.into_proxy();
704 let proxy_ = proxy.clone();
705 let task = fasync::Task::spawn(async move {
706 let mut speaker_gain_stream =
707 HangingGetStream::new(proxy.clone(), HeadsetGainProxy::watch_speaker_gain);
708 let mut microphone_gain_stream = HangingGetStream::new(
709 proxy.clone(),
710 HeadsetGainProxy::watch_microphone_gain,
711 );
712
713 loop {
714 futures::select! {
715 gain = speaker_gain_stream.next() => {
716 let mut inner = this.inner.lock().await;
717 let peer = inner.peers.get_mut(&id);
718 match (peer, gain) {
719 (Some(peer), Some(Ok(gain))) => peer.speaker_gain = gain,
720 _ => break,
721 }
722 }
723 gain = microphone_gain_stream.next() => {
724 let mut inner = this.inner.lock().await;
725 let peer = inner.peers.get_mut(&id);
726 match (peer, gain) {
727 (Some(peer), Some(Ok(gain))) => peer.microphone_gain = gain,
728 _ => break,
729 }
730 }
731 }
732 }
733 info!("Headset gain control channel for peer {:?} closed", id);
734 });
735 let mut inner = self.inner.lock().await;
736 let peer = inner
737 .peers
738 .get_mut(&id)
739 .ok_or_else(|| format_err!("peer removed: {:?}", id))?;
740 if let Some(requested) = peer.requested_speaker_gain.take() {
741 proxy_.set_speaker_gain(requested)?;
742 }
743 if let Some(requested) = peer.requested_microphone_gain.take() {
744 proxy_.set_microphone_gain(requested)?;
745 }
746 peer.gain_control_watcher = Some(task);
747 peer.gain_control = Some(proxy_);
748 }
749 }
750 Ok(())
751 }
752
753 async fn manage_peer(mut self, id: PeerId, mut stream: PeerHandlerRequestStream) {
760 while let Some(Ok(request)) = stream.next().await {
761 if let Err(err) = self.handle_peer_request(id, request).await {
762 error!(err:%; "");
763 break;
764 };
765 }
766 self.inner.lock().await.remove_peer(id);
767 }
768
769 async fn watch_for_peers(
777 self,
778 mut stream: CallManagerRequestStream,
779 ) -> Result<(), fidl::Error> {
780 let mut peers = HashMap::new();
784 while let Some(CallManagerRequest::PeerConnected { id, handle, responder }) =
785 stream.try_next().await?
786 {
787 let stream = handle.into_stream();
788 info!("Handling Peer: {:?}", id);
789 {
790 let mut inner = self.inner.lock().await;
791 let _ = inner.peers.insert(id, PeerState::default());
792 inner.active_peer = Some(id);
793 }
794
795 let task = fasync::Task::spawn(self.clone().manage_peer(id, stream));
796 let _ = peers.insert(id, task);
797 let _ = responder.send();
798 }
799 Ok(())
800 }
801
802 async fn manage_call(self, peer_id: PeerId, call_id: CallId, mut stream: CallRequestStream) {
810 while let Some(request) = stream.next().await {
811 info!("Got call request: {:?} {:?} -> {:?}", peer_id, call_id, request);
812 let mut inner = self.inner.lock().await;
813 let state = if let Some(state) = inner.calls.get_mut(&call_id) {
814 state
815 } else {
816 info!("Call management by {:?} ended: {:?}", peer_id, call_id);
817 break;
818 };
819 match request {
820 Ok(CallRequest::WatchState { responder, .. }) => {
821 if state.responder.is_some() {
822 warn!("Call client sent multiple WatchState requests. Closing channel");
823 break;
824 }
825 state.responder = Some(responder);
826 if let Err(e) = state.update_state(state.state) {
829 info!("Call ended: {}", e);
830 break;
831 }
832 }
833 Ok(CallRequest::RequestHold { .. }) => {
834 if let Err(e) = state.update_state(FidlCallState::OngoingHeld) {
835 info!("Call ended: {}", e);
836 break;
837 }
838 }
839 Ok(CallRequest::RequestActive { .. }) => {
840 if let Err(e) = state.update_state(FidlCallState::OngoingActive) {
841 info!("Call ended: {}", e);
842 break;
843 }
844 }
845 Ok(CallRequest::RequestTerminate { .. }) => {
846 if let Err(e) = state.update_state(FidlCallState::Terminated) {
847 info!("Call ended: {}", e);
848 break;
849 }
850 }
851 Ok(CallRequest::RequestTransferAudio { .. }) => {
852 if let Err(e) = state.update_state(FidlCallState::TransferredToAg) {
853 info!("Call ended: {}", e);
854 break;
855 }
856 }
857 Ok(CallRequest::SendDtmfCode { code, responder, .. }) => {
858 state.dtmf_codes.push(code);
859 if let Err(e) = responder.send(Ok(())) {
860 info!("Call ended: {}", e);
861 break;
862 }
863 }
864 Err(e) => {
865 warn!("Call fidl channel error: {}", e);
866 }
867 }
868 }
869
870 let mut inner = self.inner.lock().await;
872 if let Some(call) = inner.calls.get_mut(&call_id) {
873 call.peer_id = None
874 }
875 if let Some(peer) = inner.peers.get_mut(&peer_id) {
876 let _ = peer.call_tasks.remove(&call_id);
877 }
878 }
879
880 pub async fn set_speaker_gain(&self, value: u64) -> Result<(), Error> {
885 let value = value as u8;
886 let mut inner = self.inner.lock().await;
887 let peer = inner.active_peer_mut().ok_or_else(|| format_err!("No active peer"))?;
888 if peer.speaker_gain != value {
889 if let Some(gain_control) = &peer.gain_control {
890 gain_control.set_speaker_gain(value)?;
891 } else {
892 peer.requested_speaker_gain = Some(value);
893 }
894 }
895 Ok(())
896 }
897
898 pub async fn set_microphone_gain(&self, value: u64) -> Result<(), Error> {
903 let value = value as u8;
904 let mut inner = self.inner.lock().await;
905 let peer = inner.active_peer_mut().ok_or_else(|| format_err!("No active peer"))?;
906 if peer.microphone_gain != value {
907 if let Some(gain_control) = &peer.gain_control {
908 gain_control.set_microphone_gain(value)?;
909 } else {
910 peer.requested_microphone_gain = Some(value);
911 }
912 }
913 Ok(())
914 }
915
916 pub async fn update_network_information(
922 &self,
923 network: NetworkInformation,
924 ) -> Result<(), Error> {
925 let mut inner = self.inner.lock().await;
926
927 let last_net = std::mem::replace(&mut inner.manager.network, NetworkInformation::default());
929 inner.manager.network = NetworkInformation {
930 service_available: network.service_available.or(last_net.service_available),
931 signal_strength: network.signal_strength.or(last_net.signal_strength),
932 roaming: network.roaming.or(last_net.roaming),
933 ..last_net
934 };
935 let current_network = inner.manager.network.clone();
936
937 for peer in inner.peers.values_mut() {
938 if Some(¤t_network) != peer.reported_network.as_ref() {
940 if let Some(responder) = peer.network_responder.take() {
941 responder.send(¤t_network)?;
942 peer.reported_network = Some(current_network.clone());
943 }
944 }
945 }
946
947 Ok(())
948 }
949
950 pub async fn set_subscriber_number(&self, number: &str) {
951 self.inner.lock().await.manager.subscriber_numbers = vec![number.to_owned()];
952 }
953
954 pub async fn set_operator(&self, value: &str) {
955 self.inner.lock().await.manager.operator = value.to_owned();
956 }
957
958 pub async fn set_nrec_support(&self, value: bool) {
959 self.inner.lock().await.manager.nrec_support = value;
960 }
961
962 pub async fn set_battery_level(&self, value: u64) -> Result<(), Error> {
963 if value > 5 {
964 bail!("Value out of range: {}. Battery level must be 0-5.", value);
965 }
966 let mut inner = self.inner.lock().await;
967 let proxy = inner
968 .test_proxy
969 .as_ref()
970 .ok_or_else(|| format_err!("Cannot set battery without HfpTest proxy"))?;
971 proxy.battery_indicator(value as u8)?;
972 inner.manager.battery_level = Some(value as u8);
973 Ok(())
974 }
975
976 pub async fn get_state(&self) -> StateSer {
977 let inner = self.inner.lock().await;
978 StateSer {
979 manager: (&inner.manager).into(),
980 peers: inner
981 .peers
982 .iter()
983 .map(|(&PeerId { value: id }, peer)| (id, peer.into()))
984 .collect(),
985 calls: inner.calls.iter().map(|(&id, call)| (id, call.into())).collect(),
986 }
987 }
988
989 pub async fn set_last_dialed(&self, number: Option<Number>) {
994 self.inner.lock().await.manager.dialer.last_dialed = number;
995 }
996
997 pub async fn set_memory_location(&self, location: Memory, number: Option<Number>) {
1003 let _ = match number {
1004 Some(number) => {
1005 self.inner.lock().await.manager.dialer.address_book.insert(location, number)
1006 }
1007 None => self.inner.lock().await.manager.dialer.address_book.remove(&location),
1008 };
1009 }
1010
1011 pub async fn set_dial_result(&self, number: Number, status: zx::Status) {
1020 let _ = self.inner.lock().await.manager.dialer.dial_result.insert(number, status);
1021 }
1022
1023 pub async fn set_connection_behavior(&self, autoconnect: bool) -> Result<(), Error> {
1030 let inner = self.inner.lock().await;
1031 let proxy = inner.test_proxy.as_ref().ok_or_else(|| {
1032 format_err!("Cannot set slc connection behavior on command without HfpTest proxy")
1033 })?;
1034 let () = proxy.set_connection_behavior(&ConnectionBehavior {
1035 autoconnect: Some(autoconnect),
1036 ..Default::default()
1037 })?;
1038 Ok(())
1039 }
1040
1041 pub async fn cleanup(&self) {
1043 *self.inner.lock().await = TestCallManagerInner::default();
1044 }
1045}
1046
1047#[cfg(test)]
1048mod tests {
1049 use super::*;
1050 use fidl_fuchsia_bluetooth_hfp::PeerHandlerMarker;
1051
1052 #[fuchsia::test]
1053 async fn outgoing_call_does_not_deadlock() {
1054 let manager = TestCallManager::new();
1055
1056 manager.set_dial_result("123".to_string(), zx::Status::OK).await;
1058
1059 let (proxy, stream) = fidl::endpoints::create_proxy_and_stream::<PeerHandlerMarker>();
1060
1061 fasync::Task::local({
1063 let manager = manager.clone();
1064 async move {
1065 manager.manage_peer(PeerId { value: 1 }, stream).await;
1066 }
1067 })
1068 .detach();
1069
1070 let result =
1072 proxy.request_outgoing_call(&CallAction::DialFromNumber("123".to_string())).await;
1073 assert!(result.is_ok());
1074 }
1075}