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 #include "cooperate.h"
17 
18 #ifdef ENABLE_PERFORMANCE_CHECK
19 #include <sstream>
20 #include "utility.h"
21 #endif // ENABLE_PERFORMANCE_CHECK
22 
23 #include "devicestatus_define.h"
24 
25 #undef LOG_TAG
26 #define LOG_TAG "Cooperate"
27 
28 namespace OHOS {
29 namespace Msdp {
30 namespace DeviceStatus {
31 namespace Cooperate {
32 
Cooperate(IContext *env)33 Cooperate::Cooperate(IContext *env)
34     : env_(env), context_(env), sm_(env)
35 {
36     auto [sender, receiver] = Channel<CooperateEvent>::OpenChannel();
37     receiver_ = receiver;
38     receiver_.Enable();
39     context_.AttachSender(sender);
40     context_.Enable();
41     StartWorker();
42 }
43 
~Cooperate()44 Cooperate::~Cooperate()
45 {
46     StopWorker();
47     context_.Disable();
48 }
49 
AddObserver(std::shared_ptr<ICooperateObserver> observer)50 void Cooperate::AddObserver(std::shared_ptr<ICooperateObserver> observer)
51 {
52     CALL_DEBUG_ENTER;
53     auto ret = context_.Sender().Send(CooperateEvent(
54         CooperateEventType::ADD_OBSERVER,
55         AddObserverEvent {
56             .observer = observer
57         }));
58     if (ret != Channel<CooperateEvent>::NO_ERROR) {
59         FI_HILOGE("Failed to send event via channel, error:%{public}d", ret);
60     }
61 }
62 
RemoveObserver(std::shared_ptr<ICooperateObserver> observer)63 void Cooperate::RemoveObserver(std::shared_ptr<ICooperateObserver> observer)
64 {
65     CALL_DEBUG_ENTER;
66     auto ret = context_.Sender().Send(CooperateEvent(
67         CooperateEventType::REMOVE_OBSERVER,
68         RemoveObserverEvent {
69             .observer = observer
70         }));
71     if (ret != Channel<CooperateEvent>::NO_ERROR) {
72         FI_HILOGE("Failed to send event via channel, error:%{public}d", ret);
73     }
74 }
75 
RegisterListener(int32_t pid)76 int32_t Cooperate::RegisterListener(int32_t pid)
77 {
78     CALL_DEBUG_ENTER;
79     auto ret = context_.Sender().Send(CooperateEvent(
80         CooperateEventType::REGISTER_LISTENER,
81         RegisterListenerEvent {
82             .pid = pid
83         }));
84     if (ret != Channel<CooperateEvent>::NO_ERROR) {
85         FI_HILOGE("Failed to send event via channel, error:%{public}d", ret);
86     }
87     return RET_OK;
88 }
89 
UnregisterListener(int32_t pid)90 int32_t Cooperate::UnregisterListener(int32_t pid)
91 {
92     CALL_DEBUG_ENTER;
93     auto ret = context_.Sender().Send(CooperateEvent(
94         CooperateEventType::UNREGISTER_LISTENER,
95         UnregisterListenerEvent {
96             .pid = pid
97         }));
98     if (ret != Channel<CooperateEvent>::NO_ERROR) {
99         FI_HILOGE("Failed to send event via channel, error:%{public}d", ret);
100     }
101     return RET_OK;
102 }
103 
RegisterHotAreaListener(int32_t pid)104 int32_t Cooperate::RegisterHotAreaListener(int32_t pid)
105 {
106     CALL_DEBUG_ENTER;
107     auto ret = context_.Sender().Send(CooperateEvent(
108         CooperateEventType::REGISTER_HOTAREA_LISTENER,
109         RegisterHotareaListenerEvent {
110             .pid = pid
111         }));
112     if (ret != Channel<CooperateEvent>::NO_ERROR) {
113         FI_HILOGE("Failed to send event via channel, error:%{public}d", ret);
114     }
115     return RET_OK;
116 }
117 
UnregisterHotAreaListener(int32_t pid)118 int32_t Cooperate::UnregisterHotAreaListener(int32_t pid)
119 {
120     CALL_DEBUG_ENTER;
121     auto ret = context_.Sender().Send(CooperateEvent(
122         CooperateEventType::UNREGISTER_HOTAREA_LISTENER,
123         UnregisterHotareaListenerEvent {
124             .pid = pid
125         }));
126     if (ret != Channel<CooperateEvent>::NO_ERROR) {
127         FI_HILOGE("Failed to send event via channel, error:%{public}d", ret);
128     }
129     return RET_OK;
130 }
131 
Enable(int32_t tokenId, int32_t pid, int32_t userData)132 int32_t Cooperate::Enable(int32_t tokenId, int32_t pid, int32_t userData)
133 {
134     CALL_DEBUG_ENTER;
135     auto ret = context_.Sender().Send(CooperateEvent(
136         CooperateEventType::ENABLE,
137         EnableCooperateEvent {
138             .tokenId = tokenId,
139             .pid = pid,
140             .userData = userData,
141         }));
142     if (ret != Channel<CooperateEvent>::NO_ERROR) {
143         FI_HILOGE("Failed to send event via channel, error:%{public}d", ret);
144     }
145     return RET_OK;
146 }
147 
Disable(int32_t pid, int32_t userData)148 int32_t Cooperate::Disable(int32_t pid, int32_t userData)
149 {
150     CALL_DEBUG_ENTER;
151     auto ret = context_.Sender().Send(CooperateEvent(
152         CooperateEventType::DISABLE,
153         DisableCooperateEvent {
154             .pid = pid,
155             .userData = userData,
156         }));
157     if (ret != Channel<CooperateEvent>::NO_ERROR) {
158         FI_HILOGE("Failed to send event via channel, error:%{public}d", ret);
159     }
160     return RET_OK;
161 }
162 
Start(int32_t pid, int32_t userData, const std::string &remoteNetworkId, int32_t startDeviceId)163 int32_t Cooperate::Start(int32_t pid, int32_t userData, const std::string &remoteNetworkId, int32_t startDeviceId)
164 {
165     CALL_DEBUG_ENTER;
166 
167 #ifdef ENABLE_PERFORMANCE_CHECK
168     std::ostringstream ss;
169     ss << "start_cooperation_with_" << Utility::Anonymize(remoteNetworkId).c_str();
170     context_.StartTrace(ss.str());
171 #endif // ENABLE_PERFORMANCE_CHECK
172     StartCooperateEvent event {
173         .pid = pid,
174         .userData = userData,
175         .remoteNetworkId = remoteNetworkId,
176         .startDeviceId = startDeviceId,
177         .errCode = std::make_shared<std::promise<int32_t>>(),
178     };
179     auto errCode = event.errCode->get_future();
180     auto ret = context_.Sender().Send(CooperateEvent(CooperateEventType::START, event));
181     if (ret != Channel<CooperateEvent>::NO_ERROR) {
182         FI_HILOGE("Failed to send event via channel, error:%{public}d", ret);
183     }
184     return errCode.get();
185 }
186 
Stop(int32_t pid, int32_t userData, bool isUnchained)187 int32_t Cooperate::Stop(int32_t pid, int32_t userData, bool isUnchained)
188 {
189     CALL_DEBUG_ENTER;
190     auto ret = context_.Sender().Send(CooperateEvent(
191         CooperateEventType::STOP,
192         StopCooperateEvent {
193             .pid = pid,
194             .userData = userData,
195             .isUnchained = isUnchained,
196         }));
197     if (ret != Channel<CooperateEvent>::NO_ERROR) {
198         FI_HILOGE("Failed to send event via channel, error:%{public}d", ret);
199     }
200     return RET_OK;
201 }
202 
GetCooperateState(int32_t pid, int32_t userData, const std::string &networkId)203 int32_t Cooperate::GetCooperateState(int32_t pid, int32_t userData, const std::string &networkId)
204 {
205     CALL_DEBUG_ENTER;
206     auto ret = context_.Sender().Send(CooperateEvent(
207         CooperateEventType::GET_COOPERATE_STATE,
208         GetCooperateStateEvent {
209             .pid = pid,
210             .userData = userData,
211             .networkId = networkId,
212         }));
213     if (ret != Channel<CooperateEvent>::NO_ERROR) {
214         FI_HILOGE("Failed to send event via channel, error:%{public}d", ret);
215     }
216     return RET_OK;
217 }
218 
RegisterEventListener(int32_t pid, const std::string &networkId)219 int32_t Cooperate::RegisterEventListener(int32_t pid, const std::string &networkId)
220 {
221     CALL_DEBUG_ENTER;
222     auto ret = context_.Sender().Send(CooperateEvent(
223         CooperateEventType::REGISTER_EVENT_LISTENER,
224         RegisterEventListenerEvent {
225             .pid = pid,
226             .networkId = networkId,
227         }));
228     if (ret != Channel<CooperateEvent>::NO_ERROR) {
229         FI_HILOGE("Failed to send event via channel, error:%{public}d", ret);
230     }
231     return RET_OK;
232 }
233 
UnregisterEventListener(int32_t pid, const std::string &networkId)234 int32_t Cooperate::UnregisterEventListener(int32_t pid, const std::string &networkId)
235 {
236     CALL_DEBUG_ENTER;
237     auto ret = context_.Sender().Send(CooperateEvent(
238         CooperateEventType::UNREGISTER_EVENT_LISTENER,
239         UnregisterEventListenerEvent {
240             .pid = pid,
241             .networkId = networkId,
242         }));
243     if (ret != Channel<CooperateEvent>::NO_ERROR) {
244         FI_HILOGE("Failed to send event via channel, error:%{public}d", ret);
245     }
246     return RET_OK;
247 }
248 
GetCooperateState(const std::string &udId, bool &state)249 int32_t Cooperate::GetCooperateState(const std::string &udId, bool &state)
250 {
251     CALL_DEBUG_ENTER;
252     state = sm_.IsCooperateEnable();
253     return RET_OK;
254 }
255 
Update(uint32_t mask, uint32_t flag)256 int32_t Cooperate::Update(uint32_t mask, uint32_t flag)
257 {
258     auto ret = context_.Sender().Send(CooperateEvent(
259         CooperateEventType::UPDATE_COOPERATE_FLAG,
260         UpdateCooperateFlagEvent {
261             .mask = mask,
262             .flag = flag,
263         }));
264     if (ret != Channel<CooperateEvent>::NO_ERROR) {
265         FI_HILOGE("Failed to send event via channel, error:%{public}d", ret);
266     }
267     return RET_OK;
268 }
269 
SetDamplingCoefficient(uint32_t direction, double coefficient)270 int32_t Cooperate::SetDamplingCoefficient(uint32_t direction, double coefficient)
271 {
272     auto ret = context_.Sender().Send(CooperateEvent(
273         CooperateEventType::SET_DAMPLING_COEFFICIENT,
274         SetDamplingCoefficientEvent {
275             .direction = direction,
276             .coefficient = coefficient,
277         }));
278     if (ret != Channel<CooperateEvent>::NO_ERROR) {
279         FI_HILOGE("Failed to send event via channel, error:%{public}d", ret);
280     }
281     return RET_OK;
282 }
283 
Dump(int32_t fd)284 void Cooperate::Dump(int32_t fd)
285 {
286     CALL_DEBUG_ENTER;
287     auto ret = context_.Sender().Send(CooperateEvent(
288         CooperateEventType::DUMP,
289         DumpEvent {
290             .fd = fd
291         }));
292     if (ret != Channel<CooperateEvent>::NO_ERROR) {
293         FI_HILOGE("Failed to send event via channel, error:%{public}d", ret);
294     }
295 }
296 
Loop()297 void Cooperate::Loop()
298 {
299     CALL_DEBUG_ENTER;
300     bool running = true;
301     SetThreadName("OS_Cooperate");
302     LoadMotionDrag();
303 
304     while (running) {
305         CooperateEvent event = receiver_.Receive();
306         switch (event.type) {
307             case CooperateEventType::NOOP: {
308                 break;
309             }
310             case CooperateEventType::QUIT: {
311                 FI_HILOGI("Skip out of loop");
312                 running = false;
313                 break;
314             }
315             case CooperateEventType::SET_DAMPLING_COEFFICIENT: {
316                 SetDamplingCoefficient(event);
317                 break;
318             }
319             default: {
320                 sm_.OnEvent(context_, event);
321                 break;
322             }
323         }
324     }
325 }
326 
StartWorker()327 void Cooperate::StartWorker()
328 {
329     CALL_DEBUG_ENTER;
330     std::lock_guard guard(lock_);
331     if (!workerStarted_) {
332         workerStarted_ = true;
333         worker_ = std::thread([this] { this->Loop(); });
334     }
335 }
336 
StopWorker()337 void Cooperate::StopWorker()
338 {
339     CALL_DEBUG_ENTER;
340     std::lock_guard guard(lock_);
341     if (workerStarted_) {
342         auto ret = context_.Sender().Send(CooperateEvent(CooperateEventType::QUIT));
343         if (ret != Channel<CooperateEvent>::NO_ERROR) {
344             FI_HILOGE("Failed to send event via channel, error:%{public}d", ret);
345         }
346         if (worker_.joinable()) {
347             worker_.join();
348         }
349         workerStarted_ = false;
350     }
351 }
352 
LoadMotionDrag()353 void Cooperate::LoadMotionDrag()
354 {
355     FI_HILOGI("Load 'MotionDrag' module");
356     IMotionDrag *motionDrag = env_->GetPluginManager().LoadMotionDrag();
357     if (motionDrag == nullptr) {
358         FI_HILOGE("Failed to load motion drag");
359         return;
360     }
361     motionDrag->Enable(context_.EventHandler());
362 }
363 
SetDamplingCoefficient(const CooperateEvent &event)364 void Cooperate::SetDamplingCoefficient(const CooperateEvent &event)
365 {
366     SetDamplingCoefficientEvent notice = std::get<SetDamplingCoefficientEvent>(event.event);
367     context_.inputEventBuilder_.SetDamplingCoefficient(notice.direction, notice.coefficient);
368 }
369 
CreateInstance(IContext *env)370 extern "C" ICooperate* CreateInstance(IContext *env)
371 {
372     CHKPP(env);
373     return new Cooperate(env);
374 }
375 
DestroyInstance(ICooperate *instance)376 extern "C" void DestroyInstance(ICooperate *instance)
377 {
378     if (instance != nullptr) {
379         delete instance;
380     }
381 }
382 } // namespace Cooperate
383 } // namespace DeviceStatus
384 } // namespace Msdp
385 } // namespace OHOS