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_free.h"
17 
18 #include "devicestatus_define.h"
19 #include "utility.h"
20 
21 #undef LOG_TAG
22 #define LOG_TAG "CooperateFree"
23 
24 namespace OHOS {
25 namespace Msdp {
26 namespace DeviceStatus {
27 namespace Cooperate {
28 
29 namespace {
30 const std::string FINGER_PRINT { "hw_fingerprint_mouse" };
31 }
32 
CooperateFree(IStateMachine & parent,IContext * env)33 CooperateFree::CooperateFree(IStateMachine &parent, IContext *env)
34     : ICooperateState(parent), env_(env)
35 {
36     initial_ = std::make_shared<Initial>(*this);
37     Initial::BuildChains(initial_, *this);
38     current_ = initial_;
39 }
40 
~CooperateFree()41 CooperateFree::~CooperateFree()
42 {
43     Initial::RemoveChains(initial_);
44 }
45 
OnEvent(Context & context,const CooperateEvent & event)46 void CooperateFree::OnEvent(Context &context, const CooperateEvent &event)
47 {
48     current_->OnEvent(context, event);
49 }
50 
OnEnterState(Context & context)51 void CooperateFree::OnEnterState(Context &context)
52 {
53     CALL_INFO_TRACE;
54     bool hasLocalPointerDevice =  HasLocalPointerDevice();
55     FI_HILOGI("HasLocalPointerDevice:%{public}s", hasLocalPointerDevice ? "true" : "false");
56     bool visible = !context.NeedHideCursor() && hasLocalPointerDevice;
57     env_->GetInput().SetPointerVisibility(visible, 1);
58 }
59 
OnLeaveState(Context & context)60 void CooperateFree::OnLeaveState(Context &context)
61 {
62     CALL_INFO_TRACE;
63     UpdateCooperateFlagEvent event {
64         .mask = COOPERATE_FLAG_HIDE_CURSOR,
65     };
66     context.UpdateCooperateFlag(event);
67 }
68 
HasLocalPointerDevice() const69 bool CooperateFree::HasLocalPointerDevice() const
70 {
71     return env_->GetDeviceManager().AnyOf([this](std::shared_ptr<IDevice> dev) {
72         if ((dev == nullptr) || (dev->GetName() == FINGER_PRINT)) {
73             return false;
74         }
75         return (dev->IsPointerDevice() && !dev->IsRemote());
76     });
77 }
78 
HasLocalKeyboardDevice() const79 bool CooperateFree::HasLocalKeyboardDevice() const
80 {
81     return env_->GetDeviceManager().AnyOf([this](std::shared_ptr<IDevice> dev) {
82         CHKPR(dev, false);
83         return (dev->IsKeyboard() && !dev->IsRemote());
84     });
85 }
86 
UnchainConnections(Context & context,const StopCooperateEvent & event) const87 void CooperateFree::UnchainConnections(Context &context, const StopCooperateEvent &event) const
88 {
89     CALL_INFO_TRACE;
90     if (event.isUnchained) {
91         FI_HILOGI("Unchain all connections");
92         context.dsoftbus_.CloseAllSessions();
93         context.eventMgr_.OnUnchain(event);
94     }
95 }
96 
Initial(CooperateFree & parent)97 CooperateFree::Initial::Initial(CooperateFree &parent)
98     : ICooperateStep(parent, nullptr), parent_(parent)
99 {
100     AddHandler(CooperateEventType::START, [this](Context &context, const CooperateEvent &event) {
101         this->OnStart(context, event);
102     });
103     AddHandler(CooperateEventType::STOP, [this](Context &context, const CooperateEvent &event) {
104         this->OnStop(context, event);
105     });
106     AddHandler(CooperateEventType::APP_CLOSED, [this](Context &context, const CooperateEvent &event) {
107         this->OnAppClosed(context, event);
108     });
109     AddHandler(CooperateEventType::DSOFTBUS_START_COOPERATE, [this](Context &context, const CooperateEvent &event) {
110         this->OnRemoteStart(context, event);
111     });
112 }
113 
OnProgress(Context & context,const CooperateEvent & event)114 void CooperateFree::Initial::OnProgress(Context &context, const CooperateEvent &event)
115 {}
116 
OnReset(Context & context,const CooperateEvent & event)117 void CooperateFree::Initial::OnReset(Context &context, const CooperateEvent &event)
118 {}
119 
BuildChains(std::shared_ptr<Initial> initial,CooperateFree & parent)120 void CooperateFree::Initial::BuildChains(std::shared_ptr<Initial> initial, CooperateFree &parent)
121 {}
122 
RemoveChains(std::shared_ptr<Initial> initial)123 void CooperateFree::Initial::RemoveChains(std::shared_ptr<Initial> initial)
124 {}
125 
OnStart(Context & context,const CooperateEvent & event)126 void CooperateFree::Initial::OnStart(Context &context, const CooperateEvent &event)
127 {
128     CALL_INFO_TRACE;
129     StartCooperateEvent notice = std::get<StartCooperateEvent>(event.event);
130     FI_HILOGI("[start cooperation] With \'%{public}s\'", Utility::Anonymize(notice.remoteNetworkId).c_str());
131     context.StartCooperate(notice);
132     context.eventMgr_.StartCooperate(notice);
133 
134     int32_t ret = context.dsoftbus_.OpenSession(context.Peer());
135     if (ret != RET_OK) {
136         FI_HILOGE("[start cooperation] Failed to connect to \'%{public}s\'",
137             Utility::Anonymize(context.Peer()).c_str());
138         int32_t errNum = (ret == RET_ERR ? static_cast<int32_t>(CoordinationErrCode::OPEN_SESSION_FAILED) : ret);
139         DSoftbusStartCooperateFinished failNotice {
140             .success = false,
141             .errCode = errNum
142         };
143         context.eventMgr_.StartCooperateFinish(failNotice);
144         return;
145     }
146     DSoftbusStartCooperate startNotice {
147         .originNetworkId = context.Local(),
148         .success = true,
149         .cursorPos = context.NormalizedCursorPosition(),
150     };
151     context.OnStartCooperate(startNotice.extra);
152     context.dsoftbus_.StartCooperate(context.Peer(), startNotice);
153     context.inputEventInterceptor_.Enable(context);
154     context.eventMgr_.StartCooperateFinish(startNotice);
155     FI_HILOGI("[start cooperation] Cooperation with \'%{public}s\' established",
156         Utility::Anonymize(context.Peer()).c_str());
157     TransiteTo(context, CooperateState::COOPERATE_STATE_OUT);
158     context.OnTransitionOut();
159 #ifdef ENABLE_PERFORMANCE_CHECK
160     std::ostringstream ss;
161     ss << "start_cooperation_with_ " << Utility::Anonymize(context.Peer()).c_str();
162     context.FinishTrace(ss.str());
163 #endif // ENABLE_PERFORMANCE_CHECK
164 }
165 
OnStop(Context & context,const CooperateEvent & event)166 void CooperateFree::Initial::OnStop(Context &context, const CooperateEvent &event)
167 {
168     CALL_INFO_TRACE;
169     StopCooperateEvent notice = std::get<StopCooperateEvent>(event.event);
170     parent_.UnchainConnections(context, notice);
171 }
172 
OnAppClosed(Context & context,const CooperateEvent & event)173 void CooperateFree::Initial::OnAppClosed(Context &context, const CooperateEvent &event)
174 {
175     FI_HILOGI("[app closed] Close all connections");
176     context.dsoftbus_.CloseAllSessions();
177 }
178 
OnRemoteStart(Context & context,const CooperateEvent & event)179 void CooperateFree::Initial::OnRemoteStart(Context &context, const CooperateEvent &event)
180 {
181     CALL_INFO_TRACE;
182     DSoftbusStartCooperate notice = std::get<DSoftbusStartCooperate>(event.event);
183     context.OnRemoteStartCooperate(notice.extra);
184     context.eventMgr_.RemoteStart(notice);
185     context.RemoteStartSuccess(notice);
186     context.inputEventBuilder_.Enable(context);
187     context.eventMgr_.RemoteStartFinish(notice);
188     context.inputDevMgr_.AddVirtualInputDevice(context.Peer());
189     FI_HILOGI("[remote start] Cooperation with \'%{public}s\' established", Utility::Anonymize(context.Peer()).c_str());
190     TransiteTo(context, CooperateState::COOPERATE_STATE_IN);
191     context.OnTransitionIn();
192 }
193 } // namespace Cooperate
194 } // namespace DeviceStatus
195 } // namespace Msdp
196 } // namespace OHOS
197