Android音量设置from top to bottom

  • A+
所属分类:音频杂谈

这次的分析是从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& 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(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;

|

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: