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
23 namespace OHOS {
24 namespace CastEngine {
25 namespace CastEngineService {
26 DEFINE_CAST_ENGINE_LABEL("Cast-Session-State");
27
Enter(SessionState state)28 void 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
Exit()42 void 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
HandleMessage(const Message & msg)53 bool 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
GetStateId() const66 SessionState CastSessionImpl::BaseState::GetStateId() const
67 {
68 return stateId_;
69 }
70
Enter()71 void CastSessionImpl::DefaultState::Enter()
72 {
73 BaseState::Enter(SessionState::DEFAULT);
74 }
75
Exit()76 void CastSessionImpl::DefaultState::Exit()
77 {
78 BaseState::Exit();
79 }
80
HandleMessage(const Message & msg)81 bool 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
Enter()103 void CastSessionImpl::DisconnectedState::Enter()
104 {
105 BaseState::Enter(SessionState::DISCONNECTED);
106 }
107
Exit()108 void CastSessionImpl::DisconnectedState::Exit()
109 {
110 BaseState::Exit();
111 }
112
HandleMessage(const Message & msg)113 bool 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
Enter()146 void CastSessionImpl::AuthingState::Enter()
147 {
148 BaseState::Enter(SessionState::AUTHING);
149 }
150
Exit()151 void CastSessionImpl::AuthingState::Exit()
152 {
153 BaseState::Exit();
154 }
155
HandleMessage(const Message & msg)156 bool 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
Enter()203 void CastSessionImpl::ConnectingState::Enter()
204 {
205 BaseState::Enter(SessionState::CONNECTING);
206 }
207
Exit()208 void CastSessionImpl::ConnectingState::Exit()
209 {
210 BaseState::Exit();
211 }
212
HandleMessage(const Message & msg)213 bool 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
HandleSetupMessage(const Message & msg,sptr<CastSessionImpl> session)251 void 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
HandleSetupSuccessMessage(const Message & msg,const MessageId & msgId,sptr<CastSessionImpl> session)265 void 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
HandleDisconnectMessage(const Message & msg,sptr<CastSessionImpl> session)280 void 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
HandleErrorMessage(const Message & msg,sptr<CastSessionImpl> session)294 void 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
HandleRenderReadyMessage(const Message & msg,sptr<CastSessionImpl> session)304 void 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
HandleConnectMessage(const Message & msg,const MessageId & msgId,sptr<CastSessionImpl> session)318 void 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
Enter()329 void 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
Exit()365 void CastSessionImpl::ConnectedState::Exit()
366 {
367 BaseState::Exit();
368 }
369
HandleMessage(const Message & msg)370 bool 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
Enter()421 void CastSessionImpl::StreamState::Enter()
422 {
423 BaseState::Enter(SessionState::STREAM);
424 }
425
Exit()426 void CastSessionImpl::StreamState::Exit()
427 {
428 BaseState::Exit();
429 }
430
HandleMessage(const Message & msg)431 bool 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
Enter()470 void CastSessionImpl::PausedState::Enter()
471 {
472 BaseState::Enter(SessionState::PAUSED);
473 }
474
Exit()475 void CastSessionImpl::PausedState::Exit()
476 {
477 BaseState::Exit();
478 }
479
HandleMessage(const Message & msg)480 bool 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
Enter()511 void CastSessionImpl::PlayingState::Enter()
512 {
513 BaseState::Enter(SessionState::PLAYING);
514 }
515
Exit()516 void CastSessionImpl::PlayingState::Exit()
517 {
518 BaseState::Exit();
519 }
520
HandleMessage(const Message & msg)521 bool 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
Enter()559 void 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
Exit()571 void CastSessionImpl::DisconnectingState::Exit()
572 {
573 BaseState::Exit();
574 }
575
HandleMessage(const Message & msg)576 bool 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