• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2022, The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 //! Implementation of NotificationManagerAndroid and its builder.
16 
17 use crate::jclass_name::{
18     MULTICAST_LIST_UPDATE_STATUS_CLASS, RFTEST_PERIODIC_TX_CLASS, RFTEST_PER_RX_CLASS,
19     UWB_DL_TDOA_MEASUREMENT_CLASS, UWB_OWR_AOA_MEASUREMENT_CLASS, UWB_RADAR_DATA_CLASS,
20     UWB_RADAR_SWEEP_DATA_CLASS, UWB_RANGING_DATA_CLASS, UWB_TWO_WAY_MEASUREMENT_CLASS,
21 };
22 
23 use std::collections::HashMap;
24 use std::sync::Arc;
25 
26 use jni::errors::Error as JNIError;
27 use jni::objects::{GlobalRef, JClass, JMethodID, JObject, JValue};
28 use jni::signature::TypeSignature;
29 use jni::sys::jvalue;
30 use jni::{AttachGuard, JavaVM};
31 use log::{debug, error};
32 use uwb_core::error::{Error as UwbError, Result as UwbResult};
33 use uwb_core::params::{ControleeStatusList, UwbAddress};
34 use uwb_core::uci::uci_manager_sync::{NotificationManager, NotificationManagerBuilder};
35 use uwb_core::uci::{
36     CoreNotification, DataRcvNotification, RadarDataRcvNotification, RangingMeasurements,
37     RfTestNotification, RfTestPerRxData, SessionNotification, SessionRangeData,
38 };
39 use uwb_uci_packets::{
40     radar_bytes_per_sample_value, ExtendedAddressDlTdoaRangingMeasurement,
41     ExtendedAddressOwrAoaRangingMeasurement, ExtendedAddressTwoWayRangingMeasurement,
42     MacAddressIndicator, RangingMeasurementType, SessionState,
43     ShortAddressDlTdoaRangingMeasurement, ShortAddressOwrAoaRangingMeasurement,
44     ShortAddressTwoWayRangingMeasurement, StatusCode,
45 };
46 
47 // Byte size of mac address length:
48 const SHORT_MAC_ADDRESS_LEN: i32 = 2;
49 const EXTENDED_MAC_ADDRESS_LEN: i32 = 8;
50 const MAX_ANCHOR_LOCATION_LEN: i32 = 12;
51 const MAX_RANGING_ROUNDS_LEN: i32 = 16;
52 const MAX_RADAR_VENDOR_DATA_LEN: i32 = 256;
53 
54 // Maximum allowed number of Java Object to be allocated inside with_local_frame
55 const MAX_JAVA_OBJECTS_CAPACITY: i32 = 50;
56 
57 #[derive(Debug, PartialEq)]
58 enum MacAddress {
59     Short(u16),
60     Extended(u64),
61 }
62 impl MacAddress {
into_ne_bytes(self) -> Vec<u8>63     fn into_ne_bytes(self) -> Vec<u8> {
64         match self {
65             MacAddress::Short(val) => val.to_ne_bytes().into(),
66             MacAddress::Extended(val) => val.to_ne_bytes().into(),
67         }
68     }
69 }
70 
71 struct TwoWayRangingMeasurement {
72     mac_address: MacAddress,
73     status: StatusCode,
74     nlos: u8,
75     distance: u16,
76     aoa_azimuth: u16,
77     aoa_azimuth_fom: u8,
78     aoa_elevation: u16,
79     aoa_elevation_fom: u8,
80     aoa_destination_azimuth: u16,
81     aoa_destination_azimuth_fom: u8,
82     aoa_destination_elevation: u16,
83     aoa_destination_elevation_fom: u8,
84     slot_index: u8,
85     rssi: u8,
86 }
87 
88 struct OwrAoaRangingMeasurement {
89     mac_address: MacAddress,
90     status: StatusCode,
91     nlos: u8,
92     frame_sequence_number: u8,
93     block_index: u16,
94     aoa_azimuth: u16,
95     aoa_azimuth_fom: u8,
96     aoa_elevation: u16,
97     aoa_elevation_fom: u8,
98 }
99 
100 impl From<ShortAddressTwoWayRangingMeasurement> for TwoWayRangingMeasurement {
from(measurement: ShortAddressTwoWayRangingMeasurement) -> Self101     fn from(measurement: ShortAddressTwoWayRangingMeasurement) -> Self {
102         TwoWayRangingMeasurement {
103             mac_address: MacAddress::Short(measurement.mac_address),
104             status: (measurement.status),
105             nlos: (measurement.nlos),
106             distance: (measurement.distance),
107             aoa_azimuth: (measurement.aoa_azimuth),
108             aoa_azimuth_fom: (measurement.aoa_azimuth_fom),
109             aoa_elevation: (measurement.aoa_elevation),
110             aoa_elevation_fom: (measurement.aoa_elevation_fom),
111             aoa_destination_azimuth: (measurement.aoa_destination_azimuth),
112             aoa_destination_azimuth_fom: (measurement.aoa_destination_azimuth_fom),
113             aoa_destination_elevation: (measurement.aoa_destination_elevation),
114             aoa_destination_elevation_fom: (measurement.aoa_destination_elevation_fom),
115             slot_index: (measurement.slot_index),
116             rssi: (measurement.rssi),
117         }
118     }
119 }
120 
121 impl From<ExtendedAddressTwoWayRangingMeasurement> for TwoWayRangingMeasurement {
from(measurement: ExtendedAddressTwoWayRangingMeasurement) -> Self122     fn from(measurement: ExtendedAddressTwoWayRangingMeasurement) -> Self {
123         TwoWayRangingMeasurement {
124             mac_address: MacAddress::Extended(measurement.mac_address),
125             status: (measurement.status),
126             nlos: (measurement.nlos),
127             distance: (measurement.distance),
128             aoa_azimuth: (measurement.aoa_azimuth),
129             aoa_azimuth_fom: (measurement.aoa_azimuth_fom),
130             aoa_elevation: (measurement.aoa_elevation),
131             aoa_elevation_fom: (measurement.aoa_elevation_fom),
132             aoa_destination_azimuth: (measurement.aoa_destination_azimuth),
133             aoa_destination_azimuth_fom: (measurement.aoa_destination_azimuth_fom),
134             aoa_destination_elevation: (measurement.aoa_destination_elevation),
135             aoa_destination_elevation_fom: (measurement.aoa_destination_elevation_fom),
136             slot_index: (measurement.slot_index),
137             rssi: (measurement.rssi),
138         }
139     }
140 }
141 
142 impl From<ShortAddressOwrAoaRangingMeasurement> for OwrAoaRangingMeasurement {
from(measurement: ShortAddressOwrAoaRangingMeasurement) -> Self143     fn from(measurement: ShortAddressOwrAoaRangingMeasurement) -> Self {
144         OwrAoaRangingMeasurement {
145             mac_address: MacAddress::Short(measurement.mac_address),
146             status: (measurement.status),
147             nlos: (measurement.nlos),
148             frame_sequence_number: (measurement.frame_sequence_number),
149             block_index: (measurement.block_index),
150             aoa_azimuth: (measurement.aoa_azimuth),
151             aoa_azimuth_fom: (measurement.aoa_azimuth_fom),
152             aoa_elevation: (measurement.aoa_elevation),
153             aoa_elevation_fom: (measurement.aoa_elevation_fom),
154         }
155     }
156 }
157 
158 impl From<ExtendedAddressOwrAoaRangingMeasurement> for OwrAoaRangingMeasurement {
from(measurement: ExtendedAddressOwrAoaRangingMeasurement) -> Self159     fn from(measurement: ExtendedAddressOwrAoaRangingMeasurement) -> Self {
160         OwrAoaRangingMeasurement {
161             mac_address: MacAddress::Extended(measurement.mac_address),
162             status: (measurement.status),
163             nlos: (measurement.nlos),
164             frame_sequence_number: (measurement.frame_sequence_number),
165             block_index: (measurement.block_index),
166             aoa_azimuth: (measurement.aoa_azimuth),
167             aoa_azimuth_fom: (measurement.aoa_azimuth_fom),
168             aoa_elevation: (measurement.aoa_elevation),
169             aoa_elevation_fom: (measurement.aoa_elevation_fom),
170         }
171     }
172 }
173 
174 struct DlTdoaRangingMeasurement {
175     mac_address: MacAddress,
176     pub status: u8,
177     pub message_type: u8,
178     pub message_control: u16,
179     pub block_index: u16,
180     pub round_index: u8,
181     pub nlos: u8,
182     pub aoa_azimuth: u16,
183     pub aoa_azimuth_fom: u8,
184     pub aoa_elevation: u16,
185     pub aoa_elevation_fom: u8,
186     pub rssi: u8,
187     pub tx_timestamp: u64,
188     pub rx_timestamp: u64,
189     pub anchor_cfo: u16,
190     pub cfo: u16,
191     pub initiator_reply_time: u32,
192     pub responder_reply_time: u32,
193     pub initiator_responder_tof: u16,
194     pub dt_anchor_location: Vec<u8>,
195     pub ranging_rounds: Vec<u8>,
196 }
197 
198 impl From<ExtendedAddressDlTdoaRangingMeasurement> for DlTdoaRangingMeasurement {
from(measurement: ExtendedAddressDlTdoaRangingMeasurement) -> Self199     fn from(measurement: ExtendedAddressDlTdoaRangingMeasurement) -> Self {
200         DlTdoaRangingMeasurement {
201             mac_address: MacAddress::Extended(measurement.mac_address),
202             status: (measurement.measurement.status),
203             message_type: (measurement.measurement.message_type),
204             message_control: (measurement.measurement.message_control),
205             block_index: (measurement.measurement.block_index),
206             round_index: (measurement.measurement.round_index),
207             nlos: (measurement.measurement.nlos),
208             aoa_azimuth: (measurement.measurement.aoa_azimuth),
209             aoa_azimuth_fom: (measurement.measurement.aoa_azimuth_fom),
210             aoa_elevation: (measurement.measurement.aoa_elevation),
211             aoa_elevation_fom: (measurement.measurement.aoa_elevation_fom),
212             rssi: (measurement.measurement.rssi),
213             tx_timestamp: (measurement.measurement.tx_timestamp),
214             rx_timestamp: (measurement.measurement.rx_timestamp),
215             anchor_cfo: (measurement.measurement.anchor_cfo),
216             cfo: (measurement.measurement.cfo),
217             initiator_reply_time: (measurement.measurement.initiator_reply_time),
218             responder_reply_time: (measurement.measurement.responder_reply_time),
219             initiator_responder_tof: (measurement.measurement.initiator_responder_tof),
220             dt_anchor_location: (measurement.measurement.dt_anchor_location),
221             ranging_rounds: (measurement.measurement.ranging_rounds),
222         }
223     }
224 }
225 
226 impl From<ShortAddressDlTdoaRangingMeasurement> for DlTdoaRangingMeasurement {
from(measurement: ShortAddressDlTdoaRangingMeasurement) -> Self227     fn from(measurement: ShortAddressDlTdoaRangingMeasurement) -> Self {
228         DlTdoaRangingMeasurement {
229             mac_address: MacAddress::Short(measurement.mac_address),
230             status: (measurement.measurement.status),
231             message_type: (measurement.measurement.message_type),
232             message_control: (measurement.measurement.message_control),
233             block_index: (measurement.measurement.block_index),
234             round_index: (measurement.measurement.round_index),
235             nlos: (measurement.measurement.nlos),
236             aoa_azimuth: (measurement.measurement.aoa_azimuth),
237             aoa_azimuth_fom: (measurement.measurement.aoa_azimuth_fom),
238             aoa_elevation: (measurement.measurement.aoa_elevation),
239             aoa_elevation_fom: (measurement.measurement.aoa_elevation_fom),
240             rssi: (measurement.measurement.rssi),
241             tx_timestamp: (measurement.measurement.tx_timestamp),
242             rx_timestamp: (measurement.measurement.rx_timestamp),
243             anchor_cfo: (measurement.measurement.anchor_cfo),
244             cfo: (measurement.measurement.cfo),
245             initiator_reply_time: (measurement.measurement.initiator_reply_time),
246             responder_reply_time: (measurement.measurement.responder_reply_time),
247             initiator_responder_tof: (measurement.measurement.initiator_responder_tof),
248             dt_anchor_location: (measurement.measurement.dt_anchor_location),
249             ranging_rounds: (measurement.measurement.ranging_rounds),
250         }
251     }
252 }
253 
254 pub(crate) struct NotificationManagerAndroid {
255     pub chip_id: String,
256     // 'static annotation is needed as env is 'sent' by tokio::task::spawn_local.
257     pub env: AttachGuard<'static>,
258     /// Global reference to the class loader object (java/lang/ClassLoader) from the java thread
259     /// that local java UCI classes can be loaded.
260     /// See http://yangyingchao.github.io/android/2015/01/13/Android-JNI-FindClass-Error.html
261     pub class_loader_obj: GlobalRef,
262     /// Global reference to the java class holding the various UCI notification callback functions.
263     pub callback_obj: GlobalRef,
264     // *_jmethod_id are cached for faster callback using call_method_unchecked
265     pub jmethod_id_map: HashMap<String, JMethodID>,
266     // jclass are cached for faster callback
267     pub jclass_map: HashMap<String, GlobalRef>,
268 }
269 
270 // TODO(b/246678053): Need to add callbacks for Data Packet Rx, and Data Packet Tx events (like
271 // DATA_CREDIT_NTF, DATA_STATUS_NTF).
272 impl NotificationManagerAndroid {
273     /// Finds JClass stored in jclass map. Should be a member function, but disjoint field borrow
274     /// checker fails and mutability of individual fields has to be annotated.
find_local_class<'a>( jclass_map: &'a mut HashMap<String, GlobalRef>, class_loader_obj: &'a GlobalRef, env: &'a AttachGuard<'static>, class_name: &'a str, ) -> Result<JClass<'a>, JNIError>275     fn find_local_class<'a>(
276         jclass_map: &'a mut HashMap<String, GlobalRef>,
277         class_loader_obj: &'a GlobalRef,
278         env: &'a AttachGuard<'static>,
279         class_name: &'a str,
280     ) -> Result<JClass<'a>, JNIError> {
281         // Look for cached class
282         if jclass_map.get(class_name).is_none() {
283             // Find class using the class loader object, needed as this call is initiated from a
284             // different native thread.
285 
286             let env_class_name = *env.new_string(class_name).map_err(|e| {
287                 error!("UCI JNI: failed to create Java String: {e:?}");
288                 e
289             })?;
290             let class_value = env
291                 .call_method(
292                     class_loader_obj.as_obj(),
293                     "findClass",
294                     "(Ljava/lang/String;)Ljava/lang/Class;",
295                     &[JValue::Object(env_class_name)],
296                 )
297                 .map_err(|e| {
298                     error!("UCI JNI: failed to find java class {}: {:?}", class_name, e);
299                     e
300                 })?;
301             let jclass = match class_value.l() {
302                 Ok(obj) => Ok(JClass::from(obj)),
303                 Err(e) => {
304                     error!("UCI JNI: failed to find java class {}: {:?}", class_name, e);
305                     Err(e)
306                 }
307             }?;
308             // Cache JClass as a global reference.
309             jclass_map.insert(
310                 class_name.to_owned(),
311                 env.new_global_ref(jclass).map_err(|e| {
312                     error!("UCI JNI: global reference conversion failed: {:?}", e);
313                     e
314                 })?,
315             );
316         }
317         // Return JClass
318         Ok(jclass_map.get(class_name).unwrap().as_obj().into())
319     }
320 
cached_jni_call( &mut self, name: &str, sig: &str, args: &[jvalue], ) -> Result<JObject, JNIError>321     fn cached_jni_call(
322         &mut self,
323         name: &str,
324         sig: &str,
325         args: &[jvalue],
326     ) -> Result<JObject, JNIError> {
327         debug!("UCI JNI: callback {}", name);
328         let type_signature = TypeSignature::from_str(sig).map_err(|e| {
329             error!("UCI JNI: Invalid type signature: {:?}", e);
330             e
331         })?;
332         if type_signature.args.len() != args.len() {
333             error!(
334                 "UCI: type_signature requires {} args, but {} is provided",
335                 type_signature.args.len(),
336                 args.len()
337             );
338             return Err(jni::errors::Error::InvalidArgList(type_signature));
339         }
340         let name_signature = name.to_owned() + sig;
341         if !self.jmethod_id_map.contains_key(&name_signature) {
342             self.jmethod_id_map.insert(
343                 name_signature.clone(),
344                 self.env.get_method_id(self.callback_obj.as_obj(), name, sig).map_err(|e| {
345                     error!("UCI JNI: failed to get method: {:?}", e);
346                     e
347                 })?,
348             );
349         }
350         match self.env.call_method_unchecked(
351             self.callback_obj.as_obj(),
352             self.jmethod_id_map.get(&name_signature).unwrap().to_owned(),
353             type_signature.ret,
354             args,
355         ) {
356             Ok(_) => Ok(JObject::null()),
357             Err(e) => {
358                 error!("UCI JNI: callback {} failed!", name);
359                 Err(e)
360             }
361         }
362     }
363 
on_session_status_notification( &mut self, session_id: u32, session_token: u32, session_state: SessionState, reason_code: u8, ) -> Result<JObject, JNIError>364     fn on_session_status_notification(
365         &mut self,
366         session_id: u32,
367         session_token: u32,
368         session_state: SessionState,
369         reason_code: u8,
370     ) -> Result<JObject, JNIError> {
371         self.cached_jni_call(
372             "onSessionStatusNotificationReceived",
373             "(JIII)V",
374             &[
375                 jvalue::from(JValue::Long(session_id as i64)),
376                 jvalue::from(JValue::Int(session_token as i32)),
377                 jvalue::from(JValue::Int(session_state as i32)),
378                 jvalue::from(JValue::Int(reason_code as i32)),
379             ],
380         )
381     }
382 
on_session_update_multicast_notification( &mut self, session_id: u32, remaining_multicast_list_size: usize, status_list: ControleeStatusList, ) -> Result<JObject, JNIError>383     fn on_session_update_multicast_notification(
384         &mut self,
385         session_id: u32,
386         remaining_multicast_list_size: usize,
387         status_list: ControleeStatusList,
388     ) -> Result<JObject, JNIError> {
389         let remaining_multicast_list_size: i32 =
390             remaining_multicast_list_size.try_into().map_err(|_| JNIError::InvalidCtorReturn)?;
391         let mac_address_vec: Vec<[u8; 2]>;
392         let subsession_id_vec: Vec<_>;
393         let status_vec: Vec<_>;
394         let count: i32;
395         match status_list {
396             ControleeStatusList::V1(status_list) => {
397                 count = status_list.len().try_into().map_err(|_| JNIError::InvalidCtorReturn)?;
398                 (mac_address_vec, (subsession_id_vec, status_vec)) = status_list
399                     .into_iter()
400                     .map(|cs| (cs.mac_address, (cs.subsession_id as i64, i32::from(cs.status))))
401                     .unzip();
402             }
403             ControleeStatusList::V2(status_list) => {
404                 count = status_list.len().try_into().map_err(|_| JNIError::InvalidCtorReturn)?;
405                 (mac_address_vec, (subsession_id_vec, status_vec)) = status_list
406                     .into_iter()
407                     .map(|cs| (cs.mac_address, (0_i64, i32::from(cs.status))))
408                     .unzip();
409             }
410         }
411         let subsession_id_jlongarray = self.env.new_long_array(count)?;
412         let status_jintarray = self.env.new_int_array(count)?;
413 
414         let mac_address_vec_i8 =
415             mac_address_vec.iter().flat_map(|&[a, b]| vec![a as i8, b as i8]).collect::<Vec<i8>>();
416         let mac_address_slice: &[i8] = &mac_address_vec_i8;
417         let mac_address_jbytearray = self.env.new_byte_array(mac_address_slice.len() as i32)?;
418 
419         self.env.set_byte_array_region(mac_address_jbytearray, 0, mac_address_slice)?;
420         self.env.set_long_array_region(subsession_id_jlongarray, 0, &subsession_id_vec)?;
421         self.env.set_int_array_region(status_jintarray, 0, &status_vec)?;
422         let multicast_update_jclass = NotificationManagerAndroid::find_local_class(
423             &mut self.jclass_map,
424             &self.class_loader_obj,
425             &self.env,
426             MULTICAST_LIST_UPDATE_STATUS_CLASS,
427         )?;
428         let method_sig = "(L".to_owned() + MULTICAST_LIST_UPDATE_STATUS_CLASS + ";)V";
429 
430         // Safety: mac_address_jintarray is safely instantiated above.
431         let mac_address_jobject = unsafe { JObject::from_raw(mac_address_jbytearray) };
432 
433         // Safety: subsession_id_jlongarray is safely instantiated above.
434         let subsession_id_jobject = unsafe { JObject::from_raw(subsession_id_jlongarray) };
435 
436         // Safety: status_jintarray is safely instantiated above.
437         let status_jobject = unsafe { JObject::from_raw(status_jintarray) };
438 
439         let multicast_update_jobject = self.env.new_object(
440             multicast_update_jclass,
441             "(JII[B[J[I)V",
442             &[
443                 JValue::Long(session_id as i64),
444                 JValue::Int(remaining_multicast_list_size),
445                 JValue::Int(count),
446                 JValue::Object(mac_address_jobject),
447                 JValue::Object(subsession_id_jobject),
448                 JValue::Object(status_jobject),
449             ],
450         )?;
451         self.cached_jni_call(
452             "onMulticastListUpdateNotificationReceived",
453             &method_sig,
454             &[jvalue::from(JValue::Object(multicast_update_jobject))],
455         )
456     }
457 
458     // TODO(b/246678053): Re-factor usage of the RangingMeasurement enum below, to extract the
459     // fields in a common/caller method (and preferably not handle TwoWay/OwrAoa in this method).
on_session_dl_tdoa_range_data_notification( &mut self, range_data: SessionRangeData, ) -> Result<JObject, JNIError>460     fn on_session_dl_tdoa_range_data_notification(
461         &mut self,
462         range_data: SessionRangeData,
463     ) -> Result<JObject, JNIError> {
464         let raw_notification_jbytearray =
465             self.env.byte_array_from_slice(&range_data.raw_ranging_data)?;
466         let measurement_jclass = NotificationManagerAndroid::find_local_class(
467             &mut self.jclass_map,
468             &self.class_loader_obj,
469             &self.env,
470             UWB_DL_TDOA_MEASUREMENT_CLASS,
471         )?;
472         let bytearray_len: i32 = match &range_data.ranging_measurements {
473             uwb_core::uci::RangingMeasurements::ShortAddressTwoWay(_) => SHORT_MAC_ADDRESS_LEN,
474             uwb_core::uci::RangingMeasurements::ExtendedAddressTwoWay(_) => {
475                 EXTENDED_MAC_ADDRESS_LEN
476             }
477             uwb_core::uci::RangingMeasurements::ShortAddressDltdoa(_) => SHORT_MAC_ADDRESS_LEN,
478             uwb_core::uci::RangingMeasurements::ExtendedAddressDltdoa(_) => {
479                 EXTENDED_MAC_ADDRESS_LEN
480             }
481             _ => {
482                 return Err(JNIError::InvalidCtorReturn);
483             }
484         };
485         let address_jbytearray = self.env.new_byte_array(bytearray_len)?;
486         let anchor_location = self.env.new_byte_array(MAX_ANCHOR_LOCATION_LEN)?;
487         let active_ranging_rounds = self.env.new_byte_array(MAX_RANGING_ROUNDS_LEN)?;
488 
489         // Safety: address_jbytearray is safely instantiated above.
490         let address_jobject = unsafe { JObject::from_raw(address_jbytearray) };
491         // Safety: anchor_location is safely instantiated above.
492         let anchor_jobject = unsafe { JObject::from_raw(anchor_location) };
493         // Safety: active_ranging_rounds is safely instantiated above.
494         let active_ranging_rounds_jobject = unsafe { JObject::from_raw(active_ranging_rounds) };
495 
496         let zero_initiated_measurement_jobject = self
497             .env
498             .new_object(
499                 measurement_jclass,
500                 "([BIIIIIIIIIIIJJIIJJI[B[B)V",
501                 &[
502                     JValue::Object(address_jobject),
503                     JValue::Int(0),
504                     JValue::Int(0),
505                     JValue::Int(0),
506                     JValue::Int(0),
507                     JValue::Int(0),
508                     JValue::Int(0),
509                     JValue::Int(0),
510                     JValue::Int(0),
511                     JValue::Int(0),
512                     JValue::Int(0),
513                     JValue::Int(0),
514                     JValue::Long(0),
515                     JValue::Long(0),
516                     JValue::Int(0),
517                     JValue::Int(0),
518                     JValue::Long(0),
519                     JValue::Long(0),
520                     JValue::Int(0),
521                     JValue::Object(anchor_jobject),
522                     JValue::Object(active_ranging_rounds_jobject),
523                 ],
524             )
525             .map_err(|e| {
526                 error!("UCI JNI: measurement object creation failed: {:?}", e);
527                 e
528             })?;
529         let measurement_count: i32 = match &range_data.ranging_measurements {
530             RangingMeasurements::ShortAddressTwoWay(v) => v.len(),
531             RangingMeasurements::ExtendedAddressTwoWay(v) => v.len(),
532             RangingMeasurements::ShortAddressDltdoa(v) => v.len(),
533             RangingMeasurements::ExtendedAddressDltdoa(v) => v.len(),
534             _ => {
535                 return Err(JNIError::InvalidCtorReturn);
536             }
537         }
538         .try_into()
539         .map_err(|_| JNIError::InvalidCtorReturn)?;
540         let mac_indicator = match &range_data.ranging_measurements {
541             RangingMeasurements::ShortAddressTwoWay(_) => MacAddressIndicator::ShortAddress,
542             RangingMeasurements::ExtendedAddressTwoWay(_) => MacAddressIndicator::ExtendedAddress,
543             RangingMeasurements::ShortAddressDltdoa(_) => MacAddressIndicator::ShortAddress,
544             RangingMeasurements::ExtendedAddressDltdoa(_) => MacAddressIndicator::ExtendedAddress,
545             _ => {
546                 return Err(JNIError::InvalidCtorReturn);
547             }
548         };
549 
550         let measurements_jobjectarray = self.env.new_object_array(
551             measurement_count,
552             measurement_jclass,
553             zero_initiated_measurement_jobject,
554         )?;
555 
556         for (i, measurement) in match range_data.ranging_measurements {
557             RangingMeasurements::ShortAddressDltdoa(v) => {
558                 v.into_iter().map(DlTdoaRangingMeasurement::from).collect::<Vec<_>>()
559             }
560             RangingMeasurements::ExtendedAddressDltdoa(v) => {
561                 v.into_iter().map(DlTdoaRangingMeasurement::from).collect::<Vec<_>>()
562             }
563             _ => Vec::new(),
564         }
565         .into_iter()
566         .enumerate()
567         {
568             // cast to i8 as java do not support unsigned:
569             let mac_address_i8 = measurement
570                 .mac_address
571                 .into_ne_bytes()
572                 .iter()
573                 .map(|b| b.to_owned() as i8)
574                 .collect::<Vec<_>>();
575             let mac_address_jbytearray = self.env.new_byte_array(mac_address_i8.len() as i32)?;
576             self.env.set_byte_array_region(mac_address_jbytearray, 0, &mac_address_i8)?;
577 
578             let dt_anchor_location_jbytearray =
579                 self.env.byte_array_from_slice(&measurement.dt_anchor_location)?;
580 
581             let ranging_rounds_jbytearray =
582                 self.env.byte_array_from_slice(&measurement.ranging_rounds)?;
583 
584             // Safety: mac_address_jbytearray is safely instantiated above.
585             let mac_address_jobject = unsafe { JObject::from_raw(mac_address_jbytearray) };
586             let dt_anchor_location_jobject =
587             // Safety: dt_anchor_location_jbytearray is safely instantiated above.
588                 unsafe { JObject::from_raw(dt_anchor_location_jbytearray) };
589             // Safety: ranging_rounds_jbytearray is safely instantiated above.
590             let ranging_rounds_jobject = unsafe { JObject::from_raw(ranging_rounds_jbytearray) };
591 
592             let measurement_jobject = self
593                 .env
594                 .new_object(
595                     measurement_jclass,
596                     "([BIIIIIIIIIIIJJIIJJI[B[B)V",
597                     &[
598                         JValue::Object(mac_address_jobject),
599                         JValue::Int(measurement.status as i32),
600                         JValue::Int(measurement.message_type as i32),
601                         JValue::Int(measurement.message_control as i32),
602                         JValue::Int(measurement.block_index as i32),
603                         JValue::Int(measurement.round_index as i32),
604                         JValue::Int(measurement.nlos as i32),
605                         JValue::Int(measurement.aoa_azimuth as i32),
606                         JValue::Int(measurement.aoa_azimuth_fom as i32),
607                         JValue::Int(measurement.aoa_elevation as i32),
608                         JValue::Int(measurement.aoa_elevation_fom as i32),
609                         JValue::Int(measurement.rssi as i32),
610                         JValue::Long(measurement.tx_timestamp as i64),
611                         JValue::Long(measurement.rx_timestamp as i64),
612                         JValue::Int(measurement.anchor_cfo as i32),
613                         JValue::Int(measurement.cfo as i32),
614                         JValue::Long(measurement.initiator_reply_time as i64),
615                         JValue::Long(measurement.responder_reply_time as i64),
616                         JValue::Int(measurement.initiator_responder_tof as i32),
617                         JValue::Object(dt_anchor_location_jobject),
618                         JValue::Object(ranging_rounds_jobject),
619                     ],
620                 )
621                 .map_err(|e| {
622                     error!("UCI JNI: measurement object creation failed: {:?}", e);
623                     e
624                 })?;
625             self.env
626                 .set_object_array_element(measurements_jobjectarray, i as i32, measurement_jobject)
627                 .map_err(|e| {
628                     error!("UCI JNI: measurement object copy failed: {:?}", e);
629                     e
630                 })?;
631         }
632         // Create UwbRangingData
633         let ranging_data_jclass = NotificationManagerAndroid::find_local_class(
634             &mut self.jclass_map,
635             &self.class_loader_obj,
636             &self.env,
637             UWB_RANGING_DATA_CLASS,
638         )?;
639 
640         let method_sig = "(JJIJIJII[L".to_owned() + UWB_DL_TDOA_MEASUREMENT_CLASS + ";[B)V";
641 
642         // Safety: measurements_jobjectarray is safely instantiated above.
643         let measurements_jobject = unsafe { JObject::from_raw(measurements_jobjectarray) };
644         // Safety: raw_notification_jbytearray is safely instantiated above.
645         let raw_notification_jobject = unsafe { JObject::from_raw(raw_notification_jbytearray) };
646 
647         let range_data_jobject = self
648             .env
649             .new_object(
650                 ranging_data_jclass,
651                 &method_sig,
652                 &[
653                     JValue::Long(range_data.sequence_number as i64),
654                     // session_token below has already been mapped to session_id by uci layer.
655                     JValue::Long(range_data.session_token as i64),
656                     JValue::Int(range_data.rcr_indicator as i32),
657                     JValue::Long(range_data.current_ranging_interval_ms as i64),
658                     JValue::Int(range_data.ranging_measurement_type as i32),
659                     JValue::Long(range_data.hus_primary_session_id as i64),
660                     JValue::Int(mac_indicator as i32),
661                     JValue::Int(measurement_count),
662                     JValue::Object(measurements_jobject),
663                     JValue::Object(raw_notification_jobject),
664                 ],
665             )
666             .map_err(|e| {
667                 error!("UCI JNI: Ranging Data object creation failed: {:?}", e);
668                 e
669             })?;
670 
671         let method_sig = "(L".to_owned() + UWB_RANGING_DATA_CLASS + ";)V";
672         self.cached_jni_call(
673             "onRangeDataNotificationReceived",
674             &method_sig,
675             &[jvalue::from(JValue::Object(range_data_jobject))],
676         )
677     }
678 
on_two_way_range_data_notification( &mut self, bytearray_len: i32, measurement_count: i32, measurements: Vec<TwoWayRangingMeasurement>, ) -> Result<jni::sys::jobjectArray, JNIError>679     fn on_two_way_range_data_notification(
680         &mut self,
681         bytearray_len: i32,
682         measurement_count: i32,
683         measurements: Vec<TwoWayRangingMeasurement>,
684     ) -> Result<jni::sys::jobjectArray, JNIError> {
685         let measurement_jclass = NotificationManagerAndroid::find_local_class(
686             &mut self.jclass_map,
687             &self.class_loader_obj,
688             &self.env,
689             UWB_TWO_WAY_MEASUREMENT_CLASS,
690         )?;
691         let address_jbytearray = self.env.new_byte_array(bytearray_len)?;
692 
693         // Safety: address_jbytearray is safely instantiated above.
694         let address_jobject = unsafe { JObject::from_raw(address_jbytearray) };
695 
696         let zero_initiated_measurement_jobject = self
697             .env
698             .new_object(
699                 measurement_jclass,
700                 "([BIIIIIIIIIIIII)V",
701                 &[
702                     JValue::Object(address_jobject),
703                     JValue::Int(0),
704                     JValue::Int(0),
705                     JValue::Int(0),
706                     JValue::Int(0),
707                     JValue::Int(0),
708                     JValue::Int(0),
709                     JValue::Int(0),
710                     JValue::Int(0),
711                     JValue::Int(0),
712                     JValue::Int(0),
713                     JValue::Int(0),
714                     JValue::Int(0),
715                     JValue::Int(0),
716                 ],
717             )
718             .map_err(|e| {
719                 error!("UCI JNI: measurement object creation failed: {:?}", e);
720                 e
721             })?;
722 
723         let measurements_jobjectarray = self.env.new_object_array(
724             measurement_count,
725             measurement_jclass,
726             zero_initiated_measurement_jobject,
727         )?;
728         for (i, measurement) in measurements.into_iter().enumerate() {
729             // cast to i8 as java do not support unsigned:
730             let mac_address_i8 = measurement
731                 .mac_address
732                 .into_ne_bytes()
733                 .iter()
734                 .map(|b| b.to_owned() as i8)
735                 .collect::<Vec<_>>();
736             let mac_address_jbytearray = self.env.new_byte_array(mac_address_i8.len() as i32)?;
737             self.env.set_byte_array_region(mac_address_jbytearray, 0, &mac_address_i8)?;
738             // casting as i32 is fine since it is wider than actual integer type.
739 
740             // Safety: mac_address_jbytearray is safely instantiated above.
741             let mac_address_jobject = unsafe { JObject::from_raw(mac_address_jbytearray) };
742             let measurement_jobject = self
743                 .env
744                 .new_object(
745                     measurement_jclass,
746                     "([BIIIIIIIIIIIII)V",
747                     &[
748                         JValue::Object(mac_address_jobject),
749                         JValue::Int(i32::from(measurement.status)),
750                         JValue::Int(measurement.nlos as i32),
751                         JValue::Int(measurement.distance as i32),
752                         JValue::Int(measurement.aoa_azimuth as i32),
753                         JValue::Int(measurement.aoa_azimuth_fom as i32),
754                         JValue::Int(measurement.aoa_elevation as i32),
755                         JValue::Int(measurement.aoa_elevation_fom as i32),
756                         JValue::Int(measurement.aoa_destination_azimuth as i32),
757                         JValue::Int(measurement.aoa_destination_azimuth_fom as i32),
758                         JValue::Int(measurement.aoa_destination_elevation as i32),
759                         JValue::Int(measurement.aoa_destination_elevation_fom as i32),
760                         JValue::Int(measurement.slot_index as i32),
761                         JValue::Int(measurement.rssi as i32),
762                     ],
763                 )
764                 .map_err(|e| {
765                     error!("UCI JNI: measurement object creation failed: {:?}", e);
766                     e
767                 })?;
768             self.env
769                 .set_object_array_element(measurements_jobjectarray, i as i32, measurement_jobject)
770                 .map_err(|e| {
771                     error!("UCI JNI: measurement object copy failed: {:?}", e);
772                     e
773                 })?;
774         }
775 
776         Ok(measurements_jobjectarray)
777     }
778 
on_session_owr_aoa_range_data_notification( &mut self, range_data: SessionRangeData, ) -> Result<JObject, JNIError>779     fn on_session_owr_aoa_range_data_notification(
780         &mut self,
781         range_data: SessionRangeData,
782     ) -> Result<JObject, JNIError> {
783         if range_data.ranging_measurement_type != RangingMeasurementType::OwrAoa {
784             return Err(JNIError::InvalidCtorReturn);
785         }
786 
787         let raw_notification_jbytearray =
788             self.env.byte_array_from_slice(&range_data.raw_ranging_data)?;
789 
790         let (mac_indicator, measurement): (MacAddressIndicator, OwrAoaRangingMeasurement) =
791             match range_data.ranging_measurements {
792                 RangingMeasurements::ExtendedAddressOwrAoa(m) => {
793                     (MacAddressIndicator::ExtendedAddress, m.into())
794                 }
795                 RangingMeasurements::ShortAddressOwrAoa(m) => {
796                     (MacAddressIndicator::ShortAddress, m.into())
797                 }
798                 _ => {
799                     return Err(JNIError::InvalidCtorReturn);
800                 }
801             };
802 
803         // cast to i8 as java do not support unsigned.
804         let mac_address_i8 = measurement
805             .mac_address
806             .into_ne_bytes()
807             .iter()
808             .map(|b| b.to_owned() as i8)
809             .collect::<Vec<_>>();
810         // casting as i32 is fine since it is wider than actual integer type.
811         let mac_address_jbytearray = self.env.new_byte_array(mac_address_i8.len() as i32)?;
812         self.env.set_byte_array_region(mac_address_jbytearray, 0, &mac_address_i8)?;
813         // Safety: mac_address_jbytearray is safely instantiated above.
814         let mac_address_jobject = unsafe { JObject::from_raw(mac_address_jbytearray) };
815 
816         let measurement_jclass = NotificationManagerAndroid::find_local_class(
817             &mut self.jclass_map,
818             &self.class_loader_obj,
819             &self.env,
820             UWB_OWR_AOA_MEASUREMENT_CLASS,
821         )?;
822         let measurement_jobject = self
823             .env
824             .new_object(
825                 measurement_jclass,
826                 "([BIIIIIIII)V",
827                 &[
828                     JValue::Object(mac_address_jobject),
829                     JValue::Int(i32::from(measurement.status)),
830                     JValue::Int(measurement.nlos as i32),
831                     JValue::Int(measurement.frame_sequence_number as i32),
832                     JValue::Int(measurement.block_index as i32),
833                     JValue::Int(measurement.aoa_azimuth as i32),
834                     JValue::Int(measurement.aoa_azimuth_fom as i32),
835                     JValue::Int(measurement.aoa_elevation as i32),
836                     JValue::Int(measurement.aoa_elevation_fom as i32),
837                 ],
838             )
839             .map_err(|e| {
840                 error!("UCI JNI: OwrAoA measurement jobject creation failed: {:?}", e);
841                 e
842             })?;
843 
844         // Create UwbRangingData
845         let ranging_data_jclass = NotificationManagerAndroid::find_local_class(
846             &mut self.jclass_map,
847             &self.class_loader_obj,
848             &self.env,
849             UWB_RANGING_DATA_CLASS,
850         )?;
851         let method_sig = "(JJIJIJIIL".to_owned() + UWB_OWR_AOA_MEASUREMENT_CLASS + ";[B)V";
852 
853         // Safety: raw_notification_jobject is safely instantiated above.
854         let raw_notification_jobject = unsafe { JObject::from_raw(raw_notification_jbytearray) };
855 
856         let range_data_jobject = self
857             .env
858             .new_object(
859                 ranging_data_jclass,
860                 &method_sig,
861                 &[
862                     JValue::Long(range_data.sequence_number as i64),
863                     // session_token below has already been mapped to session_id by uci layer.
864                     JValue::Long(range_data.session_token as i64),
865                     JValue::Int(range_data.rcr_indicator as i32),
866                     JValue::Long(range_data.current_ranging_interval_ms as i64),
867                     JValue::Int(range_data.ranging_measurement_type as i32),
868                     JValue::Long(range_data.hus_primary_session_id as i64),
869                     JValue::Int(mac_indicator as i32),
870                     JValue::Int(1), // measurement_count
871                     JValue::Object(measurement_jobject),
872                     JValue::Object(raw_notification_jobject),
873                 ],
874             )
875             .map_err(|e| {
876                 error!("UCI JNI: Ranging Data object creation failed: {:?}", e);
877                 e
878             })?;
879         let method_sig = "(L".to_owned() + UWB_RANGING_DATA_CLASS + ";)V";
880         self.cached_jni_call(
881             "onRangeDataNotificationReceived",
882             &method_sig,
883             &[jvalue::from(JValue::Object(range_data_jobject))],
884         )
885     }
886 
on_session_two_way_range_data_notification( &mut self, range_data: SessionRangeData, ) -> Result<JObject, JNIError>887     fn on_session_two_way_range_data_notification(
888         &mut self,
889         range_data: SessionRangeData,
890     ) -> Result<JObject, JNIError> {
891         let raw_notification_jbytearray =
892             self.env.byte_array_from_slice(&range_data.raw_ranging_data)?;
893 
894         let (bytearray_len, mac_indicator) = match &range_data.ranging_measurements {
895             RangingMeasurements::ExtendedAddressTwoWay(_) => {
896                 (EXTENDED_MAC_ADDRESS_LEN, MacAddressIndicator::ExtendedAddress)
897             }
898             RangingMeasurements::ShortAddressTwoWay(_) => {
899                 (SHORT_MAC_ADDRESS_LEN, MacAddressIndicator::ShortAddress)
900             }
901             _ => {
902                 return Err(JNIError::InvalidCtorReturn);
903             }
904         };
905 
906         let measurement_count: i32 = match &range_data.ranging_measurements {
907             RangingMeasurements::ShortAddressTwoWay(v) => v.len().try_into(),
908             RangingMeasurements::ExtendedAddressTwoWay(v) => v.len().try_into(),
909             _ => {
910                 return Err(JNIError::InvalidCtorReturn);
911             }
912         }
913         .map_err(|_| JNIError::InvalidCtorReturn)?;
914 
915         let measurements_jobjectarray = match range_data.ranging_measurement_type {
916             RangingMeasurementType::TwoWay => {
917                 let measurements = match range_data.ranging_measurements {
918                     RangingMeasurements::ExtendedAddressTwoWay(v) => {
919                         v.into_iter().map(TwoWayRangingMeasurement::from).collect::<Vec<_>>()
920                     }
921                     RangingMeasurements::ShortAddressTwoWay(v) => {
922                         v.into_iter().map(TwoWayRangingMeasurement::from).collect::<Vec<_>>()
923                     }
924                     _ => return Err(JNIError::InvalidCtorReturn),
925                 };
926                 self.on_two_way_range_data_notification(
927                     bytearray_len,
928                     measurement_count,
929                     measurements,
930                 )?
931             }
932             _ => {
933                 return Err(JNIError::InvalidCtorReturn);
934             }
935         };
936 
937         // Create UwbRangingData
938         let ranging_data_jclass = NotificationManagerAndroid::find_local_class(
939             &mut self.jclass_map,
940             &self.class_loader_obj,
941             &self.env,
942             UWB_RANGING_DATA_CLASS,
943         )?;
944         let method_sig = "(JJIJIJII[L".to_owned() + UWB_TWO_WAY_MEASUREMENT_CLASS + ";[B)V";
945 
946         // Safety: measurements_jobjectarray is safely instantiated above.
947         let measurements_jobject = unsafe { JObject::from_raw(measurements_jobjectarray) };
948         // Safety: raw_notification_jobject is safely instantiated above.
949         let raw_notification_jobject = unsafe { JObject::from_raw(raw_notification_jbytearray) };
950         let range_data_jobject = self
951             .env
952             .new_object(
953                 ranging_data_jclass,
954                 &method_sig,
955                 &[
956                     JValue::Long(range_data.sequence_number as i64),
957                     // session_token below has already been mapped to session_id by uci layer.
958                     JValue::Long(range_data.session_token as i64),
959                     JValue::Int(range_data.rcr_indicator as i32),
960                     JValue::Long(range_data.current_ranging_interval_ms as i64),
961                     JValue::Int(range_data.ranging_measurement_type as i32),
962                     JValue::Long(range_data.hus_primary_session_id as i64),
963                     JValue::Int(mac_indicator as i32),
964                     JValue::Int(measurement_count),
965                     JValue::Object(measurements_jobject),
966                     JValue::Object(raw_notification_jobject),
967                 ],
968             )
969             .map_err(|e| {
970                 error!("UCI JNI: Ranging Data object creation failed: {:?}", e);
971                 e
972             })?;
973         let method_sig = "(L".to_owned() + UWB_RANGING_DATA_CLASS + ";)V";
974         self.cached_jni_call(
975             "onRangeDataNotificationReceived",
976             &method_sig,
977             &[jvalue::from(JValue::Object(range_data_jobject))],
978         )
979     }
980 
on_data_transfer_status_notification( &mut self, session_id: u32, uci_sequence_number: u16, status_code: u8, tx_count: u8, ) -> Result<JObject, JNIError>981     fn on_data_transfer_status_notification(
982         &mut self,
983         session_id: u32,
984         uci_sequence_number: u16,
985         status_code: u8,
986         tx_count: u8,
987     ) -> Result<JObject, JNIError> {
988         self.cached_jni_call(
989             "onDataSendStatus",
990             "(JIJI)V",
991             &[
992                 jvalue::from(JValue::Long(session_id as i64)),
993                 jvalue::from(JValue::Int(status_code as i32)),
994                 jvalue::from(JValue::Long(uci_sequence_number as i64)),
995                 jvalue::from(JValue::Int(tx_count as i32)),
996             ],
997         )
998     }
999 
on_data_transfer_phase_config_notification( &mut self, session_id: u32, status_code: u8, ) -> Result<JObject, JNIError>1000     fn on_data_transfer_phase_config_notification(
1001         &mut self,
1002         session_id: u32,
1003         status_code: u8,
1004     ) -> Result<JObject, JNIError> {
1005         self.cached_jni_call(
1006             "onDataTransferPhaseConfigNotificationReceived",
1007             "(JI)V",
1008             &[
1009                 jvalue::from(JValue::Long(session_id as i64)),
1010                 jvalue::from(JValue::Int(status_code as i32)),
1011             ],
1012         )
1013     }
1014 
on_rf_periodic_tx_notification( &mut self, status: u8, raw_notification_data: &[u8], ) -> Result<JObject, JNIError>1015     fn on_rf_periodic_tx_notification(
1016         &mut self,
1017         status: u8,
1018         raw_notification_data: &[u8],
1019     ) -> Result<JObject, JNIError> {
1020         let raw_notification_jbytearray = self.env.byte_array_from_slice(raw_notification_data)?;
1021         // Safety: raw_notification_jbytearray safely instantiated above.
1022         let raw_notification_jobject = unsafe { JObject::from_raw(raw_notification_jbytearray) };
1023 
1024         let periodic_tx_jclass = NotificationManagerAndroid::find_local_class(
1025             &mut self.jclass_map,
1026             &self.class_loader_obj,
1027             &self.env,
1028             RFTEST_PERIODIC_TX_CLASS,
1029         )?;
1030         let method_sig = "(L".to_owned() + RFTEST_PERIODIC_TX_CLASS + ";)V";
1031 
1032         let periodic_tx_jobject = self.env.new_object(
1033             periodic_tx_jclass,
1034             "(I[B)V",
1035             &[JValue::Int(status as i32), JValue::Object(raw_notification_jobject)],
1036         )?;
1037         self.cached_jni_call(
1038             "onPeriodicTxDataNotificationReceived",
1039             &method_sig,
1040             &[jvalue::from(JValue::Object(periodic_tx_jobject))],
1041         )
1042     }
1043 
on_rf_per_rx_notification( &mut self, per_rx_data: RfTestPerRxData, ) -> Result<JObject, JNIError>1044     fn on_rf_per_rx_notification(
1045         &mut self,
1046         per_rx_data: RfTestPerRxData,
1047     ) -> Result<JObject, JNIError> {
1048         let raw_notification_jbytearray =
1049             self.env.byte_array_from_slice(&per_rx_data.raw_notification_data)?;
1050         // Safety: raw_notification_jbytearray safely instantiated above.
1051         let raw_notification_jobject = unsafe { JObject::from_raw(raw_notification_jbytearray) };
1052 
1053         let per_rx_jclass = NotificationManagerAndroid::find_local_class(
1054             &mut self.jclass_map,
1055             &self.class_loader_obj,
1056             &self.env,
1057             RFTEST_PER_RX_CLASS,
1058         )?;
1059         let method_sig = "(L".to_owned() + RFTEST_PER_RX_CLASS + ";)V";
1060 
1061         let per_rx_jobject = self.env.new_object(
1062             per_rx_jclass,
1063             "(IJJJJJJJJJJJJJ[B)V",
1064             &[
1065                 JValue::Int(i32::from(per_rx_data.status)),
1066                 JValue::Long(per_rx_data.attempts as i64),
1067                 JValue::Long(per_rx_data.acq_detect as i64),
1068                 JValue::Long(per_rx_data.acq_reject as i64),
1069                 JValue::Long(per_rx_data.rx_fail as i64),
1070                 JValue::Long(per_rx_data.sync_cir_ready as i64),
1071                 JValue::Long(per_rx_data.sfd_fail as i64),
1072                 JValue::Long(per_rx_data.sfd_found as i64),
1073                 JValue::Long(per_rx_data.phr_dec_error as i64),
1074                 JValue::Long(per_rx_data.phr_bit_error as i64),
1075                 JValue::Long(per_rx_data.psdu_dec_error as i64),
1076                 JValue::Long(per_rx_data.psdu_bit_error as i64),
1077                 JValue::Long(per_rx_data.sts_found as i64),
1078                 JValue::Long(per_rx_data.eof as i64),
1079                 JValue::Object(raw_notification_jobject),
1080             ],
1081         )?;
1082         self.cached_jni_call(
1083             "onPerRxDataNotificationReceived",
1084             &method_sig,
1085             &[jvalue::from(JValue::Object(per_rx_jobject))],
1086         )
1087     }
1088 }
1089 
1090 impl NotificationManager for NotificationManagerAndroid {
on_core_notification(&mut self, core_notification: CoreNotification) -> UwbResult<()>1091     fn on_core_notification(&mut self, core_notification: CoreNotification) -> UwbResult<()> {
1092         debug!("UCI JNI: core notification callback.");
1093         let env = *self.env;
1094         env.with_local_frame(MAX_JAVA_OBJECTS_CAPACITY, || {
1095             let env_chip_id_jobject = *env.new_string(&self.chip_id).map_err(|e| {
1096                 error!("UCI JNI: failed to create Java String: {e:?}");
1097                 e
1098             })?;
1099 
1100             match core_notification {
1101                 CoreNotification::DeviceStatus(device_state) => self.cached_jni_call(
1102                     "onDeviceStatusNotificationReceived",
1103                     "(ILjava/lang/String;)V",
1104                     &[
1105                         jvalue::from(JValue::Int(device_state as i32)),
1106                         jvalue::from(JValue::Object(env_chip_id_jobject)),
1107                     ],
1108                 ),
1109                 CoreNotification::GenericError(generic_error) => self.cached_jni_call(
1110                     "onCoreGenericErrorNotificationReceived",
1111                     "(ILjava/lang/String;)V",
1112                     &[
1113                         jvalue::from(JValue::Int(i32::from(generic_error))),
1114                         jvalue::from(JValue::Object(env_chip_id_jobject)),
1115                     ],
1116                 ),
1117             }
1118         })
1119         .map_err(|e| {
1120             error!("on_core_notification error: {:?}", e);
1121             UwbError::ForeignFunctionInterface
1122         })?;
1123 
1124         Ok(())
1125     }
1126 
on_session_notification( &mut self, session_notification: SessionNotification, ) -> UwbResult<()>1127     fn on_session_notification(
1128         &mut self,
1129         session_notification: SessionNotification,
1130     ) -> UwbResult<()> {
1131         debug!("UCI JNI: session notification callback.");
1132         let env = *self.env;
1133         env.with_local_frame(MAX_JAVA_OBJECTS_CAPACITY, || {
1134             match session_notification {
1135                 SessionNotification::Status {
1136                     session_id,
1137                     session_token,
1138                     session_state,
1139                     reason_code,
1140                 } => self.on_session_status_notification(
1141                     session_id,
1142                     session_token,
1143                     session_state,
1144                     reason_code,
1145                 ),
1146                 SessionNotification::UpdateControllerMulticastListV1 {
1147                     session_token,
1148                     remaining_multicast_list_size,
1149                     status_list,
1150                 } => self.on_session_update_multicast_notification(
1151                     session_token,
1152                     remaining_multicast_list_size,
1153                     ControleeStatusList::V1(status_list),
1154                 ),
1155                 SessionNotification::UpdateControllerMulticastListV2 {
1156                     session_token,
1157                     status_list,
1158                 } => self.on_session_update_multicast_notification(
1159                     session_token,
1160                     0_usize,
1161                     ControleeStatusList::V2(status_list),
1162                 ),
1163                 // TODO(b/246678053): Match here on range_data.ranging_measurement_type instead.
1164                 SessionNotification::SessionInfo(range_data) => {
1165                     match range_data.ranging_measurements {
1166                         uwb_core::uci::RangingMeasurements::ShortAddressTwoWay(_) => {
1167                             self.on_session_two_way_range_data_notification(range_data)
1168                         }
1169                         uwb_core::uci::RangingMeasurements::ExtendedAddressTwoWay(_) => {
1170                             self.on_session_two_way_range_data_notification(range_data)
1171                         }
1172                         uwb_core::uci::RangingMeasurements::ShortAddressOwrAoa(_) => {
1173                             self.on_session_owr_aoa_range_data_notification(range_data)
1174                         }
1175                         uwb_core::uci::RangingMeasurements::ExtendedAddressOwrAoa(_) => {
1176                             self.on_session_owr_aoa_range_data_notification(range_data)
1177                         }
1178                         uwb_core::uci::RangingMeasurements::ShortAddressDltdoa(_) => {
1179                             self.on_session_dl_tdoa_range_data_notification(range_data)
1180                         }
1181                         uwb_core::uci::RangingMeasurements::ExtendedAddressDltdoa(_) => {
1182                             self.on_session_dl_tdoa_range_data_notification(range_data)
1183                         }
1184                     }
1185                 }
1186                 SessionNotification::DataTransferStatus {
1187                     session_token,
1188                     uci_sequence_number,
1189                     status,
1190                     tx_count,
1191                 } => self.on_data_transfer_status_notification(
1192                     session_token,
1193                     uci_sequence_number,
1194                     u8::from(status),
1195                     tx_count,
1196                 ),
1197                 // This session notification should not come here, as it's handled within
1198                 // UciManager, for internal state management related to sending data packet(s).
1199                 SessionNotification::DataCredit { session_token, credit_availability } => {
1200                     error!(
1201                         "UCI JNI: Received unexpected DataCredit notification for \
1202                             session_token {}, credit_availability {:?}",
1203                         session_token, credit_availability
1204                     );
1205                     Err(JNIError::InvalidCtorReturn)
1206                 }
1207                 SessionNotification::DataTransferPhaseConfig { session_token, status } => {
1208                     self.on_data_transfer_phase_config_notification(session_token, u8::from(status))
1209                 }
1210             }
1211         })
1212         .map_err(|e| {
1213             error!("on_session_notification error {:?}", e);
1214             UwbError::ForeignFunctionInterface
1215         })?;
1216         Ok(())
1217     }
1218 
on_vendor_notification( &mut self, vendor_notification: uwb_core::params::RawUciMessage, ) -> UwbResult<()>1219     fn on_vendor_notification(
1220         &mut self,
1221         vendor_notification: uwb_core::params::RawUciMessage,
1222     ) -> UwbResult<()> {
1223         debug!("UCI JNI: vendor notification callback.");
1224         let env = *self.env;
1225         env.with_local_frame(MAX_JAVA_OBJECTS_CAPACITY, || {
1226             let payload_jbytearray =
1227                 self.env.byte_array_from_slice(&vendor_notification.payload)?;
1228 
1229             // Safety: payload_jbytearray safely instantiated above.
1230             let payload_jobject = unsafe { JObject::from_raw(payload_jbytearray) };
1231             self.cached_jni_call(
1232                 "onVendorUciNotificationReceived",
1233                 "(II[B)V",
1234                 &[
1235                     // Java only has signed integer. The range for signed int32 should be sufficient.
1236                     jvalue::from(JValue::Int(
1237                         vendor_notification
1238                             .gid
1239                             .try_into()
1240                             .map_err(|_| JNIError::InvalidCtorReturn)?,
1241                     )),
1242                     jvalue::from(JValue::Int(
1243                         vendor_notification
1244                             .oid
1245                             .try_into()
1246                             .map_err(|_| JNIError::InvalidCtorReturn)?,
1247                     )),
1248                     jvalue::from(JValue::Object(payload_jobject)),
1249                 ],
1250             )
1251         })
1252         .map_err(|e| {
1253             error!("on_vendor_notification error: {:?}", e);
1254             UwbError::ForeignFunctionInterface
1255         })?;
1256         Ok(())
1257     }
1258 
on_data_rcv_notification( &mut self, data_rcv_notification: DataRcvNotification, ) -> UwbResult<()>1259     fn on_data_rcv_notification(
1260         &mut self,
1261         data_rcv_notification: DataRcvNotification,
1262     ) -> UwbResult<()> {
1263         debug!("UCI JNI: Data Rcv notification callback.");
1264         let env = *self.env;
1265         env.with_local_frame(MAX_JAVA_OBJECTS_CAPACITY, || {
1266             let source_address_jbytearray = match &data_rcv_notification.source_address {
1267                 UwbAddress::Short(a) => self.env.byte_array_from_slice(a)?,
1268                 UwbAddress::Extended(a) => self.env.byte_array_from_slice(a)?,
1269             };
1270             let payload_jbytearray =
1271                 self.env.byte_array_from_slice(&data_rcv_notification.payload)?;
1272             // Safety: source_address_jbytearray safely instantiated above.
1273             let source_address_jobject = unsafe { JObject::from_raw(source_address_jbytearray) };
1274             // Safety: payload_jbytearray safely instantiated above.
1275             let payload_jobject = unsafe { JObject::from_raw(payload_jbytearray) };
1276             self.cached_jni_call(
1277                 "onDataReceived",
1278                 "(JIJ[B[B)V",
1279                 &[
1280                     // session_token below has already been mapped to session_id by uci layer.
1281                     jvalue::from(JValue::Long(data_rcv_notification.session_token as i64)),
1282                     jvalue::from(JValue::Int(i32::from(data_rcv_notification.status))),
1283                     jvalue::from(JValue::Long(data_rcv_notification.uci_sequence_num as i64)),
1284                     jvalue::from(JValue::Object(source_address_jobject)),
1285                     jvalue::from(JValue::Object(payload_jobject)),
1286                 ],
1287             )
1288         })
1289         .map_err(|e| {
1290             error!("on_data_rcv_notification error: {:?}", e);
1291             UwbError::ForeignFunctionInterface
1292         })?;
1293         Ok(())
1294     }
1295 
on_radar_data_rcv_notification( &mut self, radar_data_rcv_notification: RadarDataRcvNotification, ) -> UwbResult<()>1296     fn on_radar_data_rcv_notification(
1297         &mut self,
1298         radar_data_rcv_notification: RadarDataRcvNotification,
1299     ) -> UwbResult<()> {
1300         debug!("UCI JNI: Radar Data Rcv notification callback.");
1301         let env = *self.env;
1302         env.with_local_frame(MAX_JAVA_OBJECTS_CAPACITY, || {
1303             let radar_sweep_data_jclass = NotificationManagerAndroid::find_local_class(
1304                 &mut self.jclass_map,
1305                 &self.class_loader_obj,
1306                 &self.env,
1307                 UWB_RADAR_SWEEP_DATA_CLASS,
1308             )?;
1309 
1310             let max_sample_data_length =
1311                 radar_bytes_per_sample_value(radar_data_rcv_notification.bits_per_sample) as i32
1312                     * radar_data_rcv_notification.samples_per_sweep as i32;
1313             let sample_data_jbytearray = self.env.new_byte_array(max_sample_data_length)?;
1314             let vendor_data_jbytearray = self.env.new_byte_array(MAX_RADAR_VENDOR_DATA_LEN)?;
1315 
1316             // Safety: sample_data_jbytearray is safely instantiated above.
1317             let sample_data_jobject = unsafe { JObject::from_raw(sample_data_jbytearray) };
1318             // Safety: vendor_data_jbytearray is safely instantiated above.
1319             let vendor_data_jobject = unsafe { JObject::from_raw(vendor_data_jbytearray) };
1320 
1321             let sweep_data_sig: &str = "(JJ[B[B)V";
1322 
1323             let zero_initiated_sweep_data = self
1324                 .env
1325                 .new_object(
1326                     radar_sweep_data_jclass,
1327                     sweep_data_sig,
1328                     &[
1329                         JValue::Long(0),
1330                         JValue::Long(0),
1331                         JValue::Object(vendor_data_jobject),
1332                         JValue::Object(sample_data_jobject),
1333                     ],
1334                 )
1335                 .map_err(|e| {
1336                     error!(
1337                         "UCI JNI: zero initiated RadarSweepData object creation failed: {:?}",
1338                         e
1339                     );
1340                     e
1341                 })?;
1342 
1343             let radar_sweep_data_jobjectarray = self
1344                 .env
1345                 .new_object_array(
1346                     radar_data_rcv_notification.sweep_data.len() as i32,
1347                     radar_sweep_data_jclass,
1348                     zero_initiated_sweep_data,
1349                 )
1350                 .map_err(|e| {
1351                     error!("UCI JNI: RadarSweepData object array creation failed: {:?}", e);
1352                     e
1353                 })?;
1354 
1355             for (i, sweep_data) in radar_data_rcv_notification.sweep_data.into_iter().enumerate() {
1356                 let vendor_data_jbytearray =
1357                     self.env.byte_array_from_slice(&sweep_data.vendor_specific_data)?;
1358                 let sample_data_jbytearray =
1359                     self.env.byte_array_from_slice(&sweep_data.sample_data)?;
1360                 // Safety: vendor_data_jbytearray instantiated above
1361                 let vendor_data_jobject = unsafe { JObject::from_raw(vendor_data_jbytearray) };
1362                 // Safety: sample_data_jbytearray instantiated above
1363                 let sample_data_jobject = unsafe { JObject::from_raw(sample_data_jbytearray) };
1364                 let sweep_data_jobject = self
1365                     .env
1366                     .new_object(
1367                         radar_sweep_data_jclass,
1368                         sweep_data_sig,
1369                         &[
1370                             JValue::Long(sweep_data.sequence_number as i64),
1371                             JValue::Long(sweep_data.timestamp as i64),
1372                             JValue::Object(vendor_data_jobject),
1373                             JValue::Object(sample_data_jobject),
1374                         ],
1375                     )
1376                     .map_err(|e| {
1377                         error!("UCI JNI: RadarSweepData object creation failed: {:?}", e);
1378                         e
1379                     })?;
1380 
1381                 self.env
1382                     .set_object_array_element(
1383                         radar_sweep_data_jobjectarray,
1384                         i as i32,
1385                         sweep_data_jobject,
1386                     )
1387                     .map_err(|e| {
1388                         error!(
1389                             "UCI JNI: sweep_data_jobject copy into jobjectarray failed: {:?}",
1390                             e
1391                         );
1392                         e
1393                     })?;
1394             }
1395 
1396             let radar_sweep_data_array_jobject =
1397                 // Safety: radar_sweep_data_jobjectarray is safely instantiated above.
1398                 unsafe { JObject::from_raw(radar_sweep_data_jobjectarray) };
1399 
1400             let radar_data_jclass = NotificationManagerAndroid::find_local_class(
1401                 &mut self.jclass_map,
1402                 &self.class_loader_obj,
1403                 &self.env,
1404                 UWB_RADAR_DATA_CLASS,
1405             )?;
1406 
1407             let radar_data_jobject = self
1408                 .env
1409                 .new_object(
1410                     radar_data_jclass,
1411                     "(JIIIII[L".to_owned() + UWB_RADAR_SWEEP_DATA_CLASS + ";)V",
1412                     &[
1413                         // session_token below has already been mapped to session_id by uci layer.
1414                         JValue::Long(radar_data_rcv_notification.session_token as i64),
1415                         JValue::Int(radar_data_rcv_notification.status as i32),
1416                         JValue::Int(radar_data_rcv_notification.radar_data_type as i32),
1417                         JValue::Int(radar_data_rcv_notification.samples_per_sweep as i32),
1418                         JValue::Int(radar_data_rcv_notification.bits_per_sample as i32),
1419                         JValue::Int(radar_data_rcv_notification.sweep_offset as i32),
1420                         JValue::Object(radar_sweep_data_array_jobject),
1421                     ],
1422                 )
1423                 .map_err(|e| {
1424                     error!("UCI JNI: UwbRadarData object creation failed: {:?}", e);
1425                     e
1426                 })?;
1427 
1428             let method_sig = "(L".to_owned() + UWB_RADAR_DATA_CLASS + ";)V";
1429 
1430             self.cached_jni_call(
1431                 "onRadarDataMessageReceived",
1432                 &method_sig,
1433                 &[jvalue::from(JValue::Object(radar_data_jobject))],
1434             )
1435         })
1436         .map_err(|e| {
1437             error!("on_radar_data_rcv_notification error: {:?}", e);
1438             UwbError::ForeignFunctionInterface
1439         })?;
1440         Ok(())
1441     }
1442 
on_rf_test_notification( &mut self, rf_test_notification: RfTestNotification, ) -> UwbResult<()>1443     fn on_rf_test_notification(
1444         &mut self,
1445         rf_test_notification: RfTestNotification,
1446     ) -> UwbResult<()> {
1447         debug!("UCI JNI: RF test notification callback.");
1448         let env = *self.env;
1449         env.with_local_frame(MAX_JAVA_OBJECTS_CAPACITY, || match rf_test_notification {
1450             RfTestNotification::TestPeriodicTxNtf { status, raw_notification_data } => {
1451                 self.on_rf_periodic_tx_notification(u8::from(status), &raw_notification_data)
1452             }
1453             RfTestNotification::TestPerRxNtf(per_rx_data) => {
1454                 self.on_rf_per_rx_notification(per_rx_data)
1455             }
1456         })
1457         .map_err(|e| {
1458             error!("on_rf_test_notification error: {:?}", e);
1459             UwbError::ForeignFunctionInterface
1460         })?;
1461         Ok(())
1462     }
1463 }
1464 pub(crate) struct NotificationManagerAndroidBuilder {
1465     pub chip_id: String,
1466     pub vm: &'static Arc<JavaVM>,
1467     pub class_loader_obj: GlobalRef,
1468     pub callback_obj: GlobalRef,
1469 }
1470 
1471 impl NotificationManagerBuilder for NotificationManagerAndroidBuilder {
1472     type NotificationManager = NotificationManagerAndroid;
1473 
build(self) -> Option<Self::NotificationManager>1474     fn build(self) -> Option<Self::NotificationManager> {
1475         if let Ok(env) = self.vm.attach_current_thread() {
1476             Some(NotificationManagerAndroid {
1477                 chip_id: self.chip_id,
1478                 env,
1479                 class_loader_obj: self.class_loader_obj,
1480                 callback_obj: self.callback_obj,
1481                 jmethod_id_map: HashMap::new(),
1482                 jclass_map: HashMap::new(),
1483             })
1484         } else {
1485             None
1486         }
1487     }
1488 }
1489 
1490 #[cfg(test)]
1491 mod tests {
1492     use super::*;
1493 
1494     #[test]
test_get_two_way_ranigng_measurement_from_short_address_two_way_ranging_measurement()1495     fn test_get_two_way_ranigng_measurement_from_short_address_two_way_ranging_measurement() {
1496         let short_address_measurement = ShortAddressTwoWayRangingMeasurement {
1497             mac_address: 0x1234,
1498             status: StatusCode::UciStatusOk,
1499             nlos: 0,
1500             distance: 1,
1501             aoa_azimuth: 2,
1502             aoa_azimuth_fom: 3,
1503             aoa_elevation: 4,
1504             aoa_elevation_fom: 5,
1505             aoa_destination_azimuth: 6,
1506             aoa_destination_azimuth_fom: 7,
1507             aoa_destination_elevation: 8,
1508             aoa_destination_elevation_fom: 9,
1509             slot_index: 10,
1510             rssi: 11,
1511         };
1512         let measurement = TwoWayRangingMeasurement::from(short_address_measurement.clone());
1513         assert_eq!(
1514             measurement.mac_address,
1515             MacAddress::Short(short_address_measurement.mac_address)
1516         );
1517         assert_eq!(measurement.status, short_address_measurement.status);
1518         assert_eq!(measurement.nlos, short_address_measurement.nlos);
1519         assert_eq!(measurement.distance, short_address_measurement.distance);
1520         assert_eq!(measurement.aoa_azimuth, short_address_measurement.aoa_azimuth);
1521         assert_eq!(measurement.aoa_azimuth_fom, short_address_measurement.aoa_azimuth_fom);
1522         assert_eq!(measurement.aoa_elevation, short_address_measurement.aoa_elevation);
1523         assert_eq!(measurement.aoa_elevation_fom, short_address_measurement.aoa_elevation_fom);
1524         assert_eq!(
1525             measurement.aoa_destination_azimuth,
1526             short_address_measurement.aoa_destination_azimuth
1527         );
1528         assert_eq!(
1529             measurement.aoa_destination_azimuth_fom,
1530             short_address_measurement.aoa_destination_azimuth_fom
1531         );
1532         assert_eq!(
1533             measurement.aoa_destination_elevation,
1534             short_address_measurement.aoa_destination_elevation
1535         );
1536         assert_eq!(
1537             measurement.aoa_destination_elevation_fom,
1538             short_address_measurement.aoa_destination_elevation_fom
1539         );
1540         assert_eq!(measurement.slot_index, short_address_measurement.slot_index);
1541         assert_eq!(measurement.rssi, short_address_measurement.rssi);
1542     }
1543 
1544     #[test]
test_get_two_way_ranigng_measurement_from_extended_address_two_way_ranging_measurement()1545     fn test_get_two_way_ranigng_measurement_from_extended_address_two_way_ranging_measurement() {
1546         let extended_address_measurement = ExtendedAddressTwoWayRangingMeasurement {
1547             mac_address: 0x1234_5678,
1548             status: StatusCode::UciStatusOk,
1549             nlos: 0,
1550             distance: 1,
1551             aoa_azimuth: 2,
1552             aoa_azimuth_fom: 3,
1553             aoa_elevation: 4,
1554             aoa_elevation_fom: 5,
1555             aoa_destination_azimuth: 6,
1556             aoa_destination_azimuth_fom: 7,
1557             aoa_destination_elevation: 8,
1558             aoa_destination_elevation_fom: 9,
1559             slot_index: 10,
1560             rssi: 11,
1561         };
1562         let measurement = TwoWayRangingMeasurement::from(extended_address_measurement.clone());
1563         assert_eq!(
1564             measurement.mac_address,
1565             MacAddress::Extended(extended_address_measurement.mac_address)
1566         );
1567         assert_eq!(measurement.status, extended_address_measurement.status);
1568         assert_eq!(measurement.nlos, extended_address_measurement.nlos);
1569         assert_eq!(measurement.distance, extended_address_measurement.distance);
1570         assert_eq!(measurement.aoa_azimuth, extended_address_measurement.aoa_azimuth);
1571         assert_eq!(measurement.aoa_azimuth_fom, extended_address_measurement.aoa_azimuth_fom);
1572         assert_eq!(measurement.aoa_elevation, extended_address_measurement.aoa_elevation);
1573         assert_eq!(measurement.aoa_elevation_fom, extended_address_measurement.aoa_elevation_fom);
1574         assert_eq!(
1575             measurement.aoa_destination_azimuth,
1576             extended_address_measurement.aoa_destination_azimuth
1577         );
1578         assert_eq!(
1579             measurement.aoa_destination_azimuth_fom,
1580             extended_address_measurement.aoa_destination_azimuth_fom
1581         );
1582         assert_eq!(
1583             measurement.aoa_destination_elevation,
1584             extended_address_measurement.aoa_destination_elevation
1585         );
1586         assert_eq!(
1587             measurement.aoa_destination_elevation_fom,
1588             extended_address_measurement.aoa_destination_elevation_fom
1589         );
1590         assert_eq!(measurement.slot_index, extended_address_measurement.slot_index);
1591         assert_eq!(measurement.rssi, extended_address_measurement.rssi);
1592     }
1593 
1594     #[test]
test_get_owr_aoa_ranging_measurement_from_short_address_measurement()1595     fn test_get_owr_aoa_ranging_measurement_from_short_address_measurement() {
1596         let short_address_measurement = ShortAddressOwrAoaRangingMeasurement {
1597             mac_address: 0x1234,
1598             status: StatusCode::UciStatusOk,
1599             nlos: 0,
1600             frame_sequence_number: 1,
1601             block_index: 2,
1602             aoa_azimuth: 3,
1603             aoa_azimuth_fom: 4,
1604             aoa_elevation: 5,
1605             aoa_elevation_fom: 6,
1606         };
1607         let measurement = OwrAoaRangingMeasurement::from(short_address_measurement.clone());
1608         assert_eq!(
1609             measurement.mac_address,
1610             MacAddress::Short(short_address_measurement.mac_address)
1611         );
1612         assert_eq!(measurement.status, short_address_measurement.status);
1613         assert_eq!(measurement.nlos, short_address_measurement.nlos);
1614         assert_eq!(
1615             measurement.frame_sequence_number,
1616             short_address_measurement.frame_sequence_number
1617         );
1618         assert_eq!(measurement.block_index, short_address_measurement.block_index);
1619         assert_eq!(measurement.aoa_azimuth, short_address_measurement.aoa_azimuth);
1620         assert_eq!(measurement.aoa_azimuth_fom, short_address_measurement.aoa_azimuth_fom);
1621         assert_eq!(measurement.aoa_elevation, short_address_measurement.aoa_elevation);
1622         assert_eq!(measurement.aoa_elevation_fom, short_address_measurement.aoa_elevation_fom);
1623     }
1624 
1625     #[test]
test_get_owr_aoa_ranging_measurement_from_extended_address_measurement()1626     fn test_get_owr_aoa_ranging_measurement_from_extended_address_measurement() {
1627         let extended_address_measurement = ExtendedAddressOwrAoaRangingMeasurement {
1628             mac_address: 0x1234_5678,
1629             status: StatusCode::UciStatusOk,
1630             nlos: 0,
1631             frame_sequence_number: 1,
1632             block_index: 2,
1633             aoa_azimuth: 3,
1634             aoa_azimuth_fom: 4,
1635             aoa_elevation: 5,
1636             aoa_elevation_fom: 6,
1637         };
1638         let measurement = OwrAoaRangingMeasurement::from(extended_address_measurement.clone());
1639         assert_eq!(
1640             measurement.mac_address,
1641             MacAddress::Extended(extended_address_measurement.mac_address)
1642         );
1643         assert_eq!(measurement.status, extended_address_measurement.status);
1644         assert_eq!(measurement.nlos, extended_address_measurement.nlos);
1645         assert_eq!(
1646             measurement.frame_sequence_number,
1647             extended_address_measurement.frame_sequence_number
1648         );
1649         assert_eq!(measurement.block_index, extended_address_measurement.block_index);
1650         assert_eq!(measurement.aoa_azimuth, extended_address_measurement.aoa_azimuth);
1651         assert_eq!(measurement.aoa_azimuth_fom, extended_address_measurement.aoa_azimuth_fom);
1652         assert_eq!(measurement.aoa_elevation, extended_address_measurement.aoa_elevation);
1653         assert_eq!(measurement.aoa_elevation_fom, extended_address_measurement.aoa_elevation_fom);
1654     }
1655 
1656     #[test]
test_get_dl_tdoa_ranging_measurement_from_short_address_measurement()1657     fn test_get_dl_tdoa_ranging_measurement_from_short_address_measurement() {
1658         let bytes = [
1659             // All Fields in Little Endian (LE)
1660             0x0a, 0x01, 0x33, 0x05, // 2(Mac address), Status, Message Type
1661             0x53, 0x05, 0x02, 0x05, // 2(Message control), 2(Block Index)
1662             0x07, 0x09, 0x0a, 0x01, // Round Index, NLoS, 2(AoA Azimuth)
1663             0x02, 0x05, 0x07, 0x09, // AoA Azimuth FOM, 2(AoA Elevation), AoA Elevation FOM
1664             0x0a, 0x01, 0x02, 0x05, // RSSI, 3(Tx Timestamp..)
1665             0x07, 0x09, 0x0a, 0x01, // 4(Tx Timestamp..)
1666             0x02, 0x05, 0x07, 0x09, // Tx Timestamp, 3(Rx Timestamp..)
1667             0x05, 0x07, 0x09, 0x0a, // 2(Rx Timestamp), 2(Anchor Cfo)
1668             0x01, 0x02, 0x05, 0x07, // 2(Cfo), 2(Initiator Reply Time..)
1669             0x09, 0x05, 0x07, 0x09, // 2(Initiator Reply Time), 2(Responder Reply Time..)
1670             0x0a, 0x01, 0x02, 0x05, // 2(Responder Reply Time), 2(Initiator-Responder ToF)
1671             0x07, 0x09, 0x07, 0x09, // 4(Anchor Location..)
1672             0x05, 0x07, 0x09, 0x0a, // 4(Anchor Location..)
1673             0x01, 0x02, 0x05, 0x07, // 2(Anchor Location..), 2(Active Ranging Rounds..)
1674             0x09, 0x0a, 0x01, 0x02, // 4(Active Ranging Rounds..)
1675             0x05, 0x07, 0x09, 0x05, // 4(Active Ranging Rounds)
1676         ];
1677         let short_address_measurement_vec =
1678             ShortAddressDlTdoaRangingMeasurement::parse(&bytes, 1).unwrap();
1679         let short_address_measurement = &short_address_measurement_vec[0];
1680         let measurement = DlTdoaRangingMeasurement::from(short_address_measurement.clone());
1681         assert_eq!(
1682             measurement.mac_address,
1683             MacAddress::Short(short_address_measurement.mac_address)
1684         );
1685         assert_eq!(measurement.status, short_address_measurement.measurement.status);
1686         assert_eq!(measurement.message_type, short_address_measurement.measurement.message_type);
1687         assert_eq!(
1688             measurement.message_control,
1689             short_address_measurement.measurement.message_control
1690         );
1691         assert_eq!(measurement.block_index, short_address_measurement.measurement.block_index);
1692         assert_eq!(measurement.round_index, short_address_measurement.measurement.round_index);
1693         assert_eq!(measurement.nlos, short_address_measurement.measurement.nlos);
1694         assert_eq!(measurement.aoa_azimuth, short_address_measurement.measurement.aoa_azimuth);
1695         assert_eq!(
1696             measurement.aoa_azimuth_fom,
1697             short_address_measurement.measurement.aoa_azimuth_fom
1698         );
1699         assert_eq!(measurement.aoa_elevation, short_address_measurement.measurement.aoa_elevation);
1700         assert_eq!(
1701             measurement.aoa_elevation_fom,
1702             short_address_measurement.measurement.aoa_elevation_fom
1703         );
1704         assert_eq!(measurement.rssi, short_address_measurement.measurement.rssi);
1705         assert_eq!(measurement.tx_timestamp, short_address_measurement.measurement.tx_timestamp);
1706         assert_eq!(measurement.rx_timestamp, short_address_measurement.measurement.rx_timestamp);
1707         assert_eq!(measurement.anchor_cfo, short_address_measurement.measurement.anchor_cfo);
1708         assert_eq!(measurement.cfo, short_address_measurement.measurement.cfo);
1709         assert_eq!(
1710             measurement.initiator_reply_time,
1711             short_address_measurement.measurement.initiator_reply_time
1712         );
1713         assert_eq!(
1714             measurement.responder_reply_time,
1715             short_address_measurement.measurement.responder_reply_time
1716         );
1717         assert_eq!(
1718             measurement.initiator_responder_tof,
1719             short_address_measurement.measurement.initiator_responder_tof
1720         );
1721         assert_eq!(
1722             measurement.dt_anchor_location,
1723             short_address_measurement.measurement.dt_anchor_location
1724         );
1725         assert_eq!(
1726             measurement.ranging_rounds,
1727             short_address_measurement.measurement.ranging_rounds
1728         );
1729     }
1730 
1731     #[test]
test_get_dl_tdoa_ranging_measurement_from_extended_address_measurement()1732     fn test_get_dl_tdoa_ranging_measurement_from_extended_address_measurement() {
1733         let bytes = [
1734             // All Fields in Little Endian (LE)
1735             0x0a, 0x01, 0x33, 0x05, // 4(Mac address..)
1736             0x33, 0x05, 0x02, 0x05, // 4(Mac address)
1737             0x07, 0x09, 0x0a, 0x01, // Status, Message Type, 2(Message control),
1738             0x02, 0x05, 0x07, 0x09, // 2(Block Index), Round Index, NLoS,
1739             0x0a, 0x01, 0x02, 0x05, // 2(AoA Azimuth), AoA Azimuth FOM, 1(AoA Elevation..)
1740             0x07, 0x09, 0x0a, // 1(AoA Elevation), AoA Elevation FOM, RSSI,
1741             0x01, 0x02, 0x05, 0x07, // 4(Tx Timestamp..)
1742             0x09, 0x05, 0x07, 0x09, // 4(Tx Timestamp),
1743             0x0a, 0x01, 0x02, 0x05, // 4(Rx Timestamp..)
1744             0x07, 0x09, 0x05, 0x07, // 4(Rx Timestamp)
1745             0x09, 0x0a, 0x01, 0x02, // 2(Anchor Cfo), 2(Cfo),
1746             0x05, 0x07, 0x09, 0x05, // 4(Initiator Reply Time)
1747             0x07, 0x09, 0x0a, 0x01, // 4(Responder Reply Time),
1748             0x02, 0x05, 0x02, 0x05, // 2(Initiator-Responder ToF), 2(Active Ranging Rounds)
1749         ];
1750         let extended_address_measurement_vec =
1751             ExtendedAddressDlTdoaRangingMeasurement::parse(&bytes, 1).unwrap();
1752         let extended_address_measurement = &extended_address_measurement_vec[0];
1753 
1754         let measurement = DlTdoaRangingMeasurement::from(extended_address_measurement.clone());
1755         assert_eq!(
1756             measurement.mac_address,
1757             MacAddress::Extended(extended_address_measurement.mac_address)
1758         );
1759         assert_eq!(measurement.status, extended_address_measurement.measurement.status);
1760         assert_eq!(measurement.message_type, extended_address_measurement.measurement.message_type);
1761         assert_eq!(
1762             measurement.message_control,
1763             extended_address_measurement.measurement.message_control
1764         );
1765         assert_eq!(measurement.block_index, extended_address_measurement.measurement.block_index);
1766         assert_eq!(measurement.round_index, extended_address_measurement.measurement.round_index);
1767         assert_eq!(measurement.nlos, extended_address_measurement.measurement.nlos);
1768         assert_eq!(measurement.aoa_azimuth, extended_address_measurement.measurement.aoa_azimuth);
1769         assert_eq!(
1770             measurement.aoa_azimuth_fom,
1771             extended_address_measurement.measurement.aoa_azimuth_fom
1772         );
1773         assert_eq!(
1774             measurement.aoa_elevation,
1775             extended_address_measurement.measurement.aoa_elevation
1776         );
1777         assert_eq!(
1778             measurement.aoa_elevation_fom,
1779             extended_address_measurement.measurement.aoa_elevation_fom
1780         );
1781         assert_eq!(measurement.rssi, extended_address_measurement.measurement.rssi);
1782         assert_eq!(measurement.tx_timestamp, extended_address_measurement.measurement.tx_timestamp);
1783         assert_eq!(measurement.rx_timestamp, extended_address_measurement.measurement.rx_timestamp);
1784         assert_eq!(measurement.anchor_cfo, extended_address_measurement.measurement.anchor_cfo);
1785         assert_eq!(measurement.cfo, extended_address_measurement.measurement.cfo);
1786         assert_eq!(
1787             measurement.initiator_reply_time,
1788             extended_address_measurement.measurement.initiator_reply_time
1789         );
1790         assert_eq!(
1791             measurement.responder_reply_time,
1792             extended_address_measurement.measurement.responder_reply_time
1793         );
1794         assert_eq!(
1795             measurement.initiator_responder_tof,
1796             extended_address_measurement.measurement.initiator_responder_tof
1797         );
1798         assert_eq!(
1799             measurement.dt_anchor_location,
1800             extended_address_measurement.measurement.dt_anchor_location
1801         );
1802         assert_eq!(
1803             measurement.ranging_rounds,
1804             extended_address_measurement.measurement.ranging_rounds
1805         );
1806     }
1807 }
1808