Android 5.1 Android音频系统之音量控制详解( 三 )


class AudioPolicyClient : public AudioPolicyClientInterface{...sp mAudioCommandThread;// audio commands threadsp mTonePlaybackThread;// tone playback threadsp mOutputCommandThread; ...}
基本我们就可以确认了,在第一次实例化对象的时候,就会为成员变量分配指针空间,这里就相当于第一次引用了的强指针,接收命令的线程也就转起来了 。
花了比较大的工夫分析了线程的创建过程,我们去看下它的:
status_t AudioPolicyService::AudioCommandThread::volumeCommand(audio_stream_type_t stream,float volume,audio_io_handle_t output,int delayMs){sp command = new AudioCommand();command->mCommand = SET_VOLUME;sp data = http://www.kingceram.com/post/new VolumeData();data->mStream = stream;data->mVolume = volume;data->mIO = output;command->mParam = data;command->mWaitStatus = true;ALOGV("AudioCommandThread() adding set volume stream %d, volume %f, output %d",stream, volume, output);return sendCommand(command, delayMs); }
封装数据,返回,到这里似乎就跟不下去了,但不要忘了是一个线程,并且已经run起来了,那么我们需要去看下它的干了什么:
bool AudioPolicyService::AudioCommandThread::threadLoop(){...while (!exitPending()){...switch (command->mCommand) {...case SET_VOLUME: {VolumeData *data = http://www.kingceram.com/post/(VolumeData *)command->mParam.get();ALOGV("AudioCommandThread() processing set volume stream %d, \volume %f, output %d", data->mStream, data->mVolume, data->mIO);command->mStatus = AudioSystem::setStreamVolume(data->mStream,data->mVolume,data->mIO);...}}...}
一切如我们所想的,这里面的case语句指引了我们,饶了一大圈,还是到了,但是,看到就应该兴奋起来了,因为马上要到了,看吧:
status_t AudioSystem::setStreamVolume(audio_stream_type_t stream, float value,audio_io_handle_t output){if (uint32_t(stream) >= AUDIO_STREAM_CNT) return BAD_VALUE;const sp& af = AudioSystem::get_audio_flinger();if (af == 0) return PERMISSION_DENIED;af->setStreamVolume(stream, value, output);return NO_ERROR;}
剥丝抽茧,果然还是会由来完成,看下又会做什么:
status_t AudioFlinger::setStreamVolume(audio_stream_type_t stream, float value,audio_io_handle_t output){.../* 1.根据output找到thread */PlaybackThread *thread = NULL;if (output != AUDIO_IO_HANDLE_NONE) {thread = checkPlaybackThread_l(output);if (thread == NULL) {return BAD_VALUE;}}/* 2.记录当前的流类型的音量值 */mStreamTypes[stream].volume = value;.../* 3.进入到thread中去设置音量 */thread->setStreamVolume(stream, value);/* 4.厂商定制化:设置硬件音量 */#if defined (PRODUCT_STB)for (size_t i = 0; i < mAudioHwDevs.size(); i++) {AudioHwDevice *dev = mAudioHwDevs.valueAt(i);mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;ALOGE("setStreamVolume by set_master_volume");if(stream == 3)//music type,only this type can adjust hardware volumdev->hwDevice()->set_master_volume(dev->hwDevice(),value);mHardwareStatus = AUDIO_HW_IDLE;}ALOGV("setStreamVolume value over");#endif }
中的真是信息量巨大,首先,它会通过找到对应的,因为之前分析和的博客时,已经知道,会创建两个线程,一个是,一个是,而的子类有,等,所以,这里首先需要根据确认到底是哪一个,之后,记录当前的流类型的音量值,这个值,后面会使用到,注释三为什么会到中去设置呢?我们这里需要清楚,掌管的是track,其实就是到track里面去设置音量,也就是说,这里设置音量实际上改变的是数据,简单地说,对数据进行幅值强弱处理达到音量调节的目的,这也正是我开篇所说的软音量调节,因为是对数据进行处理,并没有真正地设置到硬件中去,但注释四就是设置到硬件中了,可以看到,这里是芯片厂商自己加的,通过hal层直接设置到芯片的sdk,然后设置到寄存器中,海思的硬件音量设置是在中做的,各个厂商的实现策略可能不一样,但大家一定要区别设置软音量和硬件音量的区别 。