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