• 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 "PaAdapterManager"
17 #endif
18 #ifdef SUPPORT_OLD_ENGINE
19 #include "pa_adapter_manager.h"
20 #include <sstream>
21 #include <atomic>
22 #include "audio_common_log.h"
23 #include "audio_errors.h"
24 #include "audio_schedule.h"
25 #include "pa_adapter_tools.h"
26 #include "pa_renderer_stream_impl.h"
27 #include "pa_capturer_stream_impl.h"
28 #include "audio_utils.h"
29 #include "policy_handler.h"
30 #include "core_service_handler.h"
31 
32 namespace OHOS {
33 namespace AudioStandard {
34 const uint32_t CHECK_UTIL_SUCCESS = 0;
35 const uint64_t BUF_LENGTH_IN_MSEC = 20;
36 static const uint32_t PA_RECORD_MAX_LENGTH_NORMAL = 4;
37 static const uint32_t PA_RECORD_MAX_LENGTH_WAKEUP = 30;
38 static const int32_t CONNECT_STREAM_TIMEOUT_IN_SEC = 5; // 5S
39 const char* INNER_CAPTURER_SOURCE = "Speaker.monitor";
40 const char* NEW_INNER_CAPTURER_SOURCE = "InnerCapturerSink.monitor";
41 const char* MONITOR_SOURCE_SUFFIX = ".monitor";
42 const char* DUAL_TONE_STREAM = "DualToneStream";
43 const char* NORMAL_STREAM = "NormalStream";
44 static const std::unordered_map<AudioStreamType, std::string> STREAM_TYPE_ENUM_STRING_MAP = {
45     {STREAM_VOICE_CALL, "voice_call"},
46     {STREAM_MUSIC, "music"},
47     {STREAM_RING, "ring"},
48     {STREAM_MEDIA, "media"},
49     {STREAM_VOICE_ASSISTANT, "voice_assistant"},
50     {STREAM_SYSTEM, "system"},
51     {STREAM_ALARM, "alarm"},
52     {STREAM_NOTIFICATION, "notification"},
53     {STREAM_BLUETOOTH_SCO, "bluetooth_sco"},
54     {STREAM_ENFORCED_AUDIBLE, "enforced_audible"},
55     {STREAM_DTMF, "dtmf"},
56     {STREAM_TTS, "tts"},
57     {STREAM_ACCESSIBILITY, "accessibility"},
58     {STREAM_RECORDING, "recording"},
59     {STREAM_MOVIE, "movie"},
60     {STREAM_GAME, "game"},
61     {STREAM_SPEECH, "speech"},
62     {STREAM_SYSTEM_ENFORCED, "system_enforced"},
63     {STREAM_ULTRASONIC, "ultrasonic"},
64     {STREAM_WAKEUP, "wakeup"},
65     {STREAM_VOICE_MESSAGE, "voice_message"},
66     {STREAM_NAVIGATION, "navigation"},
67     {STREAM_VOICE_COMMUNICATION, "voice_call"},
68     {STREAM_VOICE_RING, "ring"},
69     {STREAM_VOICE_CALL_ASSISTANT, "voice_call_assistant"},
70     {STREAM_CAMCORDER, "camcorder"},
71 };
72 
CheckReturnIfinvalid(bool expr,const int32_t retVal)73 static int32_t CheckReturnIfinvalid(bool expr, const int32_t retVal)
74 {
75     do {
76         if (!(expr)) {
77             return retVal;
78         }
79     } while (false);
80     return CHECK_UTIL_SUCCESS;
81 }
82 
PaAdapterManager(ManagerType type)83 PaAdapterManager::PaAdapterManager(ManagerType type)
84 {
85     AUDIO_INFO_LOG("Constructor with type:%{public}d", type);
86     mainLoop_ = nullptr;
87     api_ = nullptr;
88     context_ = nullptr;
89     isContextConnected_ = false;
90     isMainLoopStarted_ = false;
91     managerType_ = type;
92 }
93 
CreateRender(AudioProcessConfig processConfig,std::shared_ptr<IRendererStream> & stream)94 int32_t PaAdapterManager::CreateRender(AudioProcessConfig processConfig, std::shared_ptr<IRendererStream> &stream)
95 {
96     AUDIO_DEBUG_LOG("Create renderer start");
97     int32_t ret = InitPaContext();
98     CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ret, "Failed to init pa context");
99     uint32_t sessionId = 0;
100     if (managerType_ == DUP_PLAYBACK || managerType_ == DUAL_PLAYBACK ||
101         processConfig.originalSessionId < MIN_STREAMID || processConfig.originalSessionId > MAX_STREAMID) {
102         sessionId = CoreServiceHandler::GetInstance().GenerateSessionId();
103     } else {
104         sessionId = processConfig.originalSessionId;
105     }
106     AUDIO_DEBUG_LOG("Create [%{public}d] type renderer:[%{public}u]", managerType_, sessionId);
107 
108     // PaAdapterManager is solely responsible for creating paStream objects
109     // while the PaRendererStreamImpl has full authority over the subsequent management of the paStream
110     pa_stream *paStream = InitPaStream(processConfig, sessionId, false);
111     CHECK_AND_RETURN_RET_LOG(paStream != nullptr, ERR_OPERATION_FAILED, "Failed to init render!");
112     std::shared_ptr<IRendererStream> rendererStream = CreateRendererStream(processConfig, paStream);
113     CHECK_AND_RETURN_RET_LOG(rendererStream != nullptr, ERR_DEVICE_INIT, "Failed to init pa stream!");
114     rendererStream->SetStreamIndex(sessionId);
115     std::lock_guard<std::mutex> lock(streamMapMutex_);
116     rendererStreamMap_[sessionId] = rendererStream;
117     stream = rendererStream;
118 
119     std::lock_guard<std::mutex> mutex(sinkInputsMutex_);
120     SinkInput sinkInput;
121     sinkInput.streamId = static_cast<int32_t>(sessionId);
122     sinkInput.streamType = processConfig.streamType;
123     sinkInput.uid = processConfig.appInfo.appUid;
124     sinkInput.pid = processConfig.appInfo.appPid;
125     sinkInput.paStreamId = pa_stream_get_index(paStream);
126     sinkInputs_.push_back(sinkInput);
127     return SUCCESS;
128 }
129 
ReleaseRender(uint32_t streamIndex)130 int32_t PaAdapterManager::ReleaseRender(uint32_t streamIndex)
131 {
132     AUDIO_DEBUG_LOG("Release [%{public}d] type render:[%{public}u]", managerType_, streamIndex);
133     std::unique_lock<std::mutex> lock(streamMapMutex_);
134     auto it = rendererStreamMap_.find(streamIndex);
135     if (it == rendererStreamMap_.end()) {
136         AUDIO_WARNING_LOG("No matching stream");
137         return SUCCESS;
138     }
139     std::shared_ptr<IRendererStream> currentRender = rendererStreamMap_[streamIndex];
140     rendererStreamMap_[streamIndex] = nullptr;
141     rendererStreamMap_.erase(streamIndex);
142     lock.unlock();
143 
144     if (currentRender->Release() < 0) {
145         AUDIO_WARNING_LOG("Release stream %{public}d failed", streamIndex);
146         return ERR_OPERATION_FAILED;
147     }
148 
149     if (isHighResolutionExist_ == true && highResolutionIndex_ == streamIndex) {
150         isHighResolutionExist_ = false;
151     }
152     AUDIO_INFO_LOG("rendererStreamMap_.size() : %{public}zu", rendererStreamMap_.size());
153     if (rendererStreamMap_.size() == 0) {
154         AUDIO_INFO_LOG("Release the last stream");
155     }
156     std::lock_guard<std::mutex> mutex(sinkInputsMutex_);
157     sinkInputs_.erase(std::remove_if(sinkInputs_.begin(), sinkInputs_.end(), [&](const SinkInput &sinkInput) {
158         return static_cast<uint32_t>(sinkInput.streamId) == streamIndex;
159         }), sinkInputs_.end());
160     return SUCCESS;
161 }
162 
GetAllSinkInputs(std::vector<SinkInput> & sinkInputs)163 void PaAdapterManager::GetAllSinkInputs(std::vector<SinkInput> &sinkInputs)
164 {
165     std::lock_guard<std::mutex> mutex(sinkInputsMutex_);
166     sinkInputs = sinkInputs_;
167     Trace trace("PaAdapterManager::GetAllSinkInputs size:" + std::to_string(sinkInputs.size()));
168 }
169 
StartRender(uint32_t streamIndex)170 int32_t PaAdapterManager::StartRender(uint32_t streamIndex)
171 {
172     AUDIO_DEBUG_LOG("Enter StartRender");
173     std::lock_guard<std::mutex> lock(streamMapMutex_);
174     auto it = rendererStreamMap_.find(streamIndex);
175     if (it == rendererStreamMap_.end()) {
176         AUDIO_WARNING_LOG("No matching stream");
177         return SUCCESS;
178     }
179     return rendererStreamMap_[streamIndex]->Start();
180 }
181 
StopRender(uint32_t streamIndex)182 int32_t PaAdapterManager::StopRender(uint32_t streamIndex)
183 {
184     AUDIO_DEBUG_LOG("Enter StopRender");
185     std::lock_guard<std::mutex> lock(streamMapMutex_);
186     auto it = rendererStreamMap_.find(streamIndex);
187     if (it == rendererStreamMap_.end()) {
188         AUDIO_WARNING_LOG("No matching stream");
189         return SUCCESS;
190     }
191     return rendererStreamMap_[streamIndex]->Stop();
192 }
193 
PauseRender(uint32_t streamIndex)194 int32_t PaAdapterManager::PauseRender(uint32_t streamIndex)
195 {
196     AUDIO_DEBUG_LOG("Enter PauseRender");
197     std::lock_guard<std::mutex> lock(streamMapMutex_);
198     auto it = rendererStreamMap_.find(streamIndex);
199     if (it == rendererStreamMap_.end()) {
200         AUDIO_WARNING_LOG("No matching stream");
201         return SUCCESS;
202     }
203     rendererStreamMap_[streamIndex]->Pause();
204     return SUCCESS;
205 }
206 
TriggerStartIfNecessary()207 int32_t PaAdapterManager::TriggerStartIfNecessary()
208 {
209     return SUCCESS;
210 }
211 
GetStreamCount() const212 int32_t PaAdapterManager::GetStreamCount() const noexcept
213 {
214     if (managerType_ == RECORDER) {
215         return capturerStreamMap_.size();
216     } else {
217         return rendererStreamMap_.size();
218     }
219 }
220 
CreateCapturer(AudioProcessConfig processConfig,std::shared_ptr<ICapturerStream> & stream)221 int32_t PaAdapterManager::CreateCapturer(AudioProcessConfig processConfig, std::shared_ptr<ICapturerStream> &stream)
222 {
223     AUDIO_DEBUG_LOG("Create capturer start");
224     CHECK_AND_RETURN_RET_LOG(managerType_ == RECORDER, ERROR, "Invalid managerType:%{public}d", managerType_);
225     int32_t ret = InitPaContext();
226     CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ret, "Failed to init pa context");
227     uint32_t sessionId = 0;
228     if (processConfig.originalSessionId < MIN_STREAMID || processConfig.originalSessionId > MAX_STREAMID) {
229         sessionId = PolicyHandler::GetInstance().GenerateSessionId(processConfig.appInfo.appUid);
230     } else {
231         sessionId = processConfig.originalSessionId;
232     }
233 
234     // PaAdapterManager is solely responsible for creating paStream objects
235     // while the PaCapturerStreamImpl has full authority over the subsequent management of the paStream
236     pa_stream *paStream = InitPaStream(processConfig, sessionId, true);
237     CHECK_AND_RETURN_RET_LOG(paStream != nullptr, ERR_OPERATION_FAILED, "Failed to init capture");
238     std::shared_ptr<ICapturerStream> capturerStream = CreateCapturerStream(processConfig, paStream);
239     CHECK_AND_RETURN_RET_LOG(capturerStream != nullptr, ERR_DEVICE_INIT, "Failed to init pa stream");
240     capturerStream->SetStreamIndex(sessionId);
241     std::lock_guard<std::mutex> lock(streamMapMutex_);
242     capturerStreamMap_[sessionId] = capturerStream;
243     stream = capturerStream;
244     return SUCCESS;
245 }
246 
ReleaseCapturer(uint32_t streamIndex)247 int32_t PaAdapterManager::ReleaseCapturer(uint32_t streamIndex)
248 {
249     AUDIO_DEBUG_LOG("Enter ReleaseCapturer");
250     std::unique_lock<std::mutex> lock(streamMapMutex_);
251     auto it = capturerStreamMap_.find(streamIndex);
252     if (it == capturerStreamMap_.end()) {
253         AUDIO_WARNING_LOG("No matching stream");
254         return SUCCESS;
255     }
256     std::shared_ptr<ICapturerStream> currentCapturer = capturerStreamMap_[streamIndex];
257     capturerStreamMap_[streamIndex] = nullptr;
258     capturerStreamMap_.erase(streamIndex);
259     lock.unlock();
260 
261     if (currentCapturer != nullptr && currentCapturer->Release() < 0) {
262         AUDIO_WARNING_LOG("Release stream %{public}d failed", streamIndex);
263         return ERR_OPERATION_FAILED;
264     }
265 
266     if (capturerStreamMap_.size() == 0) {
267         AUDIO_INFO_LOG("Release the last stream");
268     }
269     return SUCCESS;
270 }
271 
AddUnprocessStream(int32_t appUid)272 int32_t PaAdapterManager::AddUnprocessStream(int32_t appUid)
273 {
274     unprocessAppUidSet_.insert(appUid);
275     return SUCCESS;
276 }
277 
ResetPaContext()278 int32_t PaAdapterManager::ResetPaContext()
279 {
280     AUDIO_DEBUG_LOG("Enter ResetPaContext");
281     if (context_) {
282         pa_context_set_state_callback(context_, nullptr, nullptr);
283         if (isContextConnected_ == true) {
284             PaLockGuard lock(mainLoop_);
285             pa_context_disconnect(context_);
286             pa_context_unref(context_);
287             isContextConnected_ = false;
288             context_ = nullptr;
289         }
290     }
291 
292     if (mainLoop_) {
293         pa_threaded_mainloop_free(mainLoop_);
294         isMainLoopStarted_  = false;
295         mainLoop_ = nullptr;
296     }
297 
298     api_ = nullptr;
299     return SUCCESS;
300 }
301 
InitPaContext()302 int32_t PaAdapterManager::InitPaContext()
303 {
304     AUDIO_DEBUG_LOG("Enter InitPaContext");
305     std::lock_guard<std::mutex> lock(paElementsMutex_);
306     if (context_ != nullptr) {
307         AUDIO_INFO_LOG("Context is not null, return");
308         return SUCCESS;
309     }
310     mainLoop_ = pa_threaded_mainloop_new();
311     CHECK_AND_RETURN_RET_LOG(mainLoop_ != nullptr, ERR_DEVICE_INIT, "Failed to init pa mainLoop");
312     api_ = pa_threaded_mainloop_get_api(mainLoop_);
313     if (managerType_ == PLAYBACK) {
314         pa_threaded_mainloop_set_name(mainLoop_, "OS_RendererML");
315     } else if (managerType_ == DUP_PLAYBACK) {
316         pa_threaded_mainloop_set_name(mainLoop_, "OS_DRendererML");
317     } else if (managerType_ == DUAL_PLAYBACK) {
318         pa_threaded_mainloop_set_name(mainLoop_, "OS_DualRendererML");
319     } else if (managerType_ == RECORDER) {
320         pa_threaded_mainloop_set_name(mainLoop_, "OS_CapturerML");
321     } else {
322         AUDIO_ERR_LOG("Not supported managerType:%{public}d", managerType_);
323     }
324     if (api_ == nullptr) {
325         AUDIO_ERR_LOG("Get api from mainLoop failed");
326         pa_threaded_mainloop_free(mainLoop_);
327         return ERR_DEVICE_INIT;
328     }
329 
330     std::stringstream ss;
331     ss << "app-pid<" << getpid() << ">-uid<" << getuid() << ">";
332     std::string packageName = "";
333     ss >> packageName;
334 
335     context_ = pa_context_new(api_, packageName.c_str());
336     if (context_ == nullptr) {
337         AUDIO_ERR_LOG("New context failed");
338         pa_threaded_mainloop_free(mainLoop_);
339         return ERR_DEVICE_INIT;
340     }
341 
342     pa_context_set_state_callback(context_, PAContextStateCb, mainLoop_);
343     if (pa_context_connect(context_, nullptr, PA_CONTEXT_NOFAIL, nullptr) < 0) {
344         int error = pa_context_errno(context_);
345         AUDIO_ERR_LOG("Context connect error: %{public}s", pa_strerror(error));
346         return ERR_DEVICE_INIT;
347     }
348     isContextConnected_ = true;
349     CHECK_AND_RETURN_RET_LOG(HandleMainLoopStart() == SUCCESS, ERR_DEVICE_INIT, "Failed to start pa mainLoop");
350 
351     return SUCCESS;
352 }
353 
HandleMainLoopStart()354 int32_t PaAdapterManager::HandleMainLoopStart()
355 {
356     if (pa_threaded_mainloop_start(mainLoop_) < 0) {
357         return ERR_DEVICE_INIT;
358     }
359 
360     PaLockGuard lock(mainLoop_);
361     isMainLoopStarted_ = true;
362 
363     while (true) {
364         pa_context_state_t state = pa_context_get_state(context_);
365         if (state == PA_CONTEXT_READY) {
366             AUDIO_INFO_LOG("pa context is ready");
367             break;
368         }
369 
370         if (!PA_CONTEXT_IS_GOOD(state)) {
371             int error = pa_context_errno(context_);
372             AUDIO_ERR_LOG("Context bad state error: %{public}s", pa_strerror(error));
373             lock.Unlock();
374             ResetPaContext();
375             return ERR_DEVICE_INIT;
376         }
377         pa_threaded_mainloop_wait(mainLoop_);
378     }
379     return SUCCESS;
380 }
381 
GetDeviceNameForConnect(AudioProcessConfig processConfig,uint32_t sessionId,std::string & deviceName)382 int32_t PaAdapterManager::GetDeviceNameForConnect(AudioProcessConfig processConfig, uint32_t sessionId,
383     std::string &deviceName)
384 {
385     deviceName = "";
386     if (processConfig.audioMode == AUDIO_MODE_RECORD) {
387         if (processConfig.isWakeupCapturer) {
388             int32_t ret = CoreServiceHandler::GetInstance().SetWakeUpAudioCapturerFromAudioServer(processConfig);
389             if (ret < 0) {
390                 AUDIO_ERR_LOG("ErrorCode: %{public}d", ret);
391                 return ERROR;
392             }
393             deviceName = PRIMARY_WAKEUP;
394         }
395         if (processConfig.isInnerCapturer) {
396             if (processConfig.innerCapMode == MODERN_INNER_CAP) {
397                 AUDIO_INFO_LOG("Create the modern inner-cap.");
398                 deviceName = AppendDeviceName(processConfig.innerCapId, AppendType::APPEND_CAPTURE);
399             } else {
400                 const char* innerCapturerSource = "Speaker.monitor";
401                 deviceName = innerCapturerSource;
402             }
403         } else if (processConfig.capturerInfo.sourceType == SOURCE_TYPE_REMOTE_CAST) {
404             const char* monitorSourceSuffix = ".monitor";
405             deviceName = std::string(REMOTE_CAST_INNER_CAPTURER_SINK_NAME) + std::string(monitorSourceSuffix);
406         }
407         return PolicyHandler::GetInstance().NotifyCapturerAdded(processConfig.capturerInfo,
408             processConfig.streamInfo, sessionId);
409     }
410     return SUCCESS;
411 }
412 
InitPaStream(AudioProcessConfig processConfig,uint32_t sessionId,bool isRecording)413 pa_stream *PaAdapterManager::InitPaStream(AudioProcessConfig processConfig, uint32_t sessionId, bool isRecording)
414 {
415     AUDIO_INFO_LOG("In, isInnerCapturer: %{public}d", processConfig.isInnerCapturer);
416     std::string adapterName = "";
417     if (managerType_ != DUP_PLAYBACK && managerType_ != DUAL_PLAYBACK) {
418         adapterName = CoreServiceHandler::GetInstance().GetAdapterNameBySessionId(sessionId);
419     }
420     std::lock_guard<std::mutex> lock(paElementsMutex_);
421     PaLockGuard palock(mainLoop_);
422     if (CheckReturnIfinvalid(mainLoop_ && context_, ERR_ILLEGAL_STATE) < 0) {
423         AUDIO_ERR_LOG("CheckReturnIfinvalid failed");
424         return nullptr;
425     }
426 
427     // Use struct to save spec size
428     pa_sample_spec sampleSpec = ConvertToPAAudioParams(processConfig);
429     pa_proplist *propList = pa_proplist_new();
430     CHECK_AND_RETURN_RET_LOG(propList != nullptr, nullptr, "pa_proplist_new failed");
431     const std::string streamName = GetStreamName(processConfig.streamType);
432     pa_channel_map map;
433     if (SetPaProplist(propList, map, processConfig, streamName, sessionId) != 0) {
434         AUDIO_ERR_LOG("set pa proplist failed");
435         pa_proplist_free(propList);
436         return nullptr;
437     }
438 
439     pa_stream *paStream = pa_stream_new_with_proplist(context_, streamName.c_str(), &sampleSpec,
440         isRecording ? nullptr : &map, propList);
441     if (!paStream) {
442         int32_t error = pa_context_errno(context_);
443         AUDIO_ERR_LOG("pa_stream_new_with_proplist failed, error: %{public}d", error);
444         pa_proplist_free(propList);
445         return nullptr;
446     }
447 
448     pa_proplist_free(propList);
449     pa_stream_set_state_callback(paStream, PAStreamStateCb, reinterpret_cast<void *>(this));
450     palock.Unlock();
451 
452     std::string deviceName;
453     int32_t errorCode = GetDeviceNameForConnect(processConfig, sessionId, deviceName);
454     if (errorCode != SUCCESS) {
455         AUDIO_ERR_LOG("getdevicename err: %{public}d", errorCode);
456         ReleasePaStream(paStream);
457         return nullptr;
458     }
459 
460     int32_t ret = ConnectStreamToPA(paStream, sampleSpec, processConfig.capturerInfo.sourceType,
461         processConfig.innerCapId, adapterName, deviceName);
462     if (ret < 0) {
463         AUDIO_ERR_LOG("ConnectStreamToPA failed!");
464         ReleasePaStream(paStream);
465         PolicyHandler::GetInstance().NotifyCapturerRemoved(sessionId);
466         return nullptr;
467     }
468     return paStream;
469 }
470 
ReleasePaStream(pa_stream * paStream)471 void PaAdapterManager::ReleasePaStream(pa_stream *paStream)
472 {
473     if (!paStream) {
474         AUDIO_INFO_LOG("paStream is nullptr. No need to release.");
475         return;
476     }
477     if (!mainLoop_) {
478         AUDIO_ERR_LOG("mainLoop_ is nullptr!");
479         return;
480     }
481 
482     PaLockGuard palock(mainLoop_);
483     pa_stream_set_state_callback(paStream, nullptr, nullptr);
484 
485     pa_stream_state_t state = pa_stream_get_state(paStream);
486     if (state == PA_STREAM_UNCONNECTED) {
487         AUDIO_INFO_LOG("Release paStream unconnected");
488         pa_stream_terminate(paStream);
489     }
490     pa_stream_unref(paStream);
491     AUDIO_INFO_LOG("Release paStream because of errs");
492 }
493 
CheckHighResolution(const AudioProcessConfig & processConfig)494 bool PaAdapterManager::CheckHighResolution(const AudioProcessConfig &processConfig)
495 {
496     DeviceType deviceType = processConfig.deviceType;
497     AudioStreamType streamType = processConfig.streamType;
498     AudioSamplingRate sampleRate = processConfig.streamInfo.samplingRate;
499     AudioSampleFormat sampleFormat = processConfig.streamInfo.format;
500 
501     AUDIO_DEBUG_LOG("deviceType:%{public}d, streamType:%{public}d, sampleRate:%{public}d, sampleFormat:%{public}d",
502         deviceType, streamType, sampleRate, sampleFormat);
503 
504     if (deviceType == DEVICE_TYPE_BLUETOOTH_A2DP && streamType == STREAM_MUSIC &&
505         sampleRate >= SAMPLE_RATE_48000 && sampleFormat >= SAMPLE_S24LE) {
506         return true;
507     }
508     return false;
509 }
510 
SetHighResolution(pa_proplist * propList,AudioProcessConfig & processConfig,uint32_t sessionId)511 void PaAdapterManager::SetHighResolution(pa_proplist *propList, AudioProcessConfig &processConfig, uint32_t sessionId)
512 {
513     bool spatializationEnabled = processConfig.rendererInfo.spatializationEnabled;
514     AUDIO_DEBUG_LOG("spatializationEnabled : %{public}d, isHighResolutionExist_ : %{public}d",
515         spatializationEnabled, isHighResolutionExist_);
516 
517     if (spatializationEnabled == false && isHighResolutionExist_ == false && CheckHighResolution(processConfig)) {
518         AUDIO_INFO_LOG("current stream marked as high resolution");
519         pa_proplist_sets(propList, "stream.highResolution", "1");
520         isHighResolutionExist_ = true;
521         highResolutionIndex_ = sessionId;
522     } else {
523         AUDIO_INFO_LOG("current stream marked as non-high resolution");
524         pa_proplist_sets(propList, "stream.highResolution", "0");
525     }
526 }
527 
SetPlaybackProplist(pa_proplist * propList,AudioProcessConfig & processConfig)528 void PaAdapterManager::SetPlaybackProplist(pa_proplist *propList, AudioProcessConfig &processConfig)
529 {
530         pa_proplist_sets(propList, "scene.mode",
531             processConfig.rendererInfo.effectMode == EFFECT_NONE ? "EFFECT_NONE" : "EFFECT_DEFAULT");
532         // mark dup stream for dismissing volume handle
533         std::string streamMode = managerType_ == DUP_PLAYBACK ? DUP_STREAM
534             : (managerType_ == DUAL_PLAYBACK ? DUAL_TONE_STREAM : NORMAL_STREAM);
535         pa_proplist_sets(propList, "stream.mode", streamMode.c_str());
536         pa_proplist_sets(propList, "stream.flush", "false");
537         pa_proplist_sets(propList, "stream.privacyType", std::to_string(processConfig.privacyType).c_str());
538         pa_proplist_sets(propList, "stream.usage", std::to_string(processConfig.rendererInfo.streamUsage).c_str());
539         pa_proplist_sets(propList, "scene.type", processConfig.rendererInfo.sceneType.c_str());
540         pa_proplist_sets(propList, "spatialization.enabled",
541             std::to_string(processConfig.rendererInfo.spatializationEnabled).c_str());
542         pa_proplist_sets(propList, "headtracking.enabled",
543             std::to_string(processConfig.rendererInfo.headTrackingEnabled).c_str());
544         pa_proplist_sets(propList, "expectedPlaybackDurationBytes",
545             std::to_string(processConfig.rendererInfo.expectedPlaybackDurationBytes).c_str());
546         AudioVolumeType systemVolumeType = VolumeUtils::GetVolumeTypeFromStreamType(processConfig.streamType);
547         pa_proplist_sets(propList, "systemVolume.type", std::to_string(systemVolumeType).c_str());
548 }
549 
SetRecordProplist(pa_proplist * propList,AudioProcessConfig & processConfig)550 void PaAdapterManager::SetRecordProplist(pa_proplist *propList, AudioProcessConfig &processConfig)
551 {
552     pa_proplist_sets(propList, "stream.isInnerCapturer", std::to_string(processConfig.isInnerCapturer).c_str());
553     pa_proplist_sets(propList, "stream.isWakeupCapturer", std::to_string(processConfig.isWakeupCapturer).c_str());
554     pa_proplist_sets(propList, "stream.isIpcCapturer", std::to_string(true).c_str());
555     pa_proplist_sets(propList, "stream.capturerSource",
556         std::to_string(processConfig.capturerInfo.sourceType).c_str());
557     const std::string sceneType = GetEnhanceSceneName(processConfig.capturerInfo.sourceType);
558     pa_proplist_sets(propList, "scene.type", sceneType.c_str());
559     auto item = unprocessAppUidSet_.find(processConfig.appInfo.appUid);
560     if ((item != unprocessAppUidSet_.end()) || (processConfig.capturerInfo.sourceType == SOURCE_TYPE_UNPROCESSED)) {
561         AUDIO_INFO_LOG("ByPass UID is [%{public}d]", processConfig.appInfo.appUid);
562         pa_proplist_sets(propList, "scene.bypass", "scene.bypass");
563     }
564 }
565 
SetPaProplist(pa_proplist * propList,pa_channel_map & map,AudioProcessConfig & processConfig,const std::string & streamName,uint32_t sessionId)566 int32_t PaAdapterManager::SetPaProplist(pa_proplist *propList, pa_channel_map &map, AudioProcessConfig &processConfig,
567     const std::string &streamName, uint32_t sessionId)
568 {
569     // for remote audio device router filter
570     pa_proplist_sets(propList, "stream.sessionID", std::to_string(sessionId).c_str());
571     pa_proplist_sets(propList, "stream.client.uid", std::to_string(processConfig.appInfo.appUid).c_str());
572     pa_proplist_sets(propList, "stream.client.pid", std::to_string(processConfig.appInfo.appPid).c_str());
573     pa_proplist_sets(propList, "stream.type", streamName.c_str());
574     pa_proplist_sets(propList, "media.name", streamName.c_str());
575 
576     float mVolumeFactor = 1.0f;
577     float mPowerVolumeFactor = 1.0f;
578     float mDuckVolumeFactor = 1.0f;
579     pa_proplist_sets(propList, "stream.volumeFactor", std::to_string(mVolumeFactor).c_str());
580     pa_proplist_sets(propList, "stream.powerVolumeFactor", std::to_string(mPowerVolumeFactor).c_str());
581     pa_proplist_sets(propList, "stream.duckVolumeFactor", std::to_string(mDuckVolumeFactor).c_str());
582     auto timenow = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
583     const std::string streamStartTime = ctime(&timenow);
584     pa_proplist_sets(propList, "stream.startTime", streamStartTime.c_str());
585 
586     if (processConfig.audioMode == AUDIO_MODE_PLAYBACK) {
587         SetPlaybackProplist(propList, processConfig);
588         SetHighResolution(propList, processConfig, sessionId);
589     } else if (processConfig.audioMode == AUDIO_MODE_RECORD) {
590         SetRecordProplist(propList, processConfig);
591     }
592 
593     AUDIO_INFO_LOG("Creating stream of channels %{public}d", processConfig.streamInfo.channels);
594     if (processConfig.streamInfo.channelLayout == 0) {
595         processConfig.streamInfo.channelLayout = defaultChCountToLayoutMap[processConfig.streamInfo.channels];
596     }
597     pa_proplist_sets(propList, "stream.channelLayout", std::to_string(processConfig.streamInfo.channelLayout).c_str());
598 
599     pa_channel_map_init(&map);
600     map.channels = processConfig.streamInfo.channels;
601     uint32_t channelsInLayout = ConvertChLayoutToPaChMap(processConfig.streamInfo.channelLayout, map);
602     CHECK_AND_RETURN_RET_LOG(channelsInLayout == processConfig.streamInfo.channels && channelsInLayout != 0,
603         ERR_INVALID_PARAM, "Invalid channel Layout!");
604     return SUCCESS;
605 }
606 
CreateRendererStream(AudioProcessConfig processConfig,pa_stream * paStream)607 std::shared_ptr<IRendererStream> PaAdapterManager::CreateRendererStream(AudioProcessConfig processConfig,
608     pa_stream *paStream)
609 {
610     std::lock_guard<std::mutex> lock(paElementsMutex_);
611     std::shared_ptr<PaRendererStreamImpl> rendererStream =
612         std::make_shared<PaRendererStreamImpl>(paStream, processConfig, mainLoop_);
613     if (rendererStream->InitParams() != SUCCESS) {
614         int32_t error = pa_context_errno(context_);
615         AUDIO_ERR_LOG("Create rendererStream Failed, error: %{public}d", error);
616         return nullptr;
617     }
618     return rendererStream;
619 }
620 
CreateCapturerStream(AudioProcessConfig processConfig,pa_stream * paStream)621 std::shared_ptr<ICapturerStream> PaAdapterManager::CreateCapturerStream(AudioProcessConfig processConfig,
622     pa_stream *paStream)
623 {
624     std::lock_guard<std::mutex> lock(paElementsMutex_);
625     std::shared_ptr<PaCapturerStreamImpl> capturerStream =
626         std::make_shared<PaCapturerStreamImpl>(paStream, processConfig, mainLoop_);
627     if (capturerStream->InitParams() != SUCCESS) {
628         int32_t error = pa_context_errno(context_);
629         AUDIO_ERR_LOG("Create capturerStream Failed, error: %{public}d", error);
630         return nullptr;
631     }
632     return capturerStream;
633 }
634 
ConnectStreamToPA(pa_stream * paStream,pa_sample_spec sampleSpec,SourceType source,int32_t innerCapId,std::string & adapterName,const std::string & deviceName)635 int32_t PaAdapterManager::ConnectStreamToPA(pa_stream *paStream, pa_sample_spec sampleSpec,
636     SourceType source, int32_t innerCapId, std::string &adapterName, const std::string &deviceName)
637 {
638     AUDIO_INFO_LOG("In");
639     if (CheckReturnIfinvalid(mainLoop_ && context_ && paStream, ERROR) < 0) {
640         return ERR_ILLEGAL_STATE;
641     }
642 
643     PaLockGuard lock(mainLoop_);
644     if (managerType_ == PLAYBACK || managerType_ == DUP_PLAYBACK || managerType_ == DUAL_PLAYBACK) {
645         int32_t rendererRet = ConnectRendererStreamToPA(paStream, sampleSpec, adapterName, innerCapId);
646         CHECK_AND_RETURN_RET_LOG(rendererRet == SUCCESS, rendererRet, "ConnectRendererStreamToPA failed");
647     }
648     if (managerType_ == RECORDER) {
649         int32_t capturerRet = ConnectCapturerStreamToPA(paStream, sampleSpec, adapterName, source, deviceName);
650         CHECK_AND_RETURN_RET_LOG(capturerRet == SUCCESS, capturerRet, "ConnectCapturerStreamToPA failed");
651     }
652     while (waitConnect_) {
653         pa_stream_state_t state = pa_stream_get_state(paStream);
654         if (state == PA_STREAM_READY) {
655             AUDIO_INFO_LOG("PaStream is ready");
656             break;
657         }
658         if (!PA_STREAM_IS_GOOD(state)) {
659             int32_t error = pa_context_errno(context_);
660             AUDIO_ERR_LOG("connection to stream error: %{public}s, state: %{public}d", pa_strerror(error), state);
661             return ERR_INVALID_OPERATION;
662         }
663         AudioXCollie audioXCollie("PaAdapterManager::ConnectStreamToPA", CONNECT_STREAM_TIMEOUT_IN_SEC,
664             [this](void *) {
665                 AUDIO_ERR_LOG("ConnectStreamToPA timeout");
666                 waitConnect_ = false;
667             }, nullptr, AUDIO_XCOLLIE_FLAG_LOG | AUDIO_XCOLLIE_FLAG_RECOVERY);
668         pa_threaded_mainloop_wait(mainLoop_);
669     }
670     return SUCCESS;
671 }
672 
ConnectRendererStreamToPA(pa_stream * paStream,pa_sample_spec sampleSpec,std::string & adapterName,int32_t innerCapId)673 int32_t PaAdapterManager::ConnectRendererStreamToPA(
674     pa_stream *paStream, pa_sample_spec sampleSpec, std::string &adapterName, int32_t innerCapId)
675 {
676     uint32_t tlength = 4; // 4 is tlength of playback
677     uint32_t maxlength = 4; // 4 is max buffer length of playback
678     uint32_t prebuf = 1; // 1 is prebuf of playback
679 
680     if (managerType_ == DUP_PLAYBACK || managerType_ == DUAL_PLAYBACK) {
681         maxlength = 20; // 20 for cover offload
682         prebuf = 2; // 2 is double of normal, use more prebuf for dup stream
683     }
684     AUDIO_INFO_LOG("Create ipc playback stream tlength: %{public}u, maxlength: %{public}u prebuf: %{public}u"
685         "innerCapId: %{public}d", tlength, maxlength, prebuf, innerCapId);
686     pa_buffer_attr bufferAttr;
687     bufferAttr.fragsize = static_cast<uint32_t>(-1);
688     bufferAttr.prebuf = pa_usec_to_bytes(BUF_LENGTH_IN_MSEC * PA_USEC_PER_MSEC * prebuf, &sampleSpec);
689     bufferAttr.maxlength = pa_usec_to_bytes(BUF_LENGTH_IN_MSEC * PA_USEC_PER_MSEC * maxlength, &sampleSpec);
690     bufferAttr.tlength = pa_usec_to_bytes(BUF_LENGTH_IN_MSEC * PA_USEC_PER_MSEC * tlength, &sampleSpec);
691     bufferAttr.minreq = pa_usec_to_bytes(BUF_LENGTH_IN_MSEC * PA_USEC_PER_MSEC, &sampleSpec);
692 
693     std::string dupSinkName = AppendDeviceName(innerCapId, AppendType::APPEND_RENDER);
694     const char *sinkName = nullptr;
695     if (managerType_ == DUP_PLAYBACK) {
696         sinkName = dupSinkName.c_str();
697     } else if (managerType_ == DUAL_PLAYBACK) {
698         sinkName = "Speaker";
699     } else {
700         sinkName = adapterName.c_str();
701     }
702     if (strcmp(sinkName, "") == 0) {
703         AUDIO_INFO_LOG("Sink name is null");
704         sinkName = "Speaker";
705     }
706     AUDIO_INFO_LOG("Sink name: %{public}s", sinkName);
707 
708     uint32_t flags = PA_STREAM_ADJUST_LATENCY | PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_START_CORKED |
709         PA_STREAM_VARIABLE_RATE;
710     if (managerType_ == DUP_PLAYBACK || managerType_ == DUAL_PLAYBACK) {
711         flags |= PA_STREAM_DONT_MOVE; // should not move dup streams
712     }
713     int32_t result = pa_stream_connect_playback(paStream, sinkName, &bufferAttr, static_cast<pa_stream_flags_t>(flags),
714         nullptr, nullptr);
715     if (result < 0) {
716         int32_t error = pa_context_errno(context_);
717         AUDIO_ERR_LOG("connection to stream error: %{public}d -- %{public}s,result:%{public}d", error,
718             pa_strerror(error), result);
719         return ERR_INVALID_OPERATION;
720     }
721     return SUCCESS;
722 }
723 
ConnectCapturerStreamToPA(pa_stream * paStream,pa_sample_spec sampleSpec,std::string & adapterName,SourceType source,const std::string & deviceName)724 int32_t PaAdapterManager::ConnectCapturerStreamToPA(pa_stream *paStream, pa_sample_spec sampleSpec,
725     std::string &adapterName, SourceType source, const std::string &deviceName)
726 {
727     uint32_t fragsize = 1; // 1 is frag size of recorder
728     uint32_t maxlength = (source == SOURCE_TYPE_WAKEUP) ? PA_RECORD_MAX_LENGTH_WAKEUP : PA_RECORD_MAX_LENGTH_NORMAL;
729     pa_buffer_attr bufferAttr;
730     bufferAttr.maxlength = pa_usec_to_bytes(BUF_LENGTH_IN_MSEC * PA_USEC_PER_MSEC * maxlength, &sampleSpec);
731     bufferAttr.fragsize = pa_usec_to_bytes(BUF_LENGTH_IN_MSEC * PA_USEC_PER_MSEC * fragsize, &sampleSpec);
732     AUDIO_INFO_LOG("bufferAttr, maxLength: %{public}d, fragsize: %{public}d",
733         bufferAttr.maxlength, bufferAttr.fragsize);
734 
735     const char *cDeviceName = "Built_in_mic";
736     if (source == SOURCE_TYPE_PLAYBACK_CAPTURE || source == SOURCE_TYPE_REMOTE_CAST) {
737         cDeviceName = deviceName.c_str();
738     } else {
739         cDeviceName = adapterName.c_str();
740     }
741     AUDIO_INFO_LOG("Source name: %{public}s", cDeviceName);
742 
743     uint32_t flags = PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_START_CORKED | PA_STREAM_VARIABLE_RATE;
744     if (source == SOURCE_TYPE_PLAYBACK_CAPTURE) {
745         flags |= PA_STREAM_DONT_MOVE; //inner cap source-output,should not be moved!
746     }
747     int32_t result = pa_stream_connect_record(paStream, cDeviceName, &bufferAttr,
748         static_cast<pa_stream_flags_t>(flags));
749     // PA_STREAM_ADJUST_LATENCY exist, return peek length from server;
750     if (result < 0) {
751         int32_t error = pa_context_errno(context_);
752         AUDIO_ERR_LOG("connection to stream error: %{public}d -- %{public}s,result:%{public}d", error,
753             pa_strerror(error), result);
754         return ERR_INVALID_OPERATION;
755     }
756     return SUCCESS;
757 }
758 
PAStreamUpdateStreamIndexSuccessCb(pa_stream * stream,int32_t success,void * userdata)759 void PaAdapterManager::PAStreamUpdateStreamIndexSuccessCb(pa_stream *stream, int32_t success, void *userdata)
760 {
761     AUDIO_DEBUG_LOG("PAStreamUpdateStreamIndexSuccessCb in");
762 }
763 
PAContextStateCb(pa_context * context,void * userdata)764 void PaAdapterManager::PAContextStateCb(pa_context *context, void *userdata)
765 {
766     pa_threaded_mainloop *mainLoop = reinterpret_cast<pa_threaded_mainloop *>(userdata);
767     AUDIO_INFO_LOG("Current Context State: %{public}d", pa_context_get_state(context));
768     ScheduleThreadInServer(getpid(), gettid());
769 
770     switch (pa_context_get_state(context)) {
771         case PA_CONTEXT_READY:
772             pa_threaded_mainloop_signal(mainLoop, 0);
773             break;
774         case PA_CONTEXT_TERMINATED:
775         case PA_CONTEXT_FAILED:
776             pa_threaded_mainloop_signal(mainLoop, 0);
777             break;
778 
779         case PA_CONTEXT_UNCONNECTED:
780         case PA_CONTEXT_CONNECTING:
781         case PA_CONTEXT_AUTHORIZING:
782         case PA_CONTEXT_SETTING_NAME:
783         default:
784             break;
785     }
786 }
787 
PAStreamStateCb(pa_stream * stream,void * userdata)788 void PaAdapterManager::PAStreamStateCb(pa_stream *stream, void *userdata)
789 {
790     if (!userdata) {
791         AUDIO_ERR_LOG("PAStreamStateCb: userdata is null");
792         return;
793     }
794     PaAdapterManager *adapterManger = reinterpret_cast<PaAdapterManager *>(userdata);
795     AUDIO_INFO_LOG("Current Stream State: %{public}d", pa_stream_get_state(stream));
796     switch (pa_stream_get_state(stream)) {
797         case PA_STREAM_READY:
798         case PA_STREAM_FAILED:
799         case PA_STREAM_TERMINATED:
800             pa_threaded_mainloop_signal(adapterManger->mainLoop_, 0);
801             break;
802         case PA_STREAM_UNCONNECTED:
803         case PA_STREAM_CREATING:
804         default:
805             break;
806     }
807 }
808 
GetStreamName(AudioStreamType audioType)809 const std::string PaAdapterManager::GetStreamName(AudioStreamType audioType)
810 {
811     std::string name = "unknown";
812     if (STREAM_TYPE_ENUM_STRING_MAP.find(audioType) != STREAM_TYPE_ENUM_STRING_MAP.end()) {
813         name = STREAM_TYPE_ENUM_STRING_MAP.at(audioType);
814     } else {
815         AUDIO_ERR_LOG("GetStreamName: Invalid stream type [%{public}d], return unknown", audioType);
816     }
817     const std::string streamName = name;
818     return streamName;
819 }
820 
ConvertToPAAudioParams(AudioProcessConfig processConfig)821 pa_sample_spec PaAdapterManager::ConvertToPAAudioParams(AudioProcessConfig processConfig)
822 {
823     pa_sample_spec paSampleSpec;
824     paSampleSpec.channels = processConfig.streamInfo.channels;
825     paSampleSpec.rate = processConfig.streamInfo.samplingRate;
826     switch (processConfig.streamInfo.format) {
827         case SAMPLE_U8:
828             paSampleSpec.format = (pa_sample_format_t)PA_SAMPLE_U8;
829             break;
830         case SAMPLE_S16LE:
831             paSampleSpec.format = (pa_sample_format_t)PA_SAMPLE_S16LE;
832             break;
833         case SAMPLE_S24LE:
834             paSampleSpec.format = (pa_sample_format_t)PA_SAMPLE_S24LE;
835             break;
836         case SAMPLE_S32LE:
837             paSampleSpec.format = (pa_sample_format_t)PA_SAMPLE_S32LE;
838             break;
839         case SAMPLE_F32LE:
840             paSampleSpec.format = (pa_sample_format_t)PA_SAMPLE_FLOAT32LE;
841             break;
842         default:
843             paSampleSpec.format = (pa_sample_format_t)PA_SAMPLE_INVALID;
844             break;
845     }
846     return paSampleSpec;
847 }
848 
849 
ConvertChLayoutToPaChMap(const uint64_t & channelLayout,pa_channel_map & paMap)850 uint32_t PaAdapterManager::ConvertChLayoutToPaChMap(const uint64_t &channelLayout, pa_channel_map &paMap)
851 {
852     if (channelLayout == CH_LAYOUT_MONO) {
853         pa_channel_map_init_mono(&paMap);
854         return AudioChannel::MONO;
855     }
856     uint32_t channelNum = 0;
857     uint64_t mode = (channelLayout & CH_MODE_MASK) >> CH_MODE_OFFSET;
858     switch (mode) {
859         case 0: {
860             for (auto bit = chSetToPaPositionMap.begin(); bit != chSetToPaPositionMap.end(); ++bit) {
861                 if (channelNum >= PA_CHANNELS_MAX) {
862                     return 0;
863                 }
864                 if ((channelLayout & (bit->first)) != 0) {
865                     paMap.map[channelNum++] = bit->second;
866                 }
867             }
868             break;
869         }
870         case 1: {
871             uint64_t order = (channelLayout & CH_HOA_ORDNUM_MASK) >> CH_HOA_ORDNUM_OFFSET;
872             channelNum = (order + 1) * (order + 1);
873             if (channelNum > PA_CHANNELS_MAX) {
874                 return 0;
875             }
876             for (uint32_t i = 0; i < channelNum; ++i) {
877                 paMap.map[i] = chSetToPaPositionMap[FRONT_LEFT];
878             }
879             break;
880         }
881         default:
882             channelNum = 0;
883             break;
884     }
885     return channelNum;
886 }
887 
GetEnhanceSceneName(SourceType sourceType)888 const std::string PaAdapterManager::GetEnhanceSceneName(SourceType sourceType)
889 {
890     std::string name;
891     switch (sourceType) {
892         case SOURCE_TYPE_MIC:
893         case SOURCE_TYPE_CAMCORDER:
894             name = "SCENE_RECORD";
895             break;
896         case SOURCE_TYPE_VOICE_CALL:
897         case SOURCE_TYPE_VOICE_COMMUNICATION:
898             name = "SCENE_VOIP_UP";
899             break;
900         case SOURCE_TYPE_VOICE_TRANSCRIPTION:
901             name = "SCENE_PRE_ENHANCE";
902             break;
903         case SOURCE_TYPE_VOICE_MESSAGE:
904             name = "SCENE_VOICE_MESSAGE";
905             break;
906         default:
907             name = "SCENE_OTHERS";
908     }
909     const std::string sceneName = name;
910     return sceneName;
911 }
912 
GetLatency()913 uint64_t PaAdapterManager::GetLatency() noexcept
914 {
915     return 0;
916 }
917 // 连接时拼接上内录ID
AppendDeviceName(int32_t innerCapId,AppendType type)918 std::string PaAdapterManager::AppendDeviceName(int32_t innerCapId, AppendType type)
919 {
920     if (type == AppendType::APPEND_CAPTURE) {
921         std::string tempDevName(INNER_CAPTURER_SINK);
922         return tempDevName + std::to_string(innerCapId) + ".monitor";
923     } else {
924         return std::string(INNER_CAPTURER_SINK) + std::to_string(innerCapId);
925     }
926 }
927 
928 } // namespace AudioStandard
929 } // namespace OHOS
930 #endif // SUPPORT_OLD_ENGINE