在新开发的对讲机项目中,遇到了对讲无声问题,该问题直接影响使用。
一、分析现象
测试时,会出现一方说话,另一方没有听到声音,但是对方可以听到信令的声音,说明网络链路是通的。
做出如下猜测:
- 音频数据没有发出去,定位对讲端问题
- 音频数据发出去了,接收端没有收到,定位服务器问题
- 音频数据发出去了,但是没有播放出来,定位接收端播放问题
二、初步定位问题位置
使用展讯的Logel_for_TD工具,抓取cap包
步骤:打开Logel_for_TD工具,点击Option->Device Configuration
确保CAP LOG勾选上,之后点击开始,复现问题后,保存Log文件。使用Wireshark工具打开cap包,可以看到数据包的详细信息。
经过对比发现,无声log的CAP包如下:
而有声的CAP如却是这样的:
容易得出结论,有声时会发送数据包大小为116字节的UDP包进行传送,无声时则没有,故定位问题为按下PTT键时,没有发送音频数据
三、进一步分析,为什么没有发送UDP数据包
没有发送UDP数据包可以有以下几种原因:
- 没有获取到音频数据,可能是没有启动录音或者录音器异常导致采集音频失败
- 获取到了音频数据,但是没有执行数据发送流程
- 有数据,且执行了发送,由于网络原因没有发送成功
因为Logel_for_TD抓取的cap包为送到网卡的数据,所以基本可以排除网络问题,并且通过Logel_for_TD监测复现问题时的网络环境,-93dbm左右,良好。
故只剩下1,2两种可能,没有音频数据或者没有执行发送流程。
四、确认音频数据是否获取成功
通过BND平台的debug版本进行测试,从log中看出在问题复现时,获取到的音频数据为0,故确认是录音的问题。
五、分析录音模块
5.1 测试用例测试录音器是否存在问题
对讲APK使用的原生的方案。调用opensl_es库采集和播放音频。参考frameworks/wilhelm/tests/examples/slesTestRecBuffQueue.cpp
该文件中详细叙述了如何使用:
/* Audio Record Test
First run the program from shell:
# slesTest_recBuffQueue /sdcard/myrec.raw 4
These use adb on host to retrive the file:
% adb pull /sdcard/myrec.raw myrec.raw
How to examine the output with Audacity:
Project / Import raw data
Select myrec.raw file, then click Open button
Choose these options:
Signed 16-bit PCM
Little-endian
1 Channel (Mono)
Sample rate 22050 Hz
Click Import button
*/
在编译该模块后,把生成的可执行文件push到system/bin目录下再按上述测试即可
通过数十次的测试,录音均正常。
5.2 dump音频数据
在复现问题时执行dump命令
adb root
adb remount
adb shell
setprop media.dump.path /data/local/media/
setprop media.dump.switch 0x3ff
/data/local/media/目录下生成dump_record_after_vbc.pcm和dump_record_after_express为录音时的数据
可以使用AudacityPortable(提取码:qo80)工具播放裸数据,对比发现,无声时的pcm数据为0,进一步确认了是录音问题。
5.3 是否为硬件问题
通过向展讯提供PCB原理图,分析结论硬件电路没有问题
5.4 是否为音频参数问题
使用AudioTester
(提取码:y7rv )获取Music参数,交与展讯分析
正在分析中。。。
5.5 分析是否为录音流程问题
5.5.1 BSP分析
通过抓取对比log发现,有声和无声的log有所不同(PS:这种问题一定要抓对比log)
分析如下:
对比正常log,采集声音异常时,录音流程没有发起,因此无法录到声音。
按键提示音结束后,上层下发sprd_voip_start=false,准备结束voip流程,紧接着录音应用要下发in_read命令,从而进入do_input_standby,结束voip流程的同时开启录音流程。但异常时一直没有下发in_read,导致audio_hw中录音流程没有发起。
异常log中没有这个log:in_read sco stop and do standby
正常流程如下:
07-22 15:29:11.176 146 330 D AudioPolicyManagerSPRD: stopOutput() outputDesc->mRefCount[AudioSystem::VOICE_CALL] 1
07-22 15:29:11.176 146 329 D AudioPolicyService: AudioCommandThread() processing set parameters string sprd_voip_start=false, io 0
07-22 15:29:11.176 146 329 V AudioFlinger: setParameters(): io 0, keyvalue sprd_voip_start=false, calling pid 146
07-22 15:29:11.176 146 329 W audio_hw_primary: adev_set_parameters, kvpairs : sprd_voip_start=false
07-22 15:29:11.176 146 329 I audio_hw_primary: adev_set_parameters, voip turn off by output
07-22 15:29:11.176 146 364 D audio_hw_primary: sco:out_write stop and do standby
07-22 15:29:11.176 146 364 V audio_hw_primary: do_output_standby in
07-22 15:29:11.176 146 364 W audio_hw_primary: do_output_standby.mode:0
07-22 15:29:11.176 146 364 V audio_hw_primary: do_output_standby in out
07-22 15:29:11.176 146 364 E audio_hw_primary: out_write: drop data and sleep,out->is_voip is 0, adev->voip_state is 1,adev->voip_start is 0
07-22 15:29:11.196 146 1504 D audio_hw_primary: : in_read sco stop and do standby
07-22 15:29:11.196 146 1504 V audio_hw_primary: do_input_standby, standby=0, in_devices=0x80000004
07-22 15:29:11.196 146 1504 I audio_hw_primary: do_input_standby, fmUlDlHandle=0x00000000, fm_uldl=0x00000000, pcm = 0xb887b328
07-22 15:29:11.226 146 1504 W audio_hw_primary: start_input_stream in mode:0 devices:80000004 call_start:0, is_voip:0, is_bt_sco:0
07-22 15:29:11.226 146 1504 E audio_hw_primary: select_devices_signal starting... adev->out_devices 0x1 adev->in_devices 0x80000004
07-22 15:29:11.226 146 359 V audio_hw_primary: do_select_devices E
07-22 15:29:11.226 146 1504 I audio_hw_primary: select_devices_signal finished.
07-22 15:29:11.226 146 1504 E audio_hw_primary: start_input_stream pcm_open_0
07-22 15:29:11.236 146 1504 W audio_hw_primary: rec_mode(3), sample_rate(8000)
07-22 15:29:11.236 146 1504 W audio_hw_primary: extendArraySize=118, eq_size=52, dp_size=38
07-22 15:29:11.236 146 1504 I audio_hw_primary: record process module created is successful.
**请上层同事协助客户排查,是否客户自身应用流程有问题。**
5.5.2 流程分析
//这里在1秒钟之内start和stop了output这次output对应的stream 是0
STREAM_VOICE_CALL = 0;
07-22 15:34:30.126 146 146 D AudioPolicyManagerSPRD: startOutput() output 2, stream 0, session 13
07-22 15:34:30.766 146 308 D AudioPolicyManagerSPRD: stopOutput() output 2, stream 0, session 13
07-22 15:34:30.766 146 307 W audio_hw_primary: adev_set_parameters, kvpairs : sprd_voip_start=false
这次声音导致voip关闭了,正常的对讲最好是将voip打开
打开voip的方法就是在audiorecord和和播录音的那个player的流类型要设置成STREAM_VOICE_CALL 而且这个player要跟record一起stop。
根据展讯建议,播放Tone音不使用STREAM_VOICE_CALL,我测试去掉了TONE音,但是问题依然存在。