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 Dispatcher and related methods. 16 17 use crate::notification_manager_android::NotificationManagerAndroidBuilder; 18 19 use std::collections::HashMap; 20 use std::ops::Deref; 21 use std::sync::{Arc, RwLock, RwLockReadGuard}; 22 23 use jni::objects::{GlobalRef, JObject, JString}; 24 use jni::{JNIEnv, JavaVM, MonitorGuard}; 25 use lazy_static::lazy_static; 26 use log::error; 27 use tokio::runtime::{Builder as RuntimeBuilder, Runtime}; 28 use uci_hal_android::uci_hal_android::UciHalAndroid; 29 use uwb_core::error::{Error, Result}; 30 use uwb_core::uci::pcapng_uci_logger_factory::PcapngUciLoggerFactoryBuilder; 31 use uwb_core::uci::uci_logger::UciLoggerMode; 32 use uwb_core::uci::uci_logger_factory::UciLoggerFactory; 33 use uwb_core::uci::uci_manager_sync::UciManagerSync; 34 use uwb_core::uci::UciManagerImpl; 35 36 lazy_static! { 37 /// Shared unique dispatcher that may be created and deleted during runtime. 38 static ref DISPATCHER: RwLock<Option<Dispatcher>> = RwLock::new(None); 39 } 40 41 /// Dispatcher is managed by Java side. Construction and Destruction are provoked by JNI function 42 /// nativeDispatcherNew and nativeDispatcherDestroy respectively. 43 /// Destruction does NOT wait until the spawned threads are closed. 44 pub(crate) struct Dispatcher { 45 pub manager_map: HashMap<String, UciManagerSync<UciManagerImpl>>, 46 _runtime: Runtime, 47 } 48 impl Dispatcher { 49 /// Constructs Dispatcher. new<T: AsRef<str>>( vm: &'static Arc<JavaVM>, class_loader_obj: GlobalRef, callback_obj: GlobalRef, chip_ids: &[T], ) -> Result<Dispatcher>50 fn new<T: AsRef<str>>( 51 vm: &'static Arc<JavaVM>, 52 class_loader_obj: GlobalRef, 53 callback_obj: GlobalRef, 54 chip_ids: &[T], 55 ) -> Result<Dispatcher> { 56 let runtime = RuntimeBuilder::new_multi_thread() 57 .thread_name("UwbService") 58 .enable_all() 59 .build() 60 .map_err(|_| Error::ForeignFunctionInterface)?; 61 let mut manager_map = HashMap::<String, UciManagerSync<UciManagerImpl>>::new(); 62 let mut log_file_factory = PcapngUciLoggerFactoryBuilder::new() 63 .log_path("/data/misc/apexdata/com.android.uwb/log".into()) 64 .filename_prefix("uwb_uci".to_owned()) 65 .runtime_handle(runtime.handle().to_owned()) 66 .build() 67 .ok_or(Error::Unknown)?; 68 for chip_id in chip_ids { 69 let logger = log_file_factory.build_logger(chip_id.as_ref()).ok_or(Error::Unknown)?; 70 let manager = UciManagerSync::new( 71 UciHalAndroid::new(chip_id.as_ref()), 72 NotificationManagerAndroidBuilder { 73 chip_id: chip_id.as_ref().to_owned(), 74 vm, 75 class_loader_obj: class_loader_obj.clone(), 76 callback_obj: callback_obj.clone(), 77 }, 78 logger, 79 UciLoggerMode::Filtered, 80 runtime.handle().to_owned(), 81 )?; 82 manager_map.insert(chip_id.as_ref().to_string(), manager); 83 } 84 Ok(Self { manager_map, _runtime: runtime }) 85 } 86 87 /// Sets log mode for all chips. set_logger_mode(&self, logger_mode: UciLoggerMode) -> Result<()>88 pub fn set_logger_mode(&self, logger_mode: UciLoggerMode) -> Result<()> { 89 for (_, manager) in self.manager_map.iter() { 90 manager.set_logger_mode(logger_mode.clone())?; 91 } 92 Ok(()) 93 } 94 95 /// Constructs the unique dispatcher. new_dispatcher<T: AsRef<str>>( vm: &'static Arc<JavaVM>, class_loader_obj: GlobalRef, callback_obj: GlobalRef, chip_ids: &[T], ) -> Result<()>96 pub fn new_dispatcher<T: AsRef<str>>( 97 vm: &'static Arc<JavaVM>, 98 class_loader_obj: GlobalRef, 99 callback_obj: GlobalRef, 100 chip_ids: &[T], 101 ) -> Result<()> { 102 if DISPATCHER.try_read().map_err(|_| Error::Unknown)?.is_some() { 103 error!("UCI JNI: Dispatcher already exists when trying to create."); 104 return Err(Error::BadParameters); 105 } 106 let dispatcher = Dispatcher::new(vm, class_loader_obj, callback_obj, chip_ids)?; 107 DISPATCHER.write().map_err(|_| Error::Unknown)?.replace(dispatcher); 108 Ok(()) 109 } 110 111 /// Gets pointer value of the unique dispatcher get_dispatcher_ptr() -> Result<*const Dispatcher>112 pub fn get_dispatcher_ptr() -> Result<*const Dispatcher> { 113 let read_lock = DISPATCHER.read().map_err(|_| Error::Unknown)?; 114 match &*read_lock { 115 Some(dispatcher_ref) => Ok(dispatcher_ref), 116 None => Err(Error::BadParameters), 117 } 118 } 119 120 /// Destroys the unique Dispather. destroy_dispatcher() -> Result<()>121 pub fn destroy_dispatcher() -> Result<()> { 122 if DISPATCHER.try_read().map_err(|_| Error::Unknown)?.is_none() { 123 error!("UCI JNI: Dispatcher already does not exist when trying to destroy."); 124 return Err(Error::BadParameters); 125 } 126 let _ = DISPATCHER.write().map_err(|_| Error::Unknown)?.take(); 127 Ok(()) 128 } 129 130 /// Gets reference to the unique Dispatcher. get_dispatcher<'a>(env: JNIEnv<'a>, obj: JObject<'a>) -> Result<GuardedDispatcher<'a>>131 pub fn get_dispatcher<'a>(env: JNIEnv<'a>, obj: JObject<'a>) -> Result<GuardedDispatcher<'a>> { 132 let jni_guard = env.lock_obj(obj).map_err(|_| Error::ForeignFunctionInterface)?; 133 let read_lock = DISPATCHER.read().map_err(|_| Error::Unknown)?; 134 GuardedDispatcher::new(jni_guard, read_lock) 135 } 136 137 /// Gets reference to UciManagerSync with chip_id. get_uci_manager<'a>( env: JNIEnv<'a>, obj: JObject<'a>, chip_id: JString, ) -> Result<GuardedUciManager<'a>>138 pub fn get_uci_manager<'a>( 139 env: JNIEnv<'a>, 140 obj: JObject<'a>, 141 chip_id: JString, 142 ) -> Result<GuardedUciManager<'a>> { 143 let guarded_dispatcher = Self::get_dispatcher(env, obj)?; 144 let chip_id_str = 145 String::from(env.get_string(chip_id).map_err(|_| Error::ForeignFunctionInterface)?); 146 guarded_dispatcher.into_guarded_uci_manager(&chip_id_str) 147 } 148 } 149 150 /// Lifetimed reference to UciManagerSync that locks Java object while reference is alive. 151 pub(crate) struct GuardedUciManager<'a> { 152 _jni_guard: MonitorGuard<'a>, 153 read_lock: RwLockReadGuard<'a, Option<Dispatcher>>, 154 chip_id: String, 155 } 156 157 impl<'a> Deref for GuardedUciManager<'a> { 158 type Target = UciManagerSync<UciManagerImpl>; deref(&self) -> &Self::Target159 fn deref(&self) -> &Self::Target { 160 // Unwrap GuardedUciManager will not panic since content is checked at creation. 161 self.read_lock.as_ref().unwrap().manager_map.get(&self.chip_id).unwrap() 162 } 163 } 164 165 /// Lifetimed reference to Dispatcher that locks Java object while reference is alive. 166 pub(crate) struct GuardedDispatcher<'a> { 167 _jni_guard: MonitorGuard<'a>, 168 read_lock: RwLockReadGuard<'a, Option<Dispatcher>>, 169 } 170 171 impl<'a> GuardedDispatcher<'a> { 172 /// Constructor: new( jni_guard: MonitorGuard<'a>, read_lock: RwLockReadGuard<'a, Option<Dispatcher>>, ) -> Result<Self>173 pub fn new( 174 jni_guard: MonitorGuard<'a>, 175 read_lock: RwLockReadGuard<'a, Option<Dispatcher>>, 176 ) -> Result<Self> { 177 // Check RwLockReadGuard contains Dispatcher: 178 if read_lock.is_none() { 179 return Err(Error::BadParameters); 180 }; 181 Ok(GuardedDispatcher { _jni_guard: jni_guard, read_lock }) 182 } 183 184 /// Conversion to GuardedUciManager: into_guarded_uci_manager(self, chip_id: &str) -> Result<GuardedUciManager<'a>>185 pub fn into_guarded_uci_manager(self, chip_id: &str) -> Result<GuardedUciManager<'a>> { 186 let _uci_manager = self.manager_map.get(chip_id).ok_or(Error::BadParameters)?; 187 Ok(GuardedUciManager { 188 _jni_guard: self._jni_guard, 189 read_lock: self.read_lock, 190 chip_id: chip_id.to_owned(), 191 }) 192 } 193 } 194 195 impl<'a> Deref for GuardedDispatcher<'a> { 196 type Target = Dispatcher; deref(&self) -> &Self::Target197 fn deref(&self) -> &Self::Target { 198 // Unwrap GuardedDispatcher will not panic since content is checked at creation. 199 self.read_lock.as_ref().unwrap() 200 } 201 } 202