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 //! This module contains structures and methods for converting 16 //! Java objects into native rust objects and vice versa. 17 use jni::objects::{JClass, JObject, JValue}; 18 use jni::sys::{jbyteArray, jint}; 19 use jni::JNIEnv; 20 use num_traits::FromPrimitive; 21 use std::num::TryFromIntError; 22 23 use uwb_core::params::{ 24 AoaResultRequest, AppConfigParams, BprfPhrDataRate, CccAppConfigParamsBuilder, CccHoppingMode, 25 CccProtocolVersion, CccPulseShapeCombo, CccUwbChannel, CccUwbConfig, ChapsPerSlot, CountryCode, 26 DeviceRole, DeviceType, FiraAppConfigParamsBuilder, HoppingMode, KeyRotation, MacAddressMode, 27 MacFcsType, MultiNodeMode, PreambleDuration, PrfMode, PsduDataRate, PulseShape, 28 RangeDataNtfConfig, RangingRoundUsage, RframeConfig, StsConfig, StsLength, 29 TxAdaptivePayloadPower, UwbAddress, UwbChannel, 30 }; 31 use uwb_core::uci::{RangingMeasurements, SessionRangeData}; 32 use uwb_uci_packets::{ 33 Controlee, ExtendedAddressTwoWayRangingMeasurement, MacAddressIndicator, PowerStats, 34 ShortAddressTwoWayRangingMeasurement, StatusCode, 35 }; 36 37 use crate::context::JniContext; 38 use crate::error::{Error, Result}; 39 40 /// Wrapper struct for FiraOpenSessionsParams Java class 41 pub struct FiraOpenSessionParamsJni<'a> { 42 jni_context: JniContext<'a>, 43 } 44 45 impl<'a> FiraOpenSessionParamsJni<'a> { new(env: JNIEnv<'a>, params_obj: JObject<'a>) -> Self46 pub fn new(env: JNIEnv<'a>, params_obj: JObject<'a>) -> Self { 47 Self { jni_context: JniContext::new(env, params_obj) } 48 } 49 50 int_field!(device_type, DeviceType, "getDeviceType"); 51 int_field!(ranging_round_usage, RangingRoundUsage, "getRangingRoundUsage"); 52 int_field!(sts_config, StsConfig, "getStsConfig"); 53 int_field!(multi_node_mode, MultiNodeMode, "getMultiNodeMode"); 54 int_field!(channel_number, UwbChannel, "getChannelNumber"); 55 int_field!(mac_fcs_type, MacFcsType, "getFcsType"); 56 int_field!(aoa_result_request, AoaResultRequest, "getAoaResultRequest"); 57 int_field!(range_data_ntf_config, RangeDataNtfConfig, "getRangeDataNtfConfig"); 58 int_field!(device_role, DeviceRole, "getDeviceRole"); 59 int_field!(rframe_config, RframeConfig, "getRframeConfig"); 60 int_field!(psdu_data_rate, PsduDataRate, "getPsduDataRate"); 61 int_field!(preamble_duration, PreambleDuration, "getPreambleDuration"); 62 int_field!(prf_mode, PrfMode, "getPrfMode"); 63 int_field!(mac_address_mode, MacAddressMode, "getMacAddressMode"); 64 int_field!(hopping_mode, HoppingMode, "getHoppingMode"); 65 int_field!(bprf_phr_data_rate, BprfPhrDataRate, "getBprfPhrDataRate"); 66 int_field!(sts_length, StsLength, "getStsLength"); 67 int_field!(slot_duration_rstu, u16, "getSlotDurationRstu"); 68 int_field!(ranging_interval_ms, u32, "getRangingIntervalMs"); 69 int_field!(range_data_ntf_proximity_near_cm, u16, "getRangeDataNtfProximityNear"); 70 int_field!(range_data_ntf_proximity_far_cm, u16, "getRangeDataNtfProximityFar"); 71 int_field!(preamble_code_index, u8, "getPreambleCodeIndex"); 72 int_field!(sfd_id, u8, "getSfdId"); 73 int_field!(slots_per_rr, u8, "getSlotsPerRangingRound"); 74 int_field!(key_rotation_rate, u8, "getKeyRotationRate"); 75 int_field!(session_priority, u8, "getSessionPriority"); 76 int_field!(number_of_sts_segments, u8, "getStsSegmentCount"); 77 int_field!(max_rr_retry, u16, "getMaxRangingRoundRetries"); 78 int_field!(uwb_initiation_time_ms, u32, "getInitiationTimeMs"); 79 int_field!(block_stride_length, u8, "getBlockStrideLength"); 80 int_field!(in_band_termination_attempt_count, u8, "getInBandTerminationAttemptCount"); 81 int_field!(sub_session_id, u32, "getSubSessionId"); 82 int_field!(number_of_range_measurements, u8, "getNumOfMsrmtFocusOnRange"); 83 int_field!(number_of_aoa_azimuth_measurements, u8, "getNumOfMsrmtFocusOnAoaAzimuth"); 84 int_field!(number_of_aoa_elevation_measurements, u8, "getNumOfMsrmtFocusOnAoaElevation"); 85 bool_field!(key_rotation, KeyRotation, "isKeyRotationEnabled"); 86 bool_field!( 87 tx_adaptive_payload_power, 88 TxAdaptivePayloadPower, 89 "isTxAdaptivePayloadPowerEnabled" 90 ); 91 device_mac_address(&self) -> Result<UwbAddress>92 fn device_mac_address(&self) -> Result<UwbAddress> { 93 let address_obj = 94 self.jni_context.object_getter("getDeviceAddress", "()Landroid/uwb/UwbAddress;")?; 95 96 UwbAddressJni::new(self.jni_context.env, address_obj).try_into() 97 } 98 dest_mac_address(&self) -> Result<Vec<UwbAddress>>99 fn dest_mac_address(&self) -> Result<Vec<UwbAddress>> { 100 let jlist = self.jni_context.list_getter("getDestAddressList")?; 101 102 let mut dest_addresses = vec![]; 103 let size = jlist.size()? as u32; 104 for i in 0..size { 105 if let Some(obj) = jlist.get(i as jint)? { 106 dest_addresses.push(UwbAddressJni::new(self.jni_context.env, obj).try_into()?); 107 } 108 } 109 Ok(dest_addresses) 110 } 111 vendor_id(&self) -> Result<[u8; 2]>112 fn vendor_id(&self) -> Result<[u8; 2]> { 113 let vendor_id_bytes = self.jni_context.byte_arr_getter("getVendorId")?; 114 let len = vendor_id_bytes.len(); 115 116 vendor_id_bytes 117 .try_into() 118 .map_err(|_| Error::Parse(format!("Invalid vendor_id size, expected 2 got {}", len))) 119 } 120 static_sts_iv(&self) -> Result<[u8; 6]>121 fn static_sts_iv(&self) -> Result<[u8; 6]> { 122 let static_sts_iv_bytes = self.jni_context.byte_arr_getter("getStaticStsIV")?; 123 let len = static_sts_iv_bytes.len(); 124 125 static_sts_iv_bytes.try_into().map_err(|_| { 126 Error::Parse(format!("Invalid static_sts_iv size, expected 6 got {}", len)) 127 }) 128 } 129 } 130 131 impl TryFrom<FiraOpenSessionParamsJni<'_>> for AppConfigParams { 132 type Error = Error; 133 try_from(jni_obj: FiraOpenSessionParamsJni) -> Result<Self>134 fn try_from(jni_obj: FiraOpenSessionParamsJni) -> Result<Self> { 135 FiraAppConfigParamsBuilder::new() 136 .device_type(jni_obj.device_type()?) 137 .ranging_round_usage(jni_obj.ranging_round_usage()?) 138 .sts_config(jni_obj.sts_config()?) 139 .multi_node_mode(jni_obj.multi_node_mode()?) 140 .channel_number(jni_obj.channel_number()?) 141 .slot_duration_rstu(jni_obj.slot_duration_rstu()?) 142 .ranging_interval_ms(jni_obj.ranging_interval_ms()?) 143 .mac_fcs_type(jni_obj.mac_fcs_type()?) 144 .aoa_result_request(jni_obj.aoa_result_request()?) 145 .range_data_ntf_config(jni_obj.range_data_ntf_config()?) 146 .range_data_ntf_proximity_near_cm(jni_obj.range_data_ntf_proximity_near_cm()?) 147 .range_data_ntf_proximity_far_cm(jni_obj.range_data_ntf_proximity_far_cm()?) 148 .device_role(jni_obj.device_role()?) 149 .rframe_config(jni_obj.rframe_config()?) 150 .preamble_code_index(jni_obj.preamble_code_index()?) 151 .sfd_id(jni_obj.sfd_id()?) 152 .psdu_data_rate(jni_obj.psdu_data_rate()?) 153 .preamble_duration(jni_obj.preamble_duration()?) 154 .slots_per_rr(jni_obj.slots_per_rr()?) 155 .prf_mode(jni_obj.prf_mode()?) 156 .key_rotation_rate(jni_obj.key_rotation_rate()?) 157 .session_priority(jni_obj.session_priority()?) 158 .mac_address_mode(jni_obj.mac_address_mode()?) 159 .number_of_sts_segments(jni_obj.number_of_sts_segments()?) 160 .max_rr_retry(jni_obj.max_rr_retry()?) 161 .uwb_initiation_time_ms(jni_obj.uwb_initiation_time_ms()?) 162 .hopping_mode(jni_obj.hopping_mode()?) 163 .block_stride_length(jni_obj.block_stride_length()?) 164 .in_band_termination_attempt_count(jni_obj.in_band_termination_attempt_count()?) 165 .sub_session_id(jni_obj.sub_session_id()?) 166 .bprf_phr_data_rate(jni_obj.bprf_phr_data_rate()?) 167 .sts_length(jni_obj.sts_length()?) 168 .number_of_range_measurements(jni_obj.number_of_range_measurements()?) 169 .number_of_aoa_azimuth_measurements(jni_obj.number_of_aoa_azimuth_measurements()?) 170 .number_of_aoa_elevation_measurements(jni_obj.number_of_aoa_elevation_measurements()?) 171 .tx_adaptive_payload_power(jni_obj.tx_adaptive_payload_power()?) 172 .key_rotation(jni_obj.key_rotation()?) 173 .device_mac_address(jni_obj.device_mac_address()?) 174 .dst_mac_address(jni_obj.dest_mac_address()?) 175 .vendor_id(jni_obj.vendor_id()?) 176 .static_sts_iv(jni_obj.static_sts_iv()?) 177 .build() 178 .ok_or_else(|| Error::Parse(String::from("Bad parameters"))) 179 180 // TODO(b/244787320): implement the rest of the fields 181 // ------ 182 // * result_report_config -- struct (can't find corresponding java fields) 183 // * ranging_round_control -- struct (can't find corresponding java fields) 184 // ------ 185 // Following fields are defined in FiraOpenSessionParams in rust 186 // but don't exist as params on Java's side: 187 // * ranging_time_struct 188 // * responder_slot_index 189 // * scheduled_mode 190 // * max_number_of_measurements 191 } 192 } 193 194 /// Wrapper struct for UwbAddress Java class 195 struct UwbAddressJni<'a> { 196 jni_context: JniContext<'a>, 197 } 198 199 impl<'a> UwbAddressJni<'a> { new(env: JNIEnv<'a>, address_obj: JObject<'a>) -> Self200 fn new(env: JNIEnv<'a>, address_obj: JObject<'a>) -> Self { 201 Self { jni_context: JniContext::new(env, address_obj) } 202 } 203 bytes(&self) -> Result<Vec<u8>>204 fn bytes(&self) -> Result<Vec<u8>> { 205 self.jni_context.byte_arr_getter("toBytes").map_err(|e| e.into()) 206 } 207 } 208 209 impl TryFrom<UwbAddressJni<'_>> for UwbAddress { 210 type Error = Error; 211 try_from(addr_obj: UwbAddressJni<'_>) -> Result<Self>212 fn try_from(addr_obj: UwbAddressJni<'_>) -> Result<Self> { 213 addr_obj.bytes()?.try_into().map_err(|e: &str| Error::Parse(e.to_string())) 214 } 215 } 216 217 impl TryFrom<UwbAddressJni<'_>> for u16 { 218 type Error = Error; 219 try_from(addr_obj: UwbAddressJni<'_>) -> Result<Self>220 fn try_from(addr_obj: UwbAddressJni<'_>) -> Result<Self> { 221 let uwb_addr = UwbAddress::try_from(addr_obj)?; 222 match uwb_addr { 223 UwbAddress::Extended(_) => { 224 Err(Error::Parse(String::from("Can't cast to u16 from UwbAddress::Extended"))) 225 } 226 UwbAddress::Short(val) => Ok(u16::from_le_bytes(val)), 227 } 228 } 229 } 230 231 /// Wrapper struct for CccOpenRangingParams Java class 232 pub struct CccOpenRangingParamsJni<'a> { 233 jni_context: JniContext<'a>, 234 } 235 236 impl<'a> CccOpenRangingParamsJni<'a> { new(env: JNIEnv<'a>, params_obj: JObject<'a>) -> Self237 pub fn new(env: JNIEnv<'a>, params_obj: JObject<'a>) -> Self { 238 Self { jni_context: JniContext::new(env, params_obj) } 239 } 240 241 int_field!(uwb_config, CccUwbConfig, "getUwbConfig"); 242 int_field!(channel_number, CccUwbChannel, "getChannel"); 243 int_field!(chaps_per_slot, ChapsPerSlot, "getNumChapsPerSlot"); 244 int_field!(hopping_config_mode, u8, "getHoppingConfigMode"); 245 int_field!(hopping_sequence, u8, "getHoppingSequence"); 246 int_field!(ran_multiplier, u32, "getRanMultiplier"); 247 int_field!(num_responder_nodes, u8, "getNumResponderNodes"); 248 int_field!(slots_per_rr, u8, "getNumSlotsPerRound"); 249 int_field!(sync_code_index, u8, "getSyncCodeIndex"); 250 hopping_mode(&self) -> Result<CccHoppingMode>251 fn hopping_mode(&self) -> Result<CccHoppingMode> { 252 let config_mode = self.hopping_config_mode()?; 253 let sequence = self.hopping_sequence()?; 254 255 // TODO(cante): maybe move this to ccc_params 256 Ok(match (config_mode, sequence) { 257 (0, _) => CccHoppingMode::Disable, 258 (1, 0) => CccHoppingMode::ContinuousDefault, 259 (1, 1) => CccHoppingMode::ContinuousAes, 260 (2, 0) => CccHoppingMode::AdaptiveDefault, 261 (2, 1) => CccHoppingMode::AdaptiveAes, 262 _ => return Err(Error::Parse(String::from("Invalid hopping mode"))), 263 }) 264 } 265 pulse_shape_combo(&self) -> Result<CccPulseShapeCombo>266 fn pulse_shape_combo(&self) -> Result<CccPulseShapeCombo> { 267 let pulse_obj = self.jni_context.object_getter( 268 "getPulseShapeCombo", 269 "()Lcom/google/uwb/support/ccc/CccPulseShapeCombo;", 270 )?; 271 272 CccPulseShapeComboJni::new(self.jni_context.env, pulse_obj).try_into() 273 } 274 protocol_version(&self) -> Result<CccProtocolVersion>275 fn protocol_version(&self) -> Result<CccProtocolVersion> { 276 let protocol_version_obj = self.jni_context.object_getter( 277 "getProtocolVersion", 278 "()Lcom/google/uwb/support/ccc/CccProtocolVersion;", 279 )?; 280 281 CccProtocolVersionJni::new(self.jni_context.env, protocol_version_obj).try_into() 282 } 283 } 284 285 impl TryFrom<CccOpenRangingParamsJni<'_>> for AppConfigParams { 286 type Error = Error; 287 try_from(jni_obj: CccOpenRangingParamsJni<'_>) -> Result<Self>288 fn try_from(jni_obj: CccOpenRangingParamsJni<'_>) -> Result<Self> { 289 CccAppConfigParamsBuilder::new() 290 .channel_number(jni_obj.channel_number()?) 291 .chaps_per_slot(jni_obj.chaps_per_slot()?) 292 .hopping_mode(jni_obj.hopping_mode()?) 293 .num_responder_nodes(jni_obj.num_responder_nodes()?) 294 .protocol_version(jni_obj.protocol_version()?) 295 .pulse_shape_combo(jni_obj.pulse_shape_combo()?) 296 .ran_multiplier(jni_obj.ran_multiplier()?) 297 .slots_per_rr(jni_obj.slots_per_rr()?) 298 .sync_code_index(jni_obj.sync_code_index()?) 299 .uwb_config(jni_obj.uwb_config()?) 300 .build() 301 .ok_or_else(|| Error::Parse(String::from("Bad parameters"))) 302 } 303 } 304 305 /// Wrapper struct for CccPuleShapeCombo Java class 306 struct CccPulseShapeComboJni<'a> { 307 jni_context: JniContext<'a>, 308 } 309 310 impl<'a> CccPulseShapeComboJni<'a> { new(env: JNIEnv<'a>, pulse_obj: JObject<'a>) -> Self311 fn new(env: JNIEnv<'a>, pulse_obj: JObject<'a>) -> Self { 312 Self { jni_context: JniContext::new(env, pulse_obj) } 313 } 314 315 int_field!(initiator_tx, PulseShape, "getInitiatorTx"); 316 int_field!(responder_tx, PulseShape, "getResponderTx"); 317 } 318 319 impl TryFrom<CccPulseShapeComboJni<'_>> for CccPulseShapeCombo { 320 type Error = Error; 321 try_from(jni_obj: CccPulseShapeComboJni<'_>) -> Result<Self>322 fn try_from(jni_obj: CccPulseShapeComboJni<'_>) -> Result<Self> { 323 let initiator_tx = jni_obj.initiator_tx()?; 324 let responder_tx = jni_obj.responder_tx()?; 325 326 Ok(CccPulseShapeCombo { initiator_tx, responder_tx }) 327 } 328 } 329 330 /// Wrapper struct for CccProtocolVersion Java class 331 struct CccProtocolVersionJni<'a> { 332 jni_context: JniContext<'a>, 333 } 334 335 impl<'a> CccProtocolVersionJni<'a> { new(env: JNIEnv<'a>, protocol_obj: JObject<'a>) -> Self336 fn new(env: JNIEnv<'a>, protocol_obj: JObject<'a>) -> Self { 337 Self { jni_context: JniContext::new(env, protocol_obj) } 338 } 339 340 int_field!(major, u8, "getMajor"); 341 int_field!(minor, u8, "getMinor"); 342 } 343 344 impl TryFrom<CccProtocolVersionJni<'_>> for CccProtocolVersion { 345 type Error = Error; 346 try_from(jni_obj: CccProtocolVersionJni<'_>) -> Result<Self>347 fn try_from(jni_obj: CccProtocolVersionJni<'_>) -> Result<Self> { 348 let major = jni_obj.major()?; 349 let minor = jni_obj.minor()?; 350 351 Ok(CccProtocolVersion { major, minor }) 352 } 353 } 354 355 /// Wrapper struct for FiraControleeParams. 356 /// Internally FiraControleeParams is an array of UwbAddresses and an array of subSessionIds, 357 /// The `Controlee` struct from uwb_uci_packets represents a single pair of UwbAddress and 358 /// subSessionId, hence this wrapper returns a Vec<Controlee> from the as_vec method. 359 360 pub struct FiraControleeParamsJni<'a> { 361 jni_context: JniContext<'a>, 362 } 363 364 impl<'a> FiraControleeParamsJni<'a> { new(env: JNIEnv<'a>, controlee_obj: JObject<'a>) -> Self365 pub fn new(env: JNIEnv<'a>, controlee_obj: JObject<'a>) -> Self { 366 Self { jni_context: JniContext::new(env, controlee_obj) } 367 } 368 as_vec(&self) -> Result<Vec<Controlee>>369 pub fn as_vec(&self) -> Result<Vec<Controlee>> { 370 let env = self.jni_context.env; 371 let addr_arr = 372 self.jni_context.object_getter("getAddressList", "[android/uwb/UwbAddress;")?; 373 let addr_len = env.get_array_length(addr_arr.into_raw())?; 374 375 let subs_arr = self.jni_context.object_getter("getSubSessionIdList", "[I")?; 376 let subs_len = env.get_array_length(subs_arr.into_raw())?; 377 378 if addr_len != subs_len { 379 return Err(Error::Parse(format!( 380 "Mismatched array sizes, addressList size: {}, subSessionIdList size: {}", 381 addr_len, subs_len 382 ))); 383 } 384 385 let mut controlees = vec![]; 386 387 let size: usize = addr_len.try_into().unwrap(); 388 let mut subs_arr_vec = vec![0i32; size]; 389 env.get_int_array_region(subs_arr.into_raw(), 0, &mut subs_arr_vec)?; 390 391 for (i, sub_session) in subs_arr_vec.iter().enumerate() { 392 let uwb_address_obj = env.get_object_array_element(addr_arr.into_raw(), i as i32)?; 393 let uwb_address: u16 = UwbAddressJni::new(env, uwb_address_obj).try_into()?; 394 controlees 395 .push(Controlee { short_address: uwb_address, subsession_id: *sub_session as u32 }); 396 } 397 398 Ok(controlees) 399 } 400 } 401 402 /// Wrapper struct for CountryCode 403 pub struct CountryCodeJni<'a> { 404 env: JNIEnv<'a>, 405 country_code_arr: jbyteArray, 406 } 407 408 impl<'a> CountryCodeJni<'a> { new(env: JNIEnv<'a>, country_code_arr: jbyteArray) -> Self409 pub fn new(env: JNIEnv<'a>, country_code_arr: jbyteArray) -> Self { 410 Self { env, country_code_arr } 411 } 412 } 413 414 impl TryFrom<CountryCodeJni<'_>> for CountryCode { 415 type Error = Error; 416 try_from(jni: CountryCodeJni<'_>) -> Result<Self>417 fn try_from(jni: CountryCodeJni<'_>) -> Result<Self> { 418 let country_code_vec = jni.env.convert_byte_array(jni.country_code_arr)?; 419 if country_code_vec.len() != 2 { 420 return Err(Error::Parse(format!( 421 "Country code invalid length. Received {} bytes.", 422 country_code_vec.len() 423 ))); 424 } 425 426 let country_code = [country_code_vec[0], country_code_vec[1]]; 427 match CountryCode::new(&country_code) { 428 Some(val) => Ok(val), 429 _ => Err(Error::Parse(format!( 430 "Couldn't parse country code. Received {:?}", 431 country_code_vec 432 ))), 433 } 434 } 435 } 436 437 pub struct PowerStatsWithEnv<'a> { 438 env: JNIEnv<'a>, 439 power_stats: PowerStats, 440 } 441 442 impl<'a> PowerStatsWithEnv<'a> { new(env: JNIEnv<'a>, power_stats: PowerStats) -> Self443 pub fn new(env: JNIEnv<'a>, power_stats: PowerStats) -> Self { 444 Self { env, power_stats } 445 } 446 } 447 448 pub struct PowerStatsJni<'a> { 449 pub jni_context: JniContext<'a>, 450 } 451 452 impl<'a> TryFrom<PowerStatsWithEnv<'a>> for PowerStatsJni<'a> { 453 type Error = Error; 454 try_from(pse: PowerStatsWithEnv<'a>) -> Result<Self>455 fn try_from(pse: PowerStatsWithEnv<'a>) -> Result<Self> { 456 let cls = pse.env.find_class("com/android/server/uwb/info/UwbPowerStats")?; 457 let vals = vec![ 458 pse.power_stats.tx_time_ms, 459 pse.power_stats.rx_time_ms, 460 pse.power_stats.idle_time_ms, 461 pse.power_stats.total_wake_count, 462 ] 463 .into_iter() 464 .map(|val| Ok(JValue::Int(i32::try_from(val)?))) 465 .collect::<std::result::Result<Vec<JValue>, TryFromIntError>>() 466 .map_err(|_| Error::Parse(String::from("Power Stats parse error")))?; 467 468 let new_obj = pse.env.new_object(cls, "(IIII)V", vals.as_slice())?; 469 470 Ok(Self { jni_context: JniContext { env: pse.env, obj: new_obj } }) 471 } 472 } 473 474 pub struct SessionRangeDataWithEnv<'a> { 475 env: JNIEnv<'a>, 476 uwb_ranging_data_jclass: JClass<'a>, 477 uwb_two_way_measurement_jclass: JClass<'a>, 478 session_range_data: SessionRangeData, 479 } 480 481 impl<'a> SessionRangeDataWithEnv<'a> { new( env: JNIEnv<'a>, uwb_ranging_data_jclass: JClass<'a>, uwb_two_way_measurement_jclass: JClass<'a>, session_range_data: SessionRangeData, ) -> Self482 pub fn new( 483 env: JNIEnv<'a>, 484 uwb_ranging_data_jclass: JClass<'a>, 485 uwb_two_way_measurement_jclass: JClass<'a>, 486 session_range_data: SessionRangeData, 487 ) -> Self { 488 Self { env, uwb_ranging_data_jclass, uwb_two_way_measurement_jclass, session_range_data } 489 } 490 } 491 pub struct UwbRangingDataJni<'a> { 492 pub jni_context: JniContext<'a>, 493 } 494 495 impl<'a> TryFrom<SessionRangeDataWithEnv<'a>> for UwbRangingDataJni<'a> { 496 type Error = Error; try_from(data_obj: SessionRangeDataWithEnv<'a>) -> Result<Self>497 fn try_from(data_obj: SessionRangeDataWithEnv<'a>) -> Result<Self> { 498 let (mac_address_indicator, measurements_size) = 499 match data_obj.session_range_data.ranging_measurements { 500 RangingMeasurements::ShortAddressTwoWay(ref m) => { 501 (MacAddressIndicator::ShortAddress, m.len()) 502 } 503 RangingMeasurements::ExtendedAddressTwoWay(ref m) => { 504 (MacAddressIndicator::ExtendedAddress, m.len()) 505 } 506 RangingMeasurements::ShortAddressDltdoa(ref m) => { 507 (MacAddressIndicator::ShortAddress, m.len()) 508 } 509 RangingMeasurements::ExtendedAddressDltdoa(ref m) => { 510 (MacAddressIndicator::ExtendedAddress, m.len()) 511 } 512 RangingMeasurements::ShortAddressOwrAoa(ref m) => { 513 (MacAddressIndicator::ShortAddress, 1) 514 } 515 RangingMeasurements::ExtendedAddressOwrAoa(ref m) => { 516 (MacAddressIndicator::ExtendedAddress, 1) 517 } 518 }; 519 let measurements_jni = UwbTwoWayMeasurementJni::try_from(RangingMeasurementsWithEnv::new( 520 data_obj.env, 521 data_obj.uwb_two_way_measurement_jclass, 522 data_obj.session_range_data.ranging_measurements, 523 ))?; 524 let raw_notification_jbytearray = 525 data_obj.env.byte_array_from_slice(&data_obj.session_range_data.raw_ranging_data)?; 526 // TODO(b/270443790): Check on using OwrAoa measurement class here. 527 528 // Safety: raw_notification_jbytearray safely instantiated above. 529 let raw_notification_jobject = unsafe { JObject::from_raw(raw_notification_jbytearray) }; 530 let ranging_data_jni = data_obj.env.new_object( 531 data_obj.uwb_ranging_data_jclass, 532 "(JJIJIII[Lcom/android/server/uwb/data/UwbTwoWayMeasurement;[B)V", 533 &[ 534 JValue::Long(data_obj.session_range_data.sequence_number as i64), 535 JValue::Long(data_obj.session_range_data.session_token as i64), 536 JValue::Int(data_obj.session_range_data.rcr_indicator as i32), 537 JValue::Long(data_obj.session_range_data.current_ranging_interval_ms as i64), 538 JValue::Int(data_obj.session_range_data.ranging_measurement_type as i32), 539 JValue::Int(mac_address_indicator as i32), 540 JValue::Int(measurements_size as i32), 541 JValue::Object(measurements_jni.jni_context.obj), 542 JValue::Object(raw_notification_jobject), 543 ], 544 )?; 545 546 Ok(UwbRangingDataJni { jni_context: JniContext::new(data_obj.env, ranging_data_jni) }) 547 } 548 } 549 550 // Byte size of mac address length: 551 const SHORT_MAC_ADDRESS_LEN: i32 = 2; 552 const EXTENDED_MAC_ADDRESS_LEN: i32 = 8; 553 554 enum MacAddress { 555 Short(u16), 556 Extended(u64), 557 } 558 impl MacAddress { into_ne_bytes_i8(self) -> Vec<i8>559 fn into_ne_bytes_i8(self) -> Vec<i8> { 560 match self { 561 MacAddress::Short(val) => val.to_ne_bytes().into_iter().map(|b| b as i8).collect(), 562 MacAddress::Extended(val) => val.to_ne_bytes().into_iter().map(|b| b as i8).collect(), 563 } 564 } 565 } 566 struct TwoWayRangingMeasurement { 567 mac_address: MacAddress, 568 status: StatusCode, 569 nlos: u8, 570 distance: u16, 571 aoa_azimuth: u16, 572 aoa_azimuth_fom: u8, 573 aoa_elevation: u16, 574 aoa_elevation_fom: u8, 575 aoa_destination_azimuth: u16, 576 aoa_destination_azimuth_fom: u8, 577 aoa_destination_elevation: u16, 578 aoa_destination_elevation_fom: u8, 579 slot_index: u8, 580 rssi: u8, 581 } 582 583 impl From<ShortAddressTwoWayRangingMeasurement> for TwoWayRangingMeasurement { from(measurement: ShortAddressTwoWayRangingMeasurement) -> Self584 fn from(measurement: ShortAddressTwoWayRangingMeasurement) -> Self { 585 TwoWayRangingMeasurement { 586 mac_address: MacAddress::Short(measurement.mac_address), 587 status: (measurement.status), 588 nlos: (measurement.nlos), 589 distance: (measurement.distance), 590 aoa_azimuth: (measurement.aoa_azimuth), 591 aoa_azimuth_fom: (measurement.aoa_azimuth_fom), 592 aoa_elevation: (measurement.aoa_elevation), 593 aoa_elevation_fom: (measurement.aoa_elevation_fom), 594 aoa_destination_azimuth: (measurement.aoa_destination_azimuth), 595 aoa_destination_azimuth_fom: (measurement.aoa_destination_azimuth_fom), 596 aoa_destination_elevation: (measurement.aoa_destination_elevation), 597 aoa_destination_elevation_fom: (measurement.aoa_destination_elevation_fom), 598 slot_index: (measurement.slot_index), 599 rssi: (measurement.rssi), 600 } 601 } 602 } 603 604 impl From<ExtendedAddressTwoWayRangingMeasurement> for TwoWayRangingMeasurement { from(measurement: ExtendedAddressTwoWayRangingMeasurement) -> Self605 fn from(measurement: ExtendedAddressTwoWayRangingMeasurement) -> Self { 606 TwoWayRangingMeasurement { 607 mac_address: MacAddress::Extended(measurement.mac_address), 608 status: (measurement.status), 609 nlos: (measurement.nlos), 610 distance: (measurement.distance), 611 aoa_azimuth: (measurement.aoa_azimuth), 612 aoa_azimuth_fom: (measurement.aoa_azimuth_fom), 613 aoa_elevation: (measurement.aoa_elevation), 614 aoa_elevation_fom: (measurement.aoa_elevation_fom), 615 aoa_destination_azimuth: (measurement.aoa_destination_azimuth), 616 aoa_destination_azimuth_fom: (measurement.aoa_destination_azimuth_fom), 617 aoa_destination_elevation: (measurement.aoa_destination_elevation), 618 aoa_destination_elevation_fom: (measurement.aoa_destination_elevation_fom), 619 slot_index: (measurement.slot_index), 620 rssi: (measurement.rssi), 621 } 622 } 623 } 624 625 pub struct RangingMeasurementsWithEnv<'a> { 626 env: JNIEnv<'a>, 627 uwb_two_way_measurement_jclass: JClass<'a>, 628 ranging_measurements: RangingMeasurements, 629 } 630 impl<'a> RangingMeasurementsWithEnv<'a> { new( env: JNIEnv<'a>, uwb_two_way_measurement_jclass: JClass<'a>, ranging_measurements: RangingMeasurements, ) -> Self631 pub fn new( 632 env: JNIEnv<'a>, 633 uwb_two_way_measurement_jclass: JClass<'a>, 634 ranging_measurements: RangingMeasurements, 635 ) -> Self { 636 Self { env, uwb_two_way_measurement_jclass, ranging_measurements } 637 } 638 } 639 pub struct UwbTwoWayMeasurementJni<'a> { 640 pub jni_context: JniContext<'a>, 641 } 642 643 impl<'a> TryFrom<RangingMeasurementsWithEnv<'a>> for UwbTwoWayMeasurementJni<'a> { 644 type Error = Error; try_from(measurements_obj: RangingMeasurementsWithEnv<'a>) -> Result<Self>645 fn try_from(measurements_obj: RangingMeasurementsWithEnv<'a>) -> Result<Self> { 646 let (measurements_vec, byte_arr_size) = match measurements_obj.ranging_measurements { 647 RangingMeasurements::ShortAddressTwoWay(m) => ( 648 m.into_iter().map(TwoWayRangingMeasurement::from).collect::<Vec<_>>(), 649 SHORT_MAC_ADDRESS_LEN, 650 ), 651 RangingMeasurements::ExtendedAddressTwoWay(m) => ( 652 m.into_iter().map(TwoWayRangingMeasurement::from).collect::<Vec<_>>(), 653 EXTENDED_MAC_ADDRESS_LEN, 654 ), 655 // TODO(b/260495115): Re-work needed to handle DlTDoAShort and DlTDoAExtended. 656 // TODO(b/270443790): Handle OwrAoa (Short and Extended). 657 _ => todo!(), 658 }; 659 let address_jbytearray = measurements_obj.env.new_byte_array(byte_arr_size)?; 660 661 // Safety: address_jbytearray safely instantiated above. 662 let address_jobject = unsafe { JObject::from_raw(address_jbytearray) }; 663 let zero_initiated_measurement_jobject = measurements_obj.env.new_object( 664 measurements_obj.uwb_two_way_measurement_jclass, 665 "([BIIIIIIIIIIIII)V", 666 &[ 667 JValue::Object(address_jobject), 668 JValue::Int(0), 669 JValue::Int(0), 670 JValue::Int(0), 671 JValue::Int(0), 672 JValue::Int(0), 673 JValue::Int(0), 674 JValue::Int(0), 675 JValue::Int(0), 676 JValue::Int(0), 677 JValue::Int(0), 678 JValue::Int(0), 679 JValue::Int(0), 680 JValue::Int(0), 681 ], 682 )?; 683 let measurements_array_jobject = measurements_obj.env.new_object_array( 684 measurements_vec.len() as i32, 685 measurements_obj.uwb_two_way_measurement_jclass, 686 zero_initiated_measurement_jobject, 687 )?; 688 for (i, measurement) in measurements_vec.into_iter().enumerate() { 689 let mac_address_bytes = measurement.mac_address.into_ne_bytes_i8(); 690 let mac_address_bytes_jbytearray = 691 measurements_obj.env.new_byte_array(byte_arr_size)?; 692 measurements_obj.env.set_byte_array_region( 693 mac_address_bytes_jbytearray, 694 0, 695 mac_address_bytes.as_slice(), 696 )?; 697 698 // Safety: mac_address_bytes_jbytearray safely instantiated above. 699 let mac_address_bytes_jobject = 700 unsafe { JObject::from_raw(mac_address_bytes_jbytearray) }; 701 702 let measurement_jobject = measurements_obj.env.new_object( 703 measurements_obj.uwb_two_way_measurement_jclass, 704 "([BIIIIIIIIIIIII)V", 705 &[ 706 JValue::Object(mac_address_bytes_jobject), 707 JValue::Int(i32::from(measurement.status)), 708 JValue::Int(measurement.nlos as i32), 709 JValue::Int(measurement.distance as i32), 710 JValue::Int(measurement.aoa_azimuth as i32), 711 JValue::Int(measurement.aoa_azimuth_fom as i32), 712 JValue::Int(measurement.aoa_elevation as i32), 713 JValue::Int(measurement.aoa_elevation_fom as i32), 714 JValue::Int(measurement.aoa_destination_azimuth as i32), 715 JValue::Int(measurement.aoa_destination_azimuth_fom as i32), 716 JValue::Int(measurement.aoa_destination_elevation as i32), 717 JValue::Int(measurement.aoa_destination_elevation_fom as i32), 718 JValue::Int(measurement.slot_index as i32), 719 JValue::Int(measurement.rssi as i32), 720 ], 721 )?; 722 measurements_obj.env.set_object_array_element( 723 measurements_array_jobject, 724 i as i32, 725 measurement_jobject, 726 )?; 727 } 728 729 // Safety: measurements_array_jobject safely instantiated above. 730 let measurements_jobject = unsafe { JObject::from_raw(measurements_array_jobject) }; 731 Ok(UwbTwoWayMeasurementJni { 732 jni_context: JniContext::new(measurements_obj.env, measurements_jobject), 733 }) 734 } 735 } 736 737 /// Boilerplate code macro for defining int getters 738 macro_rules! int_field { 739 ($field: ident, $ret: ty, $method: expr) => { 740 fn $field(&self) -> Result<$ret> { 741 let val = self.jni_context.int_getter($method)?; 742 <$ret>::from_i32(val).ok_or_else(|| { 743 Error::Parse(format!("{} parse error. Received {}", stringify!($field), val)) 744 }) 745 } 746 }; 747 } 748 749 /// Boilerplate code macro for defining bool getters 750 macro_rules! bool_field { 751 ($field: ident, $ret: ty, $method: expr) => { 752 fn $field(&self) -> Result<$ret> { 753 let val = self.jni_context.bool_getter($method)?; 754 <$ret>::from_u8(val as u8).ok_or_else(|| { 755 Error::Parse(format!("{} Parse error. Received {}", stringify!($field), val)) 756 }) 757 } 758 }; 759 } 760 761 pub(crate) use bool_field; 762 pub(crate) use int_field; 763