1e0e9324cSopenharmony_ci/*
2e0e9324cSopenharmony_ci * Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development Co., Ltd.
3e0e9324cSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4e0e9324cSopenharmony_ci * you may not use this file except in compliance with the License.
5e0e9324cSopenharmony_ci * You may obtain a copy of the License at
6e0e9324cSopenharmony_ci *
7e0e9324cSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8e0e9324cSopenharmony_ci *
9e0e9324cSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10e0e9324cSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11e0e9324cSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12e0e9324cSopenharmony_ci * See the License for the specific language governing permissions and
13e0e9324cSopenharmony_ci * limitations under the License.
14e0e9324cSopenharmony_ci */
15e0e9324cSopenharmony_ci
16e0e9324cSopenharmony_ci#include "context_manager.h"
17e0e9324cSopenharmony_ci#include "common/common_macro.h"
18e0e9324cSopenharmony_ci#include "common/const_def.h"
19e0e9324cSopenharmony_ci#include "common/event_comm.h"
20e0e9324cSopenharmony_ci#include "common/sharing_log.h"
21e0e9324cSopenharmony_ci#include "configuration/include/config.h"
22e0e9324cSopenharmony_ci#include "magic_enum.hpp"
23e0e9324cSopenharmony_ci#include "network/network_session_manager.h"
24e0e9324cSopenharmony_ci
25e0e9324cSopenharmony_cinamespace OHOS {
26e0e9324cSopenharmony_cinamespace Sharing {
27e0e9324cSopenharmony_ci
28e0e9324cSopenharmony_ciContextManager::~ContextManager()
29e0e9324cSopenharmony_ci{
30e0e9324cSopenharmony_ci    SHARING_LOGD("id: %{public}s.", std::string(magic_enum::enum_name(ModuleType::MODULE_CONTEXT)).c_str());
31e0e9324cSopenharmony_ci    std::lock_guard<std::mutex> lock(mutex_);
32e0e9324cSopenharmony_ci    contexts_.clear();
33e0e9324cSopenharmony_ci}
34e0e9324cSopenharmony_ci
35e0e9324cSopenharmony_civoid ContextManager::Init()
36e0e9324cSopenharmony_ci{
37e0e9324cSopenharmony_ci    SHARING_LOGD("trace.");
38e0e9324cSopenharmony_ci    SharingValue::Ptr values = nullptr;
39e0e9324cSopenharmony_ci    auto ret = Config::GetInstance().GetConfig("context", "agentLimit", "maxSinkAgent", values);
40e0e9324cSopenharmony_ci    if (ret == CONFIGURE_ERROR_NONE) {
41e0e9324cSopenharmony_ci        int32_t value;
42e0e9324cSopenharmony_ci        values->GetValue<int32_t>(value);
43e0e9324cSopenharmony_ci        maxSinkAgent_ = static_cast<uint32_t>(value);
44e0e9324cSopenharmony_ci    } else {
45e0e9324cSopenharmony_ci        maxSinkAgent_ = MAX_SINK_AGENT_NUM;
46e0e9324cSopenharmony_ci    }
47e0e9324cSopenharmony_ci
48e0e9324cSopenharmony_ci    ret = Config::GetInstance().GetConfig("context", "agentLimit", "maxSrcAgent", values);
49e0e9324cSopenharmony_ci    if (ret == CONFIGURE_ERROR_NONE) {
50e0e9324cSopenharmony_ci        int32_t value;
51e0e9324cSopenharmony_ci        values->GetValue<int32_t>(value);
52e0e9324cSopenharmony_ci        maxSrcAgent_ = static_cast<uint32_t>(value);
53e0e9324cSopenharmony_ci    } else {
54e0e9324cSopenharmony_ci        maxSrcAgent_ = MAX_SRC_AGENT_NUM;
55e0e9324cSopenharmony_ci    }
56e0e9324cSopenharmony_ci
57e0e9324cSopenharmony_ci    ret = Config::GetInstance().GetConfig("context", "agentLimit", "maxContext", values);
58e0e9324cSopenharmony_ci    if (ret == CONFIGURE_ERROR_NONE) {
59e0e9324cSopenharmony_ci        int32_t value;
60e0e9324cSopenharmony_ci        values->GetValue<int32_t>(value);
61e0e9324cSopenharmony_ci        maxContext_ = static_cast<uint32_t>(value);
62e0e9324cSopenharmony_ci    } else {
63e0e9324cSopenharmony_ci        maxContext_ = MAX_CONTEXT_NUM;
64e0e9324cSopenharmony_ci    }
65e0e9324cSopenharmony_ci
66e0e9324cSopenharmony_ci    int32_t logOn;
67e0e9324cSopenharmony_ci    ret = Config::GetInstance().GetConfig("network", "networkLimit", "logOn", values);
68e0e9324cSopenharmony_ci    if (ret == CONFIGURE_ERROR_NONE) {
69e0e9324cSopenharmony_ci        values->GetValue<int32_t>(logOn);
70e0e9324cSopenharmony_ci    } else {
71e0e9324cSopenharmony_ci        logOn = 0;
72e0e9324cSopenharmony_ci    }
73e0e9324cSopenharmony_ci
74e0e9324cSopenharmony_ci    NetworkSessionManager::GetInstance().SetLogFlag(static_cast<int8_t>(logOn));
75e0e9324cSopenharmony_ci}
76e0e9324cSopenharmony_ci
77e0e9324cSopenharmony_ciint32_t ContextManager::HandleEvent(SharingEvent &event)
78e0e9324cSopenharmony_ci{
79e0e9324cSopenharmony_ci    SHARING_LOGD("trace.");
80e0e9324cSopenharmony_ci    RETURN_INVALID_IF_NULL(event.eventMsg);
81e0e9324cSopenharmony_ci    SHARING_LOGI("fromMgr: %{public}u, srcId: %{public}u, toMgr: %{public}u, dstId: %{public}u, event: %{public}s.",
82e0e9324cSopenharmony_ci                 event.eventMsg->fromMgr, event.eventMsg->srcId, event.eventMsg->toMgr, event.eventMsg->dstId,
83e0e9324cSopenharmony_ci                 std::string(magic_enum::enum_name(event.eventMsg->type)).c_str());
84e0e9324cSopenharmony_ci    switch (event.eventMsg->type) {
85e0e9324cSopenharmony_ci        case EventType::EVENT_CONFIGURE_CONTEXT:
86e0e9324cSopenharmony_ci            HandleConfiguration(event);
87e0e9324cSopenharmony_ci            break;
88e0e9324cSopenharmony_ci        case EventType::EVENT_CONTEXTMGR_CREATE:
89e0e9324cSopenharmony_ci            event.eventMsg->dstId = HandleContextCreate();
90e0e9324cSopenharmony_ci            break;
91e0e9324cSopenharmony_ci        case EventType::EVENT_CONTEXTMGR_AGENT_CREATE:
92e0e9324cSopenharmony_ci            HandleAgentCreate(event);
93e0e9324cSopenharmony_ci            break;
94e0e9324cSopenharmony_ci        case EventType::EVENT_CONTEXTMGR_STATE_CHANNEL_DESTROY:
95e0e9324cSopenharmony_ci            HandleMediachannelDestroy(event);
96e0e9324cSopenharmony_ci            break;
97e0e9324cSopenharmony_ci        default:
98e0e9324cSopenharmony_ci            HandleContextEvent(event);
99e0e9324cSopenharmony_ci            break;
100e0e9324cSopenharmony_ci    }
101e0e9324cSopenharmony_ci
102e0e9324cSopenharmony_ci    return 0;
103e0e9324cSopenharmony_ci}
104e0e9324cSopenharmony_ci
105e0e9324cSopenharmony_civoid ContextManager::HandleConfiguration(SharingEvent &event)
106e0e9324cSopenharmony_ci{
107e0e9324cSopenharmony_ci    SHARING_LOGD("trace.");
108e0e9324cSopenharmony_ci    auto eventMsg = ConvertEventMsg<ConfigEventMsg>(event);
109e0e9324cSopenharmony_ci    if (eventMsg && eventMsg->data) {
110e0e9324cSopenharmony_ci        auto data = eventMsg->data;
111e0e9324cSopenharmony_ci        if (data->HasTag("agentLimit")) {
112e0e9324cSopenharmony_ci            auto valueTest = data->GetSharingValue("agentLimit", "testdescription");
113e0e9324cSopenharmony_ci            if (valueTest != nullptr && valueTest->IsString()) {
114e0e9324cSopenharmony_ci                std::string valueData;
115e0e9324cSopenharmony_ci                valueTest->GetValue<std::string>(valueData);
116e0e9324cSopenharmony_ci                SHARING_LOGD("sinkLimit: %{public}s.", valueData.c_str());
117e0e9324cSopenharmony_ci            }
118e0e9324cSopenharmony_ci        } else if (data->HasTag("networkLimit")) {
119e0e9324cSopenharmony_ci            auto logFlag = data->GetSharingValue("networkLimit", "logOn");
120e0e9324cSopenharmony_ci            if (logFlag != nullptr && logFlag->IsInt32()) {
121e0e9324cSopenharmony_ci                int32_t valueData = -1;
122e0e9324cSopenharmony_ci                if (logFlag->GetValue<int32_t>(valueData)) {
123e0e9324cSopenharmony_ci                    SHARING_LOGD("logFlag: %{public}d.", valueData);
124e0e9324cSopenharmony_ci                    NetworkSessionManager::GetInstance().SetLogFlag(valueData);
125e0e9324cSopenharmony_ci                }
126e0e9324cSopenharmony_ci            }
127e0e9324cSopenharmony_ci        }
128e0e9324cSopenharmony_ci    } else {
129e0e9324cSopenharmony_ci        SHARING_LOGE("msg null.");
130e0e9324cSopenharmony_ci    }
131e0e9324cSopenharmony_ci}
132e0e9324cSopenharmony_ci
133e0e9324cSopenharmony_civoid ContextManager::HandleAgentCreate(SharingEvent &event)
134e0e9324cSopenharmony_ci{
135e0e9324cSopenharmony_ci    SHARING_LOGD("trace.");
136e0e9324cSopenharmony_ci    RETURN_IF_NULL(event.eventMsg);
137e0e9324cSopenharmony_ci
138e0e9324cSopenharmony_ci    auto contextEventMsg = ConvertEventMsg<ContextEventMsg>(event);
139e0e9324cSopenharmony_ci    RETURN_IF_NULL(contextEventMsg);
140e0e9324cSopenharmony_ci    if (!CheckAgentSize((AgentType)contextEventMsg->agentType)) {
141e0e9324cSopenharmony_ci        return;
142e0e9324cSopenharmony_ci    }
143e0e9324cSopenharmony_ci
144e0e9324cSopenharmony_ci    if (event.eventMsg->dstId == INVALID_ID || GetContextById(event.eventMsg->dstId) == nullptr) {
145e0e9324cSopenharmony_ci        event.eventMsg->dstId = HandleContextCreate();
146e0e9324cSopenharmony_ci    }
147e0e9324cSopenharmony_ci
148e0e9324cSopenharmony_ci    if (event.eventMsg->dstId == INVALID_ID) {
149e0e9324cSopenharmony_ci        SHARING_LOGE("create context error! invalid id.");
150e0e9324cSopenharmony_ci        return;
151e0e9324cSopenharmony_ci    }
152e0e9324cSopenharmony_ci
153e0e9324cSopenharmony_ci    event.eventMsg->type = EVENT_CONTEXT_AGENT_CREATE;
154e0e9324cSopenharmony_ci    HandleContextEvent(event);
155e0e9324cSopenharmony_ci}
156e0e9324cSopenharmony_ci
157e0e9324cSopenharmony_cibool ContextManager::CheckAgentSize(AgentType agentType)
158e0e9324cSopenharmony_ci{
159e0e9324cSopenharmony_ci    SHARING_LOGD("trace.");
160e0e9324cSopenharmony_ci    std::lock_guard<std::mutex> lock(mutex_);
161e0e9324cSopenharmony_ci    if (agentType == SINK_AGENT) {
162e0e9324cSopenharmony_ci        int32_t sinkCount = 0;
163e0e9324cSopenharmony_ci        for (auto &item : contexts_) {
164e0e9324cSopenharmony_ci            sinkCount += (item.second->GetSinkAgentSize());
165e0e9324cSopenharmony_ci        }
166e0e9324cSopenharmony_ci        SHARING_LOGI("now sink agent num: %{public}d.", sinkCount);
167e0e9324cSopenharmony_ci        if (sinkCount >= GetAgentSinkLimit()) {
168e0e9324cSopenharmony_ci            SHARING_LOGE("check agent size error! limit sink agent size.");
169e0e9324cSopenharmony_ci            return false;
170e0e9324cSopenharmony_ci        }
171e0e9324cSopenharmony_ci    } else {
172e0e9324cSopenharmony_ci        int32_t srcCount = 0;
173e0e9324cSopenharmony_ci        for (auto &item : contexts_) {
174e0e9324cSopenharmony_ci            srcCount += (item.second->GetSrcAgentSize());
175e0e9324cSopenharmony_ci        }
176e0e9324cSopenharmony_ci        SHARING_LOGI("now src agent num: %{public}d.", srcCount);
177e0e9324cSopenharmony_ci        if (srcCount >= GetAgentSrcLimit()) {
178e0e9324cSopenharmony_ci            SHARING_LOGE("check agent size error! limit src agent size.");
179e0e9324cSopenharmony_ci            return false;
180e0e9324cSopenharmony_ci        }
181e0e9324cSopenharmony_ci    }
182e0e9324cSopenharmony_ci
183e0e9324cSopenharmony_ci    return true;
184e0e9324cSopenharmony_ci}
185e0e9324cSopenharmony_ci
186e0e9324cSopenharmony_ciuint32_t ContextManager::HandleContextCreate()
187e0e9324cSopenharmony_ci{
188e0e9324cSopenharmony_ci    SHARING_LOGD("trace.");
189e0e9324cSopenharmony_ci    std::lock_guard<std::mutex> lock(mutex_);
190e0e9324cSopenharmony_ci    if (contexts_.size() >= maxContext_) {
191e0e9324cSopenharmony_ci        SHARING_LOGE("create context error! limit context size.");
192e0e9324cSopenharmony_ci        return INVALID_ID;
193e0e9324cSopenharmony_ci    }
194e0e9324cSopenharmony_ci
195e0e9324cSopenharmony_ci    auto context = std::make_shared<Context>();
196e0e9324cSopenharmony_ci    contexts_.emplace(context->GetId(), context);
197e0e9324cSopenharmony_ci    SHARING_LOGI("contextId: %{public}d contextSize: %{public}zu.", context->GetId(), contexts_.size());
198e0e9324cSopenharmony_ci    return context->GetId();
199e0e9324cSopenharmony_ci}
200e0e9324cSopenharmony_ci
201e0e9324cSopenharmony_civoid ContextManager::HandleMediachannelDestroy(SharingEvent &event)
202e0e9324cSopenharmony_ci{
203e0e9324cSopenharmony_ci    SHARING_LOGD("trace.");
204e0e9324cSopenharmony_ci    RETURN_IF_NULL(event.eventMsg);
205e0e9324cSopenharmony_ci    auto context = GetContextById(event.eventMsg->dstId);
206e0e9324cSopenharmony_ci    if (context) {
207e0e9324cSopenharmony_ci        event.eventMsg->type = EVENT_CONTEXT_STATE_AGENT_DESTROY;
208e0e9324cSopenharmony_ci        context->HandleEvent(event);
209e0e9324cSopenharmony_ci        if (context->IsEmptyAgent()) {
210e0e9324cSopenharmony_ci            DestroyContext(event.eventMsg->dstId);
211e0e9324cSopenharmony_ci        } else {
212e0e9324cSopenharmony_ci            SHARING_LOGD("need wait other agent destroy contextId: %{public}u.", context->GetId());
213e0e9324cSopenharmony_ci        }
214e0e9324cSopenharmony_ci    } else {
215e0e9324cSopenharmony_ci        SHARING_LOGW("exception to enter! dstId: %{public}u.", event.eventMsg->dstId);
216e0e9324cSopenharmony_ci    }
217e0e9324cSopenharmony_ci}
218e0e9324cSopenharmony_ci
219e0e9324cSopenharmony_civoid ContextManager::HandleContextEvent(SharingEvent &event)
220e0e9324cSopenharmony_ci{
221e0e9324cSopenharmony_ci    SHARING_LOGD("trace.");
222e0e9324cSopenharmony_ci    RETURN_IF_NULL(event.eventMsg);
223e0e9324cSopenharmony_ci    auto context = GetContextById(event.eventMsg->dstId);
224e0e9324cSopenharmony_ci    if (context) {
225e0e9324cSopenharmony_ci        context->HandleEvent(event);
226e0e9324cSopenharmony_ci    } else {
227e0e9324cSopenharmony_ci        SHARING_LOGE("context not exist, contextId: %{public}u eventType: %{public}s.", event.eventMsg->dstId,
228e0e9324cSopenharmony_ci                     std::string(magic_enum::enum_name(event.eventMsg->type)).c_str());
229e0e9324cSopenharmony_ci    }
230e0e9324cSopenharmony_ci}
231e0e9324cSopenharmony_ci
232e0e9324cSopenharmony_ciContext::Ptr ContextManager::GetContextById(uint32_t contextId)
233e0e9324cSopenharmony_ci{
234e0e9324cSopenharmony_ci    SHARING_LOGD("trace.");
235e0e9324cSopenharmony_ci    std::lock_guard<std::mutex> lock(mutex_);
236e0e9324cSopenharmony_ci    auto itr = contexts_.find(contextId);
237e0e9324cSopenharmony_ci    if (itr != contexts_.end()) {
238e0e9324cSopenharmony_ci        return itr->second;
239e0e9324cSopenharmony_ci    }
240e0e9324cSopenharmony_ci
241e0e9324cSopenharmony_ci    return nullptr;
242e0e9324cSopenharmony_ci}
243e0e9324cSopenharmony_ci
244e0e9324cSopenharmony_civoid ContextManager::DestroyContext(uint32_t contextId)
245e0e9324cSopenharmony_ci{
246e0e9324cSopenharmony_ci    SHARING_LOGD("trace.");
247e0e9324cSopenharmony_ci    bool paFlag = false;
248e0e9324cSopenharmony_ci    {
249e0e9324cSopenharmony_ci        std::lock_guard<std::mutex> lock(mutex_);
250e0e9324cSopenharmony_ci        auto itr = contexts_.find(contextId);
251e0e9324cSopenharmony_ci        if (itr != contexts_.end()) {
252e0e9324cSopenharmony_ci            if (itr->second != nullptr) {
253e0e9324cSopenharmony_ci                itr->second->Release();
254e0e9324cSopenharmony_ci            }
255e0e9324cSopenharmony_ci            contexts_.erase(itr);
256e0e9324cSopenharmony_ci        }
257e0e9324cSopenharmony_ci        if (0 == contexts_.size()) {
258e0e9324cSopenharmony_ci            paFlag = true;
259e0e9324cSopenharmony_ci        }
260e0e9324cSopenharmony_ci    }
261e0e9324cSopenharmony_ci
262e0e9324cSopenharmony_ci    if (paFlag) {
263e0e9324cSopenharmony_ci        system("pactl set-default-source Built_in_mic");
264e0e9324cSopenharmony_ci        system("pactl set-default-sink Speaker");
265e0e9324cSopenharmony_ci    }
266e0e9324cSopenharmony_ci
267e0e9324cSopenharmony_ci    SHARING_LOGI("contextId: %{public}d contextSize: %{public}zu.", contextId, contexts_.size());
268e0e9324cSopenharmony_ci}
269e0e9324cSopenharmony_ci
270e0e9324cSopenharmony_ci} // namespace Sharing
271e0e9324cSopenharmony_ci} // namespace OHOS