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