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 }
133 }
134 }
135
IsEmptySrcAgent(uint32_t sinkAgentId)136 bool Context::IsEmptySrcAgent(uint32_t sinkAgentId)
137 {
138 SHARING_LOGD("trace.");
139 std::lock_guard<std::mutex> lock(mutex_);
140 for (auto &item : agents_) {
141 if (item.second->GetAgentType() == SRC_AGENT) {
142 auto srcAgent = std::static_pointer_cast<SrcAgent>(item.second);
143 if (srcAgent && srcAgent->GetSinkAgentId() == sinkAgentId) {
144 return false;
145 }
146 }
147 }
148
149 return true;
150 }
151
GetSinkAgentSize()152 int32_t Context::GetSinkAgentSize()
153 {
154 SHARING_LOGD("trace.");
155 std::lock_guard<std::mutex> lock(mutex_);
156 int32_t agentSize = 0;
157 for (auto &item : agents_) {
158 if (item.second->GetAgentType() == SINK_AGENT) {
159 SHARING_LOGD("agent id still has %{public}d.", item.second->GetId());
160 ++agentSize;
161 }
162 }
163
164 return agentSize;
165 }
166
GetSrcAgentSize()167 int32_t Context::GetSrcAgentSize()
168 {
169 SHARING_LOGD("trace.");
170 std::lock_guard<std::mutex> lock(mutex_);
171 int32_t agentSize = 0;
172 for (auto &item : agents_) {
173 if (item.second->GetAgentType() == SRC_AGENT) {
174 ++agentSize;
175 }
176 }
177
178 return agentSize;
179 }
180
SendInteractionEvent(EventType eventType, ContextEventMsg::Ptr &eventMsg)181 void Context::SendInteractionEvent(EventType eventType, ContextEventMsg::Ptr &eventMsg)
182 {
183 SHARING_LOGD("trace.");
184 auto interactionMsg = std::make_shared<InteractionEventMsg>();
185 interactionMsg->fromMgr = ModuleType::MODULE_CONTEXT;
186 interactionMsg->srcId = GetId();
187 interactionMsg->toMgr = ModuleType::MODULE_INTERACTION;
188 interactionMsg->dstId = interactionId_;
189
190 interactionMsg->type = eventType;
191 interactionMsg->errorCode = eventMsg->errorCode;
192 interactionMsg->agentId = eventMsg->agentId;
193 interactionMsg->agentType = eventMsg->agentType;
194 interactionMsg->contextId = GetId();
195 interactionMsg->surfaceId = eventMsg->surfaceId;
196
197 SharingEvent event;
198 event.eventMsg = std::move(interactionMsg);
199 SendEvent(event);
200 SHARING_LOGI("event: %{public}u is sended by contextId: %{public}u.", event.eventMsg->type, GetId());
201 }
202
IsEmptyAgent()203 bool Context::IsEmptyAgent()
204 {
205 SHARING_LOGD("trace.");
206 std::lock_guard<std::mutex> lock(mutex_);
207 return agents_.size() == 0;
208 }
209
OnAgentNotify(AgentStatusMsg::Ptr &statusMsg)210 void Context::OnAgentNotify(AgentStatusMsg::Ptr &statusMsg)
211 {
212 SHARING_LOGD("trace.");
213 RETURN_IF_NULL(statusMsg);
214 RETURN_IF_NULL(statusMsg->msg);
215 SHARING_LOGI("contextId: %{public}u, agentId: %{public}u, toMgr: %{public}u, dstId: %{public}u, event: %{public}s.",
216 GetId(), statusMsg->agentId, statusMsg->msg->toMgr, statusMsg->msg->dstId,
217 std::string(magic_enum::enum_name(statusMsg->msg->type)).c_str());
218
219 if (statusMsg->msg) {
220 if (statusMsg->msg->toMgr == ModuleType::MODULE_INTERACTION) {
221 statusMsg->msg->dstId = interactionId_;
222 auto interactionMsg = std::static_pointer_cast<InteractionEventMsg>(statusMsg->msg);
223 RETURN_IF_NULL(interactionMsg);
224 interactionMsg->contextId = GetId();
225 } else if (statusMsg->msg->toMgr == ModuleType::MODULE_CONTEXT) {
226 statusMsg->msg->dstId = GetId();
227 }
228
229 SharingEvent event;
230 event.eventMsg = std::move(statusMsg->msg);
231 event.eventMsg->fromMgr = ModuleType::MODULE_CONTEXT;
232 event.eventMsg->srcId = GetId();
233
234 SendEvent(event);
235 SHARING_LOGI("event: %{public}s is sended by contextId: %{public}u.",
236 std::string(magic_enum::enum_name(event.eventMsg->type)).c_str(), GetId());
237 }
238 }
239
HandleCreateAgent(const std::string &className, AgentType agentType, uint32_t sinkAgentId)240 uint32_t Context::HandleCreateAgent(const std::string &className, AgentType agentType, uint32_t sinkAgentId)
241 {
242 SHARING_LOGI("contextId: %{public}u, agentType: %{public}s, sinkAgentId: %{public}u.", GetId(),
243 std::string(magic_enum::enum_name(agentType)).c_str(), sinkAgentId);
244
245 std::shared_ptr<Agent> agent = nullptr;
246 if (agentType == AgentType::SINK_AGENT) {
247 auto sinkAgent = std::make_shared<SinkAgent>();
248 if (sinkAgent->CreateSession(className) == SharingErrorCode::ERR_SESSION_CREATE) {
249 SHARING_LOGE("create agent session error.");
250 return INVALID_ID;
251 } else {
252 auto channelMsg = std::make_shared<ChannelEventMsg>();
253 channelMsg->agentId = sinkAgent->GetId();
254 channelMsg->toMgr = ModuleType::MODULE_MEDIACHANNEL;
255 channelMsg->type = EVENT_MEDIA_CHANNEL_CREATE;
256
257 SharingEvent event;
258 event.eventMsg = channelMsg;
259 event.eventMsg->fromMgr = ModuleType::MODULE_CONTEXT;
260 event.eventMsg->toMgr = ModuleType::MODULE_MEDIACHANNEL;
261 event.eventMsg->srcId = GetId();
262 SendSyncEvent(event);
263
264 SHARING_LOGI("create agent create media channel agentId: %{public}u channelId: %{public}u.",
265 sinkAgent->GetId(), channelMsg->srcId);
266 sinkAgent->UpdateMediaChannelId(channelMsg->srcId);
267
268 agent = sinkAgent;
269 }
270 } else {
271 std::lock_guard<std::mutex> lock(mutex_);
272 Agent::Ptr sinkAgent = nullptr;
273 if (agents_.find(sinkAgentId) != agents_.end()) {
274 sinkAgent = agents_.find(sinkAgentId)->second;
275 }
276 if (sinkAgent != nullptr && !sinkAgent->GetDestroy()) {
277 auto srcAgent = std::make_shared<SrcAgent>();
278 if (srcAgent->CreateSession(className) == SharingErrorCode::ERR_SESSION_CREATE) {
279 SHARING_LOGE("create agent session error.");
280 return INVALID_ID;
281 } else {
282 SHARING_LOGI("channelId: %{public}u is set to src agentId: %{public}u.", sinkAgent->GetMediaChannelId(),
283 srcAgent->GetId());
284 srcAgent->UpdateMediaChannelId(sinkAgent->GetMediaChannelId());
285 srcAgent->SetSinkAgentId(sinkAgentId);
286 }
287 agent = srcAgent;
288 } else {
289 SHARING_LOGE("sinkAgentId invalid.");
290 return INVALID_ID;
291 }
292 }
293
294 agent->SetAgentListener(shared_from_this());
295
296 std::lock_guard<std::mutex> lock(mutex_);
297 agents_.emplace(agent->GetId(), agent);
298 SHARING_LOGI("contextId: %{public}u, create agent className: %{public}s "
299 "agentType: %{public}s agentId: %{public}u size: %{public}zu.",
300 GetId(), className.c_str(), std::string(magic_enum::enum_name(agentType)).c_str(), agent->GetId(),
301 agents_.size());
302 return agent->GetId();
303 }
304
GetAgentById(uint32_t agentId)305 Agent::Ptr Context::GetAgentById(uint32_t agentId)
306 {
307 SHARING_LOGD("trace.");
308 std::lock_guard<std::mutex> lock(mutex_);
309 auto itr = agents_.find(agentId);
310 if (itr != agents_.end()) {
311 return itr->second;
312 }
313
314 return nullptr;
315 }
316
RemoveAgent(uint32_t agentId)317 void Context::RemoveAgent(uint32_t agentId)
318 {
319 SHARING_LOGD("contextId: %{public}u, remove agentId: %{public}u.", GetId(), agentId);
320 std::lock_guard<std::mutex> lock(mutex_);
321 auto itr = agents_.find(agentId);
322 if (itr != agents_.end()) {
323 agents_.erase(itr);
324 }
325 }
326
HandleStateDestroyAgent(SharingEvent &event)327 void Context::HandleStateDestroyAgent(SharingEvent &event)
328 {
329 SHARING_LOGD("trace.");
330 auto eventMsg = ConvertEventMsg<ContextEventMsg>(event);
331 if (eventMsg) {
332 auto agent = GetAgentById(eventMsg->agentId);
333 if (agent) {
334 AgentType agentType = agent->GetAgentType();
335 if (agentType == AgentType::SRC_AGENT) {
336 auto srcAgent = std::static_pointer_cast<SrcAgent>(agent);
337 uint32_t sinkAgentId = srcAgent->GetSinkAgentId();
338 RemoveAgent(eventMsg->agentId);
339 CheckNeedDestroySink(sinkAgentId);
340 } else if (agentType == AgentType::SINK_AGENT) {
341 RemoveAgent(eventMsg->agentId);
342 }
343
344 eventMsg->agentType = agentType;
345 SendInteractionEvent(EVENT_INTERACTION_STATE_AGENT_DESTROYED, eventMsg);
346 } else {
347 SHARING_LOGE("agent null agentId: %{public}d.", eventMsg->agentId);
348 }
349 }
350 }
351
CheckNeedDestroySink(uint32_t sinkAgentId)352 void Context::CheckNeedDestroySink(uint32_t sinkAgentId)
353 {
354 SHARING_LOGD("trace.");
355 auto agent = GetAgentById(sinkAgentId);
356 RETURN_IF_NULL(agent);
357
358 if (agent->GetDestroy() && IsEmptySrcAgent(sinkAgentId)) {
359 SHARING_LOGI("produer destroyed. src agent is all destroyed. destroy sink agent now. "
360 "contextId: %{public}u, sinkAgentId: %{public}u.", GetId(), sinkAgentId);
361
362 SharingEvent event;
363 auto agentEvent = std::make_shared<AgentEventMsg>();
364 event.eventMsg = std::move(agentEvent);
365 event.eventMsg->fromMgr = ModuleType::MODULE_CONTEXT;
366 event.eventMsg->srcId = GetId();
367 event.eventMsg->toMgr = ModuleType::MODULE_CONTEXT;
368 event.eventMsg->dstId = GetId();
369 event.eventMsg->type = EVENT_AGENT_DESTROY;
370 agent->HandleEvent(event);
371 }
372 }
373
374 } // namespace Sharing
375 } // namespace OHOS