三星设备上android.media.AudioRecord.read崩溃问题排查与解决咨询
三星设备AudioRecord崩溃原因分析与解决办法
据Google Play反馈,以下崩溃仅出现在三星设备上:
[libc.so] abort SIGABRT backtrace: #00 pc 0x00000000000537d4 /apex/com.android.runtime/lib64/bionic/libc.so (abort+168) #01 pc 0x00000000006f365c /apex/com.android.art/lib64/libart.so (art::Runtime::Abort(char const*)+596) #02 pc 0x0000000000016ea8 /apex/com.android.art/lib64/libbase.so (android::base::SetAborter(std::__1::function<void (char const*)>&&)::$_3::__invoke(char const*)+80) #03 pc 0x0000000000006f60 /system/lib64/liblog.so (__android_log_assert+312) #04 pc 0x00000000000b20bc /system/lib64/libaudioclient.so (android::ClientProxy::releaseBuffer(android::Proxy::Buffer*)+240) #05 pc 0x00000000000654c0 /system/lib64/libaudioclient.so (android::AudioRecord::releaseBuffer(android::AudioRecord::Buffer const*)+168) #06 pc 0x0000000000068484 /system/lib64/libaudioclient.so (android::AudioRecord::read(void*, unsigned long, bool)+388) #07 pc 0x0000000000188ca0 /system/lib64/libandroid_runtime.so (int android_media_AudioRecord_readInArray<_jshortArray*>(_JNIEnv*, _jobject*, _jshortArray*, int, int, unsigned char)+232) #08 pc 0x00000000002ee1c0 /data/misc/apexdata/com.android.art/dalvik-cache/arm64/boot.oat (art_jni_trampoline+128) #09 pc 0x00000000020009f0 /memfd:jit-cache (android.media.AudioRecord.read+240)
用户提供的相关代码(在其他设备上运行正常,应用已有数百万下载量):
AudioRecord ar = new AudioRecord(MediaRecorder.AudioSource.MIC, iAudioSampleRate, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, N * 10); ... _ar.startRecording(); ... if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { iReadCount = _ar.read(buffer, 0, buffer.length, AudioRecord.READ_NON_BLOCKING); } else { iReadCount = _ar.read(buffer, 0, buffer.length); }
可能的崩溃原因
- 三星定制音频服务的严格校验:崩溃栈显示在
releaseBuffer阶段触发断言失败,说明三星对AudioFlinger的定制实现中,对缓冲区状态的校验比原生Android更严格。比如调用read时缓冲区未就绪、已被释放或状态异常,直接触发断言导致崩溃。 - 非阻塞读的时序竞态:Android M及以上使用的
READ_NON_BLOCKING模式,在三星设备上可能存在时序问题。比如startRecording后,AudioRecord尚未完全进入就绪状态就执行read,导致底层缓冲区操作异常。 - 缓冲区大小不兼容:初始化时使用固定值
N*10作为缓冲区大小,可能不符合三星设备音频硬件的要求(比如不是硬件帧大小的整数倍),导致后续读写时缓冲区状态混乱。 - 生命周期管理疏漏:存在重复调用
startRecording/stop,或者read操作时AudioRecord已被意外释放,导致Native层操作无效对象。
潜在解决办法
- 增加就绪状态校验:调用
read前,先通过getRecordingState()确认AudioRecord处于RECORDSTATE_RECORDING状态,避免在未就绪时执行读写操作。 - 使用硬件兼容的缓冲区大小:用
AudioRecord.getMinBufferSize()获取当前设备的最小缓冲区大小,以此为基准设置缓冲区(比如取其2倍或整数倍),替代固定值N*10。示例:int minBufferSize = AudioRecord.getMinBufferSize(iAudioSampleRate, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT); int bufferSize = minBufferSize * 2; // 保证缓冲区足够且符合硬件要求 AudioRecord ar = new AudioRecord(MediaRecorder.AudioSource.MIC, iAudioSampleRate, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSize); - 优化读写模式:尝试在所有版本中统一使用阻塞读模式,或者针对三星设备单独禁用
READ_NON_BLOCKING,验证是否是非阻塞模式导致的兼容性问题。 - 强化生命周期管理:确保
startRecording仅调用一次,read操作前AudioRecord未被release,使用完毕后正确调用stop()和release()释放资源;若出现异常,尝试重新初始化AudioRecord而非直接崩溃。
内容的提问来源于stack exchange,提问作者Hong
相关产品推荐
相关产品推荐

