捋一捋代码流程:
上层流程之前有分析过,可以参考这个:
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决定了,通话声音无法调到最小。。。至于为什么这么做,还是没有答案啊!!!