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