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