Android audio音频流数据异常问题怎么解决
导读:本文共19307字符,通常情况下阅读需要64分钟。同时您也可以点击右侧朗读,来听本文内容。按键盘←(左) →(右) 方向键可以翻页。
摘要:这篇文章主要介绍“Androidaudio音频流数据异常问题怎么解决”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Androidaudio音频流数据异常问题怎么解决”文章能帮助大家解决问题。一、背景在 Android 系统的开发过程当中,音频异常问题通常有如下几类,无声,调节不了声音,爆音,声音卡顿,声音效果异常(忽大忽小,低音缺失等)等。尤其声音效果这部... ...
目录
(为您整理了一些要点),点击可以直达。这篇文章主要介绍“Androidaudio音频流数据异常问题怎么解决”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Androidaudio音频流数据异常问题怎么解决”文章能帮助大家解决问题。
一、背景
在 Android
系统的开发过程当中,音频异常问题通常有如下几类,无声,调节不了声音,爆音,声音卡顿,声音效果异常(忽大忽小,低音缺失等)等。
尤其声音效果这部分问题通常从日志上信息量较少,相对难定位根因。想要分析此类问题,便需要对声音传输链路有一定的了解,能够在链路中对各节点的音频流进行采集,通过对比分析音频流的实际效果来缩小问题范围,找出原因。
网上已经有很多音频框架图和相关的大致介绍,这里就不再赘述,只分享下音频流的传输链路,和我们可以重点其中的哪些关键节点,来帮助我们快速定位问题。
二、Android Audio 音频系统
1. 音频链路
抓取音频链路当中的音频数据是分析声音异常问题的有效方法,通过抓取不同节点的声音数据,可以帮助我们快速定位问题发生的原因。下面先来看一张安卓官方的音频系统框架图:
Audio
音频数据流整体上经过 APP
,framework
,hal
,kernel driver
四个部分,从应用端发起,不管调用 audio
还是 media
接口,最终还是会由 AudioTrack
将数据往下传,经由 AudioFlinger
启动 MixThread
或 DirectThread
等,将多个 APP
的声音混合到一起,将声音传输到 hal
层。
系统会根据音频流类型 stream
和音频策略 strategy
来选择对应的 output
,从而找到对应的 module
,将音频数据传输给 hal
层音频库 so
做声音相关的处理并传给 audio driver
。
音频流传输路径图:
从上述的音频流流程可以看到,我们首先要确认,当前音频流是经由哪一个 hal
层库做处理,是 primary
,usb
还是三方 so
等,然后可以在对应的节点抓取相应的音频信息分析。
可以根据自己的需要在音频流的部分节点埋下相应的 dump
指令,将 pcm 写入到相应的节点当中。
2. 音频链路关键节点:
  AudioTrack
:应用写入音频流的起点,有 MODE_STATIC
和 MODE_STREAM
模式,通过 write
接口将数据写入。
此节点写入的数据是由应用层最原始的音频数据。   
AudioFlinger
:负责启动线程完成各个应用的混音,音频流声音调节等工作。设备同时可能存在多个应用播放声音,这时便需要将各个应用的声音混合在一起,并且做音量的调节。
例如在车载场景中,音乐应用播放歌曲和地图应用语音导航的声音需要同时存在,便使用到了混音的功能,当导航语音响起时,歌曲声音有一个明显的变小,便可以设置音频流的音量。   
audio_hw_hal
:hal
层音频处理的入口,为 Android
原生逻辑,各厂家需要按照规范实现其中的音频设置等接口,声明 HAL_MODULE_INFO_SYM
结构体,实现 legacy_adev_open
方法,承接起连接 framework
和 audio driver
的作用,完成一些音效算法等逻辑处理。
AudioStreamOut
:和 audio_hw_hal
一样,是Android
给厂家提供的通用类,厂家在实现自己的通用库实现时需要可以按照谷歌规范,然后在相应的音频处理接口中实现自己的对音频流做音效,增益等处理。
audio_hw_hal.cpp
代码如下,不同厂家这里的实现略有差异,这里只截取部分 AOSP
源码。
3. 音频库的选择
从音频流传输路径图可以看到,如何找到是哪一个音频 so
处理声音也是至关重要的。我们知道,系统对于应用层曝光的其实只有通道类型。
举个例子:当用户打电话时,可以使用通话通道 STREAM_VOICE_CALL
,当用户播放视频时,可以使用媒体通道 STREAM_MUSIC
,当发送通知时,可以使用 STREAM_NOTIFICATION
。
那传入这些通道的声音数据,又是怎么最终流向到具体的硬件输出设备呢?
以媒体通道为例,当应用层将音频数据往 MUSIC
通道写入时,系统便会根据 StreamType
来生成相应的
audio_attributes_t(.usage = AUDIO_USAGE_MEDIA, .content_type = AUDIO_CONTENT_TYPE_MUSIC})
再通过 audio_attributes_t
来获取对应的 ProductStrategy
(STRATEGY_MEDIA
),最后在拿到对应的 outputDevice
。
Android
原生逻辑outputDevice
的选择在 Engine.cpp
上,会具体根据当前设备是否有接蓝牙,耳机等外设,按照优先级来选择相应的外设设备作为输出,可能是耳机 (AUDIO_DEVICE_OUT_WIRED_HEADSET
),听筒(AUDIO_DEVICE_OUT_EARPIECE
),喇叭(AUDIO_DEVICE_OUT_SPEAKER
)等。
具体可以看 getDeviceForStrategyInt
方法。
/**Copyright(C)2015TheAndroidOpenSourceProject**LicensedundertheApacheLicense,Version2.0(the"License");*youmaynotusethisfileexceptincompliancewiththeLicense.*YoumayobtainacopyoftheLicenseat**http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,software*distributedundertheLicenseisdistributedonan"ASIS"BASIS,*WITHOUTWARRANTIESORCONDITIONSOFANYKIND,eitherexpressorimplied.*SeetheLicenseforthespecificlanguagegoverningpermissionsand*limitationsundertheLicense.*/#defineLOG_TAG"APM::AudioPolicyEngine"//#defineLOG_NDEBUG0//#defineVERY_VERBOSE_LOGGING#ifdefVERY_VERBOSE_LOGGING#defineALOGVVALOGV#else#defineALOGVV(a...)do{}while(0)#endif#include"Engine.h"#include<AudioPolicyManagerObserver.h>#include<AudioPort.h>#include<IOProfile.h>#include<policy.h>#include<utils/String8.h>#include<utils/Log.h>namespaceandroid{namespaceaudio_policy{Engine::Engine():mManagerInterface(this),mPhoneState(AUDIO_MODE_NORMAL),mApmObserver(NULL){for(inti=0;i<AUDIO_POLICY_FORCE_USE_CNT;i++){mForceUse[i]=AUDIO_POLICY_FORCE_NONE;}}Engine::~Engine(){}voidEngine::setObserver(AudioPolicyManagerObserver*observer){ALOG_ASSERT(observer!=NULL,"InvalidAudioPolicyManagerobserver");mApmObserver=observer;}status_tEngine::initCheck(){return(mApmObserver!=NULL)?NO_ERROR:NO_INIT;}status_tEngine::setPhoneState(audio_mode_tstate){ALOGV("setPhoneState()state%d",state);if(state<0||state>=AUDIO_MODE_CNT){ALOGW("setPhoneState()invalidstate%d",state);returnBAD_VALUE;}if(state==mPhoneState){ALOGW("setPhoneState()settingsamestate%d",state);returnBAD_VALUE;}//storepreviousphonestateformanagementofsonificationstrategybelowintoldState=mPhoneState;mPhoneState=state;if(!is_state_in_call(oldState)&&is_state_in_call(state)){ALOGV("EnteringcallinsetPhoneState()");mApmObserver->getVolumeCurves().switchVolumeCurve(AUDIO_STREAM_VOICE_CALL,AUDIO_STREAM_DTMF);}elseif(is_state_in_call(oldState)&&!is_state_in_call(state)){ALOGV("ExitingcallinsetPhoneState()");mApmObserver->getVolumeCurves().restoreOriginVolumeCurve(AUDIO_STREAM_DTMF);}returnNO_ERROR;}status_tEngine::setForceUse(audio_policy_force_use_tusage,audio_policy_forced_cfg_tconfig){switch(usage){caseAUDIO_POLICY_FORCE_FOR_COMMUNICATION:if(config!=AUDIO_POLICY_FORCE_SPEAKER&&config!=AUDIO_POLICY_FORCE_BT_SCO&&config!=AUDIO_POLICY_FORCE_NONE){ALOGW("setForceUse()invalidconfig%dforFOR_COMMUNICATION",config);returnBAD_VALUE;}mForceUse[usage]=config;break;caseAUDIO_POLICY_FORCE_FOR_MEDIA:if(config!=AUDIO_POLICY_FORCE_HEADPHONES&&config!=AUDIO_POLICY_FORCE_BT_A2DP&&config!=AUDIO_POLICY_FORCE_WIRED_ACCESSORY&&config!=AUDIO_POLICY_FORCE_ANALOG_DOCK&&config!=AUDIO_POLICY_FORCE_DIGITAL_DOCK&&config!=AUDIO_POLICY_FORCE_NONE&&config!=AUDIO_POLICY_FORCE_NO_BT_A2DP&&config!=AUDIO_POLICY_FORCE_SPEAKER){ALOGW("setForceUse()invalidconfig%dforFOR_MEDIA",config);returnBAD_VALUE;}mForceUse[usage]=config;break;caseAUDIO_POLICY_FORCE_FOR_RECORD:if(config!=AUDIO_POLICY_FORCE_BT_SCO&&config!=AUDIO_POLICY_FORCE_WIRED_ACCESSORY&&config!=AUDIO_POLICY_FORCE_NONE){ALOGW("setForceUse()invalidconfig%dforFOR_RECORD",config);returnBAD_VALUE;}mForceUse[usage]=config;break;caseAUDIO_POLICY_FORCE_FOR_DOCK:if(config!=AUDIO_POLICY_FORCE_NONE&&config!=AUDIO_POLICY_FORCE_BT_CAR_DOCK&&config!=AUDIO_POLICY_FORCE_BT_DESK_DOCK&&config!=AUDIO_POLICY_FORCE_WIRED_ACCESSORY&&config!=AUDIO_POLICY_FORCE_ANALOG_DOCK&&config!=AUDIO_POLICY_FORCE_DIGITAL_DOCK){ALOGW("setForceUse()invalidconfig%dforFOR_DOCK",config);}mForceUse[usage]=config;break;caseAUDIO_POLICY_FORCE_FOR_SYSTEM:if(config!=AUDIO_POLICY_FORCE_NONE&&config!=AUDIO_POLICY_FORCE_SYSTEM_ENFORCED){ALOGW("setForceUse()invalidconfig%dforFOR_SYSTEM",config);}mForceUse[usage]=config;break;caseAUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO:if(config!=AUDIO_POLICY_FORCE_NONE&&config!=AUDIO_POLICY_FORCE_HDMI_SYSTEM_AUDIO_ENFORCED){ALOGW("setForceUse()invalidconfig%dforHDMI_SYSTEM_AUDIO",config);}mForceUse[usage]=config;break;caseAUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND:if(config!=AUDIO_POLICY_FORCE_NONE&&config!=AUDIO_POLICY_FORCE_ENCODED_SURROUND_NEVER&&config!=AUDIO_POLICY_FORCE_ENCODED_SURROUND_ALWAYS&&config!=AUDIO_POLICY_FORCE_ENCODED_SURROUND_MANUAL){ALOGW("setForceUse()invalidconfig%dforENCODED_SURROUND",config);returnBAD_VALUE;}mForceUse[usage]=config;break;caseAUDIO_POLICY_FORCE_FOR_VIBRATE_RINGING:if(config!=AUDIO_POLICY_FORCE_BT_SCO&&config!=AUDIO_POLICY_FORCE_NONE){ALOGW("setForceUse()invalidconfig%dforFOR_VIBRATE_RINGING",config);returnBAD_VALUE;}mForceUse[usage]=config;break;default:ALOGW("setForceUse()invalidusage%d",usage);break;//TODOreturnBAD_VALUE?}returnNO_ERROR;}routing_strategyEngine::getStrategyForStream(audio_stream_type_tstream){//streamtostrategymappingswitch(stream){caseAUDIO_STREAM_VOICE_CALL:caseAUDIO_STREAM_BLUETOOTH_SCO:returnSTRATEGY_PHONE;caseAUDIO_STREAM_RING:caseAUDIO_STREAM_ALARM:returnSTRATEGY_SONIFICATION;caseAUDIO_STREAM_NOTIFICATION:returnSTRATEGY_SONIFICATION_RESPECTFUL;caseAUDIO_STREAM_DTMF:returnSTRATEGY_DTMF;default:ALOGE("unknownstreamtype%d",stream);caseAUDIO_STREAM_SYSTEM://NOTE:SYSTEMstreamusesMEDIAstrategybecausemutingmusicandswitchingoutputs//whilekeyclicksareplayedproducesapoorresultcaseAUDIO_STREAM_MUSIC:returnSTRATEGY_MEDIA;caseAUDIO_STREAM_ENFORCED_AUDIBLE:returnSTRATEGY_ENFORCED_AUDIBLE;caseAUDIO_STREAM_TTS:returnSTRATEGY_TRANSMITTED_THROUGH_SPEAKER;caseAUDIO_STREAM_ACCESSIBILITY:returnSTRATEGY_ACCESSIBILITY;caseAUDIO_STREAM_REROUTING:returnSTRATEGY_REROUTING;}}routing_strategyEngine::getStrategyForUsage(audio_usage_tusage){//usagetostrategymappingswitch(usage){caseAUDIO_USAGE_ASSISTANCE_ACCESSIBILITY:returnSTRATEGY_ACCESSIBILITY;caseAUDIO_USAGE_MEDIA:caseAUDIO_USAGE_GAME:caseAUDIO_USAGE_ASSISTANT:caseAUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:caseAUDIO_USAGE_ASSISTANCE_SONIFICATION:returnSTRATEGY_MEDIA;caseAUDIO_USAGE_VOICE_COMMUNICATION:returnSTRATEGY_PHONE;caseAUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING:returnSTRATEGY_DTMF;caseAUDIO_USAGE_ALARM:caseAUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE:returnSTRATEGY_SONIFICATION;caseAUDIO_USAGE_NOTIFICATION:caseAUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST:caseAUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT:caseAUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED:caseAUDIO_USAGE_NOTIFICATION_EVENT:returnSTRATEGY_SONIFICATION_RESPECTFUL;caseAUDIO_USAGE_UNKNOWN:default:returnSTRATEGY_MEDIA;}}audio_devices_tEngine::getDeviceForStrategy(routing_strategystrategy)const{DeviceVectoravailableOutputDevices=mApmObserver->getAvailableOutputDevices();DeviceVectoravailableInputDevices=mApmObserver->getAvailableInputDevices();constSwAudioOutputCollection&outputs=mApmObserver->getOutputs();returngetDeviceForStrategyInt(strategy,availableOutputDevices,availableInputDevices,outputs,(uint32_t)AUDIO_DEVICE_NONE);}audio_devices_tEngine::getDeviceForStrategyInt(routing_strategystrategy,DeviceVectoravailableOutputDevices,DeviceVectoravailableInputDevices,constSwAudioOutputCollection&outputs,uint32_toutputDeviceTypesToIgnore)const{uint32_tdevice=AUDIO_DEVICE_NONE;uint32_tavailableOutputDevicesType=availableOutputDevices.types()&~outputDeviceTypesToIgnore;switch(strategy){caseSTRATEGY_TRANSMITTED_THROUGH_SPEAKER:device=availableOutputDevicesType&AUDIO_DEVICE_OUT_SPEAKER;break;caseSTRATEGY_SONIFICATION_RESPECTFUL:if(isInCall()||outputs.isStreamActiveLocally(AUDIO_STREAM_VOICE_CALL)){device=getDeviceForStrategyInt(STRATEGY_SONIFICATION,availableOutputDevices,availableInputDevices,outputs,outputDeviceTypesToIgnore);}else{boolmedia_active_locally=outputs.isStreamActiveLocally(AUDIO_STREAM_MUSIC,SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY)||outputs.isStreamActiveLocally(AUDIO_STREAM_ACCESSIBILITY,SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY);//routingissameasmediawithoutthe"remote"devicedevice=getDeviceForStrategyInt(STRATEGY_MEDIA,availableOutputDevices,availableInputDevices,outputs,AUDIO_DEVICE_OUT_REMOTE_SUBMIX|outputDeviceTypesToIgnore);//ifnomediaisplayingonthedevice,checkformandatoryuseof"safe"speaker//whenmediawouldhaveplayedonspeaker,andthesafespeakerpathisavailableif(!media_active_locally&&(device&AUDIO_DEVICE_OUT_SPEAKER)&&(availableOutputDevicesType&AUDIO_DEVICE_OUT_SPEAKER_SAFE)){device|=AUDIO_DEVICE_OUT_SPEAKER_SAFE;device&=~AUDIO_DEVICE_OUT_SPEAKER;}}break;caseSTRATEGY_DTMF:if(!isInCall()){//whenoffcall,DTMFstrategyfollowsthesamerulesasMEDIAstrategydevice=getDeviceForStrategyInt(STRATEGY_MEDIA,availableOutputDevices,availableInputDevices,outputs,outputDeviceTypesToIgnore);break;}//whenincall,DTMFandPHONEstrategiesfollowthesamerules//FALLTHROUGHcaseSTRATEGY_PHONE://Forceuseofonlydevicesonprimaryoutputif://-incallAND//-cannotroutefromvoicecallRXOR//-audioHALversionis<3.0andTXdeviceisontheprimaryHWmoduleif(getPhoneState()==AUDIO_MODE_IN_CALL){audio_devices_ttxDevice=getDeviceForInputSource(AUDIO_SOURCE_VOICE_COMMUNICATION);sp<AudioOutputDescriptor>primaryOutput=outputs.getPrimaryOutput();audio_devices_tavailPrimaryInputDevices=availableInputDevices.getDevicesFromHwModule(primaryOutput->getModuleHandle());//TODO:getPrimaryOutputreturnonlydevicesfromfirstmodulein//audio_policy_configuration.xml,hearingaidisnotthere,butit's//aprimarydevice//FIXME:thisisnottherightwayofsolvingthisproblemaudio_devices_tavailPrimaryOutputDevices=(primaryOutput->supportedDevices()|AUDIO_DEVICE_OUT_HEARING_AID)&availableOutputDevices.types();if(((availableInputDevices.types()&AUDIO_DEVICE_IN_TELEPHONY_RX&~AUDIO_DEVICE_BIT_IN)==0)||(((txDevice&availPrimaryInputDevices&~AUDIO_DEVICE_BIT_IN)!=0)&&(primaryOutput->getAudioPort()->getModuleVersionMajor()<3))){availableOutputDevicesType=availPrimaryOutputDevices;}}//forphonestrategy,wefirstconsidertheforceduseandthentheavailabledevicesby//orderofpriorityswitch(mForceUse[AUDIO_POLICY_FORCE_FOR_COMMUNICATION]){caseAUDIO_POLICY_FORCE_BT_SCO:if(!isInCall()||strategy!=STRATEGY_DTMF){device=availableOutputDevicesType&AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT;if(device)break;}device=availableOutputDevicesType&AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET;if(device)break;device=availableOutputDevicesType&AUDIO_DEVICE_OUT_BLUETOOTH_SCO;if(device)break;//ifSCOdeviceisrequestedbutnoSCOdeviceisavailable,fallbacktodefaultcase//FALLTHROUGHdefault://FORCE_NONEdevice=availableOutputDevicesType&AUDIO_DEVICE_OUT_HEARING_AID;if(device)break;//whennotinaphonecall,phonestrategyshouldrouteSTREAM_VOICE_CALLtoA2DPif(!isInCall()&&(mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA]!=AUDIO_POLICY_FORCE_NO_BT_A2DP)&&outputs.isA2dpSupported()){device=availableOutputDevicesType&AUDIO_DEVICE_OUT_BLUETOOTH_A2DP;if(device)break;device=availableOutputDevicesType&AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;if(device)break;}device=availableOutputDevicesType&AUDIO_DEVICE_OUT_WIRED_HEADPHONE;if(device)break;device=availableOutputDevicesType&AUDIO_DEVICE_OUT_WIRED_HEADSET;if(device)break;device=availableOutputDevicesType&AUDIO_DEVICE_OUT_LINE;if(device)break;device=availableOutputDevicesType&AUDIO_DEVICE_OUT_USB_HEADSET;if(device)break;device=availableOutputDevicesType&AUDIO_DEVICE_OUT_USB_DEVICE;if(device)break;if(!isInCall()){device=availableOutputDevicesType&AUDIO_DEVICE_OUT_USB_ACCESSORY;if(device)break;device=availableOutputDevicesType&AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET;if(device)break;device=availableOutputDevicesType&AUDIO_DEVICE_OUT_AUX_DIGITAL;if(device)break;device=availableOutputDevicesType&AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;if(device)break;}device=availableOutputDevicesType&AUDIO_DEVICE_OUT_EARPIECE;break;caseAUDIO_POLICY_FORCE_SPEAKER://whennotinaphonecall,phonestrategyshouldrouteSTREAM_VOICE_CALLto//A2DPspeakerwhenforcingtospeakeroutputif(!isInCall()&&(mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA]!=AUDIO_POLICY_FORCE_NO_BT_A2DP)&&outputs.isA2dpSupported()){device=availableOutputDevicesType&AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;if(device)break;}if(!isInCall()){device=availableOutputDevicesType&AUDIO_DEVICE_OUT_USB_ACCESSORY;if(device)break;device=availableOutputDevicesType&AUDIO_DEVICE_OUT_USB_DEVICE;if(device)break;device=availableOutputDevicesType&AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET;if(device)break;device=availableOutputDevicesType&AUDIO_DEVICE_OUT_AUX_DIGITAL;if(device)break;device=availableOutputDevicesType&AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;if(device)break;}device=availableOutputDevicesType&AUDIO_DEVICE_OUT_SPEAKER;break;}break;caseSTRATEGY_SONIFICATION://Ifincall,justselecttheSTRATEGY_PHONEdevice:Therestofthebehaviorishandledby//handleIncallSonification().if(isInCall()||outputs.isStreamActiveLocally(AUDIO_STREAM_VOICE_CALL)){device=getDeviceForStrategyInt(STRATEGY_PHONE,availableOutputDevices,availableInputDevices,outputs,outputDeviceTypesToIgnore);break;}//FALLTHROUGHcaseSTRATEGY_ENFORCED_AUDIBLE://strategySTRATEGY_ENFORCED_AUDIBLEusessameroutingpolicyasSTRATEGY_SONIFICATION//except://-whenincallwhereitdoesn'tdefaulttoSTRATEGY_PHONEbehavior//-incountrieswherenotenforcedinwhichcaseitfollowsSTRATEGY_MEDIAif((strategy==STRATEGY_SONIFICATION)||(mForceUse[AUDIO_POLICY_FORCE_FOR_SYSTEM]==AUDIO_POLICY_FORCE_SYSTEM_ENFORCED)){device=availableOutputDevicesType&AUDIO_DEVICE_OUT_SPEAKER;}//ifSCOheadsetisconnectedandwearetoldtouseit,playringtoneover//speakerandBTSCOif((availableOutputDevicesType&AUDIO_DEVICE_OUT_ALL_SCO)!=0){uint32_tdevice2=AUDIO_DEVICE_NONE;device2=availableOutputDevicesType&AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT;if(device2==AUDIO_DEVICE_NONE){device2=availableOutputDevicesType&AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET;}if(device2==AUDIO_DEVICE_NONE){device2=availableOutputDevicesType&AUDIO_DEVICE_OUT_BLUETOOTH_SCO;}//UseONLYBluetoothSCOoutputwhenringinginvibrationmodeif(!((mForceUse[AUDIO_POLICY_FORCE_FOR_SYSTEM]==AUDIO_POLICY_FORCE_SYSTEM_ENFORCED)&&(strategy==STRATEGY_ENFORCED_AUDIBLE))){if(mForceUse[AUDIO_POLICY_FORCE_FOR_VIBRATE_RINGING]==AUDIO_POLICY_FORCE_BT_SCO){if(device2!=AUDIO_DEVICE_NONE){device=device2;break;}}}//UsebothBluetoothSCOandphonedefaultoutputwhenringinginnormalmodeif(mForceUse[AUDIO_POLICY_FORCE_FOR_COMMUNICATION]==AUDIO_POLICY_FORCE_BT_SCO){if((strategy==STRATEGY_SONIFICATION)&&(device&AUDIO_DEVICE_OUT_SPEAKER)&&(availableOutputDevicesType&AUDIO_DEVICE_OUT_SPEAKER_SAFE)){device|=AUDIO_DEVICE_OUT_SPEAKER_SAFE;device&=~AUDIO_DEVICE_OUT_SPEAKER;}if(device2!=AUDIO_DEVICE_NONE){device|=device2;break;}}}//Theseconddeviceusedforsonificationisthesameasthedeviceusedbymediastrategy//FALLTHROUGHcaseSTRATEGY_ACCESSIBILITY:if(strategy==STRATEGY_ACCESSIBILITY){//donotrouteaccessibilitypromptstoadigitaloutputcurrentlyconfiguredwitha//compressedformatastheywouldlikelynotbemixedanddropped.for(size_ti=0;i<outputs.size();i++){sp<AudioOutputDescriptor>desc=outputs.valueAt(i);audio_devices_tdevices=desc->device()&(AUDIO_DEVICE_OUT_HDMI|AUDIO_DEVICE_OUT_SPDIF|AUDIO_DEVICE_OUT_HDMI_ARC);if(desc->isActive()&&!audio_is_linear_pcm(desc->mFormat)&&devices!=AUDIO_DEVICE_NONE){availableOutputDevicesType=availableOutputDevices.types()&~devices;}}availableOutputDevices=availableOutputDevices.getDevicesFromType(availableOutputDevicesType);if(outputs.isStreamActive(AUDIO_STREAM_RING)||outputs.isStreamActive(AUDIO_STREAM_ALARM)){returngetDeviceForStrategyInt(STRATEGY_SONIFICATION,availableOutputDevices,availableInputDevices,outputs,outputDeviceTypesToIgnore);}if(isInCall()){returngetDeviceForStrategyInt(STRATEGY_PHONE,availableOutputDevices,availableInputDevices,outputs,outputDeviceTypesToIgnore);}}//Forothercases,STRATEGY_ACCESSIBILITYbehaveslikeSTRATEGY_MEDIA//FALLTHROUGH//FIXME:STRATEGY_REROUTINGfollowSTRATEGY_MEDIAfornowcaseSTRATEGY_REROUTING:caseSTRATEGY_MEDIA:{uint32_tdevice2=AUDIO_DEVICE_NONE;if(strategy!=STRATEGY_SONIFICATION){//nosonificationonremotesubmix(e.g.WFD)if(availableOutputDevices.getDevice(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,String8("0"))!=0){device2=availableOutputDevices.types()&AUDIO_DEVICE_OUT_REMOTE_SUBMIX;}}if(isInCall()&&(strategy==STRATEGY_MEDIA)){device=getDeviceForStrategyInt(STRATEGY_PHONE,availableOutputDevices,availableInputDevices,outputs,outputDeviceTypesToIgnore);break;}if(device2==AUDIO_DEVICE_NONE){device2=availableOutputDevicesType&AUDIO_DEVICE_OUT_HEARING_AID;}if((device2==AUDIO_DEVICE_NONE)&&(mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA]!=AUDIO_POLICY_FORCE_NO_BT_A2DP)&&outputs.isA2dpSupported()){device2=availableOutputDevicesType&AUDIO_DEVICE_OUT_BLUETOOTH_A2DP;if(device2==AUDIO_DEVICE_NONE){device2=availableOutputDevicesType&AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;}if(device2==AUDIO_DEVICE_NONE){device2=availableOutputDevicesType&AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;}}if((device2==AUDIO_DEVICE_NONE)&&(mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA]==AUDIO_POLICY_FORCE_SPEAKER)){device2=availableOutputDevicesType&AUDIO_DEVICE_OUT_SPEAKER;}if(device2==AUDIO_DEVICE_NONE){device2=availableOutputDevicesType&AUDIO_DEVICE_OUT_WIRED_HEADPHONE;}if(device2==AUDIO_DEVICE_NONE){device2=availableOutputDevicesType&AUDIO_DEVICE_OUT_LINE;}if(device2==AUDIO_DEVICE_NONE){device2=availableOutputDevicesType&AUDIO_DEVICE_OUT_WIRED_HEADSET;}if(device2==AUDIO_DEVICE_NONE){device2=availableOutputDevicesType&AUDIO_DEVICE_OUT_USB_HEADSET;}if(device2==AUDIO_DEVICE_NONE){device2=availableOutputDevicesType&AUDIO_DEVICE_OUT_USB_ACCESSORY;}if(device2==AUDIO_DEVICE_NONE){device2=availableOutputDevicesType&AUDIO_DEVICE_OUT_USB_DEVICE;}if(device2==AUDIO_DEVICE_NONE){device2=availableOutputDevicesType&AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET;}if((device2==AUDIO_DEVICE_NONE)&&(strategy!=STRATEGY_SONIFICATION)){//nosonificationonauxdigital(e.g.HDMI)device2=availableOutputDevicesType&AUDIO_DEVICE_OUT_AUX_DIGITAL;}if((device2==AUDIO_DEVICE_NONE)&&(mForceUse[AUDIO_POLICY_FORCE_FOR_DOCK]==AUDIO_POLICY_FORCE_ANALOG_DOCK)){device2=availableOutputDevicesType&AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;}if(device2==AUDIO_DEVICE_NONE){device2=availableOutputDevicesType&AUDIO_DEVICE_OUT_SPEAKER;}intdevice3=AUDIO_DEVICE_NONE;if(strategy==STRATEGY_MEDIA){//ARC,SPDIFandAUX_LINEcanco-existwithothers.device3=availableOutputDevicesType&AUDIO_DEVICE_OUT_HDMI_ARC;device3|=(availableOutputDevicesType&AUDIO_DEVICE_OUT_SPDIF);device3|=(availableOutputDevicesType&AUDIO_DEVICE_OUT_AUX_LINE);}device2|=device3;//deviceisDEVICE_OUT_SPEAKERifwecomefromcaseSTRATEGY_SONIFICATIONor//STRATEGY_ENFORCED_AUDIBLE,AUDIO_DEVICE_NONEotherwisedevice|=device2;//Ifhdmisystemaudiomodeison,removespeakeroutofoutputlist.if((strategy==STRATEGY_MEDIA)&&(mForceUse[AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO]==AUDIO_POLICY_FORCE_HDMI_SYSTEM_AUDIO_ENFORCED)){device&=~AUDIO_DEVICE_OUT_SPEAKER;}//forSTRATEGY_SONIFICATION://ifSPEAKERwasselected,andSPEAKER_SAFEisavailable,useSPEAKER_SAFEinsteadif((strategy==STRATEGY_SONIFICATION)&&(device&AUDIO_DEVICE_OUT_SPEAKER)&&(availableOutputDevicesType&AUDIO_DEVICE_OUT_SPEAKER_SAFE)){device|=AUDIO_DEVICE_OUT_SPEAKER_SAFE;device&=~AUDIO_DEVICE_OUT_SPEAKER;}}break;default:ALOGW("getDeviceForStrategy()unknownstrategy:%d",strategy);break;}if(device==AUDIO_DEVICE_NONE){ALOGV("getDeviceForStrategy()nodevicefoundforstrategy%d",strategy);device=mApmObserver->getDefaultOutputDevice()->type();ALOGE_IF(device==AUDIO_DEVICE_NONE,"getDeviceForStrategy()nodefaultdevicedefined");}ALOGVV("getDeviceForStrategy()strategy%d,device%x",strategy,device);returndevice;}audio_devices_tEngine::getDeviceForInputSource(audio_source_tinputSource)const{constDeviceVector&availableOutputDevices=mApmObserver->getAvailableOutputDevices();constDeviceVector&availableInputDevices=mApmObserver->getAvailableInputDevices();constSwAudioOutputCollection&outputs=mApmObserver->getOutputs();audio_devices_tavailableDeviceTypes=availableInputDevices.types()&~AUDIO_DEVICE_BIT_IN;uint32_tdevice=AUDIO_DEVICE_NONE;//whenacallisactive,forcedeviceselectiontomatchsourceVOICE_COMMUNICATION//formostotherinputsourcestoavoidreroutingcallTXaudioif(isInCall()){switch(inputSource){caseAUDIO_SOURCE_DEFAULT:caseAUDIO_SOURCE_MIC:caseAUDIO_SOURCE_VOICE_RECOGNITION:caseAUDIO_SOURCE_UNPROCESSED:caseAUDIO_SOURCE_HOTWORD:caseAUDIO_SOURCE_CAMCORDER:inputSource=AUDIO_SOURCE_VOICE_COMMUNICATION;break;default:break;}}switch(inputSource){caseAUDIO_SOURCE_VOICE_UPLINK:if(availableDeviceTypes&AUDIO_DEVICE_IN_VOICE_CALL){device=AUDIO_DEVICE_IN_VOICE_CALL;break;}break;caseAUDIO_SOURCE_DEFAULT:caseAUDIO_SOURCE_MIC:if(availableDeviceTypes&AUDIO_DEVICE_IN_BLUETOOTH_A2DP){device=AUDIO_DEVICE_IN_BLUETOOTH_A2DP;}elseif((mForceUse[AUDIO_POLICY_FORCE_FOR_RECORD]==AUDIO_POLICY_FORCE_BT_SCO)&&(availableDeviceTypes&AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET)){device=AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET;}elseif(availableDeviceTypes&AUDIO_DEVICE_IN_WIRED_HEADSET){device=AUDIO_DEVICE_IN_WIRED_HEADSET;}elseif(availableDeviceTypes&AUDIO_DEVICE_IN_USB_HEADSET){device=AUDIO_DEVICE_IN_USB_HEADSET;}elseif(availableDeviceTypes&AUDIO_DEVICE_IN_USB_DEVICE){device=AUDIO_DEVICE_IN_USB_DEVICE;}elseif(availableDeviceTypes&AUDIO_DEVICE_IN_BUILTIN_MIC){device=AUDIO_DEVICE_IN_BUILTIN_MIC;}break;caseAUDIO_SOURCE_VOICE_COMMUNICATION://AllowonlyuseofdevicesonprimaryinputifincallandHALdoesnotsupportrouting//tovoicecallpath.if((getPhoneState()==AUDIO_MODE_IN_CALL)&&(availableOutputDevices.types()&AUDIO_DEVICE_OUT_TELEPHONY_TX)==0){sp<AudioOutputDescriptor>primaryOutput=outputs.getPrimaryOutput();availableDeviceTypes=availableInputDevices.getDevicesFromHwModule(primaryOutput->getModuleHandle())&~AUDIO_DEVICE_BIT_IN;}switch(mForceUse[AUDIO_POLICY_FORCE_FOR_COMMUNICATION]){caseAUDIO_POLICY_FORCE_BT_SCO://ifSCOdeviceisrequestedbutnoSCOdeviceisavailable,fallbacktodefaultcaseif(availableDeviceTypes&AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET){device=AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET;break;}//FALLTHROUGHdefault://FORCE_NONEif(availableDeviceTypes&AUDIO_DEVICE_IN_WIRED_HEADSET){device=AUDIO_DEVICE_IN_WIRED_HEADSET;}elseif(availableDeviceTypes&AUDIO_DEVICE_IN_USB_HEADSET){device=AUDIO_DEVICE_IN_USB_HEADSET;}elseif(availableDeviceTypes&AUDIO_DEVICE_IN_USB_DEVICE){device=AUDIO_DEVICE_IN_USB_DEVICE;}elseif(availableDeviceTypes&AUDIO_DEVICE_IN_BUILTIN_MIC){device=AUDIO_DEVICE_IN_BUILTIN_MIC;}break;caseAUDIO_POLICY_FORCE_SPEAKER:if(availableDeviceTypes&AUDIO_DEVICE_IN_BACK_MIC){device=AUDIO_DEVICE_IN_BACK_MIC;}elseif(availableDeviceTypes&AUDIO_DEVICE_IN_BUILTIN_MIC){device=AUDIO_DEVICE_IN_BUILTIN_MIC;}break;}break;caseAUDIO_SOURCE_VOICE_RECOGNITION:caseAUDIO_SOURCE_UNPROCESSED:caseAUDIO_SOURCE_HOTWORD:if(mForceUse[AUDIO_POLICY_FORCE_FOR_RECORD]==AUDIO_POLICY_FORCE_BT_SCO&&availableDeviceTypes&AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET){device=AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET;}elseif(availableDeviceTypes&AUDIO_DEVICE_IN_WIRED_HEADSET){device=AUDIO_DEVICE_IN_WIRED_HEADSET;}elseif(availableDeviceTypes&AUDIO_DEVICE_IN_USB_HEADSET){device=AUDIO_DEVICE_IN_USB_HEADSET;}elseif(availableDeviceTypes&AUDIO_DEVICE_IN_USB_DEVICE){device=AUDIO_DEVICE_IN_USB_DEVICE;}elseif(availableDeviceTypes&AUDIO_DEVICE_IN_BUILTIN_MIC){device=AUDIO_DEVICE_IN_BUILTIN_MIC;}break;caseAUDIO_SOURCE_CAMCORDER:if(availableDeviceTypes&AUDIO_DEVICE_IN_BACK_MIC){device=AUDIO_DEVICE_IN_BACK_MIC;}elseif(availableDeviceTypes&AUDIO_DEVICE_IN_BUILTIN_MIC){device=AUDIO_DEVICE_IN_BUILTIN_MIC;}break;caseAUDIO_SOURCE_VOICE_DOWNLINK:caseAUDIO_SOURCE_VOICE_CALL:if(availableDeviceTypes&AUDIO_DEVICE_IN_VOICE_CALL){device=AUDIO_DEVICE_IN_VOICE_CALL;}break;caseAUDIO_SOURCE_REMOTE_SUBMIX:if(availableDeviceTypes&AUDIO_DEVICE_IN_REMOTE_SUBMIX){device=AUDIO_DEVICE_IN_REMOTE_SUBMIX;}break;caseAUDIO_SOURCE_FM_TUNER:if(availableDeviceTypes&AUDIO_DEVICE_IN_FM_TUNER){device=AUDIO_DEVICE_IN_FM_TUNER;}break;default:ALOGW("getDeviceForInputSource()invalidinputsource%d",inputSource);break;}if(device==AUDIO_DEVICE_NONE){ALOGV("getDeviceForInputSource()nodevicefoundforsource%d",inputSource);if(availableDeviceTypes&AUDIO_DEVICE_IN_STUB){device=AUDIO_DEVICE_IN_STUB;}ALOGE_IF(device==AUDIO_DEVICE_NONE,"getDeviceForInputSource()nodefaultdevicedefined");}ALOGV("getDeviceForInputSource()inputsource%d,device%08x",inputSource,device);returndevice;}template<>AudioPolicyManagerInterface*Engine::queryInterface(){return&mManagerInterface;}}//namespaceaudio_policy}//namespaceandroid
通过以上分析,我们知道了音频会流向哪个输出设备,那么下一个问题来了,是由谁负责传输和对音频数据做最后的处理呢?
这里就需要看音频设备的策略文件,还是以媒体通道为例,假设设备没有接任何外接设备,选择的 outputDevice
是 AUDIO_DEVICE_OUT_SPEAKER
。
接下来就要看哪个 output
so
支持 AUDIO_DEVICE_OUT_SPEAKER
,符合度最高的 output
so
将会负责数据传输,最终经由 tinyalsa
写入到 pcm
节点中。
不同的 Android
版本在配置文件上会有些许差异,可能放置在 *audio_policy_configuration.xml
中,有些在 audio_policy.conf
中。
三、案例分析
1. 声音忽大忽小问题
具体分析
有用户反馈使用优酷视频播放视频时,概率性出现声音忽大忽小的问题,一旦出现就是在播放指定音频时是必现的。接下来联系用户帮提供设备的日志信息和操作步骤,按照用户操作来复现问题,通过 demo
还原用户环境参数便能复现。 首先分析确认发现在这个过程中声音音量均无变化,所以初步怀疑可能是和音频流数据出现异常有关。在上图中数字有标识的5个点中分别抓取音频,使用 Audacity
导入音频文件来进行分析,发现位置4的音频正常,而位置5的音频出现了声音异常的现象。具体见下图:
所以便可以确认在音频数据经过 hal 层音效处理前是正常等,经过音效处理后,在某些特殊的声音数据下,音效库缩小了声音的幅值,从而导致声音的异常。
为了实锤是音效库 so 导致的问题,通过关闭音效库的功能,最终发现声音忽大忽小的问题消失了。
从以上尝试的结果综合分析可以确认,是音效 so 库对通道声音进行处理时影响到了原有声音的功能。通过修改 so
库最终来解决这个问题。
2. 应用卡顿问题
有用户反馈说是打开应用A播放视频正常,然后直接返回到 home 目录,应用A后台播放时会出现断音的现象。
具体分析
声音卡顿,录音掉帧类的现象在声音问题中非常常见。从现象上来看,就是用户切换到后台时没有暂停播放,视频在后台播放时出现。老规矩,我们先分析相关 log
,通过日志分析发现,当问题出现时,日志上频繁打印 get null buffer
的信息。
所以怀疑是否是音频数据丢失导致的。dump
音频数据抓取到系统混音后输出到输出设备的原始音频,可以帮助实锤上层系统传下来的数据是否正常。于是发现位置3的音频如下:
从抓取到的音频可以看到,在后台异常播放时,在该时间段内会出现明显音频丢帧的现象。接下来要看看是在哪一块出现了丢帧。进一步分析 audioTrack
传下来的数据,出现了丢失掉一部分音频的现象,时长相当于原音频的一半。
基于此,为了实锤是应用A传下来的数据就有缺失,从日志信息跟踪,决定在 audioTrack 上加日志信息来看,发现当切换到后台时,audioTrack 每次还是写 4096 个 byte
,但是写数据的频率降低了一半。   
正常:28.600-27.546=1.054 44次 间隔 1.054/43= 0.0245秒/次。   
异常:40.839-39.804=1.035 22次 间隔 1.035/21= 0.0493秒/次。
考虑到这一块是否是和后台进程的优先级相关。当进程降低时导致了写数据的线程能够拿到的CPU资源变小,出现了断音的问题。通过和其他型号的平板对比发现,各厂家 Android 10 的平板大部分均有此问题,而 android7 和 android 8 的平板就没有这个问题。基于以上情况,更加怀疑是和 android 的特性相关,可能是新的 android 平板针对后台线程优先级做了处理,目的也很明确,就是限制后台应用的活跃程度,来保证设备性能。
此时进一步分析最终发现是和 TimerSlackHigh
的参数相关。
system/core/libprocessgroup/profiles/task_profiles.json:
{"Name":"TimerSlackHigh","Actions":[{"Name":"SetTimerSlack","Params":{"Slack":"40000000"}}]},{"Name":"TimerSlackNormal","Actions":[{"Name":"SetTimerSlack","Params":{"Slack":"50000"}}]},
该参数影响了应用后台线程 sleep/wait 之间所消耗的时间。可以看到,当应用从前台切换到后台时,这个时间从50 微秒上调到 40 毫秒。从而导致写入音频数据量大大减少。通过修改参数可以解决,但是提高后台线程的活跃度,很可能影响到整体性能,因此不作处理。最终像用户解释,切换后台时可以手动停止播放视频,同时反馈给应用,由应用规范应用流程,起后台进程来做单独处理。
关于“Androidaudio音频流数据异常问题怎么解决”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注亿速云行业资讯频道,小编每天都会为大家更新不同的知识点。
Android audio音频流数据异常问题怎么解决的详细内容,希望对您有所帮助,信息来源于网络。