Android [Audio] 如何分析音量大小相关的问题

可以参考下面说明来分析音量大小相关的问题

  1. 调节音量的流程

(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. 音量大小问题的debug

(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

你可能感兴趣的:(Android [Audio] 如何分析音量大小相关的问题)