一、代码模块位置

1、AudioFlinger



    1. frameworks/base/services/audioflinger/  
    2. +-- Android.mk  
    3. +-- AudioBufferProvider.h  
    4. +-- AudioFlinger.cpp  
    5. +-- AudioFlinger.h  
    6. +-- AudioMixer.cpp  
    7. +-- AudioMixer.h  
    8. +-- AudioPolicyService.cpp  
    9. +-- AudioPolicyService.h  
    10. +-- AudioResampler.cpp  
    11. +-- AudioResamplerCubic.cpp  
    12. +-- AudioResamplerCubic.h  
    13. +-- AudioResampler.h  
    14. +-- AudioResamplerSinc.cpp  
    15. +-- AudioResamplerSinc.h



    两种Audio Hardware HAL接口定义:


    1/ legacy:hardware/libhardware_legacy/include/hardware_legacy/AudioHardwareInterface.h


    2/ 非legacy:hardware/libhardware/include/hardware/audio.h


    2、audio_hw




    1. hardware/libhardware_legacy/audio/  
    2. +-- A2dpAudioInterface.cpp  
    3. +-- A2dpAudioInterface.h  
    4. +-- Android.mk  
    5. +-- AudioDumpInterface.cpp  
    6. +-- AudioDumpInterface.h  
    7. +-- AudioHardwareGeneric.cpp  
    8. +-- AudioHardwareGeneric.h  
    9. +-- AudioHardwareInterface.cpp  
    10. +-- AudioHardwareStub.cpp  
    11. +-- AudioHardwareStub.h  
    12. +-- audio_hw_hal.cpp  
    13. +-- AudioPolicyCompatClient.cpp  
    14. +-- AudioPolicyCompatClient.h  
    15. +-- audio_policy_hal.cpp  
    16. +-- AudioPolicyManagerBase.cpp  
    17. +-- AudioPolicyManagerDefault.cpp  
    18. +-- AudioPolicyManagerDefault.h


    事实上legacy也要封装成非legacy中的audio.h,确切的说需要一个联系legacy interface和not legacy interface的中间层,这里的audio_hw_hal.cpp就充当这样的一个角色了。因此,我们其实也可以把2.3之前的alsa_sound这一套东西也搬过来。



    1. hardware/libhardware/modules/audio/  
    2. +-- Android.mk  
    3. +-- audio_hw.c  
    4. +-- audio_policy.c



      1. device/samsung/tuna/audio/  
      2. +-- Android.mk  
      3. +-- audio_hw.c  
      4. +-- ril_interface.c  
      5. +-- ril_interface.h



      3、tinyalsa


      1. external/tinyalsa/  
      2. +-- Android.mk  
      3. +-- include  
      4. |   +-- tinyalsa  
      5. |       +-- asoundlib.h  
      6. +-- mixer.c      ##类alsa-lib的control,作用音频部件开关、音量调节等  
      7. +-- pcm.c        ##类alsa-lib的pcm,作用音频pcm数据回放录制  
      8. +-- README  
      9. +-- tinycap.c    ##类alsa_arecord  
      10. +-- tinymix.c    ##类alsa_amixer  
      11. +-- tinyplay.c   ##类alsa_aplay


      这其实是历史的必然了,alsa-lib太过复杂繁琐了,我看得也很不爽;更重要的商业上面的考虑,必须移除被GNU GPL授权证所约束的部份,alsa-lib并不是个例。

      注意:上面的hardware/libhardware_legacy/audio/、hardware/libhardware/modules/audio/、device/samsung/tuna/audio/是同层的。之一是legacy audio,用于兼容2.2时代的alsa_sound;之二是stub audio接口;之三是Samsung Tuna的音频抽象层实现。调用层次:AudioFlinger -> audio_hw -> tinyalsa。



      二、Audio Hardware HAL加载





      1、AudioFlinger


        1. //加载audio hardware hal
        2. static int load_audio_interface(const char *if_name, const
        3.                                 audio_hw_device_t **dev)  
        4. {  
        5. int
        6.       
        7. //根据classid和if_name找到指定的动态库并加载,这里加载的是音频动态库,如libaudio.primary.tuna.so
        8.     rc = hw_get_module_by_class(AUDIO_HARDWARE_MODULE_ID, if_name, mod);  
        9. if
        10. goto
        11.   
        12. //加载好的动态库模块必有个open方法,调用open方法打开音频设备模块
        13.     rc = audio_hw_device_open(*mod, dev);  
        14. "couldn't open audio hw device in %s.%s (%s)",  
        15.             AUDIO_HARDWARE_MODULE_ID, if_name, strerror(-rc));  
        16. if
        17. goto
        18.   
        19. return
        20.   
        21. out:  
        22.     *mod = NULL;  
        23.     *dev = NULL;  
        24. return
        25. }  
        26.   
        27. //音频设备接口,hw_get_module_by_class需要根据这些字符串找到相关的音频模块库
        28. static const char
        29. "primary", //主音频设备,一般为本机codec
        30. "a2dp",    //a2dp设备,蓝牙高保真音频
        31. "usb",     //usb-audio设备,这个东东我2.3就考虑要实现了,现在终于支持了
        32. };  
        33. #define ARRAY_SIZE(x) (sizeof((x))/sizeof(((x)[0])))
        34.   
        35. // ----------------------------------------------------------------------------
        36.   
        37. AudioFlinger::AudioFlinger()  
        38.     : BnAudioFlinger(),  
        39. false), mNextUniqueId(1),  
        40. false)  
        41. {  
        42. }  
        43.   
        44. void
        45. {  
        46. int
        47.   
        48.     Mutex::Autolock _l(mLock);  
        49.   
        50. /* TODO: move all this work into an Init() function */
        51.     mHardwareStatus = AUDIO_HW_IDLE;  
        52.   
        53. //打开audio_interfaces数组定义的所有音频设备
        54. for (size_t
        55. const
        56.         audio_hw_device_t *dev;  
        57.   
        58.         rc = load_audio_interface(audio_interfaces[i], &mod, &dev);  
        59. if
        60. continue;  
        61.   
        62. "Loaded %s audio interface from %s (%s)", audio_interfaces[i],  
        63.              mod->name, mod->id);  
        64. //mAudioHwDevs是一个Vector,存储已打开的audio hw devices
        65.   
        66. if
        67.             mPrimaryHardwareDev = dev;  
        68. "Using '%s' (%s.%s) as the primary audio interface",  
        69.                  mod->name, mod->id, audio_interfaces[i]);  
        70.         }  
        71.     }  
        72.   
        73.     mHardwareStatus = AUDIO_HW_INIT;  
        74.   
        75. if
        76. "Primary audio interface not found");  
        77. return;  
        78.     }  
        79.   
        80. //对audio hw devices进行一些初始化,如mode、master volume的设置
        81. for (size_t
        82.         audio_hw_device_t *dev = mAudioHwDevs[i];  
        83.   
        84.         mHardwareStatus = AUDIO_HW_INIT;  
        85.         rc = dev->init_check(dev);  
        86. if
        87.             AutoMutex lock(mHardwareLock);  
        88.   
        89.             mMode = AUDIO_MODE_NORMAL;  
        90.             mHardwareStatus = AUDIO_HW_SET_MODE;  
        91.             dev->set_mode(dev, mMode);  
        92.             mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;  
        93.             dev->set_master_volume(dev, 1.0f);  
        94.             mHardwareStatus = AUDIO_HW_IDLE;  
        95.         }  
        96.     }  
        97. }



        以上对AudioFlinger进行的分析,主要是通过hw_get_module_by_class()找到模块接口名字if_name相匹配的模块库,加载,然后audio_hw_device_open()调用模块的open方法,完成音频设备模块的初始化。






        留意AudioFlinger的构造函数只有简单的私有变量的初始化操作了,把音频设备初始化放到onFirstRef(),Android终于改进了这一点,好的设计根本不应该把可能会失败的操作放到构造函数中。onFirstRef是RefBase类的一个虚函数,在构造sp的时候就会被调用。因此,在构造sp<AudioFlinger>的时候就会触发onFirstRef方法,从而完成音频设备模块初始化。





        2、hw_get_module_by_class





        我们接下来看看hw_get_module_by_class,实现在hardware/libhardware/ hardware.c中,它作用加载指定名字的模块库(.so文件),这个应该是用于加载所有硬件设备相关的库文件,并不只是音频设备。



        1. int hw_get_module_by_class(const char *class_id, const char
        2. const struct
        3. {  
        4. int
        5. int
        6. const struct
        7. char
        8. char
        9. char
        10.   
        11. if
        12. "%s.%s", class_id, inst);  
        13. else
        14.         strlcpy(name, class_id, PATH_MAX);  
        15.           
        16. //这里我们以音频库为例,AudioFlinger调用到这个函数时,
        17. //class_id=AUDIO_HARDWARE_MODULE_ID="audio",inst="primary"(或"a2dp"或"usb")
        18. //那么此时name="audio.primary"
        19.   
        20. /*
        21.      * Here we rely on the fact that calling dlopen multiple times on
        22.      * the same .so will simply increment a refcount (and not load
        23.      * a new copy of the library).
        24.      * We also assume that dlopen() is thread-safe.
        25.      */
        26.   
        27. /* Loop through the configuration variants looking for a module */
        28. for
        29. if
        30. //通过property_get找到厂家标记如"ro.product.board=tuna",这时prop="tuna"
        31. if
        32. continue;  
        33.             }  
        34. sizeof(path), "%s/%s.%s.so",  
        35. //#define HAL_LIBRARY_PATH2 "/vendor/lib/hw"
        36. if (access(path, R_OK) == 0) break;  
        37.   
        38. sizeof(path), "%s/%s.%s.so",  
        39. //#define HAL_LIBRARY_PATH1 "/system/lib/hw"
        40. if (access(path, R_OK) == 0) break;  
        41. else
        42. sizeof(path), "%s/%s.default.so", //如没有指定的库文件,则加载default.so,即stub-device
        43.                      HAL_LIBRARY_PATH1, name);  
        44. if (access(path, R_OK) == 0) break;  
        45.         }  
        46.     }  
        47. //到这里,完成一个模块库的完整路径名称,如path="/system/lib/hw/audio.primary.tuna.so"
        48. //如何生成audio.primary.tuna.so?请看相关的Android.mk文件,其中有定义LOCAL_MODULE := audio.primary.tuna
        49.   
        50.     status = -ENOENT;  
        51. if
        52. /* load the module, if this fails, we're doomed, and we should not try
        53.          * to load a different variant. */
        54. //加载模块库
        55.     }  
        56.   
        57. return
        58. }



        1. /**
        2.  * Every hardware module must have a data structure named HAL_MODULE_INFO_SYM
        3.  * and the fields of this data structure must begin with hw_module_t
        4.  * followed by module specific information.
        5.  */
        6. typedef struct
        7. /** tag must be initialized to HARDWARE_MODULE_TAG */
        8.     uint32_t tag;  
        9.   
        10. /** major version number for the module */
        11.     uint16_t version_major;  
        12.   
        13. /** minor version number of the module */
        14.     uint16_t version_minor;  
        15.   
        16. /** Identifier of module */
        17. const char
        18.   
        19. /** Name of this module */
        20. const char
        21.   
        22. /** Author/owner/implementor of the module */
        23. const char
        24.   
        25. /** Modules methods */
        26. struct
        27.   
        28. /** module's dso */
        29. void* dso;  
        30.   
        31. /** padding to 128 bytes, reserved for future use */
        32.     uint32_t reserved[32-7];  
        33.   
        34. } hw_module_t;  
        35.   
        36. typedef struct
        37. /** Open a specific device */
        38. int (*open)(const struct hw_module_t* module, const char* id,  
        39. struct
        40.   
        41. } hw_module_methods_t;



        例如,在audio_hw.c中,它是这样定义的:



        1. static struct
        2.     .open = adev_open,  
        3. };  
        4.   
        5. struct
        6.     .common = {  
        7.         .tag = HARDWARE_MODULE_TAG,  
        8.         .version_major = 1,  
        9.         .version_minor = 0,  
        10.         .id = AUDIO_HARDWARE_MODULE_ID,  
        11. "Tuna audio HW HAL",  
        12. "The Android Open Source Project",  
        13.         .methods = &hal_module_methods,  
        14.     },  
        15. };




        3、audio_hw



        好了,经过一番周折,又dlopen又dlsym的,终于进入我们的audio_hw。这部分没什么好说的,按照hardware/libhardware/include/hardware/audio.h定义的接口实现就行了。这些接口全扔到一个结构体里面的,这样做的好处是:不必用大量的dlsym来获取各个接口函数的地址,只需找到这个结构体即可,从易用性和可扩充性来说,都是首选方式。



        接口定义如下:

          1. struct
          2. struct
          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. const struct
          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 (*init_check)(const struct
          17.   
          18. /** set the audio volume of a voice call. Range is between 0.0 and 1.0 */
          19. int (*set_voice_volume)(struct audio_hw_device *dev, float
          20.   
          21. /**
          22.      * set the audio volume for all audio activities other than voice call.
          23.      * Range between 0.0 and 1.0. If any value other than 0 is returned,
          24.      * the software mixer will emulate this capability.
          25.      */
          26. int (*set_master_volume)(struct audio_hw_device *dev, float
          27.   
          28. /**
          29.      * setMode is called when the audio mode changes. AUDIO_MODE_NORMAL mode
          30.      * is for standard audio playback, AUDIO_MODE_RINGTONE when a ringtone is
          31.      * playing, and AUDIO_MODE_IN_CALL when a call is in progress.
          32.      */
          33. int (*set_mode)(struct audio_hw_device *dev, int
          34.   
          35. /* mic mute */
          36. int (*set_mic_mute)(struct audio_hw_device *dev, bool
          37. int (*get_mic_mute)(const struct audio_hw_device *dev, bool
          38.   
          39. /* set/get global audio parameters */
          40. int (*set_parameters)(struct audio_hw_device *dev, const char
          41.   
          42. /*
          43.      * Returns a pointer to a heap allocated string. The caller is responsible
          44.      * for freeing the memory for it.
          45.      */
          46. char * (*get_parameters)(const struct
          47. const char
          48.   
          49. /* Returns audio input buffer size according to parameters passed or
          50.      * 0 if one of the parameters is not supported
          51.      */
          52. size_t (*get_input_buffer_size)(const struct
          53. int
          54. int
          55.   
          56. /** This method creates and opens the audio hardware output stream */
          57. int (*open_output_stream)(struct
          58. int
          59.                               uint32_t *sample_rate,  
          60. struct
          61.   
          62. void (*close_output_stream)(struct
          63. struct
          64.   
          65. /** This method creates and opens the audio hardware input stream */
          66. int (*open_input_stream)(struct
          67. int
          68.                              uint32_t *sample_rate,  
          69.                              audio_in_acoustics_t acoustics,  
          70. struct
          71.   
          72. void (*close_input_stream)(struct
          73. struct
          74.   
          75. /** This method dumps the state of the audio hardware */
          76. int (*dump)(const struct audio_hw_device *dev, int
          77. };  
          78. typedef struct



          注:这是比较标准的C接口设计方法了,但是个人感觉还是用C++比较好,直观易读。2.3之前都是用C++实现这些接口设计的,到了4.0,不知道为何采纳用C?不会理由是做底层的不懂C++吧?!




          三、Audio Hardware HAL的legacy实现



          之前提到两种Audio Hardware HAL接口定义:
          1/ legacy:hardware/libhardware_legacy/include/hardware_legacy/AudioHardwareInterface.h
          2/ 非legacy:hardware/libhardware/include/hardware/audio.h
          前者是2.3及之前的音频设备接口定义,后者是4.0的接口定义。



          为了兼容以前的设计,4.0实现一个中间层:hardware/libhardware_legacy/audio/audio_hw_hal.cpp,结构与其他的audio_hw.c大同小异,差别在于open方法:


          1. static int legacy_adev_open(const hw_module_t* module, const char* name,  
          2.                             hw_device_t** device)  
          3. {  
          4.     ......  
          5.   
          6.     ladev->hwif = createAudioHardware();  
          7. if
          8.         ret = -EIO;  
          9. goto
          10.     }  
          11.   
          12.     ......  
          13. }

          因此老一套的alsa-lib、alsa-utils和alsa_sound也可以照搬过来,这里的文件被编译成静态库的,因此你需要修改alsa_sound里面的Android.mk文件,链接这个静态库。还有alsa_sound的命名空间原来是“android”,现在需要改成“android_audio_legacy”。


          四、a2dp Audio HAL的实现


          4.0的a2dp audio hal放到bluez里实现了,我找了好一会才找到:


          external/Bluetooth/bluez/audio/android_audio_hw.c


          大致与上面提到的audio_hw.c类似,因为都是基于audio.h定义的接口来实现的。


          如果需要编译这个库,须在BoardConfig.mk里定义:


          BOARD_HAVE_BLUETOOTH := true



          开始还提到现在支持3种audio设备了,分别是primary、a2dp和usb。目前剩下usb audio hal我没有找到,不知是否需要自己去实现?其实alsa-driver都支持大部分的usb-audio设备了,因此上层也可调用tinyalsa的接口,就像samsung tuna的audio_hw.c那样。



          五、音质改进???


          可使用audio echo cancel和更好的resampler(SRC)???



          --to be continued…