xref: /aosp_15_r20/frameworks/av/services/audioflinger/DeviceEffectManager.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
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/FallibleLockGuard.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     // Keep a reference on disconnected handle to delay destruction without lock held.
75     std::vector<sp<IAfEffectHandle>> disconnectedHandles{};
76     audio_utils::lock_guard _l(mutex());
77     for (auto& effectProxies : mDeviceEffects) {
78         for (auto& effect : effectProxies.second) {
79             sp<IAfEffectHandle> disconnectedHandle = effect->onReleasePatch(handle);
80             if (disconnectedHandle != nullptr) {
81                 disconnectedHandles.push_back(std::move(disconnectedHandle));
82             }
83         }
84     }
85 }
86 
onUpdateAudioPatch(audio_patch_handle_t oldHandle,audio_patch_handle_t newHandle,const IAfPatchPanel::Patch & patch)87 void DeviceEffectManager::onUpdateAudioPatch(audio_patch_handle_t oldHandle,
88         audio_patch_handle_t newHandle, const IAfPatchPanel::Patch& patch) {
89     ALOGV("%s oldhandle %d newHandle %d mHalHandle %d device sink %08x",
90             __func__, oldHandle, newHandle, patch.mHalHandle,
91             patch.mAudioPatch.num_sinks > 0 ? patch.mAudioPatch.sinks[0].ext.device.type : 0);
92     audio_utils::lock_guard _l(mutex());
93     for (auto& effectProxies : mDeviceEffects) {
94         for (auto& effect : effectProxies.second) {
95             const status_t status = effect->onUpdatePatch(oldHandle, newHandle, patch);
96             ALOGV("%s Effect onUpdatePatch status %d", __func__, status);
97             ALOGW_IF(status != NO_ERROR, "%s onUpdatePatch error %d", __func__, status);
98         }
99     }
100 }
101 
102 // 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)103 sp<IAfEffectHandle> DeviceEffectManager::createEffect_l(
104         effect_descriptor_t *descriptor,
105         const AudioDeviceTypeAddr& device,
106         const sp<Client>& client,
107         const sp<IEffectClient>& effectClient,
108         const std::map<audio_patch_handle_t, IAfPatchPanel::Patch>& patches,
109         int *enabled,
110         status_t *status,
111         bool probe,
112         bool notifyFramesProcessed) {
113     sp<IAfDeviceEffectProxy> effect;
114     std::vector<sp<IAfDeviceEffectProxy>> effectsForDevice = {};
115     sp<IAfEffectHandle> handle;
116     status_t lStatus;
117 
118     lStatus = checkEffectCompatibility(descriptor);
119     if (probe || lStatus != NO_ERROR) {
120        *status = lStatus;
121        return handle;
122     }
123 
124     {
125         audio_utils::lock_guard _l(mutex());
126         auto iter = mDeviceEffects.find(device);
127         if (iter != mDeviceEffects.end()) {
128             effectsForDevice = iter->second;
129             for (const auto& iterEffect : effectsForDevice) {
130                 if (memcmp(&iterEffect->desc().uuid, &descriptor->uuid, sizeof(effect_uuid_t)) ==
131                     0) {
132                     effect = iterEffect;
133                     break;
134                 }
135             }
136         }
137         if (effect == nullptr) {
138             effect = IAfDeviceEffectProxy::create(device, mMyCallback,
139                     descriptor,
140                     mAfDeviceEffectManagerCallback->nextUniqueId(AUDIO_UNIQUE_ID_USE_EFFECT),
141                     notifyFramesProcessed);
142             effectsForDevice.push_back(effect);
143         }
144         // create effect handle and connect it to effect module
145         handle = IAfEffectHandle::create(
146                 effect, client, effectClient, 0 /*priority*/, notifyFramesProcessed);
147         lStatus = handle->initCheck();
148         if (lStatus == NO_ERROR) {
149             lStatus = effect->addHandle(handle.get());
150             if (lStatus == NO_ERROR) {
151                 lStatus = effect->init_l(patches);
152                 if (lStatus == NAME_NOT_FOUND) {
153                     lStatus = NO_ERROR;
154                 }
155                 if (lStatus == NO_ERROR || lStatus == ALREADY_EXISTS) {
156                     mDeviceEffects.erase(device);
157                     mDeviceEffects.emplace(device, effectsForDevice);
158                 }
159             }
160         }
161     }
162     if (enabled != nullptr) {
163         *enabled = (int)effect->isEnabled();
164     }
165     *status = lStatus;
166     return handle;
167 }
168 
169 /* static */
checkEffectCompatibility(const effect_descriptor_t * desc)170 status_t DeviceEffectManager::checkEffectCompatibility(
171         const effect_descriptor_t *desc) {
172     const sp<EffectsFactoryHalInterface> effectsFactory =
173             audioflinger::EffectConfiguration::getEffectsFactoryHal();
174     if (effectsFactory == nullptr) {
175         return BAD_VALUE;
176     }
177 
178     static const AudioHalVersionInfo sMinDeviceEffectHalVersion =
179             AudioHalVersionInfo(AudioHalVersionInfo::Type::HIDL, 6, 0);
180     static const AudioHalVersionInfo halVersion =
181             audioflinger::EffectConfiguration::getAudioHalVersionInfo();
182 
183     // We can trust AIDL generated AudioHalVersionInfo comparison operator (based on std::tie) as
184     // long as the type, major and minor sequence doesn't change in the definition.
185     if (((desc->flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_PRE_PROC
186             && (desc->flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_POST_PROC)
187             || halVersion < sMinDeviceEffectHalVersion) {
188         ALOGW("%s() non pre/post processing device effect %s or incompatible API version %s",
189                 __func__, desc->name, halVersion.toString().c_str());
190         return BAD_VALUE;
191     }
192 
193     return NO_ERROR;
194 }
195 
196 /* static */
createEffectHal(const effect_uuid_t * pEffectUuid,int32_t sessionId,int32_t deviceId,sp<EffectHalInterface> * effect)197 status_t DeviceEffectManager::createEffectHal(
198         const effect_uuid_t *pEffectUuid, int32_t sessionId, int32_t deviceId,
199         sp<EffectHalInterface> *effect) {
200     status_t status = NO_INIT;
201     const sp<EffectsFactoryHalInterface> effectsFactory =
202             audioflinger::EffectConfiguration::getEffectsFactoryHal();
203     if (effectsFactory != 0) {
204         status = effectsFactory->createEffect(
205                 pEffectUuid, sessionId, AUDIO_IO_HANDLE_NONE, deviceId, effect);
206     }
207     return status;
208 }
209 
dump(int fd)210 void DeviceEffectManager::dump(int fd)
211 {
212     afutils::FallibleLockGuard l{mutex()};
213     if (!l) {
214         String8 result("DeviceEffectManager may be deadlocked\n");
215         write(fd, result.c_str(), result.size());
216     }
217 
218     String8 heading("\nDevice Effects:\n");
219     write(fd, heading.c_str(), heading.size());
220     for (const auto& iter : mDeviceEffects) {
221         String8 outStr;
222         outStr.appendFormat("%*sEffect for device %s address %s:\n", 2, "",
223                 ::android::toString(iter.first.mType).c_str(), iter.first.getAddress());
224         for (const auto& effect : iter.second) {
225             write(fd, outStr.c_str(), outStr.size());
226             effect->dump2(fd, 4);
227         }
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