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
SetRecordProplist(pa_proplist * propList,AudioProcessConfig & processConfig)515 void PaAdapterManager::SetRecordProplist(pa_proplist *propList, AudioProcessConfig &processConfig)
516 {
517 pa_proplist_sets(propList, "stream.isInnerCapturer", std::to_string(processConfig.isInnerCapturer).c_str());
518 pa_proplist_sets(propList, "stream.isWakeupCapturer", std::to_string(processConfig.isWakeupCapturer).c_str());
519 pa_proplist_sets(propList, "stream.isIpcCapturer", std::to_string(true).c_str());
520 pa_proplist_sets(propList, "stream.capturerSource",
521 std::to_string(processConfig.capturerInfo.sourceType).c_str());
522 pa_proplist_sets(propList, "scene.type", GetEnhanceSceneName(processConfig.capturerInfo.sourceType).c_str());
523 enhanceMode_ = IsEnhanceMode(processConfig.capturerInfo.sourceType) ? EFFECT_DEFAULT : EFFECT_NONE;
524 pa_proplist_sets(propList, "scene.mode", GetEnhanceModeName(enhanceMode_).c_str());
525 if (processConfig.capturerInfo.sourceType == SOURCE_TYPE_UNPROCESSED) {
526 AUDIO_INFO_LOG("ByPass UID is [%{public}d]", processConfig.appInfo.appUid);
527 pa_proplist_sets(propList, "scene.bypass", "scene.bypass");
528 }
529 }
530
SetPaProplist(pa_proplist * propList,pa_channel_map & map,AudioProcessConfig & processConfig,const std::string & streamName,uint32_t sessionId)531 int32_t PaAdapterManager::SetPaProplist(pa_proplist *propList, pa_channel_map &map, AudioProcessConfig &processConfig,
532 const std::string &streamName, uint32_t sessionId)
533 {
534 // for remote audio device router filter
535 pa_proplist_sets(propList, "stream.sessionID", std::to_string(sessionId).c_str());
536 pa_proplist_sets(propList, "stream.client.uid", std::to_string(processConfig.appInfo.appUid).c_str());
537 pa_proplist_sets(propList, "stream.client.pid", std::to_string(processConfig.appInfo.appPid).c_str());
538 pa_proplist_sets(propList, "stream.type", streamName.c_str());
539 pa_proplist_sets(propList, "media.name", streamName.c_str());
540
541 float mVolumeFactor = 1.0f;
542 float mPowerVolumeFactor = 1.0f;
543 float mDuckVolumeFactor = 1.0f;
544 pa_proplist_sets(propList, "stream.volumeFactor", std::to_string(mVolumeFactor).c_str());
545 pa_proplist_sets(propList, "stream.powerVolumeFactor", std::to_string(mPowerVolumeFactor).c_str());
546 pa_proplist_sets(propList, "stream.duckVolumeFactor", std::to_string(mDuckVolumeFactor).c_str());
547 auto timenow = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
548 const std::string streamStartTime = ctime(&timenow);
549 pa_proplist_sets(propList, "stream.startTime", streamStartTime.c_str());
550
551 if (processConfig.audioMode == AUDIO_MODE_PLAYBACK) {
552 pa_proplist_sets(propList, "scene.mode",
553 IsEffectNone(processConfig.rendererInfo.streamUsage) ? "EFFECT_NONE" : "EFFECT_DEFAULT");
554 // mark dup stream for dismissing volume handle
555 std::string streamMode = managerType_ == DUP_PLAYBACK ? DUP_STREAM
556 : (managerType_ == DUAL_PLAYBACK ? DUAL_TONE_STREAM : NORMAL_STREAM);
557 pa_proplist_sets(propList, "stream.mode", streamMode.c_str());
558 pa_proplist_sets(propList, "stream.flush", "false");
559 pa_proplist_sets(propList, "spatialization.enabled", "0");
560 pa_proplist_sets(propList, "stream.privacyType", std::to_string(processConfig.privacyType).c_str());
561 pa_proplist_sets(propList, "stream.usage", std::to_string(processConfig.rendererInfo.streamUsage).c_str());
562 pa_proplist_sets(propList, "scene.type", processConfig.rendererInfo.sceneType.c_str());
563 pa_proplist_sets(propList, "stream.usage", std::to_string(processConfig.rendererInfo.streamUsage).c_str());
564 pa_proplist_sets(propList, "spatialization.enabled",
565 std::to_string(processConfig.rendererInfo.spatializationEnabled).c_str());
566 pa_proplist_sets(propList, "headtracking.enabled",
567 std::to_string(processConfig.rendererInfo.headTrackingEnabled).c_str());
568 AudioVolumeType systemVolumeType = VolumeUtils::GetVolumeTypeFromStreamType(processConfig.streamType);
569 pa_proplist_sets(propList, "systemVolume.type", std::to_string(systemVolumeType).c_str());
570 SetHighResolution(propList, processConfig, sessionId);
571 } else if (processConfig.audioMode == AUDIO_MODE_RECORD) {
572 SetRecordProplist(propList, processConfig);
573 }
574
575 AUDIO_INFO_LOG("Creating stream of channels %{public}d", processConfig.streamInfo.channels);
576 if (processConfig.streamInfo.channelLayout == 0) {
577 processConfig.streamInfo.channelLayout = defaultChCountToLayoutMap[processConfig.streamInfo.channels];
578 }
579 pa_proplist_sets(propList, "stream.channelLayout", std::to_string(processConfig.streamInfo.channelLayout).c_str());
580
581 pa_channel_map_init(&map);
582 map.channels = processConfig.streamInfo.channels;
583 uint32_t channelsInLayout = ConvertChLayoutToPaChMap(processConfig.streamInfo.channelLayout, map);
584 CHECK_AND_RETURN_RET_LOG(channelsInLayout == processConfig.streamInfo.channels && channelsInLayout != 0,
585 ERR_INVALID_PARAM, "Invalid channel Layout");
586 return SUCCESS;
587 }
588
CreateRendererStream(AudioProcessConfig processConfig,pa_stream * paStream)589 std::shared_ptr<IRendererStream> PaAdapterManager::CreateRendererStream(AudioProcessConfig processConfig,
590 pa_stream *paStream)
591 {
592 std::lock_guard<std::mutex> lock(paElementsMutex_);
593 std::shared_ptr<PaRendererStreamImpl> rendererStream =
594 std::make_shared<PaRendererStreamImpl>(paStream, processConfig, mainLoop_);
595 if (rendererStream->InitParams() != SUCCESS) {
596 int32_t error = pa_context_errno(context_);
597 AUDIO_ERR_LOG("Create rendererStream Failed, error: %{public}d", error);
598 return nullptr;
599 }
600 return rendererStream;
601 }
602
CreateCapturerStream(AudioProcessConfig processConfig,pa_stream * paStream)603 std::shared_ptr<ICapturerStream> PaAdapterManager::CreateCapturerStream(AudioProcessConfig processConfig,
604 pa_stream *paStream)
605 {
606 std::lock_guard<std::mutex> lock(paElementsMutex_);
607 std::shared_ptr<PaCapturerStreamImpl> capturerStream =
608 std::make_shared<PaCapturerStreamImpl>(paStream, processConfig, mainLoop_);
609 if (capturerStream->InitParams() != SUCCESS) {
610 int32_t error = pa_context_errno(context_);
611 AUDIO_ERR_LOG("Create capturerStream Failed, error: %{public}d", error);
612 return nullptr;
613 }
614 return capturerStream;
615 }
616
ConnectStreamToPA(pa_stream * paStream,pa_sample_spec sampleSpec,SourceType source,const std::string & deviceName)617 int32_t PaAdapterManager::ConnectStreamToPA(pa_stream *paStream, pa_sample_spec sampleSpec,
618 SourceType source, const std::string &deviceName)
619 {
620 AUDIO_DEBUG_LOG("Enter PaAdapterManager::ConnectStreamToPA");
621 if (CheckReturnIfinvalid(mainLoop_ && context_ && paStream, ERROR) < 0) {
622 return ERR_ILLEGAL_STATE;
623 }
624
625 PaLockGuard lock(mainLoop_);
626 int32_t XcollieFlag = 1; // flag 1 generate log file
627 if (managerType_ == PLAYBACK || managerType_ == DUP_PLAYBACK || managerType_ == DUAL_PLAYBACK) {
628 int32_t rendererRet = ConnectRendererStreamToPA(paStream, sampleSpec);
629 CHECK_AND_RETURN_RET_LOG(rendererRet == SUCCESS, rendererRet, "ConnectRendererStreamToPA failed");
630 }
631 if (managerType_ == RECORDER) {
632 XcollieFlag = (1 | 2); // flag 1 generate log file, flag 2 die when timeout, restart server
633 int32_t capturerRet = ConnectCapturerStreamToPA(paStream, sampleSpec, source, deviceName);
634 CHECK_AND_RETURN_RET_LOG(capturerRet == SUCCESS, capturerRet, "ConnectCapturerStreamToPA failed");
635 }
636 while (waitConnect_) {
637 pa_stream_state_t state = pa_stream_get_state(paStream);
638 if (state == PA_STREAM_READY) {
639 AUDIO_INFO_LOG("PaStream is ready");
640 break;
641 }
642 if (!PA_STREAM_IS_GOOD(state)) {
643 int32_t error = pa_context_errno(context_);
644 AUDIO_ERR_LOG("connection to stream error: %{public}s, state: %{public}d", pa_strerror(error), state);
645 return ERR_INVALID_OPERATION;
646 }
647 AudioXCollie audioXCollie("PaAdapterManager::ConnectStreamToPA", CONNECT_STREAM_TIMEOUT_IN_SEC,
648 [this](void *) {
649 AUDIO_ERR_LOG("ConnectStreamToPA timeout");
650 waitConnect_ = false;
651 }, nullptr, XcollieFlag);
652 pa_threaded_mainloop_wait(mainLoop_);
653 }
654 return SUCCESS;
655 }
656
ConnectRendererStreamToPA(pa_stream * paStream,pa_sample_spec sampleSpec)657 int32_t PaAdapterManager::ConnectRendererStreamToPA(pa_stream *paStream, pa_sample_spec sampleSpec)
658 {
659 uint32_t tlength = 4; // 4 is tlength of playback
660 uint32_t maxlength = 4; // 4 is max buffer length of playback
661 uint32_t prebuf = 1; // 1 is prebuf of playback
662
663 if (managerType_ == DUP_PLAYBACK || managerType_ == DUAL_PLAYBACK) {
664 maxlength = 20; // 20 for cover offload
665 prebuf = 2; // 2 is double of normal, use more prebuf for dup stream
666 }
667 AUDIO_INFO_LOG("Create ipc playback stream tlength: %{public}u, maxlength: %{public}u prebuf: %{public}u", tlength,
668 maxlength, prebuf);
669 pa_buffer_attr bufferAttr;
670 bufferAttr.fragsize = static_cast<uint32_t>(-1);
671 bufferAttr.prebuf = pa_usec_to_bytes(BUF_LENGTH_IN_MSEC * PA_USEC_PER_MSEC * prebuf, &sampleSpec);
672 bufferAttr.maxlength = pa_usec_to_bytes(BUF_LENGTH_IN_MSEC * PA_USEC_PER_MSEC * maxlength, &sampleSpec);
673 bufferAttr.tlength = pa_usec_to_bytes(BUF_LENGTH_IN_MSEC * PA_USEC_PER_MSEC * tlength, &sampleSpec);
674 bufferAttr.minreq = pa_usec_to_bytes(BUF_LENGTH_IN_MSEC * PA_USEC_PER_MSEC, &sampleSpec);
675
676 const char *sinkName = managerType_ == DUP_PLAYBACK ? INNER_CAPTURER_SINK.c_str() :
677 (managerType_ == DUAL_PLAYBACK ? "Speaker" : nullptr);
678 uint32_t flags = PA_STREAM_ADJUST_LATENCY | PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_START_CORKED |
679 PA_STREAM_VARIABLE_RATE;
680 if (managerType_ == DUP_PLAYBACK || managerType_ == DUAL_PLAYBACK) {
681 flags |= PA_STREAM_DONT_MOVE; // should not move dup streams
682 }
683 int32_t result = pa_stream_connect_playback(paStream, sinkName, &bufferAttr, static_cast<pa_stream_flags_t>(flags),
684 nullptr, nullptr);
685 if (result < 0) {
686 int32_t error = pa_context_errno(context_);
687 AUDIO_ERR_LOG("connection to stream error: %{public}d -- %{public}s,result:%{public}d", error,
688 pa_strerror(error), result);
689 return ERR_INVALID_OPERATION;
690 }
691 return SUCCESS;
692 }
693
ConnectCapturerStreamToPA(pa_stream * paStream,pa_sample_spec sampleSpec,SourceType source,const std::string & deviceName)694 int32_t PaAdapterManager::ConnectCapturerStreamToPA(pa_stream *paStream, pa_sample_spec sampleSpec,
695 SourceType source, const std::string &deviceName)
696 {
697 uint32_t fragsize = 1; // 1 is frag size of recorder
698 uint32_t maxlength = (source == SOURCE_TYPE_WAKEUP) ? PA_RECORD_MAX_LENGTH_WAKEUP : PA_RECORD_MAX_LENGTH_NORMAL;
699 pa_buffer_attr bufferAttr;
700 bufferAttr.maxlength = pa_usec_to_bytes(BUF_LENGTH_IN_MSEC * PA_USEC_PER_MSEC * maxlength, &sampleSpec);
701 bufferAttr.fragsize = pa_usec_to_bytes(BUF_LENGTH_IN_MSEC * PA_USEC_PER_MSEC * fragsize, &sampleSpec);
702 AUDIO_INFO_LOG("bufferAttr, maxLength: %{public}d, fragsize: %{public}d",
703 bufferAttr.maxlength, bufferAttr.fragsize);
704
705 const char *cDeviceName = (deviceName == "") ? nullptr : deviceName.c_str();
706
707 uint32_t flags = PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_START_CORKED | PA_STREAM_VARIABLE_RATE;
708 if (source == SOURCE_TYPE_PLAYBACK_CAPTURE) {
709 flags |= PA_STREAM_DONT_MOVE; //inner cap source-output,should not be moved!
710 }
711 int32_t result = pa_stream_connect_record(paStream, cDeviceName, &bufferAttr,
712 static_cast<pa_stream_flags_t>(flags));
713 // PA_STREAM_ADJUST_LATENCY exist, return peek length from server;
714 if (result < 0) {
715 int32_t error = pa_context_errno(context_);
716 AUDIO_ERR_LOG("connection to stream error: %{public}d -- %{public}s,result:%{public}d", error,
717 pa_strerror(error), result);
718 return ERR_INVALID_OPERATION;
719 }
720 return SUCCESS;
721 }
722
SetStreamAudioEnhanceMode(pa_stream * paStream,AudioEffectMode audioEnhanceMode)723 int32_t PaAdapterManager::SetStreamAudioEnhanceMode(pa_stream *paStream, AudioEffectMode audioEnhanceMode)
724 {
725 PaLockGuard lock(mainLoop_);
726 pa_proplist *propList = pa_proplist_new();
727 if (propList == nullptr) {
728 AUDIO_ERR_LOG("pa_proplist_new failed.");
729 return ERROR;
730 }
731 std::string upDevice = "DEVICE_TYPE_MIC";
732 std::string downDevice = "DEVICE_TYPE_SPEAKER";
733 std::string upAndDownDevice = upDevice + "_&_" + downDevice;
734 pa_proplist_sets(propList, "device.upAndDown", upAndDownDevice.c_str());
735 pa_operation *updatePropOperation = pa_stream_proplist_update(paStream, PA_UPDATE_REPLACE, propList,
736 nullptr, nullptr);
737 if (updatePropOperation == nullptr) {
738 AUDIO_ERR_LOG("pa_stream_proplist_update failed.");
739 return ERROR;
740 }
741 pa_proplist_free(propList);
742 pa_operation_unref(updatePropOperation);
743 return SUCCESS;
744 }
745
GetEnhanceModeName(AudioEffectMode audioEnhanceMode)746 const std::string PaAdapterManager::GetEnhanceModeName(AudioEffectMode audioEnhanceMode)
747 {
748 std::string name;
749 switch (audioEnhanceMode) {
750 case AudioEffectMode::EFFECT_NONE:
751 name = "EFFECT_NONE";
752 break;
753 case AudioEffectMode::EFFECT_DEFAULT:
754 name = "EFFECT_DEFAULT";
755 break;
756 default:
757 name = "EFFECT_DEFAULT";
758 break;
759 }
760 const std::string modeName = name;
761 return modeName;
762 }
763
PAStreamUpdateStreamIndexSuccessCb(pa_stream * stream,int32_t success,void * userdata)764 void PaAdapterManager::PAStreamUpdateStreamIndexSuccessCb(pa_stream *stream, int32_t success, void *userdata)
765 {
766 AUDIO_DEBUG_LOG("PAStreamUpdateStreamIndexSuccessCb in");
767 }
768
PAContextStateCb(pa_context * context,void * userdata)769 void PaAdapterManager::PAContextStateCb(pa_context *context, void *userdata)
770 {
771 pa_threaded_mainloop *mainLoop = reinterpret_cast<pa_threaded_mainloop *>(userdata);
772 AUDIO_INFO_LOG("Current Context State: %{public}d", pa_context_get_state(context));
773 ScheduleThreadInServer(getpid(), gettid());
774
775 switch (pa_context_get_state(context)) {
776 case PA_CONTEXT_READY:
777 pa_threaded_mainloop_signal(mainLoop, 0);
778 break;
779 case PA_CONTEXT_TERMINATED:
780 case PA_CONTEXT_FAILED:
781 pa_threaded_mainloop_signal(mainLoop, 0);
782 break;
783
784 case PA_CONTEXT_UNCONNECTED:
785 case PA_CONTEXT_CONNECTING:
786 case PA_CONTEXT_AUTHORIZING:
787 case PA_CONTEXT_SETTING_NAME:
788 default:
789 break;
790 }
791 }
792
PAStreamStateCb(pa_stream * stream,void * userdata)793 void PaAdapterManager::PAStreamStateCb(pa_stream *stream, void *userdata)
794 {
795 if (!userdata) {
796 AUDIO_ERR_LOG("PAStreamStateCb: userdata is null");
797 return;
798 }
799 PaAdapterManager *adapterManger = reinterpret_cast<PaAdapterManager *>(userdata);
800 AUDIO_INFO_LOG("Current Stream State: %{public}d", pa_stream_get_state(stream));
801 switch (pa_stream_get_state(stream)) {
802 case PA_STREAM_READY:
803 case PA_STREAM_FAILED:
804 case PA_STREAM_TERMINATED:
805 pa_threaded_mainloop_signal(adapterManger->mainLoop_, 0);
806 break;
807 case PA_STREAM_UNCONNECTED:
808 case PA_STREAM_CREATING:
809 default:
810 break;
811 }
812 }
813
GetStreamName(AudioStreamType audioType)814 const std::string PaAdapterManager::GetStreamName(AudioStreamType audioType)
815 {
816 std::string name = "unknown";
817 if (STREAM_TYPE_ENUM_STRING_MAP.find(audioType) != STREAM_TYPE_ENUM_STRING_MAP.end()) {
818 name = STREAM_TYPE_ENUM_STRING_MAP.at(audioType);
819 } else {
820 AUDIO_ERR_LOG("GetStreamName: Invalid stream type [%{public}d], return unknown", audioType);
821 }
822 const std::string streamName = name;
823 return streamName;
824 }
825
ConvertToPAAudioParams(AudioProcessConfig processConfig)826 pa_sample_spec PaAdapterManager::ConvertToPAAudioParams(AudioProcessConfig processConfig)
827 {
828 pa_sample_spec paSampleSpec;
829 paSampleSpec.channels = processConfig.streamInfo.channels;
830 paSampleSpec.rate = processConfig.streamInfo.samplingRate;
831 switch (processConfig.streamInfo.format) {
832 case SAMPLE_U8:
833 paSampleSpec.format = (pa_sample_format_t)PA_SAMPLE_U8;
834 break;
835 case SAMPLE_S16LE:
836 paSampleSpec.format = (pa_sample_format_t)PA_SAMPLE_S16LE;
837 break;
838 case SAMPLE_S24LE:
839 paSampleSpec.format = (pa_sample_format_t)PA_SAMPLE_S24LE;
840 break;
841 case SAMPLE_S32LE:
842 paSampleSpec.format = (pa_sample_format_t)PA_SAMPLE_S32LE;
843 break;
844 default:
845 paSampleSpec.format = (pa_sample_format_t)PA_SAMPLE_INVALID;
846 break;
847 }
848 return paSampleSpec;
849 }
850
851
ConvertChLayoutToPaChMap(const uint64_t & channelLayout,pa_channel_map & paMap)852 uint32_t PaAdapterManager::ConvertChLayoutToPaChMap(const uint64_t &channelLayout, pa_channel_map &paMap)
853 {
854 if (channelLayout == CH_LAYOUT_MONO) {
855 pa_channel_map_init_mono(&paMap);
856 return AudioChannel::MONO;
857 }
858 uint32_t channelNum = 0;
859 uint64_t mode = (channelLayout & CH_MODE_MASK) >> CH_MODE_OFFSET;
860 switch (mode) {
861 case 0: {
862 for (auto bit = chSetToPaPositionMap.begin(); bit != chSetToPaPositionMap.end(); ++bit) {
863 if (channelNum >= PA_CHANNELS_MAX) {
864 return 0;
865 }
866 if ((channelLayout & (bit->first)) != 0) {
867 paMap.map[channelNum++] = bit->second;
868 }
869 }
870 break;
871 }
872 case 1: {
873 uint64_t order = (channelLayout & CH_HOA_ORDNUM_MASK) >> CH_HOA_ORDNUM_OFFSET;
874 channelNum = (order + 1) * (order + 1);
875 if (channelNum > PA_CHANNELS_MAX) {
876 return 0;
877 }
878 for (uint32_t i = 0; i < channelNum; ++i) {
879 paMap.map[i] = chSetToPaPositionMap[FRONT_LEFT];
880 }
881 break;
882 }
883 default:
884 channelNum = 0;
885 break;
886 }
887 return channelNum;
888 }
889
GetEnhanceSceneName(SourceType sourceType)890 const std::string PaAdapterManager::GetEnhanceSceneName(SourceType sourceType)
891 {
892 std::string name;
893 switch (sourceType) {
894 case SOURCE_TYPE_MIC:
895 case SOURCE_TYPE_CAMCORDER:
896 name = "SCENE_RECORD";
897 break;
898 case SOURCE_TYPE_VOICE_CALL:
899 case SOURCE_TYPE_VOICE_COMMUNICATION:
900 name = "SCENE_VOIP_3A";
901 break;
902 default:
903 name = "SCENE_OTHERS";
904 }
905 const std::string sceneName = name;
906 return sceneName;
907 }
908
909 } // namespace AudioStandard
910 } // namespace OHOS
911