uwb_core: add start/stop ranging method at SessionManager

This CL adds start_ranging() and stop_ranging methods at
SessionManager. The methods call UciManager's methods and wait for the
session status notification.

Bug: 228136039
Test: cargo test
Test: cargo clippy

Change-Id: I6ff52eb00544e8595962db051c0aac431426eb4c
diff --git a/src/rust/uwb_core/src/session/session_manager.rs b/src/rust/uwb_core/src/session/session_manager.rs
index b29bd33..a44a983 100644
--- a/src/rust/uwb_core/src/session/session_manager.rs
+++ b/src/rust/uwb_core/src/session/session_manager.rs
@@ -64,6 +64,14 @@
         self.send_cmd(SessionCommand::DeinitSession { session_id }).await
     }
 
+    async fn start_ranging(&mut self, session_id: SessionId) -> Result<()> {
+        self.send_cmd(SessionCommand::StartRanging { session_id }).await
+    }
+
+    async fn stop_ranging(&mut self, session_id: SessionId) -> Result<()> {
+        self.send_cmd(SessionCommand::StopRanging { session_id }).await
+    }
+
     // Send the |cmd| to the SessionManagerActor.
     async fn send_cmd(&self, cmd: SessionCommand) -> Result<()> {
         let (result_sender, result_receiver) = oneshot::channel();
@@ -154,6 +162,27 @@
                     }
                 }
             }
+
+            SessionCommand::StartRanging { session_id } => {
+                match self.active_sessions.get_mut(&session_id) {
+                    None => {
+                        let _ = result_sender.send(Err(Error::UnknownSessionId(session_id)));
+                    }
+                    Some(session) => {
+                        session.start_ranging(result_sender);
+                    }
+                }
+            }
+            SessionCommand::StopRanging { session_id } => {
+                match self.active_sessions.get_mut(&session_id) {
+                    None => {
+                        let _ = result_sender.send(Err(Error::UnknownSessionId(session_id)));
+                    }
+                    Some(session) => {
+                        session.stop_ranging(result_sender);
+                    }
+                }
+            }
         }
     }
 
@@ -187,6 +216,8 @@
 enum SessionCommand {
     InitSession { session_id: SessionId, session_type: SessionType, params: AppConfigParams },
     DeinitSession { session_id: SessionId },
+    StartRanging { session_id: SessionId },
+    StopRanging { session_id: SessionId },
 }
 
 #[cfg(test)]
@@ -314,4 +345,53 @@
 
         assert!(mock_uci_manager.wait_expected_calls_done().await);
     }
+
+    #[tokio::test]
+    async fn test_start_stop_ranging() {
+        let session_id = 0x123;
+        let session_type = SessionType::FiraRangingSession;
+        let params = generate_params();
+        let tlvs = params.generate_tlvs();
+
+        let (mut session_manager, mut mock_uci_manager) =
+            setup_session_manager(move |uci_manager| {
+                let state_init_notf = vec![UciNotification::SessionStatus {
+                    session_id,
+                    session_state: SessionState::SessionStateInit,
+                    reason_code: ReasonCode::StateChangeWithSessionManagementCommands,
+                }];
+                let state_idle_notf = vec![UciNotification::SessionStatus {
+                    session_id,
+                    session_state: SessionState::SessionStateIdle,
+                    reason_code: ReasonCode::StateChangeWithSessionManagementCommands,
+                }];
+                let state_active_notf = vec![UciNotification::SessionStatus {
+                    session_id,
+                    session_state: SessionState::SessionStateActive,
+                    reason_code: ReasonCode::StateChangeWithSessionManagementCommands,
+                }];
+                uci_manager.expect_session_init(session_id, session_type, state_init_notf, Ok(()));
+                uci_manager.expect_session_set_app_config(
+                    session_id,
+                    tlvs,
+                    state_idle_notf.clone(),
+                    Ok(SetAppConfigResponse {
+                        status: StatusCode::UciStatusOk,
+                        config_status: vec![],
+                    }),
+                );
+                uci_manager.expect_range_start(session_id, state_active_notf, Ok(()));
+                uci_manager.expect_range_stop(session_id, state_idle_notf, Ok(()));
+            })
+            .await;
+
+        let result = session_manager.init_session(session_id, session_type, params).await;
+        assert_eq!(result, Ok(()));
+        let result = session_manager.start_ranging(session_id).await;
+        assert_eq!(result, Ok(()));
+        let result = session_manager.stop_ranging(session_id).await;
+        assert_eq!(result, Ok(()));
+
+        assert!(mock_uci_manager.wait_expected_calls_done().await);
+    }
 }
diff --git a/src/rust/uwb_core/src/session/uwb_session.rs b/src/rust/uwb_core/src/session/uwb_session.rs
index 37f3824..66b5fd6 100644
--- a/src/rust/uwb_core/src/session/uwb_session.rs
+++ b/src/rust/uwb_core/src/session/uwb_session.rs
@@ -64,6 +64,14 @@
         let _ = self.cmd_sender.send((Command::Deinitialize, result_sender));
     }
 
+    pub fn start_ranging(&mut self, result_sender: oneshot::Sender<Result<()>>) {
+        let _ = self.cmd_sender.send((Command::StartRanging, result_sender));
+    }
+
+    pub fn stop_ranging(&mut self, result_sender: oneshot::Sender<Result<()>>) {
+        let _ = self.cmd_sender.send((Command::StopRanging, result_sender));
+    }
+
     pub fn set_state(&mut self, state: SessionState) {
         let _ = self.state_sender.send(state);
     }
@@ -101,6 +109,8 @@
                             let result = match cmd {
                                 Command::Initialize { params } => self.initialize(params).await,
                                 Command::Deinitialize => self.deinitialize().await,
+                                Command::StartRanging => self.start_ranging().await,
+                                Command::StopRanging => self.stop_ranging().await,
                             };
                             let _ = result_sender.send(result);
                         }
@@ -149,6 +159,52 @@
         Ok(())
     }
 
+    async fn start_ranging(&mut self) -> Result<()> {
+        let state = *self.state_receiver.borrow();
+        match state {
+            SessionState::SessionStateActive => {
+                warn!("Session {} is already running", self.session_id);
+                Ok(())
+            }
+            SessionState::SessionStateIdle => {
+                if let Err(e) = self.uci_manager.range_start(self.session_id).await {
+                    error!("Failed to start ranging: {:?}", e);
+                    return Err(Error::Uci);
+                }
+                self.wait_state(SessionState::SessionStateActive).await?;
+
+                Ok(())
+            }
+            _ => {
+                error!("Session {} cannot start running at {:?}", self.session_id, state);
+                Err(Error::WrongState(state))
+            }
+        }
+    }
+
+    async fn stop_ranging(&mut self) -> Result<()> {
+        let state = *self.state_receiver.borrow();
+        match state {
+            SessionState::SessionStateIdle => {
+                warn!("Session {} is already stopped", self.session_id);
+                Ok(())
+            }
+            SessionState::SessionStateActive => {
+                if let Err(e) = self.uci_manager.range_stop(self.session_id).await {
+                    error!("Failed to start ranging: {:?}", e);
+                    return Err(Error::Uci);
+                }
+                self.wait_state(SessionState::SessionStateIdle).await?;
+
+                Ok(())
+            }
+            _ => {
+                error!("Session {} cannot stop running at {:?}", self.session_id, state);
+                Err(Error::WrongState(state))
+            }
+        }
+    }
+
     async fn wait_state(&mut self, expected_state: SessionState) -> Result<()> {
         const WAIT_STATE_TIMEOUT_MS: u64 = 1000;
         match timeout(Duration::from_millis(WAIT_STATE_TIMEOUT_MS), self.state_receiver.changed())
@@ -182,4 +238,6 @@
 enum Command {
     Initialize { params: AppConfigParams },
     Deinitialize,
+    StartRanging,
+    StopRanging,
 }
diff --git a/src/rust/uwb_core/src/uci/mock_uci_manager.rs b/src/rust/uwb_core/src/uci/mock_uci_manager.rs
index c69dc51..f3aa425 100644
--- a/src/rust/uwb_core/src/uci/mock_uci_manager.rs
+++ b/src/rust/uwb_core/src/uci/mock_uci_manager.rs
@@ -180,18 +180,30 @@
         );
     }
 
-    pub fn expect_range_start(&mut self, expected_session_id: SessionId, out: Result<()>) {
-        self.expected_calls
-            .lock()
-            .unwrap()
-            .push_back(ExpectedCall::RangeStart { expected_session_id, out });
+    pub fn expect_range_start(
+        &mut self,
+        expected_session_id: SessionId,
+        notfs: Vec<UciNotification>,
+        out: Result<()>,
+    ) {
+        self.expected_calls.lock().unwrap().push_back(ExpectedCall::RangeStart {
+            expected_session_id,
+            notfs,
+            out,
+        });
     }
 
-    pub fn expect_range_stop(&mut self, expected_session_id: SessionId, out: Result<()>) {
-        self.expected_calls
-            .lock()
-            .unwrap()
-            .push_back(ExpectedCall::RangeStop { expected_session_id, out });
+    pub fn expect_range_stop(
+        &mut self,
+        expected_session_id: SessionId,
+        notfs: Vec<UciNotification>,
+        out: Result<()>,
+    ) {
+        self.expected_calls.lock().unwrap().push_back(ExpectedCall::RangeStop {
+            expected_session_id,
+            notfs,
+            out,
+        });
     }
 
     pub fn expect_range_get_ranging_count(
@@ -523,10 +535,13 @@
     async fn range_start(&mut self, session_id: SessionId) -> Result<()> {
         let mut expected_calls = self.expected_calls.lock().unwrap();
         match expected_calls.pop_front() {
-            Some(ExpectedCall::RangeStart { expected_session_id, out })
+            Some(ExpectedCall::RangeStart { expected_session_id, notfs, out })
                 if expected_session_id == session_id =>
             {
                 self.expect_call_consumed.notify_one();
+                for notf in notfs.into_iter() {
+                    let _ = self.notf_sender.as_mut().unwrap().send(notf);
+                }
                 out
             }
             Some(call) => {
@@ -540,10 +555,13 @@
     async fn range_stop(&mut self, session_id: SessionId) -> Result<()> {
         let mut expected_calls = self.expected_calls.lock().unwrap();
         match expected_calls.pop_front() {
-            Some(ExpectedCall::RangeStop { expected_session_id, out })
+            Some(ExpectedCall::RangeStop { expected_session_id, notfs, out })
                 if expected_session_id == session_id =>
             {
                 self.expect_call_consumed.notify_one();
+                for notf in notfs.into_iter() {
+                    let _ = self.notf_sender.as_mut().unwrap().send(notf);
+                }
                 out
             }
             Some(call) => {
@@ -692,10 +710,12 @@
     },
     RangeStart {
         expected_session_id: SessionId,
+        notfs: Vec<UciNotification>,
         out: Result<()>,
     },
     RangeStop {
         expected_session_id: SessionId,
+        notfs: Vec<UciNotification>,
         out: Result<()>,
     },
     RangeGetRangingCount {