1. 程式人生 > >android 音量控制 流程梳理

android 音量控制 流程梳理

Android.media.AudioManager中包含了對android.media.AudioService的跨程序AIDL呼叫封裝。
正常處理過程:
1.調整音量是通過AudioManager間接呼叫AudioService.adjustStreamVolume方法來完成邏輯處理;
2.AudioService呼叫VolumePanel畫出音量調整介面,併發送音量變動廣播訊息,
3.StatusBarPolicy,接收廣播訊息判斷是否在狀態列顯示靜音或振動圖示。

問題點:
1.AudioManager如何接收音量調整事件?

答:PhoneWindowManager.interceptKeyBeforeQueueing處理的
WindowManagerService迴圈讀取下面的訊息再做分發到視窗接收,在訊息分發前會有一個類做訊息過濾處理,就是PhoneWindowManager.interceptKeyBeforeQueueing;
比如音量調整、Home鍵都在這個類裡面做特殊處理,詳細內容後面會在其它該當再補充


2.誰負責處理音量顯示的?
答:AudioManager呼叫AudioService來顯示的。事件觸發在AudioManager,程式碼的執行實現在AudioService中。狀態列是SystemUI的APK包StatusBarPolicy中接收廣播訊息來處理的。

原始碼位置:
/frameworks/base/media/java/android/media/AudioManager.java
/frameworks/base/media/java/android/media/AudioService.java
/framework/base/core/java/Android/view/VolumePanel.java
/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPolicy.java

AudioService.adjustStreamVolume方法完成以下三個功能:
一.音量調整
音量調整分為兩步:先檢視模式(Ring mode)是否需要調整? 然後再呼叫調整音量。 
調整模式通過呼叫checkForRingerModeChange(oldIndex, direction);實現,
調整音量通過呼叫streamState.adjustIndex(direction)實現。

二.向用戶顯示調整音量的介面
呼叫mVolumePanel.postVolumeChanged(streamType, flags);傳送音量變動訊息,向用戶顯示改變結果。
呼叫過程VolumePanel.postVolumeChanged->VolumePanel.onVolumeChanged->VolumePanel.onShowVolumeChanged->mToast

三.廣播音量有變動的系統事件
AudioService.sendVolumeUpdate(streamType);廣播音量有改變的系統事件,狀態列根據這廣播事件顯示靜音或振動圖示

狀態列的靜音或振動圖示顯示過程
StatusBarPolicy主要負責在靜音模式(silent mode)和振動模式(vibrate mode)下在狀態列(status bar)的右方顯示一個代表相應意義的圖示。
一.系統啟動後,StatusBarPolicy會註冊一個Receiver,它可以接收很多種廣播,其中就有AudioService在完成每一次的模式和音量更新時發出的兩個廣播事件

private BroadcastReceiver mIntentReceiver = new BroadcastReceiver()//新一個廣播接收類‘
        filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);//新增接收的廣播訊息

        filter.addAction(AudioManager.VIBRATE_SETTING_CHANGED_ACTION);
mContext.registerReceiver(mIntentReceiver, filter, null, mHandler);//註冊一個Receiver,接收廣播訊息

二.接收廣播,並呼叫updateVolume調整狀態列顯示
else if (action.equals(AudioManager.RINGER_MODE_CHANGED_ACTION) ||
                    action.equals(AudioManager.VIBRATE_SETTING_CHANGED_ACTION)) {
                updateVolume();//呼叫音量狀態列顯示