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