blob: da89e20ba4034e6895f5a97a35643867aaa9e09b [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 Yaoa03533e2023-01-25 06:38:10 +000024#include <media/AidlConversionNdk.h>
25#include <media/AidlConversionEffect.h>
Shunkai Yao44bdbad2023-01-14 05:11:58 +000026
Shunkai Yao284bb0d2023-01-10 00:42:36 +000027#include <utils/Log.h>
28
29#include "EffectConversionHelperAidl.h"
30
31namespace android {
32namespace effect {
33
34using ::aidl::android::aidl_utils::statusTFromBinderStatus;
Shunkai Yao284bb0d2023-01-10 00:42:36 +000035using ::aidl::android::hardware::audio::effect::CommandId;
Shunkai Yao44bdbad2023-01-14 05:11:58 +000036using ::aidl::android::hardware::audio::effect::Descriptor;
Shunkai Yao284bb0d2023-01-10 00:42:36 +000037using ::aidl::android::hardware::audio::effect::Parameter;
38using ::aidl::android::media::audio::common::AudioDeviceDescription;
Shunkai Yao44bdbad2023-01-14 05:11:58 +000039using android::effect::utils::EffectParamReader;
40using android::effect::utils::EffectParamWriter;
Shunkai Yao284bb0d2023-01-10 00:42:36 +000041
42using ::android::status_t;
43
44const std::map<uint32_t /* effect_command_e */, EffectConversionHelperAidl::CommandHandler>
45 EffectConversionHelperAidl::mCommandHandlerMap = {
46 {EFFECT_CMD_INIT, &EffectConversionHelperAidl::handleInit},
47 {EFFECT_CMD_SET_PARAM, &EffectConversionHelperAidl::handleSetParameter},
48 {EFFECT_CMD_GET_PARAM, &EffectConversionHelperAidl::handleGetParameter},
49 {EFFECT_CMD_SET_CONFIG, &EffectConversionHelperAidl::handleSetConfig},
50 {EFFECT_CMD_GET_CONFIG, &EffectConversionHelperAidl::handleGetConfig},
51 {EFFECT_CMD_RESET, &EffectConversionHelperAidl::handleReset},
52 {EFFECT_CMD_ENABLE, &EffectConversionHelperAidl::handleEnable},
53 {EFFECT_CMD_DISABLE, &EffectConversionHelperAidl::handleDisable},
54 {EFFECT_CMD_SET_DEVICE, &EffectConversionHelperAidl::handleSetDevice},
55 {EFFECT_CMD_SET_INPUT_DEVICE, &EffectConversionHelperAidl::handleSetDevice},
56 {EFFECT_CMD_SET_VOLUME, &EffectConversionHelperAidl::handleSetVolume},
57 {EFFECT_CMD_OFFLOAD, &EffectConversionHelperAidl::handleSetOffload},
58 {EFFECT_CMD_FIRST_PROPRIETARY, &EffectConversionHelperAidl::handleFirstPriority}};
59
Shunkai Yao44bdbad2023-01-14 05:11:58 +000060EffectConversionHelperAidl::EffectConversionHelperAidl(
61 std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
Shunkai Yaodba8ba32023-01-27 17:02:21 +000062 int32_t sessionId, int32_t ioId, const Descriptor& desc)
Shunkai Yao44bdbad2023-01-14 05:11:58 +000063 : mSessionId(sessionId), mIoId(ioId), mDesc(desc), mEffect(std::move(effect)) {
64 mCommon.session = sessionId;
65 mCommon.ioHandle = ioId;
66 mCommon.input = mCommon.output = kDefaultAudioConfig;
67}
Shunkai Yao284bb0d2023-01-10 00:42:36 +000068
69status_t EffectConversionHelperAidl::handleCommand(uint32_t cmdCode, uint32_t cmdSize,
70 void* pCmdData, uint32_t* replySize,
71 void* pReplyData) {
72 const auto& handler = mCommandHandlerMap.find(cmdCode);
73 if (handler == mCommandHandlerMap.end() || !handler->second) {
74 ALOGE("%s handler for command %u doesn't exist", __func__, cmdCode);
75 return BAD_VALUE;
76 }
77 return (this->*handler->second)(cmdSize, pCmdData, replySize, pReplyData);
78}
79
80status_t EffectConversionHelperAidl::handleInit(uint32_t cmdSize __unused,
81 const void* pCmdData __unused, uint32_t* replySize,
82 void* pReplyData) {
83 if (!replySize || *replySize < sizeof(int) || !pReplyData) {
84 return BAD_VALUE;
85 }
86
Shunkai Yao44bdbad2023-01-14 05:11:58 +000087 return *(status_t*)pReplyData =
88 statusTFromBinderStatus(mEffect->open(mCommon, std::nullopt, &mOpenReturn));
Shunkai Yao284bb0d2023-01-10 00:42:36 +000089}
90
91status_t EffectConversionHelperAidl::handleSetParameter(uint32_t cmdSize, const void* pCmdData,
92 uint32_t* replySize, void* pReplyData) {
Shunkai Yao44bdbad2023-01-14 05:11:58 +000093 if (cmdSize < sizeof(effect_param_t) || !pCmdData || !replySize ||
94 *replySize < sizeof(int) || !pReplyData) {
Shunkai Yao284bb0d2023-01-10 00:42:36 +000095 return BAD_VALUE;
96 }
97
Shunkai Yao44bdbad2023-01-14 05:11:58 +000098 auto reader = EffectParamReader(*(effect_param_t*)pCmdData);
99 if (!reader.validateCmdSize(cmdSize)) {
100 ALOGE("%s illegal param %s size %u", __func__, reader.toString().c_str(), cmdSize);
Shunkai Yao284bb0d2023-01-10 00:42:36 +0000101 return BAD_VALUE;
102 }
103
Shunkai Yaodba8ba32023-01-27 17:02:21 +0000104 return *(status_t*)pReplyData = setParameter(reader);
Shunkai Yao284bb0d2023-01-10 00:42:36 +0000105}
106
107status_t EffectConversionHelperAidl::handleGetParameter(uint32_t cmdSize, const void* pCmdData,
108 uint32_t* replySize, void* pReplyData) {
Shunkai Yao44bdbad2023-01-14 05:11:58 +0000109 if (cmdSize < sizeof(effect_param_t) || !pCmdData || !replySize || !pReplyData) {
Shunkai Yao284bb0d2023-01-10 00:42:36 +0000110 return BAD_VALUE;
111 }
112
Shunkai Yao44bdbad2023-01-14 05:11:58 +0000113 const auto reader = EffectParamReader(*(effect_param_t*)pCmdData);
Shunkai Yaodba8ba32023-01-27 17:02:21 +0000114 if (!reader.validateCmdSize(cmdSize) ||
115 *replySize < sizeof(effect_param_t) + reader.getParameterSize()) {
116 ALOGE("%s illegal param %s, replySize %u", __func__, reader.toString().c_str(),
Shunkai Yao284bb0d2023-01-10 00:42:36 +0000117 *replySize);
118 return BAD_VALUE;
119 }
120
Shunkai Yaodba8ba32023-01-27 17:02:21 +0000121 // copy effect_param_t and parameters
Shunkai Yao44bdbad2023-01-14 05:11:58 +0000122 memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + reader.getParameterSize());
Shunkai Yaodba8ba32023-01-27 17:02:21 +0000123 auto writer = EffectParamWriter(*(effect_param_t*)pReplyData);
124 status_t ret = getParameter(writer);
125 writer.finishValueWrite();
Shunkai Yao44bdbad2023-01-14 05:11:58 +0000126 *replySize = writer.getTotalSize();
Shunkai Yaodba8ba32023-01-27 17:02:21 +0000127 return ret;
Shunkai Yao284bb0d2023-01-10 00:42:36 +0000128}
129
130status_t EffectConversionHelperAidl::handleSetConfig(uint32_t cmdSize, const void* pCmdData,
131 uint32_t* replySize, void* pReplyData) {
Shunkai Yao44bdbad2023-01-14 05:11:58 +0000132 if (!replySize || *replySize != sizeof(int) || !pReplyData ||
133 cmdSize != sizeof(effect_config_t)) {
Shunkai Yao284bb0d2023-01-10 00:42:36 +0000134 return BAD_VALUE;
135 }
136
137 const auto& legacyConfig = static_cast<const effect_config_t*>(pCmdData);
138 // already open, apply latest settings
Shunkai Yaodba8ba32023-01-27 17:02:21 +0000139 Parameter::Common common;
140 common.input.base =
Shunkai Yao284bb0d2023-01-10 00:42:36 +0000141 VALUE_OR_RETURN_STATUS(::aidl::android::legacy2aidl_buffer_config_t_AudioConfigBase(
142 legacyConfig->inputCfg, true /* isInput */));
Shunkai Yaodba8ba32023-01-27 17:02:21 +0000143 common.output.base =
Shunkai Yao284bb0d2023-01-10 00:42:36 +0000144 VALUE_OR_RETURN_STATUS(::aidl::android::legacy2aidl_buffer_config_t_AudioConfigBase(
145 legacyConfig->outputCfg, false /* isInput */));
Shunkai Yaodba8ba32023-01-27 17:02:21 +0000146 common.session = mSessionId;
147 common.ioHandle = mIoId;
Shunkai Yao284bb0d2023-01-10 00:42:36 +0000148 // TODO: add access mode support
149 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
Shunkai Yaodba8ba32023-01-27 17:02:21 +0000150 mEffect->setParameter(Parameter::make<Parameter::common>(common))));
151 mCommon = 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 Yao44bdbad2023-01-14 05:11:58 +0000181 if (!replySize || *replySize != sizeof(effect_config_t) || !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,
190 const void* pCmdData __unused, uint32_t* replySize,
191 void* pReplyData) {
Shunkai Yao44bdbad2023-01-14 05:11:58 +0000192 if (!replySize || *replySize != sizeof(effect_config_t) || !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 Yao44bdbad2023-01-14 05:11:58 +0000203 if (!replySize || *replySize != sizeof(effect_config_t) || !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
211status_t EffectConversionHelperAidl::handleSetDevice(uint32_t cmdSize, const void* pCmdData,
212 uint32_t* replySize, void* pReplyData) {
Shunkai Yao44bdbad2023-01-14 05:11:58 +0000213 if (cmdSize != sizeof(uint32_t) || !pCmdData || !replySize ||
214 *replySize != sizeof(effect_config_t) || !pReplyData) {
Shunkai Yao284bb0d2023-01-10 00:42:36 +0000215 ALOGE("%s parameter invalid %u %p %p %p", __func__, cmdSize, pCmdData, replySize,
216 pReplyData);
217 return BAD_VALUE;
218 }
219 // TODO: convert from audio_devices_t to std::vector<AudioDeviceDescription>
220 // const auto& legacyDevice = *(uint32_t*)(pCmdData);
221 std::vector<AudioDeviceDescription> aidlDevices;
222 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
223 mEffect->setParameter(Parameter::make<Parameter::deviceDescription>(aidlDevices))));
224 return *static_cast<int32_t*>(pReplyData) = OK;
225}
226
227status_t EffectConversionHelperAidl::handleSetVolume(uint32_t cmdSize, const void* pCmdData,
228 uint32_t* replySize, void* pReplyData) {
229 if (cmdSize != 2 * sizeof(uint32_t) || !pCmdData || !replySize ||
Shunkai Yao44bdbad2023-01-14 05:11:58 +0000230 *replySize != sizeof(effect_config_t) || !pReplyData) {
Shunkai Yao284bb0d2023-01-10 00:42:36 +0000231 ALOGE("%s parameter invalid %u %p %p %p", __func__, cmdSize, pCmdData, replySize,
232 pReplyData);
233 return BAD_VALUE;
234 }
235 Parameter::VolumeStereo volume = {.left = (float)(*(uint32_t*)pCmdData) / (1 << 24),
236 .right = (float)(*(uint32_t*)pCmdData + 1) / (1 << 24)};
237 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
238 mEffect->setParameter(Parameter::make<Parameter::volumeStereo>(volume))));
239 return *static_cast<int32_t*>(pReplyData) = OK;
240}
241
242status_t EffectConversionHelperAidl::handleSetOffload(uint32_t cmdSize, const void* pCmdData,
243 uint32_t* replySize, void* pReplyData) {
244 if (cmdSize < sizeof(effect_offload_param_t) || !pCmdData || !replySize ||
Shunkai Yao44bdbad2023-01-14 05:11:58 +0000245 *replySize != sizeof(effect_config_t) || !pReplyData) {
Shunkai Yao284bb0d2023-01-10 00:42:36 +0000246 ALOGE("%s parameter invalid %u %p %p %p", __func__, cmdSize, pCmdData, replySize,
247 pReplyData);
248 return BAD_VALUE;
249 }
250 // TODO: handle this after effectproxy implemented in libaudiohal
251 return *static_cast<int32_t*>(pReplyData) = OK;
252}
253
254status_t EffectConversionHelperAidl::handleFirstPriority(uint32_t cmdSize __unused,
255 const void* pCmdData __unused,
256 uint32_t* replySize, void* pReplyData) {
Shunkai Yao44bdbad2023-01-14 05:11:58 +0000257 if (!replySize || *replySize != sizeof(effect_config_t) || !pReplyData) {
Shunkai Yao284bb0d2023-01-10 00:42:36 +0000258 ALOGE("%s parameter invalid %p %p", __func__, replySize, pReplyData);
259 return BAD_VALUE;
260 }
261
Shunkai Yao44bdbad2023-01-14 05:11:58 +0000262 // TODO to be implemented
Shunkai Yao284bb0d2023-01-10 00:42:36 +0000263 return OK;
264}
265
Shunkai Yaodba8ba32023-01-27 17:02:21 +0000266} // namespace effect
267} // namespace android