1/*
2 * Copyright (c) 2023-2024 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_in.h"
17
18#include "devicestatus_define.h"
19#include "utility.h"
20
21#undef LOG_TAG
22#define LOG_TAG "CooperateIn"
23
24namespace OHOS {
25namespace Msdp {
26namespace DeviceStatus {
27namespace Cooperate {
28
29CooperateIn::CooperateIn(IStateMachine &parent, IContext *env)
30    : ICooperateState(parent), env_(env)
31{
32    initial_ = std::make_shared<Initial>(*this);
33    Initial::BuildChains(initial_, *this);
34    current_ = initial_;
35}
36
37CooperateIn::~CooperateIn()
38{
39    Initial::RemoveChains(initial_);
40}
41
42void CooperateIn::OnEvent(Context &context, const CooperateEvent &event)
43{
44    current_->OnEvent(context, event);
45}
46
47void CooperateIn::OnEnterState(Context &context)
48{
49    CALL_INFO_TRACE;
50    env_->GetInput().SetPointerVisibility(!context.NeedHideCursor());
51}
52
53void CooperateIn::OnLeaveState(Context & context)
54{
55    CALL_INFO_TRACE;
56    UpdateCooperateFlagEvent event {
57        .mask = COOPERATE_FLAG_HIDE_CURSOR,
58        .flag = COOPERATE_FLAG_HIDE_CURSOR,
59    };
60    context.UpdateCooperateFlag(event);
61    CHKPV(env_);
62    env_->GetInput().SetPointerVisibility(false);
63}
64
65std::set<int32_t> CooperateIn::Initial::filterPointerActions_ {
66    MMI::PointerEvent::POINTER_ACTION_ENTER_WINDOW,
67    MMI::PointerEvent::POINTER_ACTION_LEAVE_WINDOW,
68    MMI::PointerEvent::POINTER_ACTION_PULL_IN_WINDOW,
69    MMI::PointerEvent::POINTER_ACTION_PULL_OUT_WINDOW,
70};
71
72void CooperateIn::Initial::BuildChains(std::shared_ptr<Initial> self, CooperateIn &parent)
73{
74    auto s11 = std::make_shared<RelayConfirmation>(parent, self);
75    self->relay_ = s11;
76    s11->SetNext(self);
77}
78
79void CooperateIn::Initial::RemoveChains(std::shared_ptr<Initial> self)
80{
81    if (self->relay_ != nullptr) {
82        self->relay_->SetNext(nullptr);
83        self->relay_ = nullptr;
84    }
85}
86
87CooperateIn::Initial::Initial(CooperateIn &parent)
88    : ICooperateStep(parent, nullptr), parent_(parent)
89{
90    AddHandler(CooperateEventType::DISABLE, [this](Context &context, const CooperateEvent &event) {
91        this->OnDisable(context, event);
92    });
93    AddHandler(CooperateEventType::START, [this](Context &context, const CooperateEvent &event) {
94        this->OnStart(context, event);
95    });
96    AddHandler(CooperateEventType::STOP, [this](Context &context, const CooperateEvent &event) {
97        this->OnStop(context, event);
98    });
99    AddHandler(CooperateEventType::APP_CLOSED, [this](Context &context, const CooperateEvent &event) {
100        this->OnAppClosed(context, event);
101    });
102    AddHandler(CooperateEventType::INPUT_POINTER_EVENT, [this](Context &context, const CooperateEvent &event) {
103        this->OnPointerEvent(context, event);
104    });
105    AddHandler(CooperateEventType::DDM_BOARD_OFFLINE, [this](Context &context, const CooperateEvent &event) {
106        this->OnBoardOffline(context, event);
107    });
108    AddHandler(CooperateEventType::DDP_COOPERATE_SWITCH_CHANGED,
109        [this](Context &context, const CooperateEvent &event) {
110            this->OnSwitchChanged(context, event);
111    });
112    AddHandler(CooperateEventType::DSOFTBUS_SESSION_CLOSED,
113        [this](Context &context, const CooperateEvent &event) {
114            this->OnSoftbusSessionClosed(context, event);
115    });
116    AddHandler(CooperateEventType::DSOFTBUS_START_COOPERATE,
117        [this](Context &context, const CooperateEvent &event) {
118            this->OnRemoteStart(context, event);
119    });
120    AddHandler(CooperateEventType::DSOFTBUS_STOP_COOPERATE,
121        [this](Context &context, const CooperateEvent &event) {
122            this->OnRemoteStop(context, event);
123    });
124    AddHandler(CooperateEventType::UPDATE_COOPERATE_FLAG,
125        [this](Context &context, const CooperateEvent &event) {
126            this->OnUpdateCooperateFlag(context, event);
127    });
128    AddHandler(CooperateEventType::DSOFTBUS_INPUT_DEV_SYNC,
129        [this](Context &context, const CooperateEvent &event) {
130            this->OnRemoteInputDevice(context, event);
131    });
132}
133
134void CooperateIn::Initial::OnDisable(Context &context, const CooperateEvent &event)
135{
136    FI_HILOGI("[disable cooperation] Stop cooperation");
137    parent_.StopCooperate(context, event);
138}
139
140void CooperateIn::Initial::OnStart(Context &context, const CooperateEvent &event)
141{
142    CALL_INFO_TRACE;
143    StartCooperateEvent startEvent = std::get<StartCooperateEvent>(event.event);
144
145    if (context.IsLocal(startEvent.remoteNetworkId)) {
146        DSoftbusStartCooperateFinished result {
147            .success = false,
148            .errCode = static_cast<int32_t>(CoordinationErrCode::UNEXPECTED_START_CALL)
149        };
150        context.eventMgr_.StartCooperateFinish(result);
151        return;
152    }
153    FI_HILOGI("[start] start cooperation(%{public}s, %{public}d)",
154        Utility::Anonymize(startEvent.remoteNetworkId).c_str(), startEvent.startDeviceId);
155    context.eventMgr_.StartCooperate(startEvent);
156
157    if (context.IsPeer(startEvent.remoteNetworkId)) {
158        OnComeBack(context, event);
159    } else {
160        OnRelay(context, event);
161    }
162}
163
164void CooperateIn::Initial::OnComeBack(Context &context, const CooperateEvent &event)
165{
166    CALL_INFO_TRACE;
167    context.inputEventBuilder_.Disable();
168    FI_HILOGI("[come back] To \'%{public}s\'", Utility::Anonymize(context.Peer()).c_str());
169    DSoftbusComeBack notice {
170        .originNetworkId = context.Local(),
171        .success = true,
172        .cursorPos = context.NormalizedCursorPosition(),
173    };
174    context.OnStartCooperate(notice.extra);
175    if (context.dsoftbus_.ComeBack(context.Peer(), notice) != RET_OK) {
176        notice.success = false;
177        notice.errCode = static_cast<int32_t>(CoordinationErrCode::SEND_PACKET_FAILED);
178    }
179    context.eventMgr_.StartCooperateFinish(notice);
180    context.inputDevMgr_.RemoveVirtualInputDevice(context.Peer());
181    TransiteTo(context, CooperateState::COOPERATE_STATE_FREE);
182    context.OnBack();
183}
184
185void CooperateIn::Initial::OnRelay(Context &context, const CooperateEvent &event)
186{
187    CALL_INFO_TRACE;
188    StartCooperateEvent startEvent = std::get<StartCooperateEvent>(event.event);
189    parent_.process_.StartCooperate(context, startEvent);
190    FI_HILOGI("[relay cooperate] To \'%{public}s\'", Utility::Anonymize(parent_.process_.Peer()).c_str());
191
192    if (relay_ != nullptr) {
193        Switch(relay_);
194        relay_->OnProgress(context, event);
195    }
196}
197
198void CooperateIn::Initial::OnStop(Context &context, const CooperateEvent &event)
199{
200    CALL_INFO_TRACE;
201    StopCooperateEvent param = std::get<StopCooperateEvent>(event.event);
202
203    context.eventMgr_.StopCooperate(param);
204    parent_.StopCooperate(context, event);
205
206    DSoftbusStopCooperateFinished notice {
207        .normal = true,
208    };
209    context.eventMgr_.StopCooperateFinish(notice);
210
211    parent_.UnchainConnections(context, param);
212}
213
214void CooperateIn::Initial::OnRemoteStart(Context &context, const CooperateEvent &event)
215{
216    CALL_INFO_TRACE;
217    DSoftbusStartCooperate notice = std::get<DSoftbusStartCooperate>(event.event);
218
219    if (context.IsPeer(notice.networkId) || context.IsLocal(notice.networkId)) {
220        return;
221    }
222    context.OnRemoteStartCooperate(notice.extra);
223    context.eventMgr_.RemoteStart(notice);
224
225    DSoftbusStopCooperate stopNotice {};
226    context.dsoftbus_.StopCooperate(context.Peer(), stopNotice);
227
228    context.RemoteStartSuccess(notice);
229    context.inputEventBuilder_.Update(context);
230    context.eventMgr_.RemoteStartFinish(notice);
231    FI_HILOGI("[remote start] Cooperation with \'%{public}s\' established", Utility::Anonymize(context.Peer()).c_str());
232    context.OnTransitionIn();
233}
234
235void CooperateIn::Initial::OnRemoteStop(Context &context, const CooperateEvent &event)
236{
237    DSoftbusStopCooperate notice = std::get<DSoftbusStopCooperate>(event.event);
238
239    if (!context.IsPeer(notice.networkId)) {
240        return;
241    }
242    FI_HILOGI("[remote stop] Notification from \'%{public}s\'", Utility::Anonymize(notice.networkId).c_str());
243    context.eventMgr_.RemoteStop(notice);
244    context.inputEventBuilder_.Disable();
245    context.eventMgr_.RemoteStopFinish(notice);
246    context.inputDevMgr_.RemoveVirtualInputDevice(context.Peer());
247    TransiteTo(context, CooperateState::COOPERATE_STATE_FREE);
248    context.OnResetCooperation();
249}
250
251void CooperateIn::Initial::OnAppClosed(Context &context, const CooperateEvent &event)
252{
253    FI_HILOGI("[app closed] Close all connections");
254    context.dsoftbus_.CloseAllSessions();
255    FI_HILOGI("[app closed] Stop cooperation");
256    parent_.StopCooperate(context, event);
257}
258
259void CooperateIn::Initial::OnPointerEvent(Context &context, const CooperateEvent &event)
260{
261    InputPointerEvent notice = std::get<InputPointerEvent>(event.event);
262
263    if ((notice.sourceType != MMI::PointerEvent::SOURCE_TYPE_MOUSE) ||
264        (filterPointerActions_.find(notice.pointerAction) != filterPointerActions_.end()) ||
265        !InputEventBuilder::IsLocalEvent(notice)) {
266        return;
267    }
268    FI_HILOGI("Stop cooperation on operation of local pointer");
269    context.OnPointerEvent(notice);
270    parent_.StopCooperate(context, event);
271}
272
273void CooperateIn::Initial::OnBoardOffline(Context &context, const CooperateEvent &event)
274{
275    DDMBoardOfflineEvent notice = std::get<DDMBoardOfflineEvent>(event.event);
276
277    if (!context.IsPeer(notice.networkId)) {
278        return;
279    }
280    FI_HILOGI("[board offline] Peer(\'%{public}s\') is offline", Utility::Anonymize(notice.networkId).c_str());
281    parent_.StopCooperate(context, event);
282}
283
284void CooperateIn::Initial::OnSwitchChanged(Context &context, const CooperateEvent &event)
285{
286    DDPCooperateSwitchChanged notice = std::get<DDPCooperateSwitchChanged>(event.event);
287
288    if (!context.IsPeer(notice.networkId) || notice.normal) {
289        return;
290    }
291    FI_HILOGI("[switch off] Peer(\'%{public}s\') switch off", Utility::Anonymize(notice.networkId).c_str());
292    parent_.StopCooperate(context, event);
293}
294
295void CooperateIn::Initial::OnSoftbusSessionClosed(Context &context, const CooperateEvent &event)
296{
297    DSoftbusSessionClosed notice = std::get<DSoftbusSessionClosed>(event.event);
298
299    if (!context.IsPeer(notice.networkId)) {
300        return;
301    }
302    FI_HILOGI("[softbus session closed] Disconnected with \'%{public}s\'",
303        Utility::Anonymize(notice.networkId).c_str());
304    parent_.StopCooperate(context, event);
305    context.eventMgr_.OnSoftbusSessionClosed(notice);
306}
307
308void CooperateIn::Initial::OnRemoteInputDevice(Context &context, const CooperateEvent &event)
309{
310    CALL_INFO_TRACE;
311    DSoftbusSyncInputDevice notice = std::get<DSoftbusSyncInputDevice>(event.event);
312    if (!context.IsPeer(notice.networkId)) {
313        return;
314    }
315    FI_HILOGI("Remote input device from \'%{public}s\'", Utility::Anonymize(notice.networkId).c_str());
316    context.inputDevMgr_.AddVirtualInputDevice(notice.networkId);
317}
318
319void CooperateIn::Initial::OnRemoteHotPlug(Context &context, const CooperateEvent &event)
320{
321    DSoftbusHotPlugEvent notice = std::get<DSoftbusHotPlugEvent>(event.event);
322    if (!context.IsPeer(notice.networkId)) {
323        return;
324    }
325    FI_HILOGI("Remote hot plug event from \'%{public}s\'", Utility::Anonymize(notice.networkId).c_str());
326}
327
328void CooperateIn::Initial::OnUpdateCooperateFlag(Context &context, const CooperateEvent &event)
329{
330    UpdateCooperateFlagEvent notice = std::get<UpdateCooperateFlagEvent>(event.event);
331    uint32_t changed = (notice.mask & (context.CooperateFlag() ^ notice.flag));
332    context.UpdateCooperateFlag(notice);
333
334    if (changed & COOPERATE_FLAG_FREEZE_CURSOR) {
335        FI_HILOGI("Toggle freezing state of cursor");
336        if (notice.flag & COOPERATE_FLAG_FREEZE_CURSOR) {
337            context.inputEventBuilder_.Freeze();
338        } else {
339            context.inputEventBuilder_.Thaw();
340        }
341    }
342}
343
344void CooperateIn::Initial::OnProgress(Context &context, const CooperateEvent &event)
345{}
346
347void CooperateIn::Initial::OnReset(Context &context, const CooperateEvent &event)
348{}
349
350CooperateIn::RelayConfirmation::RelayConfirmation(CooperateIn &parent, std::shared_ptr<ICooperateStep> prev)
351    : ICooperateStep(parent, prev), parent_(parent)
352{
353    AddHandler(CooperateEventType::DISABLE, [this](Context &context, const CooperateEvent &event) {
354        this->OnDisable(context, event);
355    });
356    AddHandler(CooperateEventType::STOP, [this](Context &context, const CooperateEvent &event) {
357        this->OnStop(context, event);
358    });
359    AddHandler(CooperateEventType::APP_CLOSED, [this](Context &context, const CooperateEvent &event) {
360        this->OnAppClosed(context, event);
361    });
362    AddHandler(CooperateEventType::INPUT_POINTER_EVENT,
363        [this](Context &context, const CooperateEvent &event) {
364            this->OnPointerEvent(context, event);
365    });
366    AddHandler(CooperateEventType::DDM_BOARD_OFFLINE,
367        [this](Context &context, const CooperateEvent &event) {
368            this->OnBoardOffline(context, event);
369    });
370    AddHandler(CooperateEventType::DDP_COOPERATE_SWITCH_CHANGED,
371        [this](Context &context, const CooperateEvent &event) {
372            this->OnSwitchChanged(context, event);
373    });
374    AddHandler(CooperateEventType::DSOFTBUS_SESSION_CLOSED,
375        [this](Context &context, const CooperateEvent &event) {
376            this->OnSoftbusSessionClosed(context, event);
377    });
378    AddHandler(CooperateEventType::DSOFTBUS_RELAY_COOPERATE_FINISHED,
379        [this](Context &context, const CooperateEvent &event) {
380            this->OnResponse(context, event);
381    });
382    AddHandler(CooperateEventType::DSOFTBUS_START_COOPERATE,
383        [this](Context &context, const CooperateEvent &event) {
384            this->OnRemoteStart(context, event);
385    });
386    AddHandler(CooperateEventType::DSOFTBUS_STOP_COOPERATE,
387        [this](Context &context, const CooperateEvent &event) {
388            this->OnRemoteStop(context, event);
389    });
390}
391
392void CooperateIn::RelayConfirmation::OnDisable(Context &context, const CooperateEvent &event)
393{
394    FI_HILOGI("[relay cooperate] Disable cooperation");
395    parent_.StopCooperate(context, event);
396    OnReset(context, event);
397}
398
399void CooperateIn::RelayConfirmation::OnStop(Context &context, const CooperateEvent &event)
400{
401    FI_HILOGI("[relay cooperate] Stop cooperation");
402    parent_.StopCooperate(context, event);
403    OnReset(context, event);
404
405    StopCooperateEvent param = std::get<StopCooperateEvent>(event.event);
406    parent_.UnchainConnections(context, param);
407}
408
409void CooperateIn::RelayConfirmation::OnRemoteStart(Context &context, const CooperateEvent &event)
410{
411    CALL_INFO_TRACE;
412    DSoftbusStartCooperate notice = std::get<DSoftbusStartCooperate>(event.event);
413
414    if (context.IsPeer(notice.networkId) || context.IsLocal(notice.networkId)) {
415        return;
416    }
417    FI_HILOGI("[remote start] Notification from %{public}s", Utility::Anonymize(notice.networkId).c_str());
418    if (parent_.process_.IsPeer(notice.networkId)) {
419        auto ret = context.Sender().Send(event);
420        if (ret != Channel<CooperateEvent>::NO_ERROR) {
421            FI_HILOGE("Failed to send event via channel, error:%{public}d", ret);
422        }
423        OnReset(context, event);
424        return;
425    }
426    parent_.env_->GetTimerManager().AddTimer(DEFAULT_COOLING_TIME, REPEAT_ONCE,
427        [sender = context.Sender(), event]() mutable {
428            auto ret = sender.Send(event);
429            if (ret != Channel<CooperateEvent>::NO_ERROR) {
430                FI_HILOGE("Failed to send event via channel, error:%{public}d", ret);
431            }
432        });
433}
434
435void CooperateIn::RelayConfirmation::OnRemoteStop(Context &context, const CooperateEvent &event)
436{
437    DSoftbusStopCooperate notice = std::get<DSoftbusStopCooperate>(event.event);
438
439    if (!context.IsPeer(notice.networkId)) {
440        return;
441    }
442    FI_HILOGI("[remote stop] Notification from %{public}s", Utility::Anonymize(notice.networkId).c_str());
443    auto ret = context.Sender().Send(event);
444    if (ret != Channel<CooperateEvent>::NO_ERROR) {
445        FI_HILOGE("Failed to send event via channel, error:%{public}d", ret);
446    }
447    OnReset(context, event);
448}
449
450void CooperateIn::RelayConfirmation::OnAppClosed(Context &context, const CooperateEvent &event)
451{
452    FI_HILOGI("[app closed] Close all connections");
453    context.dsoftbus_.CloseAllSessions();
454    FI_HILOGI("[relay cooperate] Stop cooperation on app closed");
455    parent_.StopCooperate(context, event);
456    OnReset(context, event);
457}
458
459void CooperateIn::RelayConfirmation::OnPointerEvent(Context &context, const CooperateEvent &event)
460{
461    InputPointerEvent notice = std::get<InputPointerEvent>(event.event);
462
463    if ((notice.sourceType != MMI::PointerEvent::SOURCE_TYPE_MOUSE) ||
464        !InputEventBuilder::IsLocalEvent(notice)) {
465        return;
466    }
467    FI_HILOGI("[relay cooperate] Stop cooperation on operation of local pointer");
468    context.OnPointerEvent(notice);
469    parent_.StopCooperate(context, event);
470    OnReset(context, event);
471}
472
473void CooperateIn::RelayConfirmation::OnBoardOffline(Context &context, const CooperateEvent &event)
474{
475    DDMBoardOfflineEvent notice = std::get<DDMBoardOfflineEvent>(event.event);
476
477    if (!context.IsPeer(notice.networkId) && !parent_.process_.IsPeer(notice.networkId)) {
478        return;
479    }
480    FI_HILOGI("[relay cooperate] Peer(%{public}s) is offline", Utility::Anonymize(notice.networkId).c_str());
481    if (context.IsPeer(notice.networkId)) {
482        parent_.StopCooperate(context, event);
483    }
484    OnReset(context, event);
485}
486
487void CooperateIn::RelayConfirmation::OnSwitchChanged(Context &context, const CooperateEvent &event)
488{
489    DDPCooperateSwitchChanged notice = std::get<DDPCooperateSwitchChanged>(event.event);
490
491    if (notice.normal ||
492        (!context.IsPeer(notice.networkId) &&
493         !parent_.process_.IsPeer(notice.networkId))) {
494        return;
495    }
496    FI_HILOGI("[relay cooperate] Peer(\'%{public}s\') switch off", Utility::Anonymize(notice.networkId).c_str());
497    if (context.IsPeer(notice.networkId)) {
498        parent_.StopCooperate(context, event);
499    }
500    OnReset(context, event);
501}
502
503void CooperateIn::RelayConfirmation::OnSoftbusSessionClosed(Context &context, const CooperateEvent &event)
504{
505    DSoftbusSessionClosed notice = std::get<DSoftbusSessionClosed>(event.event);
506
507    if (!context.IsPeer(notice.networkId) && !parent_.process_.IsPeer(notice.networkId)) {
508        return;
509    }
510    FI_HILOGI("[relay cooperate] Disconnected with \'%{public}s\'", Utility::Anonymize(notice.networkId).c_str());
511    if (context.IsPeer(notice.networkId)) {
512        parent_.StopCooperate(context, event);
513    }
514    OnReset(context, event);
515}
516
517void CooperateIn::RelayConfirmation::OnResponse(Context &context, const CooperateEvent &event)
518{
519    DSoftbusRelayCooperateFinished notice = std::get<DSoftbusRelayCooperateFinished>(event.event);
520
521    if (!context.IsPeer(notice.networkId)) {
522        return;
523    }
524    FI_HILOGI("[relay cooperate] \'%{public}s\' respond", Utility::Anonymize(notice.networkId).c_str());
525    parent_.env_->GetTimerManager().RemoveTimer(timerId_);
526    if (notice.normal) {
527        OnNormal(context, event);
528        Proceed(context, event);
529    } else {
530        OnReset(context, event);
531    }
532}
533
534void CooperateIn::RelayConfirmation::OnNormal(Context &context, const CooperateEvent &event)
535{
536    FI_HILOGI("[relay cooperate] Cooperation with \'%{public}s\' established",
537        Utility::Anonymize(parent_.process_.Peer()).c_str());
538    context.inputEventBuilder_.Disable();
539
540    DSoftbusStartCooperate notice {
541        .originNetworkId = context.Peer(),
542        .success = true,
543        .cursorPos = context.NormalizedCursorPosition(),
544    };
545    context.OnStartCooperate(notice.extra);
546    context.dsoftbus_.StartCooperate(parent_.process_.Peer(), notice);
547
548    context.eventMgr_.StartCooperateFinish(notice);
549    TransiteTo(context, CooperateState::COOPERATE_STATE_FREE);
550    context.OnRelayCooperation(parent_.process_.Peer(), context.NormalizedCursorPosition());
551}
552
553void CooperateIn::RelayConfirmation::OnProgress(Context &context, const CooperateEvent &event)
554{
555    std::string remoteNetworkId = parent_.process_.Peer();
556    FI_HILOGI("[relay cooperate] Connect \'%{public}s\'", Utility::Anonymize(remoteNetworkId).c_str());
557    int32_t ret = context.dsoftbus_.OpenSession(remoteNetworkId);
558    if (ret != RET_OK) {
559        FI_HILOGE("[relay cooperate] Failed to connect to \'%{public}s\'", Utility::Anonymize(remoteNetworkId).c_str());
560        OnReset(context, event);
561        return;
562    }
563
564    FI_HILOGI("[relay cooperate] Notify origin(\'%{public}s\')", Utility::Anonymize(context.Peer()).c_str());
565    DSoftbusRelayCooperate notice {
566        .targetNetworkId = parent_.process_.Peer(),
567    };
568    context.dsoftbus_.RelayCooperate(context.Peer(), notice);
569
570    timerId_ = parent_.env_->GetTimerManager().AddTimer(DEFAULT_TIMEOUT, REPEAT_ONCE,
571        [sender = context.Sender(), remoteNetworkId = context.Peer()]() mutable {
572            auto ret = sender.Send(CooperateEvent(
573                CooperateEventType::DSOFTBUS_RELAY_COOPERATE_FINISHED,
574                DSoftbusRelayCooperateFinished {
575                    .networkId = remoteNetworkId,
576                    .normal = false,
577                }));
578            if (ret != Channel<CooperateEvent>::NO_ERROR) {
579                FI_HILOGE("Failed to send event via channel, error:%{public}d", ret);
580            }
581        });
582}
583
584void CooperateIn::RelayConfirmation::OnReset(Context &context, const CooperateEvent &event)
585{
586    FI_HILOGI("[relay cooperate] reset cooperation with \'%{public}s\'",
587        Utility::Anonymize(parent_.process_.Peer()).c_str());
588    DSoftbusStartCooperateFinished result {
589        .success = false
590    };
591    context.eventMgr_.StartCooperateFinish(result);
592    Reset(context, event);
593}
594
595void CooperateIn::StopCooperate(Context &context, const CooperateEvent &event)
596{
597    FI_HILOGI("Stop cooperation with \'%{public}s\'", Utility::Anonymize(context.Peer()).c_str());
598    context.inputEventBuilder_.Disable();
599    context.UpdateCursorPosition();
600
601    DSoftbusStopCooperate notice {};
602    context.dsoftbus_.StopCooperate(context.Peer(), notice);
603    context.inputDevMgr_.RemoveVirtualInputDevice(context.Peer());
604    TransiteTo(context, CooperateState::COOPERATE_STATE_FREE);
605    context.OnResetCooperation();
606}
607
608void CooperateIn::UnchainConnections(Context &context, const StopCooperateEvent &event) const
609{
610    if (event.isUnchained) {
611        FI_HILOGI("Unchain all connections");
612        context.dsoftbus_.CloseAllSessions();
613        context.eventMgr_.OnUnchain(event);
614    }
615}
616} // namespace Cooperate
617} // namespace DeviceStatus
618} // namespace Msdp
619} // namespace OHOS
620