• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 &timestamp)
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 &timestamp, 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 &timestamp, 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