Android.media.AudioManager中包含了对android.media.AudioService的跨进程AIDL调用封装。因此,调整音量是通过AudioManager间接调用AudioService.adjustStreamVolume方法完成。
音量调整分为两步:先查看模式(Ring mode)是否需要调整,如果不需要调整模式,当前模式一定是正常模式(Normal mode),那就需要调整音量。
调整模式通过调用checkForRingerModeChange(oldIndex, direction);实现,调整音量通过调用streamState.adjustIndex(direction)实现。具体代码参考/framework/base/media/java/android/media/AudioService.java中的public void adjustStreamVolume(int streamType, int direction, int flags)方法。
该方法先检查模式是否需要调整,再进行音量调整。调整完毕后,做了两件事:
1、通过mVolumePanel.postVolumeChanged(streamType, flags);向用户显示改变结果。
2、通过sendVolumeUpdate(streamType);广播音量有改变的系统事件。
改变音量这个功能与用户界面有关的有两个部分,分别是/framework/base/core/java/android/view/VolumePanel.java和/framework/base/services/java/com/android/server/status/StatusBarPolicy.java。
VolumePanel主要负责向用户显示一个Toast,告诉用户目前的模式(Ring Mode)和音量大小。每次AudioService通过向post一系列Message给VolumePanel,来驱动Toast的显示。
StatusBarPolicy主要负责在静音模式(silent mode)和振动模式(vibrate mode)下在状态栏(status bar)的右方显示一个代表相应意义的图标。
系统启动后,StatusBarPolicy会注册一个Receiver,它可以接收很多种广播,其中就有AudioService在完成每一次的模式和音量更新时发出的两个广播事件AudioManager.RINGER_MODE_CHANGED_ACTION和AudioManager.VIBRATE_SETTING_CHANGED_ACTION。
接收到这两个事件时,StatusBarPolicy就会调用updateVolume()来更新状态栏上的图标。