android volume设置 代码分析

转自:https://blog.csdn.net/shi_xin/article/details/38903749


volume设置,跳过binder部分(binder请独立理解)

没有采用深度优先的方法,容易绕来绕去,就不知道再看什么了。

采用不断透调的方法讲解,一步一步从上层直逼底层,从整体上了解音量设置过程。

透调中有点难度的调用最后讲解。

一、JNI部分

android_media_AudioSystem.cpp-----framework/base/core/jni/

[cpp]  view plain  copy
  1. android_media_AudioSystem_setStreamVolumeIndex(JNIEnv *env,  
  2.                                                jobject thiz,  
  3.                                                jint stream,  
  4.                                                jint index,  
  5.                                                jint device)  
  6. {  
  7.     return check_AudioSystem_Command(  
  8.             AudioSystem::setStreamVolumeIndex(static_cast (stream),  
  9.                                               index,  
  10.                                               (audio_devices_t)device));  
  11. }  
对于函数的行惨,不必过多考虑,是上层java传给的。

关键的参数:

index:音量值;

device:如下列举了一笑部分

[cpp]  view plain  copy
  1. enum{  
  2.     AUDIO_DEVICE_NONE                          = 0x0,  
  3.     /* reserved bits */  
  4.     AUDIO_DEVICE_BIT_IN                        = 0x80000000,  
  5.     AUDIO_DEVICE_BIT_DEFAULT                   = 0x40000000,  
  6.     /* output devices */  
  7.     AUDIO_DEVICE_OUT_EARPIECE                  = 0x1,  
  8.     AUDIO_DEVICE_OUT_SPEAKER                   = 0x2,  
  9.     AUDIO_DEVICE_OUT_WIRED_HEADSET             = 0x4,  
  10.     AUDIO_DEVICE_OUT_WIRED_HEADPHONE           = 0x8,  
  11.     AUDIO_DEVICE_OUT_BLUETOOTH_SCO             = 0x10,  
  12.     AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET     = 0x20,  
  13.     。。。  
  14. }  


stream:

[cpp]  view plain  copy
  1. /* The audio stream for phone calls */  
  2.    public static final int STREAM_VOICE_CALL = 0;  
  3.    /* The audio stream for system sounds */  
  4.    public static final int STREAM_SYSTEM = 1;  
  5.    /* The audio stream for the phone ring and message alerts */  
  6.    public static final int STREAM_RING = 2;  
  7.    /* The audio stream for music playback */  
  8.    public static final int STREAM_MUSIC = 3;  
  9.    /* The audio stream for alarms */  
  10.    public static final int STREAM_ALARM = 4;  
  11.    /* The audio stream for notifications */  
  12.    public static final int STREAM_NOTIFICATION = 5;  
  13.    /* @hide The audio stream for phone calls when connected on bluetooth */  
  14.    public static final int STREAM_BLUETOOTH_SCO = 6;  
  15.    /* @hide The audio stream for enforced system sounds in certain countries (e.g camera in Japan) */  
  16.    public static final int STREAM_SYSTEM_ENFORCED = 7;  
  17.    /* @hide The audio stream for DTMF tones */  
  18.    public static final int STREAM_DTMF = 8;  

看到函数内部,调用的仕audiosystem的setStreamVolumeIndex函数,进到audiosystem

二、audiosystem

AudioSystem.cpp-----framework/av/media/libmedia/

[cpp]  view plain  copy
  1. status_t AudioSystem::setStreamVolumeIndex(audio_stream_type_t stream,  
  2.                                            int index,  
  3.                                            audio_devices_t device)  
  4. {  
  5.     const sp& aps = AudioSystem::get_audio_policy_service();  
  6.     if (aps == 0) return PERMISSION_DENIED;  
  7.     return aps->setStreamVolumeIndex(stream, index, device);  
  8. }  

这里采用了binder机制,直接无视它!知道是一种调用方式就可以。

看到函数调用了audiopolicyservice里的函数setStreamVolumeIndex;

三、audiopolicyservice

AudioPolicyService.cpp-----framework/av/media/services/audioflinger

[cpp]  view plain  copy
  1. status_t AudioPolicyService::setStreamVolumeIndex(audio_stream_type_t stream,  
  2.                                                   int index,  
  3.                                                   audio_devices_t device)  
  4. {  
  5.     if (mpAudioPolicy == NULL) {  
  6.         return NO_INIT;  
  7.     }  
  8.     if (!settingsAllowed()) {  
  9.         return PERMISSION_DENIED;  
  10.     }  
  11.     if (uint32_t(stream) >= AUDIO_STREAM_CNT) {  
  12.         return BAD_VALUE;  
  13.     }  
  14.     Mutex::Autolock _l(mLock);  
  15.     if (mpAudioPolicy->set_stream_volume_index_for_device) {  
  16.         return mpAudioPolicy->set_stream_volume_index_for_device(mpAudioPolicy,  
  17.                                                                 stream,  
  18.                                                                 index,  
  19.                                                                 device);  
  20.     } else {  
  21.         return mpAudioPolicy->set_stream_volume_index(mpAudioPolicy, stream, index);  
  22.     }  
  23. }  

函数内部,调用了
[cpp]  view plain  copy
  1. mpAudioPolicy->set_stream_volume_index_for_device  
这里mpAudioPolicy后面讲解, 疑点1 ,这里它调用的是 audio_policy_hal.cpp 中的方法;

四、

audio_policy_hal.cpp----system/core/libcutils/

[cpp]  view plain  copy
  1. static int ap_set_stream_volume_index(struct audio_policy *pol,  
  2.                                       audio_stream_type_t stream,  
  3.                                       int index)  
  4. {  
  5.     struct legacy_audio_policy *lap = to_lap(pol);  
  6.     return lap->apm->setStreamVolumeIndex((AudioSystem::stream_type)stream,  
  7.                                           index,  
  8.                                           AUDIO_DEVICE_OUT_DEFAULT);  
  9. }  

五、audiopolicymanager

audiopolicymanagerbase.c----hardware/libhardware_legacy/audio

看到四中的apm就猜到调用的仕audiopolicymanagerbase中的函数,(疑点2),进入audiopolicymanagerbase.c中的函数

[cpp]  view plain  copy
  1. status_t AudioPolicyManagerBase::setStreamVolumeIndex(AudioSystem::stream_type stream,  
  2.                                                       int index,  
  3.                                                       audio_devices_t device)  
  4. {  
  5.   
  6.     if ((index < mStreams[stream].mIndexMin) || (index > mStreams[stream].mIndexMax)) {  
  7.         return BAD_VALUE;  
  8.     }  
  9.     if (!audio_is_output_device(device)) {  
  10.         return BAD_VALUE;  
  11.     }  
  12.   
  13.     // Force max volume if stream cannot be muted  
  14.     if (!mStreams[stream].mCanBeMuted) index = mStreams[stream].mIndexMax;  
  15.   
  16.     ALOGV("setStreamVolumeIndex() stream %d, device %04x, index %d",  
  17.           stream, device, index);  
  18.   
  19.     // if device is AUDIO_DEVICE_OUT_DEFAULT set default value and  
  20.     // clear all device specific values  
  21.     if (device == AUDIO_DEVICE_OUT_DEFAULT) {  
  22.         mStreams[stream].mIndexCur.clear();  
  23.     }  
  24.     mStreams[stream].mIndexCur.add(device, index);  
  25.   
  26.     // compute and apply stream volume on all outputs according to connected device  
  27.     status_t status = NO_ERROR;  
  28.     for (size_t i = 0; i < mOutputs.size(); i++) {  
  29.         audio_devices_t curDevice =  
  30.                 getDeviceForVolume(mOutputs.valueAt(i)->device());  
  31.         if ((device == AUDIO_DEVICE_OUT_DEFAULT) || (device == curDevice)||  
  32.                status_t volStatus = checkAndSetVolume(stream, index, mOutputs.keyAt(i), curDevice);  
  33.             if (volStatus != NO_ERROR) {  
  34.                 status = volStatus;  
  35.             }  
  36.         }  
  37.     }  
  38.     return status;  
  39. }  
调用到函数checkAndSetVolume函数:

[cpp]  view plain  copy
  1. status_t AudioPolicyManagerBase::checkAndSetVolume(int stream,  
  2.                                                    int index,  
  3.                                                    audio_io_handle_t output,  
  4.                                                    audio_devices_t device,  
  5.                                                    int delayMs,  
  6.                                                    bool force)  
  7. {  
  8.        。。。。  
  9.         if (voiceVolume != mLastVoiceVolume && output == mPrimaryOutput) {  
  10.             mpClientInterface->setVoiceVolume(voiceVolume, delayMs);  
  11.             mLastVoiceVolume = voiceVolume;  
  12.         }  
  13.     }  
  14.   
  15.     return NO_ERROR;  
  16. }  
里面的mpClientInterface->setVoiceVolume,mpClientnterface实际上是audiopolicyservice,

即调用的是audioPolicyService->setStreamVolume

六、audiopolicyservice

audiopolicyservice.cpp---frameworks/av/services/audioflinger

[cpp]  view plain  copy
  1. int AudioPolicyService::setStreamVolume(audio_stream_type_t stream,  
  2.                                         float volume,  
  3.                                         audio_io_handle_t output,  
  4.                                         int delayMs)  
  5. {  
  6.     return (int)mAudioCommandThread->volumeCommand(stream, volume,  
  7.                                                    output, delayMs);  
  8. }  

volumeCommand函数也在这个文件内

[cpp]  view plain  copy
  1. status_t AudioPolicyService::AudioCommandThread::volumeCommand(audio_stream_type_t stream,  
  2.                                                                float volume,  
  3.                                                                audio_io_handle_t output,  
  4.                                                                int delayMs)  
  5. {  
  6.     status_t status = NO_ERROR;  
  7.   
  8.     AudioCommand *command = new AudioCommand();  
  9.     command->mCommand = SET_VOLUME;  
  10.     VolumeData *data = new VolumeData();  
  11.     data->mStream = stream;  
  12.     data->mVolume = volume;  
  13.     data->mIO = output;  
  14.     command->mParam = data;  
  15.     Mutex::Autolock _l(mLock);  
  16.   
  17.     insertCommand_l(command, delayMs);  
  18.      
  19.     mWaitWorkCV.signal();  
  20.     if (command->mWaitStatus) {  
  21.         command->mCond.wait(mLock);  
  22.         status =  command->mStatus;  
  23.         command->mCond.signal();  
  24.          
  25.         delete command;  
  26.     }  
  27.     return status;  
  28. }  

[cpp]  view plain  copy
  1. insertCommand_l(command, delayMs);  
加入线程队列中,即threadLoop 中;

[cpp]  view plain  copy
  1. bool AudioPolicyService::AudioCommandThread::threadLoop()  
  2. {  
  3.     nsecs_t waitTime = INT64_MAX;  
  4.   
  5.     mLock.lock();  
  6.     while (!exitPending())  
  7.     {  
  8.         while (!mAudioCommands.isEmpty()) {  
  9.             nsecs_t curTime = systemTime();  
  10.             if (mAudioCommands[0]->mTime <= curTime) {  
  11.                 AudioCommand *command = mAudioCommands[0];  
  12.                 mAudioCommands.removeAt(0);  
  13.                 mLastCommand = *command;  
  14.                 // SPRD: Delete command after waiting was end  
  15.                 bool deleteAudioCommand = true;  
  16.   
  17.                 switch (command->mCommand) {  
  18.                 。。。。  
  19.   
  20.                 case SET_VOLUME: {  
  21.                     VolumeData *data = (VolumeData *)command->mParam;  
  22.                     ALOGV("AudioCommandThread() processing set volume stream %d, \  
  23.                             volume %f, output %d", data->mStream, data->mVolume, data->mIO);  
  24.                     command->mStatus = AudioSystem::setStreamVolume(data->mStream,  
  25.                                                                     data->mVolume,  
  26.                                                                     data->mIO);  
  27.                     if (command->mWaitStatus) {  
  28.                         // SPRD: Delete command after waiting was end  
  29.                         deleteAudioCommand = false;  
  30.                         command->mCond.signal();  
  31.                         command->mCond.waitRelative(mLock, kAudioCommandTimeout);  
  32.                     }  
  33.                     delete data;  
  34.                     }break;  
  35.                。。。。。  
  36.     mLock.unlock();  
  37.     return false;  
  38. }  

调到啊udiosystem的函数

七、audiosystem

audiosystem.c---frameworks/av/media/libmedia

[cpp]  view plain  copy
  1. status_t AudioSystem::setStreamVolume(audio_stream_type_t stream, float value,  
  2.         audio_io_handle_t output)  
  3. {  
  4.     if (uint32_t(stream) >= AUDIO_STREAM_CNT) return BAD_VALUE;  
  5.     const sp& af = AudioSystem::get_audio_flinger();  
  6.     if (af == 0) return PERMISSION_DENIED;  
  7.     af->setStreamVolume(stream, value, output);  
  8.     return NO_ERROR;  
  9. }  
通过binder通信,调用audioflinger里的setStreamVolume

八、audioflinger




----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

调用过程详细分析:

疑点1、mpAudioPolicy调用的是audio_policy_hal.cpp中的方法分析:

函数内部,使用mpAudioPolicy的方法,这就需要看下audiopolicyservice的构造函数;

[cpp]  view plain  copy
  1. AudioPolicyService::AudioPolicyService()  
  2.     : BnAudioPolicyService() , mpAudioPolicyDev(NULL) , mpAudioPolicy(NULL)  
  3. {  
  4.     char value[PROPERTY_VALUE_MAX];  
  5.     const struct hw_module_t *module;  
  6.     int forced_val;  
  7.     int rc;  
  8.   
  9.     Mutex::Autolock _l(mLock);  
  10.   
  11.     // start tone playback thread  
  12.     mTonePlaybackThread = new AudioCommandThread(String8("ApmTone"), this);  
  13.     // start audio commands thread  
  14.     mAudioCommandThread = new AudioCommandThread(String8("ApmAudio"), this);  
  15.     // start output activity command thread  
  16.     mOutputCommandThread = new AudioCommandThread(String8("ApmOutput"), this);  
  17.     /* instantiate the audio policy manager */  
  18.     rc = hw_get_module(AUDIO_POLICY_HARDWARE_MODULE_ID, &module);//1.1分析  
  19.     if (rc)  
  20.         return;  
  21.   
  22.     rc = audio_policy_dev_open(module, &mpAudioPolicyDev);//1.2分析  
  23.     ALOGE_IF(rc, "couldn't open audio policy device (%s)", strerror(-rc));  
  24.     if (rc)  
  25.         return;  
  26.   
  27.     rc = mpAudioPolicyDev->create_audio_policy(mpAudioPolicyDev, &aps_ops, this,  
  28.                                                &mpAudioPolicy);//1.3分析  
  29.     ALOGE_IF(rc, "couldn't create audio policy (%s)", strerror(-rc));  
  30.     if (rc)  
  31.         return;  
  32.   
  33.     rc = mpAudioPolicy->init_check(mpAudioPolicy);  
  34.     ALOGE_IF(rc, "couldn't init_check the audio policy (%s)", strerror(-rc));  
  35.     if (rc)  
  36.         return;  
  37.   
  38.     /* SPRD: maybe set this property better, but here just change the default value @{ */  
  39.     property_get("ro.camera.sound.forced", value, "1");  
  40.     forced_val = strtol(value, NULL, 0);  
  41.     ALOGV("setForceUse() !forced_val=%d ",!forced_val);  
  42.     mpAudioPolicy->set_can_mute_enforced_audible(mpAudioPolicy, !forced_val);  
  43.     /* @} */  
  44.   
  45.     ALOGI("Loaded audio policy from %s (%s)", module->name, module->id);  
  46.   
  47.     // load audio pre processing modules  
  48.     if (access(AUDIO_EFFECT_VENDOR_CONFIG_FILE, R_OK) == 0) {  
  49.         loadPreProcessorConfig(AUDIO_EFFECT_VENDOR_CONFIG_FILE);  
  50.     } else if (access(AUDIO_EFFECT_DEFAULT_CONFIG_FILE, R_OK) == 0) {  
  51.         loadPreProcessorConfig(AUDIO_EFFECT_DEFAULT_CONFIG_FILE);  
  52.     }  
  53. }  

1.1分析hw_get_module(AUDIO_POLICY_HARDWARE_MODULE_ID, &module);

其中,#define AUDIO_POLICY_HARDWARE_MODULE_ID "audio_policy"

[cpp]  view plain  copy
  1. int hw_get_module(const char *id, const struct hw_module_t **module)

    上面函数调用Hardware.c--------audio/hardware/libhardware/

      

  2.   
int hw_get_module(const char *id, const struct hw_module_t **module){ return hw_get_module_by_class(id, NULL, module);}又调用hw_get_module_by_class,还在这个文件内;

[cpp]  view plain  copy
  1. "code" class="cpp">int hw_get_module_by_class(const char *class_id, const char *inst,  
  2.                            const struct hw_module_t **module)//class_id保存"audio_policy",inst为NULL  
  3. {  
  4.     int status;  
  5.     int i;  
  6.     const struct hw_module_t *hmi = NULL;  
  7.     char prop[PATH_MAX];  
  8.     char path[PATH_MAX];  
  9.     char name[PATH_MAX];  
  10.   
  11.     if (inst)//inst=NULL,走else  
  12.         snprintf(name, PATH_MAX, "%s.%s", class_id, inst);  
  13.     else  
  14.         strlcpy(name, class_id, PATH_MAX);//将"audio_policy"拷贝到name中;  
  15.   
  16.     /* 
  17.      * Here we rely on the fact that calling dlopen multiple times on 
  18.      * the same .so will simply increment a refcount (and not load 
  19.      * a new copy of the library). 
  20.      * We also assume that dlopen() is thread-safe. 
  21.      */  
  22.   
  23.     /* Loop through the configuration variants looking for a module */  
  24.     for (i=0 ; i
  25.         if (i < HAL_VARIANT_KEYS_COUNT) {  
  26.             if (property_get(variant_keys[i], prop, NULL) == 0) {  
  27.                 continue;  
  28.             }  
  29.             snprintf(path, sizeof(path), "%s/%s.%s.so",  
  30.                      HAL_LIBRARY_PATH2, name, prop);  
  31.             if (access(path, R_OK) == 0) break;  
  32.   
  33.             snprintf(path, sizeof(path), "%s/%s.%s.so",  
  34.                      HAL_LIBRARY_PATH1, name, prop);  
  35.             if (access(path, R_OK) == 0) break;  
  36.         } else {  
  37.             snprintf(path, sizeof(path), "%s/%s.default.so",  
  38.                      HAL_LIBRARY_PATH2, name);  
  39.             if (access(path, R_OK) == 0) break;  
  40.   
  41.             snprintf(path, sizeof(path), "%s/%s.default.so",  
  42.                      HAL_LIBRARY_PATH1, name);//#define HAL_LIBRARY_PATH1 "/system/lib/hw"  
  43.                                               //将"/system/lib/hw/audio_policy.default.so"拷贝到path中  
  44.             if (access(path, R_OK) == 0) break;//判断是否是可读文件,至此,已经确定加载audio_policy.default.so文件,下面的load将完成加载  
  45.         }  
  46.     }  
  47.   
  48.     status = -ENOENT;  
  49.     if (i < HAL_VARIANT_KEYS_COUNT+1) {  
  50.         /* load the module, if this fails, we're doomed, and we should not try 
  51.          * to load a different variant. */  
  52.         status = load(class_id, path, module);//定义的load函数,下面分析  
  53.     }  
  54.   
  55.     return status;  
  56. }  
这个函数,需要高清几个函数的使用:property_get,snprintf,access;dlopen,dlsym。这几个函数会在另外一篇文章中讲解。
[cpp]  view plain  copy
  1. /** 
  2.  * Load the file defined by the variant and if successful 
  3.  * return the dlopen handle and the hmi. 
  4.  * @return 0 = success, !0 = failure. 
  5.  */  
  6. static int load(const char *id,  
  7.         const char *path,  
  8.         const struct hw_module_t **pHmi)  
  9. {  
  10.     int status;  
  11.     void *handle;  
  12.     struct hw_module_t *hmi;  
  13.   
  14.     /* 
  15.      * load the symbols resolving undefined symbols before 
  16.      * dlopen returns. Since RTLD_GLOBAL is not or'd in with 
  17.      * RTLD_NOW the external symbols will not be global 
  18.      */  
  19.     handle = dlopen(path, RTLD_NOW);//打开指定的 文件,即audio_policy.default.so  
  20.     if (handle == NULL) {  
  21.         char const *err_str = dlerror();  
  22.         ALOGE("load: module=%s\n%s", path, err_str?err_str:"unknown");  
  23.         status = -EINVAL;  
  24.         goto done;  
  25.     }  
  26.   
  27.     /* Get the address of the struct hal_module_info. */  
  28.     const char *sym = HAL_MODULE_INFO_SYM_AS_STR;//#define HAL_MODULE_INFO_SYM_AS_STR  "HMI"  
  29.     hmi = (struct hw_module_t *)dlsym(handle, sym);//根据动态链接库操作句柄与符号,返回符号对应的地址保存给hmi  
  30.     if (hmi == NULL) {  
  31.         ALOGE("load: couldn't find symbol %s", sym);  
  32.         status = -EINVAL;  
  33.         goto done;  
  34.     }  
  35.   
  36.     /* Check that the id matches */  
  37.     if (strcmp(id, hmi->id) != 0) {  
  38.         ALOGE("load: id=%s != hmi->id=%s", id, hmi->id);  
  39.         status = -EINVAL;  
  40.         goto done;  
  41.     }  
  42.   
  43.     hmi->dso = handle;  
  44.   
  45.     /* success */  
  46.     status = 0;  
  47.   
  48.     done:  
  49.     if (status != 0) {  
  50.         hmi = NULL;  
  51.         if (handle != NULL) {  
  52.             dlclose(handle);  
  53.             handle = NULL;  
  54.         }  
  55.     } else {  
  56.         ALOGV("loaded HAL id=%s path=%s hmi=%p handle=%p",  
  57.                 id, path, *pHmi, handle);  
  58.     }  
  59.   
  60.     *pHmi = hmi;//将地址赋值给形参。至此,整个动态库so的加载完成,并将地址返回  
  61.   
  62.     return status;  
  63. }  
未完。。。。。。。。。。。。我还会回来的。。。。。。。。。。。。。。。。。

你可能感兴趣的:(Android,Audio)