xref: /aosp_15_r20/frameworks/av/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
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