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 //! Implements UciHal trait for Android.
16
17 use std::sync::Arc;
18
19 use android_hardware_uwb::aidl::android::hardware::uwb::{
20 IUwb::IUwbAsync,
21 IUwbChip::IUwbChipAsync,
22 IUwbClientCallback::{BnUwbClientCallback, IUwbClientCallbackAsyncServer},
23 UwbEvent::UwbEvent,
24 UwbStatus::UwbStatus,
25 };
26 use android_hardware_uwb::binder::{
27 BinderFeatures, DeathRecipient, ExceptionCode, IBinder, Interface, Result as BinderResult,
28 Status as BinderStatus, Strong,
29 };
30 use async_trait::async_trait;
31 use binder_tokio::{Tokio, TokioRuntime};
32 use log::error;
33 use pdl_runtime::Packet;
34 use tokio::runtime::Handle;
35 use tokio::sync::{mpsc, Mutex};
36 use uwb_core::error::{Error as UwbCoreError, Result as UwbCoreResult};
37 use uwb_core::params::uci_packets::SessionId;
38 use uwb_core::uci::uci_hal::{UciHal, UciHalPacket};
39 use uwb_uci_packets::{DeviceState, DeviceStatusNtfBuilder};
40
41 use crate::error::{Error, Result};
42
input_uci_hal_packet<T: Into<uwb_uci_packets::UciControlPacket>>( builder: T, ) -> Vec<UciHalPacket>43 fn input_uci_hal_packet<T: Into<uwb_uci_packets::UciControlPacket>>(
44 builder: T,
45 ) -> Vec<UciHalPacket> {
46 let packets: Vec<uwb_uci_packets::UciControlPacketHal> = builder.into().into();
47 packets.into_iter().map(|packet| packet.encode_to_vec().unwrap()).collect()
48 }
49
50 /// Send device status notification with error state.
send_device_state_error_notification( uci_sender: &mpsc::UnboundedSender<UciHalPacket>, ) -> UwbCoreResult<()>51 fn send_device_state_error_notification(
52 uci_sender: &mpsc::UnboundedSender<UciHalPacket>,
53 ) -> UwbCoreResult<()> {
54 let raw_message_packets = input_uci_hal_packet(DeviceStatusNtfBuilder {
55 device_state: DeviceState::DeviceStateError,
56 });
57 for raw_message_packet in raw_message_packets {
58 if let Err(e) = uci_sender.send(raw_message_packet) {
59 error!("Error sending device state error notification: {:?}", e);
60 return Err(UwbCoreError::BadParameters);
61 }
62 }
63 Ok(())
64 }
65
66 /// Redirects the raw UCI callbacks to UciHalAndroid and manages the HalEvent.
67 ///
68 /// RawUciCallback Redirects Raw UCI callbacks upstream, and manages HalEvent.
69 /// RawUciCallback is declared as a seprate struct as a struct with IUwbClientCallbackAsyncServer
70 /// trait is consumed by BnUwbClientCallback, thus it cannot be implemented for UciHalAndroid.
71 #[derive(Clone, Debug)]
72 struct RawUciCallback {
73 uci_sender: mpsc::UnboundedSender<UciHalPacket>,
74 hal_open_result_sender: mpsc::Sender<Result<()>>,
75 hal_close_result_sender: mpsc::Sender<Result<()>>,
76 }
77
78 impl RawUciCallback {
new( uci_sender: mpsc::UnboundedSender<UciHalPacket>, hal_open_result_sender: mpsc::Sender<Result<()>>, hal_close_result_sender: mpsc::Sender<Result<()>>, ) -> Self79 pub fn new(
80 uci_sender: mpsc::UnboundedSender<UciHalPacket>,
81 hal_open_result_sender: mpsc::Sender<Result<()>>,
82 hal_close_result_sender: mpsc::Sender<Result<()>>,
83 ) -> Self {
84 Self { uci_sender, hal_open_result_sender, hal_close_result_sender }
85 }
86 }
87
88 impl Interface for RawUciCallback {}
89
90 #[async_trait]
91 impl IUwbClientCallbackAsyncServer for RawUciCallback {
onHalEvent(&self, event: UwbEvent, _event_status: UwbStatus) -> BinderResult<()>92 async fn onHalEvent(&self, event: UwbEvent, _event_status: UwbStatus) -> BinderResult<()> {
93 match event {
94 // UwbEvent::ERROR is processed differently by UciHalAndroid depending on its state.
95 //
96 // If error occurs before POST_INIT_CPLT received: UciHalAndroid handles the error.
97 // If error occurs after POST_INIT_CPLT received: UciHalAndroid redirects the error
98 // upstream by converting it to UCI DeviceStatusNtf.
99 // Both are attempted as RawUciCallback is not aware of the state for UciHalAndroid.
100 // Similarly, error due to close of hal cannot be reported as both the reason of the
101 // error and expectation of UciHalAndroid are unknown.
102 UwbEvent::ERROR => {
103 // Error sending hal_open_result_sender is not meaningful, as RawUciCallback do not
104 // know the reason for UwbEvent::ERROR. The receiving end only listens to
105 // hal_open_result_sender when it is expecting POST_INIT_CPLT or ERROR.
106 let _ = self.hal_open_result_sender.try_send(Err(Error::BinderStatus(
107 BinderStatus::new_exception(ExceptionCode::TRANSACTION_FAILED, None),
108 )));
109
110 send_device_state_error_notification(&self.uci_sender)
111 .map_err(|e| BinderStatus::from(Error::from(e)))
112 }
113 UwbEvent::POST_INIT_CPLT => self.hal_open_result_sender.try_send(Ok(())).map_err(|e| {
114 error!("Failed sending POST_INIT_CPLT: {:?}", e);
115 BinderStatus::new_exception(ExceptionCode::TRANSACTION_FAILED, None)
116 }),
117 UwbEvent::CLOSE_CPLT => self.hal_close_result_sender.try_send(Ok(())).map_err(|e| {
118 error!("Failed sending CLOSE_CPLT: {:?}", e);
119 BinderStatus::new_exception(ExceptionCode::TRANSACTION_FAILED, None)
120 }),
121 _ => Ok(()),
122 }
123 }
124
onUciMessage(&self, data: &[u8]) -> BinderResult<()>125 async fn onUciMessage(&self, data: &[u8]) -> BinderResult<()> {
126 self.uci_sender.send(data.to_owned()).map_err(|e| {
127 error!("Failed sending UCI response or notification: {:?}", e);
128 BinderStatus::new_exception(ExceptionCode::TRANSACTION_FAILED, None)
129 })
130 }
131 }
132
133 /// Implentation of UciHal trait for Android.
134 #[derive(Default)]
135 pub struct UciHalAndroid {
136 chip_id: String,
137 hal_close_result_receiver: Option<mpsc::Receiver<Result<()>>>,
138 hal_death_recipient: Option<Arc<Mutex<DeathRecipient>>>,
139 hal_uci_recipient: Option<Strong<dyn IUwbChipAsync<Tokio>>>,
140 }
141
142 #[allow(dead_code)]
143 impl UciHalAndroid {
144 /// Constructor for empty UciHal.
new(chip_id: &str) -> Self145 pub fn new(chip_id: &str) -> Self {
146 Self {
147 chip_id: chip_id.to_owned(),
148 hal_close_result_receiver: None,
149 hal_death_recipient: None,
150 hal_uci_recipient: None,
151 }
152 }
153 }
154
155 #[async_trait]
156 impl UciHal for UciHalAndroid {
157 /// Open the UCI HAL and power on the UWBS.
open( &mut self, packet_sender: mpsc::UnboundedSender<UciHalPacket>, ) -> UwbCoreResult<()>158 async fn open(
159 &mut self,
160 packet_sender: mpsc::UnboundedSender<UciHalPacket>,
161 ) -> UwbCoreResult<()> {
162 // Returns error if UciHalAndroid is already open.
163 if self.hal_uci_recipient.is_some() {
164 return Err(UwbCoreError::BadParameters);
165 }
166
167 // Get hal service.
168 let service_name = "android.hardware.uwb.IUwb/default";
169 let i_uwb: Strong<dyn IUwbAsync<Tokio>> = binder_tokio::wait_for_interface(service_name)
170 .await
171 .map_err(|e| UwbCoreError::from(Error::from(e)))?;
172 let chip_names = i_uwb.getChips().await.map_err(|e| UwbCoreError::from(Error::from(e)))?;
173 if chip_names.is_empty() {
174 error!("No UWB chip available.");
175 return Err(UwbCoreError::BadParameters);
176 }
177 let chip_name: &str = match &self.chip_id == "default" {
178 true => &chip_names[0],
179 false => &self.chip_id,
180 };
181 if !chip_names.contains(&chip_name.to_string()) {
182 return Err(UwbCoreError::BadParameters);
183 }
184 let i_uwb_chip = i_uwb
185 .getChip(chip_name)
186 .await
187 .map_err(|e| UwbCoreError::from(Error::from(e)))?
188 .into_async();
189
190 // If the binder object unexpectedly goes away (typically because its hosting process has
191 // been killed), then the `DeathRecipient`'s callback will be called.
192 let packet_sender_clone = packet_sender.clone();
193 let mut bare_death_recipient = DeathRecipient::new(move || {
194 send_device_state_error_notification(&packet_sender_clone).unwrap_or_else(|e| {
195 error!("Error sending device state error notification: {:?}", e);
196 });
197 });
198 i_uwb_chip
199 .as_binder()
200 .link_to_death(&mut bare_death_recipient)
201 .map_err(|e| UwbCoreError::from(Error::from(e)))?;
202
203 // Connect callback to packet_sender.
204 let (hal_open_result_sender, mut hal_open_result_receiver) = mpsc::channel::<Result<()>>(1);
205 let (hal_close_result_sender, hal_close_result_receiver) = mpsc::channel::<Result<()>>(1);
206 let m_cback = BnUwbClientCallback::new_async_binder(
207 RawUciCallback::new(
208 packet_sender.clone(),
209 hal_open_result_sender,
210 hal_close_result_sender,
211 ),
212 TokioRuntime(Handle::current()),
213 BinderFeatures::default(),
214 );
215 i_uwb_chip.open(&m_cback).await.map_err(|e| UwbCoreError::from(Error::from(e)))?;
216 // Initialize core and wait for POST_INIT_CPLT.
217 i_uwb_chip.coreInit().await.map_err(|e| UwbCoreError::from(Error::from(e)))?;
218 match hal_open_result_receiver.recv().await {
219 Some(Ok(())) => {
220 // Workaround while http://b/243140882 is not fixed:
221 // Send DEVICE_STATE_READY notification as chip is not sending this notification.
222 let device_ready_ntfs = input_uci_hal_packet(
223 DeviceStatusNtfBuilder { device_state: DeviceState::DeviceStateReady }.build(),
224 );
225 for device_ready_ntf in device_ready_ntfs {
226 packet_sender.send(device_ready_ntf).unwrap_or_else(|e| {
227 error!("UCI HAL: failed to send device ready notification: {:?}", e);
228 });
229 }
230 // End of workaround.
231 self.hal_uci_recipient.replace(i_uwb_chip);
232 self.hal_death_recipient.replace(Arc::new(Mutex::new(bare_death_recipient)));
233 self.hal_close_result_receiver.replace(hal_close_result_receiver);
234 Ok(())
235 }
236 _ => {
237 error!("POST_INIT_CPLT event is not received");
238 Err(UwbCoreError::Unknown)
239 }
240 }
241 }
242
close(&mut self) -> UwbCoreResult<()>243 async fn close(&mut self) -> UwbCoreResult<()> {
244 // Reset UciHalAndroid regardless of whether hal_close is successful or not.
245 let hal_uci_recipient = self.hal_uci_recipient.take();
246 let _hal_death_recipient = self.hal_death_recipient.take();
247 let hal_close_result_receiver = self.hal_close_result_receiver.take();
248 match hal_uci_recipient {
249 Some(i_uwb_chip) => {
250 i_uwb_chip.close().await.map_err(|e| UwbCoreError::from(Error::from(e)))
251 }
252 None => Err(UwbCoreError::BadParameters),
253 }?;
254 match hal_close_result_receiver.unwrap().recv().await {
255 // When RawUciCallback received an error due to this close() function, currently none of
256 // the error messages will be triggered, and this close() will be pending until timeout,
257 // as the reason for the UwbEvent::ERROR cannot be determined.
258 Some(result) => result.map_err(|_| UwbCoreError::Unknown),
259 None => Err(UwbCoreError::Unknown),
260 }
261 }
262
send_packet(&mut self, packet: UciHalPacket) -> UwbCoreResult<()>263 async fn send_packet(&mut self, packet: UciHalPacket) -> UwbCoreResult<()> {
264 match &self.hal_uci_recipient {
265 Some(i_uwb_chip) => {
266 let bytes_written = i_uwb_chip
267 .sendUciMessage(&packet)
268 .await
269 .map_err(|e| UwbCoreError::from(Error::from(e)))?;
270 if bytes_written != packet.len() as i32 {
271 log::error!(
272 "sendUciMessage did not write the full packet: {} != {}",
273 bytes_written,
274 packet.len()
275 );
276 Err(UwbCoreError::PacketTxError)
277 } else {
278 Ok(())
279 }
280 }
281 None => Err(UwbCoreError::BadParameters),
282 }
283 }
284
notify_session_initialized(&mut self, session_id: SessionId) -> UwbCoreResult<()>285 async fn notify_session_initialized(&mut self, session_id: SessionId) -> UwbCoreResult<()> {
286 match &self.hal_uci_recipient {
287 Some(i_uwb_chip) => {
288 i_uwb_chip
289 // HAL API accepts signed int, so cast received session_id as i32.
290 .sessionInit(session_id as i32)
291 .await
292 .map_err(|e| UwbCoreError::from(Error::from(e)))?;
293 Ok(())
294 }
295 None => Err(UwbCoreError::BadParameters),
296 }
297 }
298 }
299
300 #[cfg(test)]
301 mod tests {
302 use super::*;
303
304 #[test]
test_send_device_state_error_notification()305 fn test_send_device_state_error_notification() {
306 let (uci_sender, _) = mpsc::unbounded_channel();
307 let res = send_device_state_error_notification(&uci_sender);
308 assert_eq!(res, Err(UwbCoreError::BadParameters));
309 }
310
311 #[tokio::test]
test_new()312 async fn test_new() {
313 let chip_id = "test_chip_id";
314 let hal = UciHalAndroid::new(chip_id);
315 assert_eq!(hal.chip_id, chip_id);
316 assert!(hal.hal_close_result_receiver.is_none());
317 assert!(hal.hal_death_recipient.is_none());
318 assert!(hal.hal_uci_recipient.is_none());
319 }
320
321 #[tokio::test]
test_open_error()322 async fn test_open_error() {
323 let chip_id = "test_chip_id";
324 let mut hal = UciHalAndroid::new(chip_id);
325 let packet_sender = mpsc::unbounded_channel().0;
326 let res = hal.open(packet_sender).await;
327 assert_eq!(res, Err(UwbCoreError::BadParameters));
328 }
329
330 #[tokio::test]
test_close()331 async fn test_close() {
332 let chip_id = "test_chip_id";
333 let mut hal = UciHalAndroid::new(chip_id);
334 let (_, receiver) = mpsc::channel::<Result<()>>(1);
335 let death_recipient = Arc::new(Mutex::new(DeathRecipient::new(|| {})));
336 hal.hal_close_result_receiver = Some(receiver);
337 hal.hal_death_recipient = Some(death_recipient.clone());
338 let res = hal.close().await;
339 assert_eq!(res, Err(UwbCoreError::BadParameters));
340 assert!(hal.hal_close_result_receiver.is_none());
341 assert!(hal.hal_death_recipient.is_none());
342 assert!(hal.hal_uci_recipient.is_none());
343 }
344 }
345