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