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