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, RFTEST_PERIODIC_TX_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 RfTestNotification, 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 on_rf_periodic_tx_notification( &mut self, status: u8, raw_notification_data: &[u8], ) -> Result<JObject, JNIError>1012 fn on_rf_periodic_tx_notification( 1013 &mut self, 1014 status: u8, 1015 raw_notification_data: &[u8], 1016 ) -> Result<JObject, JNIError> { 1017 let raw_notification_jbytearray = self.env.byte_array_from_slice(raw_notification_data)?; 1018 // Safety: raw_notification_jbytearray safely instantiated above. 1019 let raw_notification_jobject = unsafe { JObject::from_raw(raw_notification_jbytearray) }; 1020 1021 let periodic_tx_jclass = NotificationManagerAndroid::find_local_class( 1022 &mut self.jclass_map, 1023 &self.class_loader_obj, 1024 &self.env, 1025 RFTEST_PERIODIC_TX_CLASS, 1026 )?; 1027 let method_sig = "(L".to_owned() + RFTEST_PERIODIC_TX_CLASS + ";)V"; 1028 1029 let periodic_tx_jobject = self.env.new_object( 1030 periodic_tx_jclass, 1031 "(I[B)V", 1032 &[JValue::Int(status as i32), JValue::Object(raw_notification_jobject)], 1033 )?; 1034 self.cached_jni_call( 1035 "onPeriodicTxDataNotificationReceived", 1036 &method_sig, 1037 &[jvalue::from(JValue::Object(periodic_tx_jobject))], 1038 ) 1039 } 1040 } 1041 1042 impl NotificationManager for NotificationManagerAndroid { on_core_notification(&mut self, core_notification: CoreNotification) -> UwbResult<()>1043 fn on_core_notification(&mut self, core_notification: CoreNotification) -> UwbResult<()> { 1044 debug!("UCI JNI: core notification callback."); 1045 let env = *self.env; 1046 env.with_local_frame(MAX_JAVA_OBJECTS_CAPACITY, || { 1047 let env_chip_id_jobject = *env.new_string(&self.chip_id).map_err(|e| { 1048 error!("UCI JNI: failed to create Java String: {e:?}"); 1049 e 1050 })?; 1051 1052 match core_notification { 1053 CoreNotification::DeviceStatus(device_state) => self.cached_jni_call( 1054 "onDeviceStatusNotificationReceived", 1055 "(ILjava/lang/String;)V", 1056 &[ 1057 jvalue::from(JValue::Int(device_state as i32)), 1058 jvalue::from(JValue::Object(env_chip_id_jobject)), 1059 ], 1060 ), 1061 CoreNotification::GenericError(generic_error) => self.cached_jni_call( 1062 "onCoreGenericErrorNotificationReceived", 1063 "(ILjava/lang/String;)V", 1064 &[ 1065 jvalue::from(JValue::Int(i32::from(generic_error))), 1066 jvalue::from(JValue::Object(env_chip_id_jobject)), 1067 ], 1068 ), 1069 } 1070 }) 1071 .map_err(|e| { 1072 error!("on_core_notification error: {:?}", e); 1073 UwbError::ForeignFunctionInterface 1074 })?; 1075 1076 Ok(()) 1077 } 1078 on_session_notification( &mut self, session_notification: SessionNotification, ) -> UwbResult<()>1079 fn on_session_notification( 1080 &mut self, 1081 session_notification: SessionNotification, 1082 ) -> UwbResult<()> { 1083 debug!("UCI JNI: session notification callback."); 1084 let env = *self.env; 1085 env.with_local_frame(MAX_JAVA_OBJECTS_CAPACITY, || { 1086 match session_notification { 1087 SessionNotification::Status { 1088 session_id, 1089 session_token, 1090 session_state, 1091 reason_code, 1092 } => self.on_session_status_notification( 1093 session_id, 1094 session_token, 1095 session_state, 1096 reason_code, 1097 ), 1098 SessionNotification::UpdateControllerMulticastListV1 { 1099 session_token, 1100 remaining_multicast_list_size, 1101 status_list, 1102 } => self.on_session_update_multicast_notification( 1103 session_token, 1104 remaining_multicast_list_size, 1105 ControleeStatusList::V1(status_list), 1106 ), 1107 SessionNotification::UpdateControllerMulticastListV2 { 1108 session_token, 1109 status_list, 1110 } => self.on_session_update_multicast_notification( 1111 session_token, 1112 0_usize, 1113 ControleeStatusList::V2(status_list), 1114 ), 1115 // TODO(b/246678053): Match here on range_data.ranging_measurement_type instead. 1116 SessionNotification::SessionInfo(range_data) => { 1117 match range_data.ranging_measurements { 1118 uwb_core::uci::RangingMeasurements::ShortAddressTwoWay(_) => { 1119 self.on_session_two_way_range_data_notification(range_data) 1120 } 1121 uwb_core::uci::RangingMeasurements::ExtendedAddressTwoWay(_) => { 1122 self.on_session_two_way_range_data_notification(range_data) 1123 } 1124 uwb_core::uci::RangingMeasurements::ShortAddressOwrAoa(_) => { 1125 self.on_session_owr_aoa_range_data_notification(range_data) 1126 } 1127 uwb_core::uci::RangingMeasurements::ExtendedAddressOwrAoa(_) => { 1128 self.on_session_owr_aoa_range_data_notification(range_data) 1129 } 1130 uwb_core::uci::RangingMeasurements::ShortAddressDltdoa(_) => { 1131 self.on_session_dl_tdoa_range_data_notification(range_data) 1132 } 1133 uwb_core::uci::RangingMeasurements::ExtendedAddressDltdoa(_) => { 1134 self.on_session_dl_tdoa_range_data_notification(range_data) 1135 } 1136 } 1137 } 1138 SessionNotification::DataTransferStatus { 1139 session_token, 1140 uci_sequence_number, 1141 status, 1142 tx_count, 1143 } => self.on_data_transfer_status_notification( 1144 session_token, 1145 uci_sequence_number, 1146 u8::from(status), 1147 tx_count, 1148 ), 1149 // This session notification should not come here, as it's handled within 1150 // UciManager, for internal state management related to sending data packet(s). 1151 SessionNotification::DataCredit { session_token, credit_availability } => { 1152 error!( 1153 "UCI JNI: Received unexpected DataCredit notification for \ 1154 session_token {}, credit_availability {:?}", 1155 session_token, credit_availability 1156 ); 1157 Err(JNIError::InvalidCtorReturn) 1158 } 1159 SessionNotification::DataTransferPhaseConfig { session_token, status } => { 1160 self.on_data_transfer_phase_config_notification(session_token, u8::from(status)) 1161 } 1162 } 1163 }) 1164 .map_err(|e| { 1165 error!("on_session_notification error {:?}", e); 1166 UwbError::ForeignFunctionInterface 1167 })?; 1168 Ok(()) 1169 } 1170 on_vendor_notification( &mut self, vendor_notification: uwb_core::params::RawUciMessage, ) -> UwbResult<()>1171 fn on_vendor_notification( 1172 &mut self, 1173 vendor_notification: uwb_core::params::RawUciMessage, 1174 ) -> UwbResult<()> { 1175 debug!("UCI JNI: vendor notification callback."); 1176 let env = *self.env; 1177 env.with_local_frame(MAX_JAVA_OBJECTS_CAPACITY, || { 1178 let payload_jbytearray = 1179 self.env.byte_array_from_slice(&vendor_notification.payload)?; 1180 1181 // Safety: payload_jbytearray safely instantiated above. 1182 let payload_jobject = unsafe { JObject::from_raw(payload_jbytearray) }; 1183 self.cached_jni_call( 1184 "onVendorUciNotificationReceived", 1185 "(II[B)V", 1186 &[ 1187 // Java only has signed integer. The range for signed int32 should be sufficient. 1188 jvalue::from(JValue::Int( 1189 vendor_notification 1190 .gid 1191 .try_into() 1192 .map_err(|_| JNIError::InvalidCtorReturn)?, 1193 )), 1194 jvalue::from(JValue::Int( 1195 vendor_notification 1196 .oid 1197 .try_into() 1198 .map_err(|_| JNIError::InvalidCtorReturn)?, 1199 )), 1200 jvalue::from(JValue::Object(payload_jobject)), 1201 ], 1202 ) 1203 }) 1204 .map_err(|e| { 1205 error!("on_vendor_notification error: {:?}", e); 1206 UwbError::ForeignFunctionInterface 1207 })?; 1208 Ok(()) 1209 } 1210 on_data_rcv_notification( &mut self, data_rcv_notification: DataRcvNotification, ) -> UwbResult<()>1211 fn on_data_rcv_notification( 1212 &mut self, 1213 data_rcv_notification: DataRcvNotification, 1214 ) -> UwbResult<()> { 1215 debug!("UCI JNI: Data Rcv notification callback."); 1216 let env = *self.env; 1217 env.with_local_frame(MAX_JAVA_OBJECTS_CAPACITY, || { 1218 let source_address_jbytearray = match &data_rcv_notification.source_address { 1219 UwbAddress::Short(a) => self.env.byte_array_from_slice(a)?, 1220 UwbAddress::Extended(a) => self.env.byte_array_from_slice(a)?, 1221 }; 1222 let payload_jbytearray = 1223 self.env.byte_array_from_slice(&data_rcv_notification.payload)?; 1224 // Safety: source_address_jbytearray safely instantiated above. 1225 let source_address_jobject = unsafe { JObject::from_raw(source_address_jbytearray) }; 1226 // Safety: payload_jbytearray safely instantiated above. 1227 let payload_jobject = unsafe { JObject::from_raw(payload_jbytearray) }; 1228 self.cached_jni_call( 1229 "onDataReceived", 1230 "(JIJ[B[B)V", 1231 &[ 1232 // session_token below has already been mapped to session_id by uci layer. 1233 jvalue::from(JValue::Long(data_rcv_notification.session_token as i64)), 1234 jvalue::from(JValue::Int(i32::from(data_rcv_notification.status))), 1235 jvalue::from(JValue::Long(data_rcv_notification.uci_sequence_num as i64)), 1236 jvalue::from(JValue::Object(source_address_jobject)), 1237 jvalue::from(JValue::Object(payload_jobject)), 1238 ], 1239 ) 1240 }) 1241 .map_err(|e| { 1242 error!("on_data_rcv_notification error: {:?}", e); 1243 UwbError::ForeignFunctionInterface 1244 })?; 1245 Ok(()) 1246 } 1247 on_radar_data_rcv_notification( &mut self, radar_data_rcv_notification: RadarDataRcvNotification, ) -> UwbResult<()>1248 fn on_radar_data_rcv_notification( 1249 &mut self, 1250 radar_data_rcv_notification: RadarDataRcvNotification, 1251 ) -> UwbResult<()> { 1252 debug!("UCI JNI: Radar Data Rcv notification callback."); 1253 let env = *self.env; 1254 env.with_local_frame(MAX_JAVA_OBJECTS_CAPACITY, || { 1255 let radar_sweep_data_jclass = NotificationManagerAndroid::find_local_class( 1256 &mut self.jclass_map, 1257 &self.class_loader_obj, 1258 &self.env, 1259 UWB_RADAR_SWEEP_DATA_CLASS, 1260 )?; 1261 1262 let max_sample_data_length = 1263 radar_bytes_per_sample_value(radar_data_rcv_notification.bits_per_sample) as i32 1264 * radar_data_rcv_notification.samples_per_sweep as i32; 1265 let sample_data_jbytearray = self.env.new_byte_array(max_sample_data_length)?; 1266 let vendor_data_jbytearray = self.env.new_byte_array(MAX_RADAR_VENDOR_DATA_LEN)?; 1267 1268 // Safety: sample_data_jbytearray is safely instantiated above. 1269 let sample_data_jobject = unsafe { JObject::from_raw(sample_data_jbytearray) }; 1270 // Safety: vendor_data_jbytearray is safely instantiated above. 1271 let vendor_data_jobject = unsafe { JObject::from_raw(vendor_data_jbytearray) }; 1272 1273 let sweep_data_sig: &str = "(JJ[B[B)V"; 1274 1275 let zero_initiated_sweep_data = self 1276 .env 1277 .new_object( 1278 radar_sweep_data_jclass, 1279 sweep_data_sig, 1280 &[ 1281 JValue::Long(0), 1282 JValue::Long(0), 1283 JValue::Object(vendor_data_jobject), 1284 JValue::Object(sample_data_jobject), 1285 ], 1286 ) 1287 .map_err(|e| { 1288 error!( 1289 "UCI JNI: zero initiated RadarSweepData object creation failed: {:?}", 1290 e 1291 ); 1292 e 1293 })?; 1294 1295 let radar_sweep_data_jobjectarray = self 1296 .env 1297 .new_object_array( 1298 radar_data_rcv_notification.sweep_data.len() as i32, 1299 radar_sweep_data_jclass, 1300 zero_initiated_sweep_data, 1301 ) 1302 .map_err(|e| { 1303 error!("UCI JNI: RadarSweepData object array creation failed: {:?}", e); 1304 e 1305 })?; 1306 1307 for (i, sweep_data) in radar_data_rcv_notification.sweep_data.into_iter().enumerate() { 1308 let vendor_data_jbytearray = 1309 self.env.byte_array_from_slice(&sweep_data.vendor_specific_data)?; 1310 let sample_data_jbytearray = 1311 self.env.byte_array_from_slice(&sweep_data.sample_data)?; 1312 // Safety: vendor_data_jbytearray instantiated above 1313 let vendor_data_jobject = unsafe { JObject::from_raw(vendor_data_jbytearray) }; 1314 // Safety: sample_data_jbytearray instantiated above 1315 let sample_data_jobject = unsafe { JObject::from_raw(sample_data_jbytearray) }; 1316 let sweep_data_jobject = self 1317 .env 1318 .new_object( 1319 radar_sweep_data_jclass, 1320 sweep_data_sig, 1321 &[ 1322 JValue::Long(sweep_data.sequence_number as i64), 1323 JValue::Long(sweep_data.timestamp as i64), 1324 JValue::Object(vendor_data_jobject), 1325 JValue::Object(sample_data_jobject), 1326 ], 1327 ) 1328 .map_err(|e| { 1329 error!("UCI JNI: RadarSweepData object creation failed: {:?}", e); 1330 e 1331 })?; 1332 1333 self.env 1334 .set_object_array_element( 1335 radar_sweep_data_jobjectarray, 1336 i as i32, 1337 sweep_data_jobject, 1338 ) 1339 .map_err(|e| { 1340 error!( 1341 "UCI JNI: sweep_data_jobject copy into jobjectarray failed: {:?}", 1342 e 1343 ); 1344 e 1345 })?; 1346 } 1347 1348 let radar_sweep_data_array_jobject = 1349 // Safety: radar_sweep_data_jobjectarray is safely instantiated above. 1350 unsafe { JObject::from_raw(radar_sweep_data_jobjectarray) }; 1351 1352 let radar_data_jclass = NotificationManagerAndroid::find_local_class( 1353 &mut self.jclass_map, 1354 &self.class_loader_obj, 1355 &self.env, 1356 UWB_RADAR_DATA_CLASS, 1357 )?; 1358 1359 let radar_data_jobject = self 1360 .env 1361 .new_object( 1362 radar_data_jclass, 1363 "(JIIIII[L".to_owned() + UWB_RADAR_SWEEP_DATA_CLASS + ";)V", 1364 &[ 1365 // session_token below has already been mapped to session_id by uci layer. 1366 JValue::Long(radar_data_rcv_notification.session_token as i64), 1367 JValue::Int(radar_data_rcv_notification.status as i32), 1368 JValue::Int(radar_data_rcv_notification.radar_data_type as i32), 1369 JValue::Int(radar_data_rcv_notification.samples_per_sweep as i32), 1370 JValue::Int(radar_data_rcv_notification.bits_per_sample as i32), 1371 JValue::Int(radar_data_rcv_notification.sweep_offset as i32), 1372 JValue::Object(radar_sweep_data_array_jobject), 1373 ], 1374 ) 1375 .map_err(|e| { 1376 error!("UCI JNI: UwbRadarData object creation failed: {:?}", e); 1377 e 1378 })?; 1379 1380 let method_sig = "(L".to_owned() + UWB_RADAR_DATA_CLASS + ";)V"; 1381 1382 self.cached_jni_call( 1383 "onRadarDataMessageReceived", 1384 &method_sig, 1385 &[jvalue::from(JValue::Object(radar_data_jobject))], 1386 ) 1387 }) 1388 .map_err(|e| { 1389 error!("on_radar_data_rcv_notification error: {:?}", e); 1390 UwbError::ForeignFunctionInterface 1391 })?; 1392 Ok(()) 1393 } 1394 on_rf_test_notification( &mut self, rf_test_notification: RfTestNotification, ) -> UwbResult<()>1395 fn on_rf_test_notification( 1396 &mut self, 1397 rf_test_notification: RfTestNotification, 1398 ) -> UwbResult<()> { 1399 debug!("UCI JNI: RF test notification callback."); 1400 let env = *self.env; 1401 env.with_local_frame(MAX_JAVA_OBJECTS_CAPACITY, || match rf_test_notification { 1402 RfTestNotification::TestPeriodicTxNtf { status, raw_notification_data } => { 1403 self.on_rf_periodic_tx_notification(u8::from(status), &raw_notification_data) 1404 } 1405 }) 1406 .map_err(|e| { 1407 error!("on_rf_test_notification error: {:?}", e); 1408 UwbError::ForeignFunctionInterface 1409 })?; 1410 Ok(()) 1411 } 1412 } 1413 pub(crate) struct NotificationManagerAndroidBuilder { 1414 pub chip_id: String, 1415 pub vm: &'static Arc<JavaVM>, 1416 pub class_loader_obj: GlobalRef, 1417 pub callback_obj: GlobalRef, 1418 } 1419 1420 impl NotificationManagerBuilder for NotificationManagerAndroidBuilder { 1421 type NotificationManager = NotificationManagerAndroid; 1422 build(self) -> Option<Self::NotificationManager>1423 fn build(self) -> Option<Self::NotificationManager> { 1424 if let Ok(env) = self.vm.attach_current_thread() { 1425 Some(NotificationManagerAndroid { 1426 chip_id: self.chip_id, 1427 env, 1428 class_loader_obj: self.class_loader_obj, 1429 callback_obj: self.callback_obj, 1430 jmethod_id_map: HashMap::new(), 1431 jclass_map: HashMap::new(), 1432 }) 1433 } else { 1434 None 1435 } 1436 } 1437 } 1438 1439 #[cfg(test)] 1440 mod tests { 1441 use super::*; 1442 1443 #[test] test_get_two_way_ranigng_measurement_from_short_address_two_way_ranging_measurement()1444 fn test_get_two_way_ranigng_measurement_from_short_address_two_way_ranging_measurement() { 1445 let short_address_measurement = ShortAddressTwoWayRangingMeasurement { 1446 mac_address: 0x1234, 1447 status: StatusCode::UciStatusOk, 1448 nlos: 0, 1449 distance: 1, 1450 aoa_azimuth: 2, 1451 aoa_azimuth_fom: 3, 1452 aoa_elevation: 4, 1453 aoa_elevation_fom: 5, 1454 aoa_destination_azimuth: 6, 1455 aoa_destination_azimuth_fom: 7, 1456 aoa_destination_elevation: 8, 1457 aoa_destination_elevation_fom: 9, 1458 slot_index: 10, 1459 rssi: 11, 1460 }; 1461 let measurement = TwoWayRangingMeasurement::from(short_address_measurement.clone()); 1462 assert_eq!( 1463 measurement.mac_address, 1464 MacAddress::Short(short_address_measurement.mac_address) 1465 ); 1466 assert_eq!(measurement.status, short_address_measurement.status); 1467 assert_eq!(measurement.nlos, short_address_measurement.nlos); 1468 assert_eq!(measurement.distance, short_address_measurement.distance); 1469 assert_eq!(measurement.aoa_azimuth, short_address_measurement.aoa_azimuth); 1470 assert_eq!(measurement.aoa_azimuth_fom, short_address_measurement.aoa_azimuth_fom); 1471 assert_eq!(measurement.aoa_elevation, short_address_measurement.aoa_elevation); 1472 assert_eq!(measurement.aoa_elevation_fom, short_address_measurement.aoa_elevation_fom); 1473 assert_eq!( 1474 measurement.aoa_destination_azimuth, 1475 short_address_measurement.aoa_destination_azimuth 1476 ); 1477 assert_eq!( 1478 measurement.aoa_destination_azimuth_fom, 1479 short_address_measurement.aoa_destination_azimuth_fom 1480 ); 1481 assert_eq!( 1482 measurement.aoa_destination_elevation, 1483 short_address_measurement.aoa_destination_elevation 1484 ); 1485 assert_eq!( 1486 measurement.aoa_destination_elevation_fom, 1487 short_address_measurement.aoa_destination_elevation_fom 1488 ); 1489 assert_eq!(measurement.slot_index, short_address_measurement.slot_index); 1490 assert_eq!(measurement.rssi, short_address_measurement.rssi); 1491 } 1492 1493 #[test] test_get_two_way_ranigng_measurement_from_extended_address_two_way_ranging_measurement()1494 fn test_get_two_way_ranigng_measurement_from_extended_address_two_way_ranging_measurement() { 1495 let extended_address_measurement = ExtendedAddressTwoWayRangingMeasurement { 1496 mac_address: 0x1234_5678, 1497 status: StatusCode::UciStatusOk, 1498 nlos: 0, 1499 distance: 1, 1500 aoa_azimuth: 2, 1501 aoa_azimuth_fom: 3, 1502 aoa_elevation: 4, 1503 aoa_elevation_fom: 5, 1504 aoa_destination_azimuth: 6, 1505 aoa_destination_azimuth_fom: 7, 1506 aoa_destination_elevation: 8, 1507 aoa_destination_elevation_fom: 9, 1508 slot_index: 10, 1509 rssi: 11, 1510 }; 1511 let measurement = TwoWayRangingMeasurement::from(extended_address_measurement.clone()); 1512 assert_eq!( 1513 measurement.mac_address, 1514 MacAddress::Extended(extended_address_measurement.mac_address) 1515 ); 1516 assert_eq!(measurement.status, extended_address_measurement.status); 1517 assert_eq!(measurement.nlos, extended_address_measurement.nlos); 1518 assert_eq!(measurement.distance, extended_address_measurement.distance); 1519 assert_eq!(measurement.aoa_azimuth, extended_address_measurement.aoa_azimuth); 1520 assert_eq!(measurement.aoa_azimuth_fom, extended_address_measurement.aoa_azimuth_fom); 1521 assert_eq!(measurement.aoa_elevation, extended_address_measurement.aoa_elevation); 1522 assert_eq!(measurement.aoa_elevation_fom, extended_address_measurement.aoa_elevation_fom); 1523 assert_eq!( 1524 measurement.aoa_destination_azimuth, 1525 extended_address_measurement.aoa_destination_azimuth 1526 ); 1527 assert_eq!( 1528 measurement.aoa_destination_azimuth_fom, 1529 extended_address_measurement.aoa_destination_azimuth_fom 1530 ); 1531 assert_eq!( 1532 measurement.aoa_destination_elevation, 1533 extended_address_measurement.aoa_destination_elevation 1534 ); 1535 assert_eq!( 1536 measurement.aoa_destination_elevation_fom, 1537 extended_address_measurement.aoa_destination_elevation_fom 1538 ); 1539 assert_eq!(measurement.slot_index, extended_address_measurement.slot_index); 1540 assert_eq!(measurement.rssi, extended_address_measurement.rssi); 1541 } 1542 1543 #[test] test_get_owr_aoa_ranging_measurement_from_short_address_measurement()1544 fn test_get_owr_aoa_ranging_measurement_from_short_address_measurement() { 1545 let short_address_measurement = ShortAddressOwrAoaRangingMeasurement { 1546 mac_address: 0x1234, 1547 status: StatusCode::UciStatusOk, 1548 nlos: 0, 1549 frame_sequence_number: 1, 1550 block_index: 2, 1551 aoa_azimuth: 3, 1552 aoa_azimuth_fom: 4, 1553 aoa_elevation: 5, 1554 aoa_elevation_fom: 6, 1555 }; 1556 let measurement = OwrAoaRangingMeasurement::from(short_address_measurement.clone()); 1557 assert_eq!( 1558 measurement.mac_address, 1559 MacAddress::Short(short_address_measurement.mac_address) 1560 ); 1561 assert_eq!(measurement.status, short_address_measurement.status); 1562 assert_eq!(measurement.nlos, short_address_measurement.nlos); 1563 assert_eq!( 1564 measurement.frame_sequence_number, 1565 short_address_measurement.frame_sequence_number 1566 ); 1567 assert_eq!(measurement.block_index, short_address_measurement.block_index); 1568 assert_eq!(measurement.aoa_azimuth, short_address_measurement.aoa_azimuth); 1569 assert_eq!(measurement.aoa_azimuth_fom, short_address_measurement.aoa_azimuth_fom); 1570 assert_eq!(measurement.aoa_elevation, short_address_measurement.aoa_elevation); 1571 assert_eq!(measurement.aoa_elevation_fom, short_address_measurement.aoa_elevation_fom); 1572 } 1573 1574 #[test] test_get_owr_aoa_ranging_measurement_from_extended_address_measurement()1575 fn test_get_owr_aoa_ranging_measurement_from_extended_address_measurement() { 1576 let extended_address_measurement = ExtendedAddressOwrAoaRangingMeasurement { 1577 mac_address: 0x1234_5678, 1578 status: StatusCode::UciStatusOk, 1579 nlos: 0, 1580 frame_sequence_number: 1, 1581 block_index: 2, 1582 aoa_azimuth: 3, 1583 aoa_azimuth_fom: 4, 1584 aoa_elevation: 5, 1585 aoa_elevation_fom: 6, 1586 }; 1587 let measurement = OwrAoaRangingMeasurement::from(extended_address_measurement.clone()); 1588 assert_eq!( 1589 measurement.mac_address, 1590 MacAddress::Extended(extended_address_measurement.mac_address) 1591 ); 1592 assert_eq!(measurement.status, extended_address_measurement.status); 1593 assert_eq!(measurement.nlos, extended_address_measurement.nlos); 1594 assert_eq!( 1595 measurement.frame_sequence_number, 1596 extended_address_measurement.frame_sequence_number 1597 ); 1598 assert_eq!(measurement.block_index, extended_address_measurement.block_index); 1599 assert_eq!(measurement.aoa_azimuth, extended_address_measurement.aoa_azimuth); 1600 assert_eq!(measurement.aoa_azimuth_fom, extended_address_measurement.aoa_azimuth_fom); 1601 assert_eq!(measurement.aoa_elevation, extended_address_measurement.aoa_elevation); 1602 assert_eq!(measurement.aoa_elevation_fom, extended_address_measurement.aoa_elevation_fom); 1603 } 1604 1605 #[test] test_get_dl_tdoa_ranging_measurement_from_short_address_measurement()1606 fn test_get_dl_tdoa_ranging_measurement_from_short_address_measurement() { 1607 let bytes = [ 1608 // All Fields in Little Endian (LE) 1609 0x0a, 0x01, 0x33, 0x05, // 2(Mac address), Status, Message Type 1610 0x53, 0x05, 0x02, 0x05, // 2(Message control), 2(Block Index) 1611 0x07, 0x09, 0x0a, 0x01, // Round Index, NLoS, 2(AoA Azimuth) 1612 0x02, 0x05, 0x07, 0x09, // AoA Azimuth FOM, 2(AoA Elevation), AoA Elevation FOM 1613 0x0a, 0x01, 0x02, 0x05, // RSSI, 3(Tx Timestamp..) 1614 0x07, 0x09, 0x0a, 0x01, // 4(Tx Timestamp..) 1615 0x02, 0x05, 0x07, 0x09, // Tx Timestamp, 3(Rx Timestamp..) 1616 0x05, 0x07, 0x09, 0x0a, // 2(Rx Timestamp), 2(Anchor Cfo) 1617 0x01, 0x02, 0x05, 0x07, // 2(Cfo), 2(Initiator Reply Time..) 1618 0x09, 0x05, 0x07, 0x09, // 2(Initiator Reply Time), 2(Responder Reply Time..) 1619 0x0a, 0x01, 0x02, 0x05, // 2(Responder Reply Time), 2(Initiator-Responder ToF) 1620 0x07, 0x09, 0x07, 0x09, // 4(Anchor Location..) 1621 0x05, 0x07, 0x09, 0x0a, // 4(Anchor Location..) 1622 0x01, 0x02, 0x05, 0x07, // 2(Anchor Location..), 2(Active Ranging Rounds..) 1623 0x09, 0x0a, 0x01, 0x02, // 4(Active Ranging Rounds..) 1624 0x05, 0x07, 0x09, 0x05, // 4(Active Ranging Rounds) 1625 ]; 1626 let short_address_measurement_vec = 1627 ShortAddressDlTdoaRangingMeasurement::parse(&bytes, 1).unwrap(); 1628 let short_address_measurement = &short_address_measurement_vec[0]; 1629 let measurement = DlTdoaRangingMeasurement::from(short_address_measurement.clone()); 1630 assert_eq!( 1631 measurement.mac_address, 1632 MacAddress::Short(short_address_measurement.mac_address) 1633 ); 1634 assert_eq!(measurement.status, short_address_measurement.measurement.status); 1635 assert_eq!(measurement.message_type, short_address_measurement.measurement.message_type); 1636 assert_eq!( 1637 measurement.message_control, 1638 short_address_measurement.measurement.message_control 1639 ); 1640 assert_eq!(measurement.block_index, short_address_measurement.measurement.block_index); 1641 assert_eq!(measurement.round_index, short_address_measurement.measurement.round_index); 1642 assert_eq!(measurement.nlos, short_address_measurement.measurement.nlos); 1643 assert_eq!(measurement.aoa_azimuth, short_address_measurement.measurement.aoa_azimuth); 1644 assert_eq!( 1645 measurement.aoa_azimuth_fom, 1646 short_address_measurement.measurement.aoa_azimuth_fom 1647 ); 1648 assert_eq!(measurement.aoa_elevation, short_address_measurement.measurement.aoa_elevation); 1649 assert_eq!( 1650 measurement.aoa_elevation_fom, 1651 short_address_measurement.measurement.aoa_elevation_fom 1652 ); 1653 assert_eq!(measurement.rssi, short_address_measurement.measurement.rssi); 1654 assert_eq!(measurement.tx_timestamp, short_address_measurement.measurement.tx_timestamp); 1655 assert_eq!(measurement.rx_timestamp, short_address_measurement.measurement.rx_timestamp); 1656 assert_eq!(measurement.anchor_cfo, short_address_measurement.measurement.anchor_cfo); 1657 assert_eq!(measurement.cfo, short_address_measurement.measurement.cfo); 1658 assert_eq!( 1659 measurement.initiator_reply_time, 1660 short_address_measurement.measurement.initiator_reply_time 1661 ); 1662 assert_eq!( 1663 measurement.responder_reply_time, 1664 short_address_measurement.measurement.responder_reply_time 1665 ); 1666 assert_eq!( 1667 measurement.initiator_responder_tof, 1668 short_address_measurement.measurement.initiator_responder_tof 1669 ); 1670 assert_eq!( 1671 measurement.dt_anchor_location, 1672 short_address_measurement.measurement.dt_anchor_location 1673 ); 1674 assert_eq!( 1675 measurement.ranging_rounds, 1676 short_address_measurement.measurement.ranging_rounds 1677 ); 1678 } 1679 1680 #[test] test_get_dl_tdoa_ranging_measurement_from_extended_address_measurement()1681 fn test_get_dl_tdoa_ranging_measurement_from_extended_address_measurement() { 1682 let bytes = [ 1683 // All Fields in Little Endian (LE) 1684 0x0a, 0x01, 0x33, 0x05, // 4(Mac address..) 1685 0x33, 0x05, 0x02, 0x05, // 4(Mac address) 1686 0x07, 0x09, 0x0a, 0x01, // Status, Message Type, 2(Message control), 1687 0x02, 0x05, 0x07, 0x09, // 2(Block Index), Round Index, NLoS, 1688 0x0a, 0x01, 0x02, 0x05, // 2(AoA Azimuth), AoA Azimuth FOM, 1(AoA Elevation..) 1689 0x07, 0x09, 0x0a, // 1(AoA Elevation), AoA Elevation FOM, RSSI, 1690 0x01, 0x02, 0x05, 0x07, // 4(Tx Timestamp..) 1691 0x09, 0x05, 0x07, 0x09, // 4(Tx Timestamp), 1692 0x0a, 0x01, 0x02, 0x05, // 4(Rx Timestamp..) 1693 0x07, 0x09, 0x05, 0x07, // 4(Rx Timestamp) 1694 0x09, 0x0a, 0x01, 0x02, // 2(Anchor Cfo), 2(Cfo), 1695 0x05, 0x07, 0x09, 0x05, // 4(Initiator Reply Time) 1696 0x07, 0x09, 0x0a, 0x01, // 4(Responder Reply Time), 1697 0x02, 0x05, 0x02, 0x05, // 2(Initiator-Responder ToF), 2(Active Ranging Rounds) 1698 ]; 1699 let extended_address_measurement_vec = 1700 ExtendedAddressDlTdoaRangingMeasurement::parse(&bytes, 1).unwrap(); 1701 let extended_address_measurement = &extended_address_measurement_vec[0]; 1702 1703 let measurement = DlTdoaRangingMeasurement::from(extended_address_measurement.clone()); 1704 assert_eq!( 1705 measurement.mac_address, 1706 MacAddress::Extended(extended_address_measurement.mac_address) 1707 ); 1708 assert_eq!(measurement.status, extended_address_measurement.measurement.status); 1709 assert_eq!(measurement.message_type, extended_address_measurement.measurement.message_type); 1710 assert_eq!( 1711 measurement.message_control, 1712 extended_address_measurement.measurement.message_control 1713 ); 1714 assert_eq!(measurement.block_index, extended_address_measurement.measurement.block_index); 1715 assert_eq!(measurement.round_index, extended_address_measurement.measurement.round_index); 1716 assert_eq!(measurement.nlos, extended_address_measurement.measurement.nlos); 1717 assert_eq!(measurement.aoa_azimuth, extended_address_measurement.measurement.aoa_azimuth); 1718 assert_eq!( 1719 measurement.aoa_azimuth_fom, 1720 extended_address_measurement.measurement.aoa_azimuth_fom 1721 ); 1722 assert_eq!( 1723 measurement.aoa_elevation, 1724 extended_address_measurement.measurement.aoa_elevation 1725 ); 1726 assert_eq!( 1727 measurement.aoa_elevation_fom, 1728 extended_address_measurement.measurement.aoa_elevation_fom 1729 ); 1730 assert_eq!(measurement.rssi, extended_address_measurement.measurement.rssi); 1731 assert_eq!(measurement.tx_timestamp, extended_address_measurement.measurement.tx_timestamp); 1732 assert_eq!(measurement.rx_timestamp, extended_address_measurement.measurement.rx_timestamp); 1733 assert_eq!(measurement.anchor_cfo, extended_address_measurement.measurement.anchor_cfo); 1734 assert_eq!(measurement.cfo, extended_address_measurement.measurement.cfo); 1735 assert_eq!( 1736 measurement.initiator_reply_time, 1737 extended_address_measurement.measurement.initiator_reply_time 1738 ); 1739 assert_eq!( 1740 measurement.responder_reply_time, 1741 extended_address_measurement.measurement.responder_reply_time 1742 ); 1743 assert_eq!( 1744 measurement.initiator_responder_tof, 1745 extended_address_measurement.measurement.initiator_responder_tof 1746 ); 1747 assert_eq!( 1748 measurement.dt_anchor_location, 1749 extended_address_measurement.measurement.dt_anchor_location 1750 ); 1751 assert_eq!( 1752 measurement.ranging_rounds, 1753 extended_address_measurement.measurement.ranging_rounds 1754 ); 1755 } 1756 } 1757