1 /*
2 * Copyright (C) 2022 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 <algorithm>
18 #include <cstddef>
19 #include <cstdint>
20 #include <iterator>
21 #include <memory>
22 #define LOG_TAG "EffectsFactoryHalAidl"
23 //#define LOG_NDEBUG 0
24
25 #include <error/expected_utils.h>
26 #include <aidl/android/media/audio/common/AudioStreamType.h>
27 #include <android/binder_manager.h>
28 #include <com_android_media_audio.h>
29 #include <media/AidlConversionCppNdk.h>
30 #include <media/AidlConversionEffect.h>
31 #include <system/audio.h>
32 #include <system/audio_aidl_utils.h>
33 #include <system/audio_effects/effect_uuid.h>
34 #include <utils/Log.h>
35
36 #include "AidlUtils.h"
37 #include "EffectBufferHalAidl.h"
38 #include "EffectHalAidl.h"
39 #include "EffectProxy.h"
40 #include "EffectsFactoryHalAidl.h"
41
42 using ::aidl::android::legacy2aidl_audio_uuid_t_AudioUuid;
43 using ::aidl::android::aidl_utils::statusTFromBinderStatus;
44 using ::aidl::android::hardware::audio::effect::Descriptor;
45 using ::aidl::android::hardware::audio::effect::IFactory;
46 using ::aidl::android::hardware::audio::effect::Processing;
47 using ::aidl::android::media::audio::common::AudioDevice;
48 using ::aidl::android::media::audio::common::AudioDeviceAddress;
49 using ::aidl::android::media::audio::common::AudioSource;
50 using ::aidl::android::media::audio::common::AudioStreamType;
51 using ::aidl::android::media::audio::common::AudioUuid;
52 using ::android::audio::utils::toString;
53 using ::android::base::unexpected;
54 using ::android::detail::AudioHalVersionInfo;
55
56 namespace android {
57 namespace effect {
58
EffectsFactoryHalAidl(std::shared_ptr<IFactory> effectsFactory)59 EffectsFactoryHalAidl::EffectsFactoryHalAidl(std::shared_ptr<IFactory> effectsFactory)
60 : mFactory(effectsFactory),
61 mHalVersion(AudioHalVersionInfo(
62 AudioHalVersionInfo::Type::AIDL,
63 [this]() {
64 int32_t majorVersion = 0;
65 return (mFactory && mFactory->getInterfaceVersion(&majorVersion).isOk())
66 ? majorVersion
67 : 0;
68 }())),
__anonc260a4e00202() 69 mHalDescList([this]() {
70 std::vector<Descriptor> list;
71 if (mFactory) {
72 mFactory->queryEffects(std::nullopt, std::nullopt, std::nullopt, &list).isOk();
73 filterHalDescriptors(list);
74 }
75 return list;
76 }()),
__anonc260a4e00302() 77 mProxyUuidDescriptorMap([this]() {
78 std::map<AudioUuid, std::vector<Descriptor>> proxyUuidMap;
79 for (const auto& desc : mHalDescList) {
80 if (desc.common.id.proxy.has_value()) {
81 const auto& uuid = desc.common.id.proxy.value();
82 if (proxyUuidMap.count(uuid) == 0) {
83 proxyUuidMap.insert({uuid, {desc}});
84 } else {
85 proxyUuidMap[uuid].emplace_back(desc);
86 }
87 }
88 }
89 return proxyUuidMap;
90 }()),
__anonc260a4e00402() 91 mProxyDescList([this]() {
92 std::vector<Descriptor> list;
93 for (const auto& proxy : mProxyUuidDescriptorMap) {
94 if (Descriptor desc;
95 EffectProxy::buildDescriptor(proxy.first /* uuid */,
96 proxy.second /* sub-effect descriptor list */,
97 &desc /* proxy descriptor */)
98 .isOk()) {
99 list.emplace_back(std::move(desc));
100 }
101 }
102 return list;
103 }()),
__anonc260a4e00502() 104 mNonProxyDescList([this]() {
105 std::vector<Descriptor> list;
106 std::copy_if(mHalDescList.begin(), mHalDescList.end(), std::back_inserter(list),
107 [](const Descriptor& desc) { return !desc.common.id.proxy.has_value(); });
108 return list;
109 }()),
110 mEffectCount(mNonProxyDescList.size() + mProxyDescList.size()),
__anonc260a4e00702() 111 mAidlProcessings([this]() -> std::vector<Processing> {
112 std::vector<Processing> processings;
113 if (!mFactory || !mFactory->queryProcessing(std::nullopt, &processings).isOk()) {
114 ALOGE("%s queryProcessing failed", __func__);
115 }
116 return processings;
117 }()) {
118 ALOG_ASSERT(mFactory != nullptr, "Provided IEffectsFactory service is NULL");
119 ALOGI("%s with %zu nonProxyEffects and %zu proxyEffects", __func__, mNonProxyDescList.size(),
120 mProxyDescList.size());
121 }
122
queryNumberEffects(uint32_t * pNumEffects)123 status_t EffectsFactoryHalAidl::queryNumberEffects(uint32_t *pNumEffects) {
124 if (pNumEffects == nullptr) {
125 return BAD_VALUE;
126 }
127
128 *pNumEffects = mEffectCount;
129 return OK;
130 }
131
getDescriptor(uint32_t index,effect_descriptor_t * pDescriptor)132 status_t EffectsFactoryHalAidl::getDescriptor(uint32_t index, effect_descriptor_t* pDescriptor) {
133 if (pDescriptor == nullptr) {
134 return BAD_VALUE;
135 }
136
137 if (index >= mEffectCount) {
138 ALOGE("%s index %d exceed max number %zu", __func__, index, mEffectCount);
139 return INVALID_OPERATION;
140 }
141
142 if (index >= mNonProxyDescList.size()) {
143 *pDescriptor =
144 VALUE_OR_RETURN_STATUS(::aidl::android::aidl2legacy_Descriptor_effect_descriptor(
145 mProxyDescList.at(index - mNonProxyDescList.size())));
146 } else {
147 *pDescriptor =
148 VALUE_OR_RETURN_STATUS(::aidl::android::aidl2legacy_Descriptor_effect_descriptor(
149 mNonProxyDescList.at(index)));
150 }
151 return OK;
152 }
153
getDescriptor(const effect_uuid_t * halUuid,effect_descriptor_t * pDescriptor)154 status_t EffectsFactoryHalAidl::getDescriptor(const effect_uuid_t* halUuid,
155 effect_descriptor_t* pDescriptor) {
156 if (halUuid == nullptr) {
157 return BAD_VALUE;
158 }
159
160 AudioUuid uuid =
161 VALUE_OR_RETURN_STATUS(::aidl::android::legacy2aidl_audio_uuid_t_AudioUuid(*halUuid));
162 return getHalDescriptorWithImplUuid(uuid, pDescriptor);
163 }
164
getDescriptors(const effect_uuid_t * halType,std::vector<effect_descriptor_t> * descriptors)165 status_t EffectsFactoryHalAidl::getDescriptors(const effect_uuid_t* halType,
166 std::vector<effect_descriptor_t>* descriptors) {
167 if (halType == nullptr) {
168 return BAD_VALUE;
169 }
170
171 AudioUuid type =
172 VALUE_OR_RETURN_STATUS(::aidl::android::legacy2aidl_audio_uuid_t_AudioUuid(*halType));
173 return getHalDescriptorWithTypeUuid(type, descriptors);
174 }
175
createEffect(const effect_uuid_t * uuid,int32_t sessionId,int32_t ioId,int32_t deviceId __unused,sp<EffectHalInterface> * effect)176 status_t EffectsFactoryHalAidl::createEffect(const effect_uuid_t* uuid, int32_t sessionId,
177 int32_t ioId, int32_t deviceId __unused,
178 sp<EffectHalInterface>* effect) {
179 if (uuid == nullptr || effect == nullptr) {
180 return BAD_VALUE;
181 }
182 ALOGV("%s session %d ioId %d", __func__, sessionId, ioId);
183
184 AudioUuid aidlUuid =
185 VALUE_OR_RETURN_STATUS(::aidl::android::legacy2aidl_audio_uuid_t_AudioUuid(*uuid));
186 if (!com_android_media_audio_audio_eraser_effect() && isAudioEraser(aidlUuid)) {
187 ALOGE("%s Audio eraser effect not supported yet", __func__);
188 return BAD_VALUE;
189 }
190
191 std::shared_ptr<IEffect> aidlEffect;
192 // Use EffectProxy interface instead of IFactory to create
193 const bool isProxy = isProxyEffect(aidlUuid);
194 if (isProxy) {
195 aidlEffect = ndk::SharedRefBase::make<EffectProxy>(
196 aidlUuid, mProxyUuidDescriptorMap.at(aidlUuid) /* sub-effect descriptor list */,
197 mFactory);
198 } else {
199 RETURN_STATUS_IF_ERROR(
200 statusTFromBinderStatus(mFactory->createEffect(aidlUuid, &aidlEffect)));
201 }
202 if (aidlEffect == nullptr) {
203 ALOGE("%s failed to create effect with UUID: %s", __func__, toString(aidlUuid).c_str());
204 return NAME_NOT_FOUND;
205 }
206 Descriptor desc;
207 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(aidlEffect->getDescriptor(&desc)));
208
209 *effect = sp<EffectHalAidl>::make(mFactory, aidlEffect, sessionId, ioId, desc, isProxy);
210 return OK;
211 }
212
dumpEffects(int fd)213 status_t EffectsFactoryHalAidl::dumpEffects(int fd) {
214 // TODO: b/333803769 improve the effect dump implementation
215 RETURN_STATUS_IF_ERROR(mFactory->dump(fd, nullptr, 0));
216 return OK;
217 }
218
allocateBuffer(size_t size,sp<EffectBufferHalInterface> * buffer)219 status_t EffectsFactoryHalAidl::allocateBuffer(size_t size, sp<EffectBufferHalInterface>* buffer) {
220 return EffectBufferHalAidl::allocate(size, buffer);
221 }
222
mirrorBuffer(void * external,size_t size,sp<EffectBufferHalInterface> * buffer)223 status_t EffectsFactoryHalAidl::mirrorBuffer(void* external, size_t size,
224 sp<EffectBufferHalInterface>* buffer) {
225 return EffectBufferHalAidl::mirror(external, size, buffer);
226 }
227
getHalVersion() const228 AudioHalVersionInfo EffectsFactoryHalAidl::getHalVersion() const {
229 return mHalVersion;
230 }
231
getHalDescriptorWithImplUuid(const AudioUuid & uuid,effect_descriptor_t * pDescriptor)232 status_t EffectsFactoryHalAidl::getHalDescriptorWithImplUuid(const AudioUuid& uuid,
233 effect_descriptor_t* pDescriptor) {
234 if (pDescriptor == nullptr) {
235 return BAD_VALUE;
236 }
237
238 const auto& list = isProxyEffect(uuid) ? mProxyDescList : mNonProxyDescList;
239 auto matchIt = std::find_if(list.begin(), list.end(),
240 [&](const auto& desc) { return desc.common.id.uuid == uuid; });
241 if (matchIt == list.end()) {
242 ALOGE("%s UUID not found in HAL and proxy list %s", __func__, toString(uuid).c_str());
243 return NAME_NOT_FOUND;
244 }
245
246 *pDescriptor = VALUE_OR_RETURN_STATUS(
247 ::aidl::android::aidl2legacy_Descriptor_effect_descriptor(*matchIt));
248 return OK;
249 }
250
getHalDescriptorWithTypeUuid(const AudioUuid & type,std::vector<effect_descriptor_t> * descriptors)251 status_t EffectsFactoryHalAidl::getHalDescriptorWithTypeUuid(
252 const AudioUuid& type, std::vector<effect_descriptor_t>* descriptors) {
253 if (descriptors == nullptr) {
254 return BAD_VALUE;
255 }
256
257 std::vector<Descriptor> result;
258 std::copy_if(mNonProxyDescList.begin(), mNonProxyDescList.end(), std::back_inserter(result),
259 [&](auto& desc) { return desc.common.id.type == type; });
260 std::copy_if(mProxyDescList.begin(), mProxyDescList.end(), std::back_inserter(result),
261 [&](auto& desc) { return desc.common.id.type == type; });
262 if (result.empty()) {
263 ALOGW("%s UUID type not found in HAL and proxy list %s", __func__, toString(type).c_str());
264 return BAD_VALUE;
265 }
266
267 *descriptors = VALUE_OR_RETURN_STATUS(
268 aidl::android::convertContainer<std::vector<effect_descriptor_t>>(
269 result, ::aidl::android::aidl2legacy_Descriptor_effect_descriptor));
270 return OK;
271 }
272
isProxyEffect(const AudioUuid & uuid) const273 bool EffectsFactoryHalAidl::isProxyEffect(const AudioUuid& uuid) const {
274 return 0 != mProxyUuidDescriptorMap.count(uuid);
275 }
276
getProcessings() const277 std::shared_ptr<const effectsConfig::Processings> EffectsFactoryHalAidl::getProcessings() const {
278
279 auto getConfigEffectWithDescriptor =
280 [](const auto& desc) -> std::shared_ptr<const effectsConfig::Effect> {
281 effectsConfig::Effect effect = {.name = desc.common.name, .isProxy = false};
282 if (const auto uuid =
283 ::aidl::android::aidl2legacy_AudioUuid_audio_uuid_t(desc.common.id.uuid);
284 uuid.ok()) {
285 static_cast<effectsConfig::EffectImpl&>(effect).uuid = uuid.value();
286 return std::make_shared<const effectsConfig::Effect>(effect);
287 } else {
288 return nullptr;
289 }
290 };
291
292 auto getConfigProcessingWithAidlProcessing =
293 [&](const auto& aidlProcess, std::vector<effectsConfig::InputStream>& preprocess,
294 std::vector<effectsConfig::OutputStream>& postprocess,
295 std::vector<effectsConfig::DeviceEffects>& deviceprocess) {
296 if (aidlProcess.type.getTag() == Processing::Type::streamType) {
297 AudioStreamType aidlType =
298 aidlProcess.type.template get<Processing::Type::streamType>();
299 const auto type =
300 ::aidl::android::aidl2legacy_AudioStreamType_audio_stream_type_t(
301 aidlType);
302 if (!type.ok()) {
303 return;
304 }
305
306 std::vector<std::shared_ptr<const effectsConfig::Effect>> effects;
307 std::transform(aidlProcess.ids.begin(), aidlProcess.ids.end(),
308 std::back_inserter(effects), getConfigEffectWithDescriptor);
309 effectsConfig::OutputStream stream = {.type = type.value(),
310 .effects = std::move(effects)};
311 postprocess.emplace_back(stream);
312 } else if (aidlProcess.type.getTag() == Processing::Type::source) {
313 AudioSource aidlType =
314 aidlProcess.type.template get<Processing::Type::source>();
315 const auto type =
316 ::aidl::android::aidl2legacy_AudioSource_audio_source_t(aidlType);
317 if (!type.ok()) {
318 return;
319 }
320
321 std::vector<std::shared_ptr<const effectsConfig::Effect>> effects;
322 std::transform(aidlProcess.ids.begin(), aidlProcess.ids.end(),
323 std::back_inserter(effects), getConfigEffectWithDescriptor);
324 effectsConfig::InputStream stream = {.type = type.value(),
325 .effects = std::move(effects)};
326 preprocess.emplace_back(stream);
327 } else if (aidlProcess.type.getTag() == Processing::Type::device) {
328 AudioDevice aidlDevice =
329 aidlProcess.type.template get<Processing::Type::device>();
330 std::vector<std::shared_ptr<const effectsConfig::Effect>> effects;
331 std::transform(aidlProcess.ids.begin(), aidlProcess.ids.end(),
332 std::back_inserter(effects), getConfigEffectWithDescriptor);
333 audio_devices_t type;
334 char address[AUDIO_DEVICE_MAX_ADDRESS_LEN];
335 status_t status = ::aidl::android::aidl2legacy_AudioDevice_audio_device(
336 aidlDevice, &type, address);
337 if (status != NO_ERROR) {
338 ALOGE("%s device effect has invalid device type / address", __func__);
339 return;
340 }
341 effectsConfig::DeviceEffects device = {
342 {.type = type, .effects = std::move(effects)},
343 .address = address,
344 };
345 deviceprocess.emplace_back(device);
346 }
347 };
348
349 static std::shared_ptr<const effectsConfig::Processings> processings(
350 [&]() -> std::shared_ptr<const effectsConfig::Processings> {
351 std::vector<effectsConfig::InputStream> preprocess;
352 std::vector<effectsConfig::OutputStream> postprocess;
353 std::vector<effectsConfig::DeviceEffects> deviceprocess;
354 for (const auto& processing : mAidlProcessings) {
355 getConfigProcessingWithAidlProcessing(processing, preprocess, postprocess,
356 deviceprocess);
357 }
358
359 if (0 == preprocess.size() && 0 == postprocess.size() &&
360 0 == deviceprocess.size()) {
361 return nullptr;
362 }
363
364 return std::make_shared<const effectsConfig::Processings>(
365 effectsConfig::Processings({.preprocess = std::move(preprocess),
366 .postprocess = std::move(postprocess),
367 .deviceprocess = std::move(deviceprocess)}));
368 }());
369
370 return processings;
371 }
372
373 // Return 0 for AIDL, as the AIDL interface is not aware of the configuration file.
getSkippedElements() const374 ::android::error::Result<size_t> EffectsFactoryHalAidl::getSkippedElements() const {
375 return 0;
376 }
377
378
isAudioEraser(const AudioUuid & uuid)379 bool EffectsFactoryHalAidl::isAudioEraser(const AudioUuid& uuid) {
380 return uuid == getEffectTypeUuidEraser();
381 }
382
filterHalDescriptors(std::vector<Descriptor> & descs)383 void EffectsFactoryHalAidl::filterHalDescriptors(std::vector<Descriptor>& descs) {
384 if (!com_android_media_audio_audio_eraser_effect()) {
385 descs.erase(std::remove_if(descs.begin(), descs.end(),
386 [](const Descriptor& desc) {
387 return isAudioEraser(desc.common.id.type);
388 }),
389 descs.end());
390 }
391
392 return;
393 }
394
395 } // namespace effect
396
397 // When a shared library is built from a static library, even explicit
398 // exports from a static library are optimized out unless actually used by
399 // the shared library. See EffectsFactoryHalEntry.cpp.
createIEffectsFactoryImpl()400 extern "C" void* createIEffectsFactoryImpl() {
401 return new effect::EffectsFactoryHalAidl(getServiceInstance<IFactory>("default"));
402 }
403
404 } // namespace android
405