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