AudioEffect.cpp revision f5aafb209d01ba2ab6cb55d1a12cfc653e2b4be0
1/*
2**
3** Copyright 2010, 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_NDEBUG 0
20#define LOG_TAG "AudioEffect"
21
22#include <stdint.h>
23#include <sys/types.h>
24#include <limits.h>
25
26#include <private/media/AudioEffectShared.h>
27#include <media/AudioEffect.h>
28
29#include <utils/Log.h>
30#include <binder/IPCThreadState.h>
31
32
33
34namespace android {
35
36// ---------------------------------------------------------------------------
37
38AudioEffect::AudioEffect()
39    : mStatus(NO_INIT)
40{
41}
42
43
44AudioEffect::AudioEffect(const effect_uuid_t *type,
45                const effect_uuid_t *uuid,
46                int32_t priority,
47                effect_callback_t cbf,
48                void* user,
49                int sessionId,
50                audio_io_handle_t output
51                )
52    : mStatus(NO_INIT)
53{
54    mStatus = set(type, uuid, priority, cbf, user, sessionId, output);
55}
56
57AudioEffect::AudioEffect(const char *typeStr,
58                const char *uuidStr,
59                int32_t priority,
60                effect_callback_t cbf,
61                void* user,
62                int sessionId,
63                audio_io_handle_t output
64                )
65    : mStatus(NO_INIT)
66{
67    effect_uuid_t type;
68    effect_uuid_t *pType = NULL;
69    effect_uuid_t uuid;
70    effect_uuid_t *pUuid = NULL;
71
72    LOGV("Constructor string\n - type: %s\n - uuid: %s", typeStr, uuidStr);
73
74    if (typeStr != NULL) {
75        if (stringToGuid(typeStr, &type) == NO_ERROR) {
76            pType = &type;
77        }
78    }
79
80    if (uuidStr != NULL) {
81        if (stringToGuid(uuidStr, &uuid) == NO_ERROR) {
82            pUuid = &uuid;
83        }
84    }
85
86    mStatus = set(pType, pUuid, priority, cbf, user, sessionId, output);
87}
88
89status_t AudioEffect::set(const effect_uuid_t *type,
90                const effect_uuid_t *uuid,
91                int32_t priority,
92                effect_callback_t cbf,
93                void* user,
94                int sessionId,
95                audio_io_handle_t output)
96{
97    sp<IEffect> iEffect;
98    sp<IMemory> cblk;
99    int enabled;
100
101    LOGV("set %p mUserData: %p", this, user);
102
103    if (mIEffect != 0) {
104        LOGW("Effect already in use");
105        return INVALID_OPERATION;
106    }
107
108    const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
109    if (audioFlinger == 0) {
110        LOGE("set(): Could not get audioflinger");
111        return NO_INIT;
112    }
113
114    if (type == NULL && uuid == NULL) {
115        LOGW("Must specify at least type or uuid");
116        return BAD_VALUE;
117    }
118
119    mPriority = priority;
120    mCbf = cbf;
121    mUserData = user;
122    mSessionId = sessionId;
123
124    memset(&mDescriptor, 0, sizeof(effect_descriptor_t));
125    memcpy(&mDescriptor.type, EFFECT_UUID_NULL, sizeof(effect_uuid_t));
126    memcpy(&mDescriptor.uuid, EFFECT_UUID_NULL, sizeof(effect_uuid_t));
127
128    if (type != NULL) {
129        memcpy(&mDescriptor.type, type, sizeof(effect_uuid_t));
130    }
131    if (uuid != NULL) {
132        memcpy(&mDescriptor.uuid, uuid, sizeof(effect_uuid_t));
133    }
134
135    mIEffectClient = new EffectClient(this);
136
137    iEffect = audioFlinger->createEffect(getpid(), (effect_descriptor_t *)&mDescriptor,
138            mIEffectClient, priority, output, mSessionId, &mStatus, &mId, &enabled);
139
140    if (iEffect == 0 || (mStatus != NO_ERROR && mStatus != ALREADY_EXISTS)) {
141        LOGE("set(): AudioFlinger could not create effect, status: %d", mStatus);
142        return mStatus;
143    }
144
145    mEnabled = (volatile int32_t)enabled;
146
147    mIEffect = iEffect;
148    cblk = iEffect->getCblk();
149    if (cblk == 0) {
150        mStatus = NO_INIT;
151        LOGE("Could not get control block");
152        return mStatus;
153    }
154
155    mIEffect = iEffect;
156    mCblkMemory = cblk;
157    mCblk = static_cast<effect_param_cblk_t*>(cblk->pointer());
158    int bufOffset = ((sizeof(effect_param_cblk_t) - 1) / sizeof(int) + 1) * sizeof(int);
159    mCblk->buffer = (uint8_t *)mCblk + bufOffset;
160
161    iEffect->asBinder()->linkToDeath(mIEffectClient);
162    LOGV("set() %p OK effect: %s id: %d status %d enabled %d, ", this, mDescriptor.name, mId, mStatus, mEnabled);
163
164    return mStatus;
165}
166
167
168AudioEffect::~AudioEffect()
169{
170    LOGV("Destructor %p", this);
171
172    if (mStatus == NO_ERROR || mStatus == ALREADY_EXISTS) {
173        setEnabled(false);
174        if (mIEffect != NULL) {
175            mIEffect->disconnect();
176            mIEffect->asBinder()->unlinkToDeath(mIEffectClient);
177        }
178         IPCThreadState::self()->flushCommands();
179    }
180    mIEffect.clear();
181    mIEffectClient.clear();
182    mCblkMemory.clear();
183}
184
185
186status_t AudioEffect::initCheck() const
187{
188    return mStatus;
189}
190
191// -------------------------------------------------------------------------
192
193effect_descriptor_t AudioEffect::descriptor() const
194{
195    return mDescriptor;
196}
197
198bool AudioEffect::getEnabled() const
199{
200    return (mEnabled != 0);
201}
202
203status_t AudioEffect::setEnabled(bool enabled)
204{
205    if (mStatus != NO_ERROR) {
206        return INVALID_OPERATION;
207    }
208
209    status_t status = NO_ERROR;
210
211    AutoMutex lock(mLock);
212    if (enabled != mEnabled) {
213        if (enabled) {
214            LOGV("enable %p", this);
215            status = mIEffect->enable();
216        } else {
217            LOGV("disable %p", this);
218            status = mIEffect->disable();
219        }
220        if (status == NO_ERROR) {
221            mEnabled = enabled;
222        }
223    }
224    return status;
225}
226
227status_t AudioEffect::command(uint32_t cmdCode,
228                              uint32_t cmdSize,
229                              void *cmdData,
230                              uint32_t *replySize,
231                              void *replyData)
232{
233    if (mStatus != NO_ERROR && mStatus != ALREADY_EXISTS) {
234        LOGV("command() bad status %d", mStatus);
235        return INVALID_OPERATION;
236    }
237
238    if (cmdCode == EFFECT_CMD_ENABLE || cmdCode == EFFECT_CMD_DISABLE) {
239        if (mEnabled == (cmdCode == EFFECT_CMD_ENABLE)) {
240            return NO_ERROR;
241        }
242        if (replySize == NULL || *replySize != sizeof(status_t) || replyData == NULL) {
243            return BAD_VALUE;
244        }
245        mLock.lock();
246    }
247
248    status_t status = mIEffect->command(cmdCode, cmdSize, cmdData, replySize, replyData);
249
250    if (cmdCode == EFFECT_CMD_ENABLE || cmdCode == EFFECT_CMD_DISABLE) {
251        if (status == NO_ERROR) {
252            status = *(status_t *)replyData;
253        }
254        if (status == NO_ERROR) {
255            mEnabled = (cmdCode == EFFECT_CMD_ENABLE);
256        }
257        mLock.unlock();
258    }
259
260    return status;
261}
262
263
264status_t AudioEffect::setParameter(effect_param_t *param)
265{
266    if (mStatus != NO_ERROR) {
267        return INVALID_OPERATION;
268    }
269
270    if (param == NULL || param->psize == 0 || param->vsize == 0) {
271        return BAD_VALUE;
272    }
273
274    uint32_t size = sizeof(int);
275    uint32_t psize = ((param->psize - 1) / sizeof(int) + 1) * sizeof(int) + param->vsize;
276
277    LOGV("setParameter: param: %d, param2: %d", *(int *)param->data, (param->psize == 8) ? *((int *)param->data + 1): -1);
278
279    return mIEffect->command(EFFECT_CMD_SET_PARAM, sizeof (effect_param_t) + psize, param, &size, &param->status);
280}
281
282status_t AudioEffect::setParameterDeferred(effect_param_t *param)
283{
284    if (mStatus != NO_ERROR) {
285        return INVALID_OPERATION;
286    }
287
288    if (param == NULL || param->psize == 0 || param->vsize == 0) {
289        return BAD_VALUE;
290    }
291
292    Mutex::Autolock _l(mCblk->lock);
293
294    int psize = ((param->psize - 1) / sizeof(int) + 1) * sizeof(int) + param->vsize;
295    int size = ((sizeof(effect_param_t) + psize - 1) / sizeof(int) + 1) * sizeof(int);
296
297    if (mCblk->clientIndex + size > EFFECT_PARAM_BUFFER_SIZE) {
298        return NO_MEMORY;
299    }
300    int *p = (int *)(mCblk->buffer + mCblk->clientIndex);
301    *p++ = size;
302    memcpy(p, param, sizeof(effect_param_t) + psize);
303    mCblk->clientIndex += size;
304
305    return NO_ERROR;
306}
307
308status_t AudioEffect::setParameterCommit()
309{
310    if (mStatus != NO_ERROR) {
311        return INVALID_OPERATION;
312    }
313
314    Mutex::Autolock _l(mCblk->lock);
315    if (mCblk->clientIndex == 0) {
316        return INVALID_OPERATION;
317    }
318    uint32_t size = 0;
319    return mIEffect->command(EFFECT_CMD_SET_PARAM_COMMIT, 0, NULL, &size, NULL);
320}
321
322status_t AudioEffect::getParameter(effect_param_t *param)
323{
324    if (mStatus != NO_ERROR && mStatus != ALREADY_EXISTS) {
325        return INVALID_OPERATION;
326    }
327
328    if (param == NULL || param->psize == 0 || param->vsize == 0) {
329        return BAD_VALUE;
330    }
331
332    LOGV("getParameter: param: %d, param2: %d", *(int *)param->data, (param->psize == 8) ? *((int *)param->data + 1): -1);
333
334    uint32_t psize = sizeof(effect_param_t) + ((param->psize - 1) / sizeof(int) + 1) * sizeof(int) + param->vsize;
335
336    return mIEffect->command(EFFECT_CMD_GET_PARAM, sizeof(effect_param_t) + param->psize, param, &psize, param);
337}
338
339
340// -------------------------------------------------------------------------
341
342void AudioEffect::binderDied()
343{
344    LOGW("IEffect died");
345    mStatus = NO_INIT;
346    if (mCbf) {
347        status_t status = DEAD_OBJECT;
348        mCbf(EVENT_ERROR, mUserData, &status);
349    }
350    mIEffect.clear();
351}
352
353// -------------------------------------------------------------------------
354
355void AudioEffect::controlStatusChanged(bool controlGranted)
356{
357    LOGV("controlStatusChanged %p control %d callback %p mUserData %p", this, controlGranted, mCbf, mUserData);
358    if (controlGranted) {
359        if (mStatus == ALREADY_EXISTS) {
360            mStatus = NO_ERROR;
361        }
362    } else {
363        if (mStatus == NO_ERROR) {
364            mStatus = ALREADY_EXISTS;
365        }
366    }
367    if (mCbf) {
368        mCbf(EVENT_CONTROL_STATUS_CHANGED, mUserData, &controlGranted);
369    }
370}
371
372void AudioEffect::enableStatusChanged(bool enabled)
373{
374    LOGV("enableStatusChanged %p enabled %d mCbf %p", this, enabled, mCbf);
375    if (mStatus == ALREADY_EXISTS) {
376        mEnabled = enabled;
377        if (mCbf) {
378            mCbf(EVENT_ENABLE_STATUS_CHANGED, mUserData, &enabled);
379        }
380    }
381}
382
383void AudioEffect::commandExecuted(uint32_t cmdCode,
384                                  uint32_t cmdSize,
385                                  void *cmdData,
386                                  uint32_t replySize,
387                                  void *replyData)
388{
389    if (cmdData == NULL || replyData == NULL) {
390        return;
391    }
392
393    if (mCbf && cmdCode == EFFECT_CMD_SET_PARAM) {
394        effect_param_t *cmd = (effect_param_t *)cmdData;
395        cmd->status = *(int32_t *)replyData;
396        mCbf(EVENT_PARAMETER_CHANGED, mUserData, cmd);
397    }
398}
399
400// -------------------------------------------------------------------------
401
402status_t AudioEffect::loadEffectLibrary(const char *libPath, int *handle)
403{
404    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
405    if (af == 0) return PERMISSION_DENIED;
406    return af->loadEffectLibrary(libPath, handle);
407}
408
409status_t AudioEffect::unloadEffectLibrary(int handle)
410{
411    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
412    if (af == 0) return PERMISSION_DENIED;
413    return af->unloadEffectLibrary(handle);
414}
415
416status_t AudioEffect::queryNumberEffects(uint32_t *numEffects)
417{
418    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
419    if (af == 0) return PERMISSION_DENIED;
420    return af->queryNumberEffects(numEffects);
421}
422
423status_t AudioEffect::queryEffect(uint32_t index, effect_descriptor_t *descriptor)
424{
425    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
426    if (af == 0) return PERMISSION_DENIED;
427    return af->queryEffect(index, descriptor);
428}
429
430status_t AudioEffect::getEffectDescriptor(effect_uuid_t *uuid, effect_descriptor_t *descriptor)
431{
432    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
433    if (af == 0) return PERMISSION_DENIED;
434    return af->getEffectDescriptor(uuid, descriptor);
435}
436
437// -------------------------------------------------------------------------
438
439status_t AudioEffect::stringToGuid(const char *str, effect_uuid_t *guid)
440{
441    if (str == NULL || guid == NULL) {
442        return BAD_VALUE;
443    }
444
445    int tmp[10];
446
447    if (sscanf(str, "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
448            tmp, tmp+1, tmp+2, tmp+3, tmp+4, tmp+5, tmp+6, tmp+7, tmp+8, tmp+9) < 10) {
449        return BAD_VALUE;
450    }
451    guid->timeLow = (uint32_t)tmp[0];
452    guid->timeMid = (uint16_t)tmp[1];
453    guid->timeHiAndVersion = (uint16_t)tmp[2];
454    guid->clockSeq = (uint16_t)tmp[3];
455    guid->node[0] = (uint8_t)tmp[4];
456    guid->node[1] = (uint8_t)tmp[5];
457    guid->node[2] = (uint8_t)tmp[6];
458    guid->node[3] = (uint8_t)tmp[7];
459    guid->node[4] = (uint8_t)tmp[8];
460    guid->node[5] = (uint8_t)tmp[9];
461
462    return NO_ERROR;
463}
464
465status_t AudioEffect::guidToString(const effect_uuid_t *guid, char *str, size_t maxLen)
466{
467    if (guid == NULL || str == NULL) {
468        return BAD_VALUE;
469    }
470
471    snprintf(str, maxLen, "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
472            guid->timeLow,
473            guid->timeMid,
474            guid->timeHiAndVersion,
475            guid->clockSeq,
476            guid->node[0],
477            guid->node[1],
478            guid->node[2],
479            guid->node[3],
480            guid->node[4],
481            guid->node[5]);
482
483    return NO_ERROR;
484}
485
486
487}; // namespace android
488
489