Android Audio代码分析24 - AudioEffect::setEnabled函数

之前已经看过,通过接口getEnabled可以取得effect的enable状态。
今天来看看如何来改变enable状态。


*****************************************源码*************************************************
    //Test case 2.0: test setEnabled() and getEnabled() in valid state
    @LargeTest
    public void test2_0SetEnabledGetEnabled() throws Exception {
        boolean result = false;
        String msg = "test2_0SetEnabledGetEnabled()";


        try {
            AudioEffect effect = new AudioEffect(AudioEffect.EFFECT_TYPE_EQUALIZER,
                    AudioEffect.EFFECT_TYPE_NULL,
                    0,
                    0);
            assertNotNull(msg + ": could not create AudioEffect", effect);
            try {
                effect.setEnabled(true);
                assertTrue(msg + ": invalid state from getEnabled", effect.getEnabled());
                effect.setEnabled(false);
                assertFalse(msg + ": invalid state to getEnabled", effect.getEnabled());
                result = true;
            } catch (IllegalStateException e) {
                msg = msg.concat(": setEnabled() in wrong state");
            } finally {
                effect.release();
            }
        } catch (IllegalArgumentException e) {
            msg = msg.concat(": Equalizer not found");
            loge(msg, ": Equalizer not found");
        } catch (UnsupportedOperationException e) {
            msg = msg.concat(": Effect library not loaded");
            loge(msg, ": Effect library not loaded");
        }
        assertTrue(msg, result);
    }

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


#######################说明################################
    //Test case 2.0: test setEnabled() and getEnabled() in valid state
    @LargeTest
    public void test2_0SetEnabledGetEnabled() throws Exception {
        boolean result = false;
        String msg = "test2_0SetEnabledGetEnabled()";


        try {
            AudioEffect effect = new AudioEffect(AudioEffect.EFFECT_TYPE_EQUALIZER,
                    AudioEffect.EFFECT_TYPE_NULL,
                    0,
                    0);
            assertNotNull(msg + ": could not create AudioEffect", effect);
            try {
                effect.setEnabled(true);
// ++++++++++++++++++++++++++++++setEnabled++++++++++++++++++++++++++++++++++
    /**
     * Enable or disable the effect.
     * Creating an audio effect does not automatically apply this effect on the audio source. It
     * creates the resources necessary to process this effect but the audio signal is still bypassed
     * through the effect engine. Calling this method will make that the effect is actually applied
     * or not to the audio content being played in the corresponding audio session.
     *
     * @param enabled the requested enable state
     * @return {@link #SUCCESS} in case of success, {@link #ERROR_INVALID_OPERATION}
     *         or {@link #ERROR_DEAD_OBJECT} in case of failure.
     * @throws IllegalStateException
     */
// 创建一个audio effect,它并不会自发发挥作用。
// 该函数可以启动/停止该audio effect发挥作用。
    public int setEnabled(boolean enabled) throws IllegalStateException {
        checkState("setEnabled()");
        return native_setEnabled(enabled);
// ++++++++++++++++++++++++++++++android_media_AudioEffect_native_setEnabled++++++++++++++++++++++++++++++++++
static jint
android_media_AudioEffect_native_setEnabled(JNIEnv *env, jobject thiz, jboolean enabled)
{
    // retrieve the AudioEffect object
    AudioEffect* lpAudioEffect = (AudioEffect *)env->GetIntField(
        thiz, fields.fidNativeAudioEffect);


    if (lpAudioEffect == NULL) {
        jniThrowException(env, "java/lang/IllegalStateException",
            "Unable to retrieve AudioEffect pointer for enable()");
        return AUDIOEFFECT_ERROR_NO_INIT;
    }


    return translateError(lpAudioEffect->setEnabled(enabled));
// ++++++++++++++++++++++++++++++AudioEffect::setEnabled++++++++++++++++++++++++++++++++++
status_t AudioEffect::setEnabled(bool enabled)
{
    if (mStatus != NO_ERROR) {
        return INVALID_OPERATION;
    }


    if (enabled) {
        LOGV("enable %p", this);
        if (android_atomic_or(1, &mEnabled) == 0) {
// mIEffect的赋值在函数AudioEffect::set中。
//    iEffect = audioFlinger->createEffect(getpid(), (effect_descriptor_t *)&mDescriptor,
//            mIEffectClient, priority, output, mSessionId, &mStatus, &mId, &enabled);
//    mIEffect = iEffect;


// 函数AudioFlinger::createEffect中,调用了函数AudioFlinger::PlaybackThread::createEffect_l来创建一个对象并将其返回。
        // create effect on selected output trhead
//        handle = thread->createEffect_l(client, effectClient, priority, sessionId,
//                &desc, enabled, &lStatus);


// 函数AudioFlinger::PlaybackThread::createEffect_l中创建了一个EffectHandle对象并将其返回
        // create effect handle and connect it to effect module
//        handle = new EffectHandle(effect, client, effectClient, priority);
//        lStatus = effect->addHandle(handle);


// 所以,此处调用的其实是函数AudioFlinger::EffectHandle::enable。
           return mIEffect->enable();
// +++++++++++++++++++++++++++++AudioFlinger::EffectHandle::enable+++++++++++++++++++++++++++++++++++
status_t AudioFlinger::EffectHandle::enable()
{
    if (!mHasControl) return INVALID_OPERATION;
    if (mEffect == 0) return DEAD_OBJECT;


    return mEffect->setEnabled(true);
// +++++++++++++++++++++++++++++AudioFlinger::EffectModule::setEnabled+++++++++++++++++++++++++++++++++++
status_t AudioFlinger::EffectModule::setEnabled(bool enabled)
{
    Mutex::Autolock _l(mLock);
    LOGV("setEnabled %p enabled %d", this, enabled);


    if (enabled != isEnabled()) {
        switch (mState) {
        // going from disabled to enabled
        case IDLE:
            mState = STARTING;
            break;
        case STOPPED:
            mState = RESTART;
            break;
        case STOPPING:
            mState = ACTIVE;
            break;


        // going from enabled to disabled
        case RESTART:
            mState = STOPPED;
            break;
        case STARTING:
            mState = IDLE;
            break;
        case ACTIVE:
            mState = STOPPING;
            break;
        }
        for (size_t i = 1; i < mHandles.size(); i++) {
// 函数AudioFlinger::PlaybackThread::createEffect_l中创建了一个EffectHandle对象后,
// 会调用函数AudioFlinger::EffectModule::addHandle将其添加到mHandles中。
            sp<EffectHandle> h = mHandles[i].promote();
            if (h != 0) {
// 因此,此处调用的是函数AudioFlinger::EffectHandle::setEnabled。
                h->setEnabled(enabled);
// ++++++++++++++++++++++++++++AudioFlinger::EffectHandle::setEnabled++++++++++++++++++++++++++++++++++++
void AudioFlinger::EffectHandle::setEnabled(bool enabled)
{
// mEffectClient在AudioFlinger::EffectHandle::EffectHandle的构造函数中被赋值
// 该client对象最初在函数AudioEffect::set中被创建:mIEffectClient = new EffectClient(this);
// 接着传给了函数AudioFlinger::createEffect,接着到函数AudioFlinger::PlaybackThread::createEffect_l,
// 最终到了AudioFlinger::EffectHandle::EffectHandle的构造函数。
    if (mEffectClient != 0) {
        mEffectClient->enableStatusChanged(enabled);
// ++++++++++++++++++++++++++++EffectClient::enableStatusChanged++++++++++++++++++++++++++++++++++++
        virtual void enableStatusChanged(bool enabled) {
// mEffect在 EffectClient 的构造函数中被赋值, 
// 所赋值在函数 AudioEffect::set 中传入 : mIEffectClient = new EffectClient(this);
// 所以,此处调用的是函数 AudioEffect::enableStatusChanged
            mEffect->enableStatusChanged(enabled);
// ++++++++++++++++++++++++++++AudioEffect::enableStatusChanged++++++++++++++++++++++++++++++++++++
void AudioEffect::enableStatusChanged(bool enabled)
{
    LOGV("enableStatusChanged %p enabled %d mCbf %p", this, enabled, mCbf);
    if (mStatus == ALREADY_EXISTS) {
        if (enabled) {
            android_atomic_or(1, &mEnabled);
        } else {
            android_atomic_and(~1, &mEnabled);
        }
        if (mCbf) {
// 此处其实是调用的函数 effectCallback
            mCbf(EVENT_ENABLE_STATUS_CHANGED, mUserData, &enabled);
// +++++++++++++++++++++++++++++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;
    }


// callbackInfo 是由输入参数 user 转化而来: effect_callback_cookie *callbackInfo = (effect_callback_cookie *)user;
// 函数 AudioEffect::enableStatusChanged 调用 effectCallback 时传入的是 mUserData 。
// mUserData 在函数 AudioEffect::set 中被赋值 mUserData = user;
// user 最初由函数 android_media_AudioEffect_native_setup 传给了 AudioEffect 的构造函数,
// 然后传给了函数 AudioEffect::set 。
// user 的最初来源是 lpJniStorage->mCallbackData , 
// 此处调用的 midPostNativeEvent 函数其实是对象 lpJniStorage->mCallbackData.audioEffect_class = (jclass)env->NewGlobalRef(fields.clazzEffect);
// 的PostNativeEvent函数。
// env->NewGlobalRef(fields.clazzEffect)是创建一个fields.clazzEffect的全局的引用。
// fields.clazzEffect的由来:
//    jclass clazz = env->FindClass(kClassPathName);
// fields.clazzEffect = (jclass)env->NewGlobalRef(clazz);
// kClassPathName 的定义:static const char* const kClassPathName = "android/media/audiofx/AudioEffect";
// fields.midPostNativeEvent 的由来 :
//    fields.midPostNativeEvent = env->GetStaticMethodID(
//            fields.clazzEffect,
//            "postEventFromNative", "(Ljava/lang/Object;IIILjava/lang/Object;)V");
// 所以,此处调用的其实是 java 侧类 AudioEffect 的 postEventFromNative 函数
    env->CallStaticVoidMethod(
        callbackInfo->audioEffect_class,
        fields.midPostNativeEvent,
        callbackInfo->audioEffect_ref, event, arg1, arg2, obj);
// ++++++++++++++++++++++++++postEventFromNative++++++++++++++++++++++++++++++++++++++
    private static void postEventFromNative(Object effect_ref, int what,
            int arg1, int arg2, Object obj) {
        AudioEffect effect = (AudioEffect) ((WeakReference) effect_ref).get();
// 因为是 weak reference ,存在已被回收的可能
        if (effect == null) {
            return;
        }
// mNativeEventHandler 在函数 createNativeEventHandler 中被赋值
        if (effect.mNativeEventHandler != null) {
// ++++++++++++++++++++++++++++++createNativeEventHandler++++++++++++++++++++++++++++++++++
    // Convenience method for the creation of the native event handler
    // It is called only when a non-null event listener is set.
    // precondition:
    // mNativeEventHandler is null
    private void createNativeEventHandler() {
        Looper looper;
        if ((looper = Looper.myLooper()) != null) {
// 类 NativeEventHandler 中的一个重要函数就是 handleMessage
            mNativeEventHandler = new NativeEventHandler(this, looper);
// +++++++++++++++++++++++++++++handleMessage+++++++++++++++++++++++++++++++++++
        public void handleMessage(Message msg) {
            if (mAudioEffect == null) {
                return;
            }
            switch (msg.what) {
// 通过回调函数,告诉 java 侧状态改变, java 侧作相应相应
            case NATIVE_EVENT_ENABLED_STATUS:
                OnEnableStatusChangeListener enableStatusChangeListener = null;
                synchronized (mListenerLock) {
                    enableStatusChangeListener = mAudioEffect.mEnableStatusChangeListener;
                }
                if (enableStatusChangeListener != null) {
                    enableStatusChangeListener.onEnableStatusChange(
                            mAudioEffect, (boolean) (msg.arg1 != 0));
                }
                break;
            case NATIVE_EVENT_CONTROL_STATUS:
                OnControlStatusChangeListener controlStatusChangeListener = null;
                synchronized (mListenerLock) {
                    controlStatusChangeListener = mAudioEffect.mControlChangeStatusListener;
                }
                if (controlStatusChangeListener != null) {
                    controlStatusChangeListener.onControlStatusChange(
                            mAudioEffect, (boolean) (msg.arg1 != 0));
                }
                break;
            case NATIVE_EVENT_PARAMETER_CHANGED:
                OnParameterChangeListener parameterChangeListener = null;
                synchronized (mListenerLock) {
                    parameterChangeListener = mAudioEffect.mParameterChangeListener;
                }
                if (parameterChangeListener != null) {
                    // arg1 contains offset of parameter value from start of
                    // byte array
                    int vOffset = msg.arg1;
                    byte[] p = (byte[]) msg.obj;
                    // See effect_param_t in EffectApi.h for psize and vsize
                    // fields offsets
                    int status = byteArrayToInt(p, 0);
                    int psize = byteArrayToInt(p, 4);
                    int vsize = byteArrayToInt(p, 8);
                    byte[] param = new byte[psize];
                    byte[] value = new byte[vsize];
                    System.arraycopy(p, 12, param, 0, psize);
                    System.arraycopy(p, vOffset, value, 0, vsize);


                    parameterChangeListener.onParameterChange(mAudioEffect,
                            status, param, value);
                }
                break;


            default:
                Log.e(TAG, "handleMessage() Unknown event type: " + msg.what);
                break;
            }
        }
// -----------------------------handleMessage-----------------------------------
        } else if ((looper = Looper.getMainLooper()) != null) {
            mNativeEventHandler = new NativeEventHandler(this, looper);
        } else {
            mNativeEventHandler = null;
        }
    }

// 函数 setEnableStatusListener 中会调用函数 createNativeEventHandler
// +++++++++++++++++++++++++++++createNativeEventHandler+++++++++++++++++++++++++++++++++++
    /**
     * Sets the listener AudioEffect notifies when the effect engine is enabled
     * or disabled.
     *
     * @param listener
     */
    public void setEnableStatusListener(OnEnableStatusChangeListener listener) {
        synchronized (mListenerLock) {
            mEnableStatusChangeListener = listener;
        }
        if ((listener != null) && (mNativeEventHandler == null)) {
            createNativeEventHandler();
        }
    }
// 应用程序中会创建一个 Listener 并调用函数 setEnableStatusListener 设置到 AudioEffect 对象中。
// 如文件 MediaAudioEffectTest.java 中的 createListenerLooper 函数。
// -----------------------------createNativeEventHandler-----------------------------------
// ------------------------------createNativeEventHandler----------------------------------
            Message m = effect.mNativeEventHandler.obtainMessage(what, arg1,
                    arg2, obj);
            effect.mNativeEventHandler.sendMessage(m);
        }


    }
// --------------------------postEventFromNative--------------------------------------


effectCallback_Exit:
    if (array) {
        env->DeleteLocalRef(array);
    }


    if (env->ExceptionCheck()) {
        env->ExceptionDescribe();
        env->ExceptionClear();
    }
}
// -----------------------------effectCallback-----------------------------------
        }
    }
}
// ----------------------------AudioEffect::enableStatusChanged------------------------------------
        }
// ----------------------------EffectClient::enableStatusChanged------------------------------------
    }
}
// ----------------------------AudioFlinger::EffectHandle::setEnabled------------------------------------
            }
        }
    }
    return NO_ERROR;
}
// -----------------------------AudioFlinger::EffectModule::setEnabled-----------------------------------
}
// -----------------------------AudioFlinger::EffectHandle::enable-----------------------------------
        }
    } else {
        LOGV("disable %p", this);
        if (android_atomic_and(~1, &mEnabled) == 1) {
           return mIEffect->disable();
        }
    }
    return NO_ERROR;
}
// ------------------------------AudioEffect::setEnabled----------------------------------
}
// ------------------------------android_media_AudioEffect_native_setEnabled----------------------------------
    }
// ------------------------------setEnabled----------------------------------
                assertTrue(msg + ": invalid state from getEnabled", effect.getEnabled());
                effect.setEnabled(false);
                assertFalse(msg + ": invalid state to getEnabled", effect.getEnabled());
                result = true;
            } catch (IllegalStateException e) {
                msg = msg.concat(": setEnabled() in wrong state");
            } finally {
                effect.release();
            }
        } catch (IllegalArgumentException e) {
            msg = msg.concat(": Equalizer not found");
            loge(msg, ": Equalizer not found");
        } catch (UnsupportedOperationException e) {
            msg = msg.concat(": Effect library not loaded");
            loge(msg, ": Effect library not loaded");
        }
        assertTrue(msg, result);
    }

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


&&&&&&&&&&&&&&&&&&&&&&&总结&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
setEnabled 最终会调用到 EffectModule 中的 setEnabled 函数。
函数 EffectModule::setEnabled 会修改当前状态,并调用函数 EffectHandle::setEnabled 。
函数 EffectHandle::setEnabled 会回调到 java 侧的函数 postEventFromNative ,将状态改变告诉给 java 侧。
函数 postEventFromNative 会调用 NativeEventHandler::handleMessage 函数来处理 native 侧过来的 event 。
handleMessage 函数中调用 Listener 的 onEnableStatusChange 函数,将改变告诉给应用成员。
应用程序在初始化阶段会创建一个自己的 Listener ,并将它注册到 AudioEffect 对象。


至于 native 侧如何回调 java 侧的函数, 在后面的文章中再详细介绍。
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值