1 // Copyright 2022, The Android Open Source Project 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 use std::collections::BTreeMap; 16 17 use log::{debug, error, warn}; 18 use tokio::sync::{mpsc, oneshot}; 19 20 use crate::error::{Error, Result}; 21 use crate::params::app_config_params::AppConfigParams; 22 use crate::params::uci_packets::{ 23 Controlee, ReasonCode, SessionId, SessionState, SessionType, UpdateMulticastListAction, 24 }; 25 use crate::session::uwb_session::{Response as SessionResponse, ResponseSender, UwbSession}; 26 use crate::uci::notification::{SessionNotification as UciSessionNotification, SessionRangeData}; 27 use crate::uci::uci_manager::UciManager; 28 use crate::utils::clean_mpsc_receiver; 29 30 const MAX_SESSION_COUNT: usize = 5; 31 32 /// The notifications that are sent from SessionManager to its caller. 33 #[derive(Debug, PartialEq)] 34 pub(crate) enum SessionNotification { 35 SessionState { session_id: SessionId, session_state: SessionState, reason_code: ReasonCode }, 36 RangeData { session_id: SessionId, range_data: SessionRangeData }, 37 } 38 39 /// The SessionManager organizes the state machine of the existing UWB ranging sessions, sends 40 /// the session-related requests to the UciManager, and handles the session notifications from the 41 /// UciManager. 42 /// Using the actor model, SessionManager delegates the requests to SessionManagerActor. 43 pub(crate) struct SessionManager { 44 cmd_sender: mpsc::UnboundedSender<(SessionCommand, ResponseSender)>, 45 } 46 47 impl SessionManager { new<T: UciManager>( uci_manager: T, uci_notf_receiver: mpsc::UnboundedReceiver<UciSessionNotification>, session_notf_sender: mpsc::UnboundedSender<SessionNotification>, ) -> Self48 pub fn new<T: UciManager>( 49 uci_manager: T, 50 uci_notf_receiver: mpsc::UnboundedReceiver<UciSessionNotification>, 51 session_notf_sender: mpsc::UnboundedSender<SessionNotification>, 52 ) -> Self { 53 let (cmd_sender, cmd_receiver) = mpsc::unbounded_channel(); 54 let mut actor = SessionManagerActor::new( 55 cmd_receiver, 56 uci_manager, 57 uci_notf_receiver, 58 session_notf_sender, 59 ); 60 tokio::spawn(async move { actor.run().await }); 61 62 Self { cmd_sender } 63 } 64 init_session( &mut self, session_id: SessionId, session_type: SessionType, params: AppConfigParams, ) -> Result<()>65 pub async fn init_session( 66 &mut self, 67 session_id: SessionId, 68 session_type: SessionType, 69 params: AppConfigParams, 70 ) -> Result<()> { 71 let result = self 72 .send_cmd(SessionCommand::InitSession { session_id, session_type, params }) 73 .await 74 .map(|_| ()); 75 if result.is_err() && result != Err(Error::DuplicatedSessionId) { 76 let _ = self.deinit_session(session_id).await; 77 } 78 result 79 } 80 deinit_session(&mut self, session_id: SessionId) -> Result<()>81 pub async fn deinit_session(&mut self, session_id: SessionId) -> Result<()> { 82 self.send_cmd(SessionCommand::DeinitSession { session_id }).await?; 83 Ok(()) 84 } 85 start_ranging(&mut self, session_id: SessionId) -> Result<AppConfigParams>86 pub async fn start_ranging(&mut self, session_id: SessionId) -> Result<AppConfigParams> { 87 match self.send_cmd(SessionCommand::StartRanging { session_id }).await? { 88 SessionResponse::AppConfigParams(params) => Ok(params), 89 _ => panic!("start_ranging() should reply AppConfigParams result"), 90 } 91 } 92 stop_ranging(&mut self, session_id: SessionId) -> Result<()>93 pub async fn stop_ranging(&mut self, session_id: SessionId) -> Result<()> { 94 self.send_cmd(SessionCommand::StopRanging { session_id }).await?; 95 Ok(()) 96 } 97 reconfigure( &mut self, session_id: SessionId, params: AppConfigParams, ) -> Result<()>98 pub async fn reconfigure( 99 &mut self, 100 session_id: SessionId, 101 params: AppConfigParams, 102 ) -> Result<()> { 103 self.send_cmd(SessionCommand::Reconfigure { session_id, params }).await?; 104 Ok(()) 105 } 106 update_controller_multicast_list( &mut self, session_id: SessionId, action: UpdateMulticastListAction, controlees: Vec<Controlee>, ) -> Result<()>107 pub async fn update_controller_multicast_list( 108 &mut self, 109 session_id: SessionId, 110 action: UpdateMulticastListAction, 111 controlees: Vec<Controlee>, 112 ) -> Result<()> { 113 self.send_cmd(SessionCommand::UpdateControllerMulticastList { 114 session_id, 115 action, 116 controlees, 117 }) 118 .await?; 119 Ok(()) 120 } 121 session_params(&mut self, session_id: SessionId) -> Result<AppConfigParams>122 pub async fn session_params(&mut self, session_id: SessionId) -> Result<AppConfigParams> { 123 match self.send_cmd(SessionCommand::GetParams { session_id }).await? { 124 SessionResponse::AppConfigParams(params) => Ok(params), 125 _ => panic!("session_params() should reply AppConfigParams result"), 126 } 127 } 128 129 // Send the |cmd| to the SessionManagerActor. send_cmd(&self, cmd: SessionCommand) -> Result<SessionResponse>130 async fn send_cmd(&self, cmd: SessionCommand) -> Result<SessionResponse> { 131 let (result_sender, result_receiver) = oneshot::channel(); 132 self.cmd_sender.send((cmd, result_sender)).map_err(|cmd| { 133 error!("Failed to send cmd: {:?}", cmd.0); 134 Error::Unknown 135 })?; 136 result_receiver.await.unwrap_or_else(|e| { 137 error!("Failed to receive the result for cmd: {:?}", e); 138 Err(Error::Unknown) 139 }) 140 } 141 } 142 143 struct SessionManagerActor<T: UciManager> { 144 // Receive the commands and the corresponding response senders from SessionManager. 145 cmd_receiver: mpsc::UnboundedReceiver<(SessionCommand, ResponseSender)>, 146 // Send the notification to SessionManager's caller. 147 session_notf_sender: mpsc::UnboundedSender<SessionNotification>, 148 149 // The UciManager for delegating UCI requests. 150 uci_manager: T, 151 // Receive the notification from |uci_manager|. 152 uci_notf_receiver: mpsc::UnboundedReceiver<UciSessionNotification>, 153 154 active_sessions: BTreeMap<SessionId, UwbSession>, 155 } 156 157 impl<T: UciManager> SessionManagerActor<T> { new( cmd_receiver: mpsc::UnboundedReceiver<(SessionCommand, ResponseSender)>, uci_manager: T, uci_notf_receiver: mpsc::UnboundedReceiver<UciSessionNotification>, session_notf_sender: mpsc::UnboundedSender<SessionNotification>, ) -> Self158 fn new( 159 cmd_receiver: mpsc::UnboundedReceiver<(SessionCommand, ResponseSender)>, 160 uci_manager: T, 161 uci_notf_receiver: mpsc::UnboundedReceiver<UciSessionNotification>, 162 session_notf_sender: mpsc::UnboundedSender<SessionNotification>, 163 ) -> Self { 164 Self { 165 cmd_receiver, 166 session_notf_sender, 167 uci_manager, 168 uci_notf_receiver, 169 active_sessions: BTreeMap::new(), 170 } 171 } 172 run(&mut self)173 async fn run(&mut self) { 174 loop { 175 tokio::select! { 176 cmd = self.cmd_receiver.recv() => { 177 match cmd { 178 None => { 179 debug!("SessionManager is about to drop."); 180 break; 181 }, 182 Some((cmd, result_sender)) => { 183 self.handle_cmd(cmd, result_sender); 184 } 185 } 186 } 187 188 Some(notf) = self.uci_notf_receiver.recv() => { 189 self.handle_uci_notification(notf); 190 } 191 } 192 } 193 } 194 handle_cmd(&mut self, cmd: SessionCommand, result_sender: ResponseSender)195 fn handle_cmd(&mut self, cmd: SessionCommand, result_sender: ResponseSender) { 196 match cmd { 197 SessionCommand::InitSession { session_id, session_type, params } => { 198 if self.active_sessions.contains_key(&session_id) { 199 warn!("Session {} already exists", session_id); 200 let _ = result_sender.send(Err(Error::DuplicatedSessionId)); 201 return; 202 } 203 if self.active_sessions.len() == MAX_SESSION_COUNT { 204 warn!("The amount of active sessions already reached {}", MAX_SESSION_COUNT); 205 let _ = result_sender.send(Err(Error::MaxSessionsExceeded)); 206 return; 207 } 208 209 if !params.is_type_matched(session_type) { 210 warn!( 211 "session_type {:?} doesn't match with the params {:?}", 212 session_type, params 213 ); 214 let _ = result_sender.send(Err(Error::BadParameters)); 215 return; 216 } 217 218 let mut session = 219 UwbSession::new(self.uci_manager.clone(), session_id, session_type); 220 session.initialize(params, result_sender); 221 222 // We store the session first. If the initialize() fails, then SessionManager will 223 // call deinit_session() to remove it. 224 self.active_sessions.insert(session_id, session); 225 } 226 SessionCommand::DeinitSession { session_id } => { 227 match self.active_sessions.remove(&session_id) { 228 None => { 229 warn!("Session {} doesn't exist", session_id); 230 let _ = result_sender.send(Err(Error::BadParameters)); 231 } 232 Some(mut session) => { 233 session.deinitialize(result_sender); 234 } 235 } 236 } 237 SessionCommand::StartRanging { session_id } => { 238 match self.active_sessions.get_mut(&session_id) { 239 None => { 240 warn!("Session {} doesn't exist", session_id); 241 let _ = result_sender.send(Err(Error::BadParameters)); 242 } 243 Some(session) => { 244 session.start_ranging(result_sender); 245 } 246 } 247 } 248 SessionCommand::StopRanging { session_id } => { 249 match self.active_sessions.get_mut(&session_id) { 250 None => { 251 warn!("Session {} doesn't exist", session_id); 252 let _ = result_sender.send(Err(Error::BadParameters)); 253 } 254 Some(session) => { 255 session.stop_ranging(result_sender); 256 } 257 } 258 } 259 SessionCommand::Reconfigure { session_id, params } => { 260 match self.active_sessions.get_mut(&session_id) { 261 None => { 262 warn!("Session {} doesn't exist", session_id); 263 let _ = result_sender.send(Err(Error::BadParameters)); 264 } 265 Some(session) => { 266 session.reconfigure(params, result_sender); 267 } 268 } 269 } 270 SessionCommand::UpdateControllerMulticastList { session_id, action, controlees } => { 271 match self.active_sessions.get_mut(&session_id) { 272 None => { 273 warn!("Session {} doesn't exist", session_id); 274 let _ = result_sender.send(Err(Error::BadParameters)); 275 } 276 Some(session) => { 277 session.update_controller_multicast_list(action, controlees, result_sender); 278 } 279 } 280 } 281 SessionCommand::GetParams { session_id } => { 282 match self.active_sessions.get_mut(&session_id) { 283 None => { 284 warn!("Session {} doesn't exist", session_id); 285 let _ = result_sender.send(Err(Error::BadParameters)); 286 } 287 Some(session) => { 288 session.params(result_sender); 289 } 290 } 291 } 292 } 293 } 294 handle_uci_notification(&mut self, notf: UciSessionNotification)295 fn handle_uci_notification(&mut self, notf: UciSessionNotification) { 296 match notf { 297 UciSessionNotification::Status { session_token, session_state, reason_code } => { 298 let reason_code = match ReasonCode::try_from(reason_code) { 299 Ok(r) => r, 300 Err(_) => { 301 error!( 302 "Received unknown reason_code {:?} in UciSessionNotification", 303 reason_code 304 ); 305 return; 306 } 307 }; 308 if session_state == SessionState::SessionStateDeinit { 309 debug!("Session {} is deinitialized", session_token); 310 let _ = self.active_sessions.remove(&session_token); 311 let _ = self.session_notf_sender.send(SessionNotification::SessionState { 312 session_id: session_token, 313 session_state, 314 reason_code, 315 }); 316 return; 317 } 318 319 match self.active_sessions.get_mut(&session_token) { 320 Some(session) => { 321 session.on_session_status_changed(session_state); 322 let _ = self.session_notf_sender.send(SessionNotification::SessionState { 323 session_id: session_token, 324 session_state, 325 reason_code, 326 }); 327 } 328 None => { 329 warn!( 330 "Received notification of the unknown Session {}: {:?}, {:?}", 331 session_token, session_state, reason_code 332 ); 333 } 334 } 335 } 336 UciSessionNotification::UpdateControllerMulticastList { 337 session_token, 338 remaining_multicast_list_size: _, 339 status_list, 340 } => match self.active_sessions.get_mut(&session_token) { 341 Some(session) => session.on_controller_multicast_list_udpated(status_list), 342 None => { 343 warn!( 344 "Received the notification of the unknown Session {}: {:?}", 345 session_token, status_list 346 ); 347 } 348 }, 349 UciSessionNotification::SessionInfo(range_data) => { 350 if self.active_sessions.get(&range_data.session_token).is_some() { 351 let _ = self.session_notf_sender.send(SessionNotification::RangeData { 352 session_id: range_data.session_token, 353 range_data, 354 }); 355 } else { 356 warn!("Received range data of the unknown Session: {:?}", range_data); 357 } 358 } 359 UciSessionNotification::DataCredit { session_token, credit_availability: _ } => { 360 match self.active_sessions.get(&session_token) { 361 Some(_) => { 362 /* 363 * TODO(b/270443790): Handle the DataCredit notification in the new 364 * code flow. 365 */ 366 } 367 None => { 368 warn!( 369 "Received the Data Credit notification for an unknown Session {}", 370 session_token 371 ); 372 } 373 } 374 } 375 UciSessionNotification::DataTransferStatus { 376 session_token, 377 uci_sequence_number: _, 378 status: _, 379 } => { 380 match self.active_sessions.get(&session_token) { 381 Some(_) => { 382 /* 383 * TODO(b/270443790): Handle the DataTransferStatus notification in the 384 * new code flow. 385 */ 386 } 387 None => { 388 warn!( 389 "Received a Data Transfer Status notification for unknown Session {}", 390 session_token 391 ); 392 } 393 } 394 } 395 } 396 } 397 } 398 399 impl<T: UciManager> Drop for SessionManagerActor<T> { drop(&mut self)400 fn drop(&mut self) { 401 // mpsc receiver is about to be dropped. Clean shutdown the mpsc message. 402 clean_mpsc_receiver(&mut self.uci_notf_receiver); 403 } 404 } 405 406 #[derive(Debug)] 407 enum SessionCommand { 408 InitSession { 409 session_id: SessionId, 410 session_type: SessionType, 411 params: AppConfigParams, 412 }, 413 DeinitSession { 414 session_id: SessionId, 415 }, 416 StartRanging { 417 session_id: SessionId, 418 }, 419 StopRanging { 420 session_id: SessionId, 421 }, 422 Reconfigure { 423 session_id: SessionId, 424 params: AppConfigParams, 425 }, 426 UpdateControllerMulticastList { 427 session_id: SessionId, 428 action: UpdateMulticastListAction, 429 controlees: Vec<Controlee>, 430 }, 431 GetParams { 432 session_id: SessionId, 433 }, 434 } 435 436 #[cfg(test)] 437 pub(crate) mod test_utils { 438 use super::*; 439 440 use crate::params::ccc_app_config_params::*; 441 use crate::params::fira_app_config_params::*; 442 use crate::params::uci_packets::{ 443 RangingMeasurementType, ReasonCode, ShortAddressTwoWayRangingMeasurement, StatusCode, 444 }; 445 use crate::uci::mock_uci_manager::MockUciManager; 446 use crate::uci::notification::{RangingMeasurements, UciNotification}; 447 use crate::utils::init_test_logging; 448 generate_params() -> AppConfigParams449 pub(crate) fn generate_params() -> AppConfigParams { 450 FiraAppConfigParamsBuilder::new() 451 .device_type(DeviceType::Controller) 452 .multi_node_mode(MultiNodeMode::Unicast) 453 .device_mac_address(UwbAddress::Short([1, 2])) 454 .dst_mac_address(vec![UwbAddress::Short([3, 4])]) 455 .device_role(DeviceRole::Initiator) 456 .vendor_id([0xFE, 0xDC]) 457 .static_sts_iv([0xDF, 0xCE, 0xAB, 0x12, 0x34, 0x56]) 458 .build() 459 .unwrap() 460 } 461 generate_ccc_params() -> AppConfigParams462 pub(crate) fn generate_ccc_params() -> AppConfigParams { 463 CccAppConfigParamsBuilder::new() 464 .protocol_version(CccProtocolVersion { major: 2, minor: 1 }) 465 .uwb_config(CccUwbConfig::Config0) 466 .pulse_shape_combo(CccPulseShapeCombo { 467 initiator_tx: PulseShape::PrecursorFree, 468 responder_tx: PulseShape::PrecursorFreeSpecial, 469 }) 470 .ran_multiplier(3) 471 .channel_number(CccUwbChannel::Channel9) 472 .chaps_per_slot(ChapsPerSlot::Value9) 473 .num_responder_nodes(1) 474 .slots_per_rr(3) 475 .sync_code_index(12) 476 .hopping_mode(CccHoppingMode::ContinuousAes) 477 .build() 478 .unwrap() 479 } 480 session_range_data(session_id: SessionId) -> SessionRangeData481 pub(crate) fn session_range_data(session_id: SessionId) -> SessionRangeData { 482 SessionRangeData { 483 sequence_number: 1, 484 session_token: session_id, 485 current_ranging_interval_ms: 3, 486 ranging_measurement_type: RangingMeasurementType::TwoWay, 487 ranging_measurements: RangingMeasurements::ShortAddressTwoWay(vec![ 488 ShortAddressTwoWayRangingMeasurement { 489 mac_address: 0x123, 490 status: StatusCode::UciStatusOk, 491 nlos: 0, 492 distance: 4, 493 aoa_azimuth: 5, 494 aoa_azimuth_fom: 6, 495 aoa_elevation: 7, 496 aoa_elevation_fom: 8, 497 aoa_destination_azimuth: 9, 498 aoa_destination_azimuth_fom: 10, 499 aoa_destination_elevation: 11, 500 aoa_destination_elevation_fom: 12, 501 slot_index: 0, 502 rssi: u8::MAX, 503 }, 504 ]), 505 rcr_indicator: 0, 506 raw_ranging_data: vec![0x12, 0x34], 507 } 508 } 509 session_status_notf( session_id: SessionId, session_state: SessionState, ) -> UciNotification510 pub(crate) fn session_status_notf( 511 session_id: SessionId, 512 session_state: SessionState, 513 ) -> UciNotification { 514 UciNotification::Session(UciSessionNotification::Status { 515 session_token: session_id, 516 session_state, 517 reason_code: ReasonCode::StateChangeWithSessionManagementCommands.into(), 518 }) 519 } 520 range_data_notf(range_data: SessionRangeData) -> UciNotification521 pub(crate) fn range_data_notf(range_data: SessionRangeData) -> UciNotification { 522 UciNotification::Session(UciSessionNotification::SessionInfo(range_data)) 523 } 524 setup_session_manager<F>( setup_uci_manager_fn: F, ) -> (SessionManager, MockUciManager, mpsc::UnboundedReceiver<SessionNotification>) where F: FnOnce(&mut MockUciManager),525 pub(super) async fn setup_session_manager<F>( 526 setup_uci_manager_fn: F, 527 ) -> (SessionManager, MockUciManager, mpsc::UnboundedReceiver<SessionNotification>) 528 where 529 F: FnOnce(&mut MockUciManager), 530 { 531 init_test_logging(); 532 let (uci_notf_sender, uci_notf_receiver) = mpsc::unbounded_channel(); 533 let (session_notf_sender, session_notf_receiver) = mpsc::unbounded_channel(); 534 let mut uci_manager = MockUciManager::new(); 535 uci_manager.expect_open_hal(vec![], Ok(())); 536 setup_uci_manager_fn(&mut uci_manager); 537 uci_manager.set_session_notification_sender(uci_notf_sender).await; 538 let _ = uci_manager.open_hal().await; 539 540 ( 541 SessionManager::new(uci_manager.clone(), uci_notf_receiver, session_notf_sender), 542 uci_manager, 543 session_notf_receiver, 544 ) 545 } 546 } 547 548 #[cfg(test)] 549 mod tests { 550 use super::test_utils::*; 551 use super::*; 552 553 use std::collections::HashMap; 554 555 use crate::params::ccc_started_app_config_params::CccStartedAppConfigParams; 556 use crate::params::uci_packets::{ 557 AppConfigTlv, AppConfigTlvType, ControleeStatus, Controlees, MulticastUpdateStatusCode, 558 ReasonCode, SetAppConfigResponse, StatusCode, 559 }; 560 use crate::params::utils::{u32_to_bytes, u64_to_bytes, u8_to_bytes}; 561 use crate::params::{FiraAppConfigParamsBuilder, KeyRotation}; 562 use crate::uci::notification::UciNotification; 563 564 #[tokio::test] test_init_deinit_session()565 async fn test_init_deinit_session() { 566 let session_id = 0x123; 567 let session_type = SessionType::FiraRangingSession; 568 let params = generate_params(); 569 570 let tlvs = params.generate_tlvs(); 571 let (mut session_manager, mut mock_uci_manager, mut session_notf_receiver) = 572 setup_session_manager(move |uci_manager| { 573 uci_manager.expect_session_init( 574 session_id, 575 session_type, 576 vec![session_status_notf(session_id, SessionState::SessionStateInit)], 577 Ok(()), 578 ); 579 uci_manager.expect_session_set_app_config( 580 session_id, 581 tlvs, 582 vec![session_status_notf(session_id, SessionState::SessionStateIdle)], 583 Ok(SetAppConfigResponse { 584 status: StatusCode::UciStatusOk, 585 config_status: vec![], 586 }), 587 ); 588 uci_manager.expect_session_deinit( 589 session_id, 590 vec![session_status_notf(session_id, SessionState::SessionStateDeinit)], 591 Ok(()), 592 ); 593 }) 594 .await; 595 596 // Deinit a session before initialized should fail. 597 let result = session_manager.deinit_session(session_id).await; 598 assert_eq!(result, Err(Error::BadParameters)); 599 600 // Initialize a normal session should be successful. 601 let result = session_manager.init_session(session_id, session_type, params.clone()).await; 602 assert_eq!(result, Ok(())); 603 let session_notf = session_notf_receiver.recv().await.unwrap(); 604 assert_eq!( 605 session_notf, 606 SessionNotification::SessionState { 607 session_id, 608 session_state: SessionState::SessionStateInit, 609 reason_code: ReasonCode::StateChangeWithSessionManagementCommands 610 } 611 ); 612 let session_notf = session_notf_receiver.recv().await.unwrap(); 613 assert_eq!( 614 session_notf, 615 SessionNotification::SessionState { 616 session_id, 617 session_state: SessionState::SessionStateIdle, 618 reason_code: ReasonCode::StateChangeWithSessionManagementCommands 619 } 620 ); 621 622 // Initialize a session multiple times without deinitialize should fail. 623 let result = session_manager.init_session(session_id, session_type, params).await; 624 assert_eq!(result, Err(Error::DuplicatedSessionId)); 625 626 // Deinitialize the session should be successful, and should receive the deinitialized 627 // notification. 628 let result = session_manager.deinit_session(session_id).await; 629 assert_eq!(result, Ok(())); 630 let session_notf = session_notf_receiver.recv().await.unwrap(); 631 assert_eq!( 632 session_notf, 633 SessionNotification::SessionState { 634 session_id, 635 session_state: SessionState::SessionStateDeinit, 636 reason_code: ReasonCode::StateChangeWithSessionManagementCommands 637 } 638 ); 639 640 // Deinit a session after deinitialized should fail. 641 let result = session_manager.deinit_session(session_id).await; 642 assert_eq!(result, Err(Error::BadParameters)); 643 644 assert!(mock_uci_manager.wait_expected_calls_done().await); 645 } 646 647 #[tokio::test] test_init_session_timeout()648 async fn test_init_session_timeout() { 649 let session_id = 0x123; 650 let session_type = SessionType::FiraRangingSession; 651 let params = generate_params(); 652 653 let (mut session_manager, mut mock_uci_manager, _) = 654 setup_session_manager(move |uci_manager| { 655 let notfs = vec![]; // Not sending SessionStatus notification. 656 uci_manager.expect_session_init(session_id, session_type, notfs, Ok(())); 657 }) 658 .await; 659 660 let result = session_manager.init_session(session_id, session_type, params).await; 661 assert_eq!(result, Err(Error::Timeout)); 662 663 assert!(mock_uci_manager.wait_expected_calls_done().await); 664 } 665 666 #[tokio::test] test_start_stop_ranging()667 async fn test_start_stop_ranging() { 668 let session_id = 0x123; 669 let session_type = SessionType::FiraRangingSession; 670 let params = generate_params(); 671 let tlvs = params.generate_tlvs(); 672 673 let (mut session_manager, mut mock_uci_manager, _) = 674 setup_session_manager(move |uci_manager| { 675 uci_manager.expect_session_init( 676 session_id, 677 session_type, 678 vec![session_status_notf(session_id, SessionState::SessionStateInit)], 679 Ok(()), 680 ); 681 uci_manager.expect_session_set_app_config( 682 session_id, 683 tlvs, 684 vec![session_status_notf(session_id, SessionState::SessionStateIdle)], 685 Ok(SetAppConfigResponse { 686 status: StatusCode::UciStatusOk, 687 config_status: vec![], 688 }), 689 ); 690 uci_manager.expect_range_start( 691 session_id, 692 vec![session_status_notf(session_id, SessionState::SessionStateActive)], 693 Ok(()), 694 ); 695 uci_manager.expect_range_stop( 696 session_id, 697 vec![session_status_notf(session_id, SessionState::SessionStateIdle)], 698 Ok(()), 699 ); 700 }) 701 .await; 702 703 let result = session_manager.init_session(session_id, session_type, params.clone()).await; 704 assert_eq!(result, Ok(())); 705 let result = session_manager.start_ranging(session_id).await; 706 assert_eq!(result, Ok(params)); 707 let result = session_manager.stop_ranging(session_id).await; 708 assert_eq!(result, Ok(())); 709 710 assert!(mock_uci_manager.wait_expected_calls_done().await); 711 } 712 713 #[tokio::test] test_ccc_start_ranging()714 async fn test_ccc_start_ranging() { 715 let session_id = 0x123; 716 let session_type = SessionType::Ccc; 717 // params that is passed to UciManager::session_set_app_config(). 718 let params = generate_ccc_params(); 719 let tlvs = params.generate_tlvs(); 720 // The params that is received from UciManager::session_get_app_config(). 721 let received_config_map = HashMap::from([ 722 (AppConfigTlvType::StsIndex, u32_to_bytes(3)), 723 (AppConfigTlvType::CccHopModeKey, u32_to_bytes(5)), 724 (AppConfigTlvType::CccUwbTime0, u64_to_bytes(7)), 725 (AppConfigTlvType::RangingInterval, u32_to_bytes(96)), 726 (AppConfigTlvType::PreambleCodeIndex, u8_to_bytes(9)), 727 ]); 728 let received_tlvs = received_config_map 729 .iter() 730 .map(|(key, value)| AppConfigTlv::new(*key, value.clone())) 731 .collect(); 732 let started_params = 733 CccStartedAppConfigParams::from_config_map(received_config_map).unwrap(); 734 735 let (mut session_manager, mut mock_uci_manager, _) = 736 setup_session_manager(move |uci_manager| { 737 uci_manager.expect_session_init( 738 session_id, 739 session_type, 740 vec![session_status_notf(session_id, SessionState::SessionStateInit)], 741 Ok(()), 742 ); 743 uci_manager.expect_session_set_app_config( 744 session_id, 745 tlvs, 746 vec![session_status_notf(session_id, SessionState::SessionStateIdle)], 747 Ok(SetAppConfigResponse { 748 status: StatusCode::UciStatusOk, 749 config_status: vec![], 750 }), 751 ); 752 uci_manager.expect_range_start( 753 session_id, 754 vec![session_status_notf(session_id, SessionState::SessionStateActive)], 755 Ok(()), 756 ); 757 uci_manager.expect_session_get_app_config(session_id, vec![], Ok(received_tlvs)); 758 }) 759 .await; 760 761 let result = session_manager.init_session(session_id, session_type, params.clone()).await; 762 assert_eq!(result, Ok(())); 763 let result = session_manager.start_ranging(session_id).await; 764 assert_eq!(result, Ok(AppConfigParams::CccStarted(started_params))); 765 766 assert!(mock_uci_manager.wait_expected_calls_done().await); 767 } 768 769 #[tokio::test] test_update_controller_multicast_list()770 async fn test_update_controller_multicast_list() { 771 let session_id = 0x123; 772 let session_type = SessionType::FiraRangingSession; 773 let params = generate_params(); 774 let tlvs = params.generate_tlvs(); 775 let action = UpdateMulticastListAction::AddControlee; 776 let short_address: [u8; 2] = [0x12, 0x34]; 777 let controlees = vec![Controlee { short_address, subsession_id: 0x24 }]; 778 779 let controlees_clone = controlees.clone(); 780 let (mut session_manager, mut mock_uci_manager, _) = 781 setup_session_manager(move |uci_manager| { 782 let multicast_list_notf = vec![UciNotification::Session( 783 UciSessionNotification::UpdateControllerMulticastList { 784 session_token: session_id, 785 remaining_multicast_list_size: 1, 786 status_list: vec![ControleeStatus { 787 mac_address: [0x34, 0x12], 788 subsession_id: 0x24, 789 status: MulticastUpdateStatusCode::StatusOkMulticastListUpdate, 790 }], 791 }, 792 )]; 793 uci_manager.expect_session_init( 794 session_id, 795 session_type, 796 vec![session_status_notf(session_id, SessionState::SessionStateInit)], 797 Ok(()), 798 ); 799 uci_manager.expect_session_set_app_config( 800 session_id, 801 tlvs, 802 vec![session_status_notf(session_id, SessionState::SessionStateIdle)], 803 Ok(SetAppConfigResponse { 804 status: StatusCode::UciStatusOk, 805 config_status: vec![], 806 }), 807 ); 808 uci_manager.expect_session_update_controller_multicast_list( 809 session_id, 810 action, 811 Controlees::NoSessionKey(controlees_clone), 812 multicast_list_notf, 813 Ok(()), 814 ); 815 }) 816 .await; 817 818 let result = session_manager.init_session(session_id, session_type, params).await; 819 assert_eq!(result, Ok(())); 820 let result = 821 session_manager.update_controller_multicast_list(session_id, action, controlees).await; 822 assert_eq!(result, Ok(())); 823 824 assert!(mock_uci_manager.wait_expected_calls_done().await); 825 } 826 827 #[tokio::test] test_ccc_update_controller_multicast_list()828 async fn test_ccc_update_controller_multicast_list() { 829 let session_id = 0x123; 830 let session_type = SessionType::Ccc; 831 let params = generate_ccc_params(); 832 let tlvs = params.generate_tlvs(); 833 let action = UpdateMulticastListAction::AddControlee; 834 let short_address: [u8; 2] = [0x12, 0x34]; 835 let controlees = vec![Controlee { short_address, subsession_id: 0x24 }]; 836 837 let (mut session_manager, mut mock_uci_manager, _) = 838 setup_session_manager(move |uci_manager| { 839 uci_manager.expect_session_init( 840 session_id, 841 session_type, 842 vec![session_status_notf(session_id, SessionState::SessionStateInit)], 843 Ok(()), 844 ); 845 uci_manager.expect_session_set_app_config( 846 session_id, 847 tlvs, 848 vec![session_status_notf(session_id, SessionState::SessionStateIdle)], 849 Ok(SetAppConfigResponse { 850 status: StatusCode::UciStatusOk, 851 config_status: vec![], 852 }), 853 ); 854 }) 855 .await; 856 857 let result = session_manager.init_session(session_id, session_type, params).await; 858 assert_eq!(result, Ok(())); 859 // CCC session doesn't support update_controller_multicast_list. 860 let result = 861 session_manager.update_controller_multicast_list(session_id, action, controlees).await; 862 assert_eq!(result, Err(Error::BadParameters)); 863 864 assert!(mock_uci_manager.wait_expected_calls_done().await); 865 } 866 867 #[tokio::test] test_update_controller_multicast_list_without_notification()868 async fn test_update_controller_multicast_list_without_notification() { 869 let session_id = 0x123; 870 let session_type = SessionType::FiraRangingSession; 871 let params = generate_params(); 872 let tlvs = params.generate_tlvs(); 873 let action = UpdateMulticastListAction::AddControlee; 874 let short_address: [u8; 2] = [0x12, 0x34]; 875 let controlees = vec![Controlee { short_address, subsession_id: 0x24 }]; 876 877 let controlees_clone = controlees.clone(); 878 let (mut session_manager, mut mock_uci_manager, _) = 879 setup_session_manager(move |uci_manager| { 880 uci_manager.expect_session_init( 881 session_id, 882 session_type, 883 vec![session_status_notf(session_id, SessionState::SessionStateInit)], 884 Ok(()), 885 ); 886 uci_manager.expect_session_set_app_config( 887 session_id, 888 tlvs, 889 vec![session_status_notf(session_id, SessionState::SessionStateIdle)], 890 Ok(SetAppConfigResponse { 891 status: StatusCode::UciStatusOk, 892 config_status: vec![], 893 }), 894 ); 895 uci_manager.expect_session_update_controller_multicast_list( 896 session_id, 897 action, 898 uwb_uci_packets::Controlees::NoSessionKey(controlees_clone), 899 vec![], // Not sending notification. 900 Ok(()), 901 ); 902 }) 903 .await; 904 905 let result = session_manager.init_session(session_id, session_type, params).await; 906 assert_eq!(result, Ok(())); 907 // This method should timeout waiting for the notification. 908 let result = 909 session_manager.update_controller_multicast_list(session_id, action, controlees).await; 910 assert_eq!(result, Err(Error::Timeout)); 911 912 assert!(mock_uci_manager.wait_expected_calls_done().await); 913 } 914 915 #[tokio::test] test_receive_session_range_data()916 async fn test_receive_session_range_data() { 917 let session_id = 0x123; 918 let session_type = SessionType::FiraRangingSession; 919 let params = generate_params(); 920 let tlvs = params.generate_tlvs(); 921 let range_data = session_range_data(session_id); 922 let range_data_clone = range_data.clone(); 923 924 let (mut session_manager, mut mock_uci_manager, mut session_notf_receiver) = 925 setup_session_manager(move |uci_manager| { 926 uci_manager.expect_session_init( 927 session_id, 928 session_type, 929 vec![session_status_notf(session_id, SessionState::SessionStateInit)], 930 Ok(()), 931 ); 932 uci_manager.expect_session_set_app_config( 933 session_id, 934 tlvs, 935 vec![ 936 session_status_notf(session_id, SessionState::SessionStateIdle), 937 range_data_notf(range_data_clone), 938 ], 939 Ok(SetAppConfigResponse { 940 status: StatusCode::UciStatusOk, 941 config_status: vec![], 942 }), 943 ); 944 }) 945 .await; 946 947 let result = session_manager.init_session(session_id, session_type, params).await; 948 assert_eq!(result, Ok(())); 949 let session_notf = session_notf_receiver.recv().await.unwrap(); 950 assert_eq!( 951 session_notf, 952 SessionNotification::SessionState { 953 session_id, 954 session_state: SessionState::SessionStateInit, 955 reason_code: ReasonCode::StateChangeWithSessionManagementCommands 956 } 957 ); 958 let session_notf = session_notf_receiver.recv().await.unwrap(); 959 assert_eq!( 960 session_notf, 961 SessionNotification::SessionState { 962 session_id, 963 session_state: SessionState::SessionStateIdle, 964 reason_code: ReasonCode::StateChangeWithSessionManagementCommands 965 } 966 ); 967 968 let session_notf = session_notf_receiver.recv().await.unwrap(); 969 assert_eq!(session_notf, SessionNotification::RangeData { session_id, range_data }); 970 971 assert!(mock_uci_manager.wait_expected_calls_done().await); 972 } 973 974 #[tokio::test] test_reconfigure_app_config()975 async fn test_reconfigure_app_config() { 976 let session_id = 0x123; 977 let session_type = SessionType::FiraRangingSession; 978 979 let initial_params = generate_params(); 980 let initial_tlvs = initial_params.generate_tlvs(); 981 982 let non_default_key_rotation_val = KeyRotation::Enable; 983 let idle_params = FiraAppConfigParamsBuilder::from_params(&initial_params) 984 .unwrap() 985 .key_rotation(non_default_key_rotation_val) 986 .build() 987 .unwrap(); 988 let idle_tlvs = idle_params 989 .generate_updated_tlvs(&initial_params, SessionState::SessionStateIdle) 990 .unwrap(); 991 992 let non_default_block_stride_val = 2u8; 993 let active_params = FiraAppConfigParamsBuilder::from_params(&idle_params) 994 .unwrap() 995 .block_stride_length(non_default_block_stride_val) 996 .build() 997 .unwrap(); 998 let active_tlvs = active_params 999 .generate_updated_tlvs(&idle_params, SessionState::SessionStateIdle) 1000 .unwrap(); 1001 1002 let (mut session_manager, mut mock_uci_manager, _) = 1003 setup_session_manager(move |uci_manager| { 1004 uci_manager.expect_session_init( 1005 session_id, 1006 session_type, 1007 vec![session_status_notf(session_id, SessionState::SessionStateInit)], 1008 Ok(()), 1009 ); 1010 uci_manager.expect_session_set_app_config( 1011 session_id, 1012 initial_tlvs, 1013 vec![session_status_notf(session_id, SessionState::SessionStateIdle)], 1014 Ok(SetAppConfigResponse { 1015 status: StatusCode::UciStatusOk, 1016 config_status: vec![], 1017 }), 1018 ); 1019 uci_manager.expect_session_set_app_config( 1020 session_id, 1021 idle_tlvs, 1022 vec![], 1023 Ok(SetAppConfigResponse { 1024 status: StatusCode::UciStatusOk, 1025 config_status: vec![], 1026 }), 1027 ); 1028 uci_manager.expect_range_start( 1029 session_id, 1030 vec![session_status_notf(session_id, SessionState::SessionStateActive)], 1031 Ok(()), 1032 ); 1033 uci_manager.expect_session_set_app_config( 1034 session_id, 1035 active_tlvs, 1036 vec![], 1037 Ok(SetAppConfigResponse { 1038 status: StatusCode::UciStatusOk, 1039 config_status: vec![], 1040 }), 1041 ); 1042 }) 1043 .await; 1044 1045 // Reconfiguring without first initing a session should fail. 1046 let result = session_manager.reconfigure(session_id, initial_params.clone()).await; 1047 assert_eq!(result, Err(Error::BadParameters)); 1048 1049 let result = 1050 session_manager.init_session(session_id, session_type, initial_params.clone()).await; 1051 assert_eq!(result, Ok(())); 1052 1053 // Reconfiguring any parameters during idle state should succeed. 1054 let result = session_manager.reconfigure(session_id, idle_params.clone()).await; 1055 assert_eq!(result, Ok(())); 1056 1057 let result = session_manager.start_ranging(session_id).await; 1058 assert_eq!(result, Ok(idle_params)); 1059 1060 // Reconfiguring most parameters during active state should fail. 1061 let result = session_manager.reconfigure(session_id, initial_params).await; 1062 assert_eq!(result, Err(Error::BadParameters)); 1063 1064 // Only some parameters are allowed to be reconfigured during active state. 1065 let result = session_manager.reconfigure(session_id, active_params).await; 1066 assert_eq!(result, Ok(())); 1067 1068 assert!(mock_uci_manager.wait_expected_calls_done().await); 1069 } 1070 1071 #[tokio::test] test_session_params()1072 async fn test_session_params() { 1073 let session_id = 0x123; 1074 let session_type = SessionType::FiraRangingSession; 1075 1076 let params = generate_params(); 1077 let tlvs = params.generate_tlvs(); 1078 1079 let (mut session_manager, mut mock_uci_manager, _) = 1080 setup_session_manager(move |uci_manager| { 1081 uci_manager.expect_session_init( 1082 session_id, 1083 session_type, 1084 vec![session_status_notf(session_id, SessionState::SessionStateInit)], 1085 Ok(()), 1086 ); 1087 uci_manager.expect_session_set_app_config( 1088 session_id, 1089 tlvs, 1090 vec![session_status_notf(session_id, SessionState::SessionStateIdle)], 1091 Ok(SetAppConfigResponse { 1092 status: StatusCode::UciStatusOk, 1093 config_status: vec![], 1094 }), 1095 ); 1096 }) 1097 .await; 1098 1099 // Getting session params without initing a session should fail 1100 let result = session_manager.session_params(session_id).await; 1101 assert_eq!(result, Err(Error::BadParameters)); 1102 1103 let result = session_manager.init_session(session_id, session_type, params.clone()).await; 1104 result.unwrap(); 1105 1106 // Getting session params after they've been properly set should succeed 1107 let result = session_manager.session_params(session_id).await; 1108 assert_eq!(result, Ok(params)); 1109 1110 assert!(mock_uci_manager.wait_expected_calls_done().await); 1111 } 1112 } 1113