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