一、Audio音頻架構簡介
二、Android Audio系統框架
三、Audio架構以及各層的代碼分布圖
四、音頻框架在Android系統中的進一步細化
五、創建聲卡和注冊聲卡
六、Android Audio系統的結構
七、Audio音頻原理介紹
八、Audio音頻策略制定與策略執行的呼叫流程
九、Android AudioPolicyService服務啟動程序
十、Android系統中所有的音頻介面設備保存到AudioFlinger的成員變數mAudioHwDevs中
十一、audio_policy.conf同時定義了多個audio介面
十二、通過AudioFlinger的loadHwModule加載各audio介面對應的庫檔案實作呼叫PlaybackThread播放執行緒或RecordThread錄音執行緒
十三、AudioFlinger的openInput()方法呼叫流程分析
十四、AudioFlinger的openOutput()方法的呼叫流程分析
十五、Audio系統為了能正常播放音頻資料,需要創建抽象的音頻輸出介面物件,打開音頻輸出程序
十六、打開音頻輸入的流程
十七、打開音頻輸出后,在AudioFlinger與AudioPolicyService中的表現形式
十八、打開音頻輸入后,在AudioFlinger與AudioPolicyService中的表現形式
十九、AudioPolicyService加載完系統定義的所有音頻介面,并生成相應的資料物件
二十、AudioPolicyService與AudioTrack和AudioFlinger的關系
二十一、AudioPolicyService注冊名為服務的流程
二十二、AudioTrack構造程序
二十三、AudioTrack和AudioFlinger的關系
二十四、audio_policy與AudioPolicyService、AudioPolicyCompatClient之間的關系

一、Audio音頻架構簡介
APP
整個音頻體系的最上層
Framework
MediaPlayer和MediaRecorder、AudioTrack和AudioRecorder,Android系統為控制音頻系統提供了AudioManager、AudioService及AudioSystem類,這些都是framework為便利上層應用開發所設計的
Libraries
系統服務AudioFlinger和AudioPolicyService(比如:ServiceManager、LocationManagerService、ActivityManagerService等等),音頻體系中另一個重要的系統服務是MediaPlayerService
HAL
硬體抽象層是AudioFlinger直接訪問的物件,這說明了兩個問題,一方面AudioFlinger并不直接呼叫底層的驅動程式;另一方面,AudioFlinger上層(包括和它同一層的MediaPlayerService)的模塊只需要與它進行互動就可以實作音頻相關的功能了,因而我們可以認為AudioFlinger是Android音頻系統中真正的“隔離板”,無論下面如何變化,上層的實作都可以保持兼容,音頻方面的硬體抽象層主要分為兩部分,即AudioFlinger和AudioPolicyService,實際上后者并不是一個真實的設備,只是采用虛擬設備的方式來讓廠商可以方便地定制出自己的策略,抽象層的任務是將AudioFlinger/AudioPolicyService真正地與硬體設備關聯起來
以前Android系統中的Audio系統依賴于ALSA-lib,但后期就變為了tinyalsa,這樣的轉變不應該對上層造成破壞,因而Audio HAL提供了統一的介面來定義它與AudioFlinger/AudioPolicyService之間的通信方式,這就是audio_hw_device、audio_stream_in及audio_stream_out等等存在的目的,這些Struct資料型別內部大多只是函式指標的定義,是一些“殼”,當AudioFlinger/AudioPolicyService初始化時,它們會去尋找系統中最匹配的實作(這些實作駐留在以audio.primary.*,audio.a2dp.*為名的各種庫中)來填充這些“殼”
理解Android音頻系統的時候分為兩條線索
以庫為線索,比如:AudioPolicyService和AudioFlinger都是在libaudioflinger庫中,而AudioTrack、AudioRecorder等一系列實作則在libmedia庫中
以行程為線索,庫并不代表一個行程,行程則依賴于庫來運行,雖然有的類是在同一個庫中實作的,但并不代表它們會在同一個行程中被呼叫,比如AudioFlinger和AudioPolicyService都駐留于名為mediaserver的系統行程中,而AudioTrack/AudioRecorder和MediaPlayer/MediaRecorder一樣實際上只是應用行程的一部分,它們通過binder服務來與其它系統行程通信
二、Android Audio系統框架

三、Audio架構以及各層的代碼分布圖

四、音頻框架在Android系統中的進一步細化

五、創建聲卡和注冊聲卡

六、Android Audio系統的結構

七、Audio音頻原理介紹
AudioFlinger、AudioPolicyService和AudioTrack/AudioRecorder拋開MediaPlayer、MediaRecorder這些與應用開發直接關聯的部分,整個音頻系統的核心就是由這三者構建而成的,其中前兩個都是System Service,駐留在mediaserver行程中,不斷地處理AudioTrack/AudioRecorder的請求,音頻的回放和錄制從大的流程上看都是相似的,所以我們側重于對AudioTrack的分析
把所有媒體相關的native層服務(包括AudioFlinger,MediaPlayerService,CameraService和AudioPolicyService)啟動起來,編譯生成的mediaserver將被燒錄到設備的/system/bin/mediaserver路徑,然后由系統啟動時的init行程啟動
Audio系統的結構
libmedia.so提供Audio介面,這些Audio介面既向上層開放,也向本地代碼開放
libaudiofilnger.so提供Audio介面實作
Audio硬體抽象層提供到硬體的介面,供AudioFlinger呼叫
Audio使用JNI和JAVA對上層提供介面
media庫中的Audio框架部分
Android 的Audio的核心框架在media庫中提供,其中對上面主要實作AudioSystem、AudioTrack和AudioRecorder三個類,提供了IAudioFlinger類介面,在這個類中,可以獲得IAudioTrack和IAudioRecorder兩個介面,分別用于聲音的播放和錄制,AudioTrack和AudioRecorder分別通過呼叫IAudioTrack和IAudioRecorder來實作
Audio系統的頭檔案
路徑為:frameworks/base/include/media/
AudioSystem.h
IAudioFlinger.h
AudioTrack.h
IAudioTrack.h
AudioRecorder.h
IAudioRecorder.h
Ixxx的介面通過AudioFlinger來實作,其他介面通過JNI向上層提供介面
Audio系統的頭檔案在frameworks/base/include/media/目錄中,主要的頭檔案如下
AudioSystem.h:media庫的Audio部分對上層的總管介面
IAudioFlinger.h:需要下層實作的總管介面
AudioTrack.h:放音部分對上介面
IAudioTrack.h:放音部分需要下層實作的介面
AudioRecorder.h:錄音部分對上介面
IAudioRecorder.h:錄音部分需要下層實作的介面
IAudioFlinger.h、IAudioTrack.h和IAudioRecorder.h這三個介面通過下層的繼承來實作(即:AudioFlinger)
AudioFlinger.h,AudioTrack.h和AudioRecorder.h是對上層提供的介面,它們既供本地程式呼叫(例如:聲音的播放器、錄制器等),也可以通過JNI向Java層提供介面
AudioTrack和AudioRecorder都具有start,stop和pause等介面,前者具有write介面,用于聲音的播放,后者具有read介面,用于聲音的錄制
AudioSystem用于Audio系統的控制作業,主要包含一些set和get介面,是一個對上層的類
AudioFlinger是Audio系統的核心,來自AudioTrack的資料,最終在這里得到處理并被寫入Audio HAL層
MediaPlayer在framework層還是會創建AudioTrack,把解碼后的PCM數流傳遞給AudioTrack,AudioTrack再傳遞給AudioFlinger進行混音,然后才傳遞給硬體播放,所以是MediaPlayer包含了AudioTrack,使用AudioTrack播放音樂
MediaPlayer提供了更完整的封裝和狀態控制,相比MediaPlayer,AudioTrack更為精練、高效,實際上MediaPlayerService的內部實作就是使用了AudioTrack把所有媒體相關的native層服務(包括AudioFlinger,MediaPlayerService,CameraService和AudioPolicyService)啟動起來,編譯生成的mediaserver將被燒錄到設備的/system/bin/mediaserver路徑,然后由系統啟動時的init行程啟動
兩種Audio Hardware HAL介面定義
legacy:hardware/libhardware_legacy/include/hardware_legacy/AudioHardwareInterface.h
非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方法事實上legacy也要封裝成非legacy中的audio.h,確切的說需要一個聯系legacy interface和not legacy interface的中間層,這里的audio_hw_hal.cpp就充當這樣的一個角色了
hardware/libhardware/modules/audio/
createAudioHardware()函式
external/tinyalsa/
mixer.c 類alsa-lib的control,作用音頻部件開關、音量調節等
pcm.c 類alsa-lib的pcm,作用音頻pcm資料回放錄制
上面的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硬體抽象層的實作在各個系統中可能是不同的,需要使用代碼去繼承相應的類并實作它們,作為Android系統本地框架層和驅動程式介面AudioFlinger繼承了libmedia.so(Audio本地框架類)里面的介面,上層呼叫的只是libmedia.so部分的介面,但實際上呼叫的內容是libaudioflinger.so,使用JNI和Java對上層提供介面,JNI部分通過呼叫libmedia.so庫提供的介面來實作
Audio硬體抽象層提供到硬體的介面,供AudioFlinger呼叫,Audio的硬體抽象層實際上是各個平臺開發程序中需要主要關注和獨立完成的部分,因為Android中的Audio系統不涉及編解碼環節,只負責上層系統和底層Audio硬體的互動,所以通常以PCM作為輸入/輸出格式
IAudioFlinger類介面通過該類可以獲得IAudioTrack和IAudioRecorder兩個介面,分別用于聲音的播放和錄制,AudioTrack和AudioRecorder分別通過呼叫IAudioTrack和IAudioRecorder來實作
硬體抽象層主要實作了AudioStreamInALSA和AudioStreamOutALSA兩個類,這兩個類又會呼叫該檔案下的 ALSAStreamOps類的方法,AudioStreamInALSA是錄音部分呼叫的路徑,在AudioStreamInALSA的建構式中會對alsa進行一些初始化引數設定,
AudioStreamInALSA的read方法是最主要的方法,audioflinger層的read呼叫就是對 AudioStreamInALSA的read的呼叫,由于
錄音部分出現單聲道和雙聲道資料傳輸的問題,修改read方法如下,即可實作了錄音功能正常, 避免了在編碼的時候修改資料時其他編碼仍不能作業的弊端
八、Audio音頻策略制定與策略執行的呼叫流程

AudioPolicyService是策略的制定者,AudioFlinger則是策略的執行者
AudioTrack是AudioFlinger的客戶端,AudioFlinger是Android系統中Audio管理的中樞
在Android中AudioPolicyService最終都會呼叫到AudioFlinger中去,因為AudioFlinger實際創建并管理了硬體設備
AudioFlinger類是代表整個AudioFlinger服務的類,其余所有的作業類都是通過內部類的方式在其中定義的
九、Android AudioPolicyService服務啟動程序
AudioPolicyService完成的作業
加載audio_policy.default.so庫得到audio_policy_module模塊
通過audio_policy_module模塊打開audio_policy_device設備
通過audio_policy_device設備創建audio_policy
hw_get_module函式加載硬體抽象層模塊的程序
audio_policy實作在audio_policy_hal.cpp中,audio_policy_service_ops實作在AudioPolicyService.cpp中,create_audio_policy()函式就是創建并初始化一個legacy_audio_policy物件,AudioPolicyCompatClient是對audio_policy_service_ops的封裝類,對外提供audio_policy_service_ops資料結構中定義的介面
Android AudioPolicyService服務啟動程序
參考AudioPolicyCompatClient物件,這樣音頻管理器AudioPolicyManager就可以使用audio_policy_service_ops中的介面
優先加載/vendor/etc/audio_policy.conf組態檔,如果該組態檔不存在,則加載/system/etc/audio_policy.conf組態檔,如果該檔案還是不存在,則通過函式defaultAudioPolicyConfig()來設定默認音頻介面
設定各種音頻流對應的音量調節點
通過名稱打開對應的音頻介面硬體抽象庫
打開mAttachedOutputDevices對應的輸出
將輸出IOProfile封裝為AudioOutputDescriptor物件
設定當前音頻介面的默認輸出設備
打開輸出,在AudioFlinger中創建PlaybackThread執行緒,并回傳該執行緒的id
設定可以使用的輸出設備為mAttachedOutputDevices
將輸出描述符物件AudioOutputDescriptor及創建的PlaybackThread執行緒id以鍵值對形式保存
設定默認輸出設備
AudioPolicyManagerBase物件構造程序中主要完成以下幾個步驟
loadAudioPolicyConfig(AUDIO_POLICY_CONFIG_FILE)加載audio_policy.conf組態檔
initializeVolumeCurves()初始化各種音頻流對應的音量調節點
加載audio policy硬體抽象庫:mpClientInterface->loadHwModule(mHwModules[i]->mName)
打開attached_output_devices輸出mpClientInterface->openOutput();
保存輸出設備描述符物件addOutput(output, outputDesc);
十、Android系統中所有的音頻介面設備保存到AudioFlinger的成員變數mAudioHwDevs中

audio_policy.conf檔案
從audio_policy.conf檔案中可以發現,系統包含了primary、a2dp、usb等音頻介面,對應著系統中的audio.<primary/a2dp/usb>.<device>.so,每個音頻介面中又包含了若干個outputs & inputs,并且每個output or input又包含了若干個devices,且還有采樣頻率,聲道數等資訊,這些devices資訊、采樣頻率資訊 & 聲道資訊等都會保存在各自module的IOProfile中,按上文中audio_policy.conf組態檔所描述,系統最后會生成6個modules(eg.primary,a2dp,hdmi,r_submix,hs_usb & usb)以及7個outputs
十一、audio_policy.conf同時定義了多個audio介面

不同的Android產品在音頻的設計上通常是存在差異的,而這些差異可以通過Audio的組態檔audio_policy.conf來獲得,在Android系統中音頻組態檔存放路徑有兩處,存放地址可以從AudioPolicyManagerBase.cpp檔案中獲取
在AudioPolicyManager.cpp檔案中可以知道系統會首先加載vendor/etc目錄下的configure檔案,再加載system/etc目錄下的configure檔案,若這兩者加載都發生錯誤的話,系統會加載default組態檔,并命名為primary module
通過loadGlobalConfig(root)函式來讀取這些全域配置資訊,通過loadHwModules()函式來加載系統配置的所有audio介面(加載音頻介面),由于audio_policy.conf可以定義多個音頻介面,因此該函式回圈呼叫loadHwModule()來決議每個音頻介面引數資訊,Android定義HwModule類來描述每一個audio介面引數,定義IOProfile類來描述輸入輸出模式配置
/system/etc/audio_policy.conf
/vendor/etc/audio_policy.conf
加載audio_module模塊
AudioPolicyManager通過讀取audio_policy.conf組態檔,可以知道系統當前支持哪些音頻介面以及attached的輸入輸出設備、默認輸出設備,接下來就需要加載這些音頻介面的硬體抽象庫
AudioPolicyClientInterface提供了加載音頻介面硬體抽象庫的介面函式,AudioPolicyCompatClient通過代理audio_policy_service_ops實作AudioPolicyClientInterface介面
AudioPolicyCompatClient將音頻模塊加載作業交給audio_policy_service_ops,AudioPolicyService又將其轉交給AudioFlinger
當AudioPolicyManagerBase構造時,它會根據用戶提供的audio_policy.conf來分析系統中有哪些audio介面(primary,a2dp以及usb),然后通過AudioFlinger::loadHwModule加載各audio介面對應的庫檔案,并依次打開其中的output(openOutput)和input(openInput)
打開音頻輸出時創建一個audio_stream_out通道,并創建AudioStreamOut物件以及新建PlaybackThread播放執行緒
打開音頻輸入時創建一個audio_stream_in通道,并創建AudioStreamIn物件以及創建RecordThread錄音執行緒
audio_policy.conf檔案定義了兩種音頻配置資訊
當前系統支持的音頻輸入輸出設備及默認輸入輸出設備,這些資訊是通過global_configuration配置項來設定,在global_configuration中定義了三種音頻設備資訊
attached_output_devices:已連接的輸出設備
default_output_device:默認輸出設備
attached_input_devices:已連接的輸入設備
系統支持的音頻介面資訊
audio_policy.conf定義了系統支持的所有音頻介面引數資訊,比如primary、a2dp、usb等
每種音頻介面包含輸入輸出,每種輸入輸出又包含多種輸入輸出配置,每種輸入輸出配置又支持多種音頻設備,AudioPolicyManagerBase首先加載/vendor/etc/audio_policy.conf,如果該檔案不存在,則加載/system/etc/audio_policy.conf
audio_policy.conf同時定義了多個audio 介面,每一個audio介面包含若干output和input,而每個output和input又同時支持多種輸入輸出模式,每種輸入輸出模式又支持若干種設備
十二、通過AudioFlinger的loadHwModule加載各audio介面對應的庫檔案實作呼叫PlaybackThread播放執行緒或RecordThread錄音執行緒

十三、AudioFlinger的openInput()方法呼叫流程分析

十四、AudioFlinger的openOutput()方法的呼叫流程分析

十五、Audio系統為了能正常播放音頻資料,需要創建抽象的音頻輸出介面物件,打開音頻輸出程序

十六、打開音頻輸入的流程

十七、打開音頻輸出后,在AudioFlinger與AudioPolicyService中的表現形式

十八、打開音頻輸入后,在AudioFlinger與AudioPolicyService中的表現形式

十九、AudioPolicyService加載完系統定義的所有音頻介面,并生成相應的資料物件

二十、AudioPolicyService與AudioTrack和AudioFlinger的關系

二十一、AudioPolicyService注冊名為服務的流程

二十二、AudioTrack構造程序



二十三、AudioTrack和AudioFlinger的關系

二十四、audio_policy與AudioPolicyService、AudioPolicyCompatClient之間的關系

關注微信公眾號,獲取更多最新文章

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/243932.html
標籤:其他
