1 /*
2 * Copyright (c) 2023-2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #ifndef LOG_TAG
16 #define LOG_TAG "RendererInClientInner"
17 #endif
18
19 #include "renderer_in_client.h"
20 #include "renderer_in_client_private.h"
21
22 #include <atomic>
23 #include <cinttypes>
24 #include <condition_variable>
25 #include <sstream>
26 #include <string>
27 #include <mutex>
28 #include <thread>
29
30 #include "iservice_registry.h"
31 #include "system_ability_definition.h"
32 #include "securec.h"
33 #include "hisysevent.h"
34
35 #include "audio_errors.h"
36 #include "audio_policy_manager.h"
37 #include "audio_manager_base.h"
38 #include "audio_renderer_log.h"
39 #include "audio_ring_cache.h"
40 #include "audio_channel_blend.h"
41 #include "audio_server_death_recipient.h"
42 #include "audio_stream_tracker.h"
43 #include "audio_system_manager.h"
44 #include "futex_tool.h"
45 #include "ipc_stream_listener_impl.h"
46 #include "ipc_stream_listener_stub.h"
47 #include "volume_ramp.h"
48 #include "callback_handler.h"
49 #include "audio_speed.h"
50 #include "audio_spatial_channel_converter.h"
51 #include "audio_policy_manager.h"
52 #include "audio_spatialization_manager.h"
53 #include "policy_handler.h"
54 #include "volume_tools.h"
55
56 #include "media_monitor_manager.h"
57
58 using namespace OHOS::HiviewDFX;
59 using namespace OHOS::AppExecFwk;
60
61 namespace OHOS {
62 namespace AudioStandard {
63 namespace {
64 const uint64_t OLD_BUF_DURATION_IN_USEC = 92880; // This value is used for compatibility purposes.
65 const uint64_t AUDIO_US_PER_S = 1000000;
66 const uint64_t MAX_BUF_DURATION_IN_USEC = 2000000; // 2S
67 static const size_t MAX_WRITE_SIZE = 20 * 1024 * 1024; // 20M
68 static const int32_t OPERATION_TIMEOUT_IN_MS = 1000; // 1000ms
69 static const int32_t OFFLOAD_OPERATION_TIMEOUT_IN_MS = 8000; // 8000ms for offload
70 static const int32_t WRITE_CACHE_TIMEOUT_IN_MS = 1500; // 1500ms
71 static const int32_t WRITE_BUFFER_TIMEOUT_IN_MS = 20; // ms
72 static const uint32_t WAIT_FOR_NEXT_CB = 5000; // 5ms
73 static constexpr int32_t ONE_MINUTE = 60;
74 static const int32_t MAX_WRITE_INTERVAL_MS = 40;
75 constexpr int32_t RETRY_WAIT_TIME_MS = 500; // 500ms
76 constexpr int32_t MAX_RETRY_COUNT = 8;
77 } // namespace
78
79 static AppExecFwk::BundleInfo gBundleInfo_;
80 std::mutex g_serverProxyMutex;
81 sptr<IStandardAudioService> gServerProxy_ = nullptr;
82
GetAudioServerProxy()83 const sptr<IStandardAudioService> RendererInClientInner::GetAudioServerProxy()
84 {
85 std::lock_guard<std::mutex> lock(g_serverProxyMutex);
86 if (gServerProxy_ == nullptr) {
87 auto samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
88 if (samgr == nullptr) {
89 AUDIO_ERR_LOG("GetAudioServerProxy: get sa manager failed");
90 return nullptr;
91 }
92 sptr<IRemoteObject> object = samgr->GetSystemAbility(AUDIO_DISTRIBUTED_SERVICE_ID);
93 if (object == nullptr) {
94 AUDIO_ERR_LOG("GetAudioServerProxy: get audio service remote object failed");
95 return nullptr;
96 }
97 gServerProxy_ = iface_cast<IStandardAudioService>(object);
98 if (gServerProxy_ == nullptr) {
99 AUDIO_ERR_LOG("GetAudioServerProxy: get audio service proxy failed");
100 return nullptr;
101 }
102
103 // register death recipent to restore proxy
104 sptr<AudioServerDeathRecipient> asDeathRecipient =
105 new(std::nothrow) AudioServerDeathRecipient(getpid(), getuid());
106 if (asDeathRecipient != nullptr) {
107 asDeathRecipient->SetNotifyCb([] (pid_t pid, pid_t uid) { AudioServerDied(pid, uid); });
108 bool result = object->AddDeathRecipient(asDeathRecipient);
109 if (!result) {
110 AUDIO_ERR_LOG("GetAudioServerProxy: failed to add deathRecipient");
111 }
112 }
113 }
114 sptr<IStandardAudioService> gasp = gServerProxy_;
115 return gasp;
116 }
117
AudioServerDied(pid_t pid,pid_t uid)118 void RendererInClientInner::AudioServerDied(pid_t pid, pid_t uid)
119 {
120 AUDIO_INFO_LOG("audio server died clear proxy, will restore proxy in next call");
121 std::lock_guard<std::mutex> lock(g_serverProxyMutex);
122 gServerProxy_ = nullptr;
123 }
124
RegisterTracker(const std::shared_ptr<AudioClientTracker> & proxyObj)125 void RendererInClientInner::RegisterTracker(const std::shared_ptr<AudioClientTracker> &proxyObj)
126 {
127 if (audioStreamTracker_ && audioStreamTracker_.get() && !streamTrackerRegistered_) {
128 // make sure sessionId_ is valid.
129 AUDIO_INFO_LOG("Calling register tracker, sessionid is %{public}d", sessionId_);
130 AudioRegisterTrackerInfo registerTrackerInfo;
131
132 rendererInfo_.samplingRate = static_cast<AudioSamplingRate>(curStreamParams_.samplingRate);
133 rendererInfo_.format = static_cast<AudioSampleFormat>(curStreamParams_.format);
134 registerTrackerInfo.sessionId = sessionId_;
135 registerTrackerInfo.clientPid = clientPid_;
136 registerTrackerInfo.state = state_;
137 registerTrackerInfo.rendererInfo = rendererInfo_;
138 registerTrackerInfo.capturerInfo = capturerInfo_;
139 registerTrackerInfo.channelCount = curStreamParams_.channels;
140
141 audioStreamTracker_->RegisterTracker(registerTrackerInfo, proxyObj);
142 streamTrackerRegistered_ = true;
143 }
144 }
145
UpdateTracker(const std::string & updateCase)146 void RendererInClientInner::UpdateTracker(const std::string &updateCase)
147 {
148 if (audioStreamTracker_ && audioStreamTracker_.get()) {
149 AUDIO_DEBUG_LOG("Renderer:Calling Update tracker for %{public}s", updateCase.c_str());
150 audioStreamTracker_->UpdateTracker(sessionId_, state_, clientPid_, rendererInfo_, capturerInfo_);
151 }
152 }
153
IsHighResolution() const154 bool RendererInClientInner::IsHighResolution() const noexcept
155 {
156 return eStreamType_ == STREAM_MUSIC && curStreamParams_.samplingRate >= SAMPLE_RATE_48000 &&
157 curStreamParams_.format >= SAMPLE_S24LE;
158 }
159
InitDirectPipeType()160 void RendererInClientInner::InitDirectPipeType()
161 {
162 if (rendererInfo_.rendererFlags == AUDIO_FLAG_VOIP_DIRECT || IsHighResolution()) {
163 AudioPipeType originType = rendererInfo_.pipeType;
164 int32_t type = ipcStream_->GetStreamManagerType();
165 if (type == AUDIO_DIRECT_MANAGER_TYPE) {
166 rendererInfo_.pipeType = (rendererInfo_.rendererFlags == AUDIO_FLAG_VOIP_DIRECT) ?
167 PIPE_TYPE_CALL_OUT : PIPE_TYPE_DIRECT_MUSIC;
168 } else if (originType == PIPE_TYPE_DIRECT_MUSIC) {
169 rendererInfo_.pipeType = PIPE_TYPE_NORMAL_OUT;
170 }
171 }
172 }
173
174 // call this without lock, we should be able to call deinit in any case.
DeinitIpcStream()175 int32_t RendererInClientInner::DeinitIpcStream()
176 {
177 Trace trace("RendererInClientInner::DeinitIpcStream");
178 ipcStream_->Release();
179 ringCache_->ResetBuffer();
180 return SUCCESS;
181 }
182
ConstructConfig()183 const AudioProcessConfig RendererInClientInner::ConstructConfig()
184 {
185 AudioProcessConfig config = {};
186
187 config.appInfo.appPid = clientPid_;
188 config.appInfo.appUid = clientUid_;
189 config.appInfo.appTokenId = appTokenId_;
190 config.appInfo.appFullTokenId = fullTokenId_;
191
192 config.streamInfo.channels = static_cast<AudioChannel>(curStreamParams_.channels);
193 config.streamInfo.encoding = static_cast<AudioEncodingType>(curStreamParams_.encoding);
194 config.streamInfo.format = static_cast<AudioSampleFormat>(curStreamParams_.format);
195 config.streamInfo.samplingRate = static_cast<AudioSamplingRate>(curStreamParams_.samplingRate);
196 config.streamInfo.channelLayout = static_cast<AudioChannelLayout>(curStreamParams_.channelLayout);
197 config.originalSessionId = curStreamParams_.originalSessionId;
198
199 config.audioMode = AUDIO_MODE_PLAYBACK;
200
201 if (rendererInfo_.rendererFlags != AUDIO_FLAG_NORMAL && rendererInfo_.rendererFlags != AUDIO_FLAG_VOIP_DIRECT) {
202 AUDIO_WARNING_LOG("ConstructConfig find renderer flag invalid:%{public}d", rendererInfo_.rendererFlags);
203 rendererInfo_.rendererFlags = 0;
204 }
205 config.rendererInfo = rendererInfo_;
206
207 config.capturerInfo = {};
208
209 config.streamType = eStreamType_;
210
211 config.deviceType = AudioPolicyManager::GetInstance().GetActiveOutputDevice();
212
213 config.privacyType = privacyType_;
214
215 clientConfig_ = config;
216
217 return config;
218 }
219
InitSharedBuffer()220 int32_t RendererInClientInner::InitSharedBuffer()
221 {
222 CHECK_AND_RETURN_RET_LOG(ipcStream_ != nullptr, ERR_OPERATION_FAILED, "InitSharedBuffer failed, null ipcStream_.");
223 int32_t ret = ipcStream_->ResolveBuffer(clientBuffer_);
224
225 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS && clientBuffer_ != nullptr, ret, "ResolveBuffer failed:%{public}d", ret);
226
227 uint32_t totalSizeInFrame = 0;
228 uint32_t byteSizePerFrame = 0;
229 ret = clientBuffer_->GetSizeParameter(totalSizeInFrame, spanSizeInFrame_, byteSizePerFrame);
230
231 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS && byteSizePerFrame == sizePerFrameInByte_, ret, "GetSizeParameter failed"
232 ":%{public}d, byteSizePerFrame:%{public}u, sizePerFrameInByte_:%{public}zu", ret, byteSizePerFrame,
233 sizePerFrameInByte_);
234
235 clientSpanSizeInByte_ = spanSizeInFrame_ * byteSizePerFrame;
236
237 AUDIO_INFO_LOG("totalSizeInFrame_[%{public}u] spanSizeInFrame[%{public}u] sizePerFrameInByte_[%{public}zu]"
238 "clientSpanSizeInByte_[%{public}zu]", totalSizeInFrame, spanSizeInFrame_, sizePerFrameInByte_,
239 clientSpanSizeInByte_);
240
241 return SUCCESS;
242 }
243
244 // InitCacheBuffer should be able to modify the cache size between clientSpanSizeInByte_ and 4 * clientSpanSizeInByte_
InitCacheBuffer(size_t targetSize)245 int32_t RendererInClientInner::InitCacheBuffer(size_t targetSize)
246 {
247 CHECK_AND_RETURN_RET_LOG(clientSpanSizeInByte_ != 0, ERR_OPERATION_FAILED, "clientSpanSizeInByte_ invalid");
248
249 AUDIO_INFO_LOG("old size:%{public}zu, new size:%{public}zu", cacheSizeInByte_, targetSize);
250 cacheSizeInByte_ = targetSize;
251
252 if (ringCache_ == nullptr) {
253 ringCache_ = AudioRingCache::Create(cacheSizeInByte_);
254 } else {
255 OptResult result = ringCache_->ReConfig(cacheSizeInByte_, false); // false --> clear buffer
256 if (result.ret != OPERATION_SUCCESS) {
257 AUDIO_ERR_LOG("ReConfig AudioRingCache to size %{public}u failed:ret%{public}zu", result.ret, targetSize);
258 return ERR_OPERATION_FAILED;
259 }
260 }
261
262 return SUCCESS;
263 }
264
InitIpcStream()265 int32_t RendererInClientInner::InitIpcStream()
266 {
267 Trace trace("RendererInClientInner::InitIpcStream");
268 AudioProcessConfig config = ConstructConfig();
269 bool resetSilentMode = (gServerProxy_ == nullptr) ? true : false;
270 sptr<IStandardAudioService> gasp = RendererInClientInner::GetAudioServerProxy();
271 CHECK_AND_RETURN_RET_LOG(gasp != nullptr, ERR_OPERATION_FAILED, "Create failed, can not get service.");
272 int32_t errorCode = 0;
273 sptr<IRemoteObject> ipcProxy = gasp->CreateAudioProcess(config, errorCode);
274 for (int32_t retrycount = 0; (errorCode == ERR_RETRY_IN_CLIENT) && (retrycount < MAX_RETRY_COUNT); retrycount++) {
275 AUDIO_WARNING_LOG("retry in client");
276 std::this_thread::sleep_for(std::chrono::milliseconds(RETRY_WAIT_TIME_MS));
277 ipcProxy = gasp->CreateAudioProcess(config, errorCode);
278 }
279 CHECK_AND_RETURN_RET_LOG(ipcProxy != nullptr, ERR_OPERATION_FAILED, "failed with null ipcProxy.");
280 ipcStream_ = iface_cast<IpcStream>(ipcProxy);
281 CHECK_AND_RETURN_RET_LOG(ipcStream_ != nullptr, ERR_OPERATION_FAILED, "failed when iface_cast.");
282
283 // in plan next: old listener_ is destoried here, will server receive dieth notify?
284 listener_ = sptr<IpcStreamListenerImpl>::MakeSptr(shared_from_this());
285 int32_t ret = ipcStream_->RegisterStreamListener(listener_->AsObject());
286 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ret, "RegisterStreamListener failed:%{public}d", ret);
287
288 if (resetSilentMode && gServerProxy_ != nullptr && silentModeAndMixWithOthers_) {
289 ipcStream_->SetSilentModeAndMixWithOthers(silentModeAndMixWithOthers_);
290 }
291 ret = InitSharedBuffer();
292 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ret, "InitSharedBuffer failed:%{public}d", ret);
293
294 ret = InitCacheBuffer(clientSpanSizeInByte_);
295 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ret, "InitCacheBuffer failed:%{public}d", ret);
296
297 ret = ipcStream_->GetAudioSessionID(sessionId_);
298 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ret, "GetAudioSessionID failed:%{public}d", ret);
299 traceTag_ = "[" + std::to_string(sessionId_) + "]RendererInClient"; // [100001]RendererInClient
300 InitCallbackHandler();
301 return SUCCESS;
302 }
303
SetInnerVolume(float volume)304 int32_t RendererInClientInner::SetInnerVolume(float volume)
305 {
306 CHECK_AND_RETURN_RET_LOG(clientBuffer_ != nullptr, ERR_OPERATION_FAILED, "buffer is not inited");
307 clientBuffer_->SetStreamVolume(volume);
308 CHECK_AND_RETURN_RET_LOG(ipcStream_ != nullptr, false, "ipcStream is not inited!");
309 int32_t ret = ipcStream_->SetClientVolume();
310 if (ret != SUCCESS) {
311 AUDIO_ERR_LOG("Set Client Volume failed:%{public}u", ret);
312 return ERROR;
313 }
314 AUDIO_PRERELEASE_LOGI("SetClientVolume success, volume: %{public}f", volume);
315 return SUCCESS;
316 }
317
InitCallbackBuffer(uint64_t bufferDurationInUs)318 void RendererInClientInner::InitCallbackBuffer(uint64_t bufferDurationInUs)
319 {
320 if (bufferDurationInUs > MAX_BUF_DURATION_IN_USEC) {
321 AUDIO_ERR_LOG("InitCallbackBuffer with invalid duration %{public}" PRIu64", use default instead.",
322 bufferDurationInUs);
323 bufferDurationInUs = OLD_BUF_DURATION_IN_USEC;
324 }
325 // Calculate buffer size based on duration.
326
327 size_t metaSize = 0;
328 if (curStreamParams_.encoding == ENCODING_AUDIOVIVID) {
329 CHECK_AND_RETURN_LOG(converter_ != nullptr, "converter is not inited");
330 metaSize = converter_->GetMetaSize();
331 converter_->GetInputBufferSize(cbBufferSize_);
332 } else {
333 cbBufferSize_ = static_cast<size_t>(bufferDurationInUs * curStreamParams_.samplingRate / AUDIO_US_PER_S) *
334 sizePerFrameInByte_;
335 }
336 AUDIO_INFO_LOG("duration %{public}" PRIu64 ", ecodingType: %{public}d, size: %{public}zu, metaSize: %{public}zu",
337 bufferDurationInUs, curStreamParams_.encoding, cbBufferSize_, metaSize);
338 std::lock_guard<std::mutex> lock(cbBufferMutex_);
339 cbBuffer_ = std::make_unique<uint8_t[]>(cbBufferSize_ + metaSize);
340 }
341
342 // Sleep or wait in WaitForRunning to avoid dead looping.
WaitForRunning()343 bool RendererInClientInner::WaitForRunning()
344 {
345 Trace trace("RendererInClientInner::WaitForRunning");
346 // check renderer state_: call client write only in running else wait on statusMutex_
347 std::unique_lock<std::mutex> stateLock(statusMutex_);
348 if (state_ != RUNNING) {
349 bool stopWaiting = cbThreadCv_.wait_for(stateLock, std::chrono::milliseconds(OPERATION_TIMEOUT_IN_MS), [this] {
350 return state_ == RUNNING || cbThreadReleased_;
351 });
352 if (cbThreadReleased_) {
353 AUDIO_INFO_LOG("CBThread end in non-running status, sessionID :%{public}d", sessionId_);
354 return false;
355 }
356 if (!stopWaiting) {
357 AUDIO_DEBUG_LOG("Wait timeout, current state_ is %{public}d", state_.load()); // wait 0.5s
358 return false;
359 }
360 }
361 return true;
362 }
363
ProcessWriteInner(BufferDesc & bufferDesc)364 int32_t RendererInClientInner::ProcessWriteInner(BufferDesc &bufferDesc)
365 {
366 int32_t result = 0; // Ensure result with default value.
367 if (curStreamParams_.encoding == ENCODING_AUDIOVIVID) {
368 result = WriteInner(bufferDesc.buffer, bufferDesc.bufLength, bufferDesc.metaBuffer, bufferDesc.metaLength);
369 }
370 if (curStreamParams_.encoding == ENCODING_PCM) {
371 if (bufferDesc.dataLength != 0) {
372 result = WriteInner(bufferDesc.buffer, bufferDesc.bufLength);
373 sleepCount_ = LOG_COUNT_LIMIT;
374 } else {
375 if (sleepCount_++ == LOG_COUNT_LIMIT) {
376 sleepCount_ = 0;
377 AUDIO_WARNING_LOG("OnWriteData Process 1st or 500 times INVALID buffer");
378 }
379 usleep(WAIT_FOR_NEXT_CB);
380 }
381 }
382 if (result < 0) {
383 AUDIO_WARNING_LOG("Call write fail, result:%{public}d, bufLength:%{public}zu", result, bufferDesc.bufLength);
384 }
385 return result;
386 }
387
WriteCallbackFunc()388 bool RendererInClientInner::WriteCallbackFunc()
389 {
390 if (cbThreadReleased_) {
391 AUDIO_INFO_LOG("Callback thread released");
392 return false;
393 }
394 Trace traceLoop("RendererInClientInner::WriteCallbackFunc");
395 if (!WaitForRunning()) {
396 return true;
397 }
398 if (cbBufferQueue_.Size() > 1) { // One callback, one enqueue, queue size should always be 1.
399 AUDIO_WARNING_LOG("The queue is too long, reducing data through loops");
400 }
401 BufferDesc temp;
402 while (cbBufferQueue_.PopNotWait(temp)) {
403 Trace traceQueuePop("RendererInClientInner::QueueWaitPop");
404 if (state_ != RUNNING) {
405 cbBufferQueue_.Push(temp);
406 AUDIO_INFO_LOG("Repush left buffer in queue");
407 break;
408 }
409 traceQueuePop.End();
410 // call write here.
411 int32_t result = ProcessWriteInner(temp);
412 // only run in pause scene
413 if (result > 0 && static_cast<size_t>(result) < temp.dataLength) {
414 BufferDesc tmp = {temp.buffer + static_cast<size_t>(result),
415 temp.bufLength - static_cast<size_t>(result), temp.dataLength - static_cast<size_t>(result)};
416 cbBufferQueue_.Push(tmp);
417 AUDIO_INFO_LOG("Repush %{public}zu bytes in queue", temp.dataLength - static_cast<size_t>(result));
418 break;
419 }
420 }
421 if (state_ != RUNNING) {
422 return true;
423 }
424 // call client write
425 std::unique_lock<std::mutex> lockCb(writeCbMutex_);
426 if (writeCb_ != nullptr) {
427 Trace traceCb("RendererInClientInner::OnWriteData");
428 writeCb_->OnWriteData(cbBufferSize_);
429 }
430 lockCb.unlock();
431
432 Trace traceQueuePush("RendererInClientInner::QueueWaitPush");
433 std::unique_lock<std::mutex> lockBuffer(cbBufferMutex_);
434 cbBufferQueue_.WaitNotEmptyFor(std::chrono::milliseconds(WRITE_BUFFER_TIMEOUT_IN_MS));
435 return true;
436 }
437
FlushRingCache()438 int32_t RendererInClientInner::FlushRingCache()
439 {
440 ringCache_->ResetBuffer();
441 return SUCCESS;
442 }
443
DrainRingCache()444 int32_t RendererInClientInner::DrainRingCache()
445 {
446 // send all data in ringCache_ to server even if GetReadableSize() < clientSpanSizeInByte_.
447 Trace trace("RendererInClientInner::DrainRingCache " + std::to_string(sessionId_));
448
449 OptResult result = ringCache_->GetReadableSize();
450 CHECK_AND_RETURN_RET_LOG(result.ret == OPERATION_SUCCESS, ERR_OPERATION_FAILED, "ring cache unreadable");
451 size_t readableSize = result.size;
452 if (readableSize == 0) {
453 AUDIO_WARNING_LOG("Readable size is already zero");
454 return SUCCESS;
455 }
456
457 BufferDesc desc = {};
458 uint64_t curWriteIndex = clientBuffer_->GetCurWriteFrame();
459 int32_t ret = clientBuffer_->GetWriteBuffer(curWriteIndex, desc);
460 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_OPERATION_FAILED, "GetWriteBuffer failed %{public}d", ret);
461
462 // if readableSize < clientSpanSizeInByte_, server will recv a data with some empty data.
463 // it looks like this: |*******_____|
464 size_t minSize = std::min(readableSize, clientSpanSizeInByte_);
465 result = ringCache_->Dequeue({desc.buffer, minSize});
466 CHECK_AND_RETURN_RET_LOG(result.ret == OPERATION_SUCCESS, ERROR, "ringCache Dequeue failed %{public}d", result.ret);
467 clientBuffer_->SetCurWriteFrame(curWriteIndex + spanSizeInFrame_);
468 CHECK_AND_RETURN_RET_LOG(ipcStream_ != nullptr, ERR_ILLEGAL_STATE, "ipcStream is nullptr");
469 ipcStream_->UpdatePosition(); // notiify server update position
470 HandleRendererPositionChanges(minSize);
471 return SUCCESS;
472 }
473
ProcessSpeed(uint8_t * & buffer,size_t & bufferSize,bool & speedCached)474 bool RendererInClientInner::ProcessSpeed(uint8_t *&buffer, size_t &bufferSize, bool &speedCached)
475 {
476 speedCached = false;
477 #ifdef SONIC_ENABLE
478 if (!isEqual(speed_, 1.0f)) {
479 Trace trace(traceTag_ + " ProcessSpeed");
480 if (audioSpeed_ == nullptr) {
481 AUDIO_ERR_LOG("audioSpeed_ is nullptr, use speed default 1.0");
482 return true;
483 }
484 int32_t outBufferSize = 0;
485 if (audioSpeed_->ChangeSpeedFunc(buffer, bufferSize, speedBuffer_, outBufferSize) == 0) {
486 bufferSize = 0;
487 AUDIO_ERR_LOG("process speed error");
488 return false;
489 }
490 if (outBufferSize == 0) {
491 AUDIO_DEBUG_LOG("speed buffer is not full");
492 return false;
493 }
494 buffer = speedBuffer_.get();
495 bufferSize = static_cast<size_t>(outBufferSize);
496 speedCached = true;
497 }
498 #endif
499 return true;
500 }
501
DfxWriteInterval()502 void RendererInClientInner::DfxWriteInterval()
503 {
504 if (preWriteEndTime_ != 0 &&
505 ((ClockTime::GetCurNano() / AUDIO_US_PER_SECOND) - preWriteEndTime_) > MAX_WRITE_INTERVAL_MS) {
506 AUDIO_WARNING_LOG("[%{public}s] write interval too long cost %{public}" PRId64,
507 logUtilsTag_.c_str(), (ClockTime::GetCurNano() / AUDIO_US_PER_SECOND) - preWriteEndTime_);
508 }
509 }
WriteInner(uint8_t * pcmBuffer,size_t pcmBufferSize,uint8_t * metaBuffer,size_t metaBufferSize)510 int32_t RendererInClientInner::WriteInner(uint8_t *pcmBuffer, size_t pcmBufferSize, uint8_t *metaBuffer,
511 size_t metaBufferSize)
512 {
513 Trace trace("RendererInClient::Write with meta " + std::to_string(pcmBufferSize));
514 CHECK_AND_RETURN_RET_LOG(curStreamParams_.encoding == ENCODING_AUDIOVIVID, ERR_NOT_SUPPORTED,
515 "Write: Write not supported. encoding doesnot match.");
516 BufferDesc bufDesc = {pcmBuffer, pcmBufferSize, pcmBufferSize, metaBuffer, metaBufferSize};
517 CHECK_AND_RETURN_RET_LOG(converter_ != nullptr, ERR_WRITE_FAILED, "Write: converter isn't init.");
518 CHECK_AND_RETURN_RET_LOG(converter_->CheckInputValid(bufDesc), ERR_INVALID_PARAM, "Write: Invalid input.");
519
520 WriteMuteDataSysEvent(pcmBuffer, pcmBufferSize);
521
522 converter_->Process(bufDesc);
523 uint8_t *buffer;
524 uint32_t bufferSize;
525 converter_->GetOutputBufferStream(buffer, bufferSize);
526 return WriteInner(buffer, bufferSize);
527 }
528
FirstFrameProcess()529 void RendererInClientInner::FirstFrameProcess()
530 {
531 if (ipcStream_ == nullptr) {
532 AUDIO_ERR_LOG("Error: ipcStream_ is not initialized!");
533 return;
534 }
535
536 // if first call, call set thread priority. if thread tid change recall set thread priority
537 if (needSetThreadPriority_.exchange(false)) {
538 ipcStream_->RegisterThreadPriority(gettid(),
539 AudioSystemManager::GetInstance()->GetSelfBundleName(clientConfig_.appInfo.appUid));
540 }
541
542 if (!hasFirstFrameWrited_.exchange(true)) { OnFirstFrameWriting(); }
543 }
544
WriteRingCache(uint8_t * buffer,size_t bufferSize,bool speedCached,size_t oriBufferSize)545 int32_t RendererInClientInner::WriteRingCache(uint8_t *buffer, size_t bufferSize, bool speedCached,
546 size_t oriBufferSize)
547 {
548 size_t targetSize = bufferSize;
549 size_t offset = 0;
550 while (targetSize >= sizePerFrameInByte_) {
551 // 1. write data into ring cache
552 OptResult result = ringCache_->GetWritableSize();
553 CHECK_AND_RETURN_RET_LOG(result.ret == OPERATION_SUCCESS, speedCached ? oriBufferSize : bufferSize - targetSize,
554 "RingCache write status invalid size is:%{public}zu", result.size);
555
556 size_t writableSize = result.size;
557 Trace::Count("RendererInClient::CacheBuffer->writableSize", writableSize);
558
559 size_t writeSize = std::min(writableSize, targetSize);
560 BufferWrap bufferWrap = {buffer + offset, writeSize};
561
562 if (writeSize > 0) {
563 result = ringCache_->Enqueue(bufferWrap);
564 if (result.ret != OPERATION_SUCCESS) {
565 // in plan: recall enqueue in some cases
566 AUDIO_ERR_LOG("RingCache Enqueue failed ret:%{public}d size:%{public}zu", result.ret, result.size);
567 break;
568 }
569 offset += writeSize;
570 targetSize -= writeSize;
571 clientWrittenBytes_ += writeSize;
572 }
573
574 // 2. copy data from cache to OHAudioBuffer
575 result = ringCache_->GetReadableSize();
576 CHECK_AND_RETURN_RET_LOG(result.ret == OPERATION_SUCCESS, speedCached ? oriBufferSize : bufferSize - targetSize,
577 "RingCache read status invalid size is:%{public}zu", result.size);
578 size_t readableSize = result.size;
579 Trace::Count("RendererInClient::CacheBuffer->readableSize", readableSize);
580
581 if (readableSize < clientSpanSizeInByte_) { continue; }
582 // if readable size is enough, we will call write data to server
583 int32_t ret = WriteCacheData();
584 CHECK_AND_RETURN_RET_LOG(ret != ERR_ILLEGAL_STATE, speedCached ? oriBufferSize : bufferSize - targetSize,
585 "Status changed while write");
586 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERROR, "WriteCacheData failed %{public}d", ret);
587 }
588 preWriteEndTime_ = ClockTime::GetCurNano() / AUDIO_US_PER_SECOND;
589 return speedCached ? oriBufferSize : bufferSize - targetSize;
590 }
591
WriteInner(uint8_t * buffer,size_t bufferSize)592 int32_t RendererInClientInner::WriteInner(uint8_t *buffer, size_t bufferSize)
593 {
594 // eg: RendererInClient::sessionId:100001 WriteSize:3840
595 DfxWriteInterval();
596 Trace trace(traceTag_+ " WriteSize:" + std::to_string(bufferSize));
597 CHECK_AND_RETURN_RET_LOG(buffer != nullptr && bufferSize < MAX_WRITE_SIZE && bufferSize > 0, ERR_INVALID_PARAM,
598 "invalid size is %{public}zu", bufferSize);
599
600 // Bugfix. Callback threadloop would go into infinite loop, consuming too much data from app
601 // but fail to play them due to audio server's death. Block and exit callback threadloop when server died.
602 if (gServerProxy_ == nullptr) {
603 cbThreadReleased_ = true;
604 uint32_t samplingRate = clientConfig_.streamInfo.samplingRate;
605 uint32_t channels = clientConfig_.streamInfo.channels;
606 uint32_t samplePerFrame = Util::GetSamplePerFrame(clientConfig_.streamInfo.format);
607 // calculate wait time by buffer size, 10e6 is converting seconds to microseconds
608 uint32_t waitTimeUs = bufferSize * 10e6 / (samplingRate * channels * samplePerFrame);
609 AUDIO_ERR_LOG("server is died! wait %{public}d us", waitTimeUs);
610 usleep(waitTimeUs);
611 return ERR_WRITE_BUFFER;
612 }
613
614 CHECK_AND_RETURN_RET_LOG(gServerProxy_ != nullptr, ERROR, "server is died");
615 if (clientBuffer_->GetStreamStatus() == nullptr) {
616 AUDIO_ERR_LOG("The stream status is null!");
617 return ERR_INVALID_PARAM;
618 }
619
620 if (clientBuffer_->GetStreamStatus()->load() == STREAM_STAND_BY) {
621 Trace trace2(traceTag_+ " call start to exit stand-by");
622 CHECK_AND_RETURN_RET_LOG(ipcStream_ != nullptr, ERROR, "ipcStream is not inited!");
623 int32_t ret = ipcStream_->Start();
624 AUDIO_INFO_LOG("%{public}u call start to exit stand-by ret %{public}u", sessionId_, ret);
625 }
626
627 FirstFrameProcess();
628
629 std::lock_guard<std::mutex> lock(writeMutex_);
630
631 size_t oriBufferSize = bufferSize;
632 bool speedCached = false;
633 if (!ProcessSpeed(buffer, bufferSize, speedCached)) {
634 return bufferSize;
635 }
636
637 WriteMuteDataSysEvent(buffer, bufferSize);
638
639 CHECK_AND_RETURN_RET_PRELOG(state_ == RUNNING, ERR_ILLEGAL_STATE,
640 "Write: Illegal state:%{public}u sessionid: %{public}u", state_.load(), sessionId_);
641
642 // hold lock
643 if (isBlendSet_) {
644 audioBlend_.Process(buffer, bufferSize);
645 }
646
647 return WriteRingCache(buffer, bufferSize, speedCached, oriBufferSize);
648 }
649
ResetFramePosition()650 void RendererInClientInner::ResetFramePosition()
651 {
652 Trace trace("RendererInClientInner::ResetFramePosition");
653 uint64_t timestampVal = 0;
654 uint64_t latency = 0;
655 CHECK_AND_RETURN_LOG(ipcStream_ != nullptr, "ipcStream is not inited!");
656 int32_t ret = ipcStream_->GetAudioPosition(lastFlushReadIndex_, timestampVal, latency);
657 if (ret != SUCCESS) {
658 AUDIO_PRERELEASE_LOGE("Get position failed: %{public}u", ret);
659 return;
660 }
661 lastFramePosition_ = 0;
662 lastReadIdx_ = 0;
663 lastLatency_ = latency;
664 lastLatencyPosition_ = latency * speed_;
665 }
666
WriteMuteDataSysEvent(uint8_t * buffer,size_t bufferSize)667 void RendererInClientInner::WriteMuteDataSysEvent(uint8_t *buffer, size_t bufferSize)
668 {
669 if (silentModeAndMixWithOthers_) {
670 return;
671 }
672 if (IsInvalidBuffer(buffer, bufferSize)) {
673 if (startMuteTime_ == 0) {
674 startMuteTime_ = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
675 }
676 std::time_t currentTime = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
677 if ((currentTime - startMuteTime_ >= ONE_MINUTE) && !isUpEvent_) {
678 AUDIO_WARNING_LOG("write silent data for some time");
679 isUpEvent_ = true;
680 std::shared_ptr<Media::MediaMonitor::EventBean> bean = std::make_shared<Media::MediaMonitor::EventBean>(
681 Media::MediaMonitor::AUDIO, Media::MediaMonitor::BACKGROUND_SILENT_PLAYBACK,
682 Media::MediaMonitor::FREQUENCY_AGGREGATION_EVENT);
683 bean->Add("CLIENT_UID", appUid_);
684 Media::MediaMonitor::MediaMonitorManager::GetInstance().WriteLogMsg(bean);
685 }
686 } else if (buffer[0] != 0 && startMuteTime_ != 0) {
687 startMuteTime_ = 0;
688 }
689 }
690
IsInvalidBuffer(uint8_t * buffer,size_t bufferSize)691 bool RendererInClientInner::IsInvalidBuffer(uint8_t *buffer, size_t bufferSize)
692 {
693 bool isInvalid = false;
694 uint8_t ui8Data = 0;
695 int16_t i16Data = 0;
696 switch (clientConfig_.streamInfo.format) {
697 case SAMPLE_U8:
698 CHECK_AND_RETURN_RET_LOG(bufferSize > 0, false, "buffer size is too small");
699 ui8Data = *buffer;
700 isInvalid = ui8Data == 0;
701 break;
702 case SAMPLE_S16LE:
703 CHECK_AND_RETURN_RET_LOG(bufferSize > 1, false, "buffer size is too small");
704 i16Data = *(reinterpret_cast<const int16_t*>(buffer));
705 isInvalid = i16Data == 0;
706 break;
707 default:
708 break;
709 }
710 return isInvalid;
711 }
712
DrainIncompleteFrame(OptResult result,bool stopFlag,size_t targetSize,BufferDesc * desc,bool & dropIncompleteFrame)713 int32_t RendererInClientInner::DrainIncompleteFrame(OptResult result, bool stopFlag,
714 size_t targetSize, BufferDesc *desc, bool &dropIncompleteFrame)
715 {
716 if (result.size < clientSpanSizeInByte_ && stopFlag) {
717 result = ringCache_->Dequeue({desc->buffer, targetSize});
718 CHECK_AND_RETURN_RET_LOG(result.ret == OPERATION_SUCCESS, ERROR,
719 "ringCache Dequeue failed %{public}d", result.ret);
720 int32_t ret = memset_s(desc->buffer, targetSize, 0, targetSize);
721 CHECK_AND_RETURN_RET_LOG(ret == EOK, ERROR, "DrainIncompleteFrame memset output failed");
722 AUDIO_WARNING_LOG("incomplete frame is set to 0");
723 dropIncompleteFrame = true;
724 }
725 return SUCCESS;
726 }
727
728
WriteCacheData(bool isDrain,bool stopFlag)729 int32_t RendererInClientInner::WriteCacheData(bool isDrain, bool stopFlag)
730 {
731 Trace traceCache(isDrain ? "RendererInClientInner::DrainCacheData" : "RendererInClientInner::WriteCacheData");
732
733 OptResult result = ringCache_->GetReadableSize();
734 CHECK_AND_RETURN_RET_LOG(result.ret == OPERATION_SUCCESS, ERR_OPERATION_FAILED, "ring cache unreadable");
735 if (result.size == 0) {
736 AUDIO_WARNING_LOG("Readable size is already zero");
737 return SUCCESS;
738 }
739 size_t targetSize = isDrain ? std::min(result.size, clientSpanSizeInByte_) : clientSpanSizeInByte_;
740
741 int32_t sizeInFrame = clientBuffer_->GetAvailableDataFrames();
742 CHECK_AND_RETURN_RET_LOG(sizeInFrame >= 0, ERROR, "GetAvailableDataFrames invalid, %{public}d", sizeInFrame);
743
744 FutexCode futexRes = FUTEX_OPERATION_FAILED;
745 if (static_cast<uint32_t>(sizeInFrame) < spanSizeInFrame_) {
746 int32_t timeout = offloadEnable_ ? OFFLOAD_OPERATION_TIMEOUT_IN_MS : WRITE_CACHE_TIMEOUT_IN_MS;
747 futexRes = FutexTool::FutexWait(clientBuffer_->GetFutex(), static_cast<int64_t>(timeout) * AUDIO_US_PER_SECOND,
748 [this] () {
749 return (state_ != RUNNING) ||
750 (static_cast<uint32_t>(clientBuffer_->GetAvailableDataFrames()) >= spanSizeInFrame_);
751 });
752 CHECK_AND_RETURN_RET_LOG(state_ == RUNNING, ERR_ILLEGAL_STATE, "failed with state:%{public}d", state_.load());
753 CHECK_AND_RETURN_RET_LOG(futexRes != FUTEX_TIMEOUT, ERROR,
754 "write data time out, mode is %{public}s", (offloadEnable_ ? "offload" : "normal"));
755 sizeInFrame = clientBuffer_->GetAvailableDataFrames();
756 }
757
758 if (sizeInFrame < 0 || static_cast<uint32_t>(clientBuffer_->GetAvailableDataFrames()) < spanSizeInFrame_) {
759 AUDIO_ERR_LOG("failed: sizeInFrame is:%{public}d, futexRes:%{public}d", sizeInFrame, futexRes);
760 return ERROR;
761 }
762 BufferDesc desc = {};
763 uint64_t curWriteIndex = clientBuffer_->GetCurWriteFrame();
764 int32_t ret = clientBuffer_->GetWriteBuffer(curWriteIndex, desc);
765 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERROR, "GetWriteBuffer failed %{public}d", ret);
766 bool dropIncompleteFrame = false;
767 CHECK_AND_RETURN_RET_LOG(DrainIncompleteFrame(result, stopFlag, targetSize, &desc, dropIncompleteFrame) == SUCCESS,
768 ERROR, "DrainIncompleteFrame failed");
769 if (dropIncompleteFrame) {
770 return SUCCESS;
771 }
772 result = ringCache_->Dequeue({desc.buffer, targetSize});
773 CHECK_AND_RETURN_RET_LOG(result.ret == OPERATION_SUCCESS, ERROR, "ringCache Dequeue failed %{public}d", result.ret);
774 if (isDrain && targetSize < clientSpanSizeInByte_ && clientConfig_.streamInfo.format == SAMPLE_U8) {
775 size_t leftSize = clientSpanSizeInByte_ - targetSize;
776 int32_t ret = memset_s(desc.buffer + targetSize, leftSize, 0X7F, leftSize);
777 CHECK_AND_RETURN_RET_LOG(ret == EOK, ERROR, "left buffer memset output failed");
778 }
779 if (!ProcessVolume()) {
780 return ERR_OPERATION_FAILED;
781 }
782
783 DumpFileUtil::WriteDumpFile(dumpOutFd_, static_cast<void *>(desc.buffer), desc.bufLength);
784 VolumeTools::DfxOperation(desc, clientConfig_.streamInfo, traceTag_, volumeDataCount_);
785 clientBuffer_->SetCurWriteFrame(curWriteIndex + spanSizeInFrame_);
786
787 CHECK_AND_RETURN_RET_LOG(ipcStream_ != nullptr, ERR_OPERATION_FAILED, "WriteCacheData failed, null ipcStream_.");
788 ipcStream_->UpdatePosition(); // notiify server update position
789 HandleRendererPositionChanges(desc.bufLength);
790 return SUCCESS;
791 }
792
ProcessVolume()793 bool RendererInClientInner::ProcessVolume()
794 {
795 // volume process in client
796 if (volumeRamp_.IsActive()) {
797 // do not call SetVolume here.
798 clientVolume_ = volumeRamp_.GetRampVolume();
799 AUDIO_INFO_LOG("clientVolume_:%{public}f", clientVolume_);
800 Trace traceVolume("RendererInClientInner::WriteCacheData:Ramp:clientVolume_:" + std::to_string(clientVolume_));
801 SetInnerVolume(clientVolume_);
802 }
803 return true;
804 }
805
RegisterSpatializationStateEventListener()806 int32_t RendererInClientInner::RegisterSpatializationStateEventListener()
807 {
808 if (firstSpatializationRegistered_) {
809 firstSpatializationRegistered_ = false;
810 } else {
811 UnregisterSpatializationStateEventListener(spatializationRegisteredSessionID_);
812 }
813
814 if (!spatializationStateChangeCallback_) {
815 spatializationStateChangeCallback_ = std::make_shared<SpatializationStateChangeCallbackImpl>();
816 CHECK_AND_RETURN_RET_LOG(spatializationStateChangeCallback_, ERROR, "Memory Allocation Failed !!");
817 }
818 spatializationStateChangeCallback_->SetRendererInClientPtr(shared_from_this());
819
820 int32_t ret = AudioPolicyManager::GetInstance().RegisterSpatializationStateEventListener(
821 sessionId_, rendererInfo_.streamUsage, spatializationStateChangeCallback_);
822 CHECK_AND_RETURN_RET_LOG(ret == 0, ERROR, "RegisterSpatializationStateEventListener failed");
823 spatializationRegisteredSessionID_ = sessionId_;
824
825 return SUCCESS;
826 }
827
UnregisterSpatializationStateEventListener(uint32_t sessionID)828 int32_t RendererInClientInner::UnregisterSpatializationStateEventListener(uint32_t sessionID)
829 {
830 int32_t ret = AudioPolicyManager::GetInstance().UnregisterSpatializationStateEventListener(sessionID);
831 CHECK_AND_RETURN_RET_LOG(ret == 0, ERROR, "UnregisterSpatializationStateEventListener failed");
832 return SUCCESS;
833 }
834
DrainAudioStreamInner(bool stopFlag)835 bool RendererInClientInner::DrainAudioStreamInner(bool stopFlag)
836 {
837 Trace trace("RendererInClientInner::DrainAudioStreamInner " + std::to_string(sessionId_));
838 if (state_ != RUNNING) {
839 AUDIO_ERR_LOG("Drain failed. Illegal state:%{public}u", state_.load());
840 return false;
841 }
842 CHECK_AND_RETURN_RET_LOG(WriteCacheData(true, stopFlag) == SUCCESS, false, "Drain cache failed");
843
844 CHECK_AND_RETURN_RET_LOG(ipcStream_ != nullptr, false, "ipcStream is not inited!");
845 AUDIO_INFO_LOG("stopFlag:%{public}d", stopFlag);
846 int32_t ret = ipcStream_->Drain(stopFlag);
847 if (ret != SUCCESS) {
848 AUDIO_ERR_LOG("Drain call server failed:%{public}u", ret);
849 return false;
850 }
851 std::unique_lock<std::mutex> waitLock(callServerMutex_);
852 bool stopWaiting = callServerCV_.wait_for(waitLock, std::chrono::milliseconds(OPERATION_TIMEOUT_IN_MS), [this] {
853 return notifiedOperation_ == DRAIN_STREAM; // will be false when got notified.
854 });
855
856 // clear cbBufferQueue
857 if (renderMode_ == RENDER_MODE_CALLBACK && stopFlag) {
858 cbBufferQueue_.Clear();
859 if (memset_s(cbBuffer_.get(), cbBufferSize_, 0, cbBufferSize_) != EOK) {
860 AUDIO_ERR_LOG("memset_s buffer failed");
861 };
862 }
863
864 if (notifiedOperation_ != DRAIN_STREAM || notifiedResult_ != SUCCESS) {
865 AUDIO_ERR_LOG("Drain failed: %{public}s Operation:%{public}d result:%{public}" PRId64".",
866 (!stopWaiting ? "timeout" : "no timeout"), notifiedOperation_, notifiedResult_);
867 notifiedOperation_ = MAX_OPERATION_CODE;
868 return false;
869 }
870 notifiedOperation_ = MAX_OPERATION_CODE;
871 waitLock.unlock();
872 AUDIO_INFO_LOG("Drain stream SUCCESS, sessionId: %{public}d", sessionId_);
873 return true;
874 }
875
SpatializationStateChangeCallbackImpl()876 SpatializationStateChangeCallbackImpl::SpatializationStateChangeCallbackImpl()
877 {
878 AUDIO_INFO_LOG("Instance create");
879 }
880
~SpatializationStateChangeCallbackImpl()881 SpatializationStateChangeCallbackImpl::~SpatializationStateChangeCallbackImpl()
882 {
883 AUDIO_INFO_LOG("Instance destory");
884 }
885
SetRendererInClientPtr(std::shared_ptr<RendererInClientInner> rendererInClientPtr)886 void SpatializationStateChangeCallbackImpl::SetRendererInClientPtr(
887 std::shared_ptr<RendererInClientInner> rendererInClientPtr)
888 {
889 rendererInClientPtr_ = rendererInClientPtr;
890 }
891
OnSpatializationStateChange(const AudioSpatializationState & spatializationState)892 void SpatializationStateChangeCallbackImpl::OnSpatializationStateChange(
893 const AudioSpatializationState &spatializationState)
894 {
895 std::shared_ptr<RendererInClientInner> rendererInClient = rendererInClientPtr_.lock();
896 if (rendererInClient != nullptr) {
897 rendererInClient->OnSpatializationStateChange(spatializationState);
898 }
899 }
900 } // namespace AudioStandard
901 } // namespace OHOS