• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <media/audiohal/EffectsFactoryHalInterface.h>
27 
28 // ----------------------------------------------------------------------------
29 
30 
31 namespace android {
32 
33 using media::IEffectClient;
34 
createAudioPatch(audio_patch_handle_t handle,const PatchPanel::Patch & patch)35 void AudioFlinger::DeviceEffectManager::createAudioPatch(audio_patch_handle_t handle,
36         const PatchPanel::Patch& patch) {
37     ALOGV("%s handle %d mHalHandle %d num sinks %d device sink %08x",
38             __func__, handle, patch.mHalHandle,
39             patch.mAudioPatch.num_sinks,
40             patch.mAudioPatch.num_sinks > 0 ? patch.mAudioPatch.sinks[0].ext.device.type : 0);
41 
42     mCommandThread->createAudioPatchCommand(handle, patch);
43 }
44 
onCreateAudioPatch(audio_patch_handle_t handle,const PatchPanel::Patch & patch)45 void AudioFlinger::DeviceEffectManager::onCreateAudioPatch(audio_patch_handle_t handle,
46         const PatchPanel::Patch& patch) {
47     ALOGV("%s handle %d mHalHandle %d device sink %08x",
48             __func__, handle, patch.mHalHandle,
49             patch.mAudioPatch.num_sinks > 0 ? patch.mAudioPatch.sinks[0].ext.device.type : 0);
50     Mutex::Autolock _l(mLock);
51     for (auto& effect : mDeviceEffects) {
52         status_t status = effect.second->onCreatePatch(handle, patch);
53         ALOGV("%s Effect onCreatePatch status %d", __func__, status);
54         ALOGW_IF(status == BAD_VALUE, "%s onCreatePatch error %d", __func__, status);
55     }
56 }
57 
releaseAudioPatch(audio_patch_handle_t handle)58 void AudioFlinger::DeviceEffectManager::releaseAudioPatch(audio_patch_handle_t handle) {
59     ALOGV("%s", __func__);
60     mCommandThread->releaseAudioPatchCommand(handle);
61 }
62 
onReleaseAudioPatch(audio_patch_handle_t handle)63 void AudioFlinger::DeviceEffectManager::onReleaseAudioPatch(audio_patch_handle_t handle) {
64     ALOGV("%s", __func__);
65     Mutex::Autolock _l(mLock);
66     for (auto& effect : mDeviceEffects) {
67         effect.second->onReleasePatch(handle);
68     }
69 }
70 
71 // 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)72 sp<AudioFlinger::EffectHandle> AudioFlinger::DeviceEffectManager::createEffect_l(
73         effect_descriptor_t *descriptor,
74         const AudioDeviceTypeAddr& device,
75         const sp<AudioFlinger::Client>& client,
76         const sp<IEffectClient>& effectClient,
77         const std::map<audio_patch_handle_t, PatchPanel::Patch>& patches,
78         int *enabled,
79         status_t *status,
80         bool probe) {
81     sp<DeviceEffectProxy> effect;
82     sp<EffectHandle> handle;
83     status_t lStatus;
84 
85     lStatus = checkEffectCompatibility(descriptor);
86     if (probe || lStatus != NO_ERROR) {
87        *status = lStatus;
88        return handle;
89     }
90 
91     {
92         Mutex::Autolock _l(mLock);
93         auto iter = mDeviceEffects.find(device);
94         if (iter != mDeviceEffects.end()) {
95             effect = iter->second;
96         } else {
97             effect = new DeviceEffectProxy(device, mMyCallback,
98                     descriptor, mAudioFlinger.nextUniqueId(AUDIO_UNIQUE_ID_USE_EFFECT));
99         }
100         // create effect handle and connect it to effect module
101         handle = new EffectHandle(effect, client, effectClient, 0 /*priority*/);
102         lStatus = handle->initCheck();
103         if (lStatus == NO_ERROR) {
104             lStatus = effect->addHandle(handle.get());
105             if (lStatus == NO_ERROR) {
106                 effect->init(patches);
107                 mDeviceEffects.emplace(device, effect);
108             }
109         }
110     }
111     if (enabled != NULL) {
112         *enabled = (int)effect->isEnabled();
113     }
114     *status = lStatus;
115     return handle;
116 }
117 
checkEffectCompatibility(const effect_descriptor_t * desc)118 status_t AudioFlinger::DeviceEffectManager::checkEffectCompatibility(
119         const effect_descriptor_t *desc) {
120     sp<EffectsFactoryHalInterface> effectsFactory = mAudioFlinger.getEffectsFactory();
121     if (effectsFactory == nullptr) {
122         return BAD_VALUE;
123     }
124 
125     static const float sMinDeviceEffectHalVersion = 6.0;
126     float halVersion = effectsFactory->getHalVersion();
127 
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 %f",
132                 __func__, desc->name, halVersion);
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     sp<EffectsFactoryHalInterface> effectsFactory = mAudioFlinger.getEffectsFactory();
144     if (effectsFactory != 0) {
145         status = effectsFactory->createEffect(
146                 pEffectUuid, sessionId, AUDIO_IO_HANDLE_NONE, deviceId, effect);
147     }
148     return status;
149 }
150 
dump(int fd)151 void AudioFlinger::DeviceEffectManager::dump(int fd) {
152     const bool locked = dumpTryLock(mLock);
153     if (!locked) {
154         String8 result("DeviceEffectManager may be deadlocked\n");
155         write(fd, result.string(), result.size());
156     }
157 
158     String8 heading("\nDevice Effects:\n");
159     write(fd, heading.string(), heading.size());
160     for (const auto& iter : mDeviceEffects) {
161         String8 outStr;
162         outStr.appendFormat("%*sEffect for device %s address %s:\n", 2, "",
163                 ::android::toString(iter.first.mType).c_str(), iter.first.getAddress());
164         write(fd, outStr.string(), outStr.size());
165         iter.second->dump(fd, 4);
166     }
167 
168     if (locked) {
169         mLock.unlock();
170     }
171 }
172 
173 
removeEffect(const sp<DeviceEffectProxy> & effect)174 size_t AudioFlinger::DeviceEffectManager::removeEffect(const sp<DeviceEffectProxy>& effect)
175 {
176     Mutex::Autolock _l(mLock);
177     mDeviceEffects.erase(effect->device());
178     return mDeviceEffects.size();
179 }
180 
disconnectEffectHandle(EffectHandle * handle,bool unpinIfLast)181 bool AudioFlinger::DeviceEffectManagerCallback::disconnectEffectHandle(
182         EffectHandle *handle, bool unpinIfLast) {
183     sp<EffectBase> effectBase = handle->effect().promote();
184     if (effectBase == nullptr) {
185         return false;
186     }
187 
188     sp<DeviceEffectProxy> effect = effectBase->asDeviceEffectProxy();
189     if (effect == nullptr) {
190         return false;
191     }
192     // restore suspended effects if the disconnected handle was enabled and the last one.
193     bool remove = (effect->removeHandle(handle) == 0) && (!effect->isPinned() || unpinIfLast);
194     if (remove) {
195         mManager.removeEffect(effect);
196         if (handle->enabled()) {
197             effectBase->checkSuspendOnEffectEnabled(false, false /*threadLocked*/);
198         }
199     }
200     return true;
201 }
202 
203 // -----------  DeviceEffectManager::CommandThread implementation ----------
204 
205 
~CommandThread()206 AudioFlinger::DeviceEffectManager::CommandThread::~CommandThread()
207 {
208     Mutex::Autolock _l(mLock);
209     mCommands.clear();
210 }
211 
onFirstRef()212 void AudioFlinger::DeviceEffectManager::CommandThread::onFirstRef()
213 {
214     run("DeviceEffectManage_CommandThread", ANDROID_PRIORITY_AUDIO);
215 }
216 
threadLoop()217 bool AudioFlinger::DeviceEffectManager::CommandThread::threadLoop()
218 {
219     mLock.lock();
220     while (!exitPending())
221     {
222         while (!mCommands.empty() && !exitPending()) {
223             sp<Command> command = mCommands.front();
224             mCommands.pop_front();
225             mLock.unlock();
226 
227             switch (command->mCommand) {
228             case CREATE_AUDIO_PATCH: {
229                 CreateAudioPatchData *data = (CreateAudioPatchData *)command->mData.get();
230                 ALOGV("CommandThread() processing create audio patch handle %d", data->mHandle);
231                 mManager.onCreateAudioPatch(data->mHandle, data->mPatch);
232                 } break;
233             case RELEASE_AUDIO_PATCH: {
234                 ReleaseAudioPatchData *data = (ReleaseAudioPatchData *)command->mData.get();
235                 ALOGV("CommandThread() processing release audio patch handle %d", data->mHandle);
236                 mManager.onReleaseAudioPatch(data->mHandle);
237                 } break;
238             default:
239                 ALOGW("CommandThread() unknown command %d", command->mCommand);
240             }
241             mLock.lock();
242         }
243 
244         // At this stage we have either an empty command queue or the first command in the queue
245         // has a finite delay. So unless we are exiting it is safe to wait.
246         if (!exitPending()) {
247             ALOGV("CommandThread() going to sleep");
248             mWaitWorkCV.wait(mLock);
249         }
250     }
251     mLock.unlock();
252     return false;
253 }
254 
sendCommand(sp<Command> command)255 void AudioFlinger::DeviceEffectManager::CommandThread::sendCommand(sp<Command> command) {
256     Mutex::Autolock _l(mLock);
257     mCommands.push_back(command);
258     mWaitWorkCV.signal();
259 }
260 
createAudioPatchCommand(audio_patch_handle_t handle,const PatchPanel::Patch & patch)261 void AudioFlinger::DeviceEffectManager::CommandThread::createAudioPatchCommand(
262         audio_patch_handle_t handle, const PatchPanel::Patch& patch)
263 {
264     sp<Command> command = new Command(CREATE_AUDIO_PATCH, new CreateAudioPatchData(handle, patch));
265     ALOGV("CommandThread() adding create patch handle %d mHalHandle %d.", handle, patch.mHalHandle);
266     sendCommand(command);
267 }
268 
releaseAudioPatchCommand(audio_patch_handle_t handle)269 void AudioFlinger::DeviceEffectManager::CommandThread::releaseAudioPatchCommand(
270         audio_patch_handle_t handle)
271 {
272     sp<Command> command = new Command(RELEASE_AUDIO_PATCH, new ReleaseAudioPatchData(handle));
273     ALOGV("CommandThread() adding release patch");
274     sendCommand(command);
275 }
276 
exit()277 void AudioFlinger::DeviceEffectManager::CommandThread::exit()
278 {
279     ALOGV("CommandThread::exit");
280     {
281         AutoMutex _l(mLock);
282         requestExit();
283         mWaitWorkCV.signal();
284     }
285     // Note that we can call it from the thread loop if all other references have been released
286     // but it will safely return WOULD_BLOCK in this case
287     requestExitAndWait();
288 }
289 
290 } // namespace android
291