1 // Copyright 2022, The Android Open Source Project 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 //! Implementation of NotificationManagerAndroid and its builder. 16 17 use crate::jclass_name::{ 18 MULTICAST_LIST_UPDATE_STATUS_CLASS, UWB_DL_TDOA_MEASUREMENT_CLASS, 19 UWB_OWR_AOA_MEASUREMENT_CLASS, UWB_RANGING_DATA_CLASS, UWB_TWO_WAY_MEASUREMENT_CLASS, 20 }; 21 22 use std::collections::HashMap; 23 use std::sync::Arc; 24 25 use jni::errors::Error as JNIError; 26 use jni::objects::{GlobalRef, JClass, JMethodID, JObject, JValue}; 27 use jni::signature::TypeSignature; 28 use jni::sys::jvalue; 29 use jni::{AttachGuard, JavaVM}; 30 use log::{debug, error}; 31 use uwb_core::error::{Error as UwbError, Result as UwbResult}; 32 use uwb_core::params::UwbAddress; 33 use uwb_core::uci::uci_manager_sync::{NotificationManager, NotificationManagerBuilder}; 34 use uwb_core::uci::{ 35 CoreNotification, DataRcvNotification, RangingMeasurements, SessionNotification, 36 SessionRangeData, 37 }; 38 use uwb_uci_packets::{ 39 ControleeStatus, ExtendedAddressDlTdoaRangingMeasurement, 40 ExtendedAddressOwrAoaRangingMeasurement, ExtendedAddressTwoWayRangingMeasurement, 41 MacAddressIndicator, RangingMeasurementType, SessionState, 42 ShortAddressDlTdoaRangingMeasurement, ShortAddressOwrAoaRangingMeasurement, 43 ShortAddressTwoWayRangingMeasurement, StatusCode, 44 }; 45 46 // Byte size of mac address length: 47 const SHORT_MAC_ADDRESS_LEN: i32 = 2; 48 const EXTENDED_MAC_ADDRESS_LEN: i32 = 8; 49 const MAX_ANCHOR_LOCATION_LEN: i32 = 12; 50 const MAX_RANGING_ROUNDS_LEN: i32 = 16; 51 52 // Maximum allowed number of Java Object to be allocated inside with_local_frame 53 const MAX_JAVA_OBJECTS_CAPACITY: i32 = 50; 54 55 enum MacAddress { 56 Short(u16), 57 Extended(u64), 58 } 59 impl MacAddress { into_ne_bytes(self) -> Vec<u8>60 fn into_ne_bytes(self) -> Vec<u8> { 61 match self { 62 MacAddress::Short(val) => val.to_ne_bytes().into(), 63 MacAddress::Extended(val) => val.to_ne_bytes().into(), 64 } 65 } 66 } 67 68 struct TwoWayRangingMeasurement { 69 mac_address: MacAddress, 70 status: StatusCode, 71 nlos: u8, 72 distance: u16, 73 aoa_azimuth: u16, 74 aoa_azimuth_fom: u8, 75 aoa_elevation: u16, 76 aoa_elevation_fom: u8, 77 aoa_destination_azimuth: u16, 78 aoa_destination_azimuth_fom: u8, 79 aoa_destination_elevation: u16, 80 aoa_destination_elevation_fom: u8, 81 slot_index: u8, 82 rssi: u8, 83 } 84 85 struct OwrAoaRangingMeasurement { 86 mac_address: MacAddress, 87 status: StatusCode, 88 nlos: u8, 89 frame_sequence_number: u8, 90 block_index: u16, 91 aoa_azimuth: u16, 92 aoa_azimuth_fom: u8, 93 aoa_elevation: u16, 94 aoa_elevation_fom: u8, 95 } 96 97 impl From<ShortAddressTwoWayRangingMeasurement> for TwoWayRangingMeasurement { from(measurement: ShortAddressTwoWayRangingMeasurement) -> Self98 fn from(measurement: ShortAddressTwoWayRangingMeasurement) -> Self { 99 TwoWayRangingMeasurement { 100 mac_address: MacAddress::Short(measurement.mac_address), 101 status: (measurement.status), 102 nlos: (measurement.nlos), 103 distance: (measurement.distance), 104 aoa_azimuth: (measurement.aoa_azimuth), 105 aoa_azimuth_fom: (measurement.aoa_azimuth_fom), 106 aoa_elevation: (measurement.aoa_elevation), 107 aoa_elevation_fom: (measurement.aoa_elevation_fom), 108 aoa_destination_azimuth: (measurement.aoa_destination_azimuth), 109 aoa_destination_azimuth_fom: (measurement.aoa_destination_azimuth_fom), 110 aoa_destination_elevation: (measurement.aoa_destination_elevation), 111 aoa_destination_elevation_fom: (measurement.aoa_destination_elevation_fom), 112 slot_index: (measurement.slot_index), 113 rssi: (measurement.rssi), 114 } 115 } 116 } 117 118 impl From<ExtendedAddressTwoWayRangingMeasurement> for TwoWayRangingMeasurement { from(measurement: ExtendedAddressTwoWayRangingMeasurement) -> Self119 fn from(measurement: ExtendedAddressTwoWayRangingMeasurement) -> Self { 120 TwoWayRangingMeasurement { 121 mac_address: MacAddress::Extended(measurement.mac_address), 122 status: (measurement.status), 123 nlos: (measurement.nlos), 124 distance: (measurement.distance), 125 aoa_azimuth: (measurement.aoa_azimuth), 126 aoa_azimuth_fom: (measurement.aoa_azimuth_fom), 127 aoa_elevation: (measurement.aoa_elevation), 128 aoa_elevation_fom: (measurement.aoa_elevation_fom), 129 aoa_destination_azimuth: (measurement.aoa_destination_azimuth), 130 aoa_destination_azimuth_fom: (measurement.aoa_destination_azimuth_fom), 131 aoa_destination_elevation: (measurement.aoa_destination_elevation), 132 aoa_destination_elevation_fom: (measurement.aoa_destination_elevation_fom), 133 slot_index: (measurement.slot_index), 134 rssi: (measurement.rssi), 135 } 136 } 137 } 138 139 impl From<ShortAddressOwrAoaRangingMeasurement> for OwrAoaRangingMeasurement { from(measurement: ShortAddressOwrAoaRangingMeasurement) -> Self140 fn from(measurement: ShortAddressOwrAoaRangingMeasurement) -> Self { 141 OwrAoaRangingMeasurement { 142 mac_address: MacAddress::Short(measurement.mac_address), 143 status: (measurement.status), 144 nlos: (measurement.nlos), 145 frame_sequence_number: (measurement.frame_sequence_number), 146 block_index: (measurement.block_index), 147 aoa_azimuth: (measurement.aoa_azimuth), 148 aoa_azimuth_fom: (measurement.aoa_azimuth_fom), 149 aoa_elevation: (measurement.aoa_elevation), 150 aoa_elevation_fom: (measurement.aoa_elevation_fom), 151 } 152 } 153 } 154 155 impl From<ExtendedAddressOwrAoaRangingMeasurement> for OwrAoaRangingMeasurement { from(measurement: ExtendedAddressOwrAoaRangingMeasurement) -> Self156 fn from(measurement: ExtendedAddressOwrAoaRangingMeasurement) -> Self { 157 OwrAoaRangingMeasurement { 158 mac_address: MacAddress::Extended(measurement.mac_address), 159 status: (measurement.status), 160 nlos: (measurement.nlos), 161 frame_sequence_number: (measurement.frame_sequence_number), 162 block_index: (measurement.block_index), 163 aoa_azimuth: (measurement.aoa_azimuth), 164 aoa_azimuth_fom: (measurement.aoa_azimuth_fom), 165 aoa_elevation: (measurement.aoa_elevation), 166 aoa_elevation_fom: (measurement.aoa_elevation_fom), 167 } 168 } 169 } 170 171 struct DlTdoaRangingMeasurement { 172 mac_address: MacAddress, 173 pub status: u8, 174 pub message_type: u8, 175 pub message_control: u16, 176 pub block_index: u16, 177 pub round_index: u8, 178 pub nlos: u8, 179 pub aoa_azimuth: u16, 180 pub aoa_azimuth_fom: u8, 181 pub aoa_elevation: u16, 182 pub aoa_elevation_fom: u8, 183 pub rssi: u8, 184 pub tx_timestamp: u64, 185 pub rx_timestamp: u64, 186 pub anchor_cfo: u16, 187 pub cfo: u16, 188 pub initiator_reply_time: u32, 189 pub responder_reply_time: u32, 190 pub initiator_responder_tof: u16, 191 pub dt_anchor_location: Vec<u8>, 192 pub ranging_rounds: Vec<u8>, 193 } 194 195 impl From<ExtendedAddressDlTdoaRangingMeasurement> for DlTdoaRangingMeasurement { from(measurement: ExtendedAddressDlTdoaRangingMeasurement) -> Self196 fn from(measurement: ExtendedAddressDlTdoaRangingMeasurement) -> Self { 197 DlTdoaRangingMeasurement { 198 mac_address: MacAddress::Extended(measurement.mac_address), 199 status: (measurement.measurement.status), 200 message_type: (measurement.measurement.message_type), 201 message_control: (measurement.measurement.message_control), 202 block_index: (measurement.measurement.block_index), 203 round_index: (measurement.measurement.round_index), 204 nlos: (measurement.measurement.nlos), 205 aoa_azimuth: (measurement.measurement.aoa_azimuth), 206 aoa_azimuth_fom: (measurement.measurement.aoa_azimuth_fom), 207 aoa_elevation: (measurement.measurement.aoa_elevation), 208 aoa_elevation_fom: (measurement.measurement.aoa_elevation_fom), 209 rssi: (measurement.measurement.rssi), 210 tx_timestamp: (measurement.measurement.tx_timestamp), 211 rx_timestamp: (measurement.measurement.rx_timestamp), 212 anchor_cfo: (measurement.measurement.anchor_cfo), 213 cfo: (measurement.measurement.cfo), 214 initiator_reply_time: (measurement.measurement.initiator_reply_time), 215 responder_reply_time: (measurement.measurement.responder_reply_time), 216 initiator_responder_tof: (measurement.measurement.initiator_responder_tof), 217 dt_anchor_location: (measurement.measurement.dt_anchor_location), 218 ranging_rounds: (measurement.measurement.ranging_rounds), 219 } 220 } 221 } 222 223 impl From<ShortAddressDlTdoaRangingMeasurement> for DlTdoaRangingMeasurement { from(measurement: ShortAddressDlTdoaRangingMeasurement) -> Self224 fn from(measurement: ShortAddressDlTdoaRangingMeasurement) -> Self { 225 DlTdoaRangingMeasurement { 226 mac_address: MacAddress::Short(measurement.mac_address), 227 status: (measurement.measurement.status), 228 message_type: (measurement.measurement.message_type), 229 message_control: (measurement.measurement.message_control), 230 block_index: (measurement.measurement.block_index), 231 round_index: (measurement.measurement.round_index), 232 nlos: (measurement.measurement.nlos), 233 aoa_azimuth: (measurement.measurement.aoa_azimuth), 234 aoa_azimuth_fom: (measurement.measurement.aoa_azimuth_fom), 235 aoa_elevation: (measurement.measurement.aoa_elevation), 236 aoa_elevation_fom: (measurement.measurement.aoa_elevation_fom), 237 rssi: (measurement.measurement.rssi), 238 tx_timestamp: (measurement.measurement.tx_timestamp), 239 rx_timestamp: (measurement.measurement.rx_timestamp), 240 anchor_cfo: (measurement.measurement.anchor_cfo), 241 cfo: (measurement.measurement.cfo), 242 initiator_reply_time: (measurement.measurement.initiator_reply_time), 243 responder_reply_time: (measurement.measurement.responder_reply_time), 244 initiator_responder_tof: (measurement.measurement.initiator_responder_tof), 245 dt_anchor_location: (measurement.measurement.dt_anchor_location), 246 ranging_rounds: (measurement.measurement.ranging_rounds), 247 } 248 } 249 } 250 251 pub(crate) struct NotificationManagerAndroid { 252 pub chip_id: String, 253 // 'static annotation is needed as env is 'sent' by tokio::task::spawn_local. 254 pub env: AttachGuard<'static>, 255 /// Global reference to the class loader object (java/lang/ClassLoader) from the java thread 256 /// that local java UCI classes can be loaded. 257 /// See http://yangyingchao.github.io/android/2015/01/13/Android-JNI-FindClass-Error.html 258 pub class_loader_obj: GlobalRef, 259 /// Global reference to the java class holding the various UCI notification callback functions. 260 pub callback_obj: GlobalRef, 261 // *_jmethod_id are cached for faster callback using call_method_unchecked 262 pub jmethod_id_map: HashMap<String, JMethodID>, 263 // jclass are cached for faster callback 264 pub jclass_map: HashMap<String, GlobalRef>, 265 } 266 267 // TODO(b/246678053): Need to add callbacks for Data Packet Rx, and Data Packet Tx events (like 268 // DATA_CREDIT_NTF, DATA_STATUS_NTF). 269 impl NotificationManagerAndroid { 270 /// Finds JClass stored in jclass map. Should be a member function, but disjoint field borrow 271 /// 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>272 fn find_local_class<'a>( 273 jclass_map: &'a mut HashMap<String, GlobalRef>, 274 class_loader_obj: &'a GlobalRef, 275 env: &'a AttachGuard<'static>, 276 class_name: &'a str, 277 ) -> Result<JClass<'a>, JNIError> { 278 // Look for cached class 279 if jclass_map.get(class_name).is_none() { 280 // Find class using the class loader object, needed as this call is initiated from a 281 // different native thread. 282 283 let env_class_name = *env.new_string(class_name).map_err(|e| { 284 error!("UCI JNI: failed to create Java String: {e:?}"); 285 e 286 })?; 287 let class_value = env 288 .call_method( 289 class_loader_obj.as_obj(), 290 "findClass", 291 "(Ljava/lang/String;)Ljava/lang/Class;", 292 &[JValue::Object(env_class_name)], 293 ) 294 .map_err(|e| { 295 error!("UCI JNI: failed to find java class {}: {:?}", class_name, e); 296 e 297 })?; 298 let jclass = match class_value.l() { 299 Ok(obj) => Ok(JClass::from(obj)), 300 Err(e) => { 301 error!("UCI JNI: failed to find java class {}: {:?}", class_name, e); 302 Err(e) 303 } 304 }?; 305 // Cache JClass as a global reference. 306 jclass_map.insert( 307 class_name.to_owned(), 308 env.new_global_ref(jclass).map_err(|e| { 309 error!("UCI JNI: global reference conversion failed: {:?}", e); 310 e 311 })?, 312 ); 313 } 314 // Return JClass 315 Ok(jclass_map.get(class_name).unwrap().as_obj().into()) 316 } 317 cached_jni_call( &mut self, name: &str, sig: &str, args: &[jvalue], ) -> Result<JObject, JNIError>318 fn cached_jni_call( 319 &mut self, 320 name: &str, 321 sig: &str, 322 args: &[jvalue], 323 ) -> Result<JObject, JNIError> { 324 debug!("UCI JNI: callback {}", name); 325 let type_signature = TypeSignature::from_str(sig).map_err(|e| { 326 error!("UCI JNI: Invalid type signature: {:?}", e); 327 e 328 })?; 329 if type_signature.args.len() != args.len() { 330 error!( 331 "UCI: type_signature requires {} args, but {} is provided", 332 type_signature.args.len(), 333 args.len() 334 ); 335 return Err(jni::errors::Error::InvalidArgList(type_signature)); 336 } 337 let name_signature = name.to_owned() + sig; 338 if self.jmethod_id_map.get(&name_signature).is_none() { 339 self.jmethod_id_map.insert( 340 name_signature.clone(), 341 self.env.get_method_id(self.callback_obj.as_obj(), name, sig).map_err(|e| { 342 error!("UCI JNI: failed to get method: {:?}", e); 343 e 344 })?, 345 ); 346 } 347 match self.env.call_method_unchecked( 348 self.callback_obj.as_obj(), 349 self.jmethod_id_map.get(&name_signature).unwrap().to_owned(), 350 type_signature.ret, 351 args, 352 ) { 353 Ok(_) => Ok(JObject::null()), 354 Err(e) => { 355 error!("UCI JNI: callback {} failed!", name); 356 Err(e) 357 } 358 } 359 } 360 on_session_status_notification( &mut self, session_id: u32, session_state: SessionState, reason_code: u8, ) -> Result<JObject, JNIError>361 fn on_session_status_notification( 362 &mut self, 363 session_id: u32, 364 session_state: SessionState, 365 reason_code: u8, 366 ) -> Result<JObject, JNIError> { 367 self.cached_jni_call( 368 "onSessionStatusNotificationReceived", 369 "(JII)V", 370 &[ 371 jvalue::from(JValue::Long(session_id as i64)), 372 jvalue::from(JValue::Int(session_state as i32)), 373 jvalue::from(JValue::Int(reason_code as i32)), 374 ], 375 ) 376 } 377 on_session_update_multicast_notification( &mut self, session_id: u32, remaining_multicast_list_size: usize, status_list: Vec<ControleeStatus>, ) -> Result<JObject, JNIError>378 fn on_session_update_multicast_notification( 379 &mut self, 380 session_id: u32, 381 remaining_multicast_list_size: usize, 382 status_list: Vec<ControleeStatus>, 383 ) -> Result<JObject, JNIError> { 384 let remaining_multicast_list_size: i32 = 385 remaining_multicast_list_size.try_into().map_err(|_| JNIError::InvalidCtorReturn)?; 386 let count: i32 = status_list.len().try_into().map_err(|_| JNIError::InvalidCtorReturn)?; 387 let subsession_id_jlongarray = self.env.new_long_array(count)?; 388 let status_jintarray = self.env.new_int_array(count)?; 389 let (mac_address_vec, (subsession_id_vec, status_vec)): (Vec<[u8; 2]>, (Vec<_>, Vec<_>)) = 390 status_list 391 .into_iter() 392 .map(|cs| (cs.mac_address, (cs.subsession_id as i64, cs.status as i32))) 393 .unzip(); 394 395 let mac_address_vec_i8 = 396 mac_address_vec.iter().flat_map(|&[a, b]| vec![a as i8, b as i8]).collect::<Vec<i8>>(); 397 let mac_address_slice: &[i8] = &mac_address_vec_i8; 398 let mac_address_jbytearray = self.env.new_byte_array(mac_address_slice.len() as i32)?; 399 400 self.env.set_byte_array_region(mac_address_jbytearray, 0, mac_address_slice)?; 401 self.env.set_long_array_region(subsession_id_jlongarray, 0, &subsession_id_vec)?; 402 self.env.set_int_array_region(status_jintarray, 0, &status_vec)?; 403 let multicast_update_jclass = NotificationManagerAndroid::find_local_class( 404 &mut self.jclass_map, 405 &self.class_loader_obj, 406 &self.env, 407 MULTICAST_LIST_UPDATE_STATUS_CLASS, 408 )?; 409 let method_sig = "(L".to_owned() + MULTICAST_LIST_UPDATE_STATUS_CLASS + ";)V"; 410 411 // Safety: mac_address_jintarray is safely instantiated above. 412 let mac_address_jobject = unsafe { JObject::from_raw(mac_address_jbytearray) }; 413 414 // Safety: subsession_id_jlongarray is safely instantiated above. 415 let subsession_id_jobject = unsafe { JObject::from_raw(subsession_id_jlongarray) }; 416 417 // Safety: status_jintarray is safely instantiated above. 418 let status_jobject = unsafe { JObject::from_raw(status_jintarray) }; 419 420 let multicast_update_jobject = self.env.new_object( 421 multicast_update_jclass, 422 "(JII[B[J[I)V", 423 &[ 424 JValue::Long(session_id as i64), 425 JValue::Int(remaining_multicast_list_size), 426 JValue::Int(count), 427 JValue::Object(mac_address_jobject), 428 JValue::Object(subsession_id_jobject), 429 JValue::Object(status_jobject), 430 ], 431 )?; 432 self.cached_jni_call( 433 "onMulticastListUpdateNotificationReceived", 434 &method_sig, 435 &[jvalue::from(JValue::Object(multicast_update_jobject))], 436 ) 437 } 438 439 // TODO(b/246678053): Re-factor usage of the RangingMeasurement enum below, to extract the 440 // 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>441 fn on_session_dl_tdoa_range_data_notification( 442 &mut self, 443 range_data: SessionRangeData, 444 ) -> Result<JObject, JNIError> { 445 let raw_notification_jbytearray = 446 self.env.byte_array_from_slice(&range_data.raw_ranging_data)?; 447 let measurement_jclass = NotificationManagerAndroid::find_local_class( 448 &mut self.jclass_map, 449 &self.class_loader_obj, 450 &self.env, 451 UWB_DL_TDOA_MEASUREMENT_CLASS, 452 )?; 453 let bytearray_len: i32 = match &range_data.ranging_measurements { 454 uwb_core::uci::RangingMeasurements::ShortAddressTwoWay(_) => SHORT_MAC_ADDRESS_LEN, 455 uwb_core::uci::RangingMeasurements::ExtendedAddressTwoWay(_) => { 456 EXTENDED_MAC_ADDRESS_LEN 457 } 458 uwb_core::uci::RangingMeasurements::ShortAddressDltdoa(_) => SHORT_MAC_ADDRESS_LEN, 459 uwb_core::uci::RangingMeasurements::ExtendedAddressDltdoa(_) => { 460 EXTENDED_MAC_ADDRESS_LEN 461 } 462 _ => { 463 return Err(JNIError::InvalidCtorReturn); 464 } 465 }; 466 let address_jbytearray = self.env.new_byte_array(bytearray_len)?; 467 let anchor_location = self.env.new_byte_array(MAX_ANCHOR_LOCATION_LEN)?; 468 let active_ranging_rounds = self.env.new_byte_array(MAX_RANGING_ROUNDS_LEN)?; 469 470 // Safety: address_jbytearray is safely instantiated above. 471 let address_jobject = unsafe { JObject::from_raw(address_jbytearray) }; 472 // Safety: anchor_location is safely instantiated above. 473 let anchor_jobject = unsafe { JObject::from_raw(anchor_location) }; 474 // Safety: active_ranging_rounds is safely instantiated above. 475 let active_ranging_rounds_jobject = unsafe { JObject::from_raw(active_ranging_rounds) }; 476 477 let zero_initiated_measurement_jobject = self 478 .env 479 .new_object( 480 measurement_jclass, 481 "([BIIIIIIIIIIIJJIIJJI[B[B)V", 482 &[ 483 JValue::Object(address_jobject), 484 JValue::Int(0), 485 JValue::Int(0), 486 JValue::Int(0), 487 JValue::Int(0), 488 JValue::Int(0), 489 JValue::Int(0), 490 JValue::Int(0), 491 JValue::Int(0), 492 JValue::Int(0), 493 JValue::Int(0), 494 JValue::Int(0), 495 JValue::Long(0), 496 JValue::Long(0), 497 JValue::Int(0), 498 JValue::Int(0), 499 JValue::Long(0), 500 JValue::Long(0), 501 JValue::Int(0), 502 JValue::Object(anchor_jobject), 503 JValue::Object(active_ranging_rounds_jobject), 504 ], 505 ) 506 .map_err(|e| { 507 error!("UCI JNI: measurement object creation failed: {:?}", e); 508 e 509 })?; 510 let measurement_count: i32 = match &range_data.ranging_measurements { 511 RangingMeasurements::ShortAddressTwoWay(v) => v.len(), 512 RangingMeasurements::ExtendedAddressTwoWay(v) => v.len(), 513 RangingMeasurements::ShortAddressDltdoa(v) => v.len(), 514 RangingMeasurements::ExtendedAddressDltdoa(v) => v.len(), 515 _ => { 516 return Err(JNIError::InvalidCtorReturn); 517 } 518 } 519 .try_into() 520 .map_err(|_| JNIError::InvalidCtorReturn)?; 521 let mac_indicator = match &range_data.ranging_measurements { 522 RangingMeasurements::ShortAddressTwoWay(_) => MacAddressIndicator::ShortAddress, 523 RangingMeasurements::ExtendedAddressTwoWay(_) => MacAddressIndicator::ExtendedAddress, 524 RangingMeasurements::ShortAddressDltdoa(_) => MacAddressIndicator::ShortAddress, 525 RangingMeasurements::ExtendedAddressDltdoa(_) => MacAddressIndicator::ExtendedAddress, 526 _ => { 527 return Err(JNIError::InvalidCtorReturn); 528 } 529 }; 530 531 let measurements_jobjectarray = self.env.new_object_array( 532 measurement_count, 533 measurement_jclass, 534 zero_initiated_measurement_jobject, 535 )?; 536 537 for (i, measurement) in match range_data.ranging_measurements { 538 RangingMeasurements::ShortAddressDltdoa(v) => { 539 v.into_iter().map(DlTdoaRangingMeasurement::from).collect::<Vec<_>>() 540 } 541 RangingMeasurements::ExtendedAddressDltdoa(v) => { 542 v.into_iter().map(DlTdoaRangingMeasurement::from).collect::<Vec<_>>() 543 } 544 _ => Vec::new(), 545 } 546 .into_iter() 547 .enumerate() 548 { 549 // cast to i8 as java do not support unsigned: 550 let mac_address_i8 = measurement 551 .mac_address 552 .into_ne_bytes() 553 .iter() 554 .map(|b| b.to_owned() as i8) 555 .collect::<Vec<_>>(); 556 let mac_address_jbytearray = self.env.new_byte_array(mac_address_i8.len() as i32)?; 557 self.env.set_byte_array_region(mac_address_jbytearray, 0, &mac_address_i8)?; 558 559 let dt_anchor_location_jbytearray = 560 self.env.byte_array_from_slice(&measurement.dt_anchor_location)?; 561 562 let ranging_rounds_jbytearray = 563 self.env.byte_array_from_slice(&measurement.ranging_rounds)?; 564 565 // Safety: mac_address_jbytearray is safely instantiated above. 566 let mac_address_jobject = unsafe { JObject::from_raw(mac_address_jbytearray) }; 567 // Safety: dt_anchor_location_jbytearray is safely instantiated above. 568 let dt_anchor_location_jobject = 569 unsafe { JObject::from_raw(dt_anchor_location_jbytearray) }; 570 // Safety: ranging_rounds_jbytearray is safely instantiated above. 571 let ranging_rounds_jobject = unsafe { JObject::from_raw(ranging_rounds_jbytearray) }; 572 573 let measurement_jobject = self 574 .env 575 .new_object( 576 measurement_jclass, 577 "([BIIIIIIIIIIIJJIIJJI[B[B)V", 578 &[ 579 JValue::Object(mac_address_jobject), 580 JValue::Int(measurement.status as i32), 581 JValue::Int(measurement.message_type as i32), 582 JValue::Int(measurement.message_control as i32), 583 JValue::Int(measurement.block_index as i32), 584 JValue::Int(measurement.round_index as i32), 585 JValue::Int(measurement.nlos as i32), 586 JValue::Int(measurement.aoa_azimuth as i32), 587 JValue::Int(measurement.aoa_azimuth_fom as i32), 588 JValue::Int(measurement.aoa_elevation as i32), 589 JValue::Int(measurement.aoa_elevation_fom as i32), 590 JValue::Int(measurement.rssi as i32), 591 JValue::Long(measurement.tx_timestamp as i64), 592 JValue::Long(measurement.rx_timestamp as i64), 593 JValue::Int(measurement.anchor_cfo as i32), 594 JValue::Int(measurement.cfo as i32), 595 JValue::Long(measurement.initiator_reply_time as i64), 596 JValue::Long(measurement.responder_reply_time as i64), 597 JValue::Int(measurement.initiator_responder_tof as i32), 598 JValue::Object(dt_anchor_location_jobject), 599 JValue::Object(ranging_rounds_jobject), 600 ], 601 ) 602 .map_err(|e| { 603 error!("UCI JNI: measurement object creation failed: {:?}", e); 604 e 605 })?; 606 self.env 607 .set_object_array_element(measurements_jobjectarray, i as i32, measurement_jobject) 608 .map_err(|e| { 609 error!("UCI JNI: measurement object copy failed: {:?}", e); 610 e 611 })?; 612 } 613 // Create UwbRangingData 614 let ranging_data_jclass = NotificationManagerAndroid::find_local_class( 615 &mut self.jclass_map, 616 &self.class_loader_obj, 617 &self.env, 618 UWB_RANGING_DATA_CLASS, 619 )?; 620 621 let method_sig = "(JJIJIII[L".to_owned() + UWB_DL_TDOA_MEASUREMENT_CLASS + ";[B)V"; 622 623 // Safety: measurements_jobjectarray is safely instantiated above. 624 let measurements_jobject = unsafe { JObject::from_raw(measurements_jobjectarray) }; 625 // Safety: raw_notification_jbytearray is safely instantiated above. 626 let raw_notification_jobject = unsafe { JObject::from_raw(raw_notification_jbytearray) }; 627 628 let range_data_jobject = self 629 .env 630 .new_object( 631 ranging_data_jclass, 632 &method_sig, 633 &[ 634 JValue::Long(range_data.sequence_number as i64), 635 // session_token below has already been mapped to session_id by uci layer. 636 JValue::Long(range_data.session_token as i64), 637 JValue::Int(range_data.rcr_indicator as i32), 638 JValue::Long(range_data.current_ranging_interval_ms as i64), 639 JValue::Int(range_data.ranging_measurement_type as i32), 640 JValue::Int(mac_indicator as i32), 641 JValue::Int(measurement_count), 642 JValue::Object(measurements_jobject), 643 JValue::Object(raw_notification_jobject), 644 ], 645 ) 646 .map_err(|e| { 647 error!("UCI JNI: Ranging Data object creation failed: {:?}", e); 648 e 649 })?; 650 651 let method_sig = "(L".to_owned() + UWB_RANGING_DATA_CLASS + ";)V"; 652 self.cached_jni_call( 653 "onRangeDataNotificationReceived", 654 &method_sig, 655 &[jvalue::from(JValue::Object(range_data_jobject))], 656 ) 657 } 658 on_two_way_range_data_notification( &mut self, bytearray_len: i32, measurement_count: i32, measurements: Vec<TwoWayRangingMeasurement>, ) -> Result<jni::sys::jobjectArray, JNIError>659 fn on_two_way_range_data_notification( 660 &mut self, 661 bytearray_len: i32, 662 measurement_count: i32, 663 measurements: Vec<TwoWayRangingMeasurement>, 664 ) -> Result<jni::sys::jobjectArray, JNIError> { 665 let measurement_jclass = NotificationManagerAndroid::find_local_class( 666 &mut self.jclass_map, 667 &self.class_loader_obj, 668 &self.env, 669 UWB_TWO_WAY_MEASUREMENT_CLASS, 670 )?; 671 let address_jbytearray = self.env.new_byte_array(bytearray_len)?; 672 673 // Safety: address_jbytearray is safely instantiated above. 674 let address_jobject = unsafe { JObject::from_raw(address_jbytearray) }; 675 676 let zero_initiated_measurement_jobject = self 677 .env 678 .new_object( 679 measurement_jclass, 680 "([BIIIIIIIIIIIII)V", 681 &[ 682 JValue::Object(address_jobject), 683 JValue::Int(0), 684 JValue::Int(0), 685 JValue::Int(0), 686 JValue::Int(0), 687 JValue::Int(0), 688 JValue::Int(0), 689 JValue::Int(0), 690 JValue::Int(0), 691 JValue::Int(0), 692 JValue::Int(0), 693 JValue::Int(0), 694 JValue::Int(0), 695 JValue::Int(0), 696 ], 697 ) 698 .map_err(|e| { 699 error!("UCI JNI: measurement object creation failed: {:?}", e); 700 e 701 })?; 702 703 let measurements_jobjectarray = self.env.new_object_array( 704 measurement_count, 705 measurement_jclass, 706 zero_initiated_measurement_jobject, 707 )?; 708 for (i, measurement) in measurements.into_iter().enumerate() { 709 // cast to i8 as java do not support unsigned: 710 let mac_address_i8 = measurement 711 .mac_address 712 .into_ne_bytes() 713 .iter() 714 .map(|b| b.to_owned() as i8) 715 .collect::<Vec<_>>(); 716 let mac_address_jbytearray = self.env.new_byte_array(mac_address_i8.len() as i32)?; 717 self.env.set_byte_array_region(mac_address_jbytearray, 0, &mac_address_i8)?; 718 // casting as i32 is fine since it is wider than actual integer type. 719 720 // Safety: mac_address_jbytearray is safely instantiated above. 721 let mac_address_jobject = unsafe { JObject::from_raw(mac_address_jbytearray) }; 722 let measurement_jobject = self 723 .env 724 .new_object( 725 measurement_jclass, 726 "([BIIIIIIIIIIIII)V", 727 &[ 728 JValue::Object(mac_address_jobject), 729 JValue::Int(i32::from(measurement.status)), 730 JValue::Int(measurement.nlos as i32), 731 JValue::Int(measurement.distance as i32), 732 JValue::Int(measurement.aoa_azimuth as i32), 733 JValue::Int(measurement.aoa_azimuth_fom as i32), 734 JValue::Int(measurement.aoa_elevation as i32), 735 JValue::Int(measurement.aoa_elevation_fom as i32), 736 JValue::Int(measurement.aoa_destination_azimuth as i32), 737 JValue::Int(measurement.aoa_destination_azimuth_fom as i32), 738 JValue::Int(measurement.aoa_destination_elevation as i32), 739 JValue::Int(measurement.aoa_destination_elevation_fom as i32), 740 JValue::Int(measurement.slot_index as i32), 741 JValue::Int(measurement.rssi as i32), 742 ], 743 ) 744 .map_err(|e| { 745 error!("UCI JNI: measurement object creation failed: {:?}", e); 746 e 747 })?; 748 self.env 749 .set_object_array_element(measurements_jobjectarray, i as i32, measurement_jobject) 750 .map_err(|e| { 751 error!("UCI JNI: measurement object copy failed: {:?}", e); 752 e 753 })?; 754 } 755 756 Ok(measurements_jobjectarray) 757 } 758 on_session_owr_aoa_range_data_notification( &mut self, range_data: SessionRangeData, ) -> Result<JObject, JNIError>759 fn on_session_owr_aoa_range_data_notification( 760 &mut self, 761 range_data: SessionRangeData, 762 ) -> Result<JObject, JNIError> { 763 if range_data.ranging_measurement_type != RangingMeasurementType::OwrAoa { 764 return Err(JNIError::InvalidCtorReturn); 765 } 766 767 let raw_notification_jbytearray = 768 self.env.byte_array_from_slice(&range_data.raw_ranging_data)?; 769 770 let (mac_indicator, measurement): (MacAddressIndicator, OwrAoaRangingMeasurement) = 771 match range_data.ranging_measurements { 772 RangingMeasurements::ExtendedAddressOwrAoa(m) => { 773 (MacAddressIndicator::ExtendedAddress, m.into()) 774 } 775 RangingMeasurements::ShortAddressOwrAoa(m) => { 776 (MacAddressIndicator::ShortAddress, m.into()) 777 } 778 _ => { 779 return Err(JNIError::InvalidCtorReturn); 780 } 781 }; 782 783 // cast to i8 as java do not support unsigned. 784 let mac_address_i8 = measurement 785 .mac_address 786 .into_ne_bytes() 787 .iter() 788 .map(|b| b.to_owned() as i8) 789 .collect::<Vec<_>>(); 790 // casting as i32 is fine since it is wider than actual integer type. 791 let mac_address_jbytearray = self.env.new_byte_array(mac_address_i8.len() as i32)?; 792 self.env.set_byte_array_region(mac_address_jbytearray, 0, &mac_address_i8)?; 793 // Safety: mac_address_jbytearray is safely instantiated above. 794 let mac_address_jobject = unsafe { JObject::from_raw(mac_address_jbytearray) }; 795 796 let measurement_jclass = NotificationManagerAndroid::find_local_class( 797 &mut self.jclass_map, 798 &self.class_loader_obj, 799 &self.env, 800 UWB_OWR_AOA_MEASUREMENT_CLASS, 801 )?; 802 let measurement_jobject = self 803 .env 804 .new_object( 805 measurement_jclass, 806 "([BIIIIIIII)V", 807 &[ 808 JValue::Object(mac_address_jobject), 809 JValue::Int(i32::from(measurement.status)), 810 JValue::Int(measurement.nlos as i32), 811 JValue::Int(measurement.frame_sequence_number as i32), 812 JValue::Int(measurement.block_index as i32), 813 JValue::Int(measurement.aoa_azimuth as i32), 814 JValue::Int(measurement.aoa_azimuth_fom as i32), 815 JValue::Int(measurement.aoa_elevation as i32), 816 JValue::Int(measurement.aoa_elevation_fom as i32), 817 ], 818 ) 819 .map_err(|e| { 820 error!("UCI JNI: OwrAoA measurement jobject creation failed: {:?}", e); 821 e 822 })?; 823 824 // Create UwbRangingData 825 let ranging_data_jclass = NotificationManagerAndroid::find_local_class( 826 &mut self.jclass_map, 827 &self.class_loader_obj, 828 &self.env, 829 UWB_RANGING_DATA_CLASS, 830 )?; 831 let method_sig = "(JJIJIIIL".to_owned() + UWB_OWR_AOA_MEASUREMENT_CLASS + ";[B)V"; 832 833 // Safety: raw_notification_jobject is safely instantiated above. 834 let raw_notification_jobject = unsafe { JObject::from_raw(raw_notification_jbytearray) }; 835 836 let range_data_jobject = self 837 .env 838 .new_object( 839 ranging_data_jclass, 840 &method_sig, 841 &[ 842 JValue::Long(range_data.sequence_number as i64), 843 // session_token below has already been mapped to session_id by uci layer. 844 JValue::Long(range_data.session_token as i64), 845 JValue::Int(range_data.rcr_indicator as i32), 846 JValue::Long(range_data.current_ranging_interval_ms as i64), 847 JValue::Int(range_data.ranging_measurement_type as i32), 848 JValue::Int(mac_indicator as i32), 849 JValue::Int(1), // measurement_count 850 JValue::Object(measurement_jobject), 851 JValue::Object(raw_notification_jobject), 852 ], 853 ) 854 .map_err(|e| { 855 error!("UCI JNI: Ranging Data object creation failed: {:?}", e); 856 e 857 })?; 858 let method_sig = "(L".to_owned() + UWB_RANGING_DATA_CLASS + ";)V"; 859 self.cached_jni_call( 860 "onRangeDataNotificationReceived", 861 &method_sig, 862 &[jvalue::from(JValue::Object(range_data_jobject))], 863 ) 864 } 865 on_session_two_way_range_data_notification( &mut self, range_data: SessionRangeData, ) -> Result<JObject, JNIError>866 fn on_session_two_way_range_data_notification( 867 &mut self, 868 range_data: SessionRangeData, 869 ) -> Result<JObject, JNIError> { 870 let raw_notification_jbytearray = 871 self.env.byte_array_from_slice(&range_data.raw_ranging_data)?; 872 873 let (bytearray_len, mac_indicator) = match &range_data.ranging_measurements { 874 RangingMeasurements::ExtendedAddressTwoWay(_) => { 875 (EXTENDED_MAC_ADDRESS_LEN, MacAddressIndicator::ExtendedAddress) 876 } 877 RangingMeasurements::ShortAddressTwoWay(_) => { 878 (SHORT_MAC_ADDRESS_LEN, MacAddressIndicator::ShortAddress) 879 } 880 _ => { 881 return Err(JNIError::InvalidCtorReturn); 882 } 883 }; 884 885 let measurement_count: i32 = match &range_data.ranging_measurements { 886 RangingMeasurements::ShortAddressTwoWay(v) => v.len().try_into(), 887 RangingMeasurements::ExtendedAddressTwoWay(v) => v.len().try_into(), 888 _ => { 889 return Err(JNIError::InvalidCtorReturn); 890 } 891 } 892 .map_err(|_| JNIError::InvalidCtorReturn)?; 893 894 let measurements_jobjectarray = match range_data.ranging_measurement_type { 895 RangingMeasurementType::TwoWay => { 896 let measurements = match range_data.ranging_measurements { 897 RangingMeasurements::ExtendedAddressTwoWay(v) => { 898 v.into_iter().map(TwoWayRangingMeasurement::from).collect::<Vec<_>>() 899 } 900 RangingMeasurements::ShortAddressTwoWay(v) => { 901 v.into_iter().map(TwoWayRangingMeasurement::from).collect::<Vec<_>>() 902 } 903 _ => return Err(JNIError::InvalidCtorReturn), 904 }; 905 self.on_two_way_range_data_notification( 906 bytearray_len, 907 measurement_count, 908 measurements, 909 )? 910 } 911 _ => { 912 return Err(JNIError::InvalidCtorReturn); 913 } 914 }; 915 916 // Create UwbRangingData 917 let ranging_data_jclass = NotificationManagerAndroid::find_local_class( 918 &mut self.jclass_map, 919 &self.class_loader_obj, 920 &self.env, 921 UWB_RANGING_DATA_CLASS, 922 )?; 923 let method_sig = "(JJIJIII[L".to_owned() + UWB_TWO_WAY_MEASUREMENT_CLASS + ";[B)V"; 924 925 // Safety: measurements_jobjectarray is safely instantiated above. 926 let measurements_jobject = unsafe { JObject::from_raw(measurements_jobjectarray) }; 927 // Safety: raw_notification_jobject is safely instantiated above. 928 let raw_notification_jobject = unsafe { JObject::from_raw(raw_notification_jbytearray) }; 929 let range_data_jobject = self 930 .env 931 .new_object( 932 ranging_data_jclass, 933 &method_sig, 934 &[ 935 JValue::Long(range_data.sequence_number as i64), 936 // session_token below has already been mapped to session_id by uci layer. 937 JValue::Long(range_data.session_token as i64), 938 JValue::Int(range_data.rcr_indicator as i32), 939 JValue::Long(range_data.current_ranging_interval_ms as i64), 940 JValue::Int(range_data.ranging_measurement_type as i32), 941 JValue::Int(mac_indicator as i32), 942 JValue::Int(measurement_count), 943 JValue::Object(measurements_jobject), 944 JValue::Object(raw_notification_jobject), 945 ], 946 ) 947 .map_err(|e| { 948 error!("UCI JNI: Ranging Data object creation failed: {:?}", e); 949 e 950 })?; 951 let method_sig = "(L".to_owned() + UWB_RANGING_DATA_CLASS + ";)V"; 952 self.cached_jni_call( 953 "onRangeDataNotificationReceived", 954 &method_sig, 955 &[jvalue::from(JValue::Object(range_data_jobject))], 956 ) 957 } 958 on_data_transfer_status_notification( &mut self, session_id: u32, uci_sequence_number: u8, status_code: u8, ) -> Result<JObject, JNIError>959 fn on_data_transfer_status_notification( 960 &mut self, 961 session_id: u32, 962 uci_sequence_number: u8, 963 status_code: u8, 964 ) -> Result<JObject, JNIError> { 965 self.cached_jni_call( 966 "onDataSendStatus", 967 "(JIJ)V", 968 &[ 969 jvalue::from(JValue::Long(session_id as i64)), 970 jvalue::from(JValue::Int(status_code as i32)), 971 jvalue::from(JValue::Long(uci_sequence_number as i64)), 972 ], 973 ) 974 } 975 } 976 977 impl NotificationManager for NotificationManagerAndroid { on_core_notification(&mut self, core_notification: CoreNotification) -> UwbResult<()>978 fn on_core_notification(&mut self, core_notification: CoreNotification) -> UwbResult<()> { 979 debug!("UCI JNI: core notification callback."); 980 let env = *self.env; 981 env.with_local_frame(MAX_JAVA_OBJECTS_CAPACITY, || { 982 let env_chip_id_jobject = *self.env.new_string(&self.chip_id).unwrap(); 983 984 match core_notification { 985 CoreNotification::DeviceStatus(device_state) => self.cached_jni_call( 986 "onDeviceStatusNotificationReceived", 987 "(ILjava/lang/String;)V", 988 &[ 989 jvalue::from(JValue::Int(device_state as i32)), 990 jvalue::from(JValue::Object(env_chip_id_jobject)), 991 ], 992 ), 993 CoreNotification::GenericError(generic_error) => self.cached_jni_call( 994 "onCoreGenericErrorNotificationReceived", 995 "(ILjava/lang/String;)V", 996 &[ 997 jvalue::from(JValue::Int(i32::from(generic_error))), 998 jvalue::from(JValue::Object(env_chip_id_jobject)), 999 ], 1000 ), 1001 } 1002 }) 1003 .map_err(|_| UwbError::ForeignFunctionInterface)?; 1004 1005 Ok(()) 1006 } 1007 on_session_notification( &mut self, session_notification: SessionNotification, ) -> UwbResult<()>1008 fn on_session_notification( 1009 &mut self, 1010 session_notification: SessionNotification, 1011 ) -> UwbResult<()> { 1012 debug!("UCI JNI: session notification callback."); 1013 let env = *self.env; 1014 env.with_local_frame(MAX_JAVA_OBJECTS_CAPACITY, || { 1015 match session_notification { 1016 // session_token below has already been mapped to session_id by uci layer. 1017 SessionNotification::Status { session_token, session_state, reason_code } => { 1018 self.on_session_status_notification(session_token, session_state, reason_code) 1019 } 1020 SessionNotification::UpdateControllerMulticastList { 1021 session_token, 1022 remaining_multicast_list_size, 1023 status_list, 1024 } => self.on_session_update_multicast_notification( 1025 session_token, 1026 remaining_multicast_list_size, 1027 status_list, 1028 ), 1029 // TODO(b/246678053): Match here on range_data.ranging_measurement_type instead. 1030 SessionNotification::SessionInfo(range_data) => { 1031 match range_data.ranging_measurements { 1032 uwb_core::uci::RangingMeasurements::ShortAddressTwoWay(_) => { 1033 self.on_session_two_way_range_data_notification(range_data) 1034 } 1035 uwb_core::uci::RangingMeasurements::ExtendedAddressTwoWay(_) => { 1036 self.on_session_two_way_range_data_notification(range_data) 1037 } 1038 uwb_core::uci::RangingMeasurements::ShortAddressOwrAoa(_) => { 1039 self.on_session_owr_aoa_range_data_notification(range_data) 1040 } 1041 uwb_core::uci::RangingMeasurements::ExtendedAddressOwrAoa(_) => { 1042 self.on_session_owr_aoa_range_data_notification(range_data) 1043 } 1044 uwb_core::uci::RangingMeasurements::ShortAddressDltdoa(_) => { 1045 self.on_session_dl_tdoa_range_data_notification(range_data) 1046 } 1047 uwb_core::uci::RangingMeasurements::ExtendedAddressDltdoa(_) => { 1048 self.on_session_dl_tdoa_range_data_notification(range_data) 1049 } 1050 } 1051 } 1052 SessionNotification::DataTransferStatus { 1053 session_token, 1054 uci_sequence_number, 1055 status, 1056 } => self.on_data_transfer_status_notification( 1057 session_token, 1058 uci_sequence_number, 1059 u8::from(status), 1060 ), 1061 // This session notification should not come here, as it's handled within 1062 // UciManager, for internal state management related to sending data packet(s). 1063 SessionNotification::DataCredit { session_token, credit_availability } => { 1064 error!( 1065 "UCI JNI: Received unexpected DataCredit notification for \ 1066 session_token {}, credit_availability {:?}", 1067 session_token, credit_availability 1068 ); 1069 Err(JNIError::InvalidCtorReturn) 1070 } 1071 } 1072 }) 1073 .map_err(|_| UwbError::ForeignFunctionInterface)?; 1074 Ok(()) 1075 } 1076 on_vendor_notification( &mut self, vendor_notification: uwb_core::params::RawUciMessage, ) -> UwbResult<()>1077 fn on_vendor_notification( 1078 &mut self, 1079 vendor_notification: uwb_core::params::RawUciMessage, 1080 ) -> UwbResult<()> { 1081 debug!("UCI JNI: vendor notification callback."); 1082 let env = *self.env; 1083 env.with_local_frame(MAX_JAVA_OBJECTS_CAPACITY, || { 1084 let payload_jbytearray = 1085 self.env.byte_array_from_slice(&vendor_notification.payload)?; 1086 1087 // Safety: payload_jbytearray safely instantiated above. 1088 let payload_jobject = unsafe { JObject::from_raw(payload_jbytearray) }; 1089 self.cached_jni_call( 1090 "onVendorUciNotificationReceived", 1091 "(II[B)V", 1092 &[ 1093 // Java only has signed integer. The range for signed int32 should be sufficient. 1094 jvalue::from(JValue::Int( 1095 vendor_notification 1096 .gid 1097 .try_into() 1098 .map_err(|_| JNIError::InvalidCtorReturn)?, 1099 )), 1100 jvalue::from(JValue::Int( 1101 vendor_notification 1102 .oid 1103 .try_into() 1104 .map_err(|_| JNIError::InvalidCtorReturn)?, 1105 )), 1106 jvalue::from(JValue::Object(payload_jobject)), 1107 ], 1108 ) 1109 }) 1110 .map_err(|_| UwbError::ForeignFunctionInterface)?; 1111 Ok(()) 1112 } 1113 on_data_rcv_notification( &mut self, data_rcv_notification: DataRcvNotification, ) -> UwbResult<()>1114 fn on_data_rcv_notification( 1115 &mut self, 1116 data_rcv_notification: DataRcvNotification, 1117 ) -> UwbResult<()> { 1118 debug!("UCI JNI: Data Rcv notification callback."); 1119 let env = *self.env; 1120 env.with_local_frame(MAX_JAVA_OBJECTS_CAPACITY, || { 1121 let source_address_jbytearray = match &data_rcv_notification.source_address { 1122 UwbAddress::Short(a) => self.env.byte_array_from_slice(a)?, 1123 UwbAddress::Extended(a) => self.env.byte_array_from_slice(a)?, 1124 }; 1125 let payload_jbytearray = 1126 self.env.byte_array_from_slice(&data_rcv_notification.payload)?; 1127 // Safety: source_address_jbytearray safely instantiated above. 1128 let source_address_jobject = unsafe { JObject::from_raw(source_address_jbytearray) }; 1129 // Safety: payload_jbytearray safely instantiated above. 1130 let payload_jobject = unsafe { JObject::from_raw(payload_jbytearray) }; 1131 self.cached_jni_call( 1132 "onDataReceived", 1133 "(JIJ[BII[B)V", 1134 &[ 1135 // session_token below has already been mapped to session_id by uci layer. 1136 jvalue::from(JValue::Long(data_rcv_notification.session_token as i64)), 1137 jvalue::from(JValue::Int(data_rcv_notification.status as i32)), 1138 jvalue::from(JValue::Long(data_rcv_notification.uci_sequence_num as i64)), 1139 jvalue::from(JValue::Object(source_address_jobject)), 1140 jvalue::from(JValue::Int(data_rcv_notification.source_fira_component as i32)), 1141 jvalue::from(JValue::Int(data_rcv_notification.dest_fira_component as i32)), 1142 jvalue::from(JValue::Object(payload_jobject)), 1143 ], 1144 ) 1145 }) 1146 .map_err(|_| UwbError::ForeignFunctionInterface)?; 1147 Ok(()) 1148 } 1149 } 1150 pub(crate) struct NotificationManagerAndroidBuilder { 1151 pub chip_id: String, 1152 pub vm: &'static Arc<JavaVM>, 1153 pub class_loader_obj: GlobalRef, 1154 pub callback_obj: GlobalRef, 1155 } 1156 1157 impl NotificationManagerBuilder for NotificationManagerAndroidBuilder { 1158 type NotificationManager = NotificationManagerAndroid; 1159 build(self) -> Option<Self::NotificationManager>1160 fn build(self) -> Option<Self::NotificationManager> { 1161 if let Ok(env) = self.vm.attach_current_thread() { 1162 Some(NotificationManagerAndroid { 1163 chip_id: self.chip_id, 1164 env, 1165 class_loader_obj: self.class_loader_obj, 1166 callback_obj: self.callback_obj, 1167 jmethod_id_map: HashMap::new(), 1168 jclass_map: HashMap::new(), 1169 }) 1170 } else { 1171 None 1172 } 1173 } 1174 } 1175