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

  1. 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函数)来通知模式的改变。

  1. 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对象不在该文件中声明,但是它由构造函数AudioPolicyManagerBase::AudioPolicyManagerBase(AudioPolicyClientInterface *clientInterface)的参数传递过来。现在找一下AudioPolicyManagerBase在哪里被实例化,经查找在AudioPolicyService::AudioPolicyService()
 : BnAudioPolicyService() , mpPolicyManager(NULL)
 {
 char value[PROPERTY_VALUE_MAX]; 
 // start tone playback thread
 mTonePlaybackThread = new AudioCommandThread(String8(""));
 // start audio commands thread
 mAudioCommandThread = new AudioCommandThread(String8("ApmCommandThread")); 
 #if defined (GENERIC_AUDIO) || defined (AUDIO_POLICY_TEST)
mpPolicyManager = new AudioPolicyManagerBase(this);
 LOGV("build for GENERIC_AUDIO - using generic audio policy");
 #else
 // if running in emulation - use the emulator driver
 if (property_get("ro.kernel.qemu", value, 0)) {
 LOGV("Running in emulation - using generic audio policy");
mpPolicyManager = new AudioPolicyManagerBase(this);
 }
 else {
 LOGV("Using hardware specific audio policy");
mpPolicyManager = createAudioPolicyManager(this);
 }
 #endif 
 // load properties
 property_get("ro.camera.sound.forced", value, "0");
 mpPolicyManager->setSystemProperty("ro.camera.sound.forced", value);
 }中被实例化。
 在AudioPolicyService类继承了public BnAudioPolicyService, public AudioPolicyClientInterface,
 public IBinder::DeathRecipient三个类,在AudioPolicyService中找到函数setStreamVolume和setVoiceVolume
 status_t AudioPolicyService::setStreamVolume(AudioSystem::stream_type stream,
 float volume,
 audio_io_handle_t output,
 int delayMs)
 {
return mAudioCommandThread->volumeCommand((int)stream, volume, (int)output, delayMs);
 } 
 status_t AudioPolicyService::setVoiceVolume(float volume, int delayMs)
 {
return mAudioCommandThread->voiceVolumeCommand(volume, delayMs);
 }
 他们都是调用mAudioCommandThread类中的函数,实现音量的改变。
 status_t AudioPolicyService::AudioCommandThread::voiceVolumeCommand(float volume, int delayMs)
 {
 status_t status = NO_ERROR; 
 AudioCommand *command = new AudioCommand();
 command->mCommand = SET_VOICE_VOLUME;
 VoiceVolumeData *data = new VoiceVolumeData();
 data->mVolume = volume;
 command->mParam = data;
 if (delayMs == 0) {
 command->mWaitStatus = true;
 } else {
 command->mWaitStatus = false;
 }
Mutex::Autolock _l(mLock);
insertCommand_l(command, delayMs);
 LOGV("AudioCommandThread() adding set voice volume volume %f", volume);
 mWaitWorkCV.signal();
 if (command->mWaitStatus) {
 command->mCond.wait(mLock);
 status = command->mStatus;
 mWaitWorkCV.signal();
 }
 return status;
 } 

 status_t AudioPolicyService::AudioCommandThread::volumeCommand(int stream,
 float volume,
 int output,
 int delayMs)
 {
 status_t status = NO_ERROR; 
 AudioCommand *command = new AudioCommand();
 command->mCommand = SET_VOLUME;
 VolumeData *data = new VolumeData();
 data->mStream = stream;
 data->mVolume = volume;
 data->mIO = output;
 command->mParam = data;
 if (delayMs == 0) {
 command->mWaitStatus = true;
 } else {
 command->mWaitStatus = false;
 }
Mutex::Autolock _l(mLock);
insertCommand_l(command, delayMs);
 LOGV("AudioCommandThread() adding set volume stream %d, volume %f, output %d",
 stream, volume, output);
 mWaitWorkCV.signal();
 if (command->mWaitStatus) {
 command->mCond.wait(mLock);
 status = command->mStatus;
 mWaitWorkCV.signal();
 }
 return status;
 }
 以上两个函数中都是自动加锁后,开始调节音量。
Mutex::Autolock _l(mLock);
insertCommand_l(command, delayMs);函数定义如下:
 // insertCommand_l() must be called with mLock held
 void AudioPolicyService::AudioCommandThread::insertCommand_l(AudioCommand *command, int delayMs)
 {
 ssize_t i;
 Vector <AudioCommand *> removedCommands;
 command->mTime = systemTime() + milliseconds(delayMs);
 // acquire wake lock to make sure delayed commands are processed
 if (mName != "" && mAudioCommands.isEmpty()) {
 acquire_wake_lock(PARTIAL_WAKE_LOCK, mName.string());
 }
 // check same pending commands with later time stamps and eliminate them
 for (i = mAudioCommands.size()1; i >= 0; i-) {
 AudioCommand *command2 = mAudioCommands[i];
 // commands are sorted by increasing time stamp: no need to scan the rest of mAudioCommands
 if (command2->mTime <= command->mTime) break;
 if (command2->mCommand != command->mCommand) continue;
 switch (command->mCommand) {
 case SET_PARAMETERS: {
 ParametersData *data = (ParametersData *)command->mParam;
 ParametersData *data2 = (ParametersData *)command2->mParam;
 if (data->mIO != data2->mIO) break;
 LOGV("Comparing parameter command %s to new command %s",
 data2->mKeyValuePairs.string(), data->mKeyValuePairs.string());
 AudioParameter param = AudioParameter(data->mKeyValuePairs);
 AudioParameter param2 = AudioParameter(data2->mKeyValuePairs);
 for (size_t j = 0; j < param.size(); j++) {
 String8 key;
 String8 value;
 param.getAt(j, key, value);
 for (size_t k = 0; k < param2.size(); k++) {
 String8 key2;
 String8 value2;
 param2.getAt(k, key2, value2);
 if (key2 == key) {
 param2.remove(key2);
 LOGV("Filtering out parameter %s", key2.string());
 break;
 }
 }
 }
 // if all keys have been filtered out, remove the command.
 // otherwise, update the key value pairs
 if (param2.size() == 0) {
 removedCommands.add(command2);
 } else {
 data2->mKeyValuePairs = param2.toString();
 }
 } break;
case SET_VOLUME: {
VolumeData *data = (VolumeData *)command->mParam;
VolumeData *data2 = (VolumeData *)command2->mParam;
if (data->mIO != data2->mIO) break;
if (data->mStream != data2->mStream) break;
LOGV("Filtering out volume command on output %d for stream %d",
data->mIO, data->mStream);
removedCommands.add(command2);
} break;
 case SET_FM_VOLUME: {
 removedCommands.add(command2);
 } break;
 case START_TONE:
 case STOP_TONE:
 default:
 break;
 }
 }
 // remove filtered commands
 for (size_t j = 0; j < removedCommands.size(); j++) {
 // removed commands always have time stamps greater than current command
 for (size_t k = i + 1; k < mAudioCommands.size(); k++) {
 if (mAudioCommands[k] == removedCommands[j]) {
 LOGV("suppressing command: %d", mAudioCommands[k]->mCommand);
 mAudioCommands.removeAt(k);
 break;
 }
 }
 }
 removedCommands.clear();
 // insert command at the right place according to its time stamp
 LOGV("inserting command: %d at index %d, num commands %d",
 command->mCommand, (int)i+1, mAudioCommands.size());
 mAudioCommands.insertAt(command, i + 1);
 }
 3. mVolumePanel.postVolumeChanged(streamType, flags); //更新音量改变UI.
 4. sendVolumeUpdate:发送AudioManager.VOLUME_CHANGED_ACTION,处理intent的目的是用于播放那个短促的蜂鸣声(见ToneGenerator.java的startTone)。
 5. ToneGenerator.java的startTone的分析: 通过jni调用到ToneGenerator.cpp的startTone函数。
1. public void adjustVolume(int direction, int flags) 方法体
public void adjustVolume(int direction, int flags) {
 IAudioService service = getService();
 try {
 service.adjustVolume(direction, flags);
 } catch (RemoteException e) {
 Log.e(TAG, "Dead object in adjustVolume", e);
 }
 }
 调用IAudioService service = getService();
 service.adjustVolume(direction, flags);他们在IAudioService.java中定义。在audioservice.java中有该方法的实现。查找方法同上1. public void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags)
方法体
 public void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags) {
 IAudioService service = getService();
 try {
 service.adjustSuggestedStreamVolume(direction, suggestedStreamType, flags);
 } catch (RemoteException e) {
 Log.e(TAG, "Dead object in adjustVolume", e);
 }
 }
 调用IAudioService service = getService();
 service.adjustSuggestedStreamVolume(direction, suggestedStreamType, flags);
 他们在IAudioService.java文件中定义。在audioservice.java中有该方法的实现。
 查找方法同上
 4.public void setStreamVolume(int streamType, int index, int flags) 方法体
 public void setStreamVolume(int streamType, int index, int flags) {
 IAudioService service = getService();
 try {
 service.setStreamVolume(streamType, index, flags);
 } catch (RemoteException e) {
 Log.e(TAG, "Dead object in setStreamVolume", e);
 }
 }


调用IAudioService service = getService();
service.setStreamVolume(streamType, index, flags);
他们在IAudioService.java文件中定义。在audioservice.java中有该方法的实现。
现在转到IAudioService.java文件:IAudioService.java文件是接口文件,在audioservice.java文件中实现音量调节函数的定义。
查找方法同上