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