前言
分为两部分分析
AudioService ---> AudioSystem
AudioManager ---> AudioService
AudioSystem只提供了一个可以使用的接口
http://androidxref.com/5.1.1_r6/xref/frameworks/base/media/java/android/media/AudioSystem.java
public static native int setStreamVolumeIndex(int stream, int index, int device);
参数有stream, index, device
setStreamVolumeIndex调用位置
通过如下两个函数,可以了解到
1.判断是否为mute, 若是则直接设置为0
2.判断是否最大音量的情况,若是则最大音量
3.两个边界完了才是从index取值
下面两个函数都是VolumeStreamState的方法,apply打头
VolumeStreamState.applyDeviceVolume_syncVSS
参数只有device
// must be called while synchronized VolumeStreamState.class
public void applyDeviceVolume_syncVSS(int device) {
int index;
if (isMuted_syncVSS()) { // muted
index = 0;
} else if (((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 && mAvrcpAbsVolSupported)
|| ((device & mFullVolumeDevices) != 0)) { // abs , full volume
index = (mIndexMax + 5)/10;
} else {
index = (getIndex(device) + 5)/10;
}
AudioSystem.setStreamVolumeIndex(mStreamType, index, device); // <-------------
}
VolumeStreamState.applyAllVolumes
public void applyAllVolumes() {
synchronized (VolumeStreamState.class) {
// apply default volume first: by convention this will reset all
// devices volumes in audio policy manager to the supplied value
int index;
if (isMuted_syncVSS()) { // mute
index = 0;
} else {
index = (getIndex(AudioSystem.DEVICE_OUT_DEFAULT) + 5)/10;
}
AudioSystem.setStreamVolumeIndex(mStreamType, index, AudioSystem.DEVICE_OUT_DEFAULT); // <-----------
// then apply device specific volumes
Set set = mIndex.entrySet();
Iterator i = set.iterator();
while (i.hasNext()) {
Map.Entry entry = (Map.Entry)i.next();
int device = ((Integer)entry.getKey()).intValue();
if (device != AudioSystem.DEVICE_OUT_DEFAULT) {
if (isMuted_syncVSS()) {
index = 0;
} else if (((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 &&
mAvrcpAbsVolSupported)
|| ((device & mFullVolumeDevices) != 0))
{
index = (mIndexMax + 5)/10;
} else {
index = ((Integer)entry.getValue() + 5)/10;
}
AudioSystem.setStreamVolumeIndex(mStreamType, index, device); // <----------------
}
}
}
}
applyDeviceVolume_syncVSS 调用位置
public void checkFixedVolumeDevices
public void checkFixedVolumeDevices() {
synchronized (VolumeStreamState.class) {
// ignore settings for fixed volume devices: volume should always be at max or 0
if (mStreamVolumeAlias[mStreamType] == AudioSystem.STREAM_MUSIC) {
Set set = mIndex.entrySet();
Iterator i = set.iterator();
while (i.hasNext()) {
Map.Entry entry = (Map.Entry)i.next();
int device = ((Integer)entry.getKey()).intValue();
int index = ((Integer)entry.getValue()).intValue();
if (((device & mFullVolumeDevices) != 0)
|| (((device & mFixedVolumeDevices) != 0) && index != 0)) {
entry.setValue(mIndexMax);
}
applyDeviceVolume_syncVSS(device); // <--------
}
}
}
}
AudioHandler.setDeviceVolume
private class AudioHandler extends Handler {
private void setDeviceVolume(VolumeStreamState streamState, int device) { <-----------
synchronized (VolumeStreamState.class) {
// Apply volume
streamState.applyDeviceVolume_syncVSS(device);
// Apply change to all streams using this one as alias
int numStreamTypes = AudioSystem.getNumStreamTypes();
for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
if (streamType != streamState.mStreamType &&
mStreamVolumeAlias[streamType] == streamState.mStreamType) {
// Make sure volume is also maxed out on A2DP device for aliased stream
// that may have a different device selected
int streamDevice = getDeviceForStream(streamType);
if ((device != streamDevice) && mAvrcpAbsVolSupported &&
((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0)) {
mStreamStates[streamType].applyDeviceVolume_syncVSS(device);
}
mStreamStates[streamType].applyDeviceVolume_syncVSS(streamDevice);
}
}
}
// Post a persist volume msg
sendMsg(mAudioHandler,
MSG_PERSIST_VOLUME,
SENDMSG_QUEUE,
device,
0,
streamState,
PERSIST_DELAY);
}
applyAllVolumes调用位置
private void checkAllAliasStreamVolumes
public void forceRemoteSubmixFullVolume
private void setAllVolumes(VolumeStreamState streamState)
MSG_MEDIA_SERVER_DIED
Basic Principle & Model
AudioSevice VolumeStreamState AudioSystem
Fuctions ------> applyDeviceVolume_syncVSS -------> setStreamVolumeIndex
applyAllVolumes
解决了 AudioService ---> AudioSystem,接下来解决 AudioManager ---> AudioService
Develper API call follow
从物理按键调节音量,会看到弹出进度条,进度条上的刻度移动,并且伴有响声。通过Developer API调用,会有更多的元素,这里只考虑音量变化,其他的元素之后做分析。
http://developer.android.com/reference/android/media/AudioManager.html
http://developer.android.com/reference/android/media/AudioManager.html
AudioManager.adjustStreamVolume(int streamType, int direction, int flags)
AudioManager.adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags)
AudioManager.setStreamVolume(int streamType, int index, int flags)
AudioManager.adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags)
AudioManager.setStreamVolume(int streamType, int index, int flags)