Snap for 11224086 from 5100eb322e6fa1ed6dc7db36501a42774de885ef to mainline-tzdata5-release

Change-Id: Ib74ce235da75abac429642f71554453509d30198
diff --git a/src/Android.bp b/src/Android.bp
index 193ac98..c0448b7 100755
--- a/src/Android.bp
+++ b/src/Android.bp
@@ -331,6 +331,9 @@
                 "libcutils",
                 "liblog",
                 "libutils",
+                "libbinder_ndk",
+                "libbinder",
+                "libc++",
             ],
             // See b/268061150
             stem: "libuci_hal_android_tests_host",
diff --git a/src/rust/uwb_core/examples/main.rs b/src/rust/uwb_core/examples/main.rs
index 63317b1..5f298c6 100644
--- a/src/rust/uwb_core/examples/main.rs
+++ b/src/rust/uwb_core/examples/main.rs
@@ -52,6 +52,7 @@
             UwbError::Timeout => {}
             UwbError::CommandRetry => {}
             UwbError::DuplicatedSessionId => {}
+            UwbError::RegulationUwbOff => {}
             UwbError::Unknown => {}
 
             // UwbError is non_exhaustive so we need to add a wild branch here.
diff --git a/src/rust/uwb_core/protos/uwb_service.proto b/src/rust/uwb_core/protos/uwb_service.proto
index e13765e..d7c4c38 100644
--- a/src/rust/uwb_core/protos/uwb_service.proto
+++ b/src/rust/uwb_core/protos/uwb_service.proto
@@ -56,8 +56,11 @@
   // Duplicated SessionId.
   DUPLICATED_SESSION_ID = 8;
 
+  //Regulation UWB off
+  REGULATION_UWB_OFF = 9;
+
   // The unknown error.
-  UNKNOWN = 9;
+  UNKNOWN = 10;
 }
 
 // Represent uwb_uci_packets::StatusCode.
@@ -73,6 +76,7 @@
   UCI_STATUS_UNKNOWN_OID = 8;
   UCI_STATUS_READ_ONLY = 9;
   UCI_STATUS_COMMAND_RETRY = 10;
+  UCI_STATUS_UNKNOWN = 11;
 
   UCI_STATUS_SESSION_NOT_EXIST = 17;
   UCI_STATUS_SESSION_DUPLICATE = 18;
@@ -103,6 +107,7 @@
   UCI_STATUS_ERROR_CCC_SE_BUSY = 80;
   UCI_STATUS_ERROR_CCC_LIFECYCLE = 81;
   UCI_STATUS_ERROR_STOPPED_DUE_TO_OTHER_SESSION_CONFLICT = 82;
+  UCI_STATUS_REGULATION_UWB_OFF = 83;
   // All vendor specific status code will be mapped to UCI_STATUS_VENDOR_SPECIFIC.
   UCI_STATUS_RFU_OR_VENDOR_SPECIFIC = 255;
 }
@@ -183,10 +188,15 @@
 
 // Represent uwb_uci_packets::SessionType.
 enum SessionType {
-  FIRA_RANGING_SESSION = 0;
-  FIRA_DATA_TRANSFER = 1;
-  CCC = 2;
-  DEVICE_TEST_MODE = 3;
+  FIRA_RANGING_SESSION = 0x00;
+  FIRA_RANGING_AND_IN_BAND_DATA_SESSION = 0x01;
+  FIRA_DATA_TRANSFER = 0x02;
+  FIRA_RANGING_ONLY_PHASE = 0x03;
+  FIRA_IN_BAND_DATA_PHASE = 0x04;
+  FIRA_RANGING_WITH_DATA_PHASE = 0x05;
+  CCC = 0xA0;
+  RADAR_SESSION = 0xA1;
+  DEVICE_TEST_MODE = 0xD0;
 }
 
 // Represent uwb_uci_packets::UpdateMulticastListAction.
diff --git a/src/rust/uwb_core/src/error.rs b/src/rust/uwb_core/src/error.rs
index 0b9c6b3..5889448 100644
--- a/src/rust/uwb_core/src/error.rs
+++ b/src/rust/uwb_core/src/error.rs
@@ -49,6 +49,9 @@
     /// Packet Tx Error
     #[error("The packet send failed with an error")]
     PacketTxError,
+    /// Country code regulation UWB Off
+    #[error("The country code command failed with a UWB regulatory error")]
+    RegulationUwbOff,
     /// The unknown error.
     #[error("The unknown error")]
     Unknown,
diff --git a/src/rust/uwb_core/src/params/app_config_params.rs b/src/rust/uwb_core/src/params/app_config_params.rs
index bb06d52..a264002 100644
--- a/src/rust/uwb_core/src/params/app_config_params.rs
+++ b/src/rust/uwb_core/src/params/app_config_params.rs
@@ -94,8 +94,12 @@
     pub fn is_type_matched(&self, session_type: SessionType) -> bool {
         match self {
             Self::Fira(_) => {
-                session_type == SessionType::FiraDataTransfer
+                session_type == SessionType::FiraDataTransferSession
                     || session_type == SessionType::FiraRangingSession
+                    || session_type == SessionType::FiraRangingAndInBandDataSession
+                    || session_type == SessionType::FiraRangingOnlyPhase
+                    || session_type == SessionType::FiraInBandDataPhase
+                    || session_type == SessionType::FiraRangingWithDataPhase
             }
             Self::Ccc(_) | Self::CccStarted(_) => session_type == SessionType::Ccc,
         }
diff --git a/src/rust/uwb_core/src/params/uci_packets.rs b/src/rust/uwb_core/src/params/uci_packets.rs
index 5cd5822..e3a7722 100644
--- a/src/rust/uwb_core/src/params/uci_packets.rs
+++ b/src/rust/uwb_core/src/params/uci_packets.rs
@@ -20,12 +20,13 @@
 
 // Re-export enums and structs from uwb_uci_packets.
 pub use uwb_uci_packets::{
-    AppConfigStatus, AppConfigTlv as RawAppConfigTlv, AppConfigTlvType, CapTlv, CapTlvType,
-    Controlee, ControleeStatus, Controlees, CreditAvailability, DataRcvStatusCode,
+    AppConfigStatus, AppConfigTlv as RawAppConfigTlv, AppConfigTlvType, BitsPerSample, CapTlv,
+    CapTlvType, Controlee, ControleeStatus, Controlees, CreditAvailability, DataRcvStatusCode,
     DataTransferNtfStatusCode, DeviceConfigId, DeviceConfigStatus, DeviceConfigTlv, DeviceState,
     ExtendedAddressDlTdoaRangingMeasurement, ExtendedAddressOwrAoaRangingMeasurement,
     ExtendedAddressTwoWayRangingMeasurement, GroupId, MessageType, MulticastUpdateStatusCode,
-    PowerStats, RangingMeasurementType, ReasonCode, ResetConfig, SessionState, SessionType,
+    PhaseList, PowerStats, RadarConfigStatus, RadarConfigTlv, RadarConfigTlvType, RadarDataType,
+    RangingMeasurementType, ReasonCode, ResetConfig, SessionState, SessionType,
     ShortAddressDlTdoaRangingMeasurement, ShortAddressOwrAoaRangingMeasurement,
     ShortAddressTwoWayRangingMeasurement, StatusCode, UpdateMulticastListAction,
 };
@@ -124,6 +125,19 @@
     HashMap::from_iter(tlvs.iter().map(|config| (config.cfg_id, &config.v)))
 }
 
+/// Compare if two RadarConfigTlv array are equal. Convert the array to HashMap before comparing
+/// because the order of TLV elements doesn't matter.
+#[allow(dead_code)]
+pub fn radar_config_tlvs_eq(a: &[RadarConfigTlv], b: &[RadarConfigTlv]) -> bool {
+    radar_config_tlvs_to_map(a) == radar_config_tlvs_to_map(b)
+}
+
+fn radar_config_tlvs_to_map(
+    tlvs: &[RadarConfigTlv],
+) -> HashMap<RadarConfigTlvType, &Vec<u8>, RandomState> {
+    HashMap::from_iter(tlvs.iter().map(|config| (config.cfg_id, &config.v)))
+}
+
 /// The response of the UciManager::core_set_config() method.
 #[derive(Debug, Clone, PartialEq)]
 pub struct CoreSetConfigResponse {
@@ -142,6 +156,15 @@
     pub config_status: Vec<AppConfigStatus>,
 }
 
+/// The response of the UciManager::android_set_radar_config() method.
+#[derive(Debug, Clone, PartialEq)]
+pub struct AndroidRadarConfigResponse {
+    /// The status code of the response.
+    pub status: StatusCode,
+    /// The status of each config TLV.
+    pub config_status: Vec<RadarConfigStatus>,
+}
+
 /// The response from UciManager::session_update_dt_tag_ranging_rounds() method.
 #[derive(Debug, Clone, PartialEq, Eq)]
 pub struct SessionUpdateDtTagRangingRoundsResponse {
@@ -184,9 +207,28 @@
     }
 }
 
+/// absolute time in UWBS Time domain(ms) when this configuration applies
+#[derive(Debug, Clone, PartialEq, Copy)]
+pub struct UpdateTime([u8; 8]);
+
+impl UpdateTime {
+    /// Create a UpdateTime instance.
+    pub fn new(update_time: &[u8; 8]) -> Option<Self> {
+        Some(Self(*update_time))
+    }
+}
+
+impl From<UpdateTime> for [u8; 8] {
+    fn from(item: UpdateTime) -> [u8; 8] {
+        item.0
+    }
+}
+
 /// The response of the UciManager::core_get_device_info() method.
 #[derive(Debug, Clone, PartialEq, Eq)]
 pub struct GetDeviceInfoResponse {
+    /// Status
+    pub status: StatusCode,
     /// The UCI version.
     pub uci_version: u16,
     /// The MAC version.
diff --git a/src/rust/uwb_core/src/proto/mappings.rs b/src/rust/uwb_core/src/proto/mappings.rs
index a08046d..c10cf0e 100644
--- a/src/rust/uwb_core/src/proto/mappings.rs
+++ b/src/rust/uwb_core/src/proto/mappings.rs
@@ -116,6 +116,7 @@
             ProtoStatusCode::UCI_STATUS_UNKNOWN_OID => StatusCode::UciStatusUnknownOid,
             ProtoStatusCode::UCI_STATUS_READ_ONLY => StatusCode::UciStatusReadOnly,
             ProtoStatusCode::UCI_STATUS_COMMAND_RETRY => StatusCode::UciStatusCommandRetry,
+            ProtoStatusCode::UCI_STATUS_UNKNOWN => StatusCode::UciStatusUnknown,
             ProtoStatusCode::UCI_STATUS_SESSION_NOT_EXIST => StatusCode::UciStatusSessionNotExist,
             ProtoStatusCode::UCI_STATUS_SESSION_DUPLICATE => StatusCode::UciStatusSessionDuplicate,
             ProtoStatusCode::UCI_STATUS_SESSION_ACTIVE => StatusCode::UciStatusSessionActive,
@@ -179,6 +180,7 @@
             ProtoStatusCode::UCI_STATUS_ERROR_STOPPED_DUE_TO_OTHER_SESSION_CONFLICT => {
                 StatusCode::UciStatusErrorStoppedDueToOtherSessionConflict
             }
+            ProtoStatusCode::UCI_STATUS_REGULATION_UWB_OFF => StatusCode::UciStatusRegulationUwbOff,
             _ =>  StatusCode::VendorSpecificStatusCode2,
         }
     }
@@ -198,6 +200,7 @@
             StatusCode::UciStatusUnknownOid => ProtoStatusCode::UCI_STATUS_UNKNOWN_OID,
             StatusCode::UciStatusReadOnly => ProtoStatusCode::UCI_STATUS_READ_ONLY,
             StatusCode::UciStatusCommandRetry => ProtoStatusCode::UCI_STATUS_COMMAND_RETRY,
+            StatusCode::UciStatusUnknown => ProtoStatusCode::UCI_STATUS_UNKNOWN,
             StatusCode::UciStatusSessionNotExist => ProtoStatusCode::UCI_STATUS_SESSION_NOT_EXIST,
             StatusCode::UciStatusSessionDuplicate => ProtoStatusCode::UCI_STATUS_SESSION_DUPLICATE,
             StatusCode::UciStatusSessionActive => ProtoStatusCode::UCI_STATUS_SESSION_ACTIVE,
@@ -270,6 +273,9 @@
             StatusCode::UciStatusErrorStoppedDueToOtherSessionConflict => {
                 ProtoStatusCode::UCI_STATUS_ERROR_STOPPED_DUE_TO_OTHER_SESSION_CONFLICT
             }
+            StatusCode::UciStatusRegulationUwbOff => {
+                ProtoStatusCode::UCI_STATUS_REGULATION_UWB_OFF
+            }
             _ => ProtoStatusCode::UCI_STATUS_RFU_OR_VENDOR_SPECIFIC,
         }
     }
@@ -526,8 +532,13 @@
 enum_mapping! {
     ProtoSessionType => SessionType,
     FIRA_RANGING_SESSION => FiraRangingSession,
-    FIRA_DATA_TRANSFER => FiraDataTransfer,
+    FIRA_DATA_TRANSFER => FiraDataTransferSession,
+    FIRA_RANGING_AND_IN_BAND_DATA_SESSION => FiraRangingAndInBandDataSession,
+    FIRA_RANGING_ONLY_PHASE => FiraRangingOnlyPhase,
+    FIRA_IN_BAND_DATA_PHASE => FiraInBandDataPhase,
+    FIRA_RANGING_WITH_DATA_PHASE => FiraRangingWithDataPhase,
     CCC => Ccc,
+    RADAR_SESSION => RadarSession,
     DEVICE_TEST_MODE => DeviceTestMode,
 }
 
@@ -703,6 +714,7 @@
             Err(Error::Timeout) => Self::TIMEOUT,
             Err(Error::CommandRetry) => Self::COMMAND_RETRY,
             Err(Error::DuplicatedSessionId) => Self::DUPLICATED_SESSION_ID,
+            Err(Error::RegulationUwbOff) => Self::REGULATION_UWB_OFF,
             Err(_) => Self::UNKNOWN,
         }
     }
diff --git a/src/rust/uwb_core/src/service/uwb_service.rs b/src/rust/uwb_core/src/service/uwb_service.rs
index ce00f95..012fbda 100644
--- a/src/rust/uwb_core/src/service/uwb_service.rs
+++ b/src/rust/uwb_core/src/service/uwb_service.rs
@@ -576,6 +576,7 @@
     use tokio::runtime::Runtime;
 
     use crate::params::uci_packets::{SessionState, SetAppConfigResponse, StatusCode};
+    use crate::params::GetDeviceInfoResponse;
     use crate::service::mock_uwb_service_callback::MockUwbServiceCallback;
     use crate::service::uwb_service_builder::default_runtime;
     use crate::service::uwb_service_callback_builder::UwbServiceCallbackSendBuilder;
@@ -584,6 +585,16 @@
     };
     use crate::uci::mock_uci_manager::MockUciManager;
     use crate::uci::notification::UciNotification;
+    use uwb_uci_packets::StatusCode::UciStatusOk;
+
+    const GET_DEVICE_INFO_RSP: GetDeviceInfoResponse = GetDeviceInfoResponse {
+        status: UciStatusOk,
+        uci_version: 0,
+        mac_version: 0,
+        phy_version: 0,
+        uci_test_version: 0,
+        vendor_spec_info: vec![],
+    };
 
     fn setup_uwb_service(
         uci_manager: MockUciManager,
@@ -599,7 +610,7 @@
     #[test]
     fn test_open_close_uci() {
         let mut uci_manager = MockUciManager::new();
-        uci_manager.expect_open_hal(vec![], Ok(()));
+        uci_manager.expect_open_hal(vec![], Ok(GET_DEVICE_INFO_RSP));
         uci_manager.expect_close_hal(false, Ok(()));
         let (service, _, _runtime) = setup_uwb_service(uci_manager);
 
@@ -618,7 +629,7 @@
         let range_data = session_range_data(session_id);
 
         let mut uci_manager = MockUciManager::new();
-        uci_manager.expect_open_hal(vec![], Ok(()));
+        uci_manager.expect_open_hal(vec![], Ok(GET_DEVICE_INFO_RSP));
         uci_manager.expect_session_init(
             session_id,
             session_type,
@@ -788,7 +799,7 @@
         let mut uci_manager = MockUciManager::new();
         uci_manager.expect_open_hal(
             vec![UciNotification::Vendor(RawUciMessage { gid, oid, payload: payload.clone() })],
-            Ok(()),
+            Ok(GET_DEVICE_INFO_RSP),
         );
         let (service, mut callback, _runtime) = setup_uwb_service(uci_manager);
 
@@ -804,7 +815,7 @@
         let mut uci_manager = MockUciManager::new();
         uci_manager.expect_open_hal(
             vec![UciNotification::Core(CoreNotification::DeviceStatus(state))],
-            Ok(()),
+            Ok(GET_DEVICE_INFO_RSP),
         );
         let (service, mut callback, _runtime) = setup_uwb_service(uci_manager);
         callback.expect_on_uci_device_status_changed(state);
@@ -819,7 +830,7 @@
         uci_manager.expect_open_hal(vec![], Err(Error::Timeout));
         // Then UwbService should close_hal() and open_hal() to reset the HAL.
         uci_manager.expect_close_hal(true, Ok(()));
-        uci_manager.expect_open_hal(vec![], Ok(()));
+        uci_manager.expect_open_hal(vec![], Ok(GET_DEVICE_INFO_RSP));
         let (service, mut callback, _runtime) = setup_uwb_service(uci_manager.clone());
 
         callback.expect_on_service_reset(true);
@@ -838,11 +849,11 @@
             vec![UciNotification::Core(CoreNotification::DeviceStatus(
                 DeviceState::DeviceStateError,
             ))],
-            Ok(()),
+            Ok(GET_DEVICE_INFO_RSP),
         );
         // Then UwbService should close_hal() and open_hal() to reset the HAL.
         uci_manager.expect_close_hal(true, Ok(()));
-        uci_manager.expect_open_hal(vec![], Ok(()));
+        uci_manager.expect_open_hal(vec![], Ok(GET_DEVICE_INFO_RSP));
         let (service, mut callback, _runtime) = setup_uwb_service(uci_manager.clone());
 
         callback.expect_on_service_reset(true);
diff --git a/src/rust/uwb_core/src/session/session_manager.rs b/src/rust/uwb_core/src/session/session_manager.rs
index e49dd9c..449d50d 100644
--- a/src/rust/uwb_core/src/session/session_manager.rs
+++ b/src/rust/uwb_core/src/session/session_manager.rs
@@ -443,9 +443,20 @@
     use crate::params::uci_packets::{
         RangingMeasurementType, ReasonCode, ShortAddressTwoWayRangingMeasurement, StatusCode,
     };
+    use crate::params::GetDeviceInfoResponse;
     use crate::uci::mock_uci_manager::MockUciManager;
     use crate::uci::notification::{RangingMeasurements, UciNotification};
     use crate::utils::init_test_logging;
+    use uwb_uci_packets::StatusCode::UciStatusOk;
+
+    const GET_DEVICE_INFO_RSP: GetDeviceInfoResponse = GetDeviceInfoResponse {
+        status: UciStatusOk,
+        uci_version: 0,
+        mac_version: 0,
+        phy_version: 0,
+        uci_test_version: 0,
+        vendor_spec_info: vec![],
+    };
 
     pub(crate) fn generate_params() -> AppConfigParams {
         FiraAppConfigParamsBuilder::new()
@@ -533,7 +544,7 @@
         let (uci_notf_sender, uci_notf_receiver) = mpsc::unbounded_channel();
         let (session_notf_sender, session_notf_receiver) = mpsc::unbounded_channel();
         let mut uci_manager = MockUciManager::new();
-        uci_manager.expect_open_hal(vec![], Ok(()));
+        uci_manager.expect_open_hal(vec![], Ok(GET_DEVICE_INFO_RSP));
         setup_uci_manager_fn(&mut uci_manager);
         uci_manager.set_session_notification_sender(uci_notf_sender).await;
         let _ = uci_manager.open_hal().await;
diff --git a/src/rust/uwb_core/src/uci.rs b/src/rust/uwb_core/src/uci.rs
index cac1be2..4364966 100644
--- a/src/rust/uwb_core/src/uci.rs
+++ b/src/rust/uwb_core/src/uci.rs
@@ -41,8 +41,8 @@
 // Re-export the public elements.
 pub use command::UciCommand;
 pub use notification::{
-    CoreNotification, DataRcvNotification, RangingMeasurements, SessionNotification,
-    SessionRangeData, UciNotification,
+    CoreNotification, DataRcvNotification, RadarDataRcvNotification, RadarSweepData,
+    RangingMeasurements, SessionNotification, SessionRangeData, UciNotification,
 };
 pub use uci_hal::{NopUciHal, UciHal, UciHalPacket};
 pub use uci_logger_factory::{NopUciLoggerFactory, UciLoggerFactory};
diff --git a/src/rust/uwb_core/src/uci/command.rs b/src/rust/uwb_core/src/uci/command.rs
index 2afb5a8..864ca8f 100644
--- a/src/rust/uwb_core/src/uci/command.rs
+++ b/src/rust/uwb_core/src/uci/command.rs
@@ -20,9 +20,12 @@
 use crate::error::{Error, Result};
 use crate::params::uci_packets::{
     AppConfigTlv, AppConfigTlvType, Controlees, CountryCode, DeviceConfigId, DeviceConfigTlv,
-    ResetConfig, SessionId, SessionToken, SessionType, UpdateMulticastListAction,
+    RadarConfigTlv, RadarConfigTlvType, ResetConfig, SessionId, SessionToken, SessionType,
+    UpdateMulticastListAction, UpdateTime,
 };
-use uwb_uci_packets::{build_session_update_controller_multicast_list_cmd, GroupId, MessageType};
+use uwb_uci_packets::{
+    build_session_update_controller_multicast_list_cmd, GroupId, MessageType, PhaseList,
+};
 
 /// The enum to represent the UCI commands. The definition of each field should follow UCI spec.
 #[allow(missing_docs)]
@@ -80,10 +83,24 @@
     SessionGetRangingCount {
         session_token: SessionToken,
     },
+    SessionSetHybridConfig {
+        session_token: SessionToken,
+        number_of_phases: u8,
+        update_time: UpdateTime,
+        phase_list: Vec<PhaseList>,
+    },
     AndroidSetCountryCode {
         country_code: CountryCode,
     },
     AndroidGetPowerStats,
+    AndroidSetRadarConfig {
+        session_token: SessionToken,
+        config_tlvs: Vec<RadarConfigTlv>,
+    },
+    AndroidGetRadarConfig {
+        session_token: SessionToken,
+        radar_cfg: Vec<RadarConfigTlvType>,
+    },
     RawUciCmd {
         mt: u32,
         gid: u32,
@@ -148,6 +165,22 @@
                 .build()
                 .into()
             }
+            UciCommand::AndroidSetRadarConfig { session_token, config_tlvs } => {
+                uwb_uci_packets::AndroidSetRadarConfigCmdBuilder {
+                    session_token,
+                    tlvs: config_tlvs,
+                }
+                .build()
+                .into()
+            }
+            UciCommand::AndroidGetRadarConfig { session_token, radar_cfg } => {
+                uwb_uci_packets::AndroidGetRadarConfigCmdBuilder {
+                    session_token,
+                    tlvs: radar_cfg.into_iter().map(u8::from).collect(),
+                }
+                .build()
+                .into()
+            }
             UciCommand::SessionUpdateDtTagRangingRounds {
                 session_token,
                 ranging_round_indexes,
@@ -189,6 +222,19 @@
             UciCommand::SessionQueryMaxDataSize { session_token } => {
                 uwb_uci_packets::SessionQueryMaxDataSizeCmdBuilder { session_token }.build().into()
             }
+            UciCommand::SessionSetHybridConfig {
+                session_token,
+                number_of_phases,
+                update_time,
+                phase_list,
+            } => uwb_uci_packets::SessionSetHybridConfigCmdBuilder {
+                session_token,
+                number_of_phases,
+                update_time: update_time.into(),
+                phase_list,
+            }
+            .build()
+            .into(),
         };
         Ok(packet)
     }
@@ -387,5 +433,23 @@
         cmd = UciCommand::AndroidGetPowerStats {};
         packet = uwb_uci_packets::UciControlPacket::try_from(cmd).unwrap();
         assert_eq!(packet, uwb_uci_packets::AndroidGetPowerStatsCmdBuilder {}.build().into());
+
+        cmd = UciCommand::AndroidSetRadarConfig { session_token: 1, config_tlvs: vec![] };
+        packet = uwb_uci_packets::UciControlPacket::try_from(cmd.clone()).unwrap();
+        assert_eq!(
+            packet,
+            uwb_uci_packets::AndroidSetRadarConfigCmdBuilder { session_token: 1, tlvs: vec![] }
+                .build()
+                .into()
+        );
+
+        cmd = UciCommand::AndroidGetRadarConfig { session_token: 1, radar_cfg: vec![] };
+        packet = uwb_uci_packets::UciControlPacket::try_from(cmd).unwrap();
+        assert_eq!(
+            packet,
+            uwb_uci_packets::AndroidGetRadarConfigCmdBuilder { session_token: 1, tlvs: vec![] }
+                .build()
+                .into()
+        );
     }
 }
diff --git a/src/rust/uwb_core/src/uci/error.rs b/src/rust/uwb_core/src/uci/error.rs
index 3101eec..3f040eb 100644
--- a/src/rust/uwb_core/src/uci/error.rs
+++ b/src/rust/uwb_core/src/uci/error.rs
@@ -22,7 +22,10 @@
         StatusCode::UciStatusInvalidParam
         | StatusCode::UciStatusInvalidRange
         | StatusCode::UciStatusInvalidMsgSize => Err(Error::BadParameters),
-        StatusCode::UciStatusSessionNotExist
+        StatusCode::UciStatusSessionDuplicate => Err(Error::DuplicatedSessionId),
+        StatusCode::UciStatusFailed
+        | StatusCode::UciStatusSessionNotExist
+        | StatusCode::UciStatusSessionNotConfigured
         | StatusCode::UciStatusErrorCccSeBusy
         | StatusCode::UciStatusErrorCccLifecycle => Err(Error::ProtocolSpecific),
         StatusCode::UciStatusCommandRetry => Err(Error::CommandRetry),
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 21e1ddb..f6e84ba 100644
--- a/src/rust/uwb_core/src/uci/mock_uci_manager.rs
+++ b/src/rust/uwb_core/src/uci/mock_uci_manager.rs
@@ -27,13 +27,16 @@
 
 use crate::error::{Error, Result};
 use crate::params::uci_packets::{
-    app_config_tlvs_eq, device_config_tlvs_eq, AppConfigTlv, AppConfigTlvType, CapTlv, Controlees,
-    CoreSetConfigResponse, CountryCode, DeviceConfigId, DeviceConfigTlv, GetDeviceInfoResponse,
-    PowerStats, RawUciMessage, ResetConfig, SessionId, SessionState, SessionToken, SessionType,
-    SessionUpdateDtTagRangingRoundsResponse, SetAppConfigResponse, UpdateMulticastListAction,
+    app_config_tlvs_eq, device_config_tlvs_eq, radar_config_tlvs_eq, AndroidRadarConfigResponse,
+    AppConfigTlv, AppConfigTlvType, CapTlv, Controlees, CoreSetConfigResponse, CountryCode,
+    DeviceConfigId, DeviceConfigTlv, GetDeviceInfoResponse, PhaseList, PowerStats, RadarConfigTlv,
+    RadarConfigTlvType, RawUciMessage, ResetConfig, SessionId, SessionState, SessionToken,
+    SessionType, SessionUpdateDtTagRangingRoundsResponse, SetAppConfigResponse,
+    UpdateMulticastListAction, UpdateTime,
 };
 use crate::uci::notification::{
-    CoreNotification, DataRcvNotification, SessionNotification, UciNotification,
+    CoreNotification, DataRcvNotification, RadarDataRcvNotification, SessionNotification,
+    UciNotification,
 };
 use crate::uci::uci_logger::UciLoggerMode;
 use crate::uci::uci_manager::UciManager;
@@ -47,6 +50,7 @@
     session_notf_sender: mpsc::UnboundedSender<SessionNotification>,
     vendor_notf_sender: mpsc::UnboundedSender<RawUciMessage>,
     data_rcv_notf_sender: mpsc::UnboundedSender<DataRcvNotification>,
+    radar_data_rcv_notf_sender: mpsc::UnboundedSender<RadarDataRcvNotification>,
 }
 
 #[allow(dead_code)]
@@ -60,6 +64,7 @@
             session_notf_sender: mpsc::unbounded_channel().0,
             vendor_notf_sender: mpsc::unbounded_channel().0,
             data_rcv_notf_sender: mpsc::unbounded_channel().0,
+            radar_data_rcv_notf_sender: mpsc::unbounded_channel().0,
         }
     }
 
@@ -79,7 +84,11 @@
     /// Prepare Mock to expect for open_hal.
     ///
     /// MockUciManager expects call, returns out as response, followed by notfs sent.
-    pub fn expect_open_hal(&mut self, notfs: Vec<UciNotification>, out: Result<()>) {
+    pub fn expect_open_hal(
+        &mut self,
+        notfs: Vec<UciNotification>,
+        out: Result<GetDeviceInfoResponse>,
+    ) {
         self.expected_calls.lock().unwrap().push_back(ExpectedCall::OpenHal { notfs, out });
     }
 
@@ -368,6 +377,41 @@
         self.expected_calls.lock().unwrap().push_back(ExpectedCall::AndroidGetPowerStats { out });
     }
 
+    /// Prepare Mock to expect android_set_radar_config.
+    ///
+    /// MockUciManager expects call with parameters, returns out as response, followed by notfs
+    /// sent.
+    pub fn expect_android_set_radar_config(
+        &mut self,
+        expected_session_id: SessionId,
+        expected_config_tlvs: Vec<RadarConfigTlv>,
+        notfs: Vec<UciNotification>,
+        out: Result<AndroidRadarConfigResponse>,
+    ) {
+        self.expected_calls.lock().unwrap().push_back(ExpectedCall::AndroidSetRadarConfig {
+            expected_session_id,
+            expected_config_tlvs,
+            notfs,
+            out,
+        });
+    }
+
+    /// Prepare Mock to expect android_get_app_config.
+    ///
+    /// MockUciManager expects call with parameters, returns out as response.
+    pub fn expect_android_get_radar_config(
+        &mut self,
+        expected_session_id: SessionId,
+        expected_config_ids: Vec<RadarConfigTlvType>,
+        out: Result<Vec<RadarConfigTlv>>,
+    ) {
+        self.expected_calls.lock().unwrap().push_back(ExpectedCall::AndroidGetRadarConfig {
+            expected_session_id,
+            expected_config_ids,
+            out,
+        });
+    }
+
     /// Prepare Mock to expect raw_uci_cmd.
     ///
     /// MockUciManager expects call with parameters, returns out as response.
@@ -408,6 +452,26 @@
         });
     }
 
+    /// Prepare Mock to expect session_set_hybrid_config.
+    ///
+    /// MockUciManager expects call with parameters, returns out as response
+    pub fn expect_session_set_hybrid_config(
+        &mut self,
+        expected_session_id: SessionId,
+        expected_number_of_phases: u8,
+        expected_update_time: UpdateTime,
+        expected_phase_list: Vec<PhaseList>,
+        out: Result<()>,
+    ) {
+        self.expected_calls.lock().unwrap().push_back(ExpectedCall::SessionSetHybridConfig {
+            expected_session_id,
+            expected_number_of_phases,
+            expected_update_time,
+            expected_phase_list,
+            out,
+        });
+    }
+
     /// Call Mock to send notifications.
     fn send_notifications(&self, notfs: Vec<UciNotification>) {
         for notf in notfs.into_iter() {
@@ -461,8 +525,14 @@
     ) {
         self.data_rcv_notf_sender = data_rcv_notf_sender;
     }
+    async fn set_radar_data_rcv_notification_sender(
+        &mut self,
+        radar_data_rcv_notf_sender: mpsc::UnboundedSender<RadarDataRcvNotification>,
+    ) {
+        self.radar_data_rcv_notf_sender = radar_data_rcv_notf_sender;
+    }
 
-    async fn open_hal(&self) -> Result<()> {
+    async fn open_hal(&self) -> Result<GetDeviceInfoResponse> {
         let mut expected_calls = self.expected_calls.lock().unwrap();
         match expected_calls.pop_front() {
             Some(ExpectedCall::OpenHal { notfs, out }) => {
@@ -873,6 +943,56 @@
         }
     }
 
+    async fn android_set_radar_config(
+        &self,
+        session_id: SessionId,
+        config_tlvs: Vec<RadarConfigTlv>,
+    ) -> Result<AndroidRadarConfigResponse> {
+        let mut expected_calls = self.expected_calls.lock().unwrap();
+        match expected_calls.pop_front() {
+            Some(ExpectedCall::AndroidSetRadarConfig {
+                expected_session_id,
+                expected_config_tlvs,
+                notfs,
+                out,
+            }) if expected_session_id == session_id
+                && radar_config_tlvs_eq(&expected_config_tlvs, &config_tlvs) =>
+            {
+                self.expect_call_consumed.notify_one();
+                self.send_notifications(notfs);
+                out
+            }
+            Some(call) => {
+                expected_calls.push_front(call);
+                Err(Error::MockUndefined)
+            }
+            None => Err(Error::MockUndefined),
+        }
+    }
+
+    async fn android_get_radar_config(
+        &self,
+        session_id: SessionId,
+        config_ids: Vec<RadarConfigTlvType>,
+    ) -> Result<Vec<RadarConfigTlv>> {
+        let mut expected_calls = self.expected_calls.lock().unwrap();
+        match expected_calls.pop_front() {
+            Some(ExpectedCall::AndroidGetRadarConfig {
+                expected_session_id,
+                expected_config_ids,
+                out,
+            }) if expected_session_id == session_id && expected_config_ids == config_ids => {
+                self.expect_call_consumed.notify_one();
+                out
+            }
+            Some(call) => {
+                expected_calls.push_front(call);
+                Err(Error::MockUndefined)
+            }
+            None => Err(Error::MockUndefined),
+        }
+    }
+
     async fn raw_uci_cmd(
         &self,
         mt: u32,
@@ -941,13 +1061,45 @@
     ) -> Result<SessionToken> {
         Ok(1) // No uci call here, no mock required.
     }
+
+    async fn session_set_hybrid_config(
+        &self,
+        session_id: SessionId,
+        number_of_phases: u8,
+        update_time: UpdateTime,
+        phase_list: Vec<PhaseList>,
+    ) -> Result<()> {
+        let mut expected_calls = self.expected_calls.lock().unwrap();
+        match expected_calls.pop_front() {
+            Some(ExpectedCall::SessionSetHybridConfig {
+                expected_session_id,
+                expected_number_of_phases,
+                expected_update_time,
+                expected_phase_list,
+                out,
+            }) if expected_session_id == session_id
+                && expected_number_of_phases == number_of_phases
+                && expected_update_time == update_time
+                && expected_phase_list.len() == phase_list.len()
+                && expected_phase_list == phase_list =>
+            {
+                self.expect_call_consumed.notify_one();
+                out
+            }
+            Some(call) => {
+                expected_calls.push_front(call);
+                Err(Error::MockUndefined)
+            }
+            None => Err(Error::MockUndefined),
+        }
+    }
 }
 
 #[derive(Clone)]
 enum ExpectedCall {
     OpenHal {
         notfs: Vec<UciNotification>,
-        out: Result<()>,
+        out: Result<GetDeviceInfoResponse>,
     },
     CloseHal {
         expected_force: bool,
@@ -1040,6 +1192,17 @@
     AndroidGetPowerStats {
         out: Result<PowerStats>,
     },
+    AndroidSetRadarConfig {
+        expected_session_id: SessionId,
+        expected_config_tlvs: Vec<RadarConfigTlv>,
+        notfs: Vec<UciNotification>,
+        out: Result<AndroidRadarConfigResponse>,
+    },
+    AndroidGetRadarConfig {
+        expected_session_id: SessionId,
+        expected_config_ids: Vec<RadarConfigTlvType>,
+        out: Result<Vec<RadarConfigTlv>>,
+    },
     RawUciCmd {
         expected_mt: u32,
         expected_gid: u32,
@@ -1054,4 +1217,11 @@
         expected_app_payload_data: Vec<u8>,
         out: Result<()>,
     },
+    SessionSetHybridConfig {
+        expected_session_id: SessionId,
+        expected_number_of_phases: u8,
+        expected_update_time: UpdateTime,
+        expected_phase_list: Vec<PhaseList>,
+        out: Result<()>,
+    },
 }
diff --git a/src/rust/uwb_core/src/uci/notification.rs b/src/rust/uwb_core/src/uci/notification.rs
index eab8233..d99f602 100644
--- a/src/rust/uwb_core/src/uci/notification.rs
+++ b/src/rust/uwb_core/src/uci/notification.rs
@@ -15,15 +15,20 @@
 use std::convert::{TryFrom, TryInto};
 
 use log::{debug, error};
-use uwb_uci_packets::{parse_diagnostics_ntf, Packet, UCI_PACKET_HEADER_LEN};
+use uwb_uci_packets::{
+    parse_diagnostics_ntf, radar_bytes_per_sample_value, Packet, RadarDataRcv, RadarSweepDataRaw,
+    UCI_PACKET_HEADER_LEN, UCI_RADAR_SEQUENCE_NUMBER_LEN, UCI_RADAR_TIMESTAMP_LEN,
+    UCI_RADAR_VENDOR_DATA_LEN_LEN,
+};
 
 use crate::error::{Error, Result};
 use crate::params::fira_app_config_params::UwbAddress;
 use crate::params::uci_packets::{
-    ControleeStatus, CreditAvailability, DataRcvStatusCode, DataTransferNtfStatusCode, DeviceState,
-    ExtendedAddressDlTdoaRangingMeasurement, ExtendedAddressOwrAoaRangingMeasurement,
-    ExtendedAddressTwoWayRangingMeasurement, RangingMeasurementType, RawUciMessage, SessionState,
-    SessionToken, ShortAddressDlTdoaRangingMeasurement, ShortAddressOwrAoaRangingMeasurement,
+    BitsPerSample, ControleeStatus, CreditAvailability, DataRcvStatusCode,
+    DataTransferNtfStatusCode, DeviceState, ExtendedAddressDlTdoaRangingMeasurement,
+    ExtendedAddressOwrAoaRangingMeasurement, ExtendedAddressTwoWayRangingMeasurement,
+    RadarDataType, RangingMeasurementType, RawUciMessage, SessionState, SessionToken,
+    ShortAddressDlTdoaRangingMeasurement, ShortAddressOwrAoaRangingMeasurement,
     ShortAddressTwoWayRangingMeasurement, StatusCode,
 };
 
@@ -81,8 +86,8 @@
     DataTransferStatus {
         /// SessionToken : u32
         session_token: SessionToken,
-        /// Sequence Number: u8
-        uci_sequence_number: u8,
+        /// Sequence Number: u16
+        uci_sequence_number: u16,
         /// Data Transfer Status Code
         status: DataTransferNtfStatusCode,
         /// Transmission count
@@ -145,7 +150,7 @@
     pub session_token: SessionToken,
 
     /// The status of the data rx.
-    pub status: DataRcvStatusCode,
+    pub status: StatusCode,
 
     /// The sequence number of the data packet.
     pub uci_sequence_num: u16,
@@ -157,6 +162,142 @@
     pub payload: Vec<u8>,
 }
 
+/// The Radar sweep data struct
+#[derive(Debug, Clone, std::cmp::PartialEq)]
+pub struct RadarSweepData {
+    /// Counter of a single radar sweep per receiver. Starting
+    /// with 0 when the radar session is started.
+    pub sequence_number: u32,
+
+    /// Timestamp when this radar sweep is received. Unit is
+    /// based on the PRF.
+    pub timestamp: u32,
+
+    /// The radar vendor specific data.
+    pub vendor_specific_data: Vec<u8>,
+
+    /// The radar sample data.
+    pub sample_data: Vec<u8>,
+}
+
+/// The RADAR_DATA_RCV packet
+#[derive(Debug, Clone, std::cmp::PartialEq)]
+pub struct RadarDataRcvNotification {
+    /// The identifier of the session on which radar data transfer is happening.
+    pub session_token: SessionToken,
+
+    /// The status of the radar data rx.
+    pub status: DataRcvStatusCode,
+
+    /// The radar data type.
+    pub radar_data_type: RadarDataType,
+
+    /// The number of sweeps.
+    pub number_of_sweeps: u8,
+
+    /// Number of samples captured for each radar sweep.
+    pub samples_per_sweep: u8,
+
+    /// Bits per sample in the radar sweep.
+    pub bits_per_sample: BitsPerSample,
+
+    /// Defines the start offset with respect to 0cm distance. Unit in samples.
+    pub sweep_offset: u16,
+
+    /// Radar sweep data.
+    pub sweep_data: Vec<RadarSweepData>,
+}
+
+impl From<&uwb_uci_packets::RadarSweepDataRaw> for RadarSweepData {
+    fn from(evt: &uwb_uci_packets::RadarSweepDataRaw) -> Self {
+        Self {
+            sequence_number: evt.sequence_number,
+            timestamp: evt.timestamp,
+            vendor_specific_data: evt.vendor_specific_data.clone(),
+            sample_data: evt.sample_data.clone(),
+        }
+    }
+}
+
+impl TryFrom<uwb_uci_packets::UciDataPacket> for RadarDataRcvNotification {
+    type Error = Error;
+    fn try_from(evt: uwb_uci_packets::UciDataPacket) -> std::result::Result<Self, Self::Error> {
+        match evt.specialize() {
+            uwb_uci_packets::UciDataPacketChild::RadarDataRcv(evt) => parse_radar_data(evt),
+            _ => Err(Error::Unknown),
+        }
+    }
+}
+
+fn parse_radar_data(data: RadarDataRcv) -> Result<RadarDataRcvNotification> {
+    let session_token = data.get_session_handle();
+    let status = data.get_status();
+    let radar_data_type = data.get_radar_data_type();
+    let number_of_sweeps = data.get_number_of_sweeps();
+    let samples_per_sweep = data.get_samples_per_sweep();
+    let bits_per_sample = data.get_bits_per_sample();
+    let bytes_per_sample_value = radar_bytes_per_sample_value(bits_per_sample);
+    let sweep_offset = data.get_sweep_offset();
+
+    Ok(RadarDataRcvNotification {
+        session_token,
+        status,
+        radar_data_type,
+        number_of_sweeps,
+        samples_per_sweep,
+        bits_per_sample,
+        sweep_offset,
+        sweep_data: parse_radar_sweep_data(
+            number_of_sweeps,
+            samples_per_sweep,
+            bytes_per_sample_value,
+            data.get_sweep_data().clone(),
+        )?,
+    })
+}
+
+fn parse_radar_sweep_data(
+    number_of_sweeps: u8,
+    samples_per_sweep: u8,
+    bytes_per_sample_value: u8,
+    data: Vec<u8>,
+) -> Result<Vec<RadarSweepData>> {
+    let mut radar_sweep_data: Vec<RadarSweepData> = Vec::new();
+    let mut sweep_data_cursor = 0;
+    for _ in 0..number_of_sweeps {
+        let vendor_data_len_index =
+            sweep_data_cursor + UCI_RADAR_SEQUENCE_NUMBER_LEN + UCI_RADAR_TIMESTAMP_LEN;
+        if data.len() <= vendor_data_len_index {
+            error!("Invalid radar sweep data length for vendor, data: {:?}", &data);
+            return Err(Error::BadParameters);
+        }
+        let vendor_specific_data_len = data[vendor_data_len_index] as usize;
+        let sweep_data_len = UCI_RADAR_SEQUENCE_NUMBER_LEN
+            + UCI_RADAR_TIMESTAMP_LEN
+            + UCI_RADAR_VENDOR_DATA_LEN_LEN
+            + vendor_specific_data_len
+            + (samples_per_sweep * bytes_per_sample_value) as usize;
+        if data.len() < sweep_data_cursor + sweep_data_len {
+            error!("Invalid radar sweep data length, data: {:?}", &data);
+            return Err(Error::BadParameters);
+        }
+        radar_sweep_data.push(
+            (&RadarSweepDataRaw::parse(
+                &data[sweep_data_cursor..sweep_data_cursor + sweep_data_len],
+            )
+            .map_err(|e| {
+                error!("Failed to parse raw Radar Sweep Data {:?}, data: {:?}", e, &data);
+                Error::BadParameters
+            })?)
+                .into(),
+        );
+
+        sweep_data_cursor += sweep_data_len;
+    }
+
+    Ok(radar_sweep_data)
+}
+
 impl TryFrom<uwb_uci_packets::UciDataPacket> for DataRcvNotification {
     type Error = Error;
     fn try_from(evt: uwb_uci_packets::UciDataPacket) -> std::result::Result<Self, Self::Error> {
@@ -168,10 +309,7 @@
                 source_address: UwbAddress::Extended(evt.get_source_mac_address().to_le_bytes()),
                 payload: evt.get_data().to_vec(),
             }),
-            _ => {
-                error!("Unknown UciData packet: {:?}", evt);
-                Err(Error::Unknown)
-            }
+            _ => Err(Error::Unknown),
         }
     }
 }
diff --git a/src/rust/uwb_core/src/uci/response.rs b/src/rust/uwb_core/src/uci/response.rs
index dfeb6c8..d70f9f7 100644
--- a/src/rust/uwb_core/src/uci/response.rs
+++ b/src/rust/uwb_core/src/uci/response.rs
@@ -16,8 +16,8 @@
 
 use crate::error::{Error, Result};
 use crate::params::uci_packets::{
-    AppConfigTlv, CapTlv, CoreSetConfigResponse, DeviceConfigTlv, GetDeviceInfoResponse,
-    PowerStats, RawUciMessage, SessionHandle, SessionState,
+    AndroidRadarConfigResponse, AppConfigTlv, CapTlv, CoreSetConfigResponse, DeviceConfigTlv,
+    GetDeviceInfoResponse, PowerStats, RadarConfigTlv, RawUciMessage, SessionHandle, SessionState,
     SessionUpdateDtTagRangingRoundsResponse, SetAppConfigResponse, StatusCode, UciControlPacket,
 };
 use crate::uci::error::status_code_to_result;
@@ -48,8 +48,11 @@
     SessionGetRangingCount(Result<usize>),
     AndroidSetCountryCode(Result<()>),
     AndroidGetPowerStats(Result<PowerStats>),
+    AndroidSetRadarConfig(AndroidRadarConfigResponse),
+    AndroidGetRadarConfig(Result<Vec<RadarConfigTlv>>),
     RawUciCmd(Result<RawUciMessage>),
     SendUciData(Result<()>),
+    SessionSetHybridConfig(Result<()>),
 }
 
 impl UciResponse {
@@ -75,7 +78,10 @@
             Self::SessionGetRangingCount(result) => Self::matches_result_retry(result),
             Self::AndroidSetCountryCode(result) => Self::matches_result_retry(result),
             Self::AndroidGetPowerStats(result) => Self::matches_result_retry(result),
+            Self::AndroidGetRadarConfig(result) => Self::matches_result_retry(result),
+            Self::AndroidSetRadarConfig(resp) => Self::matches_status_retry(&resp.status),
             Self::RawUciCmd(result) => Self::matches_result_retry(result),
+            Self::SessionSetHybridConfig(result) => Self::matches_result_retry(result),
 
             Self::CoreSetConfig(resp) => Self::matches_status_retry(&resp.status),
             Self::SessionSetAppConfig(resp) => Self::matches_status_retry(&resp.status),
@@ -120,6 +126,7 @@
         match evt.specialize() {
             CoreResponseChild::GetDeviceInfoRsp(evt) => Ok(UciResponse::CoreGetDeviceInfo(
                 status_code_to_result(evt.get_status()).map(|_| GetDeviceInfoResponse {
+                    status: evt.get_status(),
                     uci_version: evt.get_uci_version(),
                     mac_version: evt.get_mac_version(),
                     phy_version: evt.get_phy_version(),
@@ -204,7 +211,12 @@
                 ))
             }
             SessionConfigResponseChild::SessionQueryMaxDataSizeRsp(evt) => {
-                Ok(UciResponse::SessionQueryMaxDataSize(Ok(evt.get_max_data_size())))
+                Ok(UciResponse::SessionQueryMaxDataSize(
+                    status_code_to_result(evt.get_status()).map(|_| evt.get_max_data_size()),
+                ))
+            }
+            SessionConfigResponseChild::SessionSetHybridConfigRsp(evt) => {
+                Ok(UciResponse::SessionSetHybridConfig(status_code_to_result(evt.get_status())))
             }
             _ => Err(Error::Unknown),
         }
@@ -247,6 +259,17 @@
                     status_code_to_result(evt.get_stats().status).map(|_| evt.get_stats().clone()),
                 ))
             }
+            AndroidResponseChild::AndroidSetRadarConfigRsp(evt) => {
+                Ok(UciResponse::AndroidSetRadarConfig(AndroidRadarConfigResponse {
+                    status: evt.get_status(),
+                    config_status: evt.get_cfg_status().clone(),
+                }))
+            }
+            AndroidResponseChild::AndroidGetRadarConfigRsp(evt) => {
+                Ok(UciResponse::AndroidGetRadarConfig(
+                    status_code_to_result(evt.get_status()).map(|_| evt.get_tlvs().clone()),
+                ))
+            }
             _ => Err(Error::Unknown),
         }
     }
diff --git a/src/rust/uwb_core/src/uci/uci_manager.rs b/src/rust/uwb_core/src/uci/uci_manager.rs
index 24c0737..a1a97f1 100644
--- a/src/rust/uwb_core/src/uci/uci_manager.rs
+++ b/src/rust/uwb_core/src/uci/uci_manager.rs
@@ -24,16 +24,18 @@
 //use crate::uci::error::{Error, Result};
 use crate::error::{Error, Result};
 use crate::params::uci_packets::{
-    AppConfigTlv, AppConfigTlvType, CapTlv, Controlees, CoreSetConfigResponse, CountryCode,
-    CreditAvailability, DeviceConfigId, DeviceConfigTlv, DeviceState, GetDeviceInfoResponse,
-    GroupId, MessageType, PowerStats, RawUciMessage, ResetConfig, SessionId, SessionState,
-    SessionToken, SessionType, SessionUpdateDtTagRangingRoundsResponse, SetAppConfigResponse,
-    UciDataPacket, UciDataPacketHal, UpdateMulticastListAction,
+    AndroidRadarConfigResponse, AppConfigTlv, AppConfigTlvType, CapTlv, Controlees,
+    CoreSetConfigResponse, CountryCode, CreditAvailability, DeviceConfigId, DeviceConfigTlv,
+    DeviceState, GetDeviceInfoResponse, GroupId, MessageType, PowerStats, RadarConfigTlv,
+    RadarConfigTlvType, RawUciMessage, ResetConfig, SessionId, SessionState, SessionToken,
+    SessionType, SessionUpdateDtTagRangingRoundsResponse, SetAppConfigResponse, UciDataPacket,
+    UciDataPacketHal, UpdateMulticastListAction, UpdateTime,
 };
 use crate::params::utils::bytes_to_u64;
 use crate::uci::message::UciMessage;
 use crate::uci::notification::{
-    CoreNotification, DataRcvNotification, SessionNotification, SessionRangeData, UciNotification,
+    CoreNotification, DataRcvNotification, RadarDataRcvNotification, SessionNotification,
+    SessionRangeData, UciNotification,
 };
 use crate::uci::response::UciResponse;
 use crate::uci::timeout_uci_hal::TimeoutUciHal;
@@ -41,7 +43,7 @@
 use crate::uci::uci_logger::{UciLogger, UciLoggerMode, UciLoggerWrapper};
 use crate::utils::{clean_mpsc_receiver, PinSleep};
 use std::collections::{HashMap, VecDeque};
-use uwb_uci_packets::{Packet, RawUciControlPacket, UciDataSnd, UciDefragPacket};
+use uwb_uci_packets::{Packet, PhaseList, RawUciControlPacket, UciDataSnd, UciDefragPacket};
 
 const UCI_TIMEOUT_MS: u64 = 800;
 const MAX_RETRY_COUNT: usize = 3;
@@ -68,10 +70,14 @@
         &mut self,
         data_rcv_notf_sender: mpsc::UnboundedSender<DataRcvNotification>,
     );
+    async fn set_radar_data_rcv_notification_sender(
+        &mut self,
+        radar_data_rcv_notf_sender: mpsc::UnboundedSender<RadarDataRcvNotification>,
+    );
 
     // Open the UCI HAL.
     // All the UCI commands should be called after the open_hal() completes successfully.
-    async fn open_hal(&self) -> Result<()>;
+    async fn open_hal(&self) -> Result<GetDeviceInfoResponse>;
 
     // Close the UCI HAL.
     async fn close_hal(&self, force: bool) -> Result<()>;
@@ -126,6 +132,16 @@
     // Send the Android-specific UCI commands
     async fn android_set_country_code(&self, country_code: CountryCode) -> Result<()>;
     async fn android_get_power_stats(&self) -> Result<PowerStats>;
+    async fn android_set_radar_config(
+        &self,
+        session_id: SessionId,
+        config_tlvs: Vec<RadarConfigTlv>,
+    ) -> Result<AndroidRadarConfigResponse>;
+    async fn android_get_radar_config(
+        &self,
+        session_id: SessionId,
+        config_ids: Vec<RadarConfigTlvType>,
+    ) -> Result<Vec<RadarConfigTlv>>;
 
     // Send a raw uci command.
     async fn raw_uci_cmd(
@@ -150,6 +166,14 @@
         &self,
         session_id: SessionId,
     ) -> Result<SessionToken>;
+    /// Send UCI command for setting hybrid config
+    async fn session_set_hybrid_config(
+        &self,
+        session_id: SessionId,
+        number_of_phases: u8,
+        update_time: UpdateTime,
+        phase_list: Vec<PhaseList>,
+    ) -> Result<()>;
 }
 
 /// UciManagerImpl is the main implementation of UciManager. Using the actor model, UciManagerImpl
@@ -246,17 +270,32 @@
             .send_cmd(UciManagerCmd::SetDataRcvNotificationSender { data_rcv_notf_sender })
             .await;
     }
+    async fn set_radar_data_rcv_notification_sender(
+        &mut self,
+        radar_data_rcv_notf_sender: mpsc::UnboundedSender<RadarDataRcvNotification>,
+    ) {
+        let _ = self
+            .send_cmd(UciManagerCmd::SetRadarDataRcvNotificationSender {
+                radar_data_rcv_notf_sender,
+            })
+            .await;
+    }
 
-    async fn open_hal(&self) -> Result<()> {
+    async fn open_hal(&self) -> Result<GetDeviceInfoResponse> {
         match self.send_cmd(UciManagerCmd::OpenHal).await {
             Ok(UciResponse::OpenHal) => {
                 // According to the UCI spec: "The Host shall send CORE_GET_DEVICE_INFO_CMD to
                 // retrieve the device information.", we call get_device_info() after successfully
                 // opening the HAL.
-                let device_info = self.core_get_device_info().await;
+                let device_info = match self.core_get_device_info().await {
+                    Ok(resp) => resp,
+                    Err(e) => {
+                        return Err(e);
+                    }
+                };
                 debug!("UCI device info: {:?}", device_info);
 
-                Ok(())
+                Ok(device_info)
             }
             Ok(_) => Err(Error::Unknown),
             Err(e) => Err(e),
@@ -502,6 +541,38 @@
         }
     }
 
+    async fn android_set_radar_config(
+        &self,
+        session_id: SessionId,
+        config_tlvs: Vec<RadarConfigTlv>,
+    ) -> Result<AndroidRadarConfigResponse> {
+        let cmd = UciCommand::AndroidSetRadarConfig {
+            session_token: self.get_session_token(&session_id).await?,
+            config_tlvs,
+        };
+        match self.send_cmd(UciManagerCmd::SendUciCommand { cmd }).await {
+            Ok(UciResponse::AndroidSetRadarConfig(resp)) => Ok(resp),
+            Ok(_) => Err(Error::Unknown),
+            Err(e) => Err(e),
+        }
+    }
+
+    async fn android_get_radar_config(
+        &self,
+        session_id: SessionId,
+        radar_cfg: Vec<RadarConfigTlvType>,
+    ) -> Result<Vec<RadarConfigTlv>> {
+        let cmd = UciCommand::AndroidGetRadarConfig {
+            session_token: self.get_session_token(&session_id).await?,
+            radar_cfg,
+        };
+        match self.send_cmd(UciManagerCmd::SendUciCommand { cmd }).await {
+            Ok(UciResponse::AndroidGetRadarConfig(resp)) => resp,
+            Ok(_) => Err(Error::Unknown),
+            Err(e) => Err(e),
+        }
+    }
+
     async fn raw_uci_cmd(
         &self,
         mt: u32,
@@ -552,6 +623,27 @@
     ) -> Result<SessionToken> {
         Ok(self.get_session_token(&session_id).await?)
     }
+
+    /// Send UCI command for setting hybrid config
+    async fn session_set_hybrid_config(
+        &self,
+        session_id: SessionId,
+        number_of_phases: u8,
+        update_time: UpdateTime,
+        phase_list: Vec<PhaseList>,
+    ) -> Result<()> {
+        let cmd = UciCommand::SessionSetHybridConfig {
+            session_token: self.get_session_token(&session_id).await?,
+            number_of_phases,
+            update_time,
+            phase_list,
+        };
+        match self.send_cmd(UciManagerCmd::SendUciCommand { cmd }).await {
+            Ok(UciResponse::SessionSetHybridConfig(resp)) => resp,
+            Ok(_) => Err(Error::Unknown),
+            Err(e) => Err(e),
+        }
+    }
 }
 
 struct UciManagerActor<T: UciHal, U: UciLogger> {
@@ -605,6 +697,7 @@
     session_notf_sender: mpsc::UnboundedSender<SessionNotification>,
     vendor_notf_sender: mpsc::UnboundedSender<RawUciMessage>,
     data_rcv_notf_sender: mpsc::UnboundedSender<DataRcvNotification>,
+    radar_data_rcv_notf_sender: mpsc::UnboundedSender<RadarDataRcvNotification>,
 
     // Used to store the last init session id to help map the session handle sent
     // in session int response can be correctly mapped.
@@ -645,6 +738,7 @@
             session_notf_sender: mpsc::unbounded_channel().0,
             vendor_notf_sender: mpsc::unbounded_channel().0,
             data_rcv_notf_sender: mpsc::unbounded_channel().0,
+            radar_data_rcv_notf_sender: mpsc::unbounded_channel().0,
             last_init_session_id: None,
             session_id_to_token_map,
         }
@@ -778,6 +872,10 @@
                 self.data_rcv_notf_sender = data_rcv_notf_sender;
                 let _ = result_sender.send(Ok(UciResponse::SetNotification));
             }
+            UciManagerCmd::SetRadarDataRcvNotificationSender { radar_data_rcv_notf_sender } => {
+                self.radar_data_rcv_notf_sender = radar_data_rcv_notf_sender;
+                let _ = result_sender.send(Ok(UciResponse::SetNotification));
+            }
             UciManagerCmd::OpenHal => {
                 if self.is_hal_opened {
                     warn!("The UCI HAL is already opened, skip.");
@@ -1064,7 +1162,7 @@
             }
             UciDefragPacket::Data(packet) => {
                 self.logger.log_uci_data(&packet);
-                self.handle_data_rcv(packet);
+                self.handle_data_rcv(packet).await;
             }
             UciDefragPacket::Raw(result, raw_uci_control_packet) => {
                 // Handle response to raw UCI cmd. We want to send it back as
@@ -1275,14 +1373,42 @@
         }
     }
 
-    fn handle_data_rcv(&mut self, packet: UciDataPacket) {
-        match packet.try_into() {
-            Ok(data_rcv) => {
-                let _ = self.data_rcv_notf_sender.send(data_rcv);
+    async fn handle_data_rcv(&mut self, packet: UciDataPacket) {
+        if let Ok(data) = DataRcvNotification::try_from(packet.clone()) {
+            match self.get_session_id(&data.session_token).await {
+                Ok(session_id) => {
+                    let _ = self.data_rcv_notf_sender.send(DataRcvNotification {
+                        session_token: session_id,
+                        status: data.status,
+                        uci_sequence_num: data.uci_sequence_num,
+                        source_address: data.source_address,
+                        payload: data.payload,
+                    });
+                }
+                Err(e) => {
+                    error!("Unable to find session Id, error {:?}", e);
+                }
             }
-            Err(e) => {
-                error!("Unable to parse incoming Data packet, error {:?}", e);
+        } else if let Ok(data) = RadarDataRcvNotification::try_from(packet.clone()) {
+            match self.get_session_id(&data.session_token).await {
+                Ok(session_id) => {
+                    let _ = self.radar_data_rcv_notf_sender.send(RadarDataRcvNotification {
+                        session_token: session_id,
+                        status: data.status,
+                        radar_data_type: data.radar_data_type,
+                        number_of_sweeps: data.number_of_sweeps,
+                        samples_per_sweep: data.samples_per_sweep,
+                        bits_per_sample: data.bits_per_sample,
+                        sweep_offset: data.sweep_offset,
+                        sweep_data: data.sweep_data,
+                    });
+                }
+                Err(e) => {
+                    error!("Unable to find session Id, error {:?}", e);
+                }
             }
+        } else {
+            error!("Unable to parse incoming Data packet, packet {:?}", packet);
         }
     }
 
@@ -1371,6 +1497,9 @@
     SetDataRcvNotificationSender {
         data_rcv_notf_sender: mpsc::UnboundedSender<DataRcvNotification>,
     },
+    SetRadarDataRcvNotificationSender {
+        radar_data_rcv_notf_sender: mpsc::UnboundedSender<RadarDataRcvNotification>,
+    },
     OpenHal,
     CloseHal {
         force: bool,
@@ -1383,7 +1512,7 @@
     },
 }
 
-#[cfg(any(test))]
+#[cfg(test)]
 mod tests {
     use super::*;
 
@@ -1392,12 +1521,13 @@
     use uwb_uci_packets::{SessionGetCountCmdBuilder, SessionGetCountRspBuilder};
 
     use crate::params::uci_packets::{
-        AppConfigStatus, AppConfigTlvType, CapTlvType, Controlee, DataRcvStatusCode,
-        DataTransferNtfStatusCode, StatusCode,
+        AppConfigStatus, AppConfigTlvType, BitsPerSample, CapTlvType, Controlee, DataRcvStatusCode,
+        DataTransferNtfStatusCode, RadarDataType, StatusCode,
     };
     use crate::params::UwbAddress;
     use crate::uci::mock_uci_hal::MockUciHal;
     use crate::uci::mock_uci_logger::{MockUciLogger, UciLogEvent};
+    use crate::uci::notification::RadarSweepData;
     use crate::uci::uci_logger::NopUciLogger;
     use crate::utils::init_test_logging;
 
@@ -1582,6 +1712,7 @@
         .await;
 
         let expected_result = GetDeviceInfoResponse {
+            status,
             uci_version,
             mac_version,
             phy_version,
@@ -1897,6 +2028,47 @@
     }
 
     #[tokio::test]
+    async fn test_session_set_hybrid_config_ok() {
+        let session_id = 0x123;
+        let session_token = 0x123;
+        let number_of_phases = 0x02;
+        let update_time = UpdateTime::new(&[0x0; 8]).unwrap();
+        let phase_list = vec![
+            PhaseList { session_token: 0x12, start_slot_index: 0x13, end_slot_index: 0x01 },
+            PhaseList { session_token: 0x14, start_slot_index: 0x13, end_slot_index: 0x01 },
+        ];
+        let phase_list_clone = phase_list.clone();
+
+        let (uci_manager, mut mock_hal) = setup_uci_manager_with_session_active(
+            |mut hal| async move {
+                let cmd = UciCommand::SessionSetHybridConfig {
+                    session_token,
+                    number_of_phases,
+                    update_time,
+                    phase_list: phase_list_clone,
+                };
+                let resp =
+                    into_uci_hal_packets(uwb_uci_packets::SessionSetHybridConfigRspBuilder {
+                        status: uwb_uci_packets::StatusCode::UciStatusOk,
+                    });
+
+                hal.expected_send_command(cmd, resp, Ok(()));
+            },
+            UciLoggerMode::Disabled,
+            mpsc::unbounded_channel::<UciLogEvent>().0,
+            session_id,
+            session_token,
+        )
+        .await;
+
+        let result = uci_manager
+            .session_set_hybrid_config(session_token, number_of_phases, update_time, phase_list)
+            .await;
+        assert!(result.is_ok());
+        assert!(mock_hal.wait_expected_calls_done().await);
+    }
+
+    #[tokio::test]
     async fn test_session_get_app_config_ok() {
         let session_id = 0x123;
         let session_token = 0x123;
@@ -2197,6 +2369,76 @@
     }
 
     #[tokio::test]
+    async fn test_android_set_radar_config_ok() {
+        let session_id = 0x123;
+        let session_token = 0x123;
+        let config_tlv =
+            RadarConfigTlv { cfg_id: RadarConfigTlvType::SamplesPerSweep, v: vec![0x12, 0x34] };
+        let config_tlv_clone = config_tlv.clone();
+
+        let (uci_manager, mut mock_hal) = setup_uci_manager_with_session_initialized(
+            |mut hal| async move {
+                let cmd = UciCommand::AndroidSetRadarConfig {
+                    session_token,
+                    config_tlvs: vec![config_tlv_clone],
+                };
+                let resp = into_uci_hal_packets(uwb_uci_packets::AndroidSetRadarConfigRspBuilder {
+                    status: uwb_uci_packets::StatusCode::UciStatusOk,
+                    cfg_status: vec![],
+                });
+
+                hal.expected_send_command(cmd, resp, Ok(()));
+            },
+            UciLoggerMode::Disabled,
+            mpsc::unbounded_channel::<UciLogEvent>().0,
+            session_id,
+            session_token,
+        )
+        .await;
+
+        let expected_result =
+            AndroidRadarConfigResponse { status: StatusCode::UciStatusOk, config_status: vec![] };
+        let result =
+            uci_manager.android_set_radar_config(session_id, vec![config_tlv]).await.unwrap();
+        assert_eq!(result, expected_result);
+        assert!(mock_hal.wait_expected_calls_done().await);
+    }
+
+    #[tokio::test]
+    async fn test_android_get_radar_config_ok() {
+        let session_id = 0x123;
+        let session_token = 0x123;
+        let config_id = RadarConfigTlvType::SamplesPerSweep;
+        let tlv =
+            RadarConfigTlv { cfg_id: RadarConfigTlvType::SamplesPerSweep, v: vec![0x12, 0x34] };
+        let tlv_clone = tlv.clone();
+
+        let (uci_manager, mut mock_hal) = setup_uci_manager_with_session_initialized(
+            |mut hal| async move {
+                let cmd =
+                    UciCommand::AndroidGetRadarConfig { session_token, radar_cfg: vec![config_id] };
+                let resp = into_uci_hal_packets(uwb_uci_packets::AndroidGetRadarConfigRspBuilder {
+                    status: uwb_uci_packets::StatusCode::UciStatusOk,
+                    tlvs: vec![tlv_clone],
+                });
+
+                hal.expected_send_command(cmd, resp, Ok(()));
+            },
+            UciLoggerMode::Disabled,
+            mpsc::unbounded_channel::<UciLogEvent>().0,
+            session_id,
+            session_token,
+        )
+        .await;
+
+        let expected_result = vec![tlv];
+        let result =
+            uci_manager.android_get_radar_config(session_id, vec![config_id]).await.unwrap();
+        assert_eq!(result, expected_result);
+        assert!(mock_hal.wait_expected_calls_done().await);
+    }
+
+    #[tokio::test]
     async fn test_raw_uci_cmd_vendor_gid_ok() {
         let mt = 0x1;
         let gid = 0xF; // Vendor reserved GID.
@@ -2346,7 +2588,7 @@
         let resp_payload_fragment_1 = vec![0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08];
         let resp_payload_fragment_2 = vec![0x09, 0x0a, 0x0b];
         let mut resp_payload_expected = resp_payload_fragment_1.clone();
-        resp_payload_expected.extend(resp_payload_fragment_2.clone().into_iter());
+        resp_payload_expected.extend(resp_payload_fragment_2.clone());
 
         let (uci_manager, mut mock_hal) = setup_uci_manager_with_open_hal(
             |mut hal| async move {
@@ -2623,7 +2865,7 @@
         let app_data = vec![0x01, 0x02, 0x03];
         let data_rcv_payload = vec![
             0x05, 0x00, 0x00, 0x00, // SessionToken
-            0x00, // DataRcvStatusCode
+            0x00, // StatusCode
             0xa0, 0xb0, 0xc0, 0xd0, 0xa1, 0xb1, 0xc1, 0xd1, // MacAddress
             0x0a, 0x00, // UciSequenceNumber
             0x03, 0x00, // AppDataLen
@@ -2633,8 +2875,8 @@
         // Setup the DataPacketRcv (Rx by HAL) and the expected DataRcvNotification.
         let data_packet_rcv = build_uci_packet(mt_data, pbf, dpf, oid, data_rcv_payload);
         let expected_data_rcv_notification = DataRcvNotification {
-            session_token,
-            status: DataRcvStatusCode::UciStatusSuccess,
+            session_token: session_id,
+            status: StatusCode::UciStatusOk,
             uci_sequence_num,
             source_address,
             payload: app_data,
@@ -2683,7 +2925,7 @@
         let app_data_fragment_1_len = 200;
         let mut data_rcv_payload_fragment_1: Vec<u8> = vec![
             0x05, 0x00, 0x00, 0x00, // SessionToken
-            0x00, // DataRcvStatusCode
+            0x00, // StatusCode
             0xa0, 0xb0, 0xc0, 0xd0, 0xa1, 0xb1, 0xc1, 0xd1, // MacAddress
             0x0a, 0x00, // UciSequenceNumber
             0x2c, 0x01, // AppData Length (300)
@@ -2704,8 +2946,8 @@
         let data_packet_rcv_fragment_2 =
             build_uci_packet(mt_data, pbf_fragment_2, dpf, oid, data_rcv_payload_fragment_2);
         let expected_data_rcv_notification = DataRcvNotification {
-            session_token,
-            status: DataRcvStatusCode::UciStatusSuccess,
+            session_token: session_id,
+            status: StatusCode::UciStatusOk,
             uci_sequence_num,
             source_address,
             payload: app_data,
@@ -2743,6 +2985,109 @@
     #[tokio::test]
     async fn test_data_packet_recv_bad_payload_len_failure() {}
 
+    // Test Radar Data packet receive for a single packet (on an active UWB session).
+    #[tokio::test]
+    async fn test_radar_data_packet_recv_ok() {
+        let mt_data = 0x0;
+        let pbf = 0x0;
+        let dpf = 0xf;
+        let oid = 0x0;
+        let session_id = 0x3;
+        let session_token = 0x5;
+        let radar_data_type = RadarDataType::RadarSweepSamples;
+        let number_of_sweeps = 0x02;
+        let samples_per_sweep = 0x02;
+        let bits_per_sample = BitsPerSample::Value32;
+        let sweep_offset = 0x0;
+        let sequence_number_1 = 0xa;
+        let sequence_number_2 = 0xb;
+        let timestamp_1 = 0xc;
+        let timestamp_2 = 0xd;
+        let vendor_specific_data_1 = vec![0x0b];
+        let vendor_specific_data_2 = vec![0x0b, 0x0c];
+        let sample_data_1 = vec![0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa];
+        let sample_data_2 = vec![0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8];
+        let radar_data_rcv_payload = vec![
+            0x05, 0x00, 0x00, 0x00, // session_handle
+            0x00, // status
+            0x00, // radar data type
+            0x02, // number of sweeps
+            0x02, // samples per sweep
+            0x00, // bits per sample
+            0x00, 0x00, // sweep offset
+            0x10, 0x11, // sweep data size
+            // sweep data 1
+            0x0a, 0x00, 0x00, 0x00, // sequence number
+            0x0c, 0x00, 0x00, 0x00, // timestamp
+            0x01, // vendor specific data length
+            0x0b, // vendor specific data
+            0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, // sample data
+            // sweep data 2
+            0x0b, 0x00, 0x00, 0x00, // sequence number
+            0x0d, 0x00, 0x00, 0x00, // timestamp
+            0x02, // vendor specific data length
+            0x0b, 0x0c, // vendor specific data
+            0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // sample data
+        ];
+
+        // Setup the DataPacketRcv (Rx by HAL) and the expected DataRcvNotification.
+        let radar_data_packet_rcv =
+            build_uci_packet(mt_data, pbf, dpf, oid, radar_data_rcv_payload);
+        let expected_radar_data_rcv_notification = RadarDataRcvNotification {
+            session_token: session_id,
+            status: DataRcvStatusCode::UciStatusSuccess,
+            radar_data_type,
+            number_of_sweeps,
+            samples_per_sweep,
+            bits_per_sample,
+            sweep_offset,
+            sweep_data: vec![
+                RadarSweepData {
+                    sequence_number: sequence_number_1,
+                    timestamp: timestamp_1,
+                    vendor_specific_data: vendor_specific_data_1,
+                    sample_data: sample_data_1,
+                },
+                RadarSweepData {
+                    sequence_number: sequence_number_2,
+                    timestamp: timestamp_2,
+                    vendor_specific_data: vendor_specific_data_2,
+                    sample_data: sample_data_2,
+                },
+            ],
+        };
+
+        // Setup an active UWBS session over which the DataPacket will be received by the Host.
+        let (mut uci_manager, mut mock_hal) = setup_uci_manager_with_session_active(
+            |_| async move {},
+            UciLoggerMode::Disabled,
+            mpsc::unbounded_channel::<UciLogEvent>().0,
+            session_id,
+            session_token,
+        )
+        .await;
+
+        let (radar_data_rcv_notification_sender, mut radar_data_rcv_notification_receiver) =
+            mpsc::unbounded_channel::<RadarDataRcvNotification>();
+        uci_manager
+            .set_radar_data_rcv_notification_sender(radar_data_rcv_notification_sender)
+            .await;
+
+        // Inject the UCI DataPacketRcv into HAL.
+        let result = mock_hal.receive_packet(radar_data_packet_rcv);
+        assert!(result.is_ok());
+
+        // UciManager should send a DataRcvNotification (for the valid Rx packet).
+        let result = tokio::time::timeout(
+            Duration::from_millis(100),
+            radar_data_rcv_notification_receiver.recv(),
+        )
+        .await;
+        assert!(result.is_ok());
+        assert_eq!(result.unwrap(), Some(expected_radar_data_rcv_notification));
+        assert!(mock_hal.wait_expected_calls_done().await);
+    }
+
     #[tokio::test]
     async fn test_data_packet_send_ok() {
         // Test Data packet send for a single packet (on a UWB session).
@@ -2777,8 +3122,7 @@
                 ntfs.append(&mut into_uci_hal_packets(
                     uwb_uci_packets::DataTransferStatusNtfBuilder {
                         session_token,
-                        // TODO(b/282230468): Remove the u16-to-u8 conversion once spec is updated.
-                        uci_sequence_number: uci_sequence_number.try_into().unwrap(),
+                        uci_sequence_number,
                         status,
                         tx_count,
                     },
@@ -2868,8 +3212,7 @@
                 ntfs.append(&mut into_uci_hal_packets(
                     uwb_uci_packets::DataTransferStatusNtfBuilder {
                         session_token,
-                        // TODO(b/282230468): Remove the u16-to-u8 conversion once spec is updated.
-                        uci_sequence_number: uci_sequence_number.try_into().unwrap(),
+                        uci_sequence_number,
                         status,
                         tx_count,
                     },
@@ -2932,8 +3275,7 @@
                 ntfs.append(&mut into_uci_hal_packets(
                     uwb_uci_packets::DataTransferStatusNtfBuilder {
                         session_token,
-                        // TODO(b/282230468): Remove the u16-to-u8 conversion once spec is updated.
-                        uci_sequence_number: uci_sequence_number.try_into().unwrap(),
+                        uci_sequence_number,
                         status,
                         tx_count,
                     },
diff --git a/src/rust/uwb_core/src/uci/uci_manager_sync.rs b/src/rust/uwb_core/src/uci/uci_manager_sync.rs
index 4b1cf25..27a213b 100644
--- a/src/rust/uwb_core/src/uci/uci_manager_sync.rs
+++ b/src/rust/uwb_core/src/uci/uci_manager_sync.rs
@@ -26,18 +26,21 @@
 
 use crate::error::{Error, Result};
 use crate::params::{
-    AppConfigTlv, AppConfigTlvType, CapTlv, CoreSetConfigResponse, CountryCode, DeviceConfigId,
-    DeviceConfigTlv, GetDeviceInfoResponse, PowerStats, RawUciMessage, ResetConfig, SessionId,
-    SessionState, SessionType, SessionUpdateDtTagRangingRoundsResponse, SetAppConfigResponse,
-    UpdateMulticastListAction,
+    AndroidRadarConfigResponse, AppConfigTlv, AppConfigTlvType, CapTlv, CoreSetConfigResponse,
+    CountryCode, DeviceConfigId, DeviceConfigTlv, GetDeviceInfoResponse, PowerStats,
+    RadarConfigTlv, RadarConfigTlvType, RawUciMessage, ResetConfig, SessionId, SessionState,
+    SessionType, SessionUpdateDtTagRangingRoundsResponse, SetAppConfigResponse,
+    UpdateMulticastListAction, UpdateTime,
 };
 #[cfg(any(test, feature = "mock-utils"))]
 use crate::uci::mock_uci_manager::MockUciManager;
-use crate::uci::notification::{CoreNotification, DataRcvNotification, SessionNotification};
+use crate::uci::notification::{
+    CoreNotification, DataRcvNotification, RadarDataRcvNotification, SessionNotification,
+};
 use crate::uci::uci_hal::UciHal;
 use crate::uci::uci_logger::{UciLogger, UciLoggerMode};
 use crate::uci::uci_manager::{UciManager, UciManagerImpl};
-use uwb_uci_packets::Controlees;
+use uwb_uci_packets::{Controlees, PhaseList};
 
 /// The NotificationManager processes UciNotification relayed from UciManagerSync in a sync fashion.
 /// The UciManagerSync assumes the NotificationManager takes the responsibility to properly handle
@@ -59,6 +62,12 @@
         &mut self,
         data_rcv_notification: DataRcvNotification,
     ) -> Result<()>;
+
+    /// Callback for RadarDataRcvNotification.
+    fn on_radar_data_rcv_notification(
+        &mut self,
+        radar_data_rcv_notification: RadarDataRcvNotification,
+    ) -> Result<()>;
 }
 
 /// Builder for NotificationManager. Builder is sent between threads.
@@ -74,6 +83,7 @@
     session_notification_receiver: mpsc::UnboundedReceiver<SessionNotification>,
     vendor_notification_receiver: mpsc::UnboundedReceiver<RawUciMessage>,
     data_rcv_notification_receiver: mpsc::UnboundedReceiver<DataRcvNotification>,
+    radar_data_rcv_notification_receiver: mpsc::UnboundedReceiver<RadarDataRcvNotification>,
     notification_manager: U,
 }
 impl<U: NotificationManager> NotificationDriver<U> {
@@ -82,6 +92,7 @@
         session_notification_receiver: mpsc::UnboundedReceiver<SessionNotification>,
         vendor_notification_receiver: mpsc::UnboundedReceiver<RawUciMessage>,
         data_rcv_notification_receiver: mpsc::UnboundedReceiver<DataRcvNotification>,
+        radar_data_rcv_notification_receiver: mpsc::UnboundedReceiver<RadarDataRcvNotification>,
         notification_manager: U,
     ) -> Self {
         Self {
@@ -89,6 +100,7 @@
             session_notification_receiver,
             vendor_notification_receiver,
             data_rcv_notification_receiver,
+            radar_data_rcv_notification_receiver,
             notification_manager,
         }
     }
@@ -115,6 +127,11 @@
                         error!("NotificationDriver: OnDataRcv callback error: {:?}",e);
                 });
                 }
+                Some(data) = self.radar_data_rcv_notification_receiver.recv() =>{
+                    self.notification_manager.on_radar_data_rcv_notification(data).unwrap_or_else(|e|{
+                        error!("NotificationDriver: OnRadarDataRcv callback error: {:?}",e);
+                });
+                }
                 else =>{
                     debug!("NotificationDriver dropping.");
                     break;
@@ -149,11 +166,16 @@
             mpsc::unbounded_channel::<RawUciMessage>();
         let (data_rcv_notification_sender, data_rcv_notification_receiver) =
             mpsc::unbounded_channel::<DataRcvNotification>();
+        let (radar_data_rcv_notification_sender, radar_data_rcv_notification_receiver) =
+            mpsc::unbounded_channel::<RadarDataRcvNotification>();
         self.runtime_handle.to_owned().block_on(async {
             self.uci_manager.set_core_notification_sender(core_notification_sender).await;
             self.uci_manager.set_session_notification_sender(session_notification_sender).await;
             self.uci_manager.set_vendor_notification_sender(vendor_notification_sender).await;
             self.uci_manager.set_data_rcv_notification_sender(data_rcv_notification_sender).await;
+            self.uci_manager
+                .set_radar_data_rcv_notification_sender(radar_data_rcv_notification_sender)
+                .await;
         });
         // The potentially !Send NotificationManager is created in a separate thread.
         let (driver_status_sender, mut driver_status_receiver) = mpsc::unbounded_channel::<bool>();
@@ -186,6 +208,7 @@
                 session_notification_receiver,
                 vendor_notification_receiver,
                 data_rcv_notification_receiver,
+                radar_data_rcv_notification_receiver,
                 notification_manager,
             );
             local.spawn_local(async move {
@@ -204,7 +227,7 @@
         self.runtime_handle.block_on(self.uci_manager.set_logger_mode(logger_mode))
     }
     /// Start UCI HAL and blocking until UCI commands can be sent.
-    pub fn open_hal(&self) -> Result<()> {
+    pub fn open_hal(&self) -> Result<GetDeviceInfoResponse> {
         self.runtime_handle.block_on(self.uci_manager.open_hal())
     }
 
@@ -342,6 +365,26 @@
         self.runtime_handle.block_on(self.uci_manager.android_get_power_stats())
     }
 
+    /// Set radar config. Android-specific method.
+    pub fn android_set_radar_config(
+        &self,
+        session_id: SessionId,
+        config_tlvs: Vec<RadarConfigTlv>,
+    ) -> Result<AndroidRadarConfigResponse> {
+        self.runtime_handle
+            .block_on(self.uci_manager.android_set_radar_config(session_id, config_tlvs))
+    }
+
+    /// Get radar config. Android-specific method.
+    pub fn android_get_radar_config(
+        &self,
+        session_id: SessionId,
+        config_ids: Vec<RadarConfigTlvType>,
+    ) -> Result<Vec<RadarConfigTlv>> {
+        self.runtime_handle
+            .block_on(self.uci_manager.android_get_radar_config(session_id, config_ids))
+    }
+
     /// Send a raw UCI command.
     pub fn raw_uci_cmd(
         &self,
@@ -368,10 +411,27 @@
             app_payload_data,
         ))
     }
+
     /// Get session token for session id.
     pub fn get_session_token(&self, session_id: SessionId) -> Result<u32> {
         self.runtime_handle.block_on(self.uci_manager.get_session_token_from_session_id(session_id))
     }
+
+    /// Send UCI command for setting hybrid configuration
+    pub fn session_set_hybrid_config(
+        &self,
+        session_id: SessionId,
+        number_of_phases: u8,
+        update_time: UpdateTime,
+        phase_list: Vec<PhaseList>,
+    ) -> Result<()> {
+        self.runtime_handle.block_on(self.uci_manager.session_set_hybrid_config(
+            session_id,
+            number_of_phases,
+            update_time,
+            phase_list,
+        ))
+    }
 }
 
 impl UciManagerSync<UciManagerImpl> {
@@ -432,6 +492,7 @@
     use crate::params::uci_packets::GetDeviceInfoResponse;
     use crate::uci::mock_uci_manager::MockUciManager;
     use crate::uci::{CoreNotification, UciNotification};
+    use uwb_uci_packets::StatusCode::UciStatusOk;
 
     /// Mock NotificationManager forwarding notifications received.
     /// The nonsend_counter is deliberately !send to check UciManagerSync::redirect_notification.
@@ -467,6 +528,13 @@
             self.nonsend_counter.replace_with(|&mut prev| prev + 1);
             Ok(())
         }
+        fn on_radar_data_rcv_notification(
+            &mut self,
+            _data_rcv_notf: RadarDataRcvNotification,
+        ) -> Result<()> {
+            self.nonsend_counter.replace_with(|&mut prev| prev + 1);
+            Ok(())
+        }
     }
 
     /// Builder for MockNotificationManager.
@@ -499,17 +567,20 @@
         let test_rt = Builder::new_multi_thread().enable_all().build().unwrap();
         let (notf_sender, mut notf_receiver) = mpsc::unbounded_channel::<UciNotification>();
         let mut uci_manager_impl = MockUciManager::new();
-        uci_manager_impl.expect_open_hal(
-            vec![UciNotification::Core(CoreNotification::DeviceStatus(DeviceStateReady))],
-            Ok(()),
-        );
-        uci_manager_impl.expect_core_get_device_info(Ok(GetDeviceInfoResponse {
+        let get_device_info_rsp = GetDeviceInfoResponse {
+            status: UciStatusOk,
             uci_version: 0,
             mac_version: 0,
             phy_version: 0,
             uci_test_version: 0,
             vendor_spec_info: vec![],
-        }));
+        };
+
+        uci_manager_impl.expect_open_hal(
+            vec![UciNotification::Core(CoreNotification::DeviceStatus(DeviceStateReady))],
+            Ok(get_device_info_rsp.clone()),
+        );
+        uci_manager_impl.expect_core_get_device_info(Ok(get_device_info_rsp));
         let uci_manager_sync = UciManagerSync::new_mock(
             uci_manager_impl,
             test_rt.handle().to_owned(),
diff --git a/src/rust/uwb_uci_packets/src/lib.rs b/src/rust/uwb_uci_packets/src/lib.rs
index 38b0910..eab7f9f 100644
--- a/src/rust/uwb_uci_packets/src/lib.rs
+++ b/src/rust/uwb_uci_packets/src/lib.rs
@@ -53,6 +53,11 @@
 const UCI_CONTROL_HEADER_OID_BYTE_POSITION: usize = 1;
 const UCI_CONTROL_HEADER_OID_MASK: u8 = 0x3F;
 
+// Radar field lengths
+pub const UCI_RADAR_SEQUENCE_NUMBER_LEN: usize = 4;
+pub const UCI_RADAR_TIMESTAMP_LEN: usize = 4;
+pub const UCI_RADAR_VENDOR_DATA_LEN_LEN: usize = 1;
+
 #[derive(Debug, Clone, PartialEq, FromPrimitive)]
 pub enum TimeStampLength {
     Timestamp40Bit = 0x0,
@@ -123,8 +128,8 @@
         let initiator_responder_tof = extract_u16(bytes, &mut ptr, 2)?;
         let dt_location_type = (message_control >> 5) & 0x3;
         let dt_anchor_location = match DTAnchorLocationType::from_u16(dt_location_type)? {
-            DTAnchorLocationType::Wgs84 => extract_vec(bytes, &mut ptr, 10)?,
-            DTAnchorLocationType::Relative => extract_vec(bytes, &mut ptr, 12)?,
+            DTAnchorLocationType::Wgs84 => extract_vec(bytes, &mut ptr, 12)?,
+            DTAnchorLocationType::Relative => extract_vec(bytes, &mut ptr, 10)?,
             _ => vec![],
         };
         let active_ranging_rounds = ((message_control >> 7) & 0xf) as u8;
@@ -432,16 +437,21 @@
     }
 }
 
-// UCI Data packet functions.
-fn is_uci_data_rcv_packet(message_type: MessageType, data_packet_format: DataPacketFormat) -> bool {
-    message_type == MessageType::Data && data_packet_format == DataPacketFormat::DataRcv
+fn is_uci_data_packet(message_type: MessageType) -> bool {
+    message_type == MessageType::Data
 }
 
-fn try_into_data_payload(packet: UciPacketHal) -> Result<Bytes> {
-    if is_uci_data_rcv_packet(
-        packet.get_message_type(),
-        packet.get_group_id_or_data_packet_format().try_into()?,
-    ) {
+fn is_data_rcv_or_radar_format(data_packet_format: DataPacketFormat) -> bool {
+    data_packet_format == DataPacketFormat::DataRcv
+        || data_packet_format == DataPacketFormat::RadarDataMessage
+}
+
+fn try_into_data_payload(
+    packet: UciPacketHal,
+    expected_data_packet_format: DataPacketFormat,
+) -> Result<Bytes> {
+    let dpf: DataPacketFormat = packet.get_group_id_or_data_packet_format().try_into()?;
+    if is_uci_data_packet(packet.get_message_type()) && dpf == expected_data_packet_format {
         Ok(packet.to_bytes().slice(UCI_PACKET_HAL_HEADER_LEN..))
     } else {
         error!("Received unexpected data packet fragment: {:?}", packet);
@@ -459,12 +469,17 @@
             return Err(Error::InvalidPacketError);
         }
 
+        let dpf: DataPacketFormat = packets[0].get_group_id_or_data_packet_format().try_into()?;
+        if !is_data_rcv_or_radar_format(dpf) {
+            error!("Unexpected data packet format {:?}", dpf);
+        }
+
         // Create the reassembled payload.
         let mut payload_buf = Bytes::new();
         for packet in packets {
             // Ensure that the fragment is a Data Rcv packet.
             // Get payload by stripping the header.
-            payload_buf = [payload_buf, try_into_data_payload(packet)?].concat().into();
+            payload_buf = [payload_buf, try_into_data_payload(packet, dpf)?].concat().into();
         }
 
         // Create assembled |UciDataPacket| and convert to bytes again since we need to
@@ -472,7 +487,7 @@
         UciDataPacket::parse(
             &UciDataPacketBuilder {
                 message_type: MessageType::Data,
-                data_packet_format: DataPacketFormat::DataRcv,
+                data_packet_format: dpf,
                 payload: Some(payload_buf.into()),
             }
             .build()
@@ -824,10 +839,7 @@
 ) -> Result<SessionUpdateControllerMulticastListCmd> {
     let mut controlees_buf = BytesMut::new();
     match controlees {
-        Controlees::NoSessionKey(controlee_v1)
-            if action == UpdateMulticastListAction::AddControlee
-                || action == UpdateMulticastListAction::RemoveControlee =>
-        {
+        Controlees::NoSessionKey(controlee_v1) => {
             controlees_buf.extend_from_slice(&(controlee_v1.len() as u8).to_le_bytes());
             for controlee in controlee_v1 {
                 controlees_buf.extend_from_slice(&write_controlee(&controlee));
@@ -868,6 +880,17 @@
     }
 }
 
+// Radar data 'bits per sample' field isn't a raw value, instead it's an enum
+// that maps to the raw value. We need this mapping to get the max sample size
+// length.
+pub fn radar_bytes_per_sample_value(bps: BitsPerSample) -> u8 {
+    match bps {
+        BitsPerSample::Value32 => 4,
+        BitsPerSample::Value48 => 6,
+        BitsPerSample::Value64 => 8,
+    }
+}
+
 #[cfg(test)]
 mod tests {
     use super::*;
@@ -1012,7 +1035,7 @@
             // All Fields in Little Endian (LE)
             // First measurement
             0x0a, 0x01, 0x33, 0x05, // 2(Mac address), Status, Message Type
-            0x33, 0x05, 0x02, 0x05, // 2(Message control), 2(Block Index)
+            0x53, 0x05, 0x02, 0x05, // 2(Message control), 2(Block Index)
             0x07, 0x09, 0x0a, 0x01, // Round Index, NLoS, 2(AoA Azimuth)
             0x02, 0x05, 0x07, 0x09, // AoA Azimuth FOM, 2(AoA Elevation), AoA Elevation FOM
             0x0a, 0x01, 0x02, 0x05, // RSSI, 3(Tx Timestamp..)
@@ -1041,9 +1064,10 @@
             0x0a, 0x01, 0x02, 0x05, // 2(Responder Reply Time), 2(Initiator-Responder ToF)
             0x07, 0x09, 0x07, 0x09, // 4(Anchor Location..)
             0x05, 0x07, 0x09, 0x0a, // 4(Anchor Location..)
-            0x01, 0x02, 0x05, 0x07, // 2(Anchor Location..), 2(Active Ranging Rounds..)
-            0x09, 0x0a, 0x01, 0x02, // 4(Active Ranging Rounds..)
-            0x05, 0x07, 0x09, 0x05, // 4(Active Ranging Rounds)
+            0x01, 0x02, 0x01, 0x02, // 4(Anchor Location)
+            0x05, 0x07, 0x09, 0x0a, // 4(Active Ranging Rounds..)
+            0x01, 0x02, 0x05, 0x07, // 4(Active Ranging Rounds..)
+            0x09, 0x05, // 2(Active Ranging Rounds)
         ];
 
         let measurements = ShortAddressDlTdoaRangingMeasurement::parse(&bytes, 2).unwrap();
@@ -1053,7 +1077,7 @@
         assert_eq!(*mac_address_1, 0x010a);
         assert_eq!(measurement_1.status, 0x33);
         assert_eq!(measurement_1.message_type, 0x05);
-        assert_eq!(measurement_1.message_control, 0x0533);
+        assert_eq!(measurement_1.message_control, 0x0553);
         assert_eq!(measurement_1.block_index, 0x0502);
         assert_eq!(measurement_1.round_index, 0x07);
         assert_eq!(measurement_1.nlos, 0x09);
@@ -1100,11 +1124,11 @@
         assert_eq!(measurement_2.responder_reply_time, 0x010a0907);
         assert_eq!(measurement_2.initiator_responder_tof, 0x0502);
         assert_eq!(
-            measurement_1.dt_anchor_location,
-            vec![0x07, 0x09, 0x07, 0x09, 0x05, 0x07, 0x09, 0x0a, 0x01, 0x02]
+            measurement_2.dt_anchor_location,
+            vec![0x07, 0x09, 0x07, 0x09, 0x05, 0x07, 0x09, 0x0a, 0x01, 0x02, 0x01, 0x02]
         );
         assert_eq!(
-            measurement_1.ranging_rounds,
+            measurement_2.ranging_rounds,
             vec![0x05, 0x07, 0x09, 0x0a, 0x01, 0x02, 0x05, 0x07, 0x09, 0x05,]
         );
     }
diff --git a/src/rust/uwb_uci_packets/uci_packets.pdl b/src/rust/uwb_uci_packets/uci_packets.pdl
index 12bdb6c..1f3969c 100644
--- a/src/rust/uwb_uci_packets/uci_packets.pdl
+++ b/src/rust/uwb_uci_packets/uci_packets.pdl
@@ -22,6 +22,7 @@
 enum DataPacketFormat: 4 {
     DATA_SND = 0x01,
     DATA_RCV = 0x02,
+    RADAR_DATA_MESSAGE = 0x0f,
 }
 
 // Define a merged enum across GroupId & DataPacketFormat as they are at the same bits in
@@ -87,6 +88,8 @@
     ANDROID_GET_POWER_STATS = 0x0,
     ANDROID_SET_COUNTRY_CODE = 0x1,
     ANDROID_FIRA_RANGE_DIAGNOSTICS = 0x2,
+    ANDROID_RADAR_SET_APP_CONFIG = 0x11,
+    ANDROID_RADAR_GET_APP_CONFIG = 0x12,
 }
 
 enum StatusCode : 8 {
@@ -144,6 +147,7 @@
         UCI_STATUS_ERROR_CCC_SE_BUSY = 0x50,
         UCI_STATUS_ERROR_CCC_LIFECYCLE = 0x51,
         UCI_STATUS_ERROR_STOPPED_DUE_TO_OTHER_SESSION_CONFLICT = 0x52,
+        UCI_STATUS_REGULATION_UWB_OFF = 0x53,
     },
 
     // For internal usage, we will use 0xFF as default.
@@ -172,6 +176,7 @@
     UCI_DATA_TRANSFER_STATUS_ERROR_REJECTED = 0x04,
     UCI_DATA_TRANSFER_STATUS_SESSION_TYPE_NOT_SUPPORTED = 0x05,
     UCI_DATA_TRANSFER_STATUS_ERROR_DATA_TRANSFER_IS_ONGOING = 0x06,
+    UCI_DATA_TRANSFER_STATUS_INVALID_FORMAT = 0x07,
 }
 
 enum ResetConfig : 8 {
@@ -245,11 +250,14 @@
     MIN_FRAMES_PER_RR = 0x3A,
     MTU_SIZE = 0x3B,
     INTER_FRAME_INTERVAL = 0x3C,
-    RFU_APP_CFG_TLV_TYPE_RANGE_1 = 0x3D..0x44,
+    RFU_APP_CFG_TLV_TYPE_RANGE_1 = 0x3D..0x42,
+    DLTDOA_BLOCK_STRIDING = 0x43,
+    RFU_APP_CFG_TLV_TYPE_RANGE_2 = 0x44,
     SESSION_KEY = 0x45,
     SUBSESSION_KEY = 0x46,
     SESSION_DATA_TRANSFER_STATUS_NTF_CONFIG = 0x47,
-    RFU_APP_CFG_TLV_TYPE_RANGE_2 = 0x48..0x9F,
+    SESSION_TIME_BASE = 0x48,
+    RFU_APP_CFG_TLV_TYPE_RANGE_3 = 0x49..0x9F,
 
     VENDOR_SPECIFIC_APP_CFG_TLV_TYPE_RANGE_1 = 0xA0..0xDF {
         // CCC specific
@@ -263,7 +271,7 @@
     },
 
     // Reserved for extension IDs.
-    RFU_APP_CFG_TLV_TYPE_RANGE_3 = 0xE0..0xE2,
+    RFU_APP_CFG_TLV_TYPE_RANGE_4 = 0xE0..0xE2,
 
     VENDOR_SPECIFIC_APP_CFG_TLV_TYPE_RANGE_2 = 0xE3..0xFF {
         // Interleaving ratio if AOA_RESULT_REQ is set to 0xF0.
@@ -315,6 +323,8 @@
         CCC_SUPPORTED_PULSE_SHAPE_COMBOS = 0xA6,
         CCC_SUPPORTED_RAN_MULTIPLIER = 0xA7,
         CCC_SUPPORTED_MAX_RANGING_SESSION_NUMBER = 0xA8,
+        // RADAR specific
+        RADAR_SUPPORT = 0xB0
     },
 
     SUPPORTED_POWER_STATS = 0xC0,
@@ -416,9 +426,12 @@
     STATUS_ERROR_MULTICAST_LIST_FULL = 0x01,
     STATUS_ERROR_KEY_FETCH_FAIL = 0x02,
     STATUS_ERROR_SUB_SESSION_ID_NOT_FOUND = 0x03,
-    STATUS_ERROR_SUB_SESSION_KEY_NOT_FOUND = 0x05,
-    STATUS_ERROR_SUB_SESSION_KEY_NOT_APPLICABLE = 0x06,
-    STATUS_ERROR_SESSION_KEY_NOT_FOUND = 0x07,
+    STATUS_ERROR_SUB_SESSION_KEY_NOT_FOUND = 0x04,
+    STATUS_ERROR_SUB_SESSION_KEY_NOT_APPLICABLE = 0x05,
+    STATUS_ERROR_SESSION_KEY_NOT_FOUND = 0x06,
+    STATUS_ERROR_ADDRESS_NOT_FOUND = 0x07,
+    STATUS_ERROR_ADDRESS_ALREADY_PRESENT = 0x08,
+    RFU_STATUS_CODE_RANGE_1 = 0x09..0xFF,
 }
 
 enum MacAddressIndicator : 8 {
@@ -428,8 +441,13 @@
 
 enum SessionType: 8 {
     FIRA_RANGING_SESSION = 0x00,
-    FIRA_DATA_TRANSFER = 0x01,
+    FIRA_RANGING_AND_IN_BAND_DATA_SESSION = 0x01,
+    FIRA_DATA_TRANSFER_SESSION = 0x02,
+    FIRA_RANGING_ONLY_PHASE = 0x03,
+    FIRA_IN_BAND_DATA_PHASE = 0x04,
+    FIRA_RANGING_WITH_DATA_PHASE = 0x05,
     CCC = 0xA0,
+    RADAR_SESSION = 0xA1,
     DEVICE_TEST_MODE = 0xD0,
 }
 
@@ -519,7 +537,7 @@
 
 packet UciDataRcv : UciDataPacket (data_packet_format = DATA_RCV, message_type = DATA) {
     session_token: 32, // Session ID or Session Handle (based on UWBS version)
-    status: DataRcvStatusCode,
+    status: StatusCode,
     source_mac_address: 64,
     uci_sequence_number: 16,
     _size_(data): 16,
@@ -922,6 +940,23 @@
     _payload_,
 }
 
+struct PhaseList {
+    session_token: 32,
+    start_slot_index: 16,
+    end_slot_index: 16,
+}
+
+packet SessionSetHybridConfigCmd : SessionConfigCommand (opcode = 0x0c) { //SESSION_SET_HUS_CONFIG
+    session_token: 32,
+    number_of_phases: 8,
+    update_time: 8[8],
+    phase_list: PhaseList[],
+}
+
+packet SessionSetHybridConfigRsp : SessionConfigResponse (opcode = 0x0c) { //SESSION_SET_HUS_CONFIG
+    status: StatusCode,
+}
+
 struct SessionUpdateControllerMulticastListCmdPayload {
     _count_(controlees): 8,
     controlees: Controlee[],
@@ -973,7 +1008,7 @@
 
 packet DataTransferStatusNtf : SessionControlNotification (opcode = 0x05) { // SESSION_DATA_TRANSFER_STATUS_NTF
     session_token: 32, // Session ID or Session Handle (based on UWBS version)
-    uci_sequence_number: 8,
+    uci_sequence_number: 16,
     status: DataTransferNtfStatusCode,
     tx_count: 8,
 }
@@ -992,11 +1027,12 @@
 
 packet SessionQueryMaxDataSizeRsp : SessionConfigResponse (opcode = 0xB) { //QUER_MAX_DATA_SIZE
     session_token: 32, // Session ID or Session Handle (based on UWBS version)
+    status: StatusCode,
     max_data_size: 16,
 }
 
 test SessionQueryMaxDataSizeRsp {
-  "\x41\x0B\x00\x06\x00\x00\x00\x00\x0E7\0x07",
+  "\x41\x0B\x00\x06\x00\x00\x00\x00\x00\x0E7\0x07",
 }
 
 packet SessionStartCmd : SessionControlCommand (opcode = 0x0) { //RANGE_START
@@ -1348,3 +1384,88 @@
 packet TestNotification : UciNotification (group_id = TEST) {
     _payload_,
 }
+
+enum RadarDataType : 8 {
+    RADAR_SWEEP_SAMPLES = 0x00,
+}
+
+enum RadarConfigTlvType : 8 {
+    RADAR_TIMING_PARAMS = 0x00,
+    SAMPLES_PER_SWEEP = 0x01,
+    CHANNEL_NUMBER = 0x02,
+    SWEEP_OFFSET = 0x03,
+    RFRAME_CONFIG = 0x04,
+    PREAMBLE_DURATION = 0x05,
+    PREAMBLE_CODE_INDEX = 0x06,
+    SESSION_PRIORITY = 0x07,
+    BITS_PER_SAMPLE = 0x08,
+    PRF_MODE = 0x09,
+    NUMBER_OF_BURSTS = 0x0A,
+    RADAR_DATA_TYPE = 0x0B,
+
+    RFU_RADAR_APP_CFG_TLV_TYPE_RANGE = 0x0C..0x9F,
+
+    VENDOR_SPECIFIC_RADAR_APP_CFG_TLV_TYPE_RANGE = 0xA0..0xDF,
+}
+
+struct RadarConfigTlv {
+    cfg_id: RadarConfigTlvType,
+    _count_(v): 8,
+    v: 8[],
+}
+
+struct RadarConfigStatus {
+    cfg_id: RadarConfigTlvType,
+    status: StatusCode,
+}
+
+packet AndroidSetRadarConfigCmd: AndroidCommand (opcode = 0x11) {
+    session_token: 32,
+    _count_(tlvs): 8,
+    tlvs: RadarConfigTlv[]
+}
+
+packet AndroidSetRadarConfigRsp : AndroidResponse (opcode = 0x11) {
+    status: StatusCode,
+    _count_(cfg_status): 8,
+    cfg_status: RadarConfigStatus[],
+}
+
+packet AndroidGetRadarConfigCmd: AndroidCommand (opcode = 0x12) {
+    session_token: 32,
+    _count_(tlvs): 8,
+    tlvs: 8[], // RadarConfigTlvType (Infra does not allow array of enums)
+}
+
+packet AndroidGetRadarConfigRsp : AndroidResponse (opcode = 0x12) {
+    status: StatusCode,
+    _count_(tlvs): 8,
+    tlvs: RadarConfigTlv[],
+}
+
+enum BitsPerSample : 8 {
+    VALUE_32 = 0x00,
+    VALUE_48 = 0x01,
+    VALUE_64 = 0x02
+}
+
+struct RadarSweepDataRaw {
+    sequence_number: 32,
+    timestamp: 32,
+    _count_(vendor_specific_data): 8,
+    vendor_specific_data: 8[],
+    sample_data: 8[],
+}
+
+packet RadarDataRcv : UciDataPacket (data_packet_format = RADAR_DATA_MESSAGE, message_type = DATA) {
+    session_handle: 32,
+    status: DataRcvStatusCode,
+    radar_data_type: RadarDataType,
+    number_of_sweeps: 8,
+    samples_per_sweep: 8,
+    bits_per_sample: BitsPerSample,
+    sweep_offset: 16,
+    sweep_data_size: 16,
+    sweep_data: 8[],
+}
+