天天看點

android volume設定 代碼分析volume設定,跳過binder部分(binder請獨立了解) 一、JNI部分二、audiosystem 三、audiopolicyservice四、五、audiopolicymanager六、audiopolicyservice七、audiosystem八、audioflinger調用過程詳細分析:疑點1、mpAudioPolicy調用的是audio_policy_hal.cpp中的方法分析:

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 <audio_stream_type_t>(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<IAudioPolicyService>& 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<IAudioFlinger>& 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"

<p>int hw_get_module(const char *id, const struct hw_module_t **module)</p><p>上面函數調用Hardware.c--------audio/hardware/libhardware/</p><p>
</p>
           

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,還在這個檔案内;

<pre name="code" class="cpp">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<HAL_VARIANT_KEYS_COUNT+1 ; i++) {
        if (i < HAL_VARIANT_KEYS_COUNT) {
            if (property_get(variant_keys[i], prop, NULL) == 0) {
                continue;
            }
            snprintf(path, sizeof(path), "%s/%s.%s.so",
                     HAL_LIBRARY_PATH2, name, prop);
            if (access(path, R_OK) == 0) break;

            snprintf(path, sizeof(path), "%s/%s.%s.so",
                     HAL_LIBRARY_PATH1, name, prop);
            if (access(path, R_OK) == 0) break;
        } else {
            snprintf(path, sizeof(path), "%s/%s.default.so",
                     HAL_LIBRARY_PATH2, name);
            if (access(path, R_OK) == 0) break;

            snprintf(path, sizeof(path), "%s/%s.default.so",
                     HAL_LIBRARY_PATH1, name);//#define HAL_LIBRARY_PATH1 "/system/lib/hw"
                                              //将"/system/lib/hw/audio_policy.default.so"拷貝到path中
            if (access(path, R_OK) == 0) break;//判斷是否是可讀檔案,至此,已經确定加載audio_policy.default.so檔案,下面的load将完成加載</u>
        }
    }

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

未完。。。。。。。。。。。。我還會回來的。。。。。。。。。。。。。。。。。