Android Audio代码分析6 - AudioEffect

在看AudioSessionId相关代码的时候了解到,共用一个AudioSessionId的AudioTrack和MediaPlayer会共用一个AudioEffect。
今天就来看看AudioEffect是个什么东东。

看这个类的目的,主要是为了搞清楚AudioEffect是个什么东东。
打算重点看看类的介绍及其构造函数上。

*****************************************源码*************************************************
public class AudioEffect {
static {
System.loadLibrary("audioeffect_jni");
native_init();
}
...
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(this),
type.toString(), uuid.toString(), priority, audioSession, id,
desc);
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;
}
}
...
}
**********************************************************************************************
源码路径:
frameworks\base\media\java\android\media\audiofx\AudioEffect.java

###########################################说明################################################
先看看整个类的注释:
/**
* AudioEffect is the base class for controlling audio effects provided by the android audio
* framework.
*

Applications should not use the AudioEffect class directly but one of its derived classes to
* control specific effects:
*


    *
  • {@link android.media.audiofx.Equalizer}

  • *
  • {@link android.media.audiofx.Virtualizer}

  • *
  • {@link android.media.audiofx.BassBoost}

  • *
  • {@link android.media.audiofx.PresetReverb}

  • *
  • {@link android.media.audiofx.EnvironmentalReverb}

  • *

*

If the audio effect is to be applied to a specific AudioTrack or MediaPlayer instance,
* the application must specify the audio session ID of that instance when creating the AudioEffect.
* (see {@link android.media.MediaPlayer#getAudioSessionId()} for details on audio sessions).
* To apply an effect to the global audio output mix, session 0 must be specified when creating the
* AudioEffect.
*

Creating an effect on the output mix (audio session 0) requires permission
* {@link android.Manifest.permission#MODIFY_AUDIO_SETTINGS}
*

Creating an AudioEffect object will create the corresponding effect engine in the audio
* framework if no instance of the same effect type exists in the specified audio session.
* If one exists, this instance will be used.
*

The application creating the AudioEffect object (or a derived class) will either receive
* control of the effect engine or not depending on the priority parameter. If priority is higher
* than the priority used by the current effect engine owner, the control will be transfered to the
* new object. Otherwise control will remain with the previous object. In this case, the new
* application will be notified of changes in effect engine state or control ownership by the
* appropiate listener.
*/
大致意思如下:
AudioEffect是由android audio framework提供的控制audio effect的基类。
应用程序不应该直接创建AudioEffect的对象,而应该创建由其派生的,控制特定effect的类的对象。
可创建对象的派生类如下:
*

  • {@link android.media.audiofx.Equalizer}

  • *
  • {@link android.media.audiofx.Virtualizer}

  • *
  • {@link android.media.audiofx.BassBoost}

  • *
  • {@link android.media.audiofx.PresetReverb}

  • *
  • {@link android.media.audiofx.EnvironmentalReverb}

  • *
    如果一个audio effect被指定给一个特定的AudioTrack或者MediaPlayer,创建AudioEffect对象的时候必须指定一个AudioSessionId。
    如果想创建一个对global audio output mix都起作用的audio effect,需要将AudioSessionId指定为0.
    想创建一个对global audio output mix都起作用的audio effect需要特定的许可:
    * {@link android.Manifest.permission#MODIFY_AUDIO_SETTINGS}
    创建AudioEffect对象时,如果指定的AudioSession中不存在该类型的AudioEffect,则会在audio framework中创建一个effect engine。
    否则,将使用已存在的AudioEffect对象。
    应用程序创建了一个AudioEffect对象后,能否取得effect enging的控制权,取决于优先级。
    如果优先级比正控制effect enging的应用程序的优先级高,则会把控制权抢过来。
    否则只能眼睁睁的看着人家继续控制。
    不过,如果effect enging的状态或者所有权改变时,监听器将会通知应用程序。

    再看看其构造函数及注释
    // Constructor, Finalize
    // --------------------
    /**
    * 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
    */

    注释中详细介绍了各个参数。

    参数type是要创建的effect的类型。标准的类型已经在AudioEffect类中定义了,可以直接使用。
    若要使用其他的类型,需要提供OpenSLES interface ID,并且在平台中存在该类型。
    若指定的类型不存在,则会抛出IllegalArgumentException异常。
    若type为EFFECT_TYPE_NULL,则只会根据uuid来选择effect。
    标准的类型如下:
    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    /**
    * The following UUIDs define effect types corresponding to standard audio
    * effects whose implementation and interface conform to the OpenSL ES
    * specification. The definitions match the corresponding interface IDs in
    * OpenSLES_IID.h
    */

    /**
    * UUID for environmental reverb effect
    * @hide
    */
    public static final UUID EFFECT_TYPE_ENV_REVERB = UUID
    .fromString("c2e5d5f0-94bd-4763-9cac-4e234d06839e");
    /**
    * UUID for preset reverb effect
    * @hide
    */
    public static final UUID EFFECT_TYPE_PRESET_REVERB = UUID
    .fromString("47382d60-ddd8-11db-bf3a-0002a5d5c51b");
    /**
    * UUID for equalizer effect
    * @hide
    */
    public static final UUID EFFECT_TYPE_EQUALIZER = UUID
    .fromString("0bed4300-ddd6-11db-8f34-0002a5d5c51b");
    /**
    * UUID for bass boost effect
    * @hide
    */
    public static final UUID EFFECT_TYPE_BASS_BOOST = UUID
    .fromString("0634f220-ddd4-11db-a0fc-0002a5d5c51b");
    /**
    * UUID for virtualizer effect
    * @hide
    */
    public static final UUID EFFECT_TYPE_VIRTUALIZER = UUID
    .fromString("37cc2c00-dddd-11db-8577-0002a5d5c51b");

    /**
    * Null effect UUID. Used when the UUID for effect type of
    * @hide
    */
    public static final UUID EFFECT_TYPE_NULL = UUID
    .fromString("ec7178ec-e5e1-4432-a3f4-4657e6795210");
    ----------------------------------------------------------------

    参数uuid用于指定一个特定effect的实现。
    若uuid为EFFECT_TYPE_NULL,则只会根据type来选择effect。
    关于uuid的取值,搜了下代码,发现,如果type不为EFFECT_TYPE_NULL,uuid多被指定为EFFECT_TYPE_NULL。
    uuid不为EFFECT_TYPE_NULL的地方,type多被指定为EFFECT_TYPE_NULL。
    基本上是靠两个中的一个来选择类型的,为何要两个参数?
    难道type用来指定标准的?uuid用来指定其他的?
    发现有如下的代码:
    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    // creating a volume controller on output mix ensures that ro.audio.silent mutes
    // audio after the effects and not before
    vc = new AudioEffect(
    AudioEffect.EFFECT_TYPE_NULL,
    UUID.fromString("119341a0-8469-11df-81f9-0002a5d5c51b"),
    0,
    0);
    ----------------------------------------------------------------

    priority是优先级,前文有说过,会根据优先级来判断effect engine的控制权。

    audioSession我们已经多次提到过。
    相同audioSession ID的AudioTrack和MediaPlayer共享Audio Effect。

    public AudioEffect(UUID type, UUID uuid, int priority, int audioSession)
    throws IllegalArgumentException, UnsupportedOperationException,
    RuntimeException {
    int[] id = new int[1];
    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    类Descriptor的注释:
    /**
    * The effect descriptor contains information on a particular effect implemented in the
    * audio framework:

    *


      *
    • type: UUID corresponding to the OpenSL ES interface implemented by this effect

    • *
    • uuid: UUID for this particular implementation

    • *
    • connectMode: {@link #EFFECT_INSERT} or {@link #EFFECT_AUXILIARY}

    • *
    • name: human readable effect name

    • *
    • implementor: human readable effect implementor name

    • *

    * The method {@link #queryEffects()} returns an array of Descriptors to facilitate effects
    * enumeration.
    */
    ----------------------------------------------------------------
    Descriptor[] desc = new Descriptor[1];
    // native initialization
    // native_setup在以前有说过。
    // 该函数肯定会调到native中的XXX_native_setup之类的函数中,
    // 并最终创建一个native侧的AudioEffect对象,并通过函数函数SetIntField保存到java侧。
    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    果然,在文件frameworks\base\media\audioeffect\android_media_AudioEffect.cpp中找到了JNI函数对照表:
    // Dalvik VM type signatures
    static JNINativeMethod gMethods[] = {
    {"native_init", "()V", (void *)android_media_AudioEffect_native_init},
    {"native_setup", "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;II[I[Ljava/lang/Object;)I",
    (void *)android_media_AudioEffect_native_setup},
    {"native_finalize", "()V", (void *)android_media_AudioEffect_native_finalize},
    {"native_release", "()V", (void *)android_media_AudioEffect_native_release},
    {"native_setEnabled", "(Z)I", (void *)android_media_AudioEffect_native_setEnabled},
    {"native_getEnabled", "()Z", (void *)android_media_AudioEffect_native_getEnabled},
    {"native_hasControl", "()Z", (void *)android_media_AudioEffect_native_hasControl},
    {"native_setParameter", "(I[BI[B)I", (void *)android_media_AudioEffect_native_setParameter},
    {"native_getParameter", "(I[B[I[B)I", (void *)android_media_AudioEffect_native_getParameter},
    {"native_command", "(II[B[I[B)I", (void *)android_media_AudioEffect_native_command},
    {"native_query_effects", "()[Ljava/lang/Object;", (void *)android_media_AudioEffect_native_queryEffects},
    };
    ----------------------------------------------------------------
    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    函数android_media_AudioEffect_native_setup的实现也在文件frameworks\base\media\audioeffect\android_media_AudioEffect.cpp中。
    static jint
    android_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;
    }
    }

    if (typeStr == NULL && uuidStr == NULL) {
    lStatus = AUDIOEFFECT_ERROR_BAD_VALUE;
    goto setup_failure;
    }

    // 此处创建了一个AudioEffectJniStorage对象。
    // 在看AudioTrack代码的时候,见到过相似的类。
    // 是Android进程间共享内存用的。
    lpJniStorage = new AudioEffectJniStorage();
    if (lpJniStorage == NULL) {
    LOGE("setup: Error creating JNI Storage");
    goto setup_failure;
    }

    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;
    }

    // 如我们所料,此处创建了一个native侧的AudioEffect(class AudioEffect : public RefBase)对象。
    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    关于类AudioEffect的说明。与java侧类的说明意思相同。
    /* Constructor.
    * AudioEffect is the base class for creating and controlling an effect engine from
    * the application process. Creating an AudioEffect object will create the effect engine
    * in the AudioFlinger if no engine of the specified type exists. If one exists, this engine
    * will be used. The application creating the AudioEffect object (or a derived class like
    * Reverb for instance) will either receive control of the effect engine or not, depending
    * on the priority parameter. If priority is higher than the priority used by the current
    * effect engine owner, the control will be transfered to the new application. Otherwise
    * control will remain to the previous application. In this case, the new application will be
    * notified of changes in effect engine state or control ownership by the effect callback.
    * After creating the AudioEffect, the application must call the initCheck() method and
    * check the creation status before trying to control the effect engine (see initCheck()).
    * If the effect is to be applied to an AudioTrack or MediaPlayer only the application
    * must specify the audio session ID corresponding to this player.
    */
    ----------------------------------------------------------------
    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    构造函数中,各参数的说明。
    /* Constructor.
    *
    * Parameters:
    *
    * type: type of effect created: can be null if uuid is specified. This corresponds to
    * the OpenSL ES interface implemented by this effect.
    * uuid: Uuid of effect created: can be null if type is specified. This uuid corresponds to
    * a particular implementation of an effect type.
    * priority: requested priority for effect control: the priority level corresponds to the
    * value of priority parameter: negative values indicate lower priorities, positive values
    * higher priorities, 0 being the normal priority.
    * cbf: optional callback function (see effect_callback_t)
    * user: pointer to context for use by the callback receiver.
    * sessionID: audio session this effect is associated to. If 0, the effect will be global to
    * the output mix. If not 0, the effect will be applied to all players
    * (AudioTrack or MediaPLayer) within the same audio session.
    * output: HAL audio output stream to which this effect must be attached. Leave at 0 for
    * automatic output selection by AudioFlinger.
    */
    这些参数以前都有遇到过。
    ----------------------------------------------------------------
    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    类AudioEffect的构造函数代码:
    (可见其中没做太多工作。
    主要工作应该是在set函数中完成的。)
    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;
    }
    }

    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    set函数注释:
    /* Initialize an uninitialized AudioEffect.
    * Returned status (from utils/Errors.h) can be:
    * - NO_ERROR or ALREADY_EXISTS: successful initialization
    * - INVALID_OPERATION: AudioEffect is already initialized
    * - BAD_VALUE: invalid parameter
    * - NO_INIT: audio flinger or audio hardware not initialized
    * */

    代码:
    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;
    sp cblk;
    int enabled;

    LOGV("set %p mUserData: %p", this, user);

    if (mIEffect != 0) {
    LOGW("Effect already in use");
    return INVALID_OPERATION;
    }

    const sp& audioFlinger = AudioSystem::get_audio_flinger();
    if (audioFlinger == 0) {
    LOGE("set(): Could not get audioflinger");
    return NO_INIT;
    }

    if (type == NULL && uuid == NULL) {
    LOGW("Must specify at least type or uuid");
    return BAD_VALUE;
    }

    mPriority = priority;
    mCbf = cbf;
    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));
    }

    // 这边只是相当于客户端,服务端在audioflinger侧
    // Implements the IEffectClient interface
    // class EffectClient : public android::BnEffectClient, public android::IBinder::DeathRecipient
    mIEffectClient = new EffectClient(this);

    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    sp AudioFlinger::createEffect(pid_t pid,
    effect_descriptor_t *pDesc,
    const sp& effectClient,
    int32_t priority,
    int output,
    int sessionId,
    status_t *status,
    int *id,
    int *enabled)
    {
    status_t lStatus = NO_ERROR;
    sp handle;
    effect_interface_t itfe;
    effect_descriptor_t desc;
    sp client;
    wp 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;
    }

    // AudioSystem::SESSION_OUTPUT_MIX其实就是0.
    // 介绍AudioSessionId的时候,说过如果AudioSessionid为0,则AudioEffect对整个output mix都起作用。
    // 不过需要有特殊的许可。该许可通过函数settingsAllowed来判断
    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    函数settingsAllowed的实现:
    static bool settingsAllowed() {
    #ifndef HAVE_ANDROID_OS
    return true;
    #endif
    #if AUDIOFLINGER_SECURITY_ENABLED
    if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
    bool ok = checkCallingPermission(String16("android.permission.MODIFY_AUDIO_SETTINGS"));
    if (!ok) LOGE("Request requires android.permission.MODIFY_AUDIO_SETTINGS");
    return ok;
    #else
    if (!checkCallingPermission(String16("android.permission.MODIFY_AUDIO_SETTINGS")))
    LOGW("WARNING: Need to add android.permission.MODIFY_AUDIO_SETTINGS to manifest");
    return true;
    #endif
    }
    ----------------------------------------------------------------
    // check audio settings permission for global effects
    if (sessionId == AudioSystem::SESSION_OUTPUT_MIX && !settingsAllowed()) {
    lStatus = PERMISSION_DENIED;
    goto Exit;
    }

    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    SESSION_OUTPUT_STAGE = -1, // session for effects attached to a particular output stream
    // (value must be less than 0)
    ----------------------------------------------------------------
    // 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应该由AudioPolicyManager来指定
    // output must be specified by AudioPolicyManager when using session
    // AudioSystem::SESSION_OUTPUT_STAGE
    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
    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    audio_io_handle_t AudioSystem::getOutputForEffect(effect_descriptor_t *desc)
    {
    const sp& aps = AudioSystem::get_audio_policy_service();
    if (aps == 0) return PERMISSION_DENIED;
    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    virtual audio_io_handle_t getOutputForEffect(effect_descriptor_t *desc)
    {
    Parcel data, reply;
    data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
    data.write(desc, sizeof(effect_descriptor_t));
    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    status_t BnAudioPolicyService::onTransact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
    {
    ...
    case GET_OUTPUT_FOR_EFFECT: {
    CHECK_INTERFACE(IAudioPolicyService, data, reply);
    effect_descriptor_t desc;
    data.read(&desc, sizeof(effect_descriptor_t));
    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    audio_io_handle_t AudioPolicyService::getOutputForEffect(effect_descriptor_t *desc)
    {
    if (mpPolicyManager == NULL) {
    return NO_INIT;
    }
    Mutex::Autolock _l(mLock);
    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    audio_io_handle_t AudioPolicyManagerBase::getOutputForEffect(effect_descriptor_t *desc)
    {
    LOGV("getOutputForEffect()");
    // 函数getOutput以前有看过,不过当时由于篇幅问题,未列出代码,今天列出来看看
    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    audio_io_handle_t AudioPolicyManagerBase::getOutput(AudioSystem::stream_type stream,
    uint32_t samplingRate,
    uint32_t format,
    uint32_t channels,
    AudioSystem::output_flags flags)
    {
    audio_io_handle_t output = 0;
    uint32_t latency = 0;
    // 获取策略
    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    AudioPolicyManagerBase::routing_strategy AudioPolicyManagerBase::getStrategy(
    AudioSystem::stream_type stream) {
    // stream to strategy mapping
    switch (stream) {
    case AudioSystem::VOICE_CALL:
    case AudioSystem::BLUETOOTH_SCO:
    return STRATEGY_PHONE;
    case AudioSystem::RING:
    case AudioSystem::NOTIFICATION:
    case AudioSystem::ALARM:
    case AudioSystem::ENFORCED_AUDIBLE:
    return STRATEGY_SONIFICATION;
    case AudioSystem::DTMF:
    return STRATEGY_DTMF;
    default:
    LOGE("unknown stream type");
    case AudioSystem::SYSTEM:
    // NOTE: SYSTEM stream uses MEDIA strategy because muting music and switching outputs
    // while key clicks are played produces a poor result
    case AudioSystem::TTS:
    case AudioSystem::MUSIC:
    return STRATEGY_MEDIA;
    }
    }
    ----------------------------------------------------------------
    routing_strategy strategy = getStrategy((AudioSystem::stream_type)stream);
    // 获取device
    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    uint32_t AudioPolicyManagerBase::getDeviceForStrategy(routing_strategy strategy, bool fromCache)
    {
    uint32_t device = 0;

    if (fromCache) {
    LOGV("getDeviceForStrategy() from cache strategy %d, device %x", strategy, mDeviceForStrategy[strategy]);
    // mDeviceForStrategy在以下函数中赋值
    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    void AudioPolicyManagerBase::updateDeviceForStrategy()
    {
    for (int i = 0; i < NUM_STRATEGIES; i++) {
    mDeviceForStrategy[i] = getDeviceForStrategy((routing_strategy)i, false);
    }
    }
    ----------------------------------------------------------------
    return mDeviceForStrategy[strategy];
    }

    switch (strategy) {
    case STRATEGY_DTMF:
    if (!isInCall()) {
    // when off call, DTMF strategy follows the same rules as MEDIA strategy
    device = getDeviceForStrategy(STRATEGY_MEDIA, false);
    break;
    }
    // when in call, DTMF and PHONE strategies follow the same rules
    // FALL THROUGH

    case STRATEGY_PHONE:
    // for phone strategy, we first consider the forced use and then the available devices by order
    // of priority
    switch (mForceUse[AudioSystem::FOR_COMMUNICATION]) {
    case AudioSystem::FORCE_BT_SCO:
    if (!isInCall() || strategy != STRATEGY_DTMF) {
    // 所以device的类型
    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    // output devices
    public static final int DEVICE_OUT_EARPIECE = 0x1;
    public static final int DEVICE_OUT_SPEAKER = 0x2;
    public static final int DEVICE_OUT_WIRED_HEADSET = 0x4;
    public static final int DEVICE_OUT_WIRED_HEADPHONE = 0x8;
    public static final int DEVICE_OUT_BLUETOOTH_SCO = 0x10;
    public static final int DEVICE_OUT_BLUETOOTH_SCO_HEADSET = 0x20;
    public static final int DEVICE_OUT_BLUETOOTH_SCO_CARKIT = 0x40;
    public static final int DEVICE_OUT_BLUETOOTH_A2DP = 0x80;
    public static final int DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES = 0x100;
    public static final int DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER = 0x200;
    public static final int DEVICE_OUT_AUX_DIGITAL = 0x400;
    public static final int DEVICE_OUT_WIRED_HDMI = 0x4000;
    public static final int DEVICE_OUT_DEFAULT = 0x8000;
    // input devices
    public static final int DEVICE_IN_COMMUNICATION = 0x10000;
    public static final int DEVICE_IN_AMBIENT = 0x20000;
    public static final int DEVICE_IN_BUILTIN_MIC1 = 0x40000;
    public static final int DEVICE_IN_BUILTIN_MIC2 = 0x80000;
    public static final int DEVICE_IN_MIC_ARRAY = 0x100000;
    public static final int DEVICE_IN_BLUETOOTH_SCO_HEADSET = 0x200000;
    public static final int DEVICE_IN_WIRED_HEADSET = 0x400000;
    public static final int DEVICE_IN_AUX_DIGITAL = 0x800000;
    public static final int DEVICE_IN_DEFAULT = 0x80000000;
    ----------------------------------------------------------------
    device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
    if (device) break;
    }
    device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET;
    if (device) break;
    device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO;
    if (device) break;
    // if SCO device is requested but no SCO device is available, fall back to default case
    // FALL THROUGH

    default: // FORCE_NONE
    device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE;
    if (device) break;
    device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET;
    if (device) break;
    #ifdef WITH_A2DP
    // when not in a phone call, phone strategy should route STREAM_VOICE_CALL to A2DP
    if (!isInCall()) {
    device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP;
    if (device) break;
    device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
    if (device) break;
    }
    #endif
    device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_EARPIECE;
    if (device == 0) {
    LOGE("getDeviceForStrategy() earpiece device not found");
    }
    break;

    case AudioSystem::FORCE_SPEAKER:
    if (!isInCall() || strategy != STRATEGY_DTMF) {
    device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
    if (device) break;
    }
    #ifdef WITH_A2DP
    // when not in a phone call, phone strategy should route STREAM_VOICE_CALL to
    // A2DP speaker when forcing to speaker output
    if (!isInCall()) {
    device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
    if (device) break;
    }
    #endif
    device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER;
    if (device == 0) {
    LOGE("getDeviceForStrategy() speaker device not found");
    }
    break;
    }
    break;

    case STRATEGY_SONIFICATION:

    // If incall, just select the STRATEGY_PHONE device: The rest of the behavior is handled by
    // handleIncallSonification().
    if (isInCall()) {
    device = getDeviceForStrategy(STRATEGY_PHONE, false);
    break;
    }
    device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER;
    if (device == 0) {
    LOGE("getDeviceForStrategy() speaker device not found");
    }
    // The second device used for sonification is the same as the device used by media strategy
    // FALL THROUGH

    case STRATEGY_MEDIA: {
    uint32_t device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_AUX_DIGITAL;

    if (device2 == 0) {
    device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HDMI;
    }
    if (device2 == 0) {
    device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE;
    }
    if (device2 == 0) {
    device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET;
    }
    #ifdef WITH_A2DP
    if (mA2dpOutput != 0) {
    if (strategy == STRATEGY_SONIFICATION && !a2dpUsedForSonification()) {
    break;
    }
    if (device2 == 0) {
    device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP;
    }
    if (device2 == 0) {
    device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
    }
    if (device2 == 0) {
    device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
    }
    }
    #endif
    if (device2 == 0) {
    device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER;
    }

    // device is DEVICE_OUT_SPEAKER if we come from case STRATEGY_SONIFICATION, 0 otherwise
    device |= device2;
    if (device == 0) {
    LOGE("getDeviceForStrategy() speaker device not found");
    }
    } break;

    default:
    LOGW("getDeviceForStrategy() unknown strategy: %d", strategy);
    break;
    }

    LOGV("getDeviceForStrategy() strategy %d, device %x", strategy, device);
    return device;
    }
    ----------------------------------------------------------------
    uint32_t device = getDeviceForStrategy(strategy);
    LOGV("getOutput() stream %d, samplingRate %d, format %d, channels %x, flags %x", stream, samplingRate, format, channels, flags);

    #ifdef AUDIO_POLICY_TEST
    if (mCurOutput != 0) {
    LOGV("getOutput() test output mCurOutput %d, samplingRate %d, format %d, channels %x, mDirectOutput %d",
    mCurOutput, mTestSamplingRate, mTestFormat, mTestChannels, mDirectOutput);

    if (mTestOutputs[mCurOutput] == 0) {
    LOGV("getOutput() opening test output");
    AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor();
    outputDesc->mDevice = mTestDevice;
    outputDesc->mSamplingRate = mTestSamplingRate;
    outputDesc->mFormat = mTestFormat;
    outputDesc->mChannels = mTestChannels;
    outputDesc->mLatency = mTestLatencyMs;
    outputDesc->mFlags = (AudioSystem::output_flags)(mDirectOutput ? AudioSystem::OUTPUT_FLAG_DIRECT : 0);
    outputDesc->mRefCount[stream] = 0;
    // mpClientInterface在构造函数中被赋值。
    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    AudioPolicyManagerBase::AudioPolicyManagerBase(AudioPolicyClientInterface *clientInterface)
    :
    #ifdef AUDIO_POLICY_TEST
    Thread(false),
    #endif //AUDIO_POLICY_TEST
    mPhoneState(AudioSystem::MODE_NORMAL), mRingerMode(0),
    mMusicStopTime(0), mLimitRingtoneVolume(false), mLastVoiceVolume(-1.0f),
    mTotalEffectsCpuLoad(0), mTotalEffectsMemory(0),
    mA2dpSuspended(false)
    {
    mpClientInterface = clientInterface;

    for (int i = 0; i < AudioSystem::NUM_FORCE_USE; i++) {
    mForceUse[i] = AudioSystem::FORCE_NONE;
    }

    // devices available by default are speaker, ear piece and microphone
    mAvailableOutputDevices = AudioSystem::DEVICE_OUT_EARPIECE |
    AudioSystem::DEVICE_OUT_SPEAKER;
    mAvailableInputDevices = AudioSystem::DEVICE_IN_BUILTIN_MIC;

    #ifdef WITH_A2DP
    mA2dpOutput = 0;
    mDuplicatedOutput = 0;
    mA2dpDeviceAddress = String8("");
    #endif
    mScoDeviceAddress = String8("");

    // open hardware output
    AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor();
    outputDesc->mDevice = (uint32_t)AudioSystem::DEVICE_OUT_SPEAKER;
    mHardwareOutput = mpClientInterface->openOutput(&outputDesc->mDevice,
    &outputDesc->mSamplingRate,
    &outputDesc->mFormat,
    &outputDesc->mChannels,
    &outputDesc->mLatency,
    outputDesc->mFlags);

    if (mHardwareOutput == 0) {
    LOGE("Failed to initialize hardware output stream, samplingRate: %d, format %d, channels %d",
    outputDesc->mSamplingRate, outputDesc->mFormat, outputDesc->mChannels);
    } else {
    addOutput(mHardwareOutput, outputDesc);
    setOutputDevice(mHardwareOutput, (uint32_t)AudioSystem::DEVICE_OUT_SPEAKER, true);
    //TODO: configure audio effect output stage here
    }

    updateDeviceForStrategy();
    #ifdef AUDIO_POLICY_TEST
    AudioParameter outputCmd = AudioParameter();
    outputCmd.addInt(String8("set_id"), 0);
    mpClientInterface->setParameters(mHardwareOutput, outputCmd.toString());

    mTestDevice = AudioSystem::DEVICE_OUT_SPEAKER;
    mTestSamplingRate = 44100;
    mTestFormat = AudioSystem::PCM_16_BIT;
    mTestChannels = AudioSystem::CHANNEL_OUT_STEREO;
    mTestLatencyMs = 0;
    mCurOutput = 0;
    mDirectOutput = false;
    for (int i = 0; i < NUM_TEST_OUTPUTS; i++) {
    mTestOutputs[i] = 0;
    }

    const size_t SIZE = 256;
    char buffer[SIZE];
    snprintf(buffer, SIZE, "AudioPolicyManagerTest");
    run(buffer, ANDROID_PRIORITY_AUDIO);
    #endif //AUDIO_POLICY_TEST
    }
    ----------------------------------------------------------------
    // AudioPolicyManagerBase对象在AudioPolicyService的构造函数中被创建
    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    AudioPolicyService::AudioPolicyService()
    : BnAudioPolicyService() , mpPolicyManager(NULL)
    {
    char value[PROPERTY_VALUE_MAX];

    // start tone playback thread
    mTonePlaybackThread = new AudioCommandThread(String8(""));
    // start audio commands thread
    mAudioCommandThread = new AudioCommandThread(String8("ApmCommandThread"));

    #if (defined GENERIC_AUDIO) || (defined AUDIO_POLICY_TEST)
    mpPolicyManager = new AudioPolicyManagerBase(this);
    LOGV("build for GENERIC_AUDIO - using generic audio policy");
    #else
    // if running in emulation - use the emulator driver
    if (property_get("ro.kernel.qemu", value, 0)) {
    LOGV("Running in emulation - using generic audio policy");
    mpPolicyManager = new AudioPolicyManagerBase(this);
    }
    else {
    LOGV("Using hardware specific audio policy");
    // 我们用到的肯定是这儿的
    // 函数createAudioPolicyManager的实现都在hardware中
    // 我们使用到的是alsa中的
    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    extern "C" AudioPolicyInterface* createAudioPolicyManager(AudioPolicyClientInterface *clientInterface)
    {
    // AudioPolicyManagerALSA的构造函数中没作什么特殊处理
    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    // Nothing currently different between the Base implementation.
    // 注释说它和base没什么差别
    // getOutput函数中调用的openOutput接口,应该是在AudioPolicyService中实现的了

    AudioPolicyManagerALSA::AudioPolicyManagerALSA(AudioPolicyClientInterface *clientInterface)
    : AudioPolicyManagerBase(clientInterface)
    {
    }
    ----------------------------------------------------------------
    return new AudioPolicyManagerALSA(clientInterface);
    }
    ----------------------------------------------------------------
    mpPolicyManager = createAudioPolicyManager(this);
    }
    #endif

    // load properties
    property_get("ro.camera.sound.forced", value, "0");
    mpPolicyManager->setSystemProperty("ro.camera.sound.forced", value);
    }
    ----------------------------------------------------------------
    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    audio_io_handle_t AudioPolicyService::openOutput(uint32_t *pDevices,
    uint32_t *pSamplingRate,
    uint32_t *pFormat,
    uint32_t *pChannels,
    uint32_t *pLatencyMs,
    AudioSystem::output_flags flags)
    {
    sp af = AudioSystem::get_audio_flinger();
    if (af == 0) {
    LOGW("openOutput() could not get AudioFlinger");
    return 0;
    }

    // 又调到了audioflinger中
    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    int AudioFlinger::openOutput(uint32_t *pDevices,
    uint32_t *pSamplingRate,
    uint32_t *pFormat,
    uint32_t *pChannels,
    uint32_t *pLatencyMs,
    uint32_t flags)
    {
    status_t status;
    PlaybackThread *thread = NULL;
    mHardwareStatus = AUDIO_HW_OUTPUT_OPEN;
    uint32_t samplingRate = pSamplingRate ? *pSamplingRate : 0;
    uint32_t format = pFormat ? *pFormat : 0;
    uint32_t channels = pChannels ? *pChannels : 0;
    uint32_t latency = pLatencyMs ? *pLatencyMs : 0;

    LOGV("openOutput(), Device %x, SamplingRate %d, Format %d, Channels %x, flags %x",
    pDevices ? *pDevices : 0,
    samplingRate,
    format,
    channels,
    flags);

    if (pDevices == NULL || *pDevices == 0) {
    return 0;
    }
    Mutex::Autolock _l(mLock);

    // 又调到了HAL层的openOutputStream函数
    AudioStreamOut *output = mAudioHardware->openOutputStream(*pDevices,
    (int *)&format,
    &channels,
    &samplingRate,
    &status);
    LOGV("openOutput() openOutputStream returned output %p, SamplingRate %d, Format %d, Channels %x, status %d",
    output,
    samplingRate,
    format,
    channels,
    status);

    mHardwareStatus = AUDIO_HW_IDLE;
    if (output != 0) {
    int id = nextUniqueId();
    if ((flags & AudioSystem::OUTPUT_FLAG_DIRECT) ||
    (format != AudioSystem::PCM_16_BIT) ||
    (channels != AudioSystem::CHANNEL_OUT_STEREO)) {
    thread = new DirectOutputThread(this, output, id, *pDevices);
    LOGV("openOutput() created direct output: ID %d thread %p", id, thread);
    } else {
    thread = new MixerThread(this, output, id, *pDevices);
    LOGV("openOutput() created mixer output: ID %d thread %p", id, thread);

    #ifdef LVMX
    unsigned bitsPerSample =
    (format == AudioSystem::PCM_16_BIT) ? 16 :
    ((format == AudioSystem::PCM_8_BIT) ? 8 : 0);
    unsigned channelCount = (channels == AudioSystem::CHANNEL_OUT_STEREO) ? 2 : 1;
    int audioOutputType = LifeVibes::threadIdToAudioOutputType(thread->id());

    LifeVibes::init_aot(audioOutputType, samplingRate, bitsPerSample, channelCount);
    LifeVibes::setDevice(audioOutputType, *pDevices);
    #endif

    }
    mPlaybackThreads.add(id, thread);

    if (pSamplingRate) *pSamplingRate = samplingRate;
    if (pFormat) *pFormat = format;
    if (pChannels) *pChannels = channels;
    if (pLatencyMs) *pLatencyMs = thread->latency();

    // notify client processes of the new output creation
    thread->audioConfigChanged_l(AudioSystem::OUTPUT_OPENED);
    return id;
    }

    return 0;
    }
    ----------------------------------------------------------------
    return af->openOutput(pDevices,
    pSamplingRate,
    (uint32_t *)pFormat,
    pChannels,
    pLatencyMs,
    flags);
    }
    ----------------------------------------------------------------
    mTestOutputs[mCurOutput] = mpClientInterface->openOutput(&outputDesc->mDevice,
    &outputDesc->mSamplingRate,
    &outputDesc->mFormat,
    &outputDesc->mChannels,
    &outputDesc->mLatency,
    outputDesc->mFlags);
    if (mTestOutputs[mCurOutput]) {
    AudioParameter outputCmd = AudioParameter();
    outputCmd.addInt(String8("set_id"),mCurOutput);
    mpClientInterface->setParameters(mTestOutputs[mCurOutput],outputCmd.toString());
    addOutput(mTestOutputs[mCurOutput], outputDesc);
    }
    }
    return mTestOutputs[mCurOutput];
    }
    #endif //AUDIO_POLICY_TEST

    // open a direct output if required by specified parameters
    if (needsDirectOuput(stream, samplingRate, format, channels, flags, device)) {

    LOGV("getOutput() opening direct output device %x", device);
    AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor();
    outputDesc->mDevice = device;
    outputDesc->mSamplingRate = samplingRate;
    outputDesc->mFormat = format;
    outputDesc->mChannels = channels;
    outputDesc->mLatency = 0;
    outputDesc->mFlags = (AudioSystem::output_flags)(flags | AudioSystem::OUTPUT_FLAG_DIRECT);
    outputDesc->mRefCount[stream] = 0;
    output = mpClientInterface->openOutput(&outputDesc->mDevice,
    &outputDesc->mSamplingRate,
    &outputDesc->mFormat,
    &outputDesc->mChannels,
    &outputDesc->mLatency,
    outputDesc->mFlags);

    // only accept an output with the requeted parameters
    if (output == 0 ||
    (samplingRate != 0 && samplingRate != outputDesc->mSamplingRate) ||
    (format != 0 && format != outputDesc->mFormat) ||
    (channels != 0 && channels != outputDesc->mChannels)) {
    LOGV("getOutput() failed opening direct output: samplingRate %d, format %d, channels %d",
    samplingRate, format, channels);
    if (output != 0) {
    mpClientInterface->closeOutput(output);
    }
    delete outputDesc;
    return 0;
    }
    addOutput(output, outputDesc);
    return output;
    }

    if (channels != 0 && channels != AudioSystem::CHANNEL_OUT_MONO &&
    channels != AudioSystem::CHANNEL_OUT_STEREO) {
    return 0;
    }
    // open a non direct output

    // get which output is suitable for the specified stream. The actual routing change will happen
    // when startOutput() will be called
    uint32_t a2dpDevice = device & AudioSystem::DEVICE_OUT_ALL_A2DP;
    if (AudioSystem::popCount((AudioSystem::audio_devices)device) == 2) {
    #ifdef WITH_A2DP
    if (a2dpUsedForSonification() && a2dpDevice != 0) {
    // if playing on 2 devices among which one is A2DP, use duplicated output
    LOGV("getOutput() using duplicated output");
    LOGW_IF((mA2dpOutput == 0), "getOutput() A2DP device in multiple %x selected but A2DP output not opened", device);
    output = mDuplicatedOutput;
    } else
    #endif
    {
    // if playing on 2 devices among which none is A2DP, use hardware output
    output = mHardwareOutput;
    }
    LOGV("getOutput() using output %d for 2 devices %x", output, device);
    } else {
    #ifdef WITH_A2DP
    if (a2dpDevice != 0) {
    // if playing on A2DP device, use a2dp output
    LOGW_IF((mA2dpOutput == 0), "getOutput() A2DP device %x selected but A2DP output not opened", device);
    output = mA2dpOutput;
    } else
    #endif
    {
    // if playing on not A2DP device, use hardware output
    output = mHardwareOutput;
    }
    }


    LOGW_IF((output ==0), "getOutput() could not find output for stream %d, samplingRate %d, format %d, channels %x, flags %x",
    stream, samplingRate, format, channels, flags);

    return output;
    }
    ----------------------------------------------------------------
    // apply simple rule where global effects are attached to the same output as MUSIC streams
    return getOutput(AudioSystem::MUSIC);
    }
    原来到最后只是获取了MUSIC的output。
    ----------------------------------------------------------------
    return mpPolicyManager->getOutputForEffect(desc);
    }
    ----------------------------------------------------------------
    audio_io_handle_t output = getOutputForEffect(&desc);
    reply->writeInt32(static_cast (output));
    return NO_ERROR;
    } break;
    ...
    }
    ----------------------------------------------------------------
    remote()->transact(GET_OUTPUT_FOR_EFFECT, data, &reply);
    return static_cast (reply.readInt32());
    }
    ----------------------------------------------------------------
    return aps->getOutputForEffect(desc);
    }
    ----------------------------------------------------------------
    output = AudioSystem::getOutputForEffect(&desc);
    }
    }

    {
    Mutex::Autolock _l(mLock);


    if (!EffectIsNullUuid(&pDesc->uuid)) {
    // if uuid is specified, request effect descriptor
    lStatus = EffectGetDescriptor(&pDesc->uuid, &desc);
    if (lStatus < 0) {
    LOGW("createEffect() error %d from EffectGetDescriptor", lStatus);
    goto Exit;
    }
    } else {
    // if uuid is not specified, look for an available implementation
    // of the required type in effect factory
    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;

    // 得到Effect的个数
    lStatus = EffectQueryNumberEffects(&numEffects);
    if (lStatus < 0) {
    LOGW("createEffect() error %d from EffectQueryNumberEffects", lStatus);
    goto Exit;
    }
    // 寻找匹配的effect
    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
    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)
    if (sessionId == AudioSystem::SESSION_OUTPUT_MIX &&
    (d.flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_AUXILIARY) {
    memcpy(&desc, &d, sizeof(effect_descriptor_t));
    }
    }

    // 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.
    // If output is 0 here, sessionId is neither SESSION_OUTPUT_STAGE nor SESSION_OUTPUT_MIX
    // because of code checking output when entering the function.
    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;
    }
    }
    // 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
    if (output == 0 && mPlaybackThreads.size()) {
    output = mPlaybackThreads.keyAt(0);
    }
    }
    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);
    }

    // 在函数AudioEffect::Set函数中创建的EffectClient对象(effectClient),在此处并未作太多处理,而是直接传给了函数thread->createEffect_l
    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    // PlaybackThread::createEffect_l() must be called with AudioFlinger::mLock held
    sp AudioFlinger::PlaybackThread::createEffect_l(
    const sp& client,
    const sp& effectClient,
    int32_t priority,
    int sessionId,
    effect_descriptor_t *desc,
    int *enabled,
    status_t *status
    )
    {
    sp effect;
    sp handle;
    status_t lStatus;
    sp track;
    sp 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);

    // 先看是否存在指定session的effect链,如果不存在,创建一个
    // 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);
    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());

    // 是否存在相同描述的effect,不存在的话,创建一个
    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;

    effect->setDevice(mDevice);
    effect->setMode(mAudioFlinger->getMode());
    }
    // 看看下面EffectHandle的注释,便于理解
    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    // The EffectHandle class implements the IEffect interface. It provides resources
    // to receive parameter updates, keeps track of effect control
    // ownership and state and has a pointer to the EffectModule object it is controlling.
    // There is one EffectHandle object for each application controlling (or using)
    // an effect module.
    // The EffectHandle is obtained by calling AudioFlinger::createEffect().
    ----------------------------------------------------------------
    // 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;
    }
    ----------------------------------------------------------------
    // 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();
    }
    }

    Exit:
    if(status) {
    *status = lStatus;
    }
    return handle;
    }
    ----------------------------------------------------------------
    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;
    }

    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(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;
    }
    ----------------------------------------------------------------
    mStatus = set(pType, pUuid, priority, cbf, user, sessionId, output);
    }
    ----------------------------------------------------------------
    // 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;
    }

    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;
    }
    ----------------------------------------------------------------
    int initResult = native_setup(new WeakReference(this),
    type.toString(), uuid.toString(), priority, audioSession, id,
    desc);
    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;
    }
    }
    ###############################################################################################

    &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&总结&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
    每一个session id都对应一个effect链表。
    创建effect时,会首先检查指定session id的effect链表是否存在,不存在的话创建一个。
    然后看链表中相同描述的effect是否存在,不存在的话,创建一个。
    但没个应用程序都拥有一个自己的EffectHandle。
    &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

    你可能感兴趣的:(Android Audio代码分析6 - AudioEffect)