1 /*
2 * Copyright (c) 2023-2024 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 "AudioEndpointInner"
17 #endif
18
19 #include "audio_endpoint.h"
20
21 #include <atomic>
22 #include <cinttypes>
23 #include <condition_variable>
24 #include <thread>
25 #include <vector>
26 #include <mutex>
27
28 #include "securec.h"
29
30 #include "audio_errors.h"
31 #include "audio_service_log.h"
32 #include "audio_schedule.h"
33 #include "audio_utils.h"
34 #include "bluetooth_renderer_sink.h"
35 #include "fast_audio_renderer_sink.h"
36 #include "fast_audio_capturer_source.h"
37 #include "format_converter.h"
38 #include "i_audio_capturer_source.h"
39 #include "i_stream_manager.h"
40 #include "linear_pos_time_model.h"
41 #include "policy_handler.h"
42 #include "audio_log_utils.h"
43 #include "media_monitor_manager.h"
44 #include "audio_dump_pcm.h"
45 #ifdef DAUDIO_ENABLE
46 #include "remote_fast_audio_renderer_sink.h"
47 #include "remote_fast_audio_capturer_source.h"
48 #endif
49
50 namespace OHOS {
51 namespace AudioStandard {
52 namespace {
53 static constexpr int32_t VOLUME_SHIFT_NUMBER = 16; // 1 >> 16 = 65536, max volume
54 static constexpr int64_t RECORD_DELAY_TIME_NS = 4000000; // 4ms = 4 * 1000 * 1000ns
55 static constexpr int64_t RECORD_VOIP_DELAY_TIME_NS = 20000000; // 20ms = 20 * 1000 * 1000ns
56 static constexpr int64_t MAX_SPAN_DURATION_NS = 100000000; // 100ms = 100 * 1000 * 1000ns
57 static constexpr int64_t DELAY_STOP_HDI_TIME = 10000000000; // 10s
58 static constexpr int64_t WAIT_CLIENT_STANDBY_TIME_NS = 1000000000; // 1s = 1000 * 1000 * 1000ns
59 static constexpr int64_t DELAY_STOP_HDI_TIME_FOR_ZERO_VOLUME_NS = 4000000000; // 4s = 4 * 1000 * 1000 * 1000ns
60 static constexpr int64_t DELAY_STOP_HDI_TIME_WHEN_NO_RUNNING_NS = 1000000000; // 1s
61 static constexpr int32_t SLEEP_TIME_IN_DEFAULT = 400; // 400ms
62 static constexpr int64_t DELTA_TO_REAL_READ_START_TIME = 0; // 0ms
63 const uint16_t GET_MAX_AMPLITUDE_FRAMES_THRESHOLD = 40;
64 static const int32_t HALF_FACTOR = 2;
65 }
66
ConvertToHdiAdapterFormat(AudioSampleFormat format)67 static enum HdiAdapterFormat ConvertToHdiAdapterFormat(AudioSampleFormat format)
68 {
69 enum HdiAdapterFormat adapterFormat;
70 switch (format) {
71 case AudioSampleFormat::SAMPLE_U8:
72 adapterFormat = HdiAdapterFormat::SAMPLE_U8;
73 break;
74 case AudioSampleFormat::SAMPLE_S16LE:
75 adapterFormat = HdiAdapterFormat::SAMPLE_S16;
76 break;
77 case AudioSampleFormat::SAMPLE_S24LE:
78 adapterFormat = HdiAdapterFormat::SAMPLE_S24;
79 break;
80 case AudioSampleFormat::SAMPLE_S32LE:
81 adapterFormat = HdiAdapterFormat::SAMPLE_S32;
82 break;
83 default:
84 adapterFormat = HdiAdapterFormat::INVALID_WIDTH;
85 break;
86 }
87
88 return adapterFormat;
89 }
90
91 class MockCallbacks : public IStatusCallback, public IWriteCallback {
92 public:
93 explicit MockCallbacks(uint32_t streamIndex);
94 virtual ~MockCallbacks() = default;
95 void OnStatusUpdate(IOperation operation) override;
96 int32_t OnWriteData(size_t length) override;
97 private:
98 uint32_t streamIndex_ = 0;
99 };
100
101 class AudioEndpointInner : public AudioEndpoint {
102 public:
103 AudioEndpointInner(EndpointType type, uint64_t id, const AudioProcessConfig &clientConfig);
104 ~AudioEndpointInner();
105
106 bool Config(const DeviceInfo &deviceInfo) override;
107 bool StartDevice();
108 void HandleStartDeviceFailed();
109 bool StopDevice();
110
111 // when audio process start.
112 int32_t OnStart(IAudioProcessStream *processStream) override;
113 // when audio process pause.
114 int32_t OnPause(IAudioProcessStream *processStream) override;
115 // when audio process request update handle info.
116 int32_t OnUpdateHandleInfo(IAudioProcessStream *processStream) override;
117
118 /**
119 * Call LinkProcessStream when first create process or link other process with this endpoint.
120 * Here are cases:
121 * case1: endpointStatus_ = UNLINKED, link not running process; UNLINKED-->IDEL & godown
122 * case2: endpointStatus_ = UNLINKED, link running process; UNLINKED-->IDEL & godown
123 * case3: endpointStatus_ = IDEL, link not running process; IDEL-->IDEL
124 * case4: endpointStatus_ = IDEL, link running process; IDEL-->STARTING-->RUNNING
125 * case5: endpointStatus_ = RUNNING; RUNNING-->RUNNING
126 */
127 int32_t LinkProcessStream(IAudioProcessStream *processStream) override;
128 void LinkProcessStreamExt(IAudioProcessStream *processStream,
129 const std::shared_ptr<OHAudioBuffer>& processBuffer);
130
131 int32_t UnlinkProcessStream(IAudioProcessStream *processStream) override;
132
133 int32_t GetPreferBufferInfo(uint32_t &totalSizeInframe, uint32_t &spanSizeInframe) override;
134
135 void Dump(std::string &dumpString) override;
136
137 std::string GetEndpointName() override;
GetEndpointType()138 EndpointType GetEndpointType() override
139 {
140 return endpointType_;
141 }
142 int32_t SetVolume(AudioStreamType streamType, float volume) override;
143
144 int32_t ResolveBuffer(std::shared_ptr<OHAudioBuffer> &buffer) override;
145
GetBuffer()146 std::shared_ptr<OHAudioBuffer> GetBuffer() override
147 {
148 return dstAudioBuffer_;
149 }
150
151 // for inner-cap
152 bool ShouldInnerCap() override;
153 int32_t EnableFastInnerCap() override;
154 int32_t DisableFastInnerCap() override;
155
156 int32_t InitDupStream();
157
158 EndpointStatus GetStatus() override;
159
160 void Release() override;
161
GetDeviceInfo()162 DeviceInfo &GetDeviceInfo() override
163 {
164 return deviceInfo_;
165 }
166
GetDeviceRole()167 DeviceRole GetDeviceRole() override
168 {
169 return deviceInfo_.deviceRole;
170 }
171
172 float GetMaxAmplitude() override;
173 uint32_t GetLinkedProcessCount() override;
174
175 private:
176 AudioProcessConfig GetInnerCapConfig();
177 void StartThread(const IAudioSinkAttr &attr);
178 void MixToDupStream(const std::vector<AudioStreamData> &srcDataList);
179 bool ConfigInputPoint(const DeviceInfo &deviceInfo);
180 int32_t PrepareDeviceBuffer(const DeviceInfo &deviceInfo);
181 int32_t GetAdapterBufferInfo(const DeviceInfo &deviceInfo);
182 void ReSyncPosition();
183 void RecordReSyncPosition();
184 void InitAudiobuffer(bool resetReadWritePos);
185 void ProcessData(const std::vector<AudioStreamData> &srcDataList, const AudioStreamData &dstData);
186 void ProcessSingleData(const AudioStreamData &srcData, const AudioStreamData &dstData);
187 void HandleZeroVolumeCheckEvent();
188 void HandleRendererDataParams(const AudioStreamData &srcData, const AudioStreamData &dstData);
189 int32_t HandleCapturerDataParams(const BufferDesc &writeBuf, const BufferDesc &readBuf,
190 const BufferDesc &convertedBuffer);
191 void ZeroVolumeCheck(const int32_t vol);
192 int64_t GetPredictNextReadTime(uint64_t posInFrame);
193 int64_t GetPredictNextWriteTime(uint64_t posInFrame);
194 bool PrepareNextLoop(uint64_t curWritePos, int64_t &wakeUpTime);
195 bool RecordPrepareNextLoop(uint64_t curReadPos, int64_t &wakeUpTime);
196
197 /**
198 * @brief Get the current read position in frame and the read-time with it.
199 *
200 * @param frames the read position in frame
201 * @param nanoTime the time in nanosecond when device-sink start read the buffer
202 */
203 bool GetDeviceHandleInfo(uint64_t &frames, int64_t &nanoTime);
204 int32_t GetProcLastWriteDoneInfo(const std::shared_ptr<OHAudioBuffer> processBuffer, uint64_t curWriteFrame,
205 uint64_t &proHandleFrame, int64_t &proHandleTime);
206
207 void CheckStandBy();
208 bool IsAnyProcessRunning();
209 bool IsAnyProcessRunningInner();
210 bool CheckAllBufferReady(int64_t checkTime, uint64_t curWritePos);
211 void WaitAllProcessReady(uint64_t curWritePos);
212 bool ProcessToEndpointDataHandle(uint64_t curWritePos);
213 void GetAllReadyProcessData(std::vector<AudioStreamData> &audioDataList);
214
215 std::string GetStatusStr(EndpointStatus status);
216
217 int32_t WriteToSpecialProcBuf(const std::shared_ptr<OHAudioBuffer> &procBuf, const BufferDesc &readBuf,
218 const BufferDesc &convertedBuffer, bool muteFlag);
219 void WriteToProcessBuffers(const BufferDesc &readBuf);
220 int32_t ReadFromEndpoint(uint64_t curReadPos);
221 bool KeepWorkloopRunning();
222
223 void EndpointWorkLoopFuc();
224 void RecordEndpointWorkLoopFuc();
225
226 // Call GetMmapHandlePosition in ipc may block more than a cycle, call it in another thread.
227 void AsyncGetPosTime();
228 bool DelayStopDevice();
229
230 IMmapAudioRendererSink *GetFastSink(const DeviceInfo &deviceInfo, EndpointType type);
231 IMmapAudioCapturerSource *GetFastSource(const std::string &networkId, EndpointType type, IAudioSourceAttr &attr);
232
233 void InitLatencyMeasurement();
234 void DeinitLatencyMeasurement();
235 void CheckPlaySignal(uint8_t *buffer, size_t bufferSize);
236 void CheckRecordSignal(uint8_t *buffer, size_t bufferSize);
237 void DfxOperation(BufferDesc &buffer, AudioSampleFormat format, AudioChannel channel) const;
238
239 void CheckUpdateState(char *frame, uint64_t replyBytes);
240
241 void ProcessUpdateAppsUidForPlayback();
242 void ProcessUpdateAppsUidForRecord();
243
244 void WriterRenderStreamStandbySysEvent(uint32_t sessionId, int32_t standby);
245 private:
246 static constexpr int64_t ONE_MILLISECOND_DURATION = 1000000; // 1ms
247 static constexpr int64_t THREE_MILLISECOND_DURATION = 3000000; // 3ms
248 static constexpr int64_t WRITE_TO_HDI_AHEAD_TIME = -1000000; // ahead 1ms
249 static constexpr int32_t UPDATE_THREAD_TIMEOUT = 1000; // 1000ms
250 enum ThreadStatus : uint32_t {
251 WAITTING = 0,
252 SLEEPING,
253 INRUNNING
254 };
255 enum FastSinkType {
256 NONE_FAST_SINK = 0,
257 FAST_SINK_TYPE_NORMAL,
258 FAST_SINK_TYPE_REMOTE,
259 FAST_SINK_TYPE_VOIP,
260 FAST_SINK_TYPE_BLUETOOTH
261 };
262 enum FastSourceType {
263 NONE_FAST_SOURCE = 0,
264 FAST_SOURCE_TYPE_NORMAL,
265 FAST_SOURCE_TYPE_REMOTE,
266 FAST_SOURCE_TYPE_VOIP
267 };
268 // SamplingRate EncodingType SampleFormat Channel
269 DeviceInfo deviceInfo_;
270 AudioStreamInfo dstStreamInfo_;
271 EndpointType endpointType_;
272 int32_t id_ = 0;
273 std::mutex listLock_;
274 std::vector<IAudioProcessStream *> processList_;
275 std::vector<std::shared_ptr<OHAudioBuffer>> processBufferList_;
276 AudioProcessConfig clientConfig_;
277
278 std::atomic<bool> isInited_ = false;
279
280 // for inner-cap
281 std::mutex dupMutex_;
282 std::atomic<bool> isInnerCapEnabled_ = false;
283 uint32_t dupStreamIndex_ = 0;
284 std::shared_ptr<MockCallbacks> dupStreamCallback_ = nullptr;
285 std::shared_ptr<IRendererStream> dupStream_ = nullptr;
286 size_t dupBufferSize_ = 0;
287 std::unique_ptr<uint8_t []> dupBuffer_ = nullptr;
288 FILE *dumpC2SDup_ = nullptr; // client to server inner-cap dump file
289 std::string dupDumpName_ = "";
290
291 IMmapAudioRendererSink *fastSink_ = nullptr;
292 IMmapAudioCapturerSource *fastSource_ = nullptr;
293 FastSinkType fastSinkType_ = NONE_FAST_SINK;
294 FastSourceType fastSourceType_ = NONE_FAST_SOURCE;
295
296 LinearPosTimeModel readTimeModel_;
297 LinearPosTimeModel writeTimeModel_;
298
299 int64_t spanDuration_ = 0; // nano second
300 int64_t serverAheadReadTime_ = 0;
301 int dstBufferFd_ = -1; // -1: invalid fd.
302 uint32_t dstTotalSizeInframe_ = 0;
303 uint32_t dstSpanSizeInframe_ = 0;
304 uint32_t dstByteSizePerFrame_ = 0;
305 std::shared_ptr<OHAudioBuffer> dstAudioBuffer_ = nullptr;
306
307 std::atomic<EndpointStatus> endpointStatus_ = INVALID;
308 bool isStarted_ = false;
309 int64_t delayStopTime_ = INT64_MAX;
310 int64_t delayStopTimeForZeroVolume_ = INT64_MAX;
311
312 std::atomic<ThreadStatus> threadStatus_ = WAITTING;
313 std::thread endpointWorkThread_;
314 std::mutex loopThreadLock_;
315 std::condition_variable workThreadCV_;
316 int64_t lastHandleProcessTime_ = 0;
317
318 std::thread updatePosTimeThread_;
319 std::mutex updateThreadLock_;
320 std::condition_variable updateThreadCV_;
321 std::atomic<bool> stopUpdateThread_ = false;
322
323 std::atomic<uint64_t> posInFrame_ = 0;
324 std::atomic<int64_t> timeInNano_ = 0;
325
326 bool isDeviceRunningInIdel_ = true; // will call start sink when linked.
327 bool needReSyncPosition_ = true;
328 FILE *dumpHdi_ = nullptr;
329 mutable int64_t volumeDataCount_ = 0;
330 std::string logUtilsTag_ = "";
331 std::string dumpHdiName_ = "";
332
333 bool signalDetected_ = false;
334 bool latencyMeasEnabled_ = false;
335 size_t detectedTime_ = 0;
336 std::shared_ptr<SignalDetectAgent> signalDetectAgent_ = nullptr;
337
338 // for get amplitude
339 float maxAmplitude_ = 0;
340 int64_t lastGetMaxAmplitudeTime_ = 0;
341 int64_t last10FrameStartTime_ = 0;
342 bool startUpdate_ = false;
343 int renderFrameNum_ = 0;
344
345 bool zeroVolumeStopDevice_ = false;
346 bool isVolumeAlreadyZero_ = false;
347 };
348
GenerateEndpointKey(DeviceInfo & deviceInfo,int32_t endpointFlag)349 std::string AudioEndpoint::GenerateEndpointKey(DeviceInfo &deviceInfo, int32_t endpointFlag)
350 {
351 // All primary sinks share one endpoint
352 int32_t endpointId = 0;
353 if (deviceInfo.deviceType == DEVICE_TYPE_BLUETOOTH_A2DP) {
354 endpointId = deviceInfo.deviceId;
355 }
356 return deviceInfo.networkId + "_" + std::to_string(endpointId) + "_" +
357 std::to_string(deviceInfo.deviceRole) + "_" + std::to_string(endpointFlag);
358 }
359
CreateEndpoint(EndpointType type,uint64_t id,const AudioProcessConfig & clientConfig,const DeviceInfo & deviceInfo)360 std::shared_ptr<AudioEndpoint> AudioEndpoint::CreateEndpoint(EndpointType type, uint64_t id,
361 const AudioProcessConfig &clientConfig, const DeviceInfo &deviceInfo)
362 {
363 std::shared_ptr<AudioEndpoint> audioEndpoint = nullptr;
364 if (type == EndpointType::TYPE_INDEPENDENT && deviceInfo.deviceRole != INPUT_DEVICE &&
365 deviceInfo.networkId == LOCAL_NETWORK_ID) {
366 audioEndpoint = std::make_shared<AudioEndpointSeparate>(type, id, clientConfig.streamType);
367 } else {
368 audioEndpoint = std::make_shared<AudioEndpointInner>(type, id, clientConfig);
369 }
370 CHECK_AND_RETURN_RET_LOG(audioEndpoint != nullptr, nullptr, "Create AudioEndpoint failed.");
371
372 if (!audioEndpoint->Config(deviceInfo)) {
373 AUDIO_ERR_LOG("Config AudioEndpoint failed.");
374 audioEndpoint = nullptr;
375 }
376 return audioEndpoint;
377 }
378
AudioEndpointInner(EndpointType type,uint64_t id,const AudioProcessConfig & clientConfig)379 AudioEndpointInner::AudioEndpointInner(EndpointType type, uint64_t id,
380 const AudioProcessConfig &clientConfig) : endpointType_(type), id_(id), clientConfig_(clientConfig)
381 {
382 AUDIO_INFO_LOG("AudioEndpoint type:%{public}d", endpointType_);
383 if (clientConfig_.audioMode == AUDIO_MODE_PLAYBACK) {
384 logUtilsTag_ = "AudioEndpoint::Play";
385 } else {
386 logUtilsTag_ = "AudioEndpoint::Rec";
387 }
388 }
389
GetEndpointName()390 std::string AudioEndpointInner::GetEndpointName()
391 {
392 return GenerateEndpointKey(deviceInfo_, id_);
393 }
394
SetVolume(AudioStreamType streamType,float volume)395 int32_t AudioEndpointInner::SetVolume(AudioStreamType streamType, float volume)
396 {
397 // No need set hdi volume in shared stream mode.
398 return SUCCESS;
399 }
400
ResolveBuffer(std::shared_ptr<OHAudioBuffer> & buffer)401 int32_t AudioEndpointInner::ResolveBuffer(std::shared_ptr<OHAudioBuffer> &buffer)
402 {
403 return SUCCESS;
404 }
405
MockCallbacks(uint32_t streamIndex)406 MockCallbacks::MockCallbacks(uint32_t streamIndex) : streamIndex_(streamIndex)
407 {
408 AUDIO_INFO_LOG("DupStream %{public}u create MockCallbacks", streamIndex_);
409 }
410
OnStatusUpdate(IOperation operation)411 void MockCallbacks::OnStatusUpdate(IOperation operation)
412 {
413 AUDIO_INFO_LOG("DupStream %{public}u recv operation: %{public}d", streamIndex_, operation);
414 }
415
OnWriteData(size_t length)416 int32_t MockCallbacks::OnWriteData(size_t length)
417 {
418 Trace trace("DupStream::OnWriteData length " + std::to_string(length));
419 return SUCCESS;
420 }
421
ShouldInnerCap()422 bool AudioEndpointInner::ShouldInnerCap()
423 {
424 bool shouldBecapped = false;
425 std::lock_guard<std::mutex> lock(listLock_);
426 for (uint32_t i = 0; i < processList_.size(); i++) {
427 if (processList_[i]->GetInnerCapState()) {
428 shouldBecapped = true;
429 break;
430 }
431 }
432 AUDIO_INFO_LOG("find endpoint inner-cap state: %{public}s", shouldBecapped ? "true" : "false");
433 return shouldBecapped;
434 }
435
GetInnerCapConfig()436 AudioProcessConfig AudioEndpointInner::GetInnerCapConfig()
437 {
438 AudioProcessConfig processConfig;
439
440 processConfig.appInfo.appPid = static_cast<int32_t>(getpid());
441 processConfig.appInfo.appUid = static_cast<int32_t>(getuid());
442
443 processConfig.streamInfo = dstStreamInfo_;
444
445 processConfig.audioMode = AUDIO_MODE_PLAYBACK;
446
447 // processConfig.rendererInfo ?
448
449 processConfig.streamType = STREAM_MUSIC;
450
451 return processConfig;
452 }
453
InitDupStream()454 int32_t AudioEndpointInner::InitDupStream()
455 {
456 std::lock_guard<std::mutex> lock(dupMutex_);
457 CHECK_AND_RETURN_RET_LOG(isInnerCapEnabled_ == false, SUCCESS, "already enabled");
458
459 AudioProcessConfig processConfig = GetInnerCapConfig();
460 int32_t ret = IStreamManager::GetDupPlaybackManager().CreateRender(processConfig, dupStream_);
461 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS && dupStream_ != nullptr, ERR_OPERATION_FAILED, "Failed: %{public}d", ret);
462 dupStreamIndex_ = dupStream_->GetStreamIndex();
463
464 dupStreamCallback_ = std::make_shared<MockCallbacks>(dupStreamIndex_);
465 dupStream_->RegisterStatusCallback(dupStreamCallback_);
466 dupStream_->RegisterWriteCallback(dupStreamCallback_);
467
468 // eg: /data/local/tmp/LocalDevice6_0_c2s_dup_48000_2_1.pcm
469 AudioStreamInfo tempInfo = processConfig.streamInfo;
470 dupDumpName_ = GetEndpointName() + "_c2s_dup_" + std::to_string(tempInfo.samplingRate) + "_" +
471 std::to_string(tempInfo.channels) + "_" + std::to_string(tempInfo.format) + ".pcm";
472 DumpFileUtil::OpenDumpFile(DUMP_SERVER_PARA, dupDumpName_, &dumpC2SDup_);
473
474 AUDIO_INFO_LOG("Dup Renderer %{public}d with Endpoint status: %{public}s", dupStreamIndex_,
475 GetStatusStr(endpointStatus_).c_str());
476
477 // buffer init
478 dupBufferSize_ = dstSpanSizeInframe_ * dstByteSizePerFrame_; // each
479 CHECK_AND_RETURN_RET_LOG(dupBufferSize_ < dstAudioBuffer_->GetDataSize(), ERR_OPERATION_FAILED, "Init buffer fail");
480 dupBuffer_ = std::make_unique<uint8_t []>(dupBufferSize_);
481 ret = memset_s(reinterpret_cast<void *>(dupBuffer_.get()), dupBufferSize_, 0, dupBufferSize_);
482 if (ret != EOK) {
483 AUDIO_WARNING_LOG("memset buffer fail, ret %{public}d", ret);
484 }
485
486 if (endpointStatus_ == RUNNING || (endpointStatus_ == IDEL && isDeviceRunningInIdel_)) {
487 int32_t audioId = deviceInfo_.deviceId;
488 AUDIO_INFO_LOG("Endpoint %{public}d is already running, let's start the dup stream", audioId);
489 dupStream_->Start();
490 }
491 // mark enabled last
492 isInnerCapEnabled_ = true;
493 return SUCCESS;
494 }
495
EnableFastInnerCap()496 int32_t AudioEndpointInner::EnableFastInnerCap()
497 {
498 if (isInnerCapEnabled_) {
499 AUDIO_INFO_LOG("InnerCap is already enabled");
500 return SUCCESS;
501 }
502
503 CHECK_AND_RETURN_RET_LOG(deviceInfo_.deviceRole == OUTPUT_DEVICE, ERR_INVALID_OPERATION, "Not output device!");
504 int32_t ret = InitDupStream();
505 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_OPERATION_FAILED, "Init dup stream failed");
506 return SUCCESS;
507 }
508
DisableFastInnerCap()509 int32_t AudioEndpointInner::DisableFastInnerCap()
510 {
511 if (deviceInfo_.deviceRole != OUTPUT_DEVICE) {
512 return SUCCESS;
513 }
514 std::lock_guard<std::mutex> lock(dupMutex_);
515 if (!isInnerCapEnabled_) {
516 AUDIO_INFO_LOG("InnerCap is already disabled.");
517 return SUCCESS;
518 }
519 isInnerCapEnabled_ = false;
520 AUDIO_INFO_LOG("Disable dup renderer %{public}d with Endpoint status: %{public}s", dupStreamIndex_,
521 GetStatusStr(endpointStatus_).c_str());
522
523 IStreamManager::GetDupPlaybackManager().ReleaseRender(dupStreamIndex_);
524 dupStream_ = nullptr;
525
526 return SUCCESS;
527 }
528
GetStatus()529 AudioEndpoint::EndpointStatus AudioEndpointInner::GetStatus()
530 {
531 AUDIO_INFO_LOG("AudioEndpoint get status:%{public}s", GetStatusStr(endpointStatus_).c_str());
532 return endpointStatus_.load();
533 }
534
Release()535 void AudioEndpointInner::Release()
536 {
537 // Wait for thread end and then clear other data to avoid using any cleared data in thread.
538 AUDIO_INFO_LOG("Release enter.");
539 if (!isInited_.load()) {
540 AUDIO_WARNING_LOG("already released");
541 return;
542 }
543
544 isInited_.store(false);
545 workThreadCV_.notify_all();
546 if (endpointWorkThread_.joinable()) {
547 AUDIO_DEBUG_LOG("AudioEndpoint join work thread start");
548 endpointWorkThread_.join();
549 AUDIO_DEBUG_LOG("AudioEndpoint join work thread end");
550 }
551
552 stopUpdateThread_.store(true);
553 updateThreadCV_.notify_all();
554 if (updatePosTimeThread_.joinable()) {
555 AUDIO_DEBUG_LOG("AudioEndpoint join update thread start");
556 updatePosTimeThread_.join();
557 AUDIO_DEBUG_LOG("AudioEndpoint join update thread end");
558 }
559
560 if (fastSink_ != nullptr) {
561 fastSink_->DeInit();
562 fastSink_ = nullptr;
563 }
564
565 if (fastSource_ != nullptr) {
566 fastSource_->DeInit();
567 fastSource_ = nullptr;
568 }
569
570 endpointStatus_.store(INVALID);
571
572 if (dstAudioBuffer_ != nullptr) {
573 AUDIO_INFO_LOG("Set device buffer null");
574 dstAudioBuffer_ = nullptr;
575 }
576
577 if (deviceInfo_.deviceRole == OUTPUT_DEVICE && isInnerCapEnabled_) {
578 DisableFastInnerCap();
579 }
580
581 DumpFileUtil::CloseDumpFile(&dumpHdi_);
582 }
583
~AudioEndpointInner()584 AudioEndpointInner::~AudioEndpointInner()
585 {
586 if (isInited_.load()) {
587 AudioEndpointInner::Release();
588 }
589 AUDIO_INFO_LOG("~AudioEndpoint()");
590 }
591
Dump(std::string & dumpString)592 void AudioEndpointInner::Dump(std::string &dumpString)
593 {
594 // dump endpoint stream info
595 dumpString += "Endpoint stream info:\n";
596 AppendFormat(dumpString, " - samplingRate: %d\n", dstStreamInfo_.samplingRate);
597 AppendFormat(dumpString, " - channels: %u\n", dstStreamInfo_.channels);
598 AppendFormat(dumpString, " - format: %u\n", dstStreamInfo_.format);
599 AppendFormat(dumpString, " - sink type: %d\n", fastSinkType_);
600 AppendFormat(dumpString, " - source type: %d\n", fastSourceType_);
601
602 // dump status info
603 AppendFormat(dumpString, " - Current endpoint status: %s\n", GetStatusStr(endpointStatus_).c_str());
604 if (dstAudioBuffer_ != nullptr) {
605 AppendFormat(dumpString, " - Currend hdi read position: %u\n", dstAudioBuffer_->GetCurReadFrame());
606 AppendFormat(dumpString, " - Currend hdi write position: %u\n", dstAudioBuffer_->GetCurWriteFrame());
607 }
608
609 // dump linked process info
610 std::lock_guard<std::mutex> lock(listLock_);
611 AppendFormat(dumpString, " - linked process:: %zu\n", processBufferList_.size());
612 for (auto item : processBufferList_) {
613 AppendFormat(dumpString, " - process read position: %u\n", item->GetCurReadFrame());
614 AppendFormat(dumpString, " - process write position: %u\n", item->GetCurWriteFrame());
615 }
616 dumpString += "\n";
617 }
618
ConfigInputPoint(const DeviceInfo & deviceInfo)619 bool AudioEndpointInner::ConfigInputPoint(const DeviceInfo &deviceInfo)
620 {
621 AUDIO_INFO_LOG("ConfigInputPoint enter.");
622 IAudioSourceAttr attr = {};
623 attr.sampleRate = dstStreamInfo_.samplingRate;
624 attr.channel = dstStreamInfo_.channels;
625 attr.format = ConvertToHdiAdapterFormat(dstStreamInfo_.format);
626 attr.deviceNetworkId = deviceInfo.networkId.c_str();
627 attr.deviceType = deviceInfo.deviceType;
628 attr.audioStreamFlag = endpointType_ == TYPE_VOIP_MMAP ? AUDIO_FLAG_VOIP_FAST : AUDIO_FLAG_MMAP;
629 attr.sourceType = endpointType_ == TYPE_VOIP_MMAP ? SOURCE_TYPE_VOICE_COMMUNICATION : SOURCE_TYPE_MIC;
630
631 fastSource_ = GetFastSource(deviceInfo.networkId, endpointType_, attr);
632
633 if (deviceInfo.networkId == LOCAL_NETWORK_ID) {
634 attr.adapterName = "primary";
635 fastSource_ = FastAudioCapturerSource::GetInstance();
636 } else {
637 #ifdef DAUDIO_ENABLE
638 attr.adapterName = "remote";
639 fastSource_ = RemoteFastAudioCapturerSource::GetInstance(deviceInfo.networkId);
640 #endif
641 }
642 CHECK_AND_RETURN_RET_LOG(fastSource_ != nullptr, false, "ConfigInputPoint GetInstance failed.");
643
644 int32_t err = fastSource_->Init(attr);
645 if (err != SUCCESS || !fastSource_->IsInited()) {
646 AUDIO_ERR_LOG("init remote fast fail, err %{public}d.", err);
647 fastSource_ = nullptr;
648 return false;
649 }
650 if (PrepareDeviceBuffer(deviceInfo) != SUCCESS) {
651 fastSource_->DeInit();
652 fastSource_ = nullptr;
653 return false;
654 }
655
656 bool ret = writeTimeModel_.ConfigSampleRate(dstStreamInfo_.samplingRate);
657 CHECK_AND_RETURN_RET_LOG(ret != false, false, "Config LinearPosTimeModel failed.");
658
659 endpointStatus_ = UNLINKED;
660 isInited_.store(true);
661 endpointWorkThread_ = std::thread([this] { this->RecordEndpointWorkLoopFuc(); });
662 pthread_setname_np(endpointWorkThread_.native_handle(), "OS_AudioEpLoop");
663
664 updatePosTimeThread_ = std::thread([this] { this->AsyncGetPosTime(); });
665 pthread_setname_np(updatePosTimeThread_.native_handle(), "OS_AudioEpUpdate");
666
667 // eg: input_endpoint_hdi_audio_8_0_20240527202236189_48000_2_1.pcm
668 dumpHdiName_ = "input_endpoint_hdi_audio_" + std::to_string(attr.deviceType) + '_' +
669 std::to_string(endpointType_) + '_' + GetTime() +
670 '_' + std::to_string(attr.sampleRate) + "_" +
671 std::to_string(attr.channel) + "_" + std::to_string(attr.format) + ".pcm";
672 DumpFileUtil::OpenDumpFile(DUMP_SERVER_PARA, dumpHdiName_, &dumpHdi_);
673 return true;
674 }
675
GetFastSource(const std::string & networkId,EndpointType type,IAudioSourceAttr & attr)676 IMmapAudioCapturerSource *AudioEndpointInner::GetFastSource(const std::string &networkId, EndpointType type,
677 IAudioSourceAttr &attr)
678 {
679 AUDIO_INFO_LOG("Network id %{public}s, endpoint type %{public}d", networkId.c_str(), type);
680 #ifdef DAUDIO_ENABLE
681 if (networkId != LOCAL_NETWORK_ID) {
682 attr.adapterName = "remote";
683 fastSourceType_ = type == AudioEndpoint::TYPE_MMAP ? FAST_SOURCE_TYPE_REMOTE : FAST_SOURCE_TYPE_VOIP;
684 // Distributed only requires a singleton because there won't be both voip and regular fast simultaneously
685 return RemoteFastAudioCapturerSource::GetInstance(networkId);
686 }
687 #endif
688
689 attr.adapterName = "primary";
690 if (type == AudioEndpoint::TYPE_MMAP) {
691 fastSourceType_ = FAST_SOURCE_TYPE_NORMAL;
692 return FastAudioCapturerSource::GetInstance();
693 } else if (type == AudioEndpoint::TYPE_VOIP_MMAP) {
694 fastSourceType_ = FAST_SOURCE_TYPE_VOIP;
695 return FastAudioCapturerSource::GetVoipInstance();
696 }
697 return nullptr;
698 }
699
StartThread(const IAudioSinkAttr & attr)700 void AudioEndpointInner::StartThread(const IAudioSinkAttr &attr)
701 {
702 endpointStatus_ = UNLINKED;
703 isInited_.store(true);
704 endpointWorkThread_ = std::thread([this] { this->EndpointWorkLoopFuc(); });
705 pthread_setname_np(endpointWorkThread_.native_handle(), "OS_AudioEpLoop");
706
707 updatePosTimeThread_ = std::thread([this] { this->AsyncGetPosTime(); });
708 pthread_setname_np(updatePosTimeThread_.native_handle(), "OS_AudioEpUpdate");
709
710 // eg: endpoint_hdi_audio_8_0_20240527202236189_48000_2_1.pcm
711 dumpHdiName_ = "endpoint_hdi_audio_" + std::to_string(attr.deviceType) + '_' + std::to_string(endpointType_) +
712 '_' + GetTime() + '_' +
713 std::to_string(attr.sampleRate) + "_" +
714 std::to_string(attr.channel) + "_" + std::to_string(attr.format) + ".pcm";
715 DumpFileUtil::OpenDumpFile(DUMP_SERVER_PARA, dumpHdiName_, &dumpHdi_);
716 }
717
Config(const DeviceInfo & deviceInfo)718 bool AudioEndpointInner::Config(const DeviceInfo &deviceInfo)
719 {
720 AUDIO_INFO_LOG("Config enter, deviceRole %{public}d.", deviceInfo.deviceRole);
721 deviceInfo_ = deviceInfo;
722 bool res = deviceInfo_.audioStreamInfo.CheckParams();
723 CHECK_AND_RETURN_RET_LOG(res, false, "samplingRate or channels size is 0");
724
725 dstStreamInfo_ = {
726 *deviceInfo.audioStreamInfo.samplingRate.rbegin(),
727 deviceInfo.audioStreamInfo.encoding,
728 deviceInfo.audioStreamInfo.format,
729 *deviceInfo.audioStreamInfo.channels.rbegin()
730 };
731 dstStreamInfo_.channelLayout = deviceInfo.audioStreamInfo.channelLayout;
732
733 if (deviceInfo.deviceRole == INPUT_DEVICE) {
734 return ConfigInputPoint(deviceInfo);
735 }
736
737 fastSink_ = GetFastSink(deviceInfo, endpointType_);
738 CHECK_AND_RETURN_RET_LOG(fastSink_ != nullptr, false, "Get fastSink instance failed");
739
740 IAudioSinkAttr attr = {};
741 attr.adapterName = deviceInfo.networkId == LOCAL_NETWORK_ID ? "primary" : "remote";
742 attr.sampleRate = dstStreamInfo_.samplingRate; // 48000hz
743 attr.channel = dstStreamInfo_.channels; // STEREO = 2
744 attr.format = ConvertToHdiAdapterFormat(dstStreamInfo_.format); // SAMPLE_S16LE = 1
745 attr.deviceNetworkId = deviceInfo.networkId.c_str();
746 attr.deviceType = static_cast<int32_t>(deviceInfo.deviceType);
747 attr.audioStreamFlag = endpointType_ == TYPE_VOIP_MMAP ? AUDIO_FLAG_VOIP_FAST : AUDIO_FLAG_MMAP;
748
749 fastSink_->Init(attr);
750 if (!fastSink_->IsInited()) {
751 fastSink_ = nullptr;
752 return false;
753 }
754 if (PrepareDeviceBuffer(deviceInfo) != SUCCESS) {
755 fastSink_->DeInit();
756 fastSink_ = nullptr;
757 return false;
758 }
759
760 float initVolume = 1.0; // init volume to 1.0
761 fastSink_->SetVolume(initVolume, initVolume);
762
763 bool ret = readTimeModel_.ConfigSampleRate(dstStreamInfo_.samplingRate);
764 CHECK_AND_RETURN_RET_LOG(ret != false, false, "Config LinearPosTimeModel failed.");
765
766 StartThread(attr);
767 return true;
768 }
769
GetFastSink(const DeviceInfo & deviceInfo,EndpointType type)770 IMmapAudioRendererSink *AudioEndpointInner::GetFastSink(const DeviceInfo &deviceInfo, EndpointType type)
771 {
772 AUDIO_INFO_LOG("Network id %{public}s, endpoint type %{public}d", deviceInfo.networkId.c_str(), type);
773 if (deviceInfo.networkId != LOCAL_NETWORK_ID) {
774 #ifdef DAUDIO_ENABLE
775 fastSinkType_ = type == AudioEndpoint::TYPE_MMAP ? FAST_SINK_TYPE_REMOTE : FAST_SINK_TYPE_VOIP;
776 // Distributed only requires a singleton because there won't be both voip and regular fast simultaneously
777 return RemoteFastAudioRendererSink::GetInstance(deviceInfo.networkId);
778 #endif
779 }
780
781 if (deviceInfo.deviceType == DEVICE_TYPE_BLUETOOTH_A2DP && deviceInfo.a2dpOffloadFlag != A2DP_OFFLOAD) {
782 fastSinkType_ = FAST_SINK_TYPE_BLUETOOTH;
783 return BluetoothRendererSink::GetMmapInstance();
784 }
785
786 if (type == AudioEndpoint::TYPE_MMAP) {
787 fastSinkType_ = FAST_SINK_TYPE_NORMAL;
788 return FastAudioRendererSink::GetInstance();
789 } else if (type == AudioEndpoint::TYPE_VOIP_MMAP) {
790 fastSinkType_ = FAST_SINK_TYPE_VOIP;
791 return FastAudioRendererSink::GetVoipInstance();
792 }
793 return nullptr;
794 }
795
GetAdapterBufferInfo(const DeviceInfo & deviceInfo)796 int32_t AudioEndpointInner::GetAdapterBufferInfo(const DeviceInfo &deviceInfo)
797 {
798 int32_t ret = 0;
799 AUDIO_INFO_LOG("GetAdapterBufferInfo enter, deviceRole %{public}d.", deviceInfo.deviceRole);
800 if (deviceInfo.deviceRole == INPUT_DEVICE) {
801 CHECK_AND_RETURN_RET_LOG(fastSource_ != nullptr, ERR_INVALID_HANDLE,
802 "fast source is null.");
803 ret = fastSource_->GetMmapBufferInfo(dstBufferFd_, dstTotalSizeInframe_, dstSpanSizeInframe_,
804 dstByteSizePerFrame_);
805 } else {
806 CHECK_AND_RETURN_RET_LOG(fastSink_ != nullptr, ERR_INVALID_HANDLE, "fast sink is null.");
807 ret = fastSink_->GetMmapBufferInfo(dstBufferFd_, dstTotalSizeInframe_, dstSpanSizeInframe_,
808 dstByteSizePerFrame_);
809 }
810
811 if (ret != SUCCESS || dstBufferFd_ == -1 || dstTotalSizeInframe_ == 0 || dstSpanSizeInframe_ == 0 ||
812 dstByteSizePerFrame_ == 0) {
813 AUDIO_ERR_LOG("get mmap buffer info fail, ret %{public}d, dstBufferFd %{public}d, \
814 dstTotalSizeInframe %{public}d, dstSpanSizeInframe %{public}d, dstByteSizePerFrame %{public}d.",
815 ret, dstBufferFd_, dstTotalSizeInframe_, dstSpanSizeInframe_, dstByteSizePerFrame_);
816 return ERR_ILLEGAL_STATE;
817 }
818 AUDIO_DEBUG_LOG("end, fd %{public}d.", dstBufferFd_);
819 return SUCCESS;
820 }
821
PrepareDeviceBuffer(const DeviceInfo & deviceInfo)822 int32_t AudioEndpointInner::PrepareDeviceBuffer(const DeviceInfo &deviceInfo)
823 {
824 AUDIO_INFO_LOG("enter, deviceRole %{public}d.", deviceInfo.deviceRole);
825 if (dstAudioBuffer_ != nullptr) {
826 AUDIO_INFO_LOG("endpoint buffer is preapred, fd:%{public}d", dstBufferFd_);
827 return SUCCESS;
828 }
829
830 int32_t ret = GetAdapterBufferInfo(deviceInfo);
831 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_OPERATION_FAILED,
832 "get adapter buffer Info fail, ret %{public}d.", ret);
833
834 // spanDuration_ may be less than the correct time of dstSpanSizeInframe_.
835 spanDuration_ = static_cast<int64_t>(dstSpanSizeInframe_) * AUDIO_NS_PER_SECOND /
836 static_cast<int64_t>(dstStreamInfo_.samplingRate);
837 int64_t temp = spanDuration_ / 5 * 3; // 3/5 spanDuration
838 serverAheadReadTime_ = temp < ONE_MILLISECOND_DURATION ? ONE_MILLISECOND_DURATION : temp; // at least 1ms ahead.
839 AUDIO_DEBUG_LOG("panDuration %{public}" PRIu64" ns, serverAheadReadTime %{public}" PRIu64" ns.",
840 spanDuration_, serverAheadReadTime_);
841
842 CHECK_AND_RETURN_RET_LOG(spanDuration_ > 0 && spanDuration_ < MAX_SPAN_DURATION_NS,
843 ERR_INVALID_PARAM, "mmap span info error, spanDuration %{public}" PRIu64".", spanDuration_);
844 dstAudioBuffer_ = OHAudioBuffer::CreateFromRemote(dstTotalSizeInframe_, dstSpanSizeInframe_, dstByteSizePerFrame_,
845 AUDIO_SERVER_ONLY, dstBufferFd_, OHAudioBuffer::INVALID_BUFFER_FD);
846 CHECK_AND_RETURN_RET_LOG(dstAudioBuffer_ != nullptr && dstAudioBuffer_->GetBufferHolder() ==
847 AudioBufferHolder::AUDIO_SERVER_ONLY, ERR_ILLEGAL_STATE, "create buffer from remote fail.");
848
849 if (dstAudioBuffer_ == nullptr || dstAudioBuffer_->GetStreamStatus() == nullptr) {
850 AUDIO_ERR_LOG("The stream status is null!");
851 return ERR_INVALID_PARAM;
852 }
853
854 dstAudioBuffer_->GetStreamStatus()->store(StreamStatus::STREAM_IDEL);
855
856 // clear data buffer
857 ret = memset_s(dstAudioBuffer_->GetDataBase(), dstAudioBuffer_->GetDataSize(), 0, dstAudioBuffer_->GetDataSize());
858 if (ret != EOK) {
859 AUDIO_WARNING_LOG("memset buffer fail, ret %{public}d, fd %{public}d.", ret, dstBufferFd_);
860 }
861 InitAudiobuffer(true);
862
863 AUDIO_DEBUG_LOG("end, fd %{public}d.", dstBufferFd_);
864 return SUCCESS;
865 }
866
InitAudiobuffer(bool resetReadWritePos)867 void AudioEndpointInner::InitAudiobuffer(bool resetReadWritePos)
868 {
869 CHECK_AND_RETURN_LOG((dstAudioBuffer_ != nullptr), "dst audio buffer is null.");
870 if (resetReadWritePos) {
871 dstAudioBuffer_->ResetCurReadWritePos(0, 0);
872 }
873
874 uint32_t spanCount = dstAudioBuffer_->GetSpanCount();
875 for (uint32_t i = 0; i < spanCount; i++) {
876 SpanInfo *spanInfo = dstAudioBuffer_->GetSpanInfoByIndex(i);
877 CHECK_AND_RETURN_LOG(spanInfo != nullptr, "InitAudiobuffer failed.");
878 if (deviceInfo_.deviceRole == INPUT_DEVICE) {
879 spanInfo->spanStatus = SPAN_WRITE_DONE;
880 } else {
881 spanInfo->spanStatus = SPAN_READ_DONE;
882 }
883 spanInfo->offsetInFrame = 0;
884
885 spanInfo->readStartTime = 0;
886 spanInfo->readDoneTime = 0;
887
888 spanInfo->writeStartTime = 0;
889 spanInfo->writeDoneTime = 0;
890
891 spanInfo->volumeStart = 1 << VOLUME_SHIFT_NUMBER; // 65536 for initialize
892 spanInfo->volumeEnd = 1 << VOLUME_SHIFT_NUMBER; // 65536 for initialize
893 spanInfo->isMute = false;
894 }
895 return;
896 }
897
GetPreferBufferInfo(uint32_t & totalSizeInframe,uint32_t & spanSizeInframe)898 int32_t AudioEndpointInner::GetPreferBufferInfo(uint32_t &totalSizeInframe, uint32_t &spanSizeInframe)
899 {
900 totalSizeInframe = dstTotalSizeInframe_;
901 spanSizeInframe = dstSpanSizeInframe_;
902 return SUCCESS;
903 }
904
IsAnyProcessRunning()905 bool AudioEndpointInner::IsAnyProcessRunning()
906 {
907 std::lock_guard<std::mutex> lock(listLock_);
908 return IsAnyProcessRunningInner();
909 }
910
911 // Should be called with AudioEndpointInner::listLock_ locked
IsAnyProcessRunningInner()912 bool AudioEndpointInner::IsAnyProcessRunningInner()
913 {
914 bool isRunning = false;
915 for (size_t i = 0; i < processBufferList_.size(); i++) {
916 if (processBufferList_[i]->GetStreamStatus() &&
917 processBufferList_[i]->GetStreamStatus()->load() == STREAM_RUNNING) {
918 isRunning = true;
919 break;
920 }
921 }
922 return isRunning;
923 }
924
RecordReSyncPosition()925 void AudioEndpointInner::RecordReSyncPosition()
926 {
927 AUDIO_INFO_LOG("RecordReSyncPosition enter.");
928 uint64_t curHdiWritePos = 0;
929 int64_t writeTime = 0;
930 CHECK_AND_RETURN_LOG(GetDeviceHandleInfo(curHdiWritePos, writeTime),
931 "get device handle info fail.");
932 AUDIO_DEBUG_LOG("get capturer info, curHdiWritePos %{public}" PRIu64", writeTime %{public}" PRId64".",
933 curHdiWritePos, writeTime);
934 int64_t temp = ClockTime::GetCurNano() - writeTime;
935 if (temp > spanDuration_) {
936 AUDIO_WARNING_LOG("GetDeviceHandleInfo cost long time %{public}" PRIu64".", temp);
937 }
938
939 writeTimeModel_.ResetFrameStamp(curHdiWritePos, writeTime);
940 uint64_t nextDstReadPos = curHdiWritePos;
941 uint64_t nextDstWritePos = curHdiWritePos;
942 InitAudiobuffer(false);
943 int32_t ret = dstAudioBuffer_->ResetCurReadWritePos(nextDstReadPos, nextDstWritePos);
944 CHECK_AND_RETURN_LOG(ret == SUCCESS, "ResetCurReadWritePos failed.");
945
946 SpanInfo *nextReadSapn = dstAudioBuffer_->GetSpanInfo(nextDstReadPos);
947 CHECK_AND_RETURN_LOG(nextReadSapn != nullptr, "GetSpanInfo failed.");
948 nextReadSapn->offsetInFrame = nextDstReadPos;
949 nextReadSapn->spanStatus = SpanStatus::SPAN_WRITE_DONE;
950 }
951
ReSyncPosition()952 void AudioEndpointInner::ReSyncPosition()
953 {
954 Trace loopTrace("AudioEndpoint::ReSyncPosition");
955 uint64_t curHdiReadPos = 0;
956 int64_t readTime = 0;
957 bool res = GetDeviceHandleInfo(curHdiReadPos, readTime);
958 CHECK_AND_RETURN_LOG(res, "ReSyncPosition call GetDeviceHandleInfo failed.");
959 int64_t curTime = ClockTime::GetCurNano();
960 int64_t temp = curTime - readTime;
961 if (temp > spanDuration_) {
962 AUDIO_ERR_LOG("GetDeviceHandleInfo may cost long time.");
963 }
964
965 readTimeModel_.ResetFrameStamp(curHdiReadPos, readTime);
966 uint64_t nextDstWritePos = curHdiReadPos + dstSpanSizeInframe_;
967 InitAudiobuffer(false);
968 int32_t ret = dstAudioBuffer_->ResetCurReadWritePos(nextDstWritePos, nextDstWritePos);
969 CHECK_AND_RETURN_LOG(ret == SUCCESS, "ResetCurReadWritePos failed.");
970
971 SpanInfo *nextWriteSapn = dstAudioBuffer_->GetSpanInfo(nextDstWritePos);
972 CHECK_AND_RETURN_LOG(nextWriteSapn != nullptr, "GetSpanInfo failed.");
973 nextWriteSapn->offsetInFrame = nextDstWritePos;
974 nextWriteSapn->spanStatus = SpanStatus::SPAN_READ_DONE;
975 return;
976 }
977
StartDevice()978 bool AudioEndpointInner::StartDevice()
979 {
980 AUDIO_INFO_LOG("StartDevice enter.");
981 // how to modify the status while unlinked and started?
982 CHECK_AND_RETURN_RET_LOG(endpointStatus_ == IDEL, false, "Endpoint status is %{public}s",
983 GetStatusStr(endpointStatus_).c_str());
984 endpointStatus_ = STARTING;
985 if ((deviceInfo_.deviceRole == INPUT_DEVICE && (fastSource_ == nullptr || fastSource_->Start() != SUCCESS)) ||
986 (deviceInfo_.deviceRole == OUTPUT_DEVICE && (fastSink_ == nullptr || fastSink_->Start() != SUCCESS))) {
987 HandleStartDeviceFailed();
988 return false;
989 }
990 isStarted_ = true;
991
992 if (isInnerCapEnabled_) {
993 Trace trace("AudioEndpointInner::StartDupStream");
994 std::lock_guard<std::mutex> lock(dupMutex_);
995 if (dupStream_ != nullptr) {
996 dupStream_->Start();
997 }
998 }
999
1000 std::unique_lock<std::mutex> lock(loopThreadLock_);
1001 needReSyncPosition_ = true;
1002 endpointStatus_ = IsAnyProcessRunning() ? RUNNING : IDEL;
1003 workThreadCV_.notify_all();
1004 AUDIO_DEBUG_LOG("StartDevice out, status is %{public}s", GetStatusStr(endpointStatus_).c_str());
1005 return true;
1006 }
1007
HandleStartDeviceFailed()1008 void AudioEndpointInner::HandleStartDeviceFailed()
1009 {
1010 AUDIO_ERR_LOG("Start failed for %{public}d, endpoint type %{public}u, process list size: %{public}zu.",
1011 deviceInfo_.deviceRole, endpointType_, processList_.size());
1012 std::lock_guard<std::mutex> lock(listLock_);
1013 isStarted_ = false;
1014 if (processList_.size() <= 1) { // The endpoint only has the current stream
1015 endpointStatus_ = UNLINKED;
1016 } else {
1017 endpointStatus_ = IDEL;
1018 }
1019 workThreadCV_.notify_all();
1020 }
1021
1022 // will not change state to stopped
DelayStopDevice()1023 bool AudioEndpointInner::DelayStopDevice()
1024 {
1025 AUDIO_INFO_LOG("Status:%{public}s", GetStatusStr(endpointStatus_).c_str());
1026
1027 // Clear data buffer to avoid noise in some case.
1028 if (dstAudioBuffer_ != nullptr) {
1029 int32_t ret = memset_s(dstAudioBuffer_->GetDataBase(), dstAudioBuffer_->GetDataSize(), 0,
1030 dstAudioBuffer_->GetDataSize());
1031 if (ret != EOK) {
1032 AUDIO_WARNING_LOG("reset buffer fail, ret %{public}d.", ret);
1033 }
1034 }
1035
1036 if (isInnerCapEnabled_) {
1037 Trace trace("AudioEndpointInner::StopDupStreamInDelay");
1038 std::lock_guard<std::mutex> lock(dupMutex_);
1039 if (dupStream_ != nullptr) {
1040 dupStream_->Stop();
1041 }
1042 }
1043
1044 if (deviceInfo_.deviceRole == INPUT_DEVICE) {
1045 CHECK_AND_RETURN_RET_LOG(fastSource_ != nullptr && fastSource_->Stop() == SUCCESS,
1046 false, "Source stop failed.");
1047 } else {
1048 CHECK_AND_RETURN_RET_LOG(endpointStatus_ == IDEL && fastSink_ != nullptr && fastSink_->Stop() == SUCCESS,
1049 false, "Sink stop failed.");
1050 }
1051 isStarted_ = false;
1052 return true;
1053 }
1054
StopDevice()1055 bool AudioEndpointInner::StopDevice()
1056 {
1057 DeinitLatencyMeasurement();
1058
1059 AUDIO_INFO_LOG("StopDevice with status:%{public}s", GetStatusStr(endpointStatus_).c_str());
1060 // todo
1061 endpointStatus_ = STOPPING;
1062 // Clear data buffer to avoid noise in some case.
1063 if (dstAudioBuffer_ != nullptr) {
1064 int32_t ret = memset_s(dstAudioBuffer_->GetDataBase(), dstAudioBuffer_->GetDataSize(), 0,
1065 dstAudioBuffer_->GetDataSize());
1066 AUDIO_INFO_LOG("StopDevice clear buffer ret:%{public}d", ret);
1067 }
1068
1069 if (isInnerCapEnabled_) {
1070 Trace trace("AudioEndpointInner::StopDupStream");
1071 std::lock_guard<std::mutex> lock(dupMutex_);
1072 if (dupStream_ != nullptr) {
1073 dupStream_->Stop();
1074 }
1075 }
1076
1077 if (deviceInfo_.deviceRole == INPUT_DEVICE) {
1078 CHECK_AND_RETURN_RET_LOG(fastSource_ != nullptr && fastSource_->Stop() == SUCCESS,
1079 false, "Source stop failed.");
1080 } else {
1081 CHECK_AND_RETURN_RET_LOG(fastSink_ != nullptr && fastSink_->Stop() == SUCCESS,
1082 false, "Sink stop failed.");
1083 }
1084 endpointStatus_ = STOPPED;
1085 isStarted_ = false;
1086 return true;
1087 }
1088
OnStart(IAudioProcessStream * processStream)1089 int32_t AudioEndpointInner::OnStart(IAudioProcessStream *processStream)
1090 {
1091 InitLatencyMeasurement();
1092 // Prevents the audio from immediately stopping at 0 volume on start
1093 delayStopTimeForZeroVolume_ = ClockTime::GetCurNano() + DELAY_STOP_HDI_TIME_FOR_ZERO_VOLUME_NS;
1094 AUDIO_PRERELEASE_LOGI("OnStart endpoint status:%{public}s", GetStatusStr(endpointStatus_).c_str());
1095 if (endpointStatus_ == RUNNING) {
1096 AUDIO_INFO_LOG("OnStart find endpoint already in RUNNING.");
1097 return SUCCESS;
1098 }
1099 if (endpointStatus_ == IDEL) {
1100 // call sink start
1101 if (!isStarted_) {
1102 CHECK_AND_RETURN_RET_LOG(StartDevice(), ERR_OPERATION_FAILED, "StartDevice failed");
1103 }
1104 }
1105
1106 endpointStatus_ = RUNNING;
1107 delayStopTime_ = INT64_MAX;
1108 return SUCCESS;
1109 }
1110
OnPause(IAudioProcessStream * processStream)1111 int32_t AudioEndpointInner::OnPause(IAudioProcessStream *processStream)
1112 {
1113 AUDIO_PRERELEASE_LOGI("OnPause endpoint status:%{public}s", GetStatusStr(endpointStatus_).c_str());
1114 if (endpointStatus_ == RUNNING) {
1115 endpointStatus_ = IsAnyProcessRunning() ? RUNNING : IDEL;
1116 }
1117 if (endpointStatus_ == IDEL) {
1118 // delay call sink stop when no process running
1119 AUDIO_PRERELEASE_LOGI("OnPause status is IDEL, need delay call stop");
1120 delayStopTime_ = ClockTime::GetCurNano() + DELAY_STOP_HDI_TIME;
1121 }
1122 // todo
1123 return SUCCESS;
1124 }
1125
GetProcLastWriteDoneInfo(const std::shared_ptr<OHAudioBuffer> processBuffer,uint64_t curWriteFrame,uint64_t & proHandleFrame,int64_t & proHandleTime)1126 int32_t AudioEndpointInner::GetProcLastWriteDoneInfo(const std::shared_ptr<OHAudioBuffer> processBuffer,
1127 uint64_t curWriteFrame, uint64_t &proHandleFrame, int64_t &proHandleTime)
1128 {
1129 CHECK_AND_RETURN_RET_LOG(processBuffer != nullptr, ERR_INVALID_HANDLE, "Process found but buffer is null");
1130 uint64_t curReadFrame = processBuffer->GetCurReadFrame();
1131 SpanInfo *curWriteSpan = processBuffer->GetSpanInfo(curWriteFrame);
1132 CHECK_AND_RETURN_RET_LOG(curWriteSpan != nullptr, ERR_INVALID_HANDLE,
1133 "curWriteSpan of curWriteFrame %{public}" PRIu64" is null", curWriteFrame);
1134 if (curWriteSpan->spanStatus == SpanStatus::SPAN_WRITE_DONE || curWriteFrame < dstSpanSizeInframe_ ||
1135 curWriteFrame < curReadFrame) {
1136 proHandleFrame = curWriteFrame;
1137 proHandleTime = curWriteSpan->writeDoneTime;
1138 } else {
1139 int32_t ret = GetProcLastWriteDoneInfo(processBuffer, curWriteFrame - dstSpanSizeInframe_,
1140 proHandleFrame, proHandleTime);
1141 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ret,
1142 "get process last write done info fail, ret %{public}d.", ret);
1143 }
1144
1145 AUDIO_INFO_LOG("GetProcLastWriteDoneInfo end, curWriteFrame %{public}" PRIu64", proHandleFrame %{public}" PRIu64", "
1146 "proHandleTime %{public}" PRId64".", curWriteFrame, proHandleFrame, proHandleTime);
1147 return SUCCESS;
1148 }
1149
OnUpdateHandleInfo(IAudioProcessStream * processStream)1150 int32_t AudioEndpointInner::OnUpdateHandleInfo(IAudioProcessStream *processStream)
1151 {
1152 Trace trace("AudioEndpoint::OnUpdateHandleInfo");
1153 bool isFind = false;
1154 std::lock_guard<std::mutex> lock(listLock_);
1155 auto processItr = processList_.begin();
1156 while (processItr != processList_.end()) {
1157 if (*processItr != processStream) {
1158 processItr++;
1159 continue;
1160 }
1161 std::shared_ptr<OHAudioBuffer> processBuffer = (*processItr)->GetStreamBuffer();
1162 CHECK_AND_RETURN_RET_LOG(processBuffer != nullptr, ERR_OPERATION_FAILED, "Process found but buffer is null");
1163 uint64_t proHandleFrame = 0;
1164 int64_t proHandleTime = 0;
1165 if (deviceInfo_.deviceRole == INPUT_DEVICE) {
1166 uint64_t curWriteFrame = processBuffer->GetCurWriteFrame();
1167 int32_t ret = GetProcLastWriteDoneInfo(processBuffer, curWriteFrame, proHandleFrame, proHandleTime);
1168 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ret,
1169 "get process last write done info fail, ret %{public}d.", ret);
1170 processBuffer->SetHandleInfo(proHandleFrame, proHandleTime);
1171 } else {
1172 // For output device, handle info is updated in CheckAllBufferReady
1173 processBuffer->GetHandleInfo(proHandleFrame, proHandleTime);
1174 }
1175
1176 isFind = true;
1177 break;
1178 }
1179 CHECK_AND_RETURN_RET_LOG(isFind, ERR_OPERATION_FAILED, "Can not find any process to UpdateHandleInfo");
1180 return SUCCESS;
1181 }
1182
LinkProcessStream(IAudioProcessStream * processStream)1183 int32_t AudioEndpointInner::LinkProcessStream(IAudioProcessStream *processStream)
1184 {
1185 CHECK_AND_RETURN_RET_LOG(processStream != nullptr, ERR_INVALID_PARAM, "IAudioProcessStream is null");
1186 std::shared_ptr<OHAudioBuffer> processBuffer = processStream->GetStreamBuffer();
1187 processBuffer->SetSessionId(processStream->GetAudioSessionId());
1188 CHECK_AND_RETURN_RET_LOG(processBuffer != nullptr, ERR_INVALID_PARAM, "processBuffer is null");
1189 CHECK_AND_RETURN_RET_LOG(processBuffer->GetStreamStatus() != nullptr, ERR_INVALID_PARAM,
1190 "the stream status is null");
1191
1192 CHECK_AND_RETURN_RET_LOG(processList_.size() < MAX_LINKED_PROCESS, ERR_OPERATION_FAILED, "reach link limit.");
1193
1194 AUDIO_INFO_LOG("LinkProcessStream start status is:%{public}s.", GetStatusStr(endpointStatus_).c_str());
1195
1196 bool needEndpointRunning = processBuffer->GetStreamStatus()->load() == STREAM_RUNNING;
1197
1198 if (endpointStatus_ == STARTING) {
1199 AUDIO_INFO_LOG("LinkProcessStream wait start begin.");
1200 std::unique_lock<std::mutex> lock(loopThreadLock_);
1201 workThreadCV_.wait_for(lock, std::chrono::milliseconds(SLEEP_TIME_IN_DEFAULT), [this] {
1202 return endpointStatus_ != STARTING;
1203 });
1204 AUDIO_DEBUG_LOG("LinkProcessStream wait start end.");
1205 }
1206
1207 if (endpointStatus_ == RUNNING) {
1208 LinkProcessStreamExt(processStream, processBuffer);
1209 return SUCCESS;
1210 }
1211
1212 if (endpointStatus_ == UNLINKED) {
1213 endpointStatus_ = IDEL; // handle push_back in IDEL
1214 if (isDeviceRunningInIdel_) {
1215 CHECK_AND_RETURN_RET_LOG(StartDevice(), ERR_OPERATION_FAILED, "StartDevice failed");
1216 delayStopTime_ = ClockTime::GetCurNano() + DELAY_STOP_HDI_TIME;
1217 }
1218 }
1219
1220 if (endpointStatus_ == IDEL) {
1221 {
1222 std::lock_guard<std::mutex> lock(listLock_);
1223 processList_.push_back(processStream);
1224 processBufferList_.push_back(processBuffer);
1225 }
1226 if (!needEndpointRunning) {
1227 AUDIO_INFO_LOG("LinkProcessStream success, process stream status is not running.");
1228 return SUCCESS;
1229 }
1230 // needEndpointRunning = true
1231 if (isDeviceRunningInIdel_) {
1232 endpointStatus_ = IsAnyProcessRunning() ? RUNNING : IDEL;
1233 } else {
1234 // needEndpointRunning = true & isDeviceRunningInIdel_ = false
1235 // KeepWorkloopRunning will wait on IDEL
1236 CHECK_AND_RETURN_RET_LOG(StartDevice(), ERR_OPERATION_FAILED, "StartDevice failed");
1237 }
1238 AUDIO_INFO_LOG("LinkProcessStream success with status:%{public}s", GetStatusStr(endpointStatus_).c_str());
1239 return SUCCESS;
1240 }
1241
1242 AUDIO_INFO_LOG("LinkProcessStream success with status:%{public}s", GetStatusStr(endpointStatus_).c_str());
1243 return SUCCESS;
1244 }
1245
LinkProcessStreamExt(IAudioProcessStream * processStream,const std::shared_ptr<OHAudioBuffer> & processBuffer)1246 void AudioEndpointInner::LinkProcessStreamExt(IAudioProcessStream *processStream,
1247 const std::shared_ptr<OHAudioBuffer>& processBuffer)
1248 {
1249 std::lock_guard<std::mutex> lock(listLock_);
1250 processList_.push_back(processStream);
1251 processBufferList_.push_back(processBuffer);
1252 AUDIO_INFO_LOG("LinkProcessStream success in RUNNING.");
1253 }
1254
UnlinkProcessStream(IAudioProcessStream * processStream)1255 int32_t AudioEndpointInner::UnlinkProcessStream(IAudioProcessStream *processStream)
1256 {
1257 AUDIO_INFO_LOG("UnlinkProcessStream in status:%{public}s.", GetStatusStr(endpointStatus_).c_str());
1258 CHECK_AND_RETURN_RET_LOG(processStream != nullptr, ERR_INVALID_PARAM, "IAudioProcessStream is null");
1259 std::shared_ptr<OHAudioBuffer> processBuffer = processStream->GetStreamBuffer();
1260 CHECK_AND_RETURN_RET_LOG(processBuffer != nullptr, ERR_INVALID_PARAM, "processBuffer is null");
1261
1262 bool isFind = false;
1263 std::lock_guard<std::mutex> lock(listLock_);
1264 auto processItr = processList_.begin();
1265 auto bufferItr = processBufferList_.begin();
1266 while (processItr != processList_.end()) {
1267 if (*processItr == processStream && *bufferItr == processBuffer) {
1268 processList_.erase(processItr);
1269 processBufferList_.erase(bufferItr);
1270 isFind = true;
1271 break;
1272 } else {
1273 processItr++;
1274 bufferItr++;
1275 }
1276 }
1277 if (processList_.size() == 0) {
1278 StopDevice();
1279 endpointStatus_ = UNLINKED;
1280 } else if (!IsAnyProcessRunningInner()) {
1281 endpointStatus_ = IDEL;
1282 isStarted_ = false;
1283 delayStopTime_ = DELAY_STOP_HDI_TIME_WHEN_NO_RUNNING_NS;
1284 }
1285
1286 AUDIO_DEBUG_LOG("UnlinkProcessStream end, %{public}s the process.", (isFind ? "find and remove" : "not find"));
1287 return SUCCESS;
1288 }
1289
CheckStandBy()1290 void AudioEndpointInner::CheckStandBy()
1291 {
1292 if (endpointStatus_ == RUNNING) {
1293 endpointStatus_ = IsAnyProcessRunning() ? RUNNING : IDEL;
1294 }
1295
1296 if (endpointStatus_ == RUNNING) {
1297 return;
1298 }
1299
1300 AUDIO_INFO_LOG("endpoint status:%{public}s", GetStatusStr(endpointStatus_).c_str());
1301 if (endpointStatus_ == IDEL) {
1302 // delay call sink stop when no process running
1303 AUDIO_INFO_LOG("status is IDEL, need delay call stop");
1304 delayStopTime_ = ClockTime::GetCurNano() + DELAY_STOP_HDI_TIME;
1305 }
1306 }
1307
CheckAllBufferReady(int64_t checkTime,uint64_t curWritePos)1308 bool AudioEndpointInner::CheckAllBufferReady(int64_t checkTime, uint64_t curWritePos)
1309 {
1310 bool isAllReady = true;
1311 bool needCheckStandby = false;
1312 {
1313 // lock list without sleep
1314 std::lock_guard<std::mutex> lock(listLock_);
1315 for (size_t i = 0; i < processBufferList_.size(); i++) {
1316 std::shared_ptr<OHAudioBuffer> tempBuffer = processBufferList_[i];
1317 uint64_t eachCurReadPos = processBufferList_[i]->GetCurReadFrame();
1318 lastHandleProcessTime_ = checkTime;
1319 processBufferList_[i]->SetHandleInfo(eachCurReadPos, lastHandleProcessTime_); // update handle info
1320 if (tempBuffer->GetStreamStatus() &&
1321 tempBuffer->GetStreamStatus()->load() != StreamStatus::STREAM_RUNNING) {
1322 // Process is not running, server will continue to check the same location in the next cycle.
1323 int64_t duration = 5000000; // 5ms
1324 processBufferList_[i]->SetHandleInfo(eachCurReadPos, lastHandleProcessTime_ + duration);
1325 continue; // process not running
1326 }
1327 // Status is RUNNING
1328 int64_t current = ClockTime::GetCurNano();
1329 int64_t lastWrittenTime = tempBuffer->GetLastWrittenTime();
1330 if (current - lastWrittenTime > WAIT_CLIENT_STANDBY_TIME_NS) {
1331 Trace trace("AudioEndpoint::MarkClientStandby");
1332 AUDIO_INFO_LOG("change the status to stand-by, session %{public}u", tempBuffer->GetSessionId());
1333 CHECK_AND_RETURN_RET_LOG(tempBuffer->GetStreamStatus() != nullptr, false, "GetStreamStatus failed");
1334 tempBuffer->GetStreamStatus()->store(StreamStatus::STREAM_STAND_BY);
1335 WriterRenderStreamStandbySysEvent(tempBuffer->GetSessionId(), 1);
1336 needCheckStandby = true;
1337 continue;
1338 }
1339 uint64_t curRead = tempBuffer->GetCurReadFrame();
1340 SpanInfo *curReadSpan = tempBuffer->GetSpanInfo(curRead);
1341 if (curReadSpan == nullptr || curReadSpan->spanStatus != SpanStatus::SPAN_WRITE_DONE) {
1342 AUDIO_DEBUG_LOG("Find one process not ready"); // print uid of the process?
1343 isAllReady = false;
1344 continue;
1345 }
1346 // process Status is RUNNING && buffer status is WRITE_DONE
1347 tempBuffer->SetLastWrittenTime(current);
1348 }
1349 }
1350
1351 if (needCheckStandby) {
1352 CheckStandBy();
1353 }
1354
1355 if (!isAllReady) {
1356 WaitAllProcessReady(curWritePos);
1357 }
1358 return isAllReady;
1359 }
1360
WaitAllProcessReady(uint64_t curWritePos)1361 void AudioEndpointInner::WaitAllProcessReady(uint64_t curWritePos)
1362 {
1363 Trace trace("AudioEndpoint::WaitAllProcessReady");
1364 int64_t tempWakeupTime = readTimeModel_.GetTimeOfPos(curWritePos) + WRITE_TO_HDI_AHEAD_TIME;
1365 if (tempWakeupTime - ClockTime::GetCurNano() < ONE_MILLISECOND_DURATION) {
1366 ClockTime::RelativeSleep(ONE_MILLISECOND_DURATION);
1367 } else {
1368 ClockTime::AbsoluteSleep(tempWakeupTime); // sleep to hdi read time ahead 1ms.
1369 }
1370 }
1371
MixToDupStream(const std::vector<AudioStreamData> & srcDataList)1372 void AudioEndpointInner::MixToDupStream(const std::vector<AudioStreamData> &srcDataList)
1373 {
1374 Trace trace("AudioEndpointInner::MixToDupStream");
1375 std::lock_guard<std::mutex> lock(dupMutex_);
1376 CHECK_AND_RETURN_LOG(dupBuffer_ != nullptr, "Buffer is not ready");
1377
1378 for (size_t i = 0; i < srcDataList.size(); i++) {
1379 if (!srcDataList[i].isInnerCaped) {
1380 continue;
1381 }
1382 size_t dataLength = dupBufferSize_;
1383 dataLength /= 2; // SAMPLE_S16LE--> 2 byte
1384 int16_t *dstPtr = reinterpret_cast<int16_t *>(dupBuffer_.get());
1385
1386 for (size_t offset = 0; dataLength > 0; dataLength--) {
1387 int32_t sum = *dstPtr;
1388 sum += *(reinterpret_cast<int16_t *>(srcDataList[i].bufferDesc.buffer) + offset);
1389 *dstPtr = sum > INT16_MAX ? INT16_MAX : (sum < INT16_MIN ? INT16_MIN : sum);
1390 dstPtr++;
1391 offset++;
1392 }
1393 }
1394 BufferDesc temp;
1395 temp.buffer = dupBuffer_.get();
1396 temp.bufLength = dupBufferSize_;
1397 temp.dataLength = dupBufferSize_;
1398
1399 CHECK_AND_RETURN_LOG(dupStream_ != nullptr, "dupStream_ is nullptr");
1400 int32_t ret = dupStream_->EnqueueBuffer(temp);
1401 CHECK_AND_RETURN_LOG(ret == SUCCESS, "EnqueueBuffer failed:%{public}d", ret);
1402
1403 ret = memset_s(reinterpret_cast<void *>(dupBuffer_.get()), dupBufferSize_, 0, dupBufferSize_);
1404 if (ret != EOK) {
1405 AUDIO_WARNING_LOG("memset buffer fail, ret %{public}d", ret);
1406 }
1407 }
1408
ProcessData(const std::vector<AudioStreamData> & srcDataList,const AudioStreamData & dstData)1409 void AudioEndpointInner::ProcessData(const std::vector<AudioStreamData> &srcDataList, const AudioStreamData &dstData)
1410 {
1411 size_t srcListSize = srcDataList.size();
1412
1413 for (size_t i = 0; i < srcListSize; i++) {
1414 if (srcDataList[i].streamInfo.format != SAMPLE_S16LE || srcDataList[i].streamInfo.channels != STEREO ||
1415 srcDataList[i].bufferDesc.bufLength != dstData.bufferDesc.bufLength ||
1416 srcDataList[i].bufferDesc.dataLength != dstData.bufferDesc.dataLength) {
1417 AUDIO_ERR_LOG("ProcessData failed, streamInfo are different");
1418 return;
1419 }
1420 }
1421
1422 // Assum using the same format and same size
1423 CHECK_AND_RETURN_LOG(dstData.streamInfo.format == SAMPLE_S16LE && dstData.streamInfo.channels == STEREO,
1424 "ProcessData failed, streamInfo are not support");
1425
1426 size_t dataLength = dstData.bufferDesc.dataLength;
1427 dataLength /= 2; // SAMPLE_S16LE--> 2 byte
1428 int16_t *dstPtr = reinterpret_cast<int16_t *>(dstData.bufferDesc.buffer);
1429 for (size_t offset = 0; dataLength > 0; dataLength--) {
1430 int32_t sum = 0;
1431 for (size_t i = 0; i < srcListSize; i++) {
1432 int32_t vol = srcDataList[i].volumeStart; // change to modify volume of each channel
1433 int16_t *srcPtr = reinterpret_cast<int16_t *>(srcDataList[i].bufferDesc.buffer) + offset;
1434 sum += (*srcPtr * static_cast<int64_t>(vol)) >> VOLUME_SHIFT_NUMBER; // 1/65536
1435 ZeroVolumeCheck(vol);
1436 }
1437 offset++;
1438 *dstPtr++ = sum > INT16_MAX ? INT16_MAX : (sum < INT16_MIN ? INT16_MIN : sum);
1439 }
1440 HandleZeroVolumeCheckEvent();
1441 }
1442
HandleZeroVolumeCheckEvent()1443 void AudioEndpointInner::HandleZeroVolumeCheckEvent()
1444 {
1445 if (!zeroVolumeStopDevice_ && (ClockTime::GetCurNano() >= delayStopTimeForZeroVolume_)) {
1446 if (isStarted_) {
1447 if (fastSink_ != nullptr && fastSink_->Stop() == SUCCESS) {
1448 AUDIO_INFO_LOG("Volume from none-zero to zero more than 4s, stop device success.");
1449 isStarted_ = false;
1450 } else {
1451 AUDIO_INFO_LOG("Volume from none-zero to zero more than 4s, stop device failed.");
1452 isStarted_ = true;
1453 }
1454 }
1455 zeroVolumeStopDevice_ = true;
1456 }
1457 }
1458
1459
HandleRendererDataParams(const AudioStreamData & srcData,const AudioStreamData & dstData)1460 void AudioEndpointInner::HandleRendererDataParams(const AudioStreamData &srcData, const AudioStreamData &dstData)
1461 {
1462 if (srcData.streamInfo.encoding != dstData.streamInfo.encoding) {
1463 AUDIO_ERR_LOG("Different encoding formats");
1464 return;
1465 }
1466 if (srcData.streamInfo.format == SAMPLE_S16LE && srcData.streamInfo.channels == STEREO) {
1467 return ProcessSingleData(srcData, dstData);
1468 }
1469 if (srcData.streamInfo.format == SAMPLE_S16LE && srcData.streamInfo.channels == MONO) {
1470 CHECK_AND_RETURN_LOG(processList_.size() > 0 && processList_[0] != nullptr, "No avaliable process");
1471 BufferDesc &convertedBuffer = processList_[0]->GetConvertedBuffer();
1472 int32_t ret = FormatConverter::S16MonoToS16Stereo(srcData.bufferDesc, convertedBuffer);
1473 CHECK_AND_RETURN_LOG(ret == SUCCESS, "Convert channel from mono to stereo failed");
1474 AudioStreamData dataAfterProcess = srcData;
1475 dataAfterProcess.bufferDesc = convertedBuffer;
1476 ProcessSingleData(dataAfterProcess, dstData);
1477 ret = memset_s(static_cast<void *>(convertedBuffer.buffer), convertedBuffer.bufLength, 0,
1478 convertedBuffer.bufLength);
1479 CHECK_AND_RETURN_LOG(ret == EOK, "memset converted buffer to 0 failed");
1480 }
1481 }
1482
ProcessSingleData(const AudioStreamData & srcData,const AudioStreamData & dstData)1483 void AudioEndpointInner::ProcessSingleData(const AudioStreamData &srcData, const AudioStreamData &dstData)
1484 {
1485 CHECK_AND_RETURN_LOG(dstData.streamInfo.format == SAMPLE_S16LE && dstData.streamInfo.channels == STEREO,
1486 "ProcessData failed, streamInfo are not support");
1487
1488 size_t dataLength = dstData.bufferDesc.dataLength;
1489 dataLength /= 2; // SAMPLE_S16LE--> 2 byte
1490 int16_t *dstPtr = reinterpret_cast<int16_t *>(dstData.bufferDesc.buffer);
1491 for (size_t offset = 0; dataLength > 0; dataLength--) {
1492 int32_t vol = srcData.volumeStart; // change to modify volume of each channel
1493 int16_t *srcPtr = reinterpret_cast<int16_t *>(srcData.bufferDesc.buffer) + offset;
1494 int32_t sum = (*srcPtr * static_cast<int64_t>(vol)) >> VOLUME_SHIFT_NUMBER; // 1/65536
1495 ZeroVolumeCheck(vol);
1496 offset++;
1497 *dstPtr++ = sum > INT16_MAX ? INT16_MAX : (sum < INT16_MIN ? INT16_MIN : sum);
1498 }
1499 HandleZeroVolumeCheckEvent();
1500 }
1501
ZeroVolumeCheck(const int32_t vol)1502 void AudioEndpointInner::ZeroVolumeCheck(const int32_t vol)
1503 {
1504 if (std::abs(vol - 0) <= std::numeric_limits<float>::epsilon()) {
1505 if (!zeroVolumeStopDevice_ && !isVolumeAlreadyZero_) {
1506 AUDIO_INFO_LOG("Begin zero volume, will stop device.");
1507 delayStopTimeForZeroVolume_ = ClockTime::GetCurNano() + DELAY_STOP_HDI_TIME_FOR_ZERO_VOLUME_NS;
1508 isVolumeAlreadyZero_ = true;
1509 }
1510 } else {
1511 if (zeroVolumeStopDevice_ && !isStarted_) {
1512 if (fastSink_ == nullptr || fastSink_->Start() != SUCCESS) {
1513 AUDIO_INFO_LOG("Volume from zero to none-zero, start device failed.");
1514 isStarted_ = false;
1515 } else {
1516 AUDIO_INFO_LOG("Volume from zero to none-zero, start device success.");
1517 isStarted_ = true;
1518 needReSyncPosition_ = true;
1519 }
1520 zeroVolumeStopDevice_ = false;
1521 }
1522 isVolumeAlreadyZero_ = false;
1523 delayStopTimeForZeroVolume_ = INT64_MAX;
1524 }
1525 }
1526
1527 // call with listLock_ hold
GetAllReadyProcessData(std::vector<AudioStreamData> & audioDataList)1528 void AudioEndpointInner::GetAllReadyProcessData(std::vector<AudioStreamData> &audioDataList)
1529 {
1530 for (size_t i = 0; i < processBufferList_.size(); i++) {
1531 uint64_t curRead = processBufferList_[i]->GetCurReadFrame();
1532 Trace trace("AudioEndpoint::ReadProcessData->" + std::to_string(curRead));
1533 SpanInfo *curReadSpan = processBufferList_[i]->GetSpanInfo(curRead);
1534 CHECK_AND_CONTINUE_LOG(curReadSpan != nullptr, "GetSpanInfo failed, can not get client curReadSpan");
1535 AudioStreamData streamData;
1536 Volume vol = {true, 1.0f, 0};
1537 AudioStreamType streamType = processList_[i]->GetAudioStreamType();
1538 AudioVolumeType volumeType = VolumeUtils::GetVolumeTypeFromStreamType(streamType);
1539 DeviceType deviceType = PolicyHandler::GetInstance().GetActiveOutPutDevice();
1540 bool muteFlag = processList_[i]->GetMuteState();
1541 if (deviceInfo_.networkId == LOCAL_NETWORK_ID &&
1542 !(deviceInfo_.deviceType == DEVICE_TYPE_BLUETOOTH_A2DP && volumeType == STREAM_MUSIC &&
1543 PolicyHandler::GetInstance().IsAbsVolumeSupported()) &&
1544 PolicyHandler::GetInstance().GetSharedVolume(volumeType, deviceType, vol)) {
1545 streamData.volumeStart = vol.isMute ? 0 : static_cast<int32_t>(curReadSpan->volumeStart * vol.volumeFloat);
1546 } else {
1547 streamData.volumeStart = curReadSpan->volumeStart;
1548 }
1549 streamData.volumeEnd = curReadSpan->volumeEnd;
1550 streamData.streamInfo = processList_[i]->GetStreamInfo();
1551 streamData.isInnerCaped = processList_[i]->GetInnerCapState();
1552 SpanStatus targetStatus = SpanStatus::SPAN_WRITE_DONE;
1553 if (curReadSpan->spanStatus.compare_exchange_strong(targetStatus, SpanStatus::SPAN_READING)) {
1554 processBufferList_[i]->GetReadbuffer(curRead, streamData.bufferDesc); // check return?
1555 if (muteFlag) {
1556 memset_s(static_cast<void *>(streamData.bufferDesc.buffer), streamData.bufferDesc.bufLength,
1557 0, streamData.bufferDesc.bufLength);
1558 }
1559 CheckPlaySignal(streamData.bufferDesc.buffer, streamData.bufferDesc.bufLength);
1560 audioDataList.push_back(streamData);
1561 curReadSpan->readStartTime = ClockTime::GetCurNano();
1562 processList_[i]->WriteDumpFile(static_cast<void *>(streamData.bufferDesc.buffer),
1563 streamData.bufferDesc.bufLength);
1564 }
1565 }
1566 }
1567
ProcessToEndpointDataHandle(uint64_t curWritePos)1568 bool AudioEndpointInner::ProcessToEndpointDataHandle(uint64_t curWritePos)
1569 {
1570 std::lock_guard<std::mutex> lock(listLock_);
1571
1572 std::vector<AudioStreamData> audioDataList;
1573 GetAllReadyProcessData(audioDataList);
1574
1575 AudioStreamData dstStreamData;
1576 dstStreamData.streamInfo = dstStreamInfo_;
1577 int32_t ret = dstAudioBuffer_->GetWriteBuffer(curWritePos, dstStreamData.bufferDesc);
1578 CHECK_AND_RETURN_RET_LOG(((ret == SUCCESS && dstStreamData.bufferDesc.buffer != nullptr)), false,
1579 "GetWriteBuffer failed, ret:%{public}d", ret);
1580
1581 SpanInfo *curWriteSpan = dstAudioBuffer_->GetSpanInfo(curWritePos);
1582 CHECK_AND_RETURN_RET_LOG(curWriteSpan != nullptr, false, "GetSpanInfo failed, can not get curWriteSpan");
1583
1584 dstStreamData.volumeStart = curWriteSpan->volumeStart;
1585 dstStreamData.volumeEnd = curWriteSpan->volumeEnd;
1586
1587 Trace trace("AudioEndpoint::WriteDstBuffer=>" + std::to_string(curWritePos));
1588 // do write work
1589 if (audioDataList.size() == 0) {
1590 memset_s(dstStreamData.bufferDesc.buffer, dstStreamData.bufferDesc.bufLength, 0,
1591 dstStreamData.bufferDesc.bufLength);
1592 } else {
1593 if (endpointType_ == TYPE_VOIP_MMAP && audioDataList.size() == 1) {
1594 HandleRendererDataParams(audioDataList[0], dstStreamData);
1595 } else {
1596 ProcessData(audioDataList, dstStreamData);
1597 }
1598 }
1599
1600 if (isInnerCapEnabled_) {
1601 MixToDupStream(audioDataList);
1602 }
1603
1604 DfxOperation(dstStreamData.bufferDesc, dstStreamInfo_.format, dstStreamInfo_.channels);
1605
1606 if (AudioDump::GetInstance().GetVersionType() == BETA_VERSION) {
1607 DumpFileUtil::WriteDumpFile(dumpHdi_, static_cast<void *>(dstStreamData.bufferDesc.buffer),
1608 dstStreamData.bufferDesc.bufLength);
1609 AudioCacheMgr::GetInstance().CacheData(dumpHdiName_,
1610 static_cast<void *>(dstStreamData.bufferDesc.buffer), dstStreamData.bufferDesc.bufLength);
1611 }
1612
1613 CheckUpdateState(reinterpret_cast<char *>(dstStreamData.bufferDesc.buffer),
1614 dstStreamData.bufferDesc.bufLength);
1615
1616 return true;
1617 }
1618
DfxOperation(BufferDesc & buffer,AudioSampleFormat format,AudioChannel channel) const1619 void AudioEndpointInner::DfxOperation(BufferDesc &buffer, AudioSampleFormat format, AudioChannel channel) const
1620 {
1621 ChannelVolumes vols = VolumeTools::CountVolumeLevel(buffer, format, channel);
1622 if (channel == MONO) {
1623 Trace::Count(logUtilsTag_, vols.volStart[0]);
1624 } else {
1625 Trace::Count(logUtilsTag_, (vols.volStart[0] + vols.volStart[1]) / HALF_FACTOR);
1626 }
1627 AudioLogUtils::ProcessVolumeData(logUtilsTag_, vols, volumeDataCount_);
1628 }
1629
CheckUpdateState(char * frame,uint64_t replyBytes)1630 void AudioEndpointInner::CheckUpdateState(char *frame, uint64_t replyBytes)
1631 {
1632 if (startUpdate_) {
1633 if (renderFrameNum_ == 0) {
1634 last10FrameStartTime_ = ClockTime::GetCurNano();
1635 }
1636 renderFrameNum_++;
1637 maxAmplitude_ = UpdateMaxAmplitude(static_cast<ConvertHdiFormat>(dstStreamInfo_.format),
1638 frame, replyBytes);
1639 if (renderFrameNum_ == GET_MAX_AMPLITUDE_FRAMES_THRESHOLD) {
1640 renderFrameNum_ = 0;
1641 if (last10FrameStartTime_ > lastGetMaxAmplitudeTime_) {
1642 startUpdate_ = false;
1643 maxAmplitude_ = 0;
1644 }
1645 }
1646 }
1647 }
1648
GetMaxAmplitude()1649 float AudioEndpointInner::GetMaxAmplitude()
1650 {
1651 lastGetMaxAmplitudeTime_ = ClockTime::GetCurNano();
1652 startUpdate_ = true;
1653 return maxAmplitude_;
1654 }
1655
GetPredictNextReadTime(uint64_t posInFrame)1656 int64_t AudioEndpointInner::GetPredictNextReadTime(uint64_t posInFrame)
1657 {
1658 Trace trace("AudioEndpoint::GetPredictNextRead");
1659 uint64_t handleSpanCnt = posInFrame / dstSpanSizeInframe_;
1660 uint32_t startPeriodCnt = 20; // sync each time when start
1661 uint32_t oneBigPeriodCnt = 40; // 200ms
1662 if (handleSpanCnt < startPeriodCnt || handleSpanCnt % oneBigPeriodCnt == 0) {
1663 updateThreadCV_.notify_all();
1664 }
1665 uint64_t readFrame = 0;
1666 int64_t readtime = 0;
1667 if (readTimeModel_.GetFrameStamp(readFrame, readtime)) {
1668 if (readFrame != posInFrame_) {
1669 readTimeModel_.UpdataFrameStamp(posInFrame_, timeInNano_);
1670 }
1671 }
1672
1673 int64_t nextHdiReadTime = readTimeModel_.GetTimeOfPos(posInFrame);
1674 return nextHdiReadTime;
1675 }
1676
GetPredictNextWriteTime(uint64_t posInFrame)1677 int64_t AudioEndpointInner::GetPredictNextWriteTime(uint64_t posInFrame)
1678 {
1679 uint64_t handleSpanCnt = posInFrame / dstSpanSizeInframe_;
1680 uint32_t startPeriodCnt = 20;
1681 uint32_t oneBigPeriodCnt = 40;
1682 if (handleSpanCnt < startPeriodCnt || handleSpanCnt % oneBigPeriodCnt == 0) {
1683 updateThreadCV_.notify_all();
1684 }
1685 uint64_t writeFrame = 0;
1686 int64_t writetime = 0;
1687 if (writeTimeModel_.GetFrameStamp(writeFrame, writetime)) {
1688 if (writeFrame != posInFrame_) {
1689 writeTimeModel_.UpdataFrameStamp(posInFrame_, timeInNano_);
1690 }
1691 }
1692 int64_t nextHdiWriteTime = writeTimeModel_.GetTimeOfPos(posInFrame);
1693 return nextHdiWriteTime;
1694 }
1695
RecordPrepareNextLoop(uint64_t curReadPos,int64_t & wakeUpTime)1696 bool AudioEndpointInner::RecordPrepareNextLoop(uint64_t curReadPos, int64_t &wakeUpTime)
1697 {
1698 uint64_t nextHandlePos = curReadPos + dstSpanSizeInframe_;
1699 int64_t nextHdiWriteTime = GetPredictNextWriteTime(nextHandlePos);
1700 int64_t tempDelay = endpointType_ == TYPE_VOIP_MMAP ? RECORD_VOIP_DELAY_TIME_NS : RECORD_DELAY_TIME_NS;
1701 int64_t predictWakeupTime = nextHdiWriteTime + tempDelay;
1702 if (predictWakeupTime <= ClockTime::GetCurNano()) {
1703 wakeUpTime = ClockTime::GetCurNano() + ONE_MILLISECOND_DURATION;
1704 AUDIO_ERR_LOG("hdi send wrong position time");
1705 } else {
1706 wakeUpTime = predictWakeupTime;
1707 }
1708
1709 int32_t ret = dstAudioBuffer_->SetCurWriteFrame(nextHandlePos);
1710 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, false, "set dst buffer write frame fail, ret %{public}d.", ret);
1711 ret = dstAudioBuffer_->SetCurReadFrame(nextHandlePos);
1712 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, false, "set dst buffer read frame fail, ret %{public}d.", ret);
1713
1714 return true;
1715 }
1716
PrepareNextLoop(uint64_t curWritePos,int64_t & wakeUpTime)1717 bool AudioEndpointInner::PrepareNextLoop(uint64_t curWritePos, int64_t &wakeUpTime)
1718 {
1719 uint64_t nextHandlePos = curWritePos + dstSpanSizeInframe_;
1720 Trace prepareTrace("AudioEndpoint::PrepareNextLoop " + std::to_string(nextHandlePos));
1721 int64_t nextHdiReadTime = GetPredictNextReadTime(nextHandlePos);
1722 int64_t predictWakeupTime = nextHdiReadTime - serverAheadReadTime_;
1723 if (predictWakeupTime <= ClockTime::GetCurNano()) {
1724 wakeUpTime = ClockTime::GetCurNano() + ONE_MILLISECOND_DURATION;
1725 AUDIO_ERR_LOG("hdi send wrong position time");
1726 } else {
1727 wakeUpTime = predictWakeupTime;
1728 }
1729
1730 SpanInfo *nextWriteSpan = dstAudioBuffer_->GetSpanInfo(nextHandlePos);
1731 CHECK_AND_RETURN_RET_LOG(nextWriteSpan != nullptr, false, "GetSpanInfo failed, can not get next write span");
1732
1733 int32_t ret1 = dstAudioBuffer_->SetCurWriteFrame(nextHandlePos);
1734 int32_t ret2 = dstAudioBuffer_->SetCurReadFrame(nextHandlePos);
1735 CHECK_AND_RETURN_RET_LOG(ret1 == SUCCESS && ret2 == SUCCESS, false,
1736 "SetCurWriteFrame or SetCurReadFrame failed, ret1:%{public}d ret2:%{public}d", ret1, ret2);
1737 // handl each process buffer info
1738 int64_t curReadDoneTime = ClockTime::GetCurNano();
1739 {
1740 std::lock_guard<std::mutex> lock(listLock_);
1741 for (size_t i = 0; i < processBufferList_.size(); i++) {
1742 uint64_t eachCurReadPos = processBufferList_[i]->GetCurReadFrame();
1743 SpanInfo *tempSpan = processBufferList_[i]->GetSpanInfo(eachCurReadPos);
1744 CHECK_AND_RETURN_RET_LOG(tempSpan != nullptr, false,
1745 "GetSpanInfo failed, can not get process read span");
1746 SpanStatus targetStatus = SpanStatus::SPAN_READING;
1747 CHECK_AND_RETURN_RET_LOG(processBufferList_[i]->GetStreamStatus() != nullptr, false,
1748 "stream status is null");
1749 if (tempSpan->spanStatus.compare_exchange_strong(targetStatus, SpanStatus::SPAN_READ_DONE)) {
1750 tempSpan->readDoneTime = curReadDoneTime;
1751 BufferDesc bufferReadDone = { nullptr, 0, 0};
1752 processBufferList_[i]->GetReadbuffer(eachCurReadPos, bufferReadDone);
1753 if (bufferReadDone.buffer != nullptr && bufferReadDone.bufLength != 0) {
1754 memset_s(bufferReadDone.buffer, bufferReadDone.bufLength, 0, bufferReadDone.bufLength);
1755 }
1756 processBufferList_[i]->SetCurReadFrame(eachCurReadPos + dstSpanSizeInframe_); // use client span size
1757 } else if (processBufferList_[i]->GetStreamStatus() &&
1758 processBufferList_[i]->GetStreamStatus()->load() == StreamStatus::STREAM_RUNNING) {
1759 AUDIO_DEBUG_LOG("Current %{public}" PRIu64" span not ready:%{public}d", eachCurReadPos, targetStatus);
1760 }
1761 }
1762 }
1763 return true;
1764 }
1765
GetDeviceHandleInfo(uint64_t & frames,int64_t & nanoTime)1766 bool AudioEndpointInner::GetDeviceHandleInfo(uint64_t &frames, int64_t &nanoTime)
1767 {
1768 Trace trace("AudioEndpoint::GetMmapHandlePosition");
1769 int64_t timeSec = 0;
1770 int64_t timeNanoSec = 0;
1771 int32_t ret = 0;
1772 if (deviceInfo_.deviceRole == INPUT_DEVICE) {
1773 CHECK_AND_RETURN_RET_LOG(fastSource_ != nullptr && fastSource_->IsInited(),
1774 false, "Source start failed.");
1775 // GetMmapHandlePosition will call using ipc.
1776 ret = fastSource_->GetMmapHandlePosition(frames, timeSec, timeNanoSec);
1777 } else {
1778 CHECK_AND_RETURN_RET_LOG(fastSink_ != nullptr && fastSink_->IsInited(),
1779 false, "GetDeviceHandleInfo failed: sink is not inited.");
1780 // GetMmapHandlePosition will call using ipc.
1781 ret = fastSink_->GetMmapHandlePosition(frames, timeSec, timeNanoSec);
1782 }
1783 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, false, "Call adapter GetMmapHandlePosition failed: %{public}d", ret);
1784 trace.End();
1785 nanoTime = timeNanoSec + timeSec * AUDIO_NS_PER_SECOND;
1786 Trace infoTrace("AudioEndpoint::GetDeviceHandleInfo frames=>" + std::to_string(frames) + " " +
1787 std::to_string(nanoTime) + " at " + std::to_string(ClockTime::GetCurNano()));
1788 nanoTime += DELTA_TO_REAL_READ_START_TIME; // global delay in server
1789 return true;
1790 }
1791
AsyncGetPosTime()1792 void AudioEndpointInner::AsyncGetPosTime()
1793 {
1794 AUDIO_INFO_LOG("AsyncGetPosTime thread start.");
1795 while (!stopUpdateThread_) {
1796 std::unique_lock<std::mutex> lock(updateThreadLock_);
1797 updateThreadCV_.wait_for(lock, std::chrono::milliseconds(UPDATE_THREAD_TIMEOUT));
1798 if (stopUpdateThread_) {
1799 break;
1800 }
1801 if (endpointStatus_ == IDEL && isStarted_ && ClockTime::GetCurNano() > delayStopTime_) {
1802 AUDIO_INFO_LOG("IDEL for too long, let's call hdi stop");
1803 DelayStopDevice();
1804 continue;
1805 }
1806 if (endpointStatus_ == IDEL && !isStarted_) {
1807 continue;
1808 }
1809 // get signaled, call get pos-time
1810 uint64_t curHdiHandlePos = posInFrame_;
1811 int64_t handleTime = timeInNano_;
1812 if (!GetDeviceHandleInfo(curHdiHandlePos, handleTime)) {
1813 AUDIO_WARNING_LOG("AsyncGetPosTime call GetDeviceHandleInfo failed.");
1814 continue;
1815 }
1816 // keep it
1817 if (posInFrame_ != curHdiHandlePos) {
1818 posInFrame_ = curHdiHandlePos;
1819 timeInNano_ = handleTime;
1820 }
1821 }
1822 }
1823
GetStatusStr(EndpointStatus status)1824 std::string AudioEndpointInner::GetStatusStr(EndpointStatus status)
1825 {
1826 switch (status) {
1827 case INVALID:
1828 return "INVALID";
1829 case UNLINKED:
1830 return "UNLINKED";
1831 case IDEL:
1832 return "IDEL";
1833 case STARTING:
1834 return "STARTING";
1835 case RUNNING:
1836 return "RUNNING";
1837 case STOPPING:
1838 return "STOPPING";
1839 case STOPPED:
1840 return "STOPPED";
1841 default:
1842 break;
1843 }
1844 return "NO_SUCH_STATUS";
1845 }
1846
KeepWorkloopRunning()1847 bool AudioEndpointInner::KeepWorkloopRunning()
1848 {
1849 EndpointStatus targetStatus = INVALID;
1850 switch (endpointStatus_.load()) {
1851 case RUNNING:
1852 return true;
1853 case IDEL:
1854 if (ClockTime::GetCurNano() > delayStopTime_) {
1855 targetStatus = RUNNING;
1856 break;
1857 }
1858 if (isDeviceRunningInIdel_) {
1859 return true;
1860 }
1861 break;
1862 case UNLINKED:
1863 targetStatus = IDEL;
1864 break;
1865 case STARTING:
1866 targetStatus = RUNNING;
1867 break;
1868 case STOPPING:
1869 targetStatus = STOPPED;
1870 break;
1871 default:
1872 break;
1873 }
1874
1875 // when return false, EndpointWorkLoopFuc will continue loop immediately. Wait to avoid a inifity loop.
1876 std::unique_lock<std::mutex> lock(loopThreadLock_);
1877 AUDIO_PRERELEASE_LOGI("Status is %{public}s now, wait for %{public}s...", GetStatusStr(endpointStatus_).c_str(),
1878 GetStatusStr(targetStatus).c_str());
1879 threadStatus_ = WAITTING;
1880 workThreadCV_.wait_for(lock, std::chrono::milliseconds(SLEEP_TIME_IN_DEFAULT));
1881 AUDIO_DEBUG_LOG("Wait end. Cur is %{public}s now, target is %{public}s...", GetStatusStr(endpointStatus_).c_str(),
1882 GetStatusStr(targetStatus).c_str());
1883
1884 return false;
1885 }
1886
WriteToSpecialProcBuf(const std::shared_ptr<OHAudioBuffer> & procBuf,const BufferDesc & readBuf,const BufferDesc & convertedBuffer,bool muteFlag)1887 int32_t AudioEndpointInner::WriteToSpecialProcBuf(const std::shared_ptr<OHAudioBuffer> &procBuf,
1888 const BufferDesc &readBuf, const BufferDesc &convertedBuffer, bool muteFlag)
1889 {
1890 CHECK_AND_RETURN_RET_LOG(procBuf != nullptr, ERR_INVALID_HANDLE, "process buffer is null.");
1891 uint64_t curWritePos = procBuf->GetCurWriteFrame();
1892 Trace trace("AudioEndpoint::WriteProcessData-<" + std::to_string(curWritePos));
1893
1894 int32_t writeAbleSize = procBuf->GetAvailableDataFrames();
1895 if (writeAbleSize <= 0 || static_cast<uint32_t>(writeAbleSize) <= dstSpanSizeInframe_) {
1896 AUDIO_WARNING_LOG("client read too slow: curWritePos:%{public}" PRIu64" writeAbleSize:%{public}d",
1897 curWritePos, writeAbleSize);
1898 return ERR_OPERATION_FAILED;
1899 }
1900
1901 SpanInfo *curWriteSpan = procBuf->GetSpanInfo(curWritePos);
1902 CHECK_AND_RETURN_RET_LOG(curWriteSpan != nullptr, ERR_INVALID_HANDLE,
1903 "get write span info of procBuf fail.");
1904
1905 AUDIO_DEBUG_LOG("process buffer write start, curWritePos %{public}" PRIu64".", curWritePos);
1906 curWriteSpan->spanStatus.store(SpanStatus::SPAN_WRITTING);
1907 curWriteSpan->writeStartTime = ClockTime::GetCurNano();
1908
1909 BufferDesc writeBuf;
1910 int32_t ret = procBuf->GetWriteBuffer(curWritePos, writeBuf);
1911 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ret, "get write buffer fail, ret %{public}d.", ret);
1912 if (muteFlag) {
1913 memset_s(static_cast<void *>(writeBuf.buffer), writeBuf.bufLength, 0, writeBuf.bufLength);
1914 } else {
1915 if (endpointType_ == TYPE_VOIP_MMAP) {
1916 ret = HandleCapturerDataParams(writeBuf, readBuf, convertedBuffer);
1917 } else {
1918 ret = memcpy_s(static_cast<void *>(writeBuf.buffer), writeBuf.bufLength,
1919 static_cast<void *>(readBuf.buffer), readBuf.bufLength);
1920 }
1921 }
1922
1923 CHECK_AND_RETURN_RET_LOG(ret == EOK, ERR_WRITE_FAILED, "memcpy data to process buffer fail, "
1924 "curWritePos %{public}" PRIu64", ret %{public}d.", curWritePos, ret);
1925
1926 curWriteSpan->writeDoneTime = ClockTime::GetCurNano();
1927 procBuf->SetHandleInfo(curWritePos, curWriteSpan->writeDoneTime);
1928 ret = procBuf->SetCurWriteFrame(curWritePos + dstSpanSizeInframe_);
1929 if (ret != SUCCESS) {
1930 AUDIO_WARNING_LOG("set procBuf next write frame fail, ret %{public}d.", ret);
1931 curWriteSpan->spanStatus.store(SpanStatus::SPAN_READ_DONE);
1932 return ERR_OPERATION_FAILED;
1933 }
1934 curWriteSpan->spanStatus.store(SpanStatus::SPAN_WRITE_DONE);
1935 return SUCCESS;
1936 }
1937
HandleCapturerDataParams(const BufferDesc & writeBuf,const BufferDesc & readBuf,const BufferDesc & convertedBuffer)1938 int32_t AudioEndpointInner::HandleCapturerDataParams(const BufferDesc &writeBuf, const BufferDesc &readBuf,
1939 const BufferDesc &convertedBuffer)
1940 {
1941 if (clientConfig_.streamInfo.format == SAMPLE_S16LE && clientConfig_.streamInfo.channels == STEREO) {
1942 return memcpy_s(static_cast<void *>(writeBuf.buffer), writeBuf.bufLength,
1943 static_cast<void *>(readBuf.buffer), readBuf.bufLength);
1944 }
1945 if (clientConfig_.streamInfo.format == SAMPLE_S16LE && clientConfig_.streamInfo.channels == MONO) {
1946 int32_t ret = FormatConverter::S16StereoToS16Mono(readBuf, convertedBuffer);
1947 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_WRITE_FAILED, "Convert channel from stereo to mono failed");
1948 ret = memcpy_s(static_cast<void *>(writeBuf.buffer), writeBuf.bufLength,
1949 static_cast<void *>(convertedBuffer.buffer), convertedBuffer.bufLength);
1950 CHECK_AND_RETURN_RET_LOG(ret == EOK, ERR_WRITE_FAILED, "memcpy_s failed");
1951 ret = memset_s(static_cast<void *>(convertedBuffer.buffer), convertedBuffer.bufLength, 0,
1952 convertedBuffer.bufLength);
1953 CHECK_AND_RETURN_RET_LOG(ret == EOK, ERR_WRITE_FAILED, "memset converted buffer to 0 failed");
1954 return EOK;
1955 }
1956 return ERR_NOT_SUPPORTED;
1957 }
1958
WriteToProcessBuffers(const BufferDesc & readBuf)1959 void AudioEndpointInner::WriteToProcessBuffers(const BufferDesc &readBuf)
1960 {
1961 CheckRecordSignal(readBuf.buffer, readBuf.bufLength);
1962 std::lock_guard<std::mutex> lock(listLock_);
1963 for (size_t i = 0; i < processBufferList_.size(); i++) {
1964 CHECK_AND_CONTINUE_LOG(processBufferList_[i] != nullptr,
1965 "process buffer %{public}zu is null.", i);
1966 if (processBufferList_[i]->GetStreamStatus() &&
1967 processBufferList_[i]->GetStreamStatus()->load() != STREAM_RUNNING) {
1968 AUDIO_WARNING_LOG("process buffer %{public}zu not running, stream status %{public}d.",
1969 i, processBufferList_[i]->GetStreamStatus()->load());
1970 continue;
1971 }
1972
1973 int32_t ret = WriteToSpecialProcBuf(processBufferList_[i], readBuf, processList_[i]->GetConvertedBuffer(),
1974 processList_[i]->GetMuteState());
1975 CHECK_AND_CONTINUE_LOG(ret == SUCCESS,
1976 "endpoint write to process buffer %{public}zu fail, ret %{public}d.", i, ret);
1977 AUDIO_DEBUG_LOG("endpoint process buffer %{public}zu write success.", i);
1978 }
1979 }
1980
ReadFromEndpoint(uint64_t curReadPos)1981 int32_t AudioEndpointInner::ReadFromEndpoint(uint64_t curReadPos)
1982 {
1983 Trace trace("AudioEndpoint::ReadDstBuffer=<" + std::to_string(curReadPos));
1984 AUDIO_DEBUG_LOG("ReadFromEndpoint enter, dstAudioBuffer curReadPos %{public}" PRIu64".", curReadPos);
1985 CHECK_AND_RETURN_RET_LOG(dstAudioBuffer_ != nullptr, ERR_INVALID_HANDLE,
1986 "dst audio buffer is null.");
1987 SpanInfo *curReadSpan = dstAudioBuffer_->GetSpanInfo(curReadPos);
1988 CHECK_AND_RETURN_RET_LOG(curReadSpan != nullptr, ERR_INVALID_HANDLE,
1989 "get source read span info of source adapter fail.");
1990 curReadSpan->readStartTime = ClockTime::GetCurNano();
1991 curReadSpan->spanStatus.store(SpanStatus::SPAN_READING);
1992 BufferDesc readBuf;
1993 int32_t ret = dstAudioBuffer_->GetReadbuffer(curReadPos, readBuf);
1994 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ret, "get read buffer fail, ret %{public}d.", ret);
1995 DfxOperation(readBuf, dstStreamInfo_.format, dstStreamInfo_.channels);
1996 if (AudioDump::GetInstance().GetVersionType() == BETA_VERSION) {
1997 DumpFileUtil::WriteDumpFile(dumpHdi_, static_cast<void *>(readBuf.buffer), readBuf.bufLength);
1998 AudioCacheMgr::GetInstance().CacheData(dumpHdiName_,
1999 static_cast<void *>(readBuf.buffer), readBuf.bufLength);
2000 }
2001 WriteToProcessBuffers(readBuf);
2002 ret = memset_s(readBuf.buffer, readBuf.bufLength, 0, readBuf.bufLength);
2003 if (ret != EOK) {
2004 AUDIO_WARNING_LOG("reset buffer fail, ret %{public}d.", ret);
2005 }
2006 curReadSpan->readDoneTime = ClockTime::GetCurNano();
2007 curReadSpan->spanStatus.store(SpanStatus::SPAN_READ_DONE);
2008 return SUCCESS;
2009 }
2010
RecordEndpointWorkLoopFuc()2011 void AudioEndpointInner::RecordEndpointWorkLoopFuc()
2012 {
2013 ScheduleReportData(getpid(), gettid(), "audio_server");
2014 int64_t curTime = 0;
2015 uint64_t curReadPos = 0;
2016 int64_t wakeUpTime = ClockTime::GetCurNano();
2017 AUDIO_INFO_LOG("Record endpoint work loop fuc start.");
2018 while (isInited_.load()) {
2019 if (!KeepWorkloopRunning()) {
2020 continue;
2021 }
2022 threadStatus_ = INRUNNING;
2023 if (needReSyncPosition_) {
2024 RecordReSyncPosition();
2025 wakeUpTime = ClockTime::GetCurNano();
2026 needReSyncPosition_ = false;
2027 continue;
2028 }
2029 curTime = ClockTime::GetCurNano();
2030 Trace loopTrace("Record_loop_trace");
2031 if (curTime - wakeUpTime > THREE_MILLISECOND_DURATION) {
2032 AUDIO_WARNING_LOG("Wake up cost %{public}" PRId64" ms!", (curTime - wakeUpTime) / AUDIO_US_PER_SECOND);
2033 } else if (curTime - wakeUpTime > ONE_MILLISECOND_DURATION) {
2034 AUDIO_DEBUG_LOG("Wake up cost %{public}" PRId64" ms!", (curTime - wakeUpTime) / AUDIO_US_PER_SECOND);
2035 }
2036
2037 curReadPos = dstAudioBuffer_->GetCurReadFrame();
2038 CHECK_AND_BREAK_LOG(ReadFromEndpoint(curReadPos) == SUCCESS, "read from endpoint to process service fail.");
2039
2040 bool ret = RecordPrepareNextLoop(curReadPos, wakeUpTime);
2041 CHECK_AND_BREAK_LOG(ret, "PrepareNextLoop failed!");
2042
2043 ProcessUpdateAppsUidForRecord();
2044
2045 loopTrace.End();
2046 threadStatus_ = SLEEPING;
2047 ClockTime::AbsoluteSleep(wakeUpTime);
2048 }
2049 }
2050
EndpointWorkLoopFuc()2051 void AudioEndpointInner::EndpointWorkLoopFuc()
2052 {
2053 ScheduleReportData(getpid(), gettid(), "audio_server");
2054 int64_t curTime = 0;
2055 uint64_t curWritePos = 0;
2056 int64_t wakeUpTime = ClockTime::GetCurNano();
2057 AUDIO_INFO_LOG("Endpoint work loop fuc start");
2058 int32_t ret = 0;
2059 while (isInited_.load()) {
2060 if (!KeepWorkloopRunning()) {
2061 continue;
2062 }
2063 ret = 0;
2064 threadStatus_ = INRUNNING;
2065 curTime = ClockTime::GetCurNano();
2066 Trace loopTrace("AudioEndpoint::loop_trace");
2067 if (needReSyncPosition_) {
2068 ReSyncPosition();
2069 wakeUpTime = curTime;
2070 needReSyncPosition_ = false;
2071 continue;
2072 }
2073 if (curTime - wakeUpTime > THREE_MILLISECOND_DURATION) {
2074 AUDIO_WARNING_LOG("Wake up cost %{public}" PRId64" ms!", (curTime - wakeUpTime) / AUDIO_US_PER_SECOND);
2075 } else if (curTime - wakeUpTime > ONE_MILLISECOND_DURATION) {
2076 AUDIO_DEBUG_LOG("Wake up cost %{public}" PRId64" ms!", (curTime - wakeUpTime) / AUDIO_US_PER_SECOND);
2077 }
2078
2079 // First, wake up at client may-write-done time, and check if all process write done.
2080 // If not, do another sleep to the possible latest write time.
2081 curWritePos = dstAudioBuffer_->GetCurWriteFrame();
2082 if (!CheckAllBufferReady(wakeUpTime, curWritePos)) {
2083 curTime = ClockTime::GetCurNano();
2084 }
2085
2086 // then do mix & write to hdi buffer and prepare next loop
2087 if (!ProcessToEndpointDataHandle(curWritePos)) {
2088 AUDIO_ERR_LOG("ProcessToEndpointDataHandle failed!");
2089 break;
2090 }
2091
2092 // prepare info of next loop
2093 if (!PrepareNextLoop(curWritePos, wakeUpTime)) {
2094 AUDIO_ERR_LOG("PrepareNextLoop failed!");
2095 break;
2096 }
2097
2098 ProcessUpdateAppsUidForPlayback();
2099
2100 loopTrace.End();
2101 // start sleep
2102 threadStatus_ = SLEEPING;
2103 ClockTime::AbsoluteSleep(wakeUpTime);
2104 }
2105 AUDIO_DEBUG_LOG("Endpoint work loop fuc end, ret %{public}d", ret);
2106 }
2107
InitLatencyMeasurement()2108 void AudioEndpointInner::InitLatencyMeasurement()
2109 {
2110 if (!AudioLatencyMeasurement::CheckIfEnabled()) {
2111 return;
2112 }
2113 signalDetectAgent_ = std::make_shared<SignalDetectAgent>();
2114 CHECK_AND_RETURN_LOG(signalDetectAgent_ != nullptr, "LatencyMeas signalDetectAgent_ is nullptr");
2115 signalDetectAgent_->sampleFormat_ = SAMPLE_S16LE;
2116 signalDetectAgent_->formatByteSize_ = GetFormatByteSize(SAMPLE_S16LE);
2117 latencyMeasEnabled_ = true;
2118 signalDetected_ = false;
2119 }
2120
DeinitLatencyMeasurement()2121 void AudioEndpointInner::DeinitLatencyMeasurement()
2122 {
2123 signalDetectAgent_ = nullptr;
2124 latencyMeasEnabled_ = false;
2125 }
2126
CheckPlaySignal(uint8_t * buffer,size_t bufferSize)2127 void AudioEndpointInner::CheckPlaySignal(uint8_t *buffer, size_t bufferSize)
2128 {
2129 if (!latencyMeasEnabled_) {
2130 return;
2131 }
2132 CHECK_AND_RETURN_LOG(signalDetectAgent_ != nullptr, "LatencyMeas signalDetectAgent_ is nullptr");
2133 size_t byteSize = static_cast<size_t>(GetFormatByteSize(dstStreamInfo_.format));
2134 size_t newlyCheckedTime = bufferSize / (dstStreamInfo_.samplingRate /
2135 MILLISECOND_PER_SECOND) / (byteSize * sizeof(uint8_t) * dstStreamInfo_.channels);
2136 detectedTime_ += newlyCheckedTime;
2137 if (detectedTime_ >= MILLISECOND_PER_SECOND && signalDetectAgent_->signalDetected_ &&
2138 !signalDetectAgent_->dspTimestampGot_) {
2139 AudioParamKey key = NONE;
2140 std::string condition = "debug_audio_latency_measurement";
2141 std::string dspTime = fastSink_->GetAudioParameter(key, condition);
2142 LatencyMonitor::GetInstance().UpdateDspTime(dspTime);
2143 LatencyMonitor::GetInstance().UpdateSinkOrSourceTime(true,
2144 signalDetectAgent_->lastPeakBufferTime_);
2145 AUDIO_INFO_LOG("LatencyMeas fastSink signal detected");
2146 LatencyMonitor::GetInstance().ShowTimestamp(true);
2147 signalDetectAgent_->dspTimestampGot_ = true;
2148 signalDetectAgent_->signalDetected_ = false;
2149 }
2150 signalDetected_ = signalDetectAgent_->CheckAudioData(buffer, bufferSize);
2151 if (signalDetected_) {
2152 AUDIO_INFO_LOG("LatencyMeas fastSink signal detected");
2153 detectedTime_ = 0;
2154 }
2155 }
2156
CheckRecordSignal(uint8_t * buffer,size_t bufferSize)2157 void AudioEndpointInner::CheckRecordSignal(uint8_t *buffer, size_t bufferSize)
2158 {
2159 if (!latencyMeasEnabled_) {
2160 return;
2161 }
2162 CHECK_AND_RETURN_LOG(signalDetectAgent_ != nullptr, "LatencyMeas signalDetectAgent_ is nullptr");
2163 signalDetected_ = signalDetectAgent_->CheckAudioData(buffer, bufferSize);
2164 if (signalDetected_) {
2165 AudioParamKey key = NONE;
2166 std::string condition = "debug_audio_latency_measurement";
2167 std::string dspTime = fastSource_->GetAudioParameter(key, condition);
2168 LatencyMonitor::GetInstance().UpdateSinkOrSourceTime(false,
2169 signalDetectAgent_->lastPeakBufferTime_);
2170 LatencyMonitor::GetInstance().UpdateDspTime(dspTime);
2171 AUDIO_INFO_LOG("LatencyMeas fastSource signal detected");
2172 signalDetected_ = false;
2173 }
2174 }
2175
ProcessUpdateAppsUidForPlayback()2176 void AudioEndpointInner::ProcessUpdateAppsUidForPlayback()
2177 {
2178 std::vector<int32_t> appsUid;
2179 {
2180 std::lock_guard<std::mutex> lock(listLock_);
2181
2182 appsUid.reserve(processList_.size());
2183 for (auto iProccessStream : processList_) {
2184 appsUid.push_back(iProccessStream->GetAppInfo().appUid);
2185 }
2186 }
2187 CHECK_AND_RETURN_LOG(fastSink_, "fastSink_ is nullptr");
2188 fastSink_->UpdateAppsUid(appsUid);
2189 }
2190
ProcessUpdateAppsUidForRecord()2191 void AudioEndpointInner::ProcessUpdateAppsUidForRecord()
2192 {
2193 std::vector<int32_t> appsUid;
2194 {
2195 std::lock_guard<std::mutex> lock(listLock_);
2196
2197 appsUid.reserve(processList_.size());
2198 for (auto iProccessStream : processList_) {
2199 appsUid.push_back(iProccessStream->GetAppInfo().appUid);
2200 }
2201 }
2202 CHECK_AND_RETURN_LOG(fastSource_, "fastSource_ is nullptr");
2203 fastSource_->UpdateAppsUid(appsUid);
2204 }
2205
WriterRenderStreamStandbySysEvent(uint32_t sessionId,int32_t standby)2206 void AudioEndpointInner::WriterRenderStreamStandbySysEvent(uint32_t sessionId, int32_t standby)
2207 {
2208 std::shared_ptr<Media::MediaMonitor::EventBean> bean = std::make_shared<Media::MediaMonitor::EventBean>(
2209 Media::MediaMonitor::AUDIO, Media::MediaMonitor::STREAM_STANDBY,
2210 Media::MediaMonitor::BEHAVIOR_EVENT);
2211 bean->Add("STREAMID", static_cast<int32_t>(sessionId));
2212 bean->Add("STANDBY", standby);
2213 Media::MediaMonitor::MediaMonitorManager::GetInstance().WriteLogMsg(bean);
2214 }
2215
GetLinkedProcessCount()2216 uint32_t AudioEndpointInner::GetLinkedProcessCount()
2217 {
2218 std::lock_guard<std::mutex> lock(listLock_);
2219 return processList_.size();
2220 }
2221 } // namespace AudioStandard
2222 } // namespace OHOS
2223