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, RFTEST_PER_RX_CLASS, 19 UWB_DL_TDOA_MEASUREMENT_CLASS, UWB_OWR_AOA_MEASUREMENT_CLASS, UWB_RADAR_DATA_CLASS, 20 UWB_RADAR_SWEEP_DATA_CLASS, 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, RfTestPerRxData, 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 = "(JJIJIJII[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::Long(range_data.hus_primary_session_id as i64), 660 JValue::Int(mac_indicator as i32), 661 JValue::Int(measurement_count), 662 JValue::Object(measurements_jobject), 663 JValue::Object(raw_notification_jobject), 664 ], 665 ) 666 .map_err(|e| { 667 error!("UCI JNI: Ranging Data object creation failed: {:?}", e); 668 e 669 })?; 670 671 let method_sig = "(L".to_owned() + UWB_RANGING_DATA_CLASS + ";)V"; 672 self.cached_jni_call( 673 "onRangeDataNotificationReceived", 674 &method_sig, 675 &[jvalue::from(JValue::Object(range_data_jobject))], 676 ) 677 } 678 on_two_way_range_data_notification( &mut self, bytearray_len: i32, measurement_count: i32, measurements: Vec<TwoWayRangingMeasurement>, ) -> Result<jni::sys::jobjectArray, JNIError>679 fn on_two_way_range_data_notification( 680 &mut self, 681 bytearray_len: i32, 682 measurement_count: i32, 683 measurements: Vec<TwoWayRangingMeasurement>, 684 ) -> Result<jni::sys::jobjectArray, JNIError> { 685 let measurement_jclass = NotificationManagerAndroid::find_local_class( 686 &mut self.jclass_map, 687 &self.class_loader_obj, 688 &self.env, 689 UWB_TWO_WAY_MEASUREMENT_CLASS, 690 )?; 691 let address_jbytearray = self.env.new_byte_array(bytearray_len)?; 692 693 // Safety: address_jbytearray is safely instantiated above. 694 let address_jobject = unsafe { JObject::from_raw(address_jbytearray) }; 695 696 let zero_initiated_measurement_jobject = self 697 .env 698 .new_object( 699 measurement_jclass, 700 "([BIIIIIIIIIIIII)V", 701 &[ 702 JValue::Object(address_jobject), 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 JValue::Int(0), 716 ], 717 ) 718 .map_err(|e| { 719 error!("UCI JNI: measurement object creation failed: {:?}", e); 720 e 721 })?; 722 723 let measurements_jobjectarray = self.env.new_object_array( 724 measurement_count, 725 measurement_jclass, 726 zero_initiated_measurement_jobject, 727 )?; 728 for (i, measurement) in measurements.into_iter().enumerate() { 729 // cast to i8 as java do not support unsigned: 730 let mac_address_i8 = measurement 731 .mac_address 732 .into_ne_bytes() 733 .iter() 734 .map(|b| b.to_owned() as i8) 735 .collect::<Vec<_>>(); 736 let mac_address_jbytearray = self.env.new_byte_array(mac_address_i8.len() as i32)?; 737 self.env.set_byte_array_region(mac_address_jbytearray, 0, &mac_address_i8)?; 738 // casting as i32 is fine since it is wider than actual integer type. 739 740 // Safety: mac_address_jbytearray is safely instantiated above. 741 let mac_address_jobject = unsafe { JObject::from_raw(mac_address_jbytearray) }; 742 let measurement_jobject = self 743 .env 744 .new_object( 745 measurement_jclass, 746 "([BIIIIIIIIIIIII)V", 747 &[ 748 JValue::Object(mac_address_jobject), 749 JValue::Int(i32::from(measurement.status)), 750 JValue::Int(measurement.nlos as i32), 751 JValue::Int(measurement.distance as i32), 752 JValue::Int(measurement.aoa_azimuth as i32), 753 JValue::Int(measurement.aoa_azimuth_fom as i32), 754 JValue::Int(measurement.aoa_elevation as i32), 755 JValue::Int(measurement.aoa_elevation_fom as i32), 756 JValue::Int(measurement.aoa_destination_azimuth as i32), 757 JValue::Int(measurement.aoa_destination_azimuth_fom as i32), 758 JValue::Int(measurement.aoa_destination_elevation as i32), 759 JValue::Int(measurement.aoa_destination_elevation_fom as i32), 760 JValue::Int(measurement.slot_index as i32), 761 JValue::Int(measurement.rssi as i32), 762 ], 763 ) 764 .map_err(|e| { 765 error!("UCI JNI: measurement object creation failed: {:?}", e); 766 e 767 })?; 768 self.env 769 .set_object_array_element(measurements_jobjectarray, i as i32, measurement_jobject) 770 .map_err(|e| { 771 error!("UCI JNI: measurement object copy failed: {:?}", e); 772 e 773 })?; 774 } 775 776 Ok(measurements_jobjectarray) 777 } 778 on_session_owr_aoa_range_data_notification( &mut self, range_data: SessionRangeData, ) -> Result<JObject, JNIError>779 fn on_session_owr_aoa_range_data_notification( 780 &mut self, 781 range_data: SessionRangeData, 782 ) -> Result<JObject, JNIError> { 783 if range_data.ranging_measurement_type != RangingMeasurementType::OwrAoa { 784 return Err(JNIError::InvalidCtorReturn); 785 } 786 787 let raw_notification_jbytearray = 788 self.env.byte_array_from_slice(&range_data.raw_ranging_data)?; 789 790 let (mac_indicator, measurement): (MacAddressIndicator, OwrAoaRangingMeasurement) = 791 match range_data.ranging_measurements { 792 RangingMeasurements::ExtendedAddressOwrAoa(m) => { 793 (MacAddressIndicator::ExtendedAddress, m.into()) 794 } 795 RangingMeasurements::ShortAddressOwrAoa(m) => { 796 (MacAddressIndicator::ShortAddress, m.into()) 797 } 798 _ => { 799 return Err(JNIError::InvalidCtorReturn); 800 } 801 }; 802 803 // cast to i8 as java do not support unsigned. 804 let mac_address_i8 = measurement 805 .mac_address 806 .into_ne_bytes() 807 .iter() 808 .map(|b| b.to_owned() as i8) 809 .collect::<Vec<_>>(); 810 // casting as i32 is fine since it is wider than actual integer type. 811 let mac_address_jbytearray = self.env.new_byte_array(mac_address_i8.len() as i32)?; 812 self.env.set_byte_array_region(mac_address_jbytearray, 0, &mac_address_i8)?; 813 // Safety: mac_address_jbytearray is safely instantiated above. 814 let mac_address_jobject = unsafe { JObject::from_raw(mac_address_jbytearray) }; 815 816 let measurement_jclass = NotificationManagerAndroid::find_local_class( 817 &mut self.jclass_map, 818 &self.class_loader_obj, 819 &self.env, 820 UWB_OWR_AOA_MEASUREMENT_CLASS, 821 )?; 822 let measurement_jobject = self 823 .env 824 .new_object( 825 measurement_jclass, 826 "([BIIIIIIII)V", 827 &[ 828 JValue::Object(mac_address_jobject), 829 JValue::Int(i32::from(measurement.status)), 830 JValue::Int(measurement.nlos as i32), 831 JValue::Int(measurement.frame_sequence_number as i32), 832 JValue::Int(measurement.block_index as i32), 833 JValue::Int(measurement.aoa_azimuth as i32), 834 JValue::Int(measurement.aoa_azimuth_fom as i32), 835 JValue::Int(measurement.aoa_elevation as i32), 836 JValue::Int(measurement.aoa_elevation_fom as i32), 837 ], 838 ) 839 .map_err(|e| { 840 error!("UCI JNI: OwrAoA measurement jobject creation failed: {:?}", e); 841 e 842 })?; 843 844 // Create UwbRangingData 845 let ranging_data_jclass = NotificationManagerAndroid::find_local_class( 846 &mut self.jclass_map, 847 &self.class_loader_obj, 848 &self.env, 849 UWB_RANGING_DATA_CLASS, 850 )?; 851 let method_sig = "(JJIJIJIIL".to_owned() + UWB_OWR_AOA_MEASUREMENT_CLASS + ";[B)V"; 852 853 // Safety: raw_notification_jobject is safely instantiated above. 854 let raw_notification_jobject = unsafe { JObject::from_raw(raw_notification_jbytearray) }; 855 856 let range_data_jobject = self 857 .env 858 .new_object( 859 ranging_data_jclass, 860 &method_sig, 861 &[ 862 JValue::Long(range_data.sequence_number as i64), 863 // session_token below has already been mapped to session_id by uci layer. 864 JValue::Long(range_data.session_token as i64), 865 JValue::Int(range_data.rcr_indicator as i32), 866 JValue::Long(range_data.current_ranging_interval_ms as i64), 867 JValue::Int(range_data.ranging_measurement_type as i32), 868 JValue::Long(range_data.hus_primary_session_id as i64), 869 JValue::Int(mac_indicator as i32), 870 JValue::Int(1), // measurement_count 871 JValue::Object(measurement_jobject), 872 JValue::Object(raw_notification_jobject), 873 ], 874 ) 875 .map_err(|e| { 876 error!("UCI JNI: Ranging Data object creation failed: {:?}", e); 877 e 878 })?; 879 let method_sig = "(L".to_owned() + UWB_RANGING_DATA_CLASS + ";)V"; 880 self.cached_jni_call( 881 "onRangeDataNotificationReceived", 882 &method_sig, 883 &[jvalue::from(JValue::Object(range_data_jobject))], 884 ) 885 } 886 on_session_two_way_range_data_notification( &mut self, range_data: SessionRangeData, ) -> Result<JObject, JNIError>887 fn on_session_two_way_range_data_notification( 888 &mut self, 889 range_data: SessionRangeData, 890 ) -> Result<JObject, JNIError> { 891 let raw_notification_jbytearray = 892 self.env.byte_array_from_slice(&range_data.raw_ranging_data)?; 893 894 let (bytearray_len, mac_indicator) = match &range_data.ranging_measurements { 895 RangingMeasurements::ExtendedAddressTwoWay(_) => { 896 (EXTENDED_MAC_ADDRESS_LEN, MacAddressIndicator::ExtendedAddress) 897 } 898 RangingMeasurements::ShortAddressTwoWay(_) => { 899 (SHORT_MAC_ADDRESS_LEN, MacAddressIndicator::ShortAddress) 900 } 901 _ => { 902 return Err(JNIError::InvalidCtorReturn); 903 } 904 }; 905 906 let measurement_count: i32 = match &range_data.ranging_measurements { 907 RangingMeasurements::ShortAddressTwoWay(v) => v.len().try_into(), 908 RangingMeasurements::ExtendedAddressTwoWay(v) => v.len().try_into(), 909 _ => { 910 return Err(JNIError::InvalidCtorReturn); 911 } 912 } 913 .map_err(|_| JNIError::InvalidCtorReturn)?; 914 915 let measurements_jobjectarray = match range_data.ranging_measurement_type { 916 RangingMeasurementType::TwoWay => { 917 let measurements = match range_data.ranging_measurements { 918 RangingMeasurements::ExtendedAddressTwoWay(v) => { 919 v.into_iter().map(TwoWayRangingMeasurement::from).collect::<Vec<_>>() 920 } 921 RangingMeasurements::ShortAddressTwoWay(v) => { 922 v.into_iter().map(TwoWayRangingMeasurement::from).collect::<Vec<_>>() 923 } 924 _ => return Err(JNIError::InvalidCtorReturn), 925 }; 926 self.on_two_way_range_data_notification( 927 bytearray_len, 928 measurement_count, 929 measurements, 930 )? 931 } 932 _ => { 933 return Err(JNIError::InvalidCtorReturn); 934 } 935 }; 936 937 // Create UwbRangingData 938 let ranging_data_jclass = NotificationManagerAndroid::find_local_class( 939 &mut self.jclass_map, 940 &self.class_loader_obj, 941 &self.env, 942 UWB_RANGING_DATA_CLASS, 943 )?; 944 let method_sig = "(JJIJIJII[L".to_owned() + UWB_TWO_WAY_MEASUREMENT_CLASS + ";[B)V"; 945 946 // Safety: measurements_jobjectarray is safely instantiated above. 947 let measurements_jobject = unsafe { JObject::from_raw(measurements_jobjectarray) }; 948 // Safety: raw_notification_jobject is safely instantiated above. 949 let raw_notification_jobject = unsafe { JObject::from_raw(raw_notification_jbytearray) }; 950 let range_data_jobject = self 951 .env 952 .new_object( 953 ranging_data_jclass, 954 &method_sig, 955 &[ 956 JValue::Long(range_data.sequence_number as i64), 957 // session_token below has already been mapped to session_id by uci layer. 958 JValue::Long(range_data.session_token as i64), 959 JValue::Int(range_data.rcr_indicator as i32), 960 JValue::Long(range_data.current_ranging_interval_ms as i64), 961 JValue::Int(range_data.ranging_measurement_type as i32), 962 JValue::Long(range_data.hus_primary_session_id as i64), 963 JValue::Int(mac_indicator as i32), 964 JValue::Int(measurement_count), 965 JValue::Object(measurements_jobject), 966 JValue::Object(raw_notification_jobject), 967 ], 968 ) 969 .map_err(|e| { 970 error!("UCI JNI: Ranging Data object creation failed: {:?}", e); 971 e 972 })?; 973 let method_sig = "(L".to_owned() + UWB_RANGING_DATA_CLASS + ";)V"; 974 self.cached_jni_call( 975 "onRangeDataNotificationReceived", 976 &method_sig, 977 &[jvalue::from(JValue::Object(range_data_jobject))], 978 ) 979 } 980 on_data_transfer_status_notification( &mut self, session_id: u32, uci_sequence_number: u16, status_code: u8, tx_count: u8, ) -> Result<JObject, JNIError>981 fn on_data_transfer_status_notification( 982 &mut self, 983 session_id: u32, 984 uci_sequence_number: u16, 985 status_code: u8, 986 tx_count: u8, 987 ) -> Result<JObject, JNIError> { 988 self.cached_jni_call( 989 "onDataSendStatus", 990 "(JIJI)V", 991 &[ 992 jvalue::from(JValue::Long(session_id as i64)), 993 jvalue::from(JValue::Int(status_code as i32)), 994 jvalue::from(JValue::Long(uci_sequence_number as i64)), 995 jvalue::from(JValue::Int(tx_count as i32)), 996 ], 997 ) 998 } 999 on_data_transfer_phase_config_notification( &mut self, session_id: u32, status_code: u8, ) -> Result<JObject, JNIError>1000 fn on_data_transfer_phase_config_notification( 1001 &mut self, 1002 session_id: u32, 1003 status_code: u8, 1004 ) -> Result<JObject, JNIError> { 1005 self.cached_jni_call( 1006 "onDataTransferPhaseConfigNotificationReceived", 1007 "(JI)V", 1008 &[ 1009 jvalue::from(JValue::Long(session_id as i64)), 1010 jvalue::from(JValue::Int(status_code as i32)), 1011 ], 1012 ) 1013 } 1014 on_rf_periodic_tx_notification( &mut self, status: u8, raw_notification_data: &[u8], ) -> Result<JObject, JNIError>1015 fn on_rf_periodic_tx_notification( 1016 &mut self, 1017 status: u8, 1018 raw_notification_data: &[u8], 1019 ) -> Result<JObject, JNIError> { 1020 let raw_notification_jbytearray = self.env.byte_array_from_slice(raw_notification_data)?; 1021 // Safety: raw_notification_jbytearray safely instantiated above. 1022 let raw_notification_jobject = unsafe { JObject::from_raw(raw_notification_jbytearray) }; 1023 1024 let periodic_tx_jclass = NotificationManagerAndroid::find_local_class( 1025 &mut self.jclass_map, 1026 &self.class_loader_obj, 1027 &self.env, 1028 RFTEST_PERIODIC_TX_CLASS, 1029 )?; 1030 let method_sig = "(L".to_owned() + RFTEST_PERIODIC_TX_CLASS + ";)V"; 1031 1032 let periodic_tx_jobject = self.env.new_object( 1033 periodic_tx_jclass, 1034 "(I[B)V", 1035 &[JValue::Int(status as i32), JValue::Object(raw_notification_jobject)], 1036 )?; 1037 self.cached_jni_call( 1038 "onPeriodicTxDataNotificationReceived", 1039 &method_sig, 1040 &[jvalue::from(JValue::Object(periodic_tx_jobject))], 1041 ) 1042 } 1043 on_rf_per_rx_notification( &mut self, per_rx_data: RfTestPerRxData, ) -> Result<JObject, JNIError>1044 fn on_rf_per_rx_notification( 1045 &mut self, 1046 per_rx_data: RfTestPerRxData, 1047 ) -> Result<JObject, JNIError> { 1048 let raw_notification_jbytearray = 1049 self.env.byte_array_from_slice(&per_rx_data.raw_notification_data)?; 1050 // Safety: raw_notification_jbytearray safely instantiated above. 1051 let raw_notification_jobject = unsafe { JObject::from_raw(raw_notification_jbytearray) }; 1052 1053 let per_rx_jclass = NotificationManagerAndroid::find_local_class( 1054 &mut self.jclass_map, 1055 &self.class_loader_obj, 1056 &self.env, 1057 RFTEST_PER_RX_CLASS, 1058 )?; 1059 let method_sig = "(L".to_owned() + RFTEST_PER_RX_CLASS + ";)V"; 1060 1061 let per_rx_jobject = self.env.new_object( 1062 per_rx_jclass, 1063 "(IJJJJJJJJJJJJJ[B)V", 1064 &[ 1065 JValue::Int(i32::from(per_rx_data.status)), 1066 JValue::Long(per_rx_data.attempts as i64), 1067 JValue::Long(per_rx_data.acq_detect as i64), 1068 JValue::Long(per_rx_data.acq_reject as i64), 1069 JValue::Long(per_rx_data.rx_fail as i64), 1070 JValue::Long(per_rx_data.sync_cir_ready as i64), 1071 JValue::Long(per_rx_data.sfd_fail as i64), 1072 JValue::Long(per_rx_data.sfd_found as i64), 1073 JValue::Long(per_rx_data.phr_dec_error as i64), 1074 JValue::Long(per_rx_data.phr_bit_error as i64), 1075 JValue::Long(per_rx_data.psdu_dec_error as i64), 1076 JValue::Long(per_rx_data.psdu_bit_error as i64), 1077 JValue::Long(per_rx_data.sts_found as i64), 1078 JValue::Long(per_rx_data.eof as i64), 1079 JValue::Object(raw_notification_jobject), 1080 ], 1081 )?; 1082 self.cached_jni_call( 1083 "onPerRxDataNotificationReceived", 1084 &method_sig, 1085 &[jvalue::from(JValue::Object(per_rx_jobject))], 1086 ) 1087 } 1088 } 1089 1090 impl NotificationManager for NotificationManagerAndroid { on_core_notification(&mut self, core_notification: CoreNotification) -> UwbResult<()>1091 fn on_core_notification(&mut self, core_notification: CoreNotification) -> UwbResult<()> { 1092 debug!("UCI JNI: core notification callback."); 1093 let env = *self.env; 1094 env.with_local_frame(MAX_JAVA_OBJECTS_CAPACITY, || { 1095 let env_chip_id_jobject = *env.new_string(&self.chip_id).map_err(|e| { 1096 error!("UCI JNI: failed to create Java String: {e:?}"); 1097 e 1098 })?; 1099 1100 match core_notification { 1101 CoreNotification::DeviceStatus(device_state) => self.cached_jni_call( 1102 "onDeviceStatusNotificationReceived", 1103 "(ILjava/lang/String;)V", 1104 &[ 1105 jvalue::from(JValue::Int(device_state as i32)), 1106 jvalue::from(JValue::Object(env_chip_id_jobject)), 1107 ], 1108 ), 1109 CoreNotification::GenericError(generic_error) => self.cached_jni_call( 1110 "onCoreGenericErrorNotificationReceived", 1111 "(ILjava/lang/String;)V", 1112 &[ 1113 jvalue::from(JValue::Int(i32::from(generic_error))), 1114 jvalue::from(JValue::Object(env_chip_id_jobject)), 1115 ], 1116 ), 1117 } 1118 }) 1119 .map_err(|e| { 1120 error!("on_core_notification error: {:?}", e); 1121 UwbError::ForeignFunctionInterface 1122 })?; 1123 1124 Ok(()) 1125 } 1126 on_session_notification( &mut self, session_notification: SessionNotification, ) -> UwbResult<()>1127 fn on_session_notification( 1128 &mut self, 1129 session_notification: SessionNotification, 1130 ) -> UwbResult<()> { 1131 debug!("UCI JNI: session notification callback."); 1132 let env = *self.env; 1133 env.with_local_frame(MAX_JAVA_OBJECTS_CAPACITY, || { 1134 match session_notification { 1135 SessionNotification::Status { 1136 session_id, 1137 session_token, 1138 session_state, 1139 reason_code, 1140 } => self.on_session_status_notification( 1141 session_id, 1142 session_token, 1143 session_state, 1144 reason_code, 1145 ), 1146 SessionNotification::UpdateControllerMulticastListV1 { 1147 session_token, 1148 remaining_multicast_list_size, 1149 status_list, 1150 } => self.on_session_update_multicast_notification( 1151 session_token, 1152 remaining_multicast_list_size, 1153 ControleeStatusList::V1(status_list), 1154 ), 1155 SessionNotification::UpdateControllerMulticastListV2 { 1156 session_token, 1157 status_list, 1158 } => self.on_session_update_multicast_notification( 1159 session_token, 1160 0_usize, 1161 ControleeStatusList::V2(status_list), 1162 ), 1163 // TODO(b/246678053): Match here on range_data.ranging_measurement_type instead. 1164 SessionNotification::SessionInfo(range_data) => { 1165 match range_data.ranging_measurements { 1166 uwb_core::uci::RangingMeasurements::ShortAddressTwoWay(_) => { 1167 self.on_session_two_way_range_data_notification(range_data) 1168 } 1169 uwb_core::uci::RangingMeasurements::ExtendedAddressTwoWay(_) => { 1170 self.on_session_two_way_range_data_notification(range_data) 1171 } 1172 uwb_core::uci::RangingMeasurements::ShortAddressOwrAoa(_) => { 1173 self.on_session_owr_aoa_range_data_notification(range_data) 1174 } 1175 uwb_core::uci::RangingMeasurements::ExtendedAddressOwrAoa(_) => { 1176 self.on_session_owr_aoa_range_data_notification(range_data) 1177 } 1178 uwb_core::uci::RangingMeasurements::ShortAddressDltdoa(_) => { 1179 self.on_session_dl_tdoa_range_data_notification(range_data) 1180 } 1181 uwb_core::uci::RangingMeasurements::ExtendedAddressDltdoa(_) => { 1182 self.on_session_dl_tdoa_range_data_notification(range_data) 1183 } 1184 } 1185 } 1186 SessionNotification::DataTransferStatus { 1187 session_token, 1188 uci_sequence_number, 1189 status, 1190 tx_count, 1191 } => self.on_data_transfer_status_notification( 1192 session_token, 1193 uci_sequence_number, 1194 u8::from(status), 1195 tx_count, 1196 ), 1197 // This session notification should not come here, as it's handled within 1198 // UciManager, for internal state management related to sending data packet(s). 1199 SessionNotification::DataCredit { session_token, credit_availability } => { 1200 error!( 1201 "UCI JNI: Received unexpected DataCredit notification for \ 1202 session_token {}, credit_availability {:?}", 1203 session_token, credit_availability 1204 ); 1205 Err(JNIError::InvalidCtorReturn) 1206 } 1207 SessionNotification::DataTransferPhaseConfig { session_token, status } => { 1208 self.on_data_transfer_phase_config_notification(session_token, u8::from(status)) 1209 } 1210 } 1211 }) 1212 .map_err(|e| { 1213 error!("on_session_notification error {:?}", e); 1214 UwbError::ForeignFunctionInterface 1215 })?; 1216 Ok(()) 1217 } 1218 on_vendor_notification( &mut self, vendor_notification: uwb_core::params::RawUciMessage, ) -> UwbResult<()>1219 fn on_vendor_notification( 1220 &mut self, 1221 vendor_notification: uwb_core::params::RawUciMessage, 1222 ) -> UwbResult<()> { 1223 debug!("UCI JNI: vendor notification callback."); 1224 let env = *self.env; 1225 env.with_local_frame(MAX_JAVA_OBJECTS_CAPACITY, || { 1226 let payload_jbytearray = 1227 self.env.byte_array_from_slice(&vendor_notification.payload)?; 1228 1229 // Safety: payload_jbytearray safely instantiated above. 1230 let payload_jobject = unsafe { JObject::from_raw(payload_jbytearray) }; 1231 self.cached_jni_call( 1232 "onVendorUciNotificationReceived", 1233 "(II[B)V", 1234 &[ 1235 // Java only has signed integer. The range for signed int32 should be sufficient. 1236 jvalue::from(JValue::Int( 1237 vendor_notification 1238 .gid 1239 .try_into() 1240 .map_err(|_| JNIError::InvalidCtorReturn)?, 1241 )), 1242 jvalue::from(JValue::Int( 1243 vendor_notification 1244 .oid 1245 .try_into() 1246 .map_err(|_| JNIError::InvalidCtorReturn)?, 1247 )), 1248 jvalue::from(JValue::Object(payload_jobject)), 1249 ], 1250 ) 1251 }) 1252 .map_err(|e| { 1253 error!("on_vendor_notification error: {:?}", e); 1254 UwbError::ForeignFunctionInterface 1255 })?; 1256 Ok(()) 1257 } 1258 on_data_rcv_notification( &mut self, data_rcv_notification: DataRcvNotification, ) -> UwbResult<()>1259 fn on_data_rcv_notification( 1260 &mut self, 1261 data_rcv_notification: DataRcvNotification, 1262 ) -> UwbResult<()> { 1263 debug!("UCI JNI: Data Rcv notification callback."); 1264 let env = *self.env; 1265 env.with_local_frame(MAX_JAVA_OBJECTS_CAPACITY, || { 1266 let source_address_jbytearray = match &data_rcv_notification.source_address { 1267 UwbAddress::Short(a) => self.env.byte_array_from_slice(a)?, 1268 UwbAddress::Extended(a) => self.env.byte_array_from_slice(a)?, 1269 }; 1270 let payload_jbytearray = 1271 self.env.byte_array_from_slice(&data_rcv_notification.payload)?; 1272 // Safety: source_address_jbytearray safely instantiated above. 1273 let source_address_jobject = unsafe { JObject::from_raw(source_address_jbytearray) }; 1274 // Safety: payload_jbytearray safely instantiated above. 1275 let payload_jobject = unsafe { JObject::from_raw(payload_jbytearray) }; 1276 self.cached_jni_call( 1277 "onDataReceived", 1278 "(JIJ[B[B)V", 1279 &[ 1280 // session_token below has already been mapped to session_id by uci layer. 1281 jvalue::from(JValue::Long(data_rcv_notification.session_token as i64)), 1282 jvalue::from(JValue::Int(i32::from(data_rcv_notification.status))), 1283 jvalue::from(JValue::Long(data_rcv_notification.uci_sequence_num as i64)), 1284 jvalue::from(JValue::Object(source_address_jobject)), 1285 jvalue::from(JValue::Object(payload_jobject)), 1286 ], 1287 ) 1288 }) 1289 .map_err(|e| { 1290 error!("on_data_rcv_notification error: {:?}", e); 1291 UwbError::ForeignFunctionInterface 1292 })?; 1293 Ok(()) 1294 } 1295 on_radar_data_rcv_notification( &mut self, radar_data_rcv_notification: RadarDataRcvNotification, ) -> UwbResult<()>1296 fn on_radar_data_rcv_notification( 1297 &mut self, 1298 radar_data_rcv_notification: RadarDataRcvNotification, 1299 ) -> UwbResult<()> { 1300 debug!("UCI JNI: Radar Data Rcv notification callback."); 1301 let env = *self.env; 1302 env.with_local_frame(MAX_JAVA_OBJECTS_CAPACITY, || { 1303 let radar_sweep_data_jclass = NotificationManagerAndroid::find_local_class( 1304 &mut self.jclass_map, 1305 &self.class_loader_obj, 1306 &self.env, 1307 UWB_RADAR_SWEEP_DATA_CLASS, 1308 )?; 1309 1310 let max_sample_data_length = 1311 radar_bytes_per_sample_value(radar_data_rcv_notification.bits_per_sample) as i32 1312 * radar_data_rcv_notification.samples_per_sweep as i32; 1313 let sample_data_jbytearray = self.env.new_byte_array(max_sample_data_length)?; 1314 let vendor_data_jbytearray = self.env.new_byte_array(MAX_RADAR_VENDOR_DATA_LEN)?; 1315 1316 // Safety: sample_data_jbytearray is safely instantiated above. 1317 let sample_data_jobject = unsafe { JObject::from_raw(sample_data_jbytearray) }; 1318 // Safety: vendor_data_jbytearray is safely instantiated above. 1319 let vendor_data_jobject = unsafe { JObject::from_raw(vendor_data_jbytearray) }; 1320 1321 let sweep_data_sig: &str = "(JJ[B[B)V"; 1322 1323 let zero_initiated_sweep_data = self 1324 .env 1325 .new_object( 1326 radar_sweep_data_jclass, 1327 sweep_data_sig, 1328 &[ 1329 JValue::Long(0), 1330 JValue::Long(0), 1331 JValue::Object(vendor_data_jobject), 1332 JValue::Object(sample_data_jobject), 1333 ], 1334 ) 1335 .map_err(|e| { 1336 error!( 1337 "UCI JNI: zero initiated RadarSweepData object creation failed: {:?}", 1338 e 1339 ); 1340 e 1341 })?; 1342 1343 let radar_sweep_data_jobjectarray = self 1344 .env 1345 .new_object_array( 1346 radar_data_rcv_notification.sweep_data.len() as i32, 1347 radar_sweep_data_jclass, 1348 zero_initiated_sweep_data, 1349 ) 1350 .map_err(|e| { 1351 error!("UCI JNI: RadarSweepData object array creation failed: {:?}", e); 1352 e 1353 })?; 1354 1355 for (i, sweep_data) in radar_data_rcv_notification.sweep_data.into_iter().enumerate() { 1356 let vendor_data_jbytearray = 1357 self.env.byte_array_from_slice(&sweep_data.vendor_specific_data)?; 1358 let sample_data_jbytearray = 1359 self.env.byte_array_from_slice(&sweep_data.sample_data)?; 1360 // Safety: vendor_data_jbytearray instantiated above 1361 let vendor_data_jobject = unsafe { JObject::from_raw(vendor_data_jbytearray) }; 1362 // Safety: sample_data_jbytearray instantiated above 1363 let sample_data_jobject = unsafe { JObject::from_raw(sample_data_jbytearray) }; 1364 let sweep_data_jobject = self 1365 .env 1366 .new_object( 1367 radar_sweep_data_jclass, 1368 sweep_data_sig, 1369 &[ 1370 JValue::Long(sweep_data.sequence_number as i64), 1371 JValue::Long(sweep_data.timestamp as i64), 1372 JValue::Object(vendor_data_jobject), 1373 JValue::Object(sample_data_jobject), 1374 ], 1375 ) 1376 .map_err(|e| { 1377 error!("UCI JNI: RadarSweepData object creation failed: {:?}", e); 1378 e 1379 })?; 1380 1381 self.env 1382 .set_object_array_element( 1383 radar_sweep_data_jobjectarray, 1384 i as i32, 1385 sweep_data_jobject, 1386 ) 1387 .map_err(|e| { 1388 error!( 1389 "UCI JNI: sweep_data_jobject copy into jobjectarray failed: {:?}", 1390 e 1391 ); 1392 e 1393 })?; 1394 } 1395 1396 let radar_sweep_data_array_jobject = 1397 // Safety: radar_sweep_data_jobjectarray is safely instantiated above. 1398 unsafe { JObject::from_raw(radar_sweep_data_jobjectarray) }; 1399 1400 let radar_data_jclass = NotificationManagerAndroid::find_local_class( 1401 &mut self.jclass_map, 1402 &self.class_loader_obj, 1403 &self.env, 1404 UWB_RADAR_DATA_CLASS, 1405 )?; 1406 1407 let radar_data_jobject = self 1408 .env 1409 .new_object( 1410 radar_data_jclass, 1411 "(JIIIII[L".to_owned() + UWB_RADAR_SWEEP_DATA_CLASS + ";)V", 1412 &[ 1413 // session_token below has already been mapped to session_id by uci layer. 1414 JValue::Long(radar_data_rcv_notification.session_token as i64), 1415 JValue::Int(radar_data_rcv_notification.status as i32), 1416 JValue::Int(radar_data_rcv_notification.radar_data_type as i32), 1417 JValue::Int(radar_data_rcv_notification.samples_per_sweep as i32), 1418 JValue::Int(radar_data_rcv_notification.bits_per_sample as i32), 1419 JValue::Int(radar_data_rcv_notification.sweep_offset as i32), 1420 JValue::Object(radar_sweep_data_array_jobject), 1421 ], 1422 ) 1423 .map_err(|e| { 1424 error!("UCI JNI: UwbRadarData object creation failed: {:?}", e); 1425 e 1426 })?; 1427 1428 let method_sig = "(L".to_owned() + UWB_RADAR_DATA_CLASS + ";)V"; 1429 1430 self.cached_jni_call( 1431 "onRadarDataMessageReceived", 1432 &method_sig, 1433 &[jvalue::from(JValue::Object(radar_data_jobject))], 1434 ) 1435 }) 1436 .map_err(|e| { 1437 error!("on_radar_data_rcv_notification error: {:?}", e); 1438 UwbError::ForeignFunctionInterface 1439 })?; 1440 Ok(()) 1441 } 1442 on_rf_test_notification( &mut self, rf_test_notification: RfTestNotification, ) -> UwbResult<()>1443 fn on_rf_test_notification( 1444 &mut self, 1445 rf_test_notification: RfTestNotification, 1446 ) -> UwbResult<()> { 1447 debug!("UCI JNI: RF test notification callback."); 1448 let env = *self.env; 1449 env.with_local_frame(MAX_JAVA_OBJECTS_CAPACITY, || match rf_test_notification { 1450 RfTestNotification::TestPeriodicTxNtf { status, raw_notification_data } => { 1451 self.on_rf_periodic_tx_notification(u8::from(status), &raw_notification_data) 1452 } 1453 RfTestNotification::TestPerRxNtf(per_rx_data) => { 1454 self.on_rf_per_rx_notification(per_rx_data) 1455 } 1456 }) 1457 .map_err(|e| { 1458 error!("on_rf_test_notification error: {:?}", e); 1459 UwbError::ForeignFunctionInterface 1460 })?; 1461 Ok(()) 1462 } 1463 } 1464 pub(crate) struct NotificationManagerAndroidBuilder { 1465 pub chip_id: String, 1466 pub vm: &'static Arc<JavaVM>, 1467 pub class_loader_obj: GlobalRef, 1468 pub callback_obj: GlobalRef, 1469 } 1470 1471 impl NotificationManagerBuilder for NotificationManagerAndroidBuilder { 1472 type NotificationManager = NotificationManagerAndroid; 1473 build(self) -> Option<Self::NotificationManager>1474 fn build(self) -> Option<Self::NotificationManager> { 1475 if let Ok(env) = self.vm.attach_current_thread() { 1476 Some(NotificationManagerAndroid { 1477 chip_id: self.chip_id, 1478 env, 1479 class_loader_obj: self.class_loader_obj, 1480 callback_obj: self.callback_obj, 1481 jmethod_id_map: HashMap::new(), 1482 jclass_map: HashMap::new(), 1483 }) 1484 } else { 1485 None 1486 } 1487 } 1488 } 1489 1490 #[cfg(test)] 1491 mod tests { 1492 use super::*; 1493 1494 #[test] test_get_two_way_ranigng_measurement_from_short_address_two_way_ranging_measurement()1495 fn test_get_two_way_ranigng_measurement_from_short_address_two_way_ranging_measurement() { 1496 let short_address_measurement = ShortAddressTwoWayRangingMeasurement { 1497 mac_address: 0x1234, 1498 status: StatusCode::UciStatusOk, 1499 nlos: 0, 1500 distance: 1, 1501 aoa_azimuth: 2, 1502 aoa_azimuth_fom: 3, 1503 aoa_elevation: 4, 1504 aoa_elevation_fom: 5, 1505 aoa_destination_azimuth: 6, 1506 aoa_destination_azimuth_fom: 7, 1507 aoa_destination_elevation: 8, 1508 aoa_destination_elevation_fom: 9, 1509 slot_index: 10, 1510 rssi: 11, 1511 }; 1512 let measurement = TwoWayRangingMeasurement::from(short_address_measurement.clone()); 1513 assert_eq!( 1514 measurement.mac_address, 1515 MacAddress::Short(short_address_measurement.mac_address) 1516 ); 1517 assert_eq!(measurement.status, short_address_measurement.status); 1518 assert_eq!(measurement.nlos, short_address_measurement.nlos); 1519 assert_eq!(measurement.distance, short_address_measurement.distance); 1520 assert_eq!(measurement.aoa_azimuth, short_address_measurement.aoa_azimuth); 1521 assert_eq!(measurement.aoa_azimuth_fom, short_address_measurement.aoa_azimuth_fom); 1522 assert_eq!(measurement.aoa_elevation, short_address_measurement.aoa_elevation); 1523 assert_eq!(measurement.aoa_elevation_fom, short_address_measurement.aoa_elevation_fom); 1524 assert_eq!( 1525 measurement.aoa_destination_azimuth, 1526 short_address_measurement.aoa_destination_azimuth 1527 ); 1528 assert_eq!( 1529 measurement.aoa_destination_azimuth_fom, 1530 short_address_measurement.aoa_destination_azimuth_fom 1531 ); 1532 assert_eq!( 1533 measurement.aoa_destination_elevation, 1534 short_address_measurement.aoa_destination_elevation 1535 ); 1536 assert_eq!( 1537 measurement.aoa_destination_elevation_fom, 1538 short_address_measurement.aoa_destination_elevation_fom 1539 ); 1540 assert_eq!(measurement.slot_index, short_address_measurement.slot_index); 1541 assert_eq!(measurement.rssi, short_address_measurement.rssi); 1542 } 1543 1544 #[test] test_get_two_way_ranigng_measurement_from_extended_address_two_way_ranging_measurement()1545 fn test_get_two_way_ranigng_measurement_from_extended_address_two_way_ranging_measurement() { 1546 let extended_address_measurement = ExtendedAddressTwoWayRangingMeasurement { 1547 mac_address: 0x1234_5678, 1548 status: StatusCode::UciStatusOk, 1549 nlos: 0, 1550 distance: 1, 1551 aoa_azimuth: 2, 1552 aoa_azimuth_fom: 3, 1553 aoa_elevation: 4, 1554 aoa_elevation_fom: 5, 1555 aoa_destination_azimuth: 6, 1556 aoa_destination_azimuth_fom: 7, 1557 aoa_destination_elevation: 8, 1558 aoa_destination_elevation_fom: 9, 1559 slot_index: 10, 1560 rssi: 11, 1561 }; 1562 let measurement = TwoWayRangingMeasurement::from(extended_address_measurement.clone()); 1563 assert_eq!( 1564 measurement.mac_address, 1565 MacAddress::Extended(extended_address_measurement.mac_address) 1566 ); 1567 assert_eq!(measurement.status, extended_address_measurement.status); 1568 assert_eq!(measurement.nlos, extended_address_measurement.nlos); 1569 assert_eq!(measurement.distance, extended_address_measurement.distance); 1570 assert_eq!(measurement.aoa_azimuth, extended_address_measurement.aoa_azimuth); 1571 assert_eq!(measurement.aoa_azimuth_fom, extended_address_measurement.aoa_azimuth_fom); 1572 assert_eq!(measurement.aoa_elevation, extended_address_measurement.aoa_elevation); 1573 assert_eq!(measurement.aoa_elevation_fom, extended_address_measurement.aoa_elevation_fom); 1574 assert_eq!( 1575 measurement.aoa_destination_azimuth, 1576 extended_address_measurement.aoa_destination_azimuth 1577 ); 1578 assert_eq!( 1579 measurement.aoa_destination_azimuth_fom, 1580 extended_address_measurement.aoa_destination_azimuth_fom 1581 ); 1582 assert_eq!( 1583 measurement.aoa_destination_elevation, 1584 extended_address_measurement.aoa_destination_elevation 1585 ); 1586 assert_eq!( 1587 measurement.aoa_destination_elevation_fom, 1588 extended_address_measurement.aoa_destination_elevation_fom 1589 ); 1590 assert_eq!(measurement.slot_index, extended_address_measurement.slot_index); 1591 assert_eq!(measurement.rssi, extended_address_measurement.rssi); 1592 } 1593 1594 #[test] test_get_owr_aoa_ranging_measurement_from_short_address_measurement()1595 fn test_get_owr_aoa_ranging_measurement_from_short_address_measurement() { 1596 let short_address_measurement = ShortAddressOwrAoaRangingMeasurement { 1597 mac_address: 0x1234, 1598 status: StatusCode::UciStatusOk, 1599 nlos: 0, 1600 frame_sequence_number: 1, 1601 block_index: 2, 1602 aoa_azimuth: 3, 1603 aoa_azimuth_fom: 4, 1604 aoa_elevation: 5, 1605 aoa_elevation_fom: 6, 1606 }; 1607 let measurement = OwrAoaRangingMeasurement::from(short_address_measurement.clone()); 1608 assert_eq!( 1609 measurement.mac_address, 1610 MacAddress::Short(short_address_measurement.mac_address) 1611 ); 1612 assert_eq!(measurement.status, short_address_measurement.status); 1613 assert_eq!(measurement.nlos, short_address_measurement.nlos); 1614 assert_eq!( 1615 measurement.frame_sequence_number, 1616 short_address_measurement.frame_sequence_number 1617 ); 1618 assert_eq!(measurement.block_index, short_address_measurement.block_index); 1619 assert_eq!(measurement.aoa_azimuth, short_address_measurement.aoa_azimuth); 1620 assert_eq!(measurement.aoa_azimuth_fom, short_address_measurement.aoa_azimuth_fom); 1621 assert_eq!(measurement.aoa_elevation, short_address_measurement.aoa_elevation); 1622 assert_eq!(measurement.aoa_elevation_fom, short_address_measurement.aoa_elevation_fom); 1623 } 1624 1625 #[test] test_get_owr_aoa_ranging_measurement_from_extended_address_measurement()1626 fn test_get_owr_aoa_ranging_measurement_from_extended_address_measurement() { 1627 let extended_address_measurement = ExtendedAddressOwrAoaRangingMeasurement { 1628 mac_address: 0x1234_5678, 1629 status: StatusCode::UciStatusOk, 1630 nlos: 0, 1631 frame_sequence_number: 1, 1632 block_index: 2, 1633 aoa_azimuth: 3, 1634 aoa_azimuth_fom: 4, 1635 aoa_elevation: 5, 1636 aoa_elevation_fom: 6, 1637 }; 1638 let measurement = OwrAoaRangingMeasurement::from(extended_address_measurement.clone()); 1639 assert_eq!( 1640 measurement.mac_address, 1641 MacAddress::Extended(extended_address_measurement.mac_address) 1642 ); 1643 assert_eq!(measurement.status, extended_address_measurement.status); 1644 assert_eq!(measurement.nlos, extended_address_measurement.nlos); 1645 assert_eq!( 1646 measurement.frame_sequence_number, 1647 extended_address_measurement.frame_sequence_number 1648 ); 1649 assert_eq!(measurement.block_index, extended_address_measurement.block_index); 1650 assert_eq!(measurement.aoa_azimuth, extended_address_measurement.aoa_azimuth); 1651 assert_eq!(measurement.aoa_azimuth_fom, extended_address_measurement.aoa_azimuth_fom); 1652 assert_eq!(measurement.aoa_elevation, extended_address_measurement.aoa_elevation); 1653 assert_eq!(measurement.aoa_elevation_fom, extended_address_measurement.aoa_elevation_fom); 1654 } 1655 1656 #[test] test_get_dl_tdoa_ranging_measurement_from_short_address_measurement()1657 fn test_get_dl_tdoa_ranging_measurement_from_short_address_measurement() { 1658 let bytes = [ 1659 // All Fields in Little Endian (LE) 1660 0x0a, 0x01, 0x33, 0x05, // 2(Mac address), Status, Message Type 1661 0x53, 0x05, 0x02, 0x05, // 2(Message control), 2(Block Index) 1662 0x07, 0x09, 0x0a, 0x01, // Round Index, NLoS, 2(AoA Azimuth) 1663 0x02, 0x05, 0x07, 0x09, // AoA Azimuth FOM, 2(AoA Elevation), AoA Elevation FOM 1664 0x0a, 0x01, 0x02, 0x05, // RSSI, 3(Tx Timestamp..) 1665 0x07, 0x09, 0x0a, 0x01, // 4(Tx Timestamp..) 1666 0x02, 0x05, 0x07, 0x09, // Tx Timestamp, 3(Rx Timestamp..) 1667 0x05, 0x07, 0x09, 0x0a, // 2(Rx Timestamp), 2(Anchor Cfo) 1668 0x01, 0x02, 0x05, 0x07, // 2(Cfo), 2(Initiator Reply Time..) 1669 0x09, 0x05, 0x07, 0x09, // 2(Initiator Reply Time), 2(Responder Reply Time..) 1670 0x0a, 0x01, 0x02, 0x05, // 2(Responder Reply Time), 2(Initiator-Responder ToF) 1671 0x07, 0x09, 0x07, 0x09, // 4(Anchor Location..) 1672 0x05, 0x07, 0x09, 0x0a, // 4(Anchor Location..) 1673 0x01, 0x02, 0x05, 0x07, // 2(Anchor Location..), 2(Active Ranging Rounds..) 1674 0x09, 0x0a, 0x01, 0x02, // 4(Active Ranging Rounds..) 1675 0x05, 0x07, 0x09, 0x05, // 4(Active Ranging Rounds) 1676 ]; 1677 let short_address_measurement_vec = 1678 ShortAddressDlTdoaRangingMeasurement::parse(&bytes, 1).unwrap(); 1679 let short_address_measurement = &short_address_measurement_vec[0]; 1680 let measurement = DlTdoaRangingMeasurement::from(short_address_measurement.clone()); 1681 assert_eq!( 1682 measurement.mac_address, 1683 MacAddress::Short(short_address_measurement.mac_address) 1684 ); 1685 assert_eq!(measurement.status, short_address_measurement.measurement.status); 1686 assert_eq!(measurement.message_type, short_address_measurement.measurement.message_type); 1687 assert_eq!( 1688 measurement.message_control, 1689 short_address_measurement.measurement.message_control 1690 ); 1691 assert_eq!(measurement.block_index, short_address_measurement.measurement.block_index); 1692 assert_eq!(measurement.round_index, short_address_measurement.measurement.round_index); 1693 assert_eq!(measurement.nlos, short_address_measurement.measurement.nlos); 1694 assert_eq!(measurement.aoa_azimuth, short_address_measurement.measurement.aoa_azimuth); 1695 assert_eq!( 1696 measurement.aoa_azimuth_fom, 1697 short_address_measurement.measurement.aoa_azimuth_fom 1698 ); 1699 assert_eq!(measurement.aoa_elevation, short_address_measurement.measurement.aoa_elevation); 1700 assert_eq!( 1701 measurement.aoa_elevation_fom, 1702 short_address_measurement.measurement.aoa_elevation_fom 1703 ); 1704 assert_eq!(measurement.rssi, short_address_measurement.measurement.rssi); 1705 assert_eq!(measurement.tx_timestamp, short_address_measurement.measurement.tx_timestamp); 1706 assert_eq!(measurement.rx_timestamp, short_address_measurement.measurement.rx_timestamp); 1707 assert_eq!(measurement.anchor_cfo, short_address_measurement.measurement.anchor_cfo); 1708 assert_eq!(measurement.cfo, short_address_measurement.measurement.cfo); 1709 assert_eq!( 1710 measurement.initiator_reply_time, 1711 short_address_measurement.measurement.initiator_reply_time 1712 ); 1713 assert_eq!( 1714 measurement.responder_reply_time, 1715 short_address_measurement.measurement.responder_reply_time 1716 ); 1717 assert_eq!( 1718 measurement.initiator_responder_tof, 1719 short_address_measurement.measurement.initiator_responder_tof 1720 ); 1721 assert_eq!( 1722 measurement.dt_anchor_location, 1723 short_address_measurement.measurement.dt_anchor_location 1724 ); 1725 assert_eq!( 1726 measurement.ranging_rounds, 1727 short_address_measurement.measurement.ranging_rounds 1728 ); 1729 } 1730 1731 #[test] test_get_dl_tdoa_ranging_measurement_from_extended_address_measurement()1732 fn test_get_dl_tdoa_ranging_measurement_from_extended_address_measurement() { 1733 let bytes = [ 1734 // All Fields in Little Endian (LE) 1735 0x0a, 0x01, 0x33, 0x05, // 4(Mac address..) 1736 0x33, 0x05, 0x02, 0x05, // 4(Mac address) 1737 0x07, 0x09, 0x0a, 0x01, // Status, Message Type, 2(Message control), 1738 0x02, 0x05, 0x07, 0x09, // 2(Block Index), Round Index, NLoS, 1739 0x0a, 0x01, 0x02, 0x05, // 2(AoA Azimuth), AoA Azimuth FOM, 1(AoA Elevation..) 1740 0x07, 0x09, 0x0a, // 1(AoA Elevation), AoA Elevation FOM, RSSI, 1741 0x01, 0x02, 0x05, 0x07, // 4(Tx Timestamp..) 1742 0x09, 0x05, 0x07, 0x09, // 4(Tx Timestamp), 1743 0x0a, 0x01, 0x02, 0x05, // 4(Rx Timestamp..) 1744 0x07, 0x09, 0x05, 0x07, // 4(Rx Timestamp) 1745 0x09, 0x0a, 0x01, 0x02, // 2(Anchor Cfo), 2(Cfo), 1746 0x05, 0x07, 0x09, 0x05, // 4(Initiator Reply Time) 1747 0x07, 0x09, 0x0a, 0x01, // 4(Responder Reply Time), 1748 0x02, 0x05, 0x02, 0x05, // 2(Initiator-Responder ToF), 2(Active Ranging Rounds) 1749 ]; 1750 let extended_address_measurement_vec = 1751 ExtendedAddressDlTdoaRangingMeasurement::parse(&bytes, 1).unwrap(); 1752 let extended_address_measurement = &extended_address_measurement_vec[0]; 1753 1754 let measurement = DlTdoaRangingMeasurement::from(extended_address_measurement.clone()); 1755 assert_eq!( 1756 measurement.mac_address, 1757 MacAddress::Extended(extended_address_measurement.mac_address) 1758 ); 1759 assert_eq!(measurement.status, extended_address_measurement.measurement.status); 1760 assert_eq!(measurement.message_type, extended_address_measurement.measurement.message_type); 1761 assert_eq!( 1762 measurement.message_control, 1763 extended_address_measurement.measurement.message_control 1764 ); 1765 assert_eq!(measurement.block_index, extended_address_measurement.measurement.block_index); 1766 assert_eq!(measurement.round_index, extended_address_measurement.measurement.round_index); 1767 assert_eq!(measurement.nlos, extended_address_measurement.measurement.nlos); 1768 assert_eq!(measurement.aoa_azimuth, extended_address_measurement.measurement.aoa_azimuth); 1769 assert_eq!( 1770 measurement.aoa_azimuth_fom, 1771 extended_address_measurement.measurement.aoa_azimuth_fom 1772 ); 1773 assert_eq!( 1774 measurement.aoa_elevation, 1775 extended_address_measurement.measurement.aoa_elevation 1776 ); 1777 assert_eq!( 1778 measurement.aoa_elevation_fom, 1779 extended_address_measurement.measurement.aoa_elevation_fom 1780 ); 1781 assert_eq!(measurement.rssi, extended_address_measurement.measurement.rssi); 1782 assert_eq!(measurement.tx_timestamp, extended_address_measurement.measurement.tx_timestamp); 1783 assert_eq!(measurement.rx_timestamp, extended_address_measurement.measurement.rx_timestamp); 1784 assert_eq!(measurement.anchor_cfo, extended_address_measurement.measurement.anchor_cfo); 1785 assert_eq!(measurement.cfo, extended_address_measurement.measurement.cfo); 1786 assert_eq!( 1787 measurement.initiator_reply_time, 1788 extended_address_measurement.measurement.initiator_reply_time 1789 ); 1790 assert_eq!( 1791 measurement.responder_reply_time, 1792 extended_address_measurement.measurement.responder_reply_time 1793 ); 1794 assert_eq!( 1795 measurement.initiator_responder_tof, 1796 extended_address_measurement.measurement.initiator_responder_tof 1797 ); 1798 assert_eq!( 1799 measurement.dt_anchor_location, 1800 extended_address_measurement.measurement.dt_anchor_location 1801 ); 1802 assert_eq!( 1803 measurement.ranging_rounds, 1804 extended_address_measurement.measurement.ranging_rounds 1805 ); 1806 } 1807 } 1808