1use crate::legacy::{Iface, IfaceRef};
6use crate::mode_management::iface_manager_api::IfaceManagerApi;
7use crate::mode_management::phy_manager::PhyManagerApi;
8use anyhow::format_err;
9use fidl::endpoints::create_proxy;
10use fidl_fuchsia_wlan_common as fidl_common;
11use fidl_fuchsia_wlan_device_service::{DeviceMonitorProxy, DeviceWatcherEvent};
12use futures::lock::Mutex;
13use log::{error, info};
14use std::sync::Arc;
15
16pub struct Listener {
17 proxy: DeviceMonitorProxy,
18 legacy_shim: IfaceRef,
19 phy_manager: Arc<Mutex<dyn PhyManagerApi>>,
20 iface_manager: Arc<Mutex<dyn IfaceManagerApi>>,
21}
22
23pub async fn handle_event(listener: &Listener, evt: DeviceWatcherEvent) {
24 info!("got event: {:?}", evt);
25 match evt {
26 DeviceWatcherEvent::OnPhyAdded { phy_id } => {
27 on_phy_added(listener, phy_id).await;
28 }
29 DeviceWatcherEvent::OnPhyRemoved { phy_id } => {
30 info!("phy removed: {}", phy_id);
31 let mut phy_manager = listener.phy_manager.lock().await;
32 phy_manager.remove_phy(phy_id);
33 }
34 DeviceWatcherEvent::OnIfaceAdded { iface_id } => {
35 let mut iface_manager = listener.iface_manager.lock().await;
38 if let Err(e) = iface_manager.handle_added_iface(iface_id).await {
39 error!("Failed to add interface {} to IfaceManager: {}", iface_id, e);
40 return;
41 }
42
43 if let Err(e) = on_iface_added_legacy(listener, iface_id).await {
44 error!("error adding new iface {}: {}", iface_id, e)
45 }
46 }
47 DeviceWatcherEvent::OnIfaceRemoved { iface_id } => {
48 let mut iface_manager = listener.iface_manager.lock().await;
49 match iface_manager.handle_removed_iface(iface_id).await {
50 Ok(()) => {}
51 Err(e) => info!("Unable to record idle interface {}: {:?}", iface_id, e),
52 }
53
54 listener.legacy_shim.remove_if_matching(iface_id);
55 info!("iface removed: {}", iface_id);
56 }
57 }
58}
59
60async fn on_phy_added(listener: &Listener, phy_id: u16) {
61 info!("phy {} added", phy_id);
62 let mut phy_manager = listener.phy_manager.lock().await;
63 if let Err(e) = phy_manager.add_phy(phy_id).await {
64 info!("error adding new phy {}: {}", phy_id, e);
65 phy_manager.log_phy_add_failure();
66 }
67}
68
69async fn on_iface_added_legacy(listener: &Listener, iface_id: u16) -> Result<(), anyhow::Error> {
71 let response = match listener.proxy.query_iface(iface_id).await? {
72 Ok(response) => response,
73 Err(zx::sys::ZX_ERR_NOT_FOUND) => {
74 return Err(format_err!("Could not find iface: {}", iface_id));
75 }
76 Err(status) => return Err(format_err!("Could not query iface information: {}", status)),
77 };
78
79 let service = listener.proxy.clone();
80
81 match response.role {
82 fidl_common::WlanMacRole::Client => {
83 let legacy_shim = listener.legacy_shim.clone();
84 let (sme, remote) = create_proxy();
85
86 let result = service
87 .get_client_sme(iface_id, remote)
88 .await
89 .map_err(|e| format_err!("Failed to get client SME: {}", e))?;
90 result.map_err(|e| {
91 format_err!("GetClientSme returned an error: {}", zx::Status::err_from_raw(e))
92 })?;
93
94 let lc = Iface { sme: sme.clone(), iface_id };
95 legacy_shim.set_if_empty(lc);
96 }
97 fidl_common::WlanMacRole::Ap => {}
99 fidl_common::WlanMacRole::Mesh => {
100 return Err(format_err!("Unexpectedly observed a mesh iface: {}", iface_id));
101 }
102 fidl_common::WlanMacRoleUnknown!() => {
103 return Err(format_err!(
104 "Unknown WlanMacRole type {:?} on iface {}",
105 response.role,
106 iface_id
107 ));
108 }
109 }
110
111 info!("new iface {} added successfully", iface_id);
112 Ok(())
113}
114
115impl Listener {
116 pub fn new(
117 proxy: DeviceMonitorProxy,
118 legacy_shim: IfaceRef,
119 phy_manager: Arc<Mutex<dyn PhyManagerApi>>,
120 iface_manager: Arc<Mutex<dyn IfaceManagerApi>>,
121 ) -> Self {
122 Listener { proxy, legacy_shim, phy_manager, iface_manager }
123 }
124}
125
126#[cfg(test)]
127mod tests {
128 use super::*;
129 use crate::access_point::{state_machine as ap_fsm, types as ap_types};
130 use crate::client::types as client_types;
131 use crate::mode_management::Defect;
132 use crate::mode_management::iface_manager_api::{ConnectAttemptRequest, SmeForScan};
133 use crate::mode_management::phy_manager::{CreateClientIfacesReason, PhyManagerError};
134 use crate::mode_management::recovery::RecoverySummary;
135 use anyhow::Error;
136 use assert_matches::assert_matches;
137 use async_trait::async_trait;
138 use fidl_fuchsia_wlan_device_service as fidl_service;
139 use fidl_fuchsia_wlan_sme as fidl_sme;
140 use fuchsia_async as fasync;
141 use futures::StreamExt;
142 use futures::channel::oneshot;
143 use futures::task::Poll;
144 use ieee80211::MacAddr;
145 use std::collections::HashMap;
146 use std::pin::pin;
147
148 struct TestValues {
149 phy_manager: Arc<Mutex<FakePhyManager>>,
150 iface_manager: Arc<Mutex<FakeIfaceManager>>,
151 monitor_proxy: fidl_service::DeviceMonitorProxy,
152 monitor_stream: fidl_service::DeviceMonitorRequestStream,
153 }
154
155 fn test_setup(add_phy_succeeds: bool, add_iface_succeeds: bool) -> TestValues {
156 let phy_manager =
157 Arc::new(Mutex::new(FakePhyManager::new(add_phy_succeeds, add_iface_succeeds)));
158 let iface_manager = Arc::new(Mutex::new(FakeIfaceManager::new()));
159 let (monitor_proxy, monitor_requests) = create_proxy::<fidl_service::DeviceMonitorMarker>();
160 let monitor_stream = monitor_requests.into_stream();
161
162 TestValues { phy_manager, iface_manager, monitor_proxy, monitor_stream }
163 }
164
165 #[fuchsia::test]
166 fn test_phy_add_succeeds() {
167 let mut exec = fasync::TestExecutor::new();
168 let test_values = test_setup(true, false);
169
170 let listener = Listener::new(
171 test_values.monitor_proxy,
172 IfaceRef::new(),
173 test_values.phy_manager.clone(),
174 test_values.iface_manager.clone(),
175 );
176
177 let fut = on_phy_added(&listener, 0);
179 let mut fut = pin!(fut);
180 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(()));
181
182 let list_phys_fut = async move {
184 let phy_manager = test_values.phy_manager.lock().await;
185 phy_manager.phys.clone()
186 };
187 let mut list_phys_fut = pin!(list_phys_fut);
188 let phys =
189 assert_matches!(exec.run_until_stalled(&mut list_phys_fut), Poll::Ready(phys) => phys);
190
191 assert_eq!(phys, vec![0]);
192 }
193
194 #[fuchsia::test]
195 fn test_phy_add_fails() {
196 let mut exec = fasync::TestExecutor::new();
197 let test_values = test_setup(false, false);
198
199 let listener = Listener::new(
200 test_values.monitor_proxy,
201 IfaceRef::new(),
202 test_values.phy_manager.clone(),
203 test_values.iface_manager.clone(),
204 );
205
206 let fut = on_phy_added(&listener, 0);
208 let mut fut = pin!(fut);
209 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(()));
210
211 let phy_manager_fut = async move {
213 let phy_manager = test_values.phy_manager.lock().await;
214 assert!(phy_manager.phys.is_empty());
215 assert_eq!(phy_manager.failed_phys, 1);
216 };
217 let mut phy_manager_fut = pin!(phy_manager_fut);
218 assert_matches!(exec.run_until_stalled(&mut phy_manager_fut), Poll::Ready(()));
219 }
220
221 #[fuchsia::test]
222 fn test_add_legacy_ap_iface() {
223 let mut exec = fasync::TestExecutor::new();
224 let mut test_values = test_setup(false, false);
225
226 let listener = Listener::new(
227 test_values.monitor_proxy,
228 IfaceRef::new(),
229 test_values.phy_manager.clone(),
230 test_values.iface_manager.clone(),
231 );
232
233 let fut = on_iface_added_legacy(&listener, 0);
234 let mut fut = pin!(fut);
235
236 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
238
239 let iface_response = Some(fidl_service::QueryIfaceResponse {
241 role: fidl_common::WlanMacRole::Ap,
242 id: 0,
243 phy_id: 0,
244 phy_assigned_id: 0,
245 sta_addr: [0, 1, 2, 3, 4, 5],
246 factory_addr: [0, 1, 2, 3, 4, 5],
247 });
248 send_query_iface_response(&mut exec, &mut test_values.monitor_stream, iface_response);
249
250 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Ok(())));
252 }
253
254 #[fuchsia::test]
255 fn test_add_legacy_unknown_iface() {
256 let mut exec = fasync::TestExecutor::new();
257 let mut test_values = test_setup(false, false);
258
259 let listener = Listener::new(
260 test_values.monitor_proxy,
261 IfaceRef::new(),
262 test_values.phy_manager.clone(),
263 test_values.iface_manager.clone(),
264 );
265
266 let fut = on_iface_added_legacy(&listener, 0);
267 let mut fut = pin!(fut);
268
269 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
271
272 let iface_response = Some(fidl_service::QueryIfaceResponse {
274 role: fidl_common::WlanMacRole::unknown(),
275 id: 0,
276 phy_id: 0,
277 phy_assigned_id: 0,
278 sta_addr: [0, 1, 2, 3, 4, 5],
279 factory_addr: [0, 1, 2, 3, 4, 5],
280 });
281 send_query_iface_response(&mut exec, &mut test_values.monitor_stream, iface_response);
282
283 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
286 }
287
288 #[fuchsia::test]
289 fn test_add_legacy_mesh_iface() {
290 let mut exec = fasync::TestExecutor::new();
291 let mut test_values = test_setup(false, false);
292
293 let listener = Listener::new(
294 test_values.monitor_proxy,
295 IfaceRef::new(),
296 test_values.phy_manager.clone(),
297 test_values.iface_manager.clone(),
298 );
299
300 let fut = on_iface_added_legacy(&listener, 0);
301 let mut fut = pin!(fut);
302
303 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
305
306 let iface_response = Some(fidl_service::QueryIfaceResponse {
308 role: fidl_common::WlanMacRole::Mesh,
309 id: 0,
310 phy_id: 0,
311 phy_assigned_id: 0,
312 sta_addr: [0, 1, 2, 3, 4, 5],
313 factory_addr: [0, 1, 2, 3, 4, 5],
314 });
315 send_query_iface_response(&mut exec, &mut test_values.monitor_stream, iface_response);
316
317 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
319 }
320
321 #[fuchsia::test]
322 fn test_add_legacy_client_iface_succeeds() {
323 let mut exec = fasync::TestExecutor::new();
324 let mut test_values = test_setup(false, false);
325
326 let listener = Listener::new(
327 test_values.monitor_proxy,
328 IfaceRef::new(),
329 test_values.phy_manager.clone(),
330 test_values.iface_manager.clone(),
331 );
332
333 let fut = on_iface_added_legacy(&listener, 0);
334 let mut fut = pin!(fut);
335
336 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
338
339 let iface_response = Some(fidl_service::QueryIfaceResponse {
341 role: fidl_common::WlanMacRole::Client,
342 id: 0,
343 phy_id: 0,
344 phy_assigned_id: 0,
345 sta_addr: [0, 1, 2, 3, 4, 5],
346 factory_addr: [0, 1, 2, 3, 4, 5],
347 });
348 send_query_iface_response(&mut exec, &mut test_values.monitor_stream, iface_response);
349
350 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
352 assert_matches!(
353 exec.run_until_stalled(&mut test_values.monitor_stream.next()),
354 Poll::Ready(Some(Ok(fidl_service::DeviceMonitorRequest::GetClientSme {
355 iface_id: 0, sme_server: _, responder
356 }))) => {
357 assert!(responder.send(Ok(())).is_ok())
358 }
359 );
360
361 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Ok(())));
363
364 assert!(listener.legacy_shim.get().is_ok());
366 }
367
368 #[fuchsia::test]
369 fn test_add_legacy_client_iface_fails() {
370 let mut exec = fasync::TestExecutor::new();
371 let mut test_values = test_setup(false, false);
372
373 let listener = Listener::new(
374 test_values.monitor_proxy,
375 IfaceRef::new(),
376 test_values.phy_manager.clone(),
377 test_values.iface_manager.clone(),
378 );
379
380 let fut = on_iface_added_legacy(&listener, 0);
381 let mut fut = pin!(fut);
382
383 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
385
386 let iface_response = Some(fidl_service::QueryIfaceResponse {
388 role: fidl_common::WlanMacRole::Client,
389 id: 0,
390 phy_id: 0,
391 phy_assigned_id: 0,
392 sta_addr: [0, 1, 2, 3, 4, 5],
393 factory_addr: [0, 1, 2, 3, 4, 5],
394 });
395 send_query_iface_response(&mut exec, &mut test_values.monitor_stream, iface_response);
396
397 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
399 assert_matches!(
400 exec.run_until_stalled(&mut test_values.monitor_stream.next()),
401 Poll::Ready(Some(Ok(fidl_service::DeviceMonitorRequest::GetClientSme {
402 iface_id: 0, sme_server: _, responder
403 }))) => {
404 assert!(responder.send(Err(zx::sys::ZX_ERR_NOT_FOUND)).is_ok())
405 }
406 );
407
408 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
410
411 assert!(listener.legacy_shim.get().is_err());
413 }
414
415 #[fuchsia::test]
416 fn test_add_legacy_client_iface_query_fails() {
417 let mut exec = fasync::TestExecutor::new();
418 let test_values = test_setup(false, false);
419
420 let listener = Listener::new(
421 test_values.monitor_proxy,
422 IfaceRef::new(),
423 test_values.phy_manager.clone(),
424 test_values.iface_manager.clone(),
425 );
426
427 drop(test_values.monitor_stream);
429
430 let fut = on_iface_added_legacy(&listener, 0);
431 let mut fut = pin!(fut);
432
433 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
435
436 assert!(listener.legacy_shim.get().is_err());
438 }
439
440 #[fuchsia::test]
441 fn test_handle_add_phy_event() {
442 let mut exec = fasync::TestExecutor::new();
443 let test_values = test_setup(true, false);
444
445 let listener = Listener::new(
446 test_values.monitor_proxy,
447 IfaceRef::new(),
448 test_values.phy_manager.clone(),
449 test_values.iface_manager.clone(),
450 );
451
452 let fut = handle_event(&listener, DeviceWatcherEvent::OnPhyAdded { phy_id: 0 });
454 let mut fut = pin!(fut);
455 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(()));
456
457 let list_phys_fut = async move {
459 let phy_manager = test_values.phy_manager.lock().await;
460 phy_manager.phys.clone()
461 };
462 let mut list_phys_fut = pin!(list_phys_fut);
463 let phys =
464 assert_matches!(exec.run_until_stalled(&mut list_phys_fut), Poll::Ready(phys) => phys);
465
466 assert_eq!(phys, vec![0]);
467 }
468
469 #[fuchsia::test]
470 fn test_handle_remove_phy_event() {
471 let mut exec = fasync::TestExecutor::new();
472 let test_values = test_setup(false, false);
473
474 {
476 let phy_manager = test_values.phy_manager.clone();
477 let add_phy_fut = async move {
478 let mut phy_manager = phy_manager.lock().await;
479 phy_manager.phys.push(0);
480 };
481 let mut add_phy_fut = pin!(add_phy_fut);
482 assert_matches!(exec.run_until_stalled(&mut add_phy_fut), Poll::Ready(()));
483 }
484
485 let listener = Listener::new(
486 test_values.monitor_proxy,
487 IfaceRef::new(),
488 test_values.phy_manager.clone(),
489 test_values.iface_manager.clone(),
490 );
491
492 let fut = handle_event(&listener, DeviceWatcherEvent::OnPhyRemoved { phy_id: 0 });
494 let mut fut = pin!(fut);
495 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(()));
496
497 let list_phys_fut = async move {
499 let phy_manager = test_values.phy_manager.lock().await;
500 phy_manager.phys.clone()
501 };
502 let mut list_phys_fut = pin!(list_phys_fut);
503 let phys =
504 assert_matches!(exec.run_until_stalled(&mut list_phys_fut), Poll::Ready(phys) => phys);
505
506 assert!(phys.is_empty());
507 }
508
509 #[fuchsia::test]
510 fn test_handle_remove_nonexistent_iface_event() {
511 let mut exec = fasync::TestExecutor::new();
512 let test_values = test_setup(false, false);
513
514 {
516 let iface_manager = test_values.iface_manager.clone();
517 let add_iface_fut = async move {
518 let mut iface_manager = iface_manager.lock().await;
519 iface_manager.ifaces.push(0);
520 };
521 let mut add_iface_fut = pin!(add_iface_fut);
522 assert_matches!(exec.run_until_stalled(&mut add_iface_fut), Poll::Ready(()));
523 }
524
525 let (sme, _) = create_proxy::<fidl_sme::ClientSmeMarker>();
527 let iface_ref = IfaceRef::new();
528 iface_ref.set_if_empty(Iface { sme, iface_id: 0 });
529
530 let listener = Listener::new(
531 test_values.monitor_proxy,
532 iface_ref,
533 test_values.phy_manager.clone(),
534 test_values.iface_manager.clone(),
535 );
536
537 let fut = handle_event(&listener, DeviceWatcherEvent::OnIfaceRemoved { iface_id: 123 });
539 let mut fut = pin!(fut);
540 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(()));
541
542 assert!(listener.legacy_shim.get().is_ok());
544 }
545
546 #[fuchsia::test]
547 fn test_handle_remove_iface_event() {
548 let mut exec = fasync::TestExecutor::new();
549 let test_values = test_setup(false, false);
550
551 {
553 let iface_manager = test_values.iface_manager.clone();
554 let add_iface_fut = async move {
555 let mut iface_manager = iface_manager.lock().await;
556 iface_manager.ifaces.push(0);
557 };
558 let mut add_iface_fut = pin!(add_iface_fut);
559 assert_matches!(exec.run_until_stalled(&mut add_iface_fut), Poll::Ready(()));
560 }
561
562 let (sme, _) = create_proxy::<fidl_sme::ClientSmeMarker>();
564 let iface_ref = IfaceRef::new();
565 iface_ref.set_if_empty(Iface { sme, iface_id: 0 });
566
567 let listener = Listener::new(
568 test_values.monitor_proxy,
569 iface_ref,
570 test_values.phy_manager.clone(),
571 test_values.iface_manager.clone(),
572 );
573
574 let fut = handle_event(&listener, DeviceWatcherEvent::OnIfaceRemoved { iface_id: 0 });
576 let mut fut = pin!(fut);
577 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(()));
578
579 {
581 let phy_manager = test_values.phy_manager.clone();
582 let iface_manager = test_values.iface_manager.clone();
583 let verify_fut = async move {
584 let phy_manager = phy_manager.lock().await;
585 let iface_manager = iface_manager.lock().await;
586 assert!(phy_manager.ifaces.is_empty());
587 assert!(iface_manager.ifaces.is_empty());
588 };
589 let mut verify_fut = pin!(verify_fut);
590 assert_matches!(exec.run_until_stalled(&mut verify_fut), Poll::Ready(()));
591 }
592
593 assert!(listener.legacy_shim.get().is_err());
595 }
596
597 #[fuchsia::test]
598 fn test_handle_iface_added_succeeds() {
599 let mut exec = fasync::TestExecutor::new();
600 let mut test_values = test_setup(false, true);
601
602 let listener = Listener::new(
603 test_values.monitor_proxy,
604 IfaceRef::new(),
605 test_values.phy_manager.clone(),
606 test_values.iface_manager.clone(),
607 );
608
609 let fut = handle_event(&listener, DeviceWatcherEvent::OnIfaceAdded { iface_id: 0 });
610 let mut fut = pin!(fut);
611
612 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
614
615 let iface_response = Some(fidl_service::QueryIfaceResponse {
617 role: fidl_common::WlanMacRole::Client,
618 id: 0,
619 phy_id: 0,
620 phy_assigned_id: 0,
621 sta_addr: [0, 1, 2, 3, 4, 5],
622 factory_addr: [0, 1, 2, 3, 4, 5],
623 });
624 send_query_iface_response(&mut exec, &mut test_values.monitor_stream, iface_response);
625
626 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
628 assert_matches!(
629 exec.run_until_stalled(&mut test_values.monitor_stream.next()),
630 Poll::Ready(Some(Ok(fidl_service::DeviceMonitorRequest::GetClientSme {
631 iface_id: 0, sme_server: _, responder
632 }))) => {
633 assert!(responder.send(Ok(())).is_ok())
634 }
635 );
636
637 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(()));
639
640 {
642 let iface_manager = test_values.iface_manager.clone();
643 let verify_fut = async move {
644 let iface_manager = iface_manager.lock().await;
645 assert_eq!(iface_manager.ifaces, vec![0]);
646 };
647 let mut verify_fut = pin!(verify_fut);
648 assert_matches!(exec.run_until_stalled(&mut verify_fut), Poll::Ready(()));
649 }
650
651 assert!(listener.legacy_shim.get().is_ok());
653 }
654
655 #[fuchsia::test]
656 fn test_handle_iface_added_fails_due_to_monitor_service() {
657 let mut exec = fasync::TestExecutor::new();
658 let test_values = test_setup(false, true);
659
660 let listener = Listener::new(
661 test_values.monitor_proxy,
662 IfaceRef::new(),
663 test_values.phy_manager.clone(),
664 test_values.iface_manager.clone(),
665 );
666
667 drop(test_values.monitor_stream);
670
671 let fut = handle_event(&listener, DeviceWatcherEvent::OnIfaceAdded { iface_id: 0 });
673 let mut fut = pin!(fut);
674 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(()));
675
676 {
678 let iface_manager = test_values.iface_manager.clone();
679 let verify_fut = async move {
680 let iface_manager = iface_manager.lock().await;
681 assert_eq!(iface_manager.ifaces, vec![0]);
682 };
683 let mut verify_fut = pin!(verify_fut);
684 assert_matches!(exec.run_until_stalled(&mut verify_fut), Poll::Ready(()));
685 }
686
687 assert!(listener.legacy_shim.get().is_err());
689 }
690
691 #[derive(Debug)]
692 struct FakePhyManager {
693 phys: Vec<u16>,
694 ifaces: Vec<u16>,
695 failed_phys: u32,
696 add_phy_succeeds: bool,
697 add_iface_succeeds: bool,
698 }
699
700 impl FakePhyManager {
701 fn new(add_phy_succeeds: bool, add_iface_succeeds: bool) -> Self {
702 FakePhyManager {
703 phys: Vec::new(),
704 ifaces: Vec::new(),
705 failed_phys: 0,
706 add_phy_succeeds,
707 add_iface_succeeds,
708 }
709 }
710 }
711
712 #[async_trait(?Send)]
713 impl PhyManagerApi for FakePhyManager {
714 async fn add_phy(&mut self, phy_id: u16) -> Result<(), PhyManagerError> {
715 if self.add_phy_succeeds {
716 self.phys.push(phy_id);
717 Ok(())
718 } else {
719 Err(PhyManagerError::PhyQueryFailure)
720 }
721 }
722
723 fn remove_phy(&mut self, phy_id: u16) {
724 self.phys.retain(|phy| *phy != phy_id)
725 }
726
727 async fn on_iface_added(&mut self, iface_id: u16) -> Result<(), PhyManagerError> {
728 if self.add_iface_succeeds {
729 self.ifaces.push(iface_id);
730 Ok(())
731 } else {
732 Err(PhyManagerError::IfaceQueryFailure)
733 }
734 }
735
736 fn on_iface_removed(&mut self, iface_id: u16) {
737 self.ifaces.retain(|iface| *iface != iface_id)
738 }
739
740 async fn create_all_client_ifaces(
741 &mut self,
742 _reason: CreateClientIfacesReason,
743 ) -> HashMap<u16, Result<Vec<u16>, PhyManagerError>> {
744 unimplemented!()
745 }
746
747 fn client_connections_enabled(&self) -> bool {
748 unimplemented!()
749 }
750
751 async fn destroy_all_client_ifaces(&mut self) -> Result<(), PhyManagerError> {
752 unimplemented!()
753 }
754
755 fn get_client(&mut self) -> Option<u16> {
756 unimplemented!();
757 }
758
759 async fn create_or_get_ap_iface(&mut self) -> Result<Option<u16>, PhyManagerError> {
760 unimplemented!();
761 }
762
763 async fn destroy_ap_iface(&mut self, _iface_id: u16) -> Result<(), PhyManagerError> {
764 unimplemented!();
765 }
766
767 async fn destroy_all_ap_ifaces(&mut self) -> Result<(), PhyManagerError> {
768 unimplemented!();
769 }
770
771 fn suggest_ap_mac(&mut self, _mac: MacAddr) {
772 unimplemented!()
773 }
774
775 fn get_phy_ids(&self) -> Vec<u16> {
776 unimplemented!()
777 }
778
779 fn log_phy_add_failure(&mut self) {
780 self.failed_phys += 1;
781 }
782
783 async fn set_country_code(
784 &mut self,
785 _country_code: Option<client_types::CountryCode>,
786 ) -> Result<(), PhyManagerError> {
787 unimplemented!();
788 }
789
790 fn record_defect(&mut self, _defect: Defect) {
791 unimplemented!();
792 }
793
794 async fn perform_recovery(&mut self, _summary: RecoverySummary) {
795 unimplemented!();
796 }
797
798 async fn on_before_suspend(&mut self) {}
799 async fn on_after_resume(&mut self) {}
800 }
801
802 #[derive(Debug)]
803 struct FakeIfaceManager {
804 ifaces: Vec<u16>,
805 }
806
807 impl FakeIfaceManager {
808 fn new() -> Self {
809 FakeIfaceManager { ifaces: Vec::new() }
810 }
811 }
812
813 #[async_trait(?Send)]
814 impl IfaceManagerApi for FakeIfaceManager {
815 async fn disconnect(
816 &mut self,
817 _network_id: client_types::NetworkIdentifier,
818 _reason: client_types::DisconnectReason,
819 ) -> Result<(), Error> {
820 unimplemented!();
821 }
822
823 async fn connect(&mut self, _connect_req: ConnectAttemptRequest) -> Result<(), Error> {
824 unimplemented!();
825 }
826
827 async fn record_idle_client(&mut self, _iface_id: u16) -> Result<(), Error> {
828 unimplemented!();
829 }
830
831 async fn has_idle_client(&mut self) -> Result<bool, Error> {
832 unimplemented!();
833 }
834
835 async fn handle_added_iface(&mut self, iface_id: u16) -> Result<(), Error> {
836 self.ifaces.push(iface_id);
837 Ok(())
838 }
839
840 async fn handle_removed_iface(&mut self, iface_id: u16) -> Result<(), Error> {
841 self.ifaces.retain(|iface| *iface != iface_id);
842 Ok(())
843 }
844
845 async fn get_sme_proxy_for_scan(&mut self) -> Result<SmeForScan, Error> {
846 unimplemented!()
847 }
848
849 async fn stop_client_connections(
850 &mut self,
851 _reason: client_types::DisconnectReason,
852 ) -> Result<(), Error> {
853 unimplemented!()
854 }
855
856 async fn start_client_connections(&mut self) -> Result<(), Error> {
857 unimplemented!()
858 }
859
860 async fn start_ap(
861 &mut self,
862 _config: ap_fsm::ApConfig,
863 ) -> Result<oneshot::Receiver<()>, Error> {
864 unimplemented!();
865 }
866
867 async fn stop_ap(
868 &mut self,
869 _ssid: ap_types::Ssid,
870 _password: Vec<u8>,
871 ) -> Result<(), Error> {
872 unimplemented!();
873 }
874
875 async fn stop_all_aps(&mut self) -> Result<(), Error> {
876 unimplemented!()
877 }
878
879 async fn set_country(
880 &mut self,
881 _country_code: Option<client_types::CountryCode>,
882 ) -> Result<(), Error> {
883 unimplemented!();
884 }
885 }
886
887 #[track_caller]
888 fn send_query_iface_response(
889 exec: &mut fasync::TestExecutor,
890 server: &mut fidl_service::DeviceMonitorRequestStream,
891 iface_info: Option<fidl_service::QueryIfaceResponse>,
892 ) {
893 let response = iface_info.as_ref().ok_or(zx::sys::ZX_ERR_NOT_FOUND);
894 assert_matches!(
895 exec.run_until_stalled(&mut server.next()),
896 Poll::Ready(Some(Ok(
897 fidl_service::DeviceMonitorRequest::QueryIface {
898 iface_id: _,
899 responder,
900 }
901 ))) => {
902 responder.send(response).expect("sending fake iface info");
903 }
904 );
905 }
906}