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::base::unexpected;
53 using ::android::detail::AudioHalVersionInfo;
54
55 namespace android {
56 namespace effect {
57
EffectsFactoryHalAidl(std::shared_ptr<IFactory> effectsFactory)58 EffectsFactoryHalAidl::EffectsFactoryHalAidl(std::shared_ptr<IFactory> effectsFactory)
59 : mFactory(effectsFactory),
60 mHalVersion(AudioHalVersionInfo(
61 AudioHalVersionInfo::Type::AIDL,
62 [this]() {
63 int32_t majorVersion = 0;
64 return (mFactory && mFactory->getInterfaceVersion(&majorVersion).isOk())
65 ? majorVersion
66 : 0;
67 }())),
__anon23f71f600202() 68 mHalDescList([this]() {
69 std::vector<Descriptor> list;
70 if (mFactory) {
71 mFactory->queryEffects(std::nullopt, std::nullopt, std::nullopt, &list).isOk();
72 filterHalDescriptors(list);
73 }
74 return list;
75 }()),
__anon23f71f600302() 76 mProxyUuidDescriptorMap([this]() {
77 std::map<AudioUuid, std::vector<Descriptor>> proxyUuidMap;
78 for (const auto& desc : mHalDescList) {
79 if (desc.common.id.proxy.has_value()) {
80 const auto& uuid = desc.common.id.proxy.value();
81 if (proxyUuidMap.count(uuid) == 0) {
82 proxyUuidMap.insert({uuid, {desc}});
83 } else {
84 proxyUuidMap[uuid].emplace_back(desc);
85 }
86 }
87 }
88 return proxyUuidMap;
89 }()),
__anon23f71f600402() 90 mProxyDescList([this]() {
91 std::vector<Descriptor> list;
92 for (const auto& proxy : mProxyUuidDescriptorMap) {
93 if (Descriptor desc;
94 EffectProxy::buildDescriptor(proxy.first /* uuid */,
95 proxy.second /* sub-effect descriptor list */,
96 &desc /* proxy descriptor */)
97 .isOk()) {
98 list.emplace_back(std::move(desc));
99 }
100 }
101 return list;
102 }()),
__anon23f71f600502() 103 mNonProxyDescList([this]() {
104 std::vector<Descriptor> list;
105 std::copy_if(mHalDescList.begin(), mHalDescList.end(), std::back_inserter(list),
106 [](const Descriptor& desc) { return !desc.common.id.proxy.has_value(); });
107 return list;
108 }()),
109 mEffectCount(mNonProxyDescList.size() + mProxyDescList.size()),
__anon23f71f600702() 110 mAidlProcessings([this]() -> std::vector<Processing> {
111 std::vector<Processing> processings;
112 if (!mFactory || !mFactory->queryProcessing(std::nullopt, &processings).isOk()) {
113 ALOGE("%s queryProcessing failed", __func__);
114 }
115 return processings;
116 }()) {
117 ALOG_ASSERT(mFactory != nullptr, "Provided IEffectsFactory service is NULL");
118 ALOGI("%s with %zu nonProxyEffects and %zu proxyEffects", __func__, mNonProxyDescList.size(),
119 mProxyDescList.size());
120 }
121
queryNumberEffects(uint32_t * pNumEffects)122 status_t EffectsFactoryHalAidl::queryNumberEffects(uint32_t *pNumEffects) {
123 if (pNumEffects == nullptr) {
124 return BAD_VALUE;
125 }
126
127 *pNumEffects = mEffectCount;
128 return OK;
129 }
130
getDescriptor(uint32_t index,effect_descriptor_t * pDescriptor)131 status_t EffectsFactoryHalAidl::getDescriptor(uint32_t index, effect_descriptor_t* pDescriptor) {
132 if (pDescriptor == nullptr) {
133 return BAD_VALUE;
134 }
135
136 if (index >= mEffectCount) {
137 ALOGE("%s index %d exceed max number %zu", __func__, index, mEffectCount);
138 return INVALID_OPERATION;
139 }
140
141 if (index >= mNonProxyDescList.size()) {
142 *pDescriptor =
143 VALUE_OR_RETURN_STATUS(::aidl::android::aidl2legacy_Descriptor_effect_descriptor(
144 mProxyDescList.at(index - mNonProxyDescList.size())));
145 } else {
146 *pDescriptor =
147 VALUE_OR_RETURN_STATUS(::aidl::android::aidl2legacy_Descriptor_effect_descriptor(
148 mNonProxyDescList.at(index)));
149 }
150 return OK;
151 }
152
getDescriptor(const effect_uuid_t * halUuid,effect_descriptor_t * pDescriptor)153 status_t EffectsFactoryHalAidl::getDescriptor(const effect_uuid_t* halUuid,
154 effect_descriptor_t* pDescriptor) {
155 if (halUuid == nullptr) {
156 return BAD_VALUE;
157 }
158
159 AudioUuid uuid =
160 VALUE_OR_RETURN_STATUS(::aidl::android::legacy2aidl_audio_uuid_t_AudioUuid(*halUuid));
161 return getHalDescriptorWithImplUuid(uuid, pDescriptor);
162 }
163
getDescriptors(const effect_uuid_t * halType,std::vector<effect_descriptor_t> * descriptors)164 status_t EffectsFactoryHalAidl::getDescriptors(const effect_uuid_t* halType,
165 std::vector<effect_descriptor_t>* descriptors) {
166 if (halType == nullptr) {
167 return BAD_VALUE;
168 }
169
170 AudioUuid type =
171 VALUE_OR_RETURN_STATUS(::aidl::android::legacy2aidl_audio_uuid_t_AudioUuid(*halType));
172 return getHalDescriptorWithTypeUuid(type, descriptors);
173 }
174
createEffect(const effect_uuid_t * uuid,int32_t sessionId,int32_t ioId,int32_t deviceId __unused,sp<EffectHalInterface> * effect)175 status_t EffectsFactoryHalAidl::createEffect(const effect_uuid_t* uuid, int32_t sessionId,
176 int32_t ioId, int32_t deviceId __unused,
177 sp<EffectHalInterface>* effect) {
178 if (uuid == nullptr || effect == nullptr) {
179 return BAD_VALUE;
180 }
181 ALOGV("%s session %d ioId %d", __func__, sessionId, ioId);
182
183 AudioUuid aidlUuid =
184 VALUE_OR_RETURN_STATUS(::aidl::android::legacy2aidl_audio_uuid_t_AudioUuid(*uuid));
185 if (!com_android_media_audio_audio_eraser_effect() && isAudioEraser(aidlUuid)) {
186 ALOGE("%s Audio eraser effect not supported yet", __func__);
187 return BAD_VALUE;
188 }
189
190 std::shared_ptr<IEffect> aidlEffect;
191 // Use EffectProxy interface instead of IFactory to create
192 const bool isProxy = isProxyEffect(aidlUuid);
193 if (isProxy) {
194 aidlEffect = ndk::SharedRefBase::make<EffectProxy>(
195 aidlUuid, mProxyUuidDescriptorMap.at(aidlUuid) /* sub-effect descriptor list */,
196 mFactory);
197 } else {
198 RETURN_STATUS_IF_ERROR(
199 statusTFromBinderStatus(mFactory->createEffect(aidlUuid, &aidlEffect)));
200 }
201 if (aidlEffect == nullptr) {
202 ALOGE("%s failed to create effect with UUID: %s", __func__,
203 ::android::audio::utils::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__,
243 ::android::audio::utils::toString(uuid).c_str());
244 return NAME_NOT_FOUND;
245 }
246
247 *pDescriptor = VALUE_OR_RETURN_STATUS(
248 ::aidl::android::aidl2legacy_Descriptor_effect_descriptor(*matchIt));
249 return OK;
250 }
251
getHalDescriptorWithTypeUuid(const AudioUuid & type,std::vector<effect_descriptor_t> * descriptors)252 status_t EffectsFactoryHalAidl::getHalDescriptorWithTypeUuid(
253 const AudioUuid& type, std::vector<effect_descriptor_t>* descriptors) {
254 if (descriptors == nullptr) {
255 return BAD_VALUE;
256 }
257
258 std::vector<Descriptor> result;
259 std::copy_if(mNonProxyDescList.begin(), mNonProxyDescList.end(), std::back_inserter(result),
260 [&](auto& desc) { return desc.common.id.type == type; });
261 std::copy_if(mProxyDescList.begin(), mProxyDescList.end(), std::back_inserter(result),
262 [&](auto& desc) { return desc.common.id.type == type; });
263 if (result.empty()) {
264 ALOGW("%s UUID type not found in HAL and proxy list %s", __func__,
265 ::android::audio::utils::toString(type).c_str());
266 return BAD_VALUE;
267 }
268
269 *descriptors = VALUE_OR_RETURN_STATUS(
270 aidl::android::convertContainer<std::vector<effect_descriptor_t>>(
271 result, ::aidl::android::aidl2legacy_Descriptor_effect_descriptor));
272 return OK;
273 }
274
isProxyEffect(const AudioUuid & uuid) const275 bool EffectsFactoryHalAidl::isProxyEffect(const AudioUuid& uuid) const {
276 return 0 != mProxyUuidDescriptorMap.count(uuid);
277 }
278
getProcessings() const279 std::shared_ptr<const effectsConfig::Processings> EffectsFactoryHalAidl::getProcessings() const {
280
281 auto getConfigEffectWithDescriptor =
282 [](const auto& desc) -> std::shared_ptr<const effectsConfig::Effect> {
283 effectsConfig::Effect effect = {.name = desc.common.name, .isProxy = false};
284 if (const auto uuid =
285 ::aidl::android::aidl2legacy_AudioUuid_audio_uuid_t(desc.common.id.uuid);
286 uuid.ok()) {
287 static_cast<effectsConfig::EffectImpl&>(effect).uuid = uuid.value();
288 return std::make_shared<const effectsConfig::Effect>(effect);
289 } else {
290 return nullptr;
291 }
292 };
293
294 auto getConfigProcessingWithAidlProcessing =
295 [&](const auto& aidlProcess, std::vector<effectsConfig::InputStream>& preprocess,
296 std::vector<effectsConfig::OutputStream>& postprocess,
297 std::vector<effectsConfig::DeviceEffects>& deviceprocess) {
298 if (aidlProcess.type.getTag() == Processing::Type::streamType) {
299 AudioStreamType aidlType =
300 aidlProcess.type.template get<Processing::Type::streamType>();
301 const auto type =
302 ::aidl::android::aidl2legacy_AudioStreamType_audio_stream_type_t(
303 aidlType);
304 if (!type.ok()) {
305 return;
306 }
307
308 std::vector<std::shared_ptr<const effectsConfig::Effect>> effects;
309 std::transform(aidlProcess.ids.begin(), aidlProcess.ids.end(),
310 std::back_inserter(effects), getConfigEffectWithDescriptor);
311 effectsConfig::OutputStream stream = {.type = type.value(),
312 .effects = std::move(effects)};
313 postprocess.emplace_back(stream);
314 } else if (aidlProcess.type.getTag() == Processing::Type::source) {
315 AudioSource aidlType =
316 aidlProcess.type.template get<Processing::Type::source>();
317 const auto type =
318 ::aidl::android::aidl2legacy_AudioSource_audio_source_t(aidlType);
319 if (!type.ok()) {
320 return;
321 }
322
323 std::vector<std::shared_ptr<const effectsConfig::Effect>> effects;
324 std::transform(aidlProcess.ids.begin(), aidlProcess.ids.end(),
325 std::back_inserter(effects), getConfigEffectWithDescriptor);
326 effectsConfig::InputStream stream = {.type = type.value(),
327 .effects = std::move(effects)};
328 preprocess.emplace_back(stream);
329 } else if (aidlProcess.type.getTag() == Processing::Type::device) {
330 AudioDevice aidlDevice =
331 aidlProcess.type.template get<Processing::Type::device>();
332 std::vector<std::shared_ptr<const effectsConfig::Effect>> effects;
333 std::transform(aidlProcess.ids.begin(), aidlProcess.ids.end(),
334 std::back_inserter(effects), getConfigEffectWithDescriptor);
335 audio_devices_t type;
336 char address[AUDIO_DEVICE_MAX_ADDRESS_LEN];
337 status_t status = ::aidl::android::aidl2legacy_AudioDevice_audio_device(
338 aidlDevice, &type, address);
339 if (status != NO_ERROR) {
340 ALOGE("%s device effect has invalid device type / address", __func__);
341 return;
342 }
343 effectsConfig::DeviceEffects device = {
344 {.type = type, .effects = std::move(effects)},
345 .address = address,
346 };
347 deviceprocess.emplace_back(device);
348 }
349 };
350
351 static std::shared_ptr<const effectsConfig::Processings> processings(
352 [&]() -> std::shared_ptr<const effectsConfig::Processings> {
353 std::vector<effectsConfig::InputStream> preprocess;
354 std::vector<effectsConfig::OutputStream> postprocess;
355 std::vector<effectsConfig::DeviceEffects> deviceprocess;
356 for (const auto& processing : mAidlProcessings) {
357 getConfigProcessingWithAidlProcessing(processing, preprocess, postprocess,
358 deviceprocess);
359 }
360
361 if (0 == preprocess.size() && 0 == postprocess.size() &&
362 0 == deviceprocess.size()) {
363 return nullptr;
364 }
365
366 return std::make_shared<const effectsConfig::Processings>(
367 effectsConfig::Processings({.preprocess = std::move(preprocess),
368 .postprocess = std::move(postprocess),
369 .deviceprocess = std::move(deviceprocess)}));
370 }());
371
372 return processings;
373 }
374
375 // Return 0 for AIDL, as the AIDL interface is not aware of the configuration file.
getSkippedElements() const376 ::android::error::Result<size_t> EffectsFactoryHalAidl::getSkippedElements() const {
377 return 0;
378 }
379
380
isAudioEraser(const AudioUuid & uuid)381 bool EffectsFactoryHalAidl::isAudioEraser(const AudioUuid& uuid) {
382 return uuid == getEffectTypeUuidEraser();
383 }
384
filterHalDescriptors(std::vector<Descriptor> & descs)385 void EffectsFactoryHalAidl::filterHalDescriptors(std::vector<Descriptor>& descs) {
386 if (!com_android_media_audio_audio_eraser_effect()) {
387 descs.erase(std::remove_if(descs.begin(), descs.end(),
388 [](const Descriptor& desc) {
389 return isAudioEraser(desc.common.id.type);
390 }),
391 descs.end());
392 }
393
394 return;
395 }
396
397 } // namespace effect
398
399 // When a shared library is built from a static library, even explicit
400 // exports from a static library are optimized out unless actually used by
401 // the shared library. See EffectsFactoryHalEntry.cpp.
createIEffectsFactoryImpl()402 extern "C" void* createIEffectsFactoryImpl() {
403 return new effect::EffectsFactoryHalAidl(getServiceInstance<IFactory>("default"));
404 }
405
406 } // namespace android
407