Home | History | Annotate | Download | only in libmedia
      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 
     34 namespace android {
     35 
     36 // ---------------------------------------------------------------------------
     37 
     38 AudioEffect::AudioEffect()
     39     : mStatus(NO_INIT)
     40 {
     41 }
     42 
     43 
     44 AudioEffect::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 io
     51                 )
     52     : mStatus(NO_INIT)
     53 {
     54     mStatus = set(type, uuid, priority, cbf, user, sessionId, io);
     55 }
     56 
     57 AudioEffect::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 io
     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     ALOGV("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, io);
     87 }
     88 
     89 status_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 io)
     96 {
     97     sp<IEffect> iEffect;
     98     sp<IMemory> cblk;
     99     int enabled;
    100 
    101     ALOGV("set %p mUserData: %p uuid: %p timeLow %08x", this, user, type, type ? type->timeLow : 0);
    102 
    103     if (mIEffect != 0) {
    104         ALOGW("Effect already in use");
    105         return INVALID_OPERATION;
    106     }
    107 
    108     const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
    109     if (audioFlinger == 0) {
    110         ALOGE("set(): Could not get audioflinger");
    111         return NO_INIT;
    112     }
    113 
    114     if (type == NULL && uuid == NULL) {
    115         ALOGW("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     mDescriptor.type = *(type != NULL ? type : EFFECT_UUID_NULL);
    126     mDescriptor.uuid = *(uuid != NULL ? uuid : EFFECT_UUID_NULL);
    127 
    128     mIEffectClient = new EffectClient(this);
    129 
    130     iEffect = audioFlinger->createEffect((effect_descriptor_t *)&mDescriptor,
    131             mIEffectClient, priority, io, mSessionId, &mStatus, &mId, &enabled);
    132 
    133     if (iEffect == 0 || (mStatus != NO_ERROR && mStatus != ALREADY_EXISTS)) {
    134         ALOGE("set(): AudioFlinger could not create effect, status: %d", mStatus);
    135         return mStatus;
    136     }
    137 
    138     mEnabled = (volatile int32_t)enabled;
    139 
    140     mIEffect = iEffect;
    141     cblk = iEffect->getCblk();
    142     if (cblk == 0) {
    143         mStatus = NO_INIT;
    144         ALOGE("Could not get control block");
    145         return mStatus;
    146     }
    147 
    148     mCblkMemory = cblk;
    149     mCblk = static_cast<effect_param_cblk_t*>(cblk->pointer());
    150     int bufOffset = ((sizeof(effect_param_cblk_t) - 1) / sizeof(int) + 1) * sizeof(int);
    151     mCblk->buffer = (uint8_t *)mCblk + bufOffset;
    152 
    153     iEffect->asBinder()->linkToDeath(mIEffectClient);
    154     mClientPid = IPCThreadState::self()->getCallingPid();
    155     ALOGV("set() %p OK effect: %s id: %d status %d enabled %d pid %d", this, mDescriptor.name, mId,
    156             mStatus, mEnabled, mClientPid);
    157 
    158     if (mSessionId > AUDIO_SESSION_OUTPUT_MIX) {
    159         AudioSystem::acquireAudioSessionId(mSessionId, mClientPid);
    160     }
    161 
    162     return mStatus;
    163 }
    164 
    165 
    166 AudioEffect::~AudioEffect()
    167 {
    168     ALOGV("Destructor %p", this);
    169 
    170     if (mStatus == NO_ERROR || mStatus == ALREADY_EXISTS) {
    171         if (mSessionId > AUDIO_SESSION_OUTPUT_MIX) {
    172             AudioSystem::releaseAudioSessionId(mSessionId, mClientPid);
    173         }
    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 
    186 status_t AudioEffect::initCheck() const
    187 {
    188     return mStatus;
    189 }
    190 
    191 // -------------------------------------------------------------------------
    192 
    193 effect_descriptor_t AudioEffect::descriptor() const
    194 {
    195     return mDescriptor;
    196 }
    197 
    198 bool AudioEffect::getEnabled() const
    199 {
    200     return (mEnabled != 0);
    201 }
    202 
    203 status_t AudioEffect::setEnabled(bool enabled)
    204 {
    205     if (mStatus != NO_ERROR) {
    206         return (mStatus == ALREADY_EXISTS) ? (status_t) INVALID_OPERATION : mStatus;
    207     }
    208 
    209     status_t status = NO_ERROR;
    210 
    211     AutoMutex lock(mLock);
    212     if (enabled != mEnabled) {
    213         if (enabled) {
    214             ALOGV("enable %p", this);
    215             status = mIEffect->enable();
    216         } else {
    217             ALOGV("disable %p", this);
    218             status = mIEffect->disable();
    219         }
    220         if (status == NO_ERROR) {
    221             mEnabled = enabled;
    222         }
    223     }
    224     return status;
    225 }
    226 
    227 status_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         ALOGV("command() bad status %d", mStatus);
    235         return mStatus;
    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 
    264 status_t AudioEffect::setParameter(effect_param_t *param)
    265 {
    266     if (mStatus != NO_ERROR) {
    267         return (mStatus == ALREADY_EXISTS) ? (status_t) INVALID_OPERATION : mStatus;
    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     ALOGV("setParameter: param: %d, param2: %d", *(int *)param->data,
    278             (param->psize == 8) ? *((int *)param->data + 1): -1);
    279 
    280     return mIEffect->command(EFFECT_CMD_SET_PARAM, sizeof (effect_param_t) + psize, param, &size,
    281             &param->status);
    282 }
    283 
    284 status_t AudioEffect::setParameterDeferred(effect_param_t *param)
    285 {
    286     if (mStatus != NO_ERROR) {
    287         return (mStatus == ALREADY_EXISTS) ? (status_t) INVALID_OPERATION : mStatus;
    288     }
    289 
    290     if (param == NULL || param->psize == 0 || param->vsize == 0) {
    291         return BAD_VALUE;
    292     }
    293 
    294     Mutex::Autolock _l(mCblk->lock);
    295 
    296     int psize = ((param->psize - 1) / sizeof(int) + 1) * sizeof(int) + param->vsize;
    297     int size = ((sizeof(effect_param_t) + psize - 1) / sizeof(int) + 1) * sizeof(int);
    298 
    299     if (mCblk->clientIndex + size > EFFECT_PARAM_BUFFER_SIZE) {
    300         return NO_MEMORY;
    301     }
    302     int *p = (int *)(mCblk->buffer + mCblk->clientIndex);
    303     *p++ = size;
    304     memcpy(p, param, sizeof(effect_param_t) + psize);
    305     mCblk->clientIndex += size;
    306 
    307     return NO_ERROR;
    308 }
    309 
    310 status_t AudioEffect::setParameterCommit()
    311 {
    312     if (mStatus != NO_ERROR) {
    313         return (mStatus == ALREADY_EXISTS) ? (status_t) INVALID_OPERATION : mStatus;
    314     }
    315 
    316     Mutex::Autolock _l(mCblk->lock);
    317     if (mCblk->clientIndex == 0) {
    318         return INVALID_OPERATION;
    319     }
    320     uint32_t size = 0;
    321     return mIEffect->command(EFFECT_CMD_SET_PARAM_COMMIT, 0, NULL, &size, NULL);
    322 }
    323 
    324 status_t AudioEffect::getParameter(effect_param_t *param)
    325 {
    326     if (mStatus != NO_ERROR && mStatus != ALREADY_EXISTS) {
    327         return mStatus;
    328     }
    329 
    330     if (param == NULL || param->psize == 0 || param->vsize == 0) {
    331         return BAD_VALUE;
    332     }
    333 
    334     ALOGV("getParameter: param: %d, param2: %d", *(int *)param->data,
    335             (param->psize == 8) ? *((int *)param->data + 1): -1);
    336 
    337     uint32_t psize = sizeof(effect_param_t) + ((param->psize - 1) / sizeof(int) + 1) * sizeof(int) +
    338             param->vsize;
    339 
    340     return mIEffect->command(EFFECT_CMD_GET_PARAM, sizeof(effect_param_t) + param->psize, param,
    341             &psize, param);
    342 }
    343 
    344 
    345 // -------------------------------------------------------------------------
    346 
    347 void AudioEffect::binderDied()
    348 {
    349     ALOGW("IEffect died");
    350     mStatus = DEAD_OBJECT;
    351     if (mCbf != NULL) {
    352         status_t status = DEAD_OBJECT;
    353         mCbf(EVENT_ERROR, mUserData, &status);
    354     }
    355     mIEffect.clear();
    356 }
    357 
    358 // -------------------------------------------------------------------------
    359 
    360 void AudioEffect::controlStatusChanged(bool controlGranted)
    361 {
    362     ALOGV("controlStatusChanged %p control %d callback %p mUserData %p", this, controlGranted, mCbf,
    363             mUserData);
    364     if (controlGranted) {
    365         if (mStatus == ALREADY_EXISTS) {
    366             mStatus = NO_ERROR;
    367         }
    368     } else {
    369         if (mStatus == NO_ERROR) {
    370             mStatus = ALREADY_EXISTS;
    371         }
    372     }
    373     if (mCbf != NULL) {
    374         mCbf(EVENT_CONTROL_STATUS_CHANGED, mUserData, &controlGranted);
    375     }
    376 }
    377 
    378 void AudioEffect::enableStatusChanged(bool enabled)
    379 {
    380     ALOGV("enableStatusChanged %p enabled %d mCbf %p", this, enabled, mCbf);
    381     if (mStatus == ALREADY_EXISTS) {
    382         mEnabled = enabled;
    383         if (mCbf != NULL) {
    384             mCbf(EVENT_ENABLE_STATUS_CHANGED, mUserData, &enabled);
    385         }
    386     }
    387 }
    388 
    389 void AudioEffect::commandExecuted(uint32_t cmdCode,
    390                                   uint32_t cmdSize __unused,
    391                                   void *cmdData,
    392                                   uint32_t replySize __unused,
    393                                   void *replyData)
    394 {
    395     if (cmdData == NULL || replyData == NULL) {
    396         return;
    397     }
    398 
    399     if (mCbf != NULL && cmdCode == EFFECT_CMD_SET_PARAM) {
    400         effect_param_t *cmd = (effect_param_t *)cmdData;
    401         cmd->status = *(int32_t *)replyData;
    402         mCbf(EVENT_PARAMETER_CHANGED, mUserData, cmd);
    403     }
    404 }
    405 
    406 // -------------------------------------------------------------------------
    407 
    408 status_t AudioEffect::queryNumberEffects(uint32_t *numEffects)
    409 {
    410     const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
    411     if (af == 0) return PERMISSION_DENIED;
    412     return af->queryNumberEffects(numEffects);
    413 }
    414 
    415 status_t AudioEffect::queryEffect(uint32_t index, effect_descriptor_t *descriptor)
    416 {
    417     const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
    418     if (af == 0) return PERMISSION_DENIED;
    419     return af->queryEffect(index, descriptor);
    420 }
    421 
    422 status_t AudioEffect::getEffectDescriptor(const effect_uuid_t *uuid,
    423         effect_descriptor_t *descriptor) /*const*/
    424 {
    425     const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
    426     if (af == 0) return PERMISSION_DENIED;
    427     return af->getEffectDescriptor(uuid, descriptor);
    428 }
    429 
    430 
    431 status_t AudioEffect::queryDefaultPreProcessing(int audioSession,
    432                                           effect_descriptor_t *descriptors,
    433                                           uint32_t *count)
    434 {
    435     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
    436     if (aps == 0) return PERMISSION_DENIED;
    437     return aps->queryDefaultPreProcessing(audioSession, descriptors, count);
    438 }
    439 // -------------------------------------------------------------------------
    440 
    441 status_t AudioEffect::stringToGuid(const char *str, effect_uuid_t *guid)
    442 {
    443     if (str == NULL || guid == NULL) {
    444         return BAD_VALUE;
    445     }
    446 
    447     int tmp[10];
    448 
    449     if (sscanf(str, "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
    450             tmp, tmp+1, tmp+2, tmp+3, tmp+4, tmp+5, tmp+6, tmp+7, tmp+8, tmp+9) < 10) {
    451         return BAD_VALUE;
    452     }
    453     guid->timeLow = (uint32_t)tmp[0];
    454     guid->timeMid = (uint16_t)tmp[1];
    455     guid->timeHiAndVersion = (uint16_t)tmp[2];
    456     guid->clockSeq = (uint16_t)tmp[3];
    457     guid->node[0] = (uint8_t)tmp[4];
    458     guid->node[1] = (uint8_t)tmp[5];
    459     guid->node[2] = (uint8_t)tmp[6];
    460     guid->node[3] = (uint8_t)tmp[7];
    461     guid->node[4] = (uint8_t)tmp[8];
    462     guid->node[5] = (uint8_t)tmp[9];
    463 
    464     return NO_ERROR;
    465 }
    466 
    467 status_t AudioEffect::guidToString(const effect_uuid_t *guid, char *str, size_t maxLen)
    468 {
    469     if (guid == NULL || str == NULL) {
    470         return BAD_VALUE;
    471     }
    472 
    473     snprintf(str, maxLen, "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
    474             guid->timeLow,
    475             guid->timeMid,
    476             guid->timeHiAndVersion,
    477             guid->clockSeq,
    478             guid->node[0],
    479             guid->node[1],
    480             guid->node[2],
    481             guid->node[3],
    482             guid->node[4],
    483             guid->node[5]);
    484 
    485     return NO_ERROR;
    486 }
    487 
    488 
    489 }; // namespace android
    490