• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development 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 "context.h"
17 #include "agent/sinkagent/sink_agent.h"
18 #include "agent/srcagent/src_agent.h"
19 #include "common/common_macro.h"
20 #include "common/event_channel.h"
21 #include "common/sharing_log.h"
22 #include "magic_enum.hpp"
23 
24 namespace OHOS {
25 namespace Sharing {
Context()26 Context::Context()
27 {
28     SHARING_LOGD("contextId: %{public}u.", GetId());
29 }
30 
~Context()31 Context::~Context()
32 {
33     SHARING_LOGD("contextId: %{public}u.", GetId());
34 }
35 
Release()36 void Context::Release()
37 {
38     SHARING_LOGD("contextId: %{public}u.", GetId());
39     destroying_ = true;
40     std::lock_guard<std::mutex> lock(mutex_);
41     if (agents_.size()) {
42         SHARING_LOGW("exception to enter! contextId: %{public}u.", GetId());
43     }
44     agents_.clear();
45 }
46 
HandleEvent(SharingEvent & event)47 int32_t Context::HandleEvent(SharingEvent &event)
48 {
49     SHARING_LOGD("trace.");
50     RETURN_INVALID_IF_NULL(event.eventMsg);
51     SHARING_LOGI(
52         "contextId: %{public}u, fromMgr: %{public}u, srcId: %{public}u, "
53         "toMgr: %{public}u, toId: %{public}u, event: %{public}s.",
54         GetId(), event.eventMsg->fromMgr, event.eventMsg->srcId, event.eventMsg->toMgr, event.eventMsg->dstId,
55         std::string(magic_enum::enum_name(event.eventMsg->type)).c_str());
56     if (destroying_) {
57         SHARING_LOGW("destroying contextId: %{public}u.", GetId());
58         return -1;
59     }
60 
61     switch (event.eventMsg->type) {
62         case EventType::EVENT_CONTEXT_AGENT_CREATE: {
63             auto eventMsg = ConvertEventMsg<ContextEventMsg>(event);
64             if (eventMsg) {
65                 interactionId_ = eventMsg->srcId;
66                 eventMsg->agentId = HandleCreateAgent(eventMsg->className, eventMsg->agentType, eventMsg->agentId);
67             }
68             break;
69         }
70         case EventType::EVENT_CONTEXT_AGENT_DESTROY:
71             HandleAgentDestroy(event);
72             break;
73         case EventType::EVENT_CONTEXT_STATE_AGENT_DESTROY:
74             HandleStateDestroyAgent(event);
75             break;
76         default:
77             DistributeEvent(event);
78             break;
79     }
80 
81     return 0;
82 }
83 
HandleAgentDestroy(SharingEvent & event)84 void Context::HandleAgentDestroy(SharingEvent &event)
85 {
86     SHARING_LOGD("trace.");
87     RETURN_IF_NULL(event.eventMsg);
88     auto eventMsg = ConvertEventMsg<AgentEventMsg>(event);
89     if (eventMsg == nullptr) {
90         SHARING_LOGE("msg null.");
91         return;
92     }
93 
94     SHARING_LOGI("contextId: %{public}u, destroy agent agentId: %{public}u.", GetId(), eventMsg->agentId);
95     interactionId_ = eventMsg->srcId;
96     auto agent = GetAgentById(eventMsg->agentId);
97     if (agent == nullptr) {
98         SHARING_LOGE("agent null agentId: %{public}d.", eventMsg->agentId);
99         return;
100     }
101 
102     if (agent->GetAgentType() == SRC_AGENT) {
103         event.eventMsg->type = EVENT_AGENT_DESTROY;
104         agent->HandleEvent(event);
105     } else {
106         agent->SetDestroy();
107         if (IsEmptySrcAgent(eventMsg->agentId)) {
108             event.eventMsg->type = EVENT_AGENT_DESTROY;
109             agent->HandleEvent(event);
110         } else {
111             SHARING_LOGI("contextId: %{public}u, destroy agent need wait src agent destroy. agentId: %{public}u.",
112                          GetId(), eventMsg->agentId);
113             std::lock_guard<std::mutex> lock(mutex_);
114             for (auto item : agents_) {
115                 if (item.second->GetAgentType() == SRC_AGENT) {
116                     event.eventMsg->type = EVENT_AGENT_DESTROY;
117                     item.second->HandleEvent(event);
118                 }
119             }
120         }
121     }
122 }
123 
DistributeEvent(SharingEvent & event)124 void Context::DistributeEvent(SharingEvent &event)
125 {
126     SHARING_LOGD("trace.");
127     auto eventMsg = ConvertEventMsg<AgentEventMsg>(event);
128     if (eventMsg) {
129         auto agent = GetAgentById(eventMsg->agentId);
130         if (agent) {
131             agent->HandleEvent(event);
132         } else {
133             SHARING_LOGE("agent null, contextId: %{pulbic}u, agentId: %{public}u, event: %{public}s.", GetId(),
134                          eventMsg->agentId, std::string(magic_enum::enum_name(event.eventMsg->type)).c_str());
135         }
136     }
137 }
138 
IsEmptySrcAgent(uint32_t sinkAgentId)139 bool Context::IsEmptySrcAgent(uint32_t sinkAgentId)
140 {
141     SHARING_LOGD("trace.");
142     std::lock_guard<std::mutex> lock(mutex_);
143     for (auto &item : agents_) {
144         if (item.second->GetAgentType() == SRC_AGENT) {
145             auto srcAgent = std::static_pointer_cast<SrcAgent>(item.second);
146             if (srcAgent && srcAgent->GetSinkAgentId() == sinkAgentId) {
147                 return false;
148             }
149         }
150     }
151 
152     return true;
153 }
154 
GetSinkAgentSize()155 int32_t Context::GetSinkAgentSize()
156 {
157     SHARING_LOGD("trace.");
158     std::lock_guard<std::mutex> lock(mutex_);
159     int32_t agentSize = 0;
160     for (auto &item : agents_) {
161         if (item.second->GetAgentType() == SINK_AGENT) {
162             SHARING_LOGD("agent id still has %{public}d.", item.second->GetId());
163             ++agentSize;
164         }
165     }
166 
167     return agentSize;
168 }
169 
GetSrcAgentSize()170 int32_t Context::GetSrcAgentSize()
171 {
172     SHARING_LOGD("trace.");
173     std::lock_guard<std::mutex> lock(mutex_);
174     int32_t agentSize = 0;
175     for (auto &item : agents_) {
176         if (item.second->GetAgentType() == SRC_AGENT) {
177             ++agentSize;
178         }
179     }
180 
181     return agentSize;
182 }
183 
SendInteractionEvent(EventType eventType,ContextEventMsg::Ptr & eventMsg)184 void Context::SendInteractionEvent(EventType eventType, ContextEventMsg::Ptr &eventMsg)
185 {
186     SHARING_LOGD("trace.");
187     auto interactionMsg = std::make_shared<InteractionEventMsg>();
188     interactionMsg->fromMgr = ModuleType::MODULE_CONTEXT;
189     interactionMsg->srcId = GetId();
190     interactionMsg->toMgr = ModuleType::MODULE_INTERACTION;
191     interactionMsg->dstId = interactionId_;
192 
193     interactionMsg->type = eventType;
194     interactionMsg->errorCode = eventMsg->errorCode;
195     interactionMsg->agentId = eventMsg->agentId;
196     interactionMsg->agentType = eventMsg->agentType;
197     interactionMsg->contextId = GetId();
198     interactionMsg->surfaceId = eventMsg->surfaceId;
199 
200     SharingEvent event;
201     event.eventMsg = std::move(interactionMsg);
202     SendEvent(event);
203     SHARING_LOGI("event: %{public}u is sended by contextId: %{public}u.", event.eventMsg->type, GetId());
204 }
205 
IsEmptyAgent()206 bool Context::IsEmptyAgent()
207 {
208     SHARING_LOGD("trace.");
209     std::lock_guard<std::mutex> lock(mutex_);
210     return agents_.size() == 0;
211 }
212 
OnAgentNotify(AgentStatusMsg::Ptr & statusMsg)213 void Context::OnAgentNotify(AgentStatusMsg::Ptr &statusMsg)
214 {
215     SHARING_LOGD("trace.");
216     RETURN_IF_NULL(statusMsg);
217     RETURN_IF_NULL(statusMsg->msg);
218     SHARING_LOGI("contextId: %{public}u, agentId: %{public}u, toMgr: %{public}u, dstId: %{public}u, event: %{public}s.",
219                  GetId(), statusMsg->agentId, statusMsg->msg->toMgr, statusMsg->msg->dstId,
220                  std::string(magic_enum::enum_name(statusMsg->msg->type)).c_str());
221 
222     if (statusMsg->msg) {
223         if (statusMsg->msg->toMgr == ModuleType::MODULE_INTERACTION) {
224             statusMsg->msg->dstId = interactionId_;
225             auto interactionMsg = std::static_pointer_cast<InteractionEventMsg>(statusMsg->msg);
226             RETURN_IF_NULL(interactionMsg);
227             interactionMsg->contextId = GetId();
228         } else if (statusMsg->msg->toMgr == ModuleType::MODULE_CONTEXT) {
229             statusMsg->msg->dstId = GetId();
230         }
231 
232         SharingEvent event;
233         event.eventMsg = std::move(statusMsg->msg);
234         event.eventMsg->fromMgr = ModuleType::MODULE_CONTEXT;
235         event.eventMsg->srcId = GetId();
236 
237         SendEvent(event);
238         SHARING_LOGI("event: %{public}s is sended by contextId: %{public}u.",
239                      std::string(magic_enum::enum_name(event.eventMsg->type)).c_str(), GetId());
240     }
241 }
242 
HandleCreateAgent(const std::string & className,AgentType agentType,uint32_t sinkAgentId)243 uint32_t Context::HandleCreateAgent(const std::string &className, AgentType agentType, uint32_t sinkAgentId)
244 {
245     SHARING_LOGI("contextId: %{public}u, agentType: %{public}s, sinkAgentId: %{public}u.", GetId(),
246                  std::string(magic_enum::enum_name(agentType)).c_str(), sinkAgentId);
247 
248     std::shared_ptr<Agent> agent = nullptr;
249     if (agentType == AgentType::SINK_AGENT) {
250         auto sinkAgent = std::make_shared<SinkAgent>();
251         if (sinkAgent->CreateSession(className) == SharingErrorCode::ERR_SESSION_CREATE) {
252             SHARING_LOGE("create agent session error.");
253             return INVALID_ID;
254         } else {
255             auto channelMsg = std::make_shared<ChannelEventMsg>();
256             channelMsg->agentId = sinkAgent->GetId();
257             channelMsg->toMgr = ModuleType::MODULE_MEDIACHANNEL;
258             channelMsg->type = EVENT_MEDIA_CHANNEL_CREATE;
259 
260             SharingEvent event;
261             event.eventMsg = channelMsg;
262             event.eventMsg->fromMgr = ModuleType::MODULE_CONTEXT;
263             event.eventMsg->toMgr = ModuleType::MODULE_MEDIACHANNEL;
264             event.eventMsg->srcId = GetId();
265             SendSyncEvent(event);
266 
267             SHARING_LOGI("create agent create media channel agentId: %{public}u channelId: %{public}u.",
268                          sinkAgent->GetId(), channelMsg->srcId);
269             sinkAgent->UpdateMediaChannelId(channelMsg->srcId);
270 
271             agent = sinkAgent;
272         }
273     } else {
274         std::lock_guard<std::mutex> lock(mutex_);
275         Agent::Ptr sinkAgent = nullptr;
276         if (agents_.find(sinkAgentId) != agents_.end()) {
277             sinkAgent = agents_.find(sinkAgentId)->second;
278         }
279         if (sinkAgent != nullptr && !sinkAgent->GetDestroy()) {
280             auto srcAgent = std::make_shared<SrcAgent>();
281             if (srcAgent->CreateSession(className) == SharingErrorCode::ERR_SESSION_CREATE) {
282                 SHARING_LOGE("create agent session error.");
283                 return INVALID_ID;
284             } else {
285                 SHARING_LOGI("channelId: %{public}u is set to src agentId: %{public}u.", sinkAgent->GetMediaChannelId(),
286                              srcAgent->GetId());
287                 srcAgent->UpdateMediaChannelId(sinkAgent->GetMediaChannelId());
288                 srcAgent->SetSinkAgentId(sinkAgentId);
289             }
290             agent = srcAgent;
291         } else {
292             SHARING_LOGE("sinkAgentId invalid.");
293             return INVALID_ID;
294         }
295     }
296 
297     agent->SetAgentListener(shared_from_this());
298 
299     std::lock_guard<std::mutex> lock(mutex_);
300     agents_.emplace(agent->GetId(), agent);
301     SHARING_LOGI("contextId: %{public}u, create agent className: %{public}s "
302         "agentType: %{public}s agentId: %{public}u size: %{public}zu.",
303         GetId(), className.c_str(), std::string(magic_enum::enum_name(agentType)).c_str(), agent->GetId(),
304         agents_.size());
305     return agent->GetId();
306 }
307 
GetAgentById(uint32_t agentId)308 Agent::Ptr Context::GetAgentById(uint32_t agentId)
309 {
310     SHARING_LOGD("trace.");
311     std::lock_guard<std::mutex> lock(mutex_);
312     auto itr = agents_.find(agentId);
313     if (itr != agents_.end()) {
314         return itr->second;
315     }
316 
317     return nullptr;
318 }
319 
RemoveAgent(uint32_t agentId)320 void Context::RemoveAgent(uint32_t agentId)
321 {
322     SHARING_LOGD("contextId: %{public}u, remove agentId: %{public}u.", GetId(), agentId);
323     std::lock_guard<std::mutex> lock(mutex_);
324     auto itr = agents_.find(agentId);
325     if (itr != agents_.end()) {
326         agents_.erase(itr);
327     }
328 }
329 
HandleStateDestroyAgent(SharingEvent & event)330 void Context::HandleStateDestroyAgent(SharingEvent &event)
331 {
332     SHARING_LOGD("trace.");
333     auto eventMsg = ConvertEventMsg<ContextEventMsg>(event);
334     if (eventMsg) {
335         auto agent = GetAgentById(eventMsg->agentId);
336         if (agent) {
337             AgentType agentType = agent->GetAgentType();
338             if (agentType == AgentType::SRC_AGENT) {
339                 auto srcAgent = std::static_pointer_cast<SrcAgent>(agent);
340                 uint32_t sinkAgentId = srcAgent->GetSinkAgentId();
341                 RemoveAgent(eventMsg->agentId);
342                 CheckNeedDestroySink(sinkAgentId);
343             } else if (agentType == AgentType::SINK_AGENT) {
344                 RemoveAgent(eventMsg->agentId);
345             }
346 
347             eventMsg->agentType = agentType;
348             SendInteractionEvent(EVENT_INTERACTION_STATE_AGENT_DESTROYED, eventMsg);
349         } else {
350             SHARING_LOGE("agent null agentId: %{public}d.", eventMsg->agentId);
351         }
352     }
353 }
354 
CheckNeedDestroySink(uint32_t sinkAgentId)355 void Context::CheckNeedDestroySink(uint32_t sinkAgentId)
356 {
357     SHARING_LOGD("trace.");
358     auto agent = GetAgentById(sinkAgentId);
359     RETURN_IF_NULL(agent);
360 
361     if (agent->GetDestroy() && IsEmptySrcAgent(sinkAgentId)) {
362         SHARING_LOGI("produer destroyed. src agent is all destroyed. destroy sink agent now. "
363             "contextId: %{public}u, sinkAgentId: %{public}u.", GetId(), sinkAgentId);
364 
365         SharingEvent event;
366         auto agentEvent = std::make_shared<AgentEventMsg>();
367         event.eventMsg = std::move(agentEvent);
368         event.eventMsg->fromMgr = ModuleType::MODULE_CONTEXT;
369         event.eventMsg->srcId = GetId();
370         event.eventMsg->toMgr = ModuleType::MODULE_CONTEXT;
371         event.eventMsg->dstId = GetId();
372         event.eventMsg->type = EVENT_AGENT_DESTROY;
373         agent->HandleEvent(event);
374     }
375 }
376 
377 } // namespace Sharing
378 } // namespace OHOS