Android音頻框架筆記 - 上篇

提醒一下,純個人筆記,你完全可能看暈

一、音頻數(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)層級圖

音頻框架全圖

Paste_Image.png

Paste_Image.png

Paste_Image.png

三、代碼與生成的庫

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)系:

Paste_Image.png
  • 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的使用步驟

  1. 創(chuàng)建一個數(shù)據(jù)流。
  2. 構(gòu)造一個AudioRecord對象,其中需要的最小錄音緩存buffer大小可以通過getMinBufferSize方法得到。如果buffer容量過小,將導(dǎo)致對象構(gòu)造的失敗。
  3. 初始化一個buffer,該buffer大于等于AudioRecord對象用于寫聲音數(shù)據(jù)的buffer大小。
  4. 開始錄音。
  5. 從AudioRecord中讀取聲音數(shù)據(jù)到初始化buffer,將buffer中數(shù)據(jù)導(dǎo)入數(shù)據(jù)流。
  6. 停止錄音。
  7. 關(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)換過程。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,825評論 6 546
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,814評論 3 429
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,980評論 0 384
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 64,064評論 1 319
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 72,779評論 6 414
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 56,109評論 1 330
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,099評論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 43,287評論 0 291
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,799評論 1 338
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 41,515評論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,750評論 1 375
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,221評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,933評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,327評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,667評論 1 296
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,492評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 48,703評論 2 380

推薦閱讀更多精彩內(nèi)容