• 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,const int32_t uid)164 int32_t Cooperate::Start(int32_t pid, int32_t userData, const std::string &remoteNetworkId,
165     int32_t startDeviceId, const int32_t uid)
166 {
167     CALL_DEBUG_ENTER;
168     CooperateRadarInfo radarInfo {
169         .funcName =  __FUNCTION__,
170         .bizState = static_cast<int32_t> (BizState::STATE_END),
171         .bizScene = static_cast<int32_t> (BizCooperateScene::SCENE_ACTIVE),
172         .hostName = "",
173         .localNetId = Utility::DFXRadarAnonymize(context_.Local().c_str()),
174         .peerNetId = Utility::DFXRadarAnonymize(remoteNetworkId.c_str())
175     };
176     if (!sm_.IsCooperateEnable()) {
177         radarInfo.bizStage =  static_cast<int32_t> (BizCooperateStage::STAGE_CHECK_LOCAL_SWITCH);
178         radarInfo.stageRes = static_cast<int32_t> (BizCooperateStageRes::RES_FAIL);
179         radarInfo.errCode = static_cast<int32_t> (CooperateRadarErrCode::CHECK_LOCAL_SWITCH_FAILED);
180         CooperateRadar::ReportCooperateRadarInfo(radarInfo);
181     }
182 #ifdef ENABLE_PERFORMANCE_CHECK
183     std::ostringstream ss;
184     ss << "start_cooperation_with_" << Utility::Anonymize(remoteNetworkId).c_str();
185     context_.StartTrace(ss.str());
186 #endif // ENABLE_PERFORMANCE_CHECK
187     StartCooperateEvent event {
188         .pid = pid,
189         .userData = userData,
190         .remoteNetworkId = remoteNetworkId,
191         .startDeviceId = startDeviceId,
192         .errCode = std::make_shared<std::promise<int32_t>>(),
193         .uid = uid,
194     };
195     auto errCode = event.errCode->get_future();
196     auto ret = context_.Sender().Send(CooperateEvent(CooperateEventType::START, event));
197     if (ret != Channel<CooperateEvent>::NO_ERROR) {
198         FI_HILOGE("Failed to send event via channel, error:%{public}d", ret);
199     }
200     if (ret != RET_OK) {
201         radarInfo.bizStage = static_cast<int32_t> (BizCooperateStage::STAGE_CALLING_COOPERATE);
202         radarInfo.stageRes = static_cast<int32_t> (BizCooperateStageRes::RES_FAIL);
203         radarInfo.errCode = static_cast<int32_t> (CooperateRadarErrCode::CALLING_COOPERATE_FAILED);
204         CooperateRadar::ReportCooperateRadarInfo(radarInfo);
205     };
206     radarInfo.bizState = static_cast<int32_t> (BizState::STATE_BEGIN),
207     radarInfo.stageRes = static_cast<int32_t> (BizCooperateStageRes::RES_SUCCESS),
208     radarInfo.errCode = static_cast<int32_t> (CooperateRadarErrCode::CALLING_COOPERATE_SUCCESS),
209     CooperateRadar::ReportCooperateRadarInfo(radarInfo);
210     return errCode.get();
211 }
212 
Stop(int32_t pid,int32_t userData,bool isUnchained)213 int32_t Cooperate::Stop(int32_t pid, int32_t userData, bool isUnchained)
214 {
215     CALL_DEBUG_ENTER;
216     auto ret = context_.Sender().Send(CooperateEvent(
217         CooperateEventType::STOP,
218         StopCooperateEvent {
219             .pid = pid,
220             .userData = userData,
221             .isUnchained = isUnchained,
222         }));
223     if (ret != Channel<CooperateEvent>::NO_ERROR) {
224         FI_HILOGE("Failed to send event via channel, error:%{public}d", ret);
225     }
226     return RET_OK;
227 }
228 
StartWithOptions(int32_t pid,int32_t userData,const std::string & remoteNetworkId,int32_t startDeviceId,const CooperateOptions & options)229 int32_t Cooperate::StartWithOptions(int32_t pid, int32_t userData, const std::string &remoteNetworkId,
230     int32_t startDeviceId, const CooperateOptions &options)
231 {
232     CALL_DEBUG_ENTER;
233     CooperateRadarInfo radarInfo {
234         .funcName =  __FUNCTION__,
235         .bizState = static_cast<int32_t> (BizState::STATE_END),
236         .bizScene = static_cast<int32_t> (BizCooperateScene::SCENE_ACTIVE),
237         .hostName = "",
238         .localNetId = Utility::DFXRadarAnonymize(context_.Local().c_str()),
239         .peerNetId = Utility::DFXRadarAnonymize(remoteNetworkId.c_str())
240     };
241     if (!sm_.IsCooperateEnable()) {
242         radarInfo.bizStage =  static_cast<int32_t> (BizCooperateStage::STAGE_CHECK_LOCAL_SWITCH);
243         radarInfo.stageRes = static_cast<int32_t> (BizCooperateStageRes::RES_FAIL);
244         radarInfo.errCode = static_cast<int32_t> (CooperateRadarErrCode::CHECK_LOCAL_SWITCH_FAILED);
245         CooperateRadar::ReportCooperateRadarInfo(radarInfo);
246     }
247 #ifdef ENABLE_PERFORMANCE_CHECK
248     std::ostringstream ss;
249     ss << "start_cooperation_with_" << Utility::Anonymize(remoteNetworkId).c_str();
250     context_.StartTrace(ss.str());
251 #endif // ENABLE_PERFORMANCE_CHECK
252     StartWithOptionsEvent event {
253         .pid = pid,
254         .userData = userData,
255         .remoteNetworkId = remoteNetworkId,
256         .startDeviceId = startDeviceId,
257         .displayX = options.displayX,
258         .displayY = options.displayY,
259         .displayId = options.displayId,
260         .errCode = std::make_shared<std::promise<int32_t>>(),
261     };
262     FI_HILOGI("Server start cooperate,displayX:%{private}d,displayY:%{private}d,displayId:%{public}d",
263         event.displayX, event.displayY, event.displayId);
264     auto errCode = event.errCode->get_future();
265     auto ret = context_.Sender().Send(CooperateEvent(CooperateEventType::WITH_OPTIONS_START, event));
266     if (ret != Channel<CooperateEvent>::NO_ERROR) {
267         FI_HILOGE("Failed to send event via channel, error:%{public}d", ret);
268     }
269     if (ret != RET_OK) {
270         radarInfo.bizStage = static_cast<int32_t> (BizCooperateStage::STAGE_CALLING_COOPERATE);
271         radarInfo.stageRes = static_cast<int32_t> (BizCooperateStageRes::RES_FAIL);
272         radarInfo.errCode = static_cast<int32_t> (CooperateRadarErrCode::CALLING_COOPERATE_FAILED);
273         CooperateRadar::ReportCooperateRadarInfo(radarInfo);
274     };
275     radarInfo.bizState = static_cast<int32_t> (BizState::STATE_BEGIN),
276     radarInfo.stageRes = static_cast<int32_t> (BizCooperateStageRes::RES_SUCCESS),
277     radarInfo.errCode = static_cast<int32_t> (CooperateRadarErrCode::CALLING_COOPERATE_SUCCESS),
278     CooperateRadar::ReportCooperateRadarInfo(radarInfo);
279     return errCode.get();
280 }
281 
GetCooperateState(int32_t pid,int32_t userData,const std::string & networkId)282 int32_t Cooperate::GetCooperateState(int32_t pid, int32_t userData, const std::string &networkId)
283 {
284     CALL_DEBUG_ENTER;
285     auto ret = context_.Sender().Send(CooperateEvent(
286         CooperateEventType::GET_COOPERATE_STATE,
287         GetCooperateStateEvent {
288             .pid = pid,
289             .userData = userData,
290             .networkId = networkId,
291         }));
292     if (ret != Channel<CooperateEvent>::NO_ERROR) {
293         FI_HILOGE("Failed to send event via channel, error:%{public}d", ret);
294     }
295     return RET_OK;
296 }
297 
RegisterEventListener(int32_t pid,const std::string & networkId)298 int32_t Cooperate::RegisterEventListener(int32_t pid, const std::string &networkId)
299 {
300     CALL_DEBUG_ENTER;
301     auto ret = context_.Sender().Send(CooperateEvent(
302         CooperateEventType::REGISTER_EVENT_LISTENER,
303         RegisterEventListenerEvent {
304             .pid = pid,
305             .networkId = networkId,
306         }));
307     if (ret != Channel<CooperateEvent>::NO_ERROR) {
308         FI_HILOGE("Failed to send event via channel, error:%{public}d", ret);
309     }
310     return RET_OK;
311 }
312 
UnregisterEventListener(int32_t pid,const std::string & networkId)313 int32_t Cooperate::UnregisterEventListener(int32_t pid, const std::string &networkId)
314 {
315     CALL_DEBUG_ENTER;
316     auto ret = context_.Sender().Send(CooperateEvent(
317         CooperateEventType::UNREGISTER_EVENT_LISTENER,
318         UnregisterEventListenerEvent {
319             .pid = pid,
320             .networkId = networkId,
321         }));
322     if (ret != Channel<CooperateEvent>::NO_ERROR) {
323         FI_HILOGE("Failed to send event via channel, error:%{public}d", ret);
324     }
325     return RET_OK;
326 }
327 
GetCooperateState(const std::string & udId,bool & state)328 int32_t Cooperate::GetCooperateState(const std::string &udId, bool &state)
329 {
330     CALL_DEBUG_ENTER;
331     state = sm_.IsCooperateEnable();
332     return RET_OK;
333 }
334 
Update(uint32_t mask,uint32_t flag)335 int32_t Cooperate::Update(uint32_t mask, uint32_t flag)
336 {
337     auto ret = context_.Sender().Send(CooperateEvent(
338         CooperateEventType::UPDATE_COOPERATE_FLAG,
339         UpdateCooperateFlagEvent {
340             .mask = mask,
341             .flag = flag,
342         }));
343     if (ret != Channel<CooperateEvent>::NO_ERROR) {
344         FI_HILOGE("Failed to send event via channel, error:%{public}d", ret);
345     }
346     return RET_OK;
347 }
348 
SetDamplingCoefficient(uint32_t direction,double coefficient)349 int32_t Cooperate::SetDamplingCoefficient(uint32_t direction, double coefficient)
350 {
351     auto ret = context_.Sender().Send(CooperateEvent(
352         CooperateEventType::SET_DAMPLING_COEFFICIENT,
353         SetDamplingCoefficientEvent {
354             .direction = direction,
355             .coefficient = coefficient,
356         }));
357     if (ret != Channel<CooperateEvent>::NO_ERROR) {
358         FI_HILOGE("Failed to send event via channel, error:%{public}d", ret);
359     }
360     return RET_OK;
361 }
362 
Dump(int32_t fd)363 void Cooperate::Dump(int32_t fd)
364 {
365     CALL_DEBUG_ENTER;
366     auto ret = context_.Sender().Send(CooperateEvent(
367         CooperateEventType::DUMP,
368         DumpEvent {
369             .fd = fd
370         }));
371     if (ret != Channel<CooperateEvent>::NO_ERROR) {
372         FI_HILOGE("Failed to send event via channel, error:%{public}d", ret);
373     }
374 }
375 
Loop()376 void Cooperate::Loop()
377 {
378     CALL_DEBUG_ENTER;
379     bool running = true;
380     SetThreadName("OS_Cooperate");
381     LoadMotionDrag();
382 
383     while (running) {
384         CooperateEvent event = receiver_.Receive();
385         switch (event.type) {
386             case CooperateEventType::NOOP: {
387                 break;
388             }
389             case CooperateEventType::QUIT: {
390                 FI_HILOGI("Skip out of loop");
391                 running = false;
392                 break;
393             }
394             case CooperateEventType::SET_DAMPLING_COEFFICIENT: {
395                 SetDamplingCoefficient(event);
396                 break;
397             }
398             default: {
399                 sm_.OnEvent(context_, event);
400                 break;
401             }
402         }
403     }
404 }
405 
StartWorker()406 void Cooperate::StartWorker()
407 {
408     CALL_DEBUG_ENTER;
409     std::lock_guard guard(lock_);
410     if (!workerStarted_) {
411         workerStarted_ = true;
412         worker_ = std::thread([this] { this->Loop(); });
413     }
414 }
415 
StopWorker()416 void Cooperate::StopWorker()
417 {
418     CALL_DEBUG_ENTER;
419     std::lock_guard guard(lock_);
420     if (workerStarted_) {
421         auto ret = context_.Sender().Send(CooperateEvent(CooperateEventType::QUIT));
422         if (ret != Channel<CooperateEvent>::NO_ERROR) {
423             FI_HILOGE("Failed to send event via channel, error:%{public}d", ret);
424         }
425         if (worker_.joinable()) {
426             worker_.join();
427         }
428         workerStarted_ = false;
429     }
430 }
431 
LoadMotionDrag()432 void Cooperate::LoadMotionDrag()
433 {
434     FI_HILOGI("Load 'MotionDrag' module");
435     CHKPV(env_);
436     IMotionDrag *motionDrag = env_->GetPluginManager().LoadMotionDrag();
437     if (motionDrag == nullptr) {
438         FI_HILOGE("Failed to load motion drag");
439         return;
440     }
441     motionDrag->Enable(context_.EventHandler());
442 }
443 
SetDamplingCoefficient(const CooperateEvent & event)444 void Cooperate::SetDamplingCoefficient(const CooperateEvent &event)
445 {
446     SetDamplingCoefficientEvent notice = std::get<SetDamplingCoefficientEvent>(event.event);
447     context_.inputEventBuilder_.SetDamplingCoefficient(notice.direction, notice.coefficient);
448 }
449 
CreateInstance(IContext * env)450 extern "C" ICooperate* CreateInstance(IContext *env)
451 {
452     CHKPP(env);
453     return new Cooperate(env);
454 }
455 
DestroyInstance(ICooperate * instance)456 extern "C" void DestroyInstance(ICooperate *instance)
457 {
458     if (instance != nullptr) {
459         delete instance;
460     }
461 }
462 } // namespace Cooperate
463 } // namespace DeviceStatus
464 } // namespace Msdp
465 } // namespace OHOS