android volume设置 代码分析

volume设置,跳过binder部分(binder请独立理解)

没有采用深度优先的方法,容易绕来绕去,就不知道再看什么了。

采用不断透调的方法讲解,一步一步从上层直逼底层,从整体上了解音量设置过程。

透调中有点难度的调用最后讲解。

一、JNI部分

android_media_AudioSystem.cpp-----framework/base/core/jni/

android_media_AudioSystem_setStreamVolumeIndex(JNIEnv *env,
                                               jobject thiz,
                                               jint stream,
                                               jint index,
                                               jint device)
{
    return check_AudioSystem_Command(
            AudioSystem::setStreamVolumeIndex(static_cast (stream),
                                              index,
                                              (audio_devices_t)device));
}
对于函数的行惨,不必过多考虑,是上层java传给的。

关键的参数:

index:音量值;

device:如下列举了一笑部分

enum{
    AUDIO_DEVICE_NONE                          = 0x0,
    /* reserved bits */
    AUDIO_DEVICE_BIT_IN                        = 0x80000000,
    AUDIO_DEVICE_BIT_DEFAULT                   = 0x40000000,
    /* output devices */
    AUDIO_DEVICE_OUT_EARPIECE                  = 0x1,
    AUDIO_DEVICE_OUT_SPEAKER                   = 0x2,
    AUDIO_DEVICE_OUT_WIRED_HEADSET             = 0x4,
    AUDIO_DEVICE_OUT_WIRED_HEADPHONE           = 0x8,
    AUDIO_DEVICE_OUT_BLUETOOTH_SCO             = 0x10,
    AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET     = 0x20,
    。。。
}


stream:

 /* The audio stream for phone calls */
    public static final int STREAM_VOICE_CALL = 0;
    /* The audio stream for system sounds */
    public static final int STREAM_SYSTEM = 1;
    /* The audio stream for the phone ring and message alerts */
    public static final int STREAM_RING = 2;
    /* The audio stream for music playback */
    public static final int STREAM_MUSIC = 3;
    /* The audio stream for alarms */
    public static final int STREAM_ALARM = 4;
    /* The audio stream for notifications */
    public static final int STREAM_NOTIFICATION = 5;
    /* @hide The audio stream for phone calls when connected on bluetooth */
    public static final int STREAM_BLUETOOTH_SCO = 6;
    /* @hide The audio stream for enforced system sounds in certain countries (e.g camera in Japan) */
    public static final int STREAM_SYSTEM_ENFORCED = 7;
    /* @hide The audio stream for DTMF tones */
    public static final int STREAM_DTMF = 8;

看到函数内部,调用的仕audiosystem的setStreamVolumeIndex函数,进到audiosystem

二、audiosystem

AudioSystem.cpp-----framework/av/media/libmedia/

status_t AudioSystem::setStreamVolumeIndex(audio_stream_type_t stream,
                                           int index,
                                           audio_devices_t device)
{
    const sp& aps = AudioSystem::get_audio_policy_service();
    if (aps == 0) return PERMISSION_DENIED;
    return aps->setStreamVolumeIndex(stream, index, device);
}

这里采用了binder机制,直接无视它!知道是一种调用方式就可以。

看到函数调用了audiopolicyservice里的函数setStreamVolumeIndex;

三、audiopolicyservice

AudioPolicyService.cpp-----framework/av/media/services/audioflinger

status_t AudioPolicyService::setStreamVolumeIndex(audio_stream_type_t stream,
                                                  int index,
                                                  audio_devices_t device)
{
    if (mpAudioPolicy == NULL) {
        return NO_INIT;
    }
    if (!settingsAllowed()) {
        return PERMISSION_DENIED;
    }
    if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
        return BAD_VALUE;
    }
    Mutex::Autolock _l(mLock);
    if (mpAudioPolicy->set_stream_volume_index_for_device) {
        return mpAudioPolicy->set_stream_volume_index_for_device(mpAudioPolicy,
                                                                stream,
                                                                index,
                                                                device);
    } else {
        return mpAudioPolicy->set_stream_volume_index(mpAudioPolicy, stream, index);
    }
}

函数内部,调用了
mpAudioPolicy->set_stream_volume_index_for_device
这里mpAudioPolicy后面讲解, 疑点1,这里它调用的是 audio_policy_hal.cpp中的方法;

四、

audio_policy_hal.cpp----system/core/libcutils/

static int ap_set_stream_volume_index(struct audio_policy *pol,
                                      audio_stream_type_t stream,
                                      int index)
{
    struct legacy_audio_policy *lap = to_lap(pol);
    return lap->apm->setStreamVolumeIndex((AudioSystem::stream_type)stream,
                                          index,
                                          AUDIO_DEVICE_OUT_DEFAULT);
}

五、audiopolicymanager

audiopolicymanagerbase.c----hardware/libhardware_legacy/audio

看到四中的apm就猜到调用的仕audiopolicymanagerbase中的函数,(疑点2),进入audiopolicymanagerbase.c中的函数

status_t AudioPolicyManagerBase::setStreamVolumeIndex(AudioSystem::stream_type stream,
                                                      int index,
                                                      audio_devices_t device)
{

    if ((index < mStreams[stream].mIndexMin) || (index > mStreams[stream].mIndexMax)) {
        return BAD_VALUE;
    }
    if (!audio_is_output_device(device)) {
        return BAD_VALUE;
    }

    // Force max volume if stream cannot be muted
    if (!mStreams[stream].mCanBeMuted) index = mStreams[stream].mIndexMax;

    ALOGV("setStreamVolumeIndex() stream %d, device %04x, index %d",
          stream, device, index);

    // if device is AUDIO_DEVICE_OUT_DEFAULT set default value and
    // clear all device specific values
    if (device == AUDIO_DEVICE_OUT_DEFAULT) {
        mStreams[stream].mIndexCur.clear();
    }
    mStreams[stream].mIndexCur.add(device, index);

    // compute and apply stream volume on all outputs according to connected device
    status_t status = NO_ERROR;
    for (size_t i = 0; i < mOutputs.size(); i++) {
        audio_devices_t curDevice =
                getDeviceForVolume(mOutputs.valueAt(i)->device());
        if ((device == AUDIO_DEVICE_OUT_DEFAULT) || (device == curDevice)||
               status_t volStatus = checkAndSetVolume(stream, index, mOutputs.keyAt(i), curDevice);
            if (volStatus != NO_ERROR) {
                status = volStatus;
            }
        }
    }
    return status;
}
调用到函数checkAndSetVolume函数:

status_t AudioPolicyManagerBase::checkAndSetVolume(int stream,
                                                   int index,
                                                   audio_io_handle_t output,
                                                   audio_devices_t device,
                                                   int delayMs,
                                                   bool force)
{
       。。。。
        if (voiceVolume != mLastVoiceVolume && output == mPrimaryOutput) {
            mpClientInterface->setVoiceVolume(voiceVolume, delayMs);
            mLastVoiceVolume = voiceVolume;
        }
    }

    return NO_ERROR;
}
里面的mpClientInterface->setVoiceVolume,mpClientnterface实际上是audiopolicyservice,

即调用的是audioPolicyService->setStreamVolume

六、audiopolicyservice

audiopolicyservice.cpp---frameworks/av/services/audioflinger

int AudioPolicyService::setStreamVolume(audio_stream_type_t stream,
                                        float volume,
                                        audio_io_handle_t output,
                                        int delayMs)
{
    return (int)mAudioCommandThread->volumeCommand(stream, volume,
                                                   output, delayMs);
}

volumeCommand函数也在这个文件内

status_t AudioPolicyService::AudioCommandThread::volumeCommand(audio_stream_type_t stream,
                                                               float volume,
                                                               audio_io_handle_t output,
                                                               int delayMs)
{
    status_t status = NO_ERROR;

    AudioCommand *command = new AudioCommand();
    command->mCommand = SET_VOLUME;
    VolumeData *data = new VolumeData();
    data->mStream = stream;
    data->mVolume = volume;
    data->mIO = output;
    command->mParam = data;
    Mutex::Autolock _l(mLock);

    insertCommand_l(command, delayMs);
   
    mWaitWorkCV.signal();
    if (command->mWaitStatus) {
        command->mCond.wait(mLock);
        status =  command->mStatus;
        command->mCond.signal();
       
        delete command;
    }
    return status;
}

insertCommand_l(command, delayMs);
加入线程队列中,即threadLoop中;

bool AudioPolicyService::AudioCommandThread::threadLoop()
{
    nsecs_t waitTime = INT64_MAX;

    mLock.lock();
    while (!exitPending())
    {
        while (!mAudioCommands.isEmpty()) {
            nsecs_t curTime = systemTime();
            if (mAudioCommands[0]->mTime <= curTime) {
                AudioCommand *command = mAudioCommands[0];
                mAudioCommands.removeAt(0);
                mLastCommand = *command;
                // SPRD: Delete command after waiting was end
                bool deleteAudioCommand = true;

                switch (command->mCommand) {
                。。。。

                case SET_VOLUME: {
                    VolumeData *data = (VolumeData *)command->mParam;
                    ALOGV("AudioCommandThread() processing set volume stream %d, \
                            volume %f, output %d", data->mStream, data->mVolume, data->mIO);
                    command->mStatus = AudioSystem::setStreamVolume(data->mStream,
                                                                    data->mVolume,
                                                                    data->mIO);
                    if (command->mWaitStatus) {
                        // SPRD: Delete command after waiting was end
                        deleteAudioCommand = false;
                        command->mCond.signal();
                        command->mCond.waitRelative(mLock, kAudioCommandTimeout);
                    }
                    delete data;
                    }break;
               。。。。。
    mLock.unlock();
    return false;
}

调到啊udiosystem的函数

七、audiosystem

audiosystem.c---frameworks/av/media/libmedia

status_t AudioSystem::setStreamVolume(audio_stream_type_t stream, float value,
        audio_io_handle_t output)
{
    if (uint32_t(stream) >= AUDIO_STREAM_CNT) return BAD_VALUE;
    const sp& af = AudioSystem::get_audio_flinger();
    if (af == 0) return PERMISSION_DENIED;
    af->setStreamVolume(stream, value, output);
    return NO_ERROR;
}
通过binder通信,调用audioflinger里的setStreamVolume

八、audioflinger




----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

调用过程详细分析:

疑点1、mpAudioPolicy调用的是audio_policy_hal.cpp中的方法分析:

函数内部,使用mpAudioPolicy的方法,这就需要看下audiopolicyservice的构造函数;

AudioPolicyService::AudioPolicyService()
    : BnAudioPolicyService() , mpAudioPolicyDev(NULL) , mpAudioPolicy(NULL)
{
    char value[PROPERTY_VALUE_MAX];
    const struct hw_module_t *module;
    int forced_val;
    int rc;

    Mutex::Autolock _l(mLock);

    // start tone playback thread
    mTonePlaybackThread = new AudioCommandThread(String8("ApmTone"), this);
    // start audio commands thread
    mAudioCommandThread = new AudioCommandThread(String8("ApmAudio"), this);
    // start output activity command thread
    mOutputCommandThread = new AudioCommandThread(String8("ApmOutput"), this);
    /* instantiate the audio policy manager */
    rc = hw_get_module(AUDIO_POLICY_HARDWARE_MODULE_ID, &module);//1.1分析
    if (rc)
        return;

    rc = audio_policy_dev_open(module, &mpAudioPolicyDev);//1.2分析
    ALOGE_IF(rc, "couldn't open audio policy device (%s)", strerror(-rc));
    if (rc)
        return;

    rc = mpAudioPolicyDev->create_audio_policy(mpAudioPolicyDev, &aps_ops, this,
                                               &mpAudioPolicy);//1.3分析
    ALOGE_IF(rc, "couldn't create audio policy (%s)", strerror(-rc));
    if (rc)
        return;

    rc = mpAudioPolicy->init_check(mpAudioPolicy);
    ALOGE_IF(rc, "couldn't init_check the audio policy (%s)", strerror(-rc));
    if (rc)
        return;

    /* SPRD: maybe set this property better, but here just change the default value @{ */
    property_get("ro.camera.sound.forced", value, "1");
    forced_val = strtol(value, NULL, 0);
    ALOGV("setForceUse() !forced_val=%d ",!forced_val);
    mpAudioPolicy->set_can_mute_enforced_audible(mpAudioPolicy, !forced_val);
    /* @} */

    ALOGI("Loaded audio policy from %s (%s)", module->name, module->id);

    // load audio pre processing modules
    if (access(AUDIO_EFFECT_VENDOR_CONFIG_FILE, R_OK) == 0) {
        loadPreProcessorConfig(AUDIO_EFFECT_VENDOR_CONFIG_FILE);
    } else if (access(AUDIO_EFFECT_DEFAULT_CONFIG_FILE, R_OK) == 0) {
        loadPreProcessorConfig(AUDIO_EFFECT_DEFAULT_CONFIG_FILE);
    }
}

1.1分析hw_get_module(AUDIO_POLICY_HARDWARE_MODULE_ID, &module);

其中,#define AUDIO_POLICY_HARDWARE_MODULE_ID "audio_policy"

int hw_get_module(const char *id, const struct hw_module_t **module)

上面函数调用Hardware.c--------audio/hardware/libhardware/

int hw_get_module(const char *id, const struct hw_module_t **module){ return hw_get_module_by_class(id, NULL, module);}又调用hw_get_module_by_class,还在这个文件内;

int hw_get_module_by_class(const char *class_id, const char *inst,
                           const struct hw_module_t **module)//class_id保存"audio_policy",inst为NULL
{
    int status;
    int i;
    const struct hw_module_t *hmi = NULL;
    char prop[PATH_MAX];
    char path[PATH_MAX];
    char name[PATH_MAX];

    if (inst)//inst=NULL,走else
        snprintf(name, PATH_MAX, "%s.%s", class_id, inst);
    else
        strlcpy(name, class_id, PATH_MAX);//将"audio_policy"拷贝到name中;

    /*
     * Here we rely on the fact that calling dlopen multiple times on
     * the same .so will simply increment a refcount (and not load
     * a new copy of the library).
     * We also assume that dlopen() is thread-safe.
     */

    /* Loop through the configuration variants looking for a module */
    for (i=0 ; i
        }
    }

    status = -ENOENT;
    if (i < HAL_VARIANT_KEYS_COUNT+1) {
        /* load the module, if this fails, we're doomed, and we should not try
         * to load a different variant. */
        status = load(class_id, path, module);//定义的load函数,下面分析
    }

    return status;
}
这个函数,需要高清几个函数的使用:property_get,snprintf,access;dlopen,dlsym。这几个函数会在另外一篇文章中讲解。
/**
 * Load the file defined by the variant and if successful
 * return the dlopen handle and the hmi.
 * @return 0 = success, !0 = failure.
 */
static int load(const char *id,
        const char *path,
        const struct hw_module_t **pHmi)
{
    int status;
    void *handle;
    struct hw_module_t *hmi;

    /*
     * load the symbols resolving undefined symbols before
     * dlopen returns. Since RTLD_GLOBAL is not or'd in with
     * RTLD_NOW the external symbols will not be global
     */
    handle = dlopen(path, RTLD_NOW);//打开指定的 文件,即audio_policy.default.so
    if (handle == NULL) {
        char const *err_str = dlerror();
        ALOGE("load: module=%s\n%s", path, err_str?err_str:"unknown");
        status = -EINVAL;
        goto done;
    }

    /* Get the address of the struct hal_module_info. */
    const char *sym = HAL_MODULE_INFO_SYM_AS_STR;//#define HAL_MODULE_INFO_SYM_AS_STR  "HMI"
    hmi = (struct hw_module_t *)dlsym(handle, sym);//根据动态链接库操作句柄与符号,返回符号对应的地址保存给hmi
    if (hmi == NULL) {
        ALOGE("load: couldn't find symbol %s", sym);
        status = -EINVAL;
        goto done;
    }

    /* Check that the id matches */
    if (strcmp(id, hmi->id) != 0) {
        ALOGE("load: id=%s != hmi->id=%s", id, hmi->id);
        status = -EINVAL;
        goto done;
    }

    hmi->dso = handle;

    /* success */
    status = 0;

    done:
    if (status != 0) {
        hmi = NULL;
        if (handle != NULL) {
            dlclose(handle);
            handle = NULL;
        }
    } else {
        ALOGV("loaded HAL id=%s path=%s hmi=%p handle=%p",
                id, path, *pHmi, handle);
    }

    *pHmi = hmi;//将地址赋值给形参。至此,整个动态库so的加载完成,并将地址返回

    return status;
}
未完。。。。。。。。。。。。我还会回来的。。。。。。。。。。。。。。。。。




你可能感兴趣的:(android)