錄音音量安卓系統本身並未提供相關接口,同時錄音音量調節也需要硬件的支持。如果硬件支持,是可以實現的。share一下的我的方案。
先說一下思路,對於驅動來說,僅僅是調節相關ctl值就可以了。如此以來,可以看到和paly back的音量調節會有很大區別,play back調節音量,在policy startoutput時,會getVolume,音量的生效是在audioflinger 做mix時,將音量計算到音頻波形中。所以,對於錄音音量調節,我們需要把上層設置音量數值,直接給kernel就ok了。
1.來看驅動的支持
diff --git a/kernel/sound/soc/codecs/rk616_codec.c b/kernel/sound/soc/codecs/rk616_codec.c
index 831bb24..0d6949f 100755
--- a/kernel/sound/soc/codecs/rk616_codec.c
+++ b/kernel/sound/soc/codecs/rk616_codec.c
@@ -1940,6 +1940,14 @@ static const struct snd_kcontrol_new rk616_snd_path_controls[] = {
*/
SOC_ENUM_EXT("Modem Input Enable", rk616_modem_input_type,
rk616_modem_input_get, rk616_modem_input_put),
+ SOC_SINGLE_TLV("PGAL Capture Volume", RK616_PGAL_CTL,
+ RK616_PGA_VOL_SFT, 31, 0, pga_vol_tlv),//0x0a bit 5 is 0
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "PGAL Capture Switch", \
+ .info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\
+ .put = snd_soc_put_pgal_volsw, \
+ .private_value = SOC_SINGLE_VALUE(RK616_PGAL_CTL, RK616_PGA_MUTE_SFT, 1, 1)
+ },
};
2.HAL 層 通過setparameter 完成,記錄volume值,在inputstream open時,設置給ctl.
setParameter:
if (param.getInt(String8(SET_INPUT_VOLUME),cVolume) == NO_ERROR){
if (openMixer_l() != NULL){
ALOGV("WZ :SET_INPUT_VOLUME truth value: %d",cVolume);
//caculate the truth input volume
if (cVolume <= 0){
cVolume = 0;
}else if(cVolume >= 10){
cVolume = 10;
}
if (cVolume == 0){
ALOGV("SET_INPUT_VOLUME value: %d,we need mute",cVolume);
//TODO: if future we can setInputVolume while recording,we need setMicMute here
//setMicMute(true);
}else{
//setMicMute(false);
cVolume *= 3;
}
ALOGV("SET_INPUT_VOLUME truth value: %d",cVolume);
struct mixer_ctl * cvCtrl = mixer_get_control(mMixer, "PGAL Capture Volume", 0);
mixer_ctl_set_int(cvCtrl,(long long) cVolume);
mInputVolume = cVolume;
}else{
ALOGE("WZ :SET_INPUT_VOLUME openMixer fail");
}
}
AudioInputStream::open_l
struct mixer_ctl * cvCtrl = mixer_get_control(mMixer, "PGAL Capture Volume", 0);
mixer_ctl_set_int(cvCtrl,(long long) mHardware->mInputVolume);
//adjust input stream volume, mute mic
if (mHardware->mInputVolume == 0){
setGain(0.0);
}
3.關於框架層,兩個方面,一個是需要設置時在系統setting 數據庫中保存,再一個在audioservice服務利用AudioSystem setparameter實現。
安卓本身音頻框架中,設置播放音量,AudioService :: setStreamVolumeIndex->AudioSystem->AudioPolicyService->AudioPolicy完成。
來看具體實現:
1)獲取音量:
/** @see AudioManager#getInputVolume() */
public int getInputVolume(){
readInputVolumeSettings();//從數據庫讀取
return mInputVolume;
}
2)設置音量
/** @see AudioManager#setInputVolume(int) */
public void setInputVolume(int index) {
sendMsg(mAudioHandler,
MSG_PERSIST_SET_INPUT_VOLUME,
SENDMSG_QUEUE,
index,
0,
null,
0);
AudioSystem.setParameters("set_input_volume="+index);
mInputVolume = index;
Log.d(TAG,"setInputVolume mInputVolume: " + index);
}
再者就是,添加接口到frameworks/base/media/java/android/media/IAudioService.aidl,在audiomanager中爲上層app提供接口,ok,框架層部分基本完成了。