android音量调整流程+HDMI音量控制修改
2015-07-07 21:48
363 查看
当按键按下时,底层上报事件给KeyguardUpdateMonitor,窗口管理器WindowManager,从KeyguardUpdateMonitor获取具体按键信息,如果是Volume +/- 则直接由AudioManager.java处理,调用方法adjustSuggestedStreamVolume,其参数direction包括ADJUST_LOWER(-键)、ADJUST_RAISE(+键)、ADJUST_SAME(不调整),suggestedStreamType为音频流类型,flags为特殊标志位,下面会讲到。
adjustSuggestedStreamVolume方法内直接通过IAudioService获取framework层的AudioService服务,AudioService针对强制使用某种音频,通过AudioSystem的JNI从HAL层获取状态,并进行切换,再执行adjustMasterVolume / adjustSuggestedStreamVolume方法,方法内部处理了STREAM_REMOTE_MUSIC和非REMOTE_MUSIC的音量调整,STREAM_REMOTE_MUSIC是在当后台播放音乐时,不在前台运行的情况。adjustSuggestedStreamVolume先对当前stream获取在执行的streamtype类型,包括通话状态收音机播放,音乐播放等,此处需要hal层获取streamtype,得到streamtype后如果是STREAM_REMOTE_MUSIC,将清楚flags中的标志FLAG_PLAY_SOUND、FLAG_FIXED_VOLUME等。
STREAM_REMOTE_MUSIC类型继续执行adjustRemoteVolume,否则执行adjustStreamVolume,这里主要进入adjustStreamVolume方法。在adjustStreamVolume方法内检查SafeMedaiVolume在插耳机情况下需提示,如果streamtypealias为STREAM_MUSIC,且设备类型包括DEVICE_OUT_AUX_DIGITAL,将添加flags 标志位:
flags |= AudioManager.FLAG_FIXED_VOLUME
固定不能调节音量的设备包括:
final int mFixedVolumeDevices =
AudioSystem.DEVICE_OUT_AUX_DIGITAL|
AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET |
AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET |
AudioSystem.DEVICE_OUT_ALL_USB;
DEVICE_OUT_AUX_DIGITAL 是针对HDMI类型。
最后,sendVolumeUpdate直接调用mVolumePanel.postVolumeChanged(streamType, flags) 设定并显示进度条,VolumePanel内部会根据flags 标志是否包含 FLAG_FIXED_VOLUME,设定进度条sc.seekbarView.setEnabled(false / true),VolumePanel内会有个dialog显示。至此,上层的调用过程结束。
在HAL策略上只需修改一处,AudioPolicyManager的computeVolume方法,修改如下:
修改前:
if (stream == AudioSystem::MUSIC &&
index != mStreams[stream].mIndexMin &&
(device == AUDIO_DEVICE_OUT_AUX_DIGITAL||
device == AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET ||
device == AUDIO_DEVICE_OUT_USB_ACCESSORY ||
device== AUDIO_DEVICE_OUT_USB_DEVICE)) {
return 1.0;
}
修改后:
if (stream == AudioSystem::MUSIC &&
index != mStreams[stream].mIndexMin &&
(//device == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
device == AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET ||
device == AUDIO_DEVICE_OUT_USB_ACCESSORY ||
device == AUDIO_DEVICE_OUT_USB_DEVICE)) {
return 1.0;
}
具体流程如何走到这里。
对输出策略的管理上,在插HDMI时于桌面调整音量,默认不使用HDMI输出,因为在输出设备判断上有操作:
if ((device2 ==AUDIO_DEVICE_NONE)&& (strategy!= STRATEGY_SONIFICATION)) {// no sonification on aux digital (e.g.
HDMI)
device2 = mAvailableOutputDevices& AUDIO_DEVICE_OUT_AUX_DIGITAL;
}
STRATEGY_SONIFICATION为在桌面时调整的声音所使用的类型,每当调整音量时,通过ToneGenerator初始化构造对应音频流的ToneGenerator桂香,借助AudioFlinger建立AudioTrack实例,在AudioFlinger内部会对音频流类型设置AudioTrack的参数。建立AudioTrack后设置优先级为1并调度运行该线程(叫线程是因为AudioTrack继承thread本分,可查看类继承)。一旦调度startTone时,AudioTrack
start,经过AudioFlinger start 进行数据处理,最后通过AudioService调用AudioPolicyManager,从startoutput --> getNewDevice --> setOutputDevice --> setOutputDevice --> checkAndSetVolume
--> getNewDevice --> getNewDevice 等,具体可查看log:
ToneGenerator: ToneGenerator constructor: streamType=2, volume=0.011220
AudioTrack:
audiotrack 0x58ba9540 set Type 2, rate 0, fmt 1, chn 1, fcnt 0, flag 4
AudioFlinger: createTrack() sessionId: 0
AudioFlinger: createTrack() lSessionId: 26
AudioFlinger: AUDIO_OUTPUT_FLAG_FAST denied: isTimed=0 sharedBuffer=0x0 frameCount=0 mFrameCount=2048 format=1 isLinear=1 channelMask=0x1 sampleRate=44100 mSampleRate=44100 hasFastMixer=0
tid=2176 fastTrackAvailMask=0xfe
dalvikvm: threadid=81: interp stack at 0x566c5000
AudioTrack: sched_setscheduler to rt, priority: 1
AudioFlinger: Track constructor name4099, calling pid519
AudioFlinger: acquiring 26 from 519
AudioFlinger: added new entry for 26
ToneGenerator: startTone
AudioTrack: start 0x58ba9540
AudioFlinger: start(4099), calling pid 519 session 26
AudioFlinger: ? => ACTIVE (4099) on thread 0x417afb70
AudioPolicyManager: startOutput()output 2, stream2, session 26
AudioPolicyManager: getNewDevice()
STRATEGY_SONIFICATION selected device2 output= 2
AudioPolicyManager: getNewDevice() selected device2 output= 2
AudioPolicyManager: setOutputDevice() output 2 device0002 delayMs 0
AudioPolicyManager: checkDeviceMuteStrategies outputDesc = 0x41630950 prevDevice = 2 delayMs = 0
AudioPolicyManager: setOutputDevice() setting samedevice 0002 or null device for output 2
AudioPolicyManager: checkAndSetVolume stream = 2 index = 7 output = 2 device = 0x2 delayMs = 0 force = 0
AudioPolicyManager: getNewDevice()
STRATEGY_SONIFICATION selected device2 output= 2
AudioPolicyManager: getNewDevice() selected device2 output= 2
AudioFlinger: mWaitWorkCV.broadcast
AudioFlinger: thread 0x4179f050 type 0 TID 447 waking up
这里会在getNewDevice时获取输出设备,会进入策略方法进行判断,需要去掉STRATEGY_SONIFICATION部分限制,如下:
if ((device2 ==AUDIO_DEVICE_NONE))//&& (strategy!=
STRATEGY_SONIFICATION)) {// no sonification on aux digital (e.g. HDMI)
device2 = mAvailableOutputDevices& AUDIO_DEVICE_OUT_AUX_DIGITAL;
}
以上从策略层进行修改,另一种方法是从framework进行修改,从VolumePanle中修改StreamResources中的值:
VoiceStream(AudioManager.STREAM_VOICE_CALL,
R.string.volume_icon_description_incall,
R.drawable.ic_audio_phone,
R.drawable.ic_audio_phone,
false)
为,
VoiceStream(AudioManager.STREAM_MEDIA,
R.string.volume_icon_description_incall,
R.drawable.ic_audio_phone,
R.drawable.ic_audio_phone,
false)
但第二种修改不适合带modem功能的设备,第二种修改也就是直接将通话改为多媒体类型。
出处 http://wenku.baidu.com/link?url=NBpwxTLRDyCD3NErm1P3CZgYYc3HvAKN_bM9DL80m8curLxMMa8qmP69nePlILNO2iIBdoqZ41Ijjr9Sc9R03RJZ2mAikF0AHbCX_SuQ5OC
adjustSuggestedStreamVolume方法内直接通过IAudioService获取framework层的AudioService服务,AudioService针对强制使用某种音频,通过AudioSystem的JNI从HAL层获取状态,并进行切换,再执行adjustMasterVolume / adjustSuggestedStreamVolume方法,方法内部处理了STREAM_REMOTE_MUSIC和非REMOTE_MUSIC的音量调整,STREAM_REMOTE_MUSIC是在当后台播放音乐时,不在前台运行的情况。adjustSuggestedStreamVolume先对当前stream获取在执行的streamtype类型,包括通话状态收音机播放,音乐播放等,此处需要hal层获取streamtype,得到streamtype后如果是STREAM_REMOTE_MUSIC,将清楚flags中的标志FLAG_PLAY_SOUND、FLAG_FIXED_VOLUME等。
STREAM_REMOTE_MUSIC类型继续执行adjustRemoteVolume,否则执行adjustStreamVolume,这里主要进入adjustStreamVolume方法。在adjustStreamVolume方法内检查SafeMedaiVolume在插耳机情况下需提示,如果streamtypealias为STREAM_MUSIC,且设备类型包括DEVICE_OUT_AUX_DIGITAL,将添加flags 标志位:
flags |= AudioManager.FLAG_FIXED_VOLUME
固定不能调节音量的设备包括:
final int mFixedVolumeDevices =
AudioSystem.DEVICE_OUT_AUX_DIGITAL|
AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET |
AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET |
AudioSystem.DEVICE_OUT_ALL_USB;
DEVICE_OUT_AUX_DIGITAL 是针对HDMI类型。
最后,sendVolumeUpdate直接调用mVolumePanel.postVolumeChanged(streamType, flags) 设定并显示进度条,VolumePanel内部会根据flags 标志是否包含 FLAG_FIXED_VOLUME,设定进度条sc.seekbarView.setEnabled(false / true),VolumePanel内会有个dialog显示。至此,上层的调用过程结束。
在HAL策略上只需修改一处,AudioPolicyManager的computeVolume方法,修改如下:
修改前:
if (stream == AudioSystem::MUSIC &&
index != mStreams[stream].mIndexMin &&
(device == AUDIO_DEVICE_OUT_AUX_DIGITAL||
device == AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET ||
device == AUDIO_DEVICE_OUT_USB_ACCESSORY ||
device== AUDIO_DEVICE_OUT_USB_DEVICE)) {
return 1.0;
}
修改后:
if (stream == AudioSystem::MUSIC &&
index != mStreams[stream].mIndexMin &&
(//device == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
device == AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET ||
device == AUDIO_DEVICE_OUT_USB_ACCESSORY ||
device == AUDIO_DEVICE_OUT_USB_DEVICE)) {
return 1.0;
}
具体流程如何走到这里。
对输出策略的管理上,在插HDMI时于桌面调整音量,默认不使用HDMI输出,因为在输出设备判断上有操作:
if ((device2 ==AUDIO_DEVICE_NONE)&& (strategy!= STRATEGY_SONIFICATION)) {// no sonification on aux digital (e.g.
HDMI)
device2 = mAvailableOutputDevices& AUDIO_DEVICE_OUT_AUX_DIGITAL;
}
STRATEGY_SONIFICATION为在桌面时调整的声音所使用的类型,每当调整音量时,通过ToneGenerator初始化构造对应音频流的ToneGenerator桂香,借助AudioFlinger建立AudioTrack实例,在AudioFlinger内部会对音频流类型设置AudioTrack的参数。建立AudioTrack后设置优先级为1并调度运行该线程(叫线程是因为AudioTrack继承thread本分,可查看类继承)。一旦调度startTone时,AudioTrack
start,经过AudioFlinger start 进行数据处理,最后通过AudioService调用AudioPolicyManager,从startoutput --> getNewDevice --> setOutputDevice --> setOutputDevice --> checkAndSetVolume
--> getNewDevice --> getNewDevice 等,具体可查看log:
ToneGenerator: ToneGenerator constructor: streamType=2, volume=0.011220
AudioTrack:
audiotrack 0x58ba9540 set Type 2, rate 0, fmt 1, chn 1, fcnt 0, flag 4
AudioFlinger: createTrack() sessionId: 0
AudioFlinger: createTrack() lSessionId: 26
AudioFlinger: AUDIO_OUTPUT_FLAG_FAST denied: isTimed=0 sharedBuffer=0x0 frameCount=0 mFrameCount=2048 format=1 isLinear=1 channelMask=0x1 sampleRate=44100 mSampleRate=44100 hasFastMixer=0
tid=2176 fastTrackAvailMask=0xfe
dalvikvm: threadid=81: interp stack at 0x566c5000
AudioTrack: sched_setscheduler to rt, priority: 1
AudioFlinger: Track constructor name4099, calling pid519
AudioFlinger: acquiring 26 from 519
AudioFlinger: added new entry for 26
ToneGenerator: startTone
AudioTrack: start 0x58ba9540
AudioFlinger: start(4099), calling pid 519 session 26
AudioFlinger: ? => ACTIVE (4099) on thread 0x417afb70
AudioPolicyManager: startOutput()output 2, stream2, session 26
AudioPolicyManager: getNewDevice()
STRATEGY_SONIFICATION selected device2 output= 2
AudioPolicyManager: getNewDevice() selected device2 output= 2
AudioPolicyManager: setOutputDevice() output 2 device0002 delayMs 0
AudioPolicyManager: checkDeviceMuteStrategies outputDesc = 0x41630950 prevDevice = 2 delayMs = 0
AudioPolicyManager: setOutputDevice() setting samedevice 0002 or null device for output 2
AudioPolicyManager: checkAndSetVolume stream = 2 index = 7 output = 2 device = 0x2 delayMs = 0 force = 0
AudioPolicyManager: getNewDevice()
STRATEGY_SONIFICATION selected device2 output= 2
AudioPolicyManager: getNewDevice() selected device2 output= 2
AudioFlinger: mWaitWorkCV.broadcast
AudioFlinger: thread 0x4179f050 type 0 TID 447 waking up
这里会在getNewDevice时获取输出设备,会进入策略方法进行判断,需要去掉STRATEGY_SONIFICATION部分限制,如下:
if ((device2 ==AUDIO_DEVICE_NONE))//&& (strategy!=
STRATEGY_SONIFICATION)) {// no sonification on aux digital (e.g. HDMI)
device2 = mAvailableOutputDevices& AUDIO_DEVICE_OUT_AUX_DIGITAL;
}
以上从策略层进行修改,另一种方法是从framework进行修改,从VolumePanle中修改StreamResources中的值:
VoiceStream(AudioManager.STREAM_VOICE_CALL,
R.string.volume_icon_description_incall,
R.drawable.ic_audio_phone,
R.drawable.ic_audio_phone,
false)
为,
VoiceStream(AudioManager.STREAM_MEDIA,
R.string.volume_icon_description_incall,
R.drawable.ic_audio_phone,
R.drawable.ic_audio_phone,
false)
但第二种修改不适合带modem功能的设备,第二种修改也就是直接将通话改为多媒体类型。
出处 http://wenku.baidu.com/link?url=NBpwxTLRDyCD3NErm1P3CZgYYc3HvAKN_bM9DL80m8curLxMMa8qmP69nePlILNO2iIBdoqZ41Ijjr9Sc9R03RJZ2mAikF0AHbCX_SuQ5OC
相关文章推荐
- Android Studio 使用SlidingMenu侧滑菜单
- Android Studio 使用SlidingMenu侧滑菜单
- ScheduledThreadPoolExecutor定时使用
- android反射组件 (一个)java 它们的定义annotation基础知识
- Android 手机号码格式验证
- android入门学习-java简介
- Android中利用ViewHolder优化自定义Adapter的典型写法(讨论ViewHolder的修饰方式)
- 【android】开发笔记---存储篇
- Android 身份证号码查询、手机号码查询、天气查询
- Android--Listview优化
- Android之activity加载模式
- Android 画图详解
- Android 中的BroadCastReceiver
- 如何查看Android源码
- android 5.x system.img 大于2G导致编译otapackage时报错如何处理
- android5.x添加sim1,sim2标识
- Android studio学习和gradle学习列表
- kernel logo到开机动画之间闪现黑屏(android 5.X)
- Android系统启动流程
- android 通知基础