1 /*
2  * Copyright (c) 2023-2024 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 "audio_capture_ext_impl.h"
17 
18 #include <hdf_base.h>
19 #include <securec.h>
20 #include <unistd.h>
21 #include <sys/time.h>
22 
23 #include "cJSON.h"
24 
25 #include "daudio_constants.h"
26 #include "daudio_events.h"
27 #include "daudio_log.h"
28 
29 #undef DH_LOG_TAG
30 #define DH_LOG_TAG "AudioCaptureExtImpl"
31 
32 using namespace OHOS::DistributedHardware;
33 namespace OHOS {
34 namespace HDI {
35 namespace DistributedAudio {
36 namespace Audio {
37 namespace V1_0 {
38 
AudioCaptureExtImpl()39 AudioCaptureExtImpl::AudioCaptureExtImpl()
40 {
41     DHLOGI("Distributed lowlatency capture constructed.");
42 }
43 
~AudioCaptureExtImpl()44 AudioCaptureExtImpl::~AudioCaptureExtImpl()
45 {
46     UnInitAshmem();
47     DHLOGD("Distributed lowlatency capture destructed, id(%{public}d).", devDesc_.pins);
48 }
49 
InitAshmem(int32_t ashmemLength)50 int32_t AudioCaptureExtImpl::InitAshmem(int32_t ashmemLength)
51 {
52     std::string memory_name = "Capture ShareMemory";
53     if (ashmemLength < DAUDIO_MIN_ASHMEM_LEN || ashmemLength > DAUDIO_MAX_ASHMEM_LEN) {
54         DHLOGE("Init ashmem failed. length is illegal.");
55         return HDF_FAILURE;
56     }
57     ashmem_ = OHOS::Ashmem::CreateAshmem(memory_name.c_str(), ashmemLength);
58     if (ashmem_ == nullptr) {
59         DHLOGE("Create ashmem failed.");
60         return HDF_FAILURE;
61     }
62     if (!ashmem_->MapReadAndWriteAshmem()) {
63         DHLOGE("Mmap ashmem failed.");
64         return HDF_FAILURE;
65     }
66     fd_ = ashmem_->GetAshmemFd();
67     DHLOGI("Init Ashmem success, fd: %{public}d, length: %{public}d", fd_, ashmemLength);
68     return HDF_SUCCESS;
69 }
70 
UnInitAshmem()71 void AudioCaptureExtImpl::UnInitAshmem()
72 {
73     if (ashmem_ != nullptr) {
74         ashmem_->UnmapAshmem();
75         ashmem_->CloseAshmem();
76         ashmem_ = nullptr;
77         DHLOGI("UnInitAshmem success.");
78     }
79 }
80 
GetCapturePosition(uint64_t & frames,AudioTimeStamp & time)81 int32_t AudioCaptureExtImpl::GetCapturePosition(uint64_t &frames, AudioTimeStamp &time)
82 {
83     DHLOGI("Get capture position, not support yet.");
84     (void)frames;
85     (void)time;
86     return HDF_SUCCESS;
87 }
88 
CaptureFrame(std::vector<int8_t> & frame,uint64_t & replyBytes)89 int32_t AudioCaptureExtImpl::CaptureFrame(std::vector<int8_t> &frame, uint64_t &replyBytes)
90 {
91     DHLOGI("Render frame. not support in low-latency capture");
92     (void)devAttrs_.sampleRate;
93     (void)devAttrs_.channelCount;
94     (void)devAttrs_.format;
95     return HDF_SUCCESS;
96 }
97 
Start()98 int32_t AudioCaptureExtImpl::Start()
99 {
100     DHLOGI("Start capture mmap.");
101     std::string content;
102     std::initializer_list<std::pair<std::string, std::string>> items = { {KEY_DH_ID, std::to_string(dhId_)} };
103     if (WrapCJsonItem(items, content) != HDF_SUCCESS) {
104         DHLOGE("Wrap the event failed.");
105         return HDF_FAILURE;
106     }
107     DAudioEvent event = { HDF_AUDIO_EVENT_MMAP_START_MIC, content };
108     if (audioExtCallback_ == nullptr) {
109         DHLOGE("Callback is nullptr.");
110         return HDF_FAILURE;
111     }
112     int32_t ret = audioExtCallback_->NotifyEvent(captureId_, event);
113     if (ret != HDF_SUCCESS) {
114         DHLOGE("Start capture mmap failed.");
115         return HDF_FAILURE;
116     }
117     return HDF_SUCCESS;
118 }
119 
Stop()120 int32_t AudioCaptureExtImpl::Stop()
121 {
122     DHLOGI("Stop capture mmap.");
123     std::string content;
124     std::initializer_list<std::pair<std::string, std::string>> items = { {KEY_DH_ID, std::to_string(dhId_)} };
125     if (WrapCJsonItem(items, content) != HDF_SUCCESS) {
126         DHLOGE("Wrap the event failed.");
127         return HDF_FAILURE;
128     }
129     DAudioEvent event = { HDF_AUDIO_EVENT_MMAP_STOP_MIC, content };
130     if (audioExtCallback_ == nullptr) {
131         DHLOGE("Callback is nullptr.");
132         return HDF_FAILURE;
133     }
134     int32_t ret = audioExtCallback_->NotifyEvent(captureId_, event);
135     if (ret != HDF_SUCCESS) {
136         DHLOGE("Stop capture mmap failed.");
137         return HDF_FAILURE;
138     }
139     return HDF_SUCCESS;
140 }
141 
Pause()142 int32_t AudioCaptureExtImpl::Pause()
143 {
144     DHLOGI("Pause capture.");
145     std::lock_guard<std::mutex> captureLck(captureMtx_);
146     captureStatus_ = CAPTURE_STATUS_PAUSE;
147     return HDF_SUCCESS;
148 }
149 
Resume()150 int32_t AudioCaptureExtImpl::Resume()
151 {
152     return HDF_SUCCESS;
153 }
154 
Flush()155 int32_t AudioCaptureExtImpl::Flush()
156 {
157     return HDF_SUCCESS;
158 }
159 
TurnStandbyMode()160 int32_t AudioCaptureExtImpl::TurnStandbyMode()
161 {
162     DHLOGI("Turn stand by mode, not support yet.");
163     return HDF_SUCCESS;
164 }
165 
AudioDevDump(int32_t range,int32_t fd)166 int32_t AudioCaptureExtImpl::AudioDevDump(int32_t range, int32_t fd)
167 {
168     DHLOGI("Dump audio info, not support yet.");
169     (void)range;
170     (void)fd;
171     return HDF_SUCCESS;
172 }
173 
IsSupportsPauseAndResume(bool & supportPause,bool & supportResume)174 int32_t AudioCaptureExtImpl::IsSupportsPauseAndResume(bool &supportPause, bool &supportResume)
175 {
176     DHLOGI("Check whether pause and resume is supported, not support yet.");
177     (void)supportPause;
178     (void)supportResume;
179     return HDF_SUCCESS;
180 }
181 
CheckSceneCapability(const AudioSceneDescriptor & scene,bool & supported)182 int32_t AudioCaptureExtImpl::CheckSceneCapability(const AudioSceneDescriptor &scene, bool &supported)
183 {
184     DHLOGI("Check scene capability.");
185     (void)scene;
186     supported = false;
187     return HDF_SUCCESS;
188 }
189 
SelectScene(const AudioSceneDescriptor & scene)190 int32_t AudioCaptureExtImpl::SelectScene(const AudioSceneDescriptor &scene)
191 {
192     DHLOGI("Select audio scene, not support yet.");
193     (void)scene;
194     return HDF_SUCCESS;
195 }
196 
SetMute(bool mute)197 int32_t AudioCaptureExtImpl::SetMute(bool mute)
198 {
199     DHLOGI("Set mute, not support yet.");
200     (void)mute;
201     return HDF_SUCCESS;
202 }
203 
GetMute(bool & mute)204 int32_t AudioCaptureExtImpl::GetMute(bool &mute)
205 {
206     DHLOGI("Get mute, not support yet.");
207     (void)mute;
208     return HDF_SUCCESS;
209 }
210 
SetVolume(float volume)211 int32_t AudioCaptureExtImpl::SetVolume(float volume)
212 {
213     DHLOGI("Can not set vol not by this interface.");
214     (void)volume;
215     return HDF_SUCCESS;
216 }
217 
GetVolume(float & volume)218 int32_t AudioCaptureExtImpl::GetVolume(float &volume)
219 {
220     DHLOGI("Can not get vol not by this interface.");
221     (void)volume;
222     return HDF_SUCCESS;
223 }
224 
GetGainThreshold(float & min,float & max)225 int32_t AudioCaptureExtImpl::GetGainThreshold(float &min, float &max)
226 {
227     DHLOGI("Get gain threshold, not support yet.");
228     min = 0;
229     max = 0;
230     return HDF_SUCCESS;
231 }
232 
SetGain(float gain)233 int32_t AudioCaptureExtImpl::SetGain(float gain)
234 {
235     DHLOGI("Set gain, not support yet.");
236     (void) gain;
237     return HDF_SUCCESS;
238 }
239 
GetGain(float & gain)240 int32_t AudioCaptureExtImpl::GetGain(float &gain)
241 {
242     DHLOGI("Get gain, not support yet.");
243     gain = 1.0;
244     return HDF_SUCCESS;
245 }
246 
GetFrameSize(uint64_t & size)247 int32_t AudioCaptureExtImpl::GetFrameSize(uint64_t &size)
248 {
249     (void)size;
250     return HDF_SUCCESS;
251 }
252 
GetFrameCount(uint64_t & count)253 int32_t AudioCaptureExtImpl::GetFrameCount(uint64_t &count)
254 {
255     (void)count;
256     return HDF_SUCCESS;
257 }
258 
SetSampleAttributes(const AudioSampleAttributes & attrs)259 int32_t AudioCaptureExtImpl::SetSampleAttributes(const AudioSampleAttributes &attrs)
260 {
261     DHLOGI("Set sample attributes.");
262     devAttrs_ = attrs;
263     return HDF_SUCCESS;
264 }
265 
GetSampleAttributes(AudioSampleAttributes & attrs)266 int32_t AudioCaptureExtImpl::GetSampleAttributes(AudioSampleAttributes &attrs)
267 {
268     DHLOGI("Get sample attributes.");
269     attrs = devAttrs_;
270     return HDF_SUCCESS;
271 }
272 
GetCurrentChannelId(uint32_t & channelId)273 int32_t AudioCaptureExtImpl::GetCurrentChannelId(uint32_t &channelId)
274 {
275     DHLOGI("Get current channel id, not support yet.");
276     (void)channelId;
277     return HDF_SUCCESS;
278 }
279 
SetExtraParams(const std::string & keyValueList)280 int32_t AudioCaptureExtImpl::SetExtraParams(const std::string &keyValueList)
281 {
282     DHLOGI("Set extra parameters, not support yet.");
283     (void)keyValueList;
284     return HDF_SUCCESS;
285 }
286 
GetExtraParams(std::string & keyValueList)287 int32_t AudioCaptureExtImpl::GetExtraParams(std::string &keyValueList)
288 {
289     DHLOGI("Get extra parameters, not support yet.");
290     (void)keyValueList;
291     return HDF_SUCCESS;
292 }
293 
ReqMmapBuffer(int32_t reqSize,AudioMmapBufferDescriptor & desc)294 int32_t AudioCaptureExtImpl::ReqMmapBuffer(int32_t reqSize, AudioMmapBufferDescriptor &desc)
295 {
296     DHLOGI("Request mmap buffer.");
297     int32_t minSize = CalculateSampleNum(devAttrs_.sampleRate, minTimeInterval_);
298     int32_t maxSize = CalculateSampleNum(devAttrs_.sampleRate, maxTimeInterval_);
299     int32_t realSize = reqSize;
300     if (reqSize < minSize) {
301         realSize = minSize;
302     } else if (reqSize > maxSize) {
303         realSize = maxSize;
304     }
305     DHLOGI("ReqMmap buffer realsize : %{public}d, minsize: %{public}d, maxsize:%{public}d.",
306         realSize, minSize, maxSize);
307     desc.totalBufferFrames = realSize;
308     ashmemLength_ = realSize * static_cast<int32_t>(devAttrs_.channelCount) * devAttrs_.format;
309     DHLOGI("Init ashmem real sample size : %{public}d, length: %{public}d.", realSize, ashmemLength_);
310     int32_t ret = InitAshmem(ashmemLength_);
311     if (ret != HDF_SUCCESS) {
312         DHLOGE("Init ashmem error..");
313         return HDF_FAILURE;
314     }
315     desc.memoryFd = fd_;
316     desc.transferFrameSize = static_cast<int32_t>(CalculateSampleNum(devAttrs_.sampleRate, timeInterval_));
317     lengthPerTrans_ = desc.transferFrameSize * static_cast<int32_t>(devAttrs_.channelCount) * devAttrs_.format;
318     desc.isShareable = false;
319     if (audioExtCallback_ == nullptr) {
320         DHLOGE("Callback is nullptr.");
321         return HDF_FAILURE;
322     }
323     ret = audioExtCallback_->RefreshAshmemInfo(captureId_, fd_, ashmemLength_, lengthPerTrans_);
324     if (ret != HDF_SUCCESS) {
325         DHLOGE("Refresh ashmem info failed.");
326         return HDF_FAILURE;
327     }
328     return HDF_SUCCESS;
329 }
330 
GetMmapPosition(uint64_t & frames,AudioTimeStamp & time)331 int32_t AudioCaptureExtImpl::GetMmapPosition(uint64_t &frames, AudioTimeStamp &time)
332 {
333     DHLOGI("Get capture mmap position.");
334     if (audioExtCallback_ == nullptr) {
335         DHLOGE("Callback is nullptr.");
336         return HDF_FAILURE;
337     }
338     CurrentTime cTime;
339     int32_t ret = audioExtCallback_->ReadMmapPosition(captureId_, frames, cTime);
340     if (ret != HDF_SUCCESS) {
341         DHLOGE("Read mmap position failed.");
342         return HDF_FAILURE;
343     }
344     time.tvSec = cTime.tvSec;
345     time.tvNSec = cTime.tvNSec;
346     DHLOGI("Read mmap position. frames: %{public}" PRIu64", tvSec: %{public}" PRId64", tvNSec: %{public}" PRId64,
347         frames, cTime.tvSec, cTime.tvNSec);
348     return HDF_SUCCESS;
349 }
350 
AddAudioEffect(uint64_t effectid)351 int32_t AudioCaptureExtImpl::AddAudioEffect(uint64_t effectid)
352 {
353     DHLOGI("Add audio effect, not support yet.");
354     (void)effectid;
355     return HDF_SUCCESS;
356 }
357 
RemoveAudioEffect(uint64_t effectid)358 int32_t AudioCaptureExtImpl::RemoveAudioEffect(uint64_t effectid)
359 {
360     DHLOGI("Remove audio effect, not support yet.");
361     (void)effectid;
362     return HDF_SUCCESS;
363 }
364 
GetFrameBufferSize(uint64_t & bufferSize)365 int32_t AudioCaptureExtImpl::GetFrameBufferSize(uint64_t &bufferSize)
366 {
367     DHLOGI("Get frame buffer size, not support yet.");
368     (void)bufferSize;
369     return HDF_SUCCESS;
370 }
371 
GetCaptureDesc()372 const AudioDeviceDescriptor &AudioCaptureExtImpl::GetCaptureDesc()
373 {
374     return devDesc_;
375 }
376 
SetAttrs(const std::string & adpName,const AudioDeviceDescriptor & desc,const AudioSampleAttributes & attrs,const sptr<IDAudioCallback> & callback,const int32_t dhId)377 void AudioCaptureExtImpl::SetAttrs(const std::string &adpName, const AudioDeviceDescriptor &desc,
378     const AudioSampleAttributes &attrs, const sptr<IDAudioCallback> &callback, const int32_t dhId)
379 {
380     adapterName_ = adpName;
381     devDesc_ = desc;
382     devAttrs_ = attrs;
383     audioExtCallback_ = callback;
384     dhId_ = dhId;
385     if (attrs.type == AUDIO_MMAP_NOIRQ) {
386         timeInterval_ = AUDIO_MMAP_NOIRQ_INTERVAL;
387     } else if (attrs.type == AUDIO_MMAP_VOIP) {
388         timeInterval_ = AUDIO_MMAP_VOIP_INTERVAL;
389     }
390     devAttrs_.frameSize = CalculateFrameSize(attrs.sampleRate, attrs.channelCount, attrs.format, timeInterval_, true);
391     DHLOGI("Distributed lowlatency capture set attrs, id(%{public}d). framesize(%{public}d)",
392         dhId_, devAttrs_.frameSize);
393 }
394 
SetDumpFlagInner()395 void AudioCaptureExtImpl::SetDumpFlagInner()
396 {
397     DHLOGI("Set dump flag, not support yet.");
398 }
399 
GetCaptureImplExt()400 AudioCaptureInterfaceImplBase *GetCaptureImplExt()
401 {
402     DHLOGI("Get low latency capture impl.");
403     static AudioCaptureExtImpl *implBase = new AudioCaptureExtImpl();
404     return implBase;
405 }
406 } // namespace V1_0
407 } // namespace Audio
408 } // namespace Distributedaudio
409 } // namespace HDI
410 } // namespace OHOS
411