问题现象
MTK平台某项目,在voice最大音量通话时,从免提切换到耳机模式后,通话音量变小,此时通过音量键减小一格音量后,通话音量又变大;
根因分析
问题原因:
通话模式从免提切换到耳机模式后,由于MTK上层会设置一个AUDIO_DEVICE_OUT_TELEPHONY_TX 设备的音量,而该设备无对应gaindevice,导致实际在hal层设置对应音量时设置成了speaker的音量,同等级音量下,speaker的音量是比耳机模式小的;
相关代码分析:
在切换设备时,从framework侧会重新设置新通话模式的音量
AudioPolicyManagerCustomImpl::gainTable_applyAnalogGainFromCheckAndSetVolume
调用-->
AudioPolicyManagerCustomImpl::checkAndSetGainTableAnalogGain
调用-->
AudioPolicyManagerCustomImpl::setVolumeParameterToHAL
调用-->
mAudioPolicyManager->mpClientInterface->setParameters
调用-->
AudioALSAStreamManager::setAnalogVolume
调用-->
status_t AudioMTKGainController::setVoiceVolume(int index, int devices, audio_mode_t mode)
调用-->
GAIN_DEVICE AudioMTKGainController::getGainDevice(audio_devices_t devices)
在这里会根据setparameters传下来的devices 类型选择GAIN_DEVICE,由于AUDIO_DEVICE_OUT_TELEPHONY_TX 没有对应GAIN_DEVICE, 所以使用默认值speaker,从而将speaker对应的等级音量设置到modem dl下行中去,从而将先前一步设置的耳机音量给覆盖掉,导致问题现象出现;
调用-->
AudioMTKGainController::ApplyMdDlGain
调用-->
SpeechDriverNormal::SetDownlinkGain
解决方案
在AudioPolicyManagerCustomImpl.cpp做如下修改,避免通话模式设置AUDIO_DEVICE_OUT_TELEPHONY_TX 设备音量
status_t AudioPolicyManagerCustomImpl::checkAndSetGainTableAnalogGain(audio_stream_type_t stream, int index, const sp<AudioOutputDescriptor>& outputDesc,DeviceTypeSet device,
int delayMs, bool force)
{
...
if ((activeStream == AUDIO_STREAM_VOICE_CALL || activeStream == AUDIO_STREAM_BLUETOOTH_SCO) &&
outputDesc != mAudioPolicyManager->mPrimaryOutput &&
!(((sp<SwAudioOutputDescriptor>&)outputDesc)->mFlags & AUDIO_OUTPUT_FLAG_VOIP_RX)) {
// in voice, set to primary only once, skip others
bool PrimaryVolSetIsSkipped = false; // ALPS05140437 We need to check the primary output due to it may not necessary to do call routing and update to the new device
DeviceTypeSet curPrimaryDevices = mAudioPolicyManager->mPrimaryOutput->devices().types();
DeviceTypeSet curDevices = outputDesc->devices().types();
PrimaryVolSetIsSkipped = (curDevices.find(
Volume::getDeviceForVolume(curPrimaryDevices)) == curDevices.end());
if (PrimaryVolSetIsSkipped) {
ALOGD("%s skip. Cur device [%s], primary device [%s]", __FUNCTION__, dumpDeviceTypes(curDevices).c_str(), dumpDeviceTypes(curPrimaryDevices).c_str());
} else {
return NO_ERROR;
}
+
+ if (curDevices.count(AUDIO_DEVICE_OUT_TELEPHONY_TX) != 0) {
+ ALOGD("AUDIO_DEVICE_OUT_TELEPHONY_TX skip set voice volume");
+ return NO_ERROR;
}
}
...
}