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 //! IPC service definition.
17 
18 #![allow(unused_variables)]
19 
20 mod identity;
21 
22 use std::ffi::{ c_char, CString };
23 
24 use hilog_rust::{ info, error, hilog, HiLogLabel, LogType };
25 use ipc_rust::{
26     BorrowedMsgParcel, IRemoteBroker, IRemoteObj, MsgParcel, IMsgParcel,
27     RemoteObj, RemoteStub, define_remote_object
28 };
29 
30 use fusion_data_rust::Intention;
31 use fusion_utils_rust::{ call_debug_enter, FusionResult, FusionErrorCode };
32 
33 use crate::identity::{ CommonAction, compose_param_id, split_action, split_intention, split_param };
34 
35 const LOG_LABEL: HiLogLabel = HiLogLabel {
36     log_type: LogType::LogCore,
37     domain: 0xD002220,
38     tag: "FusionIpcService"
39 };
40 
41 /// SA ID for "ohos.msdp.Idevicestatus"
42 pub const MSDP_DEVICESTATUS_SERVICE_ID: i32 = 2902;
43 
44 /// Abstration of services.
45 ///
46 /// By design, for ease of extention, all service implementations are required to
47 /// map its functions to this collection of interface, with services identified
48 /// by Intentions.
49 pub trait IDeviceStatus: IRemoteBroker {
50     /// Enable the service identified by [`intention`].
enable(&self, intention: Intention, data: &BorrowedMsgParcel<'_>, reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()>51     fn enable(&self, intention: Intention, data: &BorrowedMsgParcel<'_>, reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()>;
52     /// Disable the service identified by [`intention`].
disable(&self, intention: Intention, data: &BorrowedMsgParcel<'_>, reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()>53     fn disable(&self, intention: Intention, data: &BorrowedMsgParcel<'_>, reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()>;
54     /// Start the service identified by [`intention`].
start(&self, intention: Intention, data: &BorrowedMsgParcel<'_>, reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()>55     fn start(&self, intention: Intention, data: &BorrowedMsgParcel<'_>, reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()>;
56     /// Stop the service identified by [`intention`].
stop(&self, intention: Intention, data: &BorrowedMsgParcel<'_>, reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()>57     fn stop(&self, intention: Intention, data: &BorrowedMsgParcel<'_>, reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()>;
58     /// Add a watch of state of service, with the service identified by [`intention`],
59     /// the state to watch identified by [`id`], parameters packed in [`data`] parcel.
add_watch(&self, intention: Intention, id: u32, data: &BorrowedMsgParcel<'_>, reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()>60     fn add_watch(&self, intention: Intention, id: u32, data: &BorrowedMsgParcel<'_>, reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()>;
61     /// Remove a watch of state of service.
remove_watch(&self, intention: Intention, id: u32, data: &BorrowedMsgParcel<'_>, reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()>62     fn remove_watch(&self, intention: Intention, id: u32, data: &BorrowedMsgParcel<'_>, reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()>;
63     /// Set a parameter of service, with the service identified by [`intention`],
64     /// the parameter identified by [`id`], and values packed in [`data`] parcel.
set_param(&self, intention: Intention, id: u32, data: &BorrowedMsgParcel<'_>, reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()>65     fn set_param(&self, intention: Intention, id: u32, data: &BorrowedMsgParcel<'_>, reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()>;
66     /// Get a parameter of service, with the service identified by [`intention`],
67     /// the parameter identified by [`id`].
get_param(&self, intention: Intention, id: u32, data: &BorrowedMsgParcel<'_>, reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()>68     fn get_param(&self, intention: Intention, id: u32, data: &BorrowedMsgParcel<'_>, reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()>;
69     /// Interact with service identified by [`intention`] for general purpose. This interface
70     /// supplements functions of previous intefaces. Functionalities of this interface is
71     /// service spicific.
control(&self, intention: Intention, id: u32, data: &BorrowedMsgParcel<'_>, reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()>72     fn control(&self, intention: Intention, id: u32, data: &BorrowedMsgParcel<'_>, reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()>;
73 }
74 
on_remote_request(stub: &dyn IDeviceStatus, code: u32, data: &BorrowedMsgParcel<'_>, reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()>75 fn on_remote_request(stub: &dyn IDeviceStatus, code: u32, data: &BorrowedMsgParcel<'_>,
76                      reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()> {
77     call_debug_enter!("FusionIpcService::on_remote_request");
78     let intention = split_intention(code)?;
79     let id = split_param(code);
80 
81     match split_action(code)? {
82         CommonAction::Enable => {
83             info!(LOG_LABEL, "Call stub.enable()");
84             stub.enable(intention, data, reply)
85         }
86         CommonAction::Disable => {
87             info!(LOG_LABEL, "Call stub.disable()");
88             stub.disable(intention, data, reply)
89         }
90         CommonAction::Start => {
91             info!(LOG_LABEL, "Call stub.start()");
92             stub.start(intention, data, reply)
93         }
94         CommonAction::Stop => {
95             info!(LOG_LABEL, "Call stub.stop()");
96             stub.stop(intention, data, reply)
97         }
98         CommonAction::AddWatch => {
99             info!(LOG_LABEL, "Call stub.add_watch()");
100             stub.add_watch(intention, id, data, reply)
101         }
102         CommonAction::RemoveWatch => {
103             info!(LOG_LABEL, "Call stub.remove_watch()");
104             stub.remove_watch(intention, id, data, reply)
105         }
106         CommonAction::SetParam => {
107             info!(LOG_LABEL, "Call stub.set_param()");
108             stub.set_param(intention, id, data, reply)
109         }
110         CommonAction::GetParam => {
111             info!(LOG_LABEL, "Call stub.get_param()");
112             stub.get_param(intention, id, data, reply)
113         }
114         CommonAction::Control => {
115             info!(LOG_LABEL, "Call stub.control()");
116             stub.control(intention, id, data, reply)
117         }
118     }
119 }
120 
121 define_remote_object!(
122     IDeviceStatus["ohos.msdp.Idevicestatus"] {
123         stub: FusionIpcStub(on_remote_request),
124         proxy: FusionIpcProxy,
125     }
126 );
127 
128 impl FusionIpcProxy {
transfer_data(&self, src: &dyn IMsgParcel, target: &mut dyn IMsgParcel) -> FusionResult<()>129     fn transfer_data(&self, src: &dyn IMsgParcel, target: &mut dyn IMsgParcel) -> FusionResult<()>
130     {
131         call_debug_enter!("FusionIpcProxy::transfer_data");
132         let data_size = src.get_data_size();
133         match src.read_buffer(data_size) {
134             Ok(data_vec) => {
135                 if target.write_buffer(data_vec.as_slice()) {
136                     Ok(())
137                 } else {
138                     error!(LOG_LABEL, "write_buffer() failed");
139                     Err(FusionErrorCode::Fail)
140                 }
141             }
142             Err(_) => {
143                 error!(LOG_LABEL, "read_buffer() failed");
144                 Err(FusionErrorCode::Fail)
145             }
146         }
147     }
148 
send_request(&self, action: CommonAction, intention: Intention, id: u32, data: &BorrowedMsgParcel<'_>, reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()>149     fn send_request(&self, action: CommonAction, intention: Intention, id: u32,
150         data: &BorrowedMsgParcel<'_>, reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()>
151     {
152         call_debug_enter!("FusionIpcProxy::send_request");
153         match MsgParcel::new() {
154             Some(mut data_parcel) => {
155                 self.transfer_data(data, &mut data_parcel)?;
156                 let code = compose_param_id(action, intention, id);
157                 let rep = {
158                     match self.remote.send_request(code, &data_parcel, false) {
159                         Ok(tr) => {
160                             tr
161                         }
162                         Err(_) => {
163                             error!(LOG_LABEL, "Failed to send request");
164                             return Err(FusionErrorCode::Fail);
165                         }
166                     }
167                 };
168 
169                 self.transfer_data(&rep, reply)
170             }
171             None => {
172                 error!(LOG_LABEL, "Can not deref data");
173                 Err(FusionErrorCode::Fail)
174             }
175         }
176     }
177 }
178 
179 impl IDeviceStatus for FusionIpcProxy {
enable(&self, intention: Intention, data: &BorrowedMsgParcel<'_>, reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()>180     fn enable(&self, intention: Intention, data: &BorrowedMsgParcel<'_>,
181         reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()> {
182         call_debug_enter!("FusionIpcProxy::enable");
183         self.send_request(CommonAction::Enable, intention, 0u32, data, reply)
184     }
185 
disable(&self, intention: Intention, data: &BorrowedMsgParcel<'_>, reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()>186     fn disable(&self, intention: Intention, data: &BorrowedMsgParcel<'_>,
187         reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()> {
188         call_debug_enter!("FusionIpcProxy::disable");
189         self.send_request(CommonAction::Disable, intention, 0u32, data, reply)
190     }
191 
start(&self, intention: Intention, data: &BorrowedMsgParcel<'_>, reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()>192     fn start(&self, intention: Intention, data: &BorrowedMsgParcel<'_>,
193         reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()> {
194         call_debug_enter!("FusionIpcProxy::start");
195         self.send_request(CommonAction::Start, intention, 0u32, data, reply)
196     }
197 
stop(&self, intention: Intention, data: &BorrowedMsgParcel<'_>, reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()>198     fn stop(&self, intention: Intention, data: &BorrowedMsgParcel<'_>,
199         reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()> {
200         call_debug_enter!("FusionIpcProxy::stop");
201         self.send_request(CommonAction::Stop, intention, 0u32, data, reply)
202     }
203 
add_watch(&self, intention: Intention, id: u32, data: &BorrowedMsgParcel<'_>, reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()>204     fn add_watch(&self, intention: Intention, id: u32, data: &BorrowedMsgParcel<'_>,
205         reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()> {
206         call_debug_enter!("FusionIpcProxy::add_watch");
207         self.send_request(CommonAction::AddWatch, intention, id, data, reply)
208     }
209 
remove_watch(&self, intention: Intention, id: u32, data: &BorrowedMsgParcel<'_>, reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()>210     fn remove_watch(&self, intention: Intention, id: u32, data: &BorrowedMsgParcel<'_>,
211         reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()> {
212         call_debug_enter!("FusionIpcProxy::remove_watch");
213         self.send_request(CommonAction::RemoveWatch, intention, id, data, reply)
214     }
215 
set_param(&self, intention: Intention, id: u32, data: &BorrowedMsgParcel<'_>, reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()>216     fn set_param(&self, intention: Intention, id: u32, data: &BorrowedMsgParcel<'_>,
217         reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()> {
218         call_debug_enter!("FusionIpcProxy::set_param");
219         self.send_request(CommonAction::SetParam, intention, id, data, reply)
220     }
221 
get_param(&self, intention: Intention, id: u32, data: &BorrowedMsgParcel<'_>, reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()>222     fn get_param(&self, intention: Intention, id: u32, data: &BorrowedMsgParcel<'_>,
223         reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()> {
224         call_debug_enter!("FusionIpcProxy::get_param");
225         self.send_request(CommonAction::GetParam, intention, id, data, reply)
226     }
227 
control(&self, intention: Intention, id: u32, data: &BorrowedMsgParcel<'_>, reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()>228     fn control(&self, intention: Intention, id: u32, data: &BorrowedMsgParcel<'_>,
229         reply: &mut BorrowedMsgParcel<'_>) -> FusionResult<()> {
230         call_debug_enter!("FusionIpcProxy::control");
231         self.send_request(CommonAction::Control, intention, id, data, reply)
232     }
233 }
234