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、付费专栏及课程。

余额充值