4.1 AudioPolicy的诞生
AudioPolicyService是Android音频系统的两大服务之一,另一个服务是AudioFlinger,这两大服务都在系统启动时有MediaSever加载,代码在framework/base/media/MediaServer/Main_MediaServer中。
感觉上,AudioFlinger的构造函数就是创建了一个最重要的AudioHardWare的HAL代表。注意整个系统就这一个AudioHardware了。也就是说,不管是线控耳机,蓝牙耳机,麦克,外放等等,最后都会由这一个HAL统一管理。
rc = mpAudioPolicy->init_check(mpAudioPolicy); }
构造函数中调用了policy_hal中的create_audio_policy函数和init_check函数,create_audio_policy函数的目的是设置回调函数并且调用createAudioPolicyManager函数创建AudioPolicyManager(apm)的实例。init_check函数调用的apm的init_check函数,即是AudioPolicyManagerBase的init_check函数。不同厂商还可以实现自己的AudioPolicyManager,这样做的好处就是把server断和client端分离,减少代码的耦合度。
int create_legacy_ap(){
......
lap->service_client = new AudioPolicyCompatClient(aps_ops, service);
lap->apm = createAudioPolicyManager(lap->service_client);
}
该函数首先创建一个client对象,再把client对象传给audiopolicy的server端。client调用的接口函数最终会调用server的接口函数。
构造函数就会使用mpClientInterface来访问AudioPolicyService。
AudioPolicyManagerBase::AudioPolicyManagerBase(AudioPolicyClientInterface *clientInterface)
{
......
for (size_t i = 0; i < mHwModules.size(); i++) {
mHwModules[i]->mHandle = mpClientInterface->loadHwModule(mHwModules[i]->mName);
if (mHwModules[i]->mHandle == 0) {
ALOGW("could not open HW module %s", mHwModules[i]->mName);
continue;
}
......
}
4.2.1 AudioPolicyService主要完成:
1、JAVA应用层通过JNI,经由IAudioPolicyService接口,访问AudioPolicyService提供的服务
2、输入输出设备的连接状态
3、系统的音频策略(strategy)的切换
4、音量/音频参数的设置
4.2.2 AudioPolicyService的构成
1、AudioPolicyService继承了IAudioPolicyService接口,这样AudioPolicyService就可以基于Android的Binder机制,向外部提供服务;
2、AudioPolicyService同时也继承了AudioPolicyClientInterface类,它有一个AudioPolicyInterface类的成员指针mpPolicyManager,实际上就是指向了AudioPolicyManager;
3、AudioPolicyManager类继承了AudioPolicyInterface类以便向AudioPolicyService提供服务,反过来同时还有一个AudioPolicyClientInterface指针,该指针在构造函数中被初始化,指向了AudioPolicyService,实际上,AudioPolicyService是通过成员指针mpPolicyManager访问AudioPolicyManager,而AudioPolicyManager则通过AudioPolicyClientInterface(mpClientInterface)访问AudioPolicyService;
4、AudioPolicyService有一个内部线程类AudioCommandThread,顾名思义,所有的命令(音量控制,输入、输出的切换等)最终都会在该线程中排队执行;
4.3 AudioPolicyManager
AudioPolicyService的很大一部分管理工作都是在AudioPolicyManager中完成的。包括音量管理,音频策略(strategy)管理,输入输出设备管理。
4.3.1 输入输出设备管理
音频系统为音频设备定义了一个枚举:AudioSystem::audio_devices,例如:DEVICE_OUT_SPEAKER,DEVICE_OUT_WIRED_HEADPHONE,DEVICE_OUT_BLUETOOTH_A2DP,DEVICE_IN_BUILTIN_MIC,DEVICE_IN_VOICE_CALL等等,每一个枚举值其实对应一个32bit整数的某一个位,所以这些值是可以进行位或操作的,例如我希望同时打开扬声器和耳机,那么可以这样:
newDevice = DEVICE_OUT_SPEAKER | DEVICE_OUT_WIRED_HEADPHONE;
setOutputDevice(mHardwareOutput, newDevice);
AudioPolicyManager中有两个成员变量:mAvailableOutputDevices和mAvailableInputDevices,他们记录了当前可用的输入和输出设备,当系统检测到耳机或者蓝牙已连接好时,会调用AudioPolicyManager的成员函数:
status_t AudioPolicyManager::setDeviceConnectionState(AudioSystem::audio_devices device, AudioSystem::device_connection_state state,const char *device_address)
该函数根据传入的device值和state(DEVICE_STATE_AVAILABLE/DEVICE_STATE_UNAVAILABLE)设置mAvailableOutputDevices或者mAvailableInputDevices,然后选择相应的输入或者输出设备。
其他一些相关的函数:
1、setForceUse() 设置某种场合强制使用某一设备,例如setForceUse(FOR_MEDIA, FORCE_SPEAKER)会在播放音乐时打开扬声器
2、startOutput()/stopOutput()
3、startInput()/stopInput()
4.3.2 音量管理AudioPolicyManager提供了一下几个与音量相关的函数:
1、initStreamVolume(AudioSystem::stream_type stream, int indexMin, int indexMax)
2、setStreamVolumeIndex(AudioSystem::stream_type stream, int index)
3、getStreamVolumeIndex(AudioSystem::stream_type stream)
AudioService.java中定义了每一种音频流的最大音量级别:/** @hide Maximum volume index values for audio streams */
private int[] MAX_STREAM_VOLUME = new int[] {
5, // STREAM_VOICE_CALL
7, // STREAM_SYSTEM
7, // STREAM_RING
15, // STREAM_MUSIC
7, // STREAM_ALARM
7, // STREAM_NOTIFICATION
15, // STREAM_BLUETOOTH_SCO
7, // STREAM_SYSTEM_ENFORCED
15, // STREAM_DTMF
15 // STREAM_TTS
};
由此可见,电话铃声可以有7个级别的音量,而音乐则可以有15个音量级别,java的代码通过jni,最后调用AudioPolicyManager的initStreamVolume(),把这个数组的内容传入AudioPolicyManager中,这样AudioPolicyManager也就记住了每一个音频流的音量级别。应用程序可以调用setStreamVolumeIndex设置各个音频流的音量级别,setStreamVolumeIndex会把这个整数的音量级别转化为适合人耳的对数级别,然后通过AudioPolicyService的AudioCommandThread,最终会将设置应用到AudioFlinger的相应的Track中。
4.3.3 音频策略管理
我想首先要搞清楚stream_type,device,strategy三者之间的关系:
1、AudioSystem::stream_type 音频流的类型,一共有10种类型
2、AudioSystem::audio_devices 音频输入输出设备,每一个bit代表一种设备,见前面的说明
3、AudioPolicyManager::routing_strategy 音频路由策略,可以有4种策略
getStrategy(stream_type)根据stream type,返回对应的routing strategy值,getDeviceForStrategy()则是根据routing strategy,返回可用的device。Android把10种stream type归纳为4种路由策略,然后根据路由策略决定具体的输出设备。
4.3.4 成员变量mOutputs
KeyedVector
这是AudioPolocyManager用来管理输出的键值对向量(数组),通常AudioPolocyManager会打开3个输出句柄(audio_io_handle_t),关于audio_io_handle_t,它实际上就是AudioFlinger中某个PlaybackTread的ID。这3个句柄分别是:
可以通过startOutput()把某一个stream type放入到相应的输出中。
4.3.5 popCount()这个函数主要用来计算device变量中有多少个非0位(计算32位数种1的个数),例如该函数返回2,代表同时有两个device要处理。之所以特别介绍它,是因为这个函数的实现很有意思:
uint32_t AudioSystem::popCount(uint32_t u)
{
u = ((u&0x55555555) + ((u>>1)&0x55555555));
u = ((u&0x33333333) + ((u>>2)&0x33333333));
u = ((u&0x0f0f0f0f) + ((u>>4)&0x0f0f0f0f));
u = ((u&0x00ff00ff) + ((u>>8)&0x00ff00ff));
u = ( u&0x0000ffff) + (u>>16);
return u;
}
4.3.6 AudioCommandThread
这是AudioPolicyService中的一个线程,主要用于处理音频设置相关的命令。包括:
每种命令的参数有相应的包装:
START_TONE/STOP_TONE:播放电话系统中常用的特殊音调,例如:TONE_DTMF_0,TONE_SUP_BUSY等等。
SET_VOLUME:最终会调用AudioFlinger进行音量设置
SET_VOICE_VOLUME:最终会调用AudioFlinger进行电话音量设置
SET_PARAMETERS:通过一个KeyValuePairs形式的字符串进行参数设置,KeyValuePairs的格式可以这样:
这些KeyValuePairs可以通过AudioPolicyService的成员函数setParameters()传入。
4.3 AudioPolicy总结
1、AudioPolicyService才是真正调用AudioFlinger的地方,Audio_poliy_hal、AudioPolicyManagerBase最终都会绕到AudioPolicyService里面去。
2、AduioPolicyService调用AudioFlinger里面的函数,是通过Binder机制,即调用接口IAudioFlinger接口。
3、AudioPolicyService只提供服务给AudioSystem.cpp,通过Binder接口调用。其他类不可以直接调用AudioPolicyService类,只能调用AudioSystem里面的方法间接调用AudioPolicyService。