引言

    AudioPolicyService是Android音频系统的两大服务之一,另一个服务是AudioFlinger,这两大服务都在系统启动时有 MediaSever加载,加载的代码位于:frameworks\base\media\mediaserver \main_mediaserver.cpp。AudioFlinger主要负责管理音频数据处理以及和硬件抽象层相关的工作。本文主要介绍 AudioPolicyService。

AudioPolicyService

    AudioPolicyService主要完成以下任务:

  • JAVA应用层通过JNI,经由 IAudioPolicyService接口,访问AudioPolicyService提供的服务
  • 输入输出设备的连接状态
  • 系 统的音频策略(strategy)的切换
  • 音量/音频参数的设置

    AudioPolicyService的构成

    下面这张图描述了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,顾名思义,所有的命令(音量控制,输入、输出的切换等)最 终都会在该线程中排队执行;

AudioPolicyManager

    AudioPolicyService的很大一部分管理工作都是在AudioPolicyManager中完成的。包括音量管理,音频策略 (strategy)管理,输入输出设备管理。

输入输出设备管理

音频系统为音频设备定义了一个枚 举:AudioSystem::audio_devices,例 如:DEVICE_OUT_SPEAKER,DEVICE_OUT_WIRED_HEADPHONE,DEVICE_OUT_BLUETOOTH_A2DP,DEVICE_IN_BUILTIN_MIC,DEVICE_IN_VOICE_CALL 等等,每一个枚举值其实对应一个32bit整数的某一个位,所以这些值是可以进行位或操作的,例如我希望同时打开扬声器和耳机,那么可以这样:

  1. newDevice = DEVICE_OUT_SPEAKER | DEVICE_OUT_WIRED_HEADPHONE;  
  2. setOutputDevice(mHardwareOutput, newDevice);  
newDevice = DEVICE_OUT_SPEAKER | DEVICE_OUT_WIRED_HEADPHONE; setOutputDevice(mHardwareOutput, newDevice);

AudioPolicyManager中有两个成 员变量:mAvailableOutputDevices和 mAvailableInputDevices,他们记录了当前可用的输入和输出设备,当系统检测到耳机或者蓝牙已连接好时,会调用 AudioPolicyManager的成员函数:

  1. status_t AudioPolicyManager::setDeviceConnectionState(AudioSystem::audio_devices device,  
  2.                                                   AudioSystem::device_connection_state state,  
  3.                                                   const char *device_address)  
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,然后选择相应的输入或者输出设备。

其 他一些相关的函数:

  • setForceUse()  设置某种场合强制使用某一设备,例如setForceUse(FOR_MEDIA, FORCE_SPEAKER)会在播放音乐时打开扬声器
  • startOutput()/stopOutput()
  • startInput()/stopInput()

音量管理

AudioPolicyManager提供了一下几个与音量相关的函数:

  • initStreamVolume(AudioSystem::stream_type stream, int indexMin, int indexMax)
  • setStreamVolumeIndex(AudioSystem::stream_type stream, int index)
  • getStreamVolumeIndex(AudioSystem::stream_type stream)

AudioService.java中定义了每一种音频流的最大音量级别:

  1. /** @hide Maximum volume index values for audio streams */  
  2.     private int[] MAX_STREAM_VOLUME = new int[] {  
  3.         5,  // STREAM_VOICE_CALL  
  4.         7,  // STREAM_SYSTEM  
  5.         7,  // STREAM_RING  
  6.         15, // STREAM_MUSIC  
  7.         7,  // STREAM_ALARM  
  8.         7,  // STREAM_NOTIFICATION  
  9.         15, // STREAM_BLUETOOTH_SCO  
  10.         7,  // STREAM_SYSTEM_ENFORCED  
  11.         15, // STREAM_DTMF  
  12.         15  // STREAM_TTS  
  13.     };  
/** @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中。

音频策略管理

 我想首先要搞清楚stream_type,device,strategy三者之间的关系:

  • AudioSystem::stream_type  音频流的类型,一共有10种类型
  • AudioSystem::audio_devices  音频输入输出设备,每一个bit代表一种设备,见前面的说明
  • AudioPolicyManager::routing_strategy 音频路由策略,可以有4种策略

 

getStrategy(stream_type)根据stream type,返回对应的routing strategy值,getDeviceForStrategy()则是根据routing strategy,返回可用的device。Android把10种stream type归纳为4种路由策略,然后根据路由策略决定具体的输出设备。mode也会影响输出设备的选择。

成员变量mOutputs

  1. KeyedVector mOutputs;   // list of output descriptors  
KeyedVector mOutputs; // list of output descriptors

这 是AudioPolocyManager用管理输出的键值对向量(数组),通常AudioPolocyManager会打开3个输出句柄 (audio_io_handle_t), 它实际上就是AudioFlinger中某个PlaybackTread的ID。这3个句柄分别是:

  • mHardwareOutput            // hardware output handler
  • mA2dpOutput                   // A2DP output handler
  • mDuplicatedOutput          // duplicated output handler: outputs to hardware and A2DP

可以通过 startOutput()把某一个stream type放入到相应的输出中。

popCount()

这个函数主 要用来计算device变量中有多少个非0位(计算32位数种1的个数),例如该函数返回2,代表同时有两个device要处理。之所以特别介绍它,是因 为这个函数的实现很有意思:

  1. uint32_t AudioSystem::popCount(uint32_t u)  
  2. {  
  3.     u = ((u&0x55555555) + ((u>>1)&0x55555555));  
  4.     u = ((u&0x33333333) + ((u>>2)&0x33333333));  
  5.     u = ((u&0x0f0f0f0f) + ((u>>4)&0x0f0f0f0f));  
  6.     u = ((u&0x00ff00ff) + ((u>>8)&0x00ff00ff));  
  7.     u = ( u&0x0000ffff) + (u>>16);  
  8.     return u;  
  9. }  
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; }

不知道各位看懂了么?

AudioCommandThread

    这是AudioPolicyService中的一个线程,主要用于处理音频设置相关的命令。包括:

  • START_TONE
  • STOP_TONE
  • SET_VOLUME
  • SET_PARAMETERS
  • SET_VOICE_VOLUME

     每种命令的参数有相应的包装:

  • class ToneData
  • class VolumeData
  • class ParametersData
  • class VoiceVolumeData

    START_TONE/STOP_TONE:播放电话系统中常用的特殊音调,例如:TONE_DTMF_0,TONE_SUP_BUSY等等。

    SET_VOLUME:最终会调用AudioFlinger进行音量设置

    SET_VOICE_VOLUME:最终会调用AudioFlinger进行电话音量设置

    SET_PARAMETERS:通过一个KeyValuePairs形式的字符串进行参数设置,KeyValuePairs的格式可以这样:

  •  "sampling_rate=44100"
  • "channels=2"
  • "sampling_rate=44100;channels=2"     // 组合形式

    这些KeyValuePairs可以通过AudioPolicyService的成员函数setParameters()传入。

更多相关文章

  1. Android打电话的流程
  2. android闹钟开发(四)--音乐播放与音量调节
  3. menu.addIntentOptions 添加动态菜单详解
  4. Camera服务之--JNI部分
  5. Android游戏开发菜鸟之路(三)
  6. Android(安卓)4.2 Input 流程分析
  7. Android(安卓)vold核心篇(VolumeManager)
  8. Android关于view按键音的修改
  9. Android(安卓)使用Visualizer获取播放音频的频率

随机推荐

  1. Android高德地图自定义放大缩小控件
  2. 【专题】Android(安卓)启动流程相关
  3. Android的SDK与ADT不匹配问题
  4. SQLite语法与Android数据库操作
  5. android EditText inputType说明
  6. Android(安卓)map
  7. Android(安卓)UI(1)Getting Started - Fi
  8. Android(安卓)UI 优化-使用theme 预加载
  9. android 让一个控件按钮居于底部的几种方
  10. 系出名门 Android(安卓)系列文章索引