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