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_out.h"
17 #include "cooperate_hisysevent.h"
18
19 #include "devicestatus_define.h"
20 #include "utility.h"
21
22 #undef LOG_TAG
23 #define LOG_TAG "CooperateOut"
24
25 namespace OHOS {
26 namespace Msdp {
27 namespace DeviceStatus {
28 namespace Cooperate {
29
CooperateOut(IStateMachine & parent,IContext * env)30 CooperateOut::CooperateOut(IStateMachine &parent, IContext *env)
31 : ICooperateState(parent), env_(env)
32 {
33 initial_ = std::make_shared<Initial>(*this);
34 Initial::BuildChains(initial_, *this);
35 current_ = initial_;
36 }
37
~CooperateOut()38 CooperateOut::~CooperateOut()
39 {
40 Initial::RemoveChains(initial_);
41 }
42
OnEvent(Context & context,const CooperateEvent & event)43 void CooperateOut::OnEvent(Context &context, const CooperateEvent &event)
44 {
45 current_->OnEvent(context, event);
46 }
47
OnEnterState(Context & context)48 void CooperateOut::OnEnterState(Context &context)
49 {
50 CALL_INFO_TRACE;
51 int32_t ret = env_->GetInput().SetPointerVisibility(false);
52 if (ret != RET_OK) {
53 CooperateRadarInfo radarInfo {
54 .funcName = __FUNCTION__,
55 .bizState = static_cast<int32_t> (BizState::STATE_IDLE),
56 .bizStage = static_cast<int32_t> (BizCooperateStage::STAGE_SET_CURSOR_VISIBILITY),
57 .stageRes = static_cast<int32_t> (BizCooperateStageRes::RES_FAIL),
58 .bizScene = static_cast<int32_t> (BizCooperateScene::SCENE_ACTIVE),
59 .errCode = static_cast<int32_t> (CooperateRadarErrCode::SET_CURSOR_VISIBILITY_FAILED),
60 .hostName = "",
61 .localNetId = "",
62 .peerNetId = ""
63 };
64 CooperateRadar::ReportCooperateRadarInfo(radarInfo);
65 }
66 }
67
OnLeaveState(Context & context)68 void CooperateOut::OnLeaveState(Context &context)
69 {
70 CALL_INFO_TRACE;
71 SetPointerVisible(context);
72 }
73
SetPointerVisible(Context & context)74 void CooperateOut::SetPointerVisible(Context &context)
75 {
76 CHKPV(env_);
77 bool hasLocalPointerDevice = env_->GetDeviceManager().HasLocalPointerDevice() ||
78 env_->GetInput().HasLocalPointerDevice();
79 bool visible = !context.NeedHideCursor() && hasLocalPointerDevice;
80 FI_HILOGI("Set pointer visible:%{public}s, HasLocalPointerDevice:%{public}s",
81 visible ? "true" : "false", hasLocalPointerDevice ? "true" : "false");
82 env_->GetInput().SetPointerVisibility(visible, PRIORITY);
83 }
84
SimulateShowPointerEvent()85 void CooperateOut::SimulateShowPointerEvent()
86 {
87 CALL_INFO_TRACE;
88 CHKPV(env_);
89 auto pointerEvent = OHOS::MMI::PointerEvent::Create();
90 OHOS::MMI::PointerEvent::PointerItem item;
91 item.SetPointerId(0);
92 item.SetRawDx(0);
93 item.SetRawDy(0);
94 CHKPV(pointerEvent);
95 pointerEvent->SetPointerAction(OHOS::MMI::PointerEvent::POINTER_ACTION_MOVE);
96 pointerEvent->AddFlag(OHOS::MMI::InputEvent::EVENT_FLAG_RAW_POINTER_MOVEMENT);
97 pointerEvent->SetPointerId(0);
98 pointerEvent->SetSourceType(OHOS::MMI::PointerEvent::SOURCE_TYPE_MOUSE);
99 pointerEvent->AddPointerItem(item);
100 env_->GetInput().SimulateInputEvent(pointerEvent);
101 }
102
BuildChains(std::shared_ptr<Initial> self,CooperateOut & parent)103 void CooperateOut::Initial::BuildChains(std::shared_ptr<Initial> self, CooperateOut &parent)
104 {}
105
RemoveChains(std::shared_ptr<Initial> self)106 void CooperateOut::Initial::RemoveChains(std::shared_ptr<Initial> self)
107 {}
108
Initial(CooperateOut & parent)109 CooperateOut::Initial::Initial(CooperateOut &parent)
110 : ICooperateStep(parent, nullptr), parent_(parent)
111 {
112 AddHandler(CooperateEventType::DISABLE, [this](Context &context, const CooperateEvent &event) {
113 this->OnDisable(context, event);
114 });
115 AddHandler(CooperateEventType::START, [this](Context &context, const CooperateEvent &event) {
116 this->OnStart(context, event);
117 });
118 AddHandler(CooperateEventType::WITH_OPTIONS_START, [this](Context &context, const CooperateEvent &event) {
119 this->OnStartWithOptions(context, event);
120 });
121 AddHandler(CooperateEventType::STOP, [this](Context &context, const CooperateEvent &event) {
122 this->OnStop(context, event);
123 });
124 AddHandler(CooperateEventType::APP_CLOSED, [this](Context &context, const CooperateEvent &event) {
125 this->OnAppClosed(context, event);
126 });
127 AddHandler(CooperateEventType::INPUT_HOTPLUG_EVENT, [this](Context &context, const CooperateEvent &event) {
128 this->OnHotplug(context, event);
129 });
130 AddHandler(CooperateEventType::INPUT_POINTER_EVENT, [this](Context &context, const CooperateEvent &event) {
131 this->OnPointerEvent(context, event);
132 });
133 AddHandler(CooperateEventType::DDM_BOARD_OFFLINE, [this](Context &context, const CooperateEvent &event) {
134 this->OnBoardOffline(context, event);
135 });
136 AddHandler(CooperateEventType::DDP_COOPERATE_SWITCH_CHANGED,
137 [this](Context &context, const CooperateEvent &event) {
138 this->OnSwitchChanged(context, event);
139 });
140 AddHandler(CooperateEventType::DSOFTBUS_SESSION_CLOSED,
141 [this](Context &context, const CooperateEvent &event) {
142 this->OnSoftbusSessionClosed(context, event);
143 });
144 AddHandler(CooperateEventType::DSOFTBUS_COME_BACK,
145 [this](Context &context, const CooperateEvent &event) {
146 this->OnComeBack(context, event);
147 });
148 AddHandler(CooperateEventType::DSOFTBUS_START_COOPERATE,
149 [this](Context &context, const CooperateEvent &event) {
150 this->OnRemoteStart(context, event);
151 });
152 AddHandler(CooperateEventType::DSOFTBUS_STOP_COOPERATE,
153 [this](Context &context, const CooperateEvent &event) {
154 this->OnRemoteStop(context, event);
155 });
156 AddHandler(CooperateEventType::DSOFTBUS_RELAY_COOPERATE,
157 [this](Context &context, const CooperateEvent &event) {
158 this->OnRelay(context, event);
159 });
160 AddHandler(CooperateEventType::DSOFTBUS_COOPERATE_WITH_OPTIONS,
161 [this](Context &context, const CooperateEvent &event) {
162 this->OnRemoteStartWithOptions(context, event);
163 });
164 AddHandler(CooperateEventType::DSOFTBUS_COME_BACK_WITH_OPTIONS,
165 [this](Context &context, const CooperateEvent &event) {
166 this->OnComeBackWithOptions(context, event);
167 });
168 AddHandler(CooperateEventType::DSOFTBUS_RELAY_COOPERATE_WITHOPTIONS,
169 [this](Context &context, const CooperateEvent &event) {
170 this->OnRelayWithOptions(context, event);
171 });
172 }
173
OnDisable(Context & context,const CooperateEvent & event)174 void CooperateOut::Initial::OnDisable(Context &context, const CooperateEvent &event)
175 {
176 FI_HILOGI("[disable cooperation] Stop cooperation");
177 parent_.StopCooperate(context, event);
178 }
179
OnStart(Context & context,const CooperateEvent & event)180 void CooperateOut::Initial::OnStart(Context &context, const CooperateEvent &event)
181 {
182 StartCooperateEvent param = std::get<StartCooperateEvent>(event.event);
183
184 if (parent_.env_->GetDragManager().GetDragState() == DragState::MOTION_DRAGGING) {
185 FI_HILOGE("Not allow cooperate");
186 NotAollowCooperateWhenMotionDragging result {
187 .pid = param.pid,
188 .userData = param.userData,
189 .networkId = param.remoteNetworkId,
190 .success = false,
191 .errCode = static_cast<int32_t>(CoordinationErrCode::NOT_AOLLOW_COOPERATE_WHEN_MOTION_DRAGGING)
192 };
193 context.eventMgr_.ErrorNotAollowCooperateWhenMotionDragging(result);
194 return;
195 }
196 context.eventMgr_.StartCooperate(param);
197 FI_HILOGI("[start] Start cooperation with \'%{public}s\', report success when out",
198 Utility::Anonymize(context.Peer()).c_str());
199 DSoftbusStartCooperateFinished failNotice {
200 .success = false,
201 .errCode = static_cast<int32_t>(CoordinationErrCode::UNEXPECTED_START_CALL)
202 };
203 context.eventMgr_.StartCooperateFinish(failNotice);
204 }
205
OnStartWithOptions(Context & context,const CooperateEvent & event)206 void CooperateOut::Initial::OnStartWithOptions(Context &context, const CooperateEvent &event)
207 {
208 StartWithOptionsEvent param = std::get<StartWithOptionsEvent>(event.event);
209
210 context.eventMgr_.StartCooperateWithOptions(param);
211 FI_HILOGI("[start] Start cooperation with Options\'%{public}s\', report success when out",
212 Utility::Anonymize(context.Peer()).c_str());
213 DSoftbusCooperateOptions failNotice {
214 .success = false,
215 .errCode = static_cast<int32_t>(CoordinationErrCode::UNEXPECTED_START_CALL)
216 };
217 context.eventMgr_.StartCooperateWithOptinsFinish(failNotice);
218 }
219
OnStop(Context & context,const CooperateEvent & event)220 void CooperateOut::Initial::OnStop(Context &context, const CooperateEvent &event)
221 {
222 StopCooperateEvent param = std::get<StopCooperateEvent>(event.event);
223
224 context.eventMgr_.StopCooperate(param);
225 FI_HILOGI("[stop] Stop cooperation with \'%{public}s\', unchain:%{public}d",
226 Utility::Anonymize(context.Peer()).c_str(), param.isUnchained);
227 parent_.StopCooperate(context, event);
228
229 param.networkId = context.Peer();
230 DSoftbusStopCooperateFinished notice {
231 .networkId = context.Peer(),
232 .normal = true,
233 };
234 context.eventMgr_.StopCooperateFinish(notice);
235
236 parent_.UnchainConnections(context, param);
237 }
238
OnComeBack(Context & context,const CooperateEvent & event)239 void CooperateOut::Initial::OnComeBack(Context &context, const CooperateEvent &event)
240 {
241 CALL_INFO_TRACE;
242 DSoftbusComeBack notice = std::get<DSoftbusComeBack>(event.event);
243
244 if (!context.IsPeer(notice.networkId)) {
245 return;
246 }
247 FI_HILOGI("[come back] From \'%{public}s\'", Utility::Anonymize(notice.networkId).c_str());
248 context.OnRemoteStartCooperate(notice.extra);
249 DSoftbusStartCooperate startEvent {
250 .networkId = notice.networkId,
251 };
252 context.eventMgr_.RemoteStart(startEvent);
253 context.inputEventInterceptor_.Disable();
254
255 context.RemoteStartSuccess(notice);
256 context.eventMgr_.RemoteStartFinish(notice);
257 TransiteTo(context, CooperateState::COOPERATE_STATE_FREE);
258 context.OnBack();
259 if (!context.NeedHideCursor()) {
260 parent_.SimulateShowPointerEvent();
261 }
262 }
263
OnComeBackWithOptions(Context & context,const CooperateEvent & event)264 void CooperateOut::Initial::OnComeBackWithOptions(Context &context, const CooperateEvent &event)
265 {
266 CALL_INFO_TRACE;
267 DSoftbusCooperateOptions notice = std::get<DSoftbusCooperateOptions>(event.event);
268
269 if (!context.IsPeer(notice.networkId)) {
270 return;
271 }
272 FI_HILOGI("[come back cooperate with options] From \'%{public}s\'", Utility::Anonymize(notice.networkId).c_str());
273 context.OnRemoteStartCooperate(notice.extra);
274 DSoftbusStartCooperate startEvent{
275 .networkId = notice.networkId,
276 };
277 context.eventMgr_.RemoteStart(startEvent);
278 context.inputEventInterceptor_.Disable();
279
280 context.OnRemoteStart(notice);
281 context.eventMgr_.RemoteStartWithOptionsFinish(notice);
282 TransiteTo(context, CooperateState::COOPERATE_STATE_FREE);
283 context.OnBack();
284 }
285
OnRemoteStart(Context & context,const CooperateEvent & event)286 void CooperateOut::Initial::OnRemoteStart(Context &context, const CooperateEvent &event)
287 {
288 DSoftbusStartCooperate notice = std::get<DSoftbusStartCooperate>(event.event);
289
290 if (context.IsLocal(notice.networkId)) {
291 return;
292 }
293 FI_HILOGI("[remote start] Request from \'%{public}s\'", Utility::Anonymize(notice.networkId).c_str());
294 if (context.IsPeer(notice.networkId)) {
295 FI_HILOGI("[remote start] Reset on request from peer");
296 parent_.StopCooperate(context, event);
297 return;
298 }
299 context.OnResetCooperation();
300 context.OnRemoteStartCooperate(notice.extra);
301 context.eventMgr_.RemoteStart(notice);
302 context.inputEventInterceptor_.Disable();
303
304 DSoftbusStopCooperate stopNotice {};
305 context.dsoftbus_.StopCooperate(context.Peer(), stopNotice);
306
307 context.RemoteStartSuccess(notice);
308 context.inputEventBuilder_.Enable(context);
309 context.eventMgr_.RemoteStartFinish(notice);
310 FI_HILOGI("[remote start] Cooperation with \'%{public}s\' established", Utility::Anonymize(context.Peer()).c_str());
311 TransiteTo(context, CooperateState::COOPERATE_STATE_IN);
312 context.OnTransitionIn();
313 }
314
OnRemoteStartWithOptions(Context & context,const CooperateEvent & event)315 void CooperateOut::Initial::OnRemoteStartWithOptions(Context &context, const CooperateEvent &event)
316 {
317 DSoftbusCooperateOptions notice = std::get<DSoftbusCooperateOptions>(event.event);
318 if (context.IsLocal(notice.networkId)) {
319 return;
320 }
321 FI_HILOGI("[remote start cooperate with options ] Request from '%{public}s'",
322 Utility::Anonymize(notice.networkId).c_str());
323 if (context.IsPeer(notice.networkId)) {
324 FI_HILOGI("[remote start] Reset on request from peer");
325 parent_.StopCooperate(context, event);
326 return;
327 }
328 context.OnResetCooperation();
329 context.OnRemoteStartCooperate(notice.extra);
330 context.eventMgr_.RemoteStartWithOptions(notice);
331 context.inputEventInterceptor_.Disable();
332
333 DSoftbusStopCooperate stopNotice{};
334 context.dsoftbus_.StopCooperate(context.Peer(), stopNotice);
335
336 context.OnRemoteStart(notice);
337 context.inputEventBuilder_.Enable(context);
338 context.eventMgr_.RemoteStartWithOptionsFinish(notice);
339 FI_HILOGI("[remote start] Cooperation with \'%{public}s\' established", Utility::Anonymize(context.Peer()).c_str());
340 TransiteTo(context, CooperateState::COOPERATE_STATE_IN);
341 context.OnTransitionIn();
342 }
343
OnRemoteStop(Context & context,const CooperateEvent & event)344 void CooperateOut::Initial::OnRemoteStop(Context &context, const CooperateEvent &event)
345 {
346 DSoftbusStopCooperate notice = std::get<DSoftbusStopCooperate>(event.event);
347
348 if (!context.IsPeer(notice.networkId)) {
349 return;
350 }
351 FI_HILOGI("[remote stop] Notification from \'%{public}s\'", Utility::Anonymize(notice.networkId).c_str());
352 context.eventMgr_.RemoteStop(notice);
353 context.inputEventInterceptor_.Disable();
354 context.ResetCursorPosition();
355 context.eventMgr_.RemoteStopFinish(notice);
356 TransiteTo(context, CooperateState::COOPERATE_STATE_FREE);
357 context.OnResetCooperation();
358 }
359
OnRelay(Context & context,const CooperateEvent & event)360 void CooperateOut::Initial::OnRelay(Context &context, const CooperateEvent &event)
361 {
362 DSoftbusRelayCooperate notice = std::get<DSoftbusRelayCooperate>(event.event);
363 if (!context.IsPeer(notice.networkId)) {
364 return;
365 }
366 DSoftbusRelayCooperateFinished resp {
367 .targetNetworkId = notice.targetNetworkId,
368 };
369
370 int32_t ret = context.dsoftbus_.OpenSession(notice.targetNetworkId);
371 if (ret != RET_OK) {
372 FI_HILOGE("[relay cooperate] Failed to connect to \'%{public}s\'",
373 Utility::Anonymize(notice.targetNetworkId).c_str());
374 resp.normal = false;
375 context.dsoftbus_.RelayCooperateFinish(notice.networkId, resp);
376 return;
377 }
378
379 resp.normal = true;
380 context.dsoftbus_.RelayCooperateFinish(notice.networkId, resp);
381
382 context.RelayCooperate(notice);
383 context.inputEventInterceptor_.Update(context);
384 FI_HILOGI("[relay cooperate] Relay cooperation to \'%{public}s\'", Utility::Anonymize(context.Peer()).c_str());
385 context.OnRelayCooperation(context.Peer(), context.NormalizedCursorPosition());
386 }
387
OnRelayWithOptions(Context & context,const CooperateEvent & event)388 void CooperateOut::Initial::OnRelayWithOptions(Context &context, const CooperateEvent &event)
389 {
390 DSoftbusRelayCooperate notice = std::get<DSoftbusRelayCooperate>(event.event);
391 if (!context.IsPeer(notice.networkId)) {
392 return;
393 }
394 DSoftbusRelayCooperateFinished resp {
395 .targetNetworkId = notice.targetNetworkId,
396 };
397
398 int32_t ret = context.dsoftbus_.OpenSession(notice.targetNetworkId);
399 if (ret != RET_OK) {
400 FI_HILOGE("[relay cooperate] Failed to connect to \'%{public}s\'",
401 Utility::Anonymize(notice.targetNetworkId).c_str());
402 resp.normal = false;
403 context.dsoftbus_.RelayCooperateWithOptionsFinish(notice.networkId, resp);
404 return;
405 }
406
407 resp.normal = true;
408 context.dsoftbus_.RelayCooperateWithOptionsFinish(notice.networkId, resp);
409
410 context.RelayCooperate(notice);
411 context.inputEventInterceptor_.Update(context);
412 FI_HILOGI("[relay cooperate] Relay cooperation to \'%{public}s\'", Utility::Anonymize(context.Peer()).c_str());
413 context.OnRelayCooperation(context.Peer(), context.NormalizedCursorPosition());
414 }
415
OnHotplug(Context & context,const CooperateEvent & event)416 void CooperateOut::Initial::OnHotplug(Context &context, const CooperateEvent &event)
417 {
418 InputHotplugEvent notice = std::get<InputHotplugEvent>(event.event);
419 if (notice.deviceId != context.StartDeviceId()) {
420 return;
421 }
422 FI_HILOGI("Stop cooperation on unplug of dedicated pointer");
423 parent_.StopCooperate(context, event);
424 }
425
OnAppClosed(Context & context,const CooperateEvent & event)426 void CooperateOut::Initial::OnAppClosed(Context &context, const CooperateEvent &event)
427 {
428 FI_HILOGI("[app closed] Close all connections");
429 context.dsoftbus_.CloseAllSessions();
430 FI_HILOGI("[app closed] Stop cooperation");
431 parent_.StopCooperate(context, event);
432 }
433
OnPointerEvent(Context & context,const CooperateEvent & event)434 void CooperateOut::Initial::OnPointerEvent(Context &context, const CooperateEvent &event)
435 {
436 InputPointerEvent notice = std::get<InputPointerEvent>(event.event);
437
438 if ((notice.sourceType != MMI::PointerEvent::SOURCE_TYPE_MOUSE) ||
439 (notice.deviceId == context.StartDeviceId()) ||
440 (notice.deviceId < 0)) {
441 return;
442 }
443 FI_HILOGI("Stop cooperation on operation of undedicated pointer");
444 parent_.StopCooperate(context, event);
445 }
446
OnBoardOffline(Context & context,const CooperateEvent & event)447 void CooperateOut::Initial::OnBoardOffline(Context &context, const CooperateEvent &event)
448 {
449 DDMBoardOfflineEvent notice = std::get<DDMBoardOfflineEvent>(event.event);
450
451 if (!context.IsPeer(notice.networkId)) {
452 return;
453 }
454 FI_HILOGI("[board offline] Peer(\'%{public}s\') is offline", Utility::Anonymize(notice.networkId).c_str());
455 parent_.StopCooperate(context, event);
456 }
457
OnSwitchChanged(Context & context,const CooperateEvent & event)458 void CooperateOut::Initial::OnSwitchChanged(Context &context, const CooperateEvent &event)
459 {
460 DDPCooperateSwitchChanged notice = std::get<DDPCooperateSwitchChanged>(event.event);
461
462 if (!context.IsPeer(notice.networkId) || notice.normal) {
463 return;
464 }
465 FI_HILOGI("[switch off] Peer(\'%{public}s\') switch off", Utility::Anonymize(notice.networkId).c_str());
466 parent_.StopCooperate(context, event);
467 }
468
OnSoftbusSessionClosed(Context & context,const CooperateEvent & event)469 void CooperateOut::Initial::OnSoftbusSessionClosed(Context &context, const CooperateEvent &event)
470 {
471 DSoftbusSessionClosed notice = std::get<DSoftbusSessionClosed>(event.event);
472
473 if (!context.IsPeer(notice.networkId)) {
474 return;
475 }
476 FI_HILOGI("[dsoftbus session closed] Disconnected with \'%{public}s\'",
477 Utility::Anonymize(notice.networkId).c_str());
478 parent_.StopCooperate(context, event);
479 }
480
OnProgress(Context & context,const CooperateEvent & event)481 void CooperateOut::Initial::OnProgress(Context &context, const CooperateEvent &event)
482 {}
483
OnProgressWithOptions(Context & context,const CooperateEvent & event)484 void CooperateOut::Initial::OnProgressWithOptions(Context &context, const CooperateEvent &event)
485 {}
486
OnReset(Context & context,const CooperateEvent & event)487 void CooperateOut::Initial::OnReset(Context &context, const CooperateEvent &event)
488 {}
489
StopCooperate(Context & context,const CooperateEvent & event)490 void CooperateOut::StopCooperate(Context &context, const CooperateEvent &event)
491 {
492 context.inputEventInterceptor_.Disable();
493
494 DSoftbusStopCooperate notice {};
495 context.dsoftbus_.StopCooperate(context.Peer(), notice);
496
497 context.ResetCursorPosition();
498 TransiteTo(context, CooperateState::COOPERATE_STATE_FREE);
499 context.OnResetCooperation();
500 }
501
UnchainConnections(Context & context,const StopCooperateEvent & event) const502 void CooperateOut::UnchainConnections(Context &context, const StopCooperateEvent &event) const
503 {
504 if (event.isUnchained) {
505 FI_HILOGI("Unchain all connections");
506 context.dsoftbus_.CloseAllSessions();
507 context.eventMgr_.OnUnchain(event);
508 }
509 }
510 } // namespace Cooperate
511 } // namespace DeviceStatus
512 } // namespace Msdp
513 } // namespace OHOS
514