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