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