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