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