1 /*
2 * Copyright (c) 2022-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 "softbus_adapter.h"
17 #include "softbus_error_code.h"
18
19 #include <securec.h>
20
21 #undef DH_LOG_TAG
22 #define DH_LOG_TAG "SoftbusAdapter"
23
24 namespace OHOS {
25 namespace DistributedHardware {
26 IMPLEMENT_SINGLE_INSTANCE(SoftbusAdapter);
AudioOnSoftbusSessionOpened(int32_t sessionId,int32_t result)27 static int32_t AudioOnSoftbusSessionOpened(int32_t sessionId, int32_t result)
28 {
29 return SoftbusAdapter::GetInstance().OnSoftbusSessionOpened(sessionId, result);
30 }
31
AudioOnSoftbusSessionClosed(int32_t sessionId)32 static void AudioOnSoftbusSessionClosed(int32_t sessionId)
33 {
34 SoftbusAdapter::GetInstance().OnSoftbusSessionClosed(sessionId);
35 }
36
AudioOnBytesReceived(int32_t sessionId,const void * data,uint32_t dataLen)37 static void AudioOnBytesReceived(int32_t sessionId, const void *data, uint32_t dataLen)
38 {
39 SoftbusAdapter::GetInstance().OnBytesReceived(sessionId, data, dataLen);
40 }
41
AudioOnStreamReceived(int32_t sessionId,const StreamData * data,const StreamData * ext,const StreamFrameInfo * frameInfo)42 static void AudioOnStreamReceived(int32_t sessionId, const StreamData *data, const StreamData *ext,
43 const StreamFrameInfo *frameInfo)
44 {
45 SoftbusAdapter::GetInstance().OnStreamReceived(sessionId, data, ext, frameInfo);
46 }
47
AudioOnMessageReceived(int sessionId,const void * data,unsigned int dataLen)48 static void AudioOnMessageReceived(int sessionId, const void *data, unsigned int dataLen)
49 {
50 SoftbusAdapter::GetInstance().OnMessageReceived(sessionId, data, dataLen);
51 }
52
AudioOnQosEvent(int sessionId,int eventId,int tvCount,const QosTv * tvList)53 static void AudioOnQosEvent(int sessionId, int eventId, int tvCount, const QosTv *tvList)
54 {
55 SoftbusAdapter::GetInstance().OnQosEvent(sessionId, eventId, tvCount, tvList);
56 }
57
SoftbusAdapter()58 SoftbusAdapter::SoftbusAdapter()
59 {
60 DHLOGD("Softbus adapter constructed.");
61 sessListener_.OnSessionOpened = AudioOnSoftbusSessionOpened;
62 sessListener_.OnSessionClosed = AudioOnSoftbusSessionClosed;
63 sessListener_.OnBytesReceived = AudioOnBytesReceived;
64 sessListener_.OnStreamReceived = AudioOnStreamReceived;
65 sessListener_.OnMessageReceived = AudioOnMessageReceived;
66 sessListener_.OnQosEvent = AudioOnQosEvent;
67 }
68
~SoftbusAdapter()69 SoftbusAdapter::~SoftbusAdapter()
70 {
71 DHLOGD("Softbus adapter destructed.");
72 }
73
CreateSoftbusSessionServer(const std::string & pkgName,const std::string & sessionName,const std::string & peerDevId)74 int32_t SoftbusAdapter::CreateSoftbusSessionServer(const std::string &pkgName, const std::string &sessionName,
75 const std::string &peerDevId)
76 {
77 DHLOGI("Create server, sessName: %s peerDevId: %s.", sessionName.c_str(), GetAnonyString(peerDevId).c_str());
78 std::lock_guard<std::mutex> setLock(sessSetMtx_);
79 if (mapSessionSet_.find(sessionName) == mapSessionSet_.end()) {
80 int32_t ret = CreateSessionServer(pkgName.c_str(), sessionName.c_str(), &sessListener_);
81 if (ret != SOFTBUS_OK) {
82 DHLOGE("Create session server failed, ret %d.", ret);
83 return ret;
84 }
85 } else {
86 DHLOGD("Session is already created.");
87 return DH_SUCCESS;
88 }
89
90 mapSessionSet_[sessionName].insert(peerDevId);
91 DHLOGI("Create session server success.");
92 return DH_SUCCESS;
93 }
94
RemoveSoftbusSessionServer(const std::string & pkgName,const std::string & sessionName,const std::string & peerDevId)95 int32_t SoftbusAdapter::RemoveSoftbusSessionServer(const std::string &pkgName, const std::string &sessionName,
96 const std::string &peerDevId)
97 {
98 DHLOGI("Remove server, sessName: %s peerDevId: %s.", sessionName.c_str(), GetAnonyString(peerDevId).c_str());
99 std::lock_guard<std::mutex> setLock(sessSetMtx_);
100 if (mapSessionSet_.find(sessionName) == mapSessionSet_.end()) {
101 DHLOGE("Session server already removed.");
102 return DH_SUCCESS;
103 }
104 mapSessionSet_[sessionName].erase(peerDevId);
105 if (mapSessionSet_[sessionName].empty()) {
106 mapSessionSet_.erase(sessionName);
107 int32_t ret = RemoveSessionServer(pkgName.c_str(), sessionName.c_str());
108 if (ret != SOFTBUS_OK) {
109 DHLOGE("Remove session server failed. Error code %d.", ret);
110 }
111 }
112 DHLOGI("Remove session server success.");
113 return DH_SUCCESS;
114 }
115
OpenSoftbusSession(const std::string & localSessionName,const std::string & peerSessionName,const std::string & peerDevId)116 int32_t SoftbusAdapter::OpenSoftbusSession(const std::string &localSessionName, const std::string &peerSessionName,
117 const std::string &peerDevId)
118 {
119 DHLOGI("Open softbus session, localSess: %s peerSess: %s peerDevId: %s.", localSessionName.c_str(),
120 peerSessionName.c_str(), GetAnonyString(peerDevId).c_str());
121 int dataType = TYPE_BYTES;
122 int streamType = -1;
123 if (localSessionName != CTRL_SESSION_NAME) {
124 dataType = TYPE_STREAM;
125 streamType = RAW_STREAM;
126 }
127
128 SessionAttribute attr = { 0 };
129 attr.dataType = dataType;
130 attr.linkTypeNum = LINK_TYPE_MAX;
131 LinkType linkTypeList[LINK_TYPE_MAX] = {
132 LINK_TYPE_WIFI_P2P,
133 LINK_TYPE_WIFI_WLAN_5G,
134 LINK_TYPE_WIFI_WLAN_2G,
135 LINK_TYPE_BR,
136 };
137 if (memcpy_s(attr.linkType, sizeof(attr.linkType), linkTypeList, sizeof(linkTypeList)) != EOK) {
138 DHLOGE("Softbus open session params copy failed.");
139 return ERR_DH_AUDIO_FAILED;
140 }
141 attr.attr.streamAttr.streamType = streamType;
142 int32_t sessionId = OpenSession(localSessionName.c_str(), peerSessionName.c_str(), peerDevId.c_str(), "0", &attr);
143 if (sessionId < 0) {
144 DHLOGE("Open softbus session failed sessionId: %d.", sessionId);
145 return ERR_DH_AUDIO_ADAPTER_OPEN_SESSION_FAIL;
146 }
147 DHLOGI("Open softbus session success.");
148 return sessionId;
149 }
150
CloseSoftbusSession(int32_t sessionId)151 int32_t SoftbusAdapter::CloseSoftbusSession(int32_t sessionId)
152 {
153 DHLOGI("Close softbus session: %d.", sessionId);
154 CloseSession(sessionId);
155 std::lock_guard<std::mutex> LisLock(listenerMtx_);
156 mapListenersI_.erase(sessionId);
157 StopSendDataThread();
158 DHLOGI("Close softbus session success.");
159 return DH_SUCCESS;
160 }
161
SendSoftbusBytes(int32_t sessionId,const void * data,int32_t dataLen)162 int32_t SoftbusAdapter::SendSoftbusBytes(int32_t sessionId, const void *data, int32_t dataLen)
163 {
164 DHLOGI("Send audio event, sessionId: %d.", sessionId);
165 int32_t ret = SendBytes(sessionId, data, dataLen);
166 if (ret != SOFTBUS_OK) {
167 DHLOGE("Send bytes failed, ret:%d.", ret);
168 return ERR_DH_AUDIO_TRANS_ERROR;
169 }
170 return DH_SUCCESS;
171 }
172
SendSoftbusStream(int32_t sessionId,const std::shared_ptr<AudioData> & audioData)173 int32_t SoftbusAdapter::SendSoftbusStream(int32_t sessionId, const std::shared_ptr<AudioData> &audioData)
174 {
175 DHLOGI("Send audio data, sessionId: %d.", sessionId);
176 if (audioData == nullptr) {
177 DHLOGE("Audio data is null.");
178 return ERR_DH_AUDIO_TRANS_NULL_VALUE;
179 }
180 std::lock_guard<std::mutex> lck(dataQueueMtx_);
181 while (audioDataQueue_.size() >= DATA_QUEUE_MAX_SIZE) {
182 DHLOGE("Softbus data queue overflow. data queue size: %d", audioDataQueue_.size());
183 audioDataQueue_.pop();
184 }
185 auto data = std::make_shared<SoftbusStreamData>(audioData, sessionId);
186 audioDataQueue_.push(data);
187 sendDataCond_.notify_all();
188 return DH_SUCCESS;
189 }
190
RegisterSoftbusListener(const std::shared_ptr<ISoftbusListener> & listener,const std::string & sessionName,const std::string & peerDevId)191 int32_t SoftbusAdapter::RegisterSoftbusListener(const std::shared_ptr<ISoftbusListener> &listener,
192 const std::string &sessionName, const std::string &peerDevId)
193 {
194 DHLOGI("Register listener sess: %s peerDevId: %s.", sessionName.c_str(), GetAnonyString(peerDevId).c_str());
195 std::string strListenerKey = sessionName + "_" + peerDevId;
196 std::lock_guard<std::mutex> lisLock(listenerMtx_);
197 if (mapListenersN_.find(strListenerKey) != mapListenersN_.end()) {
198 DHLOGD("Session listener already register.");
199 return DH_SUCCESS;
200 }
201 mapListenersN_.insert(std::make_pair(strListenerKey, listener));
202 return DH_SUCCESS;
203 }
204
UnRegisterSoftbusListener(const std::string & sessionName,const std::string & peerDevId)205 int32_t SoftbusAdapter::UnRegisterSoftbusListener(const std::string &sessionName, const std::string &peerDevId)
206 {
207 DHLOGI("Unregister listener sess: %s peerDevId: %s.", sessionName.c_str(), GetAnonyString(peerDevId).c_str());
208 std::string strListenerKey = sessionName + "_" + peerDevId;
209 std::lock_guard<std::mutex> lisLock(listenerMtx_);
210 mapListenersN_.erase(strListenerKey);
211 return DH_SUCCESS;
212 }
213
OnSoftbusSessionOpened(int32_t sessionId,int32_t result)214 int32_t SoftbusAdapter::OnSoftbusSessionOpened(int32_t sessionId, int32_t result)
215 {
216 DHLOGI("On session opened, sessionId: %d, result: %d.", sessionId, result);
217 if (result != SOFTBUS_OK) {
218 DHLOGE("Session open failed.");
219 return ERR_DH_AUDIO_ADAPTER_OPEN_SESSION_FAIL;
220 }
221 auto &listener = GetSoftbusListenerByName(sessionId);
222 if (!listener) {
223 DHLOGE("Get softbus listener failed.");
224 return ERR_DH_AUDIO_TRANS_ERROR;
225 }
226
227 std::lock_guard<std::mutex> lisLock(listenerMtx_);
228 if (mapListenersI_.empty()) {
229 DHLOGD("Start softbus send thread.");
230 isSessionOpened_.store(true);
231 sendDataThread_ = std::thread(&SoftbusAdapter::SendAudioData, this);
232 if (pthread_setname_np(sendDataThread_.native_handle(), SENDDATA_THREAD) != DH_SUCCESS) {
233 DHLOGE("Send data thread setname failed.");
234 }
235 }
236 mapListenersI_.insert(std::make_pair(sessionId, listener));
237 listener->OnSessionOpened(sessionId, result);
238 return DH_SUCCESS;
239 }
240
OnSoftbusSessionClosed(int32_t sessionId)241 void SoftbusAdapter::OnSoftbusSessionClosed(int32_t sessionId)
242 {
243 DHLOGI("On session closed, sessionId: %d.", sessionId);
244 auto &listener = GetSoftbusListenerById(sessionId);
245 if (!listener) {
246 DHLOGE("Get softbus listener failed.");
247 return;
248 }
249 listener->OnSessionClosed(sessionId);
250
251 std::lock_guard<std::mutex> lisLock(listenerMtx_);
252 mapListenersI_.erase(sessionId);
253 StopSendDataThread();
254 }
255
OnBytesReceived(int32_t sessionId,const void * data,uint32_t dataLen)256 void SoftbusAdapter::OnBytesReceived(int32_t sessionId, const void *data, uint32_t dataLen)
257 {
258 DHLOGI("On audio event received from session: %d.", sessionId);
259 if (data == nullptr) {
260 DHLOGE("Bytes data is null.");
261 return;
262 } else if (dataLen == 0 || dataLen > DAUDIO_MAX_RECV_DATA_LEN) {
263 DHLOGE("Stream data length is illegal, dataLen: %d.", dataLen);
264 return;
265 }
266
267 auto &listener = GetSoftbusListenerById(sessionId);
268 if (listener == nullptr) {
269 DHLOGE("Get softbus listener failed.");
270 return;
271 }
272 listener->OnBytesReceived(sessionId, data, dataLen);
273 }
274
OnStreamReceived(int32_t sessionId,const StreamData * data,const StreamData * ext,const StreamFrameInfo * streamFrameInfo)275 void SoftbusAdapter::OnStreamReceived(int32_t sessionId, const StreamData *data, const StreamData *ext,
276 const StreamFrameInfo *streamFrameInfo)
277 {
278 DHLOGI("On audio data received from session: %d.", sessionId);
279 if (data == nullptr) {
280 DHLOGE("Stream data is null.");
281 return;
282 } else if (data->bufLen <= 0 || (uint32_t)(data->bufLen) > DAUDIO_MAX_RECV_DATA_LEN) {
283 DHLOGE("Stream data length is illegal, dataLen: %d.", data->bufLen);
284 return;
285 }
286
287 auto &listener = GetSoftbusListenerById(sessionId);
288 if (!listener) {
289 DHLOGE("Get softbus listener failed.");
290 return;
291 }
292 listener->OnStreamReceived(sessionId, data, ext, streamFrameInfo);
293 }
294
OnMessageReceived(int sessionId,const void * data,unsigned int dataLen)295 void SoftbusAdapter::OnMessageReceived(int sessionId, const void *data, unsigned int dataLen)
296 {
297 DHLOGD("On message received, sessionId: %d.", sessionId);
298 }
299
OnQosEvent(int sessionId,int eventId,int tvCount,const QosTv * tvList)300 void SoftbusAdapter::OnQosEvent(int sessionId, int eventId, int tvCount, const QosTv *tvList)
301 {
302 DHLOGD("On qos event received, sessionId: %d.", sessionId);
303 }
304
GetSoftbusListenerByName(int32_t sessionId)305 std::shared_ptr<ISoftbusListener> &SoftbusAdapter::GetSoftbusListenerByName(int32_t sessionId)
306 {
307 char sessionName[DAUDIO_MAX_SESSION_NAME_LEN] = "";
308 char peerDevId[DAUDIO_MAX_DEVICE_ID_LEN] = "";
309 int32_t ret = GetPeerSessionName(sessionId, sessionName, sizeof(sessionName));
310 if (ret != SOFTBUS_OK) {
311 DHLOGE("Get peer session name failed ret: %d.", ret);
312 return nullListener_;
313 }
314 ret = GetPeerDeviceId(sessionId, peerDevId, sizeof(peerDevId));
315 if (ret != SOFTBUS_OK) {
316 DHLOGE("Get peer deviceId failed ret: %d.", ret);
317 return nullListener_;
318 }
319 std::string sessionNameStr(sessionName);
320 std::string peerDevIdStr(peerDevId);
321 std::string strListenerKey = sessionNameStr + "_" + peerDevIdStr;
322
323 DHLOGI("Get listener sess: %s, peerDevId: %s.", sessionNameStr.c_str(), GetAnonyString(peerDevIdStr).c_str());
324 std::lock_guard<std::mutex> lisLock(listenerMtx_);
325 if (mapListenersN_.find(strListenerKey) == mapListenersN_.end()) {
326 DHLOGE("Find listener failed.");
327 return nullListener_;
328 }
329 return mapListenersN_[strListenerKey];
330 }
331
GetSoftbusListenerById(int32_t sessionId)332 std::shared_ptr<ISoftbusListener> &SoftbusAdapter::GetSoftbusListenerById(int32_t sessionId)
333 {
334 std::lock_guard<std::mutex> lisLock(listenerMtx_);
335 if (mapListenersI_.find(sessionId) == mapListenersI_.end()) {
336 DHLOGE("Find listener failed.");
337 return nullListener_;
338 }
339 return mapListenersI_[sessionId];
340 }
341
SendAudioData()342 void SoftbusAdapter::SendAudioData()
343 {
344 constexpr uint8_t DATA_WAIT_TIME = 20;
345 while (isSessionOpened_.load()) {
346 std::shared_ptr<SoftbusStreamData> audioData;
347 {
348 std::unique_lock<std::mutex> lock(dataQueueMtx_);
349 sendDataCond_.wait_for(lock, std::chrono::milliseconds(DATA_WAIT_TIME),
350 [this]() { return !audioDataQueue_.empty(); });
351 if (audioDataQueue_.empty()) {
352 continue;
353 }
354 audioData = audioDataQueue_.front();
355 audioDataQueue_.pop();
356 }
357 if (audioData == nullptr || audioData->data_ == nullptr) {
358 DHLOGE("Audio data is null.");
359 continue;
360 }
361
362 StreamData data = { reinterpret_cast<char *>(audioData->data_->Data()), audioData->data_->Capacity() };
363 StreamData ext;
364 StreamFrameInfo frameInfo;
365 DHLOGI("Send audio data, sessionId: %d.", audioData->sessionId_);
366 int32_t ret = SendStream(audioData->sessionId_, &data, &ext, &frameInfo);
367 if (ret != SOFTBUS_OK) {
368 DHLOGE("Send data failed. ret: %d.", ret);
369 } else {
370 DHLOGI("Send audio data successs.");
371 }
372 }
373 }
374
StopSendDataThread()375 void SoftbusAdapter::StopSendDataThread()
376 {
377 if (mapListenersI_.empty()) {
378 DHLOGI("Stop softbus send thread.");
379 isSessionOpened_.store(false);
380 if (sendDataThread_.joinable()) {
381 sendDataThread_.join();
382 }
383 }
384 }
385 } // namespace DistributedHardware
386 } // namespace OHOS