• 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 //! 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