当前位置:编程学习 > 网站相关 >>

Audio System调节音量分析

1.调节音量:
先从上层往下一步步的走吧,和大家分享一下刨根问底的乐趣。
在应用中先实例化一个AudioManager:
AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
am对象就可以调用关于音量调节的方法:这些方法的定义都在audiomanager.java中。
在audiomanager.java文件中的方法调用audioservice.java的方法:

public void adjustStreamVolume(int streamType, int direction, int flags) 方法体
public void adjustStreamVolume(int streamType, int direction, int flags) {
IAudioService service = getService();
try {
service.adjustStreamVolume(streamType, direction, flags);
} catch (RemoteException e) {
Log.e(TAG, "Dead object in adjustStreamVolume", e);
}
}
调用IAudioService service = getService();获得audio服务,下面是服务接口:
service.adjustStreamVolume(streamType, direction, flags);他们在IAudioService.java中定义。
在audioservice.java中有该方法的实现。
public void adjustStreamVolume(int streamType, int direction, int flags) {
ensureValidDirection(direction);
ensureValidStreamType(streamType);
VolumeStreamState streamState = mStreamStates[STREAM_VOLUME_ALIAS[streamType]];
final int oldIndex = (streamState.muteCount() != 0) ? streamState.mLastAudibleIndex : streamState.mIndex;
boolean adjustVolume = true;
// If either the client forces allowing ringer modes for this adjustment,
// or the stream type is one that is affected by ringer modes
if ((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0

streamType == AudioSystem.STREAM_RING) {
// Check if the ringer mode changes with this volume adjustment. If
// it does, it will handle adjusting the volume, so we won't below
adjustVolume = checkForRingerModeChange(oldIndex, direction);
}
// If stream is muted, adjust last audible index only
int index;
if (streamState.muteCount() != 0) {
index = streamState.mLastAudibleIndex;
} else {
if (adjustVolume && streamState.adjustIndex(direction)) {
// Post message to set system volume (it in turn will post a message
// to persist). Do not change volume if stream is muted sendMsg(mAudioHandler, MSG_SET_SYSTEM_VOLUME, STREAM_VOLUME_ALIAS[streamType], SENDMSG_NOOP, 0, 0,streamState, 0);
}
index = streamState.mIndex;
}
// UI
mVolumePanel.postVolumeChanged(streamType, flags);
// Broadcast Intent
sendVolumeUpdate(streamType, oldIndex, index);
}
在这个函数中:

checkForRingerModeChange(oldIndex, direction);
 

oldIndex是以前的音量,direction表示增加还是降低音量。这个函数用于检测改变铃声模式,如振动,静音等,是通过调用setRingerMode函数来实现的。而setRingerMode通过发送广播(调用broadcastRingerMode函数)来通知模式的改变。

sendMsg(): 发送消息,处理这个消息的是handleMessage()函数,调用setStreamVolumeIndex来调节音量,
private void setStreamVolumeIndex(int stream, int index) {
AudioSystem.setStreamVolumeIndex(stream, (index + 5)/10);
}
现在又跑到audiosystem.java中。调用audiosystem.java中的setStreamVolumeIndex
public static native int setStreamVolumeIndex(int stream, int index);通过JNI调用再看看audiosystem.cpp。在audiosystem.cpp中的setStreamVolumeIndex如下:
status_t AudioSystem::setStreamVolumeIndex(stream_type stream, int index)
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return PERMISSION_DENIED;
return aps->setStreamVolumeIndex(stream, index);
}
其实,最终是通过AudioPolicyService的对应函数实现的。再看看AudioPolicyService.cpp文件中的setStreamVolumeIndex。
status_t AudioPolicyService::setStreamVolumeIndex(AudioSystem::stream_type stream, int index)
{
if (mpPolicyManager == NULL) {
return NO_INIT;
}
if (!checkPermission()) {
return PERMISSION_DENIED;
}
if (stream < 0 || stream >= AudioSystem::NUM_STREAM_TYPES) {
return BAD_VALUE;
}
return mpPolicyManager->setStreamVolumeIndex(stream, index);
}
mpPolicyManager->setStreamVolumeIndex(stream, index);
是在AudioPolicyInterface.h中声明,在AudioPolicyManagerBase.cpp中从新定义的成员函数。
#include <hardware_legacy/AudioPolicyInterface.h>有此为证!
status_t AudioPolicyManagerBase::setStreamVolumeIndex(AudioSystem::stream_type stream, int index)
if ((index < mStreams[stream].mIndexMin) || (index > mStreams[stream].mIndexMax)) {
return BAD_VALUE;
}
// Force max volume if stream cannot be muted
if (!mStreams[stream].mCanBeMuted) index = mStreams[stream].mIndexMax;
LOGD("setStreamVolumeIndex() stream %d, index %d", stream, index);
mStreams[stream].mIndexCur = index;
// compute and apply stream volume on all outputs according to connected device
status_t status = NO_ERROR;
for (size_t i = 0; i < mOutputs.size(); i++) {
status_t volStatus = checkAndSetVolume(stream, index, mOutputs.keyAt, mOutputs.valueAt->device());
if (volStatus != NO_ERROR) {
status = volStatus;
}
}
return status;
}
在AudioPolicyManagerBase.cpp中找到checkAndSetVolume。
status_t AudioPolicyManagerBase::checkAndSetVolume(int stream, int index, audio_io_handle_t output, uint32_t device, int delayMs, bool force)
{
// do not change actual stream volume if the stream is muted
if (mOutputs.valueFor(output)->mMuteCount[stream] != 0) {
LOGV("checkAndSetVolume() stream %d muted count %d", stream, mOutputs.valueFor(output)->mMuteCount[stream]);
return NO_ERROR;
}
// do not change in call volume if bluetooth is connected and vice versa
if((stream==AudioSystem::VOICE_CALL&&mForceUse[AudioSystem::FOR_COMMUNICATION] == AudioSystem::FORCE_BT_SCO) ||(stream == AudioSystem::BLUETOOTH_SCO && mForceUse[AudioSystem::FOR_COMMUNICATION] != AudioSystem::FORCE_BT_SCO)) {
LOGV("checkAndSetVolume() cannot set stream %d volume with force use = %d for comm",
stream, mForceUse[AudioSystem::FOR_COMMUNICATION]);
return INVALID_OPERATION;
}
float volume = computeVolume(stream, index, output, device);
// We actually change the volume if:
// - the float value returned by computeVolume() changed
// - the force flag is set
if (volume != mOutputs.valueFor(output)->mCurVolume[stream] ||
(stream == AudioSystem::VOICE_CALL) || force) {
mOutputs.valueFor(output)->mCurVolume[stream] = volume;
LOGV("setStreamVolume() for output %d stream %d, volume %f, delay %d", output, stream, volume, delayMs);
if (stream == AudioSystem::VOICE_CALL ||
stream == AudioSystem::DTMF ||
stream == AudioSystem::BLUETOOTH_SCO) {
// offset value to reflect actual hardware volume that never reaches 0
// 1% corresponds roughly to first step in VOICE_CALL stream volume setting (see AudioService.java)
volume = 0.01 + 0.99 * volume;
}
mpClientInterface->setStreamVolume((AudioSystem::stream_type)stream, volume, output, delayMs);
}
if (stream == AudioSystem::VOICE_CALL ||
stream == AudioSystem::BLUETOOTH_SCO) {
float voiceVolume;
// Force voice volume to max for bluetooth SCO as volume is managed by the headset
if (stream == AudioSystem::VOICE_CALL) {
voiceVolume = (float)index/(float)mStreams[stream].mIndexMax;
} else {
voiceVolume = 1.0;
}
if (voiceVolume != mLastVoiceVolume && output == mHardwareOutput) {
mpClientInterface->setVoiceVolume(voiceVolume, delayMs);
mLastVoiceVolume = voiceVolume;
}
}
return NO_ERROR;
}
mpClientInterface对象不在该文件中声明,但是它由构造函数AudioPolicyM

补充:综合编程 , 其他综合 ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,