• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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