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 #ifndef LOG_TAG
16 #define LOG_TAG "AudioDeviceAdapterImpl"
17 #endif
18
19 #include "audio_device_adapter_impl.h"
20
21 #include <securec.h>
22
23 #include "audio_errors.h"
24 #include "audio_hdi_log.h"
25
26 namespace OHOS {
27 namespace AudioStandard {
28 using OHOS::HDI::DistributedAudio::Audio::V1_0::IAudioCallback;
29 using OHOS::HDI::DistributedAudio::Audio::V1_0::AudioCallbackType;
30 using OHOS::HDI::DistributedAudio::Audio::V1_0::AudioExtParamKey;
31
32 std::shared_ptr<AudioDeviceAdapterImpl> AudioDeviceAdapterImpl::paramCallback_ = nullptr;
33
34 class AudioParamCallbackImpl final : public IAudioCallback {
35 public:
AudioParamCallbackImpl()36 AudioParamCallbackImpl() {}
~AudioParamCallbackImpl()37 ~AudioParamCallbackImpl() override {}
38
39 int32_t RenderCallback(AudioCallbackType type, int8_t &reserved, int8_t &cookie) override;
40 int32_t ParamCallback(AudioExtParamKey key, const std::string &condition, const std::string &value,
41 int8_t &reserved, int8_t cookie) override;
42 };
43
RenderCallback(AudioCallbackType type,int8_t & reserved,int8_t & cookie)44 int32_t AudioParamCallbackImpl::RenderCallback(AudioCallbackType type, int8_t &reserved, int8_t &cookie)
45 {
46 (void) type;
47 (void) reserved;
48 (void) cookie;
49 return SUCCESS;
50 }
51
ParamCallback(AudioExtParamKey key,const std::string & condition,const std::string & value,int8_t & reserved,int8_t cookie)52 int32_t AudioParamCallbackImpl::ParamCallback(AudioExtParamKey key, const std::string &condition,
53 const std::string &value, int8_t &reserved, int8_t cookie)
54 {
55 (void) cookie;
56 AUDIO_INFO_LOG("key %{public}d, condition %{public}s, value %{public}s", key, condition.c_str(), value.c_str());
57 std::shared_ptr<AudioDeviceAdapterImpl> cookies = AudioDeviceAdapterImpl::GetParamCallback();
58 AudioDeviceAdapterImpl::ParamEventCallback(static_cast<::AudioExtParamKey>(key), condition.c_str(),
59 value.c_str(), static_cast<void *>(&reserved), cookies);
60 return SUCCESS;
61 }
62
Init()63 int32_t AudioDeviceAdapterImpl::Init()
64 {
65 AUDIO_INFO_LOG("Init start.");
66
67 CHECK_AND_RETURN_RET_LOG(audioAdapter_ != nullptr, ERR_INVALID_HANDLE,
68 "Init: audio adapter is null.");
69 int32_t ret = audioAdapter_->InitAllPorts();
70 CHECK_AND_RETURN_RET_LOG(ret == 0, ERR_DEVICE_INIT, "InitAllPorts fail, ret %{public}d.", ret);
71
72 ret = RegExtraParamObserver();
73 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ret, "Init: Register extra param observer fail, ret %{public}d.", ret);
74 AUDIO_DEBUG_LOG("Init end.");
75 return SUCCESS;
76 }
77
GetRenderPortsNum()78 size_t AudioDeviceAdapterImpl::GetRenderPortsNum()
79 {
80 std::lock_guard<std::mutex> lock(renderPortsMtx_);
81 return renderPorts_.size();
82 }
83
GetCapturePortsNum()84 size_t AudioDeviceAdapterImpl::GetCapturePortsNum()
85 {
86 std::lock_guard<std::mutex> lock(capturePortsMtx_);
87 return capturePorts_.size();
88 }
89
HandleRenderParamEvent(std::shared_ptr<AudioDeviceAdapterImpl> devAdapter,const AudioParamKey audioKey,const char * condition,const char * value)90 int32_t AudioDeviceAdapterImpl::HandleRenderParamEvent(std::shared_ptr<AudioDeviceAdapterImpl> devAdapter,
91 const AudioParamKey audioKey, const char *condition, const char *value)
92 {
93 CHECK_AND_RETURN_RET_LOG(devAdapter != nullptr && condition != nullptr && value != nullptr,
94 ERR_INVALID_HANDLE, "some params are null.");
95
96 IAudioDeviceAdapterCallback *sink = nullptr;
97 {
98 std::lock_guard<std::mutex> lock(devAdapter->renderPortsMtx_);
99 if (devAdapter->renderPorts_.size() != 1) {
100 AUDIO_WARNING_LOG("Please check renderId or other infos.");
101 }
102 for (auto i = devAdapter->renderPorts_.begin(); i != devAdapter->renderPorts_.end();) {
103 sink = i->second.devAdpCb;
104 if (sink == nullptr) {
105 AUDIO_ERR_LOG("Device adapter sink callback is null.");
106 devAdapter->renderPorts_.erase(i++);
107 continue;
108 }
109 break;
110 }
111 }
112
113 CHECK_AND_RETURN_RET_LOG(sink != nullptr, ERR_INVALID_HANDLE,
114 "Not find daudio sink port in adapter, condition %{public}s.", condition);
115 sink->OnAudioParamChange(devAdapter->adapterName_, audioKey, std::string(condition), std::string(value));
116 return SUCCESS;
117 }
118
HandleCaptureParamEvent(std::shared_ptr<AudioDeviceAdapterImpl> devAdapter,const AudioParamKey audioKey,const char * condition,const char * value)119 int32_t AudioDeviceAdapterImpl::HandleCaptureParamEvent(std::shared_ptr<AudioDeviceAdapterImpl> devAdapter,
120 const AudioParamKey audioKey, const char *condition, const char *value)
121 {
122 CHECK_AND_RETURN_RET_LOG(devAdapter != nullptr && condition != nullptr && value != nullptr,
123 ERR_INVALID_HANDLE, "some params are null.");
124
125 IAudioDeviceAdapterCallback *source = nullptr;
126 {
127 std::lock_guard<std::mutex> lock(devAdapter->capturePortsMtx_);
128 if (devAdapter->capturePorts_.size() != 1) {
129 AUDIO_WARNING_LOG("Please check captureId or other infos.");
130 }
131 for (auto j = devAdapter->capturePorts_.begin(); j != devAdapter->capturePorts_.end();) {
132 source = j->second.devAdpCb;
133 if (source == nullptr) {
134 AUDIO_ERR_LOG("Device adapter source callback is null.");
135 devAdapter->capturePorts_.erase(j++);
136 continue;
137 }
138 break;
139 }
140 }
141
142 CHECK_AND_RETURN_RET_LOG(source != nullptr, ERR_INVALID_HANDLE,
143 "Not find daudio source port in adapter, condition %{public}s.", condition);
144 source->OnAudioParamChange(devAdapter->adapterName_, audioKey, std::string(condition), std::string(value));
145 return SUCCESS;
146 }
147
HandleStateChangeEvent(std::shared_ptr<AudioDeviceAdapterImpl> devAdapter,const AudioParamKey audioKey,const char * condition,const char * value)148 int32_t AudioDeviceAdapterImpl::HandleStateChangeEvent(std::shared_ptr<AudioDeviceAdapterImpl> devAdapter,
149 const AudioParamKey audioKey, const char *condition, const char *value)
150 {
151 CHECK_AND_RETURN_RET_LOG(devAdapter != nullptr && condition != nullptr && value == nullptr,
152 ERR_INVALID_HANDLE, "some params are null.");
153
154 char eventDes[EVENT_DES_SIZE];
155 char contentDes[ADAPTER_STATE_CONTENT_DES_SIZE];
156 CHECK_AND_RETURN_RET_LOG(
157 sscanf_s(condition, "%[^;];%s", eventDes, EVENT_DES_SIZE, contentDes, ADAPTER_STATE_CONTENT_DES_SIZE)
158 == PARAMS_STATE_NUM, ERR_INVALID_PARAM, "ParamEventCallback: Failed parse condition");
159 CHECK_AND_RETURN_RET_LOG(strcmp(eventDes, "ERR_EVENT") == 0, ERR_NOT_SUPPORTED,
160 "Event %{public}s is not supported.", eventDes);
161
162 AUDIO_INFO_LOG("render state invalid, destroy audioRender");
163
164 std::string devTypeKey = "DEVICE_TYPE=";
165 std::string contentDesStr = std::string(contentDes);
166 size_t devTypeKeyPos = contentDesStr.find(devTypeKey);
167 CHECK_AND_RETURN_RET_LOG(devTypeKeyPos != std::string::npos, ERR_INVALID_PARAM,
168 "Not find daudio device type info, contentDes %{public}s.", contentDesStr.c_str());
169 size_t devTypeValPos = devTypeKeyPos + devTypeKey.length();
170 CHECK_AND_RETURN_RET_LOG(devTypeValPos < contentDesStr.length(), ERR_INVALID_PARAM,
171 "Not find daudio device type value, contentDes %{public}s.", contentDesStr.c_str());
172
173 int32_t ret = SUCCESS;
174 if (contentDesStr[devTypeValPos] == DAUDIO_DEV_TYPE_SPK) {
175 AUDIO_INFO_LOG("ERR_EVENT of DAUDIO_DEV_TYPE_SPK.");
176 ret = HandleRenderParamEvent(devAdapter, audioKey, condition, value);
177 } else if (contentDesStr[devTypeValPos] == DAUDIO_DEV_TYPE_MIC) {
178 AUDIO_INFO_LOG("ERR_EVENT of DAUDIO_DEV_TYPE_MIC.");
179 ret = HandleCaptureParamEvent(devAdapter, audioKey, condition, value);
180 } else {
181 AUDIO_ERR_LOG("Device type is not supported, contentDes %{public}s.",
182 contentDesStr.c_str());
183 return ERR_NOT_SUPPORTED;
184 }
185
186 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ret,
187 "Handle state error change event %{public}s fail.", contentDesStr.c_str());
188 return SUCCESS;
189 }
190
ParamEventCallback(AudioExtParamKey key,const char * condition,const char * value,void * reserved,std::shared_ptr<AudioDeviceAdapterImpl> cookie)191 int32_t AudioDeviceAdapterImpl::ParamEventCallback(AudioExtParamKey key, const char *condition, const char *value,
192 void *reserved, std::shared_ptr<AudioDeviceAdapterImpl> cookie)
193 {
194 AUDIO_INFO_LOG("key %{public}d, condition %{public}s, value %{public}s",
195 key, condition, value);
196 AudioParamKey audioKey = AudioParamKey(key);
197 int32_t ret = SUCCESS;
198 switch (audioKey) {
199 case AudioParamKey::PARAM_KEY_STATE:
200 ret = HandleStateChangeEvent(cookie, audioKey, condition, value);
201 break;
202 case AudioParamKey::VOLUME:
203 case AudioParamKey::INTERRUPT:
204 HandleRenderParamEvent(cookie, audioKey, condition, value);
205 break;
206 default:
207 AUDIO_ERR_LOG("Audio param key %{public}d is not supported.", audioKey);
208 return ERR_NOT_SUPPORTED;
209 }
210 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ret,
211 "Handle audio param key %{public}d fail, ret %{public}d.", audioKey, ret);
212 return SUCCESS;
213 }
214
SetParamCallback(std::shared_ptr<AudioDeviceAdapterImpl> callback)215 void AudioDeviceAdapterImpl::SetParamCallback(std::shared_ptr<AudioDeviceAdapterImpl> callback)
216 {
217 AudioDeviceAdapterImpl::paramCallback_ = callback;
218 }
219
GetParamCallback()220 std::shared_ptr<AudioDeviceAdapterImpl> AudioDeviceAdapterImpl::GetParamCallback()
221 {
222 return AudioDeviceAdapterImpl::paramCallback_;
223 }
224
RegExtraParamObserver()225 int32_t AudioDeviceAdapterImpl::RegExtraParamObserver()
226 {
227 AUDIO_INFO_LOG("Register extra param observer.");
228 #ifdef FEATURE_DISTRIBUTE_AUDIO
229 std::lock_guard<std::mutex> lock(regParamCbMtx_);
230 if (isParamCbReg_.load()) {
231 AUDIO_INFO_LOG("Audio adapter already registered extra param observer.");
232 return SUCCESS;
233 }
234
235 callbackStub_ = new AudioParamCallbackImpl();
236 CHECK_AND_RETURN_RET_LOG(audioAdapter_ != nullptr, ERR_INVALID_HANDLE,
237 "audio adapter is null.");
238
239 int32_t ret = audioAdapter_->RegExtraParamObserver(callbackStub_, 0);
240 CHECK_AND_RETURN_RET_LOG(ret == 0, ERR_OPERATION_FAILED,
241 "Register extra param observer fail, ret %{public}d", ret);
242
243 isParamCbReg_.store(true);
244 AUDIO_INFO_LOG("Register extra param observer for daudio OK.");
245 #endif
246 return SUCCESS;
247 }
248
CreateRender(const AudioDeviceDescriptor & devDesc,const AudioSampleAttributes & attr,sptr<IAudioRender> & audioRender,IAudioDeviceAdapterCallback * renderCb,uint32_t & renderId)249 int32_t AudioDeviceAdapterImpl::CreateRender(const AudioDeviceDescriptor &devDesc, const AudioSampleAttributes &attr,
250 sptr<IAudioRender> &audioRender, IAudioDeviceAdapterCallback *renderCb, uint32_t &renderId)
251 {
252 AUDIO_INFO_LOG("Create render start.");
253 CHECK_AND_RETURN_RET_LOG(audioAdapter_ != nullptr, ERR_INVALID_HANDLE,
254 "audio adapter is null.");
255 int32_t ret = audioAdapter_->CreateRender(devDesc, attr, audioRender, renderId);
256 CHECK_AND_RETURN_RET_LOG(ret == 0 && audioRender != nullptr, ERR_NOT_STARTED, "AudioDeviceCreateRender failed");
257
258 std::lock_guard<std::mutex> lock(renderPortsMtx_);
259 if (renderPorts_.find(audioRender) != renderPorts_.end()) {
260 AUDIO_DEBUG_LOG("Audio render already exit in renderPorts, will replace new port info.");
261 }
262
263 DevicePortInfo renderPortInfo = {
264 .devAdpCb = renderCb,
265 .portId = 0,
266 };
267 renderPorts_[audioRender] = renderPortInfo;
268 return SUCCESS;
269 }
270
DestroyRender(sptr<IAudioRender> audioRender,uint32_t & renderId)271 void AudioDeviceAdapterImpl::DestroyRender(sptr<IAudioRender> audioRender, uint32_t &renderId)
272 {
273 CHECK_AND_RETURN_LOG(audioRender != nullptr, "DestroyRender: Audio render is null.");
274 {
275 std::lock_guard<std::mutex> lock(renderPortsMtx_);
276 AUDIO_INFO_LOG("Destroy render start.");
277 if (renderPorts_.find(audioRender) == renderPorts_.end()) {
278 AUDIO_DEBUG_LOG("Audio render is already destoried.");
279 return;
280 }
281 }
282
283 CHECK_AND_RETURN_LOG(audioAdapter_ != nullptr, "DestroyRender: Audio adapter is null.");
284 audioAdapter_->DestroyRender(renderId);
285
286 {
287 std::lock_guard<std::mutex> lock(renderPortsMtx_);
288 renderPorts_.erase(audioRender);
289 }
290 }
291
CreateCapture(const AudioDeviceDescriptor & devDesc,const AudioSampleAttributes & attr,sptr<IAudioCapture> & audioCapture,IAudioDeviceAdapterCallback * captureCb,uint32_t & captureId)292 int32_t AudioDeviceAdapterImpl::CreateCapture(const AudioDeviceDescriptor &devDesc, const AudioSampleAttributes &attr,
293 sptr<IAudioCapture> &audioCapture, IAudioDeviceAdapterCallback *captureCb, uint32_t &captureId)
294 {
295 CHECK_AND_RETURN_RET_LOG(audioAdapter_ != nullptr, ERR_INVALID_HANDLE,
296 "audio adapter is null.");
297 int32_t ret = audioAdapter_->CreateCapture(devDesc, attr, audioCapture, captureId);
298 CHECK_AND_RETURN_RET_LOG(ret == 0 && audioCapture != nullptr,
299 ERR_NOT_STARTED, "Create capture failed, error code %{public}d.", ret);
300
301 std::lock_guard<std::mutex> lock(capturePortsMtx_);
302 if (capturePorts_.find(audioCapture) != capturePorts_.end()) {
303 AUDIO_INFO_LOG("Audio capture already exit in capturePorts, will replace new port info.");
304 }
305
306 DevicePortInfo capturePortInfo = {
307 .devAdpCb = captureCb,
308 .portId = 0,
309 };
310 capturePorts_[audioCapture] = capturePortInfo;
311 return SUCCESS;
312 }
313
DestroyCapture(sptr<IAudioCapture> audioCapture,uint32_t & captureId)314 void AudioDeviceAdapterImpl::DestroyCapture(sptr<IAudioCapture> audioCapture, uint32_t &captureId)
315 {
316 CHECK_AND_RETURN_LOG(audioCapture != nullptr, "Audio capture is null.");
317 {
318 std::lock_guard<std::mutex> lock(capturePortsMtx_);
319 AUDIO_INFO_LOG("Destroy capture start.");
320 if (capturePorts_.find(audioCapture) == capturePorts_.end()) {
321 AUDIO_INFO_LOG("Audio capture is already destoried.");
322 return;
323 }
324 }
325
326 CHECK_AND_RETURN_LOG(audioAdapter_ != nullptr, "Audio adapter is null.");
327 audioAdapter_->DestroyCapture(captureId);
328
329 {
330 std::lock_guard<std::mutex> lock(capturePortsMtx_);
331 capturePorts_.erase(audioCapture);
332 }
333 }
334
SetAudioParameter(const AudioParamKey key,const std::string & condition,const std::string & value)335 void AudioDeviceAdapterImpl::SetAudioParameter(const AudioParamKey key, const std::string &condition,
336 const std::string &value)
337 {
338 #ifdef FEATURE_DISTRIBUTE_AUDIO
339 AUDIO_INFO_LOG("key %{public}d, condition: %{public}s, value: %{public}s.",
340 key, condition.c_str(), value.c_str());
341 CHECK_AND_RETURN_LOG(audioAdapter_ != nullptr, "Audio adapter is null.");
342
343 enum AudioExtParamKey hdiKey = AudioExtParamKey(key);
344 int32_t ret = audioAdapter_->SetExtraParams(hdiKey, condition, value);
345 CHECK_AND_RETURN_LOG(ret == 0, "Set audio parameter fail, ret %{public}d.", ret);
346 #else
347 AUDIO_INFO_LOG("SetAudioParameter is not supported.");
348 #endif
349 }
350
GetAudioParameter(const AudioParamKey key,const std::string & condition)351 std::string AudioDeviceAdapterImpl::GetAudioParameter(const AudioParamKey key, const std::string &condition)
352 {
353 #ifdef FEATURE_DISTRIBUTE_AUDIO
354 AUDIO_INFO_LOG("GetParameter: key %{public}d, condition: %{public}s", key,
355 condition.c_str());
356 CHECK_AND_RETURN_RET_LOG(audioAdapter_ != nullptr, "", "Audio adapter is null.");
357 enum AudioExtParamKey hdiKey = AudioExtParamKey(key);
358 std::string value;
359 int32_t ret = audioAdapter_->GetExtraParams(hdiKey, condition.c_str(), value);
360 CHECK_AND_RETURN_RET_LOG(ret == 0, "", "Get audio parameter fail, ret %{public}d", ret);
361 return value;
362 #else
363 AUDIO_INFO_LOG("GetAudioParameter is not supported.");
364 return "";
365 #endif
366 }
367
UpdateAudioRoute(const AudioRoute & route)368 int32_t AudioDeviceAdapterImpl::UpdateAudioRoute(const AudioRoute &route)
369 {
370 AUDIO_INFO_LOG("UpdateAudioRoute enter.");
371 CHECK_AND_RETURN_RET_LOG(audioAdapter_ != nullptr, ERR_INVALID_HANDLE,
372 "UpdateAudioRoute: Audio adapter is null.");
373 int32_t ret = audioAdapter_->UpdateAudioRoute(route, routeHandle_);
374 CHECK_AND_RETURN_RET_LOG(ret == 0, ERR_OPERATION_FAILED, "Update audio route fail, ret %{public}d", ret);
375 return SUCCESS;
376 }
377
Release()378 int32_t AudioDeviceAdapterImpl::Release()
379 {
380 AUDIO_INFO_LOG("Release enter.");
381 if (audioAdapter_ == nullptr) {
382 AUDIO_INFO_LOG("Audio adapter is already released.");
383 return SUCCESS;
384 }
385
386 size_t capturePortsNum = GetCapturePortsNum();
387 size_t renderPortsNum = GetRenderPortsNum();
388 CHECK_AND_RETURN_RET_LOG(capturePortsNum + renderPortsNum == 0, ERR_ILLEGAL_STATE,
389 "Audio adapter has some ports busy, capturePortsNum %zu, renderPortsNum %zu.",
390 capturePortsNum, renderPortsNum);
391 if (routeHandle_ != INVALID_ROUT_HANDLE) {
392 audioAdapter_->ReleaseAudioRoute(routeHandle_);
393 }
394 audioAdapter_ = nullptr;
395 AudioDeviceAdapterImpl::paramCallback_ = nullptr;
396 AUDIO_DEBUG_LOG("Release end.");
397 return SUCCESS;
398 }
399 } // namespace AudioStandard
400 } // namespace OHOS
401