这次的分析是从setting设置开始,进入声音设置,然后进入音量设置!
先上传上来,后期进行整理吧
调用流程:
--------------------------------------------------------------------------------------------------------
Setting应用
... ...
RingerVolumePreference(DialogPreference).onClick()
→RingerVolumePreference(DialogPreference).showDialog(Bundle)
→RingerVolumePreference.onBindDialogView(View)
→RingerVolumePreference.updateSlidersAndMutedStates()
→mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
→mAudioManager.getStreamVolume(streamType);
|
-------------------------|------------------------------------------------------------------------------
| AudioManager
getStreamVolume
|→IAudioService service = getService();
|→service.getStreamVolume(streamType);
|
---------------------------|-----------------------------------------------------------------------------
| AudioService.java AudioService(JAVA层)
getStreamVolume
ensureValidStreamType(streamType);
(mStreamStates[streamType].mLastAudibleIndex + 5) / 10;
|
VolumeStreamState
|①从setting provider中读取上次保存的音量值
|→mLastAudibleIndex = Settings.System.getInt(cr,
| mLastAudibleVolumeIndexSettingName,
| (mIndex > 0) ? mIndex : AudioManager.DEFAULT_STREAM_VOLUME[streamType]);
|②初始化native层的音量值
|→AudioSystem.initStreamVolume(streamType, 0, mIndexMax);
|③设置native层的音量值
|→setStreamVolumeIndex(streamType, mIndex);
|
AudioSystem.setStreamVolumeIndex(stream, (index + 5)/10);
initStreamVolume setStreamVolumeIndex
| |
------------------JNI----------------------------------------------------JNI-------------------------------
| | JNI层
android_media_AudioSystem_initStreamVolume android_media_AudioSystem_setStreamVolumeIndex
| |
| check_AudioSystem_Command |
| |
-------------------|---------------------------------------------------------------------------------------
| | AudioPolicyService客户端
| |
AudioSystem::initStreamVolume AudioSystem::setStreamVolumeIndex
| |
| aps = AudioSystem::get_audio_policy_service(); |
| |
aps->initStreamVolume(stream, indexMin, indexMax); aps->setStreamVolumeIndex(stream, index);
| |
remote()->transact(INIT_STREAM_VOLUME, data, &reply); remote()->transact(SET_STREAM_VOLUME, data, &reply);
| |
-------------------|-------------------binder通信-------------------------|---------------------------------
| | AudioPolicyService服务端
| |
AudioPolicyService::initStreamVolume AudioPolicyService::setStreamVolumeIndex
| |
mpAudioPolicy->init_stream_volum mpAudioPolicy->set_stream_volume_index
| |
-------------------|------------------------------------------------------|------------------------------------------
| | Audio policy HAL 硬件抽象层
|
ap_set_stream_volume_index
|
lap->apm->setStreamVolumeIndex((AudioSystem::stream_type)stream,index);
|
AudioPolicyManagerBase::setStreamVolumeIndex
|
checkAndSetVolume(stream, index, mOutputs.keyAt(i), mOutputs.valueAt(i)->device());
|
AudioPolicyManagerBase::checkAndSetVolume
|
mpClientInterface->setStreamVolume((AudioSystem::stream_type)stream, volume, output, delayMs);
|
AudioPolicyCompatClient::setStreamVolume
|
mServiceOps->set_stream_volume(mService, (audio_stream_type_t)stream,volume, output, delayMs);
|
aps_set_stream_volume AudioPolicyService.cpp
|
audioPolicyService->setStreamVolume(stream, volume, output,delay_ms);
|
mAudioCommandThread->volumeCommand((int)stream, volume,(int)output, delayMs);
|
AudioPolicyService::AudioCommandThread::volumeCommand
|
insertCommand_l(command, delayMs);
至此,我们需要去分析执行command的后台线程,会如何执行这些命令的。
----------------------------------------AudioPolicyService::AudioCommandThread::threadLoop-----------------------------------------------------
bool AudioPolicyService::AudioCommandThread::threadLoop()
{
nsecs_t waitTime = INT64_MAX;
mLock.lock();
while (!exitPending())
{
while(!mAudioCommands.isEmpty()) {
... ...
switch (command->mCommand) {
... ...
case SET_VOLUME: {
VolumeData *data = (VolumeData *)command->mParam;
LOGV("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);
if (command->mWaitStatus) { |
command->mCond.signal(); |
mWaitWorkCV.wait(mLock); |
} |
delete data; |
}break; |
... ... |
} |
|
AudioSystem::setStreamVolume
|
|
|→const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
|→af->setStreamVolume(stream, value, output);
|
|
------------------------------------------------------------|--------------------------------------------------------------------
| AudioFlinger
AudioFlinger::setStreamVolume
|
thread->setStreamVolume(stream, value);
|
AudioFlinger::PlaybackThread::setStreamVolume
|
mStreamTypes[stream].volume = value; 至此音量设置完毕
接下来分析下上面遗留的Init相关的流程:
AudioPolicyService::initStreamVolume
|
----------------------现在有必要搞清楚mpAudioPolicy到底是怎么来的----------------------------------------------------
AudioPolicyService是Android音频系统的两大服务之一,另一个服务是AudioFlinger,这两大服务都在系统启动时由MediaSever加载,
加载的代码位于:frameworks/base/media/mediaserver/main_mediaserver.cpp。AudioFlinger主要负责管理音频数据处理以及和硬件
抽象层相关的工作。下面研究下AudioPolicyService。
AudioPolicyService主要完成以下任务:
JAVA应用层通过JNI,经由IAudioPolicyService接口,访问AudioPolicyService提供的服务
输入输出设备的连接状态
系统的音频策略(strategy)的切换
音量/音频参数的设置
AudioPolicyService有一个内部线程类AudioCommandThread,顾名思义,所有的命令(音量控制,输入、输出的切换等)最终都会在该线程中排队执行;
AudioPolicyService的很大一部分管理工作都是在AudioPolicyManager中完成的。包括音量管理,音频策略(strategy)管理,输入输出设备管理。
我们现在比较关心的是音量的控制,所以我们还是到AudioCommandThread线程中了解一下。
AudioCommandThread线程是在AudioPolicyService的构造函数中创建的。
AudioPolicyService::AudioPolicyService()
→mAudioCommandThread = new AudioCommandThread(String8("ApmCommandThread"));
AudioCommandThread线程的主要工作是在bool AudioPolicyService::AudioCommandThread::threadLoop()中完成的。
threadLoop中主要处理音频设置相关的命令:
▲START_TONE/STOP_TONE:播放电话系统中常用的特殊音调,例如:TONE_DTMF_0,TONE_SUP_BUSY等等。
▲SET_VOLUME:最终会调用AudioFlinger进行音量设置
▲SET_PARAMETERS:最终会调用AudioFlinger进行电话音量设置
▲SET_VOICE_VOLUME:通过一个KeyValuePairs形式的字符串进行参数设置
我们比较关心"音量设置"相关,所以只关注SET_VOLUME.
case SET_VOLUME: {
VolumeData *data = (VolumeData *)command->mParam;
command->mStatus = AudioSystem::setStreamVolume(data->mStream,data->mVolume,data->mIO);
---------------------------------------------------------------------------------------------------------------------------------------------
下面研究一下AudioPolicyManager:
AudioPolicyManager是在AudioPolicyService的构造函数中创建的。
AudioPolicyService::AudioPolicyService
|→hw_get_module(AUDIO_POLICY_HARDWARE_MODULE_ID, &module);
|(获得AudioPolicyHardwareModule,根据模块ID找到硬件模块动态链接库的地址,然后调用load去打开动态链接库并从中获取硬件模块结构体地址。)
|struct legacy_ap_module HAL_MODULE_INFO_SYM = {
|module: {
| common: {
| tag: HARDWARE_MODULE_TAG,
| version_major: 1,
| version_minor: 0,
| id: AUDIO_POLICY_HARDWARE_MODULE_ID, //ID
| name: "LEGACY Audio Policy HAL",
| author: "The Android Open Source Project",
| methods: &legacy_ap_module_methods,
| dso : NULL,
| reserved : {0},
| },
|},
|};
|
|→audio_policy_dev_open(module, &mpAudioPolicyDev); //打开 audio policy device
|→mpAudioPolicyDev->create_audio_policy(mpAudioPolicyDev, &aps_ops, this,&mpAudioPolicy);
| |static int legacy_ap_dev_open(const hw_module_t* module, const char* name,
| | hw_device_t** device)
| |{
| | struct legacy_ap_device *dev;
| |
| | if (strcmp(name, AUDIO_POLICY_INTERFACE) != 0)
| | return -EINVAL;
| |
| | dev = (struct legacy_ap_device *)calloc(1, sizeof(*dev));
| | if (!dev)
| | return -ENOMEM;
| |
| | dev->device.common.tag = HARDWARE_DEVICE_TAG;
| | dev->device.common.version = 0;
| | dev->device.common.module = const_cast<hw_module_t*>(module);
| | dev->device.common.close = legacy_ap_dev_close;
| | dev->device.create_audio_policy = create_legacy_ap;//create_audio_policy对应的操作函数。
| | dev->device.destroy_audio_policy = destroy_legacy_ap;
| |
| | *device = &dev->device.common;
| |
| | return 0;
| |}
| |
| |→create_legacy_ap
| |→lap->policy.init_check = ap_init_check;
| |→lap->policy.init_stream_volume = ap_init_stream_volume;
| |→lap->policy.set_stream_volume_index = ap_set_stream_volume_index;
| |→... ...
| |→ap->apm = createAudioPolicyManager(lap->service_client);//创建AudioPolicyManager
| |→new AudioPolicyManagerDefault(clientInterface);
| |→AudioPolicyManagerBase::AudioPolicyManagerBase
| |→mpClientInterface = clientInterface;
|