1 /*
2 * Copyright (c) 2023-2024 Huawei Device 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 "av_trans_control_center.h"
17
18 #include "anonymous_string.h"
19 #include "av_trans_log.h"
20
21 namespace OHOS {
22 namespace DistributedHardware {
23 #undef DH_LOG_TAG
24 #define DH_LOG_TAG "AVTransControlCenter"
25
26 IMPLEMENT_SINGLE_INSTANCE(AVTransControlCenter);
27
AVTransControlCenter()28 AVTransControlCenter::AVTransControlCenter()
29 {
30 AVTRANS_LOGI("AVTransControlCenter ctor.");
31 transRole_ = TransRole::UNKNOWN;
32 rootEngineId_.store(BASE_ENGINE_ID);
33 syncManager_ = std::make_shared<AVSyncManager>();
34 }
35
~AVTransControlCenter()36 AVTransControlCenter::~AVTransControlCenter()
37 {
38 AVTRANS_LOGI("AVTransControlCenter dtor.");
39 SoftbusChannelAdapter::GetInstance().RemoveChannelServer(PKG_NAME_DH_FWK, AV_SYNC_SENDER_CONTROL_SESSION_NAME);
40 SoftbusChannelAdapter::GetInstance().RemoveChannelServer(PKG_NAME_DH_FWK, AV_SYNC_RECEIVER_CONTROL_SESSION_NAME);
41
42 sessionName_ = "";
43 initialized_ = false;
44 syncManager_ = nullptr;
45 transRole_ = TransRole::UNKNOWN;
46 rootEngineId_.store(BASE_ENGINE_ID);
47 }
48
InitializeAVCenter(const TransRole & transRole,int32_t & engineId)49 int32_t AVTransControlCenter::InitializeAVCenter(const TransRole &transRole, int32_t &engineId)
50 {
51 engineId = INVALID_ENGINE_ID;
52 if ((transRole != TransRole::AV_SENDER) && (transRole != TransRole::AV_RECEIVER)) {
53 AVTRANS_LOGE("Invalid trans role=%{public}d", transRole);
54 return ERR_DH_AVT_INVALID_PARAM_VALUE;
55 }
56
57 if (initialized_.load()) {
58 AVTRANS_LOGI("AV control center already initialized.");
59 engineId = rootEngineId_.load();
60 rootEngineId_++;
61 return DH_AVT_SUCCESS;
62 }
63
64 int32_t ret = SoftbusChannelAdapter::GetInstance().CreateChannelServer(PKG_NAME_DH_FWK,
65 AV_SYNC_RECEIVER_CONTROL_SESSION_NAME);
66 TRUE_RETURN_V_MSG_E((ret != DH_AVT_SUCCESS), ret, "Create contro center session server failed, ret=%{public}d",
67 ret);
68
69 ret = SoftbusChannelAdapter::GetInstance().RegisterChannelListener(AV_SYNC_RECEIVER_CONTROL_SESSION_NAME,
70 AV_TRANS_SPECIAL_DEVICE_ID, this);
71 TRUE_RETURN_V_MSG_E((ret != DH_AVT_SUCCESS), ret, "Register control center channel callback failed, ret=%{public}d",
72 ret);
73
74 initialized_ = true;
75 transRole_ = transRole;
76 engineId = rootEngineId_.load();
77 rootEngineId_++;
78
79 return DH_AVT_SUCCESS;
80 }
81
ReleaseAVCenter(int32_t engineId)82 int32_t AVTransControlCenter::ReleaseAVCenter(int32_t engineId)
83 {
84 AVTRANS_LOGI("Release av control center channel for engineId=%{public}d.", engineId);
85 TRUE_RETURN_V_MSG_E(IsInvalidEngineId(engineId), ERR_DH_AVT_INVALID_PARAM_VALUE,
86 "Invalid input engine id = %{public}d", engineId);
87
88 {
89 std::lock_guard<std::mutex> lock(callbackMutex_);
90 callbackMap_.erase(engineId);
91 }
92
93 std::string peerDevId;
94 {
95 std::lock_guard<std::mutex> lock(engineIdMutex_);
96 if (engine2DevIdMap_.find(engineId) == engine2DevIdMap_.end()) {
97 AVTRANS_LOGE("Input engine id is not exist, engineId = %{public}d", engineId);
98 return DH_AVT_SUCCESS;
99 }
100 peerDevId = engine2DevIdMap_[engineId];
101 engine2DevIdMap_.erase(engineId);
102
103 bool IsDevIdUsedByOthers = false;
104 for (auto it = engine2DevIdMap_.begin(); it != engine2DevIdMap_.end(); it++) {
105 if (it->second == peerDevId) {
106 IsDevIdUsedByOthers = true;
107 break;
108 }
109 }
110 if (IsDevIdUsedByOthers) {
111 AVTRANS_LOGI("Control channel is still being used by other engine, peerDevId=%{public}s.",
112 GetAnonyString(peerDevId).c_str());
113 return DH_AVT_SUCCESS;
114 }
115 }
116
117 {
118 std::lock_guard<std::mutex> lock(devIdMutex_);
119 auto iter = std::find(connectedDevIds_.begin(), connectedDevIds_.end(), peerDevId);
120 if (iter == connectedDevIds_.end()) {
121 AVTRANS_LOGE("Control channel has not been opened successfully for peerDevId=%{public}s.",
122 GetAnonyString(peerDevId).c_str());
123 return DH_AVT_SUCCESS;
124 } else {
125 connectedDevIds_.erase(iter);
126 }
127 }
128
129 SoftbusChannelAdapter::GetInstance().StopDeviceTimeSync(PKG_NAME_DH_FWK, sessionName_, peerDevId);
130 SoftbusChannelAdapter::GetInstance().CloseSoftbusChannel(sessionName_, peerDevId);
131 SoftbusChannelAdapter::GetInstance().UnRegisterChannelListener(AV_SYNC_SENDER_CONTROL_SESSION_NAME,
132 AV_TRANS_SPECIAL_DEVICE_ID);
133 SoftbusChannelAdapter::GetInstance().UnRegisterChannelListener(AV_SYNC_RECEIVER_CONTROL_SESSION_NAME,
134 AV_TRANS_SPECIAL_DEVICE_ID);
135
136 return DH_AVT_SUCCESS;
137 }
138
CreateControlChannel(int32_t engineId,const std::string & peerDevId)139 int32_t AVTransControlCenter::CreateControlChannel(int32_t engineId, const std::string &peerDevId)
140 {
141 AVTRANS_LOGI("Create control center channel for engineId=%{public}d, peerDevId=%{public}s.", engineId,
142 GetAnonyString(peerDevId).c_str());
143
144 TRUE_RETURN_V_MSG_E(IsInvalidEngineId(engineId), ERR_DH_AVT_INVALID_PARAM_VALUE,
145 "Invalid input engine id = %{public}d", engineId);
146
147 TRUE_RETURN_V_MSG_E(!initialized_.load(), ERR_DH_AVT_CREATE_CHANNEL_FAILED,
148 "AV control center has not been initialized.");
149
150 {
151 std::lock_guard<std::mutex> devLock(devIdMutex_);
152 auto iter = std::find(connectedDevIds_.begin(), connectedDevIds_.end(), peerDevId);
153 if (iter != connectedDevIds_.end()) {
154 {
155 std::lock_guard<std::mutex> lock(engineIdMutex_);
156 engine2DevIdMap_.insert(std::make_pair(engineId, peerDevId));
157 }
158 AVTRANS_LOGE("AV control center channel has already created, peerDevId=%{public}s.",
159 GetAnonyString(peerDevId).c_str());
160 return ERR_DH_AVT_CHANNEL_ALREADY_CREATED;
161 }
162 }
163
164 int32_t ret = SoftbusChannelAdapter::GetInstance().RegisterChannelListener(AV_SYNC_SENDER_CONTROL_SESSION_NAME,
165 AV_TRANS_SPECIAL_DEVICE_ID, this);
166 TRUE_RETURN_V_MSG_E((ret != DH_AVT_SUCCESS), ret, "Register control center channel callback failed, ret=%{public}d",
167 ret);
168
169 ret = SoftbusChannelAdapter::GetInstance().OpenSoftbusChannel(AV_SYNC_SENDER_CONTROL_SESSION_NAME,
170 AV_SYNC_RECEIVER_CONTROL_SESSION_NAME, peerDevId);
171 TRUE_RETURN_V_MSG_E(((ret != DH_AVT_SUCCESS) && (ret != ERR_DH_AVT_SESSION_HAS_OPENED)), ret,
172 "Create av control center channel failed, ret=%{public}d", ret);
173
174 std::lock_guard<std::mutex> lk(engineIdMutex_);
175 engine2DevIdMap_.insert(std::make_pair(engineId, peerDevId));
176
177 return DH_AVT_SUCCESS;
178 }
179
NotifyAVCenter(int32_t engineId,const AVTransEvent & event)180 int32_t AVTransControlCenter::NotifyAVCenter(int32_t engineId, const AVTransEvent& event)
181 {
182 TRUE_RETURN_V_MSG_E(IsInvalidEngineId(engineId), ERR_DH_AVT_INVALID_PARAM_VALUE,
183 "Invalid input engine id = %{public}d", engineId);
184 if (syncManager_ == nullptr) {
185 AVTRANS_LOGE("syncManager is nullptr.");
186 return ERR_DH_AVT_INVALID_PARAM_VALUE;
187 }
188
189 switch (event.type) {
190 case EventType::EVENT_ADD_STREAM: {
191 syncManager_->AddStreamInfo(AVStreamInfo{ event.content, event.peerDevId });
192 break;
193 }
194 case EventType::EVENT_REMOVE_STREAM: {
195 syncManager_->RemoveStreamInfo(AVStreamInfo{ event.content, event.peerDevId });
196 break;
197 }
198 default:
199 AVTRANS_LOGE("Unsupported event type.");
200 }
201 return DH_AVT_SUCCESS;
202 }
203
RegisterCtlCenterCallback(int32_t engineId,const sptr<IAVTransControlCenterCallback> & callback)204 int32_t AVTransControlCenter::RegisterCtlCenterCallback(int32_t engineId,
205 const sptr<IAVTransControlCenterCallback> &callback)
206 {
207 TRUE_RETURN_V_MSG_E(IsInvalidEngineId(engineId), ERR_DH_AVT_INVALID_PARAM_VALUE,
208 "Invalid input engine id = %{public}d", engineId);
209
210 if (callback == nullptr) {
211 AVTRANS_LOGE("Input callback is nullptr.");
212 return ERR_DH_AVT_INVALID_PARAM_VALUE;
213 }
214
215 std::lock_guard<std::mutex> lock(callbackMutex_);
216 callbackMap_.insert(std::make_pair(engineId, callback));
217
218 return DH_AVT_SUCCESS;
219 }
220
SendMessage(const std::shared_ptr<AVTransMessage> & message)221 int32_t AVTransControlCenter::SendMessage(const std::shared_ptr<AVTransMessage> &message)
222 {
223 AVTRANS_LOGI("SendMessage enter.");
224 TRUE_RETURN_V_MSG_E(message == nullptr, ERR_DH_AVT_INVALID_PARAM, "Input message is nullptr.");
225
226 std::string msgData = message->MarshalMessage();
227 return SoftbusChannelAdapter::GetInstance().SendBytesData(sessionName_, message->dstDevId_, msgData);
228 }
229
SetParam2Engines(AVTransTag tag,const std::string & value)230 void AVTransControlCenter::SetParam2Engines(AVTransTag tag, const std::string &value)
231 {
232 std::lock_guard<std::mutex> lock(callbackMutex_);
233 for (auto iter = callbackMap_.begin(); iter != callbackMap_.end(); iter++) {
234 if (iter->second != nullptr) {
235 iter->second->SetParameter(tag, value);
236 }
237 }
238 }
239
SetParam2Engines(const AVTransSharedMemory & memory)240 void AVTransControlCenter::SetParam2Engines(const AVTransSharedMemory &memory)
241 {
242 std::lock_guard<std::mutex> lock(callbackMutex_);
243 for (auto iter = callbackMap_.begin(); iter != callbackMap_.end(); iter++) {
244 if (iter->second != nullptr) {
245 iter->second->SetSharedMemory(memory);
246 }
247 }
248 }
249
OnChannelEvent(const AVTransEvent & event)250 void AVTransControlCenter::OnChannelEvent(const AVTransEvent &event)
251 {
252 AVTRANS_LOGI("OnChannelEvent enter. event type:%{public}d", event.type);
253 switch (event.type) {
254 case EventType::EVENT_CHANNEL_OPENED:
255 case EventType::EVENT_CHANNEL_CLOSED:
256 case EventType::EVENT_CHANNEL_OPEN_FAIL: {
257 HandleChannelEvent(event);
258 break;
259 }
260 case EventType::EVENT_DATA_RECEIVED: {
261 HandleDataReceived(event.content, event.peerDevId);
262 break;
263 }
264 case EventType::EVENT_TIME_SYNC_RESULT: {
265 SetParam2Engines(AVTransTag::TIME_SYNC_RESULT, event.content);
266 break;
267 }
268 default:
269 AVTRANS_LOGE("Unsupported event type.");
270 }
271 }
272
HandleChannelEvent(const AVTransEvent & event)273 void AVTransControlCenter::HandleChannelEvent(const AVTransEvent &event)
274 {
275 if (event.type == EventType::EVENT_CHANNEL_CLOSED) {
276 AVTRANS_LOGI("Control channel has been closed.");
277 return;
278 }
279
280 if (event.type == EventType::EVENT_CHANNEL_OPEN_FAIL) {
281 AVTRANS_LOGE("Open control channel failed for peerDevId=%{public}s.", GetAnonyString(event.peerDevId).c_str());
282 return;
283 }
284
285 if (event.type == EventType::EVENT_CHANNEL_OPENED) {
286 sessionName_ = event.content;
287 if (sessionName_ == AV_SYNC_RECEIVER_CONTROL_SESSION_NAME) {
288 SoftbusChannelAdapter::GetInstance().StartDeviceTimeSync(PKG_NAME_DH_FWK, sessionName_, event.peerDevId);
289 }
290 std::lock_guard<std::mutex> lock(devIdMutex_);
291 connectedDevIds_.push_back(event.peerDevId);
292 }
293 }
294
HandleDataReceived(const std::string & content,const std::string & peerDevId)295 void AVTransControlCenter::HandleDataReceived(const std::string &content, const std::string &peerDevId)
296 {
297 auto avMessage = std::make_shared<AVTransMessage>();
298 if (!avMessage->UnmarshalMessage(content, peerDevId)) {
299 AVTRANS_LOGE("unmarshal event content to av message failed");
300 return;
301 }
302 AVTRANS_LOGI("Handle data received, av message type = %{public}d", avMessage->type_);
303 if (syncManager_ == nullptr) {
304 AVTRANS_LOGE("syncManager is nullptr.");
305 return;
306 }
307 if ((avMessage->type_ == (uint32_t)AVTransTag::START_AV_SYNC) ||
308 (avMessage->type_ == (uint32_t)AVTransTag::STOP_AV_SYNC)) {
309 syncManager_->HandleAvSyncMessage(avMessage);
310 }
311 }
312
OnStreamReceived(const StreamData * data,const StreamData * ext)313 void AVTransControlCenter::OnStreamReceived(const StreamData *data, const StreamData *ext)
314 {
315 (void)data;
316 (void)ext;
317 }
318
IsInvalidEngineId(int32_t engineId)319 bool AVTransControlCenter::IsInvalidEngineId(int32_t engineId)
320 {
321 return (engineId < BASE_ENGINE_ID) || (engineId > rootEngineId_.load());
322 }
323 }
324 }