• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! HAL interface.
2 
3 use crate::error::UwbErr;
4 use crate::uci::uci_hrcv;
5 use crate::uci::uci_logger::{RealFileFactory, UciLogMode, UciLogger, UciLoggerImpl};
6 use crate::uci::HalCallback;
7 use android_hardware_uwb::aidl::android::hardware::uwb::{
8     IUwb::IUwbAsync,
9     IUwbChip::IUwbChipAsync,
10     IUwbClientCallback::{BnUwbClientCallback, IUwbClientCallbackAsyncServer},
11     UwbEvent::UwbEvent,
12     UwbStatus::UwbStatus,
13 };
14 use android_hardware_uwb::binder::{
15     BinderFeatures, DeathRecipient, Interface, Result as BinderResult, Strong,
16 };
17 use async_trait::async_trait;
18 use binder::IBinder;
19 use binder_tokio::{Tokio, TokioRuntime};
20 use log::error;
21 #[cfg(target_os = "android")]
22 use rustutils::system_properties;
23 use std::sync::Arc;
24 use tokio::runtime::Handle;
25 use tokio::sync::{mpsc, Mutex};
26 use uwb_uci_packets::{
27     Packet, PacketDefrager, UciCommandPacket, UciPacketChild, UciPacketHalPacket, UciPacketPacket,
28 };
29 
30 type Result<T> = std::result::Result<T, UwbErr>;
31 type SyncUciLogger = Arc<dyn UciLogger + Send + Sync>;
32 
33 const UCI_LOG_DEFAULT: UciLogMode = UciLogMode::Disabled;
34 
35 pub struct UwbClientCallback {
36     rsp_sender: mpsc::UnboundedSender<HalCallback>,
37     logger: SyncUciLogger,
38     defrager: Mutex<PacketDefrager>,
39 }
40 
41 impl UwbClientCallback {
new(rsp_sender: mpsc::UnboundedSender<HalCallback>, logger: SyncUciLogger) -> Self42     fn new(rsp_sender: mpsc::UnboundedSender<HalCallback>, logger: SyncUciLogger) -> Self {
43         UwbClientCallback { rsp_sender, logger, defrager: Default::default() }
44     }
45 
log_uci_packet(&self, packet: UciPacketPacket)46     async fn log_uci_packet(&self, packet: UciPacketPacket) {
47         match packet.specialize() {
48             UciPacketChild::UciResponse(pkt) => self.logger.log_uci_response(pkt).await,
49             UciPacketChild::UciNotification(pkt) => self.logger.log_uci_notification(pkt).await,
50             _ => {}
51         }
52     }
53 }
54 
55 impl Interface for UwbClientCallback {}
56 
57 #[async_trait]
58 impl IUwbClientCallbackAsyncServer for UwbClientCallback {
onHalEvent(&self, event: UwbEvent, event_status: UwbStatus) -> BinderResult<()>59     async fn onHalEvent(&self, event: UwbEvent, event_status: UwbStatus) -> BinderResult<()> {
60         self.rsp_sender
61             .send(HalCallback::Event { event, event_status })
62             .unwrap_or_else(|e| error!("Error sending evt callback: {:?}", e));
63         Ok(())
64     }
65 
onUciMessage(&self, data: &[u8]) -> BinderResult<()>66     async fn onUciMessage(&self, data: &[u8]) -> BinderResult<()> {
67         if let Some(packet) = self.defrager.lock().await.defragment_packet(data) {
68             // all fragments for the packet received.
69             self.log_uci_packet(packet.clone()).await;
70             let packet_msg = uci_hrcv::uci_message(packet);
71             match packet_msg {
72                 Ok(uci_hrcv::UciMessage::Response(evt)) => self
73                     .rsp_sender
74                     .send(HalCallback::UciRsp(evt))
75                     .unwrap_or_else(|e| error!("Error sending uci response: {:?}", e)),
76                 Ok(uci_hrcv::UciMessage::Notification(evt)) => self
77                     .rsp_sender
78                     .send(HalCallback::UciNtf(evt))
79                     .unwrap_or_else(|e| error!("Error sending uci notification: {:?}", e)),
80                 _ => error!("UCI message which is neither a UCI RSP or NTF: {:?}", data),
81             }
82         }
83         Ok(())
84     }
85 }
86 
get_hal_service() -> Result<Strong<dyn IUwbChipAsync<Tokio>>>87 async fn get_hal_service() -> Result<Strong<dyn IUwbChipAsync<Tokio>>> {
88     let service_name: &str = "android.hardware.uwb.IUwb/default";
89     let i_uwb: Strong<dyn IUwbAsync<Tokio>> = binder_tokio::get_interface(service_name).await?;
90     let chip_names = i_uwb.getChips().await?;
91     let i_uwb_chip = i_uwb.getChip(&chip_names[0]).await?.into_async();
92     Ok(i_uwb_chip)
93 }
94 
95 #[async_trait]
96 pub trait UwbAdaptation {
finalize(&mut self, exit_status: bool)97     async fn finalize(&mut self, exit_status: bool);
hal_open(&self) -> Result<()>98     async fn hal_open(&self) -> Result<()>;
hal_close(&self) -> Result<()>99     async fn hal_close(&self) -> Result<()>;
core_initialization(&self) -> Result<()>100     async fn core_initialization(&self) -> Result<()>;
session_initialization(&self, session_id: i32) -> Result<()>101     async fn session_initialization(&self, session_id: i32) -> Result<()>;
send_uci_message(&self, cmd: UciCommandPacket) -> Result<()>102     async fn send_uci_message(&self, cmd: UciCommandPacket) -> Result<()>;
103 }
104 
105 #[derive(Clone)]
106 pub struct UwbAdaptationImpl {
107     hal: Strong<dyn IUwbChipAsync<Tokio>>,
108     #[allow(dead_code)]
109     // Need to store the death recipient since link_to_death stores a weak pointer.
110     hal_death_recipient: Arc<Mutex<DeathRecipient>>,
111     rsp_sender: mpsc::UnboundedSender<HalCallback>,
112     logger: SyncUciLogger,
113 }
114 
115 impl UwbAdaptationImpl {
116     #[cfg(target_os = "android")]
get_uci_log_mode() -> UciLogMode117     fn get_uci_log_mode() -> UciLogMode {
118         match system_properties::read("persist.uwb.uci_logger_mode") {
119             Ok(Some(logger_mode)) => match logger_mode.as_str() {
120                 "disabled" => UciLogMode::Disabled,
121                 "filtered" => UciLogMode::Filtered,
122                 "enabled" => UciLogMode::Enabled,
123                 str => {
124                     error!("Logger mode not recognized! Value: {:?}", str);
125                     UCI_LOG_DEFAULT
126                 }
127             },
128             Ok(None) => UCI_LOG_DEFAULT,
129             Err(e) => {
130                 error!("Failed to get uci_logger_mode {:?}", e);
131                 UCI_LOG_DEFAULT
132             }
133         }
134     }
135 
136     #[cfg(not(target_os = "android"))]
get_uci_log_mode() -> UciLogMode137     fn get_uci_log_mode() -> UciLogMode {
138         // system_properties is not supported on host builds.
139         UCI_LOG_DEFAULT
140     }
141 
new_with_args( rsp_sender: mpsc::UnboundedSender<HalCallback>, hal: Strong<dyn IUwbChipAsync<Tokio>>, hal_death_recipient: Arc<Mutex<DeathRecipient>>, ) -> Result<Self>142     async fn new_with_args(
143         rsp_sender: mpsc::UnboundedSender<HalCallback>,
144         hal: Strong<dyn IUwbChipAsync<Tokio>>,
145         hal_death_recipient: Arc<Mutex<DeathRecipient>>,
146     ) -> Result<Self> {
147         let logger = UciLoggerImpl::new(
148             UwbAdaptationImpl::get_uci_log_mode(),
149             Arc::new(Mutex::new(RealFileFactory::default())),
150         )
151         .await;
152         Ok(UwbAdaptationImpl { hal, rsp_sender, logger: Arc::new(logger), hal_death_recipient })
153     }
154 
new(rsp_sender: mpsc::UnboundedSender<HalCallback>) -> Result<Self>155     pub async fn new(rsp_sender: mpsc::UnboundedSender<HalCallback>) -> Result<Self> {
156         let hal = get_hal_service().await?;
157         let rsp_sender_clone = rsp_sender.clone();
158         let mut hal_death_recipient = DeathRecipient::new(move || {
159             error!("UWB HAL died. Resetting stack...");
160             // Send error HAL event to trigger stack recovery.
161             rsp_sender_clone
162                 .send(HalCallback::Event {
163                     event: UwbEvent::ERROR,
164                     event_status: UwbStatus::FAILED,
165                 })
166                 .unwrap_or_else(|e| error!("Error sending error evt callback: {:?}", e));
167         });
168         // Register for death notification.
169         hal.as_binder().link_to_death(&mut hal_death_recipient)?;
170         Self::new_with_args(rsp_sender, hal, Arc::new(Mutex::new(hal_death_recipient))).await
171     }
172 }
173 
174 #[async_trait]
175 impl UwbAdaptation for UwbAdaptationImpl {
finalize(&mut self, _exit_status: bool)176     async fn finalize(&mut self, _exit_status: bool) {}
177 
hal_open(&self) -> Result<()>178     async fn hal_open(&self) -> Result<()> {
179         let m_cback = BnUwbClientCallback::new_async_binder(
180             UwbClientCallback::new(self.rsp_sender.clone(), self.logger.clone()),
181             TokioRuntime(Handle::current()),
182             BinderFeatures::default(),
183         );
184         Ok(self.hal.open(&m_cback).await?)
185     }
186 
hal_close(&self) -> Result<()>187     async fn hal_close(&self) -> Result<()> {
188         self.logger.close_file().await;
189         Ok(self.hal.close().await?)
190     }
191 
core_initialization(&self) -> Result<()>192     async fn core_initialization(&self) -> Result<()> {
193         Ok(self.hal.coreInit().await?)
194     }
195 
session_initialization(&self, session_id: i32) -> Result<()>196     async fn session_initialization(&self, session_id: i32) -> Result<()> {
197         Ok(self.hal.sessionInit(session_id).await?)
198     }
199 
send_uci_message(&self, cmd: UciCommandPacket) -> Result<()>200     async fn send_uci_message(&self, cmd: UciCommandPacket) -> Result<()> {
201         self.logger.log_uci_command(cmd.clone()).await;
202         let packet: UciPacketPacket = cmd.into();
203         // fragment packet.
204         let fragmented_packets: Vec<UciPacketHalPacket> = packet.into();
205         for packet in fragmented_packets {
206             self.hal.sendUciMessage(&packet.to_vec()).await?;
207         }
208         // TODO should we be validating the returned number?
209         Ok(())
210     }
211 }
212 
213 #[cfg(any(test, fuzzing))]
214 pub mod mock_adaptation;
215 #[cfg(test)]
216 mod mock_hal;
217 
218 #[cfg(test)]
219 pub mod tests {
220     use super::*;
221     use crate::adaptation::mock_hal::MockHal;
222     use crate::uci::mock_uci_logger::MockUciLogger;
223     use bytes::Bytes;
224     use uwb_uci_packets::*;
225 
create_uwb_client_callback( rsp_sender: mpsc::UnboundedSender<HalCallback>, ) -> UwbClientCallback226     fn create_uwb_client_callback(
227         rsp_sender: mpsc::UnboundedSender<HalCallback>,
228     ) -> UwbClientCallback {
229         // Add tests for the mock logger.
230         UwbClientCallback::new(rsp_sender, Arc::new(MockUciLogger::new()))
231     }
232 
setup_client_callback() -> (mpsc::UnboundedReceiver<HalCallback>, UwbClientCallback)233     fn setup_client_callback() -> (mpsc::UnboundedReceiver<HalCallback>, UwbClientCallback) {
234         // TODO: Remove this once we call it somewhere real.
235         logger::init(
236             logger::Config::default()
237                 .with_tag_on_device("uwb_test")
238                 .with_min_level(log::Level::Debug),
239         );
240         let (rsp_sender, rsp_receiver) = mpsc::unbounded_channel::<HalCallback>();
241         let uwb_client_callback = create_uwb_client_callback(rsp_sender);
242         (rsp_receiver, uwb_client_callback)
243     }
244 
245     #[tokio::test]
test_on_hal_event()246     async fn test_on_hal_event() {
247         let event = UwbEvent(0);
248         let event_status = UwbStatus(1);
249         let (mut rsp_receiver, uwb_client_callback) = setup_client_callback();
250         let result = uwb_client_callback.onHalEvent(event, event_status).await;
251         assert_eq!(result, Ok(()));
252         let response = rsp_receiver.recv().await;
253         assert!(matches!(response, Some(HalCallback::Event { event: _, event_status: _ })));
254     }
255 
256     #[tokio::test]
test_get_device_info_rsp()257     async fn test_get_device_info_rsp() {
258         let data = [
259             0x40, 0x02, 0x00, 0x0b, 0x01, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x01,
260             0x0a,
261         ];
262         let (mut rsp_receiver, uwb_client_callback) = setup_client_callback();
263         let result = uwb_client_callback.onUciMessage(&data).await;
264         assert_eq!(result, Ok(()));
265         let response = rsp_receiver.recv().await;
266         assert!(matches!(
267             response,
268             Some(HalCallback::UciRsp(uci_hrcv::UciResponse::GetDeviceInfoRsp(_)))
269         ));
270     }
271 
272     #[tokio::test]
test_get_caps_info_rsp()273     async fn test_get_caps_info_rsp() {
274         let data = [0x40, 0x03, 0x00, 0x05, 0x00, 0x01, 0x00, 0x01, 0x01];
275         let (mut rsp_receiver, uwb_client_callback) = setup_client_callback();
276         let result = uwb_client_callback.onUciMessage(&data).await;
277         assert_eq!(result, Ok(()));
278         let response = rsp_receiver.recv().await;
279         assert!(matches!(
280             response,
281             Some(HalCallback::UciRsp(uci_hrcv::UciResponse::GetCapsInfoRsp(_)))
282         ));
283     }
284 
285     #[tokio::test]
test_set_config_rsp()286     async fn test_set_config_rsp() {
287         let data = [0x40, 0x04, 0x00, 0x04, 0x01, 0x01, 0x01, 0x01];
288         let (mut rsp_receiver, uwb_client_callback) = setup_client_callback();
289         let result = uwb_client_callback.onUciMessage(&data).await;
290         assert_eq!(result, Ok(()));
291         let response = rsp_receiver.recv().await;
292         assert!(matches!(
293             response,
294             Some(HalCallback::UciRsp(uci_hrcv::UciResponse::SetConfigRsp(_)))
295         ));
296     }
297 
298     #[tokio::test]
test_get_config_rsp()299     async fn test_get_config_rsp() {
300         let data = [0x40, 0x05, 0x00, 0x05, 0x01, 0x01, 0x00, 0x01, 0x01];
301         let (mut rsp_receiver, uwb_client_callback) = setup_client_callback();
302         let result = uwb_client_callback.onUciMessage(&data).await;
303         assert_eq!(result, Ok(()));
304         let response = rsp_receiver.recv().await;
305         assert!(matches!(
306             response,
307             Some(HalCallback::UciRsp(uci_hrcv::UciResponse::GetConfigRsp(_)))
308         ));
309     }
310 
311     #[tokio::test]
test_device_reset_rsp()312     async fn test_device_reset_rsp() {
313         let data = [0x40, 0x00, 0x00, 0x01, 0x00];
314         let (mut rsp_receiver, uwb_client_callback) = setup_client_callback();
315         let result = uwb_client_callback.onUciMessage(&data).await;
316         assert_eq!(result, Ok(()));
317         let response = rsp_receiver.recv().await;
318         assert!(matches!(
319             response,
320             Some(HalCallback::UciRsp(uci_hrcv::UciResponse::DeviceResetRsp(_)))
321         ));
322     }
323 
324     #[tokio::test]
test_session_init_rsp()325     async fn test_session_init_rsp() {
326         let data = [0x41, 0x00, 0x00, 0x01, 0x11];
327         let (mut rsp_receiver, uwb_client_callback) = setup_client_callback();
328         let result = uwb_client_callback.onUciMessage(&data).await;
329         assert_eq!(result, Ok(()));
330         let response = rsp_receiver.recv().await;
331         assert!(matches!(
332             response,
333             Some(HalCallback::UciRsp(uci_hrcv::UciResponse::SessionInitRsp(_)))
334         ));
335     }
336 
337     #[tokio::test]
test_session_deinit_rsp()338     async fn test_session_deinit_rsp() {
339         let data = [0x41, 0x01, 0x00, 0x01, 0x00];
340         let (mut rsp_receiver, uwb_client_callback) = setup_client_callback();
341         let result = uwb_client_callback.onUciMessage(&data).await;
342         assert_eq!(result, Ok(()));
343         let response = rsp_receiver.recv().await;
344         assert!(matches!(
345             response,
346             Some(HalCallback::UciRsp(uci_hrcv::UciResponse::SessionDeinitRsp(_)))
347         ));
348     }
349 
350     #[tokio::test]
test_session_get_app_config_rsp()351     async fn test_session_get_app_config_rsp() {
352         let data = [0x41, 0x04, 0x00, 0x02, 0x01, 0x00];
353         let (mut rsp_receiver, uwb_client_callback) = setup_client_callback();
354         let result = uwb_client_callback.onUciMessage(&data).await;
355         assert_eq!(result, Ok(()));
356         let response = rsp_receiver.recv().await;
357         assert!(matches!(
358             response,
359             Some(HalCallback::UciRsp(uci_hrcv::UciResponse::SessionGetAppConfigRsp(_)))
360         ));
361     }
362 
363     #[tokio::test]
test_session_set_app_config_rsp()364     async fn test_session_set_app_config_rsp() {
365         let data = [0x41, 0x03, 0x00, 0x04, 0x01, 0x01, 0x01, 0x00];
366         let (mut rsp_receiver, uwb_client_callback) = setup_client_callback();
367         let result = uwb_client_callback.onUciMessage(&data).await;
368         assert_eq!(result, Ok(()));
369         let response = rsp_receiver.recv().await;
370         assert!(matches!(
371             response,
372             Some(HalCallback::UciRsp(uci_hrcv::UciResponse::SessionSetAppConfigRsp(_)))
373         ));
374     }
375 
376     #[tokio::test]
test_session_get_state_rsp()377     async fn test_session_get_state_rsp() {
378         let data = [0x41, 0x06, 0x00, 0x02, 0x00, 0x01];
379         let (mut rsp_receiver, uwb_client_callback) = setup_client_callback();
380         let result = uwb_client_callback.onUciMessage(&data).await;
381         assert_eq!(result, Ok(()));
382         let response = rsp_receiver.recv().await;
383         assert!(matches!(
384             response,
385             Some(HalCallback::UciRsp(uci_hrcv::UciResponse::SessionGetStateRsp(_)))
386         ));
387     }
388 
389     #[tokio::test]
test_session_get_count_rsp()390     async fn test_session_get_count_rsp() {
391         let data = [0x41, 0x05, 0x00, 0x02, 0x00, 0x01];
392         let (mut rsp_receiver, uwb_client_callback) = setup_client_callback();
393         let result = uwb_client_callback.onUciMessage(&data).await;
394         assert_eq!(result, Ok(()));
395         let response = rsp_receiver.recv().await;
396         assert!(matches!(
397             response,
398             Some(HalCallback::UciRsp(uci_hrcv::UciResponse::SessionGetCountRsp(_)))
399         ));
400     }
401 
402     #[tokio::test]
test_session_update_controller_multicast_list_rsp()403     async fn test_session_update_controller_multicast_list_rsp() {
404         let data = [0x41, 0x07, 0x00, 0x01, 0x00];
405         let (mut rsp_receiver, uwb_client_callback) = setup_client_callback();
406         let result = uwb_client_callback.onUciMessage(&data).await;
407         assert_eq!(result, Ok(()));
408         let response = rsp_receiver.recv().await;
409         assert!(matches!(
410             response,
411             Some(HalCallback::UciRsp(
412                 uci_hrcv::UciResponse::SessionUpdateControllerMulticastListRsp(_)
413             ))
414         ));
415     }
416 
417     #[tokio::test]
test_range_start_rsp()418     async fn test_range_start_rsp() {
419         let data = [0x42, 0x00, 0x00, 0x01, 0x00];
420         let (mut rsp_receiver, uwb_client_callback) = setup_client_callback();
421         let result = uwb_client_callback.onUciMessage(&data).await;
422         assert_eq!(result, Ok(()));
423         let response = rsp_receiver.recv().await;
424         assert!(matches!(
425             response,
426             Some(HalCallback::UciRsp(uci_hrcv::UciResponse::RangeStartRsp(_)))
427         ));
428     }
429 
430     #[tokio::test]
test_range_stop_rsp()431     async fn test_range_stop_rsp() {
432         let data = [0x42, 0x01, 0x00, 0x01, 0x00];
433         let (mut rsp_receiver, uwb_client_callback) = setup_client_callback();
434         let result = uwb_client_callback.onUciMessage(&data).await;
435         assert_eq!(result, Ok(()));
436         let response = rsp_receiver.recv().await;
437         assert!(matches!(
438             response,
439             Some(HalCallback::UciRsp(uci_hrcv::UciResponse::RangeStopRsp(_)))
440         ));
441     }
442 
443     #[tokio::test]
test_android_set_country_code_rsp()444     async fn test_android_set_country_code_rsp() {
445         let data = [0x4c, 0x01, 0x00, 0x01, 0x00];
446         let (mut rsp_receiver, uwb_client_callback) = setup_client_callback();
447         let result = uwb_client_callback.onUciMessage(&data).await;
448         assert_eq!(result, Ok(()));
449         let response = rsp_receiver.recv().await;
450         assert!(matches!(
451             response,
452             Some(HalCallback::UciRsp(uci_hrcv::UciResponse::AndroidSetCountryCodeRsp(_)))
453         ));
454     }
455 
456     #[tokio::test]
test_android_get_power_stats_rsp()457     async fn test_android_get_power_stats_rsp() {
458         let data = [
459             0x4c, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
460             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
461         ];
462         let (mut rsp_receiver, uwb_client_callback) = setup_client_callback();
463         let result = uwb_client_callback.onUciMessage(&data).await;
464         assert_eq!(result, Ok(()));
465         let response = rsp_receiver.recv().await;
466         assert!(matches!(
467             response,
468             Some(HalCallback::UciRsp(uci_hrcv::UciResponse::AndroidGetPowerStatsRsp(_)))
469         ));
470     }
471 
472     #[tokio::test]
test_raw_vendor_rsp_fragmented_packet()473     async fn test_raw_vendor_rsp_fragmented_packet() {
474         let fragment_1 = [
475             0x59, 0x01, 0x00, 0xff, 0x81, 0x93, 0xf8, 0x56, 0x53, 0x74, 0x5d, 0xcf, 0x45, 0xfa,
476             0x34, 0xbd, 0xf1, 0x56, 0x53, 0x8f, 0x13, 0xff, 0x9b, 0xdd, 0xee, 0xaf, 0x0e, 0xff,
477             0x1e, 0x63, 0xb6, 0xd7, 0xd4, 0x7b, 0xb7, 0x78, 0x30, 0xc7, 0x92, 0xd0, 0x8a, 0x5e,
478             0xf0, 0x00, 0x1d, 0x05, 0xea, 0xf9, 0x56, 0xce, 0x8b, 0xbc, 0x8b, 0x1b, 0xc2, 0xd4,
479             0x2a, 0xb8, 0x14, 0x82, 0x8b, 0xed, 0x12, 0xe5, 0x83, 0xe6, 0xb0, 0xb8, 0xa0, 0xb9,
480             0xd0, 0x90, 0x6e, 0x09, 0x4e, 0x2e, 0x22, 0x38, 0x39, 0x03, 0x66, 0xf5, 0x95, 0x14,
481             0x1c, 0xd7, 0x60, 0xbf, 0x28, 0x58, 0x9d, 0x47, 0x18, 0x1a, 0x93, 0x59, 0xbb, 0x0d,
482             0x88, 0xf7, 0x7c, 0xce, 0x13, 0xa8, 0x2f, 0x3d, 0x0e, 0xd9, 0x5c, 0x19, 0x45, 0x5d,
483             0xe8, 0xc3, 0xe0, 0x3a, 0xf3, 0x71, 0x09, 0x6e, 0x73, 0x07, 0x96, 0xa9, 0x1f, 0xf4,
484             0x57, 0x84, 0x2e, 0x59, 0x6a, 0xf6, 0x90, 0x28, 0x47, 0xc1, 0x51, 0x7c, 0x59, 0x7e,
485             0x95, 0xfc, 0xa6, 0x4d, 0x1b, 0xe6, 0xfe, 0x97, 0xa0, 0x39, 0x91, 0xa8, 0x28, 0xc9,
486             0x1d, 0x7e, 0xfc, 0xec, 0x71, 0x1d, 0x43, 0x38, 0xcb, 0xbd, 0x50, 0xea, 0x02, 0xfd,
487             0x2c, 0x7a, 0xde, 0x06, 0xdd, 0x77, 0x69, 0x4d, 0x2f, 0x57, 0xf5, 0x4b, 0x97, 0x51,
488             0x58, 0x66, 0x7a, 0x8a, 0xcb, 0x7b, 0x91, 0x18, 0xbe, 0x4e, 0x94, 0xe4, 0xf1, 0xed,
489             0x52, 0x06, 0xa7, 0xe8, 0x6b, 0xe1, 0x8f, 0x4a, 0x06, 0xe8, 0x2c, 0x9f, 0xc7, 0xcb,
490             0xd2, 0x10, 0xb0, 0x0b, 0x71, 0x80, 0x2c, 0xd1, 0xf1, 0x03, 0xc2, 0x79, 0x7e, 0x7f,
491             0x70, 0xf4, 0x8c, 0xc9, 0xcf, 0x9f, 0xcf, 0xa2, 0x8e, 0x6a, 0xe4, 0x1a, 0x28, 0x05,
492             0xa8, 0xfe, 0x7d, 0xec, 0xd9, 0x5f, 0xa7, 0xd0, 0x29, 0x63, 0x1a, 0xba, 0x39, 0xf7,
493             0xfa, 0x5e, 0xff, 0xb8, 0x5a, 0xbd, 0x35,
494         ];
495         let fragment_2 = [
496             0x49, 0x01, 0x00, 0x91, 0xe7, 0x26, 0xfb, 0xc4, 0x48, 0x68, 0x42, 0x93, 0x23, 0x1f,
497             0x87, 0xf6, 0x12, 0x5e, 0x60, 0xc8, 0x6a, 0x9d, 0x98, 0xbb, 0xb2, 0xb0, 0x47, 0x2f,
498             0xaa, 0xa5, 0xce, 0xdb, 0x32, 0x88, 0x86, 0x0d, 0x6a, 0x5a, 0xfe, 0xc8, 0xda, 0xa1,
499             0xc0, 0x06, 0x37, 0x08, 0xda, 0x67, 0x49, 0x6a, 0xa7, 0x04, 0x62, 0x95, 0xf3, 0x1e,
500             0xcd, 0x71, 0x00, 0x99, 0x68, 0xb4, 0x03, 0xb3, 0x15, 0x64, 0x8b, 0xde, 0xbc, 0x8f,
501             0x41, 0x64, 0xdf, 0x34, 0x6e, 0xff, 0x48, 0xc8, 0xe2, 0xbf, 0x02, 0x15, 0xc5, 0xbc,
502             0x0f, 0xf8, 0xa1, 0x49, 0x91, 0x71, 0xdd, 0xb4, 0x37, 0x1c, 0xfa, 0x60, 0xcb, 0x0f,
503             0xce, 0x6a, 0x0e, 0x90, 0xaf, 0x14, 0x30, 0xf2, 0x5b, 0x21, 0x6f, 0x85, 0xd3, 0x1b,
504             0x89, 0xc9, 0xba, 0x3f, 0x07, 0x11, 0xbd, 0x56, 0xda, 0xdc, 0x88, 0xb4, 0xb0, 0x57,
505             0x0b, 0x0c, 0x44, 0xd9, 0xb9, 0xd2, 0x38, 0x4c, 0xb6, 0xff, 0x83, 0xfe, 0xc8, 0x65,
506             0xbc, 0x2a, 0x10, 0xed, 0x18, 0x62, 0xd2, 0x1b, 0x87,
507         ];
508         let (mut rsp_receiver, uwb_client_callback) = setup_client_callback();
509         let result1 = uwb_client_callback.onUciMessage(&fragment_1).await;
510         assert_eq!(result1, Ok(()));
511         let result2 = uwb_client_callback.onUciMessage(&fragment_2).await;
512         assert_eq!(result2, Ok(()));
513         // One defragmented packet sent as response
514         let response = rsp_receiver.recv().await;
515         assert!(matches!(
516             response,
517             Some(HalCallback::UciRsp(uci_hrcv::UciResponse::RawVendorRsp(_)))
518         ));
519     }
520 
521     #[tokio::test]
test_generic_error_ntf()522     async fn test_generic_error_ntf() {
523         let data = [0x60, 0x07, 0x00, 0x01, 0x01];
524         let (mut rsp_receiver, uwb_client_callback) = setup_client_callback();
525         let result = uwb_client_callback.onUciMessage(&data).await;
526         assert_eq!(result, Ok(()));
527         let response = rsp_receiver.recv().await;
528         assert!(matches!(
529             response,
530             Some(HalCallback::UciNtf(uci_hrcv::UciNotification::GenericError(_)))
531         ));
532     }
533 
534     #[tokio::test]
test_device_status_ntf()535     async fn test_device_status_ntf() {
536         let data = [0x60, 0x01, 0x00, 0x01, 0x01];
537         let (mut rsp_receiver, uwb_client_callback) = setup_client_callback();
538         let result = uwb_client_callback.onUciMessage(&data).await;
539         assert_eq!(result, Ok(()));
540         let response = rsp_receiver.recv().await;
541         assert!(matches!(
542             response,
543             Some(HalCallback::UciNtf(uci_hrcv::UciNotification::DeviceStatusNtf(_)))
544         ));
545     }
546 
547     #[tokio::test]
test_session_status_ntf()548     async fn test_session_status_ntf() {
549         let data = [0x61, 0x02, 0x00, 0x06, 0x01, 0x02, 0x03, 0x04, 0x02, 0x21];
550         let (mut rsp_receiver, uwb_client_callback) = setup_client_callback();
551         let result = uwb_client_callback.onUciMessage(&data).await;
552         assert_eq!(result, Ok(()));
553         let response = rsp_receiver.recv().await;
554         assert!(matches!(
555             response,
556             Some(HalCallback::UciNtf(uci_hrcv::UciNotification::SessionStatusNtf(_)))
557         ));
558     }
559 
560     #[tokio::test]
test_session_update_controller_multicast_list_ntf()561     async fn test_session_update_controller_multicast_list_ntf() {
562         let data = [0x61, 0x07, 0x00, 0x06, 0x00, 0x01, 0x02, 0x03, 0x04, 0x00];
563         let (mut rsp_receiver, uwb_client_callback) = setup_client_callback();
564         let result = uwb_client_callback.onUciMessage(&data).await;
565         assert_eq!(result, Ok(()));
566         let response = rsp_receiver.recv().await;
567         assert!(matches!(
568             response,
569             Some(HalCallback::UciNtf(
570                 uci_hrcv::UciNotification::SessionUpdateControllerMulticastListNtf(_)
571             ))
572         ));
573     }
574 
575     #[tokio::test]
test_short_mac_two_way_range_data_ntf()576     async fn test_short_mac_two_way_range_data_ntf() {
577         let data = [
578             0x62, 0x00, 0x00, 0x19, 0x00, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00, 0x0a,
579             0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
580             0x00,
581         ];
582         let (mut rsp_receiver, uwb_client_callback) = setup_client_callback();
583         let result = uwb_client_callback.onUciMessage(&data).await;
584         assert_eq!(result, Ok(()));
585         let response = rsp_receiver.recv().await;
586         assert!(matches!(
587             response,
588             Some(HalCallback::UciNtf(uci_hrcv::UciNotification::ShortMacTwoWayRangeDataNtf(_)))
589         ));
590     }
591 
592     #[tokio::test]
test_extended_mac_two_way_range_data_ntf()593     async fn test_extended_mac_two_way_range_data_ntf() {
594         let data = [
595             0x62, 0x00, 0x00, 0x19, 0x00, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00, 0x0a,
596             0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
597             0x00,
598         ];
599         let (mut rsp_receiver, uwb_client_callback) = setup_client_callback();
600         let result = uwb_client_callback.onUciMessage(&data).await;
601         assert_eq!(result, Ok(()));
602         let response = rsp_receiver.recv().await;
603         assert!(matches!(
604             response,
605             Some(HalCallback::UciNtf(uci_hrcv::UciNotification::ExtendedMacTwoWayRangeDataNtf(_)))
606         ));
607     }
608 
609     #[tokio::test]
test_raw_vendor_ntf_fragmented_packet()610     async fn test_raw_vendor_ntf_fragmented_packet() {
611         let fragment_1 = [
612             0x79, 0x01, 0x00, 0xff, 0x81, 0x93, 0xf8, 0x56, 0x53, 0x74, 0x5d, 0xcf, 0x45, 0xfa,
613             0x34, 0xbd, 0xf1, 0x56, 0x53, 0x8f, 0x13, 0xff, 0x9b, 0xdd, 0xee, 0xaf, 0x0e, 0xff,
614             0x1e, 0x63, 0xb6, 0xd7, 0xd4, 0x7b, 0xb7, 0x78, 0x30, 0xc7, 0x92, 0xd0, 0x8a, 0x5e,
615             0xf0, 0x00, 0x1d, 0x05, 0xea, 0xf9, 0x56, 0xce, 0x8b, 0xbc, 0x8b, 0x1b, 0xc2, 0xd4,
616             0x2a, 0xb8, 0x14, 0x82, 0x8b, 0xed, 0x12, 0xe5, 0x83, 0xe6, 0xb0, 0xb8, 0xa0, 0xb9,
617             0xd0, 0x90, 0x6e, 0x09, 0x4e, 0x2e, 0x22, 0x38, 0x39, 0x03, 0x66, 0xf5, 0x95, 0x14,
618             0x1c, 0xd7, 0x60, 0xbf, 0x28, 0x58, 0x9d, 0x47, 0x18, 0x1a, 0x93, 0x59, 0xbb, 0x0d,
619             0x88, 0xf7, 0x7c, 0xce, 0x13, 0xa8, 0x2f, 0x3d, 0x0e, 0xd9, 0x5c, 0x19, 0x45, 0x5d,
620             0xe8, 0xc3, 0xe0, 0x3a, 0xf3, 0x71, 0x09, 0x6e, 0x73, 0x07, 0x96, 0xa9, 0x1f, 0xf4,
621             0x57, 0x84, 0x2e, 0x59, 0x6a, 0xf6, 0x90, 0x28, 0x47, 0xc1, 0x51, 0x7c, 0x59, 0x7e,
622             0x95, 0xfc, 0xa6, 0x4d, 0x1b, 0xe6, 0xfe, 0x97, 0xa0, 0x39, 0x91, 0xa8, 0x28, 0xc9,
623             0x1d, 0x7e, 0xfc, 0xec, 0x71, 0x1d, 0x43, 0x38, 0xcb, 0xbd, 0x50, 0xea, 0x02, 0xfd,
624             0x2c, 0x7a, 0xde, 0x06, 0xdd, 0x77, 0x69, 0x4d, 0x2f, 0x57, 0xf5, 0x4b, 0x97, 0x51,
625             0x58, 0x66, 0x7a, 0x8a, 0xcb, 0x7b, 0x91, 0x18, 0xbe, 0x4e, 0x94, 0xe4, 0xf1, 0xed,
626             0x52, 0x06, 0xa7, 0xe8, 0x6b, 0xe1, 0x8f, 0x4a, 0x06, 0xe8, 0x2c, 0x9f, 0xc7, 0xcb,
627             0xd2, 0x10, 0xb0, 0x0b, 0x71, 0x80, 0x2c, 0xd1, 0xf1, 0x03, 0xc2, 0x79, 0x7e, 0x7f,
628             0x70, 0xf4, 0x8c, 0xc9, 0xcf, 0x9f, 0xcf, 0xa2, 0x8e, 0x6a, 0xe4, 0x1a, 0x28, 0x05,
629             0xa8, 0xfe, 0x7d, 0xec, 0xd9, 0x5f, 0xa7, 0xd0, 0x29, 0x63, 0x1a, 0xba, 0x39, 0xf7,
630             0xfa, 0x5e, 0xff, 0xb8, 0x5a, 0xbd, 0x35,
631         ];
632         let fragment_2 = [
633             0x69, 0x01, 0x00, 0x91, 0xe7, 0x26, 0xfb, 0xc4, 0x48, 0x68, 0x42, 0x93, 0x23, 0x1f,
634             0x87, 0xf6, 0x12, 0x5e, 0x60, 0xc8, 0x6a, 0x9d, 0x98, 0xbb, 0xb2, 0xb0, 0x47, 0x2f,
635             0xaa, 0xa5, 0xce, 0xdb, 0x32, 0x88, 0x86, 0x0d, 0x6a, 0x5a, 0xfe, 0xc8, 0xda, 0xa1,
636             0xc0, 0x06, 0x37, 0x08, 0xda, 0x67, 0x49, 0x6a, 0xa7, 0x04, 0x62, 0x95, 0xf3, 0x1e,
637             0xcd, 0x71, 0x00, 0x99, 0x68, 0xb4, 0x03, 0xb3, 0x15, 0x64, 0x8b, 0xde, 0xbc, 0x8f,
638             0x41, 0x64, 0xdf, 0x34, 0x6e, 0xff, 0x48, 0xc8, 0xe2, 0xbf, 0x02, 0x15, 0xc5, 0xbc,
639             0x0f, 0xf8, 0xa1, 0x49, 0x91, 0x71, 0xdd, 0xb4, 0x37, 0x1c, 0xfa, 0x60, 0xcb, 0x0f,
640             0xce, 0x6a, 0x0e, 0x90, 0xaf, 0x14, 0x30, 0xf2, 0x5b, 0x21, 0x6f, 0x85, 0xd3, 0x1b,
641             0x89, 0xc9, 0xba, 0x3f, 0x07, 0x11, 0xbd, 0x56, 0xda, 0xdc, 0x88, 0xb4, 0xb0, 0x57,
642             0x0b, 0x0c, 0x44, 0xd9, 0xb9, 0xd2, 0x38, 0x4c, 0xb6, 0xff, 0x83, 0xfe, 0xc8, 0x65,
643             0xbc, 0x2a, 0x10, 0xed, 0x18, 0x62, 0xd2, 0x1b, 0x87,
644         ];
645         let (mut rsp_receiver, uwb_client_callback) = setup_client_callback();
646         let result1 = uwb_client_callback.onUciMessage(&fragment_1).await;
647         assert_eq!(result1, Ok(()));
648         let result2 = uwb_client_callback.onUciMessage(&fragment_2).await;
649         assert_eq!(result2, Ok(()));
650         // One defragmented packet sent as response
651         let response = rsp_receiver.recv().await;
652         assert!(matches!(
653             response,
654             Some(HalCallback::UciNtf(uci_hrcv::UciNotification::RawVendorNtf(_)))
655         ));
656     }
657 
658     #[tokio::test]
test_on_uci_message_bad()659     async fn test_on_uci_message_bad() {
660         let data = [
661             0x42, 0x02, 0x00, 0x0b, 0x01, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x01,
662             0x0a,
663         ];
664         let (mut rsp_receiver, uwb_client_callback) = setup_client_callback();
665         let result = uwb_client_callback.onUciMessage(&data).await;
666         assert_eq!(result, Ok(()));
667         let response = rsp_receiver.try_recv();
668         assert!(response.is_err());
669     }
670 
setup_adaptation_impl(config_fn: impl Fn(&MockHal)) -> Result<UwbAdaptationImpl>671     async fn setup_adaptation_impl(config_fn: impl Fn(&MockHal)) -> Result<UwbAdaptationImpl> {
672         // TODO: Remove this once we call it somewhere real.
673         logger::init(
674             logger::Config::default()
675                 .with_tag_on_device("uwb_test")
676                 .with_min_level(log::Level::Debug),
677         );
678         let (rsp_sender, _) = mpsc::unbounded_channel::<HalCallback>();
679         let mock_hal = MockHal::new();
680         config_fn(&mock_hal);
681 
682         UwbAdaptationImpl::new_with_args(
683             rsp_sender,
684             binder::Strong::new(Box::new(mock_hal)),
685             Arc::new(Mutex::new(DeathRecipient::new(|| {}))),
686         )
687         .await
688     }
689 
690     #[tokio::test]
test_send_uci_message()691     async fn test_send_uci_message() {
692         let cmd: UciCommandPacket = GetDeviceInfoCmdBuilder {}.build().into();
693         let adaptation_impl = setup_adaptation_impl(|mock_hal| {
694             let cmd_packet: UciPacketPacket = cmd.clone().into();
695             let mut cmd_frag_packets: Vec<UciPacketHalPacket> = cmd_packet.into();
696             let cmd_frag_data = cmd_frag_packets.pop().unwrap().to_vec();
697             let cmd_frag_data_len = cmd_frag_data.len();
698             mock_hal
699                 .expect_send_uci_message(cmd_frag_data, Ok(cmd_frag_data_len.try_into().unwrap()));
700         })
701         .await
702         .unwrap();
703         adaptation_impl.send_uci_message(cmd).await.unwrap();
704     }
705 
706     #[tokio::test]
test_send_uci_message_fragmented_packet()707     async fn test_send_uci_message_fragmented_packet() {
708         let (rsp_sender, _) = mpsc::unbounded_channel::<HalCallback>();
709         let mock_hal = MockHal::new();
710 
711         let cmd_payload: [u8; 400] = [
712             0x81, 0x93, 0xf8, 0x56, 0x53, 0x74, 0x5d, 0xcf, 0x45, 0xfa, 0x34, 0xbd, 0xf1, 0x56,
713             0x53, 0x8f, 0x13, 0xff, 0x9b, 0xdd, 0xee, 0xaf, 0x0e, 0xff, 0x1e, 0x63, 0xb6, 0xd7,
714             0xd4, 0x7b, 0xb7, 0x78, 0x30, 0xc7, 0x92, 0xd0, 0x8a, 0x5e, 0xf0, 0x00, 0x1d, 0x05,
715             0xea, 0xf9, 0x56, 0xce, 0x8b, 0xbc, 0x8b, 0x1b, 0xc2, 0xd4, 0x2a, 0xb8, 0x14, 0x82,
716             0x8b, 0xed, 0x12, 0xe5, 0x83, 0xe6, 0xb0, 0xb8, 0xa0, 0xb9, 0xd0, 0x90, 0x6e, 0x09,
717             0x4e, 0x2e, 0x22, 0x38, 0x39, 0x03, 0x66, 0xf5, 0x95, 0x14, 0x1c, 0xd7, 0x60, 0xbf,
718             0x28, 0x58, 0x9d, 0x47, 0x18, 0x1a, 0x93, 0x59, 0xbb, 0x0d, 0x88, 0xf7, 0x7c, 0xce,
719             0x13, 0xa8, 0x2f, 0x3d, 0x0e, 0xd9, 0x5c, 0x19, 0x45, 0x5d, 0xe8, 0xc3, 0xe0, 0x3a,
720             0xf3, 0x71, 0x09, 0x6e, 0x73, 0x07, 0x96, 0xa9, 0x1f, 0xf4, 0x57, 0x84, 0x2e, 0x59,
721             0x6a, 0xf6, 0x90, 0x28, 0x47, 0xc1, 0x51, 0x7c, 0x59, 0x7e, 0x95, 0xfc, 0xa6, 0x4d,
722             0x1b, 0xe6, 0xfe, 0x97, 0xa0, 0x39, 0x91, 0xa8, 0x28, 0xc9, 0x1d, 0x7e, 0xfc, 0xec,
723             0x71, 0x1d, 0x43, 0x38, 0xcb, 0xbd, 0x50, 0xea, 0x02, 0xfd, 0x2c, 0x7a, 0xde, 0x06,
724             0xdd, 0x77, 0x69, 0x4d, 0x2f, 0x57, 0xf5, 0x4b, 0x97, 0x51, 0x58, 0x66, 0x7a, 0x8a,
725             0xcb, 0x7b, 0x91, 0x18, 0xbe, 0x4e, 0x94, 0xe4, 0xf1, 0xed, 0x52, 0x06, 0xa7, 0xe8,
726             0x6b, 0xe1, 0x8f, 0x4a, 0x06, 0xe8, 0x2c, 0x9f, 0xc7, 0xcb, 0xd2, 0x10, 0xb0, 0x0b,
727             0x71, 0x80, 0x2c, 0xd1, 0xf1, 0x03, 0xc2, 0x79, 0x7e, 0x7f, 0x70, 0xf4, 0x8c, 0xc9,
728             0xcf, 0x9f, 0xcf, 0xa2, 0x8e, 0x6a, 0xe4, 0x1a, 0x28, 0x05, 0xa8, 0xfe, 0x7d, 0xec,
729             0xd9, 0x5f, 0xa7, 0xd0, 0x29, 0x63, 0x1a, 0xba, 0x39, 0xf7, 0xfa, 0x5e, 0xff, 0xb8,
730             0x5a, 0xbd, 0x35, 0xe7, 0x26, 0xfb, 0xc4, 0x48, 0x68, 0x42, 0x93, 0x23, 0x1f, 0x87,
731             0xf6, 0x12, 0x5e, 0x60, 0xc8, 0x6a, 0x9d, 0x98, 0xbb, 0xb2, 0xb0, 0x47, 0x2f, 0xaa,
732             0xa5, 0xce, 0xdb, 0x32, 0x88, 0x86, 0x0d, 0x6a, 0x5a, 0xfe, 0xc8, 0xda, 0xa1, 0xc0,
733             0x06, 0x37, 0x08, 0xda, 0x67, 0x49, 0x6a, 0xa7, 0x04, 0x62, 0x95, 0xf3, 0x1e, 0xcd,
734             0x71, 0x00, 0x99, 0x68, 0xb4, 0x03, 0xb3, 0x15, 0x64, 0x8b, 0xde, 0xbc, 0x8f, 0x41,
735             0x64, 0xdf, 0x34, 0x6e, 0xff, 0x48, 0xc8, 0xe2, 0xbf, 0x02, 0x15, 0xc5, 0xbc, 0x0f,
736             0xf8, 0xa1, 0x49, 0x91, 0x71, 0xdd, 0xb4, 0x37, 0x1c, 0xfa, 0x60, 0xcb, 0x0f, 0xce,
737             0x6a, 0x0e, 0x90, 0xaf, 0x14, 0x30, 0xf2, 0x5b, 0x21, 0x6f, 0x85, 0xd3, 0x1b, 0x89,
738             0xc9, 0xba, 0x3f, 0x07, 0x11, 0xbd, 0x56, 0xda, 0xdc, 0x88, 0xb4, 0xb0, 0x57, 0x0b,
739             0x0c, 0x44, 0xd9, 0xb9, 0xd2, 0x38, 0x4c, 0xb6, 0xff, 0x83, 0xfe, 0xc8, 0x65, 0xbc,
740             0x2a, 0x10, 0xed, 0x18, 0x62, 0xd2, 0x1b, 0x87,
741         ];
742         let cmd: UciCommandPacket = UciVendor_9_CommandBuilder {
743             opcode: 1,
744             payload: Some(Bytes::from(cmd_payload.to_vec())),
745         }
746         .build()
747         .into();
748 
749         let cmd_frag_data_1 = [
750             0x39, 0x01, 0x00, 0xff, 0x81, 0x93, 0xf8, 0x56, 0x53, 0x74, 0x5d, 0xcf, 0x45, 0xfa,
751             0x34, 0xbd, 0xf1, 0x56, 0x53, 0x8f, 0x13, 0xff, 0x9b, 0xdd, 0xee, 0xaf, 0x0e, 0xff,
752             0x1e, 0x63, 0xb6, 0xd7, 0xd4, 0x7b, 0xb7, 0x78, 0x30, 0xc7, 0x92, 0xd0, 0x8a, 0x5e,
753             0xf0, 0x00, 0x1d, 0x05, 0xea, 0xf9, 0x56, 0xce, 0x8b, 0xbc, 0x8b, 0x1b, 0xc2, 0xd4,
754             0x2a, 0xb8, 0x14, 0x82, 0x8b, 0xed, 0x12, 0xe5, 0x83, 0xe6, 0xb0, 0xb8, 0xa0, 0xb9,
755             0xd0, 0x90, 0x6e, 0x09, 0x4e, 0x2e, 0x22, 0x38, 0x39, 0x03, 0x66, 0xf5, 0x95, 0x14,
756             0x1c, 0xd7, 0x60, 0xbf, 0x28, 0x58, 0x9d, 0x47, 0x18, 0x1a, 0x93, 0x59, 0xbb, 0x0d,
757             0x88, 0xf7, 0x7c, 0xce, 0x13, 0xa8, 0x2f, 0x3d, 0x0e, 0xd9, 0x5c, 0x19, 0x45, 0x5d,
758             0xe8, 0xc3, 0xe0, 0x3a, 0xf3, 0x71, 0x09, 0x6e, 0x73, 0x07, 0x96, 0xa9, 0x1f, 0xf4,
759             0x57, 0x84, 0x2e, 0x59, 0x6a, 0xf6, 0x90, 0x28, 0x47, 0xc1, 0x51, 0x7c, 0x59, 0x7e,
760             0x95, 0xfc, 0xa6, 0x4d, 0x1b, 0xe6, 0xfe, 0x97, 0xa0, 0x39, 0x91, 0xa8, 0x28, 0xc9,
761             0x1d, 0x7e, 0xfc, 0xec, 0x71, 0x1d, 0x43, 0x38, 0xcb, 0xbd, 0x50, 0xea, 0x02, 0xfd,
762             0x2c, 0x7a, 0xde, 0x06, 0xdd, 0x77, 0x69, 0x4d, 0x2f, 0x57, 0xf5, 0x4b, 0x97, 0x51,
763             0x58, 0x66, 0x7a, 0x8a, 0xcb, 0x7b, 0x91, 0x18, 0xbe, 0x4e, 0x94, 0xe4, 0xf1, 0xed,
764             0x52, 0x06, 0xa7, 0xe8, 0x6b, 0xe1, 0x8f, 0x4a, 0x06, 0xe8, 0x2c, 0x9f, 0xc7, 0xcb,
765             0xd2, 0x10, 0xb0, 0x0b, 0x71, 0x80, 0x2c, 0xd1, 0xf1, 0x03, 0xc2, 0x79, 0x7e, 0x7f,
766             0x70, 0xf4, 0x8c, 0xc9, 0xcf, 0x9f, 0xcf, 0xa2, 0x8e, 0x6a, 0xe4, 0x1a, 0x28, 0x05,
767             0xa8, 0xfe, 0x7d, 0xec, 0xd9, 0x5f, 0xa7, 0xd0, 0x29, 0x63, 0x1a, 0xba, 0x39, 0xf7,
768             0xfa, 0x5e, 0xff, 0xb8, 0x5a, 0xbd, 0x35,
769         ];
770         let cmd_frag_data_len_1 = cmd_frag_data_1.len();
771 
772         let cmd_frag_data_2 = [
773             0x29, 0x01, 0x00, 0x91, 0xe7, 0x26, 0xfb, 0xc4, 0x48, 0x68, 0x42, 0x93, 0x23, 0x1f,
774             0x87, 0xf6, 0x12, 0x5e, 0x60, 0xc8, 0x6a, 0x9d, 0x98, 0xbb, 0xb2, 0xb0, 0x47, 0x2f,
775             0xaa, 0xa5, 0xce, 0xdb, 0x32, 0x88, 0x86, 0x0d, 0x6a, 0x5a, 0xfe, 0xc8, 0xda, 0xa1,
776             0xc0, 0x06, 0x37, 0x08, 0xda, 0x67, 0x49, 0x6a, 0xa7, 0x04, 0x62, 0x95, 0xf3, 0x1e,
777             0xcd, 0x71, 0x00, 0x99, 0x68, 0xb4, 0x03, 0xb3, 0x15, 0x64, 0x8b, 0xde, 0xbc, 0x8f,
778             0x41, 0x64, 0xdf, 0x34, 0x6e, 0xff, 0x48, 0xc8, 0xe2, 0xbf, 0x02, 0x15, 0xc5, 0xbc,
779             0x0f, 0xf8, 0xa1, 0x49, 0x91, 0x71, 0xdd, 0xb4, 0x37, 0x1c, 0xfa, 0x60, 0xcb, 0x0f,
780             0xce, 0x6a, 0x0e, 0x90, 0xaf, 0x14, 0x30, 0xf2, 0x5b, 0x21, 0x6f, 0x85, 0xd3, 0x1b,
781             0x89, 0xc9, 0xba, 0x3f, 0x07, 0x11, 0xbd, 0x56, 0xda, 0xdc, 0x88, 0xb4, 0xb0, 0x57,
782             0x0b, 0x0c, 0x44, 0xd9, 0xb9, 0xd2, 0x38, 0x4c, 0xb6, 0xff, 0x83, 0xfe, 0xc8, 0x65,
783             0xbc, 0x2a, 0x10, 0xed, 0x18, 0x62, 0xd2, 0x1b, 0x87,
784         ];
785         let cmd_frag_data_len_2 = cmd_frag_data_2.len();
786 
787         mock_hal.expect_send_uci_message(
788             cmd_frag_data_1.to_vec(),
789             Ok(cmd_frag_data_len_1.try_into().unwrap()),
790         );
791         mock_hal.expect_send_uci_message(
792             cmd_frag_data_2.to_vec(),
793             Ok(cmd_frag_data_len_2.try_into().unwrap()),
794         );
795         let adaptation_impl = UwbAdaptationImpl::new_with_args(
796             rsp_sender,
797             binder::Strong::new(Box::new(mock_hal)),
798             Arc::new(Mutex::new(DeathRecipient::new(|| {}))),
799         )
800         .await
801         .unwrap();
802         adaptation_impl.send_uci_message(cmd).await.unwrap();
803     }
804 }
805