(没有最终结论)Android 为何无法将通话音量调到最低

捋一捋代码流程:

上层流程之前有分析过,可以参考这个:

https://blog.csdn.net/bberdong/article/details/51792319(抱歉,那时候写的太随意)

咱们就从AudioPolicyManager::checkAndSetVolume说起:

status_t AudioPolicyManager::checkAndSetVolume(
    audio_stream_type_t stream,
    int index,
    const sp<AudioOutputDescriptor>& outputDesc,
    audio_devices_t device,
    int delayMs,
    bool force)
{
    ...
        if (stream == AUDIO_STREAM_VOICE_CALL ||
        stream == AUDIO_STREAM_BLUETOOTH_SCO) {
        float voiceVolume;
        // Force voice volume to max for bluetooth SCO as volume is managed by the headset
        if (stream == AUDIO_STREAM_VOICE_CALL) {
            voiceVolume = (float)index/(float)mVolumeCurves->getVolumeIndexMax(stream);
        } else {
            voiceVolume = 1.0;
        }
​
        if (voiceVolume != mLastVoiceVolume) {
            mpClientInterface->setVoiceVolume(voiceVolume, delayMs);
            mLastVoiceVolume = voiceVolume;
        }
    }
    ...
}

一般通话音量按照index/最大index来算,getVolumeIndexMax来自哪里?

//AudioService.java
public class VolumeStreamState {
    private VolumeStreamState(String settingName, int streamType) {
        mIndexMin = MIN_STREAM_VOLUME[streamType] * 10;
            mIndexMax = MAX_STREAM_VOLUME[streamType] * 10;
            AudioSystem.initStreamVolume(streamType, mIndexMin / 10, mIndexMax / 10);
    }
}

MAX_STREAM_VOLUME[STREAM_VOICE_CALL]按照100来算好了。

mIndexMax等于1000.则这次调用相当于

AudioSystem.initStreamVolume(0,0,100)

一路略过,就来到了:

void AudioPolicyManager::initStreamVolume(audio_stream_type_t stream,
                                            int indexMin,
                                            int indexMax)
{
    ...
    mVolumeCurves->initStreamVolume(stream, indexMin, indexMax);
    ...
}

回到前面

AUDIO_STREAM_VOICE_CALL则voiceVolume = index/100

AUDIO_STREAM_BLUETOOTH_SCO则voiceVolume = 1.0.

那看上去这个voiceVolume就是一个系数。

我们接着追踪setVoiceVolume的调用,一路略过,来到了

//audio_hw.c
static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)                          
{
    int ret;
    struct audio_device *adev = (struct audio_device *)dev;
    pthread_mutex_lock(&adev->lock);
    /* cache volume */
    ret = voice_set_volume(adev, volume);
    pthread_mutex_unlock(&adev->lock);
    return ret;
}
​

voice_set_volume的实现在这里(原谅我是搜索出来的,结果推原因)

//voice.c
int voice_set_volume(struct audio_device *adev, float volume)
{
    //我们在探讨音量无法调到最小,所以这里volume姑且算0
    int vol, err = 0;
​
    adev->voice.volume = volume;
    if (adev->mode == AUDIO_MODE_IN_CALL) {
        if (volume < 0.0) {
            volume = 0.0;
        } else if (volume > 1.0) {
            volume = 1.0;
        }
​
        vol = lrint(volume * 100.0);
​
        // Voice volume levels from android are mapped to driver volume levels as follows.
        // 0 -> 5, 20 -> 4, 40 ->3, 60 -> 2, 80 -> 1, 100 -> 0
        // So adjust the volume to get the correct volume index in driver
        vol = 100 - vol;
​
        err = platform_set_voice_volume(adev->platform, vol);
    }
    //这个应该是voip通话?好像微信语音就走这个
    if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
        err = voice_extn_compress_voip_set_volume(adev, volume);
​
​
    return err;
}

到这里调用变成:

platform_set_voice_volume(adev->platform,100);

接着看代码:

int platform_set_voice_volume(void *platform, int volume)
{
    struct platform_data *my_data = (struct platform_data *)platform;
    struct audio_device *adev = my_data->adev;
    struct mixer_ctl *ctl;
    const char *mixer_ctl_name = "Voice Rx Gain";
    int vol_index = 0, ret = 0;
    uint32_t set_values[ ] = {0,
                              ALL_SESSION_VSID,
                              DEFAULT_VOLUME_RAMP_DURATION_MS};
​
    // Voice volume levels are mapped to adsp volume levels as follows.
    // 100 -> 5, 80 -> 4, 60 -> 3, 40 -> 2, 20 -> 1  0 -> 0
    // But this values don't changed in kernel. So, below change is need.
    //percent_to_index返回结果范围,从0到5
    vol_index = (int)percent_to_index(volume, MIN_VOL_INDEX, MAX_VOL_INDEX);
    set_values[0] = vol_index;
​
    ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
    if (!ctl) {
        ALOGE("%s: Could not get ctl for mixer cmd - %s",
              __func__, mixer_ctl_name);
        return -EINVAL;
    }
    ALOGV("Setting voice volume index: %d", set_values[0]);
    mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));                                                                                                            
​
    if (my_data->csd != NULL) {
        ret = my_data->csd->volume(ALL_SESSION_VSID, volume,
                                   DEFAULT_VOLUME_RAMP_DURATION_MS);
        if (ret < 0) {
            ALOGE("%s: csd_volume error %d", __func__, ret);
        }
    }
    return ret;
}

vol_index的变化范围从0-5.(0是最大值...),接下来调用的就是tinymix的接口了。再往下,恐怕。。。

只能说kernel层,adsp决定了,通话声音无法调到最小。。。至于为什么这么做,还是没有答案啊!!!

猜你喜欢

转载自blog.csdn.net/bberdong/article/details/83068688