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_out.h" 17 18#include "devicestatus_define.h" 19#include "utility.h" 20 21#undef LOG_TAG 22#define LOG_TAG "CooperateOut" 23 24namespace OHOS { 25namespace Msdp { 26namespace DeviceStatus { 27namespace Cooperate { 28 29CooperateOut::CooperateOut(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 37CooperateOut::~CooperateOut() 38{ 39 Initial::RemoveChains(initial_); 40} 41 42void CooperateOut::OnEvent(Context &context, const CooperateEvent &event) 43{ 44 current_->OnEvent(context, event); 45} 46 47void CooperateOut::OnEnterState(Context &context) 48{ 49 CALL_INFO_TRACE; 50 env_->GetInput().SetPointerVisibility(false); 51} 52 53void CooperateOut::OnLeaveState(Context &context) 54{ 55 CALL_INFO_TRACE; 56 SetPointerVisible(context); 57} 58 59void CooperateOut::SetPointerVisible(Context &context) 60{ 61 CHKPV(env_); 62 bool hasLocalPointerDevice = env_->GetDeviceManager().HasLocalPointerDevice(); 63 bool visible = !context.NeedHideCursor() && hasLocalPointerDevice; 64 FI_HILOGI("Set pointer visible:%{public}s, HasLocalPointerDevice:%{public}s", 65 visible ? "true" : "false", hasLocalPointerDevice ? "true" : "false"); 66 env_->GetInput().SetPointerVisibility(visible, PRIORITY); 67} 68 69void CooperateOut::Initial::BuildChains(std::shared_ptr<Initial> self, CooperateOut &parent) 70{} 71 72void CooperateOut::Initial::RemoveChains(std::shared_ptr<Initial> self) 73{} 74 75CooperateOut::Initial::Initial(CooperateOut &parent) 76 : ICooperateStep(parent, nullptr), parent_(parent) 77{ 78 AddHandler(CooperateEventType::DISABLE, [this](Context &context, const CooperateEvent &event) { 79 this->OnDisable(context, event); 80 }); 81 AddHandler(CooperateEventType::START, [this](Context &context, const CooperateEvent &event) { 82 this->OnStart(context, event); 83 }); 84 AddHandler(CooperateEventType::STOP, [this](Context &context, const CooperateEvent &event) { 85 this->OnStop(context, event); 86 }); 87 AddHandler(CooperateEventType::APP_CLOSED, [this](Context &context, const CooperateEvent &event) { 88 this->OnAppClosed(context, event); 89 }); 90 AddHandler(CooperateEventType::INPUT_HOTPLUG_EVENT, [this](Context &context, const CooperateEvent &event) { 91 this->OnHotplug(context, event); 92 }); 93 AddHandler(CooperateEventType::INPUT_POINTER_EVENT, [this](Context &context, const CooperateEvent &event) { 94 this->OnPointerEvent(context, event); 95 }); 96 AddHandler(CooperateEventType::DDM_BOARD_OFFLINE, [this](Context &context, const CooperateEvent &event) { 97 this->OnBoardOffline(context, event); 98 }); 99 AddHandler(CooperateEventType::DDP_COOPERATE_SWITCH_CHANGED, 100 [this](Context &context, const CooperateEvent &event) { 101 this->OnSwitchChanged(context, event); 102 }); 103 AddHandler(CooperateEventType::DSOFTBUS_SESSION_CLOSED, 104 [this](Context &context, const CooperateEvent &event) { 105 this->OnSoftbusSessionClosed(context, event); 106 }); 107 AddHandler(CooperateEventType::DSOFTBUS_COME_BACK, 108 [this](Context &context, const CooperateEvent &event) { 109 this->OnComeBack(context, event); 110 }); 111 AddHandler(CooperateEventType::DSOFTBUS_START_COOPERATE, 112 [this](Context &context, const CooperateEvent &event) { 113 this->OnRemoteStart(context, event); 114 }); 115 AddHandler(CooperateEventType::DSOFTBUS_STOP_COOPERATE, 116 [this](Context &context, const CooperateEvent &event) { 117 this->OnRemoteStop(context, event); 118 }); 119 AddHandler(CooperateEventType::DSOFTBUS_RELAY_COOPERATE, 120 [this](Context &context, const CooperateEvent &event) { 121 this->OnRelay(context, event); 122 }); 123} 124 125void CooperateOut::Initial::OnDisable(Context &context, const CooperateEvent &event) 126{ 127 FI_HILOGI("[disable cooperation] Stop cooperation"); 128 parent_.StopCooperate(context, event); 129} 130 131void CooperateOut::Initial::OnStart(Context &context, const CooperateEvent &event) 132{ 133 StartCooperateEvent param = std::get<StartCooperateEvent>(event.event); 134 135 context.eventMgr_.StartCooperate(param); 136 FI_HILOGI("[start] Start cooperation with \'%{public}s\', report success when out", 137 Utility::Anonymize(context.Peer()).c_str()); 138 DSoftbusStartCooperateFinished failNotice { 139 .success = false, 140 .errCode = static_cast<int32_t>(CoordinationErrCode::UNEXPECTED_START_CALL) 141 }; 142 context.eventMgr_.StartCooperateFinish(failNotice); 143} 144 145void CooperateOut::Initial::OnStop(Context &context, const CooperateEvent &event) 146{ 147 StopCooperateEvent param = std::get<StopCooperateEvent>(event.event); 148 149 context.eventMgr_.StopCooperate(param); 150 FI_HILOGI("[stop] Stop cooperation with \'%{public}s\', unchain:%{public}d", 151 Utility::Anonymize(context.Peer()).c_str(), param.isUnchained); 152 parent_.StopCooperate(context, event); 153 154 param.networkId = context.Peer(); 155 DSoftbusStopCooperateFinished notice { 156 .networkId = context.Peer(), 157 .normal = true, 158 }; 159 context.eventMgr_.StopCooperateFinish(notice); 160 161 parent_.UnchainConnections(context, param); 162} 163 164void CooperateOut::Initial::OnComeBack(Context &context, const CooperateEvent &event) 165{ 166 CALL_INFO_TRACE; 167 DSoftbusComeBack notice = std::get<DSoftbusComeBack>(event.event); 168 169 if (!context.IsPeer(notice.networkId)) { 170 return; 171 } 172 FI_HILOGI("[come back] From \'%{public}s\'", Utility::Anonymize(notice.networkId).c_str()); 173 context.OnRemoteStartCooperate(notice.extra); 174 DSoftbusStartCooperate startEvent { 175 .networkId = notice.networkId, 176 }; 177 context.eventMgr_.RemoteStart(startEvent); 178 context.inputEventInterceptor_.Disable(); 179 180 context.RemoteStartSuccess(notice); 181 context.eventMgr_.RemoteStartFinish(notice); 182 TransiteTo(context, CooperateState::COOPERATE_STATE_FREE); 183 context.OnBack(); 184} 185 186void CooperateOut::Initial::OnRemoteStart(Context &context, const CooperateEvent &event) 187{ 188 DSoftbusStartCooperate notice = std::get<DSoftbusStartCooperate>(event.event); 189 190 if (context.IsLocal(notice.networkId)) { 191 return; 192 } 193 FI_HILOGI("[remote start] Request from \'%{public}s\'", Utility::Anonymize(notice.networkId).c_str()); 194 if (context.IsPeer(notice.networkId)) { 195 FI_HILOGI("[remote start] Reset on request from peer"); 196 parent_.StopCooperate(context, event); 197 return; 198 } 199 context.OnResetCooperation(); 200 context.OnRemoteStartCooperate(notice.extra); 201 context.eventMgr_.RemoteStart(notice); 202 context.inputEventInterceptor_.Disable(); 203 204 DSoftbusStopCooperate stopNotice {}; 205 context.dsoftbus_.StopCooperate(context.Peer(), stopNotice); 206 207 context.RemoteStartSuccess(notice); 208 context.inputEventBuilder_.Enable(context); 209 context.eventMgr_.RemoteStartFinish(notice); 210 FI_HILOGI("[remote start] Cooperation with \'%{public}s\' established", Utility::Anonymize(context.Peer()).c_str()); 211 TransiteTo(context, CooperateState::COOPERATE_STATE_IN); 212 context.OnTransitionIn(); 213} 214 215void CooperateOut::Initial::OnRemoteStop(Context &context, const CooperateEvent &event) 216{ 217 DSoftbusStopCooperate notice = std::get<DSoftbusStopCooperate>(event.event); 218 219 if (!context.IsPeer(notice.networkId)) { 220 return; 221 } 222 FI_HILOGI("[remote stop] Notification from \'%{public}s\'", Utility::Anonymize(notice.networkId).c_str()); 223 context.eventMgr_.RemoteStop(notice); 224 context.inputEventInterceptor_.Disable(); 225 context.ResetCursorPosition(); 226 context.eventMgr_.RemoteStopFinish(notice); 227 TransiteTo(context, CooperateState::COOPERATE_STATE_FREE); 228 context.OnResetCooperation(); 229} 230 231void CooperateOut::Initial::OnRelay(Context &context, const CooperateEvent &event) 232{ 233 DSoftbusRelayCooperate notice = std::get<DSoftbusRelayCooperate>(event.event); 234 if (!context.IsPeer(notice.networkId)) { 235 return; 236 } 237 DSoftbusRelayCooperateFinished resp { 238 .targetNetworkId = notice.targetNetworkId, 239 }; 240 241 int32_t ret = context.dsoftbus_.OpenSession(notice.targetNetworkId); 242 if (ret != RET_OK) { 243 FI_HILOGE("[relay cooperate] Failed to connect to \'%{public}s\'", 244 Utility::Anonymize(notice.targetNetworkId).c_str()); 245 resp.normal = false; 246 context.dsoftbus_.RelayCooperateFinish(notice.networkId, resp); 247 return; 248 } 249 250 resp.normal = true; 251 context.dsoftbus_.RelayCooperateFinish(notice.networkId, resp); 252 253 context.RelayCooperate(notice); 254 context.inputEventInterceptor_.Update(context); 255 FI_HILOGI("[relay cooperate] Relay cooperation to \'%{public}s\'", Utility::Anonymize(context.Peer()).c_str()); 256 context.OnRelayCooperation(context.Peer(), context.NormalizedCursorPosition()); 257} 258 259void CooperateOut::Initial::OnHotplug(Context &context, const CooperateEvent &event) 260{ 261 InputHotplugEvent notice = std::get<InputHotplugEvent>(event.event); 262 if (notice.deviceId != context.StartDeviceId()) { 263 return; 264 } 265 FI_HILOGI("Stop cooperation on unplug of dedicated pointer"); 266 parent_.StopCooperate(context, event); 267} 268 269void CooperateOut::Initial::OnAppClosed(Context &context, const CooperateEvent &event) 270{ 271 FI_HILOGI("[app closed] Close all connections"); 272 context.dsoftbus_.CloseAllSessions(); 273 FI_HILOGI("[app closed] Stop cooperation"); 274 parent_.StopCooperate(context, event); 275} 276 277void CooperateOut::Initial::OnPointerEvent(Context &context, const CooperateEvent &event) 278{ 279 InputPointerEvent notice = std::get<InputPointerEvent>(event.event); 280 281 if ((notice.sourceType != MMI::PointerEvent::SOURCE_TYPE_MOUSE) || 282 (notice.deviceId == context.StartDeviceId()) || 283 (notice.deviceId < 0)) { 284 return; 285 } 286 FI_HILOGI("Stop cooperation on operation of undedicated pointer"); 287 parent_.StopCooperate(context, event); 288} 289 290void CooperateOut::Initial::OnBoardOffline(Context &context, const CooperateEvent &event) 291{ 292 DDMBoardOfflineEvent notice = std::get<DDMBoardOfflineEvent>(event.event); 293 294 if (!context.IsPeer(notice.networkId)) { 295 return; 296 } 297 FI_HILOGI("[board offline] Peer(\'%{public}s\') is offline", Utility::Anonymize(notice.networkId).c_str()); 298 parent_.StopCooperate(context, event); 299} 300 301void CooperateOut::Initial::OnSwitchChanged(Context &context, const CooperateEvent &event) 302{ 303 DDPCooperateSwitchChanged notice = std::get<DDPCooperateSwitchChanged>(event.event); 304 305 if (!context.IsPeer(notice.networkId) || notice.normal) { 306 return; 307 } 308 FI_HILOGI("[switch off] Peer(\'%{public}s\') switch off", Utility::Anonymize(notice.networkId).c_str()); 309 parent_.StopCooperate(context, event); 310} 311 312void CooperateOut::Initial::OnSoftbusSessionClosed(Context &context, const CooperateEvent &event) 313{ 314 DSoftbusSessionClosed notice = std::get<DSoftbusSessionClosed>(event.event); 315 316 if (!context.IsPeer(notice.networkId)) { 317 return; 318 } 319 FI_HILOGI("[dsoftbus session closed] Disconnected with \'%{public}s\'", 320 Utility::Anonymize(notice.networkId).c_str()); 321 parent_.StopCooperate(context, event); 322} 323 324void CooperateOut::Initial::OnProgress(Context &context, const CooperateEvent &event) 325{} 326 327void CooperateOut::Initial::OnReset(Context &context, const CooperateEvent &event) 328{} 329 330void CooperateOut::StopCooperate(Context &context, const CooperateEvent &event) 331{ 332 context.inputEventInterceptor_.Disable(); 333 334 DSoftbusStopCooperate notice {}; 335 context.dsoftbus_.StopCooperate(context.Peer(), notice); 336 337 context.ResetCursorPosition(); 338 TransiteTo(context, CooperateState::COOPERATE_STATE_FREE); 339 context.OnResetCooperation(); 340} 341 342void CooperateOut::UnchainConnections(Context &context, const StopCooperateEvent &event) const 343{ 344 if (event.isUnchained) { 345 FI_HILOGI("Unchain all connections"); 346 context.dsoftbus_.CloseAllSessions(); 347 context.eventMgr_.OnUnchain(event); 348 } 349} 350} // namespace Cooperate 351} // namespace DeviceStatus 352} // namespace Msdp 353} // namespace OHOS 354