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