• 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 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                 runtime.handle().to_owned(),
80             )?;
81             manager_map.insert(chip_id.as_ref().to_string(), manager);
82         }
83         Ok(Self { manager_map, _runtime: runtime })
84     }
85 
86     /// Sets log mode for all chips.
set_logger_mode(&self, logger_mode: UciLoggerMode) -> Result<()>87     pub fn set_logger_mode(&self, logger_mode: UciLoggerMode) -> Result<()> {
88         for (_, manager) in self.manager_map.iter() {
89             manager.set_logger_mode(logger_mode.clone())?;
90         }
91         Ok(())
92     }
93 
94     /// Constructs the unique dispatcher.
new_dispatcher<T: AsRef<str>>( vm: &'static Arc<JavaVM>, class_loader_obj: GlobalRef, callback_obj: GlobalRef, chip_ids: &[T], ) -> Result<()>95     pub fn new_dispatcher<T: AsRef<str>>(
96         vm: &'static Arc<JavaVM>,
97         class_loader_obj: GlobalRef,
98         callback_obj: GlobalRef,
99         chip_ids: &[T],
100     ) -> Result<()> {
101         if DISPATCHER.try_read().map_err(|_| Error::Unknown)?.is_some() {
102             error!("UCI JNI: Dispatcher already exists when trying to create.");
103             return Err(Error::BadParameters);
104         }
105         let dispatcher = Dispatcher::new(vm, class_loader_obj, callback_obj, chip_ids)?;
106         DISPATCHER.write().map_err(|_| Error::Unknown)?.replace(dispatcher);
107         Ok(())
108     }
109 
110     /// Gets pointer value of the unique dispatcher
get_dispatcher_ptr() -> Result<*const Dispatcher>111     pub fn get_dispatcher_ptr() -> Result<*const Dispatcher> {
112         let read_lock = DISPATCHER.read().map_err(|_| Error::Unknown)?;
113         match &*read_lock {
114             Some(dispatcher_ref) => Ok(dispatcher_ref),
115             None => Err(Error::BadParameters),
116         }
117     }
118 
119     /// Destroys the unique Dispather.
destroy_dispatcher() -> Result<()>120     pub fn destroy_dispatcher() -> Result<()> {
121         if DISPATCHER.try_read().map_err(|_| Error::Unknown)?.is_none() {
122             error!("UCI JNI: Dispatcher already does not exist when trying to destroy.");
123             return Err(Error::BadParameters);
124         }
125         let _ = DISPATCHER.write().map_err(|_| Error::Unknown)?.take();
126         Ok(())
127     }
128 
129     /// Gets reference to the unique Dispatcher.
get_dispatcher<'a>(env: JNIEnv<'a>, obj: JObject<'a>) -> Result<GuardedDispatcher<'a>>130     pub fn get_dispatcher<'a>(env: JNIEnv<'a>, obj: JObject<'a>) -> Result<GuardedDispatcher<'a>> {
131         let jni_guard = env.lock_obj(obj).map_err(|_| Error::ForeignFunctionInterface)?;
132         let read_lock = DISPATCHER.read().map_err(|_| Error::Unknown)?;
133         GuardedDispatcher::new(jni_guard, read_lock)
134     }
135 
136     /// Gets reference to UciManagerSync with chip_id.
get_uci_manager<'a>( env: JNIEnv<'a>, obj: JObject<'a>, chip_id: JString, ) -> Result<GuardedUciManager<'a>>137     pub fn get_uci_manager<'a>(
138         env: JNIEnv<'a>,
139         obj: JObject<'a>,
140         chip_id: JString,
141     ) -> Result<GuardedUciManager<'a>> {
142         let guarded_dispatcher = Self::get_dispatcher(env, obj)?;
143         let chip_id_str =
144             String::from(env.get_string(chip_id).map_err(|_| Error::ForeignFunctionInterface)?);
145         guarded_dispatcher.into_guarded_uci_manager(&chip_id_str)
146     }
147 }
148 
149 /// Lifetimed reference to UciManagerSync that locks Java object while reference is alive.
150 pub(crate) struct GuardedUciManager<'a> {
151     _jni_guard: MonitorGuard<'a>,
152     read_lock: RwLockReadGuard<'a, Option<Dispatcher>>,
153     chip_id: String,
154 }
155 
156 impl<'a> Deref for GuardedUciManager<'a> {
157     type Target = UciManagerSync<UciManagerImpl>;
deref(&self) -> &Self::Target158     fn deref(&self) -> &Self::Target {
159         // Unwrap GuardedUciManager will not panic since content is checked at creation.
160         self.read_lock.as_ref().unwrap().manager_map.get(&self.chip_id).unwrap()
161     }
162 }
163 
164 /// Lifetimed reference to Dispatcher that locks Java object while reference is alive.
165 pub(crate) struct GuardedDispatcher<'a> {
166     _jni_guard: MonitorGuard<'a>,
167     read_lock: RwLockReadGuard<'a, Option<Dispatcher>>,
168 }
169 
170 impl<'a> GuardedDispatcher<'a> {
171     /// Constructor:
new( jni_guard: MonitorGuard<'a>, read_lock: RwLockReadGuard<'a, Option<Dispatcher>>, ) -> Result<Self>172     pub fn new(
173         jni_guard: MonitorGuard<'a>,
174         read_lock: RwLockReadGuard<'a, Option<Dispatcher>>,
175     ) -> Result<Self> {
176         // Check RwLockReadGuard contains Dispatcher:
177         if read_lock.is_none() {
178             return Err(Error::BadParameters);
179         };
180         Ok(GuardedDispatcher { _jni_guard: jni_guard, read_lock })
181     }
182 
183     /// Conversion to GuardedUciManager:
into_guarded_uci_manager(self, chip_id: &str) -> Result<GuardedUciManager<'a>>184     pub fn into_guarded_uci_manager(self, chip_id: &str) -> Result<GuardedUciManager<'a>> {
185         let _uci_manager = self.manager_map.get(chip_id).ok_or(Error::BadParameters)?;
186         Ok(GuardedUciManager {
187             _jni_guard: self._jni_guard,
188             read_lock: self.read_lock,
189             chip_id: chip_id.to_owned(),
190         })
191     }
192 }
193 
194 impl<'a> Deref for GuardedDispatcher<'a> {
195     type Target = Dispatcher;
deref(&self) -> &Self::Target196     fn deref(&self) -> &Self::Target {
197         // Unwrap GuardedDispatcher will not panic since content is checked at creation.
198         self.read_lock.as_ref().unwrap()
199     }
200 }
201