blob: dc47d678ea554d80c9d5a4bebf19a4dcfd5b8590 [file] [log] [blame]
Shunkai Yao284bb0d2023-01-10 00:42:36 +00001/*
2 * Copyright (C) 2023 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <cstdint>
18#include <cstring>
Shunkai Yao44bdbad2023-01-14 05:11:58 +000019#include <optional>
Shunkai Yao284bb0d2023-01-10 00:42:36 +000020#define LOG_TAG "EffectConversionHelperAidl"
21//#define LOG_NDEBUG 0
22
23#include <error/expected_utils.h>
Shunkai Yao242521c2023-01-29 18:08:09 +000024#include <media/AidlConversionCppNdk.h>
Shunkai Yaoa03533e2023-01-25 06:38:10 +000025#include <media/AidlConversionNdk.h>
26#include <media/AidlConversionEffect.h>
Shunkai Yao04b073a2023-02-17 06:17:12 +000027#include <system/audio_effects/effect_visualizer.h>
Shunkai Yao44bdbad2023-01-14 05:11:58 +000028
Shunkai Yao284bb0d2023-01-10 00:42:36 +000029#include <utils/Log.h>
30
31#include "EffectConversionHelperAidl.h"
32
33namespace android {
34namespace effect {
35
36using ::aidl::android::aidl_utils::statusTFromBinderStatus;
Shunkai Yao284bb0d2023-01-10 00:42:36 +000037using ::aidl::android::hardware::audio::effect::CommandId;
Shunkai Yao44bdbad2023-01-14 05:11:58 +000038using ::aidl::android::hardware::audio::effect::Descriptor;
Shunkai Yao284bb0d2023-01-10 00:42:36 +000039using ::aidl::android::hardware::audio::effect::Parameter;
40using ::aidl::android::media::audio::common::AudioDeviceDescription;
Shunkai Yao242521c2023-01-29 18:08:09 +000041using ::aidl::android::media::audio::common::AudioMode;
42using ::aidl::android::media::audio::common::AudioSource;
Shunkai Yao44bdbad2023-01-14 05:11:58 +000043using android::effect::utils::EffectParamReader;
44using android::effect::utils::EffectParamWriter;
Shunkai Yao284bb0d2023-01-10 00:42:36 +000045
46using ::android::status_t;
47
48const std::map<uint32_t /* effect_command_e */, EffectConversionHelperAidl::CommandHandler>
49 EffectConversionHelperAidl::mCommandHandlerMap = {
50 {EFFECT_CMD_INIT, &EffectConversionHelperAidl::handleInit},
51 {EFFECT_CMD_SET_PARAM, &EffectConversionHelperAidl::handleSetParameter},
52 {EFFECT_CMD_GET_PARAM, &EffectConversionHelperAidl::handleGetParameter},
53 {EFFECT_CMD_SET_CONFIG, &EffectConversionHelperAidl::handleSetConfig},
54 {EFFECT_CMD_GET_CONFIG, &EffectConversionHelperAidl::handleGetConfig},
55 {EFFECT_CMD_RESET, &EffectConversionHelperAidl::handleReset},
56 {EFFECT_CMD_ENABLE, &EffectConversionHelperAidl::handleEnable},
57 {EFFECT_CMD_DISABLE, &EffectConversionHelperAidl::handleDisable},
Shunkai Yao242521c2023-01-29 18:08:09 +000058 {EFFECT_CMD_SET_AUDIO_SOURCE, &EffectConversionHelperAidl::handleSetAudioSource},
Shunkai Yao284bb0d2023-01-10 00:42:36 +000059 {EFFECT_CMD_SET_DEVICE, &EffectConversionHelperAidl::handleSetDevice},
60 {EFFECT_CMD_SET_INPUT_DEVICE, &EffectConversionHelperAidl::handleSetDevice},
61 {EFFECT_CMD_SET_VOLUME, &EffectConversionHelperAidl::handleSetVolume},
62 {EFFECT_CMD_OFFLOAD, &EffectConversionHelperAidl::handleSetOffload},
Shunkai Yao04b073a2023-02-17 06:17:12 +000063 {EFFECT_CMD_FIRST_PROPRIETARY, &EffectConversionHelperAidl::handleFirstPriority},
64 // Only visualizer support these commands
65 {VISUALIZER_CMD_CAPTURE, &EffectConversionHelperAidl::handleVisualizerCapture},
66 {VISUALIZER_CMD_MEASURE, &EffectConversionHelperAidl::handleVisualizerMeasure}};
Shunkai Yao284bb0d2023-01-10 00:42:36 +000067
Shunkai Yao44bdbad2023-01-14 05:11:58 +000068EffectConversionHelperAidl::EffectConversionHelperAidl(
69 std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
Shunkai Yaodba8ba32023-01-27 17:02:21 +000070 int32_t sessionId, int32_t ioId, const Descriptor& desc)
Shunkai Yao44bdbad2023-01-14 05:11:58 +000071 : mSessionId(sessionId), mIoId(ioId), mDesc(desc), mEffect(std::move(effect)) {
72 mCommon.session = sessionId;
73 mCommon.ioHandle = ioId;
74 mCommon.input = mCommon.output = kDefaultAudioConfig;
75}
Shunkai Yao284bb0d2023-01-10 00:42:36 +000076
77status_t EffectConversionHelperAidl::handleCommand(uint32_t cmdCode, uint32_t cmdSize,
78 void* pCmdData, uint32_t* replySize,
79 void* pReplyData) {
80 const auto& handler = mCommandHandlerMap.find(cmdCode);
81 if (handler == mCommandHandlerMap.end() || !handler->second) {
82 ALOGE("%s handler for command %u doesn't exist", __func__, cmdCode);
83 return BAD_VALUE;
84 }
85 return (this->*handler->second)(cmdSize, pCmdData, replySize, pReplyData);
86}
87
88status_t EffectConversionHelperAidl::handleInit(uint32_t cmdSize __unused,
89 const void* pCmdData __unused, uint32_t* replySize,
90 void* pReplyData) {
91 if (!replySize || *replySize < sizeof(int) || !pReplyData) {
92 return BAD_VALUE;
93 }
94
Shunkai Yao44bdbad2023-01-14 05:11:58 +000095 return *(status_t*)pReplyData =
96 statusTFromBinderStatus(mEffect->open(mCommon, std::nullopt, &mOpenReturn));
Shunkai Yao284bb0d2023-01-10 00:42:36 +000097}
98
99status_t EffectConversionHelperAidl::handleSetParameter(uint32_t cmdSize, const void* pCmdData,
100 uint32_t* replySize, void* pReplyData) {
Shunkai Yao44bdbad2023-01-14 05:11:58 +0000101 if (cmdSize < sizeof(effect_param_t) || !pCmdData || !replySize ||
102 *replySize < sizeof(int) || !pReplyData) {
Shunkai Yao284bb0d2023-01-10 00:42:36 +0000103 return BAD_VALUE;
104 }
105
Shunkai Yao44bdbad2023-01-14 05:11:58 +0000106 auto reader = EffectParamReader(*(effect_param_t*)pCmdData);
107 if (!reader.validateCmdSize(cmdSize)) {
108 ALOGE("%s illegal param %s size %u", __func__, reader.toString().c_str(), cmdSize);
Shunkai Yao284bb0d2023-01-10 00:42:36 +0000109 return BAD_VALUE;
110 }
111
Shunkai Yao242521c2023-01-29 18:08:09 +0000112 status_t ret = setParameter(reader);
113 EffectParamWriter writer(*(effect_param_t*)pReplyData);
114 writer.setStatus(ret);
115 return *(status_t*)pReplyData = ret;
Shunkai Yao284bb0d2023-01-10 00:42:36 +0000116}
117
118status_t EffectConversionHelperAidl::handleGetParameter(uint32_t cmdSize, const void* pCmdData,
119 uint32_t* replySize, void* pReplyData) {
Shunkai Yao44bdbad2023-01-14 05:11:58 +0000120 if (cmdSize < sizeof(effect_param_t) || !pCmdData || !replySize || !pReplyData) {
Shunkai Yao284bb0d2023-01-10 00:42:36 +0000121 return BAD_VALUE;
122 }
123
Shunkai Yao44bdbad2023-01-14 05:11:58 +0000124 const auto reader = EffectParamReader(*(effect_param_t*)pCmdData);
Shunkai Yao242521c2023-01-29 18:08:09 +0000125 if (*replySize < sizeof(effect_param_t) + reader.getParameterSize()) {
126 ALOGE("%s illegal param %s, replySize %u", __func__, reader.toString().c_str(), *replySize);
Shunkai Yao284bb0d2023-01-10 00:42:36 +0000127 return BAD_VALUE;
128 }
129
Shunkai Yaodba8ba32023-01-27 17:02:21 +0000130 // copy effect_param_t and parameters
Shunkai Yao44bdbad2023-01-14 05:11:58 +0000131 memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + reader.getParameterSize());
Shunkai Yaodba8ba32023-01-27 17:02:21 +0000132 auto writer = EffectParamWriter(*(effect_param_t*)pReplyData);
133 status_t ret = getParameter(writer);
134 writer.finishValueWrite();
Shunkai Yao242521c2023-01-29 18:08:09 +0000135 writer.setStatus(ret);
Shunkai Yao44bdbad2023-01-14 05:11:58 +0000136 *replySize = writer.getTotalSize();
Shunkai Yao242521c2023-01-29 18:08:09 +0000137 if (ret != OK) {
138 ALOGE("%s error ret %d, %s", __func__, ret, writer.toString().c_str());
139 }
Shunkai Yaodba8ba32023-01-27 17:02:21 +0000140 return ret;
Shunkai Yao284bb0d2023-01-10 00:42:36 +0000141}
142
Shunkai Yao3ecc3eb2023-02-08 19:50:16 +0000143status_t EffectConversionHelperAidl::handleSetConfig(uint32_t cmdSize,
144 const void* pCmdData __unused,
Shunkai Yao284bb0d2023-01-10 00:42:36 +0000145 uint32_t* replySize, void* pReplyData) {
Shunkai Yao44bdbad2023-01-14 05:11:58 +0000146 if (!replySize || *replySize != sizeof(int) || !pReplyData ||
147 cmdSize != sizeof(effect_config_t)) {
Shunkai Yao284bb0d2023-01-10 00:42:36 +0000148 return BAD_VALUE;
149 }
150
Shunkai Yao3ecc3eb2023-02-08 19:50:16 +0000151 // TODO: need to implement setConfig with setParameter(common)
Shunkai Yao284bb0d2023-01-10 00:42:36 +0000152 return *static_cast<int32_t*>(pReplyData) = OK;
153}
154
155status_t EffectConversionHelperAidl::handleGetConfig(uint32_t cmdSize __unused,
156 const void* pCmdData __unused,
157 uint32_t* replySize, void* pReplyData) {
Shunkai Yao44bdbad2023-01-14 05:11:58 +0000158 if (!replySize || *replySize != sizeof(effect_config_t) || !pReplyData) {
Shunkai Yao284bb0d2023-01-10 00:42:36 +0000159 ALOGE("%s parameter invalid %p %p", __func__, replySize, pReplyData);
160 return BAD_VALUE;
161 }
162
163 Parameter param;
164 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(
165 Parameter::Id::make<Parameter::Id::commonTag>(Parameter::common), &param)));
166
167 const auto& common = param.get<Parameter::common>();
168 effect_config_t* pConfig = (effect_config_t*)pReplyData;
169 pConfig->inputCfg = VALUE_OR_RETURN_STATUS(
170 ::aidl::android::aidl2legacy_AudioConfigBase_buffer_config_t(common.input.base, true));
171 pConfig->outputCfg =
172 VALUE_OR_RETURN_STATUS(::aidl::android::aidl2legacy_AudioConfigBase_buffer_config_t(
173 common.output.base, false));
Shunkai Yaodba8ba32023-01-27 17:02:21 +0000174 mCommon = common;
Shunkai Yao284bb0d2023-01-10 00:42:36 +0000175 return OK;
176}
177
178status_t EffectConversionHelperAidl::handleReset(uint32_t cmdSize __unused,
179 const void* pCmdData __unused, uint32_t* replySize,
180 void* pReplyData) {
Shunkai Yao242521c2023-01-29 18:08:09 +0000181 if (!replySize || !pReplyData) {
Shunkai Yao284bb0d2023-01-10 00:42:36 +0000182 ALOGE("%s parameter invalid %p %p", __func__, replySize, pReplyData);
183 return BAD_VALUE;
184 }
185
Shunkai Yao44bdbad2023-01-14 05:11:58 +0000186 return statusTFromBinderStatus(mEffect->command(CommandId::RESET));
Shunkai Yao284bb0d2023-01-10 00:42:36 +0000187}
188
189status_t EffectConversionHelperAidl::handleEnable(uint32_t cmdSize __unused,
Shunkai Yao242521c2023-01-29 18:08:09 +0000190 const void* pCmdData __unused,
191 uint32_t* replySize, void* pReplyData) {
192 if (!replySize || !pReplyData) {
Shunkai Yao284bb0d2023-01-10 00:42:36 +0000193 ALOGE("%s parameter invalid %p %p", __func__, replySize, pReplyData);
194 return BAD_VALUE;
195 }
196
Shunkai Yao44bdbad2023-01-14 05:11:58 +0000197 return statusTFromBinderStatus(mEffect->command(CommandId::START));
Shunkai Yao284bb0d2023-01-10 00:42:36 +0000198}
199
200status_t EffectConversionHelperAidl::handleDisable(uint32_t cmdSize __unused,
201 const void* pCmdData __unused,
202 uint32_t* replySize, void* pReplyData) {
Shunkai Yao242521c2023-01-29 18:08:09 +0000203 if (!replySize || !pReplyData) {
Shunkai Yao284bb0d2023-01-10 00:42:36 +0000204 ALOGE("%s parameter invalid %p %p", __func__, replySize, pReplyData);
205 return BAD_VALUE;
206 }
207
Shunkai Yao44bdbad2023-01-14 05:11:58 +0000208 return statusTFromBinderStatus(mEffect->command(CommandId::STOP));
Shunkai Yao284bb0d2023-01-10 00:42:36 +0000209}
210
Shunkai Yao242521c2023-01-29 18:08:09 +0000211status_t EffectConversionHelperAidl::handleSetAudioSource(uint32_t cmdSize, const void* pCmdData,
212 uint32_t* replySize, void* pReplyData) {
213 if (cmdSize != sizeof(uint32_t) || !pCmdData || !replySize || !pReplyData) {
214 ALOGE("%s parameter invalid %u %p %p %p", __func__, cmdSize, pCmdData, replySize,
215 pReplyData);
216 return BAD_VALUE;
217 }
218
219 audio_source_t source = *(audio_source_t*)pCmdData;
220 AudioSource aidlSource =
221 VALUE_OR_RETURN_STATUS(::aidl::android::legacy2aidl_audio_source_t_AudioSource(source));
222 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
223 mEffect->setParameter(Parameter::make<Parameter::source>(aidlSource))));
224 return *static_cast<int32_t*>(pReplyData) = OK;
225}
226
227status_t EffectConversionHelperAidl::handleSetAudioMode(uint32_t cmdSize, const void* pCmdData,
228 uint32_t* replySize, void* pReplyData) {
229 if (cmdSize != sizeof(uint32_t) || !pCmdData || !replySize || !pReplyData) {
230 ALOGE("%s parameter invalid %u %p %p %p", __func__, cmdSize, pCmdData, replySize,
231 pReplyData);
232 return BAD_VALUE;
233 }
234 audio_mode_t mode = *(audio_mode_t *)pCmdData;
235 AudioMode aidlMode =
236 VALUE_OR_RETURN_STATUS(::aidl::android::legacy2aidl_audio_mode_t_AudioMode(mode));
237 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
238 mEffect->setParameter(Parameter::make<Parameter::mode>(aidlMode))));
239 return *static_cast<int32_t*>(pReplyData) = OK;
240}
241
Shunkai Yao284bb0d2023-01-10 00:42:36 +0000242status_t EffectConversionHelperAidl::handleSetDevice(uint32_t cmdSize, const void* pCmdData,
243 uint32_t* replySize, void* pReplyData) {
Shunkai Yao242521c2023-01-29 18:08:09 +0000244 if (cmdSize != sizeof(uint32_t) || !pCmdData || !replySize || !pReplyData) {
Shunkai Yao284bb0d2023-01-10 00:42:36 +0000245 ALOGE("%s parameter invalid %u %p %p %p", __func__, cmdSize, pCmdData, replySize,
246 pReplyData);
247 return BAD_VALUE;
248 }
249 // TODO: convert from audio_devices_t to std::vector<AudioDeviceDescription>
250 // const auto& legacyDevice = *(uint32_t*)(pCmdData);
251 std::vector<AudioDeviceDescription> aidlDevices;
252 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
253 mEffect->setParameter(Parameter::make<Parameter::deviceDescription>(aidlDevices))));
254 return *static_cast<int32_t*>(pReplyData) = OK;
255}
Shunkai Yao284bb0d2023-01-10 00:42:36 +0000256status_t EffectConversionHelperAidl::handleSetVolume(uint32_t cmdSize, const void* pCmdData,
257 uint32_t* replySize, void* pReplyData) {
Shunkai Yao242521c2023-01-29 18:08:09 +0000258 if (cmdSize != 2 * sizeof(uint32_t) || !pCmdData || !replySize || !pReplyData) {
Shunkai Yao284bb0d2023-01-10 00:42:36 +0000259 ALOGE("%s parameter invalid %u %p %p %p", __func__, cmdSize, pCmdData, replySize,
260 pReplyData);
261 return BAD_VALUE;
262 }
263 Parameter::VolumeStereo volume = {.left = (float)(*(uint32_t*)pCmdData) / (1 << 24),
264 .right = (float)(*(uint32_t*)pCmdData + 1) / (1 << 24)};
265 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
266 mEffect->setParameter(Parameter::make<Parameter::volumeStereo>(volume))));
267 return *static_cast<int32_t*>(pReplyData) = OK;
268}
269
270status_t EffectConversionHelperAidl::handleSetOffload(uint32_t cmdSize, const void* pCmdData,
271 uint32_t* replySize, void* pReplyData) {
Shunkai Yao242521c2023-01-29 18:08:09 +0000272 if (cmdSize < sizeof(effect_offload_param_t) || !pCmdData || !replySize || !pReplyData) {
Shunkai Yao284bb0d2023-01-10 00:42:36 +0000273 ALOGE("%s parameter invalid %u %p %p %p", __func__, cmdSize, pCmdData, replySize,
274 pReplyData);
275 return BAD_VALUE;
276 }
277 // TODO: handle this after effectproxy implemented in libaudiohal
278 return *static_cast<int32_t*>(pReplyData) = OK;
279}
280
281status_t EffectConversionHelperAidl::handleFirstPriority(uint32_t cmdSize __unused,
282 const void* pCmdData __unused,
283 uint32_t* replySize, void* pReplyData) {
Shunkai Yao242521c2023-01-29 18:08:09 +0000284 if (!replySize || !pReplyData) {
Shunkai Yao284bb0d2023-01-10 00:42:36 +0000285 ALOGE("%s parameter invalid %p %p", __func__, replySize, pReplyData);
286 return BAD_VALUE;
287 }
288
Shunkai Yao44bdbad2023-01-14 05:11:58 +0000289 // TODO to be implemented
Shunkai Yao284bb0d2023-01-10 00:42:36 +0000290 return OK;
291}
292
Shunkai Yao04b073a2023-02-17 06:17:12 +0000293status_t EffectConversionHelperAidl::handleVisualizerCapture(uint32_t cmdSize __unused,
294 const void* pCmdData __unused,
295 uint32_t* replySize,
296 void* pReplyData) {
297 if (!replySize || !pReplyData) {
298 ALOGE("%s parameter invalid %p %p", __func__, replySize, pReplyData);
299 return BAD_VALUE;
300 }
301
302 const auto& uuid = VALUE_OR_RETURN_STATUS(
303 ::aidl::android::aidl2legacy_AudioUuid_audio_uuid_t(mDesc.common.id.type));
304 if (0 != memcmp(&uuid, SL_IID_VISUALIZATION, sizeof(effect_uuid_t))) {
305 ALOGE("%s visualizer command not supported by %s", __func__,
306 mDesc.common.id.toString().c_str());
307 return BAD_VALUE;
308 }
309
310 return visualizerCapture(replySize, pReplyData);
311}
312
313status_t EffectConversionHelperAidl::handleVisualizerMeasure(uint32_t cmdSize __unused,
314 const void* pCmdData __unused,
315 uint32_t* replySize,
316 void* pReplyData) {
317 if (!replySize || !pReplyData) {
318 ALOGE("%s parameter invalid %p %p", __func__, replySize, pReplyData);
319 return BAD_VALUE;
320 }
321
322 const auto& uuid = VALUE_OR_RETURN_STATUS(
323 ::aidl::android::aidl2legacy_AudioUuid_audio_uuid_t(mDesc.common.id.type));
324 if (0 != memcmp(&uuid, SL_IID_VISUALIZATION, sizeof(effect_uuid_t))) {
325 ALOGE("%s visualizer command not supported by %s", __func__,
326 mDesc.common.id.toString().c_str());
327 return BAD_VALUE;
328 }
329
330 return visualizerMeasure(replySize, pReplyData);
331}
332
Shunkai Yaodba8ba32023-01-27 17:02:21 +0000333} // namespace effect
334} // namespace android