blob: 8e107a2bcab78d7b3fe60d20f1ae36ef4894d0c9 [file] [log] [blame]
Shunkai Yaoc23916b2022-07-13 04:59:37 +00001/*
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#define LOG_TAG "AHAL_EffectFactory"
18#include <android-base/logging.h>
Shunkai Yaoea24c1a2022-09-28 17:39:23 +000019#include <dlfcn.h>
Shunkai Yaoc23916b2022-07-13 04:59:37 +000020
Shunkai Yaoea24c1a2022-09-28 17:39:23 +000021#include "effect-impl/EffectUUID.h"
Shunkai Yaoc23916b2022-07-13 04:59:37 +000022#include "effectFactory-impl/EffectFactory.h"
Shunkai Yaoc23916b2022-07-13 04:59:37 +000023
24using aidl::android::media::audio::common::AudioUuid;
25
26namespace aidl::android::hardware::audio::effect {
27
28Factory::Factory() {
Shunkai Yaoea24c1a2022-09-28 17:39:23 +000029 std::function<void(void*)> dlClose = [](void* handle) -> void {
30 if (handle && dlclose(handle)) {
31 LOG(ERROR) << "dlclose failed " << dlerror();
32 }
33 };
34 // TODO: implement this with audio_effect.xml.
35 auto libHandle =
36 std::unique_ptr<void, decltype(dlClose)>{dlopen("libequalizer.so", RTLD_LAZY), dlClose};
37 if (!libHandle) {
38 LOG(ERROR) << __func__ << ": dlopen failed, err: " << dlerror();
39 return;
40 }
41
42 LOG(DEBUG) << __func__ << " dlopen uuid: " << EqualizerSwImplUUID.toString() << " handle "
43 << libHandle;
44 mEffectLibMap.insert({EqualizerSwImplUUID, std::make_pair(std::move(libHandle), nullptr)});
45
Shunkai Yaoc23916b2022-07-13 04:59:37 +000046 Descriptor::Identity id;
Shunkai Yao121c6dd2022-09-21 23:42:08 +000047 id.type = EqualizerTypeUUID;
48 id.uuid = EqualizerSwImplUUID;
Shunkai Yaoc23916b2022-07-13 04:59:37 +000049 mIdentityList.push_back(id);
Shunkai Yaoc23916b2022-07-13 04:59:37 +000050}
51
Shunkai Yaoea24c1a2022-09-28 17:39:23 +000052Factory::~Factory() {
53 if (auto count = mEffectUuidMap.size()) {
54 LOG(ERROR) << __func__ << " remaining " << count
55 << " effect instances not destroyed indicating resource leak!";
56 for (const auto& it : mEffectUuidMap) {
57 if (auto spEffect = it.first.lock()) {
58 LOG(ERROR) << __func__ << " erase remaining instance UUID " << it.second.toString();
59 destroyEffectImpl(spEffect);
60 }
61 }
62 }
63}
64
65ndk::ScopedAStatus Factory::queryEffects(const std::optional<AudioUuid>& in_type_uuid,
66 const std::optional<AudioUuid>& in_impl_uuid,
Shunkai Yaoc23916b2022-07-13 04:59:37 +000067 std::vector<Descriptor::Identity>* _aidl_return) {
68 std::copy_if(mIdentityList.begin(), mIdentityList.end(), std::back_inserter(*_aidl_return),
69 [&](auto& desc) {
Shunkai Yaoea24c1a2022-09-28 17:39:23 +000070 return (!in_type_uuid.has_value() || in_type_uuid.value() == desc.type) &&
71 (!in_impl_uuid.has_value() || in_impl_uuid.value() == desc.uuid);
Shunkai Yaoc23916b2022-07-13 04:59:37 +000072 });
73 return ndk::ScopedAStatus::ok();
74}
75
Shunkai Yao08b687d2022-10-13 21:11:11 +000076ndk::ScopedAStatus Factory::queryProcessing(const std::optional<Processing::Type>& in_type,
77 std::vector<Processing>* _aidl_return) {
78 // TODO: implement this with audio_effect.xml.
79 if (in_type.has_value()) {
80 // return all matching process filter
81 LOG(DEBUG) << __func__ << " process type: " << in_type.value().toString();
82 }
83 LOG(DEBUG) << __func__ << " return " << _aidl_return->size();
84 return ndk::ScopedAStatus::ok();
85}
86
Shunkai Yaoea24c1a2022-09-28 17:39:23 +000087#define RETURN_IF_BINDER_EXCEPTION(functor) \
88 { \
89 binder_exception_t exception = functor; \
90 if (EX_NONE != exception) { \
91 LOG(ERROR) << #functor << ": failed with error " << exception; \
92 return ndk::ScopedAStatus::fromExceptionCode(exception); \
93 } \
94 }
95
96ndk::ScopedAStatus Factory::createEffect(const AudioUuid& in_impl_uuid,
97 std::shared_ptr<IEffect>* _aidl_return) {
Shunkai Yao45905172022-08-24 18:14:02 +000098 LOG(DEBUG) << __func__ << ": UUID " << in_impl_uuid.toString();
Shunkai Yao121c6dd2022-09-21 23:42:08 +000099 if (in_impl_uuid == EqualizerSwImplUUID) {
Shunkai Yaoea24c1a2022-09-28 17:39:23 +0000100 if (mEffectLibMap.count(in_impl_uuid)) {
101 auto& lib = mEffectLibMap[in_impl_uuid];
102 // didn't do dlsym yet
103 if (nullptr == lib.second) {
104 void* libHandle = lib.first.get();
105 struct effect_interface_s intf = {
106 .createEffectFunc = (EffectCreateFunctor)dlsym(libHandle, "createEffect"),
107 .destroyEffectFunc =
108 (EffectDestroyFunctor)dlsym(libHandle, "destroyEffect")};
109 auto dlInterface = std::make_unique<struct effect_interface_s>(intf);
110 if (!dlInterface->createEffectFunc || !dlInterface->destroyEffectFunc) {
111 LOG(ERROR) << __func__
112 << ": create or destroy symbol not exist in library: " << libHandle
113 << "!";
114 return ndk::ScopedAStatus::fromExceptionCode(EX_TRANSACTION_FAILED);
115 }
116 lib.second = std::move(dlInterface);
117 }
118
119 auto& libInterface = lib.second;
120 std::shared_ptr<IEffect> effectSp;
121 RETURN_IF_BINDER_EXCEPTION(libInterface->createEffectFunc(&effectSp));
122 if (!effectSp) {
123 LOG(ERROR) << __func__ << ": library created null instance without return error!";
124 return ndk::ScopedAStatus::fromExceptionCode(EX_TRANSACTION_FAILED);
125 }
126 *_aidl_return = effectSp;
127 mEffectUuidMap[std::weak_ptr<IEffect>(effectSp)] = in_impl_uuid;
128 LOG(DEBUG) << __func__ << ": instance " << effectSp.get() << " created successfully";
129 return ndk::ScopedAStatus::ok();
130 } else {
131 LOG(ERROR) << __func__ << ": library doesn't exist";
132 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
133 }
Shunkai Yao45905172022-08-24 18:14:02 +0000134 } else {
Shunkai Yaoea24c1a2022-09-28 17:39:23 +0000135 LOG(ERROR) << __func__ << ": UUID not supported";
Shunkai Yao45905172022-08-24 18:14:02 +0000136 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
137 }
138 return ndk::ScopedAStatus::ok();
139}
140
Shunkai Yaoea24c1a2022-09-28 17:39:23 +0000141ndk::ScopedAStatus Factory::destroyEffectImpl(const std::shared_ptr<IEffect>& in_handle) {
142 std::weak_ptr<IEffect> wpHandle(in_handle);
143 // find UUID with key (std::weak_ptr<IEffect>)
144 if (auto uuidIt = mEffectUuidMap.find(wpHandle); uuidIt != mEffectUuidMap.end()) {
145 auto& uuid = uuidIt->second;
146 // find implementation library with UUID
147 if (auto libIt = mEffectLibMap.find(uuid); libIt != mEffectLibMap.end()) {
148 if (libIt->second.second->destroyEffectFunc) {
149 RETURN_IF_BINDER_EXCEPTION(libIt->second.second->destroyEffectFunc(in_handle));
150 }
151 } else {
152 LOG(ERROR) << __func__ << ": UUID " << uuid.toString() << " does not exist in libMap!";
153 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
154 }
155 mEffectUuidMap.erase(uuidIt);
Shunkai Yao45905172022-08-24 18:14:02 +0000156 return ndk::ScopedAStatus::ok();
157 } else {
Shunkai Yaoea24c1a2022-09-28 17:39:23 +0000158 LOG(ERROR) << __func__ << ": instance " << in_handle << " does not exist!";
Shunkai Yao45905172022-08-24 18:14:02 +0000159 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
160 }
161}
162
Shunkai Yaoea24c1a2022-09-28 17:39:23 +0000163// go over the map and cleanup all expired weak_ptrs.
164void Factory::cleanupEffectMap() {
165 for (auto it = mEffectUuidMap.begin(); it != mEffectUuidMap.end();) {
166 if (nullptr == it->first.lock()) {
167 it = mEffectUuidMap.erase(it);
168 } else {
169 ++it;
170 }
171 }
172}
173
174ndk::ScopedAStatus Factory::destroyEffect(const std::shared_ptr<IEffect>& in_handle) {
175 LOG(DEBUG) << __func__ << ": instance " << in_handle.get();
176 ndk::ScopedAStatus status = destroyEffectImpl(in_handle);
177 // always do the cleanup
178 cleanupEffectMap();
179 return status;
180}
181
Shunkai Yaoc23916b2022-07-13 04:59:37 +0000182} // namespace aidl::android::hardware::audio::effect