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 FusionFrameworks.
17 
18 #![allow(dead_code)]
19 #![allow(unused_variables)]
20 
21 use std::sync::{ Mutex, Once };
22 use std::ffi::{ c_char, CString };
23 
24 use hilog_rust::{ error, info, hilog, HiLogLabel, LogType };
25 use ipc_rust::FileDesc;
26 use fusion_utils_rust::{ call_debug_enter, FusionResult, FusionErrorCode };
27 use fusion_ipc_client_rust::FusionIpcClient;
28 use fusion_data_rust::{ AllocSocketPairParam, DragData };
29 use fusion_basic_client_rust::FusionBasicClient;
30 use fusion_drag_client_rust::DragClient;
31 use fusion_coordination_client_rust::FusionCoordinationClient;
32 
33 const LOG_LABEL: HiLogLabel = HiLogLabel {
34     log_type: LogType::LogCore,
35     domain: 0xD002220,
36     tag: "FusionFrameworks"
37 };
38 
39 #[derive(Default)]
40 struct Client {
41     ipc_client: Option<FusionIpcClient>,
42     basic: FusionBasicClient,
43     drag: DragClient,
44     coordination: FusionCoordinationClient,
45 }
46 
47 impl Client {
48     /// Connect service.
connect(&mut self)49     fn connect(&mut self)
50     {
51         if self.ipc_client.is_some() {
52             return;
53         }
54         info!(LOG_LABEL, "Trying to connect server");
55         match FusionIpcClient::connect() {
56             Ok(client) => {
57                 info!(LOG_LABEL, "Connect to server successfully");
58                 self.ipc_client = Some(client);
59             }
60             Err(_) => {
61                 error!(LOG_LABEL, "Can not connect to server");
62             }
63         }
64     }
65 
alloc_socket_pair(&self, param: &AllocSocketPairParam) -> FusionResult<(FileDesc, i32)>66     fn alloc_socket_pair(&self, param: &AllocSocketPairParam) -> FusionResult<(FileDesc, i32)>
67     {
68         match self.ipc_client.as_ref() {
69             Some(ipc_client_ref) => {
70                 info!(LOG_LABEL, "Call basic.start_drag()");
71                 self.basic.alloc_socket_pair(param, ipc_client_ref)
72             }
73             None => {
74                 error!(LOG_LABEL, "ipc_client is none");
75                 Err(FusionErrorCode::Fail)
76             }
77         }
78     }
79 
start_drag(&self, drag_data: &DragData) -> FusionResult<i32>80     fn start_drag(&self, drag_data: &DragData) -> FusionResult<i32>
81     {
82         match self.ipc_client.as_ref() {
83             Some(ipc_client_ref) => {
84                 info!(LOG_LABEL, "Call drag.start_drag()");
85                 self.drag.start_drag(drag_data, ipc_client_ref)
86             }
87             None => {
88                 error!(LOG_LABEL, "ipc_client is none");
89                 Err(FusionErrorCode::Fail)
90             }
91         }
92     }
93 
register_coordination_listener(&self) -> FusionResult<()>94     fn register_coordination_listener(&self) -> FusionResult<()>
95     {
96         call_debug_enter!("FusionFrameworks::register_coordination_listener");
97         match self.ipc_client.as_ref() {
98             Some(ipc_client_ref) => {
99                 self.coordination.register_coordination_listener(ipc_client_ref)
100             }
101             None => {
102                 error!(LOG_LABEL, "ipc_client is none");
103                 Err(FusionErrorCode::Fail)
104             }
105         }
106     }
107 
unregister_coordination_listener(&self) -> FusionResult<()>108     fn unregister_coordination_listener(&self) -> FusionResult<()>
109     {
110         call_debug_enter!("FusionFrameworks::unregister_coordination_listener");
111         match self.ipc_client.as_ref() {
112             Some(ipc_client_ref) => {
113                 self.coordination.unregister_coordination_listener(ipc_client_ref)
114             }
115             None => {
116                 error!(LOG_LABEL, "ipc_client is none");
117                 Err(FusionErrorCode::Fail)
118             }
119         }
120     }
121 
enable_coordination(&self, user_data: i32) -> FusionResult<()>122     fn enable_coordination(&self, user_data: i32) -> FusionResult<()>
123     {
124         call_debug_enter!("FusionFrameworks::enable_coordination");
125         match self.ipc_client.as_ref() {
126             Some(ipc_client_ref) => {
127                 self.coordination.enable_coordination(user_data, ipc_client_ref)
128             }
129             None => {
130                 error!(LOG_LABEL, "ipc_client is none");
131                 Err(FusionErrorCode::Fail)
132             }
133         }
134     }
135 
disable_coordination(&self, user_data: i32) -> FusionResult<()>136     fn disable_coordination(&self, user_data: i32) -> FusionResult<()>
137     {
138         call_debug_enter!("FusionFrameworks::disable_coordination");
139         match self.ipc_client.as_ref() {
140             Some(ipc_client_ref) => {
141                 self.coordination.disable_coordination(user_data, ipc_client_ref)
142             }
143             None => {
144                 error!(LOG_LABEL, "ipc_client is none");
145                 Err(FusionErrorCode::Fail)
146             }
147         }
148     }
149 
start_coordination(&self, user_data: i32, remote_network_id: &str, start_device_id: i32) -> FusionResult<()>150     fn start_coordination(&self, user_data: i32,
151                           remote_network_id: &str,
152                           start_device_id: i32) -> FusionResult<()>
153     {
154         call_debug_enter!("FusionFrameworks::start_coordination");
155         match self.ipc_client.as_ref() {
156             Some(ipc_client_ref) => {
157                 info!(LOG_LABEL, "Call coordination.start_coordination");
158                 self.coordination.start_coordination(user_data, remote_network_id,
159                     start_device_id, ipc_client_ref)
160             }
161             None => {
162                 error!(LOG_LABEL, "ipc_client is none");
163                 Err(FusionErrorCode::Fail)
164             }
165         }
166     }
167 
stop_coordination(&self, user_data: i32, is_unchained: i32) -> FusionResult<()>168     fn stop_coordination(&self, user_data: i32, is_unchained: i32) -> FusionResult<()>
169     {
170         call_debug_enter!("FusionFrameworks::stop_coordination");
171         match self.ipc_client.as_ref() {
172             Some(ipc_client_ref) => {
173                 self.coordination.stop_coordination(user_data, is_unchained, ipc_client_ref)
174             }
175             None => {
176                 error!(LOG_LABEL, "ipc_client is none");
177                 Err(FusionErrorCode::Fail)
178             }
179         }
180     }
181 
get_coordination_state(&self, user_data: i32, device_id: &str) -> FusionResult<i32>182     fn get_coordination_state(&self, user_data: i32, device_id: &str) -> FusionResult<i32>
183     {
184         call_debug_enter!("FusionFrameworks::get_coordination_state");
185         match self.ipc_client.as_ref() {
186             Some(ipc_client_ref) => {
187                 self.coordination.get_coordination_state(user_data, device_id, ipc_client_ref)
188             }
189             None => {
190                 error!(LOG_LABEL, "ipc_client is none");
191                 Err(FusionErrorCode::Fail)
192             }
193         }
194     }
195 }
196 
197 /// struct FusionFrameworks
198 #[derive(Default)]
199 pub struct FusionFrameworks(Mutex<Client>);
200 
201 impl FusionFrameworks {
202     /// Get a reference to the single instance of `FusionFrameworks`.
get_instance() -> Option<&'static FusionFrameworks>203     pub fn get_instance() -> Option<&'static FusionFrameworks>
204     {
205         static mut FRAMEWORKS: Option<FusionFrameworks> = None;
206         static INIT_ONCE: Once = Once::new();
207         unsafe {
208             INIT_ONCE.call_once(|| {
209                 FRAMEWORKS = Some(FusionFrameworks::default());
210             });
211             FRAMEWORKS.as_ref()
212         }
213     }
214 
215     /// Request connection of service via socket.
alloc_socket_pair(&self, param: &AllocSocketPairParam) -> FusionResult<(FileDesc, i32)>216     pub fn alloc_socket_pair(&self, param: &AllocSocketPairParam) -> FusionResult<(FileDesc, i32)>
217     {
218         let mut guard = self.0.lock().unwrap();
219         guard.connect();
220         guard.alloc_socket_pair(param)
221     }
222 
223     /// Request service to change to [`DRAG`] mode.
start_drag(&self, drag_data: &DragData) -> FusionResult<i32>224     pub fn start_drag(&self, drag_data: &DragData) -> FusionResult<i32>
225     {
226         let mut guard = self.0.lock().unwrap();
227         guard.connect();
228         guard.start_drag(drag_data)
229     }
230 
231     /// Request to listen for events of multi-device cooperation.
register_coordination_listener(&self) -> FusionResult<()>232     pub fn register_coordination_listener(&self) -> FusionResult<()>
233     {
234         let mut guard = self.0.lock().unwrap();
235         guard.connect();
236         guard.register_coordination_listener()
237     }
238 
239     /// Request to stop listening for events of multi-device cooperation.
unregister_coordination_listener(&self) -> FusionResult<()>240     pub fn unregister_coordination_listener(&self) -> FusionResult<()>
241     {
242         let mut guard = self.0.lock().unwrap();
243         guard.connect();
244         guard.unregister_coordination_listener()
245     }
246 
247     /// Request to enable multi-device cooperation.
enable_coordination(&self, user_data: i32) -> FusionResult<()>248     pub fn enable_coordination(&self, user_data: i32) -> FusionResult<()>
249     {
250         let mut guard = self.0.lock().unwrap();
251         guard.connect();
252         guard.enable_coordination(user_data)
253     }
254 
255     /// Request to disable multi-device cooperation.
disable_coordination(&self, user_data: i32) -> FusionResult<()>256     pub fn disable_coordination(&self, user_data: i32) -> FusionResult<()>
257     {
258         let mut guard = self.0.lock().unwrap();
259         guard.connect();
260         guard.disable_coordination(user_data)
261     }
262 
263     /// Request to start multi-device cooperation.
start_coordination(&self, user_data: i32, remote_network_id: &str, start_device_id: i32) -> FusionResult<()>264     pub fn start_coordination(&self, user_data: i32,
265                               remote_network_id: &str,
266                               start_device_id: i32) -> FusionResult<()>
267     {
268         let mut guard = self.0.lock().unwrap();
269         guard.connect();
270         guard.start_coordination(user_data, remote_network_id, start_device_id)
271     }
272 
273     /// Request to stop multi-device cooperation.
stop_coordination(&self, user_data: i32, is_unchained: i32) -> FusionResult<()>274     pub fn stop_coordination(&self, user_data: i32, is_unchained: i32) -> FusionResult<()>
275     {
276         let mut guard = self.0.lock().unwrap();
277         guard.connect();
278         guard.stop_coordination(user_data, is_unchained)
279     }
280 
281     /// Request for current switch status of multi-device cooperation.
get_coordination_state(&self, user_data: i32, device_id: &str) -> FusionResult<i32>282     pub fn get_coordination_state(&self, user_data: i32, device_id: &str) -> FusionResult<i32>
283     {
284         let mut guard = self.0.lock().unwrap();
285         guard.connect();
286         guard.get_coordination_state(user_data, device_id)
287     }
288 }
289