1 /*
2  * Copyright (c) 2022-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 "daudio_manager_callback.h"
17 
18 #include <cstdint>
19 #include <hdf_base.h>
20 #include <securec.h>
21 
22 #include "audio_types.h"
23 
24 #include "daudio_constants.h"
25 #include "daudio_errorcode.h"
26 #include "daudio_log.h"
27 
28 #undef DH_LOG_TAG
29 #define DH_LOG_TAG "DAudioManagerCallback"
30 
31 using OHOS::HDI::DistributedAudio::Audioext::V2_0::AudioParameter;
32 
33 namespace OHOS {
34 namespace DistributedHardware {
CreateStream(int32_t streamId)35 int32_t DAudioManagerCallback::CreateStream(int32_t streamId /* for multistream */)
36 {
37     DHLOGI("Open device.");
38     CHECK_NULL_RETURN(callback_, HDF_FAILURE);
39     if (callback_->CreateStream(streamId) != DH_SUCCESS) {
40         DHLOGE("Call hdi callback failed.");
41         return HDF_FAILURE;
42     }
43     return HDF_SUCCESS;
44 }
45 
DestroyStream(int32_t streamId)46 int32_t DAudioManagerCallback::DestroyStream(int32_t streamId)
47 {
48     DHLOGI("Close device.");
49     CHECK_NULL_RETURN(callback_, HDF_FAILURE);
50     if (callback_->DestroyStream(streamId) != DH_SUCCESS) {
51         DHLOGE("Rall hdi callback failed.");
52         return HDF_FAILURE;
53     }
54     return HDF_SUCCESS;
55 }
56 
GetAudioParamHDF(const AudioParameter & param,AudioParamHDF & paramHDF)57 int32_t DAudioManagerCallback::GetAudioParamHDF(const AudioParameter& param, AudioParamHDF& paramHDF)
58 {
59     paramHDF.sampleRate = static_cast<AudioSampleRate>(param.sampleRate);
60     paramHDF.channelMask = static_cast<AudioChannel>(param.channelCount);
61     switch (static_cast<AudioFormat>(param.format)) {
62         case AUDIO_FORMAT_TYPE_PCM_8_BIT:
63             paramHDF.bitFormat = AudioSampleFormat::SAMPLE_U8;
64             break;
65         case AUDIO_FORMAT_TYPE_PCM_16_BIT:
66             paramHDF.bitFormat = AudioSampleFormat::SAMPLE_S16LE;
67             break;
68         case AUDIO_FORMAT_TYPE_PCM_24_BIT:
69             paramHDF.bitFormat = AudioSampleFormat::SAMPLE_S24LE;
70             break;
71         default:
72             DHLOGE("Format [%{public}" PRIu32"] does not support conversion.", param.format);
73             return HDF_FAILURE;
74     }
75     switch (static_cast<AudioCategory>(param.streamUsage)) {
76         case AUDIO_IN_MEDIA:
77             paramHDF.streamUsage = StreamUsage::STREAM_USAGE_MEDIA;
78             break;
79         case AUDIO_IN_COMMUNICATION:
80         case AUDIO_MMAP_VOIP:
81             paramHDF.streamUsage = StreamUsage::STREAM_USAGE_VOICE_COMMUNICATION;
82             break;
83         case AUDIO_IN_RINGTONE:
84             paramHDF.streamUsage = StreamUsage::STREAM_USAGE_NOTIFICATION_RINGTONE;
85             break;
86         case AUDIO_MMAP_NOIRQ:
87             paramHDF.streamUsage = StreamUsage::STREAM_USAGE_MEDIA;
88             break;
89         default:
90             DHLOGE("Stream usage [%{public}" PRIu32"] does not support conversion.", param.streamUsage);
91             return HDF_FAILURE;
92     }
93     paramHDF.frameSize = param.frameSize;
94     paramHDF.period = param.period;
95     paramHDF.ext = param.ext;
96     paramHDF.renderFlags = static_cast<OHOS::DistributedHardware::PortOperationMode>(param.renderFlags);
97     paramHDF.capturerFlags = static_cast<OHOS::DistributedHardware::PortOperationMode>(param.capturerFlags);
98     DHLOGI("HDF Param: sample rate %{public}d, channel %{public}d, bit format %{public}d, stream "
99         "usage %{public}d, frame size %{public}" PRIu32", period %{public}" PRIu32
100         ", renderFlags %{public}d, capturerFlags %{public}d, ext {%{public}s}.", paramHDF.sampleRate,
101         paramHDF.channelMask, paramHDF.bitFormat, paramHDF.streamUsage, paramHDF.frameSize, paramHDF.period,
102         paramHDF.renderFlags, paramHDF.capturerFlags, paramHDF.ext.c_str());
103     return HDF_SUCCESS;
104 }
105 
SetParameters(int32_t streamId,const AudioParameter & param)106 int32_t DAudioManagerCallback::SetParameters(int32_t streamId, const AudioParameter& param)
107 {
108     DHLOGD("Set Parameters.");
109     CHECK_NULL_RETURN(callback_, HDF_FAILURE);
110     AudioParamHDF paramHDF;
111     int32_t ret = GetAudioParamHDF(param, paramHDF);
112     if (ret != DH_SUCCESS) {
113         DHLOGE("Get audio HDF param failed.");
114         return HDF_FAILURE;
115     }
116     ret = callback_->SetParameters(streamId, paramHDF);
117     if (ret != DH_SUCCESS) {
118         DHLOGE("Call hdi callback failed.");
119         return HDF_FAILURE;
120     }
121     return HDF_SUCCESS;
122 }
123 
NotifyEvent(int32_t streamId,const OHOS::HDI::DistributedAudio::Audioext::V2_0::DAudioEvent & event)124 int32_t DAudioManagerCallback::NotifyEvent(int32_t streamId,
125     const OHOS::HDI::DistributedAudio::Audioext::V2_0::DAudioEvent& event)
126 {
127     DHLOGI("Notify event.");
128     CHECK_NULL_RETURN(callback_, HDF_FAILURE);
129     AudioEvent newEvent(AudioEventType::EVENT_UNKNOWN, event.content);
130     switch (event.type) {
131         case AudioEventHDF::AUDIO_EVENT_VOLUME_SET:
132             newEvent.type = AudioEventType::VOLUME_SET;
133             break;
134         case AudioEventHDF::AUDIO_EVENT_MUTE_SET:
135             newEvent.type = AudioEventType::VOLUME_MUTE_SET;
136             break;
137         case AudioEventHDF::AUDIO_EVENT_CHANGE_PLAY_STATUS:
138             newEvent.type = AudioEventType::CHANGE_PLAY_STATUS;
139             break;
140         case AudioEventHDF::AUDIO_EVENT_MMAP_START_SPK:
141             newEvent.type = AudioEventType::MMAP_SPK_START;
142             break;
143         case AudioEventHDF::AUDIO_EVENT_MMAP_STOP_SPK:
144             newEvent.type = AudioEventType::MMAP_SPK_STOP;
145             break;
146         case AudioEventHDF::AUDIO_EVENT_MMAP_START_MIC:
147             newEvent.type = AudioEventType::MMAP_MIC_START;
148             break;
149         case AudioEventHDF::AUDIO_EVENT_MMAP_STOP_MIC:
150             newEvent.type = AudioEventType::MMAP_MIC_STOP;
151             break;
152         case AudioEventHDF::AUDIO_EVENT_START:
153             newEvent.type = AudioEventType::AUDIO_START;
154             break;
155         case AudioEventHDF::AUDIO_EVENT_STOP:
156             newEvent.type = AudioEventType::AUDIO_STOP;
157             break;
158         default:
159             DHLOGE("Unsupport event tpye.");
160             break;
161     }
162 
163     int32_t ret = callback_->NotifyEvent(streamId, newEvent);
164     if (ret != DH_SUCCESS) {
165         DHLOGE("Call hdi callback failed.");
166         return HDF_FAILURE;
167     }
168     return HDF_SUCCESS;
169 }
170 
WriteStreamData(int32_t streamId,const OHOS::HDI::DistributedAudio::Audioext::V2_0::AudioData & data)171 int32_t DAudioManagerCallback::WriteStreamData(int32_t streamId,
172     const OHOS::HDI::DistributedAudio::Audioext::V2_0::AudioData &data)
173 {
174     DHLOGD("Write Stream Data, audio data param frameSize is %{public}d.", data.param.frameSize);
175     if (data.param.frameSize == 0 || data.param.frameSize > DEFAULT_AUDIO_DATA_SIZE) {
176         DHLOGE("Audio data param frameSize is 0. or > 4096");
177         return HDF_FAILURE;
178     }
179 
180     std::shared_ptr<AudioData> audioData = std::make_shared<AudioData>(data.param.frameSize);
181     int32_t ret = memcpy_s(audioData->Data(), audioData->Capacity(), data.data.data(), data.data.size());
182     if (ret != EOK) {
183         DHLOGE("Copy audio data failed, error code %{public}d.", ret);
184         return HDF_FAILURE;
185     }
186 
187     CHECK_NULL_RETURN(callback_, HDF_FAILURE);
188     if (callback_->WriteStreamData(streamId, audioData) != DH_SUCCESS) {
189         DHLOGE("WriteStreamData failed.");
190         return HDF_FAILURE;
191     }
192     return HDF_SUCCESS;
193 }
194 
ReadStreamData(int32_t streamId,OHOS::HDI::DistributedAudio::Audioext::V2_0::AudioData & data)195 int32_t DAudioManagerCallback::ReadStreamData(int32_t streamId,
196     OHOS::HDI::DistributedAudio::Audioext::V2_0::AudioData &data)
197 {
198     DHLOGD("Read stream data.");
199     std::shared_ptr<AudioData> audioData = nullptr;
200     CHECK_NULL_RETURN(callback_, HDF_FAILURE);
201     if (callback_->ReadStreamData(streamId, audioData) != DH_SUCCESS) {
202         DHLOGE("Read stream data failed.");
203         return HDF_FAILURE;
204     }
205 
206     CHECK_NULL_RETURN(audioData, HDF_FAILURE);
207     data.data.assign(audioData->Data(), audioData->Data()+audioData->Capacity());
208     DHLOGD("Read stream data success.");
209     return HDF_SUCCESS;
210 }
211 
ReadMmapPosition(int32_t streamId,uint64_t & frames,OHOS::HDI::DistributedAudio::Audioext::V2_0::CurrentTime & time)212 int32_t DAudioManagerCallback::ReadMmapPosition(int32_t streamId,
213     uint64_t &frames, OHOS::HDI::DistributedAudio::Audioext::V2_0::CurrentTime &time)
214 {
215     DHLOGD("Read mmap position");
216     CurrentTimeHDF timeHdf;
217     CHECK_NULL_RETURN(callback_, HDF_FAILURE);
218     if (callback_->ReadMmapPosition(streamId, frames, timeHdf) != DH_SUCCESS) {
219         DHLOGE("Read mmap position failed.");
220         return HDF_FAILURE;
221     }
222     time.tvSec = timeHdf.tvSec;
223     time.tvNSec = timeHdf.tvNSec;
224     DHLOGD("Read mmap position success.");
225     return HDF_SUCCESS;
226 }
227 
RefreshAshmemInfo(int32_t streamId,int fd,int32_t ashmemLength,int32_t lengthPerTrans)228 int32_t DAudioManagerCallback::RefreshAshmemInfo(int32_t streamId, int fd, int32_t ashmemLength,
229     int32_t lengthPerTrans)
230 {
231     DHLOGD("Refresh ashmem info.");
232     CHECK_NULL_RETURN(callback_, HDF_FAILURE);
233     if (callback_->RefreshAshmemInfo(streamId, fd, ashmemLength, lengthPerTrans) != DH_SUCCESS) {
234         DHLOGE("Refresh ashmem info failed.");
235         return HDF_FAILURE;
236     }
237     DHLOGD("Refresh ashmem info success.");
238     return HDF_SUCCESS;
239 }
240 } // DistributedHardware
241 } // OHOS
242