嵌入式音频开发(2)- AudioService初始化

代码路径

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