blob: a614736d0134450b2546cda5a1c35d8a75a23c76 [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"
26#include <media/audiohal/EffectsFactoryHalInterface.h>
27
28// ----------------------------------------------------------------------------
29
30
31namespace android {
32
Ytai Ben-Tsvi9cd89812020-07-01 17:12:06 -070033using media::IEffectClient;
34
Eric Laurentb82e6b72019-11-22 17:25:04 -080035void AudioFlinger::DeviceEffectManager::onCreateAudioPatch(audio_patch_handle_t handle,
36 const PatchPanel::Patch& patch) {
37 ALOGV("%s handle %d mHalHandle %d device sink %08x",
38 __func__, handle, patch.mHalHandle,
39 patch.mAudioPatch.num_sinks > 0 ? patch.mAudioPatch.sinks[0].ext.device.type : 0);
40 Mutex::Autolock _l(mLock);
41 for (auto& effect : mDeviceEffects) {
42 status_t status = effect.second->onCreatePatch(handle, patch);
43 ALOGV("%s Effect onCreatePatch status %d", __func__, status);
44 ALOGW_IF(status == BAD_VALUE, "%s onCreatePatch error %d", __func__, status);
45 }
46}
47
Eric Laurentb82e6b72019-11-22 17:25:04 -080048void AudioFlinger::DeviceEffectManager::onReleaseAudioPatch(audio_patch_handle_t handle) {
49 ALOGV("%s", __func__);
50 Mutex::Autolock _l(mLock);
51 for (auto& effect : mDeviceEffects) {
52 effect.second->onReleasePatch(handle);
53 }
54}
55
56// DeviceEffectManager::createEffect_l() must be called with AudioFlinger::mLock held
57sp<AudioFlinger::EffectHandle> AudioFlinger::DeviceEffectManager::createEffect_l(
58 effect_descriptor_t *descriptor,
59 const AudioDeviceTypeAddr& device,
60 const sp<AudioFlinger::Client>& client,
61 const sp<IEffectClient>& effectClient,
62 const std::map<audio_patch_handle_t, PatchPanel::Patch>& patches,
63 int *enabled,
Eric Laurent2fe0acd2020-03-13 14:30:46 -070064 status_t *status,
Eric Laurentde8caf42021-08-11 17:19:25 +020065 bool probe,
66 bool notifyFramesProcessed) {
Eric Laurentb82e6b72019-11-22 17:25:04 -080067 sp<DeviceEffectProxy> effect;
68 sp<EffectHandle> handle;
69 status_t lStatus;
70
71 lStatus = checkEffectCompatibility(descriptor);
Eric Laurent2fe0acd2020-03-13 14:30:46 -070072 if (probe || lStatus != NO_ERROR) {
Eric Laurentb82e6b72019-11-22 17:25:04 -080073 *status = lStatus;
74 return handle;
75 }
76
77 {
78 Mutex::Autolock _l(mLock);
79 auto iter = mDeviceEffects.find(device);
80 if (iter != mDeviceEffects.end()) {
81 effect = iter->second;
82 } else {
83 effect = new DeviceEffectProxy(device, mMyCallback,
Eric Laurentde8caf42021-08-11 17:19:25 +020084 descriptor, mAudioFlinger.nextUniqueId(AUDIO_UNIQUE_ID_USE_EFFECT),
85 notifyFramesProcessed);
Eric Laurentb82e6b72019-11-22 17:25:04 -080086 }
87 // create effect handle and connect it to effect module
Eric Laurentde8caf42021-08-11 17:19:25 +020088 handle = new EffectHandle(effect, client, effectClient, 0 /*priority*/,
89 notifyFramesProcessed);
Eric Laurentb82e6b72019-11-22 17:25:04 -080090 lStatus = handle->initCheck();
91 if (lStatus == NO_ERROR) {
92 lStatus = effect->addHandle(handle.get());
93 if (lStatus == NO_ERROR) {
Ram Mohan M2a05df22022-08-28 11:46:23 +053094 lStatus = effect->init(patches);
95 if (lStatus == NAME_NOT_FOUND) {
96 lStatus = NO_ERROR;
97 }
98 if (lStatus == NO_ERROR || lStatus == ALREADY_EXISTS) {
99 mDeviceEffects.emplace(device, effect);
100 }
Eric Laurentb82e6b72019-11-22 17:25:04 -0800101 }
102 }
103 }
Vlad Popa5161f8a2022-10-10 16:17:20 +0200104 if (enabled != nullptr) {
Eric Laurentb82e6b72019-11-22 17:25:04 -0800105 *enabled = (int)effect->isEnabled();
106 }
107 *status = lStatus;
108 return handle;
109}
110
111status_t AudioFlinger::DeviceEffectManager::checkEffectCompatibility(
112 const effect_descriptor_t *desc) {
Eric Laurent9289bde2020-08-18 12:49:17 -0700113 sp<EffectsFactoryHalInterface> effectsFactory = mAudioFlinger.getEffectsFactory();
114 if (effectsFactory == nullptr) {
115 return BAD_VALUE;
116 }
Eric Laurentb82e6b72019-11-22 17:25:04 -0800117
Eric Laurent9289bde2020-08-18 12:49:17 -0700118 static const float sMinDeviceEffectHalVersion = 6.0;
119 float halVersion = effectsFactory->getHalVersion();
120
121 if (((desc->flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_PRE_PROC
122 && (desc->flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_POST_PROC)
123 || halVersion < sMinDeviceEffectHalVersion) {
124 ALOGW("%s() non pre/post processing device effect %s or incompatible API version %f",
125 __func__, desc->name, halVersion);
Eric Laurentb82e6b72019-11-22 17:25:04 -0800126 return BAD_VALUE;
127 }
128
129 return NO_ERROR;
130}
131
132status_t AudioFlinger::DeviceEffectManager::createEffectHal(
133 const effect_uuid_t *pEffectUuid, int32_t sessionId, int32_t deviceId,
134 sp<EffectHalInterface> *effect) {
135 status_t status = NO_INIT;
136 sp<EffectsFactoryHalInterface> effectsFactory = mAudioFlinger.getEffectsFactory();
137 if (effectsFactory != 0) {
138 status = effectsFactory->createEffect(
139 pEffectUuid, sessionId, AUDIO_IO_HANDLE_NONE, deviceId, effect);
140 }
141 return status;
142}
143
144void AudioFlinger::DeviceEffectManager::dump(int fd) {
145 const bool locked = dumpTryLock(mLock);
146 if (!locked) {
147 String8 result("DeviceEffectManager may be deadlocked\n");
148 write(fd, result.string(), result.size());
149 }
150
Phil Burk651d0a52020-05-08 14:00:58 -0700151 String8 heading("\nDevice Effects:\n");
152 write(fd, heading.string(), heading.size());
Eric Laurentb82e6b72019-11-22 17:25:04 -0800153 for (const auto& iter : mDeviceEffects) {
154 String8 outStr;
155 outStr.appendFormat("%*sEffect for device %s address %s:\n", 2, "",
156 ::android::toString(iter.first.mType).c_str(), iter.first.getAddress());
157 write(fd, outStr.string(), outStr.size());
158 iter.second->dump(fd, 4);
159 }
160
161 if (locked) {
162 mLock.unlock();
163 }
164}
165
166
167size_t AudioFlinger::DeviceEffectManager::removeEffect(const sp<DeviceEffectProxy>& effect)
168{
169 Mutex::Autolock _l(mLock);
170 mDeviceEffects.erase(effect->device());
171 return mDeviceEffects.size();
172}
173
174bool AudioFlinger::DeviceEffectManagerCallback::disconnectEffectHandle(
175 EffectHandle *handle, bool unpinIfLast) {
176 sp<EffectBase> effectBase = handle->effect().promote();
177 if (effectBase == nullptr) {
178 return false;
179 }
180
181 sp<DeviceEffectProxy> effect = effectBase->asDeviceEffectProxy();
182 if (effect == nullptr) {
183 return false;
184 }
185 // restore suspended effects if the disconnected handle was enabled and the last one.
186 bool remove = (effect->removeHandle(handle) == 0) && (!effect->isPinned() || unpinIfLast);
187 if (remove) {
188 mManager.removeEffect(effect);
189 if (handle->enabled()) {
190 effectBase->checkSuspendOnEffectEnabled(false, false /*threadLocked*/);
191 }
192 }
193 return true;
194}
195
Eric Laurentb82e6b72019-11-22 17:25:04 -0800196} // namespace android