1 // Copyright 2022, The Android Open Source Project 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 //! Implementation of NotificationManagerAndroid and its builder. 16 17 use crate::jclass_name::{ 18 MULTICAST_LIST_UPDATE_STATUS_CLASS, UWB_DL_TDOA_MEASUREMENT_CLASS, 19 UWB_OWR_AOA_MEASUREMENT_CLASS, UWB_RADAR_DATA_CLASS, UWB_RADAR_SWEEP_DATA_CLASS, 20 UWB_RANGING_DATA_CLASS, UWB_TWO_WAY_MEASUREMENT_CLASS, 21 }; 22 23 use std::collections::HashMap; 24 use std::sync::Arc; 25 26 use jni::errors::Error as JNIError; 27 use jni::objects::{GlobalRef, JClass, JMethodID, JObject, JValue}; 28 use jni::signature::TypeSignature; 29 use jni::sys::jvalue; 30 use jni::{AttachGuard, JavaVM}; 31 use log::{debug, error}; 32 use uwb_core::error::{Error as UwbError, Result as UwbResult}; 33 use uwb_core::params::{ControleeStatusList, UwbAddress}; 34 use uwb_core::uci::uci_manager_sync::{NotificationManager, NotificationManagerBuilder}; 35 use uwb_core::uci::{ 36 CoreNotification, DataRcvNotification, RadarDataRcvNotification, RangingMeasurements, 37 SessionNotification, SessionRangeData, 38 }; 39 use uwb_uci_packets::{ 40 radar_bytes_per_sample_value, ExtendedAddressDlTdoaRangingMeasurement, 41 ExtendedAddressOwrAoaRangingMeasurement, ExtendedAddressTwoWayRangingMeasurement, 42 MacAddressIndicator, RangingMeasurementType, SessionState, 43 ShortAddressDlTdoaRangingMeasurement, ShortAddressOwrAoaRangingMeasurement, 44 ShortAddressTwoWayRangingMeasurement, StatusCode, 45 }; 46 47 // Byte size of mac address length: 48 const SHORT_MAC_ADDRESS_LEN: i32 = 2; 49 const EXTENDED_MAC_ADDRESS_LEN: i32 = 8; 50 const MAX_ANCHOR_LOCATION_LEN: i32 = 12; 51 const MAX_RANGING_ROUNDS_LEN: i32 = 16; 52 const MAX_RADAR_VENDOR_DATA_LEN: i32 = 256; 53 54 // Maximum allowed number of Java Object to be allocated inside with_local_frame 55 const MAX_JAVA_OBJECTS_CAPACITY: i32 = 50; 56 57 #[derive(Debug, PartialEq)] 58 enum MacAddress { 59 Short(u16), 60 Extended(u64), 61 } 62 impl MacAddress { into_ne_bytes(self) -> Vec<u8>63 fn into_ne_bytes(self) -> Vec<u8> { 64 match self { 65 MacAddress::Short(val) => val.to_ne_bytes().into(), 66 MacAddress::Extended(val) => val.to_ne_bytes().into(), 67 } 68 } 69 } 70 71 struct TwoWayRangingMeasurement { 72 mac_address: MacAddress, 73 status: StatusCode, 74 nlos: u8, 75 distance: u16, 76 aoa_azimuth: u16, 77 aoa_azimuth_fom: u8, 78 aoa_elevation: u16, 79 aoa_elevation_fom: u8, 80 aoa_destination_azimuth: u16, 81 aoa_destination_azimuth_fom: u8, 82 aoa_destination_elevation: u16, 83 aoa_destination_elevation_fom: u8, 84 slot_index: u8, 85 rssi: u8, 86 } 87 88 struct OwrAoaRangingMeasurement { 89 mac_address: MacAddress, 90 status: StatusCode, 91 nlos: u8, 92 frame_sequence_number: u8, 93 block_index: u16, 94 aoa_azimuth: u16, 95 aoa_azimuth_fom: u8, 96 aoa_elevation: u16, 97 aoa_elevation_fom: u8, 98 } 99 100 impl From<ShortAddressTwoWayRangingMeasurement> for TwoWayRangingMeasurement { from(measurement: ShortAddressTwoWayRangingMeasurement) -> Self101 fn from(measurement: ShortAddressTwoWayRangingMeasurement) -> Self { 102 TwoWayRangingMeasurement { 103 mac_address: MacAddress::Short(measurement.mac_address), 104 status: (measurement.status), 105 nlos: (measurement.nlos), 106 distance: (measurement.distance), 107 aoa_azimuth: (measurement.aoa_azimuth), 108 aoa_azimuth_fom: (measurement.aoa_azimuth_fom), 109 aoa_elevation: (measurement.aoa_elevation), 110 aoa_elevation_fom: (measurement.aoa_elevation_fom), 111 aoa_destination_azimuth: (measurement.aoa_destination_azimuth), 112 aoa_destination_azimuth_fom: (measurement.aoa_destination_azimuth_fom), 113 aoa_destination_elevation: (measurement.aoa_destination_elevation), 114 aoa_destination_elevation_fom: (measurement.aoa_destination_elevation_fom), 115 slot_index: (measurement.slot_index), 116 rssi: (measurement.rssi), 117 } 118 } 119 } 120 121 impl From<ExtendedAddressTwoWayRangingMeasurement> for TwoWayRangingMeasurement { from(measurement: ExtendedAddressTwoWayRangingMeasurement) -> Self122 fn from(measurement: ExtendedAddressTwoWayRangingMeasurement) -> Self { 123 TwoWayRangingMeasurement { 124 mac_address: MacAddress::Extended(measurement.mac_address), 125 status: (measurement.status), 126 nlos: (measurement.nlos), 127 distance: (measurement.distance), 128 aoa_azimuth: (measurement.aoa_azimuth), 129 aoa_azimuth_fom: (measurement.aoa_azimuth_fom), 130 aoa_elevation: (measurement.aoa_elevation), 131 aoa_elevation_fom: (measurement.aoa_elevation_fom), 132 aoa_destination_azimuth: (measurement.aoa_destination_azimuth), 133 aoa_destination_azimuth_fom: (measurement.aoa_destination_azimuth_fom), 134 aoa_destination_elevation: (measurement.aoa_destination_elevation), 135 aoa_destination_elevation_fom: (measurement.aoa_destination_elevation_fom), 136 slot_index: (measurement.slot_index), 137 rssi: (measurement.rssi), 138 } 139 } 140 } 141 142 impl From<ShortAddressOwrAoaRangingMeasurement> for OwrAoaRangingMeasurement { from(measurement: ShortAddressOwrAoaRangingMeasurement) -> Self143 fn from(measurement: ShortAddressOwrAoaRangingMeasurement) -> Self { 144 OwrAoaRangingMeasurement { 145 mac_address: MacAddress::Short(measurement.mac_address), 146 status: (measurement.status), 147 nlos: (measurement.nlos), 148 frame_sequence_number: (measurement.frame_sequence_number), 149 block_index: (measurement.block_index), 150 aoa_azimuth: (measurement.aoa_azimuth), 151 aoa_azimuth_fom: (measurement.aoa_azimuth_fom), 152 aoa_elevation: (measurement.aoa_elevation), 153 aoa_elevation_fom: (measurement.aoa_elevation_fom), 154 } 155 } 156 } 157 158 impl From<ExtendedAddressOwrAoaRangingMeasurement> for OwrAoaRangingMeasurement { from(measurement: ExtendedAddressOwrAoaRangingMeasurement) -> Self159 fn from(measurement: ExtendedAddressOwrAoaRangingMeasurement) -> Self { 160 OwrAoaRangingMeasurement { 161 mac_address: MacAddress::Extended(measurement.mac_address), 162 status: (measurement.status), 163 nlos: (measurement.nlos), 164 frame_sequence_number: (measurement.frame_sequence_number), 165 block_index: (measurement.block_index), 166 aoa_azimuth: (measurement.aoa_azimuth), 167 aoa_azimuth_fom: (measurement.aoa_azimuth_fom), 168 aoa_elevation: (measurement.aoa_elevation), 169 aoa_elevation_fom: (measurement.aoa_elevation_fom), 170 } 171 } 172 } 173 174 struct DlTdoaRangingMeasurement { 175 mac_address: MacAddress, 176 pub status: u8, 177 pub message_type: u8, 178 pub message_control: u16, 179 pub block_index: u16, 180 pub round_index: u8, 181 pub nlos: u8, 182 pub aoa_azimuth: u16, 183 pub aoa_azimuth_fom: u8, 184 pub aoa_elevation: u16, 185 pub aoa_elevation_fom: u8, 186 pub rssi: u8, 187 pub tx_timestamp: u64, 188 pub rx_timestamp: u64, 189 pub anchor_cfo: u16, 190 pub cfo: u16, 191 pub initiator_reply_time: u32, 192 pub responder_reply_time: u32, 193 pub initiator_responder_tof: u16, 194 pub dt_anchor_location: Vec<u8>, 195 pub ranging_rounds: Vec<u8>, 196 } 197 198 impl From<ExtendedAddressDlTdoaRangingMeasurement> for DlTdoaRangingMeasurement { from(measurement: ExtendedAddressDlTdoaRangingMeasurement) -> Self199 fn from(measurement: ExtendedAddressDlTdoaRangingMeasurement) -> Self { 200 DlTdoaRangingMeasurement { 201 mac_address: MacAddress::Extended(measurement.mac_address), 202 status: (measurement.measurement.status), 203 message_type: (measurement.measurement.message_type), 204 message_control: (measurement.measurement.message_control), 205 block_index: (measurement.measurement.block_index), 206 round_index: (measurement.measurement.round_index), 207 nlos: (measurement.measurement.nlos), 208 aoa_azimuth: (measurement.measurement.aoa_azimuth), 209 aoa_azimuth_fom: (measurement.measurement.aoa_azimuth_fom), 210 aoa_elevation: (measurement.measurement.aoa_elevation), 211 aoa_elevation_fom: (measurement.measurement.aoa_elevation_fom), 212 rssi: (measurement.measurement.rssi), 213 tx_timestamp: (measurement.measurement.tx_timestamp), 214 rx_timestamp: (measurement.measurement.rx_timestamp), 215 anchor_cfo: (measurement.measurement.anchor_cfo), 216 cfo: (measurement.measurement.cfo), 217 initiator_reply_time: (measurement.measurement.initiator_reply_time), 218 responder_reply_time: (measurement.measurement.responder_reply_time), 219 initiator_responder_tof: (measurement.measurement.initiator_responder_tof), 220 dt_anchor_location: (measurement.measurement.dt_anchor_location), 221 ranging_rounds: (measurement.measurement.ranging_rounds), 222 } 223 } 224 } 225 226 impl From<ShortAddressDlTdoaRangingMeasurement> for DlTdoaRangingMeasurement { from(measurement: ShortAddressDlTdoaRangingMeasurement) -> Self227 fn from(measurement: ShortAddressDlTdoaRangingMeasurement) -> Self { 228 DlTdoaRangingMeasurement { 229 mac_address: MacAddress::Short(measurement.mac_address), 230 status: (measurement.measurement.status), 231 message_type: (measurement.measurement.message_type), 232 message_control: (measurement.measurement.message_control), 233 block_index: (measurement.measurement.block_index), 234 round_index: (measurement.measurement.round_index), 235 nlos: (measurement.measurement.nlos), 236 aoa_azimuth: (measurement.measurement.aoa_azimuth), 237 aoa_azimuth_fom: (measurement.measurement.aoa_azimuth_fom), 238 aoa_elevation: (measurement.measurement.aoa_elevation), 239 aoa_elevation_fom: (measurement.measurement.aoa_elevation_fom), 240 rssi: (measurement.measurement.rssi), 241 tx_timestamp: (measurement.measurement.tx_timestamp), 242 rx_timestamp: (measurement.measurement.rx_timestamp), 243 anchor_cfo: (measurement.measurement.anchor_cfo), 244 cfo: (measurement.measurement.cfo), 245 initiator_reply_time: (measurement.measurement.initiator_reply_time), 246 responder_reply_time: (measurement.measurement.responder_reply_time), 247 initiator_responder_tof: (measurement.measurement.initiator_responder_tof), 248 dt_anchor_location: (measurement.measurement.dt_anchor_location), 249 ranging_rounds: (measurement.measurement.ranging_rounds), 250 } 251 } 252 } 253 254 pub(crate) struct NotificationManagerAndroid { 255 pub chip_id: String, 256 // 'static annotation is needed as env is 'sent' by tokio::task::spawn_local. 257 pub env: AttachGuard<'static>, 258 /// Global reference to the class loader object (java/lang/ClassLoader) from the java thread 259 /// that local java UCI classes can be loaded. 260 /// See http://yangyingchao.github.io/android/2015/01/13/Android-JNI-FindClass-Error.html 261 pub class_loader_obj: GlobalRef, 262 /// Global reference to the java class holding the various UCI notification callback functions. 263 pub callback_obj: GlobalRef, 264 // *_jmethod_id are cached for faster callback using call_method_unchecked 265 pub jmethod_id_map: HashMap<String, JMethodID>, 266 // jclass are cached for faster callback 267 pub jclass_map: HashMap<String, GlobalRef>, 268 } 269 270 // TODO(b/246678053): Need to add callbacks for Data Packet Rx, and Data Packet Tx events (like 271 // DATA_CREDIT_NTF, DATA_STATUS_NTF). 272 impl NotificationManagerAndroid { 273 /// Finds JClass stored in jclass map. Should be a member function, but disjoint field borrow 274 /// checker fails and mutability of individual fields has to be annotated. find_local_class<'a>( jclass_map: &'a mut HashMap<String, GlobalRef>, class_loader_obj: &'a GlobalRef, env: &'a AttachGuard<'static>, class_name: &'a str, ) -> Result<JClass<'a>, JNIError>275 fn find_local_class<'a>( 276 jclass_map: &'a mut HashMap<String, GlobalRef>, 277 class_loader_obj: &'a GlobalRef, 278 env: &'a AttachGuard<'static>, 279 class_name: &'a str, 280 ) -> Result<JClass<'a>, JNIError> { 281 // Look for cached class 282 if jclass_map.get(class_name).is_none() { 283 // Find class using the class loader object, needed as this call is initiated from a 284 // different native thread. 285 286 let env_class_name = *env.new_string(class_name).map_err(|e| { 287 error!("UCI JNI: failed to create Java String: {e:?}"); 288 e 289 })?; 290 let class_value = env 291 .call_method( 292 class_loader_obj.as_obj(), 293 "findClass", 294 "(Ljava/lang/String;)Ljava/lang/Class;", 295 &[JValue::Object(env_class_name)], 296 ) 297 .map_err(|e| { 298 error!("UCI JNI: failed to find java class {}: {:?}", class_name, e); 299 e 300 })?; 301 let jclass = match class_value.l() { 302 Ok(obj) => Ok(JClass::from(obj)), 303 Err(e) => { 304 error!("UCI JNI: failed to find java class {}: {:?}", class_name, e); 305 Err(e) 306 } 307 }?; 308 // Cache JClass as a global reference. 309 jclass_map.insert( 310 class_name.to_owned(), 311 env.new_global_ref(jclass).map_err(|e| { 312 error!("UCI JNI: global reference conversion failed: {:?}", e); 313 e 314 })?, 315 ); 316 } 317 // Return JClass 318 Ok(jclass_map.get(class_name).unwrap().as_obj().into()) 319 } 320 cached_jni_call( &mut self, name: &str, sig: &str, args: &[jvalue], ) -> Result<JObject, JNIError>321 fn cached_jni_call( 322 &mut self, 323 name: &str, 324 sig: &str, 325 args: &[jvalue], 326 ) -> Result<JObject, JNIError> { 327 debug!("UCI JNI: callback {}", name); 328 let type_signature = TypeSignature::from_str(sig).map_err(|e| { 329 error!("UCI JNI: Invalid type signature: {:?}", e); 330 e 331 })?; 332 if type_signature.args.len() != args.len() { 333 error!( 334 "UCI: type_signature requires {} args, but {} is provided", 335 type_signature.args.len(), 336 args.len() 337 ); 338 return Err(jni::errors::Error::InvalidArgList(type_signature)); 339 } 340 let name_signature = name.to_owned() + sig; 341 if !self.jmethod_id_map.contains_key(&name_signature) { 342 self.jmethod_id_map.insert( 343 name_signature.clone(), 344 self.env.get_method_id(self.callback_obj.as_obj(), name, sig).map_err(|e| { 345 error!("UCI JNI: failed to get method: {:?}", e); 346 e 347 })?, 348 ); 349 } 350 match self.env.call_method_unchecked( 351 self.callback_obj.as_obj(), 352 self.jmethod_id_map.get(&name_signature).unwrap().to_owned(), 353 type_signature.ret, 354 args, 355 ) { 356 Ok(_) => Ok(JObject::null()), 357 Err(e) => { 358 error!("UCI JNI: callback {} failed!", name); 359 Err(e) 360 } 361 } 362 } 363 on_session_status_notification( &mut self, session_id: u32, session_token: u32, session_state: SessionState, reason_code: u8, ) -> Result<JObject, JNIError>364 fn on_session_status_notification( 365 &mut self, 366 session_id: u32, 367 session_token: u32, 368 session_state: SessionState, 369 reason_code: u8, 370 ) -> Result<JObject, JNIError> { 371 self.cached_jni_call( 372 "onSessionStatusNotificationReceived", 373 "(JIII)V", 374 &[ 375 jvalue::from(JValue::Long(session_id as i64)), 376 jvalue::from(JValue::Int(session_token as i32)), 377 jvalue::from(JValue::Int(session_state as i32)), 378 jvalue::from(JValue::Int(reason_code as i32)), 379 ], 380 ) 381 } 382 on_session_update_multicast_notification( &mut self, session_id: u32, remaining_multicast_list_size: usize, status_list: ControleeStatusList, ) -> Result<JObject, JNIError>383 fn on_session_update_multicast_notification( 384 &mut self, 385 session_id: u32, 386 remaining_multicast_list_size: usize, 387 status_list: ControleeStatusList, 388 ) -> Result<JObject, JNIError> { 389 let remaining_multicast_list_size: i32 = 390 remaining_multicast_list_size.try_into().map_err(|_| JNIError::InvalidCtorReturn)?; 391 let mac_address_vec: Vec<[u8; 2]>; 392 let subsession_id_vec: Vec<_>; 393 let status_vec: Vec<_>; 394 let count: i32; 395 match status_list { 396 ControleeStatusList::V1(status_list) => { 397 count = status_list.len().try_into().map_err(|_| JNIError::InvalidCtorReturn)?; 398 (mac_address_vec, (subsession_id_vec, status_vec)) = status_list 399 .into_iter() 400 .map(|cs| (cs.mac_address, (cs.subsession_id as i64, i32::from(cs.status)))) 401 .unzip(); 402 } 403 ControleeStatusList::V2(status_list) => { 404 count = status_list.len().try_into().map_err(|_| JNIError::InvalidCtorReturn)?; 405 (mac_address_vec, (subsession_id_vec, status_vec)) = status_list 406 .into_iter() 407 .map(|cs| (cs.mac_address, (0_i64, i32::from(cs.status)))) 408 .unzip(); 409 } 410 } 411 let subsession_id_jlongarray = self.env.new_long_array(count)?; 412 let status_jintarray = self.env.new_int_array(count)?; 413 414 let mac_address_vec_i8 = 415 mac_address_vec.iter().flat_map(|&[a, b]| vec![a as i8, b as i8]).collect::<Vec<i8>>(); 416 let mac_address_slice: &[i8] = &mac_address_vec_i8; 417 let mac_address_jbytearray = self.env.new_byte_array(mac_address_slice.len() as i32)?; 418 419 self.env.set_byte_array_region(mac_address_jbytearray, 0, mac_address_slice)?; 420 self.env.set_long_array_region(subsession_id_jlongarray, 0, &subsession_id_vec)?; 421 self.env.set_int_array_region(status_jintarray, 0, &status_vec)?; 422 let multicast_update_jclass = NotificationManagerAndroid::find_local_class( 423 &mut self.jclass_map, 424 &self.class_loader_obj, 425 &self.env, 426 MULTICAST_LIST_UPDATE_STATUS_CLASS, 427 )?; 428 let method_sig = "(L".to_owned() + MULTICAST_LIST_UPDATE_STATUS_CLASS + ";)V"; 429 430 // Safety: mac_address_jintarray is safely instantiated above. 431 let mac_address_jobject = unsafe { JObject::from_raw(mac_address_jbytearray) }; 432 433 // Safety: subsession_id_jlongarray is safely instantiated above. 434 let subsession_id_jobject = unsafe { JObject::from_raw(subsession_id_jlongarray) }; 435 436 // Safety: status_jintarray is safely instantiated above. 437 let status_jobject = unsafe { JObject::from_raw(status_jintarray) }; 438 439 let multicast_update_jobject = self.env.new_object( 440 multicast_update_jclass, 441 "(JII[B[J[I)V", 442 &[ 443 JValue::Long(session_id as i64), 444 JValue::Int(remaining_multicast_list_size), 445 JValue::Int(count), 446 JValue::Object(mac_address_jobject), 447 JValue::Object(subsession_id_jobject), 448 JValue::Object(status_jobject), 449 ], 450 )?; 451 self.cached_jni_call( 452 "onMulticastListUpdateNotificationReceived", 453 &method_sig, 454 &[jvalue::from(JValue::Object(multicast_update_jobject))], 455 ) 456 } 457 458 // TODO(b/246678053): Re-factor usage of the RangingMeasurement enum below, to extract the 459 // fields in a common/caller method (and preferably not handle TwoWay/OwrAoa in this method). on_session_dl_tdoa_range_data_notification( &mut self, range_data: SessionRangeData, ) -> Result<JObject, JNIError>460 fn on_session_dl_tdoa_range_data_notification( 461 &mut self, 462 range_data: SessionRangeData, 463 ) -> Result<JObject, JNIError> { 464 let raw_notification_jbytearray = 465 self.env.byte_array_from_slice(&range_data.raw_ranging_data)?; 466 let measurement_jclass = NotificationManagerAndroid::find_local_class( 467 &mut self.jclass_map, 468 &self.class_loader_obj, 469 &self.env, 470 UWB_DL_TDOA_MEASUREMENT_CLASS, 471 )?; 472 let bytearray_len: i32 = match &range_data.ranging_measurements { 473 uwb_core::uci::RangingMeasurements::ShortAddressTwoWay(_) => SHORT_MAC_ADDRESS_LEN, 474 uwb_core::uci::RangingMeasurements::ExtendedAddressTwoWay(_) => { 475 EXTENDED_MAC_ADDRESS_LEN 476 } 477 uwb_core::uci::RangingMeasurements::ShortAddressDltdoa(_) => SHORT_MAC_ADDRESS_LEN, 478 uwb_core::uci::RangingMeasurements::ExtendedAddressDltdoa(_) => { 479 EXTENDED_MAC_ADDRESS_LEN 480 } 481 _ => { 482 return Err(JNIError::InvalidCtorReturn); 483 } 484 }; 485 let address_jbytearray = self.env.new_byte_array(bytearray_len)?; 486 let anchor_location = self.env.new_byte_array(MAX_ANCHOR_LOCATION_LEN)?; 487 let active_ranging_rounds = self.env.new_byte_array(MAX_RANGING_ROUNDS_LEN)?; 488 489 // Safety: address_jbytearray is safely instantiated above. 490 let address_jobject = unsafe { JObject::from_raw(address_jbytearray) }; 491 // Safety: anchor_location is safely instantiated above. 492 let anchor_jobject = unsafe { JObject::from_raw(anchor_location) }; 493 // Safety: active_ranging_rounds is safely instantiated above. 494 let active_ranging_rounds_jobject = unsafe { JObject::from_raw(active_ranging_rounds) }; 495 496 let zero_initiated_measurement_jobject = self 497 .env 498 .new_object( 499 measurement_jclass, 500 "([BIIIIIIIIIIIJJIIJJI[B[B)V", 501 &[ 502 JValue::Object(address_jobject), 503 JValue::Int(0), 504 JValue::Int(0), 505 JValue::Int(0), 506 JValue::Int(0), 507 JValue::Int(0), 508 JValue::Int(0), 509 JValue::Int(0), 510 JValue::Int(0), 511 JValue::Int(0), 512 JValue::Int(0), 513 JValue::Int(0), 514 JValue::Long(0), 515 JValue::Long(0), 516 JValue::Int(0), 517 JValue::Int(0), 518 JValue::Long(0), 519 JValue::Long(0), 520 JValue::Int(0), 521 JValue::Object(anchor_jobject), 522 JValue::Object(active_ranging_rounds_jobject), 523 ], 524 ) 525 .map_err(|e| { 526 error!("UCI JNI: measurement object creation failed: {:?}", e); 527 e 528 })?; 529 let measurement_count: i32 = match &range_data.ranging_measurements { 530 RangingMeasurements::ShortAddressTwoWay(v) => v.len(), 531 RangingMeasurements::ExtendedAddressTwoWay(v) => v.len(), 532 RangingMeasurements::ShortAddressDltdoa(v) => v.len(), 533 RangingMeasurements::ExtendedAddressDltdoa(v) => v.len(), 534 _ => { 535 return Err(JNIError::InvalidCtorReturn); 536 } 537 } 538 .try_into() 539 .map_err(|_| JNIError::InvalidCtorReturn)?; 540 let mac_indicator = match &range_data.ranging_measurements { 541 RangingMeasurements::ShortAddressTwoWay(_) => MacAddressIndicator::ShortAddress, 542 RangingMeasurements::ExtendedAddressTwoWay(_) => MacAddressIndicator::ExtendedAddress, 543 RangingMeasurements::ShortAddressDltdoa(_) => MacAddressIndicator::ShortAddress, 544 RangingMeasurements::ExtendedAddressDltdoa(_) => MacAddressIndicator::ExtendedAddress, 545 _ => { 546 return Err(JNIError::InvalidCtorReturn); 547 } 548 }; 549 550 let measurements_jobjectarray = self.env.new_object_array( 551 measurement_count, 552 measurement_jclass, 553 zero_initiated_measurement_jobject, 554 )?; 555 556 for (i, measurement) in match range_data.ranging_measurements { 557 RangingMeasurements::ShortAddressDltdoa(v) => { 558 v.into_iter().map(DlTdoaRangingMeasurement::from).collect::<Vec<_>>() 559 } 560 RangingMeasurements::ExtendedAddressDltdoa(v) => { 561 v.into_iter().map(DlTdoaRangingMeasurement::from).collect::<Vec<_>>() 562 } 563 _ => Vec::new(), 564 } 565 .into_iter() 566 .enumerate() 567 { 568 // cast to i8 as java do not support unsigned: 569 let mac_address_i8 = measurement 570 .mac_address 571 .into_ne_bytes() 572 .iter() 573 .map(|b| b.to_owned() as i8) 574 .collect::<Vec<_>>(); 575 let mac_address_jbytearray = self.env.new_byte_array(mac_address_i8.len() as i32)?; 576 self.env.set_byte_array_region(mac_address_jbytearray, 0, &mac_address_i8)?; 577 578 let dt_anchor_location_jbytearray = 579 self.env.byte_array_from_slice(&measurement.dt_anchor_location)?; 580 581 let ranging_rounds_jbytearray = 582 self.env.byte_array_from_slice(&measurement.ranging_rounds)?; 583 584 // Safety: mac_address_jbytearray is safely instantiated above. 585 let mac_address_jobject = unsafe { JObject::from_raw(mac_address_jbytearray) }; 586 let dt_anchor_location_jobject = 587 // Safety: dt_anchor_location_jbytearray is safely instantiated above. 588 unsafe { JObject::from_raw(dt_anchor_location_jbytearray) }; 589 // Safety: ranging_rounds_jbytearray is safely instantiated above. 590 let ranging_rounds_jobject = unsafe { JObject::from_raw(ranging_rounds_jbytearray) }; 591 592 let measurement_jobject = self 593 .env 594 .new_object( 595 measurement_jclass, 596 "([BIIIIIIIIIIIJJIIJJI[B[B)V", 597 &[ 598 JValue::Object(mac_address_jobject), 599 JValue::Int(measurement.status as i32), 600 JValue::Int(measurement.message_type as i32), 601 JValue::Int(measurement.message_control as i32), 602 JValue::Int(measurement.block_index as i32), 603 JValue::Int(measurement.round_index as i32), 604 JValue::Int(measurement.nlos as i32), 605 JValue::Int(measurement.aoa_azimuth as i32), 606 JValue::Int(measurement.aoa_azimuth_fom as i32), 607 JValue::Int(measurement.aoa_elevation as i32), 608 JValue::Int(measurement.aoa_elevation_fom as i32), 609 JValue::Int(measurement.rssi as i32), 610 JValue::Long(measurement.tx_timestamp as i64), 611 JValue::Long(measurement.rx_timestamp as i64), 612 JValue::Int(measurement.anchor_cfo as i32), 613 JValue::Int(measurement.cfo as i32), 614 JValue::Long(measurement.initiator_reply_time as i64), 615 JValue::Long(measurement.responder_reply_time as i64), 616 JValue::Int(measurement.initiator_responder_tof as i32), 617 JValue::Object(dt_anchor_location_jobject), 618 JValue::Object(ranging_rounds_jobject), 619 ], 620 ) 621 .map_err(|e| { 622 error!("UCI JNI: measurement object creation failed: {:?}", e); 623 e 624 })?; 625 self.env 626 .set_object_array_element(measurements_jobjectarray, i as i32, measurement_jobject) 627 .map_err(|e| { 628 error!("UCI JNI: measurement object copy failed: {:?}", e); 629 e 630 })?; 631 } 632 // Create UwbRangingData 633 let ranging_data_jclass = NotificationManagerAndroid::find_local_class( 634 &mut self.jclass_map, 635 &self.class_loader_obj, 636 &self.env, 637 UWB_RANGING_DATA_CLASS, 638 )?; 639 640 let method_sig = "(JJIJIII[L".to_owned() + UWB_DL_TDOA_MEASUREMENT_CLASS + ";[B)V"; 641 642 // Safety: measurements_jobjectarray is safely instantiated above. 643 let measurements_jobject = unsafe { JObject::from_raw(measurements_jobjectarray) }; 644 // Safety: raw_notification_jbytearray is safely instantiated above. 645 let raw_notification_jobject = unsafe { JObject::from_raw(raw_notification_jbytearray) }; 646 647 let range_data_jobject = self 648 .env 649 .new_object( 650 ranging_data_jclass, 651 &method_sig, 652 &[ 653 JValue::Long(range_data.sequence_number as i64), 654 // session_token below has already been mapped to session_id by uci layer. 655 JValue::Long(range_data.session_token as i64), 656 JValue::Int(range_data.rcr_indicator as i32), 657 JValue::Long(range_data.current_ranging_interval_ms as i64), 658 JValue::Int(range_data.ranging_measurement_type as i32), 659 JValue::Int(mac_indicator as i32), 660 JValue::Int(measurement_count), 661 JValue::Object(measurements_jobject), 662 JValue::Object(raw_notification_jobject), 663 ], 664 ) 665 .map_err(|e| { 666 error!("UCI JNI: Ranging Data object creation failed: {:?}", e); 667 e 668 })?; 669 670 let method_sig = "(L".to_owned() + UWB_RANGING_DATA_CLASS + ";)V"; 671 self.cached_jni_call( 672 "onRangeDataNotificationReceived", 673 &method_sig, 674 &[jvalue::from(JValue::Object(range_data_jobject))], 675 ) 676 } 677 on_two_way_range_data_notification( &mut self, bytearray_len: i32, measurement_count: i32, measurements: Vec<TwoWayRangingMeasurement>, ) -> Result<jni::sys::jobjectArray, JNIError>678 fn on_two_way_range_data_notification( 679 &mut self, 680 bytearray_len: i32, 681 measurement_count: i32, 682 measurements: Vec<TwoWayRangingMeasurement>, 683 ) -> Result<jni::sys::jobjectArray, JNIError> { 684 let measurement_jclass = NotificationManagerAndroid::find_local_class( 685 &mut self.jclass_map, 686 &self.class_loader_obj, 687 &self.env, 688 UWB_TWO_WAY_MEASUREMENT_CLASS, 689 )?; 690 let address_jbytearray = self.env.new_byte_array(bytearray_len)?; 691 692 // Safety: address_jbytearray is safely instantiated above. 693 let address_jobject = unsafe { JObject::from_raw(address_jbytearray) }; 694 695 let zero_initiated_measurement_jobject = self 696 .env 697 .new_object( 698 measurement_jclass, 699 "([BIIIIIIIIIIIII)V", 700 &[ 701 JValue::Object(address_jobject), 702 JValue::Int(0), 703 JValue::Int(0), 704 JValue::Int(0), 705 JValue::Int(0), 706 JValue::Int(0), 707 JValue::Int(0), 708 JValue::Int(0), 709 JValue::Int(0), 710 JValue::Int(0), 711 JValue::Int(0), 712 JValue::Int(0), 713 JValue::Int(0), 714 JValue::Int(0), 715 ], 716 ) 717 .map_err(|e| { 718 error!("UCI JNI: measurement object creation failed: {:?}", e); 719 e 720 })?; 721 722 let measurements_jobjectarray = self.env.new_object_array( 723 measurement_count, 724 measurement_jclass, 725 zero_initiated_measurement_jobject, 726 )?; 727 for (i, measurement) in measurements.into_iter().enumerate() { 728 // cast to i8 as java do not support unsigned: 729 let mac_address_i8 = measurement 730 .mac_address 731 .into_ne_bytes() 732 .iter() 733 .map(|b| b.to_owned() as i8) 734 .collect::<Vec<_>>(); 735 let mac_address_jbytearray = self.env.new_byte_array(mac_address_i8.len() as i32)?; 736 self.env.set_byte_array_region(mac_address_jbytearray, 0, &mac_address_i8)?; 737 // casting as i32 is fine since it is wider than actual integer type. 738 739 // Safety: mac_address_jbytearray is safely instantiated above. 740 let mac_address_jobject = unsafe { JObject::from_raw(mac_address_jbytearray) }; 741 let measurement_jobject = self 742 .env 743 .new_object( 744 measurement_jclass, 745 "([BIIIIIIIIIIIII)V", 746 &[ 747 JValue::Object(mac_address_jobject), 748 JValue::Int(i32::from(measurement.status)), 749 JValue::Int(measurement.nlos as i32), 750 JValue::Int(measurement.distance as i32), 751 JValue::Int(measurement.aoa_azimuth as i32), 752 JValue::Int(measurement.aoa_azimuth_fom as i32), 753 JValue::Int(measurement.aoa_elevation as i32), 754 JValue::Int(measurement.aoa_elevation_fom as i32), 755 JValue::Int(measurement.aoa_destination_azimuth as i32), 756 JValue::Int(measurement.aoa_destination_azimuth_fom as i32), 757 JValue::Int(measurement.aoa_destination_elevation as i32), 758 JValue::Int(measurement.aoa_destination_elevation_fom as i32), 759 JValue::Int(measurement.slot_index as i32), 760 JValue::Int(measurement.rssi as i32), 761 ], 762 ) 763 .map_err(|e| { 764 error!("UCI JNI: measurement object creation failed: {:?}", e); 765 e 766 })?; 767 self.env 768 .set_object_array_element(measurements_jobjectarray, i as i32, measurement_jobject) 769 .map_err(|e| { 770 error!("UCI JNI: measurement object copy failed: {:?}", e); 771 e 772 })?; 773 } 774 775 Ok(measurements_jobjectarray) 776 } 777 on_session_owr_aoa_range_data_notification( &mut self, range_data: SessionRangeData, ) -> Result<JObject, JNIError>778 fn on_session_owr_aoa_range_data_notification( 779 &mut self, 780 range_data: SessionRangeData, 781 ) -> Result<JObject, JNIError> { 782 if range_data.ranging_measurement_type != RangingMeasurementType::OwrAoa { 783 return Err(JNIError::InvalidCtorReturn); 784 } 785 786 let raw_notification_jbytearray = 787 self.env.byte_array_from_slice(&range_data.raw_ranging_data)?; 788 789 let (mac_indicator, measurement): (MacAddressIndicator, OwrAoaRangingMeasurement) = 790 match range_data.ranging_measurements { 791 RangingMeasurements::ExtendedAddressOwrAoa(m) => { 792 (MacAddressIndicator::ExtendedAddress, m.into()) 793 } 794 RangingMeasurements::ShortAddressOwrAoa(m) => { 795 (MacAddressIndicator::ShortAddress, m.into()) 796 } 797 _ => { 798 return Err(JNIError::InvalidCtorReturn); 799 } 800 }; 801 802 // cast to i8 as java do not support unsigned. 803 let mac_address_i8 = measurement 804 .mac_address 805 .into_ne_bytes() 806 .iter() 807 .map(|b| b.to_owned() as i8) 808 .collect::<Vec<_>>(); 809 // casting as i32 is fine since it is wider than actual integer type. 810 let mac_address_jbytearray = self.env.new_byte_array(mac_address_i8.len() as i32)?; 811 self.env.set_byte_array_region(mac_address_jbytearray, 0, &mac_address_i8)?; 812 // Safety: mac_address_jbytearray is safely instantiated above. 813 let mac_address_jobject = unsafe { JObject::from_raw(mac_address_jbytearray) }; 814 815 let measurement_jclass = NotificationManagerAndroid::find_local_class( 816 &mut self.jclass_map, 817 &self.class_loader_obj, 818 &self.env, 819 UWB_OWR_AOA_MEASUREMENT_CLASS, 820 )?; 821 let measurement_jobject = self 822 .env 823 .new_object( 824 measurement_jclass, 825 "([BIIIIIIII)V", 826 &[ 827 JValue::Object(mac_address_jobject), 828 JValue::Int(i32::from(measurement.status)), 829 JValue::Int(measurement.nlos as i32), 830 JValue::Int(measurement.frame_sequence_number as i32), 831 JValue::Int(measurement.block_index as i32), 832 JValue::Int(measurement.aoa_azimuth as i32), 833 JValue::Int(measurement.aoa_azimuth_fom as i32), 834 JValue::Int(measurement.aoa_elevation as i32), 835 JValue::Int(measurement.aoa_elevation_fom as i32), 836 ], 837 ) 838 .map_err(|e| { 839 error!("UCI JNI: OwrAoA measurement jobject creation failed: {:?}", e); 840 e 841 })?; 842 843 // Create UwbRangingData 844 let ranging_data_jclass = NotificationManagerAndroid::find_local_class( 845 &mut self.jclass_map, 846 &self.class_loader_obj, 847 &self.env, 848 UWB_RANGING_DATA_CLASS, 849 )?; 850 let method_sig = "(JJIJIIIL".to_owned() + UWB_OWR_AOA_MEASUREMENT_CLASS + ";[B)V"; 851 852 // Safety: raw_notification_jobject is safely instantiated above. 853 let raw_notification_jobject = unsafe { JObject::from_raw(raw_notification_jbytearray) }; 854 855 let range_data_jobject = self 856 .env 857 .new_object( 858 ranging_data_jclass, 859 &method_sig, 860 &[ 861 JValue::Long(range_data.sequence_number as i64), 862 // session_token below has already been mapped to session_id by uci layer. 863 JValue::Long(range_data.session_token as i64), 864 JValue::Int(range_data.rcr_indicator as i32), 865 JValue::Long(range_data.current_ranging_interval_ms as i64), 866 JValue::Int(range_data.ranging_measurement_type as i32), 867 JValue::Int(mac_indicator as i32), 868 JValue::Int(1), // measurement_count 869 JValue::Object(measurement_jobject), 870 JValue::Object(raw_notification_jobject), 871 ], 872 ) 873 .map_err(|e| { 874 error!("UCI JNI: Ranging Data object creation failed: {:?}", e); 875 e 876 })?; 877 let method_sig = "(L".to_owned() + UWB_RANGING_DATA_CLASS + ";)V"; 878 self.cached_jni_call( 879 "onRangeDataNotificationReceived", 880 &method_sig, 881 &[jvalue::from(JValue::Object(range_data_jobject))], 882 ) 883 } 884 on_session_two_way_range_data_notification( &mut self, range_data: SessionRangeData, ) -> Result<JObject, JNIError>885 fn on_session_two_way_range_data_notification( 886 &mut self, 887 range_data: SessionRangeData, 888 ) -> Result<JObject, JNIError> { 889 let raw_notification_jbytearray = 890 self.env.byte_array_from_slice(&range_data.raw_ranging_data)?; 891 892 let (bytearray_len, mac_indicator) = match &range_data.ranging_measurements { 893 RangingMeasurements::ExtendedAddressTwoWay(_) => { 894 (EXTENDED_MAC_ADDRESS_LEN, MacAddressIndicator::ExtendedAddress) 895 } 896 RangingMeasurements::ShortAddressTwoWay(_) => { 897 (SHORT_MAC_ADDRESS_LEN, MacAddressIndicator::ShortAddress) 898 } 899 _ => { 900 return Err(JNIError::InvalidCtorReturn); 901 } 902 }; 903 904 let measurement_count: i32 = match &range_data.ranging_measurements { 905 RangingMeasurements::ShortAddressTwoWay(v) => v.len().try_into(), 906 RangingMeasurements::ExtendedAddressTwoWay(v) => v.len().try_into(), 907 _ => { 908 return Err(JNIError::InvalidCtorReturn); 909 } 910 } 911 .map_err(|_| JNIError::InvalidCtorReturn)?; 912 913 let measurements_jobjectarray = match range_data.ranging_measurement_type { 914 RangingMeasurementType::TwoWay => { 915 let measurements = match range_data.ranging_measurements { 916 RangingMeasurements::ExtendedAddressTwoWay(v) => { 917 v.into_iter().map(TwoWayRangingMeasurement::from).collect::<Vec<_>>() 918 } 919 RangingMeasurements::ShortAddressTwoWay(v) => { 920 v.into_iter().map(TwoWayRangingMeasurement::from).collect::<Vec<_>>() 921 } 922 _ => return Err(JNIError::InvalidCtorReturn), 923 }; 924 self.on_two_way_range_data_notification( 925 bytearray_len, 926 measurement_count, 927 measurements, 928 )? 929 } 930 _ => { 931 return Err(JNIError::InvalidCtorReturn); 932 } 933 }; 934 935 // Create UwbRangingData 936 let ranging_data_jclass = NotificationManagerAndroid::find_local_class( 937 &mut self.jclass_map, 938 &self.class_loader_obj, 939 &self.env, 940 UWB_RANGING_DATA_CLASS, 941 )?; 942 let method_sig = "(JJIJIII[L".to_owned() + UWB_TWO_WAY_MEASUREMENT_CLASS + ";[B)V"; 943 944 // Safety: measurements_jobjectarray is safely instantiated above. 945 let measurements_jobject = unsafe { JObject::from_raw(measurements_jobjectarray) }; 946 // Safety: raw_notification_jobject is safely instantiated above. 947 let raw_notification_jobject = unsafe { JObject::from_raw(raw_notification_jbytearray) }; 948 let range_data_jobject = self 949 .env 950 .new_object( 951 ranging_data_jclass, 952 &method_sig, 953 &[ 954 JValue::Long(range_data.sequence_number as i64), 955 // session_token below has already been mapped to session_id by uci layer. 956 JValue::Long(range_data.session_token as i64), 957 JValue::Int(range_data.rcr_indicator as i32), 958 JValue::Long(range_data.current_ranging_interval_ms as i64), 959 JValue::Int(range_data.ranging_measurement_type as i32), 960 JValue::Int(mac_indicator as i32), 961 JValue::Int(measurement_count), 962 JValue::Object(measurements_jobject), 963 JValue::Object(raw_notification_jobject), 964 ], 965 ) 966 .map_err(|e| { 967 error!("UCI JNI: Ranging Data object creation failed: {:?}", e); 968 e 969 })?; 970 let method_sig = "(L".to_owned() + UWB_RANGING_DATA_CLASS + ";)V"; 971 self.cached_jni_call( 972 "onRangeDataNotificationReceived", 973 &method_sig, 974 &[jvalue::from(JValue::Object(range_data_jobject))], 975 ) 976 } 977 on_data_transfer_status_notification( &mut self, session_id: u32, uci_sequence_number: u16, status_code: u8, tx_count: u8, ) -> Result<JObject, JNIError>978 fn on_data_transfer_status_notification( 979 &mut self, 980 session_id: u32, 981 uci_sequence_number: u16, 982 status_code: u8, 983 tx_count: u8, 984 ) -> Result<JObject, JNIError> { 985 self.cached_jni_call( 986 "onDataSendStatus", 987 "(JIJI)V", 988 &[ 989 jvalue::from(JValue::Long(session_id as i64)), 990 jvalue::from(JValue::Int(status_code as i32)), 991 jvalue::from(JValue::Long(uci_sequence_number as i64)), 992 jvalue::from(JValue::Int(tx_count as i32)), 993 ], 994 ) 995 } 996 on_data_transfer_phase_config_notification( &mut self, session_id: u32, status_code: u8, ) -> Result<JObject, JNIError>997 fn on_data_transfer_phase_config_notification( 998 &mut self, 999 session_id: u32, 1000 status_code: u8, 1001 ) -> Result<JObject, JNIError> { 1002 self.cached_jni_call( 1003 "onDataTransferPhaseConfigNotificationReceived", 1004 "(JI)V", 1005 &[ 1006 jvalue::from(JValue::Long(session_id as i64)), 1007 jvalue::from(JValue::Int(status_code as i32)), 1008 ], 1009 ) 1010 } 1011 } 1012 1013 impl NotificationManager for NotificationManagerAndroid { on_core_notification(&mut self, core_notification: CoreNotification) -> UwbResult<()>1014 fn on_core_notification(&mut self, core_notification: CoreNotification) -> UwbResult<()> { 1015 debug!("UCI JNI: core notification callback."); 1016 let env = *self.env; 1017 env.with_local_frame(MAX_JAVA_OBJECTS_CAPACITY, || { 1018 let env_chip_id_jobject = *env.new_string(&self.chip_id).map_err(|e| { 1019 error!("UCI JNI: failed to create Java String: {e:?}"); 1020 e 1021 })?; 1022 1023 match core_notification { 1024 CoreNotification::DeviceStatus(device_state) => self.cached_jni_call( 1025 "onDeviceStatusNotificationReceived", 1026 "(ILjava/lang/String;)V", 1027 &[ 1028 jvalue::from(JValue::Int(device_state as i32)), 1029 jvalue::from(JValue::Object(env_chip_id_jobject)), 1030 ], 1031 ), 1032 CoreNotification::GenericError(generic_error) => self.cached_jni_call( 1033 "onCoreGenericErrorNotificationReceived", 1034 "(ILjava/lang/String;)V", 1035 &[ 1036 jvalue::from(JValue::Int(i32::from(generic_error))), 1037 jvalue::from(JValue::Object(env_chip_id_jobject)), 1038 ], 1039 ), 1040 } 1041 }) 1042 .map_err(|_| UwbError::ForeignFunctionInterface)?; 1043 1044 Ok(()) 1045 } 1046 on_session_notification( &mut self, session_notification: SessionNotification, ) -> UwbResult<()>1047 fn on_session_notification( 1048 &mut self, 1049 session_notification: SessionNotification, 1050 ) -> UwbResult<()> { 1051 debug!("UCI JNI: session notification callback."); 1052 let env = *self.env; 1053 env.with_local_frame(MAX_JAVA_OBJECTS_CAPACITY, || { 1054 match session_notification { 1055 SessionNotification::Status { 1056 session_id, 1057 session_token, 1058 session_state, 1059 reason_code, 1060 } => self.on_session_status_notification( 1061 session_id, 1062 session_token, 1063 session_state, 1064 reason_code, 1065 ), 1066 SessionNotification::UpdateControllerMulticastListV1 { 1067 session_token, 1068 remaining_multicast_list_size, 1069 status_list, 1070 } => self.on_session_update_multicast_notification( 1071 session_token, 1072 remaining_multicast_list_size, 1073 ControleeStatusList::V1(status_list), 1074 ), 1075 SessionNotification::UpdateControllerMulticastListV2 { 1076 session_token, 1077 status_list, 1078 } => self.on_session_update_multicast_notification( 1079 session_token, 1080 0_usize, 1081 ControleeStatusList::V2(status_list), 1082 ), 1083 // TODO(b/246678053): Match here on range_data.ranging_measurement_type instead. 1084 SessionNotification::SessionInfo(range_data) => { 1085 match range_data.ranging_measurements { 1086 uwb_core::uci::RangingMeasurements::ShortAddressTwoWay(_) => { 1087 self.on_session_two_way_range_data_notification(range_data) 1088 } 1089 uwb_core::uci::RangingMeasurements::ExtendedAddressTwoWay(_) => { 1090 self.on_session_two_way_range_data_notification(range_data) 1091 } 1092 uwb_core::uci::RangingMeasurements::ShortAddressOwrAoa(_) => { 1093 self.on_session_owr_aoa_range_data_notification(range_data) 1094 } 1095 uwb_core::uci::RangingMeasurements::ExtendedAddressOwrAoa(_) => { 1096 self.on_session_owr_aoa_range_data_notification(range_data) 1097 } 1098 uwb_core::uci::RangingMeasurements::ShortAddressDltdoa(_) => { 1099 self.on_session_dl_tdoa_range_data_notification(range_data) 1100 } 1101 uwb_core::uci::RangingMeasurements::ExtendedAddressDltdoa(_) => { 1102 self.on_session_dl_tdoa_range_data_notification(range_data) 1103 } 1104 } 1105 } 1106 SessionNotification::DataTransferStatus { 1107 session_token, 1108 uci_sequence_number, 1109 status, 1110 tx_count, 1111 } => self.on_data_transfer_status_notification( 1112 session_token, 1113 uci_sequence_number, 1114 u8::from(status), 1115 tx_count, 1116 ), 1117 // This session notification should not come here, as it's handled within 1118 // UciManager, for internal state management related to sending data packet(s). 1119 SessionNotification::DataCredit { session_token, credit_availability } => { 1120 error!( 1121 "UCI JNI: Received unexpected DataCredit notification for \ 1122 session_token {}, credit_availability {:?}", 1123 session_token, credit_availability 1124 ); 1125 Err(JNIError::InvalidCtorReturn) 1126 } 1127 SessionNotification::DataTransferPhaseConfig { session_token, status } => { 1128 self.on_data_transfer_phase_config_notification(session_token, u8::from(status)) 1129 } 1130 } 1131 }) 1132 .map_err(|_| UwbError::ForeignFunctionInterface)?; 1133 Ok(()) 1134 } 1135 on_vendor_notification( &mut self, vendor_notification: uwb_core::params::RawUciMessage, ) -> UwbResult<()>1136 fn on_vendor_notification( 1137 &mut self, 1138 vendor_notification: uwb_core::params::RawUciMessage, 1139 ) -> UwbResult<()> { 1140 debug!("UCI JNI: vendor notification callback."); 1141 let env = *self.env; 1142 env.with_local_frame(MAX_JAVA_OBJECTS_CAPACITY, || { 1143 let payload_jbytearray = 1144 self.env.byte_array_from_slice(&vendor_notification.payload)?; 1145 1146 // Safety: payload_jbytearray safely instantiated above. 1147 let payload_jobject = unsafe { JObject::from_raw(payload_jbytearray) }; 1148 self.cached_jni_call( 1149 "onVendorUciNotificationReceived", 1150 "(II[B)V", 1151 &[ 1152 // Java only has signed integer. The range for signed int32 should be sufficient. 1153 jvalue::from(JValue::Int( 1154 vendor_notification 1155 .gid 1156 .try_into() 1157 .map_err(|_| JNIError::InvalidCtorReturn)?, 1158 )), 1159 jvalue::from(JValue::Int( 1160 vendor_notification 1161 .oid 1162 .try_into() 1163 .map_err(|_| JNIError::InvalidCtorReturn)?, 1164 )), 1165 jvalue::from(JValue::Object(payload_jobject)), 1166 ], 1167 ) 1168 }) 1169 .map_err(|_| UwbError::ForeignFunctionInterface)?; 1170 Ok(()) 1171 } 1172 on_data_rcv_notification( &mut self, data_rcv_notification: DataRcvNotification, ) -> UwbResult<()>1173 fn on_data_rcv_notification( 1174 &mut self, 1175 data_rcv_notification: DataRcvNotification, 1176 ) -> UwbResult<()> { 1177 debug!("UCI JNI: Data Rcv notification callback."); 1178 let env = *self.env; 1179 env.with_local_frame(MAX_JAVA_OBJECTS_CAPACITY, || { 1180 let source_address_jbytearray = match &data_rcv_notification.source_address { 1181 UwbAddress::Short(a) => self.env.byte_array_from_slice(a)?, 1182 UwbAddress::Extended(a) => self.env.byte_array_from_slice(a)?, 1183 }; 1184 let payload_jbytearray = 1185 self.env.byte_array_from_slice(&data_rcv_notification.payload)?; 1186 // Safety: source_address_jbytearray safely instantiated above. 1187 let source_address_jobject = unsafe { JObject::from_raw(source_address_jbytearray) }; 1188 // Safety: payload_jbytearray safely instantiated above. 1189 let payload_jobject = unsafe { JObject::from_raw(payload_jbytearray) }; 1190 self.cached_jni_call( 1191 "onDataReceived", 1192 "(JIJ[B[B)V", 1193 &[ 1194 // session_token below has already been mapped to session_id by uci layer. 1195 jvalue::from(JValue::Long(data_rcv_notification.session_token as i64)), 1196 jvalue::from(JValue::Int(i32::from(data_rcv_notification.status))), 1197 jvalue::from(JValue::Long(data_rcv_notification.uci_sequence_num as i64)), 1198 jvalue::from(JValue::Object(source_address_jobject)), 1199 jvalue::from(JValue::Object(payload_jobject)), 1200 ], 1201 ) 1202 }) 1203 .map_err(|_| UwbError::ForeignFunctionInterface)?; 1204 Ok(()) 1205 } 1206 on_radar_data_rcv_notification( &mut self, radar_data_rcv_notification: RadarDataRcvNotification, ) -> UwbResult<()>1207 fn on_radar_data_rcv_notification( 1208 &mut self, 1209 radar_data_rcv_notification: RadarDataRcvNotification, 1210 ) -> UwbResult<()> { 1211 debug!("UCI JNI: Radar Data Rcv notification callback."); 1212 let env = *self.env; 1213 env.with_local_frame(MAX_JAVA_OBJECTS_CAPACITY, || { 1214 let radar_sweep_data_jclass = NotificationManagerAndroid::find_local_class( 1215 &mut self.jclass_map, 1216 &self.class_loader_obj, 1217 &self.env, 1218 UWB_RADAR_SWEEP_DATA_CLASS, 1219 )?; 1220 1221 let max_sample_data_length = 1222 radar_bytes_per_sample_value(radar_data_rcv_notification.bits_per_sample) as i32 1223 * radar_data_rcv_notification.samples_per_sweep as i32; 1224 let sample_data_jbytearray = self.env.new_byte_array(max_sample_data_length)?; 1225 let vendor_data_jbytearray = self.env.new_byte_array(MAX_RADAR_VENDOR_DATA_LEN)?; 1226 1227 // Safety: sample_data_jbytearray is safely instantiated above. 1228 let sample_data_jobject = unsafe { JObject::from_raw(sample_data_jbytearray) }; 1229 // Safety: vendor_data_jbytearray is safely instantiated above. 1230 let vendor_data_jobject = unsafe { JObject::from_raw(vendor_data_jbytearray) }; 1231 1232 let sweep_data_sig: &str = "(JJ[B[B)V"; 1233 1234 let zero_initiated_sweep_data = self 1235 .env 1236 .new_object( 1237 radar_sweep_data_jclass, 1238 sweep_data_sig, 1239 &[ 1240 JValue::Long(0), 1241 JValue::Long(0), 1242 JValue::Object(vendor_data_jobject), 1243 JValue::Object(sample_data_jobject), 1244 ], 1245 ) 1246 .map_err(|e| { 1247 error!( 1248 "UCI JNI: zero initiated RadarSweepData object creation failed: {:?}", 1249 e 1250 ); 1251 e 1252 })?; 1253 1254 let radar_sweep_data_jobjectarray = self 1255 .env 1256 .new_object_array( 1257 radar_data_rcv_notification.sweep_data.len() as i32, 1258 radar_sweep_data_jclass, 1259 zero_initiated_sweep_data, 1260 ) 1261 .map_err(|e| { 1262 error!("UCI JNI: RadarSweepData object array creation failed: {:?}", e); 1263 e 1264 })?; 1265 1266 for (i, sweep_data) in radar_data_rcv_notification.sweep_data.into_iter().enumerate() { 1267 let vendor_data_jbytearray = 1268 self.env.byte_array_from_slice(&sweep_data.vendor_specific_data)?; 1269 let sample_data_jbytearray = 1270 self.env.byte_array_from_slice(&sweep_data.sample_data)?; 1271 // Safety: vendor_data_jbytearray instantiated above 1272 let vendor_data_jobject = unsafe { JObject::from_raw(vendor_data_jbytearray) }; 1273 // Safety: sample_data_jbytearray instantiated above 1274 let sample_data_jobject = unsafe { JObject::from_raw(sample_data_jbytearray) }; 1275 let sweep_data_jobject = self 1276 .env 1277 .new_object( 1278 radar_sweep_data_jclass, 1279 sweep_data_sig, 1280 &[ 1281 JValue::Long(sweep_data.sequence_number as i64), 1282 JValue::Long(sweep_data.timestamp as i64), 1283 JValue::Object(vendor_data_jobject), 1284 JValue::Object(sample_data_jobject), 1285 ], 1286 ) 1287 .map_err(|e| { 1288 error!("UCI JNI: RadarSweepData object creation failed: {:?}", e); 1289 e 1290 })?; 1291 1292 self.env 1293 .set_object_array_element( 1294 radar_sweep_data_jobjectarray, 1295 i as i32, 1296 sweep_data_jobject, 1297 ) 1298 .map_err(|e| { 1299 error!( 1300 "UCI JNI: sweep_data_jobject copy into jobjectarray failed: {:?}", 1301 e 1302 ); 1303 e 1304 })?; 1305 } 1306 1307 let radar_sweep_data_array_jobject = 1308 // Safety: radar_sweep_data_jobjectarray is safely instantiated above. 1309 unsafe { JObject::from_raw(radar_sweep_data_jobjectarray) }; 1310 1311 let radar_data_jclass = NotificationManagerAndroid::find_local_class( 1312 &mut self.jclass_map, 1313 &self.class_loader_obj, 1314 &self.env, 1315 UWB_RADAR_DATA_CLASS, 1316 )?; 1317 1318 let radar_data_jobject = self 1319 .env 1320 .new_object( 1321 radar_data_jclass, 1322 "(JIIIII[L".to_owned() + UWB_RADAR_SWEEP_DATA_CLASS + ";)V", 1323 &[ 1324 // session_token below has already been mapped to session_id by uci layer. 1325 JValue::Long(radar_data_rcv_notification.session_token as i64), 1326 JValue::Int(radar_data_rcv_notification.status as i32), 1327 JValue::Int(radar_data_rcv_notification.radar_data_type as i32), 1328 JValue::Int(radar_data_rcv_notification.samples_per_sweep as i32), 1329 JValue::Int(radar_data_rcv_notification.bits_per_sample as i32), 1330 JValue::Int(radar_data_rcv_notification.sweep_offset as i32), 1331 JValue::Object(radar_sweep_data_array_jobject), 1332 ], 1333 ) 1334 .map_err(|e| { 1335 error!("UCI JNI: UwbRadarData object creation failed: {:?}", e); 1336 e 1337 })?; 1338 1339 let method_sig = "(L".to_owned() + UWB_RADAR_DATA_CLASS + ";)V"; 1340 1341 self.cached_jni_call( 1342 "onRadarDataMessageReceived", 1343 &method_sig, 1344 &[jvalue::from(JValue::Object(radar_data_jobject))], 1345 ) 1346 }) 1347 .map_err(|_| UwbError::ForeignFunctionInterface)?; 1348 Ok(()) 1349 } 1350 } 1351 pub(crate) struct NotificationManagerAndroidBuilder { 1352 pub chip_id: String, 1353 pub vm: &'static Arc<JavaVM>, 1354 pub class_loader_obj: GlobalRef, 1355 pub callback_obj: GlobalRef, 1356 } 1357 1358 impl NotificationManagerBuilder for NotificationManagerAndroidBuilder { 1359 type NotificationManager = NotificationManagerAndroid; 1360 build(self) -> Option<Self::NotificationManager>1361 fn build(self) -> Option<Self::NotificationManager> { 1362 if let Ok(env) = self.vm.attach_current_thread() { 1363 Some(NotificationManagerAndroid { 1364 chip_id: self.chip_id, 1365 env, 1366 class_loader_obj: self.class_loader_obj, 1367 callback_obj: self.callback_obj, 1368 jmethod_id_map: HashMap::new(), 1369 jclass_map: HashMap::new(), 1370 }) 1371 } else { 1372 None 1373 } 1374 } 1375 } 1376 1377 #[cfg(test)] 1378 mod tests { 1379 use super::*; 1380 1381 #[test] test_get_two_way_ranigng_measurement_from_short_address_two_way_ranging_measurement()1382 fn test_get_two_way_ranigng_measurement_from_short_address_two_way_ranging_measurement() { 1383 let short_address_measurement = ShortAddressTwoWayRangingMeasurement { 1384 mac_address: 0x1234, 1385 status: StatusCode::UciStatusOk, 1386 nlos: 0, 1387 distance: 1, 1388 aoa_azimuth: 2, 1389 aoa_azimuth_fom: 3, 1390 aoa_elevation: 4, 1391 aoa_elevation_fom: 5, 1392 aoa_destination_azimuth: 6, 1393 aoa_destination_azimuth_fom: 7, 1394 aoa_destination_elevation: 8, 1395 aoa_destination_elevation_fom: 9, 1396 slot_index: 10, 1397 rssi: 11, 1398 }; 1399 let measurement = TwoWayRangingMeasurement::from(short_address_measurement.clone()); 1400 assert_eq!( 1401 measurement.mac_address, 1402 MacAddress::Short(short_address_measurement.mac_address) 1403 ); 1404 assert_eq!(measurement.status, short_address_measurement.status); 1405 assert_eq!(measurement.nlos, short_address_measurement.nlos); 1406 assert_eq!(measurement.distance, short_address_measurement.distance); 1407 assert_eq!(measurement.aoa_azimuth, short_address_measurement.aoa_azimuth); 1408 assert_eq!(measurement.aoa_azimuth_fom, short_address_measurement.aoa_azimuth_fom); 1409 assert_eq!(measurement.aoa_elevation, short_address_measurement.aoa_elevation); 1410 assert_eq!(measurement.aoa_elevation_fom, short_address_measurement.aoa_elevation_fom); 1411 assert_eq!( 1412 measurement.aoa_destination_azimuth, 1413 short_address_measurement.aoa_destination_azimuth 1414 ); 1415 assert_eq!( 1416 measurement.aoa_destination_azimuth_fom, 1417 short_address_measurement.aoa_destination_azimuth_fom 1418 ); 1419 assert_eq!( 1420 measurement.aoa_destination_elevation, 1421 short_address_measurement.aoa_destination_elevation 1422 ); 1423 assert_eq!( 1424 measurement.aoa_destination_elevation_fom, 1425 short_address_measurement.aoa_destination_elevation_fom 1426 ); 1427 assert_eq!(measurement.slot_index, short_address_measurement.slot_index); 1428 assert_eq!(measurement.rssi, short_address_measurement.rssi); 1429 } 1430 1431 #[test] test_get_two_way_ranigng_measurement_from_extended_address_two_way_ranging_measurement()1432 fn test_get_two_way_ranigng_measurement_from_extended_address_two_way_ranging_measurement() { 1433 let extended_address_measurement = ExtendedAddressTwoWayRangingMeasurement { 1434 mac_address: 0x1234_5678, 1435 status: StatusCode::UciStatusOk, 1436 nlos: 0, 1437 distance: 1, 1438 aoa_azimuth: 2, 1439 aoa_azimuth_fom: 3, 1440 aoa_elevation: 4, 1441 aoa_elevation_fom: 5, 1442 aoa_destination_azimuth: 6, 1443 aoa_destination_azimuth_fom: 7, 1444 aoa_destination_elevation: 8, 1445 aoa_destination_elevation_fom: 9, 1446 slot_index: 10, 1447 rssi: 11, 1448 }; 1449 let measurement = TwoWayRangingMeasurement::from(extended_address_measurement.clone()); 1450 assert_eq!( 1451 measurement.mac_address, 1452 MacAddress::Extended(extended_address_measurement.mac_address) 1453 ); 1454 assert_eq!(measurement.status, extended_address_measurement.status); 1455 assert_eq!(measurement.nlos, extended_address_measurement.nlos); 1456 assert_eq!(measurement.distance, extended_address_measurement.distance); 1457 assert_eq!(measurement.aoa_azimuth, extended_address_measurement.aoa_azimuth); 1458 assert_eq!(measurement.aoa_azimuth_fom, extended_address_measurement.aoa_azimuth_fom); 1459 assert_eq!(measurement.aoa_elevation, extended_address_measurement.aoa_elevation); 1460 assert_eq!(measurement.aoa_elevation_fom, extended_address_measurement.aoa_elevation_fom); 1461 assert_eq!( 1462 measurement.aoa_destination_azimuth, 1463 extended_address_measurement.aoa_destination_azimuth 1464 ); 1465 assert_eq!( 1466 measurement.aoa_destination_azimuth_fom, 1467 extended_address_measurement.aoa_destination_azimuth_fom 1468 ); 1469 assert_eq!( 1470 measurement.aoa_destination_elevation, 1471 extended_address_measurement.aoa_destination_elevation 1472 ); 1473 assert_eq!( 1474 measurement.aoa_destination_elevation_fom, 1475 extended_address_measurement.aoa_destination_elevation_fom 1476 ); 1477 assert_eq!(measurement.slot_index, extended_address_measurement.slot_index); 1478 assert_eq!(measurement.rssi, extended_address_measurement.rssi); 1479 } 1480 1481 #[test] test_get_owr_aoa_ranging_measurement_from_short_address_measurement()1482 fn test_get_owr_aoa_ranging_measurement_from_short_address_measurement() { 1483 let short_address_measurement = ShortAddressOwrAoaRangingMeasurement { 1484 mac_address: 0x1234, 1485 status: StatusCode::UciStatusOk, 1486 nlos: 0, 1487 frame_sequence_number: 1, 1488 block_index: 2, 1489 aoa_azimuth: 3, 1490 aoa_azimuth_fom: 4, 1491 aoa_elevation: 5, 1492 aoa_elevation_fom: 6, 1493 }; 1494 let measurement = OwrAoaRangingMeasurement::from(short_address_measurement.clone()); 1495 assert_eq!( 1496 measurement.mac_address, 1497 MacAddress::Short(short_address_measurement.mac_address) 1498 ); 1499 assert_eq!(measurement.status, short_address_measurement.status); 1500 assert_eq!(measurement.nlos, short_address_measurement.nlos); 1501 assert_eq!( 1502 measurement.frame_sequence_number, 1503 short_address_measurement.frame_sequence_number 1504 ); 1505 assert_eq!(measurement.block_index, short_address_measurement.block_index); 1506 assert_eq!(measurement.aoa_azimuth, short_address_measurement.aoa_azimuth); 1507 assert_eq!(measurement.aoa_azimuth_fom, short_address_measurement.aoa_azimuth_fom); 1508 assert_eq!(measurement.aoa_elevation, short_address_measurement.aoa_elevation); 1509 assert_eq!(measurement.aoa_elevation_fom, short_address_measurement.aoa_elevation_fom); 1510 } 1511 1512 #[test] test_get_owr_aoa_ranging_measurement_from_extended_address_measurement()1513 fn test_get_owr_aoa_ranging_measurement_from_extended_address_measurement() { 1514 let extended_address_measurement = ExtendedAddressOwrAoaRangingMeasurement { 1515 mac_address: 0x1234_5678, 1516 status: StatusCode::UciStatusOk, 1517 nlos: 0, 1518 frame_sequence_number: 1, 1519 block_index: 2, 1520 aoa_azimuth: 3, 1521 aoa_azimuth_fom: 4, 1522 aoa_elevation: 5, 1523 aoa_elevation_fom: 6, 1524 }; 1525 let measurement = OwrAoaRangingMeasurement::from(extended_address_measurement.clone()); 1526 assert_eq!( 1527 measurement.mac_address, 1528 MacAddress::Extended(extended_address_measurement.mac_address) 1529 ); 1530 assert_eq!(measurement.status, extended_address_measurement.status); 1531 assert_eq!(measurement.nlos, extended_address_measurement.nlos); 1532 assert_eq!( 1533 measurement.frame_sequence_number, 1534 extended_address_measurement.frame_sequence_number 1535 ); 1536 assert_eq!(measurement.block_index, extended_address_measurement.block_index); 1537 assert_eq!(measurement.aoa_azimuth, extended_address_measurement.aoa_azimuth); 1538 assert_eq!(measurement.aoa_azimuth_fom, extended_address_measurement.aoa_azimuth_fom); 1539 assert_eq!(measurement.aoa_elevation, extended_address_measurement.aoa_elevation); 1540 assert_eq!(measurement.aoa_elevation_fom, extended_address_measurement.aoa_elevation_fom); 1541 } 1542 1543 #[test] test_get_dl_tdoa_ranging_measurement_from_short_address_measurement()1544 fn test_get_dl_tdoa_ranging_measurement_from_short_address_measurement() { 1545 let bytes = [ 1546 // All Fields in Little Endian (LE) 1547 0x0a, 0x01, 0x33, 0x05, // 2(Mac address), Status, Message Type 1548 0x53, 0x05, 0x02, 0x05, // 2(Message control), 2(Block Index) 1549 0x07, 0x09, 0x0a, 0x01, // Round Index, NLoS, 2(AoA Azimuth) 1550 0x02, 0x05, 0x07, 0x09, // AoA Azimuth FOM, 2(AoA Elevation), AoA Elevation FOM 1551 0x0a, 0x01, 0x02, 0x05, // RSSI, 3(Tx Timestamp..) 1552 0x07, 0x09, 0x0a, 0x01, // 4(Tx Timestamp..) 1553 0x02, 0x05, 0x07, 0x09, // Tx Timestamp, 3(Rx Timestamp..) 1554 0x05, 0x07, 0x09, 0x0a, // 2(Rx Timestamp), 2(Anchor Cfo) 1555 0x01, 0x02, 0x05, 0x07, // 2(Cfo), 2(Initiator Reply Time..) 1556 0x09, 0x05, 0x07, 0x09, // 2(Initiator Reply Time), 2(Responder Reply Time..) 1557 0x0a, 0x01, 0x02, 0x05, // 2(Responder Reply Time), 2(Initiator-Responder ToF) 1558 0x07, 0x09, 0x07, 0x09, // 4(Anchor Location..) 1559 0x05, 0x07, 0x09, 0x0a, // 4(Anchor Location..) 1560 0x01, 0x02, 0x05, 0x07, // 2(Anchor Location..), 2(Active Ranging Rounds..) 1561 0x09, 0x0a, 0x01, 0x02, // 4(Active Ranging Rounds..) 1562 0x05, 0x07, 0x09, 0x05, // 4(Active Ranging Rounds) 1563 ]; 1564 let short_address_measurement_vec = 1565 ShortAddressDlTdoaRangingMeasurement::parse(&bytes, 1).unwrap(); 1566 let short_address_measurement = &short_address_measurement_vec[0]; 1567 let measurement = DlTdoaRangingMeasurement::from(short_address_measurement.clone()); 1568 assert_eq!( 1569 measurement.mac_address, 1570 MacAddress::Short(short_address_measurement.mac_address) 1571 ); 1572 assert_eq!(measurement.status, short_address_measurement.measurement.status); 1573 assert_eq!(measurement.message_type, short_address_measurement.measurement.message_type); 1574 assert_eq!( 1575 measurement.message_control, 1576 short_address_measurement.measurement.message_control 1577 ); 1578 assert_eq!(measurement.block_index, short_address_measurement.measurement.block_index); 1579 assert_eq!(measurement.round_index, short_address_measurement.measurement.round_index); 1580 assert_eq!(measurement.nlos, short_address_measurement.measurement.nlos); 1581 assert_eq!(measurement.aoa_azimuth, short_address_measurement.measurement.aoa_azimuth); 1582 assert_eq!( 1583 measurement.aoa_azimuth_fom, 1584 short_address_measurement.measurement.aoa_azimuth_fom 1585 ); 1586 assert_eq!(measurement.aoa_elevation, short_address_measurement.measurement.aoa_elevation); 1587 assert_eq!( 1588 measurement.aoa_elevation_fom, 1589 short_address_measurement.measurement.aoa_elevation_fom 1590 ); 1591 assert_eq!(measurement.rssi, short_address_measurement.measurement.rssi); 1592 assert_eq!(measurement.tx_timestamp, short_address_measurement.measurement.tx_timestamp); 1593 assert_eq!(measurement.rx_timestamp, short_address_measurement.measurement.rx_timestamp); 1594 assert_eq!(measurement.anchor_cfo, short_address_measurement.measurement.anchor_cfo); 1595 assert_eq!(measurement.cfo, short_address_measurement.measurement.cfo); 1596 assert_eq!( 1597 measurement.initiator_reply_time, 1598 short_address_measurement.measurement.initiator_reply_time 1599 ); 1600 assert_eq!( 1601 measurement.responder_reply_time, 1602 short_address_measurement.measurement.responder_reply_time 1603 ); 1604 assert_eq!( 1605 measurement.initiator_responder_tof, 1606 short_address_measurement.measurement.initiator_responder_tof 1607 ); 1608 assert_eq!( 1609 measurement.dt_anchor_location, 1610 short_address_measurement.measurement.dt_anchor_location 1611 ); 1612 assert_eq!( 1613 measurement.ranging_rounds, 1614 short_address_measurement.measurement.ranging_rounds 1615 ); 1616 } 1617 1618 #[test] test_get_dl_tdoa_ranging_measurement_from_extended_address_measurement()1619 fn test_get_dl_tdoa_ranging_measurement_from_extended_address_measurement() { 1620 let bytes = [ 1621 // All Fields in Little Endian (LE) 1622 0x0a, 0x01, 0x33, 0x05, // 4(Mac address..) 1623 0x33, 0x05, 0x02, 0x05, // 4(Mac address) 1624 0x07, 0x09, 0x0a, 0x01, // Status, Message Type, 2(Message control), 1625 0x02, 0x05, 0x07, 0x09, // 2(Block Index), Round Index, NLoS, 1626 0x0a, 0x01, 0x02, 0x05, // 2(AoA Azimuth), AoA Azimuth FOM, 1(AoA Elevation..) 1627 0x07, 0x09, 0x0a, // 1(AoA Elevation), AoA Elevation FOM, RSSI, 1628 0x01, 0x02, 0x05, 0x07, // 4(Tx Timestamp..) 1629 0x09, 0x05, 0x07, 0x09, // 4(Tx Timestamp), 1630 0x0a, 0x01, 0x02, 0x05, // 4(Rx Timestamp..) 1631 0x07, 0x09, 0x05, 0x07, // 4(Rx Timestamp) 1632 0x09, 0x0a, 0x01, 0x02, // 2(Anchor Cfo), 2(Cfo), 1633 0x05, 0x07, 0x09, 0x05, // 4(Initiator Reply Time) 1634 0x07, 0x09, 0x0a, 0x01, // 4(Responder Reply Time), 1635 0x02, 0x05, 0x02, 0x05, // 2(Initiator-Responder ToF), 2(Active Ranging Rounds) 1636 ]; 1637 let extended_address_measurement_vec = 1638 ExtendedAddressDlTdoaRangingMeasurement::parse(&bytes, 1).unwrap(); 1639 let extended_address_measurement = &extended_address_measurement_vec[0]; 1640 1641 let measurement = DlTdoaRangingMeasurement::from(extended_address_measurement.clone()); 1642 assert_eq!( 1643 measurement.mac_address, 1644 MacAddress::Extended(extended_address_measurement.mac_address) 1645 ); 1646 assert_eq!(measurement.status, extended_address_measurement.measurement.status); 1647 assert_eq!(measurement.message_type, extended_address_measurement.measurement.message_type); 1648 assert_eq!( 1649 measurement.message_control, 1650 extended_address_measurement.measurement.message_control 1651 ); 1652 assert_eq!(measurement.block_index, extended_address_measurement.measurement.block_index); 1653 assert_eq!(measurement.round_index, extended_address_measurement.measurement.round_index); 1654 assert_eq!(measurement.nlos, extended_address_measurement.measurement.nlos); 1655 assert_eq!(measurement.aoa_azimuth, extended_address_measurement.measurement.aoa_azimuth); 1656 assert_eq!( 1657 measurement.aoa_azimuth_fom, 1658 extended_address_measurement.measurement.aoa_azimuth_fom 1659 ); 1660 assert_eq!( 1661 measurement.aoa_elevation, 1662 extended_address_measurement.measurement.aoa_elevation 1663 ); 1664 assert_eq!( 1665 measurement.aoa_elevation_fom, 1666 extended_address_measurement.measurement.aoa_elevation_fom 1667 ); 1668 assert_eq!(measurement.rssi, extended_address_measurement.measurement.rssi); 1669 assert_eq!(measurement.tx_timestamp, extended_address_measurement.measurement.tx_timestamp); 1670 assert_eq!(measurement.rx_timestamp, extended_address_measurement.measurement.rx_timestamp); 1671 assert_eq!(measurement.anchor_cfo, extended_address_measurement.measurement.anchor_cfo); 1672 assert_eq!(measurement.cfo, extended_address_measurement.measurement.cfo); 1673 assert_eq!( 1674 measurement.initiator_reply_time, 1675 extended_address_measurement.measurement.initiator_reply_time 1676 ); 1677 assert_eq!( 1678 measurement.responder_reply_time, 1679 extended_address_measurement.measurement.responder_reply_time 1680 ); 1681 assert_eq!( 1682 measurement.initiator_responder_tof, 1683 extended_address_measurement.measurement.initiator_responder_tof 1684 ); 1685 assert_eq!( 1686 measurement.dt_anchor_location, 1687 extended_address_measurement.measurement.dt_anchor_location 1688 ); 1689 assert_eq!( 1690 measurement.ranging_rounds, 1691 extended_address_measurement.measurement.ranging_rounds 1692 ); 1693 } 1694 } 1695