为了正常的体验网站,请在浏览器设置里面开启Javascript功能!

ringtone播放分析

2017-09-19 8页 doc 40KB 12阅读

用户头像

is_654168

暂无简介

举报
ringtone播放分析当播放音乐时,不同的的输出流会根据不同stragy,来选择输出设备,然后播放音乐。 下面开始分析,当选择要播放的音乐后,设备是如何设置的。 根据打印信息我们可以看到从文件AudioFlinger.cpp中 函数start开始设置输出设备 status_t AudioFlinger::PlaybackThread::Track::start() {   ……     if (!isOutputTrack() && state != ACTIVE && state != RESUMING) {             thread...
ringtone播放分析
当播放音乐时,不同的的输出流会根据不同stragy,来选择输出设备,然后播放音乐。 下面开始,当选择要播放的音乐后,设备是如何设置的。 根据打印信息我们可以看到从文件AudioFlinger.cpp中 函数start开始设置输出设备 status_t AudioFlinger::PlaybackThread::Track::start() {   ……     if (!isOutputTrack() && state != ACTIVE && state != RESUMING) {             thread->mLock.unlock();             status = AudioSystem::startOutput(thread->id(),                                            (AudioSystem::stream_type)mStreamType,                                               mSessionId);                                             thread->mLock.lock();         }       …… } 然后AudioSystem::startOutput(……)调用的是文件AudioSystem.cpp中的 status_t AudioSystem::startOutput(audio_io_handle_t output,                                   AudioSystem::stream_type stream,                                   int session) {     const sp& aps = AudioSystem::get_audio_policy_service();     if (aps == 0) return PERMISSION_DENIED;     return aps->startOutput(output, stream, session); } 然后根据打印信息可以看到aps->startOutput(output, stream, session);调用的是文件AudioYusuPolicyManager.cpp中的函数 status_t AudioYusuPolicyManager::startOutput(audio_io_handle_t output,                                             AudioSystem::stream_type stream,                                             int session) {     LOGD("startOutput() output %d, stream %d, session %d", output, stream, session); …… outputDesc->changeRefCount(stream, 1);     setOutputDevice(output, getNewDevice(output)); …… } 在函数AudioYusuPolicyManager::startOutput()中我们可以看到outputDesc->changeRefCount(stream, 1);先根据输出流调用changeRefCount()更新数组mRefCount[stream],然后早通过getNewDevice(output)获取新的设备。 uint32_t AudioYusuPolicyManager::getNewDevice(audio_io_handle_t output, bool fromCache) {     uint32_t device = 0;     AudioOutputDescriptor *outputDesc = mOutputs.valueFor(output);       if (isInCall() ||         outputDesc->isUsedByStrategy(STRATEGY_PHONE)) {         device = getDeviceForStrategy(STRATEGY_PHONE, fromCache);     } else if (outputDesc->isUsedByStrategy(STRATEGY_SONIFICATION)) {         device = getDeviceForStrategy(STRATEGY_SONIFICATION, fromCache);     } else if (outputDesc->isUsedByStrategy(STRATEGY_MEDIA)) {         device = getDeviceForStrategy(STRATEGY_MEDIA, fromCache);     } else if (outputDesc->isUsedByStrategy(STRATEGY_DTMF)) {         device = getDeviceForStrategy(STRATEGY_DTMF, fromCache);     }else if (outputDesc->isUsedByStrategy(STRATEGY_PRIPRIOTARY)) {         device = getDeviceForStrategy(STRATEGY_PRIPRIOTARY, fromCache);     }     LOGV("getNewDevice() selected device %x output= %d", device,output);     return device; } 在isUsedByStrategy()中就是根据先前更新的数组mRefCount[stream],来判断是否是对应的输出流对应的策略,isUsedByStrategy具体对应的函数是strategyRefCount() uint32_t AudioYusuPolicyManager::AudioOutputDescriptor::strategyRefCount(routing_strategy strategy) {     uint32_t refCount = 0;     for (int i = 0; i < (int)AudioSystem::NUM_STREAM_TYPES; i++) {         if (getStrategy((AudioSystem::stream_type)i) == strategy) {             refCount += mRefCount[i];         }     }     return refCount; } 根据输出流如果判断是当前对应的策略,则根据策略回去当前的设备device = getDeviceForStrategy(STRATEGY_*, fromCache); uint32_t AudioYusuPolicyManager::getDeviceForStrategy(routing_strategy strategy, bool fromCache) {     uint32_t device = 0;     LOGV("getDeviceForStrategy() from cache strategy %d, device %x mAvailableOutputDevices = %x" , strategy, mDeviceForStrategy[strategy],mAvailableOutputDevices);     if (fromCache) {         LOGV("getDeviceForStrategy() from cache strategy %d, device %x", strategy, mDeviceForStrategy[strategy]);         return mDeviceForStrategy[strategy];     } switch (strategy) { case STRATEGY_DTMF:…… case STRATEGY_PHONE:…… case STRATEGY_PRIPRIOTARY:…… case STRATEGY_SONIFICATION: // If incall, just select the STRATEGY_PHONE device: The rest of the behavior is handled by         // handleIncallSonification().         if (isInCall()) {             device = getDeviceForStrategy(STRATEGY_PHONE, false);             break;         }         device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER;         if (device == 0) {             LOGE("getDeviceForStrategy() speaker device not found");         }         // The second device used for sonification is the same as the device used by media strategy         // FALL THROUGH         case STRATEGY_MEDIA: {       // modified by chipeng         //uint32_t device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_AUX_DIGITAL;       uint32_t device2 = 0;       #ifdef WITH_A2DP               if (mA2dpOutput != 0 && (!isInCall()) ) {                   if (strategy == STRATEGY_SONIFICATION && !a2dpUsedForSonification()) {                       break;                   }                   if (device2 == 0) {                       device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP;                   }                   if (device2 == 0) {                       device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;                   }                   if (device2 == 0) {                       device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;                   }               }       #endif         if (device2 == 0) {             device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE;         }         if (device2 == 0) {             device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET;         }         // move digital         if(device2 ==0){             device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_AUX_DIGITAL;       }         if (device2 == 0) {             device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER;         }         // device is DEVICE_OUT_SPEAKER if we come from case STRATEGY_SONIFICATION, 0 otherwise         device |= device2;         if (device == 0) {             LOGE("getDeviceForStrategy() speaker device not found");         }         } break; …… } } 当获取新的设备之后然后调用setOutputDevice(output, getNewDevice(output));设置输出流的输出设备。具体流程如下 start-> startOutput-> changeRefCount-> getNewDevice->setOutputDevice; 在分析问题时,我们根据打印信息发现当插入耳机后,硬件检测到了耳机的插入并设置成功, 我们在预览情景模式播放ringtone时发信根据输出流AudioSystem:RING的获取对应的策略是STRATEGY_SONIFICATION:(闹钟也是此策略)但是在此策略中,根据上面代码可以看出输出设备的设置是外放和耳机同时播放,这就是问题的根被原因。所以我们根据分析,修改了输出流AudioSystem:RING对应的策略。 具体修改内容如下:首先在AudioYusuPolicyManager.h中添加新的策略STRATEGY_RINGTONE         enum routing_strategy {             STRATEGY_MEDIA,             STRATEGY_PHONE,             STRATEGY_SONIFICATION,             STRATEGY_DTMF,             STRATEGY_PRIPRIOTARY,             STRATEGY_RINGTONE,//add by anxueyan             NUM_STRATEGIES         }; 然后在文件AudioYusuPolicyManager.cpp中的函数getStrategy,修改输出流的策略。 AudioYusuPolicyManager::routing_strategy AudioYusuPolicyManager::getStrategy(         AudioSystem::stream_type stream) {     // stream to strategy mapping     switch (stream) {     case AudioSystem::VOICE_CALL:     case AudioSystem::BLUETOOTH_SCO:         return STRATEGY_PHONE; case AudioSystem::RING:     return STRATEGY_RINGTONE; //add by anxueyan     case AudioSystem::NOTIFICATION:     case AudioSystem::ALARM:     case AudioSystem::ENFORCED_AUDIBLE:         return STRATEGY_SONIFICATION;     case AudioSystem::DTMF:         return STRATEGY_DTMF;       ……     } } 修改函数uint32_t AudioYusuPolicyManager::getNewDevice(audio_io_handle_t output, bool fromCache) {     ……     if (isInCall() ||         outputDesc->isUsedByStrategy(STRATEGY_PHONE)) {         device = getDeviceForStrategy(STRATEGY_PHONE, fromCache); } …… //add by anxueyan else if (outputDesc->isUsedByStrategy(STRATEGY_RINGTONE)) {         device = getDeviceForStrategy(STRATEGY_RINGTONE, fromCache); } //end add     …… }  最后重点修改getDeviceForStrategy()函数,在case STRATEGY_SONIFICATION:之前添加内容如下 case STRATEGY_RINGTONE:   uint32_t device2 = 0;         // handleIncallSonification().         if (isInCall()) {             device = getDeviceForStrategy(STRATEGY_PHONE, false);             break;         }              if (device2 == 0) {           device2 = mAvailableOutputDevices&AudioSystem::DEVICE_OUT_WIRED_HEADPHONE;         }         if (device2 == 0) {             device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET;         }         // move digital         if(device2 ==0){             device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_AUX_DIGITAL;       }         if (device2 == 0) {             device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER;         }         device |= device2;         if (device == 0) {             LOGE("getDeviceForStrategy() speaker device not found");         }         break;   添加内容之后,执行命令./mk lcsh73_gb new android 即可。
/
本文档为【ringtone播放分析】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。 本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。 网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。

历史搜索

    清空历史搜索