1 /*
2  * Copyright (C) 2023 Huawei Device Co., Ltd.
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 
16 //! Implementation of client side of IPC.
17 
18 #![allow(dead_code)]
19 #![allow(unused_variables)]
20 
21 use std::ffi::{ c_char, CString };
22 
23 use hilog_rust::{ info, error, hilog, HiLogLabel, LogType };
24 use ipc_rust::{
25     BorrowedMsgParcel, FromRemoteObj, InterfaceToken, MsgParcel,
26     RemoteObjRef, Serialize, get_service,
27 };
28 
29 use fusion_data_rust::Intention;
30 use fusion_utils_rust::{ call_debug_enter, FusionResult, FusionErrorCode };
31 use fusion_ipc_service_rust::{ IDeviceStatus, FusionIpcProxy, MSDP_DEVICESTATUS_SERVICE_ID };
32 
33 const LOG_LABEL: HiLogLabel = HiLogLabel {
34     log_type: LogType::LogCore,
35     domain: 0xD002220,
36     tag: "FusionIpcClient"
37 };
38 
39 /// Representation of client side of IPC.
40 pub struct FusionIpcClient(RemoteObjRef<dyn IDeviceStatus>);
41 
42 impl FusionIpcClient {
43     /// Connect device status service.
connect() -> FusionResult<Self>44     pub fn connect() -> FusionResult<Self> {
45         call_debug_enter!("FusionIpcClient::connect");
46         match get_service(MSDP_DEVICESTATUS_SERVICE_ID) {
47             Ok(obj) => {
48                 match <dyn IDeviceStatus as FromRemoteObj>::try_from(obj) {
49                     Ok(obj_ref) => {
50                         info!(LOG_LABEL, "Connect to service successfully");
51                         Ok(FusionIpcClient(obj_ref))
52                     }
53                     Err(err) => {
54                         error!(LOG_LABEL, "Can not dereference remote object");
55                         Err(FusionErrorCode::Fail)
56                     }
57                 }
58             }
59             Err(err) => {
60                 error!(LOG_LABEL, "Can not connect to service");
61                 Err(FusionErrorCode::Fail)
62             }
63         }
64     }
65 
add_interface_token(&self, data_parcel: &mut BorrowedMsgParcel<'_>) -> FusionResult<()>66     fn add_interface_token(&self, data_parcel: &mut BorrowedMsgParcel<'_>) -> FusionResult<()> {
67         call_debug_enter!("FusionIpcClient::add_interface_token");
68         let token = InterfaceToken::new(FusionIpcProxy::get_descriptor());
69         match token.serialize(data_parcel) {
70             Ok(_) => {
71                 Ok(())
72             }
73             Err(_) => {
74                 error!(LOG_LABEL, "Failed to serialize interface token");
75                 Err(FusionErrorCode::Fail)
76             }
77         }
78     }
79 
80     /// Request to enable the service identified by [`intention`].
enable(&self, intention: Intention, data: &dyn Serialize, reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()>81     pub fn enable(&self, intention: Intention, data: &dyn Serialize,
82         reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()> {
83         call_debug_enter!("FusionIpcClient::enable");
84         match MsgParcel::new() {
85             Some(mut data_parcel) => {
86                 let mut borrowed_data_parcel = data_parcel.borrowed();
87                 info!(LOG_LABEL, "Serialize interface token");
88                 self.add_interface_token(&mut borrowed_data_parcel)?;
89 
90                 if data.serialize(&mut borrowed_data_parcel).is_err() {
91                     return Err(FusionErrorCode::Fail);
92                 }
93                 info!(LOG_LABEL, "Call proxy.enable()");
94                 self.0.enable(intention, &borrowed_data_parcel, reply)
95             }
96             None => {
97                 error!(LOG_LABEL, "Can not instantiate MsgParcel");
98                 Err(FusionErrorCode::Fail)
99             }
100         }
101     }
102 
103     /// Request to disable the service identified by [`intention`].
disable(&self, intention: Intention, data: &dyn Serialize, reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()>104     pub fn disable(&self, intention: Intention, data: &dyn Serialize,
105         reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()> {
106         call_debug_enter!("FusionIpcClient::disable");
107         match MsgParcel::new() {
108             Some(mut data_parcel) => {
109                 let mut borrowed_data_parcel = data_parcel.borrowed();
110                 info!(LOG_LABEL, "Serialize interface token");
111                 self.add_interface_token(&mut borrowed_data_parcel)?;
112 
113                 if data.serialize(&mut borrowed_data_parcel).is_err() {
114                     return Err(FusionErrorCode::Fail);
115                 }
116                 info!(LOG_LABEL, "Call proxy.disable()");
117                 self.0.disable(intention, &borrowed_data_parcel, reply)
118             }
119             None => {
120                 error!(LOG_LABEL, "Can not instantiate MsgParcel");
121                 Err(FusionErrorCode::Fail)
122             }
123         }
124     }
125 
126     /// Request to start the service identified by [`intention`].
start(&self, intention: Intention, data: &dyn Serialize, reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()>127     pub fn start(&self, intention: Intention, data: &dyn Serialize,
128         reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()> {
129         call_debug_enter!("FusionIpcClient::start");
130         match MsgParcel::new() {
131             Some(mut data_parcel) => {
132                 let mut borrowed_data_parcel = data_parcel.borrowed();
133                 info!(LOG_LABEL, "Serialize interface token");
134                 self.add_interface_token(&mut borrowed_data_parcel)?;
135 
136                 if data.serialize(&mut borrowed_data_parcel).is_err() {
137                     return Err(FusionErrorCode::Fail);
138                 }
139                 info!(LOG_LABEL, "Call proxy.start()");
140                 self.0.start(intention, &borrowed_data_parcel, reply)
141             }
142             None => {
143                 error!(LOG_LABEL, "Can not instantiate MsgParcel");
144                 Err(FusionErrorCode::Fail)
145             }
146         }
147     }
148 
149     /// Request to stop the service identified by [`intention`].
stop(&self, intention: Intention, data: &dyn Serialize, reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()>150     pub fn stop(&self, intention: Intention, data: &dyn Serialize,
151         reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()> {
152         call_debug_enter!("FusionIpcClient::stop");
153         match MsgParcel::new() {
154             Some(mut data_parcel) => {
155                 let mut borrowed_data_parcel = data_parcel.borrowed();
156                 info!(LOG_LABEL, "Serialize interface token");
157                 self.add_interface_token(&mut borrowed_data_parcel)?;
158 
159                 if data.serialize(&mut borrowed_data_parcel).is_err() {
160                     return Err(FusionErrorCode::Fail);
161                 }
162                 info!(LOG_LABEL, "Call proxy.stop()");
163                 self.0.stop(intention, &borrowed_data_parcel, reply)
164             }
165             None => {
166                 error!(LOG_LABEL, "Can not instantiate MsgParcel");
167                 Err(FusionErrorCode::Fail)
168             }
169         }
170     }
171 
172     /// Request to add a watch of state of service, with the service identified by
173     /// [`intention`], the state to watch identified by [`id`], parameters packed in
174     /// [`data`] parcel.
add_watch(&self, intention: Intention, id: u32, data: &dyn Serialize, reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()>175     pub fn add_watch(&self, intention: Intention, id: u32, data: &dyn Serialize,
176         reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()> {
177         call_debug_enter!("FusionIpcClient::add_watch");
178         match MsgParcel::new() {
179             Some(mut data_parcel) => {
180                 let mut borrowed_data_parcel = data_parcel.borrowed();
181                 info!(LOG_LABEL, "Serialize interface token");
182                 self.add_interface_token(&mut borrowed_data_parcel)?;
183 
184                 if data.serialize(&mut borrowed_data_parcel).is_err() {
185                     return Err(FusionErrorCode::Fail);
186                 }
187                 info!(LOG_LABEL, "Call proxy.add_watch()");
188                 self.0.add_watch(intention, id, &borrowed_data_parcel, reply)
189             }
190             None => {
191                 error!(LOG_LABEL, "Can not instantiate MsgParcel");
192                 Err(FusionErrorCode::Fail)
193             }
194         }
195     }
196 
197     /// Request to remove a watch of state of service.
remove_watch(&self, intention: Intention, id: u32, data: &dyn Serialize, reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()>198     pub fn remove_watch(&self, intention: Intention, id: u32, data: &dyn Serialize,
199         reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()> {
200         call_debug_enter!("FusionIpcClient::remove_watch");
201         match MsgParcel::new() {
202             Some(mut data_parcel) => {
203                 let mut borrowed_data_parcel = data_parcel.borrowed();
204                 info!(LOG_LABEL, "Serialize interface token");
205                 self.add_interface_token(&mut borrowed_data_parcel)?;
206 
207                 if data.serialize(&mut borrowed_data_parcel).is_err() {
208                     return Err(FusionErrorCode::Fail);
209                 }
210                 info!(LOG_LABEL, "Call proxy.remove_watch()");
211                 self.0.remove_watch(intention, id, &borrowed_data_parcel, reply)
212             }
213             None => {
214                 error!(LOG_LABEL, "Can not instantiate MsgParcel");
215                 Err(FusionErrorCode::Fail)
216             }
217         }
218     }
219 
220     /// Request to set a parameter of service, with the service identified by
221     /// [`intention`], the parameter identified by [`id`], and values packed in
222     /// [`data`] parcel.
set_param(&self, intention: Intention, id: u32, data: &dyn Serialize, reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()>223     pub fn set_param(&self, intention: Intention, id: u32, data: &dyn Serialize,
224         reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()> {
225         call_debug_enter!("FusionIpcClient::set_param");
226         match MsgParcel::new() {
227             Some(mut data_parcel) => {
228                 let mut borrowed_data_parcel = data_parcel.borrowed();
229                 info!(LOG_LABEL, "Serialize interface token");
230                 self.add_interface_token(&mut borrowed_data_parcel)?;
231 
232                 if data.serialize(&mut borrowed_data_parcel).is_err() {
233                     return Err(FusionErrorCode::Fail);
234                 }
235                 info!(LOG_LABEL, "Call proxy.set_param()");
236                 self.0.set_param(intention, id, &borrowed_data_parcel, reply)
237             }
238             None => {
239                 error!(LOG_LABEL, "Can not instantiate MsgParcel");
240                 Err(FusionErrorCode::Fail)
241             }
242         }
243     }
244 
245     /// Request to get a parameter of service, with the service identified by
246     /// [`intention`], the parameter identified by [`id`].
get_param(&self, intention: Intention, id: u32, data: &dyn Serialize, reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()>247     pub fn get_param(&self, intention: Intention, id: u32, data: &dyn Serialize,
248         reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()> {
249         call_debug_enter!("FusionIpcClient::get_param");
250         match MsgParcel::new() {
251             Some(mut data_parcel) => {
252                 let mut borrowed_data_parcel = data_parcel.borrowed();
253                 info!(LOG_LABEL, "Serialize interface token");
254                 self.add_interface_token(&mut borrowed_data_parcel)?;
255 
256                 if data.serialize(&mut borrowed_data_parcel).is_err() {
257                     return Err(FusionErrorCode::Fail);
258                 }
259                 info!(LOG_LABEL, "Call proxy.get_param()");
260                 self.0.get_param(intention, id, &borrowed_data_parcel, reply)
261             }
262             None => {
263                 error!(LOG_LABEL, "Can not instantiate MsgParcel");
264                 Err(FusionErrorCode::Fail)
265             }
266         }
267     }
268 
269     /// Request to interact with service identified by [`intention`] for general purpose.
270     /// This interface supplements functions of previous intefaces. Functionalities of
271     /// this interface is service spicific.
control(&self, intention: Intention, id: u32, data: &dyn Serialize, reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()>272     pub fn control(&self, intention: Intention, id: u32, data: &dyn Serialize,
273         reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()> {
274         call_debug_enter!("FusionIpcClient::control");
275         match MsgParcel::new() {
276             Some(mut data_parcel) => {
277                 let mut borrowed_data_parcel = data_parcel.borrowed();
278                 info!(LOG_LABEL, "Serialize interface token");
279                 self.add_interface_token(&mut borrowed_data_parcel)?;
280 
281                 if data.serialize(&mut borrowed_data_parcel).is_err() {
282                     return Err(FusionErrorCode::Fail);
283                 }
284                 info!(LOG_LABEL, "Call proxy.control()");
285                 self.0.control(intention, id, &borrowed_data_parcel, reply)
286             }
287             None => {
288                 error!(LOG_LABEL, "Can not instantiate MsgParcel");
289                 Err(FusionErrorCode::Fail)
290             }
291         }
292     }
293 }
294