1. 从AudioService.java 的方法入手,
doSetMasterVolume(),主要干了三件事,
1)AudioSystem.setMasterVolume(volume);
2)sendMsg(mAudioHandler, MSG_PERSIST_MASTER_VOLUME, SENDMSG_REPLACE, Math.round(volume * (float)1000.0), 0, null, PERSIST_DELAY);
3)sendMasterVolumeUpdate(flags, oldVolume, newVolume);
private void doSetMasterVolume(float volume, int flags) {
// don't allow changing master volume when muted
if (!AudioSystem.getMasterMute()) {
int oldVolume = getMasterVolume();
A<span style="background-color: rgb(102, 255, 255);">udioSystem.setMasterVolume(volume);</span>
int newVolume = getMasterVolume();
if (newVolume != oldVolume) {
// Post a persist master volume msg
<span style="background-color: rgb(102, 255, 255);">sendMsg(mAudioHandler, MSG_PERSIST_MASTER_VOLUME, SENDMSG_REPLACE,</span>
Math.round(volume * (float)1000.0), 0, null, PERSIST_DELAY);
setSystemAudioVolume(oldVolume, newVolume, getMasterMaxVolume(), flags);
}
// Send the volume update regardless whether there was a change.
<span style="background-color: rgb(102, 255, 255);">sendMasterVolumeUpdate(flags, oldVolume, newVolume);</span>
}
}
1.1 sendMsg(mAudioHandler, MSG_PERSIST_MASTER_VOLUME, SENDMSG_REPLACE,..)
setMasterVolume 是调用的audiosystem.java,暂时先放一放。先来分析sendMsg(mAudioHandler, MSG_PERSIST_MASTER_VOLUME, SENDMSG_REPLACE,
其实就是往mAudioHandler发消息。handler机制。mAudioHandler的创建的位置。
1)这个是再另一个线程中创建的,下面看下创建的流程:
》》 AudioService对象的构造函数中,调用 createAudioSystemThread(); 创建音频audiosystem线程,并运行此线程。
》》 AudioSystemThread 线程类。
private void createAudioSystemThread() {
mAudioSystemThread = new AudioSystemThread();
mAudioSystemThread.start();
waitForAudioHandlerCreation();
}
》》 在audiosystem线程类中创建mAudioHandler,,用来不断的接受其他线程发送来的消息。handler的创建方法,请参考其他资料。
/** Thread that handles native AudioSystem control. */
private class AudioSystemThread extends Thread {
AudioSystemThread() {
super("AudioService");
}
@Override
public void run() {
// Set this thread up so the handler will work on it
Looper.prepare();
synchronized(AudioService.this) {
mAudioHandler = new AudioHandler();
// Notify that the handler has been created
AudioService.this.notify();
}
// Listen for volume change requests that are set by VolumePanel
Looper.loop();
}
}
》》 AudioHandler 继承于Handler ,并实现handleMessage 方法,通过handleMessage方法处理不同的消息。
private class AudioHandler extends Handler {
<span style="white-space:pre"> </span>....
<span style="white-space:pre"> </span>....
public void handleMessage(Message msg) {
switch (msg.what) {
<span style="white-space:pre"> </span>....
<span style="white-space:pre"> </span>....
case MSG_PERSIST_MASTER_VOLUME:
if (mUseFixedVolume) {
return;
}
Settings.System.putFloatForUser(mContentResolver,
Settings.System.VOLUME_MASTER,
msg.arg1 / (float)1000.0,
UserHandle.USER_CURRENT);
break;
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>}
}
1.2 sendMasterVolumeUpdate(flags, oldVolume, newVolume);
1) 主要有两个动作,一个是更新UI,另一个是广播音量变化的消息。
// UI update and Broadcast Intent
private void sendMasterVolumeUpdate(int flags, int oldVolume, int newVolume) {
mVolumeController.postMasterVolumeChanged(updateFlagsForSystemAudio(flags));
Intent intent = new Intent(AudioManager.MASTER_VOLUME_CHANGED_ACTION);
intent.putExtra(AudioManager.EXTRA_PREV_MASTER_VOLUME_VALUE, oldVolume);
intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_VALUE, newVolume);
sendBroadcastToAll(intent);
}
2) 更新音量相关的UI。
mVolumeController.postMasterVolumeChanged(updateFlagsForSystemAudio(flags));
这个操作时由音量控制器的类完成的。控制器中的setController 方法将传入一个IVolumeController 类型的controller。
/** The controller for the volume UI. */
private final VolumeController mVolumeController = new VolumeController();
public void setController(IVolumeController controller) {
mController = controller;
mVisible = false;
}
3) 通过广播的形式发送音量变化的消息,带由于两个参数,一个是修改前的音量,一个是修改后的音量。
Intent intent = new Intent(AudioManager.MASTER_VOLUME_CHANGED_ACTION);
intent.putExtra(AudioManager.EXTRA_PREV_MASTER_VOLUME_VALUE, oldVolume);
intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_VALUE, newVolume);
sendBroadcastToAll(intent);
在看下sendBroadcastToAll 方法,其中调用的
Binder.clearCallingIdentity(); —- 清除远程调用的PID UID,设置为本进程的PID,UID.
Binder.restoreCallingIdentity(ident); —恢复远程调用进程的PID,UID.
sendBroadcastAsUser() 和 sendBroadcast(),只不过sendBroadcastAsUser()是4.2以后为多用户而新增加的方法。
UserHandle.ALL —设备所有用户可以接收到
UserHandle.CURRENT —设备当前用户
UserHandle.CURRENT_OR_SELF —当前用户和应用所属用户
UserHandle.OWNER — 设备的所有者
源码:
private void sendBroadcastToAll(Intent intent) {
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
final long ident = Binder.clearCallingIdentity();
try {
mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
接下来需要分析audioflinger 和 audiopolicy, 画流程图会比较清晰些。
参考:
http://blog.csdn.net/ffmpeg4976/article/details/50568517
http://blog.csdn.net/ffmpeg4976/article/details/50568485
http://blog.csdn.net/ffmpeg4976/article/details/50568637
http://blog.csdn.net/windskier/article/details/6921672