• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 &param = 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 &param = 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