android5.0 按鍵調節音量詳解
按鍵事件派發已經分析過,調節音量流程直接從phonewindow onkeydown 開始分析。
protected boolean onKeyDown(int featureId, int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_VOLUME_UP:
case KeyEvent.KEYCODE_VOLUME_DOWN: {
int direction = keyCode == KeyEvent.KEYCODE_VOLUME_UP ? AudioManager.ADJUST_RAISE
: AudioManager.ADJUST_LOWER;
if (mMediaController != null) {
mMediaController.adjustVolume(direction, AudioManager.FLAG_SHOW_UI);
} else {
MediaSessionLegacyHelper.getHelper(getContext()).sendAdjustVolumeBy(
mVolumeControlStreamType, direction,
AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_VIBRATE);
}
return true;
}
}
keycode用來判斷音量增減,AudioManager.ADJUST_RAISE 表示增大,ADJUST_LOWER表示降低
通過getHelper靜態函式例項化MediaSessionLegacyHelper, 呼叫其成員函式sendAdjustVolumeBy,將direction引數傳入,以供使用。
具體實現見MediaSessionLegacyHelper.java
public void sendAdjustVolumeBy(int suggestedStream, int delta, int flags) {
mSessionManager.dispatchAdjustVolume(suggestedStream, delta, flags);
}
mSessionManager 是在建構函式中獲取的系統服務manager,通過binder 機制呼叫到MediaSessionService的成員函式
dispatchAdjustVolume,
MediaSessionService.java
public void dispatchAdjustVolume(int suggestedStream, int delta, int flags) {
final int pid = Binder.getCallingPid();
final int uid = Binder.getCallingUid();
final long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
MediaSessionRecord session = mPriorityStack
.getDefaultVolumeSession(mCurrentUserId);
dispatchAdjustVolumeLocked(suggestedStream, delta, flags, session);
}
} finally {
Binder.restoreCallingIdentity(token);
}
}
private void dispatchAdjustVolumeLocked(int suggestedStream, int direction, int flags,
MediaSessionRecord session) {
mAudioService.adjustSuggestedStreamVolume(direction, suggestedStream,
flags, packageName);
}
呼叫到AudioService, 這是framework層audio控制核心,通過sendmsg函式以hanlder方式呼叫到
AudioService.java
private void setDeviceVolume(VolumeStreamState streamState, int device) {
mStreamStates[streamType].applyDeviceVolume_syncVSS(streamDevice);
}
public void applyDeviceVolume_syncVSS(int device) {
AudioSystem.setStreamVolumeIndex(mStreamType, index, device);
}
通過audioSystem呼叫本地方法setStreamVolumeIndex, 進入jni層
android_mediao_AudioSystem.cpp
static jint
android_media_AudioSystem_setStreamVolumeIndex(JNIEnv *env,
jobject thiz,
jint stream,
jint index,
jint device)
{
return (jint) check_AudioSystem_Command(
AudioSystem::setStreamVolumeIndex(static_cast <audio_stream_type_t>(stream),
index,
(audio_devices_t)device));
}
AudioSystem.cpp
status_t AudioSystem::setStreamVolumeIndex(audio_stream_type_t stream,
int index,
audio_devices_t device)
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return PERMISSION_DENIED;
return aps->setStreamVolumeIndex(stream, index, device);
}
int index,
audio_devices_t device)
{
Mutex::Autolock _l(mLock);
return mAudioPolicyManager->setStreamVolumeIndex(stream,
index,
device);
}
AudioPolicyManager.cpp
status_t AudioPolicyManager::checkAndSetVolume(audio_stream_type_t stream,
int index,
audio_io_handle_t output,
audio_devices_t device,
int delayMs,
bool force)
{
mpClientInterface->setVoiceVolume(voiceVolume, delayMs);
}
AudioPolicyClientImpl.cpp
status_t AudioPolicyService::AudioPolicyClient::setVoiceVolume(float volume, int delay_ms)
{
return mAudioPolicyService->setVoiceVolume(volume, delay_ms);
}
AudioPolicyService.cpp
int AudioPolicyService::SetVoiceVolume(float volume, int delayms){
return (int)mAudioCommandThread->voiceVolumeCommand(volume, delayms);
}
case SET_VOICE_VOLUME: {
VoiceVolumeData *data = (VoiceVolumeData *)command->mParam.get();
ALOGV("AudioCommandThread() processing set voice volume volume %f",
data->mVolume);
command->mStatus = AudioSystem::setVoiceVolume(data->mVolume);
}break;
轉了一圈又回到audiosystem::setVoiceVolume()
status_t AudioSystem::setVoiceVolume(float value)
{
const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
if (af == 0) return PERMISSION_DENIED;
return af->setVoiceVolume(value);
}
進入到audioflinger.cpp
詳情見audiofinger的分析