Home | History | Annotate | Download | only in libaudioclient
      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(const String16& opPackageName)
     39     : mStatus(NO_INIT), mOpPackageName(opPackageName)
     40 {
     41 }
     42 
     43 
     44 AudioEffect::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 
     58 AudioEffect::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 
     91 status_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 
    176 AudioEffect::~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 
    196 status_t AudioEffect::initCheck() const
    197 {
    198     return mStatus;
    199 }
    200 
    201 // -------------------------------------------------------------------------
    202 
    203 effect_descriptor_t AudioEffect::descriptor() const
    204 {
    205     return mDescriptor;
    206 }
    207 
    208 bool AudioEffect::getEnabled() const
    209 {
    210     return (mEnabled != 0);
    211 }
    212 
    213 status_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 
    237 status_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 
    274 status_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 
    294 status_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 
    320 status_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 
    334 status_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 
    357 void 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 
    370 void 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 
    388 void 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 
    399 void 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 
    418 status_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 
    425 status_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 
    432 status_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 
    441 status_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 
    451 status_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 
    477 status_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