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