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 "RendererInServer"
17 #endif
18
19 #include "renderer_in_server.h"
20 #include <cinttypes>
21 #include "securec.h"
22 #include "audio_errors.h"
23 #include "audio_renderer_log.h"
24 #include "audio_utils.h"
25 #include "audio_service.h"
26 #include "futex_tool.h"
27 #include "i_stream_manager.h"
28 #include "volume_tools.h"
29 #include "policy_handler.h"
30 #ifdef RESSCHE_ENABLE
31 #include "res_type.h"
32 #include "res_sched_client.h"
33 #endif
34 #include "media_monitor_manager.h"
35 #include "audio_volume.h"
36
37 namespace OHOS {
38 namespace AudioStandard {
39 namespace {
40 static constexpr int32_t VOLUME_SHIFT_NUMBER = 16; // 1 >> 16 = 65536, max volume
41 static const int64_t MOCK_LATENCY = 45000000; // 45000000 -> 45ms
42 static const int64_t START_MIN_COST = 80000000; // 80000000 -> 80ms
43 const float AUDIO_VOLOMUE_EPSILON = 0.0001;
44 const int32_t MEDIA_UID = 1013;
45 static constexpr int32_t ONE_MINUTE = 60;
46 static const int32_t NO_FADING = 0;
47 static const int32_t DO_FADINGOUT = 1;
48 static const int32_t FADING_OUT_DONE = 2;
49 static const float FADINGOUT_BEGIN = 1.0f;
50 static const float FADINGOUT_END = 0.0f;
51 const int32_t OFFLOAD_INNER_CAP_PREBUF = 3;
52 constexpr int32_t RELEASE_TIMEOUT_IN_SEC = 10; // 10S
53 const int32_t XCOLLIE_FLAG_DEFAULT = (1 | 2); // dump stack and kill self
54 }
55
RendererInServer(AudioProcessConfig processConfig,std::weak_ptr<IStreamListener> streamListener)56 RendererInServer::RendererInServer(AudioProcessConfig processConfig, std::weak_ptr<IStreamListener> streamListener)
57 : processConfig_(processConfig)
58 {
59 streamListener_ = streamListener;
60 managerType_ = PLAYBACK;
61 if (processConfig_.callerUid == MEDIA_UID) {
62 isNeedFade_ = true;
63 oldAppliedVolume_ = MIN_FLOAT_VOLUME;
64 }
65 }
66
~RendererInServer()67 RendererInServer::~RendererInServer()
68 {
69 if (status_ != I_STATUS_RELEASED) {
70 Release();
71 }
72 DumpFileUtil::CloseDumpFile(&dumpC2S_);
73 }
74
ConfigServerBuffer()75 int32_t RendererInServer::ConfigServerBuffer()
76 {
77 if (audioServerBuffer_ != nullptr) {
78 AUDIO_INFO_LOG("ConfigProcessBuffer: process buffer already configed!");
79 return SUCCESS;
80 }
81 stream_->GetSpanSizePerFrame(spanSizeInFrame_);
82 totalSizeInFrame_ = spanSizeInFrame_ * 4; // 4 frames
83 stream_->GetByteSizePerFrame(byteSizePerFrame_);
84 if (totalSizeInFrame_ == 0 || spanSizeInFrame_ == 0 || totalSizeInFrame_ % spanSizeInFrame_ != 0) {
85 AUDIO_ERR_LOG("ConfigProcessBuffer: ERR_INVALID_PARAM");
86 return ERR_INVALID_PARAM;
87 }
88
89 spanSizeInByte_ = spanSizeInFrame_ * byteSizePerFrame_;
90 CHECK_AND_RETURN_RET_LOG(spanSizeInByte_ != 0, ERR_OPERATION_FAILED, "Config oh audio buffer failed");
91 AUDIO_INFO_LOG("totalSizeInFrame_: %{public}zu, spanSizeInFrame_: %{public}zu, byteSizePerFrame_:%{public}zu "
92 "spanSizeInByte_: %{public}zu,", totalSizeInFrame_, spanSizeInFrame_, byteSizePerFrame_, spanSizeInByte_);
93
94 // create OHAudioBuffer in server
95 audioServerBuffer_ = OHAudioBuffer::CreateFromLocal(totalSizeInFrame_, spanSizeInFrame_, byteSizePerFrame_);
96 CHECK_AND_RETURN_RET_LOG(audioServerBuffer_ != nullptr, ERR_OPERATION_FAILED, "Create oh audio buffer failed");
97
98 // we need to clear data buffer to avoid dirty data.
99 memset_s(audioServerBuffer_->GetDataBase(), audioServerBuffer_->GetDataSize(), 0,
100 audioServerBuffer_->GetDataSize());
101 int32_t ret = InitBufferStatus();
102 AUDIO_DEBUG_LOG("Clear data buffer, ret:%{public}d", ret);
103
104 isBufferConfiged_ = true;
105 isInited_ = true;
106 return SUCCESS;
107 }
108
InitBufferStatus()109 int32_t RendererInServer::InitBufferStatus()
110 {
111 if (audioServerBuffer_ == nullptr) {
112 AUDIO_ERR_LOG("InitBufferStatus failed, null buffer.");
113 return ERR_ILLEGAL_STATE;
114 }
115
116 uint32_t spanCount = audioServerBuffer_->GetSpanCount();
117 AUDIO_INFO_LOG("InitBufferStatus: spanCount %{public}u", spanCount);
118 for (uint32_t i = 0; i < spanCount; i++) {
119 SpanInfo *spanInfo = audioServerBuffer_->GetSpanInfoByIndex(i);
120 if (spanInfo == nullptr) {
121 AUDIO_ERR_LOG("InitBufferStatus failed, null spaninfo");
122 return ERR_ILLEGAL_STATE;
123 }
124 spanInfo->spanStatus = SPAN_READ_DONE;
125 spanInfo->offsetInFrame = 0;
126
127 spanInfo->readStartTime = 0;
128 spanInfo->readDoneTime = 0;
129
130 spanInfo->writeStartTime = 0;
131 spanInfo->writeDoneTime = 0;
132
133 spanInfo->volumeStart = 1 << VOLUME_SHIFT_NUMBER; // 65536 for initialize
134 spanInfo->volumeEnd = 1 << VOLUME_SHIFT_NUMBER; // 65536 for initialize
135 spanInfo->isMute = false;
136 }
137 return SUCCESS;
138 }
139
Init()140 int32_t RendererInServer::Init()
141 {
142 if (IsHightResolution()) {
143 managerType_ = DIRECT_PLAYBACK;
144 AUDIO_INFO_LOG("current stream marked as high resolution");
145 }
146
147 if (processConfig_.rendererInfo.rendererFlags == AUDIO_FLAG_VOIP_DIRECT) {
148 if (IStreamManager::GetPlaybackManager(VOIP_PLAYBACK).GetStreamCount() <= 0) {
149 AUDIO_INFO_LOG("current stream marked as VoIP direct stream");
150 managerType_ = VOIP_PLAYBACK;
151 } else {
152 AUDIO_WARNING_LOG("One VoIP direct stream has been created! Use normal mode.");
153 }
154 }
155
156 int32_t ret = IStreamManager::GetPlaybackManager(managerType_).CreateRender(processConfig_, stream_);
157 if (ret != SUCCESS && (managerType_ == DIRECT_PLAYBACK || managerType_ == VOIP_PLAYBACK)) {
158 Trace trace("high resolution create failed use normal replace");
159 managerType_ = PLAYBACK;
160 ret = IStreamManager::GetPlaybackManager(managerType_).CreateRender(processConfig_, stream_);
161 AUDIO_INFO_LOG("high resolution create failed use normal replace");
162 }
163 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS && stream_ != nullptr, ERR_OPERATION_FAILED,
164 "Construct rendererInServer failed: %{public}d", ret);
165 streamIndex_ = stream_->GetStreamIndex();
166 AudioVolume::GetInstance()->AddStreamVolume(streamIndex_, processConfig_.streamType,
167 processConfig_.rendererInfo.streamUsage, processConfig_.appInfo.appUid, processConfig_.appInfo.appPid);
168 traceTag_ = "[" + std::to_string(streamIndex_) + "]RendererInServer"; // [100001]RendererInServer:
169 ret = ConfigServerBuffer();
170 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_OPERATION_FAILED,
171 "Construct rendererInServer failed: %{public}d", ret);
172 stream_->RegisterStatusCallback(shared_from_this());
173 stream_->RegisterWriteCallback(shared_from_this());
174
175 // eg: /data/data/.pulse_dir/10000_100001_48000_2_1_server_in.pcm
176 AudioStreamInfo tempInfo = processConfig_.streamInfo;
177 dumpFileName_ = std::to_string(processConfig_.appInfo.appPid) + "_" + std::to_string(streamIndex_)
178 + "_renderer_server_in_" + std::to_string(tempInfo.samplingRate) + "_"
179 + std::to_string(tempInfo.channels) + "_" + std::to_string(tempInfo.format) + ".pcm";
180 DumpFileUtil::OpenDumpFile(DUMP_SERVER_PARA, dumpFileName_, &dumpC2S_);
181
182 return SUCCESS;
183 }
184
WriterRenderStreamStandbySysEvent()185 void RendererInServer::WriterRenderStreamStandbySysEvent()
186 {
187 std::shared_ptr<Media::MediaMonitor::EventBean> bean = std::make_shared<Media::MediaMonitor::EventBean>(
188 Media::MediaMonitor::AUDIO, Media::MediaMonitor::STREAM_STANDBY,
189 Media::MediaMonitor::BEHAVIOR_EVENT);
190 bean->Add("STREAMID", static_cast<int32_t>(streamIndex_));
191 bean->Add("STANDBY", standByEnable_ ? 1 : 0);
192 Media::MediaMonitor::MediaMonitorManager::GetInstance().WriteLogMsg(bean);
193 }
194
OnStatusUpdate(IOperation operation)195 void RendererInServer::OnStatusUpdate(IOperation operation)
196 {
197 AUDIO_INFO_LOG("%{public}u recv operation:%{public}d standByEnable_:%{public}s", streamIndex_, operation,
198 (standByEnable_ ? "true" : "false"));
199 Trace trace(traceTag_ + " OnStatusUpdate:" + std::to_string(operation));
200 CHECK_AND_RETURN_LOG(operation != OPERATION_RELEASED, "Stream already released");
201 std::shared_ptr<IStreamListener> stateListener = streamListener_.lock();
202 CHECK_AND_RETURN_LOG(stateListener != nullptr, "StreamListener is nullptr");
203 CHECK_AND_RETURN_LOG(audioServerBuffer_->GetStreamStatus() != nullptr,
204 "stream status is nullptr");
205 switch (operation) {
206 case OPERATION_STARTED:
207 if (standByEnable_) {
208 standByEnable_ = false;
209 AUDIO_INFO_LOG("%{public}u recv stand-by started", streamIndex_);
210 audioServerBuffer_->GetStreamStatus()->store(STREAM_RUNNING);
211 FutexTool::FutexWake(audioServerBuffer_->GetFutex());
212 WriterRenderStreamStandbySysEvent();
213 }
214 status_ = I_STATUS_STARTED;
215 startedTime_ = ClockTime::GetCurNano();
216 stateListener->OnOperationHandled(START_STREAM, 0);
217 break;
218 case OPERATION_PAUSED:
219 if (standByEnable_) {
220 AUDIO_INFO_LOG("%{public}u recv stand-by paused", streamIndex_);
221 audioServerBuffer_->GetStreamStatus()->store(STREAM_STAND_BY);
222 WriterRenderStreamStandbySysEvent();
223 return;
224 }
225 status_ = I_STATUS_PAUSED;
226 stateListener->OnOperationHandled(PAUSE_STREAM, 0);
227 break;
228 case OPERATION_STOPPED:
229 status_ = I_STATUS_STOPPED;
230 stateListener->OnOperationHandled(STOP_STREAM, 0);
231 break;
232 case OPERATION_FLUSHED:
233 HandleOperationFlushed();
234 stateListener->OnOperationHandled(FLUSH_STREAM, 0);
235 break;
236 case OPERATION_DRAINED:
237 // Client's StopAudioStream will call Drain first and then Stop. If server's drain times out,
238 // Stop will be completed first. After a period of time, when Drain's callback goes here,
239 // state of server should not be changed to STARTED while the client state is Stopped.
240 OnStatusUpdateExt(operation, stateListener);
241 break;
242 default:
243 OnStatusUpdateSub(operation);
244 }
245 }
246
OnStatusUpdateExt(IOperation operation,std::shared_ptr<IStreamListener> stateListener)247 void RendererInServer::OnStatusUpdateExt(IOperation operation, std::shared_ptr<IStreamListener> stateListener)
248 {
249 if (status_ == I_STATUS_DRAINING) {
250 status_ = I_STATUS_STARTED;
251 stateListener->OnOperationHandled(DRAIN_STREAM, 0);
252 }
253 afterDrain = true;
254 }
255
OnStatusUpdateSub(IOperation operation)256 void RendererInServer::OnStatusUpdateSub(IOperation operation)
257 {
258 std::shared_ptr<IStreamListener> stateListener = streamListener_.lock();
259 switch (operation) {
260 case OPERATION_RELEASED:
261 stateListener->OnOperationHandled(RELEASE_STREAM, 0);
262 status_ = I_STATUS_RELEASED;
263 break;
264 case OPERATION_UNDERRUN:
265 AUDIO_INFO_LOG("Underrun: audioServerBuffer_->GetAvailableDataFrames(): %{public}d",
266 audioServerBuffer_->GetAvailableDataFrames());
267 // In plan, maxlength is 4
268 if (audioServerBuffer_->GetAvailableDataFrames() == static_cast<int32_t>(4 * spanSizeInFrame_)) {
269 AUDIO_INFO_LOG("Buffer is empty");
270 needForceWrite_ = 0;
271 } else {
272 AUDIO_INFO_LOG("Buffer is not empty");
273 WriteData();
274 }
275 break;
276 case OPERATION_UNDERFLOW:
277 if (ClockTime::GetCurNano() - startedTime_ > START_MIN_COST) {
278 underrunCount_++;
279 audioServerBuffer_->SetUnderrunCount(underrunCount_);
280 }
281 StandByCheck(); // if stand by is enbaled here, stream will be paused and not recv UNDERFLOW any more.
282 break;
283 case OPERATION_SET_OFFLOAD_ENABLE:
284 case OPERATION_UNSET_OFFLOAD_ENABLE:
285 offloadEnable_ = operation == OPERATION_SET_OFFLOAD_ENABLE ? true : false;
286 stateListener->OnOperationHandled(SET_OFFLOAD_ENABLE, operation == OPERATION_SET_OFFLOAD_ENABLE ? 1 : 0);
287 break;
288 default:
289 AUDIO_INFO_LOG("Invalid operation %{public}u", operation);
290 status_ = I_STATUS_INVALID;
291 }
292 }
293
StandByCheck()294 void RendererInServer::StandByCheck()
295 {
296 Trace trace(traceTag_ + " StandByCheck:standByCounter_:" + std::to_string(standByCounter_.load()));
297 AUDIO_INFO_LOG("sessionId:%{public}u standByCounter_:%{public}u standByEnable_:%{public}s ", streamIndex_,
298 standByCounter_.load(), (standByEnable_ ? "true" : "false"));
299
300 // direct standBy need not in here
301 if (managerType_ == DIRECT_PLAYBACK || managerType_ == VOIP_PLAYBACK) {
302 return;
303 }
304
305 if (standByEnable_) {
306 return;
307 }
308 standByCounter_++;
309 if (!ShouldEnableStandBy()) {
310 return;
311 }
312
313 // call enable stand by
314 standByEnable_ = true;
315 // PaAdapterManager::PauseRender will hold mutex, may cause dead lock with pa_lock
316 if (managerType_ == PLAYBACK) {
317 stream_->Pause(true);
318 }
319 }
320
ShouldEnableStandBy()321 bool RendererInServer::ShouldEnableStandBy()
322 {
323 int64_t timeCost = ClockTime::GetCurNano() - lastWriteTime_;
324
325 uint32_t maxStandByCounter = 50; // for 20ms, 50 * 20 = 1000ms
326 int64_t timeLimit = 1000000000; // 1s
327 if (offloadEnable_) {
328 maxStandByCounter = 400; // for 20ms, 50 * 400 = 8000ms
329 timeLimit = 8 * AUDIO_NS_PER_SECOND; // for 20ms 8s
330 }
331 if (standByCounter_ >= maxStandByCounter && timeCost >= timeLimit) {
332 AUDIO_INFO_LOG("sessionId:%{public}u reach the limit of stand by: %{public}u time:%{public}" PRId64"ns",
333 streamIndex_, standByCounter_.load(), timeCost);
334 return true;
335 }
336 return false;
337 }
338
HandleOperationFlushed()339 void RendererInServer::HandleOperationFlushed()
340 {
341 switch (status_) {
342 case I_STATUS_FLUSHING_WHEN_STARTED:
343 status_ = I_STATUS_STARTED;
344 break;
345 case I_STATUS_FLUSHING_WHEN_PAUSED:
346 status_ = I_STATUS_PAUSED;
347 break;
348 case I_STATUS_FLUSHING_WHEN_STOPPED:
349 status_ = I_STATUS_STOPPED;
350 break;
351 default:
352 AUDIO_WARNING_LOG("Invalid status before flusing");
353 }
354 }
355
DequeueBuffer(size_t length)356 BufferDesc RendererInServer::DequeueBuffer(size_t length)
357 {
358 return stream_->DequeueBuffer(length);
359 }
360
VolumeHandle(BufferDesc & desc)361 void RendererInServer::VolumeHandle(BufferDesc &desc)
362 {
363 // volume process in server
364 if (audioServerBuffer_ == nullptr) {
365 AUDIO_WARNING_LOG("buffer in not inited");
366 return;
367 }
368 float applyVolume = 0.0f;
369 if (muteFlag_) {
370 applyVolume = 0.0f;
371 } else {
372 applyVolume = audioServerBuffer_->GetStreamVolume();
373 }
374 float duckVolume_ = audioServerBuffer_->GetDuckFactor();
375 if (!IsVolumeSame(MAX_FLOAT_VOLUME, lowPowerVolume_, AUDIO_VOLOMUE_EPSILON)) {
376 applyVolume *= lowPowerVolume_;
377 }
378 if (!IsVolumeSame(MAX_FLOAT_VOLUME, duckVolume_, AUDIO_VOLOMUE_EPSILON)) {
379 applyVolume *= duckVolume_;
380 }
381
382 if (silentModeAndMixWithOthers_) {
383 applyVolume = 0.0f;
384 }
385
386 //in plan: put system volume handle here
387 if (!IsVolumeSame(MAX_FLOAT_VOLUME, applyVolume, AUDIO_VOLOMUE_EPSILON) ||
388 !IsVolumeSame(oldAppliedVolume_, applyVolume, AUDIO_VOLOMUE_EPSILON)) {
389 Trace traceVol("RendererInServer::VolumeTools::Process " + std::to_string(oldAppliedVolume_) + "~" +
390 std::to_string(applyVolume));
391 AudioChannel channel = processConfig_.streamInfo.channels;
392 ChannelVolumes mapVols = VolumeTools::GetChannelVolumes(channel, oldAppliedVolume_, applyVolume);
393 int32_t volRet = VolumeTools::Process(desc, processConfig_.streamInfo.format, mapVols);
394 oldAppliedVolume_ = applyVolume;
395 if (volRet != SUCCESS) {
396 AUDIO_WARNING_LOG("VolumeTools::Process error: %{public}d", volRet);
397 }
398 }
399 }
400
WriteMuteDataSysEvent(uint8_t * buffer,size_t bufferSize)401 void RendererInServer::WriteMuteDataSysEvent(uint8_t *buffer, size_t bufferSize)
402 {
403 if (silentModeAndMixWithOthers_) {
404 return;
405 }
406 if (buffer[0] == 0) {
407 if (startMuteTime_ == 0) {
408 startMuteTime_ = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
409 }
410 std::time_t currentTime = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
411 if ((currentTime - startMuteTime_ >= ONE_MINUTE) && silentState_ == 1) { // 1 means unsilent
412 silentState_ = 0; // 0 means silent
413 AUDIO_WARNING_LOG("write invalid data for some time in server");
414 ReportDataToResSched(true);
415 }
416 } else {
417 if (startMuteTime_ != 0) {
418 startMuteTime_ = 0;
419 }
420 if (silentState_ == 0) { // 0 means silent
421 AUDIO_WARNING_LOG("begin write valid data in server");
422 silentState_ = 1; // 1 means unsilent
423 ReportDataToResSched(false);
424 }
425 }
426 }
427
ReportDataToResSched(bool isSilent)428 void RendererInServer::ReportDataToResSched(bool isSilent)
429 {
430 #ifdef RESSCHE_ENABLE
431 std::unordered_map<std::string, std::string> payload;
432 payload["uid"] = std::to_string(processConfig_.appInfo.appUid);
433 payload["sessionId"] = std::to_string(streamIndex_);
434 payload["isSilent"] = std::to_string(isSilent);
435 uint32_t type = ResourceSchedule::ResType::RES_TYPE_AUDIO_RENDERER_SILENT_PLAYBACK;
436 ResourceSchedule::ResSchedClient::GetInstance().ReportData(type, 0, payload);
437 #endif
438 }
439
DoFadingOut(BufferDesc & bufferDesc)440 void RendererInServer::DoFadingOut(BufferDesc& bufferDesc)
441 {
442 std::lock_guard<std::mutex> lock(fadeoutLock_);
443 if (fadeoutFlag_ == DO_FADINGOUT) {
444 AUDIO_INFO_LOG("enter. format:%{public}u", processConfig_.streamInfo.format);
445 AudioChannel channel = processConfig_.streamInfo.channels;
446 ChannelVolumes mapVols = VolumeTools::GetChannelVolumes(channel, FADINGOUT_BEGIN, FADINGOUT_END);
447 int32_t ret = VolumeTools::Process(bufferDesc, processConfig_.streamInfo.format, mapVols);
448 if (ret != SUCCESS) {
449 AUDIO_WARNING_LOG("VolumeTools::Process failed: %{public}d", ret);
450 }
451 fadeoutFlag_ = FADING_OUT_DONE;
452 AUDIO_INFO_LOG("fadeoutFlag_ = FADING_OUT_DONE");
453 }
454 }
455
WriteData()456 int32_t RendererInServer::WriteData()
457 {
458 uint64_t currentReadFrame = audioServerBuffer_->GetCurReadFrame();
459 uint64_t currentWriteFrame = audioServerBuffer_->GetCurWriteFrame();
460 Trace trace1(traceTag_ + " WriteData"); // RendererInServer::sessionid:100001 WriteData
461 if (currentReadFrame + spanSizeInFrame_ > currentWriteFrame) {
462 Trace trace2(traceTag_ + " near underrun"); // RendererInServer::sessionid:100001 near underrun
463 if (!offloadEnable_) {
464 CHECK_AND_RETURN_RET_LOG(currentWriteFrame >= currentReadFrame, ERR_OPERATION_FAILED,
465 "invalid write and read position.");
466 uint64_t dataSize = currentWriteFrame - currentReadFrame;
467 AUDIO_INFO_LOG("sessionId: %{public}u OHAudioBuffer %{public}" PRIu64 "size is not enough",
468 streamIndex_, dataSize);
469 }
470 FutexTool::FutexWake(audioServerBuffer_->GetFutex());
471 return ERR_OPERATION_FAILED;
472 }
473
474 BufferDesc bufferDesc = {nullptr, 0, 0}; // will be changed in GetReadbuffer
475 if (audioServerBuffer_->GetReadbuffer(currentReadFrame, bufferDesc) == SUCCESS) {
476 if (bufferDesc.buffer == nullptr) {
477 AUDIO_ERR_LOG("The buffer is null!");
478 return ERR_INVALID_PARAM;
479 }
480 VolumeHandle(bufferDesc);
481 Trace::CountVolume(traceTag_, *bufferDesc.buffer);
482 if (processConfig_.streamType != STREAM_ULTRASONIC) {
483 if (currentReadFrame + spanSizeInFrame_ == currentWriteFrame) {
484 DoFadingOut(bufferDesc);
485 }
486 }
487 stream_->EnqueueBuffer(bufferDesc);
488 DumpFileUtil::WriteDumpFile(dumpC2S_, static_cast<void *>(bufferDesc.buffer), bufferDesc.bufLength);
489 if (AudioDump::GetInstance().GetVersionType() == BETA_VERSION) {
490 Media::MediaMonitor::MediaMonitorManager::GetInstance().WriteAudioBuffer(dumpFileName_,
491 static_cast<void *>(bufferDesc.buffer), bufferDesc.bufLength);
492 }
493
494 OtherStreamEnqueue(bufferDesc);
495
496 WriteMuteDataSysEvent(bufferDesc.buffer, bufferDesc.bufLength);
497 memset_s(bufferDesc.buffer, bufferDesc.bufLength, 0, bufferDesc.bufLength); // clear is needed for reuse.
498 uint64_t nextReadFrame = currentReadFrame + spanSizeInFrame_;
499 audioServerBuffer_->SetCurReadFrame(nextReadFrame);
500 } else {
501 Trace trace3("RendererInServer::WriteData GetReadbuffer failed");
502 }
503 FutexTool::FutexWake(audioServerBuffer_->GetFutex());
504 standByCounter_ = 0;
505 lastWriteTime_ = ClockTime::GetCurNano();
506 return SUCCESS;
507 }
508
OtherStreamEnqueue(const BufferDesc & bufferDesc)509 void RendererInServer::OtherStreamEnqueue(const BufferDesc &bufferDesc)
510 {
511 // for inner capture
512 if (isInnerCapEnabled_) {
513 Trace traceDup("RendererInServer::WriteData DupSteam write");
514 std::lock_guard<std::mutex> lock(dupMutex_);
515 if (dupStream_ != nullptr) {
516 if (renderEmptyCountForInnerCap_ > 0) {
517 size_t emptyBufferSize = static_cast<size_t>(renderEmptyCountForInnerCap_) * spanSizeInByte_;
518 auto buffer = std::make_unique<uint8_t []>(emptyBufferSize);
519 BufferDesc emptyBufferDesc = {buffer.get(), emptyBufferSize, emptyBufferSize};
520 memset_s(emptyBufferDesc.buffer, emptyBufferDesc.bufLength, 0, emptyBufferDesc.bufLength);
521 dupStream_->EnqueueBuffer(emptyBufferDesc);
522 renderEmptyCountForInnerCap_ = 0;
523 }
524 dupStream_->EnqueueBuffer(bufferDesc); // what if enqueue fail?
525 }
526 }
527 // for dual tone
528 if (isDualToneEnabled_) {
529 Trace traceDup("RendererInServer::WriteData DualToneSteam write");
530 std::lock_guard<std::mutex> lock(dualToneMutex_);
531 if (dualToneStream_ != nullptr) {
532 dualToneStream_->EnqueueBuffer(bufferDesc); // what if enqueue fail?
533 }
534 }
535 }
536
WriteEmptyData()537 void RendererInServer::WriteEmptyData()
538 {
539 Trace trace("RendererInServer::WriteEmptyData");
540 AUDIO_WARNING_LOG("Underrun, write empty data");
541 BufferDesc bufferDesc = stream_->DequeueBuffer(spanSizeInByte_);
542 memset_s(bufferDesc.buffer, bufferDesc.bufLength, 0, bufferDesc.bufLength);
543 stream_->EnqueueBuffer(bufferDesc);
544 return;
545 }
546
OnWriteData(size_t length)547 int32_t RendererInServer::OnWriteData(size_t length)
548 {
549 Trace trace("RendererInServer::OnWriteData length " + std::to_string(length));
550 bool mayNeedForceWrite = false;
551 if (writeLock_.try_lock()) {
552 // length unit is bytes, using spanSizeInByte_
553 for (size_t i = 0; i < length / spanSizeInByte_; i++) {
554 mayNeedForceWrite = WriteData() != SUCCESS || mayNeedForceWrite;
555 }
556 writeLock_.unlock();
557 } else {
558 mayNeedForceWrite = true;
559 }
560
561 size_t maxEmptyCount = 1;
562 size_t writableSize = stream_->GetWritableSize();
563 if (mayNeedForceWrite && writableSize >= spanSizeInByte_ * maxEmptyCount) {
564 AUDIO_DEBUG_LOG("Server need force write to recycle callback");
565 needForceWrite_ =
566 writableSize / spanSizeInByte_ > 3 ? 0 : 3 - writableSize / spanSizeInByte_; // 3 is maxlength - 1
567 }
568
569 uint64_t currentReadFrame = audioServerBuffer_->GetCurReadFrame();
570 audioServerBuffer_->SetHandleInfo(currentReadFrame, ClockTime::GetCurNano() + MOCK_LATENCY);
571
572 if (mayNeedForceWrite) {
573 return ERR_RENDERER_IN_SERVER_UNDERRUN;
574 }
575
576 return SUCCESS;
577 }
578
579 // Call WriteData will hold mainloop lock in EnqueueBuffer, we should not lock a mutex in WriteData while OnWriteData is
580 // called with mainloop locking.
UpdateWriteIndex()581 int32_t RendererInServer::UpdateWriteIndex()
582 {
583 Trace trace("RendererInServer::UpdateWriteIndex");
584 if (managerType_ != PLAYBACK) {
585 IStreamManager::GetPlaybackManager(managerType_).TriggerStartIfNecessary();
586 }
587 if (needForceWrite_ < 3 && stream_->GetWritableSize() >= spanSizeInByte_) { // 3 is maxlength - 1
588 if (writeLock_.try_lock()) {
589 AUDIO_DEBUG_LOG("Start force write data");
590 int32_t ret = WriteData();
591 if (ret == SUCCESS) {
592 needForceWrite_++;
593 }
594 writeLock_.unlock();
595 }
596 }
597
598 if (afterDrain == true) {
599 if (writeLock_.try_lock()) {
600 afterDrain = false;
601 AUDIO_DEBUG_LOG("After drain, start write data");
602 WriteData();
603 writeLock_.unlock();
604 }
605 }
606 return SUCCESS;
607 }
608
ResolveBuffer(std::shared_ptr<OHAudioBuffer> & buffer)609 int32_t RendererInServer::ResolveBuffer(std::shared_ptr<OHAudioBuffer> &buffer)
610 {
611 buffer = audioServerBuffer_;
612 return SUCCESS;
613 }
614
GetSessionId(uint32_t & sessionId)615 int32_t RendererInServer::GetSessionId(uint32_t &sessionId)
616 {
617 CHECK_AND_RETURN_RET_LOG(stream_ != nullptr, ERR_OPERATION_FAILED, "GetSessionId failed, stream_ is null");
618 sessionId = streamIndex_;
619 CHECK_AND_RETURN_RET_LOG(sessionId < INT32_MAX, ERR_OPERATION_FAILED, "GetSessionId failed, sessionId:%{public}d",
620 sessionId);
621
622 return SUCCESS;
623 }
624
Start()625 int32_t RendererInServer::Start()
626 {
627 AUDIO_INFO_LOG("sessionId: %{public}u", streamIndex_);
628 if (standByEnable_) {
629 AUDIO_INFO_LOG("sessionId: %{public}u call to exit stand by!", streamIndex_);
630 CHECK_AND_RETURN_RET_LOG(audioServerBuffer_->GetStreamStatus() != nullptr,
631 ERR_OPERATION_FAILED, "stream status is nullptr");
632 standByCounter_ = 0;
633 startedTime_ = ClockTime::GetCurNano();
634 audioServerBuffer_->GetStreamStatus()->store(STREAM_STARTING);
635 int32_t ret = (managerType_ == DIRECT_PLAYBACK || managerType_ == VOIP_PLAYBACK) ?
636 IStreamManager::GetPlaybackManager(managerType_).StartRender(streamIndex_) : stream_->Start();
637 return ret;
638 }
639 needForceWrite_ = 0;
640 std::unique_lock<std::mutex> lock(statusLock_);
641 if (status_ != I_STATUS_IDLE && status_ != I_STATUS_PAUSED && status_ != I_STATUS_STOPPED) {
642 AUDIO_ERR_LOG("RendererInServer::Start failed, Illegal state: %{public}u", status_);
643 return ERR_ILLEGAL_STATE;
644 }
645 status_ = I_STATUS_STARTING;
646 {
647 std::lock_guard<std::mutex> lock(fadeoutLock_);
648 AUDIO_INFO_LOG("fadeoutFlag_ = NO_FADING");
649 fadeoutFlag_ = NO_FADING;
650 }
651 int32_t ret = (managerType_ == DIRECT_PLAYBACK || managerType_ == VOIP_PLAYBACK) ?
652 IStreamManager::GetPlaybackManager(managerType_).StartRender(streamIndex_) : stream_->Start();
653 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ret, "Start stream failed, reason: %{public}d", ret);
654
655 startedTime_ = ClockTime::GetCurNano();
656 uint64_t currentReadFrame = audioServerBuffer_->GetCurReadFrame();
657 int64_t tempTime = ClockTime::GetCurNano() + MOCK_LATENCY;
658 audioServerBuffer_->SetHandleInfo(currentReadFrame, tempTime);
659 AUDIO_INFO_LOG("Server update position %{public}" PRIu64" time %{public}" PRId64" ", currentReadFrame, tempTime);
660 resetTime_ = true;
661
662 if (isInnerCapEnabled_) {
663 std::lock_guard<std::mutex> lock(dupMutex_);
664 if (dupStream_ != nullptr) {
665 dupStream_->Start();
666 }
667 }
668
669 if (isDualToneEnabled_) {
670 std::lock_guard<std::mutex> lock(dualToneMutex_);
671 if (dualToneStream_ != nullptr) {
672 stream_->GetAudioEffectMode(effectModeWhenDual_);
673 stream_->SetAudioEffectMode(EFFECT_NONE);
674 dualToneStream_->Start();
675 }
676 }
677 return SUCCESS;
678 }
679
Pause()680 int32_t RendererInServer::Pause()
681 {
682 AUDIO_INFO_LOG("Pause.");
683 std::unique_lock<std::mutex> lock(statusLock_);
684 if (status_ != I_STATUS_STARTED) {
685 AUDIO_ERR_LOG("RendererInServer::Pause failed, Illegal state: %{public}u", status_);
686 return ERR_ILLEGAL_STATE;
687 }
688 status_ = I_STATUS_PAUSING;
689 if (standByEnable_) {
690 AUDIO_INFO_LOG("sessionId: %{public}u call Pause while stand by", streamIndex_);
691 CHECK_AND_RETURN_RET_LOG(audioServerBuffer_->GetStreamStatus() != nullptr,
692 ERR_OPERATION_FAILED, "stream status is nullptr");
693 standByEnable_ = false;
694 audioServerBuffer_->GetStreamStatus()->store(STREAM_PAUSED);
695 }
696 standByCounter_ = 0;
697 int32_t ret = (managerType_ == DIRECT_PLAYBACK || managerType_ == VOIP_PLAYBACK) ?
698 IStreamManager::GetPlaybackManager(managerType_).PauseRender(streamIndex_) : stream_->Pause();
699 if (isInnerCapEnabled_) {
700 std::lock_guard<std::mutex> lock(dupMutex_);
701 if (dupStream_ != nullptr) {
702 dupStream_->Pause();
703 }
704 }
705 if (isDualToneEnabled_) {
706 std::lock_guard<std::mutex> lock(dualToneMutex_);
707 if (dualToneStream_ != nullptr) {
708 stream_->SetAudioEffectMode(effectModeWhenDual_);
709 dualToneStream_->Pause();
710 }
711 }
712 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ret, "Pause stream failed, reason: %{public}d", ret);
713
714 return SUCCESS;
715 }
716
Flush()717 int32_t RendererInServer::Flush()
718 {
719 AUDIO_PRERELEASE_LOGI("Flush.");
720 Trace trace(traceTag_ + " Flush");
721 std::unique_lock<std::mutex> lock(statusLock_);
722 if (status_ == I_STATUS_STARTED) {
723 status_ = I_STATUS_FLUSHING_WHEN_STARTED;
724 } else if (status_ == I_STATUS_PAUSED) {
725 status_ = I_STATUS_FLUSHING_WHEN_PAUSED;
726 } else if (status_ == I_STATUS_STOPPED) {
727 status_ = I_STATUS_FLUSHING_WHEN_STOPPED;
728 } else {
729 AUDIO_ERR_LOG("RendererInServer::Flush failed, Illegal state: %{public}u", status_);
730 return ERR_ILLEGAL_STATE;
731 }
732
733 // Flush buffer of audio server
734 uint64_t writeFrame = audioServerBuffer_->GetCurWriteFrame();
735 uint64_t readFrame = audioServerBuffer_->GetCurReadFrame();
736
737 while (readFrame < writeFrame) {
738 BufferDesc bufferDesc = {nullptr, 0, 0};
739 int32_t readResult = audioServerBuffer_->GetReadbuffer(readFrame, bufferDesc);
740 if (readResult != 0) {
741 return ERR_OPERATION_FAILED;
742 }
743 memset_s(bufferDesc.buffer, bufferDesc.bufLength, 0, bufferDesc.bufLength);
744 readFrame += spanSizeInFrame_;
745 AUDIO_INFO_LOG("On flush, read frame: %{public}" PRIu64 ", nextReadFrame: %{public}zu,"
746 "writeFrame: %{public}" PRIu64 "", readFrame, spanSizeInFrame_, writeFrame);
747 audioServerBuffer_->SetCurReadFrame(readFrame);
748 }
749
750 int ret = stream_->Flush();
751 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ret, "Flush stream failed, reason: %{public}d", ret);
752 if (isInnerCapEnabled_) {
753 std::lock_guard<std::mutex> lock(dupMutex_);
754 if (dupStream_ != nullptr) {
755 dupStream_->Flush();
756 }
757 }
758 if (isDualToneEnabled_) {
759 std::lock_guard<std::mutex> lock(dualToneMutex_);
760 if (dualToneStream_ != nullptr) {
761 dualToneStream_->Flush();
762 }
763 }
764 return SUCCESS;
765 }
766
DrainAudioBuffer()767 int32_t RendererInServer::DrainAudioBuffer()
768 {
769 return SUCCESS;
770 }
771
Drain(bool stopFlag)772 int32_t RendererInServer::Drain(bool stopFlag)
773 {
774 {
775 std::unique_lock<std::mutex> lock(statusLock_);
776 if (status_ != I_STATUS_STARTED) {
777 AUDIO_ERR_LOG("RendererInServer::Drain failed, Illegal state: %{public}u", status_);
778 return ERR_ILLEGAL_STATE;
779 }
780 status_ = I_STATUS_DRAINING;
781 }
782 AUDIO_INFO_LOG("Start drain. stopFlag:%{public}d", stopFlag);
783 if (stopFlag) {
784 std::lock_guard<std::mutex> lock(fadeoutLock_);
785 AUDIO_INFO_LOG("fadeoutFlag_ = DO_FADINGOUT");
786 fadeoutFlag_ = DO_FADINGOUT;
787 }
788 DrainAudioBuffer();
789 int ret = stream_->Drain();
790 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ret, "Drain stream failed, reason: %{public}d", ret);
791 if (isInnerCapEnabled_) {
792 std::lock_guard<std::mutex> lock(dupMutex_);
793 if (dupStream_ != nullptr) {
794 dupStream_->Drain();
795 }
796 }
797 if (isDualToneEnabled_) {
798 std::lock_guard<std::mutex> lock(dualToneMutex_);
799 if (dualToneStream_ != nullptr) {
800 dualToneStream_->Drain();
801 }
802 }
803 return SUCCESS;
804 }
805
Stop()806 int32_t RendererInServer::Stop()
807 {
808 AUDIO_INFO_LOG("Stop.");
809 {
810 std::unique_lock<std::mutex> lock(statusLock_);
811 if (status_ != I_STATUS_STARTED && status_ != I_STATUS_PAUSED && status_ != I_STATUS_DRAINING &&
812 status_ != I_STATUS_STARTING) {
813 AUDIO_ERR_LOG("RendererInServer::Stop failed, Illegal state: %{public}u", status_);
814 return ERR_ILLEGAL_STATE;
815 }
816 status_ = I_STATUS_STOPPING;
817 }
818 if (standByEnable_) {
819 AUDIO_INFO_LOG("sessionId: %{public}u call Stop while stand by", streamIndex_);
820 CHECK_AND_RETURN_RET_LOG(audioServerBuffer_->GetStreamStatus() != nullptr,
821 ERR_OPERATION_FAILED, "stream status is nullptr");
822 standByEnable_ = false;
823 audioServerBuffer_->GetStreamStatus()->store(STREAM_STOPPED);
824 }
825 {
826 std::lock_guard<std::mutex> lock(fadeoutLock_);
827 AUDIO_INFO_LOG("fadeoutFlag_ = NO_FADING");
828 fadeoutFlag_ = NO_FADING;
829 }
830 int32_t ret = (managerType_ == DIRECT_PLAYBACK || managerType_ == VOIP_PLAYBACK) ?
831 IStreamManager::GetPlaybackManager(managerType_).StopRender(streamIndex_) : stream_->Stop();
832 if (isInnerCapEnabled_) {
833 std::lock_guard<std::mutex> lock(dupMutex_);
834 if (dupStream_ != nullptr) {
835 dupStream_->Stop();
836 }
837 }
838 if (isDualToneEnabled_) {
839 std::lock_guard<std::mutex> lock(dualToneMutex_);
840 if (dualToneStream_ != nullptr) {
841 stream_->SetAudioEffectMode(effectModeWhenDual_);
842 dualToneStream_->Stop();
843 }
844 }
845 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ret, "Stop stream failed, reason: %{public}d", ret);
846 return SUCCESS;
847 }
848
Release()849 int32_t RendererInServer::Release()
850 {
851 AUDIO_INFO_LOG("Start release");
852 AudioXCollie audioXCollie(
853 "RendererInServer::Release", RELEASE_TIMEOUT_IN_SEC, nullptr, nullptr, XCOLLIE_FLAG_DEFAULT);
854 {
855 std::unique_lock<std::mutex> lock(statusLock_);
856 if (status_ == I_STATUS_RELEASED) {
857 AUDIO_INFO_LOG("Already released");
858 return SUCCESS;
859 }
860 }
861
862 if (processConfig_.audioMode == AUDIO_MODE_PLAYBACK) {
863 AudioService::GetInstance()->SetDecMaxRendererStreamCnt();
864 AudioService::GetInstance()->CleanAppUseNumMap(processConfig_.appInfo.appUid);
865 }
866
867 int32_t ret = IStreamManager::GetPlaybackManager(managerType_).ReleaseRender(streamIndex_);
868 AudioVolume::GetInstance()->RemoveStreamVolume(streamIndex_);
869 AudioService::GetInstance()->RemoveRenderer(streamIndex_);
870 if (ret < 0) {
871 AUDIO_ERR_LOG("Release stream failed, reason: %{public}d", ret);
872 status_ = I_STATUS_INVALID;
873 return ret;
874 }
875 status_ = I_STATUS_RELEASED;
876
877 if (isInnerCapEnabled_) {
878 DisableInnerCap();
879 }
880
881 if (isDualToneEnabled_) {
882 DisableDualTone();
883 }
884
885 return SUCCESS;
886 }
887
GetAudioTime(uint64_t & framePos,uint64_t & timestamp)888 int32_t RendererInServer::GetAudioTime(uint64_t &framePos, uint64_t ×tamp)
889 {
890 if (status_ == I_STATUS_STOPPED) {
891 AUDIO_WARNING_LOG("Current status is stopped");
892 return ERR_ILLEGAL_STATE;
893 }
894 stream_->GetStreamFramesWritten(framePos);
895 stream_->GetCurrentTimeStamp(timestamp);
896 if (resetTime_) {
897 resetTime_ = false;
898 resetTimestamp_ = timestamp;
899 }
900 return SUCCESS;
901 }
902
GetAudioPosition(uint64_t & framePos,uint64_t & timestamp,uint64_t & latency)903 int32_t RendererInServer::GetAudioPosition(uint64_t &framePos, uint64_t ×tamp, uint64_t &latency)
904 {
905 if (status_ == I_STATUS_STOPPED) {
906 AUDIO_PRERELEASE_LOGW("Current status is stopped");
907 return ERR_ILLEGAL_STATE;
908 }
909 stream_->GetCurrentPosition(framePos, timestamp, latency);
910 return SUCCESS;
911 }
912
GetLatency(uint64_t & latency)913 int32_t RendererInServer::GetLatency(uint64_t &latency)
914 {
915 std::unique_lock<std::mutex> lock(statusLock_);
916 return stream_->GetLatency(latency);
917 }
918
SetRate(int32_t rate)919 int32_t RendererInServer::SetRate(int32_t rate)
920 {
921 return stream_->SetRate(rate);
922 }
923
SetLowPowerVolume(float volume)924 int32_t RendererInServer::SetLowPowerVolume(float volume)
925 {
926 if (volume < MIN_FLOAT_VOLUME || volume > MAX_FLOAT_VOLUME) {
927 AUDIO_ERR_LOG("invalid volume:%{public}f", volume);
928 return ERR_INVALID_PARAM;
929 }
930 lowPowerVolume_ = volume;
931 return SUCCESS;
932 }
933
GetLowPowerVolume(float & volume)934 int32_t RendererInServer::GetLowPowerVolume(float &volume)
935 {
936 return stream_->GetLowPowerVolume(volume);
937 }
938
SetAudioEffectMode(int32_t effectMode)939 int32_t RendererInServer::SetAudioEffectMode(int32_t effectMode)
940 {
941 return stream_->SetAudioEffectMode(effectMode);
942 }
943
GetAudioEffectMode(int32_t & effectMode)944 int32_t RendererInServer::GetAudioEffectMode(int32_t &effectMode)
945 {
946 return stream_->GetAudioEffectMode(effectMode);
947 }
948
SetPrivacyType(int32_t privacyType)949 int32_t RendererInServer::SetPrivacyType(int32_t privacyType)
950 {
951 return stream_->SetPrivacyType(privacyType);
952 }
953
GetPrivacyType(int32_t & privacyType)954 int32_t RendererInServer::GetPrivacyType(int32_t &privacyType)
955 {
956 return stream_->GetPrivacyType(privacyType);
957 }
958
EnableInnerCap()959 int32_t RendererInServer::EnableInnerCap()
960 {
961 // in plan
962 if (isInnerCapEnabled_) {
963 AUDIO_INFO_LOG("InnerCap is already enabled");
964 return SUCCESS;
965 }
966 int32_t ret = InitDupStream();
967 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_OPERATION_FAILED, "Init dup stream failed");
968 return SUCCESS;
969 }
970
DisableInnerCap()971 int32_t RendererInServer::DisableInnerCap()
972 {
973 std::lock_guard<std::mutex> lock(dupMutex_);
974 if (!isInnerCapEnabled_) {
975 AUDIO_WARNING_LOG("InnerCap is already disabled.");
976 return ERR_INVALID_OPERATION;
977 }
978 isInnerCapEnabled_ = false;
979 AUDIO_INFO_LOG("Disable dup renderer %{public}u with status: %{public}d", streamIndex_, status_);
980 // in plan: call stop?
981 IStreamManager::GetDupPlaybackManager().ReleaseRender(dupStreamIndex_);
982 AudioVolume::GetInstance()->RemoveStreamVolume(dupStreamIndex_);
983 dupStream_ = nullptr;
984
985 return ERROR;
986 }
987
InitDupStream()988 int32_t RendererInServer::InitDupStream()
989 {
990 std::lock_guard<std::mutex> lock(dupMutex_);
991 int32_t ret = IStreamManager::GetDupPlaybackManager().CreateRender(processConfig_, dupStream_);
992 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS && dupStream_ != nullptr, ERR_OPERATION_FAILED, "Failed: %{public}d", ret);
993 dupStreamIndex_ = dupStream_->GetStreamIndex();
994 AudioVolume::GetInstance()->AddStreamVolume(dupStreamIndex_, processConfig_.streamType,
995 processConfig_.rendererInfo.streamUsage, processConfig_.appInfo.appUid, processConfig_.appInfo.appPid);
996
997 dupStreamCallback_ = std::make_shared<StreamCallbacks>(dupStreamIndex_);
998 dupStream_->RegisterStatusCallback(dupStreamCallback_);
999 dupStream_->RegisterWriteCallback(dupStreamCallback_);
1000
1001 AUDIO_INFO_LOG("Dup Renderer %{public}u with status: %{public}d", streamIndex_, status_);
1002
1003 isInnerCapEnabled_ = true;
1004
1005 if (status_ == I_STATUS_STARTED) {
1006 AUDIO_INFO_LOG("Renderer %{public}u is already running, let's start the dup stream", streamIndex_);
1007 dupStream_->Start();
1008
1009 if (offloadEnable_) {
1010 renderEmptyCountForInnerCap_ = OFFLOAD_INNER_CAP_PREBUF;
1011 }
1012 }
1013 return SUCCESS;
1014 }
1015
EnableDualTone()1016 int32_t RendererInServer::EnableDualTone()
1017 {
1018 if (isDualToneEnabled_) {
1019 AUDIO_INFO_LOG("DualTone is already enabled");
1020 return SUCCESS;
1021 }
1022 int32_t ret = InitDualToneStream();
1023 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_OPERATION_FAILED, "Init dual tone stream failed");
1024 return SUCCESS;
1025 }
1026
DisableDualTone()1027 int32_t RendererInServer::DisableDualTone()
1028 {
1029 std::lock_guard<std::mutex> lock(dualToneMutex_);
1030 if (!isDualToneEnabled_) {
1031 AUDIO_WARNING_LOG("DualTone is already disabled.");
1032 return ERR_INVALID_OPERATION;
1033 }
1034 isDualToneEnabled_ = false;
1035 AUDIO_INFO_LOG("Disable dual tone renderer:[%{public}u] with status: %{public}d", dualToneStreamIndex_, status_);
1036 IStreamManager::GetDualPlaybackManager().ReleaseRender(dualToneStreamIndex_);
1037 AudioVolume::GetInstance()->RemoveStreamVolume(dualToneStreamIndex_);
1038 dualToneStream_ = nullptr;
1039
1040 return ERROR;
1041 }
1042
InitDualToneStream()1043 int32_t RendererInServer::InitDualToneStream()
1044 {
1045 std::lock_guard<std::mutex> lock(dualToneMutex_);
1046
1047 int32_t ret = IStreamManager::GetDualPlaybackManager().CreateRender(processConfig_, dualToneStream_);
1048 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS && dualToneStream_ != nullptr,
1049 ERR_OPERATION_FAILED, "Failed: %{public}d", ret);
1050 dualToneStreamIndex_ = dualToneStream_->GetStreamIndex();
1051 AUDIO_INFO_LOG("init dual tone renderer:[%{public}u]", dualToneStreamIndex_);
1052 AudioVolume::GetInstance()->AddStreamVolume(dualToneStreamIndex_, processConfig_.streamType,
1053 processConfig_.rendererInfo.streamUsage, processConfig_.appInfo.appUid, processConfig_.appInfo.appPid);
1054
1055 isDualToneEnabled_ = true;
1056
1057 if (status_ == I_STATUS_STARTED) {
1058 AUDIO_INFO_LOG("Renderer %{public}u is already running, let's start the dual stream", dualToneStreamIndex_);
1059 stream_->GetAudioEffectMode(effectModeWhenDual_);
1060 stream_->SetAudioEffectMode(EFFECT_NONE);
1061 dualToneStream_->Start();
1062 }
1063 return SUCCESS;
1064 }
1065
StreamCallbacks(uint32_t streamIndex)1066 StreamCallbacks::StreamCallbacks(uint32_t streamIndex) : streamIndex_(streamIndex)
1067 {
1068 AUDIO_INFO_LOG("DupStream %{public}u create StreamCallbacks", streamIndex_);
1069 }
1070
OnStatusUpdate(IOperation operation)1071 void StreamCallbacks::OnStatusUpdate(IOperation operation)
1072 {
1073 AUDIO_INFO_LOG("DupStream %{public}u recv operation: %{public}d", streamIndex_, operation);
1074 }
1075
OnWriteData(size_t length)1076 int32_t StreamCallbacks::OnWriteData(size_t length)
1077 {
1078 Trace trace("DupStream::OnWriteData length " + std::to_string(length));
1079 return SUCCESS;
1080 }
1081
SetOffloadMode(int32_t state,bool isAppBack)1082 int32_t RendererInServer::SetOffloadMode(int32_t state, bool isAppBack)
1083 {
1084 int32_t ret = stream_->SetOffloadMode(state, isAppBack);
1085 if (isInnerCapEnabled_) {
1086 std::lock_guard<std::mutex> lock(dupMutex_);
1087 if (dupStream_ != nullptr) {
1088 dupStream_->UpdateMaxLength(350); // 350 for cover offload
1089 }
1090 }
1091 if (isDualToneEnabled_) {
1092 std::lock_guard<std::mutex> lock(dualToneMutex_);
1093 if (dualToneStream_ != nullptr) {
1094 dualToneStream_->UpdateMaxLength(350); // 350 for cover offload
1095 }
1096 }
1097 // monitor
1098 AudioVolumeType volumeType = VolumeUtils::GetVolumeTypeFromStreamType(processConfig_.streamType);
1099 float volume = AudioVolume::GetInstance()->GetVolume(streamIndex_, volumeType, "offload");
1100 AUDIO_DEBUG_LOG("sessionId %{public}u monitor volume:%{public}f [volumeType:%{public}d]",
1101 streamIndex_, volume, volumeType);
1102 AudioVolume::GetInstance()->Monitor(streamIndex_, true);
1103 return ret;
1104 }
1105
UnsetOffloadMode()1106 int32_t RendererInServer::UnsetOffloadMode()
1107 {
1108 int32_t ret = stream_->UnsetOffloadMode();
1109 if (isInnerCapEnabled_) {
1110 std::lock_guard<std::mutex> lock(dupMutex_);
1111 if (dupStream_ != nullptr) {
1112 dupStream_->UpdateMaxLength(20); // 20 for unset offload
1113 }
1114 }
1115 if (isDualToneEnabled_) {
1116 std::lock_guard<std::mutex> lock(dualToneMutex_);
1117 if (dualToneStream_ != nullptr) {
1118 dualToneStream_->UpdateMaxLength(20); // 20 for cover offload
1119 }
1120 }
1121 return ret;
1122 }
1123
GetOffloadApproximatelyCacheTime(uint64_t & timestamp,uint64_t & paWriteIndex,uint64_t & cacheTimeDsp,uint64_t & cacheTimePa)1124 int32_t RendererInServer::GetOffloadApproximatelyCacheTime(uint64_t ×tamp, uint64_t &paWriteIndex,
1125 uint64_t &cacheTimeDsp, uint64_t &cacheTimePa)
1126 {
1127 return stream_->GetOffloadApproximatelyCacheTime(timestamp, paWriteIndex, cacheTimeDsp, cacheTimePa);
1128 }
1129
OffloadSetVolume(float volume)1130 int32_t RendererInServer::OffloadSetVolume(float volume)
1131 {
1132 if (volume < MIN_FLOAT_VOLUME || volume > MAX_FLOAT_VOLUME) {
1133 AUDIO_ERR_LOG("invalid volume:%{public}f", volume);
1134 return ERR_INVALID_PARAM;
1135 }
1136
1137 AudioVolumeType volumeType = VolumeUtils::GetVolumeTypeFromStreamType(processConfig_.streamType);
1138 float systemVol = AudioVolume::GetInstance()->GetVolume(streamIndex_, volumeType, "offload");
1139 AUDIO_INFO_LOG("sessionId %{public}u set volume:%{public}f [volumeType:%{public}d systemVol:"
1140 "%{public}f]", streamIndex_, volume, volumeType, systemVol);
1141 if (IsVolumeSame(MIN_FLOAT_VOLUME, volume, AUDIO_VOLOMUE_EPSILON)) {
1142 AudioVolume::GetInstance()->SetHistoryVolume(streamIndex_, 0.0f);
1143 }
1144 return stream_->OffloadSetVolume(systemVol * volume);
1145 }
1146
UpdateSpatializationState(bool spatializationEnabled,bool headTrackingEnabled)1147 int32_t RendererInServer::UpdateSpatializationState(bool spatializationEnabled, bool headTrackingEnabled)
1148 {
1149 return stream_->UpdateSpatializationState(spatializationEnabled, headTrackingEnabled);
1150 }
1151
GetStreamManagerType() const1152 int32_t RendererInServer::GetStreamManagerType() const noexcept
1153 {
1154 return managerType_ == DIRECT_PLAYBACK ? AUDIO_DIRECT_MANAGER_TYPE : AUDIO_NORMAL_MANAGER_TYPE;
1155 }
1156
IsHightResolution() const1157 bool RendererInServer::IsHightResolution() const noexcept
1158 {
1159 Trace trace("CheckHighResolution");
1160 if (processConfig_.deviceType != DEVICE_TYPE_WIRED_HEADSET &&
1161 processConfig_.deviceType != DEVICE_TYPE_USB_HEADSET) {
1162 AUDIO_INFO_LOG("normal stream,device type:%{public}d", processConfig_.deviceType);
1163 return false;
1164 }
1165 if (processConfig_.streamType != STREAM_MUSIC || processConfig_.streamInfo.samplingRate < SAMPLE_RATE_48000 ||
1166 processConfig_.streamInfo.format < SAMPLE_S24LE ||
1167 processConfig_.rendererInfo.pipeType != PIPE_TYPE_DIRECT_MUSIC) {
1168 AUDIO_INFO_LOG("normal stream because stream info");
1169 return false;
1170 }
1171 if (processConfig_.streamInfo.samplingRate > SAMPLE_RATE_192000) {
1172 AUDIO_INFO_LOG("sample rate over 192k");
1173 return false;
1174 }
1175 if (IStreamManager::GetPlaybackManager(DIRECT_PLAYBACK).GetStreamCount() > 0) {
1176 AUDIO_INFO_LOG("high resolution exist.");
1177 return false;
1178 }
1179 return true;
1180 }
1181
SetSilentModeAndMixWithOthers(bool on)1182 int32_t RendererInServer::SetSilentModeAndMixWithOthers(bool on)
1183 {
1184 silentModeAndMixWithOthers_ = on;
1185 if (silentModeAndMixWithOthers_) {
1186 AudioVolume::GetInstance()->SetStreamVolumeMute(streamIndex_, true);
1187 } else {
1188 AudioVolume::GetInstance()->SetStreamVolumeMute(streamIndex_, false);
1189 }
1190 return SUCCESS;
1191 }
1192
SetClientVolume()1193 int32_t RendererInServer::SetClientVolume()
1194 {
1195 if (audioServerBuffer_ == nullptr) {
1196 AUDIO_WARNING_LOG("buffer in not inited");
1197 return ERROR;
1198 }
1199 float clientVolume = audioServerBuffer_->GetStreamVolume();
1200 int32_t ret = stream_->SetClientVolume(clientVolume);
1201 if (IsVolumeSame(MIN_FLOAT_VOLUME, clientVolume, AUDIO_VOLOMUE_EPSILON)) {
1202 AudioVolume::GetInstance()->SetStreamVolume(streamIndex_, 0.0f);
1203 } else {
1204 AudioVolume::GetInstance()->SetStreamVolume(streamIndex_, 1.0f);
1205 }
1206 return ret;
1207 }
1208
SetMute(bool isMute)1209 int32_t RendererInServer::SetMute(bool isMute)
1210 {
1211 if (isMute) {
1212 AudioVolume::GetInstance()->SetStreamVolumeMute(streamIndex_, true);
1213 } else {
1214 AudioVolume::GetInstance()->SetStreamVolumeMute(streamIndex_, false);
1215 }
1216 return SUCCESS;
1217 }
1218
OnDataLinkConnectionUpdate(IOperation operation)1219 void RendererInServer::OnDataLinkConnectionUpdate(IOperation operation)
1220 {
1221 std::shared_ptr<IStreamListener> stateListener = streamListener_.lock();
1222 CHECK_AND_RETURN_LOG(stateListener != nullptr, "StreamListener is nullptr");
1223 switch (operation) {
1224 case OPERATION_DATA_LINK_CONNECTING:
1225 AUDIO_DEBUG_LOG("OPERATION_DATA_LINK_CONNECTING received");
1226 stateListener->OnOperationHandled(DATA_LINK_CONNECTING, 0);
1227 break;
1228 case OPERATION_DATA_LINK_CONNECTED:
1229 AUDIO_DEBUG_LOG("OPERATION_DATA_LINK_CONNECTED received");
1230 stateListener->OnOperationHandled(DATA_LINK_CONNECTED, 0);
1231 break;
1232 default:
1233 return;
1234 }
1235 }
1236
GetActualStreamManagerType() const1237 int32_t RendererInServer::GetActualStreamManagerType() const noexcept
1238 {
1239 return managerType_;
1240 }
1241
GetStatusStr(IStatus status)1242 static std::string GetStatusStr(IStatus status)
1243 {
1244 switch (status) {
1245 case I_STATUS_INVALID:
1246 return "INVALID";
1247 case I_STATUS_IDLE:
1248 return "IDEL";
1249 case I_STATUS_STARTING:
1250 return "STARTING";
1251 case I_STATUS_STARTED:
1252 return "STARTED";
1253 case I_STATUS_PAUSING:
1254 return "PAUSING";
1255 case I_STATUS_PAUSED:
1256 return "PAUSED";
1257 case I_STATUS_FLUSHING_WHEN_STARTED:
1258 return "FLUSHING_WHEN_STARTED";
1259 case I_STATUS_FLUSHING_WHEN_PAUSED:
1260 return "FLUSHING_WHEN_PAUSED";
1261 case I_STATUS_FLUSHING_WHEN_STOPPED:
1262 return "FLUSHING_WHEN_STOPPED";
1263 case I_STATUS_DRAINING:
1264 return "DRAINING";
1265 case I_STATUS_DRAINED:
1266 return "DRAINED";
1267 case I_STATUS_STOPPING:
1268 return "STOPPING";
1269 case I_STATUS_STOPPED:
1270 return "STOPPED";
1271 case I_STATUS_RELEASING:
1272 return "RELEASING";
1273 case I_STATUS_RELEASED:
1274 return "RELEASED";
1275 default:
1276 break;
1277 }
1278 return "NO_SUCH_STATUS";
1279 }
1280
GetManagerTypeStr(ManagerType type)1281 static std::string GetManagerTypeStr(ManagerType type)
1282 {
1283 switch (type) {
1284 case PLAYBACK:
1285 return "Normal";
1286 case DUP_PLAYBACK:
1287 return "Dup Playback";
1288 case DUAL_PLAYBACK:
1289 return "DUAL Playback";
1290 case DIRECT_PLAYBACK:
1291 return "Direct";
1292 case VOIP_PLAYBACK:
1293 return "Voip";
1294 case RECORDER:
1295 return "Recorder";
1296 default:
1297 break;
1298 }
1299 return "NO_SUCH_TYPE";
1300 }
1301
Dump(std::string & dumpString)1302 bool RendererInServer::Dump(std::string &dumpString)
1303 {
1304 if (managerType_ != DIRECT_PLAYBACK && managerType_ != VOIP_PLAYBACK) {
1305 return false;
1306 }
1307 // dump audio stream info
1308 dumpString += "audio stream info:\n";
1309 AppendFormat(dumpString, " - session id:%u\n", streamIndex_);
1310 AppendFormat(dumpString, " - appid:%d\n", processConfig_.appInfo.appPid);
1311 AppendFormat(dumpString, " - stream type:%d\n", processConfig_.streamType);
1312
1313 AppendFormat(dumpString, " - samplingRate: %d\n", processConfig_.streamInfo.samplingRate);
1314 AppendFormat(dumpString, " - channels: %u\n", processConfig_.streamInfo.channels);
1315 AppendFormat(dumpString, " - format: %u\n", processConfig_.streamInfo.format);
1316 AppendFormat(dumpString, " - device type: %u\n", processConfig_.deviceType);
1317 AppendFormat(dumpString, " - sink type: %s\n", GetManagerTypeStr(managerType_).c_str());
1318
1319 // dump status info
1320 AppendFormat(dumpString, " - Current stream status: %s\n", GetStatusStr(status_).c_str());
1321 if (audioServerBuffer_ != nullptr) {
1322 AppendFormat(dumpString, " - Current read position: %u\n", audioServerBuffer_->GetCurReadFrame());
1323 AppendFormat(dumpString, " - Current write position: %u\n", audioServerBuffer_->GetCurWriteFrame());
1324 }
1325
1326 dumpString += "\n";
1327 return true;
1328 }
1329
SetNonInterruptMute(const bool muteFlag)1330 void RendererInServer::SetNonInterruptMute(const bool muteFlag)
1331 {
1332 AUDIO_INFO_LOG("mute flag %{public}d", muteFlag);
1333 muteFlag_ = muteFlag;
1334 AudioService::GetInstance()->UpdateMuteControlSet(streamIndex_, muteFlag);
1335 }
1336 } // namespace AudioStandard
1337 } // namespace OHOS
1338