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