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_free.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 "CooperateFree"
24
25 namespace OHOS {
26 namespace Msdp {
27 namespace DeviceStatus {
28 namespace Cooperate {
29
CooperateFree(IStateMachine & parent,IContext * env)30 CooperateFree::CooperateFree(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
~CooperateFree()38 CooperateFree::~CooperateFree()
39 {
40 Initial::RemoveChains(initial_);
41 }
42
OnEvent(Context & context,const CooperateEvent & event)43 void CooperateFree::OnEvent(Context &context, const CooperateEvent &event)
44 {
45 current_->OnEvent(context, event);
46 }
47
OnEnterState(Context & context)48 void CooperateFree::OnEnterState(Context &context)
49 {
50 CALL_INFO_TRACE;
51 }
52
OnLeaveState(Context & context)53 void CooperateFree::OnLeaveState(Context &context)
54 {
55 CALL_INFO_TRACE;
56 UpdateCooperateFlagEvent event {
57 .mask = COOPERATE_FLAG_HIDE_CURSOR,
58 };
59 context.UpdateCooperateFlag(event);
60 }
61
SetPointerVisible(Context & context)62 void CooperateFree::SetPointerVisible(Context &context)
63 {
64 CHKPV(env_);
65 bool hasLocalPointerDevice = env_->GetDeviceManager().HasLocalPointerDevice() ||
66 env_->GetInput().HasLocalPointerDevice();
67 bool visible = !context.NeedHideCursor() && hasLocalPointerDevice;
68 FI_HILOGI("Set pointer visible:%{public}s, HasLocalPointerDevice:%{public}s",
69 visible ? "true" : "false", hasLocalPointerDevice ? "true" : "false");
70 env_->GetInput().SetPointerVisibility(visible, PRIORITY);
71 }
72
UnchainConnections(Context & context,const StopCooperateEvent & event) const73 void CooperateFree::UnchainConnections(Context &context, const StopCooperateEvent &event) const
74 {
75 CALL_DEBUG_ENTER;
76 if (event.isUnchained) {
77 FI_HILOGI("Unchain all connections");
78 context.dsoftbus_.CloseAllSessions();
79 context.eventMgr_.OnUnchain(event);
80 }
81 }
82
SimulateShowPointerEvent()83 void CooperateFree::SimulateShowPointerEvent()
84 {
85 CALL_INFO_TRACE;
86 CHKPV(env_);
87 auto pointerEvent = OHOS::MMI::PointerEvent::Create();
88 OHOS::MMI::PointerEvent::PointerItem item;
89 item.SetPointerId(0);
90 item.SetRawDx(0);
91 item.SetRawDy(0);
92 CHKPV(pointerEvent);
93 pointerEvent->SetPointerAction(OHOS::MMI::PointerEvent::POINTER_ACTION_MOVE);
94 pointerEvent->AddFlag(OHOS::MMI::InputEvent::EVENT_FLAG_RAW_POINTER_MOVEMENT);
95 pointerEvent->SetPointerId(0);
96 pointerEvent->SetSourceType(OHOS::MMI::PointerEvent::SOURCE_TYPE_MOUSE);
97 pointerEvent->AddPointerItem(item);
98 env_->GetInput().SimulateInputEvent(pointerEvent);
99 }
100
Initial(CooperateFree & parent)101 CooperateFree::Initial::Initial(CooperateFree &parent)
102 : ICooperateStep(parent, nullptr), parent_(parent)
103 {
104 AddHandler(CooperateEventType::START, [this](Context &context, const CooperateEvent &event) {
105 this->OnStart(context, event);
106 });
107 AddHandler(CooperateEventType::WITH_OPTIONS_START, [this](Context &context, const CooperateEvent &event) {
108 this->OnStartWithOptions(context, event);
109 });
110 AddHandler(CooperateEventType::STOP, [this](Context &context, const CooperateEvent &event) {
111 this->OnStop(context, event);
112 });
113 AddHandler(CooperateEventType::DISABLE, [this](Context &context, const CooperateEvent &event) {
114 this->OnDisable(context, event);
115 });
116 AddHandler(CooperateEventType::APP_CLOSED, [this](Context &context, const CooperateEvent &event) {
117 this->OnAppClosed(context, event);
118 });
119 AddHandler(CooperateEventType::DSOFTBUS_START_COOPERATE, [this](Context &context, const CooperateEvent &event) {
120 this->OnRemoteStart(context, event);
121 });
122 AddHandler(CooperateEventType::INPUT_POINTER_EVENT, [this](Context &context, const CooperateEvent &event) {
123 this->OnPointerEvent(context, event);
124 });
125 AddHandler(CooperateEventType::UPDATE_COOPERATE_FLAG,
126 [this](Context &context, const CooperateEvent &event) {
127 this->OnUpdateCooperateFlag(context, event);
128 });
129 AddHandler(CooperateEventType::DSOFTBUS_COOPERATE_WITH_OPTIONS,
130 [this](Context &context, const CooperateEvent &event) {
131 this->OnRemoteStartWithOptions(context, event);
132 });
133 }
134
OnProgress(Context & context,const CooperateEvent & event)135 void CooperateFree::Initial::OnProgress(Context &context, const CooperateEvent &event)
136 {}
137
OnProgressWithOptions(Context & context,const CooperateEvent & event)138 void CooperateFree::Initial::OnProgressWithOptions(Context &context, const CooperateEvent &event)
139 {}
140
OnReset(Context & context,const CooperateEvent & event)141 void CooperateFree::Initial::OnReset(Context &context, const CooperateEvent &event)
142 {}
143
BuildChains(std::shared_ptr<Initial> initial,CooperateFree & parent)144 void CooperateFree::Initial::BuildChains(std::shared_ptr<Initial> initial, CooperateFree &parent)
145 {}
146
RemoveChains(std::shared_ptr<Initial> initial)147 void CooperateFree::Initial::RemoveChains(std::shared_ptr<Initial> initial)
148 {}
149
OnStart(Context & context,const CooperateEvent & event)150 void CooperateFree::Initial::OnStart(Context &context, const CooperateEvent &event)
151 {
152 CALL_INFO_TRACE;
153 StartCooperateEvent notice = std::get<StartCooperateEvent>(event.event);
154 FI_HILOGI("[start cooperation] With \'%{public}s\'", Utility::Anonymize(notice.remoteNetworkId).c_str());
155 context.StartCooperate(notice);
156 context.eventMgr_.StartCooperate(notice);
157
158 if (parent_.env_->GetDragManager().GetDragState() == DragState::MOTION_DRAGGING) {
159 FI_HILOGE("Not allow cooperate");
160 NotAollowCooperateWhenMotionDragging result {
161 .pid = notice.pid,
162 .userData = notice.userData,
163 .networkId = notice.remoteNetworkId,
164 .success = false,
165 .errCode = static_cast<int32_t>(CoordinationErrCode::NOT_AOLLOW_COOPERATE_WHEN_MOTION_DRAGGING)
166 };
167 context.eventMgr_.ErrorNotAollowCooperateWhenMotionDragging(result);
168 return;
169 }
170 int32_t ret = context.dsoftbus_.OpenSession(context.Peer());
171 if (ret != RET_OK) {
172 FI_HILOGE("[start cooperation] Failed to connect to \'%{public}s\'",
173 Utility::Anonymize(context.Peer()).c_str());
174 CooperateRadarInfo radarInfo {
175 .funcName = __FUNCTION__,
176 .bizState = static_cast<int32_t> (BizState::STATE_END),
177 .bizStage = static_cast<int32_t> (BizCooperateStage::STAGE_OPEN_DSOFTBUS_SESSION),
178 .stageRes = static_cast<int32_t> (BizCooperateStageRes::RES_FAIL),
179 .bizScene = static_cast<int32_t> (BizCooperateScene::SCENE_ACTIVE),
180 .errCode = static_cast<int32_t> (CooperateRadarErrCode::OPEN_DSOFTBUS_SESSION_FAILED),
181 .localNetId = Utility::DFXRadarAnonymize(context.Local().c_str()),
182 .peerNetId = Utility::DFXRadarAnonymize(notice.remoteNetworkId.c_str())
183 };
184 CooperateRadar::ReportCooperateRadarInfo(radarInfo);
185 int32_t errNum = (ret == RET_ERR ? static_cast<int32_t>(CoordinationErrCode::OPEN_SESSION_FAILED) : ret);
186 DSoftbusStartCooperateFinished failNotice {
187 .success = false,
188 .errCode = errNum
189 };
190 context.eventMgr_.StartCooperateFinish(failNotice);
191 return;
192 }
193 DSoftbusStartCooperate startNotice {
194 .originNetworkId = context.Local(),
195 .success = true,
196 .cursorPos = context.NormalizedCursorPosition(),
197 .pointerSpeed = context.GetPointerSpeed(),
198 .touchPadSpeed = context.GetTouchPadSpeed(),
199 };
200 context.OnStartCooperate(startNotice.extra);
201 context.dsoftbus_.StartCooperate(context.Peer(), startNotice);
202 context.inputEventInterceptor_.Enable(context);
203 context.eventMgr_.StartCooperateFinish(startNotice);
204 FI_HILOGI("[start cooperation] Cooperation with \'%{public}s\' established",
205 Utility::Anonymize(context.Peer()).c_str());
206 TransiteTo(context, CooperateState::COOPERATE_STATE_OUT);
207 context.OnTransitionOut();
208 #ifdef ENABLE_PERFORMANCE_CHECK
209 std::ostringstream ss;
210 ss << "start_cooperation_with_ " << Utility::Anonymize(context.Peer()).c_str();
211 context.FinishTrace(ss.str());
212 #endif // ENABLE_PERFORMANCE_CHECK
213 }
214
OnStop(Context & context,const CooperateEvent & event)215 void CooperateFree::Initial::OnStop(Context &context, const CooperateEvent &event)
216 {
217 CALL_INFO_TRACE;
218 StopCooperateEvent param = std::get<StopCooperateEvent>(event.event);
219 context.eventMgr_.StopCooperate(param);
220 param.networkId = context.Peer();
221 DSoftbusStopCooperateFinished notice {
222 .networkId = context.Peer(),
223 .normal = true,
224 };
225 context.eventMgr_.StopCooperateFinish(notice);
226 context.inputDevMgr_.RemoveVirtualInputDevice(context.Peer());
227 parent_.UnchainConnections(context, param);
228 }
229
OnStartWithOptions(Context & context,const CooperateEvent & event)230 void CooperateFree::Initial::OnStartWithOptions(Context &context, const CooperateEvent &event)
231 {
232 CALL_INFO_TRACE;
233 StartWithOptionsEvent notice = std::get<StartWithOptionsEvent>(event.event);
234 FI_HILOGI("[start cooperation With Options] With \'%{public}s\'",
235 Utility::Anonymize(notice.remoteNetworkId).c_str());
236 context.StartCooperateWithOptions(notice);
237 context.eventMgr_.StartCooperateWithOptions(notice);
238 int32_t ret = context.dsoftbus_.OpenSession(context.Peer());
239 if (ret != RET_OK) {
240 FI_HILOGE("[start cooperation] Failed to connect to \'%{public}s\'",
241 Utility::Anonymize(context.Peer()).c_str());
242 int32_t errNum = (ret == RET_ERR ? static_cast<int32_t>(CoordinationErrCode::OPEN_SESSION_FAILED) : ret);
243 DSoftbusStartCooperateFinished failNotice {
244 .success = false,
245 .errCode = errNum
246 };
247 context.eventMgr_.StartCooperateFinish(failNotice);
248 return;
249 }
250 DSoftbusCooperateOptions startNotice {
251 .originNetworkId = context.Local(),
252 .success = true,
253 .cooperateOptions = {notice.displayX, notice.displayY, notice.displayId},
254 };
255 context.OnStartCooperate(startNotice.extra);
256 context.dsoftbus_.StartCooperateWithOptions(context.Peer(), startNotice);
257 context.inputEventInterceptor_.Enable(context);
258 context.eventMgr_.StartCooperateWithOptinsFinish(startNotice);
259 FI_HILOGI("[start cooperation] Cooperation with \'%{public}s\' established",
260 Utility::Anonymize(context.Peer()).c_str());
261 TransiteTo(context, CooperateState::COOPERATE_STATE_OUT);
262 context.OnTransitionOut();
263 #ifdef ENABLE_PERFORMANCE_CHECK
264 std::ostringstream ss;
265 ss << "start_cooperation_with_ " << Utility::Anonymize(context.Peer()).c_str();
266 context.FinishTrace(ss.str());
267 #endif // ENABLE_PERFORMANCE_CHECK
268 }
269
OnDisable(Context & context,const CooperateEvent & event)270 void CooperateFree::Initial::OnDisable(Context &context, const CooperateEvent &event)
271 {
272 FI_HILOGI("[disable cooperation] Stop cooperation");
273 CHKPV(parent_.env_);
274 auto dragState = parent_.env_->GetDragManager().GetDragState();
275 if (dragState == DragState::START && parent_.env_->GetDragManager().IsCrossDragging()) {
276 FI_HILOGI("reset cooperation");
277 context.OnResetCooperation();
278 } else if (dragState == DragState::START) {
279 FI_HILOGI("drag state is start");
280 return;
281 }
282 bool hasLocalPointerDevice = parent_.env_->GetDeviceManager().HasLocalPointerDevice() ||
283 parent_.env_->GetInput().HasLocalPointerDevice();
284 FI_HILOGI("HasLocalPointerDevice:%{public}s", hasLocalPointerDevice ? "true" : "false");
285 context.inputDevMgr_.RemoveVirtualInputDevice(context.Peer());
286 parent_.env_->GetInput().SetPointerVisibility(hasLocalPointerDevice, PRIORITY);
287 }
288
OnAppClosed(Context & context,const CooperateEvent & event)289 void CooperateFree::Initial::OnAppClosed(Context &context, const CooperateEvent &event)
290 {
291 FI_HILOGI("[app closed] Close all connections");
292 context.inputDevMgr_.RemoveVirtualInputDevice(context.Peer());
293 context.dsoftbus_.CloseAllSessions();
294 }
295
OnRemoteStart(Context & context,const CooperateEvent & event)296 void CooperateFree::Initial::OnRemoteStart(Context &context, const CooperateEvent &event)
297 {
298 CALL_INFO_TRACE;
299 DSoftbusStartCooperate notice = std::get<DSoftbusStartCooperate>(event.event);
300 context.StorePeerPointerSpeed(notice.pointerSpeed);
301 context.StorePeerTouchPadSpeed(notice.touchPadSpeed);
302 context.OnRemoteStartCooperate(notice.extra);
303 context.eventMgr_.RemoteStart(notice);
304 context.RemoteStartSuccess(notice);
305 context.inputEventBuilder_.Enable(context);
306 context.eventMgr_.RemoteStartFinish(notice);
307 context.inputDevMgr_.AddVirtualInputDevice(context.Peer());
308 FI_HILOGI("[remote start] Cooperation with \'%{public}s\' established", Utility::Anonymize(context.Peer()).c_str());
309 TransiteTo(context, CooperateState::COOPERATE_STATE_IN);
310 context.OnTransitionIn();
311 if (!context.NeedFreezeCursor()) {
312 parent_.SimulateShowPointerEvent();
313 }
314 }
315
OnRemoteStartWithOptions(Context & context,const CooperateEvent & event)316 void CooperateFree::Initial::OnRemoteStartWithOptions(Context &context, const CooperateEvent &event)
317 {
318 CALL_INFO_TRACE;
319 DSoftbusCooperateOptions notice = std::get<DSoftbusCooperateOptions>(event.event);
320 context.OnRemoteStartCooperate(notice.extra);
321 context.eventMgr_.RemoteStartWithOptions(notice);
322 context.OnRemoteStart(notice);
323 context.inputEventBuilder_.Enable(context);
324 context.eventMgr_.RemoteStartWithOptionsFinish(notice);
325 context.inputDevMgr_.AddVirtualInputDevice(context.Peer());
326 FI_HILOGI("[remote start with options] Cooperation with \'%{public}s\' established",
327 Utility::Anonymize(context.Peer()).c_str());
328 TransiteTo(context, CooperateState::COOPERATE_STATE_IN);
329 context.OnTransitionIn();
330 }
331
OnPointerEvent(Context & context,const CooperateEvent & event)332 void CooperateFree::Initial::OnPointerEvent(Context &context, const CooperateEvent &event)
333 {
334 CALL_DEBUG_ENTER;
335 if (context.NeedHideCursor() && context.IsCooperateWithCrossDrag()) {
336 FI_HILOGD("Hide cursor before dragData rcvd when come back");
337 return;
338 }
339 InputPointerEvent notice = std::get<InputPointerEvent>(event.event);
340 CHKPV(parent_.env_);
341 if (auto dragState = parent_.env_->GetDragManager().GetDragState(); dragState == DragState::START) {
342 FI_HILOGD("Current dragState:START");
343 return;
344 }
345 if (InputEventBuilder::IsLocalEvent(notice) && context.NeedHideCursor()) {
346 UpdateCooperateFlagEvent event {
347 .mask = COOPERATE_FLAG_HIDE_CURSOR,
348 };
349 context.UpdateCooperateFlag(event);
350 parent_.SetPointerVisible(context);
351 }
352 }
353
OnUpdateCooperateFlag(Context & context,const CooperateEvent & event)354 void CooperateFree::Initial::OnUpdateCooperateFlag(Context &context, const CooperateEvent &event)
355 {
356 CALL_INFO_TRACE;
357 UpdateCooperateFlagEvent notice = std::get<UpdateCooperateFlagEvent>(event.event);
358 context.UpdateCooperateFlag(notice);
359 }
360 } // namespace Cooperate
361 } // namespace DeviceStatus
362 } // namespace Msdp
363 } // namespace OHOS
364