Android 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整數的某一個位,因此這些值是能夠進行位或操做的,例如我但願同時打開揚聲器和耳機,那麼能夠這樣:
java代碼:
- newDevice = DEVICE_OUT_SPEAKER | DEVICE_OUT_WIRED_HEADPHONE;
- setOutputDevice(mHardwareOutput, newDevice);
複製代碼
AudioPolicyManager中有兩個成員變量:mAvailableOutputDevices和 mAvailableInputDevices,他們記錄了當前可用的輸入和輸出設備,當系統檢測到耳機或者藍牙已鏈接好時,會調用 AudioPolicyManager的成員函數:
java代碼:
- status_t AudioPolicyManager::setDeviceConnectionState(AudioSystem::audio_devices device,
- AudioSystem::device_connection_state state,
- const char *device_address)
複製代碼
該函數根據傳入的device值和 state(DEVICE_STATE_AVAILABLE/DEVICE_STATE_UNAVAILABLE)設置 mAvailableOutputDevices或者mAvailableInputDevices,而後選擇相應的輸入或者輸出設備。
其餘一些相關的函數:
java代碼:
- setForceUse()
- //設置某種場合強制使用某一設備,例如setForceUse(FOR_MEDIA, FORCE_SPEAKER)會在播放音樂時打開揚聲器
- startOutput()/stopOutput()
- startInput()/stopInput()
複製代碼
音量管理
AudioPolicyManager提供了一下幾個與音量相關的函數:
java代碼:
- 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中。
歡迎關注本站公眾號,獲取更多信息