一篇不錯的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);  
相關文章
相關標籤/搜索