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