按文件分步骤,代码版本Android6.0.1
1.上层调用AudioManager的接口,要么是setStreamVolume(),要么是按了音量键adjustStreamVolume().
2.AudioService.java:
1.1分两种情况
情况一:如果setStreamVolume()--------------------------应用层调用
(1)setStreamVolume()
onSetStreamVolume(streamType, index, flags, device, caller);
(2) onSetStreamVolume()
setStreamVolumeInt(stream, index, device, false, caller);
(3)setStreamVolumeInt()
sendMsg(mAudioHandler,
MSG_SET_DEVICE_VOLUME,
SENDMSG_QUEUE,
device,
0,
streamState,
0);
mAudioHandler定义:AudioHandler mAudioHandler;
->case MSG_SET_DEVICE_VOLUME:
setDeviceVolume((VolumeStreamState) msg.obj, msg.arg1);
break;
情况二:如果adjustStreamVolume()-----------------------------音量键
直接
sendMsg(mAudioHandler,
MSG_SET_DEVICE_VOLUME,
SENDMSG_QUEUE,
device,
0,
streamState,
0);
1.2setDeviceVolume():
mStreamStates[streamType].applyDeviceVolume_syncVSS(device);
1.3applyDeviceVolume_syncVSS():
AudioSystem.setStreamVolumeIndex(mStreamType, index, device);
这一步中的index值并不是通过msg传递过来的,那么是怎么来的呢?
public void applyDeviceVolume_syncVSS(int device) {
int index;
if (mIsMuted) {//静音了
index = 0;
} else if (((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 && mAvrcpAbsVolSupported)//某类蓝牙设备保持在一个固定的音量上(雷柏a3060)
|| ((device & mFullVolumeDevices) != 0)) {//某类可调,比如Leme(乐视蓝牙耳机)
index = (mIndexMax + 5)/10;
} else {
index = (getIndex(device) + 5)/10;
}
AudioSystem.setStreamVolumeIndex(mStreamType, index, device);
}
探讨一下Leme和雷柏a3060的表现不一样的问题
用adb shell dump研究audio_flinger得知,此时,系统输出的音量db值都是0(即最大音量)。
调音量是在哪调的呢?
上代码:
if (mA2dp != null && mAvrcpAbsVolSupported) {
mA2dp.setAvrcpAbsoluteVolume(index / 10);
}
结果发现两个设备都会执行到这来,但是再往下jni层,雷柏的返回音量一直是0,其他蓝牙耳机,蓝牙音箱都正常音量值。。。估计雷柏本身支持的不够好了,毕竟设备比较久远,
我们就不深究了。
至少在这可以得出一个结论:
手机针对蓝牙音频输出设备的策略是:给你最大音量的输出,要调你自己调,比如这个地方用Avrcp协议去和蓝牙设备进行通讯来调整音量。
言归正传。很明显。index来自getIndex方法,一路找下去,发现index来自 mIndexMap
调用顺序:
情况一:adjustStreamVolume():
streamState.adjustIndex(direction * step, device, caller)
setIndex(getIndex(device) + deltaIndex, device, caller);
mIndexMap.put(device, index);
情况二:setStreamVolume():
在前面说到的1.1情况一的 setStreamVolumeInt()函数里index一路通过参数传过来,然后通过
streamState.setIndex(index, device, caller) 也进行了赋值
mIndexMap.put(device, index);
put之后,那边就可以get出来了,不过要注意
(1)set的地方和get的地方(收到msg之后)是异步的,两个线程.
(2)setIndex有个参数device。不同device,index是不一样的。
(3)setIndex里头:
boolean currentDevice = (device == getDeviceForStream(mStreamType));
int numStreamTypes = AudioSystem.getNumStreamTypes();
for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
if (streamType != mStreamType &&
mStreamVolumeAlias[streamType] == mStreamType) {
int scaledIndex = rescaleIndex(index, mStreamType, streamType);
mStreamStates[streamType].setIndex(scaledIndex, device, caller);
//根据上面的赋值可知,这个变量的意思是,本次调用想设置音量的device对应 //mStreamType
if (currentDevice) {
mStreamStates[streamType].setIndex(scaledIndex,
getDeviceForStream(streamType), caller);
}
}
}
注意这段代码,打日志的话,setIndex会被调用多次。别名一样的也会被同时设置。我自己都没懂这块是什么意思?????????????????懂的人说下
2.AudioSystem.java
public static native int setStreamVolumeIndex()
这下到ndk层了
3.android_media_AudioSystem.cpp
android_media_AudioSystem_setStreamVolumeIndex():
AudioSystem::setStreamVolumeIndex()
4.AudioSystem.cpp
status_t AudioSystem::setStreamVolumeIndex
到这层开始返回值变成了status_t这个结构体,虽然我不知道这个结构体在哪定义的,但是这个结构体很常见。
return aps->setStreamVolumeIndex(stream, index, device);
aps定义:const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
IaudioPolicyService是一个IInterface,我们找到
再往下,实在懒得分析了,等以后的吧!
Andorid6.0音量调整(设置)流程
猜你喜欢
转载自blog.csdn.net/bberdong/article/details/51792319
今日推荐
周排行