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 24namespace OHOS { 25namespace Sharing { 26Context::Context() 27{ 28 SHARING_LOGD("contextId: %{public}u.", GetId()); 29} 30 31Context::~Context() 32{ 33 SHARING_LOGD("contextId: %{public}u.", GetId()); 34} 35 36void 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 47int32_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 84void 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 124void 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 136bool 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 152int32_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 167int32_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 181void 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 203bool Context::IsEmptyAgent() 204{ 205 SHARING_LOGD("trace."); 206 std::lock_guard<std::mutex> lock(mutex_); 207 return agents_.size() == 0; 208} 209 210void 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 240uint32_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 305Agent::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 317void 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 327void 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 352void 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