Android Audio介紹


開始這篇文章之前,可以先了解<Linux音頻編程>

1. 架構

在Android中,Audio整體架構如下

audo_structure

2. Java Audio

在Java層把Audio從功能上分為三類接口

AudioService:   負責的是Audio系統的綜合管理功能, 包括音量控制、音頻IO設備的管理、音頻焦點機制
AudioTrack:     負責音頻數據的輸出,即播放
AudioRecorder:  負責音頻數據的輸出和輸入,即錄制

2.1 AudioService

AudioService由SystemServer啟動,實現了IAudioService的Bn端;AudioManager則實現了IAudioService的Bp端

AudioService的功能實現依賴Java AudioSystem類,AudioSystem是Native AudioSystem在Java層的封裝和代理

IAudioService  -   frameworks/base/media/java/android/media/IAudioService.aidl)

SystemServer::startOtherServices()
    SystemServiceManager::startService(AudioService.Lifecycle.class)
        new AudioService()
        AudioService::onStart()
            publishBinderService(Context.AUDIO_SERVICE, new AudioService());
                // 向servicemanager注冊服務
                ServiceManager.addService( , , , )
        AudioService::onBootPhase(SystemService.PHASE_ACTIVITY_MANAGER_READY)
            AudioService::systemReady()
                AudioHandler::handleMessage(MSG_SYSTEM_READY)
                    AudioService::onSystemReady()
                        AudioHandler::onLoadSoundEffects()
                        // Bluetooth releated config
                        AudioService::onIndicateSystemReady()
                            // 位於android_media_AudioSystem.cpp
                            android_media_AudioSystem_systemReady()
                                // 位於AudioSystem.cpp
                                AudioSystem::systemReady()

AudioTrack通過JNI的方式使用android_media_AudioTrack.cpp封裝的接口,進而使用到Native AudioTrack提供的接口

AudioRecord通過JNI的方式使用android_media_AudioRecord.cpp封裝的接口,進而使用到Native AudioRecord提供的接口

3. Native Audio

3.1 audioserver

Native Audio服務在Android N之前存在於mediaserver中,Android N之后由audioserver來啟動

audioserver主要啟動了兩個Native binder服務

- AudioFlinger:        音頻系統策略的執行者, 負責音頻流設備的管理及音頻流數據的處理傳輸, 由libaudioflinger實現具體功能
- AudioPolicyService : 音頻系統策略的制定者, 負責音頻設備切換的策略抉擇、音量調節策略等, 由libaudiopolicyservice實現具體功能

audioserver的啟動的詳細過程如下

/* * frameworks/av/media/audioserver/audioserver.rc */ # cat audioserver.rc service audioserver /system/bin/audioserver class core user audioserver onrestart restart vendor.audio-hal-2-0 onrestart restart audio-hal-2-0 /* * Code: frameworks/av/media/audioserver/main_audioserver.cpp * Output: /system/bin/audioserver */ main() AudioFlinger::instantiate() BinderService::instantiate() BinderService::publish() IServiceManager sm = defaultServiceManager() sm::addService("media.audio_flinger", new AudioFlinger()) AudioFlinger::onFirstRef() new PatchPanel(this) gAudioFlinger = this; AudioPolicyService::instantiate() sm::addService("media.audio_policy", new AudioPolicyService()) AudioPolicyService::onFirstRef() // Tone播放線程 new AudioCommandThread("ApmTone", this) AudioCommandThread::onFirstRef() Thread::run() AudioCommandThread::threadLoop() // Audio命令線程 new AudioCommandThread("ApmAudio", this) // 輸出命令線程 new AudioCommandThread("ApmOutput", this) new AudioPolicyClient(this) createAudioPolicyManager() new AudioPolicyManager(mAudioPolicyClient) AudioPolicyManager::AudioPolicyManager() /* * 當定義了USE_XML_AUDIO_POLICY_CONF = 1 * 加載/odm/etc/audio_policy_configuration.xml * /vendor/etc/audio_policy_configuration.xml * /system/etc/audio_policy_configuration.xml * 否則加載 * /system/etc/audio_policy.conf * /vendor/etc/audio_policy.conf */ AudioPolicyManager::loadConfig() deserializeAudioPolicyXmlConfig() // FIXME: Do a lot of things AudioPolicyManager::initialize()
// 加載音頻設備, 如primary,usb,a2dp等
AudioPolicyClient::loadHwModule()
AudioFlinger::loadHwModule()
AudioFlinger::loadHwModule_l()
DevicesFactoryHalInterface::openDevice() new AudioPolicyEffects() new UidPolicy(this) UidPolicy::registerSelf() // Oboe Service AAudioService::instantiate() SoundTriggerHwService::instantiate()

3.2 AudioFlinger

AudioFlinger實現了名為”media.audio_flinger”的binder本地端,而遠程端由libaudioclient的IAudioFlinger實現。

// 接口定義
frameworks/av/include/media/IAudioFlinger.h 

// 實現AudioFlinger本地端
libaudioflinger <==> frameworks/av/services/audioflinger/* 

// 實現AudioFlinger遠程端
libaudioclient <==> frameworks/av/media/libaudioclient/*

AudioFlinger主要提供了如下接口

IAudioFlinger

在AudioFliger中,將DeviceHalInterface抽象為AudioHwDevice(音頻設備)和AudioStreamOut(音頻輸出流)

3.3 AudioPolicyService

AudioPolicyService實現了名為”media.audio_policy”的binder本地端,而遠程端由libaudioclient的IAudioPolicyService實現。

// 接口定義
frameworks/av/include/media/IAudioPolicyService.h

// 實現AudioPolicyService本地端
libaudiopolicyservice <==> frameworks/av/services/audiopolicy/* 

// 實現AudioPolicyService遠程端
libaudioclient <==> frameworks/av/media/libaudioclient/*

AudioPolicyService主要提供了如下接口

3.4 libaudioclient

libaudioclient實現了AudioFlinger和AudioPolicyService的遠程端,並實現了如下接口供media JNI使用

// android::media::*  <===> frameworks/av/media/libaudioclient/
// JNI                <===> frameworks/base/core/jni
-----------------------------------------------------
| android::media::* | JNI                           |
-----------------------------------------------------
| AudioSystem.cpp   | android_media_AudioSystem.cpp |
| AudioRecord.cpp   | android_media_AudioRecord.cpp |
| AudioTrack.cpp    | android_media_AudioTrack.cpp  |
-----------------------------------------------------

3.5 AAudio

AAudio是在Android O版本中引入的全新Android C API。此API專為需要低延遲的高性能音頻應用而設計。應用通過讀取數據並將數據寫入流來與AAudio進行通信。

// 接口定義
frameworks/av/media/libaaudio/include/aaudio/AAudio.h

// 實現AAudio服務
libaaudioservice  <==> frameworks/av/services/oboeservice/*

// 實現AAudio客戶端
libaaudio         <==> frameworks/av/media/libaaudio/*

4. Audio HAL

Audio HAL架構比較復雜,混合了HIDL和Legacy HAL,目前已經有一套成熟的框架
可參考<Android O Treble架構下Hal進程啟動及HIDL服務注冊過程>

對廠商來說,實現以so庫的方式音頻接口,並在音頻政策配置文件(audio_policy_configuration.xml)進行配置,系統就會自動加載對應音頻設備

4.1 音頻接口

HAL接口定義在hardware/libhardware/include/hardware/audio.h文件中

- audio_hw_device:  音頻設備
- audio_stream_out: 輸出流
- audio_stream_in:  輸入流
- audio_stream:     音頻流

下面是當前已經實現或可參考的音頻設備

默認主設備:       hardware/libhardware/modules/audio
車載主設備:       device/generic/car/emulator/audio/driver
USB設備:          hardware/libhardware/modules/usbaudio
RemoteSubmix設備: hardware/libhardware/modules/audio_remote_submix
藍牙A2DP設備:     system/bt/audio_a2dp_hw

4.2 HAL接口

Audio HAL接口(以2.0為例)是對音頻接口的進一步抽象

// 音頻設備
IDevice.hal
  |- initCheck()
  |- setMasterVolume(float): 設置除voice call外其他音頻活動的音量
  |- getMasterVolume():      獲取主音量
  |- setMicMute(bool):       設置麥克風靜音狀態
  |- getMicMute():           獲取麥克風靜音狀態
  |- setMasterMute(bool):    設置靜音狀態
  |- getMasterMute(bool):    獲取靜音狀態
  |- getInputBufferSize(AudioConfig): 獲取音頻輸入緩沖區大小
  |- openOutputStream(*):    創建和打開音頻硬件輸出流
  |- openInputStream(*):     創建和打開音頻硬件輸入流
  |- supportsAudioPatches(): 判斷HAL是否支持AudioPatch
  |- createAudioPatch(*):    為SRC和SINK創建AudioPatch
  |- releaseAudioPatch(*):   釋放一個AudioPatch
  |- getAudioPort(*):        獲取指定音頻端口屬性
  |- setAudioPortConfig(*):  配置音頻端口
  |- getHwAvSync():          獲取設備的硬件同步源
  |- setScreenState(bool):   設置屏幕狀態
  |- getParameters(vec<string>): 獲取廠商定義的參數值
  |- setParameters(vec<ParameterValue>): 設置廠商定義的參數值

// 音頻代理
IDevicesFactory.hal
  |- openDevice(Device):     打開一個音頻設備

// 主音頻設備
IPrimaryDevice.hal
  |- setMasterVolume(float): 設置voice call音量
  |- setMode(AudioMode):     設置音頻模式
  |- getBtScoNrecEnabled():  獲取藍牙ECNR使能狀態
  |- setBtScoNrecEnabled():  設置藍牙ECNR使能狀態
  |- getBtScoWidebandEnabled():     獲取藍牙Wideband使能狀態
  |- setBtScoWidebandEnabled(bool): 設置藍牙Wideband使能狀態
  |- getTtyMode():           獲取當前TTY模式
  |- setTtyMode():           設置當前TTY模式
  |- getHacEnabled():        獲取HearingAid使能狀態
  |- setHacEnabled():        設置HearingAid使能狀態

// 音頻流
IStream.hal
  |- getFrameSize():         獲取幀大小
  |- getFrameCount():        獲取緩沖區幀數
  |- getBufferSize():        獲取流的緩沖區大小
  |- getSampleRate():        獲取采樣率(Hz)
  |- getSupportedSampleRates():  獲取流支持的支持的采樣率(Hz)
  |- setSampleRate(uint32_t):    設置流的采樣率
  |- getChannelMask():       獲取流的channel mask
  |- getSupportedChannelMasks(): 獲取流支持的channel mask
  |- setChannelMask():       獲取流的channel mask
  |- getFormat():            獲取流的音頻格式
  |- getSupportedFormats():  獲取流支持的音頻格式
  |- setFormat():            設置流的音頻格式
  |- getAudioProperties():   獲取流參數
  |- addEffect():            添加音效到流
  |- removeEffect(uint64_t): 從流上停止某音效
  |- standby(uint64_t):      讓硬件輸入輸出進入standby模式
  |- getDevice():            獲取流連接的設備
  |- setDevice():            連接設置到流
  |- setConnectedState():    通知設備連接狀態
  |- setHwAvSync(AudioHwSync):   設置硬件同步源
  |- getParameters(vec<string>): 獲取廠商參數
  |- setParameters(vec<ParameterValue>):  設置廠商參數
  |- start():                開始流操作(mmap模式)
  |- stop():                 停止流操作
  |- createMmapBuffer():     獲取audio mmap緩沖區信息
  |- getMmapPosition():      讀取audio mmap緩沖區讀寫位置
  |- close():                關閉和釋放流

// 音頻輸入流
IStreamIn.hal
  |- getAudioSource():       獲取輸入流的source描述
  |- setGain():              設置音頻驅動的輸入增益
  |- prepareForReading():    設置必需的傳輸層以從驅動接收音頻緩沖區
  |- getInputFramesLost():   獲取丟失的輸入幀的數量
  |- getCapturePosition():   獲取接收到的音頻幀數與時鍾時間。

// 音頻輸出流
IStreamOut.hal
  |- getLatency():           獲取硬件傳輸延遲(毫秒)
  |- setVolume(float, float):    設置音量, 用於混音后
  |- prepareForWriting():    設置必需的傳輸層將音頻緩沖區傳遞給驅動
  |- getRenderPosition():    獲取音頻DSP寫入DAC的音頻幀數
  |- getNextWriteTimestamp():    獲取下一次寫入音頻驅動時間(微秒)
  |- setCallback():          設置回調接口, 用於非阻塞模式
  |- clearCallback():        清楚回調
  |- supportsPauseAndResume():   HAL是否支持暫停和恢復流
  |- pause():                暫停流
  |- resume():               恢復流
  |- supportsDrain():        ???
  |- drain():                ???
  |- flush():                刷新流
  |- getPresentationPosition():  獲取音頻幀數

// 音頻輸入流回調
IStreamOutCallback.hal
  |- onWriteReady():         非阻塞寫入已完成
  |- onDrainReady():         Drain(?)完成
  |- onError():              出錯

4.3 HAL服務

Audio HAL服務對HAL接口和音頻接口進行了HIDL方式地封裝

/*
 * Code:   hardware/interfaces/audio/common/all-versions/default/service/service.cpp
 * Output: /vendor/bin/hw/android.hardware.audio@2.0-service
 */
main()
   // 連接至vndservicemanager
   android::ProcessState::initWithDriver("/dev/vndbinder") 
   android::ProcessState::self()->startThreadPool()

   registerPassthroughServiceImplementation<audio::V4_0::IDevicesFactory>()
   registerPassthroughServiceImplementation<audio::V2_0::IDevicesFactory>()

   registerPassthroughServiceImplementation<audio::effect::V4_0::IEffectsFactory>()
   registerPassthroughServiceImplementation<audio::effect::V2_0::IEffectsFactory>()

   registerPassthroughServiceImplementation<soundtrigger::V2_1::ISoundTriggerHw>()
   registerPassthroughServiceImplementation<soundtrigger::V2_0::ISoundTriggerHw>()

   registerPassthroughServiceImplementation<bluetooth::a2dp::V1_0::IBluetoothAudioOffload>()

   android::hardware::joinRpcThreadpool()

# cat /vendor/etc/init/android.hardware.audio@2.0-service.rc
service vendor.audio-hal-2-0 /vendor/bin/hw/android.hardware.audio@2.0-service
    class hal
    user audioserver
    oneshot
    interface android.hardware.audio@4.0::IDevicesFactory default
    interface android.hardware.audio@2.0::IDevicesFactory default

# /vendor/etc/vintf/manifest.xml
<manifest version="1.0" type="device" target-level="3">
...
    <hal format="hidl">
        <name>android.hardware.audio</name>
        <transport>hwbinder</transport>
        <version>4.0</version>
        <interface>
            <name>IDevicesFactory</name>
            <instance>default</instance>
        </interface>
    </hal>
...
</manifest>

4.4 libaudiohal

libaudiohal封裝了audio hal的接口,以libaudiohal.so的形式供AudioFlinger使用,而libaudiohal又使用了libaudiohal@4.0和libaudiohal@2.0兩個庫,同時libaudiohal@4.0和libaudiohal@2.0又分別是audio hal接口的封裝

libaudiohal最終提供的是DeviceHalInterface、DevicesFactoryHalInterface和EffectsFactoryHalInterface接口

# tree frameworks/av/media/libaudiohal
.
+--- 2.0
|   +--- Android.bp   -- libaudiohal@2.0
+--- 4.0
|   +--- Android.bp   -- libaudiohal@4.0
+--- Android.bp       -- libaudiohal

/*
 * DevicesFactoryHalInterface提供了create和openDevice兩個方法
 */
DevicesFactoryHalInterface::create()
    /*
     * 這里僅僅分析了V2_0版本, V4_0類似
     * 提供了兩種方式來訪問audio hardware
     *   - HIDL:   即DevicesFactoryHalHidl, 用於primary, usb和remote_submix
     *   - Legacy: 即DevicesFactoryHalLocal, 用於a2dp
     */
    new DevicesFactoryHalHybrid()
        new DevicesFactoryHalLocal()
        new DevicesFactoryHalHidl()
            hardware::audio::V2_0::IDevicesFactory::getService()

DevicesFactoryHalInterface::openDevice(char *name, DeviceHalInterface *device)
    DevicesFactoryHalHybrid::openDevice(name, device)
        // 針對hearing_aid和a2dp設備
        DevicesFactoryHalLocal::openDevice(name, device)
            load_audio_interface(name, audio_hw_device_t **dev)
            new DeviceHalLocal(dev)
        // 針對其他設備, 包括primary, usb, remote_submix設備
        DevicesFactoryHalHidl::openDevice(name, device)
            // 獲取HIDL接口名
            nameFromHal(name, IDevicesFactory::Device &)
            IDevicesFactory::openDevice()
                new DeviceHalHidl(IDevice)

/* 這里暫不做分析 */
EffectsFactoryHalInterface::create()

參考:
<Android音頻>


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM