一建钥、相關(guān)背景
最近公司有個項目提出一個需求,就是在webrtc jni庫里面實現(xiàn)錄音虐沥,具體實現(xiàn)的細節(jié)為:
- 采集揚聲器的聲音(對方聲音)
- 采集麥克風的聲音(本地聲音)
- 上述兩種聲音進行混音并回調(diào)到j(luò)ava層熊经。
我決定audio_tracnsport_imp.cc
里面添加相關(guān)實現(xiàn)代碼泽艘,理由有以下幾點:
- 在這個代碼里面,已經(jīng)實現(xiàn)了采集播放聲音的處理(背景噪聲消除镐依,消回聲匹涮,自動增益,頻率轉(zhuǎn)換等)槐壳,音質(zhì)最好然低。
- 此處聲音接下來直接發(fā)送到對端,最接近對端播放感受务唐。
二雳攘、錄音大概實現(xiàn)
- 1、在
AudioTransportImpl::NeedMorePlayData
函數(shù)采集揚聲器聲音:
int32_t AudioTransportImpl::NeedMorePlayData(const size_t nSamples,
const size_t nBytesPerSample,
const size_t nChannels,
const uint32_t samplesPerSec,
void* audioSamples,
size_t& nSamplesOut,
int64_t* elapsed_time_ms,
int64_t* ntp_time_ms) {
RTC_DCHECK_EQ(sizeof(int16_t) * nChannels, nBytesPerSample);
RTC_DCHECK_GE(nChannels, 1);
RTC_DCHECK_LE(nChannels, 2);
RTC_DCHECK_GE(
samplesPerSec,
static_cast<uint32_t>(AudioProcessing::NativeRate::kSampleRate8kHz));
// 100 = 1 second / data duration (10 ms).
RTC_DCHECK_EQ(nSamples * 100, samplesPerSec);
RTC_DCHECK_LE(nBytesPerSample * nSamples * nChannels,
AudioFrame::kMaxDataSizeBytes);
mixer_->Mix(nChannels, &mixed_frame_);
*elapsed_time_ms = mixed_frame_.elapsed_time_ms_;
*ntp_time_ms = mixed_frame_.ntp_time_ms_;
const auto error = audio_processing_->ProcessReverseStream(&mixed_frame_);
RTC_DCHECK_EQ(error, AudioProcessing::kNoError);
nSamplesOut = Resample(mixed_frame_, samplesPerSec, &render_resampler_,
static_cast<int16_t*>(audioSamples));
//此處采集處理揚聲器聲音
voice_recorder_->onPlayoutVoice((int16_t *) mixed_frame_.data(),
(int64_t) mixed_frame_.samples_per_channel_,
(int64_t) mixed_frame_.sample_rate_hz_,
(int64_t) mixed_frame_.num_channels_);
RTC_DCHECK_EQ(nSamplesOut, nChannels * nSamples);
return 0;
}
- 2枫笛、在
AudioTransportImpl::RecordedDataIsAvailabl
函數(shù)采集麥克風聲音:
// Not used in Chromium. Process captured audio and distribute to all sending
// streams, and try to do this at the lowest possible sample rate.
int32_t AudioTransportImpl::RecordedDataIsAvailable(
const void* audio_data,
const size_t number_of_frames,
const size_t bytes_per_sample,
const size_t number_of_channels,
const uint32_t sample_rate,
const uint32_t audio_delay_milliseconds,
const int32_t /*clock_drift*/,
const uint32_t /*volume*/,
const bool key_pressed,
uint32_t& /*new_mic_volume*/) { // NOLINT: to avoid changing APIs
RTC_DCHECK(audio_data);
RTC_DCHECK_GE(number_of_channels, 1);
RTC_DCHECK_LE(number_of_channels, 2);
RTC_DCHECK_EQ(2 * number_of_channels, bytes_per_sample);
RTC_DCHECK_GE(sample_rate, AudioProcessing::NativeRate::kSampleRate8kHz);
// 100 = 1 second / data duration (10 ms).
RTC_DCHECK_EQ(number_of_frames * 100, sample_rate);
RTC_DCHECK_LE(bytes_per_sample * number_of_frames * number_of_channels,
AudioFrame::kMaxDataSizeBytes);
int send_sample_rate_hz = 0;
size_t send_num_channels = 0;
bool swap_stereo_channels = false;
{
rtc::CritScope lock(&capture_lock_);
send_sample_rate_hz = send_sample_rate_hz_;
send_num_channels = send_num_channels_;
swap_stereo_channels = swap_stereo_channels_;
}
std::unique_ptr<AudioFrame> audio_frame(new AudioFrame());
InitializeCaptureFrame(sample_rate, send_sample_rate_hz, number_of_channels,
send_num_channels, audio_frame.get());
voe::RemixAndResample(static_cast<const int16_t*>(audio_data),
number_of_frames, number_of_channels, sample_rate,
&capture_resampler_, audio_frame.get());
ProcessCaptureFrame(audio_delay_milliseconds, key_pressed,
swap_stereo_channels, audio_processing_,
audio_frame.get());
//采集麥克風聲音
voice_recorder_->onRecordVoice(audio_frame.get());
//忽略后續(xù)代碼
....
}
- 后續(xù)進行聲音的重采樣吨灭、混音、然后回調(diào)到JAVA層刑巧,具體步驟不再贅述喧兄。
三、bug的一般調(diào)試手段
前面講了一堆無關(guān)主題的話啊楚,現(xiàn)在才進入正題吠冤。
由于在添加上述代碼后,我的程序出現(xiàn)了jni導(dǎo)致的閃退問題恭理。所以我開始查找問題根源; 由于jni代碼基本很難調(diào)試拯辙,只能在崩潰時獲取一點關(guān)鍵信息,例如以下:
----- timezone:GMT
05-07 12:24:16.332187 7971 8249 F libc : Fatal signal 11 (SIGSEGV), code 1, fault addr 0x8 in tid 8249 (AudioTrackJavaT)
05-07 12:24:16.402427 14617 14617 I AEE/AED : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
05-07 12:24:16.404351 14617 14617 I AEE/AED : Build fingerprint: 'T28/T28:6.0/MRA58K/1568261156:user/test-keys'
05-07 12:24:16.404457 14617 14617 I AEE/AED : Revision: '0'
05-07 12:24:16.404542 14617 14617 I AEE/AED : ABI: 'arm'
05-07 12:24:16.404988 14617 14617 I AEE/AED : pid: 7971, tid: 8249, name: AudioTrackJavaT >>> com.example.janusandroidtalk <<<
05-07 12:24:16.405157 14617 14617 I AEE/AED : signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x8
05-07 12:24:16.456888 14617 14617 I AEE/AED : r0 f8e4a9e0 r1 00000008 r2 f8e4a9e0 r3 de492519
05-07 12:24:16.456985 14617 14617 I AEE/AED : r4 f8e4a9e0 r5 de0adb04 r6 f8e46550 r7 de0a3eb2
05-07 12:24:16.457029 14617 14617 I AEE/AED : r8 f8cddc48 r9 f8cddc40 sl f8cddca0 fp de09b88d
05-07 12:24:16.457071 14617 14617 I AEE/AED : ip de5a8e74 sp dcc40398 lr de49252b pc de1357c8 cpsr a00f0030
05-07 12:24:16.506852 14617 14617 I AEE/AED :
05-07 12:24:16.506852 14617 14617 I AEE/AED : backtrace:
05-07 12:24:16.507029 14617 14617 I AEE/AED : #00 pc 0018f7c8 /data/app/com.example.janusandroidtalk-1/lib/arm/libjingle_peerconnection_so.so Java_org_webrtc_Logging_nativeLog
05-07 12:24:16.507138 14617 14617 I AEE/AED : #01 pc 004ec527 /data/app/com.example.janusandroidtalk-1/lib/arm/libjingle_peerconnection_so.so Java_org_webrtc_TurnCustomizer_nativeFreeTurnCustomizer
05-07 12:24:16.507222 14617 14617 I AEE/AED : #02 pc 00396061 /data/app/com.example.janusandroidtalk-1/lib/arm/libjingle_peerconnection_so.so Java_org_webrtc_YuvHelper_nativeI420Rotate
05-07 12:24:16.507295 14617 14617 I AEE/AED : #03 pc 00395ecf /data/app/com.example.janusandroidtalk-1/lib/arm/libjingle_peerconnection_so.so Java_org_webrtc_YuvHelper_nativeI420Rotate
05-07 12:24:16.507364 14617 14617 I AEE/AED : #04 pc 004ec687 /data/app/com.example.janusandroidtalk-1/lib/arm/libjingle_peerconnection_so.so Java_org_webrtc_TurnCustomizer_nativeFreeTurnCustomizer
05-07 12:24:16.507436 14617 14617 I AEE/AED : #05 pc 004ebe37 /data/app/com.example.janusandroidtalk-1/lib/arm/libjingle_peerconnection_so.so Java_org_webrtc_TurnCustomizer_nativeFreeTurnCustomizer
05-07 12:24:16.507522 14617 14617 I AEE/AED : #06 pc 004ebbe3 /data/app/com.example.janusandroidtalk-1/lib/arm/libjingle_peerconnection_so.so Java_org_webrtc_TurnCustomizer_nativeFreeTurnCustomizer
05-07 12:24:16.507592 14617 14617 I AEE/AED : #07 pc001e9f6f /data/app/com.example.janusandroidtalk-1/lib/arm/libjingle_peerconnection_so.so Java_org_webrtc_Logging_nativeLog
05-07 12:24:16.507658 14617 14617 I AEE/AED : #08 pc 001f2ecf /data/app/com.example.janusandroidtalk-1/lib/arm/libjingle_peerconnection_so.so Java_org_webrtc_audio_WebRtcAudioTrack_nativeGetPlayoutData
05-07 12:24:16.507752 14617 14617 I AEE/AED : #09 pc 020dd5a3 /data/app/com.example.janusandroidtalk-1/oat/arm/base.odex (offset 0xf21000) (void org.webrtc.audio.WebRtcAudioTrack.nativeGetPlayoutData(long, int)+94)
05-07 12:24:16.507845 14617 14617 I AEE/AED : #10 pc 020db771 /data/app/com.example.janusandroidtalk-1/oat/arm/base.odex (offset 0xf21000) (void org.webrtc.audio.WebRtcAudioTrack.access$300(long, int)+60)
05-07 12:24:16.507942 14617 14617 I AEE/AED : #11 pc 020da8a1 /data/app/com.example.janusandroidtalk-1/oat/arm/base.odex (offset 0xf21000) (void org.webrtc.audio.WebRtcAudioTrack$AudioTrackThread.run()+1204)
05-07 12:24:16.508027 14617 14617 I AEE/AED : #12 pc 000e60e1 /system/lib/libart.so (art_quick_invoke_stub_internal+64)
05-07 12:24:16.508108 14617 14617 I AEE/AED : #13 pc 003e8b37 /system/lib/libart.so (art_quick_invoke_stub+170)
05-07 12:24:16.508187 14617 14617 I AEE/AED : #14 pc 0010276c [stack:8249]
05-07 12:24:17.637421 14617 14617 I AEE/AED :
05-07 12:24:17.637421 14617 14617 I AEE/AED : Tombstone written to: /data/tombstones/tombstone_01
上述這種信息一般很難定位bug蚯斯,通常還需要用add2lin工具定位代碼:
cd ndk-bundle/toolchains/llvm/prebuilt/darwin-x86_64/bin/
./arm-linux-androideabi-addr2line -C -f -e libjingle_peerconnection_so.so 0018f7c8
以上操作一般只能定位到崩潰代碼函數(shù)名薄风,但是由于這個信息太少了饵较,一般找不到問題所在拍嵌,況且有時由于內(nèi)存越界會導(dǎo)致誤導(dǎo)性的崩潰堆棧提示。
四循诉、使用Sanitizers調(diào)試
Sanitizers是google開源的一款調(diào)試工具横辆,類似于valgrind,可以檢測包括內(nèi)存越界茄猫、訪問懸垂指針狈蚤、內(nèi)存泄露等bug,不過占用資源更少划纽,性能更強脆侮,在某些場景下比valgrind更適合。
Sanitizers在高版本的NDK里面已經(jīng)集成進去了(集成在clang編譯器內(nèi))勇劣,現(xiàn)在我們接下來講述怎么使用Sanitizers調(diào)試內(nèi)存錯誤靖避。
1潭枣、加入編譯參數(shù):
找打webrtc源碼根目錄下的編譯腳本(BUILD.gn),添加一下編譯flags:
#第98行修改
ldflags = ["-fsanitize=address"]
#在第360行添加以下
cflags += [
"-fsanitize=address",
"-fno-omit-frame-pointer",
"-g2",
"-O0",
]
cflags_c += [
"-fsanitize=address",
"-fno-omit-frame-pointer",
"-g2",
"-O0",
]
cflags_cc += [
"-fsanitize=address",
"-fno-omit-frame-pointer",
"-g2",
"-O0",
]
上述修改主要是關(guān)閉編譯優(yōu)化、添加編譯調(diào)試符號幻捏、以及開啟Sanitizers內(nèi)存檢測盆犁。
2、重新編譯代碼
#構(gòu)建
gn gen out/Debug_arm --args='target_os="android" target_cpu="arm" is_debug=true'
#編譯
ninja -C out/Debug_arm
生成的webrtc動態(tài)庫在out/Debug_arm/libjingle_peerconnection_so.so
.
3篡九、拷貝動態(tài)庫至app工程:
-
拷貝libjingle_peerconnection_so庫:
image.png 拷貝libclang_rt.asan-arm-android.so庫:
cp ndk-bundle/toolchains/llvm/prebuilt/darwin-x86_64/lib64/clang/8.0.7/lib/linux/libclang_rt.asan-arm-android.so /path/to/armeabi-v7a
4谐岁、創(chuàng)建啟動腳本:
需要指出的是,腳本路徑是resources/lib/armeabi-v7a/wrap.sh
榛臼,腳本內(nèi)容為:
#!/system/bin/sh
HERE="$(cd "$(dirname "$0")" && pwd)"
export ASAN_OPTIONS=log_to_syslog=false,allow_user_segv_handler=1,log_path=/sdcard/asan.log
ASAN_LIB=$(ls $HERE/libclang_rt.asan-*-android.so)
if [ -f "$HERE/libc++_shared.so" ]; then
# Workaround for https://github.com/android-ndk/ndk/issues/988.
export LD_PRELOAD="$ASAN_LIB $HERE/libc++_shared.so"
else
export LD_PRELOAD="$ASAN_LIB"
fi
"$@"
上述腳本中指定了Sanitizerss生成日志路徑:/sdcard/asan.log
五伊佃、分析Sanitizers日志
找到Sanitizers日志并打開:
=================================================================
==32743==ERROR: AddressSanitizer: heap-use-after-free on address 0x81d8f934 at pc 0x71f047a3 bp 0x6c598990 sp 0x6c59898c
WRITE of size 4 at 0x81d8f934 thread T74 (AudioRecordJava)
#0 0x71f047a0 (/data/app/com.jimi.t28-qMxhyaqcwCivEwMd7OGBLw==/lib/arm/libjingle_peerconnection_so.so+0x242d7a0)
#1 0x71f04176 (/data/app/com.jimi.t28-qMxhyaqcwCivEwMd7OGBLw==/lib/arm/libjingle_peerconnection_so.so+0x242d176)
#2 0x71efe490 (/data/app/com.jimi.t28-qMxhyaqcwCivEwMd7OGBLw==/lib/arm/libjingle_peerconnection_so.so+0x2427490)
#3 0x71eef78a (/data/app/com.jimi.t28-qMxhyaqcwCivEwMd7OGBLw==/lib/arm/libjingle_peerconnection_so.so+0x241878a)
#4 0x71ee8adc (/data/app/com.jimi.t28-qMxhyaqcwCivEwMd7OGBLw==/lib/arm/libjingle_peerconnection_so.so+0x2411adc)
#5 0x706d43c0 (/data/app/com.jimi.t28-qMxhyaqcwCivEwMd7OGBLw==/lib/arm/libjingle_peerconnection_so.so+0xbfd3c0)
#6 0x70769a72 (/data/app/com.jimi.t28-qMxhyaqcwCivEwMd7OGBLw==/lib/arm/libjingle_peerconnection_so.so+0xc92a72)
#7 0x70768c26 (/data/app/com.jimi.t28-qMxhyaqcwCivEwMd7OGBLw==/lib/arm/libjingle_peerconnection_so.so+0xc91c26)
#8 0xac98ca76 (/system/lib/libart.so+0x405a76)
#9 0xac98ca76 (/system/lib/libart.so+0x405a76)
#10 0xac98ca76 (/system/lib/libart.so+0x405a76)
#11 0xac98ca76 (/system/lib/libart.so+0x405a76)
#12 0xac98ca76 (/system/lib/libart.so+0x405a76)
#13 0xac98ca76 (/system/lib/libart.so+0x405a76)
#14 0xac98ca76 (/system/lib/libart.so+0x405a76)
#15 0xac98ca76 (/system/lib/libart.so+0x405a76)
#16 0xac98ca76 (/system/lib/libart.so+0x405a76)
#17 0xac98ca76 (/system/lib/libart.so+0x405a76)
#18 0xac98ca76 (/system/lib/libart.so+0x405a76)
#19 0xac98ca76 (/system/lib/libart.so+0x405a76)
#20 0xac98ca76 (/system/lib/libart.so+0x405a76)
#21 0xac98ca76 (/system/lib/libart.so+0x405a76)
#22 0xac98ca76 (/system/lib/libart.so+0x405a76)
#23 0xac98ca76 (/system/lib/libart.so+0x405a76)
#24 0xac98ca76 (/system/lib/libart.so+0x405a76)
#25 0xac98ca76 (/system/lib/libart.so+0x405a76)
#26 0xac98ca76 (/system/lib/libart.so+0x405a76)
#27 0xac98ca76 (/system/lib/libart.so+0x405a76)
#28 0xac98ca76 (/system/lib/libart.so+0x405a76)
#29 0xac98ca76 (/system/lib/libart.so+0x405a76)
#30 0xac98ca76 (/system/lib/libart.so+0x405a76)
#31 0xac98ca76 (/system/lib/libart.so+0x405a76)
#32 0xac98ca76 (/system/lib/libart.so+0x405a76)
#33 0xac98ca76 (/system/lib/libart.so+0x405a76)
#34 0xac98ca76 (/system/lib/libart.so+0x405a76)
#35 0xac98ca76 (/system/lib/libart.so+0x405a76)
#36 0xac98ca76 (/system/lib/libart.so+0x405a76)
#37 0xac98ca76 (/system/lib/libart.so+0x405a76)
#38 0xac98ca76 (/system/lib/libart.so+0x405a76)
#39 0xac98ca76 (/system/lib/libart.so+0x405a76)
#40 0xac98ca76 (/system/lib/libart.so+0x405a76)
#41 0xac98ca76 (/system/lib/libart.so+0x405a76)
#42 0xac98ca76 (/system/lib/libart.so+0x405a76)
#43 0xac98ca76 (/system/lib/libart.so+0x405a76)
#44 0xac98ca76 (/system/lib/libart.so+0x405a76)
#45 0xac98ca76 (/system/lib/libart.so+0x405a76)
#46 0xac98ca76 (/system/lib/libart.so+0x405a76)
#47 0xac98ca76 (/system/lib/libart.so+0x405a76)
#48 0xac98ca76 (/system/lib/libart.so+0x405a76)
#49 0xac98ca76 (/system/lib/libart.so+0x405a76)
#50 0xac98ca76 (/system/lib/libart.so+0x405a76)
#51 0xac98ca76 (/system/lib/libart.so+0x405a76)
#52 0xac98ca76 (/system/lib/libart.so+0x405a76)
#53 0xac98ca76 (/system/lib/libart.so+0x405a76)
#54 0xac98ca76 (/system/lib/libart.so+0x405a76)
#55 0xac98ca76 (/system/lib/libart.so+0x405a76)
#56 0xac98ca76 (/system/lib/libart.so+0x405a76)
#57 0xac98ca76 (/system/lib/libart.so+0x405a76)
#58 0xac98ca76 (/system/lib/libart.so+0x405a76)
#59 0xac98ca76 (/system/lib/libart.so+0x405a76)
#60 0xac98ca76 (/system/lib/libart.so+0x405a76)
#61 0xac98ca76 (/system/lib/libart.so+0x405a76)
#62 0xac98ca76 (/system/lib/libart.so+0x405a76)
#63 0xac98ca76 (/system/lib/libart.so+0x405a76)
#64 0xac98ca76 (/system/lib/libart.so+0x405a76)
#65 0xac98ca76 (/system/lib/libart.so+0x405a76)
#66 0xac98ca76 (/system/lib/libart.so+0x405a76)
#67 0xac98ca76 (/system/lib/libart.so+0x405a76)
#68 0xac98ca76 (/system/lib/libart.so+0x405a76)
#69 0xac98ca76 (/system/lib/libart.so+0x405a76)
#70 0xac98ca76 (/system/lib/libart.so+0x405a76)
#71 0xac98ca76 (/system/lib/libart.so+0x405a76)
#72 0xac98ca76 (/system/lib/libart.so+0x405a76)
#73 0xac98ca76 (/system/lib/libart.so+0x405a76)
#74 0xac98ca76 (/system/lib/libart.so+0x405a76)
#75 0xac98ca76 (/system/lib/libart.so+0x405a76)
#76 0xac98ca76 (/system/lib/libart.so+0x405a76)
#77 0xac98ca76 (/system/lib/libart.so+0x405a76)
#78 0xac98ca76 (/system/lib/libart.so+0x405a76)
#79 0xac98ca76 (/system/lib/libart.so+0x405a76)
#80 0xac98ca76 (/system/lib/libart.so+0x405a76)
#81 0xac98ca76 (/system/lib/libart.so+0x405a76)
#82 0xac98ca76 (/system/lib/libart.so+0x405a76)
#83 0xac98ca76 (/system/lib/libart.so+0x405a76)
#84 0xac98ca76 (/system/lib/libart.so+0x405a76)
#85 0xac98ca76 (/system/lib/libart.so+0x405a76)
#86 0xac98ca76 (/system/lib/libart.so+0x405a76)
#87 0xac98ca76 (/system/lib/libart.so+0x405a76)
#88 0xac98ca76 (/system/lib/libart.so+0x405a76)
#89 0xac98ca76 (/system/lib/libart.so+0x405a76)
#90 0xac98ca76 (/system/lib/libart.so+0x405a76)
#91 0xac98ca76 (/system/lib/libart.so+0x405a76)
#92 0xac98ca76 (/system/lib/libart.so+0x405a76)
#93 0xac98ca76 (/system/lib/libart.so+0x405a76)
#94 0xac98ca76 (/system/lib/libart.so+0x405a76)
#95 0xac98ca76 (/system/lib/libart.so+0x405a76)
#96 0xac98ca76 (/system/lib/libart.so+0x405a76)
#97 0xac98ca76 (/system/lib/libart.so+0x405a76)
#98 0xac98ca76 (/system/lib/libart.so+0x405a76)
#99 0xac98ca76 (/system/lib/libart.so+0x405a76)
#100 0xac98ca76 (/system/lib/libart.so+0x405a76)
#101 0xac98ca76 (/system/lib/libart.so+0x405a76)
#102 0xac98ca76 (/system/lib/libart.so+0x405a76)
#103 0xac98ca76 (/system/lib/libart.so+0x405a76)
#104 0xac98ca76 (/system/lib/libart.so+0x405a76)
#105 0xac98ca76 (/system/lib/libart.so+0x405a76)
#106 0xac98ca76 (/system/lib/libart.so+0x405a76)
#107 0xac98ca76 (/system/lib/libart.so+0x405a76)
#108 0xac98ca76 (/system/lib/libart.so+0x405a76)
#109 0xac98ca76 (/system/lib/libart.so+0x405a76)
#110 0xac98ca76 (/system/lib/libart.so+0x405a76)
#111 0xac98ca76 (/system/lib/libart.so+0x405a76)
#112 0xac98ca76 (/system/lib/libart.so+0x405a76)
#113 0xac98ca76 (/system/lib/libart.so+0x405a76)
#114 0xac98ca76 (/system/lib/libart.so+0x405a76)
#115 0xac98ca76 (/system/lib/libart.so+0x405a76)
#116 0xac98ca76 (/system/lib/libart.so+0x405a76)
#117 0xac98ca76 (/system/lib/libart.so+0x405a76)
#118 0xac98ca76 (/system/lib/libart.so+0x405a76)
#119 0xac98ca76 (/system/lib/libart.so+0x405a76)
#120 0xac98ca76 (/system/lib/libart.so+0x405a76)
#121 0xac98ca76 (/system/lib/libart.so+0x405a76)
#122 0xac98ca76 (/system/lib/libart.so+0x405a76)
#123 0xac98ca76 (/system/lib/libart.so+0x405a76)
#124 0xac98ca76 (/system/lib/libart.so+0x405a76)
#125 0xac98ca76 (/system/lib/libart.so+0x405a76)
#126 0xac98ca76 (/system/lib/libart.so+0x405a76)
#127 0xac98ca76 (/system/lib/libart.so+0x405a76)
#128 0xac98ca76 (/system/lib/libart.so+0x405a76)
#129 0xac98ca76 (/system/lib/libart.so+0x405a76)
#130 0xac98ca76 (/system/lib/libart.so+0x405a76)
#131 0xac98ca76 (/system/lib/libart.so+0x405a76)
#132 0xac98ca76 (/system/lib/libart.so+0x405a76)
#133 0xac98ca76 (/system/lib/libart.so+0x405a76)
#134 0xac98ca76 (/system/lib/libart.so+0x405a76)
#135 0xac98ca76 (/system/lib/libart.so+0x405a76)
#136 0xac98ca76 (/system/lib/libart.so+0x405a76)
#137 0xac98ca76 (/system/lib/libart.so+0x405a76)
#138 0xac98ca76 (/system/lib/libart.so+0x405a76)
#139 0xac98ca76 (/system/lib/libart.so+0x405a76)
#140 0xac98ca76 (/system/lib/libart.so+0x405a76)
#141 0xac98ca76 (/system/lib/libart.so+0x405a76)
#142 0xac98ca76 (/system/lib/libart.so+0x405a76)
#143 0xac98ca76 (/system/lib/libart.so+0x405a76)
#144 0xac98ca76 (/system/lib/libart.so+0x405a76)
#145 0xac98ca76 (/system/lib/libart.so+0x405a76)
#146 0xac98ca76 (/system/lib/libart.so+0x405a76)
#147 0xac98ca76 (/system/lib/libart.so+0x405a76)
#148 0xac98ca76 (/system/lib/libart.so+0x405a76)
#149 0xac98ca76 (/system/lib/libart.so+0x405a76)
#150 0xac98ca76 (/system/lib/libart.so+0x405a76)
#151 0xac98ca76 (/system/lib/libart.so+0x405a76)
#152 0xac98ca76 (/system/lib/libart.so+0x405a76)
#153 0xac98ca76 (/system/lib/libart.so+0x405a76)
#154 0xac98ca76 (/system/lib/libart.so+0x405a76)
#155 0xac98ca76 (/system/lib/libart.so+0x405a76)
#156 0xac98ca76 (/system/lib/libart.so+0x405a76)
#157 0xac98ca76 (/system/lib/libart.so+0x405a76)
#158 0xac98ca76 (/system/lib/libart.so+0x405a76)
#159 0xac98ca76 (/system/lib/libart.so+0x405a76)
#160 0xac98ca76 (/system/lib/libart.so+0x405a76)
#161 0xac98ca76 (/system/lib/libart.so+0x405a76)
#162 0xac98ca76 (/system/lib/libart.so+0x405a76)
#163 0xac98ca76 (/system/lib/libart.so+0x405a76)
#164 0xac98ca76 (/system/lib/libart.so+0x405a76)
#165 0xac98ca76 (/system/lib/libart.so+0x405a76)
#166 0xac98ca76 (/system/lib/libart.so+0x405a76)
#167 0xac98ca76 (/system/lib/libart.so+0x405a76)
#168 0xac98ca76 (/system/lib/libart.so+0x405a76)
#169 0xac98ca76 (/system/lib/libart.so+0x405a76)
#170 0xac98ca76 (/system/lib/libart.so+0x405a76)
#171 0xac98ca76 (/system/lib/libart.so+0x405a76)
#172 0xac98ca76 (/system/lib/libart.so+0x405a76)
#173 0xac98ca76 (/system/lib/libart.so+0x405a76)
#174 0xac98ca76 (/system/lib/libart.so+0x405a76)
#175 0xac98ca76 (/system/lib/libart.so+0x405a76)
#176 0xac98ca76 (/system/lib/libart.so+0x405a76)
#177 0xac98ca76 (/system/lib/libart.so+0x405a76)
#178 0xac98ca76 (/system/lib/libart.so+0x405a76)
#179 0xac98ca76 (/system/lib/libart.so+0x405a76)
#180 0xac98ca76 (/system/lib/libart.so+0x405a76)
#181 0xac98ca76 (/system/lib/libart.so+0x405a76)
#182 0xac98ca76 (/system/lib/libart.so+0x405a76)
#183 0xac98ca76 (/system/lib/libart.so+0x405a76)
#184 0xac98ca76 (/system/lib/libart.so+0x405a76)
#185 0xac98ca76 (/system/lib/libart.so+0x405a76)
#186 0xac98ca76 (/system/lib/libart.so+0x405a76)
#187 0xac98ca76 (/system/lib/libart.so+0x405a76)
#188 0xac98ca76 (/system/lib/libart.so+0x405a76)
#189 0xac98ca76 (/system/lib/libart.so+0x405a76)
#190 0xac98ca76 (/system/lib/libart.so+0x405a76)
#191 0xac98ca76 (/system/lib/libart.so+0x405a76)
#192 0xac98ca76 (/system/lib/libart.so+0x405a76)
#193 0xac98ca76 (/system/lib/libart.so+0x405a76)
#194 0xac98ca76 (/system/lib/libart.so+0x405a76)
#195 0xac98ca76 (/system/lib/libart.so+0x405a76)
#196 0xac98ca76 (/system/lib/libart.so+0x405a76)
#197 0xac98ca76 (/system/lib/libart.so+0x405a76)
#198 0xac98ca76 (/system/lib/libart.so+0x405a76)
#199 0xac98ca76 (/system/lib/libart.so+0x405a76)
#200 0xac98ca76 (/system/lib/libart.so+0x405a76)
#201 0xac98ca76 (/system/lib/libart.so+0x405a76)
#202 0xac98ca76 (/system/lib/libart.so+0x405a76)
#203 0xac98ca76 (/system/lib/libart.so+0x405a76)
#204 0xac98ca76 (/system/lib/libart.so+0x405a76)
#205 0xac98ca76 (/system/lib/libart.so+0x405a76)
#206 0xac98ca76 (/system/lib/libart.so+0x405a76)
#207 0xac98ca76 (/system/lib/libart.so+0x405a76)
#208 0xac98ca76 (/system/lib/libart.so+0x405a76)
#209 0xac98ca76 (/system/lib/libart.so+0x405a76)
#210 0xac98ca76 (/system/lib/libart.so+0x405a76)
#211 0xac98ca76 (/system/lib/libart.so+0x405a76)
#212 0xac98ca76 (/system/lib/libart.so+0x405a76)
#213 0xac98ca76 (/system/lib/libart.so+0x405a76)
#214 0xac98ca76 (/system/lib/libart.so+0x405a76)
#215 0xac98ca76 (/system/lib/libart.so+0x405a76)
#216 0xac98ca76 (/system/lib/libart.so+0x405a76)
#217 0xac98ca76 (/system/lib/libart.so+0x405a76)
#218 0xac98ca76 (/system/lib/libart.so+0x405a76)
#219 0xac98ca76 (/system/lib/libart.so+0x405a76)
#220 0xac98ca76 (/system/lib/libart.so+0x405a76)
#221 0xac98ca76 (/system/lib/libart.so+0x405a76)
#222 0xac98ca76 (/system/lib/libart.so+0x405a76)
#223 0xac98ca76 (/system/lib/libart.so+0x405a76)
#224 0xac98ca76 (/system/lib/libart.so+0x405a76)
#225 0xac98ca76 (/system/lib/libart.so+0x405a76)
#226 0xac98ca76 (/system/lib/libart.so+0x405a76)
#227 0xac98ca76 (/system/lib/libart.so+0x405a76)
#228 0xac98ca76 (/system/lib/libart.so+0x405a76)
#229 0xac98ca76 (/system/lib/libart.so+0x405a76)
#230 0xac98ca76 (/system/lib/libart.so+0x405a76)
#231 0xac98ca76 (/system/lib/libart.so+0x405a76)
#232 0xac98ca76 (/system/lib/libart.so+0x405a76)
#233 0xac98ca76 (/system/lib/libart.so+0x405a76)
#234 0xac98ca76 (/system/lib/libart.so+0x405a76)
#235 0xac98ca76 (/system/lib/libart.so+0x405a76)
#236 0xac98ca76 (/system/lib/libart.so+0x405a76)
#237 0xac98ca76 (/system/lib/libart.so+0x405a76)
#238 0xac98ca76 (/system/lib/libart.so+0x405a76)
#239 0xac98ca76 (/system/lib/libart.so+0x405a76)
#240 0xac98ca76 (/system/lib/libart.so+0x405a76)
#241 0xac98ca76 (/system/lib/libart.so+0x405a76)
#242 0xac98ca76 (/system/lib/libart.so+0x405a76)
#243 0xac98ca76 (/system/lib/libart.so+0x405a76)
#244 0xac98ca76 (/system/lib/libart.so+0x405a76)
#245 0xac98ca76 (/system/lib/libart.so+0x405a76)
#246 0xac98ca76 (/system/lib/libart.so+0x405a76)
#247 0xac98ca76 (/system/lib/libart.so+0x405a76)
#248 0xac98ca76 (/system/lib/libart.so+0x405a76)
#249 0xac98ca76 (/system/lib/libart.so+0x405a76)
#250 0xac98ca76 (/system/lib/libart.so+0x405a76)
0x81d8f934 is located 4 bytes inside of 16-byte region [0x81d8f930,0x81d8f940)
freed by thread T56 (AudioTrackJavaT) here:
#0 0xb3c8fb58 (/data/app/com.jimi.t28-qMxhyaqcwCivEwMd7OGBLw==/lib/arm/libclang_rt.asan-arm-android.so+0xbeb58)
#1 0x70159606 (/data/app/com.jimi.t28-qMxhyaqcwCivEwMd7OGBLw==/lib/arm/libjingle_peerconnection_so.so+0x682606)
#2 0xfff4c8a6 (<unknown module>)
#3 0x28a6 (<unknown module>)
previously allocated by thread T74 (AudioRecordJava) here:
#0 0xb3c8fee8 (/data/app/com.jimi.t28-qMxhyaqcwCivEwMd7OGBLw==/lib/arm/libclang_rt.asan-arm-android.so+0xbeee8)
#1 0x70a5f54a (/data/app/com.jimi.t28-qMxhyaqcwCivEwMd7OGBLw==/lib/arm/libjingle_peerconnection_so.so+0xf8854a)
#2 0x70cf5bf8 (/data/app/com.jimi.t28-qMxhyaqcwCivEwMd7OGBLw==/lib/arm/libjingle_peerconnection_so.so+0x121ebf8)
#3 0xae65f0f8 (<unknown module>)
Thread T74 (AudioRecordJava) created by T45 (worker_thread -) here:
#0 0xb3c78dc8 (/data/app/com.jimi.t28-qMxhyaqcwCivEwMd7OGBLw==/lib/arm/libclang_rt.asan-arm-android.so+0xa7dc8)
#1 0xac8fba2c (/system/lib/libart.so+0x374a2c)
Thread T45 (worker_thread -) created by T43 (pool-9-thread-1) here:
#0 0xb3c78dc8 (/data/app/com.jimi.t28-qMxhyaqcwCivEwMd7OGBLw==/lib/arm/libclang_rt.asan-arm-android.so+0xa7dc8)
#1 0x70baa018 (/data/app/com.jimi.t28-qMxhyaqcwCivEwMd7OGBLw==/lib/arm/libjingle_peerconnection_so.so+0x10d3018)
Thread T43 (pool-9-thread-1) created by T31 (AsyncServer) here:
#0 0xb3c78dc8 (/data/app/com.jimi.t28-qMxhyaqcwCivEwMd7OGBLw==/lib/arm/libclang_rt.asan-arm-android.so+0xa7dc8)
#1 0xac8fba2c (/system/lib/libart.so+0x374a2c)
Thread T31 (AsyncServer) created by T0 (com.jimi.t28) here:
#0 0xb3c78dc8 (/data/app/com.jimi.t28-qMxhyaqcwCivEwMd7OGBLw==/lib/arm/libclang_rt.asan-arm-android.so+0xa7dc8)
#1 0xac8fba2c (/system/lib/libart.so+0x374a2c)
Thread T56 (AudioTrackJavaT) created by T45 (worker_thread -) here:
#0 0xb3c78dc8 (/data/app/com.jimi.t28-qMxhyaqcwCivEwMd7OGBLw==/lib/arm/libclang_rt.asan-arm-android.so+0xa7dc8)
#1 0xac8fba2c (/system/lib/libart.so+0x374a2c)
SUMMARY: AddressSanitizer: heap-use-after-free (/data/app/com.jimi.t28-qMxhyaqcwCivEwMd7OGBLw==/lib/arm/libjingle_peerconnection_so.so+0x242d7a0)
Shadow bytes around the buggy address:
0xa1041ed0: fa fa 00 04 fa fa 04 fa fa fa 00 00 fa fa 00 04
0xa1041ee0: fa fa 00 04 fa fa 00 fa fa fa 00 fa fa fa fa fa
0xa1041ef0: fa fa 00 04 fa fa 00 fa fa fa 04 fa fa fa fa fa
0xa1041f00: fa fa 04 fa fa fa 00 00 fa fa 04 fa fa fa 04 fa
0xa1041f10: fa fa fd fa fa fa 04 fa fa fa fd fd fa fa 04 fa
=>0xa1041f20: fa fa fd fd fa fa[fd]fd fa fa fd fd fa fa fd fd
0xa1041f30: fa fa fd fd fa fa fd fa fa fa fd fd fa fa fa fa
0xa1041f40: fa fa fd fd fa fa fd fd fa fa fd fd fa fa fd fa
0xa1041f50: fa fa 00 04 fa fa 00 00 fa fa 00 04 fa fa fd fd
0xa1041f60: fa fa 04 fa fa fa fd fa fa fa fd fd fa fa fd fd
0xa1041f70: fa fa fd fa fa fa 04 fa fa fa fd fd fa fa fd fd
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==32743==ABORTING
從上述日志可以看書,崩潰的原因是在AudioRecordJava
線程非法寫入了一片已經(jīng)不存在的內(nèi)存沛善,這片內(nèi)存總共16個字節(jié)長锭魔,已經(jīng)被AudioTrackJavaT
線程釋放,這片內(nèi)存最開始在AudioRecordJava
線程創(chuàng)建路呜。
根據(jù)16進制的偏移量迷捧,使用addr2line可以定位到相關(guān)代碼。
六胀葱、總結(jié)
本次調(diào)試其實最終還是未找到bug漠秋,不過我相信這次總結(jié)后面應(yīng)該還能用到。
參考文章:
https://developer.android.com/ndk/guides/wrap-script
https://stackoverflow.com/questions/48870291/android-studio-address-sanitizer-using-build-gradle
https://developer.android.google.cn/ndk/guides/asan
https://www.linuxidc.com/Linux/2018-09/154273.htm
http://www.reibang.com/p/3a2df9b7c353