• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "CapturerInServer"
17 #endif
18 
19 #include "capturer_in_server.h"
20 #include <cinttypes>
21 #include "securec.h"
22 #include "audio_errors.h"
23 #include "audio_utils.h"
24 #include "audio_capturer_log.h"
25 #include "audio_service.h"
26 #include "audio_process_config.h"
27 #include "i_stream_manager.h"
28 #ifdef HAS_FEATURE_INNERCAPTURER
29 #include "playback_capturer_manager.h"
30 #endif
31 #include "policy_handler.h"
32 #include "media_monitor_manager.h"
33 #include "audio_dump_pcm.h"
34 #include "volume_tools.h"
35 #include "core_service_handler.h"
36 #include "stream_dfx_manager.h"
37 
38 namespace OHOS {
39 namespace AudioStandard {
40 namespace {
41     static constexpr int32_t VOLUME_SHIFT_NUMBER = 16; // 1 >> 16 = 65536, max volume
42     static const size_t CAPTURER_BUFFER_DEFAULT_NUM = 4;
43     static const size_t CAPTURER_BUFFER_WAKE_UP_NUM = 100;
44     static const uint32_t OVERFLOW_LOG_LOOP_COUNT = 100;
45     constexpr int32_t RELEASE_TIMEOUT_IN_SEC = 10; // 10S
46 }
47 
48 enum AudioByteSize : int32_t {
49     BYTE_SIZE_SAMPLE_U8 = 1,
50     BYTE_SIZE_SAMPLE_S16 = 2,
51     BYTE_SIZE_SAMPLE_S24 = 3,
52     BYTE_SIZE_SAMPLE_S32 = 4,
53 };
54 
CapturerInServer(AudioProcessConfig processConfig,std::weak_ptr<IStreamListener> streamListener)55 CapturerInServer::CapturerInServer(AudioProcessConfig processConfig, std::weak_ptr<IStreamListener> streamListener)
56 {
57     processConfig_ = processConfig;
58     streamListener_ = streamListener;
59     innerCapId_ = processConfig.innerCapId;
60 }
61 
~CapturerInServer()62 CapturerInServer::~CapturerInServer()
63 {
64     if (status_ != I_STATUS_RELEASED) {
65         Release();
66     }
67     DumpFileUtil::CloseDumpFile(&dumpS2C_);
68     if (needCheckBackground_) {
69         TurnOffMicIndicator(CAPTURER_INVALID);
70     }
71 }
72 
ConfigServerBuffer()73 int32_t CapturerInServer::ConfigServerBuffer()
74 {
75     if (audioServerBuffer_ != nullptr) {
76         AUDIO_INFO_LOG("ConfigProcessBuffer: process buffer already configed.");
77         return SUCCESS;
78     }
79     CHECK_AND_RETURN_RET_LOG(stream_ != nullptr, ERR_OPERATION_FAILED, "ConfigServerBuffer failed, stream_ is null!");
80     stream_->GetSpanSizePerFrame(spanSizeInFrame_);
81     const size_t bufferNum = ((processConfig_.capturerInfo.sourceType == SOURCE_TYPE_WAKEUP)
82         ? CAPTURER_BUFFER_WAKE_UP_NUM : CAPTURER_BUFFER_DEFAULT_NUM);
83     totalSizeInFrame_ = spanSizeInFrame_ * bufferNum;
84     stream_->GetByteSizePerFrame(byteSizePerFrame_);
85     spanSizeInBytes_ = byteSizePerFrame_ * spanSizeInFrame_;
86     AUDIO_INFO_LOG("ConfigProcessBuffer: totalSizeInFrame_: %{public}zu, spanSizeInFrame_: %{public}zu,"
87         "byteSizePerFrame_: %{public}zu, spanSizeInBytes_ %{public}zu", totalSizeInFrame_, spanSizeInFrame_,
88         byteSizePerFrame_, spanSizeInBytes_);
89     if (totalSizeInFrame_ == 0 || spanSizeInFrame_ == 0 || totalSizeInFrame_ % spanSizeInFrame_ != 0) {
90         AUDIO_ERR_LOG("ConfigProcessBuffer: ERR_INVALID_PARAM");
91         return ERR_INVALID_PARAM;
92     }
93 
94     int32_t ret = InitCacheBuffer(2 * spanSizeInBytes_);
95     CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ret, "InitCacheBuffer failed %{public}d", ret);
96 
97     // create OHAudioBuffer in server
98     audioServerBuffer_ = OHAudioBuffer::CreateFromLocal(totalSizeInFrame_, spanSizeInFrame_, byteSizePerFrame_);
99     CHECK_AND_RETURN_RET_LOG(audioServerBuffer_ != nullptr, ERR_OPERATION_FAILED, "Create oh audio buffer failed");
100 
101     // we need to clear data buffer to avoid dirty data.
102     memset_s(audioServerBuffer_->GetDataBase(), audioServerBuffer_->GetDataSize(), 0,
103         audioServerBuffer_->GetDataSize());
104     ret = InitBufferStatus();
105     AUDIO_DEBUG_LOG("Clear data buffer, ret:%{public}d", ret);
106     isBufferConfiged_ = true;
107     isInited_ = true;
108     return SUCCESS;
109 }
110 
InitBufferStatus()111 int32_t CapturerInServer::InitBufferStatus()
112 {
113     if (audioServerBuffer_ == nullptr) {
114         AUDIO_ERR_LOG("InitBufferStatus failed, null buffer!");
115         return ERR_ILLEGAL_STATE;
116     }
117 
118     uint32_t spanCount = audioServerBuffer_->GetSpanCount();
119     AUDIO_INFO_LOG("InitBufferStatus: spanCount %{public}u", spanCount);
120     for (uint32_t i = 0; i < spanCount; i++) {
121         SpanInfo *spanInfo = audioServerBuffer_->GetSpanInfoByIndex(i);
122         if (spanInfo == nullptr) {
123             AUDIO_ERR_LOG("InitBufferStatus failed, null spaninfo");
124             return ERR_ILLEGAL_STATE;
125         }
126         spanInfo->spanStatus = SPAN_READ_DONE;
127         spanInfo->offsetInFrame = 0;
128 
129         spanInfo->readStartTime = 0;
130         spanInfo->readDoneTime = 0;
131 
132         spanInfo->readStartTime = 0;
133         spanInfo->readDoneTime = 0;
134 
135         spanInfo->volumeStart = 1 << VOLUME_SHIFT_NUMBER; // 65536 for initialize
136         spanInfo->volumeEnd = 1 << VOLUME_SHIFT_NUMBER; // 65536 for initialize
137         spanInfo->isMute = false;
138     }
139     return SUCCESS;
140 }
141 
Init()142 int32_t CapturerInServer::Init()
143 {
144     int32_t ret = IStreamManager::GetRecorderManager().CreateCapturer(processConfig_, stream_);
145     CHECK_AND_RETURN_RET_LOG(ret == SUCCESS && stream_ != nullptr, ERR_OPERATION_FAILED,
146         "Construct CapturerInServer failed: %{public}d", ret);
147     streamIndex_ = stream_->GetStreamIndex();
148     capturerClock_ = CapturerClockManager::GetInstance().CreateCapturerClock(
149         streamIndex_, processConfig_.streamInfo.samplingRate);
150     ret = ConfigServerBuffer();
151     CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_OPERATION_FAILED, "ConfigServerBuffer failed: %{public}d", ret);
152     stream_->RegisterStatusCallback(shared_from_this());
153     stream_->RegisterReadCallback(shared_from_this());
154 
155     traceTag_ = "[" + std::to_string(streamIndex_) + "]CapturerServerOut"; // [100001]CapturerServerOut
156     // eg: /data/data/.pulse_dir/10000_100009_capturer_server_out_48000_2_1.pcm
157     AudioStreamInfo tempInfo = processConfig_.streamInfo;
158     dumpFileName_ = std::to_string(processConfig_.appInfo.appPid) + "_" + std::to_string(streamIndex_)
159         + "_capturer_server_out_" + std::to_string(tempInfo.samplingRate) + "_"
160         + std::to_string(tempInfo.channels) + "_" + std::to_string(tempInfo.format) + ".pcm";
161     DumpFileUtil::OpenDumpFile(DumpFileUtil::DUMP_SERVER_PARA, dumpFileName_, &dumpS2C_);
162     recorderDfx_ = std::make_unique<RecorderDfxWriter>(processConfig_.appInfo, streamIndex_);
163     AudioService::GetInstance()->RegisterMuteStateChangeCallback(streamIndex_, [this](bool flag) {
164         AUDIO_INFO_LOG("recv mute state change flag %{public}d", flag ? 1 : 0);
165         muteFlag_ = flag;
166     });
167 
168     return SUCCESS;
169 }
170 
OnStatusUpdate(IOperation operation)171 void CapturerInServer::OnStatusUpdate(IOperation operation)
172 {
173     AUDIO_INFO_LOG("CapturerInServer::OnStatusUpdate operation: %{public}d", operation);
174     operation_ = operation;
175     if (status_ == I_STATUS_RELEASED) {
176         AUDIO_WARNING_LOG("Stream already released");
177         return;
178     }
179     std::shared_ptr<IStreamListener> stateListener = streamListener_.lock();
180     CHECK_AND_RETURN_LOG((stateListener != nullptr && recorderDfx_ != nullptr), "IStreamListener is nullptr");
181     switch (operation) {
182         case OPERATION_UNDERFLOW:
183             underflowCount += 1;
184             AUDIO_INFO_LOG("Underflow!! underflow count %{public}d", underflowCount);
185             stateListener->OnOperationHandled(BUFFER_OVERFLOW, underflowCount);
186             break;
187         case OPERATION_STARTED:
188             status_ = I_STATUS_STARTED;
189             lastStartTime_ = std::chrono::duration_cast<std::chrono::milliseconds>(
190                 std::chrono::system_clock::now().time_since_epoch()).count();
191             stateListener->OnOperationHandled(START_STREAM, 0);
192             break;
193         case OPERATION_PAUSED:
194             status_ = I_STATUS_PAUSED;
195             stateListener->OnOperationHandled(PAUSE_STREAM, 0);
196             HandleOperationStopped(CAPTURER_STAGE_PAUSE_OK);
197             break;
198         case OPERATION_STOPPED:
199             status_ = I_STATUS_STOPPED;
200             stateListener->OnOperationHandled(STOP_STREAM, 0);
201             HandleOperationStopped(CAPTURER_STAGE_STOP_OK);
202             break;
203         case OPERATION_FLUSHED:
204             HandleOperationFlushed();
205             stateListener->OnOperationHandled(FLUSH_STREAM, 0);
206             break;
207         default:
208             AUDIO_INFO_LOG("Invalid operation %{public}u", operation);
209             status_ = I_STATUS_INVALID;
210     }
211 
212     CaptureConcurrentCheck(streamIndex_);
213 }
214 
HandleOperationFlushed()215 void CapturerInServer::HandleOperationFlushed()
216 {
217     if (status_ == I_STATUS_FLUSHING_WHEN_STARTED) {
218         status_ = I_STATUS_STARTED;
219     } else if (status_ == I_STATUS_FLUSHING_WHEN_PAUSED) {
220         status_ = I_STATUS_PAUSED;
221     } else if (status_ == I_STATUS_FLUSHING_WHEN_STOPPED) {
222         status_ = I_STATUS_STOPPED;
223     } else {
224         AUDIO_WARNING_LOG("Invalid status before flusing");
225     }
226 }
227 
HandleOperationStopped(CapturerStage stage)228 void CapturerInServer::HandleOperationStopped(CapturerStage stage)
229 {
230     CHECK_AND_RETURN_LOG(recorderDfx_ != nullptr, "nullptr");
231     lastStopTime_ = std::chrono::duration_cast<std::chrono::milliseconds>(
232         std::chrono::system_clock::now().time_since_epoch()).count();
233     recorderDfx_->WriteDfxStopMsg(streamIndex_, stage,
234         GetLastAudioDuration(), processConfig_);
235 }
236 
DequeueBuffer(size_t length)237 BufferDesc CapturerInServer::DequeueBuffer(size_t length)
238 {
239     return stream_->DequeueBuffer(length);
240 }
241 
IsReadDataOverFlow(size_t length,uint64_t currentWriteFrame,std::shared_ptr<IStreamListener> stateListener)242 bool CapturerInServer::IsReadDataOverFlow(size_t length, uint64_t currentWriteFrame,
243     std::shared_ptr<IStreamListener> stateListener)
244 {
245     if (audioServerBuffer_->GetWritableDataFrames() <= static_cast<int32_t>(spanSizeInFrame_)) {
246         if (overFlowLogFlag_ == 0) {
247             AUDIO_INFO_LOG("OverFlow!!!");
248         } else if (overFlowLogFlag_ == OVERFLOW_LOG_LOOP_COUNT) {
249             overFlowLogFlag_ = 0;
250         }
251         overFlowLogFlag_++;
252         int32_t engineFlag = GetEngineFlag();
253         if (engineFlag != 1) {
254             BufferDesc dstBuffer = stream_->DequeueBuffer(length);
255             stream_->EnqueueBuffer(dstBuffer);
256         }
257         stateListener->OnOperationHandled(UPDATE_STREAM, currentWriteFrame);
258         return true;
259     }
260     return false;
261 }
262 
263 
HandleStreamStatusToCapturerState(const IStatus & status)264 static CapturerState HandleStreamStatusToCapturerState(const IStatus &status)
265 {
266     switch (status) {
267         case I_STATUS_IDLE:
268             return CAPTURER_PREPARED;
269         case I_STATUS_STARTING:
270         case I_STATUS_STARTED:
271         case I_STATUS_FLUSHING_WHEN_STARTED:
272             return CAPTURER_RUNNING;
273         case I_STATUS_PAUSING:
274         case I_STATUS_PAUSED:
275         case I_STATUS_FLUSHING_WHEN_PAUSED:
276             return CAPTURER_PAUSED;
277         case I_STATUS_STOPPING:
278         case I_STATUS_STOPPED:
279         case I_STATUS_FLUSHING_WHEN_STOPPED:
280             return CAPTURER_STOPPED;
281         case I_STATUS_RELEASING:
282         case I_STATUS_RELEASED:
283             return CAPTURER_RELEASED;
284         default:
285             return CAPTURER_INVALID;
286     }
287 }
288 
GetByteSizeByFormat(enum AudioSampleFormat format)289 static uint32_t GetByteSizeByFormat(enum AudioSampleFormat format)
290 {
291     uint32_t byteSize = 0;
292     switch (format) {
293         case AudioSampleFormat::SAMPLE_U8:
294             byteSize = BYTE_SIZE_SAMPLE_U8;
295             break;
296         case AudioSampleFormat::SAMPLE_S16LE:
297             byteSize = BYTE_SIZE_SAMPLE_S16;
298             break;
299         case AudioSampleFormat::SAMPLE_S24LE:
300             byteSize = BYTE_SIZE_SAMPLE_S24;
301             break;
302         case AudioSampleFormat::SAMPLE_S32LE:
303             byteSize = BYTE_SIZE_SAMPLE_S32;
304             break;
305         case AudioSampleFormat::SAMPLE_F32LE:
306             byteSize = BYTE_SIZE_SAMPLE_S32;
307             break;
308         default:
309             byteSize = BYTE_SIZE_SAMPLE_S16;
310             break;
311     }
312     return byteSize;
313 }
314 
UpdateBufferTimeStamp(size_t readLen)315 void CapturerInServer::UpdateBufferTimeStamp(size_t readLen)
316 {
317     CHECK_AND_RETURN_LOG(capturerClock_ != nullptr, "capturerClock_ is nullptr!");
318     uint64_t timestamp = 0;
319     uint32_t sizePerPos = static_cast<uint32_t>(GetByteSizeByFormat(processConfig_.streamInfo.format)) *
320         processConfig_.streamInfo.channels;
321 
322     curProcessPos_ += lastPosInc_;
323     CHECK_AND_RETURN_LOG(readLen >= 0, "readLen is illegal!");
324     lastPosInc_ = static_cast<uint64_t>(readLen) / sizePerPos;
325 
326     capturerClock_->GetTimeStampByPosition(curProcessPos_, timestamp);
327 
328     AUDIO_DEBUG_LOG("update buffer timestamp pos:%{public}" PRIu64 " ts:%{public}" PRIu64,
329         curProcessPos_, timestamp);
330     audioServerBuffer_->SetTimeStampInfo(curProcessPos_, timestamp);
331 }
332 
ReadData(size_t length)333 void CapturerInServer::ReadData(size_t length)
334 {
335     CHECK_AND_RETURN_LOG(length >= spanSizeInBytes_,
336         "Length %{public}zu is less than spanSizeInBytes %{public}zu", length, spanSizeInBytes_);
337     std::shared_ptr<IStreamListener> stateListener = streamListener_.lock();
338     CHECK_AND_RETURN_LOG(stateListener != nullptr, "IStreamListener is nullptr!");
339     CHECK_AND_RETURN_LOG(stream_ != nullptr, "ReadData failed, stream_ is null!");
340 
341     uint64_t currentWriteFrame = audioServerBuffer_->GetCurWriteFrame();
342     if (IsReadDataOverFlow(length, currentWriteFrame, stateListener)) {
343         UpdateBufferTimeStamp(length);
344         return;
345     }
346     Trace trace(traceTag_ + "::ReadData:" + std::to_string(currentWriteFrame));
347     OptResult result = ringCache_->GetWritableSize();
348     CHECK_AND_RETURN_LOG(result.ret == OPERATION_SUCCESS, "RingCache write invalid size %{public}zu", result.size);
349     BufferDesc srcBuffer = stream_->DequeueBuffer(result.size);
350     ringCache_->Enqueue({srcBuffer.buffer, srcBuffer.bufLength});
351     result = ringCache_->GetReadableSize();
352     if (result.ret != OPERATION_SUCCESS || result.size < spanSizeInBytes_) {
353         stream_->EnqueueBuffer(srcBuffer);
354         return;
355     }
356 
357     BufferDesc dstBuffer = {nullptr, 0, 0};
358 
359     uint64_t curWritePos = audioServerBuffer_->GetCurWriteFrame();
360     if (audioServerBuffer_->GetWriteBuffer(curWritePos, dstBuffer) < 0) {
361         return;
362     }
363 
364     if ((processConfig_.capturerInfo.sourceType == SOURCE_TYPE_PLAYBACK_CAPTURE && processConfig_.innerCapMode ==
365         LEGACY_MUTE_CAP) || muteFlag_) {
366         dstBuffer.buffer = dischargeBuffer_.get(); // discharge valid data.
367     }
368     if (muteFlag_) {
369         memset_s(static_cast<void *>(dstBuffer.buffer), dstBuffer.bufLength, 0, dstBuffer.bufLength);
370     }
371     ringCache_->Dequeue({dstBuffer.buffer, dstBuffer.bufLength});
372     VolumeTools::DfxOperation(dstBuffer, processConfig_.streamInfo, traceTag_, volumeDataCount_);
373     if (AudioDump::GetInstance().GetVersionType() == DumpFileUtil::BETA_VERSION) {
374         DumpFileUtil::WriteDumpFile(dumpS2C_, static_cast<void *>(dstBuffer.buffer), dstBuffer.bufLength);
375         AudioCacheMgr::GetInstance().CacheData(dumpFileName_,
376             static_cast<void *>(dstBuffer.buffer), dstBuffer.bufLength);
377     }
378 
379     uint64_t nextWriteFrame = currentWriteFrame + spanSizeInFrame_;
380     audioServerBuffer_->SetCurWriteFrame(nextWriteFrame);
381     audioServerBuffer_->SetHandleInfo(currentWriteFrame, ClockTime::GetCurNano());
382 
383     UpdateBufferTimeStamp(dstBuffer.bufLength);
384 
385     stream_->EnqueueBuffer(srcBuffer);
386     stateListener->OnOperationHandled(UPDATE_STREAM, currentWriteFrame);
387 }
388 
OnReadData(size_t length)389 int32_t CapturerInServer::OnReadData(size_t length)
390 {
391     Trace trace(traceTag_ + "::OnReadData:" + std::to_string(length));
392     ReadData(length);
393     return SUCCESS;
394 }
395 
OnReadData(int8_t * outputData,size_t requestDataLen)396 int32_t CapturerInServer::OnReadData(int8_t *outputData, size_t requestDataLen)
397 {
398     CHECK_AND_RETURN_RET_LOG(status_.load() == I_STATUS_STARTED, ERR_READ_FAILED, "CapturerInServer is not started");
399     CHECK_AND_RETURN_RET_LOG(requestDataLen >= spanSizeInBytes_, ERR_READ_FAILED,
400         "Length %{public}zu is less than spanSizeInBytes %{public}zu", requestDataLen, spanSizeInBytes_);
401     std::shared_ptr<IStreamListener> stateListener = streamListener_.lock();
402     CHECK_AND_RETURN_RET_LOG(stateListener != nullptr, ERR_READ_FAILED, "IStreamListener is nullptr!");
403     uint64_t currentWriteFrame = audioServerBuffer_->GetCurWriteFrame();
404     if (IsReadDataOverFlow(requestDataLen, currentWriteFrame, stateListener)) {
405         UpdateBufferTimeStamp(requestDataLen);
406         return ERR_WRITE_FAILED;
407     }
408     Trace trace("CapturerInServer::ReadData:" + std::to_string(currentWriteFrame));
409     OptResult result = ringCache_->GetWritableSize();
410     CHECK_AND_RETURN_RET_LOG(result.ret == OPERATION_SUCCESS, ERR_READ_FAILED,
411         "RingCache write invalid size %{public}zu", result.size);
412 
413     BufferDesc srcBuffer = {reinterpret_cast<uint8_t *>(outputData), requestDataLen, 0};
414 
415     ringCache_->Enqueue({srcBuffer.buffer, srcBuffer.bufLength});
416     result = ringCache_->GetReadableSize();
417     if (result.ret != OPERATION_SUCCESS || result.size < spanSizeInBytes_) {
418         return SUCCESS;
419     }
420 
421     BufferDesc dstBuffer = {nullptr, 0, 0};
422     uint64_t curWritePos = audioServerBuffer_->GetCurWriteFrame();
423     CHECK_AND_RETURN_RET_LOG(audioServerBuffer_->GetWriteBuffer(curWritePos, dstBuffer) >= 0, ERR_READ_FAILED,
424         "GetWriteBuffer failed");
425     if ((processConfig_.capturerInfo.sourceType == SOURCE_TYPE_PLAYBACK_CAPTURE && processConfig_.innerCapMode ==
426         LEGACY_MUTE_CAP) || muteFlag_) {
427         dstBuffer.buffer = dischargeBuffer_.get(); // discharge valid data.
428     }
429     if (muteFlag_) {
430         memset_s(static_cast<void *>(dstBuffer.buffer), dstBuffer.bufLength, 0, dstBuffer.bufLength);
431     }
432     ringCache_->Dequeue({dstBuffer.buffer, dstBuffer.bufLength});
433     VolumeTools::DfxOperation(dstBuffer, processConfig_.streamInfo, traceTag_, volumeDataCount_);
434     if (AudioDump::GetInstance().GetVersionType() == DumpFileUtil::BETA_VERSION) {
435         DumpFileUtil::WriteDumpFile(dumpS2C_, static_cast<void *>(dstBuffer.buffer), dstBuffer.bufLength);
436         AudioCacheMgr::GetInstance().CacheData(dumpFileName_,
437             static_cast<void *>(dstBuffer.buffer), dstBuffer.bufLength);
438     }
439 
440     uint64_t nextWriteFrame = currentWriteFrame + spanSizeInFrame_;
441     audioServerBuffer_->SetCurWriteFrame(nextWriteFrame);
442     audioServerBuffer_->SetHandleInfo(currentWriteFrame, ClockTime::GetCurNano());
443 
444     UpdateBufferTimeStamp(dstBuffer.bufLength);
445 
446     stateListener->OnOperationHandled(UPDATE_STREAM, currentWriteFrame);
447 
448     return SUCCESS;
449 }
450 
UpdateReadIndex()451 int32_t CapturerInServer::UpdateReadIndex()
452 {
453     AUDIO_DEBUG_LOG("audioServerBuffer_->GetWritableDataFrames(): %{public}d, needStart: %{public}d",
454         audioServerBuffer_->GetWritableDataFrames(), needStart);
455     return SUCCESS;
456 }
457 
ResolveBuffer(std::shared_ptr<OHAudioBuffer> & buffer)458 int32_t CapturerInServer::ResolveBuffer(std::shared_ptr<OHAudioBuffer> &buffer)
459 {
460     buffer = audioServerBuffer_;
461     return SUCCESS;
462 }
463 
GetSessionId(uint32_t & sessionId)464 int32_t CapturerInServer::GetSessionId(uint32_t &sessionId)
465 {
466     CHECK_AND_RETURN_RET_LOG(stream_ != nullptr, ERR_OPERATION_FAILED, "GetSessionId failed, stream_ is null");
467     sessionId = streamIndex_;
468     CHECK_AND_RETURN_RET_LOG(sessionId < INT32_MAX, ERR_OPERATION_FAILED, "GetSessionId failed, sessionId:%{public}d",
469         sessionId);
470 
471     return SUCCESS;
472 }
473 
CheckBGCapture()474 bool CapturerInServer::CheckBGCapture()
475 {
476     uint32_t tokenId = processConfig_.appInfo.appTokenId;
477     uint64_t fullTokenId = processConfig_.appInfo.appFullTokenId;
478 
479     if (PermissionUtil::VerifyBackgroundCapture(tokenId, fullTokenId)) {
480         return true;
481     }
482 
483     CHECK_AND_RETURN_RET_LOG(processConfig_.capturerInfo.sourceType == SOURCE_TYPE_VOICE_COMMUNICATION &&
484         AudioService::GetInstance()->InForegroundList(processConfig_.appInfo.appUid), false, "Check failed");
485 
486     AudioService::GetInstance()->UpdateForegroundState(tokenId, true);
487     bool res = PermissionUtil::VerifyBackgroundCapture(tokenId, fullTokenId);
488     AUDIO_INFO_LOG("Retry result:%{public}s", (res ? "success" : "fail"));
489     AudioService::GetInstance()->UpdateForegroundState(tokenId, false);
490 
491     return res;
492 }
493 
TurnOnMicIndicator(CapturerState capturerState)494 bool CapturerInServer::TurnOnMicIndicator(CapturerState capturerState)
495 {
496     uint32_t tokenId = processConfig_.appInfo.appTokenId;
497     SwitchStreamInfo info = {
498         streamIndex_,
499         processConfig_.callerUid,
500         processConfig_.appInfo.appUid,
501         processConfig_.appInfo.appPid,
502         tokenId,
503         capturerState,
504     };
505     if (!SwitchStreamUtil::IsSwitchStreamSwitching(info, SWITCH_STATE_STARTED)) {
506         CHECK_AND_RETURN_RET_LOG(CheckBGCapture(), false, "Verify failed");
507     }
508     SwitchStreamUtil::UpdateSwitchStreamRecord(info, SWITCH_STATE_STARTED);
509 
510     if (isMicIndicatorOn_) {
511         AUDIO_WARNING_LOG("MicIndicator of stream:%{public}d is already on."
512             "No need to call NotifyPrivacyStart!", streamIndex_);
513     } else {
514         CHECK_AND_RETURN_RET_LOG(PermissionUtil::NotifyPrivacyStart(tokenId, streamIndex_),
515             false, "NotifyPrivacyStart failed!");
516         AUDIO_INFO_LOG("Turn on micIndicator of stream:%{public}d from off "
517             "after NotifyPrivacyStart success!", streamIndex_);
518         isMicIndicatorOn_ = true;
519     }
520     return true;
521 }
522 
TurnOffMicIndicator(CapturerState capturerState)523 bool CapturerInServer::TurnOffMicIndicator(CapturerState capturerState)
524 {
525     uint32_t tokenId = processConfig_.appInfo.appTokenId;
526     SwitchStreamInfo info = {
527         streamIndex_,
528         processConfig_.callerUid,
529         processConfig_.appInfo.appUid,
530         processConfig_.appInfo.appPid,
531         tokenId,
532         capturerState,
533     };
534     SwitchStreamUtil::UpdateSwitchStreamRecord(info, SWITCH_STATE_FINISHED);
535 
536     if (isMicIndicatorOn_) {
537         PermissionUtil::NotifyPrivacyStop(tokenId, streamIndex_);
538         AUDIO_INFO_LOG("Turn off micIndicator of stream:%{public}d from on after NotifyPrivacyStop!", streamIndex_);
539         isMicIndicatorOn_ = false;
540     } else {
541         AUDIO_WARNING_LOG("MicIndicator of stream:%{public}d is already off."
542             "No need to call NotifyPrivacyStop!", streamIndex_);
543     }
544     return true;
545 }
546 
Start()547 int32_t CapturerInServer::Start()
548 {
549     AudioXCollie audioXCollie(
550         "CapturerInServer::Start", RELEASE_TIMEOUT_IN_SEC, nullptr, nullptr,
551             AUDIO_XCOLLIE_FLAG_LOG | AUDIO_XCOLLIE_FLAG_RECOVERY);
552     int32_t ret = StartInner();
553     CapturerStage stage = ret == SUCCESS ? CAPTURER_STAGE_START_OK : CAPTURER_STAGE_START_FAIL;
554     if (recorderDfx_) {
555         recorderDfx_->WriteDfxStartMsg(streamIndex_, stage, processConfig_);
556     }
557     if (ret == SUCCESS) {
558         StreamDfxManager::GetInstance().CheckStreamOccupancy(streamIndex_, processConfig_, true);
559     }
560     return ret;
561 }
562 
StartInner()563 int32_t CapturerInServer::StartInner()
564 {
565     needStart = 0;
566     std::unique_lock<std::mutex> lock(statusLock_);
567 
568     if (status_ != I_STATUS_IDLE && status_ != I_STATUS_PAUSED && status_ != I_STATUS_STOPPED) {
569         AUDIO_ERR_LOG("CapturerInServer::Start failed, Illegal state: %{public}u", status_.load());
570         return ERR_ILLEGAL_STATE;
571     }
572 
573     if (!needCheckBackground_ && PermissionUtil::NeedVerifyBackgroundCapture(processConfig_.callerUid,
574         processConfig_.capturerInfo.sourceType)) {
575         AUDIO_INFO_LOG("set needCheckBackground_: true");
576         needCheckBackground_ = true;
577     }
578     if (needCheckBackground_) {
579         CHECK_AND_RETURN_RET_LOG(TurnOnMicIndicator(CAPTURER_RUNNING), ERR_PERMISSION_DENIED,
580             "Turn on micIndicator failed or check backgroud capture failed for stream:%{public}d!", streamIndex_);
581     }
582 
583     if (processConfig_.capturerInfo.sourceType != SOURCE_TYPE_PLAYBACK_CAPTURE) {
584         CoreServiceHandler::GetInstance().UpdateSessionOperation(streamIndex_, SESSION_OPERATION_START);
585     }
586 
587     if (CoreServiceHandler::GetInstance().ReloadCaptureSession(streamIndex_, SESSION_OPERATION_START) == SUCCESS) {
588         AUDIO_ERR_LOG("ReloadCaptureSession success!");
589     }
590 
591     status_ = I_STATUS_STARTING;
592     if (processConfig_.capturerInfo.sourceType == SOURCE_TYPE_PLAYBACK_CAPTURE) {
593         PlaybackCapturerManager::GetInstance()->InitAllDupBuffer(innerCapId_);
594     }
595     int32_t ret = stream_->Start();
596     CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ret, "Start stream failed, reason: %{public}d", ret);
597     resetTime_ = true;
598 
599     if (capturerClock_ != nullptr) {
600         capturerClock_->Start();
601     }
602 
603     return SUCCESS;
604 }
605 
Pause()606 int32_t CapturerInServer::Pause()
607 {
608     AudioXCollie audioXCollie(
609         "CapturerInServer::Pause", RELEASE_TIMEOUT_IN_SEC, nullptr, nullptr,
610             AUDIO_XCOLLIE_FLAG_LOG | AUDIO_XCOLLIE_FLAG_RECOVERY);
611     std::unique_lock<std::mutex> lock(statusLock_);
612 
613     if (status_ != I_STATUS_STARTED) {
614         AUDIO_ERR_LOG("failed, Illegal state: %{public}u", status_.load());
615         return ERR_ILLEGAL_STATE;
616     }
617     if (needCheckBackground_) {
618         TurnOffMicIndicator(CAPTURER_PAUSED);
619     }
620     if (CoreServiceHandler::GetInstance().ReloadCaptureSession(streamIndex_, SESSION_OPERATION_PAUSE) == SUCCESS) {
621         AUDIO_INFO_LOG("ReloadCaptureSession success!");
622     }
623 
624     status_ = I_STATUS_PAUSING;
625     int ret = stream_->Pause();
626     CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ret, "Pause stream failed, reason: %{public}d", ret);
627     CoreServiceHandler::GetInstance().UpdateSessionOperation(streamIndex_, SESSION_OPERATION_PAUSE);
628     StreamDfxManager::GetInstance().CheckStreamOccupancy(streamIndex_, processConfig_, false);
629     if (capturerClock_ != nullptr) {
630         capturerClock_->Stop();
631     }
632     return SUCCESS;
633 }
634 
Flush()635 int32_t CapturerInServer::Flush()
636 {
637     AudioXCollie audioXCollie(
638         "CapturerInServer::Flush", RELEASE_TIMEOUT_IN_SEC, nullptr, nullptr,
639             AUDIO_XCOLLIE_FLAG_LOG | AUDIO_XCOLLIE_FLAG_RECOVERY);
640     std::unique_lock<std::mutex> lock(statusLock_);
641     if (status_ == I_STATUS_STARTED) {
642         status_ = I_STATUS_FLUSHING_WHEN_STARTED;
643     } else if (status_ == I_STATUS_PAUSED) {
644         status_ = I_STATUS_FLUSHING_WHEN_PAUSED;
645     } else if (status_ == I_STATUS_STOPPED) {
646         status_ = I_STATUS_FLUSHING_WHEN_STOPPED;
647     } else {
648         AUDIO_ERR_LOG("failed, Illegal state: %{public}u", status_.load());
649         return ERR_ILLEGAL_STATE;
650     }
651 
652     // Flush buffer of audio server
653     uint64_t writeFrame = audioServerBuffer_->GetCurWriteFrame();
654     uint64_t readFrame = audioServerBuffer_->GetCurReadFrame();
655 
656     while (readFrame < writeFrame) {
657         BufferDesc bufferDesc = {nullptr, 0, 0};
658         int32_t readResult = audioServerBuffer_->GetReadbuffer(readFrame, bufferDesc);
659         if (readResult != 0) {
660             return ERR_OPERATION_FAILED;
661         }
662         memset_s(bufferDesc.buffer, bufferDesc.bufLength, 0, bufferDesc.bufLength);
663         readFrame += spanSizeInFrame_;
664         AUDIO_INFO_LOG("On flush, write frame: %{public}" PRIu64 ", nextReadFrame: %{public}zu,"
665             "readFrame: %{public}" PRIu64 "", writeFrame, spanSizeInFrame_, readFrame);
666         audioServerBuffer_->SetCurReadFrame(readFrame);
667     }
668 
669     int ret = stream_->Flush();
670     CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ret, "Flush stream failed, reason: %{public}d", ret);
671     return SUCCESS;
672 }
673 
DrainAudioBuffer()674 int32_t CapturerInServer::DrainAudioBuffer()
675 {
676     return SUCCESS;
677 }
678 
Stop()679 int32_t CapturerInServer::Stop()
680 {
681     AudioXCollie audioXCollie(
682         "CapturerInServer::Stop", RELEASE_TIMEOUT_IN_SEC, nullptr, nullptr,
683             AUDIO_XCOLLIE_FLAG_LOG | AUDIO_XCOLLIE_FLAG_RECOVERY);
684     std::unique_lock<std::mutex> lock(statusLock_);
685     if (status_ != I_STATUS_STARTED && status_ != I_STATUS_PAUSED) {
686         AUDIO_ERR_LOG("failed, Illegal state: %{public}u", status_.load());
687         return ERR_ILLEGAL_STATE;
688     }
689     status_ = I_STATUS_STOPPING;
690 
691     if (capturerClock_ != nullptr) {
692         capturerClock_->Stop();
693     }
694     if (needCheckBackground_) {
695         TurnOffMicIndicator(CAPTURER_STOPPED);
696     }
697     if (CoreServiceHandler::GetInstance().ReloadCaptureSession(streamIndex_, SESSION_OPERATION_STOP) == SUCCESS) {
698         AUDIO_INFO_LOG("ReloadCaptureSession success!");
699     }
700 
701     int ret = stream_->Stop();
702     CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ret, "Stop stream failed, reason: %{public}d", ret);
703     CoreServiceHandler::GetInstance().UpdateSessionOperation(streamIndex_, SESSION_OPERATION_STOP);
704     StreamDfxManager::GetInstance().CheckStreamOccupancy(streamIndex_, processConfig_, false);
705     return SUCCESS;
706 }
707 
Release(bool isSwitchStream)708 int32_t CapturerInServer::Release(bool isSwitchStream)
709 {
710     AudioXCollie audioXCollie("CapturerInServer::Release", RELEASE_TIMEOUT_IN_SEC,
711         nullptr, nullptr, AUDIO_XCOLLIE_FLAG_LOG | AUDIO_XCOLLIE_FLAG_RECOVERY);
712     AudioService::GetInstance()->RemoveCapturer(streamIndex_, isSwitchStream);
713     std::unique_lock<std::mutex> lock(statusLock_);
714     if (status_ == I_STATUS_RELEASED) {
715         AUDIO_INFO_LOG("Already released");
716         return SUCCESS;
717     }
718     lock.unlock();
719     AUDIO_INFO_LOG("Start release capturer");
720 
721     if (processConfig_.capturerInfo.sourceType != SOURCE_TYPE_PLAYBACK_CAPTURE) {
722         int32_t result =
723             CoreServiceHandler::GetInstance().UpdateSessionOperation(streamIndex_, SESSION_OPERATION_RELEASE);
724         CHECK_AND_RETURN_RET_LOG(result == SUCCESS, result, "Policy remove client failed, reason: %{public}d", result);
725     }
726     StreamDfxManager::GetInstance().CheckStreamOccupancy(streamIndex_, processConfig_, false);
727     int32_t ret = IStreamManager::GetRecorderManager().ReleaseCapturer(streamIndex_);
728     if (ret < 0) {
729         AUDIO_ERR_LOG("Release stream failed, reason: %{public}d", ret);
730         status_ = I_STATUS_INVALID;
731         return ret;
732     }
733     if (status_ != I_STATUS_STOPPING &&
734         status_ != I_STATUS_STOPPED) {
735         HandleOperationStopped(CAPTURER_STAGE_STOP_BY_RELEASE);
736     }
737     if (CoreServiceHandler::GetInstance().ReloadCaptureSession(streamIndex_, SESSION_OPERATION_RELEASE) == SUCCESS) {
738         AUDIO_INFO_LOG("ReloadCaptureSession success!");
739     }
740     status_ = I_STATUS_RELEASED;
741 
742     capturerClock_ = nullptr;
743     CapturerClockManager::GetInstance().DeleteCapturerClock(streamIndex_);
744 #ifdef HAS_FEATURE_INNERCAPTURER
745     if (processConfig_.capturerInfo.sourceType == SOURCE_TYPE_PLAYBACK_CAPTURE) {
746         AUDIO_INFO_LOG("Disable inner capturer for %{public}u, innerCapId :%{public}d, innerCapMode:%{public}d",
747             streamIndex_, innerCapId_, processConfig_.innerCapMode);
748         if (processConfig_.innerCapMode == MODERN_INNER_CAP) {
749             PlaybackCapturerManager::GetInstance()->RemovePlaybackCapturerFilterInfo(streamIndex_, innerCapId_);
750         } else {
751             PlaybackCapturerManager::GetInstance()->SetInnerCapturerState(false);
752         }
753         if (PlaybackCapturerManager::GetInstance()->CheckReleaseUnloadModernInnerCapSink(innerCapId_)) {
754             AudioService::GetInstance()->UnloadModernInnerCapSink(innerCapId_);
755         }
756         innerCapId_ = 0;
757     }
758 #endif
759     if (needCheckBackground_) {
760         TurnOffMicIndicator(CAPTURER_RELEASED);
761     }
762     return SUCCESS;
763 }
764 
765 #ifdef HAS_FEATURE_INNERCAPTURER
UpdatePlaybackCaptureConfigInLegacy(const AudioPlaybackCaptureConfig & config)766 int32_t CapturerInServer::UpdatePlaybackCaptureConfigInLegacy(const AudioPlaybackCaptureConfig &config)
767 {
768     Trace trace("UpdatePlaybackCaptureConfigInLegacy");
769     // Legacy mode, only usage filter works.
770     AUDIO_INFO_LOG("Update config in legacy mode with %{public}zu usage", config.filterOptions.usages.size());
771 
772     std::vector<int32_t> usage;
773     for (size_t i = 0; i < config.filterOptions.usages.size(); i++) {
774         usage.push_back(config.filterOptions.usages[i]);
775     }
776 
777     PlaybackCapturerManager::GetInstance()->SetSupportStreamUsage(usage);
778     PlaybackCapturerManager::GetInstance()->SetInnerCapturerState(true);
779     return SUCCESS;
780 }
781 
UpdatePlaybackCaptureConfig(const AudioPlaybackCaptureConfig & config)782 int32_t CapturerInServer::UpdatePlaybackCaptureConfig(const AudioPlaybackCaptureConfig &config)
783 {
784     Trace trace("UpdatePlaybackCaptureConfig:" + ProcessConfig::DumpInnerCapConfig(config));
785     CHECK_AND_RETURN_RET_LOG(processConfig_.capturerInfo.sourceType == SOURCE_TYPE_PLAYBACK_CAPTURE,
786         ERR_INVALID_OPERATION, "This not a inner-cap source!");
787 
788     AUDIO_INFO_LOG("Client using config: %{public}s", ProcessConfig::DumpInnerCapConfig(config).c_str());
789 
790     for (auto &usg : config.filterOptions.usages) {
791         if (usg != STREAM_USAGE_VOICE_COMMUNICATION) {
792             continue;
793         }
794 
795         if (!PermissionUtil::VerifyPermission(CAPTURER_VOICE_DOWNLINK_PERMISSION, processConfig_.appInfo.appTokenId)) {
796             AUDIO_ERR_LOG("downlink capturer permission check failed");
797             return ERR_PERMISSION_DENIED;
798         }
799     }
800     filterConfig_ = config;
801 
802     if (filterConfig_.filterOptions.usages.size() == 0) {
803         std::vector<StreamUsage> defalutUsages = PlaybackCapturerManager::GetInstance()->GetDefaultUsages();
804         for (size_t i = 0; i < defalutUsages.size(); i++) {
805             filterConfig_.filterOptions.usages.push_back(defalutUsages[i]);
806         }
807         AUDIO_INFO_LOG("Reset config to %{public}s", ProcessConfig::DumpInnerCapConfig(filterConfig_).c_str());
808     }
809 
810     if (processConfig_.innerCapMode != MODERN_INNER_CAP) {
811         return UpdatePlaybackCaptureConfigInLegacy(filterConfig_);
812     }
813 
814     // in plan: add more check and print config
815     PlaybackCapturerManager::GetInstance()->SetPlaybackCapturerFilterInfo(streamIndex_, filterConfig_, innerCapId_);
816     return SUCCESS;
817 }
818 #endif
819 
GetAudioTime(uint64_t & framePos,uint64_t & timestamp)820 int32_t CapturerInServer::GetAudioTime(uint64_t &framePos, uint64_t &timestamp)
821 {
822     if (status_ == I_STATUS_STOPPED) {
823         AUDIO_WARNING_LOG("Current status is stopped");
824         return ERR_ILLEGAL_STATE;
825     }
826     CHECK_AND_RETURN_RET_LOG(stream_ != nullptr, ERR_OPERATION_FAILED, "GetAudioTime failed, stream_ is null");
827     stream_->GetStreamFramesRead(framePos);
828     stream_->GetCurrentTimeStamp(timestamp);
829     if (resetTime_) {
830         resetTime_ = false;
831         resetTimestamp_ = timestamp;
832     }
833     return SUCCESS;
834 }
835 
GetLatency(uint64_t & latency)836 int32_t CapturerInServer::GetLatency(uint64_t &latency)
837 {
838     CHECK_AND_RETURN_RET_LOG(stream_ != nullptr, ERR_OPERATION_FAILED, "GetLatency failed, stream_ is null");
839     return stream_->GetLatency(latency);
840 }
841 
InitCacheBuffer(size_t targetSize)842 int32_t CapturerInServer::InitCacheBuffer(size_t targetSize)
843 {
844     CHECK_AND_RETURN_RET_LOG(spanSizeInBytes_ != 0, ERR_OPERATION_FAILED, "spanSizeInByte_ invalid");
845 
846     AUDIO_INFO_LOG("old size:%{public}zu, new size:%{public}zu", cacheSizeInBytes_, targetSize);
847     cacheSizeInBytes_ = targetSize;
848 
849     if (ringCache_ == nullptr) {
850         ringCache_ = AudioRingCache::Create(cacheSizeInBytes_);
851     } else {
852         OptResult result = ringCache_->ReConfig(cacheSizeInBytes_, false); // false --> clear buffer
853         if (result.ret != OPERATION_SUCCESS) {
854             AUDIO_ERR_LOG("ReConfig AudioRingCache to size %{public}u failed:ret%{public}zu", result.ret, targetSize);
855             return ERR_OPERATION_FAILED;
856         }
857     }
858 
859     if (processConfig_.capturerInfo.sourceType == SOURCE_TYPE_PLAYBACK_CAPTURE && processConfig_.innerCapMode ==
860         LEGACY_MUTE_CAP) {
861         dischargeBuffer_ = std::make_unique<uint8_t []>(cacheSizeInBytes_);
862     }
863 
864     return SUCCESS;
865 }
866 
SetNonInterruptMute(const bool muteFlag)867 void CapturerInServer::SetNonInterruptMute(const bool muteFlag)
868 {
869     AUDIO_INFO_LOG("muteFlag: %{public}d", muteFlag);
870     muteFlag_ = muteFlag;
871     AudioService::GetInstance()->UpdateMuteControlSet(streamIndex_, muteFlag);
872 }
873 
RestoreSession(RestoreInfo restoreInfo)874 RestoreStatus CapturerInServer::RestoreSession(RestoreInfo restoreInfo)
875 {
876     RestoreStatus restoreStatus = audioServerBuffer_->SetRestoreStatus(NEED_RESTORE);
877     if (restoreStatus == NEED_RESTORE) {
878         SwitchStreamInfo info = {
879             streamIndex_,
880             processConfig_.callerUid,
881             processConfig_.appInfo.appUid,
882             processConfig_.appInfo.appPid,
883             processConfig_.appInfo.appTokenId,
884             HandleStreamStatusToCapturerState(status_)
885         };
886         AUDIO_INFO_LOG("Insert fast record stream:%{public}u uid:%{public}d tokenId:%{public}u "
887             "into switchStreamRecord because restoreStatus:NEED_RESTORE",
888             streamIndex_, info.callerUid, info.appTokenId);
889         SwitchStreamUtil::UpdateSwitchStreamRecord(info, SWITCH_STATE_WAITING);
890 
891         audioServerBuffer_->SetRestoreInfo(restoreInfo);
892     }
893     return restoreStatus;
894 }
895 
GetLastAudioDuration()896 int64_t CapturerInServer::GetLastAudioDuration()
897 {
898     auto ret = lastStopTime_ - lastStartTime_;
899     return ret < 0 ? -1 : ret;
900 }
901 
StopSession()902 int32_t CapturerInServer::StopSession()
903 {
904     CHECK_AND_RETURN_RET_LOG(audioServerBuffer_ != nullptr, ERR_INVALID_PARAM, "audioServerBuffer_ is nullptr");
905     audioServerBuffer_->SetStopFlag(true);
906     return SUCCESS;
907 }
908 
ResolveBufferBaseAndGetServerSpanSize(std::shared_ptr<OHAudioBufferBase> & buffer,uint32_t & spanSizeInFrame,uint64_t & engineTotalSizeInFrame)909 int32_t CapturerInServer::ResolveBufferBaseAndGetServerSpanSize(std::shared_ptr<OHAudioBufferBase> &buffer,
910     uint32_t &spanSizeInFrame, uint64_t &engineTotalSizeInFrame)
911 {
912     return ERR_NOT_SUPPORTED;
913 }
914 
CaptureConcurrentCheck(uint32_t streamIndex)915 inline void CapturerInServer::CaptureConcurrentCheck(uint32_t streamIndex)
916 {
917     if (lastStatus_ == status_) {
918         return;
919     }
920     std::atomic_store(&lastStatus_, status_);
921     int32_t ret = PolicyHandler::GetInstance().CaptureConcurrentCheck(streamIndex);
922     AUDIO_INFO_LOG("ret:%{public}d streamIndex_:%{public}d status_:%{public}u", ret, streamIndex, status_.load());
923 }
924 } // namespace AudioStandard
925 } // namespace OHOS
926