1 /*
2  * Copyright (C) 2016 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 #define LOG_TAG "EffectsFactoryHalHidl"
18 //#define LOG_NDEBUG 0
19 
20 #include <optional>
21 #include <tuple>
22 
23 #include <cutils/native_handle.h>
24 
25 #include <UuidUtils.h>
26 #include <util/EffectUtils.h>
27 #include <utils/Log.h>
28 
29 #include "EffectConversionHelperHidl.h"
30 #include "EffectBufferHalHidl.h"
31 #include "EffectHalHidl.h"
32 #include "EffectsFactoryHalHidl.h"
33 
34 #include "android/media/AudioHalVersion.h"
35 
36 using ::android::base::unexpected;
37 using ::android::detail::AudioHalVersionInfo;
38 using ::android::hardware::Return;
39 using ::android::hardware::audio::common::CPP_VERSION::implementation::UuidUtils;
40 using ::android::hardware::audio::effect::CPP_VERSION::implementation::EffectUtils;
41 
42 namespace android {
43 namespace effect {
44 
45 using namespace ::android::hardware::audio::common::CPP_VERSION;
46 using namespace ::android::hardware::audio::effect::CPP_VERSION;
47 
48 class EffectDescriptorCache {
49   public:
50     using QueryResult = std::tuple<Return<void>, Result, hidl_vec<EffectDescriptor>>;
51     QueryResult queryAllDescriptors(IEffectsFactory* effectsFactory);
52   private:
53     std::mutex mLock;
54     std::optional<hidl_vec<EffectDescriptor>> mLastDescriptors;  // GUARDED_BY(mLock)
55 };
56 
queryAllDescriptors(IEffectsFactory * effectsFactory)57 EffectDescriptorCache::QueryResult EffectDescriptorCache::queryAllDescriptors(
58         IEffectsFactory* effectsFactory) {
59     {
60         std::lock_guard l(mLock);
61         if (mLastDescriptors.has_value()) {
62             return {::android::hardware::Void(), Result::OK, mLastDescriptors.value()};
63         }
64     }
65     Result retval = Result::NOT_INITIALIZED;
66     hidl_vec<EffectDescriptor> descriptors;
67     Return<void> ret = effectsFactory->getAllDescriptors(
68             [&](Result r, const hidl_vec<EffectDescriptor>& result) {
69                 retval = r;
70                 if (retval == Result::OK) {
71                     descriptors = result;
72                 }
73             });
74     if (ret.isOk() && retval == Result::OK) {
75         std::lock_guard l(mLock);
76         mLastDescriptors = descriptors;
77     }
78     return {std::move(ret), retval, std::move(descriptors)};
79 }
80 
EffectsFactoryHalHidl(sp<IEffectsFactory> effectsFactory)81 EffectsFactoryHalHidl::EffectsFactoryHalHidl(sp<IEffectsFactory> effectsFactory)
82     : EffectConversionHelperHidl("EffectsFactory"),
83       mEffectsFactory(std::move(effectsFactory)),
84       mCache(new EffectDescriptorCache),
85       mParsingResult(effectsConfig::parse()) {
86     ALOG_ASSERT(mEffectsFactory != nullptr, "Provided IEffectsFactory service is NULL");
87 }
88 
queryNumberEffects(uint32_t * pNumEffects)89 status_t EffectsFactoryHalHidl::queryNumberEffects(uint32_t *pNumEffects) {
90     if (mEffectsFactory == 0) return NO_INIT;
91     auto [ret, retval, descriptors] = mCache->queryAllDescriptors(mEffectsFactory.get());
92     if (ret.isOk() && retval == Result::OK) {
93         *pNumEffects = descriptors.size();
94         return OK;
95     } else if (ret.isOk()) {
96         return NO_INIT;
97     }
98     return processReturn(__FUNCTION__, ret);
99 }
100 
getDescriptor(uint32_t index,effect_descriptor_t * pDescriptor)101 status_t EffectsFactoryHalHidl::getDescriptor(
102         uint32_t index, effect_descriptor_t *pDescriptor) {
103     if (pDescriptor == nullptr) {
104         return BAD_VALUE;
105     }
106     if (mEffectsFactory == 0) return NO_INIT;
107     auto [ret, retval, descriptors] = mCache->queryAllDescriptors(mEffectsFactory.get());
108     if (ret.isOk() && retval == Result::OK) {
109         if (index >= descriptors.size()) return NAME_NOT_FOUND;
110         EffectUtils::effectDescriptorToHal(descriptors[index], pDescriptor);
111     } else if (ret.isOk()) {
112         return NO_INIT;
113     }
114     return processReturn(__FUNCTION__, ret);
115 }
116 
getDescriptor(const effect_uuid_t * pEffectUuid,effect_descriptor_t * pDescriptor)117 status_t EffectsFactoryHalHidl::getDescriptor(
118         const effect_uuid_t *pEffectUuid, effect_descriptor_t *pDescriptor) {
119     if (pDescriptor == nullptr || pEffectUuid == nullptr) {
120         return BAD_VALUE;
121     }
122     if (mEffectsFactory == 0) return NO_INIT;
123     Uuid hidlUuid;
124     UuidUtils::uuidFromHal(*pEffectUuid, &hidlUuid);
125     Result retval = Result::NOT_INITIALIZED;
126     Return<void> ret = mEffectsFactory->getDescriptor(hidlUuid,
127             [&](Result r, const EffectDescriptor& result) {
128                 retval = r;
129                 if (retval == Result::OK) {
130                     EffectUtils::effectDescriptorToHal(result, pDescriptor);
131                 }
132             });
133     if (ret.isOk()) {
134         if (retval == Result::OK) return OK;
135         else if (retval == Result::INVALID_ARGUMENTS) return NAME_NOT_FOUND;
136         else return NO_INIT;
137     }
138     return processReturn(__FUNCTION__, ret);
139 }
140 
getDescriptors(const effect_uuid_t * pEffectType,std::vector<effect_descriptor_t> * descriptors)141 status_t EffectsFactoryHalHidl::getDescriptors(const effect_uuid_t *pEffectType,
142                                                std::vector<effect_descriptor_t> *descriptors) {
143     if (pEffectType == nullptr || descriptors == nullptr) {
144         return BAD_VALUE;
145     }
146     if (mEffectsFactory == 0) return NO_INIT;
147 
148     auto [ret, retval, hidlDescs] = mCache->queryAllDescriptors(mEffectsFactory.get());
149     if (!ret.isOk() || retval != Result::OK) {
150         return processReturn(__FUNCTION__, ret, retval);
151     }
152     for (const auto& hidlDesc : hidlDescs) {
153         effect_descriptor_t descriptor;
154         EffectUtils::effectDescriptorToHal(hidlDesc, &descriptor);
155         if (memcmp(&descriptor.type, pEffectType, sizeof(effect_uuid_t)) == 0) {
156             descriptors->push_back(descriptor);
157         }
158     }
159     return descriptors->empty() ? NAME_NOT_FOUND : NO_ERROR;
160 }
161 
createEffect(const effect_uuid_t * pEffectUuid,int32_t sessionId,int32_t ioId,int32_t deviceId __unused,sp<EffectHalInterface> * effect)162 status_t EffectsFactoryHalHidl::createEffect(
163         const effect_uuid_t *pEffectUuid, int32_t sessionId, int32_t ioId,
164         int32_t deviceId __unused, sp<EffectHalInterface> *effect) {
165     if (mEffectsFactory == 0) return NO_INIT;
166     Uuid hidlUuid;
167     UuidUtils::uuidFromHal(*pEffectUuid, &hidlUuid);
168     Result retval = Result::NOT_INITIALIZED;
169     Return<void> ret;
170 #if MAJOR_VERSION >= 6
171     ret = mEffectsFactory->createEffect(
172             hidlUuid, sessionId, ioId, deviceId,
173             [&](Result r, const sp<IEffect>& result, uint64_t effectId) {
174                 retval = r;
175                 if (retval == Result::OK) {
176                     *effect = new EffectHalHidl(result, effectId);
177                 }
178             });
179 #else
180     if (sessionId == AUDIO_SESSION_DEVICE && ioId == AUDIO_IO_HANDLE_NONE) {
181         return INVALID_OPERATION;
182     }
183     ret = mEffectsFactory->createEffect(
184             hidlUuid, sessionId, ioId,
185             [&](Result r, const sp<IEffect>& result, uint64_t effectId) {
186                 retval = r;
187                 if (retval == Result::OK) {
188                     *effect = new EffectHalHidl(result, effectId);
189                 }
190             });
191 #endif
192     if (ret.isOk()) {
193         if (retval == Result::OK) return OK;
194         else if (retval == Result::INVALID_ARGUMENTS) return NAME_NOT_FOUND;
195         else return NO_INIT;
196     }
197     return processReturn(__FUNCTION__, ret);
198 }
199 
dumpEffects(int fd)200 status_t EffectsFactoryHalHidl::dumpEffects(int fd) {
201     if (mEffectsFactory == 0) return NO_INIT;
202     native_handle_t* hidlHandle = native_handle_create(1, 0);
203     hidlHandle->data[0] = fd;
204     Return<void> ret = mEffectsFactory->debug(hidlHandle, {} /* options */);
205     native_handle_delete(hidlHandle);
206 
207     // TODO(b/111997867, b/177271958)  Workaround - remove when fixed.
208     // A Binder transmitted fd may not close immediately due to a race condition b/111997867
209     // when the remote binder thread removes the last refcount to the fd blocks in the
210     // kernel for binder activity. We send a Binder ping() command to unblock the thread
211     // and complete the fd close / release.
212     //
213     // See DeviceHalHidl::dump(), EffectHalHidl::dump(), StreamHalHidl::dump(),
214     //     EffectsFactoryHalHidl::dumpEffects().
215 
216     (void)mEffectsFactory->ping(); // synchronous Binder call
217 
218     return processReturn(__FUNCTION__, ret);
219 }
220 
allocateBuffer(size_t size,sp<EffectBufferHalInterface> * buffer)221 status_t EffectsFactoryHalHidl::allocateBuffer(size_t size, sp<EffectBufferHalInterface>* buffer) {
222     return EffectBufferHalHidl::allocate(size, buffer);
223 }
224 
mirrorBuffer(void * external,size_t size,sp<EffectBufferHalInterface> * buffer)225 status_t EffectsFactoryHalHidl::mirrorBuffer(void* external, size_t size,
226                           sp<EffectBufferHalInterface>* buffer) {
227     return EffectBufferHalHidl::mirror(external, size, buffer);
228 }
229 
getHalVersion() const230 AudioHalVersionInfo EffectsFactoryHalHidl::getHalVersion() const {
231     return AudioHalVersionInfo(AudioHalVersionInfo::Type::HIDL, MAJOR_VERSION, MINOR_VERSION);
232 }
233 
getProcessings() const234 std::shared_ptr<const effectsConfig::Processings> EffectsFactoryHalHidl::getProcessings() const {
235     return mParsingResult.parsedConfig;
236 }
237 
getSkippedElements() const238 ::android::error::Result<size_t> EffectsFactoryHalHidl::getSkippedElements() const {
239     if (!mParsingResult.parsedConfig) {
240         return ::android::base::unexpected(BAD_VALUE);
241     }
242     return mParsingResult.nbSkippedElement;
243 }
244 
245 } // namespace effect
246 
247 // When a shared library is built from a static library, even explicit
248 // exports from a static library are optimized out unless actually used by
249 // the shared library. See EffectsFactoryHalEntry.cpp.
createIEffectsFactoryImpl()250 extern "C" void* createIEffectsFactoryImpl() {
251     auto service = hardware::audio::effect::CPP_VERSION::IEffectsFactory::getService();
252     return service ? new effect::EffectsFactoryHalHidl(service) : nullptr;
253 }
254 
255 } // namespace android
256