代码路径
AudioService类对应的Java文件是
/frameworks/base/services/core/java/com/android/server/audio/AudioService.java
阅读Android代码的时候,通过看代码路径可以大致知道模块在整个android系统中处于什么层次,以及模块的性质。这里就简单提一下(如有错误欢迎指正):
frameworks目录包含的是所有Android框架的代码。
frameworks下我们经常用到的两个目录分别是base和av。base目录下放的是java代码,av目录下则是c++代码。
从AudioService的路径我们可以知道audioservice是个音频相关的服务(server)。在frameworks/base/services/core/java/com/android/server/ 目录下有Android的各类java服务的代码。
通过浏览器阅读Android源码的链接(http://xrefandroid.com/) ,通过这个网站可以快速检阅代码,大公司一般都有自己的内源替代。
AudioService服务启动
场景:AudioService服务启动一般发生在设备/芯片开机或者重启的时候。如果出现类似开机后系统状态/参数不对,可以考虑从这里作为思考的出发点。
代码实现:AudioService定义内部类Lifecycle,Lifecycle继承SystemService。Lifecycle的构造函数会创建AudioService对象。并在onstart函数中完成AudioService的发布(这步完成后,其它进程就可以获取AudioService的binder句柄并藉此使用AudioService提供的服务)。如果我们要在Android系统中开发自己的server。我们就可以参考这个流程进行开发。
AudioService.Lifecycle由SystemServer负责启动,具体的流程和代码如下。
SystemServer启动audioservice 代码
/frameworks/base/services/java/com/android/server/SystemServer.java
调用链
run() >>> startOtherServices() >>> startService(AudioService.Lifecycle.class)
private void startOtherServices() {
...//启动其它Android非核心服务
//启动音频服务
1470 traceBeginAndSlog("StartAudioService");
1471 if (!isArc) {
1472 mSystemServiceManager.startService(AudioService.Lifecycle.class);
1473 } else {
1474 String className = context.getResources()
1475 .getString(R.string.config_deviceSpecificAudioService);
1476 try {
1477 mSystemServiceManager.startService(className + "$Lifecycle");
1478 } catch (Throwable e) {
1479 reportWtf("starting " + className, e);
1480 }
1481 }
1482 traceEnd();
...
}
内部类Lifecycle
从职责分工的角度看,通过内部类Lifecycle继承SystemService 而不是AudioService本身继承是更加合理的。这样AudioService的代码就更加聚焦于自己的业务。如果需要更换其它的方式启动Audioservice可以不需要修改AudioService的代码。但是Lifecycle作为内部类改Lifecycle的代码又无法避免要修改AudioService对应的文件。要想不修改AudioService的文件换启动方式的话,也可以不动Lifecycle的代码,只要不启动Lifecycle而采用其他方式实例化AudioService就行了。
部类Lifecycle
577 public static final class Lifecycle extends SystemService {
578 private AudioService mService;
579
580 public Lifecycle(Context context) {
581 super(context);
582 mService = new AudioService(context);
583 }
584
585 @Override
586 public void onStart() {
587 publishBinderService(Context.AUDIO_SERVICE, mService);
588 }
589
590 @Override
591 public void onBootPhase(int phase) {
592 if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
593 mService.systemReady();
594 }
595 }
596 }
597
总结:AudioService属于Android的server,由SystemServer负责启动后完成实例化并注册成为跨进程服务。
通过上面的内容,我们已经知道audioservice是怎么被实例化的,接下来我们看看audioservice在构造函数中做了哪些工作。
AudioService初始化
下面列出AudioService构造函数中比较常见的内容并给出注释。
public AudioService(Context context) {
//保存context,Android开发中context是个很重要的角色,很多资源的获取和功能的执行都涉及context
630 mContext = context;
//用于音量持久化
631 mContentResolver = context.getContentResolver();
//通过property获得媒体音量的步进数
684 int maxMusicVolume = SystemProperties.getInt("ro.config.media_vol_steps", -1);
685 if (maxMusicVolume != -1) {
686 MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] = maxMusicVolume;
687 }
//通过property获得媒体音量的默认值
689 int defaultMusicVolume = SystemProperties.getInt("ro.config.media_vol_default", -1);
690 if (defaultMusicVolume != -1 &&
691 defaultMusicVolume <= MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] &&
692 defaultMusicVolume >= MIN_STREAM_VOLUME[AudioSystem.STREAM_MUSIC]) {
693 AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] = defaultMusicVolume;
694 } else {
695 if (isPlatformTelevision()) {
696 AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] =
697 MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] / 4;
698 } else {
699 AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] =
700 MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] / 3;
701 }
702 }
//系统是否使用固定音量
760 mUseFixedVolume = mContext.getResources().getBoolean(
761 com.android.internal.R.bool.config_useFixedVolume);
762
//初始化音频设备代理 ,AudioDeviceBroker是AudioService负责管理音频设备的子类
763 mDeviceBroker = new AudioDeviceBroker(mContext, this);
764
765 // must be called before readPersistedSettings() which needs a valid mStreamVolumeAlias[]
766 // array initialized by updateStreamVolumeAlias()
767 updateStreamVolumeAlias(false /*updateVolumes*/, TAG);
//读取持久化数据(音频配置)
768 readPersistedSettings();
769 readUserRestrictions();
//监听settings变化
770 mSettingsObserver = new SettingsObserver();
//创建以及初始化所有volumeStreamState,volumeStreamState是AudioService负责处理音量的子类
771 createStreamStates();
//获取USB安全音量
773 // mSafeUsbMediaVolumeIndex must be initialized after createStreamStates() because it
774 // relies on audio policy having correct ranges for volume indexes.
775 mSafeUsbMediaVolumeIndex = getSafeUsbMediaVolumeIndex();
//设置系统的低内存模式
784 readAndSetLowRamDevice();
}
总结:audioservice主要通过property和Resource获取音频可配置参数,并在构造函数中完成不同业务子类的实例化。我们可以从中学到一些编程经验:
1.将易变(一般是那些会根据产品形态变化的参数)的参数通过可配置的方式进行初始化。
2.将设备管理和音量管理两个业务逻辑解耦,由不同的类负责。
接下来分析AudioService构造函数中一些重点的代码。
所有音量管理类初始化
private void createStreamStates() {
1198 int numStreamTypes = AudioSystem.getNumStreamTypes();
1199 VolumeStreamState[] streams = mStreamStates = new VolumeStreamState[numStreamTypes];
1200
1201 for (int i = 0; i < numStreamTypes; i++) {
1202 streams[i] =
1203 new VolumeStreamState(System.VOLUME_SETTINGS_INT[mStreamVolumeAlias[i]], i);
1204 }
1205
1206 checkAllFixedVolumeDevices();
1207 checkAllAliasStreamVolumes();
1208 checkMuteAffectedStreams();
1209 updateDefaultVolumes();
1210 }
1211
1212 // Update default indexes from aliased streams. Must be called after mStreamStates is created
1213 private void updateDefaultVolumes() {
1214 for (int stream = 0; stream < mStreamStates.length; stream++) {
1215 if (stream != mStreamVolumeAlias[stream]) {
1216 AudioSystem.DEFAULT_STREAM_VOLUME[stream] = rescaleIndex(
1217 AudioSystem.DEFAULT_STREAM_VOLUME[mStreamVolumeAlias[stream]],
1218 mStreamVolumeAlias[stream],
1219 stream);
1220 }
1221 }
1222 }
AudioService中每种streamtype的音量都由一个VolumeStreamState进行管理。createStreamStates会为系统所有的streamtype创建对应的VolumeStreamState。
VolumeStreamState构造函数
private VolumeStreamState(String settingName, int streamType) {
4518
//保存streamtype的名字用于从settings进行读写操作
4519 mVolumeIndexSettingName = settingName;
4520
4521 mStreamType = streamType;
4522 mIndexMin = MIN_STREAM_VOLUME[streamType] * 10;
4523 mIndexMax = MAX_STREAM_VOLUME[streamType] * 10;
4524 AudioSystem.initStreamVolume(streamType, mIndexMin / 10, mIndexMax / 10);
4525
4526 readSettings();
4527 mVolumeChanged = new Intent(AudioManager.VOLUME_CHANGED_ACTION);
4528 mVolumeChanged.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, mStreamType);
4529 mStreamDevicesChanged = new