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