标签:framework 音量调节 系统音量条显示 源码解析
上篇里面提到了声音调整的两种操作,接下来就要具体分析下音量调节的大概步骤,分别涉及到两部分:
android\frameworks\base\media\java\android\media\AudioService.java
android\frameworks\base\media\java\android\media\IAudioService.aidl
其中adjustStreamVolume(int streamType, int direction, int flags)函数的声明是在AudioService.aidl中,而函数的实现是在AudioService.java中。
下面具体可以看源码:
/** @see AudioManager#adjustStreamVolume(int, int, int) */
public void adjustStreamVolume(int streamType, int direction, int flags) {
if (DEBUG_VOL) Log.d(TAG, "adjustStreamVolume() stream="+streamType+", dir="+direction);
ensureValidDirection(direction);
ensureValidStreamType(streamType);
// use stream type alias here so that streams with same alias have the same behavior,
// including with regard to silent mode control (e.g the use of STREAM_RING below and in
// checkForRingerModeChange() in place of STREAM_RING or STREAM_NOTIFICATION)
int streamTypeAlias = mStreamVolumeAlias[streamType];
VolumeStreamState streamState = mStreamStates[streamTypeAlias];
final int device = getDeviceForStream(streamTypeAlias);
// get last audible index if stream is muted, current index otherwise
final int aliasIndex = streamState.getIndex(device,
(streamState.muteCount() != 0) /* lastAudible */);
boolean adjustVolume = true;
// convert one UI step (+/-1) into a number of internal units on the stream alias
int step = rescaleIndex(10, streamType, streamTypeAlias);
// If either the client forces allowing ringer modes for this adjustment,
// or the stream type is one that is affected by ringer modes
if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
(streamTypeAlias == getMasterStreamType())) {
int ringerMode = getRingerMode();
// do not vibrate if already in vibrate mode
if (ringerMode == AudioManager.RINGER_MODE_VIBRATE) {
flags &= ~AudioManager.FLAG_VIBRATE;
}
// Check if the ringer mode changes with this volume adjustment. If
// it does, it will handle adjusting the volume, so we won't below
adjustVolume = checkForRingerModeChange(aliasIndex, direction, step);
if ((streamTypeAlias == getMasterStreamType()) &&
(mRingerMode == AudioManager.RINGER_MODE_SILENT)) {
streamState.setLastAudibleIndex(0, device);
}
}
// If stream is muted, adjust last audible index only
int index;
final int oldIndex = mStreamStates[streamType].getIndex(device,
(mStreamStates[streamType].muteCount() != 0) /* lastAudible */);
if (streamState.muteCount() != 0) {
if (adjustVolume) {
// Post a persist volume msg
// no need to persist volume on all streams sharing the same alias
streamState.adjustLastAudibleIndex(direction * step, device);
sendMsg(mAudioHandler,
MSG_PERSIST_VOLUME,
SENDMSG_QUEUE,
PERSIST_LAST_AUDIBLE,
device,
streamState,
PERSIST_DELAY);
}
index = mStreamStates[streamType].getIndex(device, true /* lastAudible */);
} else {
if (adjustVolume && streamState.adjustIndex(direction * step, device)) {
// Post message to set system volume (it in turn will post a message
// to persist). Do not change volume if stream is muted.
sendMsg(mAudioHandler,
MSG_SET_DEVICE_VOLUME,
SENDMSG_QUEUE,
device,
0,
streamState,
0);
}
index = mStreamStates[streamType].getIndex(device, false /* lastAudible */);
}
sendVolumeUpdate(streamType, oldIndex, index, flags);
} 解析上面函数可知,函数最开始会有一个对于前两个参数有效性的检测,贴出具体的检测代码:
private void ensureValidDirection(int direction) {
if (direction < AudioManager.ADJUST_LOWER || direction > AudioManager.ADJUST_RAISE) {
throw new IllegalArgumentException("Bad direction " + direction);
}
}
private void ensureValidSteps(int steps) {
if (Math.abs(steps) > MAX_BATCH_VOLUME_ADJUST_STEPS) {
throw new IllegalArgumentException("Bad volume adjust steps " + steps);
}
}
private void ensureValidStreamType(int streamType) {
if (streamType < 0 || streamType >= mStreamStates.length) {
throw new IllegalArgumentException("Bad stream type " + streamType);
}
} 继续跟进源码,可以看到
int step = rescaleIndex(10, streamType, streamTypeAlias);
此参数为调整步进数值的
再下面的判断条件if (streamState.muteCount() != 0)为判断是否是从静音状态发起的音量调整以便进行不同的操作。
在函数的最后
sendVolumeUpdate(streamType, oldIndex, index, flags);
此函数则是用于更新系统音量条的显示
// UI update and Broadcast Intent
private void sendVolumeUpdate(int streamType, int oldIndex, int index, int flags) {
if (!mVoiceCapable && (streamType == AudioSystem.STREAM_RING)) {
streamType = AudioSystem.STREAM_NOTIFICATION;
}
mVolumePanel.postVolumeChanged(streamType, flags);
oldIndex = (oldIndex + 5) / 10;
index = (index + 5) / 10;
Intent intent = new Intent(AudioManager.VOLUME_CHANGED_ACTION);
if (streamType == AudioManager.STREAM_VOICE_CALL)
streamType = AudioManager.STREAM_MUSIC;
intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, streamType);
intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, index);
intent.putExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, oldIndex);
mContext.sendBroadcast(intent);
} 可以看到源码中调用了
\android\frameworks\base\core\java\android\view\VolumePanel.java
其中VolumePanel.java则用于显示系统音量条的显示,其中具体如何显示可以参考代码。同时此部分代码中会涉及到系统所有音量相关的图标显示,需要进行修改美化等操作的可以具体找到资源文件进行修改。
具体路径可以在
android\frameworks\base\core\res\res
另一种设置音量的方法setStreamVolume(int streamType, int index, int flags)也是同样的可以在上述代码中找到,关于音量调整的部分解析到此基本结束,暂时可以明白的就上述的流程了。
Android FrameWork音频管理AudioManager的一点解析(续一)
标签:framework 音量调节 系统音量条显示 源码解析
原文地址:http://blog.csdn.net/zhanghaofor/article/details/42100261