一篇不错的Android Audio架构代码梳理总结

2019年12月08日 阅读数:475
这篇文章主要向大家介绍一篇不错的Android Audio架构代码梳理总结,主要内容包括基础应用、实用技巧、原理机制等方面,希望对大家有所帮助。

分类: LINUXphp

  

为android系统添加USB AUDIO设备的放音和录音功能

分类: Android原创   3422人阅读  评论(14)  收藏  举报

目录(?)[+]html

转载请注明出处:http://blog.csdn.net/adits/article/details/8242146


开发环境简介

1. 主机系统: Unbuntu10.10
2. android系统版本: 4.0.3(Linux kernel 3.0.8)


综述

android的音频系统很是庞大复杂:涉及到java应用程序,java框架层,JNI,本地服务(AudioFlinger和AudioPolicyService),硬件抽象层HAL,ALSA-LIB和ALSA-DRIVER。
本文将先分析音频系统的启动与模块加载流程,并具体分析一个JAVA API的调用流程;最后在此基础上天然地为android系统添加USB AUDIO设备的放音和录音功能。



全文可分为以下几大部分:

1. 本地服务的启动流程分析。
1.1 AudioFlinger启动流程及其所涉及的HAL层模块启动流程分析。
1.2 AudioPolicyService启动流程及其所涉及的HAL层模块启动流程分析。

2. JAVA API setDeviceConnectionState()调用流程详解,同时为android系统添加USB AUDIO设备的放音和录音功能。

3. ALSA-LIB浅述以及asound.conf配置文件的书写。

4. 从新获取USB AUDIO设备的硬件参数。



详述

1. 本地服务的启动流程分析。

AudioFlinger和AudioPolicyService两大音频服务都是在android系统启动时就启动的。

当linux kenerl启动完成后,会启动android的init进程(system/core/init/init.c)。java


  1. <span style=< span="" style="word-wrap: break-word;">"font-size:24px;">int main(int argc, char **argv)  
  2. {  
  3.     .....  
  4.   
  5.     init_parse_config_file("/<span style="< span="" style="word-wrap: break-word;">color:#ff0000;">init.rc");  
  6.   
  7.     .....  
  8. }  


init.rc文件中保存了许多系统启动时须要启动的服务。其中就有多媒体服务mediaserver的启动:node


[plain]  view plain copy print ?
  1. service media /system/bin/mediaserver  



此服务在文件frameworks/base/media/mediaserver/main_mediaserver.cpp中定义,而音频子系统的两大本地服务AudioFlinger和AudioPolicyService就是在此启动的。linux


  1. <span xmlns=< span="" style="word-wrap: break-word;">"http://www.w3.org/1999/xhtml" style="font-size:24px;">int main(int argc, char** argv)  
  2. {  
  3.   .....  
  4.   
  5.     <span style="color:#ff0000;">AudioFlinger::instantiate();  <span style=< span="" style="word-wrap: break-word;">"color:#3333ff;">//实例化AudioFlinger  
  6.     .....  
  7.   
  8.     <span style="color:#ff0000;">AudioPolicyService::instantiate(); <span style=< span="" style="word-wrap: break-word;">"color:#3333ff;">//实例化AudioPolicyService  
  9.       
  10.     .....  
  11. }  



1.1 AudioFlinger启动流程及其所涉及的HAL层模块启动流程分析。

   根据上文分析,将调用AudioFlinger::instantiate()函数实例化AudioFlinger。可是AudioFlinger.cpp中并无找到此函数,那必然在其父类中。AudioFlinger类有不少父类,一时难以肯定instantiate()到底在哪一个父类中定义的。直接搜索吧!
grep -rn "instantiate"  frameworks/base/ 
很快找到instantiate()函数的定义处在./frameworks/base/include/binder/BinderService.h头文件中
android


  1. <span xmlns=< span="" style="word-wrap: break-word;">"http://www.w3.org/1999/xhtml" style="font-size:24px;">template<typename SERVICE>  
  2. class BinderService  
  3. {  
  4. public:  
  5.     static status_t publish() {  
  6.         sp sm(defaultServiceManager());  
  7.         return sm->addService(String16(<span style=< span="" style="word-wrap: break-word;">"color:#ff0000;">SERVICE::getServiceName()), <span style=< span="" style="word-wrap: break-word;">"color:#ff0000;">new SERVICE());  
  8.   
  9.     ......  
  10.   
  11.     static void instantiate() { publish(); }  
  12.   
  13.     .....  
  14.     }    
  15. }  


这里用到了模板,须要肯定SERVICE是什么东东。
AudioFlinger类是在AudioFlinger.h中定义的,而刚好包含了头文件BinderService.h。
数组


  1. <span xmlns=< span="" style="word-wrap: break-word;">"http://www.w3.org/1999/xhtml" style="font-size:24px;">class AudioFlinger :  
  2.     public <span style=< span="" style="word-wrap: break-word;">"color:#ff0000;">BinderService,  
  3.     public BnAudioFlinger  
  4. {  
  5.     friend class BinderService;  
  6. public:  
  7.     static char const* getServiceName() { return "media.audio_flinger"; }  
  8.   
  9.     .....  
  10.   
  11. }  


原来AudioFlinger类继承了BinderService类,同时把本身(AudioFlinger)传递给SERVICE。而addService函数第一个参数调用了AudioFlinger类的静态成员函数getServiceName()获取AudioFlinger的服务名称;其第二个参数即是建立了一个AudioFlinger的实例。至此,明白了实例化函数instantiate()就是要向服务管理器注册的服务是AudioFlinger。
既然此时实例化了AudioFlinger,那么看看AudioFlinger类的构造函数具体作了哪些初始化工做。
架构


  1. <span xmlns=< span="" style="word-wrap: break-word;">"http://www.w3.org/1999/xhtml" style="font-size:24px;">AudioFlinger::AudioFlinger()  
  2.     : BnAudioFlinger(),  
  3.         mPrimaryHardwareDev(0), mMasterVolume(1.0f), mMasterMute(false), mNextUniqueId(1),  
  4.         mBtNrecIsOff(false)  
  5. {  
  6. }  


此构造函数作了一些可有可无的事情,无论它。既然AudioFlinger服务是第一次启动,则将调到函数AudioFlinger::onFirstRef(至于为何,我尚未搞明白,能够经过log信息确信确实是这么回事)。并发


void AudioFlinger::onFirstRef()
{
    ......

    for (size_t i = 0; i < ARRAY_SIZE(audio_interfaces); i++) {
        const hw_module_t *mod;
        audio_hw_device_t *dev;

        rc = load_audio_interface(audio_interfaces[i], &mod,&dev);

        .....

        mAudioHwDevs.push(dev); // 把经过load_audio_interface()函数得到的设备存入元素为audio_hw_device_t
app

                                                     // 类型的模板变量mAudioHwDevs中

    
    .....

}

看到load_audio_interface()函数的名字,知晓,应当是加载音频接口的。



  1. <span style=< span="" style="word-wrap: break-word;">"font-size:24px;">static int load_audio_interface(const char *if_name, const hw_module_t **mod,  
  2.                                 audio_hw_device_t **dev)  
  3. {         
  4.     ......  
  5.   
  6.     rc = <span style="color:#ff0000;">hw_get_module_by_class(<span style=< span="" style="word-wrap: break-word;">"color:#ff0000;">AUDIO_HARDWARE_MODULE_ID, if_name, mod);  
  7.     if (rc)  
  8.         goto out;  
  9.           
  10.     rc = <span style="color:#ff0000;">audio_hw_device_open(*mod, <span style=< span="" style="word-wrap: break-word;">"color:#ff0000;">dev);  
  11.   
  12.     .....  
  13.   
  14. }  



首先经过函数hw_get_module_by_class获取ID号为AUDIO_HARDWARE_MODULE_ID的音频模块,此ID在头文件hardware/libhardware/include/hardware/audio.h中定义。此头文件中定义了一个十分重要的结构体struct audio_hw_device,其中包含了许多函数接口(函数指针):


  1. <span style=< span="" style="word-wrap: break-word;">"font-size:24px;">struct audio_hw_device {  
  2.     struct hw_device_t common;  
  3.   
  4.     /**  
  5.      * used by audio flinger to enumerate what devices are supported by 
  6.      * each audio_hw_device implementation. 
  7.      * 
  8.      * Return value is a bitmask of 1 or more values of audio_devices_t 
  9.      */  
  10.     uint32_t (*<span style="color:#ff0000;">get_supported_devices)(const struct audio_hw_device *dev);  
  11.   
  12.     /**  
  13.      * check to see if the audio hardware interface has been initialized. 
  14.      * returns 0 on success, -ENODEV on failure. 
  15.      */  
  16.     int (*<span style=< span="" style="word-wrap: break-word;">"color:#ff0000;">init_check)(const struct audio_hw_device *dev);  
  17.   
  18.    ......  
  19.   
  20.     /* set/get global audio parameters */  
  21.     int (*<span style=< span="" style="word-wrap: break-word;">"color:#ff0000;">set_parameters)(struct audio_hw_device *dev, const char *kv_pairs);  
  22.   
  23.    .....  
  24.   
  25.     /** This method creates and opens the audio hardware output stream */  
  26.     int (*<span style=< span="" style="word-wrap: break-word;">"color:#ff0000;">open_output_stream)(struct audio_hw_device *dev, uint32_t devices,  
  27.                               int *format, uint32_t *channels,  
  28.                               uint32_t *sample_rate,  
  29.                               struct audio_stream_out **out);  
  30.   
  31.    ......  
  32.   
  33.     /** This method creates and opens the audio hardware input stream */  
  34.     int (*open_input_stream)(struct audio_hw_device *dev, uint32_t devices,  
  35.                              int *format, uint32_t *channels,  
  36.                              uint32_t *sample_rate,  
  37.                              audio_in_acoustics_t acoustics,  
  38.                              struct audio_stream_in **stream_in);  
  39.   
  40.    .....  
  41. }  


ID为AUDIO_HARDWARE_MODULE_ID的音频模块到底在哪儿定义的那?既然是HAL层模块,一定在hardware目录下定义的


[plain]  view plain copy print ?
  1. $ grep -rn AUDIO_HARDWARE_MODULE_ID hardware/  
  2. hardware/libhardware_legacy/audio/audio_hw_hal.cpp:602:id: AUDIO_HARDWARE_MODULE_ID,  
  3. hardware/libhardware/modules/audio/audio_hw.c:435:   .id = AUDIO_HARDWARE_MODULE_ID,  
  4. hardware/libhardware/include/hardware/audio.h:37:  
  5.                                             #define AUDIO_HARDWARE_MODULE_ID "audio"  

从搜索结果发现,AUDIO_HARDWARE_MODULE_ID的音频模块有两处定义,具体用的是哪个那?
先分析下这两个模块最终编译进哪些模块。
经过查阅Android.mk晓得,audio_hw.c先被编译进audio_policy.stub模块,然后被编译进libhardware模块;
一样的,audio_hw_hal.cpp先被编译进libaudiopolicy_legacy模块,然后被编译进libhardware_legacy模块;
而libhardware和libhardware_legacy模块都在audioFlinger中用到。
经过log信息,确认使用的是libaudiopolicy_legacy模块,即具体调到hardware/libhardware_legacy/audio/audio_hw_hal.cpp文件中所定义的模块了。

在获取到HAL层音频模块后,接下来执行audio_hw_device_open()函数,打开设备。此函数也在audio.h头文件中定义,函数体以下:



  1. <span style=< span="" style="word-wrap: break-word;">"font-size:24px;">/** convenience API for opening and closing a supported device */  
  2.   
  3. static inline int audio_hw_device_open(const struct hw_module_t* module,  
  4.                                        struct audio_hw_device** device)  
  5. {  
  6.     return module->methods->open(module, AUDIO_HARDWARE_INTERFACE,  
  7.                                  (struct hw_device_t**)device);  
  8. }  



struct hw_module_t是在hardware/libhardware/include/hardware/hardware.h头文件中定义的,其中嵌套了struct hw_module_methods_t。此结构体很简单,只有一个函数指针open



  1. <span style=< span="" style="word-wrap: break-word;">"font-size:24px;">typedef struct hw_module_methods_t {  
  2.     /** Open a specific device */  
  3.     int (*open)(const struct hw_module_t* module, const char* id,   
  4.             struct hw_device_t** device);  
  5.   
  6. } hw_module_methods_t;  



在肯定具体模块后,很容易肯定open函数指针的具体实现


  1. <span style=< span="" style="word-wrap: break-word;">"font-size:24px;">struct legacy_audio_module HAL_MODULE_INFO_SYM = {   
  2.     module: {  
  3.         common: {  
  4.             tag: HARDWARE_MODULE_TAG,  
  5.             version_major: 1,  
  6.             version_minor: 0,  
  7.             id: AUDIO_HARDWARE_MODULE_ID,  
  8.             name: "LEGACY Audio HW HAL",  
  9.             author: "The Android Open Source Project",  
  10.             methods: &<span style="color:#ff0000;">legacy_audio_module_methods,  
  11.             dso : NULL,  
  12.             reserved : {0},  
  13.         },    
  14.     },    
  15. };  




  1. <span style=< span="" style="word-wrap: break-word;">"font-size:24px;">static struct hw_module_methods_t legacy_audio_module_methods = {   
  2.         open: <span style="color:#ff0000;">legacy_adev_open  
  3. };  


open()的实现就是legacy_adev_open()函数了!




  1. <span style=< span="" style="word-wrap: break-word;">"font-size:24px;">static int legacy_adev_open(const hw_module_t* module, const char* name,  
  2.                             hw_device_t** device)  
  3. {  
  4.     struct legacy_audio_device *ladev;  
  5.     int ret;  
  6.   
  7.     if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0)  // 看来对应宏AUDIO_HARDWARE_INTERFACE,除了用来判断但愿打开的是否音频硬件接口外,并无作什么更多的事情  
  8.         return -EINVAL;  
  9.   
  10.     .....  
  11.   
  12.     ladev->device.get_supported_devices = adev_get_supported_devices;  
  13.     ladev->device.init_check = <span style="color:#ff0000;">adev_init_check;  
  14.   
  15.     .....  
  16.   
  17.     ladev->device.open_output_stream = <span style="color:#ff0000;">adev_open_output_stream;  
  18.     ladev->device.close_output_stream = adev_close_output_stream;  
  19.     ladev->device.open_input_stream = adev_open_input_stream;  
  20.     ladev->device.close_input_stream = adev_close_input_stream;  
  21.   
  22.     .....  
  23.   
  24.     ladev->hwif = <span style="color:#ff0000;">createAudioHardware();  
  25.   
  26.     .....  
  27.     <span style="color:#ff0000;">*device = &ladev->device.common;  <span style=< span="" style="word-wrap: break-word;">"color:#3333ff;">// 将当前设备信息层层返回给回调函数,最后返回到  
  28.                                       // load_audio_interface()函数,并保存在  
  29.                                       // mAudioHwDevs模板变量中,供AudioFlinger类使用。  
  30.   
  31.     return 0;   
  32. }  



这里主要作了一些初始化工做,即给函数指针提供具体实现函数;但createAudioHardware()应该作了更多的事情。
先从函数createAudioHardware()的返回值入手。struct legacy_audio_device的定义以下:



  1. <span style=< span="" style="word-wrap: break-word;">"font-size:24px;">struct legacy_audio_device {  
  2.     struct audio_hw_device device;  
  3.           
  4.     struct AudioHardwareInterface *hwif;  
  5. };   



原来createAudioHardware()的返回值是一个硬件设备接口AudioHardwareInterface。
类AudioHardwareInterface正好在audio_hw_hal.cpp文件中所包含的头文件hardware_legacy/AudioHardwareInterface.h中定义的虚类(结构体能调到类,仍是头一遭见到,虽然结构体和类长得很象)。那么我很想知道createAudioHardware()具体作了哪些事情。
首先须要肯定函数createAudioHardware()的定义在哪儿?有几处定义?调用的具体是哪个?
AudioHardwareInterface.h头文件中对createAudioHardware函数的声明,没有包含在任何类中,而仅仅包含在名字空间android_audio_legacy中,这和audio_hw_hal.cpp同在一个名字空间中。



  1. <span style=< span="" style="word-wrap: break-word;">"font-size:24px;">namespace android_audio_legacy {  
  2.   
  3.     .....  
  4.   
  5. extern "C" AudioHardwareInterface* createAudioHardware(void);  
  6. }; // namespace android  



经搜索,发现createAudioHardware()函数有四处定义。



  1. <span style=< span="" style="word-wrap: break-word;">"font-size:24px;">$ grep -rn createAudioHardware hardware/ --exclude-dir=.svn  
  2. hardware/alsa_sound/AudioHardwareALSA.cpp:45:      
  3.           android_audio_legacy::AudioHardwareInterface *createAudioHardware(void) {  
  4. hardware/msm7k/libaudio-qsd8k/AudioHardware.cpp:2021:  
  5.                      extern "C" AudioHardwareInterface* createAudioHardware(void) {  
  6. hardware/msm7k/libaudio-qdsp5v2/AudioHardware.cpp:337:  
  7.                      extern "C" AudioHardwareInterface* createAudioHardware(void) {  
  8. hardware/msm7k/libaudio/AudioHardware.cpp:1132:  
  9.                      extern "C" AudioHardwareInterface* createAudioHardware(void) {  


只有AudioHardwareALSA.cpp文件中包含了头文件hardware_legacy/AudioHardwareInterface.h,而且返回值是android_audio_legacy名字空间的AudioHardwareInterface类对象。则createAudioHardware函数的具体实现极可能是它了,经过log信息证实了这一点。


进入AudioHardwareALSA.cpp,不难看出,此函数,最后会经过执行代码以下代码建立AudioHardwareALSA类对象。



  1. "font-size:24px;">return new AudioHardwareALSA();  


AudioHardwareALSA类的构造函数以下:


  1. <span xmlns=< span="" style="word-wrap: break-word;">"http://www.w3.org/1999/xhtml" style="font-size:24px;">AudioHardwareALSA::AudioHardwareALSA() :  
  2.     mALSADevice(0),  
  3.     mAcousticDevice(0)  
  4. {   
  5.     ......  
  6.   
  7.     int err = <span style=< span="" style="word-wrap: break-word;">"color:#ff0000;">hw_get_module(<span style=< span="" style="word-wrap: break-word;">"color:#ff0000;">ALSA_HARDWARE_MODULE_ID,  
  8.             (hw_module_t const**)<span style=< span="" style="word-wrap: break-word;">"color:#ff0000;">&module);  
  9.   
  10.     if (err == 0) {  
  11.         hw_device_t* device;  
  12.         err = <span style="color:#ff0000;">module->methods->open(module, <span style=< span="" style="word-wrap: break-word;">"color:#ff0000;">ALSA_HARDWARE_NAME, &device);  
  13.         if (err == 0) {  
  14.             mALSADevice = (alsa_device_t *)device;  
  15.             <span style="color:#ff0000;">mALSADevice->init(<span style=< span="" style="word-wrap: break-word;">"color:#ff0000;">mALSADevice, <span style=< span="" style="word-wrap: break-word;">"color:#ff0000;">mDeviceList);  
  16.   
  17.     .....  
  18.   
  19.     err = hw_get_module(ACOUSTICS_HARDWARE_MODULE_ID,  
  20.             (hw_module_t const**)&module);                                                                                           
  21.   
  22.     if (err == 0) {  
  23.         hw_device_t* device;  
  24.         err = module->methods->open(module, ACOUSTICS_HARDWARE_NAME, &device);   
  25.   
  26.     .....  
  27. }  



宏ALSA_HARDWARE_MODULE_ID是在头文件hardware/alsa_sound/AudioHardwareALSA.h中定义的。
模块所对应的结构体类型为hw_module_t,在头文件hardware/libhardware/include/hardware/hardware.h中定义。
在构造函数中,首先调用函数hw_get_module()获取ID为ALSA_HARDWARE_MODULE_ID的ALSA硬件模块,看来即将进入庞大而又功能强大的ALSA音频子系统了!

通过搜索,很快肯定ID为ALSA_HARDWARE_MODULE_ID的ALSA硬件抽象层的具体实如今文件hardware/alsa_sound/alsa_default.cpp中。


  1. <span xmlns=< span="" style="word-wrap: break-word;">"http://www.w3.org/1999/xhtml" style="font-size:24px;">$ grep -rn ALSA_HARDWARE_MODULE_ID hardware/ --exclude-dir=.svn  
  2. hardware/alsa_sound/AudioHardwareALSA.h:39:#define ALSA_HARDWARE_MODULE_ID "alsa"  
  3. hardware/alsa_sound/alsa_default.cpp:59:      
  4.                                         id              : ALSA_HARDWARE_MODULE_ID,  
  5. hardware/alsa_sound/AudioHardwareALSA.cpp:150:      
  6.                                    int err = hw_get_module(ALSA_HARDWARE_MODULE_ID,  



则很快找到此模块的具体内容以下:


  1. <span xmlns=< span="" style="word-wrap: break-word;">"http://www.w3.org/1999/xhtml" style="font-size:24px;">extern "C" const hw_module_t HAL_MODULE_INFO_SYM = {   
  2.     tag             : HARDWARE_MODULE_TAG,  
  3.     version_major   : 1,  
  4.     version_minor   : 0,  
  5.     id              : ALSA_HARDWARE_MODULE_ID,  
  6.     name            : "ALSA module",  
  7.     author          : "Wind River",  
  8.     methods         : &<span style="color:#ff0000;">s_module_methods,  
  9.     dso             : 0,  
  10.     reserved        : { 0, },  
  11. };  


s_module_methods函数的实现以下:


  1. <span xmlns=< span="" style="word-wrap: break-word;">"http://www.w3.org/1999/xhtml" style="font-size:24px;">static hw_module_methods_t s_module_methods = {   
  2.     open            : s_device_open  
  3. };  


s_device_open函数的实现以下:


  1. <span xmlns=< span="" style="word-wrap: break-word;">"http://www.w3.org/1999/xhtml" style="font-size:24px;">static int s_device_open(const hw_module_t* module, const char* name,  <span style=< span="" style="word-wrap: break-word;">"color:#3333ff;">//有些困惑,  
  2.               // 此open函数实现中并无对调用者传递下来的name(ALSA_HARDWARE_NAME)做如何处理。  
  3.         hw_device_t** device) <span style="color:#3333ff;"><span style=< span="" style="word-wrap: break-word;">"background-color: rgb(255, 255, 255);">//device存储返回的模块信息  
  4. {  
  5.     alsa_device_t *dev;  
  6.     dev = (alsa_device_t *) malloc(sizeof(*dev));  
  7.     if (!dev) return -ENOMEM;  
  8.   
  9.     memset(dev, 0, sizeof(*dev));  
  10.   
  11.     /* initialize the procs */  
  12.     dev->common.tag = HARDWARE_DEVICE_TAG;  
  13.     dev->common.version = 0;  
  14.     dev->common.module = (hw_module_t *) module;  
  15.     dev->common.close = s_device_close;  
  16.     dev->init = <span style="color:#ff0000;">s_init;  
  17.     dev->open = <span style="color:#ff0000;">s_open;  
  18.     dev->close = s_close;  
  19.     dev->route = <span style="color:#ff0000;">s_route;  
  20.   
  21.     <span style="color:#ff0000;">*device = &dev->common; <span style=< span="" style="word-wrap: break-word;">"color:#3333ff;">// 把此模块信息返回给调用者  
  22.     return 0;  
  23. }  



通过上述分析,知道了module->methods->open函数具体调用流程了。

而后对ALSA硬件抽象层模块作了初始化的工做。
这里用到一个结构体变量mALSADevice,它在头文件hardware/alsa_sound/AudioHardwareALSA.h中定义的struct alsa_device_t变量。


  1. <span xmlns=< span="" style="word-wrap: break-word;">"http://www.w3.org/1999/xhtml" style="font-size:24px;">struct alsa_device_t {  
  2.     hw_device_t common;  
  3.       
  4.     status_t (*init)(alsa_device_t *, ALSAHandleList &);  
  5.     status_t (*open)(alsa_handle_t *, uint32_t, int);  
  6.     status_t (*close)(alsa_handle_t *);  
  7.     status_t (*route)(alsa_handle_t *, uint32_t, int);  
  8. };    


此结构体仅仅提供了一些函数调用接口,在这里都有了具体的实现。则mALSADevice->init()将调到s_init()函数中。


  1. <span xmlns=< span="" style="word-wrap: break-word;">"http://www.w3.org/1999/xhtml" style="font-size:24px;">static status_t s_init(alsa_device_t *module, <span style=< span="" style="word-wrap: break-word;">"color:#ff0000;">ALSAHandleList &list)  
  2. {  
  3.     list.clear();  
  4.   
  5.     snd_pcm_uframes_t bufferSize = <span style="color:#ff0000;">_defaultsOut.bufferSize;  
  6.   
  7.     for (size_t i = 1; (bufferSize & ~i) != 0; i <<= 1)  
  8.         bufferSize &= ~i;       
  9.   
  10.     _defaultsOut.module = module;    
  11.     _defaultsOut.bufferSize = bufferSize;  
  12.   
  13.     <span style="color:#ff0000;">list.push_back(_defaultsOut);    
  14.   
  15.     bufferSize = <span style="color:#ff0000;">_defaultsIn.bufferSize;  
  16.   
  17.     .....  
  18.   
  19.     <span style="color:#ff0000;">list.push_back(_defaultsIn);  
  20.   
  21.     .....  
  22. }  


这里会把_defaultsOut和_defaultsIn东东保存在ALSA句柄列表ALSAHandleList中。
首先须要明确_defaultsOut和_defaultsIn具体是什么东东。


  1. <span xmlns=< span="" style="word-wrap: break-word;">"http://www.w3.org/1999/xhtml" style="font-size:24px;">static alsa_handle_t _defaultsOut = {  
  2.     module      : 0,  
  3.     devices     : android_audio_legacy::AudioSystem::DEVICE_OUT_ALL,  <span style="color:#3333ff;">// 支持的全部  
  4.                                                                       // 输出音频设备  
  5.     curDev      : 0,  
  6.     curMode     : 0,  
  7.     handle      : 0,  <span style="color:#3333ff;">// PCM节点  
  8.     format      : SND_PCM_FORMAT_S16_LE, // AudioSystem::PCM_16_BIT   
  9.     channels    : 2,    
  10.     sampleRate  : DEFAULT_SAMPLE_RATE,    
  11.     latency     : 200000, // Desired Delay in usec  
  12.     bufferSize  : DEFAULT_SAMPLE_RATE / 5, // Desired Number of samples  
  13.     modPrivate  : 0,  
  14. };  
  15.   
  16. static alsa_handle_t _defaultsIn = {  
  17.     module      : 0,  
  18.     devices     : android_audio_legacy::AudioSystem::DEVICE_IN_ALL, <span style="color:#3333ff;">// 支持的全部  
  19.                                                                     // 输入音频设备  
  20.     curDev      : 0,  
  21.     curMode     : 0,  
  22.     handle      : 0, <span style="color:#3333ff;">// PCM节点  
  23.     format      : SND_PCM_FORMAT_S16_LE, // AudioSystem::PCM_16_BIT  
  24.     channels    : 2, <span style="color:#3333ff;">// 声道数: 1表示单声道,2表示立体声。若是与实际使用的USB AUDIO设备参数  
  25.                      // 的不一致,将致使USB AUDIO设备不能使用。  
  26.     sampleRate  : DEFAULT_SAMPLE_RATE, <span style="color:#3333ff;">// 采样率,若是与实际使用的USB AUDIO设备参数  
  27.                                        // 的不一致,将致使声音失真  
  28.     <span style="color:#000000;">latency     : 250000, // Desired Delay in usec  
  29.     bufferSize  : 2048, // Desired Number of samples  
  30.     modPrivate  : 0,  
  31. };  


那ALSAHandleList又是什么东东?
ALSAHandleList在头文件hardware/alsa_sound/AudioHardwareALSA.h中定义的List模板变量。
typedef List ALSAHandleList;
原来就是struct asla_handle_t的一个列表而已,而_defaultsOut和_defaultsIn正是这样的结构体变量。


  1. <span xmlns=< span="" style="word-wrap: break-word;">"http://www.w3.org/1999/xhtml" style="font-size:24px;">struct alsa_handle_t {  
  2.     alsa_device_t *     module;  
  3.     uint32_t            devices;  
  4.     uint32_t            curDev;  
  5.     int                 curMode;  
  6.     snd_pcm_t *         handle;  <span style="color:#3333ff;">// PCM节点  
  7.     snd_pcm_format_t    format;  
  8. <span style="color:#ff0000;">    uint32_t            channels;  
  9.     uint32_t            sampleRate;  
  10.     unsigned int        latency;         // Delay in usec  
  11.     unsigned int        bufferSize;      // Size of sample buffer  
  12.     void *              modPrivate;  
  13. };  


ALSA硬件抽象层正是这样得到了输出音频通道和输入音频通道的相关初始化硬件参数,之后在使用中并不试图改变这些硬件参数(针对真能手机和平板来讲,也倒是不须要改变)。所以,在扩展android系统功能,为其添加对USB AUDIO设备的支持时,就不得不考虑时事改变channels和sampleRate这两个硬件参数的值。

至此,AudioFlinger服务首次启动过程分析完毕!


1.2 AudioPolicyService启动流程及其所涉及的HAL层模块启动流程分析。

AudioPolicyService服务的启动流程相似于AudioFlinger服务的启动过程,将简要分析。
先看下AudioPolicyService类的定义(AudioPolicyService.h)(提供此类的定义,主要是为下面instantiate()函数服务的):


  1. <span xmlns=< span="" style="word-wrap: break-word;">"http://www.w3.org/1999/xhtml" style="font-size:24px;">class AudioPolicyService :  
  2.     public <span style=< span="" style="word-wrap: break-word;">"color:#ff0000;">BinderService, <span style=< span="" style="word-wrap: break-word;">"color:#3333ff;">// 继承了BinderService类,  
  3.                                               // 并把本身(AudioPolicyService)传递给  
  4.                                               // BinderService。  
  5.     public BnAudioPolicyService,  
  6. //    public AudioPolicyClientInterface,  
  7.     public IBinder::DeathRecipient  
  8. {  
  9.     friend class BinderService;  
  10.   
  11. public:  
  12.     // for BinderService  
  13.     static const char *<span style=< span="" style="word-wrap: break-word;">"color:#ff0000;">getServiceName() { return "media.audio_policy"; }  
  14.   
  15.     .....  
  16. }  


根据前面的分析,晓得将经过调用以下代码启动AudioPolicyService服务。


  1. "http://www.w3.org/1999/xhtml" style="font-size:24px;">AudioPolicyService::instantiate();  



此代码最后将调到AudioPolicyService类的构造函数


  1. <span xmlns=< span="" style="word-wrap: break-word;">"http://www.w3.org/1999/xhtml" style="font-size:24px;">AudioPolicyService::AudioPolicyService()  
  2.     : BnAudioPolicyService() , mpAudioPolicyDev(NULL) , mpAudioPolicy(NULL)  
  3. {  
  4.     char value[PROPERTY_VALUE_MAX];  
  5.     const struct hw_module_t *module;  
  6.     int forced_val;  
  7.     int rc;  
  8.   
  9.     Mutex::Autolock _l(mLock);  
  10.   
  11.     // start tone playback thread  
  12.     mTonePlaybackThread = new AudioCommandThread(String8(""));  
  13.     // start audio commands thread  
  14.     mAudioCommandThread = new <span style=< span="" style="word-wrap: break-word;">"color:#ff0000;">AudioCommandThread(String8("ApmCommandThread"));  
  15.   
  16.     /* instantiate the audio policy manager */  
  17.     rc = <span style="color:#ff0000;">hw_get_module(<span style=< span="" style="word-wrap: break-word;">"color:#ff0000;">AUDIO_POLICY_HARDWARE_MODULE_ID, &module);  
  18.     if (rc)  
  19.         return;  
  20.   
  21.     rc = <span style="color:#ff0000;">audio_policy_dev_open(module, <span style=< span="" style="word-wrap: break-word;">"color:#ff0000;">&mpAudioPolicyDev);  
  22.     LOGE_IF(rc, "couldn't open audio policy device (%s)", strerror(-rc));  
  23.     if (rc)  
  24.         return;  
  25.   
  26.     rc = <span style="color:#ff0000;">mpAudioPolicyDev->create_audio_policy(mpAudioPolicyDev, <strong style=< span="" style="word-wrap: break-word;">"background-color: rgb(192, 192, 192);"><span style=< span="" style="word-wrap: break-word;">"color:#ff0000;">&aps_opsthis,  
  27.                                               <span style="color:#ff0000;">&mpAudioPolicy);  
  28.     LOGE_IF(rc, "couldn't create audio policy (%s)", strerror(-rc));  
  29.     if (rc)  
  30.         return;  
  31.   
  32.     rc = <span style="color:#ff0000;">mpAudioPolicy->init_check(mpAudioPolicy);  
  33.   
  34.     .....  
  35.   
  36. }  

(1)首先开启了放音线程和音频命令线程。这些工做都是经过建立AudioCommandThread线程类对象完成。



AudioCommandThread类在头文件frameworks/base/services/audioflinger/AudioPolicyService.h中定义


  1. "http://www.w3.org/1999/xhtml" style="font-size:24px;">class AudioCommandThread : public Thread {  



是AudioPolicyService类的私有子类。

AudioCommandThread线程类建立了对象后,将进入死循环中,等待要处理的事件传来。



  1. <span xmlns=< span="" style="word-wrap: break-word;">"http://www.w3.org/1999/xhtml" style="font-size:24px;">bool AudioPolicyService::AudioCommandThread::threadLoop()  
  2. {  
  3.     nsecs_t waitTime = INT64_MAX;  
  4.   
  5.     mLock.lock();  
  6.     while (!exitPending())  
  7.     {  
  8.         while(!mAudioCommands.isEmpty()) {  
  9.            .....  
  10.               
  11.                 switch (command->mCommand) {  
  12.   
  13.                 .....  
  14.   
  15.                 <span style="color:#ff0000;">case SET_PARAMETERS: {  
  16.                      ParametersData *data = (ParametersData *)command->mParam;  
  17.                      LOGV("AudioCommandThread() processing set parameters string %s, io %d",  
  18.                              data->mKeyValuePairs.string(), data->mIO);  
  19.                      command->mStatus = <span style="color:#ff0000;">AudioSystem::setParameters(data->mIO, data->mKeyValuePairs);  
  20.                      if (command->mWaitStatus) {  
  21.                          command->mCond.signal();  
  22.                          mWaitWorkCV.wait(mLock);  
  23.                      }  
  24.                      delete data;  
  25.                      }break;  
  26.   
  27.     .....  
  28. }  

这里只列出了switch语句中的一种状况的处理代码,由于后面分析setDeviceConnectionState()函数的调用流程时将用到。
当command->mCommand值为SET_PARAMETERS时,将调用libmedia库(frameworks/base/media/libmedia/AudioSystem.cpp)中的函数setParameters()作进一步处理。

(2)而后调用函数hw_get_module()得到ID号为AUDIO_POLICY_HARDWARE_MODULE_ID的硬件抽象层的音频策略模块。宏AUDIO_POLICY_HARDWARE_MODULE_ID在头文件hardware/libhardware/include/hardware/audio_policy.h中定义。



ID号为AUDIO_POLICY_HARDWARE_MODULE_ID的模块也有两处具体实现,一样经过log信息,确认调用的是libhardware_legacy模块中的AUDIO_POLICY_HARDWARE_MODULE_ID子模块的具体实现。


  1. <span xmlns=< span="" style="word-wrap: break-word;">"http://www.w3.org/1999/xhtml" style="font-size:24px;">$ grep -rn AUDIO_POLICY_HARDWARE_MODULE_ID hardware/ --exclude-dir=.svn  
  2. hardware/libhardware_legacy/audio/audio_policy_hal.cpp:414:  
  3.                                                 id: AUDIO_POLICY_HARDWARE_MODULE_ID,  
  4. hardware/libhardware/modules/audio/audio_policy.c:318:   
  5.                                   .id             = AUDIO_POLICY_HARDWARE_MODULE_ID,  



audio_policy_hal.cpp文件中定义的AUDIO_POLICY_HARDWARE_MODULE_ID模块以下:


struct legacy_ap_module HAL_MODULE_INFO_SYM = {
    module: {
        common: {
            tag: HARDWARE_MODULE_TAG,
            version_major: 1,
            version_minor: 0,
            id: AUDIO_POLICY_HARDWARE_MODULE_ID,
            name: "LEGACY Audio Policy HAL",
            author: "The Android Open Source Project",
            methods: &legacy_ap_module_methods,
            dso : NULL,
            reserved : {0},
        },
    },
};


(3)再而后调用audio_policy_dev_open()函数(在头文件hardware/libhardware/include/hardware/audio_policy.h中定义)。

首先分析函数参数:第一个参数就是上面获取的模块,第二个参数mpAudioPolicyDev是struct audio_policy_device 指针变量,在头文件AudioPolicyService.h中定义。而struct audio_policy_device是在头文件audio_policy.h中定义的。


  1. <span xmlns=< span="" style="word-wrap: break-word;">"http://www.w3.org/1999/xhtml" style="font-size:24px;">struct audio_policy_device {    
  2.     struct hw_device_t common;  
  3.   
  4.     int (*create_audio_policy)(const struct audio_policy_device *device,  
  5.                                struct audio_policy_service_ops <span style=< span="" style="word-wrap: break-word;">"color:#ff0000;background-color: rgb(153, 153, 153);">*aps_ops,  
  6.                                void *service,                   
  7.                                struct audio_policy **ap);    
  8.     .....  
  9. }  



最后看下audio_policy_dev_open()函数的实现


  1. <span xmlns=< span="" style="word-wrap: break-word;">"http://www.w3.org/1999/xhtml" style="font-size:24px;"><span xmlns=< span="" style="word-wrap: break-word;">"http://www.w3.org/1999/xhtml" style="">/** convenience API for opening and closing a supported device */  
  2.   
  3. static inline int audio_policy_dev_open(const hw_module_t* module,  
  4.                                     struct audio_policy_device** device)  
  5. {  
  6.     return module->methods->open(module, AUDIO_POLICY_INTERFACE,  
  7.                                  (hw_device_t**)device);  
  8. }  


由上述分析可知,open函数指针就指向legacy_ap_dev_open()函数。


  1. <span xmlns=< span="" style="word-wrap: break-word;">"http://www.w3.org/1999/xhtml" style=""><span xmlns=< span="" style="word-wrap: break-word;">"http://www.w3.org/1999/xhtml" style="">static int legacy_ap_dev_open(const hw_module_t* module, const char* name,  
  2.                                     hw_device_t** device) <span style="color:#3333ff;">// 参数device保存返回的模块信息  
  3. {  
  4.     struct legacy_ap_device *dev;  
  5.   
  6.     if (strcmp(name, AUDIO_POLICY_INTERFACE) != 0)<span style=< span="" style="word-wrap: break-word;">"color:#3333ff;">// 参数name(AUDIO_POLICY_INTERFACE)  
  7.                                                   // 就这点用处  
  8.         return -EINVAL;  
  9.   
  10.     dev = (struct legacy_ap_device *)calloc(1, sizeof(*dev));  
  11.     if (!dev)  
  12.         return -ENOMEM;  
  13.   
  14.     dev->device.common.tag = HARDWARE_DEVICE_TAG;  
  15.     dev->device.common.version = 0;  
  16.     dev->device.common.module = const_cast(module);  
  17.     dev->device.common.close = legacy_ap_dev_close;  
  18.     dev->device.create_audio_policy = <span style="color:#ff0000;">create_legacy_ap;  
  19.     dev->device.destroy_audio_policy = destroy_legacy_ap;  
  20.   
  21.     <span style="color:#ff0000;">*device = &dev->device.common; <span style=< span="" style="word-wrap: break-word;">"color:#3333ff;">// 将当前模块具体信息赋值给device,并回馈给调用者  
  22.   
  23.     return 0;  
  24. }  

(4)再接下来调用的mpAudioPolicyDev->create_audio_policy()函数指针具体就是create_legacy_ap()。
第二个参数&aps_ops是struct audio_policy_service_ops变量,是APS(AudioPolicyService)的操做接口,而且传递的是aps_ops的地址,则被调用者使用的将是在APS中函数接口的实现。



  1. <span xmlns=< span="" style="word-wrap: break-word;">"http://www.w3.org/1999/xhtml" style=""><span xmlns=< span="" style="word-wrap: break-word;">"http://www.w3.org/1999/xhtml" style="">namespace {  
  2.     struct audio_policy_service_ops aps_ops = {  
  3.         <span style="color:#ff0000;">open_output           : aps_open_output,  
  4.         open_duplicate_output : aps_open_dup_output,  
  5.         close_output          : aps_close_output,  
  6.         suspend_output        : aps_suspend_output,  
  7.         restore_output        : aps_restore_output,  
  8.         open_input            : aps_open_input,  
  9.         close_input           : aps_close_input,  
  10.         set_stream_volume     : aps_set_stream_volume,  
  11.         set_stream_output     : aps_set_stream_output,  
  12.         <span style="color:#ff0000;">set_parameters        : aps_set_parameters,  
  13.         get_parameters        : aps_get_parameters,  
  14.         start_tone            : aps_start_tone,  
  15.         stop_tone             : aps_stop_tone,  
  16.         set_voice_volume      : aps_set_voice_volume,  
  17.         move_effects          : aps_move_effects,  
  18.     };  
  19. }; // namespace   

struct audio_policy_service_ops在头文件hardware/libhardware/include/hardware/audio_policy.h中定义,是包含音频相关控制函数的接口。可见aps_ops接口将为HAL层提供服务。

第四个参数是&mpAudioPolicy。mpAudioPolicy是struct audio_policy的指针变量(AudioPolicyService.h)。而struct audio_policy也是在audio_policy.h中定义,将要用到的接口以下:



  1. <span xmlns=< span="" style="word-wrap: break-word;">"http://www.w3.org/1999/xhtml" style=""><span xmlns=< span="" style="word-wrap: break-word;">"http://www.w3.org/1999/xhtml" style="">struct audio_policy {  
  2.     /* 
  3.      * configuration functions 
  4.      */  
  5.   
  6.     /* indicate a change in device connection status */  
  7.     int (*set_device_connection_state)(struct audio_policy *pol,  
  8.                                        audio_devices_t device,  
  9.                                        audio_policy_dev_state_t state,  
  10.                                        const char *device_address);  
  11.   
  12.     .....  
  13.   
  14.     /* check proper initialization */  
  15.     int (*init_check)(const struct audio_policy *pol);  
  16.   
  17.     .....  
  18. }  


接下来看看create_audio_policy()函数指针的具体实现:


  1. <span xmlns=< span="" style="word-wrap: break-word;">"http://www.w3.org/1999/xhtml" style=""><span xmlns=< span="" style="word-wrap: break-word;">"http://www.w3.org/1999/xhtml" style="">static int create_legacy_ap(const struct audio_policy_device *device,  
  2.                             struct audio_policy_service_ops *aps_ops,  
  3.                             void *service,  
  4.                             struct audio_policy **ap)  
  5. {  
  6.     struct legacy_audio_policy *lap;  
  7.     int ret;  
  8.   
  9.     if (!service || !aps_ops)  
  10.         return -EINVAL;  
  11.   
  12.     lap = (struct legacy_audio_policy *)calloc(1, sizeof(*lap));  
  13.     if (!lap)  
  14.         return -ENOMEM;  
  15.   
  16.     lap->policy.set_device_connection_state = <span style="color:#ff0000;">ap_set_device_connection_state;  
  17.   
  18.     ......  
  19.   
  20.     lap->policy.init_check = ap_init_check;  
  21.     lap->policy.get_output = ap_get_output;  
  22.     lap->policy.start_output = ap_start_output;  
  23.     lap->policy.stop_output = ap_stop_output;  
  24.     lap->policy.release_output = ap_release_output;  
  25.     lap->policy.get_input = ap_get_input;  
  26.     lap->policy.start_input = <span style="color:#ff0000;">ap_start_input;  
  27.     lap->policy.stop_input = ap_stop_input;  
  28.     lap->policy.release_input = ap_release_input;  
  29.   
  30.     .....  
  31. <span style="color:#ff0000;">  
  32.     lap->service = service; <span style="color:#3333ff;">// APS  
  33.     lap->aps_ops = aps_ops; <span style="color:#3333ff;">// 在APS中实现  
  34.     lap->service_client =  
  35.         new AudioPolicyCompatClient(aps_ops, service);  
  36.     if (!lap->service_client) {  
  37.         ret = -ENOMEM;  
  38.         goto err_new_compat_client;  
  39.     }  
  40. <span style="color:#ff0000;">  
  41.     lap->apm = createAudioPolicyManager(lap->service_client);  
  42.      
  43.     ......  
  44.   
  45.     <span style="color:#ff0000;">*ap = &lap->policy; <span style=< span="" style="word-wrap: break-word;">"color:#3333ff;">// 将当前音频策略的配置的地址赋值给*ap,并返回给mpAudioPolicy  
  46.   
  47.     ......  
  48. }  



此函数中建立了重要对象:AudioPolicyCompatClient类对象和createAudioPolicyManager函数建立音频策略管理器,须要分析下。

先分析AudioPolicyCompatClient类对象的建立。此类在头文件hardware/libhardware_legacy/audio/AudioPolicyCompatClient.h中定义。


  1. <span xmlns=< span="" style="word-wrap: break-word;">"http://www.w3.org/1999/xhtml" style=""><span xmlns=< span="" style="word-wrap: break-word;">"http://www.w3.org/1999/xhtml" style="">namespace android_audio_legacy {  
  2. class AudioPolicyCompatClient : public AudioPolicyClientInterface {   
  3.        <span style="color:#3333ff;">// 父类是AudioPolicyClientInterface,与下文中提到的  
  4.        // AudioPolicyManagerBase::  
  5.        // AudioPolicyManagerBase(AudioPolicyClientInterface *clientInterface)类型一致  
  6. public:  
  7.     AudioPolicyCompatClient(struct audio_policy_service_ops *serviceOps,  
  8.                             void *service) :  
  9.             <span style="color:#ff0000;">mServiceOps(serviceOps) , mService(service) {} <span style=< span="" style="word-wrap: break-word;">"color:#3333ff;">// serviceOps = aps_ops,   
  10.                                                            // service = this(APS)  
  11.   
  12.     ......  
  13.   
  14. private:  
  15.     struct audio_policy_service_ops* mServiceOps;                     
  16.     void*                            mService;    
  17.   
  18.     ......  
  19. }  



此构造函数主要初始化两个私有化变量mServiceOps和mService,并把建立的对象做为函数createAudioPolicyManager的惟一参数,来建立音频策略管理器。
然而,函数createAudioPolicyManager有多个定义,搜索结果以下:


  1. <span xmlns=< span="" style="word-wrap: break-word;">"http://www.w3.org/1999/xhtml" style=""><span xmlns=< span="" style="word-wrap: break-word;">"http://www.w3.org/1999/xhtml" style="">$ grep -rn createAudioPolicyManager hardware/ --exclude-dir=.svn  
  2. hardware/alsa_sound/AudioPolicyManagerALSA.cpp:31:  
  3.           extern "C" android_audio_legacy::AudioPolicyInterface*   
  4.           createAudioPolicyManager(  
  5.           android_audio_legacy::AudioPolicyClientInterface *clientInterface)  
  6. hardware/libhardware_legacy/audio/AudioPolicyManagerDefault.cpp:24:  
  7.           extern "C" AudioPolicyInterface*   
  8.           createAudioPolicyManager(AudioPolicyClientInterface *clientInterface)  
  9. hardware/msm7k/libaudio-qsd8k/AudioPolicyManager.cpp:39:  
  10.           extern "C" AudioPolicyInterface*   
  11.           createAudioPolicyManager(AudioPolicyClientInterface *clientInterface)  
  12. hardware/msm7k/libaudio-qdsp5v2/AudioPolicyManager.cpp:39:  
  13.           extern "C" AudioPolicyInterface*   
  14.           createAudioPolicyManager(AudioPolicyClientInterface *clientInterface)  
  15. hardware/msm7k/libaudio/AudioPolicyManager.cpp:35:  
  16.           extern "C" AudioPolicyInterface*   
  17.           createAudioPolicyManager(AudioPolicyClientInterface *clientInterface)  



函数createAudioPolicyManager虽然有多个定义,可是它们最后将建立AudioPolicyManagerBase类对象,以AudioPolicyManagerALSA类为例分析


  1. <span xmlns=< span="" style="word-wrap: break-word;">"http://www.w3.org/1999/xhtml" style=""><span xmlns=< span="" style="word-wrap: break-word;">"http://www.w3.org/1999/xhtml" style="">AudioPolicyManagerALSA::AudioPolicyManagerALSA(  
  2.     android_audio_legacy::AudioPolicyClientInterface *<span style="color:#ff0000;">clientInterface)  
  3.     : AudioPolicyManagerBase(<span style="color:#ff0000;">clientInterface) <span style=< span="" style="word-wrap: break-word;">"color:#3333ff;">// clientInterface正是  
  4.         // AudioPolicyCompatClient类对象,而AudioPolicyCompatClient类具体实现了  
  5.         // AudioPolicyClientInterface类的需函数接口  
  6. {  
  7. }  
  8.   
  9. AudioPolicyManagerBase::AudioPolicyManagerBase(  
  10.          AudioPolicyClientInterface *clientInterface)  
  11.     :      
  12. #ifdef AUDIO_POLICY_TEST  
  13.     Thread(false),  
  14. #endif //AUDIO_POLICY_TEST  
  15.     mPhoneState(AudioSystem::MODE_NORMAL), mRingerMode(0),  
  16.     mLimitRingtoneVolume(false), mLastVoiceVolume(-1.0f),  
  17.     mTotalEffectsCpuLoad(0), mTotalEffectsMemory(0),  
  18.     mA2dpSuspended(false)  
  19. {  
  20.     <span style="color:#ff0000;">mpClientInterface = clientInterface;   <span style=< span="" style="word-wrap: break-word;">"color:#3333ff;">// mpClientInterface:将用它回调到APS  
  21.   
  22.     for (int i = 0; i < AudioSystem::NUM_FORCE_USE; i++) {  
  23.         mForceUse[i] = AudioSystem::FORCE_NONE;  
  24.     }      
  25.   
  26.     initializeVolumeCurves();  
  27.   
  28.     // devices available by default are speaker, ear piece and microphone  
  29.     mAvailableOutputDevices = AudioSystem::DEVICE_OUT_EARPIECE |  
  30.                         AudioSystem::DEVICE_OUT_SPEAKER;          <span style="color:#3333ff;">// 可用的输出音频设备  
  31.     mAvailableInputDevices = AudioSystem::DEVICE_IN_BUILTIN_MIC;  <span style="color:#3333ff;">// 可用的输入音频设备  
  32.   
  33.     ......  
  34.   
  35.     <span style="color:#ff0000;">mHardwareOutput = <span style=< span="" style="word-wrap: break-word;">"color:#cc0000;">mpClientInterface->openOutput(&outputDesc->mDevice,  
  36.                                     &outputDesc->mSamplingRate,  
  37.                                     &outputDesc->mFormat,  
  38.                                     &outputDesc->mChannels,  
  39.                                     &outputDesc->mLatency,  
  40.                                     outputDesc->mFlags);  
  41.   
  42.     ......  
  43.   
  44.          <span style="color:#ff0000;">setOutputDevice(mHardwareOutput, (uint32_t)AudioSystem::DEVICE_OUT_SPEAKER,   
  45.                                                                               true);  
  46.   
  47.     ......  
  48.   
  49. }  
  50.   



mpClientInterface->openOutput()函数先回掉到AudioPolicyCompatClient类的openOutput()函数。


  1. <span xmlns=< span="" style="word-wrap: break-word;">"http://www.w3.org/1999/xhtml" style=""><span xmlns=< span="" style="word-wrap: break-word;">"http://www.w3.org/1999/xhtml" style="">audio_io_handle_t AudioPolicyCompatClient::openOutput(uint32_t *pDevices,  
  2.                                 uint32_t *pSamplingRate,  
  3.                                 uint32_t *pFormat,  
  4.                                 uint32_t *pChannels,  
  5.                                 uint32_t *pLatencyMs,  
  6.                                 AudioSystem::output_flags flags)  
  7. {  
  8.     return <span style=< span="" style="word-wrap: break-word;">"color:#ff0000;">mServiceOps->open_output(mService, pDevices, pSamplingRate, pFormat,  
  9.                                     pChannels, pLatencyMs,  
  10.                                     (audio_policy_output_flags_t)flags);  
  11. }  




由前面分析可知,在建立AudioPolicyCompatClient类对象时,mServiceOps被初始化为APS的struct audio_policy_service_ops变量aps_ops;则将回调到ops中的open_output()函数,具体调到aps_open_output()函数:


  1. <span xmlns=< span="" style="word-wrap: break-word;">"http://www.w3.org/1999/xhtml" style="font-size:24px;">static audio_io_handle_t aps_open_output(void *service,  
  2.                                              uint32_t *pDevices,  
  3.                                              uint32_t *pSamplingRate,  
  4.                                              uint32_t *pFormat,  
  5.                                              uint32_t *pChannels,  
  6.                                              uint32_t *pLatencyMs,  
  7.                                              audio_policy_output_flags_t flags)  
  8. {  
  9.     sp af = AudioSystem::get_audio_flinger();  
  10.     if (af == NULL) {  
  11.         LOGW("%s: could not get AudioFlinger", __func__);  
  12.         return 0;  
  13.     }  
  14.   
  15.     return <span style=< span="" style="word-wrap: break-word;">"color:#ff0000;">af->openOutput(pDevices, pSamplingRate, pFormat, pChannels,  
  16.                           pLatencyMs, flags);  
  17. }  




不难看出,将调到AudioFlinger的openOutput()函数。


  1. <span xmlns=< span="" style="word-wrap: break-word;">"http://www.w3.org/1999/xhtml" style="font-size:24px;">int AudioFlinger::openOutput(uint32_t *pDevices,  
  2.                                 uint32_t *pSamplingRate,  
  3.                                 uint32_t *pFormat,  
  4.                                 uint32_t *pChannels,  
  5.                                 uint32_t *pLatencyMs,  
  6.                                 uint32_t flags)  
  7. {  
  8.      ......  
  9.   
  10.     audio_hw_device_t *outHwDev;  
  11.   
  12.      ......  
  13.   
  14.     outHwDev = findSuitableHwDev_l(*pDevices);  
  15.     if (outHwDev == NULL)  
  16.         return 0;  
  17.   
  18.     status = <span style="color:#ff0000;">outHwDev->open_output_stream(outHwDev, *pDevices, (int *)&format,  
  19.                                           &channels, &samplingRate, &outStream);  
  20.   
  21.      ......  
  22.   
  23.     return 0;   
  24. }  



struct audio_hw_device_t是在头文件hardware/libhardware/include/hardware/audio.h中定义的一个结构体。


  1. "http://www.w3.org/1999/xhtml" style="font-size:24px;">typedef struct audio_hw_device audio_hw_device_t;  


前面在分析AudioFlinger类的load_audio_interface函数时,已经分析过struct audio_hw_device。


  1. <span xmlns=< span="" style="word-wrap: break-word;">"http://www.w3.org/1999/xhtml" style="font-size:24px;">audio_hw_device_t* AudioFlinger::findSuitableHwDev_l(uint32_t devices)  
  2. {     
  3.     /* first matching HW device is returned */  
  4.     for (size_t i = 0; i < mAudioHwDevs.size(); i++) {  // 前文分析过,mAudioHwDevs变量保存了HAL层可用音频设备  
  5.         audio_hw_device_t *dev = <span style="color:#ff0000;">mAudioHwDevs[i];  
  6.         if ((<span style=< span="" style="word-wrap: break-word;">"color:#ff0000;">dev->get_supported_devices(dev) & devices) == devices)   
  7.             return dev;  
  8.     }         
  9.     return NULL;  
  10. }  




由前文分析可知,此处的get_supported_devices()函数指针将具体调到audio_hw_hal.cpp文件中的adev_get_supported_devices(),以下所示,这里列出了系统所支持的全部输出/输入音频设备。所以,咱们要也要仿照此音频设备的定义名称,在这里添加USB AUDIO音频设备的名称,以及它们在别处的定义。


  1. <span xmlns=< span="" style="word-wrap: break-word;">"http://www.w3.org/1999/xhtml" style="font-size:24px;">static uint32_t adev_get_supported_devices(const struct audio_hw_device *dev)  
  2. {  
  3.     /* XXX: The old AudioHardwareInterface interface is not smart enough to 
  4.      * tell us this, so we'll lie and basically tell AF that we support the 
  5.      * below input/output devices and cross our fingers. To do things properly, 
  6.      * audio hardware interfaces that need advanced features (like this) should 
  7.      * convert to the new HAL interface and not use this wrapper. */  
  8.   
  9.     return (/* OUT */  
  10.             AUDIO_DEVICE_OUT_EARPIECE |  
  11.             AUDIO_DEVICE_OUT_SPEAKER |  
  12.             AUDIO_DEVICE_OUT_WIRED_HEADSET |  
  13.             AUDIO_DEVICE_OUT_WIRED_HEADPHONE |  
  14.             AUDIO_DEVICE_OUT_AUX_DIGITAL |  
  15.             AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET |  
  16.             AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET |  
  17.             AUDIO_DEVICE_OUT_ALL_SCO |  
  18.             AUDIO_DEVICE_OUT_DEFAULT |  
  19.             /* IN */  
  20.             AUDIO_DEVICE_IN_COMMUNICATION |  
  21.             AUDIO_DEVICE_IN_AMBIENT |  
  22.             AUDIO_DEVICE_IN_BUILTIN_MIC |  
  23.             AUDIO_DEVICE_IN_WIRED_HEADSET |  
  24.             AUDIO_DEVICE_IN_AUX_DIGITAL |  
  25.             AUDIO_DEVICE_IN_BACK_MIC |  
  26.             AUDIO_DEVICE_IN_ALL_SCO |  
  27.             AUDIO_DEVICE_IN_DEFAULT);  
  28. }  



当找到合适的设备以后,将调用outHwDev->open_output_stream()函数打开相应设备的输出流;一样的道理,将具体调到audio_hw_hal.cpp文件中的adev_open_output_stream()函数。


  1. <span xmlns=< span="" style="word-wrap: break-word;">"http://www.w3.org/1999/xhtml" style="font-size:24px;">static int adev_open_output_stream(struct audio_hw_device *dev,  
  2.                                    uint32_t devices,  
  3.                                    int *format,  
  4.                                    uint32_t *channels,  
  5.                                    uint32_t *sample_rate,  
  6.                                    struct audio_stream_out **stream_out)  
  7. {  
  8.     struct legacy_audio_device *ladev = to_ladev(dev);  
  9.     status_t status;  
  10.     struct legacy_stream_out *out;  
  11.     int ret;  
  12.   
  13.     out = (struct legacy_stream_out *)calloc(1, sizeof(*out));  
  14.     if (!out)  
  15.         return -ENOMEM;  
  16.   
  17.     out->legacy_out = <span style="color:#ff0000;">ladev->hwif->openOutputStream(devices, format, channels,  
  18.                                                     sample_rate, &status);  
  19.   
  20.     ......  
  21. }  


由前文分析可知,ladev->hwif具体指AudioHardwareALSA类;则ladev->hwif->openOutputStream()函数调到AudioHardwareALSA::openOutputStream()函数。


  1. <span xmlns=< span="" style="word-wrap: break-word;">"http://www.w3.org/1999/xhtml" style="font-size:24px;">android_audio_legacy::AudioStreamOut *  
  2. AudioHardwareALSA::openOutputStream(uint32_t devices,  
  3.                                     int *format,  
  4.                                     uint32_t *channels,  
  5.                                     uint32_t *sampleRate,  
  6.                                     status_t *status)  
  7. {  
  8.     ......  
  9.   
  10.     // Find the appropriate alsa device  
  11.     for(ALSAHandleList::iterator it = mDeviceList.begin(); <span style=< span="" style="word-wrap: break-word;">"color:#3333ff;">// mDeviceList是用来存储  
  12.                                                            // 输出/输入音频通道信息的  
  13.                                                            // 句柄的,总共两个句柄,  
  14.                                                            // 分别对应输出和输入音频通道  
  15.         it != mDeviceList.end(); ++it)  
  16.         if (it->devices & devices) {  
  17.             err = <span style="color:#ff0000;">mALSADevice->open(&(*it), devices, mode()); <span style=< span="" style="word-wrap: break-word;">"color:#3333ff;">// 当调用open()函数时,  
  18.                                                               // 就已经知道要打开的是  
  19.                                                               // 输入音频通道仍是输出  
  20.                                                               // 音频通道  
  21.             if (err) break;  
  22.             out = <span style="color:#ff0000;">new AudioStreamOutALSA(this, &(*it)); <span style=< span="" style="word-wrap: break-word;">"color:#3333ff;">// 此类对象的建立本可没必要理会,  
  23.                          // 但它的父类ALSAStreamOps类的对象也会随之建立;而ALSAStreamOps  
  24.                          // 类将在后面用到(mParent = this(AudioHardwareALSA))  
  25.             err = out->set(format, channels, sampleRate);  
  26.             break;  
  27.         }  
  28.   
  29.     ......  
  30. }  



由前文对AudioHardwareALSA类的启动流程分析可知,mDeviceList是用来存储输出/输入音频通道信息的句柄的。
mALSADevice表示在初始化ALSA设备时所指向的一个具体ALSA设备的操做接口。则mALSADevice->open()函数,将具体调到ALSA模块的s_open()函数。


  1. <span xmlns=< span="" style="word-wrap: break-word;">"http://www.w3.org/1999/xhtml" style="font-size:24px;">static status_t s_open(alsa_handle_t *handle, uint32_t devices, int mode)  
  2. {  
  3.     // Close off previously opened device.  
  4.     // It would be nice to determine if the underlying device actually  
  5.     // changes, but we might be recovering from an error or manipulating  
  6.     // mixer settings (see asound.conf).  
  7.     //  
  8.     s_close(handle); <span style="color:#3333ff;">// 先关闭先前打开的音频通道  
  9.   
  10.     LOGD("open called for devices %08x in mode %d...", devices, mode);  
  11.   
  12.     const char *stream = <span style=< span="" style="word-wrap: break-word;">"color:#ff0000;">streamName(handle);    
  13.     const char *devName = <span style=< span="" style="word-wrap: break-word;">"color:#ff0000;">deviceName(handle, devices, mode);  
  14.   
  15.     int err;  
  16.   
  17.     for (;;) {  
  18.         // The PCM stream is opened in blocking mode, per ALSA defaults.  The  
  19.         // AudioFlinger seems to assume blocking mode too, so asynchronous mode  
  20.         // should not be used.  
  21.         err = <span style="color:#ff0000;">snd_pcm_open(<span style=< span="" style="word-wrap: break-word;">"color:#ff0000;">&handle->handle, <span style=< span="" style="word-wrap: break-word;">"color:#ff0000;">devName, <span style=< span="" style="word-wrap: break-word;">"color:#ff0000;">direction(handle),    
  22.                                       <span style="color:#3333ff;">// handle->handle:保存从ALSA-LIB中得到的PCM节点  
  23.                 SND_PCM_ASYNC);  
  24.         if (err == 0) break;  
  25.   
  26.         // See if there is a less specific name we can try.  
  27.         // Note: We are changing the contents of a const char * here.  
  28.         char *tail = strrchr(devName, '_');  
  29.         if (!tail) break;  
  30.         *tail = 0;  
  31.     }  
  32.   
  33.     if (err < 0) {  
  34.         // None of the Android defined audio devices exist. Open a generic one.  
  35.         <span style="color:#ff0000;">devName = "default";  
  36.         err = <span style="color:#ff0000;">snd_pcm_open(&handle->handle, devName, direction(handle), 0);  
  37.     }  
  38.     if (err < 0) {  
  39.         LOGE("Failed to Initialize any ALSA %s device: %s",  
  40.                 stream, strerror(err));  
  41.         return NO_INIT;  
  42.     }  
  43.   
  44.     err = <span style="color:#ff0000;">setHardwareParams(handle);  
  45.   
  46.     if (err == NO_ERROR) err = setSoftwareParams(handle);  
  47.   
  48.     LOGI("Initialized ALSA %s device %s", stream, devName);  
  49.   
  50.     handle->curDev = devices;  
  51.     handle->curMode = mode;  
  52.   
  53.     return err;  
  54. }  
  55.   



(1) 调用函数streamName()函数获取音频流名称。


  1. <span xmlns=< span="" style="word-wrap: break-word;">"http://www.w3.org/1999/xhtml" style="font-size:24px;">const char *streamName(alsa_handle_t *handle)  
  2. {     
  3.     return snd_pcm_stream_name(direction(handle));  
  4. }    



snd_pcm_stream_name()函数是ALSA-LIB API,在external/alsa-lib/src/pcm/pcm.c文件中定义。
要想得到音频流名称,不得不先分析direction()函数。


  1. <span xmlns=< span="" style="word-wrap: break-word;">"http://www.w3.org/1999/xhtml" style="font-size:24px;">snd_pcm_stream_t direction(alsa_handle_t *handle)  
  2. {  
  3.     return (handle->devices & android_audio_legacy::AudioSystem::DEVICE_OUT_ALL) ? SND_PCM_STREAM_PLAYBACK  
  4.             : SND_PCM_STREAM_CAPTURE;  
  5. }  



原来direction()函数就是用来返回PCM流的方向(放音或者录音)。
direction()函数的返回值将做为snd_pcm_stream_name()的参数,


  1. <span xmlns=< span="" style="word-wrap: break-word;">"http://www.w3.org/1999/xhtml" style="font-size:24px;">const char *snd_pcm_stream_name(snd_pcm_stream_t stream)  
  2. {  
  3.         if (stream > SND_PCM_STREAM_LAST)   
  4.                 return NULL;  
  5.         return <span style=< span="" style="word-wrap: break-word;">"color:#ff0000;">snd_pcm_stream_names[stream];  
  6. }  




  1. <span xmlns=< span="" style="word-wrap: break-word;">"http://www.w3.org/1999/xhtml" style="font-size:24px;">static const char *const snd_pcm_stream_names[] = {  
  2.         STREAM(PLAYBACK),  
  3.         STREAM(CAPTURE),  
  4. };  

好吧,音频流的名称不是放音就是录音。



(2)接下来调用deviceName()函数获取设备名称。这点很重要,将为咱们在asound.conf为新添加的USB AUDIO音频设备命名提供规则。



  1. <span xmlns=< span="" style="word-wrap: break-word;">"http://www.w3.org/1999/xhtml" style="font-size:24px;">const char *deviceName(alsa_handle_t *handle, uint32_t device, int mode)  
  2. {  
  3.     static char <span style=< span="" style="word-wrap: break-word;">"color:#ff0000;">devString[ALSA_NAME_MAX];  
  4.     int hasDevExt = 0;  
  5.   
  6.     strcpy(devString, devicePrefix[direction(handle)]);  
  7.   
  8.     for (int dev = 0; device && dev < deviceSuffixLen; dev++)  
  9.         if (device & <span style=< span="" style="word-wrap: break-word;">"color:#ff0000;">deviceSuffix[dev].device) {  
  10.             ALSA_STRCAT (devString, deviceSuffix[dev].suffix);  
  11.             device &= ~deviceSuffix[dev].device;  
  12.             <span style="color:#ff0000;">hasDevExt = 1;  
  13.         }  
  14.   
  15.     if (hasDevExt) switch (mode) {  
  16.                 case android_audio_legacy::AudioSystem::MODE_NORMAL:  
  17.         ALSA_STRCAT (devString, "_normal")  
  18.         ;  
  19.         break;  
  20.                 case android_audio_legacy::AudioSystem::MODE_RINGTONE:  
  21.         ALSA_STRCAT (devString, "_ringtone")  
  22.         ;  
  23.         break;  
  24.                 case android_audio_legacy::AudioSystem::MODE_IN_CALL:  
  25.         ALSA_STRCAT (devString, "_incall")  
  26.         ;  
  27.         break;  
  28.     };  
  29.   
  30.     return devString;  
  31. }  

用字符数组devString存储设备名称。
首先把设备前缀复制给devString。所以,做为输出音频通道设备的名称,必以AndroidPlayback为前缀;做为输入音频通道设备的名称,必以AndroidCapture为前缀。



  1. <span xmlns=< span="" style="word-wrap: break-word;">"http://www.w3.org/1999/xhtml" style="font-size:24px;">static const char *devicePrefix[SND_PCM_STREAM_LAST + 1] = {  
  2.         /* SND_PCM_STREAM_PLAYBACK : */"AndroidPlayback",  
  3.         /* SND_PCM_STREAM_CAPTURE  : */"AndroidCapture",  
  4. };  



接下来从deviceSuffix数组中查找合适的后缀,追加到devString字符数组中。


  1. "http://www.w3.org/1999/xhtml" style="font-size:24px;">/* The following table(s) need to match in order of the route bits 
  2.  */       
  3. static const device_suffix_t deviceSuffix[] = {  
  4.         {android_audio_legacy::AudioSystem::DEVICE_OUT_EARPIECE,       "_Earpiece"},  
  5.         {android_audio_legacy::AudioSystem::DEVICE_OUT_SPEAKER,        "_Speaker"},  
  6.         {android_audio_legacy::AudioSystem::DEVICE_OUT_BLUETOOTH_SCO,  "_Bluetooth"},  
  7.         {android_audio_legacy::AudioSystem::DEVICE_OUT_WIRED_HEADSET,  "_Headset"},  
  8.         {android_audio_legacy::AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP, "_Bluetooth-A2DP"},  
  9. };   



struct device_suffix_t的定义以下:


  1. <span xmlns=< span="" style="word-wrap: break-word;">"http://www.w3.org/1999/xhtml" style="font-size:24px;">struct device_suffix_t {  
  2.     const android_audio_legacy::AudioSystem::audio_devices device;  
  3.     const char *suffix;  
  4. };  



PS: 咱们也要在此数组中添加USB AUDIO音频设备的相关信息。同时也要在定义了相似DEVICE_OUT_EARPIECE设备的类中定义USB AUDIO音频设备:


  1. <span xmlns=< span="" style="word-wrap: break-word;">"http://www.w3.org/1999/xhtml" style="font-size:24px;"> 1.frameworks/base/media/java/android/media/AudioSystem.java  
  2.     2.frameworks/base/media/java/android/media/AudioManager.java  
  3.     3.hardware/libhardware_legacy/include/hardware_legacy/AudioSystemLegacy.h  
  4.     4.system/core/include/system/audio.h  


题外话:android系统中对音频设备的定义以下(AudioSystem.java):

  1. <span xmlns=< span="" style="word-wrap: break-word;">"http://www.w3.org/1999/xhtml" style=""> <span style=< span="" style="word-wrap: break-word;">"font-size:24px;">   public static final int DEVICE_OUT_EARPIECE = 0x1; // 0x1 << 0  
  2.     public static final int DEVICE_OUT_SPEAKER = 0x2;  // 0x1 << 1  
  3.     public static final int DEVICE_OUT_WIRED_HEADSET = 0x4; // 0x1 << 2  
  4.     public static final int DEVICE_OUT_WIRED_HEADPHONE = 0x8; // 0x1 << 3  
  5.     public static final int DEVICE_OUT_BLUETOOTH_SCO = 0x10; // 0x1 << 4  
  6.     public static final int DEVICE_OUT_BLUETOOTH_SCO_HEADSET = 0x20; // 0x1 << 5  
  7.     public static final int DEVICE_OUT_BLUETOOTH_SCO_CARKIT = 0x40; // 0x1 << 6  
  8.     public static final int DEVICE_OUT_BLUETOOTH_A2DP = 0x80; // 0x1 << 7  
  9.     public static final int DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES = 0x100;  
  10.                                                                       // 0x100 << 0  
  11.     public static final int DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER = 0x200; // 0x100 << 1  
  12.     public static final int DEVICE_OUT_AUX_DIGITAL = 0x400; // 0x100 << 2  
  13.     public static final int DEVICE_OUT_ANLG_DOCK_HEADSET = 0x800; // 0x100 << 3  
  14.     public static final int DEVICE_OUT_DGTL_DOCK_HEADSET = 0x1000; // 0x1000 << 0  
  15.     public static final int DEVICE_OUT_DEFAULT = 0x8000; // 0x1000 << 3  
  16.     // input devices  
  17.     public static final int DEVICE_IN_COMMUNICATION = 0x10000; // 0x10000 << 0  
  18.     public static final int DEVICE_IN_AMBIENT = 0x20000; // 0x10000 << 1  
  19.     public static final int DEVICE_IN_BUILTIN_MIC1 = 0x40000; // 0x10000 << 2  
  20.     public static final int DEVICE_IN_BUILTIN_MIC2 = 0x80000; // 0x10000 << 3  
  21.     public static final int DEVICE_IN_MIC_ARRAY = 0x100000; // 0x100000 << 0  
  22.     public static final int DEVICE_IN_BLUETOOTH_SCO_HEADSET = 0x200000;   
  23.                                                                     // 0x100000 << 1  
  24.     public static final int DEVICE_IN_WIRED_HEADSET = 0x400000; // 0x100000 << 2  
  25.     public static final int DEVICE_IN_AUX_DIGITAL = 0x800000; // 0x100000 << 3  



当设备愈来愈多时,很难保证等号右边的数字中零的个数不写错。采用注释部分的定义方式较好。

当找到了设备后缀后,将对变量hasDevExt赋值为1,表示还会有扩展名称(_normal,_ringtone或者_incall)。

至此,一个设备的PCM节点名称就造成了!

(3)程序将执行到调用snd_pcm_open() ALSA-LIB API,并把刚才获得的设备名称devName做为参数之一,调到ALSA-LIB,进而调到ALSA-DRIVER,去打开所指定的音频设备。若是打开指定的音频设备失败了,将打开默认的音频设备。

(4)若是成功打开音频设备,程序继续往下执行,将调用setHardwareParams()函数设置硬件参数。这些硬件参数包括缓冲区大小,采样率,声道数和音频格式等。其实这些硬件参数都在struct alsa_handle_t中定义,在分析初始化函数s_init()函数时已有分析,在默认音频设备配置_defaultsOut和_defaultsIn中已经指定。


可是,在使用USB AUDIO输入音频设备时,默认的输入音频配置中的声道数和采样率颇有可能与实际使用的USB AUDIO的不一致,致使USB AUDIO设备不可用或者音频失真。所以,须要在执行setHardwareParams()函数前,而且知道是要打开输入音频通道时(输出音频通道的硬件参数配置可用),须要检测时间使用的USB AUDIO音频设备的这两个硬件参数,从新对_defaultsIn中声道数和采样率进行赋值。将在后面作详细分析。

  1. <span xmlns=< span="" style="word-wrap: break-word;">"http://www.w3.org/1999/xhtml" style="font-size:24px;">status_t setHardwareParams(alsa_handle_t *handle)  
  2. {  
  3.     ......  
  4.   
  5.     unsigned int requestedRate = <span style=< span="" style="word-wrap: break-word;">"color:#ff0000;">handle->sampleRate;  
  6.   
  7.     ......  
  8.   
  9. <span style="color:#ff0000;">    err = snd_pcm_hw_params_set_channels(handle->handle, hardwareParams,  
  10.             <span style="color:#ff0000;">handle->channels);  
  11.   
  12.     ......  
  13.   
  14.     err = <span style="color:#ff0000;">snd_pcm_hw_params_set_rate_near(handle->handle, hardwareParams,  
  15.             <span style="color:#ff0000;">&requestedRate, 0);  
  16.   
  17.     ......  
  18. }  
  19.   


(5)最后程序会执行到设置软件参数的函数setHardwareParams()中。在添加USB AUDIO音频设备时,这里没有遇到问题,再也不分析。


2. JAVA API setDeviceConnectionState()调用流程详解。

把最复杂的两大本地服务分析完后,后面的任务就很轻了!
JAVA API setDeviceConnectionState()在文件frameworks/base/media/java/android/media/AudioSystem.java中定义。
    public static native int setDeviceConnectionState(int device, int state, String device_address);
第一个参数就是要打开的音频设备的标识符,将一路传递下去,直到ALSA模块(alsa_default.cpp);
第二个参数表示第一个参数所指的音频设备是否可用;
第三个参数表示设备地址,通常为空。

看到java关键字native,晓得将调到对应的JNI(frameworks/base/core/jni/android_media_AudioSystem.cpp)代码。


  1. <span xmlns=< span="" style="word-wrap: break-word;">"http://www.w3.org/1999/xhtml" style="font-size:24px;">static int   
  2. android_media_AudioSystem_setDeviceConnectionState(JNIEnv *env, jobject thiz,   
  3.                                   jint device, jint state, jstring device_address)  
  4. {  
  5.     const char *c_address = env->GetStringUTFChars(device_address, NULL);  
  6.     int status = check_AudioSystem_Command(  
  7.        <span style="color:#ff0000;">AudioSystem::setDeviceConnectionState(static_cast (device),  
  8.        static_cast (state),  
  9.        c_address));  
  10.     env->ReleaseStringUTFChars(device_address, c_address);  
  11.     return status;  
  12. }  


显然,又调到libmedia库(frameworks/base/media/libmedia/AudioSystem.cpp)中setDeviceConnectionState()函数。


  1. <span xmlns=< span="" style="word-wrap: break-word;">"http://www.w3.org/1999/xhtml" style="font-size:24px;">status_t AudioSystem::setDeviceConnectionState(audio_devices_t device,  
  2.                                                audio_policy_dev_state_t state,  
  3.                                                const char *device_address)  
  4. {  
  5.     const sp& aps = AudioSystem::get_audio_policy_service();  
  6.     const char *address = "";   
  7.   
  8.     if (aps == 0) return PERMISSION_DENIED;  
  9.   
  10.     if (device_address != NULL) {  
  11.         address = device_address;  
  12.     }     
  13.   
  14.     return <span style=< span="" style="word-wrap: break-word;">"color:#ff0000;">aps->setDeviceConnectionState(device, state, address);  
  15. }  



显然,调到APS的setDeviceConnectionState()函数。


  1. <span xmlns=< span="" style="word-wrap: break-word;">"http://www.w3.org/1999/xhtml" style="font-size:24px;">status_t AudioPolicyService::setDeviceConnectionState(audio_devices_t device,  
  2.                                                   audio_policy_dev_state_t state,  
  3.                                                   const char *device_address)  
  4. {  
  5.     ......  
  6.   
  7.     return <span style=< span="" style="word-wrap: break-word;">"color:#ff0000;">mpAudioPolicy->set_device_connection_state(mpAudioPolicy, device,  
  8.                                                       state, device_address);  
  9. }  
  10.   



根据前面对AudioPolicyService服务的启动流程分析可知,mpAudioPolicy指向在文件audio_policy_hal.cpp中定义的音频策略模块。则mpAudioPolicy->set_device_connection_state()函数具体调到函数ap_set_device_connection_state()函数。


  1. <span xmlns=< span="" style="word-wrap: break-word;">"http://www.w3.org/1999/xhtml" style="font-size:24px;">static int ap_set_device_connection_state(struct audio_policy *pol,  
  2.                                           audio_devices_t device,          
  3.                                           audio_policy_dev_state_t state,  
  4.                                           const char *device_address)      
  5. {  
  6.     struct legacy_audio_policy *lap = to_lap(pol);  
  7.     return <span style=< span="" style="word-wrap: break-word;">"color:#ff0000;">lap->apm->setDeviceConnectionState(  
  8.                     (AudioSystem::audio_devices)device,  
  9.                     (AudioSystem::device_connection_state)state,  
  10.                     device_address);                 
  11. }  



一样,由前面对AudioPolicyService服务的启动流程分析可知,lap->apm指向AudioPolicyManagerBase类对象。则lap->apm->setDeviceConnectionState()函数将调到AudioPolicyManagerBase::setDeviceConnectionState()函数。


  1. <span xmlns=< span="" style="word-wrap: break-word;">"http://www.w3.org/1999/xhtml" style="font-size: 24px;"><span style=< span="" style="word-wrap: break-word;">"font-size:18px;">status_t AudioPolicyManagerBase::setDeviceConnectionState(AudioSystem::audio_devices device,  
  2.                                                   AudioSystem::device_connection_state state,  
  3.                                                   const char *device_address)  
  4. {  
  5.     ......  
  6.   
  7.     // handle output devices  
  8.     if (AudioSystem::isOutputDevice(device)) {   <span style=< span="" style="word-wrap: break-word;">"font-size:18px;color:#3333ff;">// 若是是输出设备  
  9. <span style="font-size:18px;">  
  10.     ......  
  11.   
  12.         switch (state)  
  13.        {  
  14.         // handle output device connection  
  15.         case AudioSystem::DEVICE_STATE_AVAILABLE:  
  16.             if (mAvailableOutputDevices & device) {  
  17.                 LOGW("setDeviceConnectionState() device already connected: %x", device);  
  18.                 return INVALID_OPERATION;  
  19.             }  
  20.             LOGV("setDeviceConnectionState() connecting device %x", device);  
  21.   
  22.             // register new device as available  
  23.             mAvailableOutputDevices |= device;   <span style="color:#3333ff;">// 把当前设备加入到可用设备变量中  
  24.   
  25.         .....  
  26.   
  27.         // handle output device disconnection  
  28.         case AudioSystem::DEVICE_STATE_UNAVAILABLE: {  
  29.             if (!(mAvailableOutputDevices & device)) {  
  30.                 LOGW("setDeviceConnectionState() device not connected: %x", device);  
  31.                 return INVALID_OPERATION;  
  32.             }  
  33.   
  34.   
  35.             LOGV("setDeviceConnectionState() disconnecting device %x", device);  
  36.             // remove device from available output devices  
  37.             mAvailableOutputDevices &= ~device; <span style="color:#3333ff;">// 把当前设备从可用设备变量中去除  
  38.   
  39.         ......  
  40.         }  
  41.   
  42.         // request routing change if necessary  
  43.         uint32_t newDevice = <span style="color:#ff0000;">getNewDevice(mHardwareOutput, false);  
  44.    
  45.         ......  
  46.   
  47.         <span style="color:#ff0000;">updateDeviceForStrategy();  
  48.         <span style="font-size:24px;"><strong style=< span="" style="word-wrap: break-word;">"background-color: rgb(153, 153, 153);"><span style=< span="" style="word-wrap: break-word;">"color:#ff0000;">setOutputDevice(mHardwareOutput, newDevice);  
  49.   
  50.         <span style="color:#3333ff;">