Android调节音量分析
音量調節接口
我們知道Android Audio的音量調節接口是通過AudioManager的setStreamVolume實現的,這個函數的實現在AudioService的setStreamVolume函數中,然后會調用到setStreamVolumeInt,這個函數首先通過streamState.setIndex發送音量調節的廣播通知app更新UI。然后通過消息機制走到setDeviceVolume函數。注:如果要實現硬調音,也就是調節dsp音量不調節安卓音量,可以把config_useFixedVolume這個參數置為true。
我們簡單分析一下setDeviceVolume函數
首先是經過applyDeviceVolume_syncVSS函數走到AudioSystem.cpp的setStreamVolumeInt函數(這個后面再繼續分析)。然后發送了一個MSG_PERSIST_VOLUME的消息,通過persistVolume函數把音量值存儲到setting數據庫中。
native層音量調節的實現
我們上面分析到會走到AudioSystem::setStreamVolumeIndex函數,這個函數通過binder最終走到AudioPolicyManager::setStreamVolumeIndex函數中,然后調用AudioPolicyManager::setVolumeIndexForAttributes函數,在這個函數中Android10.0的代碼中已經有了組的概念,我們按照正常的流程往下走,會走到AudioPolicyManagerCustom::checkAndSetVolume函數中,然后這個函數會根據audiopolicy中的audio_policy_volumes.xml文件中配置的聲音曲線調用computeVolume計算出一個volumeDb值,然后通過AudioOutputDescriptor::setVolume函數去set音量。這個函數通過setCurVolume函數調用mVolumeActivities[vs].setVolume(volumeDb),這個mVolumeActivities就是當前在這個output中活動的track,所以我們跟到了AudioTrack::setVolume函數,這個函數會調用mProxy->setVolumeLR函數
void setVolumeLR(gain_minifloat_packed_t volumeLR) {mCblk->mVolumeLR = volumeLR;}通過上面的代碼我們知道就是把現在的增益保存在mCblk->mVolumeLR中,看到mCblk我們就應該能聯想到這是與audioflinger通信的環形buffer,所以使用這個音量的地方肯定在AudioFlinger中,我們去AudioFlinger中去找發現是prepareTracks_l函數通過proxy->getVolumeLR拿到的這個增益。我們知道AudioFlinger的threadLoop函數會不斷的循環的調用prepareTracks_l函數去準備音頻流和混音流的數據,在這里把audiopolicy設置的音量以及track的音量和master音量做一個計算(一般是相乘),所以現在AudioFlinger拿到的pcm數據就已經包含了修改的增益,然后通過threadLoop_wrtie函數把修改了增益的pcm數據寫到hal層,到這里整個setStreamVolume的流程就分析完成了。
例:app1:混音數據1 = 音頻數據1 * master_volume * stream1_volume * AudioTrack1_volume
app2:混音數據2 = 音頻數據2 * master_volume * stream2_volume * AudioTrack2_volume
然而在車機上會有主副屏后排屏的概念,這時候我們可以使用CarAudioManager的setGroupVolume去set音量。
setGroupVolume的實現
setGroupVolume會走到setCurrentGainIndex函數然后把音量值存儲到setting數據庫中,然后會走到AudioManager的setAudioPortGain函數中
public static int setAudioPortGain(AudioPort port, AudioGainConfig gain) {if (port == null || gain == null) {return ERROR_BAD_VALUE;}AudioPortConfig activeConfig = port.activeConfig();AudioPortConfig config = new AudioPortConfig(port, activeConfig.samplingRate(),activeConfig.channelMask(), activeConfig.format(), gain);config.mConfigMask = AudioPortConfig.GAIN;return AudioSystem.setAudioPortConfig(config);}這個函數會把增益等一些參數封裝到AudioPortConfig中然后調用AudioSystem.setAudioPortConfig函數,經過一系列的調用會走到AudioPolicyManager::setAudioPortConfig函數,然后通過binder等一系列封裝調用會走到AudioFlinger::setAudioPortConfig函數中,最終會走到hal層audio_hw的adev_set_audio_port_config函數中去,最后的實現在auto_hal.c的auto_hal_set_audio_port_config函數中,最終會調用到kernel的set_volume函數中去。這樣看來這條通路設置的應該就是dsp的音量,因為并沒有修改到AudioFlinger中pcm數據的增益,這個函數留到后面仔細分析。
總結
以上是生活随笔為你收集整理的Android调节音量分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: random.uniform()总结
- 下一篇: Python抓取分析“创造101 ”菊姐