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 "AudioProcessInClientInner"
17 #endif
18
19 #include "audio_process_in_client.h"
20
21 #include <atomic>
22 #include <cinttypes>
23 #include <condition_variable>
24 #include <sstream>
25 #include <string>
26 #include <mutex>
27 #include <thread>
28
29 #include "iservice_registry.h"
30 #include "system_ability_definition.h"
31
32 #include "audio_errors.h"
33 #include "audio_capturer_log.h"
34 #include "audio_system_manager.h"
35 #include "audio_utils.h"
36 #include "securec.h"
37
38 #include "audio_manager_base.h"
39 #include "audio_process_cb_stub.h"
40 #include "audio_server_death_recipient.h"
41 #include "fast_audio_stream.h"
42 #include "i_audio_process.h"
43 #include "linear_pos_time_model.h"
44 #include "volume_tools.h"
45 #include "format_converter.h"
46
47 namespace OHOS {
48 namespace AudioStandard {
49
50 namespace {
51 static constexpr int32_t VOLUME_SHIFT_NUMBER = 16; // 1 >> 16 = 65536, max volume
52 static const int64_t DELAY_RESYNC_TIME = 10000000000; // 10s
53 constexpr int32_t RETRY_WAIT_TIME_MS = 500; // 500ms
54 constexpr int32_t MAX_RETRY_COUNT = 8;
55 }
56
57 class ProcessCbImpl;
58 class AudioProcessInClientInner : public AudioProcessInClient,
59 public std::enable_shared_from_this<AudioProcessInClientInner> {
60 public:
61 AudioProcessInClientInner(const sptr<IAudioProcess> &ipcProxy, bool isVoipMmap);
62 ~AudioProcessInClientInner();
63
64 int32_t SaveDataCallback(const std::shared_ptr<AudioDataCallback> &dataCallback) override;
65
66 int32_t SaveUnderrunCallback(const std::shared_ptr<ClientUnderrunCallBack> &underrunCallback) override;
67
68 int32_t GetBufferDesc(BufferDesc &bufDesc) const override;
69
70 int32_t Enqueue(const BufferDesc &bufDesc) const override;
71
72 int32_t SetVolume(int32_t vol) override;
73
74 int32_t Start() override;
75
76 int32_t Pause(bool isFlush) override;
77
78 int32_t Resume() override;
79
80 int32_t Stop() override;
81
82 int32_t Release(bool isSwitchStream = false) override;
83
84 // methods for support IAudioStream
85 int32_t GetSessionID(uint32_t &sessionID) override;
86
87 bool GetAudioTime(uint32_t &framePos, int64_t &sec, int64_t &nanoSec) override;
88
89 int32_t GetBufferSize(size_t &bufferSize) override;
90
91 int32_t GetFrameCount(uint32_t &frameCount) override;
92
93 int32_t GetLatency(uint64_t &latency) override;
94
95 int32_t SetVolume(float vol) override;
96
97 float GetVolume() override;
98
99 int32_t SetDuckVolume(float vol) override;
100
101 int32_t SetMute(bool mute) override;
102
103 int32_t SetSourceDuration(int64_t duration) override;
104
105 uint32_t GetUnderflowCount() override;
106
107 uint32_t GetOverflowCount() override;
108
109 void SetUnderflowCount(uint32_t underflowCount) override;
110
111 void SetOverflowCount(uint32_t overflowCount) override;
112
113 int64_t GetFramesWritten() override;
114
115 int64_t GetFramesRead() override;
116
117 void SetPreferredFrameSize(int32_t frameSize) override;
118
119 void UpdateLatencyTimestamp(std::string ×tamp, bool isRenderer) override;
120
121 bool Init(const AudioProcessConfig &config, std::weak_ptr<FastAudioStream> weakStream);
122
123 int32_t SetDefaultOutputDevice(const DeviceType defaultOutputDevice) override;
124
125 int32_t SetSilentModeAndMixWithOthers(bool on) override;
126
127 void GetRestoreInfo(RestoreInfo &restoreInfo) override;
128
129 void SetRestoreInfo(RestoreInfo &restoreInfo) override;
130
131 RestoreStatus CheckRestoreStatus() override;
132
133 RestoreStatus SetRestoreStatus(RestoreStatus restoreStatus) override;
134
135 static const sptr<IStandardAudioService> GetAudioServerProxy();
136 static void AudioServerDied(pid_t pid, pid_t uid);
137 static constexpr AudioStreamInfo g_targetStreamInfo = {SAMPLE_RATE_48000, ENCODING_PCM, SAMPLE_S16LE, STEREO};
138
139 private:
140 // move it to a common folder
141 static bool ChannelFormatConvert(const AudioStreamData &srcData, const AudioStreamData &dstData);
142
143 bool InitAudioBuffer();
144 void ResetAudioBuffer();
145
146 bool PrepareCurrent(uint64_t curWritePos);
147 void CallClientHandleCurrent();
148 bool FinishHandleCurrent(uint64_t &curWritePos, int64_t &clientWriteCost);
149 int32_t ReadFromProcessClient() const;
150 int32_t RecordReSyncServicePos();
151 int32_t RecordPrepareCurrent(uint64_t curReadPos);
152 int32_t RecordFinishHandleCurrent(uint64_t &curReadPos, int64_t &clientReadCost);
153 bool PrepareCurrentLoop(uint64_t curWritePos);
154 bool FinishHandleCurrentLoop(uint64_t &curWritePos, int64_t &clientWriteCost);
155
156 void UpdateHandleInfo(bool isAysnc = true, bool resetReadWritePos = false);
157 int64_t GetPredictNextHandleTime(uint64_t posInFrame, bool isIndependent = false);
158 bool PrepareNext(uint64_t curHandPos, int64_t &wakeUpTime);
159 bool ClientPrepareNextLoop(uint64_t curWritePos, int64_t &wakeUpTime);
160 bool PrepareNextIndependent(uint64_t curWritePos, int64_t &wakeUpTime);
161
162 std::string GetStatusInfo(StreamStatus status);
163 bool KeepLoopRunning();
164 bool KeepLoopRunningIndependent();
165
166 void CallExitStandBy();
167
168 bool ProcessCallbackFuc(uint64_t &curWritePos, int64_t &curTime, int64_t &wakeUpTime, int64_t &clientWriteCost);
169 void ProcessCallbackFucIndependent();
170 bool RecordProcessCallbackFuc(uint64_t &curReadPos, int64_t &wakeUpTime, int64_t clientReadCost);
171 void InitPlaybackThread(std::weak_ptr<FastAudioStream> weakStream);
172 void InitRecordThread(std::weak_ptr<FastAudioStream> weakStream);
173 void CopyWithVolume(const BufferDesc &srcDesc, const BufferDesc &dstDesc) const;
174 void ProcessVolume(const AudioStreamData &targetData) const;
175 int32_t ProcessData(const BufferDesc &srcDesc, const BufferDesc &dstDesc) const;
176 void CheckIfWakeUpTooLate(int64_t &curTime, int64_t &wakeUpTime);
177 void CheckIfWakeUpTooLate(int64_t &curTime, int64_t &wakeUpTime, int64_t clientWriteCost);
178
179 void DoFadeInOut(uint64_t &curWritePos);
180
181 private:
182 static constexpr int64_t MILLISECOND_PER_SECOND = 1000; // 1000ms
183 static constexpr int64_t ONE_MILLISECOND_DURATION = 1000000; // 1ms
184 static constexpr int64_t TWO_MILLISECOND_DURATION = 2000000; // 2ms
185 static constexpr int64_t VOIP_MILLISECOND_DURATION = 20000000; // 20ms
186 static constexpr int64_t MAX_WRITE_COST_DURATION_NANO = 5000000; // 5ms
187 static constexpr int64_t MAX_READ_COST_DURATION_NANO = 5000000; // 5ms
188 static constexpr int64_t WRITE_BEFORE_DURATION_NANO = 2000000; // 2ms
189 static constexpr int64_t RECORD_RESYNC_SLEEP_NANO = 2000000; // 2ms
190 static constexpr int64_t RECORD_HANDLE_DELAY_NANO = 3000000; // 3ms
191 static constexpr size_t MAX_TIMES = 4; // 4 times spanSizeInFrame_
192 static constexpr size_t DIV = 2; // halt of span
193 static constexpr int64_t MAX_STOP_FADING_DURATION_NANO = 10000000; // 10ms
194 static constexpr int64_t WAKE_UP_LATE_COUNT = 20; // late for 20 times
195 enum ThreadStatus : uint32_t {
196 WAITTING = 0,
197 SLEEPING,
198 INRUNNING,
199 INVALID
200 };
201 AudioProcessConfig processConfig_;
202 bool needConvert_ = false;
203 size_t clientByteSizePerFrame_ = 0;
204 size_t clientSpanSizeInByte_ = 0;
205 size_t clientSpanSizeInFrame_ = 240;
206 sptr<IAudioProcess> processProxy_ = nullptr;
207 std::shared_ptr<OHAudioBuffer> audioBuffer_ = nullptr;
208 uint32_t sessionId_ = 0;
209 bool isVoipMmap_ = false;
210
211 uint32_t totalSizeInFrame_ = 0;
212 uint32_t spanSizeInFrame_ = 0;
213 uint32_t byteSizePerFrame_ = 0;
214 uint32_t spanSizeInMs_ = 0;
215 size_t spanSizeInByte_ = 0;
216 std::weak_ptr<AudioDataCallback> audioDataCallback_;
217 std::weak_ptr<ClientUnderrunCallBack> underrunCallback_;
218
219 std::unique_ptr<uint8_t[]> callbackBuffer_ = nullptr;
220
221 std::mutex statusSwitchLock_;
222 std::atomic<StreamStatus> *streamStatus_ = nullptr;
223 bool isInited_ = false;
224 bool needReSyncPosition_ = true;
225 int64_t lastPausedTime_ = INT64_MAX;
226
227 float volumeInFloat_ = 1.0f;
228 float duckVolumeInFloat_ = 1.0f;
229 float muteVolumeInFloat_ = 1.0f;
230 int32_t processVolume_ = PROCESS_VOLUME_MAX; // 0 ~ 65536
231 LinearPosTimeModel handleTimeModel_;
232
233 std::thread callbackLoop_; // thread for callback to client and write.
234 bool isCallbackLoopEnd_ = false;
235 std::atomic<ThreadStatus> threadStatus_ = INVALID;
236 std::mutex loopThreadLock_;
237 std::condition_variable threadStatusCV_;
238
239 std::atomic<uint32_t> underflowCount_ = 0;
240 std::atomic<uint32_t> overflowCount_ = 0;
241
242 FILE *dumpFile_ = nullptr;
243 mutable int64_t volumeDataCount_ = 0;
244 std::string logUtilsTag_ = "";
245
246 std::atomic<bool> startFadein_ = false; // true-fade in when start or resume stream
247 std::atomic<bool> startFadeout_ = false; // true-fade out when pause or stop stream
248
249 sptr<ProcessCbImpl> processCbImpl_ = nullptr;
250 };
251
252 // ProcessCbImpl --> sptr | AudioProcessInClientInner --> shared_ptr
253 class ProcessCbImpl : public ProcessCbStub {
254 public:
255 explicit ProcessCbImpl(std::shared_ptr<AudioProcessInClientInner> processInClientInner);
256 virtual ~ProcessCbImpl() = default;
257
258 int32_t OnEndpointChange(int32_t status) override;
259
260 private:
261 std::weak_ptr<AudioProcessInClientInner> processInClientInner_;
262 };
263
ProcessCbImpl(std::shared_ptr<AudioProcessInClientInner> processInClientInner)264 ProcessCbImpl::ProcessCbImpl(std::shared_ptr<AudioProcessInClientInner> processInClientInner)
265 {
266 if (processInClientInner == nullptr) {
267 AUDIO_ERR_LOG("ProcessCbImpl() find null processInClientInner");
268 }
269 processInClientInner_ = processInClientInner;
270 }
271
OnEndpointChange(int32_t status)272 int32_t ProcessCbImpl::OnEndpointChange(int32_t status)
273 {
274 AUDIO_INFO_LOG("OnEndpointChange: %{public}d", status);
275 return SUCCESS;
276 }
277
278 std::mutex g_audioServerProxyMutex;
279 sptr<IStandardAudioService> gAudioServerProxy = nullptr;
280
AudioProcessInClientInner(const sptr<IAudioProcess> & ipcProxy,bool isVoipMmap)281 AudioProcessInClientInner::AudioProcessInClientInner(const sptr<IAudioProcess> &ipcProxy,
282 bool isVoipMmap) : processProxy_(ipcProxy), isVoipMmap_(isVoipMmap)
283 {
284 processProxy_->GetSessionId(sessionId_);
285 AUDIO_INFO_LOG("Construct with sessionId: %{public}d", sessionId_);
286 }
287
GetAudioServerProxy()288 const sptr<IStandardAudioService> AudioProcessInClientInner::GetAudioServerProxy()
289 {
290 std::lock_guard<std::mutex> lock(g_audioServerProxyMutex);
291 if (gAudioServerProxy == nullptr) {
292 auto samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
293 CHECK_AND_RETURN_RET_LOG(samgr != nullptr, nullptr, "get sa manager failed");
294 sptr<IRemoteObject> object = samgr->GetSystemAbility(AUDIO_DISTRIBUTED_SERVICE_ID);
295 CHECK_AND_RETURN_RET_LOG(object != nullptr, nullptr, "get audio service remote object failed");
296 gAudioServerProxy = iface_cast<IStandardAudioService>(object);
297 CHECK_AND_RETURN_RET_LOG(gAudioServerProxy != nullptr, nullptr, "get audio service proxy failed");
298
299 // register death recipent to restore proxy
300 sptr<AudioServerDeathRecipient> asDeathRecipient =
301 new(std::nothrow) AudioServerDeathRecipient(getpid(), getuid());
302 if (asDeathRecipient != nullptr) {
303 asDeathRecipient->SetNotifyCb([] (pid_t pid, pid_t uid) { AudioServerDied(pid, uid); });
304 bool result = object->AddDeathRecipient(asDeathRecipient);
305 if (!result) {
306 AUDIO_WARNING_LOG("failed to add deathRecipient");
307 }
308 }
309 }
310 sptr<IStandardAudioService> gasp = gAudioServerProxy;
311 return gasp;
312 }
313
314 /**
315 * When AudioServer died, all stream in client should be notified. As they were proxy stream ,the stub stream
316 * has been destoried in server.
317 */
AudioServerDied(pid_t pid,pid_t uid)318 void AudioProcessInClientInner::AudioServerDied(pid_t pid, pid_t uid)
319 {
320 AUDIO_INFO_LOG("audio server died, will restore proxy in next call");
321 std::lock_guard<std::mutex> lock(g_audioServerProxyMutex);
322 gAudioServerProxy = nullptr;
323 }
324
Create(const AudioProcessConfig & config,std::weak_ptr<FastAudioStream> weakStream)325 std::shared_ptr<AudioProcessInClient> AudioProcessInClient::Create(const AudioProcessConfig &config,
326 std::weak_ptr<FastAudioStream> weakStream)
327 {
328 AUDIO_INFO_LOG("Create with config: render flag %{public}d, capturer flag %{public}d, streamType %{public}d.",
329 config.rendererInfo.rendererFlags, config.capturerInfo.capturerFlags, config.streamType);
330 bool ret = AudioProcessInClient::CheckIfSupport(config);
331 CHECK_AND_RETURN_RET_LOG(config.audioMode != AUDIO_MODE_PLAYBACK || ret, nullptr,
332 "CheckIfSupport failed!");
333 sptr<IStandardAudioService> gasp = AudioProcessInClientInner::GetAudioServerProxy();
334 CHECK_AND_RETURN_RET_LOG(gasp != nullptr, nullptr, "Create failed, can not get service.");
335 AudioProcessConfig resetConfig = config;
336 bool isVoipMmap = false;
337 if (config.rendererInfo.streamUsage != STREAM_USAGE_VOICE_COMMUNICATION &&
338 config.capturerInfo.sourceType != SOURCE_TYPE_VOICE_COMMUNICATION) {
339 resetConfig.streamInfo = AudioProcessInClientInner::g_targetStreamInfo;
340 if (config.audioMode == AUDIO_MODE_RECORD) {
341 resetConfig.streamInfo.format = config.streamInfo.format;
342 resetConfig.streamInfo.channels = config.streamInfo.channels;
343 }
344 } else {
345 isVoipMmap = true;
346 }
347
348 int32_t errorCode = 0;
349 sptr<IRemoteObject> ipcProxy = gasp->CreateAudioProcess(resetConfig, errorCode);
350 for (int32_t retrycount = 0; (errorCode == ERR_RETRY_IN_CLIENT) && (retrycount < MAX_RETRY_COUNT); retrycount++) {
351 AUDIO_WARNING_LOG("retry in client");
352 std::this_thread::sleep_for(std::chrono::milliseconds(RETRY_WAIT_TIME_MS));
353 ipcProxy = gasp->CreateAudioProcess(config, errorCode);
354 }
355 CHECK_AND_RETURN_RET_LOG(errorCode == SUCCESS, nullptr, "failed with create audio stream fail.");
356 CHECK_AND_RETURN_RET_LOG(ipcProxy != nullptr, nullptr, "Create failed with null ipcProxy.");
357 sptr<IAudioProcess> iProcessProxy = iface_cast<IAudioProcess>(ipcProxy);
358 CHECK_AND_RETURN_RET_LOG(iProcessProxy != nullptr, nullptr, "Create failed when iface_cast.");
359 std::shared_ptr<AudioProcessInClientInner> process =
360 std::make_shared<AudioProcessInClientInner>(iProcessProxy, isVoipMmap);
361 if (!process->Init(config, weakStream)) {
362 AUDIO_ERR_LOG("Init failed!");
363 process = nullptr;
364 }
365
366 return process;
367 }
368
~AudioProcessInClientInner()369 AudioProcessInClientInner::~AudioProcessInClientInner()
370 {
371 AUDIO_INFO_LOG("AudioProcessInClient deconstruct.");
372 if (callbackLoop_.joinable()) {
373 std::unique_lock<std::mutex> lock(loopThreadLock_);
374 isCallbackLoopEnd_ = true; // change it with lock to break the loop
375 threadStatusCV_.notify_all();
376 lock.unlock(); // should call unlock before join
377 callbackLoop_.detach();
378 }
379 if (isInited_) {
380 AudioProcessInClientInner::Release();
381 }
382 DumpFileUtil::CloseDumpFile(&dumpFile_);
383 AUDIO_INFO_LOG("[%{public}s] volume data counts: %{public}" PRId64, logUtilsTag_.c_str(), volumeDataCount_);
384 }
385
GetSessionID(uint32_t & sessionID)386 int32_t AudioProcessInClientInner::GetSessionID(uint32_t &sessionID)
387 {
388 sessionID = sessionId_;
389 return SUCCESS;
390 }
391
GetAudioTime(uint32_t & framePos,int64_t & sec,int64_t & nanoSec)392 bool AudioProcessInClientInner::GetAudioTime(uint32_t &framePos, int64_t &sec, int64_t &nanoSec)
393 {
394 CHECK_AND_RETURN_RET_LOG(audioBuffer_ != nullptr, false, "buffer is null, maybe not inited.");
395 uint64_t pos = 0;
396 if (processConfig_.audioMode == AUDIO_MODE_PLAYBACK) {
397 pos = audioBuffer_->GetCurWriteFrame();
398 } else {
399 pos = audioBuffer_->GetCurReadFrame();
400 }
401
402 if (pos > UINT32_MAX) {
403 framePos = pos % UINT32_MAX;
404 } else {
405 framePos = static_cast<uint32_t>(pos);
406 }
407 int64_t time = handleTimeModel_.GetTimeOfPos(pos);
408 int64_t deltaTime = 20000000; // note: 20ms
409 time += deltaTime;
410
411 sec = time / AUDIO_NS_PER_SECOND;
412 nanoSec = time % AUDIO_NS_PER_SECOND;
413 return true;
414 }
415
GetBufferSize(size_t & bufferSize)416 int32_t AudioProcessInClientInner::GetBufferSize(size_t &bufferSize)
417 {
418 bufferSize = clientSpanSizeInByte_;
419 return SUCCESS;
420 }
421
GetFrameCount(uint32_t & frameCount)422 int32_t AudioProcessInClientInner::GetFrameCount(uint32_t &frameCount)
423 {
424 frameCount = static_cast<uint32_t>(clientSpanSizeInFrame_);
425 AUDIO_INFO_LOG ("GetFrameCount successfully, FrameCount: %{public}u", frameCount);
426 return SUCCESS;
427 }
428
GetLatency(uint64_t & latency)429 int32_t AudioProcessInClientInner::GetLatency(uint64_t &latency)
430 {
431 latency = 20; // 20ms for debug
432 return SUCCESS;
433 }
434
SetVolume(float vol)435 int32_t AudioProcessInClientInner::SetVolume(float vol)
436 {
437 float minVol = 0.0f;
438 float maxVol = 1.0f;
439 CHECK_AND_RETURN_RET_LOG(vol >= minVol && vol <= maxVol, ERR_INVALID_PARAM,
440 "SetVolume failed to with invalid volume:%{public}f", vol);
441 int32_t volumeInt = static_cast<int32_t>(vol * PROCESS_VOLUME_MAX);
442 int32_t ret = SetVolume(volumeInt);
443 if (ret == SUCCESS) {
444 volumeInFloat_ = vol;
445 }
446 return ret;
447 }
448
GetVolume()449 float AudioProcessInClientInner::GetVolume()
450 {
451 return volumeInFloat_;
452 }
453
SetMute(bool mute)454 int32_t AudioProcessInClientInner::SetMute(bool mute)
455 {
456 muteVolumeInFloat_ = mute ? 0.0f : 1.0f;
457 return SUCCESS;
458 }
459
SetSourceDuration(int64_t duration)460 int32_t AudioProcessInClientInner::SetSourceDuration(int64_t duration)
461 {
462 CHECK_AND_RETURN_RET_LOG(processProxy_ != nullptr, ERR_OPERATION_FAILED, "ipcProxy is null.");
463 return processProxy_->SetSourceDuration(duration);
464 }
465
SetDuckVolume(float vol)466 int32_t AudioProcessInClientInner::SetDuckVolume(float vol)
467 {
468 float minVol = 0.0f;
469 float maxVol = 1.0f;
470 CHECK_AND_RETURN_RET_LOG(vol >= minVol && vol <= maxVol, ERR_INVALID_PARAM,
471 "SetDuckVolume failed to with invalid volume:%{public}f", vol);
472 duckVolumeInFloat_ = vol;
473 return SUCCESS;
474 }
475
GetUnderflowCount()476 uint32_t AudioProcessInClientInner::GetUnderflowCount()
477 {
478 return underflowCount_.load();
479 }
480
GetOverflowCount()481 uint32_t AudioProcessInClientInner::GetOverflowCount()
482 {
483 return overflowCount_.load();
484 }
485
SetUnderflowCount(uint32_t underflowCount)486 void AudioProcessInClientInner::SetUnderflowCount(uint32_t underflowCount)
487 {
488 underflowCount_ += underflowCount;
489 }
490
SetOverflowCount(uint32_t overflowCount)491 void AudioProcessInClientInner::SetOverflowCount(uint32_t overflowCount)
492 {
493 overflowCount_ += overflowCount;
494 }
495
GetFramesWritten()496 int64_t AudioProcessInClientInner::GetFramesWritten()
497 {
498 CHECK_AND_RETURN_RET_LOG(processConfig_.audioMode == AUDIO_MODE_PLAYBACK, -1, "Playback not support.");
499 CHECK_AND_RETURN_RET_LOG(audioBuffer_ != nullptr, -1, "buffer is null, maybe not inited.");
500 return audioBuffer_->GetCurWriteFrame();
501 }
502
GetFramesRead()503 int64_t AudioProcessInClientInner::GetFramesRead()
504 {
505 CHECK_AND_RETURN_RET_LOG(processConfig_.audioMode == AUDIO_MODE_RECORD, -1, "Record not support.");
506 CHECK_AND_RETURN_RET_LOG(audioBuffer_ != nullptr, -1, "buffer is null, maybe not inited.");
507 return audioBuffer_->GetCurReadFrame();
508 }
509
SetPreferredFrameSize(int32_t frameSize)510 void AudioProcessInClientInner::SetPreferredFrameSize(int32_t frameSize)
511 {
512 size_t originalSpanSizeInFrame = static_cast<size_t>(spanSizeInFrame_);
513 size_t tmp = static_cast<size_t>(frameSize);
514 size_t count = static_cast<size_t>(frameSize) / spanSizeInFrame_;
515 size_t rest = static_cast<size_t>(frameSize) % spanSizeInFrame_;
516 if (tmp <= originalSpanSizeInFrame) {
517 clientSpanSizeInFrame_ = originalSpanSizeInFrame;
518 } else if (tmp >= MAX_TIMES * originalSpanSizeInFrame) {
519 clientSpanSizeInFrame_ = MAX_TIMES * originalSpanSizeInFrame;
520 } else {
521 if (rest <= originalSpanSizeInFrame / DIV) {
522 clientSpanSizeInFrame_ = count * spanSizeInFrame_;
523 } else {
524 count++;
525 clientSpanSizeInFrame_ = count * spanSizeInFrame_;
526 }
527 }
528 if (clientByteSizePerFrame_ == 0) {
529 clientSpanSizeInByte_ = count * spanSizeInByte_;
530 } else {
531 clientSpanSizeInByte_ = clientSpanSizeInFrame_ * clientByteSizePerFrame_;
532 }
533 callbackBuffer_ = std::make_unique<uint8_t[]>(clientSpanSizeInByte_);
534 AUDIO_INFO_LOG("Set preferred callbackBuffer size:%{public}zu", clientSpanSizeInByte_);
535 memset_s(callbackBuffer_.get(), clientSpanSizeInByte_, 0, clientSpanSizeInByte_);
536 }
537
UpdateLatencyTimestamp(std::string & timestamp,bool isRenderer)538 void AudioProcessInClientInner::UpdateLatencyTimestamp(std::string ×tamp, bool isRenderer)
539 {
540 sptr<IStandardAudioService> gasp = AudioProcessInClientInner::GetAudioServerProxy();
541 if (gasp == nullptr) {
542 AUDIO_ERR_LOG("LatencyMeas failed to get AudioServerProxy");
543 return;
544 }
545 gasp->UpdateLatencyTimestamp(timestamp, isRenderer);
546 }
547
InitAudioBuffer()548 bool AudioProcessInClientInner::InitAudioBuffer()
549 {
550 CHECK_AND_RETURN_RET_LOG(processProxy_ != nullptr, false, "Init failed with null ipcProxy.");
551 processCbImpl_ = sptr<ProcessCbImpl>::MakeSptr(shared_from_this());
552 CHECK_AND_RETURN_RET_LOG(processProxy_->RegisterProcessCb(processCbImpl_) == SUCCESS, false,
553 "RegisterProcessCb failed.");
554
555 int32_t ret = processProxy_->ResolveBuffer(audioBuffer_);
556 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS && audioBuffer_ != nullptr, false,
557 "Init failed to call ResolveBuffer");
558 streamStatus_ = audioBuffer_->GetStreamStatus();
559 CHECK_AND_RETURN_RET_LOG(streamStatus_ != nullptr, false, "Init failed, access buffer failed.");
560
561 audioBuffer_->GetSizeParameter(totalSizeInFrame_, spanSizeInFrame_, byteSizePerFrame_);
562 spanSizeInByte_ = spanSizeInFrame_ * byteSizePerFrame_;
563 spanSizeInMs_ = spanSizeInFrame_ * MILLISECOND_PER_SECOND / processConfig_.streamInfo.samplingRate;
564
565 clientSpanSizeInByte_ = spanSizeInFrame_ * clientByteSizePerFrame_;
566 clientSpanSizeInFrame_ = spanSizeInFrame_;
567 if ((processConfig_.audioMode != AUDIO_MODE_PLAYBACK) && (!isVoipMmap_)) {
568 clientSpanSizeInByte_ = spanSizeInByte_;
569 }
570
571 AUDIO_INFO_LOG("Using totalSizeInFrame_ %{public}d spanSizeInFrame_ %{public}d byteSizePerFrame_ %{public}d "
572 "spanSizeInByte_ %{public}zu, spanSizeInMs_ %{public}u", totalSizeInFrame_, spanSizeInFrame_,
573 byteSizePerFrame_, spanSizeInByte_, spanSizeInMs_);
574
575 callbackBuffer_ = std::make_unique<uint8_t[]>(clientSpanSizeInByte_);
576 CHECK_AND_RETURN_RET_LOG(callbackBuffer_ != nullptr, false, "Init callbackBuffer_ failed.");
577 memset_s(callbackBuffer_.get(), clientSpanSizeInByte_, 0, clientSpanSizeInByte_);
578 AUDIO_INFO_LOG("CallbackBufferSize is %{public}zu", clientSpanSizeInByte_);
579
580 return true;
581 }
582
GetFormatSize(const AudioStreamInfo & info)583 static size_t GetFormatSize(const AudioStreamInfo &info)
584 {
585 size_t result = 0;
586 size_t bitWidthSize = 0;
587 switch (info.format) {
588 case SAMPLE_U8:
589 bitWidthSize = 1; // size is 1
590 break;
591 case SAMPLE_S16LE:
592 bitWidthSize = 2; // size is 2
593 break;
594 case SAMPLE_S24LE:
595 bitWidthSize = 3; // size is 3
596 break;
597 case SAMPLE_S32LE:
598 bitWidthSize = 4; // size is 4
599 break;
600 case SAMPLE_F32LE:
601 bitWidthSize = 4; // size is 4
602 break;
603 default:
604 bitWidthSize = 2; // size is 2
605 break;
606 }
607
608 size_t channelSize = 0;
609 switch (info.channels) {
610 case MONO:
611 channelSize = 1; // size is 1
612 break;
613 case STEREO:
614 channelSize = 2; // size is 2
615 break;
616 default:
617 channelSize = 2; // size is 2
618 break;
619 }
620 result = bitWidthSize * channelSize;
621 return result;
622 }
623
InitPlaybackThread(std::weak_ptr<FastAudioStream> weakStream)624 void AudioProcessInClientInner::InitPlaybackThread(std::weak_ptr<FastAudioStream> weakStream)
625 {
626 logUtilsTag_ = "ProcessPlay::" + std::to_string(sessionId_);
627 auto weakProcess = weak_from_this();
628 callbackLoop_ = std::thread([weakStream, weakProcess] {
629 bool keepRunning = true;
630 uint64_t curWritePos = 0;
631 int64_t curTime = 0;
632 int64_t wakeUpTime = ClockTime::GetCurNano();
633 int64_t clientWriteCost = 0;
634 std::shared_ptr<AudioProcessInClientInner> strongProcess = weakProcess.lock();
635 std::shared_ptr<FastAudioStream> strongStream = weakStream.lock();
636 if (strongProcess != nullptr) {
637 AUDIO_INFO_LOG("Callback loop of session %{public}u start", strongProcess->sessionId_);
638 strongProcess->processProxy_->RegisterThreadPriority(gettid(),
639 AudioSystemManager::GetInstance()->GetSelfBundleName(strongProcess->processConfig_.appInfo.appUid));
640 } else {
641 AUDIO_WARNING_LOG("Strong ref is nullptr, could cause error");
642 }
643 strongProcess = nullptr;
644 // Callback loop
645 while (keepRunning) {
646 strongStream = weakStream.lock();
647 strongProcess = weakProcess.lock();
648 // Check if FastAudioStream or AudioProcessInClientInner is already destroyed to avoid use after free.
649 CHECK_AND_BREAK_LOG(strongStream != nullptr, "FastAudioStream destroyed, exit AudioPlayCb");
650 CHECK_AND_BREAK_LOG(strongProcess != nullptr, "AudioProcessInClientInner destroyed, exit AudioPlayCb");
651 // Main operation in callback loop
652 keepRunning = strongProcess->ProcessCallbackFuc(curWritePos, curTime, wakeUpTime, clientWriteCost);
653 }
654 if (strongProcess != nullptr) {
655 AUDIO_INFO_LOG("Callback loop of session %{public}u end", strongProcess->sessionId_);
656 }
657 });
658 pthread_setname_np(callbackLoop_.native_handle(), "OS_AudioPlayCb");
659 }
660
InitRecordThread(std::weak_ptr<FastAudioStream> weakStream)661 void AudioProcessInClientInner::InitRecordThread(std::weak_ptr<FastAudioStream> weakStream)
662 {
663 logUtilsTag_ = "ProcessRec::" + std::to_string(sessionId_);
664 auto weakProcess = weak_from_this();
665 callbackLoop_ = std::thread([weakStream, weakProcess] {
666 bool keepRunning = true;
667 uint64_t curReadPos = 0;
668 int64_t wakeUpTime = ClockTime::GetCurNano();
669 int64_t clientReadCost = 0;
670 std::shared_ptr<AudioProcessInClientInner> strongProcess = weakProcess.lock();
671 std::shared_ptr<FastAudioStream> strongStream = weakStream.lock();
672 if (strongProcess != nullptr) {
673 AUDIO_INFO_LOG("Callback loop of session %{public}u start", strongProcess->sessionId_);
674 strongProcess->processProxy_->RegisterThreadPriority(gettid(),
675 AudioSystemManager::GetInstance()->GetSelfBundleName(strongProcess->processConfig_.appInfo.appUid));
676 } else {
677 AUDIO_WARNING_LOG("Strong ref is nullptr, could cause error");
678 }
679 strongProcess = nullptr;
680 // Callback loop
681 while (keepRunning) {
682 strongStream = weakStream.lock();
683 strongProcess = weakProcess.lock();
684 // Check if FastAudioStream or AudioProcessInClientInner is already destroyed to avoid use after free.
685 CHECK_AND_BREAK_LOG(strongStream != nullptr, "FastAudioStream destroyed, exit AudioPlayCb");
686 CHECK_AND_BREAK_LOG(strongProcess != nullptr, "AudioProcessInClientInner destroyed, exit AudioPlayCb");
687 // Main operation in callback loop
688 keepRunning = strongProcess->RecordProcessCallbackFuc(curReadPos, wakeUpTime, clientReadCost);
689 }
690 if (strongProcess != nullptr) {
691 AUDIO_INFO_LOG("Callback loop of session %{public}u end", strongProcess->sessionId_);
692 }
693 });
694 pthread_setname_np(callbackLoop_.native_handle(), "OS_AudioRecCb");
695 }
696
Init(const AudioProcessConfig & config,std::weak_ptr<FastAudioStream> weakStream)697 bool AudioProcessInClientInner::Init(const AudioProcessConfig &config, std::weak_ptr<FastAudioStream> weakStream)
698 {
699 AUDIO_INFO_LOG("Call Init.");
700 processConfig_ = config;
701 if (!isVoipMmap_ && (config.streamInfo.format != g_targetStreamInfo.format ||
702 config.streamInfo.channels != g_targetStreamInfo.channels)) {
703 needConvert_ = true;
704 }
705 clientByteSizePerFrame_ = GetFormatSize(config.streamInfo);
706
707 AUDIO_DEBUG_LOG("Using clientByteSizePerFrame_:%{public}zu", clientByteSizePerFrame_);
708 bool isBufferInited = InitAudioBuffer();
709 CHECK_AND_RETURN_RET_LOG(isBufferInited, isBufferInited, "%{public}s init audio buffer fail.", __func__);
710
711 bool ret = handleTimeModel_.ConfigSampleRate(processConfig_.streamInfo.samplingRate);
712 CHECK_AND_RETURN_RET_LOG(ret != false, false, "Init LinearPosTimeModel failed.");
713 uint64_t handlePos = 0;
714 int64_t handleTime = 0;
715 audioBuffer_->GetHandleInfo(handlePos, handleTime);
716 handleTimeModel_.ResetFrameStamp(handlePos, handleTime);
717
718 streamStatus_->store(StreamStatus::STREAM_IDEL);
719
720 AudioBufferHolder bufferHolder = audioBuffer_->GetBufferHolder();
721 bool isIndependent = bufferHolder == AudioBufferHolder::AUDIO_SERVER_INDEPENDENT;
722 if (config.audioMode == AUDIO_MODE_RECORD) {
723 InitRecordThread(weakStream);
724 } else if (isIndependent) {
725 logUtilsTag_ = "ProcessPlay::" + std::to_string(sessionId_);
726 callbackLoop_ = std::thread([this] { this->ProcessCallbackFucIndependent(); });
727 pthread_setname_np(callbackLoop_.native_handle(), "OS_AudioPlayCb");
728 } else {
729 InitPlaybackThread(weakStream);
730 }
731
732 int waitThreadStartTime = 5; // wait for thread start.
733 while (threadStatus_.load() == INVALID) {
734 AUDIO_DEBUG_LOG("%{public}s wait %{public}d ms for %{public}s started...", __func__, waitThreadStartTime,
735 config.audioMode == AUDIO_MODE_RECORD ? "RecordProcessCallbackFuc" : "ProcessCallbackFuc");
736 ClockTime::RelativeSleep(ONE_MILLISECOND_DURATION * waitThreadStartTime);
737 }
738
739 isInited_ = true;
740 return true;
741 }
742
SaveDataCallback(const std::shared_ptr<AudioDataCallback> & dataCallback)743 int32_t AudioProcessInClientInner::SaveDataCallback(const std::shared_ptr<AudioDataCallback> &dataCallback)
744 {
745 AUDIO_INFO_LOG("%{public}s enter.", __func__);
746 CHECK_AND_RETURN_RET_LOG(isInited_, ERR_ILLEGAL_STATE, "not inited!");
747
748 CHECK_AND_RETURN_RET_LOG(dataCallback != nullptr, ERR_INVALID_PARAM,
749 "data callback is null.");
750 audioDataCallback_ = dataCallback;
751 return SUCCESS;
752 }
753
SaveUnderrunCallback(const std::shared_ptr<ClientUnderrunCallBack> & underrunCallback)754 int32_t AudioProcessInClientInner::SaveUnderrunCallback(const std::shared_ptr<ClientUnderrunCallBack> &underrunCallback)
755 {
756 AUDIO_INFO_LOG("%{public}s enter.", __func__);
757 CHECK_AND_RETURN_RET_LOG(isInited_, ERR_ILLEGAL_STATE, "not inited!");
758
759 CHECK_AND_RETURN_RET_LOG(underrunCallback != nullptr, ERR_INVALID_PARAM,
760 "underrun callback is null.");
761 underrunCallback_ = underrunCallback;
762 return SUCCESS;
763 }
764
ReadFromProcessClient() const765 int32_t AudioProcessInClientInner::ReadFromProcessClient() const
766 {
767 CHECK_AND_RETURN_RET_LOG(audioBuffer_ != nullptr, ERR_INVALID_HANDLE,
768 "%{public}s audio buffer is null.", __func__);
769 uint64_t curReadPos = audioBuffer_->GetCurReadFrame();
770 Trace trace("AudioProcessInClient::ReadProcessData-<" + std::to_string(curReadPos));
771 BufferDesc readbufDesc = {nullptr, 0, 0};
772 int32_t ret = audioBuffer_->GetReadbuffer(curReadPos, readbufDesc);
773 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS && readbufDesc.buffer != nullptr &&
774 readbufDesc.bufLength == spanSizeInByte_ && readbufDesc.dataLength == spanSizeInByte_,
775 ERR_OPERATION_FAILED, "get client mmap read buffer failed, ret %{public}d.", ret);
776 ret = memcpy_s(static_cast<void *>(callbackBuffer_.get()), spanSizeInByte_,
777 static_cast<void *>(readbufDesc.buffer), spanSizeInByte_);
778 CHECK_AND_RETURN_RET_LOG(ret == EOK, ERR_OPERATION_FAILED, "%{public}s memcpy fail, ret %{public}d,"
779 " spanSizeInByte %{public}zu.", __func__, ret, spanSizeInByte_);
780 DumpFileUtil::WriteDumpFile(dumpFile_, static_cast<void *>(readbufDesc.buffer), spanSizeInByte_);
781 VolumeTools::DfxOperation(readbufDesc, processConfig_.streamInfo, logUtilsTag_, volumeDataCount_);
782
783 ret = memset_s(readbufDesc.buffer, readbufDesc.bufLength, 0, readbufDesc.bufLength);
784 if (ret != EOK) {
785 AUDIO_WARNING_LOG("reset buffer fail, ret %{public}d.", ret);
786 }
787 return SUCCESS;
788 }
789
790 // the buffer will be used by client
GetBufferDesc(BufferDesc & bufDesc) const791 int32_t AudioProcessInClientInner::GetBufferDesc(BufferDesc &bufDesc) const
792 {
793 CHECK_AND_RETURN_RET_LOG(isInited_, ERR_ILLEGAL_STATE, "%{public}s not inited!", __func__);
794 Trace trace("AudioProcessInClient::GetBufferDesc");
795
796 if (processConfig_.audioMode == AUDIO_MODE_RECORD) {
797 ReadFromProcessClient();
798 }
799
800 bufDesc.buffer = callbackBuffer_.get();
801 bufDesc.dataLength = clientSpanSizeInByte_;
802 bufDesc.bufLength = clientSpanSizeInByte_;
803 return SUCCESS;
804 }
805
CheckIfSupport(const AudioProcessConfig & config)806 bool AudioProcessInClient::CheckIfSupport(const AudioProcessConfig &config)
807 {
808 if (config.rendererInfo.streamUsage == STREAM_USAGE_VOICE_COMMUNICATION ||
809 config.capturerInfo.sourceType == SOURCE_TYPE_VOICE_COMMUNICATION) {
810 return true;
811 }
812
813 if (config.streamInfo.samplingRate != SAMPLE_RATE_48000) {
814 return false;
815 }
816
817 if (config.streamInfo.encoding != ENCODING_PCM) {
818 return false;
819 }
820
821 if (config.streamInfo.format != SAMPLE_S16LE && config.streamInfo.format != SAMPLE_S32LE &&
822 config.streamInfo.format != SAMPLE_F32LE) {
823 return false;
824 }
825
826 if (config.streamInfo.channels != MONO && config.streamInfo.channels != STEREO) {
827 return false;
828 }
829 return true;
830 }
831
S16MonoToS16Stereo(const BufferDesc & srcDesc,const BufferDesc & dstDesc)832 inline bool S16MonoToS16Stereo(const BufferDesc &srcDesc, const BufferDesc &dstDesc)
833 {
834 size_t half = 2;
835 if (srcDesc.bufLength != dstDesc.bufLength / half || srcDesc.buffer == nullptr || dstDesc.buffer == nullptr) {
836 return false;
837 }
838 int16_t *stcPtr = reinterpret_cast<int16_t *>(srcDesc.buffer);
839 int16_t *dstPtr = reinterpret_cast<int16_t *>(dstDesc.buffer);
840 size_t count = srcDesc.bufLength / half;
841 for (size_t idx = 0; idx < count; idx++) {
842 *(dstPtr++) = *stcPtr;
843 *(dstPtr++) = *stcPtr++;
844 }
845 return true;
846 }
847
S32MonoToS16Stereo(const BufferDesc & srcDesc,const BufferDesc & dstDesc)848 inline bool S32MonoToS16Stereo(const BufferDesc &srcDesc, const BufferDesc &dstDesc)
849 {
850 size_t quarter = 4;
851 if (srcDesc.bufLength != dstDesc.bufLength || srcDesc.buffer == nullptr || dstDesc.buffer == nullptr ||
852 srcDesc.bufLength % quarter != 0) {
853 return false;
854 }
855 int32_t *stcPtr = reinterpret_cast<int32_t *>(srcDesc.buffer);
856 int16_t *dstPtr = reinterpret_cast<int16_t *>(dstDesc.buffer);
857 size_t count = srcDesc.bufLength / quarter;
858
859 double maxInt32 = INT32_MAX;
860 double maxInt16 = INT16_MAX;
861 for (size_t idx = 0; idx < count; idx++) {
862 int16_t temp = static_cast<int16_t>((static_cast<double>(*stcPtr) / maxInt32) * maxInt16);
863 stcPtr++;
864 *(dstPtr++) = temp;
865 *(dstPtr++) = temp;
866 }
867 return true;
868 }
869
S32StereoS16Stereo(const BufferDesc & srcDesc,const BufferDesc & dstDesc)870 inline bool S32StereoS16Stereo(const BufferDesc &srcDesc, const BufferDesc &dstDesc)
871 {
872 size_t half = 2;
873 if (srcDesc.bufLength / half != dstDesc.bufLength || srcDesc.buffer == nullptr || dstDesc.buffer == nullptr ||
874 dstDesc.bufLength % half != 0) {
875 return false;
876 }
877 int32_t *stcPtr = reinterpret_cast<int32_t *>(srcDesc.buffer);
878 int16_t *dstPtr = reinterpret_cast<int16_t *>(dstDesc.buffer);
879 size_t count = srcDesc.bufLength / half / half;
880 double maxInt32 = INT32_MAX;
881 double maxInt16 = INT16_MAX;
882 for (size_t idx = 0; idx < count; idx++) {
883 int16_t temp = static_cast<int16_t>((static_cast<double>(*stcPtr) / maxInt32) * maxInt16);
884 stcPtr++;
885 *(dstPtr++) = temp;
886 }
887 return true;
888 }
889
890 // only support MONO to STEREO and SAMPLE_S32LE to SAMPLE_S16LE
ChannelFormatConvert(const AudioStreamData & srcData,const AudioStreamData & dstData)891 bool AudioProcessInClientInner::ChannelFormatConvert(const AudioStreamData &srcData, const AudioStreamData &dstData)
892 {
893 if (srcData.streamInfo.samplingRate != dstData.streamInfo.samplingRate ||
894 srcData.streamInfo.encoding != dstData.streamInfo.encoding) {
895 return false;
896 }
897 if (srcData.streamInfo.format == SAMPLE_S16LE && srcData.streamInfo.channels == STEREO) {
898 return true; // no need convert
899 }
900 if (srcData.streamInfo.format == SAMPLE_S16LE && srcData.streamInfo.channels == MONO) {
901 return S16MonoToS16Stereo(srcData.bufferDesc, dstData.bufferDesc);
902 }
903 if (srcData.streamInfo.format == SAMPLE_S32LE && srcData.streamInfo.channels == MONO) {
904 return S32MonoToS16Stereo(srcData.bufferDesc, dstData.bufferDesc);
905 }
906 if (srcData.streamInfo.format == SAMPLE_S32LE && srcData.streamInfo.channels == STEREO) {
907 return S32StereoS16Stereo(srcData.bufferDesc, dstData.bufferDesc);
908 }
909 if (srcData.streamInfo.format == SAMPLE_F32LE && srcData.streamInfo.channels == MONO) {
910 return FormatConverter::F32MonoToS16Stereo(srcData.bufferDesc, dstData.bufferDesc);
911 }
912 if (srcData.streamInfo.format == SAMPLE_F32LE && srcData.streamInfo.channels == STEREO) {
913 return FormatConverter::F32StereoToS16Stereo(srcData.bufferDesc, dstData.bufferDesc);
914 }
915
916 return false;
917 }
918
CopyWithVolume(const BufferDesc & srcDesc,const BufferDesc & dstDesc) const919 void AudioProcessInClientInner::CopyWithVolume(const BufferDesc &srcDesc, const BufferDesc &dstDesc) const
920 {
921 size_t len = dstDesc.dataLength;
922 len /= 2; // SAMPLE_S16LE--> 2 byte
923 int16_t *dstPtr = reinterpret_cast<int16_t *>(dstDesc.buffer);
924 for (size_t pos = 0; len > 0; len--) {
925 int32_t sum = 0;
926 int16_t *srcPtr = reinterpret_cast<int16_t *>(srcDesc.buffer) + pos;
927 sum += (*srcPtr * static_cast<int64_t>(processVolume_ * duckVolumeInFloat_ *
928 muteVolumeInFloat_)) >> VOLUME_SHIFT_NUMBER; // 1/65536
929 pos++;
930 *dstPtr++ = sum > INT16_MAX ? INT16_MAX : (sum < INT16_MIN ? INT16_MIN : sum);
931 }
932 }
933
ProcessVolume(const AudioStreamData & targetData) const934 void AudioProcessInClientInner::ProcessVolume(const AudioStreamData &targetData) const
935 {
936 size_t half = 2;
937 size_t len = targetData.bufferDesc.dataLength;
938 len /= half;
939 int16_t *dstPtr = reinterpret_cast<int16_t *>(targetData.bufferDesc.buffer);
940 for (; len > 0; len--) {
941 int32_t sum = 0;
942 sum += (*dstPtr * static_cast<int64_t>(processVolume_ * duckVolumeInFloat_ *
943 muteVolumeInFloat_)) >> VOLUME_SHIFT_NUMBER;
944 *dstPtr++ = sum > INT16_MAX ? INT16_MAX : (sum < INT16_MIN ? INT16_MIN : sum);
945 }
946 }
947
ProcessData(const BufferDesc & srcDesc,const BufferDesc & dstDesc) const948 int32_t AudioProcessInClientInner::ProcessData(const BufferDesc &srcDesc, const BufferDesc &dstDesc) const
949 {
950 int32_t ret = 0;
951 size_t round = (spanSizeInFrame_ == 0 ? 1 : clientSpanSizeInFrame_ / spanSizeInFrame_);
952 size_t offSet = clientSpanSizeInByte_ / round;
953 if (!needConvert_) {
954 AudioBufferHolder bufferHolder = audioBuffer_->GetBufferHolder();
955 if (bufferHolder == AudioBufferHolder::AUDIO_SERVER_INDEPENDENT) {
956 CopyWithVolume(srcDesc, dstDesc);
957 } else {
958 ret = memcpy_s(static_cast<void *>(dstDesc.buffer), spanSizeInByte_,
959 static_cast<void *>(srcDesc.buffer), offSet);
960 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_OPERATION_FAILED, "Copy data failed!");
961 }
962 } else {
963 Trace traceConvert("APIC::FormatConvert");
964 AudioStreamData srcData = {processConfig_.streamInfo, srcDesc, 0, 0};
965 AudioStreamData dstData = {g_targetStreamInfo, dstDesc, 0, 0};
966 bool succ = ChannelFormatConvert(srcData, dstData);
967 CHECK_AND_RETURN_RET_LOG(succ, ERR_OPERATION_FAILED, "Convert data failed!");
968 AudioBufferHolder bufferHolder = audioBuffer_->GetBufferHolder();
969 if (bufferHolder == AudioBufferHolder::AUDIO_SERVER_INDEPENDENT) {
970 ProcessVolume(dstData);
971 }
972 }
973 return SUCCESS;
974 }
975
Enqueue(const BufferDesc & bufDesc) const976 int32_t AudioProcessInClientInner::Enqueue(const BufferDesc &bufDesc) const
977 {
978 Trace trace("AudioProcessInClient::Enqueue");
979 CHECK_AND_RETURN_RET_LOG(isInited_, ERR_ILLEGAL_STATE, "not inited!");
980
981 CHECK_AND_RETURN_RET_LOG(bufDesc.buffer != nullptr && bufDesc.bufLength == clientSpanSizeInByte_ &&
982 bufDesc.dataLength == clientSpanSizeInByte_, ERR_INVALID_PARAM,
983 "bufDesc error, bufLen %{public}zu, dataLen %{public}zu, spanSize %{public}zu.",
984 bufDesc.bufLength, bufDesc.dataLength, clientSpanSizeInByte_);
985 // check if this buffer is form us.
986 if (bufDesc.buffer != callbackBuffer_.get()) {
987 AUDIO_WARNING_LOG("the buffer is not created by client.");
988 }
989
990 size_t round = (spanSizeInFrame_ == 0 ? 1 : clientSpanSizeInFrame_ / spanSizeInFrame_);
991 uint64_t curWritePos = audioBuffer_->GetCurWriteFrame();
992 for (size_t count = 0 ; count < round ; count++) {
993 BufferDesc curCallbackBuffer = {nullptr, 0, 0};
994 size_t offSet = clientSpanSizeInByte_ / round;
995 curCallbackBuffer.buffer = bufDesc.buffer + count * offSet;
996 curCallbackBuffer.bufLength = offSet;
997 curCallbackBuffer.dataLength = offSet;
998 uint64_t curPos = curWritePos + count * spanSizeInFrame_;
999 if (processConfig_.audioMode == AUDIO_MODE_PLAYBACK) {
1000 BufferDesc curWriteBuffer = {nullptr, 0, 0};
1001 Trace writeProcessDataTrace("AudioProcessInClient::WriteProcessData->" + std::to_string(curPos));
1002 int32_t ret = audioBuffer_->GetWriteBuffer(curPos, curWriteBuffer);
1003 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS && curWriteBuffer.buffer != nullptr &&
1004 curWriteBuffer.bufLength == spanSizeInByte_ && curWriteBuffer.dataLength == spanSizeInByte_,
1005 ERR_OPERATION_FAILED, "get write buffer fail, ret:%{public}d", ret);
1006 ret = ProcessData(curCallbackBuffer, curWriteBuffer);
1007 if (ret != SUCCESS) {
1008 return ERR_OPERATION_FAILED;
1009 }
1010 writeProcessDataTrace.End();
1011
1012 DumpFileUtil::WriteDumpFile(dumpFile_, static_cast<void *>(curCallbackBuffer.buffer), offSet);
1013 VolumeTools::DfxOperation(curCallbackBuffer, processConfig_.streamInfo, logUtilsTag_, volumeDataCount_);
1014 }
1015 }
1016
1017 if (memset_s(callbackBuffer_.get(), clientSpanSizeInByte_, 0, clientSpanSizeInByte_) != EOK) {
1018 AUDIO_WARNING_LOG("reset callback buffer fail.");
1019 }
1020
1021 return SUCCESS;
1022 }
1023
SetVolume(int32_t vol)1024 int32_t AudioProcessInClientInner::SetVolume(int32_t vol)
1025 {
1026 AUDIO_INFO_LOG("proc client mode %{public}d to %{public}d.", processConfig_.audioMode, vol);
1027 Trace trace("AudioProcessInClient::SetVolume " + std::to_string(vol));
1028 CHECK_AND_RETURN_RET_LOG(vol >= 0 && vol <= PROCESS_VOLUME_MAX, ERR_INVALID_PARAM,
1029 "SetVolume failed, invalid volume:%{public}d", vol);
1030 processVolume_ = vol;
1031 return SUCCESS;
1032 }
1033
Start()1034 int32_t AudioProcessInClientInner::Start()
1035 {
1036 Trace traceStart("AudioProcessInClient::Start");
1037 CHECK_AND_RETURN_RET_LOG(isInited_, ERR_ILLEGAL_STATE, "not inited!");
1038
1039 const auto [samplingRate, encoding, format, channels, channelLayout] = processConfig_.streamInfo;
1040 // eg: 100005_dump_process_client_audio_48000_2_1.pcm
1041 std::string dumpFileName = std::to_string(sessionId_) + "_dump_process_client_audio_" +
1042 std::to_string(samplingRate) + '_' + std::to_string(channels) + '_' + std::to_string(format) +
1043 ".pcm";
1044 DumpFileUtil::OpenDumpFile(DumpFileUtil::DUMP_CLIENT_PARA, dumpFileName, &dumpFile_);
1045
1046 std::lock_guard<std::mutex> lock(statusSwitchLock_);
1047 if (streamStatus_->load() == StreamStatus::STREAM_RUNNING) {
1048 AUDIO_INFO_LOG("Start find already started");
1049 return SUCCESS;
1050 }
1051
1052 startFadein_.store(true);
1053 StreamStatus targetStatus = StreamStatus::STREAM_IDEL;
1054 bool ret = streamStatus_->compare_exchange_strong(targetStatus, StreamStatus::STREAM_STARTING);
1055 if (!ret) {
1056 startFadein_.store(false);
1057 }
1058 CHECK_AND_RETURN_RET_LOG(
1059 ret, ERR_ILLEGAL_STATE, "Start failed, invalid status: %{public}s", GetStatusInfo(targetStatus).c_str());
1060
1061 if (processProxy_->Start() != SUCCESS) {
1062 streamStatus_->store(StreamStatus::STREAM_IDEL);
1063 AUDIO_ERR_LOG("Start failed to call process proxy, reset status to IDEL.");
1064 startFadein_.store(false);
1065 threadStatusCV_.notify_all();
1066 return ERR_OPERATION_FAILED;
1067 }
1068 UpdateHandleInfo();
1069 streamStatus_->store(StreamStatus::STREAM_RUNNING);
1070 threadStatusCV_.notify_all();
1071 return SUCCESS;
1072 }
1073
Pause(bool isFlush)1074 int32_t AudioProcessInClientInner::Pause(bool isFlush)
1075 {
1076 Trace tracePause("AudioProcessInClient::Pause");
1077 CHECK_AND_RETURN_RET_LOG(isInited_, ERR_ILLEGAL_STATE, "not inited!");
1078
1079 std::lock_guard<std::mutex> lock(statusSwitchLock_);
1080 if (streamStatus_->load() == StreamStatus::STREAM_PAUSED) {
1081 AUDIO_INFO_LOG("Pause find already paused");
1082 return SUCCESS;
1083 }
1084 startFadeout_.store(true);
1085 StreamStatus targetStatus = StreamStatus::STREAM_RUNNING;
1086 bool ret = streamStatus_->compare_exchange_strong(targetStatus, StreamStatus::STREAM_PAUSING);
1087 if (!ret) {
1088 startFadeout_.store(false);
1089 }
1090 CHECK_AND_RETURN_RET_LOG(
1091 ret, ERR_ILLEGAL_STATE, "Pause failed, invalid status : %{public}s", GetStatusInfo(targetStatus).c_str());
1092 ClockTime::RelativeSleep(MAX_STOP_FADING_DURATION_NANO);
1093 if (processProxy_->Pause(isFlush) != SUCCESS) {
1094 streamStatus_->store(StreamStatus::STREAM_RUNNING);
1095 AUDIO_ERR_LOG("Pause failed to call process proxy, reset status to RUNNING");
1096 startFadeout_.store(false);
1097 threadStatusCV_.notify_all(); // avoid thread blocking with status PAUSING
1098 return ERR_OPERATION_FAILED;
1099 }
1100 startFadeout_.store(false);
1101 streamStatus_->store(StreamStatus::STREAM_PAUSED);
1102
1103 lastPausedTime_ = ClockTime::GetCurNano();
1104
1105 return SUCCESS;
1106 }
1107
Resume()1108 int32_t AudioProcessInClientInner::Resume()
1109 {
1110 Trace traceResume("AudioProcessInClient::Resume");
1111 CHECK_AND_RETURN_RET_LOG(isInited_, ERR_ILLEGAL_STATE, "not inited!");
1112 std::lock_guard<std::mutex> lock(statusSwitchLock_);
1113
1114 if (streamStatus_->load() == StreamStatus::STREAM_RUNNING) {
1115 AUDIO_INFO_LOG("Resume find already running");
1116 return SUCCESS;
1117 }
1118
1119 startFadein_.store(true);
1120
1121 StreamStatus pausedStatus = StreamStatus::STREAM_PAUSED;
1122 StreamStatus stoppedStatus = StreamStatus::STREAM_STOPPED;
1123 if (!streamStatus_->compare_exchange_strong(pausedStatus, StreamStatus::STREAM_STARTING) &&
1124 !streamStatus_->compare_exchange_strong(stoppedStatus, StreamStatus::STREAM_STARTING)) {
1125 startFadein_.store(false);
1126 AUDIO_ERR_LOG("Resume failed, invalid status : %{public}s", GetStatusInfo(stoppedStatus).c_str());
1127 return ERR_ILLEGAL_STATE;
1128 }
1129
1130 if (processProxy_->Resume() != SUCCESS) {
1131 streamStatus_->store(StreamStatus::STREAM_PAUSED);
1132 AUDIO_ERR_LOG("Resume failed to call process proxy, reset status to PAUSED.");
1133 startFadein_.store(false);
1134 threadStatusCV_.notify_all();
1135 return ERR_OPERATION_FAILED;
1136 }
1137
1138 if (ClockTime::GetCurNano() - lastPausedTime_ > DELAY_RESYNC_TIME) {
1139 UpdateHandleInfo(false, true);
1140 lastPausedTime_ = INT64_MAX;
1141 } else {
1142 UpdateHandleInfo();
1143 }
1144
1145 streamStatus_->store(StreamStatus::STREAM_RUNNING);
1146 threadStatusCV_.notify_all();
1147
1148 return SUCCESS;
1149 }
1150
Stop()1151 int32_t AudioProcessInClientInner::Stop()
1152 {
1153 Trace traceStop("AudioProcessInClient::Stop");
1154 CHECK_AND_RETURN_RET_LOG(isInited_, ERR_ILLEGAL_STATE, "not inited!");
1155 std::lock_guard<std::mutex> lock(statusSwitchLock_);
1156 if (streamStatus_->load() == StreamStatus::STREAM_STOPPED) {
1157 AUDIO_INFO_LOG("Stop find already stopped");
1158 return SUCCESS;
1159 }
1160
1161 StreamStatus oldStatus = streamStatus_->load();
1162 CHECK_AND_RETURN_RET_LOG(oldStatus != STREAM_IDEL && oldStatus != STREAM_RELEASED && oldStatus != STREAM_INVALID,
1163 ERR_ILLEGAL_STATE, "Stop failed, invalid status : %{public}s", GetStatusInfo(oldStatus).c_str());
1164 if (oldStatus == STREAM_STARTING || oldStatus == STREAM_RUNNING) {
1165 startFadeout_.store(true);
1166 }
1167 streamStatus_->store(StreamStatus::STREAM_STOPPING);
1168
1169 ClockTime::RelativeSleep(MAX_STOP_FADING_DURATION_NANO);
1170
1171 processProxy_->SetUnderrunCount(underflowCount_);
1172 if (processProxy_->Stop() != SUCCESS) {
1173 streamStatus_->store(oldStatus);
1174 AUDIO_ERR_LOG("Stop failed in server, reset status to %{public}s", GetStatusInfo(oldStatus).c_str());
1175 startFadeout_.store(false);
1176 threadStatusCV_.notify_all(); // avoid thread blocking with status RUNNING
1177 return ERR_OPERATION_FAILED;
1178 }
1179 startFadeout_.store(false);
1180 streamStatus_->store(StreamStatus::STREAM_STOPPED);
1181 AUDIO_INFO_LOG("Success stop proc client mode %{public}d form %{public}s.",
1182 processConfig_.audioMode, GetStatusInfo(oldStatus).c_str());
1183 return SUCCESS;
1184 }
1185
Release(bool isSwitchStream)1186 int32_t AudioProcessInClientInner::Release(bool isSwitchStream)
1187 {
1188 Trace traceRelease("AudioProcessInClient::Release");
1189 CHECK_AND_RETURN_RET_LOG(isInited_, ERR_ILLEGAL_STATE, "not inited!");
1190 AUDIO_INFO_LOG("AudioProcessInClientInner::Release()");
1191 // not lock as status is already released
1192 if (streamStatus_->load() == StreamStatus::STREAM_RELEASED) {
1193 AUDIO_INFO_LOG("Stream status is already released");
1194 return SUCCESS;
1195 }
1196 Stop();
1197 isCallbackLoopEnd_ = true;
1198 threadStatusCV_.notify_all();
1199 std::lock_guard<std::mutex> lock(statusSwitchLock_);
1200 StreamStatus currentStatus = streamStatus_->load();
1201 if (currentStatus != STREAM_STOPPED) {
1202 AUDIO_WARNING_LOG("Release in currentStatus:%{public}s", GetStatusInfo(currentStatus).c_str());
1203 }
1204
1205 if (processProxy_->Release(isSwitchStream) != SUCCESS) {
1206 AUDIO_ERR_LOG("Release may failed in server");
1207 threadStatusCV_.notify_all(); // avoid thread blocking with status RUNNING
1208 return ERR_OPERATION_FAILED;
1209 }
1210
1211 streamStatus_->store(StreamStatus::STREAM_RELEASED);
1212 AUDIO_INFO_LOG("Success release proc client mode %{public}d.", processConfig_.audioMode);
1213 isInited_ = false;
1214 return SUCCESS;
1215 }
1216
1217 // client should call GetBufferDesc and Enqueue in OnHandleData
CallClientHandleCurrent()1218 void AudioProcessInClientInner::CallClientHandleCurrent()
1219 {
1220 Trace trace("AudioProcessInClient::CallClientHandleCurrent");
1221 std::shared_ptr<AudioDataCallback> cb = audioDataCallback_.lock();
1222 CHECK_AND_RETURN_LOG(cb != nullptr, "audio data callback is null.");
1223
1224 int64_t stamp = ClockTime::GetCurNano();
1225 cb->OnHandleData(clientSpanSizeInByte_);
1226 stamp = ClockTime::GetCurNano() - stamp;
1227 if (stamp > MAX_WRITE_COST_DURATION_NANO) {
1228 if (processConfig_.audioMode == AUDIO_MODE_PLAYBACK) {
1229 underflowCount_++;
1230 } else {
1231 overflowCount_++;
1232 }
1233 // todo
1234 // handle write time out: send underrun msg to client, reset time model with latest server handle time.
1235 }
1236
1237 int64_t limit = isVoipMmap_ ? VOIP_MILLISECOND_DURATION : MAX_WRITE_COST_DURATION_NANO;
1238 if (stamp + ONE_MILLISECOND_DURATION > limit) {
1239 AUDIO_WARNING_LOG("Client handle cb too slow, cost %{public}" PRId64"us", stamp / AUDIO_MS_PER_SECOND);
1240 }
1241 }
1242
UpdateHandleInfo(bool isAysnc,bool resetReadWritePos)1243 void AudioProcessInClientInner::UpdateHandleInfo(bool isAysnc, bool resetReadWritePos)
1244 {
1245 Trace traceSync("AudioProcessInClient::UpdateHandleInfo");
1246 uint64_t serverHandlePos = 0;
1247 int64_t serverHandleTime = 0;
1248 int32_t ret = processProxy_->RequestHandleInfo(isAysnc);
1249 CHECK_AND_RETURN_LOG(ret == SUCCESS, "RequestHandleInfo failed ret:%{public}d", ret);
1250 audioBuffer_->GetHandleInfo(serverHandlePos, serverHandleTime);
1251
1252 CheckPosTimeRes res = handleTimeModel_.UpdataFrameStamp(serverHandlePos, serverHandleTime);
1253 if (res == CHECK_FAILED) {
1254 handleTimeModel_.ResetFrameStamp(serverHandlePos, serverHandleTime);
1255 }
1256
1257 if (resetReadWritePos) {
1258 uint64_t nextWritePos = serverHandlePos + spanSizeInFrame_;
1259 ResetAudioBuffer();
1260 ret = audioBuffer_->ResetCurReadWritePos(nextWritePos, nextWritePos);
1261 CHECK_AND_RETURN_LOG(ret == SUCCESS, "ResetCurReadWritePos failed ret:%{public}d", ret);
1262 }
1263 }
1264
ResetAudioBuffer()1265 void AudioProcessInClientInner::ResetAudioBuffer()
1266 {
1267 CHECK_AND_RETURN_LOG((audioBuffer_ != nullptr), "%{public}s: audio buffer is null.", __func__);
1268
1269 uint32_t spanCount = audioBuffer_->GetSpanCount();
1270 for (uint32_t i = 0; i < spanCount; i++) {
1271 SpanInfo *spanInfo = audioBuffer_->GetSpanInfoByIndex(i);
1272 if (spanInfo == nullptr) {
1273 AUDIO_ERR_LOG("ResetAudiobuffer failed.");
1274 return;
1275 }
1276 spanInfo->spanStatus = SPAN_READ_DONE;
1277 spanInfo->offsetInFrame = 0;
1278
1279 spanInfo->readStartTime = 0;
1280 spanInfo->readDoneTime = 0;
1281
1282 spanInfo->writeStartTime = 0;
1283 spanInfo->writeDoneTime = 0;
1284
1285 spanInfo->volumeStart = 1 << VOLUME_SHIFT_NUMBER; // 65536 for initialize
1286 spanInfo->volumeEnd = 1 << VOLUME_SHIFT_NUMBER; // 65536 for initialize
1287 spanInfo->isMute = false;
1288 }
1289 return;
1290 }
1291
GetPredictNextHandleTime(uint64_t posInFrame,bool isIndependent)1292 int64_t AudioProcessInClientInner::GetPredictNextHandleTime(uint64_t posInFrame, bool isIndependent)
1293 {
1294 Trace trace("AudioProcessInClient::GetPredictNextRead");
1295 CHECK_AND_RETURN_RET_LOG(spanSizeInFrame_ != 0, 0, "spanSizeInFrame is 0.");
1296 uint64_t handleSpanCnt = 0;
1297 if (spanSizeInFrame_ != 0) {
1298 handleSpanCnt = posInFrame / spanSizeInFrame_;
1299 }
1300 uint32_t startPeriodCnt = 20; // sync each time when start
1301 uint32_t oneBigPeriodCnt = 40; // 200ms
1302 if (isIndependent) {
1303 if (handleSpanCnt % oneBigPeriodCnt == 0) {
1304 UpdateHandleInfo(true);
1305 }
1306 } else {
1307 if (handleSpanCnt < startPeriodCnt || handleSpanCnt % oneBigPeriodCnt == 0) {
1308 UpdateHandleInfo();
1309 }
1310 }
1311
1312 int64_t nextHandleTime = handleTimeModel_.GetTimeOfPos(posInFrame);
1313
1314 return nextHandleTime;
1315 }
1316
PrepareNext(uint64_t curHandPos,int64_t & wakeUpTime)1317 bool AudioProcessInClientInner::PrepareNext(uint64_t curHandPos, int64_t &wakeUpTime)
1318 {
1319 Trace trace("AudioProcessInClient::PrepareNext " + std::to_string(curHandPos));
1320 int64_t handleModifyTime = 0;
1321 if (processConfig_.audioMode == AUDIO_MODE_RECORD) {
1322 handleModifyTime = RECORD_HANDLE_DELAY_NANO;
1323 } else {
1324 handleModifyTime = -WRITE_BEFORE_DURATION_NANO;
1325 }
1326
1327 int64_t nextServerHandleTime = GetPredictNextHandleTime(curHandPos) + handleModifyTime;
1328 if (nextServerHandleTime < ClockTime::GetCurNano()) {
1329 wakeUpTime = ClockTime::GetCurNano() + ONE_MILLISECOND_DURATION; // make sure less than duration
1330 } else {
1331 wakeUpTime = nextServerHandleTime;
1332 }
1333 AUDIO_DEBUG_LOG("%{public}s end, audioMode %{public}d, curReadPos %{public}" PRIu64", nextServerHandleTime "
1334 "%{public}" PRId64" wakeUpTime %{public}" PRId64".", __func__, processConfig_.audioMode, curHandPos,
1335 nextServerHandleTime, wakeUpTime);
1336 return true;
1337 }
1338
ClientPrepareNextLoop(uint64_t curWritePos,int64_t & wakeUpTime)1339 bool AudioProcessInClientInner::ClientPrepareNextLoop(uint64_t curWritePos, int64_t &wakeUpTime)
1340 {
1341 size_t round = (spanSizeInFrame_ == 0 ? 1 : clientSpanSizeInFrame_ / spanSizeInFrame_);
1342 for (size_t count = 0; count < round; count++) {
1343 bool ret = PrepareNext(curWritePos + count * spanSizeInFrame_, wakeUpTime);
1344 CHECK_AND_RETURN_RET_LOG(ret, false, "PrepareNextLoop in process failed!");
1345 }
1346 return true;
1347 }
1348
CallExitStandBy()1349 void AudioProcessInClientInner::CallExitStandBy()
1350 {
1351 Trace trace("AudioProcessInClient::CallExitStandBy::" + std::to_string(sessionId_));
1352 int32_t result = processProxy_->Start();
1353 StreamStatus targetStatus = StreamStatus::STREAM_STARTING;
1354 bool ret = streamStatus_->compare_exchange_strong(targetStatus, StreamStatus::STREAM_RUNNING);
1355 AUDIO_INFO_LOG("Call start result:%{public}d status change: %{public}s", result, ret ? "success" : "fail");
1356 UpdateHandleInfo();
1357 }
1358
GetStatusInfo(StreamStatus status)1359 std::string AudioProcessInClientInner::GetStatusInfo(StreamStatus status)
1360 {
1361 switch (status) {
1362 case STREAM_IDEL:
1363 return "STREAM_IDEL";
1364 case STREAM_STARTING:
1365 return "STREAM_STARTING";
1366 case STREAM_RUNNING:
1367 return "STREAM_RUNNING";
1368 case STREAM_PAUSING:
1369 return "STREAM_PAUSING";
1370 case STREAM_PAUSED:
1371 return "STREAM_PAUSED";
1372 case STREAM_STOPPING:
1373 return "STREAM_STOPPING";
1374 case STREAM_STOPPED:
1375 return "STREAM_STOPPED";
1376 case STREAM_RELEASED:
1377 return "STREAM_RELEASED";
1378 case STREAM_INVALID:
1379 return "STREAM_INVALID";
1380 default:
1381 break;
1382 }
1383 return "NO_SUCH_STATUS";
1384 }
1385
KeepLoopRunning()1386 bool AudioProcessInClientInner::KeepLoopRunning()
1387 {
1388 StreamStatus targetStatus = STREAM_INVALID;
1389
1390 switch (streamStatus_->load()) {
1391 case STREAM_RUNNING:
1392 return true;
1393 case STREAM_STAND_BY:
1394 AUDIO_INFO_LOG("Status is STAND_BY, let's call exit!");
1395 CallExitStandBy();
1396 return true;
1397 case STREAM_STARTING:
1398 targetStatus = STREAM_RUNNING;
1399 break;
1400 case STREAM_IDEL:
1401 targetStatus = STREAM_STARTING;
1402 break;
1403 case STREAM_PAUSING:
1404 targetStatus = STREAM_PAUSED;
1405 break;
1406 case STREAM_PAUSED:
1407 targetStatus = STREAM_STARTING;
1408 break;
1409 case STREAM_STOPPING:
1410 targetStatus = STREAM_STOPPED;
1411 break;
1412 case STREAM_STOPPED:
1413 targetStatus = STREAM_RELEASED;
1414 break;
1415 default:
1416 break;
1417 }
1418
1419 if (startFadeout_.load() &&
1420 (targetStatus == STREAM_PAUSED || targetStatus == STREAM_STOPPED || targetStatus == STREAM_RELEASED)) {
1421 // do one more time to prepare fade out span buffer
1422 return true;
1423 }
1424
1425 Trace trace("AudioProcessInClient::InWaitStatus");
1426 std::unique_lock<std::mutex> lock(loopThreadLock_);
1427 AUDIO_DEBUG_LOG("Process status is %{public}s now, wait for %{public}s...",
1428 GetStatusInfo(streamStatus_->load()).c_str(), GetStatusInfo(targetStatus).c_str());
1429 threadStatus_ = WAITTING;
1430 threadStatusCV_.wait(lock);
1431 AUDIO_DEBUG_LOG("Process wait end. Cur is %{public}s now, target is %{public}s...",
1432 GetStatusInfo(streamStatus_->load()).c_str(), GetStatusInfo(targetStatus).c_str());
1433
1434 return false;
1435 }
1436
RecordProcessCallbackFuc(uint64_t & curReadPos,int64_t & wakeUpTime,int64_t clientReadCost)1437 bool AudioProcessInClientInner::RecordProcessCallbackFuc(uint64_t &curReadPos, int64_t &wakeUpTime,
1438 int64_t clientReadCost)
1439 {
1440 if (isCallbackLoopEnd_ || audioBuffer_ == nullptr) {
1441 return false;
1442 }
1443 if (!KeepLoopRunning()) {
1444 return true;
1445 }
1446 threadStatus_ = INRUNNING;
1447 Trace traceLoop("AudioProcessInClient Record InRunning");
1448 if (needReSyncPosition_ && RecordReSyncServicePos() == SUCCESS) {
1449 wakeUpTime = ClockTime::GetCurNano();
1450 needReSyncPosition_ = false;
1451 return true;
1452 }
1453 int64_t curTime = ClockTime::GetCurNano();
1454 int64_t wakeupCost = curTime - wakeUpTime;
1455 if (wakeupCost > ONE_MILLISECOND_DURATION) {
1456 AUDIO_WARNING_LOG("loop wake up too late, cost %{public}" PRId64"us", wakeupCost / AUDIO_MS_PER_SECOND);
1457 wakeUpTime = curTime;
1458 }
1459
1460 curReadPos = audioBuffer_->GetCurReadFrame();
1461 int32_t recordPrepare = RecordPrepareCurrent(curReadPos);
1462 CHECK_AND_RETURN_RET_LOG(recordPrepare == SUCCESS, true, "prepare current fail.");
1463 CallClientHandleCurrent();
1464 int32_t recordFinish = RecordFinishHandleCurrent(curReadPos, clientReadCost);
1465 CHECK_AND_RETURN_RET_LOG(recordFinish == SUCCESS, true, "finish handle current fail.");
1466
1467 bool ret = PrepareNext(curReadPos, wakeUpTime);
1468 CHECK_AND_RETURN_RET_LOG(ret, false, "prepare next loop in process fail.");
1469
1470 threadStatus_ = SLEEPING;
1471 curTime = ClockTime::GetCurNano();
1472 if (wakeUpTime > curTime && wakeUpTime - curTime < static_cast<int64_t>(spanSizeInMs_) *
1473 ONE_MILLISECOND_DURATION + clientReadCost) {
1474 ClockTime::AbsoluteSleep(wakeUpTime);
1475 } else {
1476 Trace trace("RecordBigWakeUpTime");
1477 AUDIO_WARNING_LOG("%{public}s wakeUpTime is too late...", __func__);
1478 ClockTime::RelativeSleep(spanSizeInMs_ * ONE_MILLISECOND_DURATION);
1479 }
1480 return true;
1481 }
1482
RecordReSyncServicePos()1483 int32_t AudioProcessInClientInner::RecordReSyncServicePos()
1484 {
1485 CHECK_AND_RETURN_RET_LOG(processProxy_ != nullptr && audioBuffer_ != nullptr, ERR_INVALID_HANDLE,
1486 "%{public}s process proxy or audio buffer is null.", __func__);
1487 uint64_t serverHandlePos = 0;
1488 int64_t serverHandleTime = 0;
1489 int32_t tryTimes = 3;
1490 int32_t ret = 0;
1491 while (tryTimes > 0) {
1492 ret = processProxy_->RequestHandleInfo();
1493 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ret, "%{public}s request handle info fail, ret %{public}d.",
1494 __func__, ret);
1495
1496 CHECK_AND_RETURN_RET_LOG(audioBuffer_->GetHandleInfo(serverHandlePos, serverHandleTime), ERR_OPERATION_FAILED,
1497 "%{public}s get handle info fail.", __func__);
1498 if (serverHandlePos > 0) {
1499 break;
1500 }
1501 ClockTime::RelativeSleep(MAX_READ_COST_DURATION_NANO);
1502 tryTimes--;
1503 }
1504 AUDIO_INFO_LOG("%{public}s get handle info OK, tryTimes %{public}d, serverHandlePos %{public}" PRIu64", "
1505 "serverHandleTime %{public}" PRId64".", __func__, tryTimes, serverHandlePos, serverHandleTime);
1506 ClockTime::AbsoluteSleep(serverHandleTime + RECORD_HANDLE_DELAY_NANO);
1507
1508 ret = audioBuffer_->SetCurReadFrame(serverHandlePos);
1509 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ret, "%{public}s set curReadPos fail, ret %{public}d.", __func__, ret);
1510 return SUCCESS;
1511 }
1512
RecordPrepareCurrent(uint64_t curReadPos)1513 int32_t AudioProcessInClientInner::RecordPrepareCurrent(uint64_t curReadPos)
1514 {
1515 CHECK_AND_RETURN_RET_LOG(audioBuffer_ != nullptr, ERR_INVALID_HANDLE,
1516 "%{public}s audio buffer is null.", __func__);
1517 SpanInfo *curReadSpan = audioBuffer_->GetSpanInfo(curReadPos);
1518 CHECK_AND_RETURN_RET_LOG(curReadSpan != nullptr, ERR_INVALID_HANDLE,
1519 "%{public}s get read span info of process client fail.", __func__);
1520
1521 int tryCount = 10;
1522 SpanStatus targetStatus = SpanStatus::SPAN_WRITE_DONE;
1523 while (!curReadSpan->spanStatus.compare_exchange_strong(targetStatus, SpanStatus::SPAN_READING)
1524 && tryCount > 0) {
1525 AUDIO_WARNING_LOG("%{public}s unready, curReadSpan %{public}" PRIu64", curSpanStatus %{public}d, wait 2ms.",
1526 __func__, curReadPos, curReadSpan->spanStatus.load());
1527 if (curReadSpan->spanStatus.load() == SpanStatus::SPAN_READING) {
1528 AUDIO_WARNING_LOG("Change status to reading while status is already reading!");
1529 return SUCCESS;
1530 }
1531 targetStatus = SpanStatus::SPAN_WRITE_DONE;
1532 tryCount--;
1533 ClockTime::RelativeSleep(RECORD_RESYNC_SLEEP_NANO);
1534 }
1535 CHECK_AND_RETURN_RET_LOG(tryCount > 0, ERR_INVALID_READ,
1536 "%{public}s wait too long, curReadSpan %{public}" PRIu64".", __func__, curReadPos);
1537
1538 curReadSpan->readStartTime = ClockTime::GetCurNano();
1539 return SUCCESS;
1540 }
1541
RecordFinishHandleCurrent(uint64_t & curReadPos,int64_t & clientReadCost)1542 int32_t AudioProcessInClientInner::RecordFinishHandleCurrent(uint64_t &curReadPos, int64_t &clientReadCost)
1543 {
1544 CHECK_AND_RETURN_RET_LOG(audioBuffer_ != nullptr, ERR_INVALID_HANDLE,
1545 "%{public}s audio buffer is null.", __func__);
1546 SpanInfo *curReadSpan = audioBuffer_->GetSpanInfo(curReadPos);
1547 CHECK_AND_RETURN_RET_LOG(curReadSpan != nullptr, ERR_INVALID_HANDLE,
1548 "%{public}s get read span info of process client fail.", __func__);
1549
1550 SpanStatus targetStatus = SpanStatus::SPAN_READING;
1551 if (!curReadSpan->spanStatus.compare_exchange_strong(targetStatus, SpanStatus::SPAN_READ_DONE)) {
1552 AUDIO_ERR_LOG("%{public}s status error, curReadSpan %{public}" PRIu64", curSpanStatus %{public}d.",
1553 __func__, curReadPos, curReadSpan->spanStatus.load());
1554 return ERR_INVALID_OPERATION;
1555 }
1556 curReadSpan->readDoneTime = ClockTime::GetCurNano();
1557
1558 clientReadCost = curReadSpan->readDoneTime - curReadSpan->readStartTime;
1559 if (clientReadCost > MAX_READ_COST_DURATION_NANO) {
1560 AUDIO_WARNING_LOG("Client read cost too long...");
1561 }
1562
1563 uint64_t nextWritePos = curReadPos + spanSizeInFrame_;
1564 int32_t ret = audioBuffer_->SetCurReadFrame(nextWritePos);
1565 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ret, "%{public}s set next hand frame %{public}" PRIu64" fail, "
1566 "ret %{public}d.", __func__, nextWritePos, ret);
1567 curReadPos = nextWritePos;
1568
1569 return SUCCESS;
1570 }
1571
PrepareCurrent(uint64_t curWritePos)1572 bool AudioProcessInClientInner::PrepareCurrent(uint64_t curWritePos)
1573 {
1574 Trace trace("AudioProcessInClient::PrepareCurrent " + std::to_string(curWritePos));
1575 SpanInfo *tempSpan = audioBuffer_->GetSpanInfo(curWritePos);
1576 if (tempSpan == nullptr) {
1577 AUDIO_ERR_LOG("GetSpanInfo failed!");
1578 return false;
1579 }
1580
1581 int tryCount = 50; // try 50 * 2 = 100ms
1582 SpanStatus targetStatus = SpanStatus::SPAN_READ_DONE;
1583 while (!tempSpan->spanStatus.compare_exchange_strong(targetStatus, SpanStatus::SPAN_WRITTING) && tryCount > 0) {
1584 tryCount--;
1585 AUDIO_PRERELEASE_LOGW("span %{public}" PRIu64" not ready, status: %{public}d, wait 2ms.", curWritePos,
1586 targetStatus);
1587 targetStatus = SpanStatus::SPAN_READ_DONE;
1588 ClockTime::RelativeSleep(ONE_MILLISECOND_DURATION + ONE_MILLISECOND_DURATION);
1589 }
1590 // If the last attempt is successful, tryCount will be equal to zero.
1591 CHECK_AND_RETURN_RET_LOG(tryCount >= 0, false,
1592 "wait on current span %{public}" PRIu64" too long...", curWritePos);
1593 tempSpan->writeStartTime = ClockTime::GetCurNano();
1594 return true;
1595 }
1596
PrepareCurrentLoop(uint64_t curWritePos)1597 bool AudioProcessInClientInner::PrepareCurrentLoop(uint64_t curWritePos)
1598 {
1599 size_t round = (spanSizeInFrame_ == 0 ? 1 : clientSpanSizeInFrame_ / spanSizeInFrame_);
1600 for (size_t count = 0; count < round; count++) {
1601 uint64_t tmp = curWritePos + count * static_cast<uint64_t>(spanSizeInFrame_);
1602 bool ret = PrepareCurrent(tmp);
1603 CHECK_AND_RETURN_RET_LOG(ret, false, "PrepareCurrent failed at %{public}" PRIu64" ", tmp);
1604 }
1605 return true;
1606 }
1607
FinishHandleCurrent(uint64_t & curWritePos,int64_t & clientWriteCost)1608 bool AudioProcessInClientInner::FinishHandleCurrent(uint64_t &curWritePos, int64_t &clientWriteCost)
1609 {
1610 Trace trace("AudioProcessInClient::FinishHandleCurrent " + std::to_string(curWritePos));
1611 SpanInfo *tempSpan = audioBuffer_->GetSpanInfo(curWritePos);
1612 CHECK_AND_RETURN_RET_LOG(tempSpan != nullptr, false, "GetSpanInfo failed!");
1613
1614 int32_t ret = ERROR;
1615 // mark status write-done and then server can read
1616 SpanStatus targetStatus = SpanStatus::SPAN_WRITTING;
1617 if (tempSpan->spanStatus.load() == targetStatus) {
1618 uint64_t nextWritePos = curWritePos + spanSizeInFrame_;
1619 ret = audioBuffer_->SetCurWriteFrame(nextWritePos); // move ahead before writedone
1620 curWritePos = nextWritePos;
1621 tempSpan->spanStatus.store(SpanStatus::SPAN_WRITE_DONE);
1622 }
1623 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, false,
1624 "SetCurWriteFrame %{public}" PRIu64" failed, ret:%{public}d", curWritePos, ret);
1625 tempSpan->writeDoneTime = ClockTime::GetCurNano();
1626 tempSpan->volumeStart = static_cast<int32_t>(processVolume_ * duckVolumeInFloat_ * muteVolumeInFloat_);
1627 tempSpan->volumeEnd = static_cast<int32_t>(processVolume_ * duckVolumeInFloat_ * muteVolumeInFloat_);
1628 clientWriteCost = tempSpan->writeDoneTime - tempSpan->writeStartTime;
1629
1630 return true;
1631 }
1632
FinishHandleCurrentLoop(uint64_t & curWritePos,int64_t & clientWriteCost)1633 bool AudioProcessInClientInner::FinishHandleCurrentLoop(uint64_t &curWritePos, int64_t &clientWriteCost)
1634 {
1635 size_t round = (spanSizeInFrame_ == 0 ? 1 : clientSpanSizeInFrame_ / spanSizeInFrame_);
1636 for (size_t count = 0; count < round; count++) {
1637 uint64_t tmp = curWritePos + count * static_cast<uint64_t>(spanSizeInFrame_);
1638 bool ret = FinishHandleCurrent(tmp, clientWriteCost);
1639 CHECK_AND_RETURN_RET_LOG(ret, false, "FinishHandleCurrent failed at %{public}" PRIu64" ", tmp);
1640 }
1641 return true;
1642 }
1643
DoFadeInOut(uint64_t & curWritePos)1644 void AudioProcessInClientInner::DoFadeInOut(uint64_t &curWritePos)
1645 {
1646 if (startFadein_.load() || startFadeout_.load()) {
1647 BufferDesc buffDesc;
1648 CHECK_AND_RETURN_LOG(audioBuffer_ != nullptr, "audioBuffer_ is null.");
1649 audioBuffer_->GetWriteBuffer(curWritePos, buffDesc);
1650 CHECK_AND_RETURN_LOG(buffDesc.buffer != nullptr, "audioBuffer_ is null.");
1651 int16_t *dstPtr = reinterpret_cast<int16_t *>(buffDesc.buffer);
1652 uint8_t channels = processConfig_.streamInfo.channels;
1653 size_t dataLength = buffDesc.dataLength / (2 * channels); // SAMPLE_S16LE,2 bytes per frame
1654
1655 bool isFadeOut = startFadeout_.load();
1656 float fadeStep = 1.0f / dataLength;
1657 for (size_t i = 0; i < dataLength; i++) {
1658 float fadeFactor;
1659 if (!isFadeOut) {
1660 fadeFactor = (i + 1) * fadeStep;
1661 } else {
1662 fadeFactor = 1.0f - ((i + 1) * fadeStep);
1663 }
1664 for (uint8_t j = 0; j < channels; j++) {
1665 dstPtr[i * channels + j] *= fadeFactor;
1666 }
1667 }
1668
1669 if (isFadeOut) {
1670 startFadeout_.store(false);
1671 } else {
1672 startFadein_.store(false);
1673 }
1674 }
1675 }
1676
ProcessCallbackFuc(uint64_t & curWritePos,int64_t & curTime,int64_t & wakeUpTime,int64_t & clientWriteCost)1677 bool AudioProcessInClientInner::ProcessCallbackFuc(uint64_t &curWritePos, int64_t &curTime,
1678 int64_t &wakeUpTime, int64_t &clientWriteCost)
1679 {
1680 if (isCallbackLoopEnd_ && !startFadeout_.load()) {
1681 return false;
1682 }
1683 if (!KeepLoopRunning()) {
1684 return true;
1685 }
1686 threadStatus_ = INRUNNING;
1687 Trace traceLoop("AudioProcessInClient::InRunning");
1688 CheckIfWakeUpTooLate(curTime, wakeUpTime);
1689 curWritePos = audioBuffer_->GetCurWriteFrame();
1690 if (!PrepareCurrentLoop(curWritePos)) {
1691 return true;
1692 }
1693 // call client write
1694 CallClientHandleCurrent();
1695 // client write done, check if time out
1696
1697 DoFadeInOut(curWritePos);
1698
1699 if (!FinishHandleCurrentLoop(curWritePos, clientWriteCost)) {
1700 return true;
1701 }
1702 if (!ClientPrepareNextLoop(curWritePos, wakeUpTime)) {
1703 return false;
1704 }
1705 traceLoop.End();
1706 // start safe sleep
1707 threadStatus_ = SLEEPING;
1708 CheckIfWakeUpTooLate(curTime, wakeUpTime, clientWriteCost);
1709 ClockTime::AbsoluteSleep(wakeUpTime);
1710 return true;
1711 }
1712
ProcessCallbackFucIndependent()1713 void AudioProcessInClientInner::ProcessCallbackFucIndependent()
1714 {
1715 AUDIO_INFO_LOG("multi play loop start");
1716 processProxy_->RegisterThreadPriority(gettid(),
1717 AudioSystemManager::GetInstance()->GetSelfBundleName(processConfig_.appInfo.appUid));
1718 int64_t curTime = 0;
1719 uint64_t curWritePos = 0;
1720 int64_t wakeUpTime = ClockTime::GetCurNano();
1721 while (!isCallbackLoopEnd_) {
1722 if (!KeepLoopRunningIndependent()) {
1723 continue;
1724 }
1725 int32_t ret = 0;
1726 threadStatus_ = INRUNNING;
1727 curTime = ClockTime::GetCurNano();
1728 Trace traceLoop("AudioProcessInClient::InRunning");
1729 if (needReSyncPosition_) {
1730 UpdateHandleInfo(true, true);
1731 wakeUpTime = curTime;
1732 needReSyncPosition_ = false;
1733 continue;
1734 }
1735 curWritePos = audioBuffer_->GetCurWriteFrame();
1736 if (streamStatus_->load() == STREAM_RUNNING) {
1737 CallClientHandleCurrent();
1738 } else {
1739 AudioStreamData writeStreamData;
1740 ret = audioBuffer_->GetWriteBuffer(curWritePos, writeStreamData.bufferDesc);
1741 CHECK_AND_RETURN_LOG(ret == SUCCESS && writeStreamData.bufferDesc.buffer != nullptr,
1742 "ret is fail or buffer is nullptr");
1743 memset_s(writeStreamData.bufferDesc.buffer, writeStreamData.bufferDesc.bufLength,
1744 0, writeStreamData.bufferDesc.bufLength);
1745 }
1746 bool prepared = true;
1747 size_t round = (spanSizeInFrame_ == 0 ? 1 : clientSpanSizeInFrame_ / spanSizeInFrame_);
1748 for (size_t count = 0; count < round; count++) {
1749 if (!PrepareNextIndependent(curWritePos + count * spanSizeInFrame_, wakeUpTime)) {
1750 prepared = false;
1751 AUDIO_ERR_LOG("PrepareNextLoop failed!");
1752 break;
1753 }
1754 }
1755 if (!prepared) {
1756 break;
1757 }
1758 traceLoop.End();
1759 // start sleep
1760 threadStatus_ = SLEEPING;
1761
1762 ClockTime::AbsoluteSleep(wakeUpTime);
1763 }
1764 }
1765
KeepLoopRunningIndependent()1766 bool AudioProcessInClientInner::KeepLoopRunningIndependent()
1767 {
1768 switch (streamStatus_->load()) {
1769 case STREAM_RUNNING:
1770 return true;
1771 case STREAM_IDEL:
1772 return true;
1773 case STREAM_PAUSED:
1774 return true;
1775 default:
1776 break;
1777 }
1778
1779 return false;
1780 }
1781
PrepareNextIndependent(uint64_t curWritePos,int64_t & wakeUpTime)1782 bool AudioProcessInClientInner::PrepareNextIndependent(uint64_t curWritePos, int64_t &wakeUpTime)
1783 {
1784 uint64_t nextHandlePos = curWritePos + spanSizeInFrame_;
1785 Trace prepareTrace("AudioEndpoint::PrepareNextLoop " + std::to_string(nextHandlePos));
1786 int64_t nextHdiReadTime = GetPredictNextHandleTime(nextHandlePos, true);
1787 uint64_t aheadTime = spanSizeInFrame_ * AUDIO_NS_PER_SECOND / processConfig_.streamInfo.samplingRate;
1788 int64_t nextServerHandleTime = nextHdiReadTime - static_cast<int64_t>(aheadTime);
1789 if (nextServerHandleTime < ClockTime::GetCurNano()) {
1790 wakeUpTime = ClockTime::GetCurNano() + ONE_MILLISECOND_DURATION; // make sure less than duration
1791 } else {
1792 wakeUpTime = nextServerHandleTime;
1793 }
1794
1795 SpanInfo *nextWriteSpan = audioBuffer_->GetSpanInfo(nextHandlePos);
1796 if (nextWriteSpan == nullptr) {
1797 AUDIO_ERR_LOG("GetSpanInfo failed, can not get next write span");
1798 return false;
1799 }
1800
1801 int32_t ret1 = audioBuffer_->SetCurWriteFrame(nextHandlePos);
1802 int32_t ret2 = audioBuffer_->SetCurReadFrame(nextHandlePos);
1803 if (ret1 != SUCCESS || ret2 != SUCCESS) {
1804 AUDIO_ERR_LOG("SetCurWriteFrame or SetCurReadFrame failed, ret1:%{public}d ret2:%{public}d", ret1, ret2);
1805 return false;
1806 }
1807 return true;
1808 }
1809
CheckIfWakeUpTooLate(int64_t & curTime,int64_t & wakeUpTime)1810 void AudioProcessInClientInner::CheckIfWakeUpTooLate(int64_t &curTime, int64_t &wakeUpTime)
1811 {
1812 curTime = ClockTime::GetCurNano();
1813 int64_t wakeupCost = curTime - wakeUpTime;
1814 if (wakeupCost > ONE_MILLISECOND_DURATION) {
1815 if (wakeupCost > TWO_MILLISECOND_DURATION) {
1816 AUDIO_WARNING_LOG("loop wake up too late, cost %{public}" PRId64"us", wakeupCost / AUDIO_MS_PER_SECOND);
1817 }
1818 wakeUpTime = curTime;
1819 }
1820 }
1821
CheckIfWakeUpTooLate(int64_t & curTime,int64_t & wakeUpTime,int64_t clientWriteCost)1822 void AudioProcessInClientInner::CheckIfWakeUpTooLate(int64_t &curTime, int64_t &wakeUpTime, int64_t clientWriteCost)
1823 {
1824 curTime = ClockTime::GetCurNano();
1825 int64_t round = static_cast<int64_t>(spanSizeInFrame_ == 0 ? 1 : clientSpanSizeInFrame_ / spanSizeInFrame_);
1826 int64_t clientBufferDurationInMs = static_cast<int64_t>(spanSizeInMs_) * ONE_MILLISECOND_DURATION * round;
1827 if (wakeUpTime - curTime > clientBufferDurationInMs + clientWriteCost) {
1828 Trace trace("BigWakeUpTime curTime[" + std::to_string(curTime) + "] target[" + std::to_string(wakeUpTime) +
1829 "] delay " + std::to_string(wakeUpTime - curTime) + "ns");
1830 AUDIO_PRERELEASE_LOGW("wakeUpTime is too late...");
1831 }
1832 }
1833
SetDefaultOutputDevice(const DeviceType defaultOutputDevice)1834 int32_t AudioProcessInClientInner::SetDefaultOutputDevice(const DeviceType defaultOutputDevice)
1835 {
1836 CHECK_AND_RETURN_RET_LOG(processProxy_ != nullptr, ERR_OPERATION_FAILED, "set failed with null ipcProxy.");
1837 return processProxy_->SetDefaultOutputDevice(defaultOutputDevice);
1838 }
1839
SetSilentModeAndMixWithOthers(bool on)1840 int32_t AudioProcessInClientInner::SetSilentModeAndMixWithOthers(bool on)
1841 {
1842 CHECK_AND_RETURN_RET_LOG(processProxy_ != nullptr, ERR_OPERATION_FAILED, "ipcProxy is null.");
1843 return processProxy_->SetSilentModeAndMixWithOthers(on);
1844 }
1845
GetRestoreInfo(RestoreInfo & restoreInfo)1846 void AudioProcessInClientInner::GetRestoreInfo(RestoreInfo &restoreInfo)
1847 {
1848 CHECK_AND_RETURN_LOG(audioBuffer_ != nullptr, "Client OHAudioBuffer is nullptr");
1849 audioBuffer_->GetRestoreInfo(restoreInfo);
1850 return;
1851 }
1852
SetRestoreInfo(RestoreInfo & restoreInfo)1853 void AudioProcessInClientInner::SetRestoreInfo(RestoreInfo &restoreInfo)
1854 {
1855 CHECK_AND_RETURN_LOG(audioBuffer_ != nullptr, "Client OHAudioBuffer is nullptr");
1856 audioBuffer_->SetRestoreInfo(restoreInfo);
1857 return;
1858 }
1859
CheckRestoreStatus()1860 RestoreStatus AudioProcessInClientInner::CheckRestoreStatus()
1861 {
1862 CHECK_AND_RETURN_RET_LOG(audioBuffer_ != nullptr, RESTORE_ERROR, "Client OHAudioBuffer is nullptr");
1863 return audioBuffer_->CheckRestoreStatus();
1864 }
1865
SetRestoreStatus(RestoreStatus restoreStatus)1866 RestoreStatus AudioProcessInClientInner::SetRestoreStatus(RestoreStatus restoreStatus)
1867 {
1868 CHECK_AND_RETURN_RET_LOG(audioBuffer_ != nullptr, RESTORE_ERROR, "Client OHAudioBuffer is nullptr");
1869 return audioBuffer_->SetRestoreStatus(restoreStatus);
1870 }
1871 } // namespace AudioStandard
1872 } // namespace OHOS
1873