AudioPolicyService 和 AudioPolicyManager

 

 

引言

AudioPolicyService是Android音頻系統的兩大服務之一,另一個服務是AudioFlinger,這兩大服務都在系統啓動時有 MediaSever加載,加載的代碼位於:frameworks/base/media/mediaserver /main_mediaserver.cpp。AudioFlinger主要負責管理音頻數據處理以及和硬件抽象層相關的工作。本文主要介紹 AudioPolicyService。

AudioPolicyService

AudioPolicyService主要完成以下任務:

  • JAVA應用層通過JNI,經由IAudioPolicyService接口,訪問AudioPolicyService提供的服務
  • 輸入輸出設備的連接狀態
  • 系統的音頻策略(strategy)的切換
  • 音量/音頻參數的設置

AudioPolicyService的構成

進一步說明:

1. AudioPolicyService繼承了IAudioPolicyService接口,這樣AudioPolicyService就可以基於Android的Binder機制,向外部提供服務;

2. AudioPolicyService同時也繼承了AudioPolicyClientInterface類,他有一個AudioPolicyInterface類的成員指針mpPolicyManager,實際上就是指向了AudioPolicyManager;

3. AudioPolicyManager類繼承了AudioPolicyInterface類以便向AudioPolicyService提供服務,反過來同時還有一個AudioPolicyClientInterface指針,該指針在構造函數中被初始化,指向了AudioPolicyService,實際上,AudioPolicyService是通過成員指針mpPolicyManager訪問AudioPolicyManager,而 AudioPolicyManager則通過AudioPolicyClientInterface(mpClientInterface)訪問 AudioPolicyService;

4. AudioPolicyService有一個內部線程類AudioCommandThread,顧名思義,所有的命令(音量控制,輸入、輸出的切換等)最終都會在該線程中排隊執行;

AudioPolicyManager

AudioPolicyService的很大一部分管理工作都是在AudioPolicyManager中完成的。包括音量管理,音頻策略(strategy)管理,輸入輸出設備管理。

輸入輸出設備管理

音頻系統爲音頻設備定義了一個枚舉:AudioSystem::audio_devices,例如:DEVICE_OUT_SPEAKER,DEVICE_OUT_WIRED_HEADPHONE,DEVICE_OUT_BLUETOOTH_A2DP,DEVICE_IN_BUILTIN_MIC,DEVICE_IN_VOICE_CALL 等等,每一個枚舉值其實對應一個32bit整數的某一個位,所以這些值是可以進行位或操作的,例如我希望同時打開揚聲器和耳機,那麼可以這樣:

  1. newDevice=DEVICE_OUT_SPEAKER|DEVICE_OUT_WIRED_HEADPHONE;
  2. setOutputDevice(mHardwareOutput,newDevice);

AudioPolicyManager中有兩個成員變量:mAvailableOutputDevices和 mAvailableInputDevices,他們記錄了當前可用的輸入和輸出設備,當系統檢測到耳機或者藍牙已連接好時,會調用 AudioPolicyManager的成員函數:

  1. status_tAudioPolicyManager::setDeviceConnectionState(AudioSystem::audio_devicesdevice,
  2. AudioSystem::device_connection_statestate,
  3. const char *device_address)

該函數根據傳入的device值和 state(DEVICE_STATE_AVAILABLE/DEVICE_STATE_UNAVAILABLE)設置 mAvailableOutputDevices或者mAvailableInputDevices,然後選擇相應的輸入或者輸出設備。

其他一些相關的函數:

  • setForceUse() 設置某種場合強制使用某一設備,例如setForceUse(FOR_MEDIA, FORCE_SPEAKER)會在播放音樂時打開揚聲器
  • startOutput()/stopOutput()
  • startInput()/stopInput()

音量管理

AudioPolicyManager提供了一下幾個與音量相關的函數:

  • initStreamVolume(AudioSystem::stream_type stream, int indexMin, int indexMax)
  • setStreamVolumeIndex(AudioSystem::stream_type stream, int index)
  • getStreamVolumeIndex(AudioSystem::stream_type stream)

由此可見,電話鈴聲可以有7個級別的音量,而音樂則可以有15個音量級別,java的代碼通過jni,最後調用 AudioPolicyManager的initStreamVolume(),把這個數組的內容傳入AudioPolicyManager中,這樣 AudioPolicyManager也就記住了每一個音頻流的音量級別。應用程序可以調用setStreamVolumeIndex設置各個音頻流的音量級別,setStreamVolumeIndex會把這個整數的音量級別轉化爲適合人耳的對數級別,然後通過AudioPolicyService的 AudioCommandThread,最終會將設置應用到AudioFlinger的相應的Track中。

AudioCommandThread

這是AudioPolicyService中的一個線程,主要用於處理音頻設置相關的命令。包括:

  • START_TONE
  • STOP_TONE
  • SET_VOLUME
  • SET_PARAMETERS
  • SET_VOICE_VOLUME

每種命令的參數有相應的包裝:

  • class ToneData
  • class VolumeData
  • class ParametersData
  • class VoiceVolumeData

START_TONE/STOP_TONE:播放電話系統中常用的特殊音調,例如:TONE_DTMF_0,TONE_SUP_BUSY等等。

SET_VOLUME:最終會調用AudioFlinger進行音量設置

SET_VOICE_VOLUME:最終會調用AudioFlinger進行電話音量設置

SET_PARAMETERS:通過一個KeyValuePairs形式的字符串進行參數設置,KeyValuePairs的格式可以這樣:

  • "sampling_rate=44100"
  • "channels=2"
  • "sampling_rate=44100;channels=2" // 組合形式

這些KeyValuePairs可以通過AudioPolicyService的成員函數setParameters()傳入。

經典收藏

轉自:

http://blog.csdn.net/DroidPhone/archive/2010/10/18/5949280.aspx

發佈了12 篇原創文章 · 獲贊 11 · 訪問量 28萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章