1 /*
2 * Copyright (c) 2025 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 #ifndef LOG_TAG
17 #define LOG_TAG "DirectAudioRenderSink"
18 #endif
19
20 #include "sink/direct_audio_render_sink.h"
21 #include <climits>
22 #include <future>
23 #include "audio_hdi_log.h"
24 #include "audio_errors.h"
25 #include "audio_dump_pcm.h"
26 #include "volume_tools.h"
27 #include "parameters.h"
28 #include "media_monitor_manager.h"
29 #include "common/hdi_adapter_info.h"
30 #include "manager/hdi_adapter_manager.h"
31
32 namespace OHOS {
33 namespace AudioStandard {
~DirectAudioRenderSink()34 DirectAudioRenderSink::~DirectAudioRenderSink()
35 {
36 }
37
Init(const IAudioSinkAttr & attr)38 int32_t DirectAudioRenderSink::Init(const IAudioSinkAttr &attr)
39 {
40 std::lock_guard<std::mutex> lock(sinkMutex_);
41 Trace trace("DirectAudioRenderSink::Init");
42 testFlag_ = system::GetIntParameter("persist.multimedia.eac3test", 0);
43 if (!testFlag_) {
44 attr_ = attr;
45 int32_t ret = CreateRender();
46 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_NOT_STARTED, "create render fail");
47 }
48 sinkInited_ = true;
49 return SUCCESS;
50 }
51
DeInit(void)52 void DirectAudioRenderSink::DeInit(void)
53 {
54 AUDIO_INFO_LOG("in");
55 Trace trace("DirectAudioRenderSink::DeInit");
56 std::lock_guard<std::mutex> lock(sinkMutex_);
57 sinkInited_ = false;
58 started_ = false;
59 if (!testFlag_) {
60 HdiAdapterManager &manager = HdiAdapterManager::GetInstance();
61 std::shared_ptr<IDeviceManager> deviceManager = manager.GetDeviceManager(HDI_DEVICE_MANAGER_TYPE_LOCAL);
62 CHECK_AND_RETURN(deviceManager != nullptr);
63 deviceManager->DestroyRender(attr_.adapterName, hdiRenderId_);
64 audioRender_ = nullptr;
65 }
66 hdiCallback_ = {};
67 DumpFileUtil::CloseDumpFile(&dumpFile_);
68 }
69
IsInited(void)70 bool DirectAudioRenderSink::IsInited(void)
71 {
72 return sinkInited_;
73 }
74
Start(void)75 int32_t DirectAudioRenderSink::Start(void)
76 {
77 std::unique_lock<std::mutex> lock(sinkMutex_);
78 AUDIO_INFO_LOG("in");
79 Trace trace("DirectAudioRenderSink::Start");
80 if (started_) {
81 return SUCCESS;
82 }
83 dumpFileName_ = "direct_sink_" + GetTime() + "_" + std::to_string(attr_.sampleRate) + "_" +
84 std::to_string(attr_.channel) + "_" + std::to_string(attr_.format) + ".pcm";
85 DumpFileUtil::OpenDumpFile(DumpFileUtil::DUMP_SERVER_PARA, dumpFileName_, &dumpFile_);
86 if (testFlag_) {
87 started_ = true;
88 lock.unlock();
89 StartTestThread();
90 return SUCCESS;
91 }
92 AudioXCollie audioXCollie("DirectAudioRenderSink::Start", TIMEOUT_SECONDS_10,
93 nullptr, nullptr, AUDIO_XCOLLIE_FLAG_LOG | AUDIO_XCOLLIE_FLAG_RECOVERY);
94 CHECK_AND_RETURN_RET_LOG(audioRender_ != nullptr, ERR_INVALID_HANDLE, "render is nullptr");
95 int32_t ret = audioRender_->Start(audioRender_);
96 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_NOT_STARTED, "start fail, ret: %{public}d", ret);
97 started_ = true;
98 return SUCCESS;
99 }
100
StartTestThread(void)101 void DirectAudioRenderSink::StartTestThread(void)
102 {
103 std::thread([this]() {
104 bool keepRunning = true;
105 while (keepRunning) {
106 std::unique_lock<std::mutex> lock(sinkMutex_);
107 keepRunning = started_ && sinkInited_;
108 hdiCallback_.serviceCallback_(CB_NONBLOCK_WRITE_COMPLETED);
109 lock.unlock();
110 std::this_thread::sleep_for(std::chrono::milliseconds(TEST_CALLBACK_TIME));
111 }
112 }).detach();
113 }
114
Stop(void)115 int32_t DirectAudioRenderSink::Stop(void)
116 {
117 std::lock_guard<std::mutex> lock(sinkMutex_);
118 AUDIO_INFO_LOG("in");
119 Trace trace("DirectAudioRenderSink::Stop");
120 if (!started_) {
121 return SUCCESS;
122 }
123 if (!testFlag_) {
124 #ifdef FEATURE_POWER_MANAGER
125 if (runningLock_ != nullptr) {
126 std::thread runningLockThread([this] {
127 runningLock_->UnLock();
128 });
129 runningLockThread.join();
130 }
131 #endif
132 AudioXCollie audioXCollie("DirectAudioRenderSink::Stop", TIMEOUT_SECONDS_10,
133 nullptr, nullptr, AUDIO_XCOLLIE_FLAG_LOG | AUDIO_XCOLLIE_FLAG_RECOVERY);
134 CHECK_AND_RETURN_RET_LOG(audioRender_ != nullptr, ERR_INVALID_HANDLE, "render is nullptr");
135 int32_t ret = audioRender_->Stop(audioRender_);
136 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_NOT_STARTED, "stop fail");
137 }
138 started_ = false;
139 return SUCCESS;
140 }
141
Resume(void)142 int32_t DirectAudioRenderSink::Resume(void)
143 {
144 AUDIO_INFO_LOG("not support");
145 return ERR_NOT_SUPPORTED;
146 }
147
Pause(void)148 int32_t DirectAudioRenderSink::Pause(void)
149 {
150 AUDIO_INFO_LOG("not support");
151 return ERR_NOT_SUPPORTED;
152 }
153
Flush(void)154 int32_t DirectAudioRenderSink::Flush(void)
155 {
156 return SUCCESS;
157 }
158
Reset(void)159 int32_t DirectAudioRenderSink::Reset(void)
160 {
161 return SUCCESS;
162 }
163
RenderFrame(char & data,uint64_t len,uint64_t & writeLen)164 int32_t DirectAudioRenderSink::RenderFrame(char &data, uint64_t len, uint64_t &writeLen)
165 {
166 if (testFlag_) {
167 DumpFileUtil::WriteDumpFile(dumpFile_, static_cast<void *>(&data), len);
168 } else {
169 int64_t stamp = ClockTime::GetCurNano();
170 CHECK_AND_RETURN_RET_LOG(audioRender_ != nullptr, ERR_INVALID_HANDLE, "render is nullptr");
171 CHECK_AND_RETURN_RET_LOG(started_, ERR_OPERATION_FAILED, "not start, invalid state");
172
173 Trace trace("DirectAudioRenderSink::RenderFrame");
174 int32_t ret = audioRender_->RenderFrame(audioRender_, reinterpret_cast<int8_t *>(&data),
175 static_cast<uint32_t>(len), &writeLen);
176 #ifdef FEATURE_POWER_MANAGER
177 if (runningLock_) {
178 runningLock_->UpdateAppsUidToPowerMgr();
179 }
180 #endif
181 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_WRITE_FAILED, "fail, ret: %{public}x", ret);
182 if (writeLen != 0) {
183 AudioStreamInfo streamInfo(static_cast<AudioSamplingRate>(attr_.sampleRate),
184 AudioEncodingType::ENCODING_EAC3, static_cast<AudioSampleFormat>(attr_.format),
185 static_cast<AudioChannel>(attr_.channel));
186 // EAC3 format is not supported to count volume
187 if (AudioDump::GetInstance().GetVersionType() == DumpFileUtil::BETA_VERSION) {
188 DumpFileUtil::WriteDumpFile(dumpFile_, static_cast<void *>(&data), writeLen);
189 AudioCacheMgr::GetInstance().CacheData(dumpFileName_, static_cast<void *>(&data), writeLen);
190 }
191 }
192 stamp = (ClockTime::GetCurNano() - stamp) / AUDIO_US_PER_SECOND;
193 }
194 return SUCCESS;
195 }
196
GetVolumeDataCount()197 int64_t DirectAudioRenderSink::GetVolumeDataCount()
198 {
199 AUDIO_WARNING_LOG("not supported");
200 return 0;
201 }
202
SuspendRenderSink(void)203 int32_t DirectAudioRenderSink::SuspendRenderSink(void)
204 {
205 return SUCCESS;
206 }
207
RestoreRenderSink(void)208 int32_t DirectAudioRenderSink::RestoreRenderSink(void)
209 {
210 return SUCCESS;
211 }
212
SetAudioParameter(const AudioParamKey key,const std::string & condition,const std::string & value)213 void DirectAudioRenderSink::SetAudioParameter(const AudioParamKey key, const std::string &condition,
214 const std::string &value)
215 {
216 }
217
GetAudioParameter(const AudioParamKey key,const std::string & condition)218 std::string DirectAudioRenderSink::GetAudioParameter(const AudioParamKey key, const std::string &condition)
219 {
220 return "";
221 }
222
SetVolume(float left,float right)223 int32_t DirectAudioRenderSink::SetVolume(float left, float right)
224 {
225 return SUCCESS;
226 }
227
GetVolume(float & left,float & right)228 int32_t DirectAudioRenderSink::GetVolume(float &left, float &right)
229 {
230 left = leftVolume_;
231 right = rightVolume_;
232 return SUCCESS;
233 }
234
GetLatency(uint32_t & latency)235 int32_t DirectAudioRenderSink::GetLatency(uint32_t &latency)
236 {
237 AUDIO_INFO_LOG("not support");
238 return ERR_NOT_SUPPORTED;
239 }
240
GetTransactionId(uint64_t & transactionId)241 int32_t DirectAudioRenderSink::GetTransactionId(uint64_t &transactionId)
242 {
243 CHECK_AND_RETURN_RET_LOG(audioRender_ != nullptr, ERR_INVALID_HANDLE, "render is nullptr");
244 transactionId = reinterpret_cast<uint64_t>(audioRender_);
245 return SUCCESS;
246 }
247
GetPresentationPosition(uint64_t & frames,int64_t & timeSec,int64_t & timeNanoSec)248 int32_t DirectAudioRenderSink::GetPresentationPosition(uint64_t &frames, int64_t &timeSec, int64_t &timeNanoSec)
249 {
250 CHECK_AND_RETURN_RET_LOG(audioRender_ != nullptr, ERR_INVALID_HANDLE, "render is nullptr");
251
252 struct AudioTimeStamp stamp = {};
253 int32_t ret = audioRender_->GetRenderPosition(audioRender_, &frames, &stamp);
254 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_OPERATION_FAILED, "get render position fail, ret: %{public}d", ret);
255 int64_t maxSec = 9223372036; // (9223372036 + 1) * 10^9 > INT64_MAX, seconds should not bigger than it
256 CHECK_AND_RETURN_RET_LOG(stamp.tvSec >= 0 && stamp.tvSec <= maxSec && stamp.tvNSec >= 0 &&
257 stamp.tvNSec <= SECOND_TO_NANOSECOND, ERR_OPERATION_FAILED,
258 "get invalid time, second: %{public}" PRId64 ", nanosecond: %{public}" PRId64, stamp.tvSec, stamp.tvNSec);
259 timeSec = stamp.tvSec;
260 timeNanoSec = stamp.tvNSec;
261 return ret;
262 }
263
GetMaxAmplitude(void)264 float DirectAudioRenderSink::GetMaxAmplitude(void)
265 {
266 return 0.0f;
267 }
268
SetAudioMonoState(bool audioMono)269 void DirectAudioRenderSink::SetAudioMonoState(bool audioMono)
270 {
271 }
272
SetAudioBalanceValue(float audioBalance)273 void DirectAudioRenderSink::SetAudioBalanceValue(float audioBalance)
274 {
275 // reset the balance coefficient value firstly
276 leftBalanceCoef_ = 1.0f;
277 rightBalanceCoef_ = 1.0f;
278
279 if (std::abs(audioBalance - 0.0f) <= std::numeric_limits<float>::epsilon()) {
280 // audioBalance is equal to 0.0f
281 audioBalanceState_ = false;
282 } else {
283 // audioBalance is not equal to 0.0f
284 audioBalanceState_ = true;
285 // calculate the balance coefficient
286 if (audioBalance > 0.0f) {
287 leftBalanceCoef_ -= audioBalance;
288 } else if (audioBalance < 0.0f) {
289 rightBalanceCoef_ += audioBalance;
290 }
291 }
292 }
293
SetSinkMuteForSwitchDevice(bool mute)294 int32_t DirectAudioRenderSink::SetSinkMuteForSwitchDevice(bool mute)
295 {
296 AUDIO_INFO_LOG("not support");
297 return ERR_NOT_SUPPORTED;
298 }
299
SetAudioScene(AudioScene audioScene,bool scoExcludeFlag)300 int32_t DirectAudioRenderSink::SetAudioScene(AudioScene audioScene, bool scoExcludeFlag)
301 {
302 AUDIO_INFO_LOG("not support");
303 return ERR_NOT_SUPPORTED;
304 }
305
GetAudioScene(void)306 int32_t DirectAudioRenderSink::GetAudioScene(void)
307 {
308 AUDIO_INFO_LOG("not support");
309 return ERR_NOT_SUPPORTED;
310 }
311
UpdateActiveDevice(std::vector<DeviceType> & outputDevices)312 int32_t DirectAudioRenderSink::UpdateActiveDevice(std::vector<DeviceType> &outputDevices)
313 {
314 AUDIO_INFO_LOG("not support");
315 return ERR_NOT_SUPPORTED;
316 }
317
RegistCallback(uint32_t type,IAudioSinkCallback * callback)318 void DirectAudioRenderSink::RegistCallback(uint32_t type, IAudioSinkCallback *callback)
319 {
320 std::lock_guard<std::mutex> lock(sinkMutex_);
321 callback_.RegistCallback(type, callback);
322 AUDIO_INFO_LOG("regist succ");
323 }
324
ResetActiveDeviceForDisconnect(DeviceType device)325 void DirectAudioRenderSink::ResetActiveDeviceForDisconnect(DeviceType device)
326 {
327 }
328
SetPaPower(int32_t flag)329 int32_t DirectAudioRenderSink::SetPaPower(int32_t flag)
330 {
331 AUDIO_INFO_LOG("not support");
332 return ERR_NOT_SUPPORTED;
333 }
334
SetPriPaPower(void)335 int32_t DirectAudioRenderSink::SetPriPaPower(void)
336 {
337 AUDIO_INFO_LOG("not support");
338 return ERR_NOT_SUPPORTED;
339 }
340
UpdateAppsUid(const int32_t appsUid[MAX_MIX_CHANNELS],const size_t size)341 int32_t DirectAudioRenderSink::UpdateAppsUid(const int32_t appsUid[MAX_MIX_CHANNELS], const size_t size)
342 {
343 #ifdef FEATURE_POWER_MANAGER
344 CHECK_AND_RETURN_RET_LOG(runningLock_, ERR_INVALID_HANDLE, "running lock is nullptr");
345 runningLock_->UpdateAppsUid(appsUid, appsUid + size);
346 #endif
347 return SUCCESS;
348 }
349
UpdateAppsUid(const std::vector<int32_t> & appsUid)350 int32_t DirectAudioRenderSink::UpdateAppsUid(const std::vector<int32_t> &appsUid)
351 {
352 #ifdef FEATURE_POWER_MANAGER
353 CHECK_AND_RETURN_RET_LOG(runningLock_, ERR_INVALID_HANDLE, "running lock is nullptr");
354 runningLock_->UpdateAppsUid(appsUid.cbegin(), appsUid.cend());
355 runningLock_->UpdateAppsUidToPowerMgr();
356 #endif
357 return SUCCESS;
358 }
359
RegistDirectHdiCallback(std::function<void (const RenderCallbackType type)> callback)360 int32_t DirectAudioRenderSink::RegistDirectHdiCallback(std::function<void(const RenderCallbackType type)> callback)
361 {
362 AUDIO_INFO_LOG("in");
363 int32_t ret = SUCCESS;
364 hdiCallback_ = {
365 .callback_.RenderCallback = &DirectAudioRenderSink::DirectRenderCallback,
366 .serviceCallback_ = callback,
367 .sink_ = this,
368 };
369 if (!testFlag_) {
370 ret = audioRender_->RegCallback(audioRender_, &hdiCallback_.callback_, (int8_t)0);
371 if (ret != SUCCESS) {
372 AUDIO_ERR_LOG("fail, error code: %{public}d", ret);
373 }
374 }
375 return ret;
376 }
377
DumpInfo(std::string & dumpString)378 void DirectAudioRenderSink::DumpInfo(std::string &dumpString)
379 {
380 dumpString += "type: directSink\tstarted: " + std::string(started_ ? "true" : "false") + "\n";
381 }
382
SetDmDeviceType(uint16_t dmDeviceType,DeviceType deviceType)383 void DirectAudioRenderSink::SetDmDeviceType(uint16_t dmDeviceType, DeviceType deviceType)
384 {
385 AUDIO_INFO_LOG("not support");
386 }
387
DirectRenderCallback(struct IAudioCallback * self,enum AudioCallbackType type,int8_t * reserved,int8_t * cookie)388 int32_t DirectAudioRenderSink::DirectRenderCallback(struct IAudioCallback *self, enum AudioCallbackType type,
389 int8_t *reserved, int8_t *cookie)
390 {
391 (void)reserved;
392 (void)cookie;
393 auto *impl = reinterpret_cast<struct DirectHdiCallback *>(self);
394 CHECK_AND_RETURN_RET_LOG(impl != nullptr, ERR_OPERATION_FAILED, "impl is nullptr");
395 auto *sink = reinterpret_cast<DirectAudioRenderSink *>(impl->sink_);
396 CHECK_AND_RETURN_RET_LOG(sink != nullptr, ERR_OPERATION_FAILED, "sink is nullptr");
397 if (!sink->started_) {
398 AUDIO_DEBUG_LOG("invalid call, started: %{public}d", sink->started_);
399 return SUCCESS;
400 }
401
402 impl->serviceCallback_(static_cast<RenderCallbackType>(type));
403 return SUCCESS;
404 }
405
InitAudioSampleAttr(struct AudioSampleAttributes & param)406 void DirectAudioRenderSink::InitAudioSampleAttr(struct AudioSampleAttributes ¶m)
407 {
408 param.channelCount = attr_.channel;
409 param.sampleRate = AUDIO_SAMPLE_RATE_48K;
410 param.interleaved = true;
411 param.streamId = static_cast<int32_t>(GenerateUniqueID(AUDIO_HDI_RENDER_ID_BASE, HDI_RENDER_OFFSET_EAC3));
412 param.type = AUDIO_DIRECT;
413 param.period = DEEP_BUFFER_RENDER_PERIOD_SIZE;
414 param.isBigEndian = false;
415 param.isSignedData = true;
416 param.stopThreshold = INT_MAX;
417 param.silenceThreshold = 0;
418 param.sampleRate = attr_.sampleRate;
419 param.channelLayout = attr_.channelLayout;
420 }
421
InitDeviceDesc(struct AudioDeviceDescriptor & deviceDesc)422 void DirectAudioRenderSink::InitDeviceDesc(struct AudioDeviceDescriptor &deviceDesc)
423 {
424 deviceDesc.pins = PIN_OUT_SPEAKER;
425 deviceDesc.desc = const_cast<char *>("");
426 }
427
CreateRender(void)428 int32_t DirectAudioRenderSink::CreateRender(void)
429 {
430 Trace trace("DirectAudioRenderSink::CreateRender");
431
432 struct AudioSampleAttributes param;
433 struct AudioDeviceDescriptor deviceDesc;
434 InitAudioSampleAttr(param);
435 InitDeviceDesc(deviceDesc);
436
437 AUDIO_INFO_LOG("create render, rate: %{public}u, channel: %{public}u, format: %{public}u", param.sampleRate,
438 param.channelCount, param.format);
439 AudioXCollie audioXCollie("DirectAudioRenderSink::CreateRender", TIMEOUT_SECONDS_10,
440 nullptr, nullptr, AUDIO_XCOLLIE_FLAG_LOG | AUDIO_XCOLLIE_FLAG_RECOVERY);
441 HdiAdapterManager &manager = HdiAdapterManager::GetInstance();
442 std::shared_ptr<IDeviceManager> deviceManager = manager.GetDeviceManager(HDI_DEVICE_MANAGER_TYPE_LOCAL);
443 CHECK_AND_RETURN_RET(deviceManager != nullptr, ERR_INVALID_HANDLE);
444 void *render = deviceManager->CreateRender(attr_.adapterName, ¶m, &deviceDesc, hdiRenderId_);
445 audioRender_ = static_cast<struct IAudioRender *>(render);
446 CHECK_AND_RETURN_RET(audioRender_ != nullptr, ERR_NOT_STARTED);
447
448 return SUCCESS;
449 }
450 } // namespace AudioStandard
451 } // namespace OHOS
452