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
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 "EffectConfiguration.h"
27 #include <media/audiohal/EffectsFactoryHalInterface.h>
28
29 // ----------------------------------------------------------------------------
30
31
32 namespace android {
33
34 using detail::AudioHalVersionInfo;
35 using media::IEffectClient;
36
onCreateAudioPatch(audio_patch_handle_t handle,const PatchPanel::Patch & patch)37 void 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) {
44 status_t status = effect.second->onCreatePatch(handle, patch);
45 ALOGV("%s Effect onCreatePatch status %d", __func__, status);
46 ALOGW_IF(status == BAD_VALUE, "%s onCreatePatch error %d", __func__, status);
47 }
48 }
49
onReleaseAudioPatch(audio_patch_handle_t handle)50 void 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
58 // DeviceEffectManager::createEffect_l() must be called with AudioFlinger::mLock held
createEffect_l(effect_descriptor_t * descriptor,const AudioDeviceTypeAddr & device,const sp<AudioFlinger::Client> & client,const sp<IEffectClient> & effectClient,const std::map<audio_patch_handle_t,PatchPanel::Patch> & patches,int * enabled,status_t * status,bool probe,bool notifyFramesProcessed)59 sp<AudioFlinger::EffectHandle> AudioFlinger::DeviceEffectManager::createEffect_l(
60 effect_descriptor_t *descriptor,
61 const AudioDeviceTypeAddr& device,
62 const sp<AudioFlinger::Client>& client,
63 const sp<IEffectClient>& effectClient,
64 const std::map<audio_patch_handle_t, PatchPanel::Patch>& patches,
65 int *enabled,
66 status_t *status,
67 bool probe,
68 bool notifyFramesProcessed) {
69 sp<DeviceEffectProxy> effect;
70 sp<EffectHandle> handle;
71 status_t lStatus;
72
73 lStatus = checkEffectCompatibility(descriptor);
74 if (probe || lStatus != NO_ERROR) {
75 *status = lStatus;
76 return handle;
77 }
78
79 {
80 Mutex::Autolock _l(mLock);
81 auto iter = mDeviceEffects.find(device);
82 if (iter != mDeviceEffects.end()) {
83 effect = iter->second;
84 } else {
85 effect = new DeviceEffectProxy(device, mMyCallback,
86 descriptor, mAudioFlinger.nextUniqueId(AUDIO_UNIQUE_ID_USE_EFFECT),
87 notifyFramesProcessed);
88 }
89 // create effect handle and connect it to effect module
90 handle = new EffectHandle(effect, client, effectClient, 0 /*priority*/,
91 notifyFramesProcessed);
92 lStatus = handle->initCheck();
93 if (lStatus == NO_ERROR) {
94 lStatus = effect->addHandle(handle.get());
95 if (lStatus == NO_ERROR) {
96 lStatus = effect->init(patches);
97 if (lStatus == NAME_NOT_FOUND) {
98 lStatus = NO_ERROR;
99 }
100 if (lStatus == NO_ERROR || lStatus == ALREADY_EXISTS) {
101 mDeviceEffects.emplace(device, effect);
102 }
103 }
104 }
105 }
106 if (enabled != nullptr) {
107 *enabled = (int)effect->isEnabled();
108 }
109 *status = lStatus;
110 return handle;
111 }
112
checkEffectCompatibility(const effect_descriptor_t * desc)113 status_t AudioFlinger::DeviceEffectManager::checkEffectCompatibility(
114 const effect_descriptor_t *desc) {
115 const sp<EffectsFactoryHalInterface> effectsFactory =
116 audioflinger::EffectConfiguration::getEffectsFactoryHal();
117 if (effectsFactory == nullptr) {
118 return BAD_VALUE;
119 }
120
121 static const AudioHalVersionInfo sMinDeviceEffectHalVersion =
122 AudioHalVersionInfo(AudioHalVersionInfo::Type::HIDL, 6, 0);
123 static const AudioHalVersionInfo halVersion =
124 audioflinger::EffectConfiguration::getAudioHalVersionInfo();
125
126 // We can trust AIDL generated AudioHalVersionInfo comparison operator (based on std::tie) as
127 // long as the type, major and minor sequence doesn't change in the definition.
128 if (((desc->flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_PRE_PROC
129 && (desc->flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_POST_PROC)
130 || halVersion < sMinDeviceEffectHalVersion) {
131 ALOGW("%s() non pre/post processing device effect %s or incompatible API version %s",
132 __func__, desc->name, halVersion.toString().c_str());
133 return BAD_VALUE;
134 }
135
136 return NO_ERROR;
137 }
138
createEffectHal(const effect_uuid_t * pEffectUuid,int32_t sessionId,int32_t deviceId,sp<EffectHalInterface> * effect)139 status_t AudioFlinger::DeviceEffectManager::createEffectHal(
140 const effect_uuid_t *pEffectUuid, int32_t sessionId, int32_t deviceId,
141 sp<EffectHalInterface> *effect) {
142 status_t status = NO_INIT;
143 const sp<EffectsFactoryHalInterface> effectsFactory =
144 audioflinger::EffectConfiguration::getEffectsFactoryHal();
145 if (effectsFactory != 0) {
146 status = effectsFactory->createEffect(
147 pEffectUuid, sessionId, AUDIO_IO_HANDLE_NONE, deviceId, effect);
148 }
149 return status;
150 }
151
dump(int fd)152 void AudioFlinger::DeviceEffectManager::dump(int fd)
153 NO_THREAD_SAFETY_ANALYSIS // conditional try lock
154 {
155 const bool locked = dumpTryLock(mLock);
156 if (!locked) {
157 String8 result("DeviceEffectManager may be deadlocked\n");
158 write(fd, result.string(), result.size());
159 }
160
161 String8 heading("\nDevice Effects:\n");
162 write(fd, heading.string(), heading.size());
163 for (const auto& iter : mDeviceEffects) {
164 String8 outStr;
165 outStr.appendFormat("%*sEffect for device %s address %s:\n", 2, "",
166 ::android::toString(iter.first.mType).c_str(), iter.first.getAddress());
167 write(fd, outStr.string(), outStr.size());
168 iter.second->dump(fd, 4);
169 }
170
171 if (locked) {
172 mLock.unlock();
173 }
174 }
175
176
removeEffect(const sp<DeviceEffectProxy> & effect)177 size_t AudioFlinger::DeviceEffectManager::removeEffect(const sp<DeviceEffectProxy>& effect)
178 {
179 Mutex::Autolock _l(mLock);
180 mDeviceEffects.erase(effect->device());
181 return mDeviceEffects.size();
182 }
183
disconnectEffectHandle(EffectHandle * handle,bool unpinIfLast)184 bool AudioFlinger::DeviceEffectManagerCallback::disconnectEffectHandle(
185 EffectHandle *handle, bool unpinIfLast) {
186 sp<EffectBase> effectBase = handle->effect().promote();
187 if (effectBase == nullptr) {
188 return false;
189 }
190
191 sp<DeviceEffectProxy> effect = effectBase->asDeviceEffectProxy();
192 if (effect == nullptr) {
193 return false;
194 }
195 // restore suspended effects if the disconnected handle was enabled and the last one.
196 bool remove = (effect->removeHandle(handle) == 0) && (!effect->isPinned() || unpinIfLast);
197 if (remove) {
198 mManager.removeEffect(effect);
199 if (handle->enabled()) {
200 effectBase->checkSuspendOnEffectEnabled(false, false /*threadLocked*/);
201 }
202 }
203 return true;
204 }
205
206 } // namespace android
207