• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 use jni::errors::{Error, JniError, Result};
18 use jni::objects::{GlobalRef, JClass, JObject, JValue, JValue::Void};
19 use jni::signature::JavaType;
20 use jni::sys::jobjectArray;
21 use jni::{AttachGuard, JNIEnv, JavaVM};
22 use log::error;
23 use num_traits::ToPrimitive;
24 use std::convert::TryInto;
25 use std::vec::Vec;
26 use uwb_uci_packets::{
27     DeviceStatusNtfPacket, ExtendedAddressTwoWayRangingMeasurement,
28     ExtendedMacTwoWayRangeDataNtfPacket, GenericErrorPacket, Packet, RangeDataNtfPacket,
29     SessionStatusNtfPacket, SessionUpdateControllerMulticastListNtfPacket,
30     ShortAddressTwoWayRangingMeasurement, ShortMacTwoWayRangeDataNtfPacket, UciNotificationChild,
31     UciNotificationPacket, UciVendor_9_NotificationChild, UciVendor_A_NotificationChild,
32     UciVendor_B_NotificationChild, UciVendor_E_NotificationChild, UciVendor_F_NotificationChild,
33 };
34 
35 const UWB_RANGING_DATA_CLASS: &str = "com/android/server/uwb/data/UwbRangingData";
36 const UWB_TWO_WAY_MEASUREMENT_CLASS: &str = "com/android/server/uwb/data/UwbTwoWayMeasurement";
37 const MULTICAST_LIST_UPDATE_STATUS_CLASS: &str =
38     "com/android/server/uwb/data/UwbMulticastListUpdateStatus";
39 const SHORT_MAC_ADDRESS_LEN: usize = 2;
40 const EXTENDED_MAC_ADDRESS_LEN: usize = 8;
41 
42 // TODO: Reconsider the best way to cache the JNIEnv.  We currently attach and detach for every
43 // call, which the documentation warns could be expensive.  We could attach the thread permanently,
44 // but that would not allow us to detach when we drop this structure.  We could cache the
45 // AttachGuard in the EventManager, but it is not Send, so we should wait to see how this is used
46 // and how expensive the current approach is.  We can call JavaVM's get_env method if we're already
47 // attached.
48 
49 // TODO: We could consider caching the method ids rather than recomputing them each time at the cost
50 // of less safety.
51 
52 pub trait EventManager {
device_status_notification_received(&self, data: DeviceStatusNtfPacket) -> Result<()>53     fn device_status_notification_received(&self, data: DeviceStatusNtfPacket) -> Result<()>;
core_generic_error_notification_received(&self, data: GenericErrorPacket) -> Result<()>54     fn core_generic_error_notification_received(&self, data: GenericErrorPacket) -> Result<()>;
session_status_notification_received(&self, data: SessionStatusNtfPacket) -> Result<()>55     fn session_status_notification_received(&self, data: SessionStatusNtfPacket) -> Result<()>;
short_range_data_notification_received( &self, data: ShortMacTwoWayRangeDataNtfPacket, ) -> Result<()>56     fn short_range_data_notification_received(
57         &self,
58         data: ShortMacTwoWayRangeDataNtfPacket,
59     ) -> Result<()>;
extended_range_data_notification_received( &self, data: ExtendedMacTwoWayRangeDataNtfPacket, ) -> Result<()>60     fn extended_range_data_notification_received(
61         &self,
62         data: ExtendedMacTwoWayRangeDataNtfPacket,
63     ) -> Result<()>;
session_update_controller_multicast_list_notification_received( &self, data: SessionUpdateControllerMulticastListNtfPacket, ) -> Result<()>64     fn session_update_controller_multicast_list_notification_received(
65         &self,
66         data: SessionUpdateControllerMulticastListNtfPacket,
67     ) -> Result<()>;
vendor_uci_notification_received(&self, data: UciNotificationPacket) -> Result<()>68     fn vendor_uci_notification_received(&self, data: UciNotificationPacket) -> Result<()>;
69 }
70 
71 // Manages calling Java callbacks through the JNI.
72 pub struct EventManagerImpl {
73     jvm: JavaVM,
74     obj: GlobalRef,
75     // cache used to lookup uwb classes in callback.
76     class_loader_obj: GlobalRef,
77 }
78 
79 impl EventManager for EventManagerImpl {
device_status_notification_received(&self, data: DeviceStatusNtfPacket) -> Result<()>80     fn device_status_notification_received(&self, data: DeviceStatusNtfPacket) -> Result<()> {
81         let env = self.jvm.attach_current_thread()?;
82         let result = self.handle_device_status_notification_received(&env, data);
83         self.clear_exception(env);
84         result
85     }
86 
core_generic_error_notification_received(&self, data: GenericErrorPacket) -> Result<()>87     fn core_generic_error_notification_received(&self, data: GenericErrorPacket) -> Result<()> {
88         let env = self.jvm.attach_current_thread()?;
89         let result = self.handle_core_generic_error_notification_received(&env, data);
90         self.clear_exception(env);
91         result
92     }
93 
session_status_notification_received(&self, data: SessionStatusNtfPacket) -> Result<()>94     fn session_status_notification_received(&self, data: SessionStatusNtfPacket) -> Result<()> {
95         let env = self.jvm.attach_current_thread()?;
96         let result = self.handle_session_status_notification_received(&env, data);
97         self.clear_exception(env);
98         result
99     }
100 
short_range_data_notification_received( &self, data: ShortMacTwoWayRangeDataNtfPacket, ) -> Result<()>101     fn short_range_data_notification_received(
102         &self,
103         data: ShortMacTwoWayRangeDataNtfPacket,
104     ) -> Result<()> {
105         let env = self.jvm.attach_current_thread()?;
106         let result = self.handle_short_range_data_notification_received(&env, data);
107         self.clear_exception(env);
108         result
109     }
110 
extended_range_data_notification_received( &self, data: ExtendedMacTwoWayRangeDataNtfPacket, ) -> Result<()>111     fn extended_range_data_notification_received(
112         &self,
113         data: ExtendedMacTwoWayRangeDataNtfPacket,
114     ) -> Result<()> {
115         let env = self.jvm.attach_current_thread()?;
116         let result = self.handle_extended_range_data_notification_received(&env, data);
117         self.clear_exception(env);
118         result
119     }
120 
session_update_controller_multicast_list_notification_received( &self, data: SessionUpdateControllerMulticastListNtfPacket, ) -> Result<()>121     fn session_update_controller_multicast_list_notification_received(
122         &self,
123         data: SessionUpdateControllerMulticastListNtfPacket,
124     ) -> Result<()> {
125         let env = self.jvm.attach_current_thread()?;
126         let result =
127             self.handle_session_update_controller_multicast_list_notification_received(&env, data);
128         self.clear_exception(env);
129         result
130     }
vendor_uci_notification_received(&self, data: UciNotificationPacket) -> Result<()>131     fn vendor_uci_notification_received(&self, data: UciNotificationPacket) -> Result<()> {
132         let env = self.jvm.attach_current_thread()?;
133         let result = self.handle_vendor_uci_notification_received(&env, data);
134         self.clear_exception(env);
135         result
136     }
137 }
138 
139 impl EventManagerImpl {
140     /// Creates a new EventManagerImpl.
new(env: JNIEnv, obj: JObject) -> Result<Self>141     pub fn new(env: JNIEnv, obj: JObject) -> Result<Self> {
142         let jvm = env.get_java_vm()?;
143         let obj = env.new_global_ref(obj)?;
144         let class_loader_obj = EventManagerImpl::get_classloader_obj(&env)?;
145         let class_loader_obj = env.new_global_ref(class_loader_obj)?;
146         Ok(EventManagerImpl { jvm, obj, class_loader_obj })
147     }
148 
get_classloader_obj<'a>(env: &'a JNIEnv) -> Result<JObject<'a>>149     fn get_classloader_obj<'a>(env: &'a JNIEnv) -> Result<JObject<'a>> {
150         // Use UwbRangingData class to find the classloader used by the java service.
151         let ranging_data_class = env.find_class(&UWB_RANGING_DATA_CLASS)?;
152         let ranging_data_class_class = env.get_object_class(ranging_data_class)?;
153         let get_class_loader_method = env.get_method_id(
154             ranging_data_class_class,
155             "getClassLoader",
156             "()Ljava/lang/ClassLoader;",
157         )?;
158         let class_loader = env.call_method_unchecked(
159             ranging_data_class,
160             get_class_loader_method,
161             JavaType::Object("java/lang/ClassLoader".into()),
162             &[Void],
163         )?;
164         class_loader.l()
165     }
166 
find_class<'a>(&'a self, env: &'a JNIEnv, class_name: &'a str) -> Result<JClass<'a>>167     fn find_class<'a>(&'a self, env: &'a JNIEnv, class_name: &'a str) -> Result<JClass<'a>> {
168         let class_value = env.call_method(
169             self.class_loader_obj.as_obj(),
170             "findClass",
171             "(Ljava/lang/String;)Ljava/lang/Class;",
172             &[JValue::Object(JObject::from(env.new_string(class_name)?))],
173         )?;
174         class_value.l().map(JClass::from)
175     }
176 
handle_device_status_notification_received( &self, env: &JNIEnv, data: DeviceStatusNtfPacket, ) -> Result<()>177     fn handle_device_status_notification_received(
178         &self,
179         env: &JNIEnv,
180         data: DeviceStatusNtfPacket,
181     ) -> Result<()> {
182         let state = data.get_device_state().to_i32().ok_or_else(|| {
183             error!("Failed converting device_state to i32");
184             Error::JniCall(JniError::Unknown)
185         })?;
186         env.call_method(
187             self.obj.as_obj(),
188             "onDeviceStatusNotificationReceived",
189             "(I)V",
190             &[JValue::Int(state)],
191         )
192         .map(|_| ()) // drop void method return
193     }
194 
handle_session_status_notification_received( &self, env: &JNIEnv, data: SessionStatusNtfPacket, ) -> Result<()>195     fn handle_session_status_notification_received(
196         &self,
197         env: &JNIEnv,
198         data: SessionStatusNtfPacket,
199     ) -> Result<()> {
200         let session_id = data.get_session_id().to_i64().ok_or_else(|| {
201             error!("Failed converting session_id to i64");
202             Error::JniCall(JniError::Unknown)
203         })?;
204         let state = data.get_session_state().to_i32().ok_or_else(|| {
205             error!("Failed converting session_state to i32");
206             Error::JniCall(JniError::Unknown)
207         })?;
208         let reason_code = data.get_reason_code().to_i32().ok_or_else(|| {
209             error!("Failed converting reason_code to i32");
210             Error::JniCall(JniError::Unknown)
211         })?;
212         env.call_method(
213             self.obj.as_obj(),
214             "onSessionStatusNotificationReceived",
215             "(JII)V",
216             &[JValue::Long(session_id), JValue::Int(state), JValue::Int(reason_code)],
217         )
218         .map(|_| ()) // drop void method return
219     }
220 
handle_core_generic_error_notification_received( &self, env: &JNIEnv, data: GenericErrorPacket, ) -> Result<()>221     fn handle_core_generic_error_notification_received(
222         &self,
223         env: &JNIEnv,
224         data: GenericErrorPacket,
225     ) -> Result<()> {
226         let status = data.get_status().to_i32().ok_or_else(|| {
227             error!("Failed converting status to i32");
228             Error::JniCall(JniError::Unknown)
229         })?;
230         env.call_method(
231             self.obj.as_obj(),
232             "onCoreGenericErrorNotificationReceived",
233             "(I)V",
234             &[JValue::Int(status)],
235         )
236         .map(|_| ()) // drop void method return
237     }
238 
create_zeroed_two_way_measurement_java<'a>( env: &'a JNIEnv, two_way_measurement_class: JClass, mac_address_java: jobjectArray, ) -> Result<JObject<'a>>239     fn create_zeroed_two_way_measurement_java<'a>(
240         env: &'a JNIEnv,
241         two_way_measurement_class: JClass,
242         mac_address_java: jobjectArray,
243     ) -> Result<JObject<'a>> {
244         env.new_object(
245             two_way_measurement_class,
246             "([BIIIIIIIIIIII)V",
247             &[
248                 JValue::Object(JObject::from(mac_address_java)),
249                 JValue::Int(0),
250                 JValue::Int(0),
251                 JValue::Int(0),
252                 JValue::Int(0),
253                 JValue::Int(0),
254                 JValue::Int(0),
255                 JValue::Int(0),
256                 JValue::Int(0),
257                 JValue::Int(0),
258                 JValue::Int(0),
259                 JValue::Int(0),
260                 JValue::Int(0),
261             ],
262         )
263     }
264 
create_short_mac_two_way_measurement_java<'a>( env: &'a JNIEnv, two_way_measurement_class: JClass, two_way_measurement: &'a ShortAddressTwoWayRangingMeasurement, ) -> Result<JObject<'a>>265     fn create_short_mac_two_way_measurement_java<'a>(
266         env: &'a JNIEnv,
267         two_way_measurement_class: JClass,
268         two_way_measurement: &'a ShortAddressTwoWayRangingMeasurement,
269     ) -> Result<JObject<'a>> {
270         let mac_address_arr = two_way_measurement.mac_address.to_ne_bytes();
271         let mac_address_java =
272             env.new_byte_array(SHORT_MAC_ADDRESS_LEN.to_i32().ok_or_else(|| {
273                 error!("Failed converting mac address len to i32");
274                 Error::JniCall(JniError::Unknown)
275             })?)?;
276         // Convert from [u8] to [i8] since java does not support unsigned byte.
277         let mac_address_arr_i8 = mac_address_arr.map(|x| x as i8);
278         env.set_byte_array_region(mac_address_java, 0, &mac_address_arr_i8)?;
279         env.new_object(
280             two_way_measurement_class,
281             "([BIIIIIIIIIIII)V",
282             &[
283                 JValue::Object(JObject::from(mac_address_java)),
284                 JValue::Int(two_way_measurement.status.to_i32().ok_or_else(|| {
285                     error!("Failed converting status to i32");
286                     Error::JniCall(JniError::Unknown)
287                 })?),
288                 JValue::Int(two_way_measurement.nlos.to_i32().ok_or_else(|| {
289                     error!("Failed converting nlos to i32");
290                     Error::JniCall(JniError::Unknown)
291                 })?),
292                 JValue::Int(two_way_measurement.distance.to_i32().ok_or_else(|| {
293                     error!("Failed converting distance to i32");
294                     Error::JniCall(JniError::Unknown)
295                 })?),
296                 JValue::Int(two_way_measurement.aoa_azimuth.to_i32().ok_or_else(|| {
297                     error!("Failed converting aoa azimuth to i32");
298                     Error::JniCall(JniError::Unknown)
299                 })?),
300                 JValue::Int(two_way_measurement.aoa_azimuth_fom.to_i32().ok_or_else(|| {
301                     error!("Failed converting aoa azimuth fom to i32");
302                     Error::JniCall(JniError::Unknown)
303                 })?),
304                 JValue::Int(two_way_measurement.aoa_elevation.to_i32().ok_or_else(|| {
305                     error!("Failed converting aoa elevation to i32");
306                     Error::JniCall(JniError::Unknown)
307                 })?),
308                 JValue::Int(two_way_measurement.aoa_elevation_fom.to_i32().ok_or_else(|| {
309                     error!("Failed converting aoa elevation fom to i32");
310                     Error::JniCall(JniError::Unknown)
311                 })?),
312                 JValue::Int(two_way_measurement.aoa_destination_azimuth.to_i32().ok_or_else(
313                     || {
314                         error!("Failed converting dest aoa azimuth to i32");
315                         Error::JniCall(JniError::Unknown)
316                     },
317                 )?),
318                 JValue::Int(two_way_measurement.aoa_destination_azimuth_fom.to_i32().ok_or_else(
319                     || {
320                         error!("Failed converting dest aoa azimuth fom to i32");
321                         Error::JniCall(JniError::Unknown)
322                     },
323                 )?),
324                 JValue::Int(two_way_measurement.aoa_destination_elevation.to_i32().ok_or_else(
325                     || {
326                         error!("Failed converting dest aoa elevation to i32");
327                         Error::JniCall(JniError::Unknown)
328                     },
329                 )?),
330                 JValue::Int(
331                     two_way_measurement.aoa_destination_elevation_fom.to_i32().ok_or_else(
332                         || {
333                             error!("Failed converting dest aoa elevation azimuth to i32");
334                             Error::JniCall(JniError::Unknown)
335                         },
336                     )?,
337                 ),
338                 JValue::Int(two_way_measurement.slot_index.to_i32().ok_or_else(|| {
339                     error!("Failed converting slot index to i32");
340                     Error::JniCall(JniError::Unknown)
341                 })?),
342             ],
343         )
344     }
345 
create_extended_mac_two_way_measurement_java<'a>( env: &'a JNIEnv, two_way_measurement_class: JClass, two_way_measurement: &'a ExtendedAddressTwoWayRangingMeasurement, ) -> Result<JObject<'a>>346     fn create_extended_mac_two_way_measurement_java<'a>(
347         env: &'a JNIEnv,
348         two_way_measurement_class: JClass,
349         two_way_measurement: &'a ExtendedAddressTwoWayRangingMeasurement,
350     ) -> Result<JObject<'a>> {
351         let mac_address_arr = two_way_measurement.mac_address.to_ne_bytes();
352         let mac_address_java =
353             env.new_byte_array(EXTENDED_MAC_ADDRESS_LEN.to_i32().ok_or_else(|| {
354                 error!("Failed converting mac address len to i32");
355                 Error::JniCall(JniError::Unknown)
356             })?)?;
357         // Convert from [u8] to [i8] since java does not support unsigned byte.
358         let mac_address_arr_i8 = mac_address_arr.map(|x| x as i8);
359         env.set_byte_array_region(mac_address_java, 0, &mac_address_arr_i8)?;
360         env.new_object(
361             two_way_measurement_class,
362             "([BIIIIIIIIIIII)V",
363             &[
364                 JValue::Object(JObject::from(mac_address_java)),
365                 JValue::Int(two_way_measurement.status.to_i32().ok_or_else(|| {
366                     error!("Failed converting status to i32");
367                     Error::JniCall(JniError::Unknown)
368                 })?),
369                 JValue::Int(two_way_measurement.nlos.to_i32().ok_or_else(|| {
370                     error!("Failed converting nlos to i32");
371                     Error::JniCall(JniError::Unknown)
372                 })?),
373                 JValue::Int(two_way_measurement.distance.to_i32().ok_or_else(|| {
374                     error!("Failed converting distance to i32");
375                     Error::JniCall(JniError::Unknown)
376                 })?),
377                 JValue::Int(two_way_measurement.aoa_azimuth.to_i32().ok_or_else(|| {
378                     error!("Failed converting aoa azimuth to i32");
379                     Error::JniCall(JniError::Unknown)
380                 })?),
381                 JValue::Int(two_way_measurement.aoa_azimuth_fom.to_i32().ok_or_else(|| {
382                     error!("Failed converting aoa azimuth fom to i32");
383                     Error::JniCall(JniError::Unknown)
384                 })?),
385                 JValue::Int(two_way_measurement.aoa_elevation.to_i32().ok_or_else(|| {
386                     error!("Failed converting aoa elevation to i32");
387                     Error::JniCall(JniError::Unknown)
388                 })?),
389                 JValue::Int(two_way_measurement.aoa_elevation_fom.to_i32().ok_or_else(|| {
390                     error!("Failed converting aoa elevation fom to i32");
391                     Error::JniCall(JniError::Unknown)
392                 })?),
393                 JValue::Int(two_way_measurement.aoa_destination_azimuth.to_i32().ok_or_else(
394                     || {
395                         error!("Failed converting dest aoa azimuth to i32");
396                         Error::JniCall(JniError::Unknown)
397                     },
398                 )?),
399                 JValue::Int(two_way_measurement.aoa_destination_azimuth_fom.to_i32().ok_or_else(
400                     || {
401                         error!("Failed converting dest aoa azimuth fom to i32");
402                         Error::JniCall(JniError::Unknown)
403                     },
404                 )?),
405                 JValue::Int(two_way_measurement.aoa_destination_elevation.to_i32().ok_or_else(
406                     || {
407                         error!("Failed converting dest aoa elevation to i32");
408                         Error::JniCall(JniError::Unknown)
409                     },
410                 )?),
411                 JValue::Int(
412                     two_way_measurement.aoa_destination_elevation_fom.to_i32().ok_or_else(
413                         || {
414                             error!("Failed converting dest aoa elevation azimuth to i32");
415                             Error::JniCall(JniError::Unknown)
416                         },
417                     )?,
418                 ),
419                 JValue::Int(two_way_measurement.slot_index.to_i32().ok_or_else(|| {
420                     error!("Failed converting slot index to i32");
421                     Error::JniCall(JniError::Unknown)
422                 })?),
423             ],
424         )
425     }
426 
create_range_data_java<'a>( &'a self, env: &'a JNIEnv, data: RangeDataNtfPacket, two_way_measurements_java: jobjectArray, num_two_way_measurements: i32, ) -> Result<JObject<'a>>427     fn create_range_data_java<'a>(
428         &'a self,
429         env: &'a JNIEnv,
430         data: RangeDataNtfPacket,
431         two_way_measurements_java: jobjectArray,
432         num_two_way_measurements: i32,
433     ) -> Result<JObject<'a>> {
434         let ranging_data_class = self.find_class(env, UWB_RANGING_DATA_CLASS)?;
435         env.new_object(
436             ranging_data_class,
437             "(JJIJIII[Lcom/android/server/uwb/data/UwbTwoWayMeasurement;)V",
438             &[
439                 JValue::Long(data.get_sequence_number().to_i64().ok_or_else(|| {
440                     error!("Failed converting seq num to i64");
441                     Error::JniCall(JniError::Unknown)
442                 })?),
443                 JValue::Long(data.get_session_id().to_i64().ok_or_else(|| {
444                     error!("Failed converting session id to i64");
445                     Error::JniCall(JniError::Unknown)
446                 })?),
447                 JValue::Int(data.get_rcr_indicator().to_i32().ok_or_else(|| {
448                     error!("Failed converting rcr indicator to i32");
449                     Error::JniCall(JniError::Unknown)
450                 })?),
451                 JValue::Long(data.get_current_ranging_interval().to_i64().ok_or_else(|| {
452                     error!("Failed converting current ranging interval to i32");
453                     Error::JniCall(JniError::Unknown)
454                 })?),
455                 JValue::Int(data.get_ranging_measurement_type().to_i32().ok_or_else(|| {
456                     error!("Failed converting ranging measurement type to i32");
457                     Error::JniCall(JniError::Unknown)
458                 })?),
459                 JValue::Int(data.get_mac_address_indicator().to_i32().ok_or_else(|| {
460                     error!("Failed converting mac address indicator to i32");
461                     Error::JniCall(JniError::Unknown)
462                 })?),
463                 JValue::Int(num_two_way_measurements),
464                 JValue::Object(JObject::from(two_way_measurements_java)),
465             ],
466         )
467     }
468 
handle_short_range_data_notification_received( &self, env: &JNIEnv, data: ShortMacTwoWayRangeDataNtfPacket, ) -> Result<()>469     fn handle_short_range_data_notification_received(
470         &self,
471         env: &JNIEnv,
472         data: ShortMacTwoWayRangeDataNtfPacket,
473     ) -> Result<()> {
474         let two_way_measurement_class = self.find_class(env, UWB_TWO_WAY_MEASUREMENT_CLASS)?;
475         let two_way_measurement_initial_java =
476             EventManagerImpl::create_zeroed_two_way_measurement_java(
477                 env,
478                 two_way_measurement_class,
479                 env.new_byte_array(EXTENDED_MAC_ADDRESS_LEN.to_i32().ok_or_else(|| {
480                     error!("Failed converting mac address len to i32");
481                     Error::JniCall(JniError::Unknown)
482                 })?)?,
483             )?;
484         let num_two_way_measurements: i32 =
485             data.get_two_way_ranging_measurements().len().to_i32().ok_or_else(|| {
486                 error!("Failed converting len to i32");
487                 Error::JniCall(JniError::Unknown)
488             })?;
489         let two_way_measurements_java = env.new_object_array(
490             num_two_way_measurements,
491             two_way_measurement_class,
492             two_way_measurement_initial_java,
493         )?;
494         for (i, two_way_measurement) in data.get_two_way_ranging_measurements().iter().enumerate() {
495             let two_way_measurement_java =
496                 EventManagerImpl::create_short_mac_two_way_measurement_java(
497                     env,
498                     two_way_measurement_class,
499                     two_way_measurement,
500                 )?;
501             env.set_object_array_element(
502                 two_way_measurements_java,
503                 i.to_i32().ok_or_else(|| {
504                     error!("Failed converting idx to i32");
505                     Error::JniCall(JniError::Unknown)
506                 })?,
507                 two_way_measurement_java,
508             )?
509         }
510         let ranging_data_java = self.create_range_data_java(
511             env,
512             data.into(),
513             two_way_measurements_java,
514             num_two_way_measurements,
515         )?;
516         env.call_method(
517             self.obj.as_obj(),
518             "onRangeDataNotificationReceived",
519             "(Lcom/android/server/uwb/data/UwbRangingData;)V",
520             &[JValue::Object(ranging_data_java)],
521         )
522         .map(|_| ()) // drop void method return
523     }
524 
handle_extended_range_data_notification_received( &self, env: &JNIEnv, data: ExtendedMacTwoWayRangeDataNtfPacket, ) -> Result<()>525     fn handle_extended_range_data_notification_received(
526         &self,
527         env: &JNIEnv,
528         data: ExtendedMacTwoWayRangeDataNtfPacket,
529     ) -> Result<()> {
530         let two_way_measurement_class = self.find_class(env, UWB_TWO_WAY_MEASUREMENT_CLASS)?;
531         let two_way_measurement_initial_java =
532             EventManagerImpl::create_zeroed_two_way_measurement_java(
533                 env,
534                 two_way_measurement_class,
535                 env.new_byte_array(EXTENDED_MAC_ADDRESS_LEN.to_i32().ok_or_else(|| {
536                     error!("Failed converting mac address len to i32");
537                     Error::JniCall(JniError::Unknown)
538                 })?)?,
539             )?;
540         let num_two_way_measurements: i32 =
541             data.get_two_way_ranging_measurements().len().to_i32().ok_or_else(|| {
542                 error!("Failed converting len to i32");
543                 Error::JniCall(JniError::Unknown)
544             })?;
545         let two_way_measurements_java = env.new_object_array(
546             num_two_way_measurements,
547             two_way_measurement_class,
548             two_way_measurement_initial_java,
549         )?;
550         for (i, two_way_measurement) in data.get_two_way_ranging_measurements().iter().enumerate() {
551             let two_way_measurement_java =
552                 EventManagerImpl::create_extended_mac_two_way_measurement_java(
553                     env,
554                     two_way_measurement_class,
555                     two_way_measurement,
556                 )?;
557             env.set_object_array_element(
558                 two_way_measurements_java,
559                 i.to_i32().ok_or_else(|| {
560                     error!("Failed converting idx to i32");
561                     Error::JniCall(JniError::Unknown)
562                 })?,
563                 two_way_measurement_java,
564             )?;
565         }
566         let ranging_data_java = self.create_range_data_java(
567             env,
568             data.into(),
569             two_way_measurements_java,
570             num_two_way_measurements,
571         )?;
572         env.call_method(
573             self.obj.as_obj(),
574             "onRangeDataNotificationReceived",
575             "(Lcom/android/server/uwb/data/UwbRangingData;)V",
576             &[JValue::Object(ranging_data_java)],
577         )
578         .map(|_| ()) // drop void method return
579     }
580 
handle_session_update_controller_multicast_list_notification_received( &self, env: &JNIEnv, data: SessionUpdateControllerMulticastListNtfPacket, ) -> Result<()>581     pub fn handle_session_update_controller_multicast_list_notification_received(
582         &self,
583         env: &JNIEnv,
584         data: SessionUpdateControllerMulticastListNtfPacket,
585     ) -> Result<()> {
586         let uwb_multicast_update_class =
587             self.find_class(env, MULTICAST_LIST_UPDATE_STATUS_CLASS)?;
588 
589         let controlee_status = data.get_controlee_status();
590         let count: i32 = controlee_status.len().try_into().map_err(|_| {
591             error!("Failed to convert controlee status length");
592             Error::JniCall(JniError::Unknown)
593         })?;
594         let mut mac_address_list: Vec<i32> = Vec::new();
595         let mut subsession_id_list: Vec<i64> = Vec::new();
596         let mut status_list: Vec<i32> = Vec::new();
597 
598         for iter in controlee_status {
599             mac_address_list.push(iter.mac_address.into());
600             subsession_id_list.push(iter.subsession_id.into());
601             status_list.push(iter.status.to_i32().ok_or_else(|| {
602                 error!("Failed to convert controlee_status's status field: {:?}", iter.status);
603                 Error::JniCall(JniError::Unknown)
604             })?);
605         }
606 
607         let mac_address_jintarray = env.new_int_array(count)?;
608         env.set_int_array_region(mac_address_jintarray, 0, mac_address_list.as_ref())?;
609         let subsession_id_jlongarray = env.new_long_array(count)?;
610         env.set_long_array_region(subsession_id_jlongarray, 0, subsession_id_list.as_ref())?;
611         let status_jintarray = env.new_int_array(count)?;
612         env.set_int_array_region(status_jintarray, 0, status_list.as_ref())?;
613 
614         let uwb_multicast_update_object = env.new_object(
615             uwb_multicast_update_class,
616             "(JII[I[J[I)V",
617             &[
618                 JValue::Long(data.get_session_id().try_into().map_err(|_| {
619                     error!("Could not convert session_id");
620                     Error::JniCall(JniError::Unknown)
621                 })?),
622                 JValue::Int(data.get_remaining_multicast_list_size().try_into().map_err(|_| {
623                     error!("Could not convert remaining multicast list size");
624                     Error::JniCall(JniError::Unknown)
625                 })?),
626                 JValue::Int(count),
627                 JValue::Object(JObject::from(mac_address_jintarray)),
628                 JValue::Object(JObject::from(subsession_id_jlongarray)),
629                 JValue::Object(JObject::from(status_jintarray)),
630             ],
631         )?;
632 
633         env.call_method(
634             self.obj.as_obj(),
635             "onMulticastListUpdateNotificationReceived",
636             "(Lcom/android/server/uwb/data/UwbMulticastListUpdateStatus;)V",
637             &[JValue::Object(uwb_multicast_update_object)],
638         )
639         .map(|_| ()) // drop void method return
640     }
641 
get_vendor_uci_payload(data: UciNotificationPacket) -> Result<Vec<u8>>642     fn get_vendor_uci_payload(data: UciNotificationPacket) -> Result<Vec<u8>> {
643         match data.specialize() {
644             UciNotificationChild::UciVendor_9_Notification(evt) => match evt.specialize() {
645                 UciVendor_9_NotificationChild::Payload(payload) => Ok(payload.to_vec()),
646                 UciVendor_9_NotificationChild::None => Ok(Vec::new()),
647             },
648             UciNotificationChild::UciVendor_A_Notification(evt) => match evt.specialize() {
649                 UciVendor_A_NotificationChild::Payload(payload) => Ok(payload.to_vec()),
650                 UciVendor_A_NotificationChild::None => Ok(Vec::new()),
651             },
652             UciNotificationChild::UciVendor_B_Notification(evt) => match evt.specialize() {
653                 UciVendor_B_NotificationChild::Payload(payload) => Ok(payload.to_vec()),
654                 UciVendor_B_NotificationChild::None => Ok(Vec::new()),
655             },
656             UciNotificationChild::UciVendor_E_Notification(evt) => match evt.specialize() {
657                 UciVendor_E_NotificationChild::Payload(payload) => Ok(payload.to_vec()),
658                 UciVendor_E_NotificationChild::None => Ok(Vec::new()),
659             },
660             UciNotificationChild::UciVendor_F_Notification(evt) => match evt.specialize() {
661                 UciVendor_F_NotificationChild::Payload(payload) => Ok(payload.to_vec()),
662                 UciVendor_F_NotificationChild::None => Ok(Vec::new()),
663             },
664             _ => {
665                 error!("Invalid vendor notification with gid {:?}", data.to_vec());
666                 Err(Error::JniCall(JniError::Unknown))
667             }
668         }
669     }
670 
handle_vendor_uci_notification_received( &self, env: &JNIEnv, data: UciNotificationPacket, ) -> Result<()>671     pub fn handle_vendor_uci_notification_received(
672         &self,
673         env: &JNIEnv,
674         data: UciNotificationPacket,
675     ) -> Result<()> {
676         let gid: i32 = data.get_group_id().to_i32().ok_or_else(|| {
677             error!("Failed to convert gid");
678             Error::JniCall(JniError::Unknown)
679         })?;
680         let oid: i32 = data.get_opcode().to_i32().ok_or_else(|| {
681             error!("Failed to convert gid");
682             Error::JniCall(JniError::Unknown)
683         })?;
684         let payload: Vec<u8> = EventManagerImpl::get_vendor_uci_payload(data)?;
685         let payload_jbytearray = env.byte_array_from_slice(payload.as_ref())?;
686 
687         env.call_method(
688             self.obj.as_obj(),
689             "onVendorUciNotificationReceived",
690             "(IIB])V",
691             &[
692                 JValue::Int(gid),
693                 JValue::Int(oid),
694                 JValue::Object(JObject::from(payload_jbytearray)),
695             ],
696         )
697         .map(|_| ()) // drop void method return
698     }
699 
700     // Attempts to clear an exception.  If we do not do this, the exception continues being thrown
701     // when the control flow returns to Java.  We discard errors here (after logging them) rather
702     // than propagating them to the caller since there's nothing they can do with that information.
clear_exception(&self, env: AttachGuard)703     fn clear_exception(&self, env: AttachGuard) {
704         match env.exception_check() {
705             Ok(true) => match env.exception_clear() {
706                 Ok(()) => {} // We successfully cleared the exception.
707                 Err(e) => error!("Error clearing JNI exception: {:?}", e),
708             },
709             Ok(false) => {} // No exception found.
710             Err(e) => error!("Error checking JNI exception: {:?}", e),
711         }
712     }
713 }
714 
715 #[cfg(any(test, fuzzing))]
716 pub mod mock_event_manager;
717