365bet取款要多久-365bet体育365bet官网-365电子游戏

AudioFlinger音频dump方法

AudioFlinger音频dump方法

一、概述

采用Android TEE方案,支持dump AudioFlinger中各个链路中的音频数据。

支持DUMP的音频数据如下:

"aftee_Date_ThreadId_C_reason.wav" // RecordThread (从hal层取到的数据)

"aftee_Date_ThreadId_M_reason.wav" //MixerThread (NormalMixer后的数据)

"aftee_Date_ThreadId_F_reason.wav" // MixerThread (FastMixer后的数据)

"aftee_Date_ThreadId_TrackId_R_reason.wav" // RecordTrack(送给AudioRecord的数据)

"aftee_Date_ThreadId_TrackId_TrackName_T_reason.wav" // PlaybackTrack (AudioTrack写下来的数据)

二、准备工作

2.1 编译时设置

修改frameworks/av/services/audioflinger/Configuration.h,对 #define TEE_SINK 取消注释重新编译 libaudioflinger.so将 64与32位的 libaudioflinger.so 推送或同步到设备的 /system/lib

Android 9 也要编译 audioserver 推进车机

2.2 运行时设置

开启debug开关

getprop | grep ro.debuggable

确认输出是:[ro.debuggable]: [1]

创建文件目录

ls -ld /data/misc/audioserver,

确认输出是:drwx------ audioserver audioserver ... audioserver

如果目录不存在,请按如下方式创建:

mkdir /data/misc/audioserver

chown audioserver:audioserver/data/misc/audioserver

修改配置文件

echo af.tee=# > /data/local.prop

af.tee 的值是一个 0 到 7 之间的数字,表示几个位的总和(每个功能一个位)

1 = 输入

2 = FastMixer 输出

4 = 各音轨的 AudioRecord 和 AudioTrack

chmod 644 /data/local.prop

重启系统三.测试和获取数据

播放音频dumpsys media.audio_flinger在 dumpsys 输出中查找如下行:

tee copied to /data/misc/audioserver/20131010101147_2.wav

这是一个 PCM .wav 文件

adb pull /data/misc/audioserver/*.wav 文件四、截取位置代码分析

T 及 R 录音文件的截取位置:

// frameworks/av/services/audioflinger/Tracks.cpp

// AudioBufferProvider interface

// getNextBuffer() = 0;

// This implementation of releaseBuffer() is used by Track and RecordTrack

void AudioFlinger::ThreadBase::TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)

{

#ifdef TEE_SINK

mTee.write(buffer->raw, buffer->frameCount);

#endif

F录音文件的截取位置:

//frameworks/av/services/audioflinger/FastMixer.cpp

void FastMixer::onWork()

{

...

// if non-NULL, then duplicate write() to this non-blocking sink

#ifdef TEE_SINK

mTee.write(buffer, frameCount);

#endif

// FIXME write() is non-blocking and lock-free for a properly implemented NBAIO sink,

// but this code should be modified to handle both non-blocking and blocking sinks

dumpState->mWriteSequence++;

ATRACE_BEGIN("write");

ssize_t framesWritten = mOutputSink->write(buffer, frameCount);

ATRACE_END();

...

}

M录音文件的截取位置:

// frameworks/av/services/audioflinger/Threads.cpp

// shared by MIXER and DIRECT, overridden by DUPLICATING

ssize_t AudioFlinger::PlaybackThread::threadLoop_write()

{

LOG_HIST_TS();

mInWrite = true;

ssize_t bytesWritten;

const size_t offset = mCurrentWriteLength - mBytesRemaining;

// If an NBAIO sink is present, use it to write the normal mixer's submix

if (mNormalSink != 0) {

const size_t count = mBytesRemaining / mFrameSize;

ATRACE_BEGIN("write");

// update the setpoint when AudioFlinger::mScreenState changes

uint32_t screenState = AudioFlinger::mScreenState;

if (screenState != mScreenState) {

mScreenState = screenState;

MonoPipe *pipe = (MonoPipe *)mPipeSink.get();

if (pipe != NULL) {

pipe->setAvgFrames((mScreenState & 1) ?

(pipe->maxFrames() * 7) / 8 : mNormalFrameCount * 2);

}

}

ssize_t framesWritten = mNormalSink->write((char *)mSinkBuffer + offset, count);

ATRACE_END();

if (framesWritten > 0) {

bytesWritten = framesWritten * mFrameSize;

#ifdef TEE_SINK

mTee.write((char *)mSinkBuffer + offset, framesWritten);

#endif

} else {

bytesWritten = framesWritten;

}