1 /*
2 * Copyright (c) 2022-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
16 #include <cstring>
17 #include <dlfcn.h>
18 #include <string>
19
20 #include "audio_errors.h"
21 #include "audio_log.h"
22 #include "remote_audio_capturer_source.h"
23
24 using namespace std;
25
26 namespace OHOS {
27 namespace AudioStandard {
28 #ifdef DEBUG_CAPTURE_DUMP
29 const char *g_audioOutTestFilePath = "/data/local/tmp/remote_audio_capture.pcm";
30 #endif // DEBUG_CAPTURE_DUMP
31
32 std::map<std::string, RemoteAudioCapturerSource *> RemoteAudioCapturerSource::allRemoteSources;
GetInstance(std::string deviceNetworkId)33 RemoteAudioCapturerSource *RemoteAudioCapturerSource::GetInstance(std::string deviceNetworkId)
34 {
35 RemoteAudioCapturerSource *audioCapturer_ = nullptr;
36 // check if it is in our map
37 if (allRemoteSources.count(deviceNetworkId)) {
38 return allRemoteSources[deviceNetworkId];
39 } else {
40 audioCapturer_ = new(std::nothrow) RemoteAudioCapturerSource(deviceNetworkId);
41 AUDIO_DEBUG_LOG("new Daudio device source:[%{public}s]", deviceNetworkId.c_str());
42 allRemoteSources[deviceNetworkId] = audioCapturer_;
43 }
44 CHECK_AND_RETURN_RET_LOG((audioCapturer_ != nullptr), nullptr, "null audioCapturer!");
45 return audioCapturer_;
46 }
47
RemoteAudioCapturerSource(std::string deviceNetworkId)48 RemoteAudioCapturerSource::RemoteAudioCapturerSource(std::string deviceNetworkId)
49 {
50 this->deviceNetworkId_ = deviceNetworkId;
51 capturerInited_ = false;
52 audioManager_ = nullptr;
53 audioAdapter_ = nullptr;
54 audioCapture_ = nullptr;
55 }
56
~RemoteAudioCapturerSource()57 RemoteAudioCapturerSource::~RemoteAudioCapturerSource()
58 {
59 if (capturerInited_ == true) {
60 DeInit();
61 } else {
62 AUDIO_INFO_LOG("RemoteAudioCapturerSource has already DeInit.");
63 }
64 }
65
DeInit()66 void RemoteAudioCapturerSource::DeInit()
67 {
68 AUDIO_INFO_LOG("%{public}s enter.", __func__);
69 capturerInited_ = false;
70
71 if ((audioCapture_ != nullptr) && (audioAdapter_ != nullptr)) {
72 audioAdapter_->DestroyCapture(audioAdapter_, audioCapture_);
73 }
74 audioCapture_ = nullptr;
75 isCapturerCreated_.store(false);
76
77 if ((audioManager_ != nullptr) && (audioAdapter_ != nullptr)) {
78 if (routeHandle_ != -1) {
79 audioAdapter_->ReleaseAudioRoute(audioAdapter_, routeHandle_);
80 }
81 audioManager_->UnloadAdapter(audioManager_, audioAdapter_);
82 }
83 audioAdapter_ = nullptr;
84 audioManager_ = nullptr;
85
86 // remove map recorder.
87 RemoteAudioCapturerSource *temp = allRemoteSources[this->deviceNetworkId_];
88 if (temp != nullptr) {
89 delete temp;
90 temp = nullptr;
91 allRemoteSources.erase(this->deviceNetworkId_);
92 }
93 #ifdef DEBUG_CAPTURE_DUMP
94 if (pfd != nullptr) {
95 fclose(pfd);
96 pfd = nullptr;
97 }
98 #endif // DEBUG_CAPTURE_DUMP
99 }
100
RegisterWakeupCloseCallback(IAudioSourceCallback * callback)101 void RemoteAudioCapturerSource::RegisterWakeupCloseCallback(IAudioSourceCallback* callback)
102 {
103 AUDIO_ERR_LOG("RegisterWakeupCloseCallback FAILED");
104 }
105
RegisterAudioCapturerSourceCallback(IAudioSourceCallback * callback)106 void RemoteAudioCapturerSource::RegisterAudioCapturerSourceCallback(IAudioSourceCallback* callback)
107 {
108 AUDIO_ERR_LOG("RegisterAudioCapturerSourceCallback FAILED");
109 }
110
SwitchAdapterCapture(struct AudioAdapterDescriptor * descs,int32_t size,const std::string & adapterNameCase,struct AudioPort & capturePort)111 int32_t SwitchAdapterCapture(struct AudioAdapterDescriptor *descs, int32_t size, const std::string &adapterNameCase,
112 struct AudioPort &capturePort)
113 {
114 if (descs == nullptr) {
115 return ERROR;
116 }
117
118 for (int32_t index = 0; index < size; index++) {
119 struct AudioAdapterDescriptor *desc = &descs[index];
120 if (desc == nullptr) {
121 continue;
122 }
123 if (adapterNameCase.compare(desc->adapterName) != 0) {
124 continue;
125 }
126 for (uint32_t port = 0; port < desc->portNum; port++) {
127 // Only find out the port of in in the sound card
128 if (desc->ports[port].portId == PIN_IN_MIC) {
129 capturePort = desc->ports[port];
130 return index;
131 }
132 }
133 }
134 AUDIO_ERR_LOG("SwitchAdapterCapture Fail");
135
136 return ERR_INVALID_INDEX;
137 }
138
CreateCapture(struct AudioPort & capturePort)139 int32_t RemoteAudioCapturerSource::CreateCapture(struct AudioPort &capturePort)
140 {
141 int32_t ret;
142 struct AudioSampleAttributes param;
143 param.type = AUDIO_IN_MEDIA;
144 param.period = deepBufferCapturePeriodSize;
145 param.streamId = REMOTE_INPUT_STREAM_ID;
146 param.isSignedData = true;
147 param.stopThreshold = maxInt32;
148 param.silenceThreshold = audioBufferSize;
149 // User needs to set
150 param.sampleRate = attr_.sampleRate;
151 param.format = (AudioFormat)(attr_.format);
152 param.isBigEndian = attr_.isBigEndian;
153 param.channelCount = attr_.channel;
154 param.silenceThreshold = attr_.bufferSize;
155 param.frameSize = param.format * param.channelCount;
156 param.startThreshold = deepBufferCapturePeriodSize / (param.frameSize);
157 param.sourceType = attr_.sourceType;
158
159 struct AudioDeviceDescriptor deviceDesc;
160 deviceDesc.portId = capturePort.portId;
161 deviceDesc.pins = PIN_IN_MIC;
162 deviceDesc.desc = nullptr;
163
164 ret = audioAdapter_->CreateCapture(audioAdapter_, &deviceDesc, ¶m, &audioCapture_);
165 if (audioCapture_ == nullptr || ret < 0) {
166 AUDIO_ERR_LOG("Create capture failed, error code %{public}d.", ret);
167 return ERR_NOT_STARTED;
168 }
169
170 isCapturerCreated_.store(true);
171 return SUCCESS;
172 }
173
Init(IAudioSourceAttr & attr)174 int32_t RemoteAudioCapturerSource::Init(IAudioSourceAttr &attr)
175 {
176 attr_ = attr;
177 int32_t ret;
178 int32_t index;
179 int32_t size = 0;
180 struct AudioAdapterDescriptor *descs = nullptr;
181 if (InitAudioManager() != 0) {
182 AUDIO_ERR_LOG("Init audio manager Fail");
183 return ERR_INVALID_HANDLE;
184 }
185 ret = audioManager_->GetAllAdapters(audioManager_, &descs, &size);
186 // adapters is 0~3
187 if (size == 0 || descs == nullptr || ret != 0) {
188 AUDIO_ERR_LOG("Get adapters Fail");
189 return ERR_NOT_STARTED;
190 }
191 // Get qualified sound card and port
192 std::string adapterNameCase = attr_.deviceNetworkId;
193 index = SwitchAdapterCapture(descs, size, adapterNameCase, audioPort);
194 if (index < 0) {
195 AUDIO_ERR_LOG("Switch Adapter Capture Fail");
196 return ERR_NOT_STARTED;
197 }
198 struct AudioAdapterDescriptor *desc = &descs[index];
199 if (audioManager_->LoadAdapter(audioManager_, desc, &audioAdapter_) != 0) {
200 AUDIO_ERR_LOG("Load Adapter Fail");
201 return ERR_NOT_STARTED;
202 }
203 if (audioAdapter_ == nullptr) {
204 AUDIO_ERR_LOG("Load audio device failed");
205 return ERR_NOT_STARTED;
206 }
207
208 // Inittialization port information, can fill through mode and other parameters
209 ret = audioAdapter_->InitAllPorts(audioAdapter_);
210 if (ret != 0) {
211 AUDIO_ERR_LOG("InitAllPorts failed");
212 return ERR_DEVICE_INIT;
213 }
214 capturerInited_ = true;
215
216 #ifdef DEBUG_CAPTURE_DUMP
217 pfd = fopen(g_audioOutTestFilePath, "rb");
218 if (pfd == nullptr) {
219 AUDIO_ERR_LOG("Error opening pcm test file!");
220 }
221 #endif // DEBUG_CAPTURE_DUMP
222
223 return SUCCESS;
224 }
225
IsInited(void)226 bool RemoteAudioCapturerSource::IsInited(void)
227 {
228 return capturerInited_;
229 }
230
InitAudioManager()231 int32_t RemoteAudioCapturerSource::InitAudioManager()
232 {
233 AUDIO_INFO_LOG("RemoteAudioCapturerSource: Initialize audio proxy manager");
234 #ifdef FEATURE_DISTRIBUTE_AUDIO
235 #ifdef __aarch64__
236 char resolvedPath[100] = "/system/lib64/libdaudio_client.z.so";
237 #else
238 char resolvedPath[100] = "/system/lib/libdaudio_client.z.so";
239 #endif
240 struct AudioManager *(*GetAudioManagerFuncs)() = nullptr;
241
242 void *handle_ = dlopen(resolvedPath, 1);
243 if (handle_ == nullptr) {
244 AUDIO_ERR_LOG("Open so Fail");
245 return ERR_INVALID_HANDLE;
246 }
247 AUDIO_INFO_LOG("dlopen successful");
248
249 GetAudioManagerFuncs = (struct AudioManager *(*)())(dlsym(handle_, "GetAudioManagerFuncs"));
250 if (GetAudioManagerFuncs == nullptr) {
251 return ERR_INVALID_HANDLE;
252 }
253 AUDIO_INFO_LOG("GetAudioManagerFuncs done");
254
255 audioManager_ = GetAudioManagerFuncs();
256 if (audioManager_ == nullptr) {
257 return ERR_INVALID_HANDLE;
258 }
259 AUDIO_INFO_LOG("daudio manager created");
260 #else
261 audioManager_ = nullptr;
262 #endif // FEATURE_DISTRIBUTE_AUDIO
263 CHECK_AND_RETURN_RET_LOG((audioManager_ != nullptr), ERR_INVALID_HANDLE, "Initialize audio proxy failed!");
264
265 return SUCCESS;
266 }
267
CaptureFrame(char * frame,uint64_t requestBytes,uint64_t & replyBytes)268 int32_t RemoteAudioCapturerSource::CaptureFrame(char *frame, uint64_t requestBytes, uint64_t &replyBytes)
269 {
270 int32_t ret;
271 CHECK_AND_RETURN_RET_LOG((audioCapture_ != nullptr), ERR_INVALID_HANDLE, "Audio capture Handle is nullptr!");
272
273 ret = audioCapture_->CaptureFrame(audioCapture_, frame, requestBytes, &replyBytes);
274 if (ret < 0) {
275 AUDIO_ERR_LOG("Capture Frame Fail");
276 return ERR_READ_FAILED;
277 }
278
279 #ifdef DEBUG_CAPTURE_DUMP
280 if (feof(pfd)) {
281 AUDIO_INFO_LOG("End of the file reached, start reading from beginning");
282 rewind(pfd);
283 }
284 size_t writeResult = fread(frame, 1, requestBytes, pfd);
285 if (writeResult != requestBytes) {
286 AUDIO_ERR_LOG("Failed to read the file.");
287 }
288 #endif // DEBUG_CAPTURE_DUMP
289
290 return SUCCESS;
291 }
292
Start(void)293 int32_t RemoteAudioCapturerSource::Start(void)
294 {
295 AUDIO_INFO_LOG("RemoteAudioCapturerSource start enter.");
296 if (!isCapturerCreated_.load()) {
297 if (CreateCapture(audioPort) != SUCCESS) {
298 AUDIO_ERR_LOG("Create capture failed.");
299 return ERR_NOT_STARTED;
300 }
301 }
302 int32_t ret;
303 CHECK_AND_RETURN_RET_LOG((audioCapture_ != nullptr), ERR_INVALID_HANDLE, "Audio capture Handle is nullptr!");
304 if (!started_) {
305 ret = audioCapture_->control.Start((AudioHandle)audioCapture_);
306 if (ret < 0) {
307 AUDIO_ERR_LOG("Remote audio capturer start fail, error code %{public}d", ret);
308 return ERR_NOT_STARTED;
309 }
310 started_ = true;
311 }
312 started_ = true;
313 return SUCCESS;
314 }
315
SetVolume(float left,float right)316 int32_t RemoteAudioCapturerSource::SetVolume(float left, float right)
317 {
318 // remote setvolume may not supported
319 float volume = 0.5;
320 CHECK_AND_RETURN_RET_LOG((audioCapture_ != nullptr), ERR_INVALID_HANDLE, "Audio capture Handle is nullptr!");
321
322 float leftVolume_ = left;
323 float rightVolume_ = right;
324 float half = 0.5;
325 if ((leftVolume_ == 0) && (rightVolume_ != 0)) {
326 volume = rightVolume_;
327 } else if ((leftVolume_ != 0) && (rightVolume_ == 0)) {
328 volume = leftVolume_;
329 } else {
330 volume = (leftVolume_ + rightVolume_) * half;
331 }
332
333 int32_t ret = audioCapture_->volume.SetVolume(reinterpret_cast<AudioHandle>(audioCapture_), volume);
334 AUDIO_INFO_LOG("remote setVolume(%{public}f, %{public}f):%{public}d", left, right, ret);
335 return ret;
336 }
337
GetVolume(float & left,float & right)338 int32_t RemoteAudioCapturerSource::GetVolume(float &left, float &right)
339 {
340 CHECK_AND_RETURN_RET_LOG((audioCapture_ != nullptr), ERR_INVALID_HANDLE, "Audio capture Handle is nullptr!");
341 float val = 0.0;
342 audioCapture_->volume.GetVolume((AudioHandle)audioCapture_, &val);
343 left = val;
344 right = val;
345
346 return SUCCESS;
347 }
348
SetMute(bool isMute)349 int32_t RemoteAudioCapturerSource::SetMute(bool isMute)
350 {
351 int32_t ret;
352 CHECK_AND_RETURN_RET_LOG((audioCapture_ != nullptr), ERR_INVALID_HANDLE, "Audio capture Handle is nullptr!");
353
354 ret = audioCapture_->volume.SetMute((AudioHandle)audioCapture_, isMute);
355 if (ret != 0) {
356 AUDIO_ERR_LOG("SetMute failed from hdi");
357 }
358
359 micMuteState_ = isMute;
360 return SUCCESS;
361 }
362
GetMute(bool & isMute)363 int32_t RemoteAudioCapturerSource::GetMute(bool &isMute)
364 {
365 int32_t ret;
366 CHECK_AND_RETURN_RET_LOG((audioCapture_ != nullptr), ERR_INVALID_HANDLE, "Audio capture Handle is nullptr!");
367
368 bool isHdiMute = false;
369 ret = audioCapture_->volume.GetMute((AudioHandle)audioCapture_, &isHdiMute);
370 if (ret != 0) {
371 AUDIO_ERR_LOG("AudioCapturerSource::GetMute failed from hdi");
372 }
373
374 isMute = micMuteState_;
375 return SUCCESS;
376 }
377
SetInputPortPin(DeviceType inputDevice,AudioRouteNode & source)378 int32_t SetInputPortPin(DeviceType inputDevice, AudioRouteNode &source)
379 {
380 int32_t ret = SUCCESS;
381
382 switch (inputDevice) {
383 case DEVICE_TYPE_MIC:
384 source.ext.device.type = PIN_IN_MIC;
385 source.ext.device.desc = "pin_in_mic";
386 break;
387 case DEVICE_TYPE_WIRED_HEADSET:
388 source.ext.device.type = PIN_IN_HS_MIC;
389 source.ext.device.desc = "pin_in_hs_mic";
390 break;
391 case DEVICE_TYPE_USB_HEADSET:
392 source.ext.device.type = PIN_IN_USB_EXT;
393 source.ext.device.desc = "pin_in_usb_ext";
394 break;
395 default:
396 ret = ERR_NOT_SUPPORTED;
397 break;
398 }
399
400 return ret;
401 }
402
SetInputRoute(DeviceType inputDevice)403 int32_t RemoteAudioCapturerSource::SetInputRoute(DeviceType inputDevice)
404 {
405 AudioRouteNode source = {};
406 AudioRouteNode sink = {};
407
408 int32_t ret = SetInputPortPin(inputDevice, source);
409 if (ret != SUCCESS) {
410 AUDIO_ERR_LOG("AudioCapturerSource: OpenOutput FAILED: %{public}d", ret);
411 return ret;
412 }
413
414 source.portId = audioPort.portId;
415 source.role = AUDIO_PORT_SOURCE_ROLE;
416 source.type = AUDIO_PORT_DEVICE_TYPE;
417 source.ext.device.moduleId = 0;
418
419 sink.portId = 0;
420 sink.role = AUDIO_PORT_SINK_ROLE;
421 sink.type = AUDIO_PORT_MIX_TYPE;
422 sink.ext.mix.moduleId = 0;
423 sink.ext.mix.streamId = REMOTE_INPUT_STREAM_ID;
424
425 AudioRoute route = {
426 .sourcesNum = 1,
427 .sources = &source,
428 .sinksNum = 1,
429 .sinks = &sink,
430 };
431
432 if (audioAdapter_ == nullptr) {
433 AUDIO_ERR_LOG("RemoteAudioCapturerSource: AudioAdapter object is null.");
434 return ERR_OPERATION_FAILED;
435 }
436
437 ret = audioAdapter_->UpdateAudioRoute(audioAdapter_, &route, &routeHandle_);
438 AUDIO_DEBUG_LOG("AudioCapturerSource: UpdateAudioRoute returns: %{public}d", ret);
439 if (ret != 0) {
440 AUDIO_ERR_LOG("AudioCapturerSource: UpdateAudioRoute failed");
441 return ERR_OPERATION_FAILED;
442 }
443 return SUCCESS;
444 }
445
GetAudioCategory(AudioScene audioScene)446 AudioCategory GetAudioCategory(AudioScene audioScene)
447 {
448 AudioCategory audioCategory;
449 switch (audioScene) {
450 case AUDIO_SCENE_DEFAULT:
451 audioCategory = AUDIO_IN_MEDIA;
452 break;
453 case AUDIO_SCENE_RINGING:
454 audioCategory = AUDIO_IN_RINGTONE;
455 break;
456 case AUDIO_SCENE_PHONE_CALL:
457 audioCategory = AUDIO_IN_CALL;
458 break;
459 case AUDIO_SCENE_PHONE_CHAT:
460 audioCategory = AUDIO_IN_COMMUNICATION;
461 break;
462 default:
463 audioCategory = AUDIO_IN_MEDIA;
464 break;
465 }
466 AUDIO_DEBUG_LOG("RemoteAudioCapturerSource: Audio category returned is: %{public}d", audioCategory);
467
468 return audioCategory;
469 }
470
SetAudioScene(AudioScene audioScene,DeviceType activeDevice)471 int32_t RemoteAudioCapturerSource::SetAudioScene(AudioScene audioScene, DeviceType activeDevice)
472 {
473 CHECK_AND_RETURN_RET_LOG((audioCapture_ != nullptr), ERR_INVALID_HANDLE, "Audio capture Handle is nullptr!");
474 struct AudioSceneDescriptor scene;
475 scene.scene.id = GetAudioCategory(audioScene);
476 scene.desc.pins = PIN_IN_MIC;
477 if (audioCapture_->scene.SelectScene == nullptr) {
478 AUDIO_ERR_LOG("AudioCapturerSource: Select scene nullptr");
479 return ERR_OPERATION_FAILED;
480 }
481
482 AUDIO_INFO_LOG("AudioCapturerSource::SelectScene start");
483 int32_t ret = audioCapture_->scene.SelectScene((AudioHandle)audioCapture_, &scene);
484 AUDIO_INFO_LOG("AudioCapturerSource::SelectScene over");
485 if (ret < 0) {
486 AUDIO_ERR_LOG("AudioCapturerSource: Select scene FAILED: %{public}d", ret);
487 return ERR_OPERATION_FAILED;
488 }
489 AUDIO_INFO_LOG("AudioCapturerSource::Select audio scene SUCCESS: %{public}d", audioScene);
490 return SUCCESS;
491 }
492
GetTransactionId()493 uint64_t RemoteAudioCapturerSource::GetTransactionId()
494 {
495 AUDIO_INFO_LOG("RemoteAudioCapturerSource::GetTransactionId in");
496 return reinterpret_cast<uint64_t>(audioCapture_);
497 }
498
Stop(void)499 int32_t RemoteAudioCapturerSource::Stop(void)
500 {
501 AUDIO_INFO_LOG("RemoteAudioCapturerSource::Stop in");
502 int32_t ret;
503 if (started_ && audioCapture_ != nullptr) {
504 ret = audioCapture_->control.Stop(reinterpret_cast<AudioHandle>(audioCapture_));
505 if (ret < 0) {
506 AUDIO_ERR_LOG("Stop capture Failed");
507 return ERR_OPERATION_FAILED;
508 }
509 }
510 started_ = false;
511 return SUCCESS;
512 }
513
Pause(void)514 int32_t RemoteAudioCapturerSource::Pause(void)
515 {
516 AUDIO_INFO_LOG("%{public}s enter.", __func__);
517 if (started_ && audioCapture_ != nullptr) {
518 int32_t ret = audioCapture_->control.Pause(reinterpret_cast<AudioHandle>(audioCapture_));
519 if (ret != 0) {
520 AUDIO_ERR_LOG("pause capture Failed");
521 return ERR_OPERATION_FAILED;
522 }
523 }
524 paused_ = true;
525 return SUCCESS;
526 }
527
Resume(void)528 int32_t RemoteAudioCapturerSource::Resume(void)
529 {
530 AUDIO_INFO_LOG("%{public}s enter.", __func__);
531 if (paused_ && audioCapture_ != nullptr) {
532 int32_t ret = audioCapture_->control.Resume(reinterpret_cast<AudioHandle>(audioCapture_));
533 if (ret != 0) {
534 AUDIO_ERR_LOG("resume capture Failed");
535 return ERR_OPERATION_FAILED;
536 }
537 }
538 paused_ = false;
539 return SUCCESS;
540 }
541
Reset(void)542 int32_t RemoteAudioCapturerSource::Reset(void)
543 {
544 AUDIO_INFO_LOG("%{public}s enter.", __func__);
545 if (started_ && audioCapture_ != nullptr) {
546 audioCapture_->control.Flush(reinterpret_cast<AudioHandle>(audioCapture_));
547 }
548 return SUCCESS;
549 }
550
Flush(void)551 int32_t RemoteAudioCapturerSource::Flush(void)
552 {
553 AUDIO_INFO_LOG("%{public}s enter.", __func__);
554 if (started_ && audioCapture_ != nullptr) {
555 audioCapture_->control.Flush(reinterpret_cast<AudioHandle>(audioCapture_));
556 }
557 return SUCCESS;
558 }
559 } // namespace AudioStandard
560 } // namesapce OHOS
561
562