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