可以参考下面说明来分析音量大小相关的问题
(1)先要走到adjustStreamVolume(),其中很关键的code ,如下:
1422 int streamTypeAlias = mStreamVolumeAlias[streamType];
1423
1424 VolumeStreamState streamState = mStreamStates[streamTypeAlias];
1425
1426 final int device = getDeviceForStream(streamTypeAlias);
先获取到该streamtype的别名,再将该别名的device 获取到。
别名的来源是
STREAM_VOLUME_ALIAS_DEFAULT
根据streamtype 获取到的device,会不同。 getDeviceForStream()的结果总结如下:
Alias streamtype streamtype 插耳机
STREAM_VOICE_CALL STREAM_VOICE_CALL
STRAEM_RING STREAM_SYSTEM headphone
STRAEM_RING speaker
STRAEM_NOTIFICATION speaker
STRAEM_ENFORCED headphone
STRAEM_DTMF headphone
STRAEM_MUSIC STRAEM_MUSIC headphone
STRAEM_MUSIC STRAEM_TTS speaker
STRAEM_ALARM STRAEM_ALARM speaker
STRAEM_BLUETOOTH_SCO STRAEM_BLUETOOTH_SCO
= ( == ());(2) 然后会走到 setIndex() , 这个是设置音量到map 里去,每个streamtype 都会对应有一个index map,是存储volume index 的地方。
4442 final boolean currentDevice = (device == getDeviceForStream(mStreamType));
4443 final int numStreamTypes = AudioSystem.getNumStreamTypes();
4444 for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
4445 final VolumeStreamState aliasStreamState = mStreamStates[streamType];
4446 if (streamType != mStreamType &&
4447 mStreamVolumeAlias[streamType] == mStreamType &&
4448 (changed || !aliasStreamState.hasIndexForDevice(device))) {
4449 final int scaledIndex = rescaleIndex(index, mStreamType, streamType);
4450 aliasStreamState.setIndex(scaledIndex, device, caller);
4451 if (currentDevice) {
4452 aliasStreamState.setIndex(scaledIndex,
4453 getDeviceForStream(streamType), caller);
4454 }
4455 }
4456 }
4457 }
这段code ,表示对当前 streamType 的别名分别进行index保存, 但是这里会对别名的两种device进行index 保存:
a. 当前streamtype的device,
b. 别名的strategy的device,即前面(1)列出来的表格里面的device(getDeviceForStream()).
为什么会对当前streamtype 的device 进行保存?因为有setAllindexes()
4511 public void setAllIndexes(VolumeStreamState srcStream, String caller) {
4512 if (mStreamType == srcStream.mStreamType) {
4513 return;
4514 }
4515 synchronized (VolumeStreamState.class) {
4516 int srcStreamType = srcStream.getStreamType();
4517 // apply default device volume from source stream to all devices first in case
4518 // some devices are present in this stream state but not in source stream state
4519 int index = srcStream.getIndex(AudioSystem.DEVICE_OUT_DEFAULT);
4520 index = rescaleIndex(index, srcStreamType, mStreamType);
4521 for (int i = 0; i < mIndexMap.size(); i++) {
4522 mIndexMap.put(mIndexMap.keyAt(i), index);
4523 }
4524 // Now apply actual volume for devices in source stream state
4525 SparseIntArray srcMap = srcStream.mIndexMap;
4526 for (int i = 0; i < srcMap.size(); i++) {
4527 int device = srcMap.keyAt(i);
4528 index = srcMap.valueAt(i);
4529 index = rescaleIndex(index, srcStreamType, mStreamType);
4530
4531 setIndex(index, device, caller);
4532 }
4533 }
4534 }
例如,当前插上有线耳机,调节来电铃声音量,此时进行setindex 的streamtype 和 device 分别有:
STRAEM_DTMF、STRAEM_ENFORCED、STREAM_SYSTEM 进行setindex 的device 为 speaker和headphone;
STRAEM_RING、 STRAEM_NOTIFICATION 进行setindex 的device 为speaker。
(3) 接下来会调用setDeviceVolume(),将 index 写到audiopolicy 中去,这才是系统真正会用到的音量。
4675 streamState.applyDeviceVolume_syncVSS(device);
4676
4677 // Apply change to all streams using this one as alias
4678 int numStreamTypes = AudioSystem.getNumStreamTypes();
4679 for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
4680 if (streamType != streamState.mStreamType &&
4681 mStreamVolumeAlias[streamType] == streamState.mStreamType) {
4682 // Make sure volume is also maxed out on A2DP device for aliased stream
4683 // that may have a different device selected
4684 int streamDevice = getDeviceForStream(streamType);
4685 if ((device != streamDevice) && mAvrcpAbsVolSupported &&
4686 ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0)) {
4687 mStreamStates[streamType].applyDeviceVolume_syncVSS(device);
4688 }
4689 mStreamStates[streamType].applyDeviceVolume_syncVSS(streamDevice);
4690 }
4691 }
4692 }
这里也会对Alias streamtype 进行循环,只是这里与setindex不同的是,它只对policy 对应的 device 进行音量设置。
4372 public void applyDeviceVolume_syncVSS(int device) {
4373 int index;
4374 if (mIsMuted) {
4375 index = 0;
4376 } else if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 && mAvrcpAbsVolSupported) {
4377 index = getAbsoluteVolumeIndex((getIndex(device) + 5)/10);
4378 } else if ((device & mFullVolumeDevices) != 0) {
4379 index = (mIndexMax + 5)/10;
4380 } else {
4381 index = (getIndex(device) + 5)/10;
4382 }
4383 Log.d(TAG, "applyDeviceVolume" + "mStreamType:" + mStreamType + ",device:" + device);
4384 AudioSystem.setStreamVolumeIndex(mStreamType, index, device);
4385 }
例如,当前插上有线耳机,调节来电铃声音量,此时把音量设置到policy 中的 的streamtype 和 device 分别有:
STRAEM_DTMF、STRAEM_ENFORCED、STREAM_SYSTEM 进行setStreamVolumeIndex 的device 为headphone;
STRAEM_RING、 STRAEM_NOTIFICATION 进行setStreamVolumeIndex 的device 为speaker。
(1) AudioService.java
把文件前面的 LOGD、DEBUG_MODE、DEBUG_AP、DEBUG_VOL都直接赋值为true;
必要时,把setIndex()里面,把mStreamType 和 device 以及 index 都打印出来。 这样可以查清当前index map里面每一个streamtype和device所对应的index的变化情况;
getDeviceForStream()也需要打印出streamtype 和device。
打出类似这样的log:
24950 10-24 08:58:24.808423 963 3018 D AudioService: Mits getDeviceForStream: stream2 device:2
24952 10-24 08:58:24.810269 963 3018 D AudioService: Mits setIndex IndexMap mStreamType= 2 device:2,index:100
(2) AudioPolicyManager.cpp
将ALOGV 打开, 即去掉前面的 //
//#define LOG_NDEBUG 0
这个文件关键API是: setStreamVolumeIndex(), 这个里面的log一定要打出来,因为它是当前系统用到audiotrack进行mix的音量。
log 类似这样:
25004 10-24 08:58:24.909459 519 5008 V APM_AudioPolicyManager: setStreamVolumeIndex() stream 8, device 00000008, index 10