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