1/* 2 * Copyright (c) 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 * Description: Cast Session states realization. 15 * Author: zhangge 16 * Create: 2022-07-19 17 */ 18 19#include "cast_session_impl.h" 20#include "cast_engine_log.h" 21#include "cast_engine_dfx.h" 22 23namespace OHOS { 24namespace CastEngine { 25namespace CastEngineService { 26DEFINE_CAST_ENGINE_LABEL("Cast-Session-State"); 27 28void CastSessionImpl::BaseState::Enter(SessionState state) 29{ 30 auto session = session_.promote(); 31 if (!session) { 32 CLOGE("Session is invalid"); 33 return; 34 } 35 36 // BaseState and its inherited classes work under the strict control of the session, 37 // so the session_ used in the BaseState member function must not be null. 38 session->sessionState_ = state; 39 CLOGI("%s enter", SESSION_STATE_STRING[static_cast<int>(state)].c_str()); 40} 41 42void CastSessionImpl::BaseState::Exit() 43{ 44 auto session = session_.promote(); 45 if (!session) { 46 CLOGE("Session is invalid"); 47 return; 48 } 49 50 CLOGI("%s exit", SESSION_STATE_STRING[static_cast<int>(session->sessionState_)].c_str()); 51} 52 53bool CastSessionImpl::BaseState::HandleMessage(const Message &msg) 54{ 55 auto session = session_.promote(); 56 if (!session) { 57 CLOGE("Session is invalid"); 58 return false; 59 } 60 61 CLOGI("msg: %s, session state: %s", session->MESSAGE_ID_STRING[msg.what_].c_str(), 62 SESSION_STATE_STRING[static_cast<int>(session->sessionState_)].c_str()); 63 return true; 64} 65 66SessionState CastSessionImpl::BaseState::GetStateId() const 67{ 68 return stateId_; 69} 70 71void CastSessionImpl::DefaultState::Enter() 72{ 73 BaseState::Enter(SessionState::DEFAULT); 74} 75 76void CastSessionImpl::DefaultState::Exit() 77{ 78 BaseState::Exit(); 79} 80 81bool CastSessionImpl::DefaultState::HandleMessage(const Message &msg) 82{ 83 auto session = session_.promote(); 84 if (!session) { 85 CLOGE("Session is invalid"); 86 return false; 87 } 88 89 BaseState::HandleMessage(msg); 90 91 MessageId msgId = static_cast<MessageId>(msg.what_); 92 switch (msgId) { 93 case MessageId::MSG_CONNECT_TIMEOUT: 94 session->ProcessStateEvent(MessageId::MSG_CONNECT_TIMEOUT, msg); 95 break; 96 default: 97 CLOGW("unsupported msg: %s, in default state", MESSAGE_ID_STRING[msgId].c_str()); 98 return false; 99 } 100 return true; 101} 102 103void CastSessionImpl::DisconnectedState::Enter() 104{ 105 BaseState::Enter(SessionState::DISCONNECTED); 106} 107 108void CastSessionImpl::DisconnectedState::Exit() 109{ 110 BaseState::Exit(); 111} 112 113bool CastSessionImpl::DisconnectedState::HandleMessage(const Message &msg) 114{ 115 auto session = session_.promote(); 116 if (!session) { 117 CLOGE("Session is invalid"); 118 return false; 119 } 120 121 BaseState::HandleMessage(msg); 122 123 MessageId msgId = static_cast<MessageId>(msg.what_); 124 std::string deviceId = msg.strArg_; 125 switch (msgId) { 126 case MessageId::MSG_AUTH: 127 session->TransferTo(session->authingState_); 128 break; 129 case MessageId::MSG_CONNECT: 130 if (session->ProcessConnect(msg) >= 0) { 131 session->ChangeDeviceState(DeviceState::CONNECTING, deviceId); 132 session->SendCastMessageDelayed(MessageId::MSG_CONNECT_TIMEOUT, TIMEOUT_CONNECT); 133 session->TransferTo(session->connectingState_); 134 } else { 135 // Connection failed 136 session->ChangeDeviceState(DeviceState::DISCONNECTED, deviceId); 137 } 138 break; 139 default: 140 CLOGW("unsupported msg: %s, in disconnected state", MESSAGE_ID_STRING[msgId].c_str()); 141 return false; 142 } 143 return true; 144} 145 146void CastSessionImpl::AuthingState::Enter() 147{ 148 BaseState::Enter(SessionState::AUTHING); 149} 150 151void CastSessionImpl::AuthingState::Exit() 152{ 153 BaseState::Exit(); 154} 155 156bool CastSessionImpl::AuthingState::HandleMessage(const Message &msg) 157{ 158 auto session = session_.promote(); 159 if (!session) { 160 CLOGE("Session is invalid"); 161 return false; 162 } 163 164 BaseState::HandleMessage(msg); 165 166 MessageId msgId = static_cast<MessageId>(msg.what_); 167 std::string deviceId = msg.strArg_; 168 switch (msgId) { 169 case MessageId::MSG_CONNECT: { 170 int port = session->ProcessConnect(msg); 171 if (port >= 0) { 172 session->ChangeDeviceState(DeviceState::CONNECTING, deviceId); 173 session->SendCastMessageDelayed(MessageId::MSG_CONNECT_TIMEOUT, TIMEOUT_CONNECT); 174 session->TransferTo(session->connectingState_); 175 session->SendConsultData(deviceId, port); 176 } else { 177 session->ChangeDeviceState(DeviceState::DISCONNECTED, deviceId); 178 } 179 break; 180 } 181 case MessageId::MSG_DISCONNECT: 182 case MessageId::MSG_CONNECT_TIMEOUT: 183 session->ProcessDisconnect(msg); 184 session->ChangeDeviceState(DeviceState::DISCONNECTED, deviceId, msg.eventCode_); 185 session->RemoveRemoteDevice(deviceId); 186 session->TransferTo(session->disconnectingState_); 187 break; 188 case MessageId::MSG_ERROR: 189 session->ProcessError(msg); 190 session->TransferTo(session->disconnectingState_); 191 break; 192 case MessageId::MSG_AUTH: 193 session->ReportDeviceStateInfo(DeviceState::AUTHING, deviceId, msg.eventCode_); 194 break; 195 default: 196 CLOGW("unsupported msg: %s, in authing state", MESSAGE_ID_STRING[msgId].c_str()); 197 return false; 198 } 199 return true; 200} 201 202 203void CastSessionImpl::ConnectingState::Enter() 204{ 205 BaseState::Enter(SessionState::CONNECTING); 206} 207 208void CastSessionImpl::ConnectingState::Exit() 209{ 210 BaseState::Exit(); 211} 212 213bool CastSessionImpl::ConnectingState::HandleMessage(const Message &msg) 214{ 215 auto session = session_.promote(); 216 if (!session) { 217 CLOGE("Session is invalid"); 218 return false; 219 } 220 BaseState::HandleMessage(msg); 221 MessageId msgId = static_cast<MessageId>(msg.what_); 222 switch (msgId) { 223 case MessageId::MSG_SETUP: 224 HandleSetupMessage(msg, session); 225 break; 226 case MessageId::MSG_SETUP_SUCCESS: 227 HandleSetupSuccessMessage(msg, msgId, session); 228 break; 229 case MessageId::MSG_DISCONNECT: 230 case MessageId::MSG_CONNECT_TIMEOUT: 231 HandleDisconnectMessage(msg, session); 232 break; 233 case MessageId::MSG_ERROR: 234 HandleErrorMessage(msg, session); 235 break; 236 case MessageId::MSG_PEER_RENDER_READY: 237 HandleRenderReadyMessage(msg, session); 238 break; 239 case MessageId::MSG_CONNECT: 240 case MessageId::MSG_PLAY: 241 case MessageId::MSG_PLAY_REQ: 242 HandleConnectMessage(msg, msgId, session); 243 break; 244 default: 245 CLOGW("unsupported msg: %s, in connecting state", MESSAGE_ID_STRING[msgId].c_str()); 246 return false; 247 } 248 return true; 249} 250 251void CastSessionImpl::ConnectingState::HandleSetupMessage(const Message &msg, sptr<CastSessionImpl> session) 252{ 253 if (!session) { 254 CLOGE("Session is invalid"); 255 return; 256 } 257 std::string deviceId = msg.strArg_; 258 if (!session->ProcessSetUp(msg)) { 259 session->ChangeDeviceState(DeviceState::DISCONNECTED, deviceId); 260 session->RemoveRemoteDevice(deviceId); 261 session->TransferTo(session->disconnectingState_); 262 } 263} 264 265void CastSessionImpl::ConnectingState::HandleSetupSuccessMessage(const Message &msg, const MessageId &msgId, 266 sptr<CastSessionImpl> session) 267{ 268 if (!session) { 269 CLOGE("Session is invalid"); 270 return; 271 } 272 if (session->ProcessSetUpSuccess(msg)) { 273 session->RemoveMessage(Message(static_cast<int>(MessageId::MSG_CONNECT_TIMEOUT))); 274 CLOGI("in connecting state, defer message: %{public}d", msgId); 275 session->DeferMessage(msg); 276 session->TransferTo(session->connectedState_); 277 }; 278} 279 280void CastSessionImpl::ConnectingState::HandleDisconnectMessage(const Message &msg, sptr<CastSessionImpl> session) 281{ 282 if (!session) { 283 CLOGE("Session is invalid"); 284 return; 285 } 286 std::string deviceId = msg.strArg_; 287 session->ProcessDisconnect(msg); 288 session->ChangeDeviceState(DeviceState::DISCONNECTED, deviceId, EventCode::ERR_CONNECTION_FAILED); 289 session->RemoveMessage(Message(static_cast<int>(MessageId::MSG_CONNECT_TIMEOUT))); 290 session->RemoveRemoteDevice(deviceId); 291 session->TransferTo(session->disconnectingState_); 292} 293 294void CastSessionImpl::ConnectingState::HandleErrorMessage(const Message &msg, sptr<CastSessionImpl> session) 295{ 296 if (!session) { 297 CLOGE("Session is invalid"); 298 return; 299 } 300 session->ProcessError(msg); 301 session->TransferTo(session->disconnectingState_); 302} 303 304void CastSessionImpl::ConnectingState::HandleRenderReadyMessage(const Message &msg, sptr<CastSessionImpl> session) 305{ 306 if (!session) { 307 CLOGE("Session is invalid"); 308 return; 309 } 310 std::string deviceId = msg.strArg_; 311 if (session->IsStreamMode()) { 312 session->RemoveMessage(Message(static_cast<int>(MessageId::MSG_CONNECT_TIMEOUT))); 313 session->ChangeDeviceState(DeviceState::STREAM, deviceId); 314 session->TransferTo(session->streamState_); 315 } 316} 317 318void CastSessionImpl::ConnectingState::HandleConnectMessage(const Message &msg, const MessageId &msgId, 319 sptr<CastSessionImpl> session) 320{ 321 if (!session) { 322 CLOGE("Session is invalid"); 323 return; 324 } 325 CLOGI("in connecting state, defer message: %d", msgId); 326 session->DeferMessage(msg); 327} 328 329void CastSessionImpl::ConnectedState::Enter() 330{ 331 BaseState::Enter(SessionState::CONNECTED); 332 333 auto session = session_.promote(); 334 if (!session) { 335 CLOGE("Session is invalid"); 336 return; 337 } 338 339 if (session->property_.protocolType == ProtocolType::COOPERATION) { 340 HiSysEventWriteWrap(__func__, { 341 {"BIZ_SCENE", static_cast<int32_t>(BIZSceneType::COOPERATION)}, 342 {"BIZ_STATE", static_cast<int32_t>(BIZStateType::BIZ_STATE_END)}, 343 {"BIZ_STAGE", static_cast<int32_t>(BIZSceneStage::COOPERATION_CAST_SUCCESS)}, 344 {"STAGE_RES", static_cast<int32_t>(StageResType::STAGE_RES_SUCCESS)}, 345 {"ERROR_CODE", CAST_RADAR_SUCCESS}}, { 346 {"TO_CALL_PKG", DSOFTBUS_NAME}, 347 {"LOCAL_SESS_NAME", ""}, 348 {"PEER_SESS_NAME", ""}, 349 {"PEER_UDID", ""}}); 350 } else { 351 auto sceneType = GetBIZSceneType(static_cast<int>(session->property_.protocolType)); 352 HiSysEventWriteWrap(__func__, { 353 {"BIZ_SCENE", sceneType}, 354 {"BIZ_STATE", static_cast<int32_t>(BIZStateType::BIZ_STATE_END)}, 355 {"BIZ_STAGE", static_cast<int32_t>(BIZSceneStage::CAST_SUCCESS)}, 356 {"STAGE_RES", static_cast<int32_t>(StageResType::STAGE_RES_SUCCESS)}, 357 {"ERROR_CODE", CAST_RADAR_SUCCESS}}, { 358 {"TO_CALL_PKG", DSOFTBUS_NAME}, 359 {"LOCAL_SESS_NAME", ""}, 360 {"PEER_SESS_NAME", ""}, 361 {"PEER_UDID", ""}}); 362 } 363} 364 365void CastSessionImpl::ConnectedState::Exit() 366{ 367 BaseState::Exit(); 368} 369 370bool CastSessionImpl::ConnectedState::HandleMessage(const Message &msg) 371{ 372 auto session = session_.promote(); 373 if (!session) { 374 return false; 375 } 376 BaseState::HandleMessage(msg); 377 MessageId msgId = static_cast<MessageId>(msg.what_); 378 const auto &deviceId = msg.strArg_; 379 switch (msgId) { 380 case MessageId::MSG_CONNECT: 381 // Designed for 1->N scenarios 382 session->ChangeDeviceState(DeviceState::CONNECTING, deviceId); 383 if (session->ProcessConnect(msg) >= 0) { 384 session->ChangeDeviceState(DeviceState::CONNECTED, deviceId); 385 session->ChangeDeviceState(DeviceState::PAUSED, deviceId); 386 session->TransferTo(session->pausedState_); 387 } else { 388 session->ChangeDeviceState(DeviceState::DISCONNECTED, deviceId); 389 } 390 return true; 391 case MessageId::MSG_SETUP_SUCCESS: 392 if (!session->IsStreamMode()) { 393 session->ChangeDeviceState(DeviceState::CONNECTED, deviceId); 394 session->ChangeDeviceState(DeviceState::PAUSED, deviceId); 395 session->TransferTo(session->pausedState_); 396 } else if (session->IsSink()) { 397 session->ChangeDeviceState(DeviceState::STREAM, deviceId); 398 session->TransferTo(session->streamState_); 399 } 400 return true; 401 case MessageId::MSG_DISCONNECT: 402 session->ProcessDisconnect(msg); 403 session->ChangeDeviceState(DeviceState::DISCONNECTED, deviceId); 404 session->RemoveRemoteDevice(deviceId); 405 session->TransferTo(session->disconnectingState_); 406 return true; 407 case MessageId::MSG_ERROR: 408 session->ProcessError(msg); 409 session->TransferTo(session->disconnectingState_); 410 return true; 411 case MessageId::MSG_PLAY_REQ: 412 CLOGI("in connected state, defer message: %d", msgId); 413 session->DeferMessage(msg); 414 return true; 415 default: 416 CLOGW("unsupported msg: %s, in connected state", MESSAGE_ID_STRING[msgId].c_str()); 417 return false; 418 } 419} 420 421void CastSessionImpl::StreamState::Enter() 422{ 423 BaseState::Enter(SessionState::STREAM); 424} 425 426void CastSessionImpl::StreamState::Exit() 427{ 428 BaseState::Exit(); 429} 430 431bool CastSessionImpl::StreamState::HandleMessage(const Message &msg) 432{ 433 auto session = session_.promote(); 434 if (!session) { 435 CLOGE("Session is invalid"); 436 return false; 437 } 438 BaseState::HandleMessage(msg); 439 MessageId msgId = static_cast<MessageId>(msg.what_); 440 const auto ¶m = msg.strArg_; 441 auto streamManager = session->StreamManagerGetter(); 442 switch (msgId) { 443 case MessageId::MSG_STREAM_RECV_ACTION_EVENT_FROM_PEERS: 444 if (msg.arg1_ == ICastStreamManager::MODULE_EVENT_ID_CHANNEL_CREATE || 445 msg.arg1_ == ICastStreamManager::MODULE_EVENT_ID_STREAM_CHANNEL) { 446 if (session->CreateStreamChannel() == INVALID_PORT) { 447 session->SendCastMessage(MessageId::MSG_ERROR); 448 } 449 break; 450 } 451 if (streamManager != nullptr) { 452 streamManager->ProcessActionsEvent(msg.arg1_, param); 453 } else { 454 CLOGE("streamManager is nullptr"); 455 } 456 break; 457 case MessageId::MSG_STREAM_SEND_ACTION_EVENT_TO_PEERS: 458 session->SendEventChange(MODULE_ID_CAST_STREAM, msg.arg1_, param); 459 break; 460 case MessageId::MSG_PEER_RENDER_READY: 461 session->SendCastRenderReadyOption(msg.arg1_); 462 break; 463 default: 464 CLOGW("unsupported msg: %s, in stream state", MESSAGE_ID_STRING[msgId].c_str()); 465 return false; 466 } 467 return true; 468} 469 470void CastSessionImpl::PausedState::Enter() 471{ 472 BaseState::Enter(SessionState::PAUSED); 473} 474 475void CastSessionImpl::PausedState::Exit() 476{ 477 BaseState::Exit(); 478} 479 480bool CastSessionImpl::PausedState::HandleMessage(const Message &msg) 481{ 482 auto session = session_.promote(); 483 if (!session) { 484 CLOGE("Session is invalid"); 485 return false; 486 } 487 488 BaseState::HandleMessage(msg); 489 MessageId msgId = static_cast<MessageId>(msg.what_); 490 491 switch (msgId) { 492 case MessageId::MSG_PLAY: 493 case MessageId::MSG_PLAY_REQ: 494 // vtp disconnect after paused for 30s. setup success after play request 495 case MessageId::MSG_SETUP_SUCCESS: 496 if (session->ProcessStateEvent(msgId, msg)) { 497 session->ChangeDeviceState(DeviceState::PLAYING, msg.strArg_); 498 session->TransferTo(session->playingState_); 499 } 500 break; 501 case MessageId::MSG_PROCESS_TRIGGER_REQ: 502 session->ProcessTriggerReq(msg); 503 break; 504 default: 505 CLOGW("unsupported msg: %s, in paused state", MESSAGE_ID_STRING[msgId].c_str()); 506 return false; 507 } 508 return true; 509} 510 511void CastSessionImpl::PlayingState::Enter() 512{ 513 BaseState::Enter(SessionState::PLAYING); 514} 515 516void CastSessionImpl::PlayingState::Exit() 517{ 518 BaseState::Exit(); 519} 520 521bool CastSessionImpl::PlayingState::HandleMessage(const Message &msg) 522{ 523 auto session = session_.promote(); 524 if (!session) { 525 CLOGE("Session is invalid"); 526 return false; 527 } 528 const auto ¶m = msg.strArg_; 529 BaseState::HandleMessage(msg); 530 MessageId msgId = static_cast<MessageId>(msg.what_); 531 switch (msgId) { 532 case MessageId::MSG_PAUSE: 533 case MessageId::MSG_PAUSE_REQ: 534 if (session->ProcessStateEvent(msgId, msg)) { 535 session->ChangeDeviceState(DeviceState::PAUSED, msg.strArg_); 536 session->TransferTo(session->pausedState_); 537 } 538 break; 539 // Reserved MSG_PLAY and MSG_PLAY_REQ for 1->N scenarios 540 case MessageId::MSG_PLAY: 541 case MessageId::MSG_PLAY_REQ: 542 break; 543 case MessageId::MSG_UPDATE_VIDEO_SIZE: 544 session->ProcessStateEvent(MessageId::MSG_UPDATE_VIDEO_SIZE, msg); 545 break; 546 case MessageId::MSG_SET_CAST_MODE: 547 session->ProcessSetCastMode(msg); 548 break; 549 case MessageId::MSG_MIRROR_SEND_ACTION_EVENT_TO_PEERS: 550 session->SendEventChange(MODULE_ID_MEDIA, msg.arg1_, param); 551 break; 552 default: 553 CLOGW("unsupported msg: %s, in playing state", MESSAGE_ID_STRING[msgId].c_str()); 554 return false; 555 } 556 return true; 557} 558 559void CastSessionImpl::DisconnectingState::Enter() 560{ 561 auto session = session_.promote(); 562 if (!session) { 563 CLOGE("Session is invalid"); 564 return; 565 } 566 567 BaseState::Enter(SessionState::DISCONNECTING); 568 session->TransferTo(session->disconnectedState_); 569} 570 571void CastSessionImpl::DisconnectingState::Exit() 572{ 573 BaseState::Exit(); 574} 575 576bool CastSessionImpl::DisconnectingState::HandleMessage(const Message &msg) 577{ 578 auto session = session_.promote(); 579 if (!session) { 580 CLOGE("Session is invalid"); 581 return false; 582 } 583 584 BaseState::HandleMessage(msg); 585 MessageId msgId = static_cast<MessageId>(msg.what_); 586 587 switch (msgId) { 588 case MessageId::MSG_CONNECT: 589 CLOGI("in connecting state, defer message: %d", msgId); 590 session->DeferMessage(msg); 591 break; 592 default: 593 CLOGW("unsupported msg: %s, in disconnecting state", MESSAGE_ID_STRING[msgId].c_str()); 594 return false; 595 } 596 return true; 597} 598} // namespace CastEngineService 599} // namespace CastEngine 600} // namespace OHOS