• 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 //! This module provides a thin adapter of UwbService and UwbServiceCallback that encodes the
16 //! arguments to protobuf.
17 
18 use log::{debug, error};
19 
20 use crate::error::{Error, Result};
21 use crate::params::{AppConfigParams, DeviceState, ReasonCode, SessionId, SessionState};
22 use crate::proto::bindings::{
23     AndroidGetPowerStatsResponse, AndroidSetCountryCodeRequest, AndroidSetCountryCodeResponse,
24     DeinitSessionRequest, DeinitSessionResponse, DisableResponse, EnableResponse,
25     InitSessionRequest, InitSessionResponse, RangeDataReceivedSignal, ReconfigureRequest,
26     ReconfigureResponse, SendVendorCmdRequest, SendVendorCmdResponse, ServiceResetSignal,
27     SessionParamsRequest, SessionParamsResponse, SessionStateChangedSignal, SetLoggerModeRequest,
28     SetLoggerModeResponse, StartRangingRequest, StartRangingResponse, Status as ProtoStatus,
29     StopRangingRequest, StopRangingResponse, UciDeviceStatusChangedSignal,
30     UpdateControllerMulticastListRequest, UpdateControllerMulticastListResponse,
31     VendorNotificationReceivedSignal,
32 };
33 use crate::proto::utils::{parse_from_bytes, write_to_bytes};
34 use crate::service::uwb_service::{UwbService, UwbServiceCallback};
35 use crate::uci::notification::SessionRangeData;
36 
37 /// A thin adapter of UwbService. The argument and the response of each method are protobuf-encoded
38 /// buffer. The definition of the protobuf is at protos/uwb_core_protos.proto.
39 ///
40 /// For the naming of the protobuf struct, the argument of a method `do_something()` will be called
41 /// `DoSomethingRequest`, and the result will be called `DoSomethingResponse`.
42 pub struct ProtoUwbService {
43     service: UwbService,
44 }
45 
46 impl ProtoUwbService {
47     /// Create a ProtoUwbService.
new(service: UwbService) -> Self48     pub fn new(service: UwbService) -> Self {
49         Self { service }
50     }
51 
52     /// Set UCI log mode.
set_logger_mode(&self, request: &[u8]) -> Result<Vec<u8>>53     pub fn set_logger_mode(&self, request: &[u8]) -> Result<Vec<u8>> {
54         let request = parse_from_bytes::<SetLoggerModeRequest>(request)?;
55         let mut resp = SetLoggerModeResponse::new();
56         resp.set_status(self.service.set_logger_mode(request.logger_mode.into()).into());
57         write_to_bytes(&resp)
58     }
59 
60     /// Enable the UWB service.
enable(&self) -> Result<Vec<u8>>61     pub fn enable(&self) -> Result<Vec<u8>> {
62         let mut resp = EnableResponse::new();
63         resp.set_status(self.service.enable().into());
64         write_to_bytes(&resp)
65     }
66 
67     /// Disable the UWB service.
disable(&self) -> Result<Vec<u8>>68     pub fn disable(&self) -> Result<Vec<u8>> {
69         let mut resp = DisableResponse::new();
70         resp.set_status(self.service.disable().into());
71         write_to_bytes(&resp)
72     }
73 
74     /// Initialize a new ranging session with the given parameters.
75     ///
76     /// Note: Currently the protobuf only support Fira parameters, but not support CCC parameters.
init_session(&self, request: &[u8]) -> Result<Vec<u8>>77     pub fn init_session(&self, request: &[u8]) -> Result<Vec<u8>> {
78         let mut request = parse_from_bytes::<InitSessionRequest>(request)?;
79         let params = request
80             .params
81             .take()
82             .ok_or_else(|| {
83                 error!("InitSessionRequest.params is empty");
84                 Error::BadParameters
85             })?
86             .try_into()
87             .map_err(|e| {
88                 error!("Failed to convert to AppConfigParams: {}", e);
89                 Error::BadParameters
90             })?;
91 
92         let mut resp = InitSessionResponse::new();
93         resp.set_status(
94             self.service
95                 .init_session(request.session_id, request.session_type.into(), params)
96                 .into(),
97         );
98         write_to_bytes(&resp)
99     }
100 
101     /// Destroy the session.
deinit_session(&self, request: &[u8]) -> Result<Vec<u8>>102     pub fn deinit_session(&self, request: &[u8]) -> Result<Vec<u8>> {
103         let request = parse_from_bytes::<DeinitSessionRequest>(request)?;
104         let mut resp = DeinitSessionResponse::new();
105         resp.set_status(self.service.deinit_session(request.session_id).into());
106         write_to_bytes(&resp)
107     }
108 
109     /// Start ranging of the session.
start_ranging(&self, request: &[u8]) -> Result<Vec<u8>>110     pub fn start_ranging(&self, request: &[u8]) -> Result<Vec<u8>> {
111         let request = parse_from_bytes::<StartRangingRequest>(request)?;
112         // Currently we only support FiRa session, not CCC. For FiRa session, the returned
113         // AppConfigParams is the same as the configured one before start_ranging(). Therefore, we
114         // don't reply the AppConfigParams received from uwb_core.
115         let mut resp = StartRangingResponse::new();
116         resp.set_status(self.service.start_ranging(request.session_id).into());
117         write_to_bytes(&resp)
118     }
119 
120     /// Stop ranging.
stop_ranging(&self, request: &[u8]) -> Result<Vec<u8>>121     pub fn stop_ranging(&self, request: &[u8]) -> Result<Vec<u8>> {
122         let request = parse_from_bytes::<StopRangingRequest>(request)?;
123         let mut resp = StopRangingResponse::new();
124         resp.set_status(self.service.stop_ranging(request.session_id).into());
125         write_to_bytes(&resp)
126     }
127 
128     /// Reconfigure the parameters of the session.
reconfigure(&self, request: &[u8]) -> Result<Vec<u8>>129     pub fn reconfigure(&self, request: &[u8]) -> Result<Vec<u8>> {
130         let mut request = parse_from_bytes::<ReconfigureRequest>(request)?;
131         let params = request
132             .params
133             .take()
134             .ok_or_else(|| {
135                 error!("ReconfigureRequest.params is empty");
136                 Error::BadParameters
137             })?
138             .try_into()
139             .map_err(|e| {
140                 error!("Failed to convert to AppConfigParams: {}", e);
141                 Error::BadParameters
142             })?;
143 
144         let mut resp = ReconfigureResponse::new();
145         resp.set_status(self.service.reconfigure(request.session_id, params).into());
146         write_to_bytes(&resp)
147     }
148 
149     /// Update the list of the controlees to the ongoing session.
update_controller_multicast_list(&self, request: &[u8]) -> Result<Vec<u8>>150     pub fn update_controller_multicast_list(&self, request: &[u8]) -> Result<Vec<u8>> {
151         let request = parse_from_bytes::<UpdateControllerMulticastListRequest>(request)?;
152         let mut controlees = vec![];
153         for controlee in request.controlees.into_iter() {
154             let controlee = controlee.try_into().map_err(|e| {
155                 error!("Failed to convert Controlee: {:?}", e);
156                 Error::BadParameters
157             })?;
158             controlees.push(controlee);
159         }
160 
161         let mut resp = UpdateControllerMulticastListResponse::new();
162         resp.set_status(
163             self.service
164                 .update_controller_multicast_list(
165                     request.session_id,
166                     request.action.into(),
167                     controlees,
168                 )
169                 .into(),
170         );
171         write_to_bytes(&resp)
172     }
173 
174     /// Set the country code. Android-specific method.
android_set_country_code(&self, request: &[u8]) -> Result<Vec<u8>>175     pub fn android_set_country_code(&self, request: &[u8]) -> Result<Vec<u8>> {
176         let request = parse_from_bytes::<AndroidSetCountryCodeRequest>(request)?;
177         let country_code = request.country_code.try_into()?;
178 
179         let mut resp = AndroidSetCountryCodeResponse::new();
180         resp.set_status(self.service.android_set_country_code(country_code).into());
181         write_to_bytes(&resp)
182     }
183 
184     /// Get the power statistics. Android-specific method.
android_get_power_stats(&self) -> Result<Vec<u8>>185     pub fn android_get_power_stats(&self) -> Result<Vec<u8>> {
186         let mut resp = AndroidGetPowerStatsResponse::new();
187         match self.service.android_get_power_stats() {
188             Ok(power_stats) => {
189                 resp.set_status(Ok(()).into());
190                 resp.set_power_stats(power_stats.into());
191             }
192             Err(e) => {
193                 resp.set_status(From::<Result<()>>::from(Err(e)));
194             }
195         }
196         write_to_bytes(&resp)
197     }
198 
199     /// Send a raw UCI message.
raw_uci_cmd(&self, request: &[u8]) -> Result<Vec<u8>>200     pub fn raw_uci_cmd(&self, request: &[u8]) -> Result<Vec<u8>> {
201         let request = parse_from_bytes::<SendVendorCmdRequest>(request)?;
202         let mut resp = SendVendorCmdResponse::new();
203         match self.service.raw_uci_cmd(request.mt, request.gid, request.oid, request.payload) {
204             Ok(msg) => {
205                 resp.set_status(Ok(()).into());
206                 resp.set_gid(msg.gid);
207                 resp.set_oid(msg.oid);
208                 resp.set_payload(msg.payload);
209             }
210             Err(e) => {
211                 resp.set_status(From::<Result<()>>::from(Err(e)));
212             }
213         }
214         write_to_bytes(&resp)
215     }
216 
217     /// Get app config params for the given session id
session_params(&self, request: &[u8]) -> Result<Vec<u8>>218     pub fn session_params(&self, request: &[u8]) -> Result<Vec<u8>> {
219         let request = parse_from_bytes::<SessionParamsRequest>(request)?;
220         let mut resp = SessionParamsResponse::new();
221         match self.service.session_params(request.session_id) {
222             Ok(AppConfigParams::Fira(params)) => {
223                 resp.set_status(Ok(()).into());
224                 resp.set_params(params.into());
225             }
226             Ok(params) => {
227                 error!("Received non-Fira session parameters: {:?}", params);
228                 resp.set_status(ProtoStatus::UNKNOWN);
229             }
230             Err(e) => {
231                 resp.set_status(From::<Result<()>>::from(Err(e)));
232             }
233         }
234         write_to_bytes(&resp)
235     }
236 }
237 
238 /// The trait that provides the same callbacks of UwbServiceCallback. It has the blanket
239 /// implementation of UwbServiceCallback trait that converts the arguments to one protobuf-encoded
240 /// payload.
241 ///
242 /// For the naming of the protobuf struct, the payload of a callback `on_something_happened()`
243 /// will be called `SomethingHappenedSignal`.
244 pub trait ProtoUwbServiceCallback: 'static {
245     /// Notify the UWB service has been reset due to internal error. All the sessions are closed.
on_service_reset(&mut self, payload: Vec<u8>)246     fn on_service_reset(&mut self, payload: Vec<u8>);
247     /// Notify the status of the UCI device.
on_uci_device_status_changed(&mut self, payload: Vec<u8>)248     fn on_uci_device_status_changed(&mut self, payload: Vec<u8>);
249     /// Notify the state of the session is changed.
on_session_state_changed(&mut self, payload: Vec<u8>)250     fn on_session_state_changed(&mut self, payload: Vec<u8>);
251     /// Notify the ranging data of the session is received.
on_range_data_received(&mut self, payload: Vec<u8>)252     fn on_range_data_received(&mut self, payload: Vec<u8>);
253     /// Notify the vendor notification is received.
on_vendor_notification_received(&mut self, payload: Vec<u8>)254     fn on_vendor_notification_received(&mut self, payload: Vec<u8>);
255 }
256 
257 impl<C: ProtoUwbServiceCallback> UwbServiceCallback for C {
on_service_reset(&mut self, success: bool)258     fn on_service_reset(&mut self, success: bool) {
259         debug!("UwbService is reset, success: {}", success);
260         let mut msg = ServiceResetSignal::new();
261         msg.set_success(success);
262         if let Ok(payload) = write_to_bytes(&msg) {
263             ProtoUwbServiceCallback::on_service_reset(self, payload);
264         } else {
265             error!("Failed to call on_service_reset()");
266         }
267     }
268 
on_uci_device_status_changed(&mut self, state: DeviceState)269     fn on_uci_device_status_changed(&mut self, state: DeviceState) {
270         debug!("UCI device status is changed: {:?}", state);
271         let mut msg = UciDeviceStatusChangedSignal::new();
272         msg.set_state(state.into());
273         if let Ok(payload) = write_to_bytes(&msg) {
274             ProtoUwbServiceCallback::on_uci_device_status_changed(self, payload);
275         } else {
276             error!("Failed to call on_uci_device_status_changed()");
277         }
278     }
279 
on_session_state_changed( &mut self, session_id: SessionId, session_state: SessionState, reason_code: ReasonCode, )280     fn on_session_state_changed(
281         &mut self,
282         session_id: SessionId,
283         session_state: SessionState,
284         reason_code: ReasonCode,
285     ) {
286         debug!(
287             "Session {:?}'s state is changed to {:?}, reason: {:?}",
288             session_id, session_state, reason_code
289         );
290         let mut msg = SessionStateChangedSignal::new();
291         msg.set_session_id(session_id);
292         msg.set_session_state(session_state.into());
293         msg.set_reason_code(reason_code.into());
294         if let Ok(payload) = write_to_bytes(&msg) {
295             ProtoUwbServiceCallback::on_session_state_changed(self, payload);
296         } else {
297             error!("Failed to call on_session_state_changed()");
298         }
299     }
300 
on_range_data_received(&mut self, session_id: SessionId, range_data: SessionRangeData)301     fn on_range_data_received(&mut self, session_id: SessionId, range_data: SessionRangeData) {
302         debug!("Received range data {:?} from Session {:?}", range_data, session_id);
303         let mut msg = RangeDataReceivedSignal::new();
304         msg.set_session_id(session_id);
305         msg.set_range_data(range_data.into());
306         if let Ok(payload) = write_to_bytes(&msg) {
307             ProtoUwbServiceCallback::on_range_data_received(self, payload);
308         } else {
309             error!("Failed to call on_range_data_received()");
310         }
311     }
312 
on_vendor_notification_received(&mut self, gid: u32, oid: u32, payload: Vec<u8>)313     fn on_vendor_notification_received(&mut self, gid: u32, oid: u32, payload: Vec<u8>) {
314         debug!("Received vendor notification: gid={}, oid={}, payload={:?}", gid, oid, payload);
315         let mut msg = VendorNotificationReceivedSignal::new();
316         msg.set_gid(gid);
317         msg.set_oid(oid);
318         msg.set_payload(payload);
319         if let Ok(payload) = write_to_bytes(&msg) {
320             ProtoUwbServiceCallback::on_vendor_notification_received(self, payload);
321         } else {
322             error!("Failed to call on_vendor_notification_received()");
323         }
324     }
325 }
326