status_t AudioPolicyManager::setStreamVolumeIndex(audio_stream_type_t stream,int index,audio_devices_t device){.../* 记录当前流类型对应的设备和index值 */mStreams[stream].mIndexCur.add(device, index);/* 获取设备策略 */audio_devices_t strategyDevice = getDeviceForStrategy(getStrategy(stream), true /*fromCache*/); .../* 检查并准备往AF中设置了 */status_t volStatus = checkAndSetVolume(stream, index, mOutputs.keyAt(i), curDevice);}
java层分析的时候说过,index值也会传入到层,这里便是记录的地方,我们重点关注函数,很多厂商自己的适配也是在这里做的:
status_t AudioPolicyManager::checkAndSetVolume(audio_stream_type_t stream,int index,audio_io_handle_t output,audio_devices_t device,int delayMs,bool force){...float driverVol[6]= {0.00,0.02,0.03,0.04,0.05,0.06};/* 计算音量值 */float volume = computeVolume(stream, index, output, device);/* 如果index值为前六个,则重新赋值 */if( index < 6){volume = driverVol[index];}.../* 这里最终会调入到AF中 */mpClientInterface->setStreamVolume(stream, volume, output, delayMs);}
我所使用的平台是海思厂商,因为计算出来的音量值是绝对音量,所以如果index值太小的话,音量的变化并不会很明显,因此,这里对前六的index值进行了重新赋值,为每个厂商自己的计算方法,不尽相同,海思的如下:
float amplification = exp( decibels * 0.115129f); // exp( dB * ln(10) / 20 )
实际上整个函数目的很简单,由index换算成真正的音量值,然后启动AF去设置,代码最后看起来跟AF没有关系,但实际上却是会调入到AF中,这里需要追一下代码:对应的类型是,在l.cpp中能找到到对应的实现:
status_t AudioPolicyService::AudioPolicyClient::setStreamVolume(audio_stream_type_t stream,float volume, audio_io_handle_t output,int delay_ms){return mAudioPolicyService->setStreamVolume(stream, volume, output,delay_ms);}
这里又会调入到中,回想一下前面,是通过index到下面的,现在由index确定了真正的音量值之后,又返回了回来,我们看下下一步又会怎么调用:
setStreamVolume@AudioPolicyService.cppint AudioPolicyService::setStreamVolume(audio_stream_type_t stream,float volume,audio_io_handle_t output,int delayMs){return (int)mAudioCommandThread->volumeCommand(stream, volume,output, delayMs);}
这段代码初看有点懵,是什么鬼?这是一个audio的命令接收线程,那么,这个线程在什么时候创建的呢?其实就是在第一次引用的强指针时候创建的,我们看下::():
void AudioPolicyService::onFirstRef(){...// start tone playback threadmTonePlaybackThread = new AudioCommandThread(String8("ApmTone"), this);// start audio commands threadmAudioCommandThread = new AudioCommandThread(String8("ApmAudio"), this);// start output activity command threadmOutputCommandThread = new AudioCommandThread(String8("ApmOutput"), this); ...}
【Android 5.1Android音频系统之音量控制详解】可以看到这里一共创建了三个命令线程,的构造函数并没有做什么实质性的事,联想前几篇博客的分析,我们看一下的函数:
void AudioPolicyService::AudioCommandThread::onFirstRef(){run(mName.string(), ANDROID_PRIORITY_AUDIO);}
果然,当第一次引用的强指针时,线程就会开始转起来,不停地接受指令了,那么,哪个地方是第一次引用强指针的呢?搜了下代码,发现只有一个地方使用了的强指针,就是声明了此成员:
- android 自定义音量调节,Android之自定义音量控制控件
- 1 Android音视频开发,android驱动开发权威指南pdf
- android x86 跑分
- 2021大厂Android面试经历,含小米、腾讯、阿里
- 吊打面试官-Android中高级面试题,分享PDF高清版
- Android-APK瘦身实践:二次瘦身如何再减少大小?
- 小白看完都学会了!五年Android开发者小米、阿里面经,大厂面经合集
- Android 12 还没用上,Android 13 已经来了
- android与ios返回按钮,Android与ios的系统交互模式差异
- Android 自定义Behavior