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