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