如下是調節音量的流程:java
Step_1.首先在調節機臺Volume_Up_Key & Volume_Down_Key操做時,系統會調用到AudioManager.java中handleKeyUp & handleKeyDown函數,以 handleKeyDown函數爲例:android
1 public void handleKeyDown(KeyEvent event, int stream) { 2 int keyCode = event.getKeyCode(); 3 switch (keyCode) { 4 case KeyEvent.KEYCODE_VOLUME_UP: /*KeyEvent 在KeyEvent.java中定義*/ 5 case KeyEvent.KEYCODE_VOLUME_DOWN: 6 7 int flags = FLAG_SHOW_UI | FLAG_VIBRATE; 8 9 if (mUseMasterVolume) { 10 adjustMasterVolume( 11 keyCode == KeyEvent.KEYCODE_VOLUME_UP 12 ? ADJUST_RAISE 13 : ADJUST_LOWER, 14 flags); 15 } else { 16 adjustSuggestedStreamVolume( 17 keyCode == KeyEvent.KEYCODE_VOLUME_UP 18 ? ADJUST_RAISE 19 : ADJUST_LOWER, 20 stream, 21 flags); 22 } 23 break; 24 ... ... 25 } 26 }
其中是否進入adjustMasterVolume 函數是經過mUseMasterVolume的值判斷的,而mUseMasterVolume的值是在AudioManager的構造函數中定義,其值的大小以下:mUseMasterVolume = mContext.getResources().getBoolean(com.android.internal.R.bool.config_useMasterVolume),因此首先從系統的配置文件config.xml中查找config_useMasterVolume值的大小app
<bool name="config_useMasterVolume">false</bool>函數
因此handleKeyDown中 switch語句中會選擇進入adjustSuggestedStreamVolume函數。post
1 public void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags) { 2 IAudioService service = getService(); 3 try { 4 if (mUseMasterVolume) { 5 service.adjustMasterVolume(direction, flags, mContext.getOpPackageName()); 6 } else { 7 service.adjustSuggestedStreamVolume(direction, suggestedStreamType, flags, 8 mContext.getOpPackageName()); 9 } 10 ... ...
11 } 12 }
Step_2.在adjustSuggestedStreamVolume函數中首先會經過binder機制獲得AudioService,並將音量控制過程轉入到AudioService.java中。this
1 public void adjustStreamVolume(int streamType, int direction, int flags, 2 String callingPackage) { 3 ... ... 4 /*音量調大時,若要超過SafeMediaVolume時,系統會彈出對話框給予確認*/ 5 if ((direction == AudioManager.ADJUST_RAISE) && 6 !checkSafeMediaVolume(streamTypeAlias, aliasIndex + step, device)) { 7 Log.e(TAG, "adjustStreamVolume() safe volume index = "+oldIndex); 8 mVolumePanel.postDisplaySafeVolumeWarning(flags); 9 } else if (streamState.adjustIndex(direction * step, device)) { 10 sendMsg(mAudioHandler, 11 MSG_SET_DEVICE_VOLUME, /*須要處理的Message值*/ 12 SENDMSG_QUEUE, 13 device, 14 0, 15 streamState, 16 0); 17 } 18 } 19 int index = mStreamStates[streamType].getIndex(device); 20 sendVolumeUpdate(streamType, oldIndex, index, flags); /*通知上層更新Volume*/ 21 }
在adjustStreamVolume 中會經過sendMsg的方式來將調節音量的事件加入到消息列隊SENDMSG_QUENE中,當輪尋到該Message時,系統會調用handleMessage函數來處理該Message,此時該處對應的Message爲MSG_SET_DEVICE_VOLUME。spa
1 public void handleMessage(Message msg) { 2 3 switch (msg.what) { 4 5 case MSG_SET_DEVICE_VOLUME: 6 setDeviceVolume((VolumeStreamState) msg.obj, msg.arg1); 7 break; 8 9 case MSG_SET_ALL_VOLUMES: 10 setAllVolumes((VolumeStreamState) msg.obj); 11 break; 12 13 ... ... 14 } 15 }
能夠發現當msg.what = MSG_SET_DEVICE_VOLUME時,會進到setDeviceVolume函數中,繼續往下分析:xml
1 private void setDeviceVolume(VolumeStreamState streamState, int device) { 2 3 // Apply volume 4 streamState.applyDeviceVolume(device); 5 6 // Apply change to all streams using this one as alias 7 ... ... 8 9 // Post a persist volume msg 10 ... ... 11 }
applyDeviceVolume就是將音量Volume設置到對應的設備Device上,繼續往下分析:事件
1 public void applyDeviceVolume(int device) { 2 int index; 3 if (isMuted()) { 4 index = 0; 5 } else if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 && 6 mAvrcpAbsVolSupported) { 7 index = (mIndexMax + 5)/10; 8 } else { 9 index = (getIndex(device) + 5)/10; 10 } 11 AudioSystem.setStreamVolumeIndex(mStreamType, index, device); 12 }
此處VolumeIndex就是對應UI界面調節音量時,音量所處在的位置下標。在AudioService.java中定義了每種音頻流對應的Max-Index,在AudioManager.java中定義了每種音頻流在第一次刷機後默認的Index。ip
Step_3.此時獲得音量的下標Index後,會調用AudioSystem.java中的setStreamVolumeIndex函數中來獲得此時音量的放大倍數。經過JNI層調用到AudioSystem.cpp文件中的 setStreamVolumeIndex中。
1 status_t AudioSystem::setStreamVolumeIndex(audio_stream_type_t stream, 2 int index, 3 audio_devices_t device) 4 { 5 const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service(); 6 if (aps == 0) return PERMISSION_DENIED; 7 return aps->setStreamVolumeIndex(stream, index, device); 8 }
setStreamVolumeIndex函數中比較簡單,經過StrongPointer來與AudioPolicyService創建聯繫,將AudioSystem中的setStreamVolumeIndex操做移到aps中完成。下面進入到AudioPolicyService.cpp文件中的setStreamVolumeIndex繼續分析:
1 status_t AudioPolicyService::setStreamVolumeIndex(audio_stream_type_t stream, 2 int index, 3 audio_devices_t device) 4 { 5 ... ... 6 if (mpAudioPolicy->set_stream_volume_index_for_device) { 7 return mpAudioPolicy->set_stream_volume_index_for_device(mpAudioPolicy, 8 stream, 9 index, 10 device); 11 } else { 12 return mpAudioPolicy->set_stream_volume_index(mpAudioPolicy, stream, index); 13 } 14 }
Step_4.AudioPolicyService.cpp做爲bn端,其對應的bp端爲AudioPolicyManagerBase.cpp。在當前函數的if語句中判斷AudioPolicyManagerBase.cpp文件中是否存在setStreamVolumeIndexForDevice函數,條件成立則會選擇setStreamVolumeIndexForDevice做爲函數入口端;不然選擇setStreamVolumeIndex做爲函數入口。如今進入AudioPolicyManagerBase.cpp中文件中完成最後的分析:
1 status_t AudioPolicyManagerBase::setStreamVolumeIndex(AudioSystem::stream_type stream, 2 int index, 3 audio_devices_t device) 4 { 5 ... ... 6 // compute and apply stream volume on all outputs according to connected device 7 status_t status = NO_ERROR; 8 for (size_t i = 0; i < mOutputs.size(); i++) { 9 audio_devices_t curDevice = 10 getDeviceForVolume(mOutputs.valueAt(i)->device()); 11 if ((device == AUDIO_DEVICE_OUT_DEFAULT) || (device == curDevice)) { 12 status_t volStatus = checkAndSetVolume(stream, index, mOutputs.keyAt(i), curDevice); 13 if (volStatus != NO_ERROR) { 14 status = volStatus; 15 } 16 } 17 } 18 return status; 19 }
繼續調用checkAndSetVolume函數:
1 status_t AudioPolicyManagerBase::checkAndSetVolume(int stream, 2 int index, 3 audio_io_handle_t output, 4 audio_devices_t device, 5 int delayMs, 6 bool force) 7 { 8 9 // do not change actual stream volume if the stream is muted 10 ... ... 11 // do not change in call volume if bluetooth is connected and vice versa 12 ... ... 13 audio_devices_t checkedDevice = (device == AUDIO_DEVICE_NONE) ? mOutputs.valueFor(output)->device() : device; 14 float volume = computeVolume(stream, index, checkedDevice); 15 16 ... ... 17 mpClientInterface->setStreamVolume((AudioSystem::stream_type)stream, volume, output, delayMs);/*將獲得的volume應用到對應的output中*/ 18 }
在checkAndSetVolume中能夠知道volume是經過computeVolume獲得的。繼續向下分析:
float AudioPolicyManagerBase::computeVolume(int stream, int index, audio_devices_t device) { ... ... volume = volIndexToAmpl(device, streamDesc, index); ... ... return volume; }
終於到了最後volIndexToAmpl,從函數名就能夠知道該函數的做用是經過volIndex獲得音量放大倍數。
float AudioPolicyManagerBase::volIndexToAmpl(audio_devices_t device, const StreamDescriptor& streamDesc, int indexInUi) { device_category deviceCategory = getDeviceCategory(device); const VolumeCurvePoint *curve = streamDesc.mVolumeCurve[deviceCategory]; // the volume index in the UI is relative to the min and max volume indices for this stream type int nbSteps = 1 + curve[VOLMAX].mIndex - curve[VOLMIN].mIndex; int volIdx = (nbSteps * (indexInUi - streamDesc.mIndexMin)) / (streamDesc.mIndexMax - streamDesc.mIndexMin); // find what part of the curve this index volume belongs to, or if it's out of bounds int segment = 0; if (volIdx < curve[VOLMIN].mIndex) { // out of bounds return 0.0f; } else if (volIdx < curve[VOLKNEE1].mIndex) { segment = 0; } else if (volIdx < curve[VOLKNEE2].mIndex) { segment = 1; } else if (volIdx <= curve[VOLMAX].mIndex) { segment = 2; } else { // out of bounds return 1.0f; } // linear interpolation in the attenuation table in dB float decibels = curve[segment].mDBAttenuation + ((float)(volIdx - curve[segment].mIndex)) * ( (curve[segment+1].mDBAttenuation - curve[segment].mDBAttenuation) / ((float)(curve[segment+1].mIndex - curve[segment].mIndex)) ); float amplification = exp( decibels * 0.115129f); // exp( dB * ln(10) / 20 ) return amplification; }
其中curve表明在用設備(如SPEAKER、HEADSET & EARPIECE)播放音頻流(如SYSTEM、MUSIC、ALARM、RING & TTS等)時的音量曲線,最後decibles & amplification就是咱們須要求的值,其中decibles表明某一音節所對應的dB值,而amplification則是由dB值轉化獲得的音量放大倍數。這樣整個音量調節過程到此就算完成了,具體的計算分析會放在後面繼續分析。