1 /*
2 * Copyright (c) 2023-2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #ifndef LOG_TAG
16 #define LOG_TAG "AudioEndpointInner"
17 #endif
18
19 #include "audio_endpoint.h"
20 #include "audio_endpoint_private.h"
21
22 #include <string>
23 #include <memory>
24
25 #include "audio_service_log.h"
26 #include "manager/hdi_adapter_manager.h"
27
28 namespace OHOS {
29 namespace AudioStandard {
30 namespace {
31 static constexpr int64_t PLAYBACK_DELAY_STOP_HDI_TIME_NS = 3000000000; // 3s = 3 * 1000 * 1000 * 1000ns
32 static constexpr int64_t RECORDER_DELAY_STOP_HDI_TIME_NS = 200000000; // 200ms = 200 * 1000 * 1000ns
33 static constexpr int64_t DELAY_STOP_HDI_TIME_FOR_ZERO_VOLUME_NS = 4000000000; // 4s = 4 * 1000 * 1000 * 1000ns
34 }
InitLatencyMeasurement()35 void AudioEndpointInner::InitLatencyMeasurement()
36 {
37 if (!AudioLatencyMeasurement::CheckIfEnabled()) {
38 return;
39 }
40 signalDetectAgent_ = std::make_shared<SignalDetectAgent>();
41 CHECK_AND_RETURN_LOG(signalDetectAgent_ != nullptr, "LatencyMeas signalDetectAgent_ is nullptr");
42 signalDetectAgent_->sampleFormat_ = SAMPLE_S16LE;
43 signalDetectAgent_->formatByteSize_ = GetFormatByteSize(SAMPLE_S16LE);
44 latencyMeasEnabled_ = true;
45 signalDetected_ = false;
46 }
47
DeinitLatencyMeasurement()48 void AudioEndpointInner::DeinitLatencyMeasurement()
49 {
50 signalDetectAgent_ = nullptr;
51 latencyMeasEnabled_ = false;
52 }
53
CheckPlaySignal(uint8_t * buffer,size_t bufferSize)54 void AudioEndpointInner::CheckPlaySignal(uint8_t *buffer, size_t bufferSize)
55 {
56 if (!latencyMeasEnabled_) {
57 return;
58 }
59 CHECK_AND_RETURN_LOG(signalDetectAgent_ != nullptr, "LatencyMeas signalDetectAgent_ is nullptr");
60 size_t byteSize = static_cast<size_t>(GetFormatByteSize(dstStreamInfo_.format));
61 size_t newlyCheckedTime = bufferSize / (dstStreamInfo_.samplingRate /
62 MILLISECOND_PER_SECOND) / (byteSize * sizeof(uint8_t) * dstStreamInfo_.channels);
63 detectedTime_ += newlyCheckedTime;
64 if (detectedTime_ >= MILLISECOND_PER_SECOND && signalDetectAgent_->signalDetected_ &&
65 !signalDetectAgent_->dspTimestampGot_) {
66 AudioParamKey key = NONE;
67 std::string condition = "debug_audio_latency_measurement";
68 std::shared_ptr<IAudioRenderSink> sink = HdiAdapterManager::GetInstance().GetRenderSink(fastRenderId_);
69 CHECK_AND_RETURN_LOG(sink != nullptr, "sink is nullptr!");
70 std::string dspTime = sink->GetAudioParameter(key, condition);
71 LatencyMonitor::GetInstance().UpdateDspTime(dspTime);
72 LatencyMonitor::GetInstance().UpdateSinkOrSourceTime(true,
73 signalDetectAgent_->lastPeakBufferTime_);
74 AUDIO_INFO_LOG("LatencyMeas fastSink signal detected");
75 LatencyMonitor::GetInstance().ShowTimestamp(true);
76 signalDetectAgent_->dspTimestampGot_ = true;
77 signalDetectAgent_->signalDetected_ = false;
78 }
79 signalDetected_ = signalDetectAgent_->CheckAudioData(buffer, bufferSize);
80 if (signalDetected_) {
81 AUDIO_INFO_LOG("LatencyMeas fastSink signal detected");
82 detectedTime_ = 0;
83 }
84 }
85
CheckRecordSignal(uint8_t * buffer,size_t bufferSize)86 void AudioEndpointInner::CheckRecordSignal(uint8_t *buffer, size_t bufferSize)
87 {
88 if (!latencyMeasEnabled_) {
89 return;
90 }
91 CHECK_AND_RETURN_LOG(signalDetectAgent_ != nullptr, "LatencyMeas signalDetectAgent_ is nullptr");
92 signalDetected_ = signalDetectAgent_->CheckAudioData(buffer, bufferSize);
93 if (signalDetected_) {
94 AudioParamKey key = NONE;
95 std::string condition = "debug_audio_latency_measurement";
96 std::shared_ptr<IAudioCaptureSource> source = HdiAdapterManager::GetInstance().GetCaptureSource(fastCaptureId_);
97 CHECK_AND_RETURN_LOG(source != nullptr, "source is nullptr!");
98 std::string dspTime = source->GetAudioParameter(key, condition);
99 LatencyMonitor::GetInstance().UpdateSinkOrSourceTime(false,
100 signalDetectAgent_->lastPeakBufferTime_);
101 LatencyMonitor::GetInstance().UpdateDspTime(dspTime);
102 AUDIO_INFO_LOG("LatencyMeas fastSource signal detected");
103 signalDetected_ = false;
104 }
105 }
106
ZeroVolumeCheck(const int32_t vol)107 void AudioEndpointInner::ZeroVolumeCheck(const int32_t vol)
108 {
109 if (fastSinkType_ == FAST_SINK_TYPE_BLUETOOTH) {
110 return;
111 }
112 if (std::abs(vol - 0) <= std::numeric_limits<float>::epsilon()) {
113 if (zeroVolumeState_ == INACTIVE) {
114 zeroVolumeStartTime_ = ClockTime::GetCurNano();
115 zeroVolumeState_ = IN_TIMING;
116 AUDIO_INFO_LOG("Begin zero volume, will stop fastSink in 4s.");
117 return;
118 }
119
120 if (zeroVolumeState_ == IN_TIMING &&
121 ClockTime::GetCurNano() - zeroVolumeStartTime_ > DELAY_STOP_HDI_TIME_FOR_ZERO_VOLUME_NS) {
122 zeroVolumeState_ = ACTIVE;
123 HandleZeroVolumeStopEvent();
124 }
125 } else {
126 if (zeroVolumeState_ == INACTIVE) {
127 return;
128 }
129 if (zeroVolumeState_ == ACTIVE) {
130 HandleZeroVolumeStartEvent();
131 }
132 ResetZeroVolumeState();
133 }
134 }
135
HandleZeroVolumeStartEvent()136 void AudioEndpointInner::HandleZeroVolumeStartEvent()
137 {
138 if (!isStarted_) {
139 std::shared_ptr<IAudioRenderSink> sink = HdiAdapterManager::GetInstance().GetRenderSink(fastRenderId_);
140 if (sink == nullptr || sink->Start() != SUCCESS) {
141 AUDIO_INFO_LOG("Volume from zero to none-zero, start fastSink failed.");
142 isStarted_ = false;
143 } else {
144 AUDIO_INFO_LOG("Volume from zero to none-zero, start fastSink success.");
145 isStarted_ = true;
146 needReSyncPosition_ = true;
147 }
148 } else {
149 AUDIO_INFO_LOG("fastSink already started");
150 }
151 }
152
HandleZeroVolumeStopEvent()153 void AudioEndpointInner::HandleZeroVolumeStopEvent()
154 {
155 if (isStarted_) {
156 std::shared_ptr<IAudioRenderSink> sink = HdiAdapterManager::GetInstance().GetRenderSink(fastRenderId_);
157 if (sink != nullptr && sink->Stop() == SUCCESS) {
158 AUDIO_INFO_LOG("Volume from none-zero to zero more than 4s, stop fastSink success.");
159 isStarted_ = false;
160 } else {
161 AUDIO_INFO_LOG("Volume from none-zero to zero more than 4s, stop fastSink failed.");
162 isStarted_ = true;
163 }
164 } else {
165 AUDIO_INFO_LOG("fastSink already stopped");
166 }
167 }
168
ResetZeroVolumeState()169 void AudioEndpointInner::ResetZeroVolumeState()
170 {
171 zeroVolumeStartTime_ = INT64_MAX;
172 zeroVolumeState_ = INACTIVE;
173 }
174
CheckStandBy()175 void AudioEndpointInner::CheckStandBy()
176 {
177 if (endpointStatus_ == RUNNING) {
178 endpointStatus_ = IsAnyProcessRunning() ? RUNNING : IDEL;
179 }
180
181 if (endpointStatus_ == RUNNING) {
182 return;
183 }
184
185 AUDIO_INFO_LOG("endpoint status:%{public}s", GetStatusStr(endpointStatus_).c_str());
186 if (endpointStatus_ == IDEL) {
187 // delay call sink stop when no process running
188 AUDIO_INFO_LOG("status is IDEL, need delay call stop");
189 delayStopTime_ = ClockTime::GetCurNano() + ((clientConfig_.audioMode == AUDIO_MODE_PLAYBACK)
190 ? PLAYBACK_DELAY_STOP_HDI_TIME_NS : RECORDER_DELAY_STOP_HDI_TIME_NS);
191 }
192 }
193
Dump(std::string & dumpString)194 void AudioEndpointInner::Dump(std::string &dumpString)
195 {
196 // dump endpoint stream info
197 dumpString += "Endpoint stream info:\n";
198 AppendFormat(dumpString, " - samplingRate: %d\n", dstStreamInfo_.samplingRate);
199 AppendFormat(dumpString, " - channels: %u\n", dstStreamInfo_.channels);
200 AppendFormat(dumpString, " - format: %u\n", dstStreamInfo_.format);
201 AppendFormat(dumpString, " - sink type: %d\n", fastSinkType_);
202 AppendFormat(dumpString, " - source type: %d\n", fastSourceType_);
203
204 // dump status info
205 AppendFormat(dumpString, " - Current endpoint status: %s\n", GetStatusStr(endpointStatus_).c_str());
206 if (dstAudioBuffer_ != nullptr) {
207 AppendFormat(dumpString, " - Currend hdi read position: %u\n", dstAudioBuffer_->GetCurReadFrame());
208 AppendFormat(dumpString, " - Currend hdi write position: %u\n", dstAudioBuffer_->GetCurWriteFrame());
209 }
210
211 // dump linked process info
212 std::lock_guard<std::mutex> lock(listLock_);
213 AppendFormat(dumpString, " - linked process:: %zu\n", processBufferList_.size());
214 for (auto item : processBufferList_) {
215 AppendFormat(dumpString, " - process read position: %u\n", item->GetCurReadFrame());
216 AppendFormat(dumpString, " - process write position: %u\n", item->GetCurWriteFrame());
217 }
218 dumpString += "\n";
219 }
220
221 } // namespace AudioStandard
222 } // namespace OHOS
223