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 ranging_measurements: RangingMeasurements::ShortAddressTwoWay(vec![ 538 ShortAddressTwoWayRangingMeasurement { 539 mac_address: 0x123, 540 status: StatusCode::UciStatusOk, 541 nlos: 0, 542 distance: 4, 543 aoa_azimuth: 5, 544 aoa_azimuth_fom: 6, 545 aoa_elevation: 7, 546 aoa_elevation_fom: 8, 547 aoa_destination_azimuth: 9, 548 aoa_destination_azimuth_fom: 10, 549 aoa_destination_elevation: 11, 550 aoa_destination_elevation_fom: 12, 551 slot_index: 0, 552 rssi: u8::MAX, 553 }, 554 ]), 555 rcr_indicator: 0, 556 raw_ranging_data: vec![0x12, 0x34], 557 } 558 } 559 session_status_notf( session_id: SessionId, session_state: SessionState, ) -> UciNotification560 pub(crate) fn session_status_notf( 561 session_id: SessionId, 562 session_state: SessionState, 563 ) -> UciNotification { 564 UciNotification::Session(UciSessionNotification::Status { 565 session_id: 0x0, 566 session_token: session_id, 567 session_state, 568 reason_code: ReasonCode::StateChangeWithSessionManagementCommands.into(), 569 }) 570 } 571 range_data_notf(range_data: SessionRangeData) -> UciNotification572 pub(crate) fn range_data_notf(range_data: SessionRangeData) -> UciNotification { 573 UciNotification::Session(UciSessionNotification::SessionInfo(range_data)) 574 } 575 setup_session_manager<F>( setup_uci_manager_fn: F, ) -> (SessionManager, MockUciManager, mpsc::UnboundedReceiver<SessionNotification>) where F: FnOnce(&mut MockUciManager),576 pub(super) async fn setup_session_manager<F>( 577 setup_uci_manager_fn: F, 578 ) -> (SessionManager, MockUciManager, mpsc::UnboundedReceiver<SessionNotification>) 579 where 580 F: FnOnce(&mut MockUciManager), 581 { 582 init_test_logging(); 583 let (uci_notf_sender, uci_notf_receiver) = mpsc::unbounded_channel(); 584 let (session_notf_sender, session_notf_receiver) = mpsc::unbounded_channel(); 585 let mut uci_manager = MockUciManager::new(); 586 uci_manager.expect_open_hal(vec![], Ok(GET_DEVICE_INFO_RSP)); 587 setup_uci_manager_fn(&mut uci_manager); 588 uci_manager.set_session_notification_sender(uci_notf_sender).await; 589 let _ = uci_manager.open_hal().await; 590 591 ( 592 SessionManager::new(uci_manager.clone(), uci_notf_receiver, session_notf_sender), 593 uci_manager, 594 session_notf_receiver, 595 ) 596 } 597 } 598 599 #[cfg(test)] 600 mod tests { 601 use super::test_utils::*; 602 use super::*; 603 604 use std::collections::HashMap; 605 606 use crate::params::ccc_started_app_config_params::CccStartedAppConfigParams; 607 use crate::params::uci_packets::{ 608 AppConfigTlv, AppConfigTlvType, ControleeStatusV1, Controlees, MulticastUpdateStatusCode, 609 ReasonCode, SessionUpdateControllerMulticastResponse, SetAppConfigResponse, StatusCode, 610 }; 611 use crate::params::utils::{u32_to_bytes, u64_to_bytes, u8_to_bytes}; 612 use crate::params::{FiraAppConfigParamsBuilder, KeyRotation}; 613 use crate::uci::notification::UciNotification; 614 615 #[tokio::test] test_init_deinit_session()616 async fn test_init_deinit_session() { 617 let session_id = 0x123; 618 let session_type = SessionType::FiraRangingSession; 619 let params = generate_params(); 620 621 let tlvs = params.generate_tlvs(); 622 let (mut session_manager, mut mock_uci_manager, mut session_notf_receiver) = 623 setup_session_manager(move |uci_manager| { 624 uci_manager.expect_session_init( 625 session_id, 626 session_type, 627 vec![session_status_notf(session_id, SessionState::SessionStateInit)], 628 Ok(()), 629 ); 630 uci_manager.expect_session_set_app_config( 631 session_id, 632 tlvs, 633 vec![session_status_notf(session_id, SessionState::SessionStateIdle)], 634 Ok(SetAppConfigResponse { 635 status: StatusCode::UciStatusOk, 636 config_status: vec![], 637 }), 638 ); 639 uci_manager.expect_session_deinit( 640 session_id, 641 vec![session_status_notf(session_id, SessionState::SessionStateDeinit)], 642 Ok(()), 643 ); 644 }) 645 .await; 646 647 // Deinit a session before initialized should fail. 648 let result = session_manager.deinit_session(session_id).await; 649 assert_eq!(result, Err(Error::BadParameters)); 650 651 // Initialize a normal session should be successful. 652 let result = session_manager.init_session(session_id, session_type, params.clone()).await; 653 assert_eq!(result, Ok(())); 654 let session_notf = session_notf_receiver.recv().await.unwrap(); 655 assert_eq!( 656 session_notf, 657 SessionNotification::SessionState { 658 session_id, 659 session_state: SessionState::SessionStateInit, 660 reason_code: ReasonCode::StateChangeWithSessionManagementCommands 661 } 662 ); 663 let session_notf = session_notf_receiver.recv().await.unwrap(); 664 assert_eq!( 665 session_notf, 666 SessionNotification::SessionState { 667 session_id, 668 session_state: SessionState::SessionStateIdle, 669 reason_code: ReasonCode::StateChangeWithSessionManagementCommands 670 } 671 ); 672 673 // Initialize a session multiple times without deinitialize should fail. 674 let result = session_manager.init_session(session_id, session_type, params).await; 675 assert_eq!(result, Err(Error::DuplicatedSessionId)); 676 677 // Deinitialize the session should be successful, and should receive the deinitialized 678 // notification. 679 let result = session_manager.deinit_session(session_id).await; 680 assert_eq!(result, Ok(())); 681 let session_notf = session_notf_receiver.recv().await.unwrap(); 682 assert_eq!( 683 session_notf, 684 SessionNotification::SessionState { 685 session_id, 686 session_state: SessionState::SessionStateDeinit, 687 reason_code: ReasonCode::StateChangeWithSessionManagementCommands 688 } 689 ); 690 691 // Deinit a session after deinitialized should fail. 692 let result = session_manager.deinit_session(session_id).await; 693 assert_eq!(result, Err(Error::BadParameters)); 694 695 assert!(mock_uci_manager.wait_expected_calls_done().await); 696 } 697 698 #[tokio::test] test_init_session_timeout()699 async fn test_init_session_timeout() { 700 let session_id = 0x123; 701 let session_type = SessionType::FiraRangingSession; 702 let params = generate_params(); 703 704 let (mut session_manager, mut mock_uci_manager, _) = 705 setup_session_manager(move |uci_manager| { 706 let notfs = vec![]; // Not sending SessionStatus notification. 707 uci_manager.expect_session_init(session_id, session_type, notfs, Ok(())); 708 }) 709 .await; 710 711 let result = session_manager.init_session(session_id, session_type, params).await; 712 assert_eq!(result, Err(Error::Timeout)); 713 714 assert!(mock_uci_manager.wait_expected_calls_done().await); 715 } 716 717 #[tokio::test] test_start_stop_ranging()718 async fn test_start_stop_ranging() { 719 let session_id = 0x123; 720 let session_type = SessionType::FiraRangingSession; 721 let params = generate_params(); 722 let tlvs = params.generate_tlvs(); 723 724 let (mut session_manager, mut mock_uci_manager, _) = 725 setup_session_manager(move |uci_manager| { 726 uci_manager.expect_session_init( 727 session_id, 728 session_type, 729 vec![session_status_notf(session_id, SessionState::SessionStateInit)], 730 Ok(()), 731 ); 732 uci_manager.expect_session_set_app_config( 733 session_id, 734 tlvs, 735 vec![session_status_notf(session_id, SessionState::SessionStateIdle)], 736 Ok(SetAppConfigResponse { 737 status: StatusCode::UciStatusOk, 738 config_status: vec![], 739 }), 740 ); 741 uci_manager.expect_range_start( 742 session_id, 743 vec![session_status_notf(session_id, SessionState::SessionStateActive)], 744 Ok(()), 745 ); 746 uci_manager.expect_range_stop( 747 session_id, 748 vec![session_status_notf(session_id, SessionState::SessionStateIdle)], 749 Ok(()), 750 ); 751 }) 752 .await; 753 754 let result = session_manager.init_session(session_id, session_type, params.clone()).await; 755 assert_eq!(result, Ok(())); 756 let result = session_manager.start_ranging(session_id).await; 757 assert_eq!(result, Ok(params)); 758 let result = session_manager.stop_ranging(session_id).await; 759 assert_eq!(result, Ok(())); 760 761 assert!(mock_uci_manager.wait_expected_calls_done().await); 762 } 763 764 #[tokio::test] test_ccc_start_ranging()765 async fn test_ccc_start_ranging() { 766 let session_id = 0x123; 767 let session_type = SessionType::Ccc; 768 // params that is passed to UciManager::session_set_app_config(). 769 let params = generate_ccc_params(); 770 let tlvs = params.generate_tlvs(); 771 // The params that is received from UciManager::session_get_app_config(). 772 let received_config_map = HashMap::from([ 773 (AppConfigTlvType::StsIndex, u32_to_bytes(3)), 774 (AppConfigTlvType::CccHopModeKey, u32_to_bytes(5)), 775 (AppConfigTlvType::CccUwbTime0, u64_to_bytes(7)), 776 (AppConfigTlvType::RangingDuration, u32_to_bytes(96)), 777 (AppConfigTlvType::PreambleCodeIndex, u8_to_bytes(9)), 778 ]); 779 let received_tlvs = received_config_map 780 .iter() 781 .map(|(key, value)| AppConfigTlv::new(*key, value.clone())) 782 .collect(); 783 let started_params = 784 CccStartedAppConfigParams::from_config_map(received_config_map).unwrap(); 785 786 let (mut session_manager, mut mock_uci_manager, _) = 787 setup_session_manager(move |uci_manager| { 788 uci_manager.expect_session_init( 789 session_id, 790 session_type, 791 vec![session_status_notf(session_id, SessionState::SessionStateInit)], 792 Ok(()), 793 ); 794 uci_manager.expect_session_set_app_config( 795 session_id, 796 tlvs, 797 vec![session_status_notf(session_id, SessionState::SessionStateIdle)], 798 Ok(SetAppConfigResponse { 799 status: StatusCode::UciStatusOk, 800 config_status: vec![], 801 }), 802 ); 803 uci_manager.expect_range_start( 804 session_id, 805 vec![session_status_notf(session_id, SessionState::SessionStateActive)], 806 Ok(()), 807 ); 808 uci_manager.expect_session_get_app_config(session_id, vec![], Ok(received_tlvs)); 809 }) 810 .await; 811 812 let result = session_manager.init_session(session_id, session_type, params.clone()).await; 813 assert_eq!(result, Ok(())); 814 let result = session_manager.start_ranging(session_id).await; 815 assert_eq!(result, Ok(AppConfigParams::CccStarted(started_params))); 816 817 assert!(mock_uci_manager.wait_expected_calls_done().await); 818 } 819 820 #[tokio::test] test_update_controller_multicast_list()821 async fn test_update_controller_multicast_list() { 822 let session_id = 0x123; 823 let session_type = SessionType::FiraRangingSession; 824 let params = generate_params(); 825 let tlvs = params.generate_tlvs(); 826 let action = UpdateMulticastListAction::AddControlee; 827 let short_address: [u8; 2] = [0x12, 0x34]; 828 let controlees = vec![Controlee { short_address, subsession_id: 0x24 }]; 829 830 let controlees_clone = controlees.clone(); 831 let (mut session_manager, mut mock_uci_manager, _) = 832 setup_session_manager(move |uci_manager| { 833 let multicast_list_notf = vec![UciNotification::Session( 834 UciSessionNotification::UpdateControllerMulticastListV1 { 835 session_token: session_id, 836 remaining_multicast_list_size: 1, 837 status_list: vec![ControleeStatusV1 { 838 mac_address: [0x34, 0x12], 839 subsession_id: 0x24, 840 status: MulticastUpdateStatusCode::StatusOkMulticastListUpdate, 841 }], 842 }, 843 )]; 844 uci_manager.expect_session_init( 845 session_id, 846 session_type, 847 vec![session_status_notf(session_id, SessionState::SessionStateInit)], 848 Ok(()), 849 ); 850 uci_manager.expect_session_set_app_config( 851 session_id, 852 tlvs, 853 vec![session_status_notf(session_id, SessionState::SessionStateIdle)], 854 Ok(SetAppConfigResponse { 855 status: StatusCode::UciStatusOk, 856 config_status: vec![], 857 }), 858 ); 859 uci_manager.expect_session_update_controller_multicast_list( 860 session_id, 861 action, 862 Controlees::NoSessionKey(controlees_clone), 863 multicast_list_notf, 864 Ok(SessionUpdateControllerMulticastResponse { 865 status: StatusCode::UciStatusOk, 866 status_list: vec![], 867 }), 868 ); 869 }) 870 .await; 871 872 let result = session_manager.init_session(session_id, session_type, params).await; 873 assert_eq!(result, Ok(())); 874 let result = 875 session_manager.update_controller_multicast_list(session_id, action, controlees).await; 876 assert_eq!(result, Ok(())); 877 878 assert!(mock_uci_manager.wait_expected_calls_done().await); 879 } 880 881 #[tokio::test] test_ccc_update_controller_multicast_list()882 async fn test_ccc_update_controller_multicast_list() { 883 let session_id = 0x123; 884 let session_type = SessionType::Ccc; 885 let params = generate_ccc_params(); 886 let tlvs = params.generate_tlvs(); 887 let action = UpdateMulticastListAction::AddControlee; 888 let short_address: [u8; 2] = [0x12, 0x34]; 889 let controlees = vec![Controlee { short_address, subsession_id: 0x24 }]; 890 891 let (mut session_manager, mut mock_uci_manager, _) = 892 setup_session_manager(move |uci_manager| { 893 uci_manager.expect_session_init( 894 session_id, 895 session_type, 896 vec![session_status_notf(session_id, SessionState::SessionStateInit)], 897 Ok(()), 898 ); 899 uci_manager.expect_session_set_app_config( 900 session_id, 901 tlvs, 902 vec![session_status_notf(session_id, SessionState::SessionStateIdle)], 903 Ok(SetAppConfigResponse { 904 status: StatusCode::UciStatusOk, 905 config_status: vec![], 906 }), 907 ); 908 }) 909 .await; 910 911 let result = session_manager.init_session(session_id, session_type, params).await; 912 assert_eq!(result, Ok(())); 913 // CCC session doesn't support update_controller_multicast_list. 914 let result = 915 session_manager.update_controller_multicast_list(session_id, action, controlees).await; 916 assert_eq!(result, Err(Error::BadParameters)); 917 918 assert!(mock_uci_manager.wait_expected_calls_done().await); 919 } 920 921 #[tokio::test] test_update_controller_multicast_list_without_notification()922 async fn test_update_controller_multicast_list_without_notification() { 923 let session_id = 0x123; 924 let session_type = SessionType::FiraRangingSession; 925 let params = generate_params(); 926 let tlvs = params.generate_tlvs(); 927 let action = UpdateMulticastListAction::AddControlee; 928 let short_address: [u8; 2] = [0x12, 0x34]; 929 let controlees = vec![Controlee { short_address, subsession_id: 0x24 }]; 930 931 let controlees_clone = controlees.clone(); 932 let (mut session_manager, mut mock_uci_manager, _) = 933 setup_session_manager(move |uci_manager| { 934 uci_manager.expect_session_init( 935 session_id, 936 session_type, 937 vec![session_status_notf(session_id, SessionState::SessionStateInit)], 938 Ok(()), 939 ); 940 uci_manager.expect_session_set_app_config( 941 session_id, 942 tlvs, 943 vec![session_status_notf(session_id, SessionState::SessionStateIdle)], 944 Ok(SetAppConfigResponse { 945 status: StatusCode::UciStatusOk, 946 config_status: vec![], 947 }), 948 ); 949 uci_manager.expect_session_update_controller_multicast_list( 950 session_id, 951 action, 952 uwb_uci_packets::Controlees::NoSessionKey(controlees_clone), 953 vec![], // Not sending notification. 954 Ok(SessionUpdateControllerMulticastResponse { 955 status: StatusCode::UciStatusOk, 956 status_list: vec![], 957 }), 958 ); 959 }) 960 .await; 961 962 let result = session_manager.init_session(session_id, session_type, params).await; 963 assert_eq!(result, Ok(())); 964 // This method should timeout waiting for the notification. 965 let result = 966 session_manager.update_controller_multicast_list(session_id, action, controlees).await; 967 assert_eq!(result, Err(Error::Timeout)); 968 969 assert!(mock_uci_manager.wait_expected_calls_done().await); 970 } 971 972 #[tokio::test] test_receive_session_range_data()973 async fn test_receive_session_range_data() { 974 let session_id = 0x123; 975 let session_type = SessionType::FiraRangingSession; 976 let params = generate_params(); 977 let tlvs = params.generate_tlvs(); 978 let range_data = session_range_data(session_id); 979 let range_data_clone = range_data.clone(); 980 981 let (mut session_manager, mut mock_uci_manager, mut session_notf_receiver) = 982 setup_session_manager(move |uci_manager| { 983 uci_manager.expect_session_init( 984 session_id, 985 session_type, 986 vec![session_status_notf(session_id, SessionState::SessionStateInit)], 987 Ok(()), 988 ); 989 uci_manager.expect_session_set_app_config( 990 session_id, 991 tlvs, 992 vec![ 993 session_status_notf(session_id, SessionState::SessionStateIdle), 994 range_data_notf(range_data_clone), 995 ], 996 Ok(SetAppConfigResponse { 997 status: StatusCode::UciStatusOk, 998 config_status: vec![], 999 }), 1000 ); 1001 }) 1002 .await; 1003 1004 let result = session_manager.init_session(session_id, session_type, params).await; 1005 assert_eq!(result, Ok(())); 1006 let session_notf = session_notf_receiver.recv().await.unwrap(); 1007 assert_eq!( 1008 session_notf, 1009 SessionNotification::SessionState { 1010 session_id, 1011 session_state: SessionState::SessionStateInit, 1012 reason_code: ReasonCode::StateChangeWithSessionManagementCommands 1013 } 1014 ); 1015 let session_notf = session_notf_receiver.recv().await.unwrap(); 1016 assert_eq!( 1017 session_notf, 1018 SessionNotification::SessionState { 1019 session_id, 1020 session_state: SessionState::SessionStateIdle, 1021 reason_code: ReasonCode::StateChangeWithSessionManagementCommands 1022 } 1023 ); 1024 1025 let session_notf = session_notf_receiver.recv().await.unwrap(); 1026 assert_eq!(session_notf, SessionNotification::RangeData { session_id, range_data }); 1027 1028 assert!(mock_uci_manager.wait_expected_calls_done().await); 1029 } 1030 1031 #[tokio::test] test_reconfigure_app_config()1032 async fn test_reconfigure_app_config() { 1033 let session_id = 0x123; 1034 let session_type = SessionType::FiraRangingSession; 1035 1036 let initial_params = generate_params(); 1037 let initial_tlvs = initial_params.generate_tlvs(); 1038 1039 let non_default_key_rotation_val = KeyRotation::Enable; 1040 let idle_params = FiraAppConfigParamsBuilder::from_params(&initial_params) 1041 .unwrap() 1042 .key_rotation(non_default_key_rotation_val) 1043 .build() 1044 .unwrap(); 1045 let idle_tlvs = idle_params 1046 .generate_updated_tlvs(&initial_params, SessionState::SessionStateIdle) 1047 .unwrap(); 1048 1049 let non_default_block_stride_val = 2u8; 1050 let active_params = FiraAppConfigParamsBuilder::from_params(&idle_params) 1051 .unwrap() 1052 .block_stride_length(non_default_block_stride_val) 1053 .build() 1054 .unwrap(); 1055 let active_tlvs = active_params 1056 .generate_updated_tlvs(&idle_params, SessionState::SessionStateIdle) 1057 .unwrap(); 1058 1059 let (mut session_manager, mut mock_uci_manager, _) = 1060 setup_session_manager(move |uci_manager| { 1061 uci_manager.expect_session_init( 1062 session_id, 1063 session_type, 1064 vec![session_status_notf(session_id, SessionState::SessionStateInit)], 1065 Ok(()), 1066 ); 1067 uci_manager.expect_session_set_app_config( 1068 session_id, 1069 initial_tlvs, 1070 vec![session_status_notf(session_id, SessionState::SessionStateIdle)], 1071 Ok(SetAppConfigResponse { 1072 status: StatusCode::UciStatusOk, 1073 config_status: vec![], 1074 }), 1075 ); 1076 uci_manager.expect_session_set_app_config( 1077 session_id, 1078 idle_tlvs, 1079 vec![], 1080 Ok(SetAppConfigResponse { 1081 status: StatusCode::UciStatusOk, 1082 config_status: vec![], 1083 }), 1084 ); 1085 uci_manager.expect_range_start( 1086 session_id, 1087 vec![session_status_notf(session_id, SessionState::SessionStateActive)], 1088 Ok(()), 1089 ); 1090 uci_manager.expect_session_set_app_config( 1091 session_id, 1092 active_tlvs, 1093 vec![], 1094 Ok(SetAppConfigResponse { 1095 status: StatusCode::UciStatusOk, 1096 config_status: vec![], 1097 }), 1098 ); 1099 }) 1100 .await; 1101 1102 // Reconfiguring without first initing a session should fail. 1103 let result = session_manager.reconfigure(session_id, initial_params.clone()).await; 1104 assert_eq!(result, Err(Error::BadParameters)); 1105 1106 let result = 1107 session_manager.init_session(session_id, session_type, initial_params.clone()).await; 1108 assert_eq!(result, Ok(())); 1109 1110 // Reconfiguring any parameters during idle state should succeed. 1111 let result = session_manager.reconfigure(session_id, idle_params.clone()).await; 1112 assert_eq!(result, Ok(())); 1113 1114 let result = session_manager.start_ranging(session_id).await; 1115 assert_eq!(result, Ok(idle_params)); 1116 1117 // Reconfiguring most parameters during active state should fail. 1118 let result = session_manager.reconfigure(session_id, initial_params).await; 1119 assert_eq!(result, Err(Error::BadParameters)); 1120 1121 // Only some parameters are allowed to be reconfigured during active state. 1122 let result = session_manager.reconfigure(session_id, active_params).await; 1123 assert_eq!(result, Ok(())); 1124 1125 assert!(mock_uci_manager.wait_expected_calls_done().await); 1126 } 1127 1128 #[tokio::test] test_session_params()1129 async fn test_session_params() { 1130 let session_id = 0x123; 1131 let session_type = SessionType::FiraRangingSession; 1132 1133 let params = generate_params(); 1134 let tlvs = params.generate_tlvs(); 1135 1136 let (mut session_manager, mut mock_uci_manager, _) = 1137 setup_session_manager(move |uci_manager| { 1138 uci_manager.expect_session_init( 1139 session_id, 1140 session_type, 1141 vec![session_status_notf(session_id, SessionState::SessionStateInit)], 1142 Ok(()), 1143 ); 1144 uci_manager.expect_session_set_app_config( 1145 session_id, 1146 tlvs, 1147 vec![session_status_notf(session_id, SessionState::SessionStateIdle)], 1148 Ok(SetAppConfigResponse { 1149 status: StatusCode::UciStatusOk, 1150 config_status: vec![], 1151 }), 1152 ); 1153 }) 1154 .await; 1155 1156 // Getting session params without initing a session should fail 1157 let result = session_manager.session_params(session_id).await; 1158 assert_eq!(result, Err(Error::BadParameters)); 1159 1160 let result = session_manager.init_session(session_id, session_type, params.clone()).await; 1161 result.unwrap(); 1162 1163 // Getting session params after they've been properly set should succeed 1164 let result = session_manager.session_params(session_id).await; 1165 assert_eq!(result, Ok(params)); 1166 1167 assert!(mock_uci_manager.wait_expected_calls_done().await); 1168 } 1169 } 1170