1 /*
2 **
3 ** Copyright 2019, The Android Open Source Project
4 **
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
8 **
9 ** http://www.apache.org/licenses/LICENSE-2.0
10 **
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
16 */
17
18 #define LOG_TAG "DeviceEffectManager"
19 //#define LOG_NDEBUG 0
20
21 #include "DeviceEffectManager.h"
22
23 #include "EffectConfiguration.h"
24
25 #include <afutils/DumpTryLock.h>
26 #include <audio_utils/primitives.h>
27 #include <media/audiohal/EffectsFactoryHalInterface.h>
28 #include <utils/Log.h>
29
30 // ----------------------------------------------------------------------------
31
32
33 namespace android {
34
35 using detail::AudioHalVersionInfo;
36 using media::IEffectClient;
37
DeviceEffectManager(const sp<IAfDeviceEffectManagerCallback> & afDeviceEffectManagerCallback)38 DeviceEffectManager::DeviceEffectManager(
39 const sp<IAfDeviceEffectManagerCallback>& afDeviceEffectManagerCallback)
40 : mAfDeviceEffectManagerCallback(afDeviceEffectManagerCallback),
41 mMyCallback(sp<DeviceEffectManagerCallback>::make(*this)) {}
42
onFirstRef()43 void DeviceEffectManager::onFirstRef() {
44 mAfDeviceEffectManagerCallback->getPatchCommandThread()->addListener(this);
45 }
46
addEffectToHal(const struct audio_port_config * device,const sp<EffectHalInterface> & effect)47 status_t DeviceEffectManager::addEffectToHal(const struct audio_port_config* device,
48 const sp<EffectHalInterface>& effect) {
49 return mAfDeviceEffectManagerCallback->addEffectToHal(device, effect);
50 };
51
removeEffectFromHal(const struct audio_port_config * device,const sp<EffectHalInterface> & effect)52 status_t DeviceEffectManager::removeEffectFromHal(const struct audio_port_config* device,
53 const sp<EffectHalInterface>& effect) {
54 return mAfDeviceEffectManagerCallback->removeEffectFromHal(device, effect);
55 };
56
onCreateAudioPatch(audio_patch_handle_t handle,const IAfPatchPanel::Patch & patch)57 void DeviceEffectManager::onCreateAudioPatch(audio_patch_handle_t handle,
58 const IAfPatchPanel::Patch& patch) {
59 ALOGV("%s handle %d mHalHandle %d device sink %08x",
60 __func__, handle, patch.mHalHandle,
61 patch.mAudioPatch.num_sinks > 0 ? patch.mAudioPatch.sinks[0].ext.device.type : 0);
62 audio_utils::lock_guard _l(mutex());
63 for (auto& effectProxies : mDeviceEffects) {
64 for (auto& effect : effectProxies.second) {
65 const status_t status = effect->onCreatePatch(handle, patch);
66 ALOGV("%s Effect onCreatePatch status %d", __func__, status);
67 ALOGW_IF(status == BAD_VALUE, "%s onCreatePatch error %d", __func__, status);
68 }
69 }
70 }
71
onReleaseAudioPatch(audio_patch_handle_t handle)72 void DeviceEffectManager::onReleaseAudioPatch(audio_patch_handle_t handle) {
73 ALOGV("%s", __func__);
74 audio_utils::lock_guard _l(mutex());
75 for (auto& effectProxies : mDeviceEffects) {
76 for (auto& effect : effectProxies.second) {
77 effect->onReleasePatch(handle);
78 }
79 }
80 }
81
onUpdateAudioPatch(audio_patch_handle_t oldHandle,audio_patch_handle_t newHandle,const IAfPatchPanel::Patch & patch)82 void DeviceEffectManager::onUpdateAudioPatch(audio_patch_handle_t oldHandle,
83 audio_patch_handle_t newHandle, const IAfPatchPanel::Patch& patch) {
84 ALOGV("%s oldhandle %d newHandle %d mHalHandle %d device sink %08x",
85 __func__, oldHandle, newHandle, patch.mHalHandle,
86 patch.mAudioPatch.num_sinks > 0 ? patch.mAudioPatch.sinks[0].ext.device.type : 0);
87 audio_utils::lock_guard _l(mutex());
88 for (auto& effectProxies : mDeviceEffects) {
89 for (auto& effect : effectProxies.second) {
90 const status_t status = effect->onUpdatePatch(oldHandle, newHandle, patch);
91 ALOGV("%s Effect onUpdatePatch status %d", __func__, status);
92 ALOGW_IF(status != NO_ERROR, "%s onUpdatePatch error %d", __func__, status);
93 }
94 }
95 }
96
97 // DeviceEffectManager::createEffect_l() must be called with AudioFlinger::mutex() held
createEffect_l(effect_descriptor_t * descriptor,const AudioDeviceTypeAddr & device,const sp<Client> & client,const sp<IEffectClient> & effectClient,const std::map<audio_patch_handle_t,IAfPatchPanel::Patch> & patches,int * enabled,status_t * status,bool probe,bool notifyFramesProcessed)98 sp<IAfEffectHandle> DeviceEffectManager::createEffect_l(
99 effect_descriptor_t *descriptor,
100 const AudioDeviceTypeAddr& device,
101 const sp<Client>& client,
102 const sp<IEffectClient>& effectClient,
103 const std::map<audio_patch_handle_t, IAfPatchPanel::Patch>& patches,
104 int *enabled,
105 status_t *status,
106 bool probe,
107 bool notifyFramesProcessed) {
108 sp<IAfDeviceEffectProxy> effect;
109 std::vector<sp<IAfDeviceEffectProxy>> effectsForDevice = {};
110 sp<IAfEffectHandle> handle;
111 status_t lStatus;
112
113 lStatus = checkEffectCompatibility(descriptor);
114 if (probe || lStatus != NO_ERROR) {
115 *status = lStatus;
116 return handle;
117 }
118
119 {
120 audio_utils::lock_guard _l(mutex());
121 auto iter = mDeviceEffects.find(device);
122 if (iter != mDeviceEffects.end()) {
123 effectsForDevice = iter->second;
124 for (const auto& iterEffect : effectsForDevice) {
125 if (memcmp(&iterEffect->desc().uuid, &descriptor->uuid, sizeof(effect_uuid_t)) ==
126 0) {
127 effect = iterEffect;
128 break;
129 }
130 }
131 }
132 if (effect == nullptr) {
133 effect = IAfDeviceEffectProxy::create(device, mMyCallback,
134 descriptor,
135 mAfDeviceEffectManagerCallback->nextUniqueId(AUDIO_UNIQUE_ID_USE_EFFECT),
136 notifyFramesProcessed);
137 effectsForDevice.push_back(effect);
138 }
139 // create effect handle and connect it to effect module
140 handle = IAfEffectHandle::create(
141 effect, client, effectClient, 0 /*priority*/, notifyFramesProcessed);
142 lStatus = handle->initCheck();
143 if (lStatus == NO_ERROR) {
144 lStatus = effect->addHandle(handle.get());
145 if (lStatus == NO_ERROR) {
146 lStatus = effect->init_l(patches);
147 if (lStatus == NAME_NOT_FOUND) {
148 lStatus = NO_ERROR;
149 }
150 if (lStatus == NO_ERROR || lStatus == ALREADY_EXISTS) {
151 mDeviceEffects.erase(device);
152 mDeviceEffects.emplace(device, effectsForDevice);
153 }
154 }
155 }
156 }
157 if (enabled != nullptr) {
158 *enabled = (int)effect->isEnabled();
159 }
160 *status = lStatus;
161 return handle;
162 }
163
164 /* static */
checkEffectCompatibility(const effect_descriptor_t * desc)165 status_t DeviceEffectManager::checkEffectCompatibility(
166 const effect_descriptor_t *desc) {
167 const sp<EffectsFactoryHalInterface> effectsFactory =
168 audioflinger::EffectConfiguration::getEffectsFactoryHal();
169 if (effectsFactory == nullptr) {
170 return BAD_VALUE;
171 }
172
173 static const AudioHalVersionInfo sMinDeviceEffectHalVersion =
174 AudioHalVersionInfo(AudioHalVersionInfo::Type::HIDL, 6, 0);
175 static const AudioHalVersionInfo halVersion =
176 audioflinger::EffectConfiguration::getAudioHalVersionInfo();
177
178 // We can trust AIDL generated AudioHalVersionInfo comparison operator (based on std::tie) as
179 // long as the type, major and minor sequence doesn't change in the definition.
180 if (((desc->flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_PRE_PROC
181 && (desc->flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_POST_PROC)
182 || halVersion < sMinDeviceEffectHalVersion) {
183 ALOGW("%s() non pre/post processing device effect %s or incompatible API version %s",
184 __func__, desc->name, halVersion.toString().c_str());
185 return BAD_VALUE;
186 }
187
188 return NO_ERROR;
189 }
190
191 /* static */
createEffectHal(const effect_uuid_t * pEffectUuid,int32_t sessionId,int32_t deviceId,sp<EffectHalInterface> * effect)192 status_t DeviceEffectManager::createEffectHal(
193 const effect_uuid_t *pEffectUuid, int32_t sessionId, int32_t deviceId,
194 sp<EffectHalInterface> *effect) {
195 status_t status = NO_INIT;
196 const sp<EffectsFactoryHalInterface> effectsFactory =
197 audioflinger::EffectConfiguration::getEffectsFactoryHal();
198 if (effectsFactory != 0) {
199 status = effectsFactory->createEffect(
200 pEffectUuid, sessionId, AUDIO_IO_HANDLE_NONE, deviceId, effect);
201 }
202 return status;
203 }
204
dump(int fd)205 void DeviceEffectManager::dump(int fd)
206 NO_THREAD_SAFETY_ANALYSIS // conditional try lock
207 {
208 const bool locked = afutils::dumpTryLock(mutex());
209 if (!locked) {
210 String8 result("DeviceEffectManager may be deadlocked\n");
211 write(fd, result.c_str(), result.size());
212 }
213
214 String8 heading("\nDevice Effects:\n");
215 write(fd, heading.c_str(), heading.size());
216 for (const auto& iter : mDeviceEffects) {
217 String8 outStr;
218 outStr.appendFormat("%*sEffect for device %s address %s:\n", 2, "",
219 ::android::toString(iter.first.mType).c_str(), iter.first.getAddress());
220 for (const auto& effect : iter.second) {
221 write(fd, outStr.c_str(), outStr.size());
222 effect->dump2(fd, 4);
223 }
224 }
225
226 if (locked) {
227 mutex().unlock();
228 }
229 }
230
removeEffect(const sp<IAfDeviceEffectProxy> & effect)231 size_t DeviceEffectManager::removeEffect(const sp<IAfDeviceEffectProxy>& effect)
232 {
233 audio_utils::lock_guard _l(mutex());
234 const auto& iter = mDeviceEffects.find(effect->device());
235 if (iter != mDeviceEffects.end()) {
236 const auto& iterEffect = std::find_if(
237 iter->second.begin(), iter->second.end(), [&effect](const auto& effectProxy) {
238 return memcmp(&effectProxy->desc().uuid, &effect->desc().uuid,
239 sizeof(effect_uuid_t)) == 0;
240 });
241 if (iterEffect != iter->second.end()) {
242 iter->second.erase(iterEffect);
243 if (iter->second.empty()) {
244 mDeviceEffects.erase(effect->device());
245 }
246 }
247 }
248 return mDeviceEffects.size();
249 }
250
disconnectEffectHandle(IAfEffectHandle * handle,bool unpinIfLast)251 bool DeviceEffectManagerCallback::disconnectEffectHandle(
252 IAfEffectHandle *handle, bool unpinIfLast) {
253 sp<IAfEffectBase> effectBase = handle->effect().promote();
254 if (effectBase == nullptr) {
255 return false;
256 }
257
258 sp<IAfDeviceEffectProxy> effect = effectBase->asDeviceEffectProxy();
259 if (effect == nullptr) {
260 return false;
261 }
262 // restore suspended effects if the disconnected handle was enabled and the last one.
263 bool remove = (effect->removeHandle(handle) == 0) && (!effect->isPinned() || unpinIfLast);
264 if (remove) {
265 mManager.removeEffect(effect);
266 if (handle->enabled()) {
267 effectBase->checkSuspendOnEffectEnabled(false, false /*threadLocked*/);
268 }
269 }
270 return true;
271 }
272
isAudioPolicyReady() const273 bool DeviceEffectManagerCallback::isAudioPolicyReady() const {
274 return mManager.afDeviceEffectManagerCallback()->isAudioPolicyReady();
275 }
276
newEffectId() const277 int DeviceEffectManagerCallback::newEffectId() const {
278 return mManager.afDeviceEffectManagerCallback()->nextUniqueId(AUDIO_UNIQUE_ID_USE_EFFECT);
279 }
280
281 } // namespace android
282