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