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