提醒一下,純個人筆記,你完全可能看暈
一、音頻數(shù)字化基礎(chǔ)知識
見書,列出知識點如下:
聲音
聲波,聲音頻率、響度, 音調(diào)、音色。
音響設(shè)備中的聲道
得翻翻初高中的課本了。聲音數(shù)字化過程
聲源 -> mic -> ADC(模-數(shù)轉(zhuǎn)換器) ,采樣、量化 -> [可選項] 過濾、音效等特殊化處理 -> 編碼 ->
其中采樣過程,涉及采樣率、采樣深度、聲道等。
奈奎斯特采樣定律: 見書。
音量調(diào)節(jié)與韋伯定律: 見書。
這得看看大學(xué)課本:高數(shù)、模擬電路、數(shù)字電路、多媒體技術(shù)。音頻編碼解碼格式
是指對原始PCM音頻數(shù)據(jù)的壓縮與編碼、解碼格式。音頻文件格式
是指存儲音頻數(shù)據(jù)的文件存儲格式。
二、架構(gòu)層級圖
音頻框架全圖
三、代碼與生成的庫
3-1、代碼位置
frameworks\av\media
\frameworks\av\services\audioflinger
frameworks/base/media/
Audio 系統(tǒng)代碼
- 1、Audio 的Java 部分
frameworks/base/media/java/android/media
frameworks/base/media/jni
生成framework.jar,media是里面的一部分。
與Audio 相關(guān)的Java包是android.media,主要包含AudioManager和Audio 系統(tǒng)的幾個類。
提供了兩套API,如:
AudioTrack.java/AudioRecord.java 更原始,更靈活,也更不方便,
MediaPlayer/MediaRecord包含了編解碼,文件格式支持,更簡便。
- 2、Audio 的JNI 部分
frameworks/base/core/jni
生成庫libandroid_runtime.so,Audio 的JNI是其中的一個部分。這部分屏蔽了對Audio本地框架調(diào)用細(xì)節(jié),簡化后,相當(dāng)于JAVA接口的本地中轉(zhuǎn),本地接口轉(zhuǎn)換本來就是JNI功能之一。
- 3、Audio 的框架部分
總位置frameworks\av\media,里面都是多媒體相關(guān)的
3.1
libmedia.so
部分,Audio系統(tǒng)的核心框架,向上層Audio 的
JNI 部分提供接口,間接為Audio的Java部分提供接口。
frameworks\av\media\libmedia
frameworks\av\include\media
舊版本:
frameworks/base/include/media/
frameworks/base/media/libmedia/
這部分內(nèi)容被編譯成庫libmedia.so,實現(xiàn)Audio系統(tǒng)的核心框架,同時提供了IAudioFlinger 類接口。在這個類中,可以獲得IAudioTrack 和IAudioRecorder 兩個接口,分別用于聲音的播放和錄制。
AudioTrack 和AudioRecorder
分別調(diào)用IAudioTrack 和IAudioRecorder 來實現(xiàn)。IAudioFlinger.h、IAudioTrack.h 和IAudioRecorder.h 這三個接口通過下層來實現(xiàn)。AudioSystem.h、AudioTrack.h 和AudioRecorder.h 是對上層提供的接口,它們既供本地程序調(diào)用,也可以通過JNI 向Java 層提供接口。從功能上看,
AudioSystem
負(fù)責(zé)的是Audio 系統(tǒng)的綜合管理功能,而AudioTrack 和AudioRecorder 分別負(fù)責(zé)音頻數(shù)據(jù)的輸出和輸入,即播放和錄制。另外一個接口是IAudioFlingerClient,它作為向IAudioFlinger中注冊的監(jiān)聽器,相當(dāng)于使用回調(diào)函數(shù)獲取IAudioFlinger運行時信息。
MediaScanner
負(fù)責(zé)媒體文件掃描。
3.2 mediaplayerservice
frameworks\av\media\libmediaplayerservice
生成 libmediaplayerservice.so
上層其中一套API的服務(wù)端實現(xiàn),即MediaPlayer/MediaRecord的服務(wù)端實現(xiàn)。
其實最終實現(xiàn),Audio部分是通過libmedia.so里的AudioTrack/AudioRecord實現(xiàn)。
此外,內(nèi)部包括了編碼、解碼、文件格式、視頻播放/錄制等。
視頻播放部分,有好幾個播放器,如StagefrightPlayer/Recorder,NuPlayer,而早期還有用openCore。
3.3 mediaserver,媒體服務(wù)進(jìn)程
frameworks\av\media\mediaserver
所有媒體服務(wù)端代碼線程都在此進(jìn)程被啟動
生成/system/bin/mediaserver
3.4 libeffects 音效部分
frameworks\av\media\libeffects
生成
/system/lib/libeffects.so // 總?cè)肟?br>
/system/lib/soundfx/ //具體各種音效
- 4、本地services
部分,音頻服務(wù)進(jìn)程
4.1 Audio Flinger
frameworks\av\services\audioflinger
舊版
frameworks/base/libs/audioflinger
這部分內(nèi)容被編譯成庫libaudioflinger.so,它是Audio系統(tǒng)的本地服務(wù)部分。(其實也有l(wèi)ibaudioresampler.so)
4.2 audiopolicy本地框架服務(wù)部分
frameworks\av\services\audiopolicy
生成libaudiopolicymanager.so, libaudiopolicyservice.so , libaudiopolicymanagerdefault.so
音頻策略的本地服務(wù)框架,
向上提供接口,即向AudioSystem.cpp/AudioService.cpp/AudioManager.cpp等提供接口,//我猜是這樣,至少AudioSystem.cpp確實包裝了AudioPolicyService.cpp
向下通過HAL層調(diào)用到廠商真正實現(xiàn)音頻策略的庫,默認(rèn)實現(xiàn)為audio_policy.default.so,而最終又調(diào)用到具體實現(xiàn)類AudioPolicyManagerBase。
功能上只負(fù)責(zé)策略性處理,包括轉(zhuǎn)給audio_policy.default.so后得到的結(jié)果,
而具體音頻處理事務(wù)轉(zhuǎn)到AudioFlinger最終去執(zhí)行。
關(guān)鍵點是AudioPolicyManagerBase 會去加載audio_policy.conf , audio_effects.conf,從而實現(xiàn)音頻設(shè)備、音效上的策略的可配置。所以一般只改配置,應(yīng)該很少有廠商去改AudioManagerBase吧。
- 5、Audio 的硬件抽象層接口
Android對Audio HAL的框架定義及遺留實現(xiàn)
hardware\libhardware\modules
hardware/libhardware_legacy/include/hardware/
HAL廠商實現(xiàn)代碼
device\samsung\manta\audio
device\asus\grouper\audio
1、Audio使用JNI和Java對上層提供接口,JNI部分通過調(diào)用libmedia庫提供的接口來實現(xiàn)。
2、 Audio 本地框架類是libmedia.so的一個部分,這些Audio框架類對上層提供接口,由下層的本地代碼去實現(xiàn)。
3、AudioFlinger繼承l(wèi)ibmeida中的接口,提供實現(xiàn)庫libaudiofilnger.so。這部分內(nèi)容沒有自己的對外頭文件,上層調(diào)用的只是libmedia本部分的接口,但實際調(diào)用的內(nèi)容是libaudioflinger.so。
4、Audio的硬件抽象層提供到硬件的接口,供AudioFlinger調(diào)用。Audio的硬件抽象層實際上是各個平臺開發(fā)過程中需要主要關(guān)注和獨立完成的部分。
在Android的Audio系統(tǒng)中,無論上層還是下層,都使用一個管理類和輸出輸入兩個類來表示整個Audio系統(tǒng),輸出輸入兩個類負(fù)責(zé)數(shù)據(jù)通道。在各個層次之間具有對應(yīng)關(guān)系:
- 6、底層音頻架構(gòu)相關(guān)**
system\core\include\system
external/tinyalsa
或 alsa版本
external/alsa-lib
external/alsa-utils
4.1后基本都用tinyalsa
- 7、其它
7.1 音頻常量定義
system\core\include\system\audio.h
AudioSystem.java
里面很多常量保持一致,一個給native引用,一個給java引用。
7.2 native層公用頭文件定義
system\core\include\system\audio.h
這個頭文件很重要,它的一些常量定義,需要上下均保持一致,所以Java層中的AudioSystem.java與此保持一致。
audio.h則是給native層的所有模塊引用,
包括JNI層的各cpp文件,libaudioflinger.so,audio.xxx.so,audio_policy.so等。
(當(dāng)然,廢話一句,到alsalib庫就不是了,它引用頭文件是alsa標(biāo)準(zhǔn)的頭文件,旨在按alsa架構(gòu)看齊,
并向上提供統(tǒng)一的alsalib接口,反而是Android的HAL層要使用alsalib的頭文件。)
音頻庫與代碼位置
libmedia.so
frameworks\av\media\libmedia
音頻服務(wù)框架代碼
libaudioflinger.so****
\frameworks\av\services\audioflinger
HAL框架代碼
hardware\libhardware\modules
HAL的官方標(biāo)準(zhǔn)實現(xiàn)代碼?
HAL廠商實現(xiàn)代碼
device\samsung\manta\audio
device\asus\grouper\audio
底層音頻架構(gòu)相關(guān)
system\core\include\system
external/tinyalsa
音頻庫與小機文件位置
音頻服務(wù)框架庫:** libaudioflinger.so libmedia.so
一般放在機器中的/system/lib目錄。
音頻設(shè)備HAL庫:audio_xxx.so
具體由硬件廠商來實現(xiàn)和定制,audio_policy.conf的配置跟這些實現(xiàn)要對應(yīng)。
這些庫即音頻HAL層框架的實現(xiàn),音頻HAL框架定義在:hardware\libhardware\include\hardware\audio.h
具體的實現(xiàn)代碼需要廠商提供,而google默認(rèn)的實現(xiàn),代碼在: ???
生成的庫,一般會有:audio_primary.so,audio_a2dp.so等。
一般放在機器中的/system/lib/hw或vendor/lib/hw目錄。
相關(guān)進(jìn)程:
systemserver: AudioFlinger, AudioPolicyService等,即Audio服務(wù)端
APP所在進(jìn)程:AudioTrack,AudioRecoder等,即Audio客戶端
andorid.process.media: 多媒體管理類所在進(jìn)程
3-2、運行時模型,進(jìn)程線程關(guān)系
四、Linux中的音頻框架
- Linux原生三種:OSS, ALSA, TinyAlsa。
目前Android使用的是TinyALSA音頻庫。TinyAlsa其實只是位于Linux應(yīng)用層的一個音頻庫,依賴于ALSA驅(qū)動架構(gòu),即底層驅(qū)動必須是用ALSA驅(qū)動架構(gòu),它是Android用于替代ALSA架構(gòu)在Linux應(yīng)用層的龐大復(fù)雜的庫,讓其更適用于嵌入式設(shè)備。
反正,它為Linux應(yīng)用層提供了統(tǒng)一方便的音頻接口。如pcm_read() / pcm_write()
而在Linux內(nèi)核中,使用的ALSA音頻架構(gòu),驅(qū)動框架按ALSA框架接口來寫,驅(qū)動那塊的移植是SOC廠商的事情。
參考:
ALSA官方文檔
http://www.alsa-project.org/~tiwai/writing-an-alsa-driver/index.html
ALSA聲卡驅(qū)動系列文章
http://blog.csdn.net/DroidPhone/article/category/1118446
各種音頻硬件通路圖
http://blog.csdn.net/qianjin0703/article/details/6387662
拼湊還算完整的一篇(部分來自以上的文章)
http://www.360doc.com/content/14/0414/10/97538_368733041.shtml
- 支持的音頻設(shè)備(輸出)列表
硬件音頻輸出設(shè)備的類型, 見書
在HAL層,一個音頻設(shè)備,用一個 audio_hw_device_t 結(jié)構(gòu)體來表示,而它支持的輸出類型,在audio_policy.conf被指明。
當(dāng)上層要打開一個OUT通道時,會尋找匹配的類型,進(jìn)行打開。
- Android支持的媒體格式
見書
可錄制的音頻來源
可錄制的視頻來源
CAMERA 或 DEFAULT
五、代碼詳解
5-1、 類的使用
AudioRecord.cpp / AudioRecord.java(只是前者的JAVA封裝)
AudioRecord.java的使用步驟
- 創(chuàng)建一個數(shù)據(jù)流。
- 構(gòu)造一個AudioRecord對象,其中需要的最小錄音緩存buffer大小可以通過getMinBufferSize方法得到。如果buffer容量過小,將導(dǎo)致對象構(gòu)造的失敗。
- 初始化一個buffer,該buffer大于等于AudioRecord對象用于寫聲音數(shù)據(jù)的buffer大小。
- 開始錄音。
- 從AudioRecord中讀取聲音數(shù)據(jù)到初始化buffer,將buffer中數(shù)據(jù)導(dǎo)入數(shù)據(jù)流。
- 停止錄音。
- 關(guān)閉數(shù)據(jù)流。
對應(yīng)的AudioRecord.cpp的使用代碼:
AudioRecord pAudioRecord = new android::AudioRecord();
pAudioRecord->set( inputSource,
sampleRateInHz,
audioFormat,
channelConfig,
minFrameCount,
AudioRecordCallback,
NULL,
0,
true,
0,
android::AudioRecord::TRANSFER_DEFAULT,
AUDIO_INPUT_FLAG_NONE, //AUDIO_INPUT_FLAG_NONE //audio_input_flags_t flags);
NULL
);
或
AudioRecord recordInstance = new AudioRecord(
MediaRecorder.AudioSource.REMOTE_SUBMIX, frequency,
AudioFormat.CHANNEL_IN_MONO, audioEncoding, bufferSize);
recordInstance.startRecording();
//AudioRecod.cpp中的set()函數(shù),看來一些限制:
AudioRecod.set(){
if (inputSource == AUDIO_SOURCE_DEFAULT) {** //默認(rèn)錄制音源,即是MIC
inputSource = AUDIO_SOURCE_MIC;
}
if (sampleRate == 0) {
ALOGE("Invalid sample rate %u", sampleRate);
return BAD_VALUE;
}
// these below should probably come from the audioFlinger too...
if (format == AUDIO_FORMAT_DEFAULT) {**//默認(rèn)數(shù)據(jù)格式,即是**AUDIO_FORMAT_PCM_16_BIT
format = AUDIO_FORMAT_PCM_16_BIT;
}
// Temporary restriction: AudioFlinger currently supports 16-bit PCM only
if (format != AUDIO_FORMAT_PCM_16_BIT) {**//數(shù)據(jù)格式,其實只能是**AUDIO_FORMAT_PCM_16_BIT
ALOGE("Format %#x is not supported", format);
return BAD_VALUE;
}
}
一些問題:
有哪些音源,輸入還是輸出? 單雙聲道? 音源和后兩者的參數(shù),如何配對?
其中:
錄制音源,*CPP中與JAVA層定義一致。有如下一些音源。
總結(jié)下,就是MIC,通話進(jìn)出,REMOTE_SUBMIX,CAMCORDER(錄像用的mic,一般沒有獨立,最終其實也是默認(rèn)的MIC)。
所以有些東西還是錄制不到的,比如主設(shè)備混音后輸出的聲音,這包括了各種可能的音樂、鈴聲、通知等聲音。
也就是,Android給到上層應(yīng)用的接口是,只能給你錄制MIC,錄制通話,錄像。其余錄音場景,不給。
typedef enum {
AUDIO_SOURCE_DEFAULT = 0,
AUDIO_SOURCE_MIC = 1,
AUDIO_SOURCE_VOICE_UPLINK = 2,
AUDIO_SOURCE_VOICE_DOWNLINK = 3,
AUDIO_SOURCE_VOICE_CALL = 4,
AUDIO_SOURCE_CAMCORDER = 5,
AUDIO_SOURCE_VOICE_RECOGNITION = 6,
AUDIO_SOURCE_VOICE_COMMUNICATION = 7,
AUDIO_SOURCE_REMOTE_SUBMIX = 8, / Source for the mix to be presented remotely. /
/ An example of remote presentation is Wifi Display /
/ where a dongle attached to a TV can be used to /
/ play the mix captured by this audio source. /
AUDIO_SOURCE_CNT,
AUDIO_SOURCE_MAX = AUDIO_SOURCE_CNT - 1,
AUDIO_SOURCE_HOTWORD = 1999, / A low-priority, preemptible audio source for
for background software hotword detection.
Same tuning as AUDIO_SOURCE_VOICE_RECOGNITION.
Used only internally to the framework. Not exposed
at the audio HAL. */
} audio_source_t;
聲道:
定義了輸入和輸出,分別又定義了單、雙、前后、5.1聲道、7.1聲道的各個聲道,然后又定義了更方便使用的各種組合聲道。
意思是按人們對于聲道的理解來定義,而不理會底層如何實現(xiàn)。
顯然,有些音源,是不可能有5.1聲道的,對吧,所以,還是有個有效匹配問題。
AudioTrack
見書,
- 簡單說來,播放流程如下:
Java端發(fā)起調(diào)用,MediaPlayer會轉(zhuǎn)至MediaPlayerService,然后會調(diào)用相應(yīng)的解碼工具解碼后創(chuàng)建AudioTrack,所有待輸出的AudioTrack在AudioFlinger::AudioMixer里合成,然后通過AudioHAL(AudioHardwareInterface的實際實現(xiàn)者)傳至實際的硬件來實現(xiàn)播放。
如果直接使用AudioTrack.java-> AudioTrack.cpp, 則后續(xù)流程直接到AudioFlinger,然后往下。
AudioTrack總結(jié)
通過這一次的分析,我自己覺得有以下幾個點:
l AudioTrack的工作原理,尤其是數(shù)據(jù)的傳遞這一塊,做了比較細(xì)致的分析,包括共享內(nèi)存,跨進(jìn)程的同步等,也能解釋不少疑惑了。
l 看起來,最重要的工作是在AudioFlinger中做的。通過AudioTrack的介紹,我們給后續(xù)深入分析AudioFlinger提供了一個切入點
工作原理和流程嘛,再說一次好了,JAVA層就看最前面那個例子吧,實在沒什么說的。
l AudioTrack被new出來,然后set了一堆信息,同時會通過Binder機制調(diào)用另外一端的AudioFlinger,得到IAudioTrack對象,通過它和AudioFlinger交互。
l 調(diào)用start函數(shù)后,會啟動一個線程專門做回調(diào)處理,代碼里邊也會有那種數(shù)據(jù)拷貝的回調(diào),但是JNI層的回調(diào)函數(shù)實際并沒有往里邊寫數(shù)據(jù),大家只要看write就可以了
l 用戶一次次得write,那AudioTrack無非就是把數(shù)據(jù)memcpy到共享buffer中咯
l 可想而知,AudioFlinger那一定有一個線程在memcpy數(shù)據(jù)到音頻設(shè)備中去。我們拭目以待。
5-2、相關(guān)類說明
多媒體管理類
MediaScannerService
三種廣播的掃描流程
三種廣播的掃描路徑
MediaProvider
MediaReceiver
MediaStore播放與錄制,JAVA層
MediaPlayer
封裝給App層,用于播放音視頻多媒體的類
狀態(tài)遷移圖
框架圖
MediaRecorder
封裝給App層,用于錄制音視頻多媒體的類。非常友好的封裝,錄制、編碼、存儲等所有細(xì)節(jié)都被封裝起來。****
狀態(tài)遷移圖
框架圖
AudioRecord.java
封裝給APP層的音頻錄制類,提供非常友好,簡化的接口和調(diào)用流程。
通過JNI封裝了AudioRecord.cpp功能類的具體事務(wù)操作。
JNI文件:android_media_AudioRecord.cpp
AudioTrack.java
AudioTrack.cpp的java層封裝類,播放音頻
AudioTrack.cpp
用于音頻數(shù)據(jù)的回放。
分兩類數(shù)據(jù)傳送模式:
主動push 和 被pull
分兩類數(shù)據(jù)操作模式:
static
數(shù)據(jù)量小,時間短,如鈴音、通知、音效。數(shù)據(jù)一次性交付,然后播放。
stream
數(shù)據(jù)量大,時間長,如音樂等。數(shù)據(jù)通過共享內(nèi)存方式傳送,以流形式傳輸播放。****
AudioRecord.cpp
音頻錄制功能類,client端,服務(wù)端才是真正執(zhí)行錄制工作的。
AudioRecord:****AudioRecordThread
- 框架層
MediaPlayerService
APP層MediaPlayer和MediaRecorder的服務(wù)端,播放和錄制操作的服務(wù)類,向下調(diào)用真正播放和操作的執(zhí)行類與功能類。
MediaRecoderClient
與客戶端MediaRecorde****r對應(yīng)的服務(wù)端的助理類,多實例,一一對應(yīng)關(guān)系。
StageFrightRecoder
直接的錄制器,錄制操作的執(zhí)行類。
Client
與客戶端MediaPlaye****r對應(yīng)的服務(wù)端的助理類,多實例,一一對應(yīng)關(guān)系。****
各種播放器類
類型有:NU_PLAYER, PV_PLAYER等
AudioSystem.cpp
包裝類,隔離AudioTrack/AudioRecord類 <==> AudioPolicyService、AudioFlinger。
因此向上提供統(tǒng)一接口,隔離后者策略類、音頻服務(wù)類的變化。
看其實現(xiàn),就是中轉(zhuǎn)調(diào)用,轉(zhuǎn)給AudioPolicyService或AudioFlinger。
AudioService
AudioFlinger
AudioFlinger(下面簡稱AF)是整個音頻系統(tǒng)的核心與難點。作為Android系統(tǒng)中的音頻中樞,它同時也是一個系統(tǒng)服務(wù),啟到承上(為上層提供訪問接口)啟下(通過HAL來管理音頻設(shè)備)的作用。AudioFlinger向下訪問AudioHardware,實現(xiàn)輸出音頻數(shù)據(jù),控制音頻參數(shù)。
AudioFlinger則是策略的執(zhí)行者,例如具體如何與音頻設(shè)備通信,如何維護(hù)現(xiàn)有系統(tǒng)中的音頻設(shè)備,以及多個音頻流的混音如何處理等等都得由它來完成。
AudioFlinger-->PlaybackThread
負(fù)責(zé)回放音頻數(shù)據(jù)工作的線程類
**AudioFlinger-->MixerThread
負(fù)責(zé)混音工作的線程類
**AudioFlinger-->MixerThread-->AudioMixer
負(fù)責(zé)混音具體事務(wù)的功能類
@ AudioFlinger的創(chuàng)建與初始化
創(chuàng)建見書,
TODO: 初始化
@ 對音頻設(shè)備的管理
AudioPolicyManagerBase 構(gòu)造函數(shù)中,AudioPolicyManagerBase->loadAudioPolicyConfig,對 audio_policy.conf加載、解析, 找出可用的音頻設(shè)備 -> AudioFlinger加載模塊
AudioPolicyService
AudioPolicyService是策略的制定者,比如什么時候打開音頻接口設(shè)備、某種Stream類型的音頻對應(yīng)什么設(shè)備等等。而AudioFlinger則是策略的執(zhí)行者,例如具體如何與音頻設(shè)備通信,如何維護(hù)現(xiàn)有系統(tǒng)中的音頻設(shè)備,以及多個音頻流的混音如何處理等等都得由它來完成。AudioPolicyService根據(jù)用戶配置來指導(dǎo)AudioFlinger加載設(shè)備接口,起到路由功能。
audio_policy.conf
不同的Android產(chǎn)品在音頻(設(shè)備)的設(shè)計上通常是存在差異的,而這些差異可以同過Audio的配置文件audio_policy.conf來獲得。在Android系統(tǒng)中音頻配置文件存放路徑有兩處,存放地址可以從AudioPolicyManagerBase.cpp文件中知道:
#define AUDIO_POLICY_VENDOR_CONFIG_FILE "/vendor/etc/audio_policy.conf"
#define AUDIO_POLICY_CONFIG_FILE "/system/etc/audio_policy.conf"
在AudioPolicyManager.cpp文件中可以知道系統(tǒng)會首先加載vendor/etc目錄下的configure文件,再加載system/etc目錄下的configure文件。若這兩者加載都發(fā)生錯誤的話,系統(tǒng)會加載default配置文件,并命名為primary module,從這可以看出,音頻系統(tǒng)中一定必須存在的module就是primary了。
TODO: 這些個配置,什么來由,在代碼中如何加載,處理,生成對應(yīng)的audio_hw_device_t,上層如何來用這些信息,干嘛用。
在HAL層,一個音頻設(shè)備,用一個 audio_hw_device_t 結(jié)構(gòu)體來表示,而它支持的輸出類型,在audio_policy.conf被指明。
當(dāng)上層要打開一個OUT通道時,會尋找匹配的類型,進(jìn)行打開。
audio_effects.conf
音效配置文件,最終機器,一般存放在:
/system/etc/audio_effects.conf
/vendor/etc/audio_effects.conf
struct default_audio_policy {
struct audio_policy policy;
struct audio_policy_service_ops *aps_ops;
void *service;
};
AudioPolicyManagerBase
是什么,干什么用?
初始化過程: AudioPolicyService構(gòu)造中: rc = mpAudioPolicyDev->create_audio_policy(mpAudioPolicyDev, &aps_ops, this,
&mpAudioPolicy); -> .... -> AudioPolicyManagerBase
@ Audio策略類的路由功能?
何謂路由功能,路由過程是怎樣的?
audio.h中的輸出設(shè)備類型是怎么回事? 與audio_policy.conf有什么關(guān)系?
policy類是如何使用這些定義及配置的?
最終如何選擇到合適的輸出設(shè)備,即對應(yīng)audio_deivce類,找到對應(yīng)輸出通道,即audio_deivce ->openOutputStream,具體打開哪一個?
Android上層定義的聲音流類型,又是如何對應(yīng)下來的?
**據(jù)說上面調(diào)用下來,輾轉(zhuǎn)libaudiopolicy.so 后,到AudioPolicyManagerBase.getDevicesForStream()->****.getDeviceForStrategy(), 里面正是AudioSystem.java/AudioSystemLegacy.h中定義的聲音流類型與audio.h中定義的音頻設(shè)備類型轉(zhuǎn)換過程。