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