今天来看看AudioEffect的构造,以及相关的一些函数。


*****************************************源码*************************************************
    //Test case 1.0: test constructor from effect type and get effect ID    @LargeTest    public void test1_0ConstructorFromType() throws Exception {        boolean result = true;        String msg = "test1_0ConstructorFromType()";        AudioEffect.Descriptor[] desc = AudioEffect.queryEffects();        assertTrue(msg+": no effects found", (desc.length != 0));        try {            AudioEffect effect = new AudioEffect(desc[0].type,                    AudioEffect.EFFECT_TYPE_NULL,                    0,                    0);            assertNotNull(msg + ": could not create AudioEffect", effect);            try {                assertTrue(msg +": invalid effect ID", (effect.getId() != 0));            } catch (IllegalStateException e) {                msg = msg.concat(": AudioEffect not initialized");                result = false;            } finally {                effect.release();            }        } catch (IllegalArgumentException e) {            msg = msg.concat(": Effect not found: "+desc[0].name);            result = false;        } catch (UnsupportedOperationException e) {            msg = msg.concat(": Effect library not loaded");            result = false;        }        assertTrue(msg, result);    }

**********************************************************************************************
源码路径:
frameworks\base\media\tests\mediaframeworktest\src\com\android\mediaframeworktest\functional\MediaAudioEffectTest.java


#######################说明################################
    //Test case 1.0: test constructor from effect type and get effect ID    @LargeTest    public void test1_0ConstructorFromType() throws Exception {        boolean result = true;        String msg = "test1_0ConstructorFromType()";        AudioEffect.Descriptor[] desc = AudioEffect.queryEffects();        assertTrue(msg+": no effects found", (desc.length != 0));        try {            AudioEffect effect = new AudioEffect(desc[0].type,                    AudioEffect.EFFECT_TYPE_NULL,                    0,                    0);// +++++++++++++++++++++++++++++++AudioEffect+++++++++++++++++++++++++++++++++    /**     * Class constructor.     *     * @param type type of effect engine created. See {@link #EFFECT_TYPE_ENV_REVERB},     *            {@link #EFFECT_TYPE_EQUALIZER} ... Types corresponding to     *            built-in effects are defined by AudioEffect class. Other types     *            can be specified provided they correspond an existing OpenSL     *            ES interface ID and the corresponsing effect is available on     *            the platform. If an unspecified effect type is requested, the     *            constructor with throw the IllegalArgumentException. This     *            parameter can be set to {@link #EFFECT_TYPE_NULL} in which     *            case only the uuid will be used to select the effect.     * @param uuid unique identifier of a particular effect implementation.     *            Must be specified if the caller wants to use a particular     *            implementation of an effect type. This parameter can be set to     *            {@link #EFFECT_TYPE_NULL} in which case only the type will     *            be used to select the effect.     * @param priority the priority level requested by the application for     *            controlling the effect engine. As the same effect engine can     *            be shared by several applications, this parameter indicates     *            how much the requesting application needs control of effect     *            parameters. The normal priority is 0, above normal is a     *            positive number, below normal a negative number.     * @param audioSession system wide unique audio session identifier. If audioSession     *            is not 0, the effect will be attached to the MediaPlayer or     *            AudioTrack in the same audio session. Otherwise, the effect     *            will apply to the output mix.     *     * @throws java.lang.IllegalArgumentException     * @throws java.lang.UnsupportedOperationException     * @throws java.lang.RuntimeException     * @hide     */    public AudioEffect(UUID type, UUID uuid, int priority, int audioSession)            throws IllegalArgumentException, UnsupportedOperationException,            RuntimeException {        int[] id = new int[1];        Descriptor[] desc = new Descriptor[1];        // native initialization        int initResult = native_setup(new WeakReference<AudioEffect>(this),                type.toString(), uuid.toString(), priority, audioSession, id,                desc);// +++++++++++++++++++++++++android_media_AudioEffect_native_setup+++++++++++++++++++++++++++++++++++++++static jintandroid_media_AudioEffect_native_setup(JNIEnv *env, jobject thiz, jobject weak_this,        jstring type, jstring uuid, jint priority, jint sessionId, jintArray jId, jobjectArray javadesc){    LOGV("android_media_AudioEffect_native_setup");    AudioEffectJniStorage* lpJniStorage = NULL;    int lStatus = AUDIOEFFECT_ERROR_NO_MEMORY;    AudioEffect* lpAudioEffect = NULL;    jint* nId = NULL;    const char *typeStr = NULL;    const char *uuidStr = NULL;    effect_descriptor_t desc;    jobject jdesc;    char str[EFFECT_STRING_LEN_MAX];    jstring jdescType;    jstring jdescUuid;    jstring jdescConnect;    jstring jdescName;    jstring jdescImplementor;    if (type != NULL) {        typeStr = env->GetStringUTFChars(type, NULL);        if (typeStr == NULL) {  // Out of memory            jniThrowException(env, "java/lang/RuntimeException", "Out of memory");            goto setup_failure;        }    }    if (uuid != NULL) {        uuidStr = env->GetStringUTFChars(uuid, NULL);        if (uuidStr == NULL) {  // Out of memory            jniThrowException(env, "java/lang/RuntimeException", "Out of memory");            goto setup_failure;        }    }// type 和 uuid 必须有一个不为空// 否则,没办法确定用哪个effect lib    if (typeStr == NULL && uuidStr == NULL) {        lStatus = AUDIOEFFECT_ERROR_BAD_VALUE;        goto setup_failure;    }    lpJniStorage = new AudioEffectJniStorage();    if (lpJniStorage == NULL) {        LOGE("setup: Error creating JNI Storage");        goto setup_failure;    }// ++++++++++++++++++++++++++++AudioEffectJniStorage++++++++++++++++++++++++++++++++++++struct effect_callback_cookie {    jclass      audioEffect_class;  // AudioEffect class    jobject     audioEffect_ref;    // AudioEffect object instance }; class AudioEffectJniStorage {    public:        effect_callback_cookie mCallbackData;    AudioEffectJniStorage() {    }    ~AudioEffectJniStorage() {    }};// ----------------------------AudioEffectJniStorage------------------------------------    lpJniStorage->mCallbackData.audioEffect_class = (jclass)env->NewGlobalRef(fields.clazzEffect);    // we use a weak reference so the AudioEffect object can be garbage collected.    lpJniStorage->mCallbackData.audioEffect_ref = env->NewGlobalRef(weak_this);    LOGV("setup: lpJniStorage: %p audioEffect_ref %p audioEffect_class %p, &mCallbackData %p",            lpJniStorage,            lpJniStorage->mCallbackData.audioEffect_ref,            lpJniStorage->mCallbackData.audioEffect_class,            &lpJniStorage->mCallbackData);    if (jId == NULL) {        LOGE("setup: NULL java array for id pointer");        lStatus = AUDIOEFFECT_ERROR_BAD_VALUE;        goto setup_failure;    }    // create the native AudioEffect object    lpAudioEffect = new AudioEffect(typeStr,                                    uuidStr,                                    priority,                                    effectCallback,                                    &lpJniStorage->mCallbackData,                                    sessionId,                                    0);    if (lpAudioEffect == NULL) {        LOGE("Error creating AudioEffect");        goto setup_failure;    }// ++++++++++++++++++++++++++++native AudioEffect++++++++++++++++++++++++++++++++++++AudioEffect::AudioEffect(const char *typeStr,                const char *uuidStr,                int32_t priority,                effect_callback_t cbf,                void* user,                int sessionId,                audio_io_handle_t output                )    : mStatus(NO_INIT){    effect_uuid_t type;    effect_uuid_t *pType = NULL;    effect_uuid_t uuid;    effect_uuid_t *pUuid = NULL;    LOGV("Constructor string\n - type: %s\n - uuid: %s", typeStr, uuidStr);    if (typeStr != NULL) {        if (stringToGuid(typeStr, &type) == NO_ERROR) {            pType = &type;        }    }    if (uuidStr != NULL) {        if (stringToGuid(uuidStr, &uuid) == NO_ERROR) {            pUuid = &uuid;        }    }    mStatus = set(pType, pUuid, priority, cbf, user, sessionId, output);// +++++++++++++++++++++++++++++AudioEffect::set+++++++++++++++++++++++++++++++++++status_t AudioEffect::set(const effect_uuid_t *type,                const effect_uuid_t *uuid,                int32_t priority,                effect_callback_t cbf,                void* user,                int sessionId,                audio_io_handle_t output){    sp<IEffect> iEffect;    sp<IMemory> cblk;    int enabled;    LOGV("set %p mUserData: %p", this, user);// 如果effect 对象已经被创建了,返回无效操作    if (mIEffect != 0) {        LOGW("Effect already in use");        return INVALID_OPERATION;    }    const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();    if (audioFlinger == 0) {        LOGE("set(): Could not get audioflinger");        return NO_INIT;    }// 再一次检查type和uuid    if (type == NULL && uuid == NULL) {        LOGW("Must specify at least type or uuid");        return BAD_VALUE;    }    mPriority = priority;// cbf其实是函数effectCallback    mCbf = cbf;// +++++++++++++++++++++++++++++effectCallback+++++++++++++++++++++++++++++++++++static void effectCallback(int event, void* user, void *info) {    effect_param_t *p;    int arg1 = 0;    int arg2 = 0;    jobject obj = NULL;    jbyteArray array = NULL;    jbyte *bytes;    bool param;    size_t size;    effect_callback_cookie *callbackInfo = (effect_callback_cookie *)user;    JNIEnv *env = AndroidRuntime::getJNIEnv();    LOGV("effectCallback: callbackInfo %p, audioEffect_ref %p audioEffect_class %p",            callbackInfo,            callbackInfo->audioEffect_ref,            callbackInfo->audioEffect_class);    if (!user || !env) {        LOGW("effectCallback error user %p, env %p", user, env);        return;    }    switch (event) {    case AudioEffect::EVENT_CONTROL_STATUS_CHANGED:        if (info == 0) {            LOGW("EVENT_CONTROL_STATUS_CHANGED info == NULL");            goto effectCallback_Exit;        }        param = *(bool *)info;        arg1 = (int)param;        LOGV("EVENT_CONTROL_STATUS_CHANGED");        break;    case AudioEffect::EVENT_ENABLE_STATUS_CHANGED:        if (info == 0) {            LOGW("EVENT_ENABLE_STATUS_CHANGED info == NULL");            goto effectCallback_Exit;        }        param = *(bool *)info;        arg1 = (int)param;        LOGV("EVENT_ENABLE_STATUS_CHANGED");        break;    case AudioEffect::EVENT_PARAMETER_CHANGED:        if (info == 0) {            LOGW("EVENT_PARAMETER_CHANGED info == NULL");            goto effectCallback_Exit;        }        p = (effect_param_t *)info;        if (p->psize == 0 || p->vsize == 0) {            goto effectCallback_Exit;        }        // arg1 contains offset of parameter value from start of byte array        arg1 = sizeof(effect_param_t) + ((p->psize - 1) / sizeof(int) + 1) * sizeof(int);        size = arg1 + p->vsize;        array = env->NewByteArray(size);        if (array == NULL) {            LOGE("effectCallback: Couldn't allocate byte array for parameter data");            goto effectCallback_Exit;        }        bytes = env->GetByteArrayElements(array, NULL);        memcpy(bytes, p, size);        env->ReleaseByteArrayElements(array, bytes, 0);        obj = array;        LOGV("EVENT_PARAMETER_CHANGED");       break;    case AudioEffect::EVENT_ERROR:        LOGW("EVENT_ERROR");        break;    }    env->CallStaticVoidMethod(        callbackInfo->audioEffect_class,        fields.midPostNativeEvent,        callbackInfo->audioEffect_ref, event, arg1, arg2, obj);effectCallback_Exit:    if (array) {        env->DeleteLocalRef(array);    }    if (env->ExceptionCheck()) {        env->ExceptionDescribe();        env->ExceptionClear();    }}// -----------------------------effectCallback-----------------------------------// user其实是AudioEffectJniStorage对象中mCallbackData成员的地址    mUserData = user;    mSessionId = sessionId;    memset(&mDescriptor, 0, sizeof(effect_descriptor_t));    memcpy(&mDescriptor.type, EFFECT_UUID_NULL, sizeof(effect_uuid_t));    memcpy(&mDescriptor.uuid, EFFECT_UUID_NULL, sizeof(effect_uuid_t));    if (type != NULL) {        memcpy(&mDescriptor.type, type, sizeof(effect_uuid_t));    }    if (uuid != NULL) {        memcpy(&mDescriptor.uuid, uuid, sizeof(effect_uuid_t));    }    mIEffectClient = new EffectClient(this);// +++++++++++++++++++++++++++++EffectClient+++++++++++++++++++++++++++++++++++     // Implements the IEffectClient interface    class EffectClient : public android::BnEffectClient,  public android::IBinder::DeathRecipient    {    public:        EffectClient(AudioEffect *effect) : mEffect(effect){}        // IEffectClient        virtual void controlStatusChanged(bool controlGranted) {            mEffect->controlStatusChanged(controlGranted);        }        virtual void enableStatusChanged(bool enabled) {            mEffect->enableStatusChanged(enabled);        }        virtual void commandExecuted(uint32_t cmdCode,                                     uint32_t cmdSize,                                     void *pCmdData,                                     uint32_t replySize,                                     void *pReplyData) {            mEffect->commandExecuted(cmdCode, cmdSize, pCmdData, replySize, pReplyData);        }        // IBinder::DeathRecipient        virtual void binderDied(const wp<IBinder>& who) {mEffect->binderDied();}    private:        AudioEffect *mEffect;    };// -----------------------------EffectClient-----------------------------------    iEffect = audioFlinger->createEffect(getpid(), (effect_descriptor_t *)&mDescriptor,            mIEffectClient, priority, output, mSessionId, &mStatus, &mId, &enabled);    if (iEffect == 0 || (mStatus != NO_ERROR && mStatus != ALREADY_EXISTS)) {        LOGE("set(): AudioFlinger could not create effect, status: %d", mStatus);        return mStatus;    }// ++++++++++++++++++++++++++AudioFlinger::createEffect++++++++++++++++++++++++++++++++++++++sp<IEffect> AudioFlinger::createEffect(pid_t pid,        effect_descriptor_t *pDesc,        const sp<IEffectClient>& effectClient,        int32_t priority,        int output,        int sessionId,        status_t *status,        int *id,        int *enabled){    status_t lStatus = NO_ERROR;    sp<EffectHandle> handle;    effect_interface_t itfe;    effect_descriptor_t desc;    sp<Client> client;    wp<Client> wclient;    LOGV("createEffect pid %d, client %p, priority %d, sessionId %d, output %d",            pid, effectClient.get(), priority, sessionId, output);    if (pDesc == NULL) {        lStatus = BAD_VALUE;        goto Exit;    }    // check audio settings permission for global effects    if (sessionId == AudioSystem::SESSION_OUTPUT_MIX && !settingsAllowed()) {        lStatus = PERMISSION_DENIED;        goto Exit;    }// +++++++++++++++++++++++++++++++audio_sessions+++++++++++++++++++++++++++++++++    // special audio session values    enum audio_sessions {        SESSION_OUTPUT_STAGE = -1, // session for effects attached to a particular output stream                                   // (value must be less than 0)        SESSION_OUTPUT_MIX = 0,    // session for effects applied to output mix. These effects can                                   // be moved by audio policy manager to another output stream                                   // (value must be 0)    };// -------------------------------audio_sessions---------------------------------    // Session AudioSystem::SESSION_OUTPUT_STAGE is reserved for output stage effects    // that can only be created by audio policy manager (running in same process)    if (sessionId == AudioSystem::SESSION_OUTPUT_STAGE && getpid() != pid) {        lStatus = PERMISSION_DENIED;        goto Exit;    }    // check recording permission for visualizer    if ((memcmp(&pDesc->type, SL_IID_VISUALIZATION, sizeof(effect_uuid_t)) == 0 ||         memcmp(&pDesc->uuid, &VISUALIZATION_UUID_, sizeof(effect_uuid_t)) == 0) &&        !recordingAllowed()) {        lStatus = PERMISSION_DENIED;        goto Exit;    }    if (output == 0) {        if (sessionId == AudioSystem::SESSION_OUTPUT_STAGE) {            // output must be specified by AudioPolicyManager when using session            // AudioSystem::SESSION_OUTPUT_STAGE// 如果sessionId为AudioSystem::SESSION_OUTPUT_STAGE,effect必须绑定到特定的output            lStatus = BAD_VALUE;            goto Exit;        } else if (sessionId == AudioSystem::SESSION_OUTPUT_MIX) {            // if the output returned by getOutputForEffect() is removed before we lock the            // mutex below, the call to checkPlaybackThread_l(output) below will detect it            // and we will exit safely            output = AudioSystem::getOutputForEffect(&desc);// ++++++++++++++++++++++++++++++AudioSystem::getOutputForEffect++++++++++++++++++++++++++++++++++audio_io_handle_t AudioSystem::getOutputForEffect(effect_descriptor_t *desc){    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();    if (aps == 0) return PERMISSION_DENIED;    return aps->getOutputForEffect(desc);// +++++++++++++++++++++++++++++AudioPolicyService::getOutputForEffect+++++++++++++++++++++++++++++++++++audio_io_handle_t AudioPolicyService::getOutputForEffect(effect_descriptor_t *desc){    if (mpPolicyManager == NULL) {        return NO_INIT;    }    Mutex::Autolock _l(mLock);    return mpPolicyManager->getOutputForEffect(desc);// ++++++++++++++++++++++++++++++AudioPolicyManagerBase::getOutputForEffect++++++++++++++++++++++++++++++++++audio_io_handle_t AudioPolicyManagerBase::getOutputForEffect(effect_descriptor_t *desc){    LOGV("getOutputForEffect()");    // apply simple rule where global effects are attached to the same output as MUSIC streams// 所有的effect都会被绑定到MUSIT stream上,所以,这儿只是简单的将MUSIC stream对应的output返回    return getOutput(AudioSystem::MUSIC);}// ------------------------------AudioPolicyManagerBase::getOutputForEffect----------------------------------}// -----------------------------AudioPolicyService::getOutputForEffect-----------------------------------}// ------------------------------AudioSystem::getOutputForEffect----------------------------------        }    }    {        Mutex::Autolock _l(mLock);        if (!EffectIsNullUuid(&pDesc->uuid)) {// 如果指定了uuid,则根据uuid寻找合适的effect descriptor            // if uuid is specified, request effect descriptor            lStatus = EffectGetDescriptor(&pDesc->uuid, &desc);            if (lStatus < 0) {                LOGW("createEffect() error %d from EffectGetDescriptor", lStatus);                goto Exit;            }// ++++++++++++++++++++++++++++++EffectGetDescriptor++++++++++++++++++++++++++++++++++路径:frameworks\base\media\libeffects\factory\EffectsFactory.cint EffectGetDescriptor(effect_uuid_t *uuid, effect_descriptor_t *pDescriptor){    lib_entry_t *l = NULL;    effect_descriptor_t *d = NULL;// init 函数我们已经看过// 如果init已经被调用过,再次进入init函数并不会有真正的动作// 也就是说,初始化操作只会进行一次    int ret = init();    if (ret < 0) {        return ret;    }    if (pDescriptor == NULL || uuid == NULL) {        return -EINVAL;    }    pthread_mutex_lock(&gLibLock);    ret = findEffect(uuid, &l, &d);    if (ret == 0) {        memcpy(pDescriptor, d, sizeof(effect_descriptor_t));    }// +++++++++++++++++++++++++++++++findEffect+++++++++++++++++++++++++++++++++int findEffect(effect_uuid_t *uuid, lib_entry_t **lib, effect_descriptor_t **desc){// gLibraryList是保存所有effect lib的列表    list_elem_t *e = gLibraryList;    lib_entry_t *l = NULL;    effect_descriptor_t *d = NULL;    int found = 0;    int ret = 0;    while (e && !found) {        l = (lib_entry_t *)e->object;        list_elem_t *efx = l->effects;        while (efx) {            d = (effect_descriptor_t *)efx->object;// 比较是否与给定的uuid一致            if (memcmp(&d->uuid, uuid, sizeof(effect_uuid_t)) == 0) {                found = 1;                break;            }            efx = efx->next;        }        e = e->next;    }    if (!found) {        LOGV("findEffect() effect not found");        ret = -ENOENT;    } else {        LOGV("findEffect() found effect: %s in lib %s", d->name, l->path);        *lib = l;        *desc = d;    }    return ret;}// -------------------------------findEffect---------------------------------    pthread_mutex_unlock(&gLibLock);    return ret;}// ------------------------------EffectGetDescriptor----------------------------------        } else {            // if uuid is not specified, look for an available implementation            // of the required type in effect factory// 如果没指定uuid,则寻找一个相同类型的可用的effect lib            if (EffectIsNullUuid(&pDesc->type)) {                LOGW("createEffect() no effect type");                lStatus = BAD_VALUE;                goto Exit;            }            uint32_t numEffects = 0;            effect_descriptor_t d;            bool found = false;            lStatus = EffectQueryNumberEffects(&numEffects);            if (lStatus < 0) {                LOGW("createEffect() error %d from EffectQueryNumberEffects", lStatus);                goto Exit;            }            for (uint32_t i = 0; i < numEffects; i++) {                lStatus = EffectQueryEffect(i, &desc);                if (lStatus < 0) {                    LOGW("createEffect() error %d from EffectQueryEffect", lStatus);                    continue;                }                if (memcmp(&desc.type, &pDesc->type, sizeof(effect_uuid_t)) == 0) {                    // If matching type found save effect descriptor. If the session is                    // 0 and the effect is not auxiliary, continue enumeration in case                    // an auxiliary version of this effect type is available// 如果session id为0,即AudioSystem::SESSION_OUTPUT_MIX,// 若找到的effect为auxiliary,则退出,否则的话就继续查找// 以防止存在可用的该类型的auxiliary的effect。// 也就是说,对于AudioSystem::SESSION_OUTPUT_MIX的session id来说,// 会优先使用auxiliary的effect。                    found = true;                    memcpy(&d, &desc, sizeof(effect_descriptor_t));                    if (sessionId != AudioSystem::SESSION_OUTPUT_MIX ||                            (desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {                        break;                    }                }            }            if (!found) {                lStatus = BAD_VALUE;                LOGW("createEffect() effect not found");                goto Exit;            }            // For same effect type, chose auxiliary version over insert version if            // connect to output mix (Compliance to OpenSL ES)// 如果不存在可用的该类型的auxiliary的effect,也只能勉强使用刚才找到的insert的了            if (sessionId == AudioSystem::SESSION_OUTPUT_MIX &&                    (d.flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_AUXILIARY) {                memcpy(&desc, &d, sizeof(effect_descriptor_t));            }        }// auxiliary的effect只能作用在AudioSystem::SESSION_OUTPUT_MIX的session id上。        // Do not allow auxiliary effects on a session different from 0 (output mix)        if (sessionId != AudioSystem::SESSION_OUTPUT_MIX &&             (desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {            lStatus = INVALID_OPERATION;            goto Exit;        }        // return effect descriptor        memcpy(pDesc, &desc, sizeof(effect_descriptor_t));        // If output is not specified try to find a matching audio session ID in one of the        // output threads.// 如果没有指定output,则尝试在output threads中寻找匹配的Session ID。        // If output is 0 here, sessionId is neither SESSION_OUTPUT_STAGE nor SESSION_OUTPUT_MIX        // because of code checking output when entering the function.// 此时,如果output仍然为0,则说明session ID即不是SESSION_OUTPUT_STAGE,也不是SESSION_OUTPUT_MIX。// 因为前面我们做过一个检查,如果output为0,若session ID是SESSION_OUTPUT_STAGE,则直接退出;// 若session ID是SESSION_OUTPUT_MIX,则会调用函数AudioSystem::getOutputForEffect来get一个output// (从最终的实现可知,函数AudioSystem::getOutputForEffect最终返回的是music stream对应的output)。        if (output == 0) {             // look for the thread where the specified audio session is present            for (size_t i = 0; i < mPlaybackThreads.size(); i++) {                if (mPlaybackThreads.valueAt(i)->hasAudioSession(sessionId) != 0) {                    output = mPlaybackThreads.keyAt(i);                    break;// ++++++++++++++++++++++++++++AudioFlinger::PlaybackThread::hasAudioSession++++++++++++++++++++++++++++++++++++uint32_t AudioFlinger::PlaybackThread::hasAudioSession(int sessionId){    Mutex::Autolock _l(mLock);    uint32_t result = 0;    if (getEffectChain_l(sessionId) != 0) {        result = EFFECT_SESSION;    }    for (size_t i = 0; i < mTracks.size(); ++i) {        sp<Track> track = mTracks[i];// 在创建track的时候,会传入一个session ID        if (sessionId == track->sessionId() &&                !(track->mCblk->flags & CBLK_INVALID_MSK)) {            result |= TRACK_SESSION;            break;        }    }    return result;}// ----------------------------AudioFlinger::PlaybackThread::hasAudioSession------------------------------------                }            }            // If no output thread contains the requested session ID, default to            // first output. The effect chain will be moved to the correct output            // thread when a track with the same session ID is created// 如果找不到output,默认使用第一个。// 如果相同session ID的trak被创建了,effect链表会被移动到新的track上。// effect的移动工作在函数AudioFlinger::createTrack中完成见随后代码            if (output == 0 && mPlaybackThreads.size()) {                output = mPlaybackThreads.keyAt(0);            }// +++++++++++++++++++++++++++++AudioFlinger::createTrack moveEffectChain_l+++++++++++++++++++++++++++++++++++        if (sessionId != NULL && *sessionId != AudioSystem::SESSION_OUTPUT_MIX) {            for (size_t i = 0; i < mPlaybackThreads.size(); i++) {                sp<PlaybackThread> t = mPlaybackThreads.valueAt(i);                if (mPlaybackThreads.keyAt(i) != output) {                    // prevent same audio session on different output threads                    uint32_t sessions = t->hasAudioSession(*sessionId);                    if (sessions & PlaybackThread::TRACK_SESSION) {                        lStatus = BAD_VALUE;                        goto Exit;                    }                    // check if an effect with same session ID is waiting for a track to be created                    if (sessions & PlaybackThread::EFFECT_SESSION) {                        effectThread = t.get();                    }                }            }            lSessionId = *sessionId;        } else {            // if no audio session id is provided, create one here            lSessionId = nextUniqueId();            if (sessionId != NULL) {                *sessionId = lSessionId;            }        }        LOGV("createTrack() lSessionId: %d", lSessionId);        track = thread->createTrack_l(client, streamType, sampleRate, format,                channelCount, frameCount, sharedBuffer, lSessionId, &lStatus);        // move effect chain to this output thread if an effect on same session was waiting        // for a track to be created        if (lStatus == NO_ERROR && effectThread != NULL) {            Mutex::Autolock _dl(thread->mLock);            Mutex::Autolock _sl(effectThread->mLock);            moveEffectChain_l(lSessionId, effectThread, thread, true);// +++++++++++++++++++++++++++++AudioFlinger::moveEffectChain_l+++++++++++++++++++++++++++++++++++// moveEffectChain_l mustbe called with both srcThread and dstThread mLocks heldstatus_t AudioFlinger::moveEffectChain_l(int session,                                   AudioFlinger::PlaybackThread *srcThread,                                   AudioFlinger::PlaybackThread *dstThread,                                   bool reRegister){    LOGV("moveEffectChain_l() session %d from thread %p to thread %p",            session, srcThread, dstThread);    sp<EffectChain> chain = srcThread->getEffectChain_l(session);    if (chain == 0) {        LOGW("moveEffectChain_l() effect chain for session %d not on source thread %p",                session, srcThread);        return INVALID_OPERATION;    }    // remove chain first. This is useful only if reconfiguring effect chain on same output thread,    // so that a new chain is created with correct parameters when first effect is added. This is    // otherwise unecessary as removeEffect_l() will remove the chain when last effect is    // removed.    srcThread->removeEffectChain_l(chain);    // transfer all effects one by one so that new effect chain is created on new thread with    // correct buffer sizes and audio parameters and effect engines reconfigured accordingly    int dstOutput = dstThread->id();    sp<EffectChain> dstChain;    uint32_t strategy;    sp<EffectModule> effect = chain->getEffectFromId_l(0);    while (effect != 0) {        srcThread->removeEffect_l(effect);        dstThread->addEffect_l(effect);        // if the move request is not received from audio policy manager, the effect must be        // re-registered with the new strategy and output        if (dstChain == 0) {            dstChain = effect->chain().promote();            if (dstChain == 0) {                LOGW("moveEffectChain_l() cannot get chain from effect %p", effect.get());                srcThread->addEffect_l(effect);                return NO_INIT;            }            strategy = dstChain->strategy();        }        if (reRegister) {            AudioSystem::unregisterEffect(effect->id());            AudioSystem::registerEffect(&effect->desc(),                                        dstOutput,                                        strategy,                                        session,                                        effect->id());// ++++++++++++++++++++++++++++AudioSystem::registerEffect++++++++++++++++++++++++++++++++++++status_t AudioSystem::registerEffect(effect_descriptor_t *desc,                                audio_io_handle_t output,                                uint32_t strategy,                                int session,                                int id){    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();    if (aps == 0) return PERMISSION_DENIED;    return aps->registerEffect(desc, output, strategy, session, id);// ++++++++++++++++++++++++++++AudioPolicyService::registerEffect++++++++++++++++++++++++++++++++++++status_t AudioPolicyService::registerEffect(effect_descriptor_t *desc,                                audio_io_handle_t output,                                uint32_t strategy,                                int session,                                int id){    if (mpPolicyManager == NULL) {        return NO_INIT;    }    return mpPolicyManager->registerEffect(desc, output, strategy, session, id);// +++++++++++++++++++++++++++AudioPolicyManagerBase::registerEffect+++++++++++++++++++++++++++++++++++++status_t AudioPolicyManagerBase::registerEffect(effect_descriptor_t *desc,                                audio_io_handle_t output,                                uint32_t strategy,                                int session,                                int id){    ssize_t index = mOutputs.indexOfKey(output);    if (index < 0) {        LOGW("registerEffect() unknown output %d", output);        return INVALID_OPERATION;    }    if (mTotalEffectsCpuLoad + desc->cpuLoad > getMaxEffectsCpuLoad()) {        LOGW("registerEffect() CPU Load limit exceeded for Fx %s, CPU %f MIPS",                desc->name, (float)desc->cpuLoad/10);        return INVALID_OPERATION;    }    if (mTotalEffectsMemory + desc->memoryUsage > getMaxEffectsMemory()) {        LOGW("registerEffect() memory limit exceeded for Fx %s, Memory %d KB",                desc->name, desc->memoryUsage);        return INVALID_OPERATION;    }    mTotalEffectsCpuLoad += desc->cpuLoad;    mTotalEffectsMemory += desc->memoryUsage;    LOGV("registerEffect() effect %s, output %d, strategy %d session %d id %d",            desc->name, output, strategy, session, id);    LOGV("registerEffect() CPU %d, memory %d", desc->cpuLoad, desc->memoryUsage);    LOGV("  total CPU %d, total memory %d", mTotalEffectsCpuLoad, mTotalEffectsMemory);    EffectDescriptor *pDesc = new EffectDescriptor();    memcpy (&pDesc->mDesc, desc, sizeof(effect_descriptor_t));    pDesc->mOutput = output;    pDesc->mStrategy = (routing_strategy)strategy;    pDesc->mSession = session;    mEffects.add(id, pDesc);    return NO_ERROR;}// ---------------------------AudioPolicyManagerBase::registerEffect-------------------------------------}// ----------------------------AudioPolicyService::registerEffect------------------------------------}// ----------------------------AudioSystem::registerEffect------------------------------------        }        effect = chain->getEffectFromId_l(0);    }    return NO_ERROR;}// -----------------------------AudioFlinger::moveEffectChain_l-----------------------------------        }// -----------------------------AudioFlinger::createTrack moveEffectChain_l-----------------------------------        }        LOGV("createEffect() got output %d for effect %s", output, desc.name);        PlaybackThread *thread = checkPlaybackThread_l(output);        if (thread == NULL) {            LOGE("createEffect() unknown output thread");            lStatus = BAD_VALUE;            goto Exit;        }        // TODO: allow attachment of effect to inputs        wclient = mClients.valueFor(pid);        if (wclient != NULL) {            client = wclient.promote();        } else {            client = new Client(this, pid);            mClients.add(pid, client);        }        // create effect on selected output trhead        handle = thread->createEffect_l(client, effectClient, priority, sessionId,                &desc, enabled, &lStatus);        if (handle != 0 && id != NULL) {            *id = handle->id();        }// ++++++++++++++++++++++++++++++AudioFlinger::PlaybackThread::createEffect_l++++++++++++++++++++++++++++++++++// PlaybackThread::createEffect_l() must be called with AudioFlinger::mLock heldsp<AudioFlinger::EffectHandle> AudioFlinger::PlaybackThread::createEffect_l(        const sp<AudioFlinger::Client>& client,        const sp<IEffectClient>& effectClient,        int32_t priority,        int sessionId,        effect_descriptor_t *desc,        int *enabled,        status_t *status        ){    sp<EffectModule> effect;    sp<EffectHandle> handle;    status_t lStatus;    sp<Track> track;    sp<EffectChain> chain;    bool chainCreated = false;    bool effectCreated = false;    bool effectRegistered = false;    if (mOutput == 0) {        LOGW("createEffect_l() Audio driver not initialized.");        lStatus = NO_INIT;        goto Exit;    }    // Do not allow auxiliary effect on session other than 0    if ((desc->flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY &&        sessionId != AudioSystem::SESSION_OUTPUT_MIX) {        LOGW("createEffect_l() Cannot add auxiliary effect %s to session %d",                desc->name, sessionId);        lStatus = BAD_VALUE;        goto Exit;    }    // Do not allow effects with session ID 0 on direct output or duplicating threads    // TODO: add rule for hw accelerated effects on direct outputs with non PCM format    if (sessionId == AudioSystem::SESSION_OUTPUT_MIX && mType != MIXER) {        LOGW("createEffect_l() Cannot add auxiliary effect %s to session %d",                desc->name, sessionId);        lStatus = BAD_VALUE;        goto Exit;    }    LOGV("createEffect_l() thread %p effect %s on session %d", this, desc->name, sessionId);    { // scope for mLock        Mutex::Autolock _l(mLock);        // check for existing effect chain with the requested audio session        chain = getEffectChain_l(sessionId);        if (chain == 0) {            // create a new chain for this session            LOGV("createEffect_l() new effect chain for session %d", sessionId);            chain = new EffectChain(this, sessionId);            addEffectChain_l(chain);// +++++++++++++++++++++++++++AudioFlinger::PlaybackThread::addEffectChain_l+++++++++++++++++++++++++++++++++++++status_t AudioFlinger::PlaybackThread::addEffectChain_l(const sp<EffectChain>& chain){    int session = chain->sessionId();    int16_t *buffer = mMixBuffer;    bool ownsBuffer = false;    LOGV("addEffectChain_l() %p on thread %p for session %d", chain.get(), this, session);    if (session > 0) {        // Only one effect chain can be present in direct output thread and it uses        // the mix buffer as input        if (mType != DIRECT) {            size_t numSamples = mFrameCount * mChannelCount;            buffer = new int16_t[numSamples];            memset(buffer, 0, numSamples * sizeof(int16_t));            LOGV("addEffectChain_l() creating new input buffer %p session %d", buffer, session);            ownsBuffer = true;        }        // Attach all tracks with same session ID to this chain.        for (size_t i = 0; i < mTracks.size(); ++i) {            sp<Track> track = mTracks[i];            if (session == track->sessionId()) {                LOGV("addEffectChain_l() track->setMainBuffer track %p buffer %p", track.get(), buffer);                track->setMainBuffer(buffer);            }        }        // indicate all active tracks in the chain        for (size_t i = 0 ; i < mActiveTracks.size() ; ++i) {            sp<Track> track = mActiveTracks[i].promote();            if (track == 0) continue;            if (session == track->sessionId()) {                LOGV("addEffectChain_l() activating track %p on session %d", track.get(), session);                chain->startTrack();            }        }    }    chain->setInBuffer(buffer, ownsBuffer);    chain->setOutBuffer(mMixBuffer);    // Effect chain for session AudioSystem::SESSION_OUTPUT_STAGE is inserted at end of effect    // chains list in order to be processed last as it contains output stage effects    // Effect chain for session AudioSystem::SESSION_OUTPUT_MIX is inserted before    // session AudioSystem::SESSION_OUTPUT_STAGE to be processed    // after track specific effects and before output stage    // It is therefore mandatory that AudioSystem::SESSION_OUTPUT_MIX == 0 and    // that AudioSystem::SESSION_OUTPUT_STAGE < AudioSystem::SESSION_OUTPUT_MIX    // Effect chain for other sessions are inserted at beginning of effect    // chains list to be processed before output mix effects. Relative order between other    // sessions is not important    size_t size = mEffectChains.size();    size_t i = 0;    for (i = 0; i < size; i++) {        if (mEffectChains[i]->sessionId() < session) break;    }    mEffectChains.insertAt(chain, i);    return NO_ERROR;}// ---------------------------AudioFlinger::PlaybackThread::addEffectChain_l-------------------------------------            chain->setStrategy(getStrategyForSession_l(sessionId));            chainCreated = true;        } else {            effect = chain->getEffectFromDesc_l(desc);        }        LOGV("createEffect_l() got effect %p on chain %p", effect == 0 ? 0 : effect.get(), chain.get());        if (effect == 0) {            int id = mAudioFlinger->nextUniqueId();            // Check CPU and memory usage            lStatus = AudioSystem::registerEffect(desc, mId, chain->strategy(), sessionId, id);            if (lStatus != NO_ERROR) {                goto Exit;            }            effectRegistered = true;            // create a new effect module if none present in the chain            effect = new EffectModule(this, chain, desc, id, sessionId);            lStatus = effect->status();            if (lStatus != NO_ERROR) {                goto Exit;            }            lStatus = chain->addEffect_l(effect);            if (lStatus != NO_ERROR) {                goto Exit;            }            effectCreated = true;// ++++++++++++++++++++++++++++AudioFlinger::EffectModule::EffectModule++++++++++++++++++++++++++++++++++++AudioFlinger::EffectModule::EffectModule(const wp<ThreadBase>& wThread,                                        const wp<AudioFlinger::EffectChain>& chain,                                        effect_descriptor_t *desc,                                        int id,                                        int sessionId)    : mThread(wThread), mChain(chain), mId(id), mSessionId(sessionId), mEffectInterface(NULL),      mStatus(NO_INIT), mState(IDLE){    LOGV("Constructor %p", this);    int lStatus;    sp<ThreadBase> thread = mThread.promote();    if (thread == 0) {        return;    }    PlaybackThread *p = (PlaybackThread *)thread.get();    memcpy(&mDescriptor, desc, sizeof(effect_descriptor_t));    // create effect engine from effect factory// 这个函数在看函数queryEffects代码的时候已经接触过    mStatus = EffectCreate(&desc->uuid, sessionId, p->id(), &mEffectInterface);    if (mStatus != NO_ERROR) {        return;    }    lStatus = init();    if (lStatus < 0) {        mStatus = lStatus;        goto Error;    }    LOGV("Constructor success name %s, Interface %p", mDescriptor.name, mEffectInterface);    return;Error:    EffectRelease(mEffectInterface);    mEffectInterface = NULL;    LOGV("Constructor Error %d", mStatus);}// ----------------------------AudioFlinger::EffectModule::EffectModule------------------------------------            effect->setDevice(mDevice);// +++++++++++++++++++++++++++AudioFlinger::EffectModule::setDevice+++++++++++++++++++++++++++++++++++++status_t AudioFlinger::EffectModule::setDevice(uint32_t device){    Mutex::Autolock _l(mLock);    status_t status = NO_ERROR;    if ((mDescriptor.flags & EFFECT_FLAG_DEVICE_MASK) == EFFECT_FLAG_DEVICE_IND) {        // convert device bit field from AudioSystem to EffectApi format.        device = deviceAudioSystemToEffectApi(device);        if (device == 0) {            return BAD_VALUE;        }        status_t cmdStatus;        uint32_t size = sizeof(status_t);// 在EffectModule的构造函数中,调用函数EffectCreate对mEffectInterface进行赋值:// mStatus = EffectCreate(&desc->uuid, sessionId, p->id(), &mEffectInterface);// 此处调用的command函数其实是调用的具体的effect lib中的command 函数// 如EffectReverb 中的Reverb_Command函数。        status = (*mEffectInterface)->command(mEffectInterface,                                              EFFECT_CMD_SET_DEVICE,                                              sizeof(uint32_t),                                              &device,                                              &size,                                              &cmdStatus);        if (status == NO_ERROR) {            status = cmdStatus;        }    }    return status;}// ---------------------------AudioFlinger::EffectModule::setDevice-------------------------------------            effect->setMode(mAudioFlinger->getMode());        }        // create effect handle and connect it to effect module        handle = new EffectHandle(effect, client, effectClient, priority);        lStatus = effect->addHandle(handle);        if (enabled) {            *enabled = (int)effect->isEnabled();        }    }Exit:    if (lStatus != NO_ERROR && lStatus != ALREADY_EXISTS) {        Mutex::Autolock _l(mLock);        if (effectCreated) {            chain->removeEffect_l(effect);        }        if (effectRegistered) {            AudioSystem::unregisterEffect(effect->id());        }        if (chainCreated) {            removeEffectChain_l(chain);        }        handle.clear();    }    if(status) {        *status = lStatus;    }    return handle;}// ------------------------------AudioFlinger::PlaybackThread::createEffect_l----------------------------------    }Exit:    if(status) {        *status = lStatus;    }    return handle;}// --------------------------AudioFlinger::createEffect--------------------------------------    mEnabled = (volatile int32_t)enabled;    mIEffect = iEffect;    cblk = iEffect->getCblk();    if (cblk == 0) {        mStatus = NO_INIT;        LOGE("Could not get control block");        return mStatus;    }    mIEffect = iEffect;    mCblkMemory = cblk;    mCblk = static_cast<effect_param_cblk_t*>(cblk->pointer());    int bufOffset = ((sizeof(effect_param_cblk_t) - 1) / sizeof(int) + 1) * sizeof(int);    mCblk->buffer = (uint8_t *)mCblk + bufOffset;    iEffect->asBinder()->linkToDeath(mIEffectClient);    LOGV("set() %p OK effect: %s id: %d status %d enabled %d, ", this, mDescriptor.name, mId, mStatus, mEnabled);    return mStatus;}// -----------------------------AudioEffect::set-----------------------------------}// ----------------------------native AudioEffect------------------------------------    lStatus = translateError(lpAudioEffect->initCheck());    if (lStatus != AUDIOEFFECT_SUCCESS && lStatus != AUDIOEFFECT_ERROR_ALREADY_EXISTS) {        LOGE("AudioEffect initCheck failed %d", lStatus);        goto setup_failure;    }    nId = (jint *) env->GetPrimitiveArrayCritical(jId, NULL);    if (nId == NULL) {        LOGE("setup: Error retrieving id pointer");        lStatus = AUDIOEFFECT_ERROR_BAD_VALUE;        goto setup_failure;    }    nId[0] = lpAudioEffect->id();    env->ReleasePrimitiveArrayCritical(jId, nId, 0);    nId = NULL;    if (typeStr) {        env->ReleaseStringUTFChars(type, typeStr);        typeStr = NULL;    }    if (uuidStr) {        env->ReleaseStringUTFChars(uuid, uuidStr);        uuidStr = NULL;    }    // get the effect descriptor    desc = lpAudioEffect->descriptor();    AudioEffect::guidToString(&desc.type, str, EFFECT_STRING_LEN_MAX);    jdescType = env->NewStringUTF(str);    AudioEffect::guidToString(&desc.uuid, str, EFFECT_STRING_LEN_MAX);    jdescUuid = env->NewStringUTF(str);    if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {        jdescConnect = env->NewStringUTF("Auxiliary");    } else {        jdescConnect = env->NewStringUTF("Insert");    }    jdescName = env->NewStringUTF(desc.name);    jdescImplementor = env->NewStringUTF(desc.implementor);    jdesc = env->NewObject(fields.clazzDesc,                           fields.midDescCstor,                           jdescType,                           jdescUuid,                           jdescConnect,                           jdescName,                           jdescImplementor);    env->DeleteLocalRef(jdescType);    env->DeleteLocalRef(jdescUuid);    env->DeleteLocalRef(jdescConnect);    env->DeleteLocalRef(jdescName);    env->DeleteLocalRef(jdescImplementor);    if (jdesc == NULL) {        LOGE("env->NewObject(fields.clazzDesc, fields.midDescCstor)");        goto setup_failure;    }    env->SetObjectArrayElement(javadesc, 0, jdesc);    env->SetIntField(thiz, fields.fidNativeAudioEffect, (int)lpAudioEffect);    env->SetIntField(thiz, fields.fidJniData, (int)lpJniStorage);    return AUDIOEFFECT_SUCCESS;    // failures:setup_failure:    if (nId != NULL) {        env->ReleasePrimitiveArrayCritical(jId, nId, 0);    }    if (lpAudioEffect) {        delete lpAudioEffect;    }    env->SetIntField(thiz, fields.fidNativeAudioEffect, 0);    if (lpJniStorage) {        delete lpJniStorage;    }    env->SetIntField(thiz, fields.fidJniData, 0);    if (uuidStr != NULL) {        env->ReleaseStringUTFChars(uuid, uuidStr);    }    if (typeStr != NULL) {        env->ReleaseStringUTFChars(type, typeStr);    }    return lStatus;}// -------------------------android_media_AudioEffect_native_setup---------------------------------------        if (initResult != SUCCESS && initResult != ALREADY_EXISTS) {            Log.e(TAG, "Error code " + initResult                    + " when initializing AudioEffect.");            switch (initResult) {            case ERROR_BAD_VALUE:                throw (new IllegalArgumentException("Effect type: " + type                        + " not supported."));            case ERROR_INVALID_OPERATION:                throw (new UnsupportedOperationException(                        "Effect library not loaded"));            default:                throw (new RuntimeException(                        "Cannot initialize effect engine for type: " + type                                + "Error: " + initResult));            }        }        mId = id[0];        mDescriptor = desc[0];        synchronized (mStateLock) {            mState = STATE_INITIALIZED;        }    }// --------------------------------AudioEffect--------------------------------            assertNotNull(msg + ": could not create AudioEffect", effect);            try {                assertTrue(msg +": invalid effect ID", (effect.getId() != 0));            } catch (IllegalStateException e) {                msg = msg.concat(": AudioEffect not initialized");                result = false;            } finally {                effect.release();            }        } catch (IllegalArgumentException e) {            msg = msg.concat(": Effect not found: "+desc[0].name);            result = false;        } catch (UnsupportedOperationException e) {            msg = msg.concat(": Effect library not loaded");            result = false;        }        assertTrue(msg, result);    }

###########################################################


&&&&&&&&&&&&&&&&&&&&&&&总结&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
在创建AudioEffect的时候:
1、如果指定了uuid,则会根据uuid 寻找匹配的effect lib来创建effect。
2、若没有指定uuid而指定了type,则会寻找相同type中可用的effect lib。
注意,如果session id为SESSION_OUTPUT_MIX,则优先使用auxiliary的effect。
在指定的type中没有可用的auxiliary的effect的情况下,才会使用insert的effect。

effect lib都被注册到一个列表中。
EffectsFactory中的init函数会将build-in的effect lib添加到该列表。
用户可以调用函数EffectLoadLibrary/EffectUnloadLibrary来注册/删除effect lib。


&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

更多相关文章

  1. Android Audio代码分析2 - 函数getMinBufferSize
  2. android关于fragment的构造函数用法建议
  3. Android Audio代码分析18 - setSampleRate函数
  4. Android Audio代码分析22 - AudioEffect::getEnabled函数
  5. android必备知识(一)java引用类型
  6. Android Chronometer控件实现计时器函数详解

随机推荐

  1. 按键及其居中
  2. adb shell
  3. Android(安卓)jni中数组参数的传递方式
  4. 【北亚服务器数据恢复】服务器reiserfs文
  5. 基于CentOS系统安装OceanBase数据库
  6. 基于CentOS系统安装OceanBase数据库
  7. javascript-基础(六)
  8. HTML-Canvas的优越性能以及实际应用
  9. 函数参数及返回值、模板字面量及模板函数
  10. Android(安卓)- 永不锁屏,开机不锁屏,删除