您的位置:首页 > 移动开发 > Android开发

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

2011-10-21 12:20 543 查看
之前已经看过,通过接口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 侧的函数, 在后面的文章中再详细介绍。

&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: