1 /*
2 * Copyright (c) 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 "AudioLoopback"
17 #endif
18
19 #include "audio_loopback_private.h"
20 #include "audio_manager_log.h"
21 #include "audio_errors.h"
22 #include "audio_stream_info.h"
23 #include "audio_policy_manager.h"
24 #include "securec.h"
25 #include "access_token.h"
26 #include "accesstoken_kit.h"
27 #include "ipc_skeleton.h"
28 #include "audio_utils.h"
29 namespace OHOS {
30 namespace AudioStandard {
31 namespace {
32 const int32_t VALUE_HUNDRED = 100;
33 const std::map<AudioLoopbackReverbPreset, std::string> audioLoopbackReverbPresetMap = {
34 {REVERB_PRESET_ORIGINAL, "disable"},
35 {REVERB_PRESET_KTV, "ktv"},
36 {REVERB_PRESET_THEATRE, "theatre"},
37 {REVERB_PRESET_CONCERT, "concert"},
38 };
39 const std::map<AudioLoopbackEqualizerPreset, std::string> audioLoopbackEqualizerPresetMap = {
40 {EQUALIZER_PRESET_FLAT, "disable"},
41 {EQUALIZER_PRESET_FULL, "full"},
42 {EQUALIZER_PRESET_BRIGHT, "bright"},
43 };
44 }
45
CreateAudioLoopback(AudioLoopbackMode mode,const AppInfo & appInfo)46 std::shared_ptr<AudioLoopback> AudioLoopback::CreateAudioLoopback(AudioLoopbackMode mode, const AppInfo &appInfo)
47 {
48 Security::AccessToken::AccessTokenID tokenId = appInfo.appTokenId;
49 tokenId = (tokenId == Security::AccessToken::INVALID_TOKENID) ? IPCSkeleton::GetCallingTokenID() : tokenId;
50 int res = Security::AccessToken::AccessTokenKit::VerifyAccessToken(tokenId, MICROPHONE_PERMISSION);
51 CHECK_AND_RETURN_RET_LOG(res == Security::AccessToken::PermissionState::PERMISSION_GRANTED,
52 nullptr, "Permission denied [tid:%{public}d]", tokenId);
53 static std::shared_ptr<AudioLoopback> instance = std::make_shared<AudioLoopbackPrivate>(mode, appInfo);
54 return instance;
55 }
56
AudioLoopbackPrivate(AudioLoopbackMode mode,const AppInfo & appInfo)57 AudioLoopbackPrivate::AudioLoopbackPrivate(AudioLoopbackMode mode, const AppInfo &appInfo)
58 {
59 appInfo_ = appInfo;
60 if (appInfo_.appPid == 0) {
61 appInfo_.appPid = getpid();
62 }
63
64 if (appInfo_.appUid < 0) {
65 appInfo_.appUid = static_cast<int32_t>(getuid());
66 }
67 mode_ = mode;
68 karaokeParams_["Karaoke_enable"] = "disable";
69 karaokeParams_["Karaoke_reverb_mode"] = "theatre";
70 karaokeParams_["Karaoke_eq_mode"] = "full";
71 karaokeParams_["Karaoke_volume"] = "50";
72 rendererOptions_ = GenerateRendererConfig();
73 capturerOptions_ = GenerateCapturerConfig();
74 InitStatus();
75 }
76
77 AudioLoopback::~AudioLoopback() = default;
78
~AudioLoopbackPrivate()79 AudioLoopbackPrivate::~AudioLoopbackPrivate()
80 {
81 AUDIO_INFO_LOG("~AudioLoopbackPrivate");
82 std::unique_lock<std::mutex> stateLock(stateMutex_);
83 CHECK_AND_RETURN_LOG(currentState_ == LOOPBACK_STATE_RUNNING, "AudioLoopback not Running");
84 currentState_ = LOOPBACK_STATE_DESTROYING;
85 stateLock.unlock();
86 DestroyAudioLoopbackInner();
87 }
88
Enable(bool enable)89 bool AudioLoopbackPrivate::Enable(bool enable)
90 {
91 Trace trace("AudioLoopbackPrivate::Enable");
92 std::lock_guard<std::mutex> lock(loopbackMutex_);
93 CHECK_AND_RETURN_RET_LOG(IsAudioLoopbackSupported(), false, "AudioLoopback not support");
94 AUDIO_INFO_LOG("Enable %{public}d, currentState_ %{public}d", enable, currentState_);
95 if (enable) {
96 CHECK_AND_RETURN_RET_LOG(GetCurrentState() != LOOPBACK_STATE_RUNNING, true, "AudioLoopback already running");
97 InitStatus();
98 CHECK_AND_RETURN_RET_LOG(CheckDeviceSupport(), false, "Device not support");
99 CreateAudioLoopback();
100 currentState_ = LOOPBACK_STATE_PREPARED;
101 UpdateStatus();
102 CHECK_AND_RETURN_RET_LOG(GetCurrentState() == LOOPBACK_STATE_RUNNING, false, "AudioLoopback Enable failed");
103 } else {
104 std::unique_lock<std::mutex> stateLock(stateMutex_);
105 CHECK_AND_RETURN_RET_LOG(currentState_ == LOOPBACK_STATE_RUNNING, true, "AudioLoopback not Running");
106 currentState_ = LOOPBACK_STATE_DESTROYING;
107 stateLock.unlock();
108 DestroyAudioLoopbackInner();
109 currentState_ = LOOPBACK_STATE_IDLE;
110 }
111 return true;
112 }
113
InitStatus()114 void AudioLoopbackPrivate::InitStatus()
115 {
116 currentState_ = LOOPBACK_STATE_IDLE;
117
118 rendererState_ = RENDERER_INVALID;
119 isRendererUsb_ = false;
120 rendererFastStatus_ = FASTSTATUS_NORMAL;
121
122 capturerState_ = CAPTURER_INVALID;
123 isCapturerUsb_ = false;
124 capturerFastStatus_ = FASTSTATUS_NORMAL;
125 }
126
GetStatus()127 AudioLoopbackStatus AudioLoopbackPrivate::GetStatus()
128 {
129 Trace trace("AudioLoopbackPrivate::GetStatus");
130 std::unique_lock<std::mutex> stateLock(stateMutex_);
131 AudioLoopbackStatus status = StateToStatus(currentState_);
132 if (status == LOOPBACK_UNAVAILABLE_SCENE || status == LOOPBACK_UNAVAILABLE_DEVICE) {
133 currentState_ = LOOPBACK_STATE_IDLE;
134 }
135 return status;
136 }
137
StateToStatus(AudioLoopbackState state)138 AudioLoopbackStatus AudioLoopbackPrivate::StateToStatus(AudioLoopbackState state)
139 {
140 if (state == LOOPBACK_STATE_RUNNING) {
141 return LOOPBACK_AVAILABLE_RUNNING;
142 }
143 bool ret = CheckDeviceSupport();
144 if (!ret) {
145 return LOOPBACK_UNAVAILABLE_DEVICE;
146 }
147 if (state == LOOPBACK_STATE_DESTROYED || state == LOOPBACK_STATE_DESTROYING) {
148 return LOOPBACK_UNAVAILABLE_SCENE;
149 }
150 return LOOPBACK_AVAILABLE_IDLE;
151 }
152
SetVolume(float volume)153 int32_t AudioLoopbackPrivate::SetVolume(float volume)
154 {
155 Trace trace("AudioLoopbackPrivate::SetVolume");
156 if (volume < 0.0 || volume > 1.0) {
157 AUDIO_ERR_LOG("SetVolume with invalid volume %{public}f", volume);
158 return ERR_INVALID_PARAM;
159 }
160 std::unique_lock<std::mutex> stateLock(stateMutex_);
161 karaokeParams_["Karaoke_volume"] = std::to_string(static_cast<int>(volume * VALUE_HUNDRED));
162 if (currentState_ == LOOPBACK_STATE_RUNNING) {
163 std::string parameters = "Karaoke_volume=" + karaokeParams_["Karaoke_volume"];
164 CHECK_AND_RETURN_RET_LOG(AudioPolicyManager::GetInstance().SetKaraokeParameters(parameters), ERROR,
165 "SetVolume failed");
166 }
167 return SUCCESS;
168 }
169
SetReverbPreset(AudioLoopbackReverbPreset preset)170 bool AudioLoopbackPrivate::SetReverbPreset(AudioLoopbackReverbPreset preset)
171 {
172 std::unique_lock<std::mutex> stateLock(stateMutex_);
173 auto it = audioLoopbackReverbPresetMap.find(preset);
174 CHECK_AND_RETURN_RET_LOG(it != audioLoopbackReverbPresetMap.end(), false, "preset invalid");
175 currentReverbPreset_ = preset;
176 karaokeParams_["Karaoke_reverb_mode"] = it->second;
177 if (currentState_ == LOOPBACK_STATE_RUNNING) {
178 std::string parameters = "Karaoke_reverb_mode=" + karaokeParams_["Karaoke_reverb_mode"];
179 CHECK_AND_RETURN_RET_LOG(AudioPolicyManager::GetInstance().SetKaraokeParameters(parameters), false,
180 "SetReverbPreset failed");
181 }
182 return true;
183 }
184
GetReverbPreset()185 AudioLoopbackReverbPreset AudioLoopbackPrivate::GetReverbPreset()
186 {
187 std::unique_lock<std::mutex> stateLock(stateMutex_);
188 return currentReverbPreset_;
189 }
190
SetEqualizerPreset(AudioLoopbackEqualizerPreset preset)191 bool AudioLoopbackPrivate::SetEqualizerPreset(AudioLoopbackEqualizerPreset preset)
192 {
193 std::unique_lock<std::mutex> stateLock(stateMutex_);
194 auto it = audioLoopbackEqualizerPresetMap.find(preset);
195 CHECK_AND_RETURN_RET_LOG(it != audioLoopbackEqualizerPresetMap.end(), false, "preset invalid");
196 currentEqualizerPreset_ = preset;
197 karaokeParams_["Karaoke_eq_mode"] = it->second;
198 if (currentState_ == LOOPBACK_STATE_RUNNING) {
199 std::string parameters = "Karaoke_eq_mode=" + karaokeParams_["Karaoke_eq_mode"];
200 CHECK_AND_RETURN_RET_LOG(AudioPolicyManager::GetInstance().SetKaraokeParameters(parameters), false,
201 "SetEqualizerPreset failed");
202 }
203 return true;
204 }
205
GetEqualizerPreset()206 AudioLoopbackEqualizerPreset AudioLoopbackPrivate::GetEqualizerPreset()
207 {
208 std::unique_lock<std::mutex> stateLock(stateMutex_);
209 return currentEqualizerPreset_;
210 }
211
SetAudioLoopbackCallback(const std::shared_ptr<AudioLoopbackCallback> & callback)212 int32_t AudioLoopbackPrivate::SetAudioLoopbackCallback(const std::shared_ptr<AudioLoopbackCallback> &callback)
213 {
214 std::unique_lock<std::mutex> stateLock(stateMutex_);
215 statusCallback_ = callback;
216 return SUCCESS;
217 }
218
RemoveAudioLoopbackCallback()219 int32_t AudioLoopbackPrivate::RemoveAudioLoopbackCallback()
220 {
221 std::unique_lock<std::mutex> stateLock(stateMutex_);
222 statusCallback_ = nullptr;
223 return SUCCESS;
224 }
225
CreateAudioLoopback()226 void AudioLoopbackPrivate::CreateAudioLoopback()
227 {
228 Trace trace("AudioLoopbackPrivate::CreateAudioLoopback");
229 audioRenderer_ = AudioRenderer::CreateRenderer(rendererOptions_, appInfo_);
230 CHECK_AND_RETURN_LOG(audioRenderer_ != nullptr, "CreateRenderer failed");
231 CHECK_AND_RETURN_LOG(audioRenderer_->IsFastRenderer(), "CreateFastRenderer failed");
232 audioRenderer_->SetRendererWriteCallback(shared_from_this());
233 rendererFastStatus_ = FASTSTATUS_FAST;
234 audioCapturer_ = AudioCapturer::CreateCapturer(capturerOptions_, appInfo_);
235 CHECK_AND_RETURN_LOG(audioCapturer_ != nullptr, "CreateCapturer failed");
236 AudioCapturerInfo capturerInfo;
237 audioCapturer_->GetCapturerInfo(capturerInfo);
238 CHECK_AND_RETURN_LOG(capturerInfo.capturerFlags == STREAM_FLAG_FAST, "CreateFastCapturer failed");
239 audioCapturer_->SetCapturerReadCallback(shared_from_this());
240 InitializeCallbacks();
241 capturerFastStatus_ = FASTSTATUS_FAST;
242 CHECK_AND_RETURN_LOG(audioRenderer_->Start(), "audioRenderer Start failed");
243 rendererState_ = RENDERER_RUNNING;
244 CHECK_AND_RETURN_LOG(audioCapturer_->Start(), "audioCapturer Start failed");
245 capturerState_ = CAPTURER_RUNNING;
246 }
247
DisableLoopback()248 void AudioLoopbackPrivate::DisableLoopback()
249 {
250 if (karaokeParams_["Karaoke_enable"] == "enable") {
251 karaokeParams_["Karaoke_enable"] = "disable";
252 std::string parameters = "Karaoke_enable=" + karaokeParams_["Karaoke_enable"];
253 CHECK_AND_RETURN_LOG(AudioPolicyManager::GetInstance().SetKaraokeParameters(parameters),
254 "DisableLoopback failed");
255 }
256 }
257
DestroyAudioLoopbackInner()258 void AudioLoopbackPrivate::DestroyAudioLoopbackInner()
259 {
260 Trace trace("AudioLoopbackPrivate::DestroyAudioLoopbackInner");
261 DisableLoopback();
262 if (audioCapturer_) {
263 audioCapturer_->Stop();
264 audioCapturer_->Release();
265 audioCapturer_ = nullptr;
266 } else {
267 AUDIO_WARNING_LOG("audioCapturer is nullptr");
268 }
269 if (audioRenderer_) {
270 audioRenderer_->Stop();
271 audioRenderer_->Release();
272 audioRenderer_ = nullptr;
273 } else {
274 AUDIO_WARNING_LOG("audioRenderer is nullptr");
275 }
276 }
277
DestroyAudioLoopback()278 void AudioLoopbackPrivate::DestroyAudioLoopback()
279 {
280 Trace trace("AudioLoopbackPrivate::DestroyAudioLoopback");
281 std::lock_guard<std::mutex> lock(loopbackMutex_);
282 DestroyAudioLoopbackInner();
283 }
284
GenerateRendererConfig()285 AudioRendererOptions AudioLoopbackPrivate::GenerateRendererConfig()
286 {
287 AudioRendererOptions rendererOptions = {};
288 rendererOptions.streamInfo.samplingRate = AudioSamplingRate::SAMPLE_RATE_48000;
289 rendererOptions.streamInfo.encoding = AudioEncodingType::ENCODING_PCM;
290 rendererOptions.streamInfo.format = AudioSampleFormat::SAMPLE_S16LE;
291 rendererOptions.streamInfo.channels = AudioChannel::STEREO;
292 rendererOptions.rendererInfo.contentType = ContentType::CONTENT_TYPE_MUSIC;
293 rendererOptions.rendererInfo.streamUsage = StreamUsage::STREAM_USAGE_MUSIC;
294 rendererOptions.rendererInfo.rendererFlags = STREAM_FLAG_FAST;
295 rendererOptions.rendererInfo.isLoopback = true;
296 rendererOptions.rendererInfo.loopbackMode = mode_;
297 return rendererOptions;
298 }
299
GenerateCapturerConfig()300 AudioCapturerOptions AudioLoopbackPrivate::GenerateCapturerConfig()
301 {
302 AudioCapturerOptions capturerOptions = {};
303 capturerOptions.streamInfo.samplingRate = AudioSamplingRate::SAMPLE_RATE_48000;
304 capturerOptions.streamInfo.encoding = AudioEncodingType::ENCODING_PCM;
305 capturerOptions.streamInfo.format = AudioSampleFormat::SAMPLE_S16LE;
306 capturerOptions.streamInfo.channels = AudioChannel::STEREO;
307 capturerOptions.capturerInfo.sourceType = SourceType::SOURCE_TYPE_MIC;
308 capturerOptions.capturerInfo.capturerFlags = STREAM_FLAG_FAST;
309 capturerOptions.capturerInfo.isLoopback = true;
310 capturerOptions.capturerInfo.loopbackMode = mode_;
311 return capturerOptions;
312 }
313
IsAudioLoopbackSupported()314 bool AudioLoopbackPrivate::IsAudioLoopbackSupported()
315 {
316 Trace trace("AudioLoopbackPrivate::IsAudioLoopbackSupported");
317 return AudioPolicyManager::GetInstance().IsAudioLoopbackSupported(mode_);
318 }
319
CheckDeviceSupport()320 bool AudioLoopbackPrivate::CheckDeviceSupport()
321 {
322 isRendererUsb_ = AudioPolicyManager::GetInstance().GetActiveOutputDevice() == DEVICE_TYPE_USB_HEADSET;
323 isCapturerUsb_ = AudioPolicyManager::GetInstance().GetActiveInputDevice() == DEVICE_TYPE_USB_HEADSET;
324 return isRendererUsb_ && isCapturerUsb_;
325 }
326
EnableLoopback()327 bool AudioLoopbackPrivate::EnableLoopback()
328 {
329 Trace trace("AudioLoopbackPrivate::EnableLoopback");
330 karaokeParams_["Karaoke_enable"] = "enable";
331 std::string parameters = "";
332 for (auto ¶m : karaokeParams_) {
333 parameters = param.first + "=" + param.second + ";";
334 CHECK_AND_RETURN_RET_LOG(AudioPolicyManager::GetInstance().SetKaraokeParameters(parameters), false,
335 "SetKaraokeParameters failed");
336 }
337 return true;
338 }
339
OnReadData(size_t length)340 void AudioLoopbackPrivate::OnReadData(size_t length)
341 {
342 CHECK_AND_RETURN_LOG(audioCapturer_ != nullptr, "audioCapturer is nullptr");
343 BufferDesc bufDesc;
344 int32_t ret = audioCapturer_->GetBufferDesc(bufDesc);
345 CHECK_AND_RETURN_LOG(ret == SUCCESS, "get bufDesc failed, bufLength=%{public}zu, dataLength=%{public}zu",
346 bufDesc.bufLength, bufDesc.dataLength);
347 }
348
OnWriteData(size_t length)349 void AudioLoopbackPrivate::OnWriteData(size_t length)
350 {
351 CHECK_AND_RETURN_LOG(audioRenderer_ != nullptr, "audioRenderer is nullptr");
352 BufferDesc bufDesc;
353 audioRenderer_->GetBufferDesc(bufDesc);
354 memset_s((void*)bufDesc.buffer, bufDesc.bufLength, 0, bufDesc.bufLength);
355 audioRenderer_->Enqueue(bufDesc);
356 }
357
RendererCallbackImpl(AudioLoopbackPrivate & parent)358 AudioLoopbackPrivate::RendererCallbackImpl::RendererCallbackImpl(AudioLoopbackPrivate &parent)
359 : parent_(parent) {}
360
OnStateChange(const RendererState state,const StateChangeCmdType cmdType)361 void AudioLoopbackPrivate::RendererCallbackImpl::OnStateChange(
362 const RendererState state, const StateChangeCmdType __attribute__((unused)) cmdType)
363 {
364 parent_.rendererState_ = state;
365 parent_.UpdateStatus();
366 }
367
OnOutputDeviceChange(const AudioDeviceDescriptor & deviceInfo,const AudioStreamDeviceChangeReason reason)368 void AudioLoopbackPrivate::RendererCallbackImpl::OnOutputDeviceChange(const AudioDeviceDescriptor &deviceInfo,
369 const AudioStreamDeviceChangeReason __attribute__((unused)) reason)
370 {
371 parent_.isRendererUsb_ = (deviceInfo.deviceType_ == DEVICE_TYPE_USB_HEADSET);
372 parent_.UpdateStatus();
373 }
374
OnFastStatusChange(FastStatus status)375 void AudioLoopbackPrivate::RendererCallbackImpl::OnFastStatusChange(FastStatus status)
376 {
377 parent_.rendererFastStatus_ = status;
378 parent_.UpdateStatus();
379 }
380
CapturerCallbackImpl(AudioLoopbackPrivate & parent)381 AudioLoopbackPrivate::CapturerCallbackImpl::CapturerCallbackImpl(AudioLoopbackPrivate &parent)
382 : parent_(parent) {}
383
OnStateChange(const CapturerState state)384 void AudioLoopbackPrivate::CapturerCallbackImpl::OnStateChange(const CapturerState state)
385 {
386 parent_.capturerState_ = state;
387 parent_.UpdateStatus();
388 }
389
OnStateChange(const AudioDeviceDescriptor & deviceInfo)390 void AudioLoopbackPrivate::CapturerCallbackImpl::OnStateChange(const AudioDeviceDescriptor &deviceInfo)
391 {
392 parent_.isCapturerUsb_ = (deviceInfo.deviceType_ == DEVICE_TYPE_USB_HEADSET);
393 parent_.UpdateStatus();
394 }
395
OnFastStatusChange(FastStatus status)396 void AudioLoopbackPrivate::CapturerCallbackImpl::OnFastStatusChange(FastStatus status)
397 {
398 parent_.capturerFastStatus_ = status;
399 parent_.UpdateStatus();
400 }
401
InitializeCallbacks()402 void AudioLoopbackPrivate::InitializeCallbacks()
403 {
404 auto rendererCallback = std::make_shared<RendererCallbackImpl>(*this);
405 audioRenderer_->SetRendererCallback(rendererCallback);
406 audioRenderer_->RegisterOutputDeviceChangeWithInfoCallback(rendererCallback);
407 audioRenderer_->SetFastStatusChangeCallback(rendererCallback);
408
409 auto capturerCallback = std::make_shared<CapturerCallbackImpl>(*this);
410 audioCapturer_->SetCapturerCallback(capturerCallback);
411 audioCapturer_->SetAudioCapturerDeviceChangeCallback(capturerCallback);
412 audioCapturer_->SetFastStatusChangeCallback(capturerCallback);
413 }
414
GetCurrentState()415 AudioLoopbackState AudioLoopbackPrivate::GetCurrentState()
416 {
417 std::unique_lock<std::mutex> stateLock(stateMutex_);
418 return currentState_;
419 }
420
UpdateStatus()421 void AudioLoopbackPrivate::UpdateStatus()
422 {
423 Trace trace("AudioLoopbackPrivate::UpdateStatus");
424 std::unique_lock<std::mutex> stateLock(stateMutex_);
425 CHECK_AND_RETURN(currentState_ == LOOPBACK_STATE_RUNNING || currentState_ == LOOPBACK_STATE_PREPARED);
426 AudioLoopbackState oldState = currentState_;
427 AudioLoopbackState newState = currentState_;
428 const bool isDeviceValid = isRendererUsb_.load() && isCapturerUsb_.load();
429 const bool isStateRunning = (rendererState_.load() == RENDERER_RUNNING) &&
430 (capturerState_.load() == CAPTURER_RUNNING);
431 const bool isFastValid = (rendererFastStatus_.load() == FASTSTATUS_FAST) &&
432 (capturerFastStatus_.load() == FASTSTATUS_FAST);
433 newState = (isDeviceValid && isStateRunning && isFastValid) ? LOOPBACK_STATE_RUNNING : LOOPBACK_STATE_DESTROYED;
434
435 if (newState == LOOPBACK_STATE_RUNNING) {
436 newState = EnableLoopback() ? LOOPBACK_STATE_RUNNING : LOOPBACK_STATE_DESTROYED;
437 }
438 if (newState != oldState) {
439 AUDIO_INFO_LOG("UpdateState: %{public}d -> %{public}d", oldState, newState);
440 if (newState == LOOPBACK_STATE_DESTROYED) {
441 currentState_ = LOOPBACK_STATE_DESTROYING;
442 auto self = shared_from_this();
443 std::thread([self] {
444 self->DestroyAudioLoopback();
445 }).detach();
446 }
447 currentState_ = newState;
448 if (statusCallback_) {
449 statusCallback_->OnStatusChange(StateToStatus(currentState_));
450 }
451 }
452 }
453 } // namespace AudioStandard
454 } // namespace OHOS