blob: 9995ed31508989bed2db3cd02ba13a78168e2707 [file] [log] [blame]
Eric Laurentb82e6b72019-11-22 17:25:04 -08001/*
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
19#define LOG_TAG "AudioFlinger::DeviceEffectManager"
20//#define LOG_NDEBUG 0
21
22#include <utils/Log.h>
23#include <audio_utils/primitives.h>
24
25#include "AudioFlinger.h"
Andy Hungba8e52b2023-05-11 14:33:03 -070026#include "EffectConfiguration.h"
Eric Laurentb82e6b72019-11-22 17:25:04 -080027#include <media/audiohal/EffectsFactoryHalInterface.h>
28
29// ----------------------------------------------------------------------------
30
31
32namespace android {
33
Shunkai Yaod7ea4092022-12-12 00:44:33 +000034using detail::AudioHalVersionInfo;
Ytai Ben-Tsvi9cd89812020-07-01 17:12:06 -070035using media::IEffectClient;
36
Eric Laurentb82e6b72019-11-22 17:25:04 -080037void AudioFlinger::DeviceEffectManager::onCreateAudioPatch(audio_patch_handle_t handle,
38 const PatchPanel::Patch& patch) {
39 ALOGV("%s handle %d mHalHandle %d device sink %08x",
40 __func__, handle, patch.mHalHandle,
41 patch.mAudioPatch.num_sinks > 0 ? patch.mAudioPatch.sinks[0].ext.device.type : 0);
42 Mutex::Autolock _l(mLock);
43 for (auto& effect : mDeviceEffects) {
Andy Hung6ac17eb2023-06-20 18:56:17 -070044 status_t status = effect.second->onCreatePatch(handle, &patch); // TODO(b/288339104) void*
Eric Laurentb82e6b72019-11-22 17:25:04 -080045 ALOGV("%s Effect onCreatePatch status %d", __func__, status);
46 ALOGW_IF(status == BAD_VALUE, "%s onCreatePatch error %d", __func__, status);
47 }
48}
49
Eric Laurentb82e6b72019-11-22 17:25:04 -080050void AudioFlinger::DeviceEffectManager::onReleaseAudioPatch(audio_patch_handle_t handle) {
51 ALOGV("%s", __func__);
52 Mutex::Autolock _l(mLock);
53 for (auto& effect : mDeviceEffects) {
54 effect.second->onReleasePatch(handle);
55 }
56}
57
François Gaffie58e73af2023-02-15 11:47:24 +010058void AudioFlinger::DeviceEffectManager::onUpdateAudioPatch(audio_patch_handle_t oldHandle,
59 audio_patch_handle_t newHandle, const PatchPanel::Patch& patch) {
60 ALOGV("%s oldhandle %d newHandle %d mHalHandle %d device sink %08x",
61 __func__, oldHandle, newHandle, patch.mHalHandle,
62 patch.mAudioPatch.num_sinks > 0 ? patch.mAudioPatch.sinks[0].ext.device.type : 0);
63 Mutex::Autolock _l(mLock);
64 for (auto& effect : mDeviceEffects) {
65 // TODO(b/288339104) void*
66 status_t status = effect.second->onUpdatePatch(oldHandle, newHandle, &patch);
67 ALOGW_IF(status != NO_ERROR, "%s onUpdatePatch error %d", __func__, status);
68 }
69}
70
Eric Laurentb82e6b72019-11-22 17:25:04 -080071// DeviceEffectManager::createEffect_l() must be called with AudioFlinger::mLock held
Andy Hung6ac17eb2023-06-20 18:56:17 -070072sp<IAfEffectHandle> AudioFlinger::DeviceEffectManager::createEffect_l(
Eric Laurentb82e6b72019-11-22 17:25:04 -080073 effect_descriptor_t *descriptor,
74 const AudioDeviceTypeAddr& device,
Andy Hung59867e42023-06-27 17:05:02 -070075 const sp<Client>& client,
Eric Laurentb82e6b72019-11-22 17:25:04 -080076 const sp<IEffectClient>& effectClient,
77 const std::map<audio_patch_handle_t, PatchPanel::Patch>& patches,
78 int *enabled,
Eric Laurent2fe0acd2020-03-13 14:30:46 -070079 status_t *status,
Eric Laurentde8caf42021-08-11 17:19:25 +020080 bool probe,
81 bool notifyFramesProcessed) {
Andy Hung6ac17eb2023-06-20 18:56:17 -070082 sp<IAfDeviceEffectProxy> effect;
83 sp<IAfEffectHandle> handle;
Eric Laurentb82e6b72019-11-22 17:25:04 -080084 status_t lStatus;
85
86 lStatus = checkEffectCompatibility(descriptor);
Eric Laurent2fe0acd2020-03-13 14:30:46 -070087 if (probe || lStatus != NO_ERROR) {
Eric Laurentb82e6b72019-11-22 17:25:04 -080088 *status = lStatus;
89 return handle;
90 }
91
92 {
93 Mutex::Autolock _l(mLock);
94 auto iter = mDeviceEffects.find(device);
95 if (iter != mDeviceEffects.end()) {
96 effect = iter->second;
97 } else {
Andy Hung6ac17eb2023-06-20 18:56:17 -070098 effect = IAfDeviceEffectProxy::create(device, mMyCallback,
Eric Laurentde8caf42021-08-11 17:19:25 +020099 descriptor, mAudioFlinger.nextUniqueId(AUDIO_UNIQUE_ID_USE_EFFECT),
100 notifyFramesProcessed);
Eric Laurentb82e6b72019-11-22 17:25:04 -0800101 }
102 // create effect handle and connect it to effect module
Andy Hung6ac17eb2023-06-20 18:56:17 -0700103 handle = IAfEffectHandle::create(
104 effect, client, effectClient, 0 /*priority*/, notifyFramesProcessed);
Eric Laurentb82e6b72019-11-22 17:25:04 -0800105 lStatus = handle->initCheck();
106 if (lStatus == NO_ERROR) {
107 lStatus = effect->addHandle(handle.get());
108 if (lStatus == NO_ERROR) {
Andy Hung6ac17eb2023-06-20 18:56:17 -0700109 lStatus = effect->init(&patches); // TODO(b/288339104) void*
Ram Mohan M2a05df22022-08-28 11:46:23 +0530110 if (lStatus == NAME_NOT_FOUND) {
111 lStatus = NO_ERROR;
112 }
113 if (lStatus == NO_ERROR || lStatus == ALREADY_EXISTS) {
114 mDeviceEffects.emplace(device, effect);
115 }
Eric Laurentb82e6b72019-11-22 17:25:04 -0800116 }
117 }
118 }
Vlad Popa5161f8a2022-10-10 16:17:20 +0200119 if (enabled != nullptr) {
Eric Laurentb82e6b72019-11-22 17:25:04 -0800120 *enabled = (int)effect->isEnabled();
121 }
122 *status = lStatus;
123 return handle;
124}
125
126status_t AudioFlinger::DeviceEffectManager::checkEffectCompatibility(
127 const effect_descriptor_t *desc) {
Andy Hungba8e52b2023-05-11 14:33:03 -0700128 const sp<EffectsFactoryHalInterface> effectsFactory =
129 audioflinger::EffectConfiguration::getEffectsFactoryHal();
Eric Laurent9289bde2020-08-18 12:49:17 -0700130 if (effectsFactory == nullptr) {
131 return BAD_VALUE;
132 }
Eric Laurentb82e6b72019-11-22 17:25:04 -0800133
Andy Hungba8e52b2023-05-11 14:33:03 -0700134 static const AudioHalVersionInfo sMinDeviceEffectHalVersion =
Shunkai Yaod7ea4092022-12-12 00:44:33 +0000135 AudioHalVersionInfo(AudioHalVersionInfo::Type::HIDL, 6, 0);
Andy Hungba8e52b2023-05-11 14:33:03 -0700136 static const AudioHalVersionInfo halVersion =
137 audioflinger::EffectConfiguration::getAudioHalVersionInfo();
Eric Laurent9289bde2020-08-18 12:49:17 -0700138
Shunkai Yaod7ea4092022-12-12 00:44:33 +0000139 // We can trust AIDL generated AudioHalVersionInfo comparison operator (based on std::tie) as
140 // long as the type, major and minor sequence doesn't change in the definition.
Eric Laurent9289bde2020-08-18 12:49:17 -0700141 if (((desc->flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_PRE_PROC
142 && (desc->flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_POST_PROC)
143 || halVersion < sMinDeviceEffectHalVersion) {
Shunkai Yao489c5a92022-12-02 05:35:41 +0000144 ALOGW("%s() non pre/post processing device effect %s or incompatible API version %s",
145 __func__, desc->name, halVersion.toString().c_str());
Eric Laurentb82e6b72019-11-22 17:25:04 -0800146 return BAD_VALUE;
147 }
148
149 return NO_ERROR;
150}
151
152status_t AudioFlinger::DeviceEffectManager::createEffectHal(
153 const effect_uuid_t *pEffectUuid, int32_t sessionId, int32_t deviceId,
154 sp<EffectHalInterface> *effect) {
155 status_t status = NO_INIT;
Andy Hungba8e52b2023-05-11 14:33:03 -0700156 const sp<EffectsFactoryHalInterface> effectsFactory =
157 audioflinger::EffectConfiguration::getEffectsFactoryHal();
Eric Laurentb82e6b72019-11-22 17:25:04 -0800158 if (effectsFactory != 0) {
159 status = effectsFactory->createEffect(
160 pEffectUuid, sessionId, AUDIO_IO_HANDLE_NONE, deviceId, effect);
161 }
162 return status;
163}
164
Andy Hung920f6572022-10-06 12:09:49 -0700165void AudioFlinger::DeviceEffectManager::dump(int fd)
166NO_THREAD_SAFETY_ANALYSIS // conditional try lock
167{
Eric Laurentb82e6b72019-11-22 17:25:04 -0800168 const bool locked = dumpTryLock(mLock);
169 if (!locked) {
170 String8 result("DeviceEffectManager may be deadlocked\n");
171 write(fd, result.string(), result.size());
172 }
173
Phil Burk651d0a52020-05-08 14:00:58 -0700174 String8 heading("\nDevice Effects:\n");
175 write(fd, heading.string(), heading.size());
Eric Laurentb82e6b72019-11-22 17:25:04 -0800176 for (const auto& iter : mDeviceEffects) {
177 String8 outStr;
178 outStr.appendFormat("%*sEffect for device %s address %s:\n", 2, "",
179 ::android::toString(iter.first.mType).c_str(), iter.first.getAddress());
180 write(fd, outStr.string(), outStr.size());
Andy Hung6ac17eb2023-06-20 18:56:17 -0700181 iter.second->dump2(fd, 4);
Eric Laurentb82e6b72019-11-22 17:25:04 -0800182 }
183
184 if (locked) {
185 mLock.unlock();
186 }
187}
188
189
Andy Hung6ac17eb2023-06-20 18:56:17 -0700190size_t AudioFlinger::DeviceEffectManager::removeEffect(const sp<IAfDeviceEffectProxy>& effect)
Eric Laurentb82e6b72019-11-22 17:25:04 -0800191{
192 Mutex::Autolock _l(mLock);
193 mDeviceEffects.erase(effect->device());
194 return mDeviceEffects.size();
195}
196
197bool AudioFlinger::DeviceEffectManagerCallback::disconnectEffectHandle(
Andy Hung6ac17eb2023-06-20 18:56:17 -0700198 IAfEffectHandle *handle, bool unpinIfLast) {
199 sp<IAfEffectBase> effectBase = handle->effect().promote();
Eric Laurentb82e6b72019-11-22 17:25:04 -0800200 if (effectBase == nullptr) {
201 return false;
202 }
203
Andy Hung6ac17eb2023-06-20 18:56:17 -0700204 sp<IAfDeviceEffectProxy> effect = effectBase->asDeviceEffectProxy();
Eric Laurentb82e6b72019-11-22 17:25:04 -0800205 if (effect == nullptr) {
206 return false;
207 }
208 // restore suspended effects if the disconnected handle was enabled and the last one.
209 bool remove = (effect->removeHandle(handle) == 0) && (!effect->isPinned() || unpinIfLast);
210 if (remove) {
211 mManager.removeEffect(effect);
212 if (handle->enabled()) {
213 effectBase->checkSuspendOnEffectEnabled(false, false /*threadLocked*/);
214 }
215 }
216 return true;
217}
218
Eric Laurentb82e6b72019-11-22 17:25:04 -0800219} // namespace android