欢迎光临
我们一直在努力

第 15 章:音频系统

Android 音频栈是 AOSP 中对性能要求最高的子系统之一。它必须将音频采样数据从 Java 应用程序一直输送到硬件 DAC,同时具备确定的延迟;还要同时支持音效处理、策略驱动的路由、带头部追踪的空间音频,以及面向专业级录音的低延迟 MMAP 通路。本章沿着 AOSP 树中的实际源码文件,逐层梳理整个音频栈,从 Java 层AudioTrackAPI 一直向下追踪到 Audio HAL 硬件接口。

音频核心服务位于frameworks/av/目录下,仅AudioFlinger就包含约 5 万行 C++ 代码;音频策略引擎、AAudio/Oboe 服务、音效库、头部追踪流水线还另有 3 万行代码。我们将阅读关键数据结构,逐行解析混音线程循环,并讲解每一处优化 —— 从运行在SCHED_FIFO优先级 3 级的 FastMixer,到完全绕过 AudioFlinger 的 MMAP 零拷贝通路。

15.1 音频架构概述 

15.1.1 整体视图 

Android 音频系统是一套分层流水线。音频数据经过多次进程边界传递,从应用代码流转至硬件:

应用层(Java / NDK)
|
v
AudioTrack / AAudio (客户端库,运行在应用进程)
| Binder IPC
v
AudioFlinger (audioserver进程 —— 混音、音效处理)
| HAL接口
v
Audio HAL (厂商进程,或通过HIDL/AIDL运行于同进程)
|
v
硬件(编解码器 / DSP / DAC)

AudioPolicyService与AudioFlinger共同运行在audioserver进程内。它不处理音频数据,只负责路由决策:选择输出设备、确定要施加的音效、音量处理逻辑。

15.1.2 进程与服务 

audioserver进程托管三大核心服务:

服务
Binder 接口
源码位置
AudioFlinger IAudioFlinger frameworks/av/services/audioflinger/AudioFlinger.cpp(5288 行)
AudioPolicyService IAudioPolicyService frameworks/av/services/audiopolicy/service/AudioPolicyService.cpp(2759 行)
AAudioService IAAudioService frameworks/av/services/oboeservice/AAudioService.cpp(527 行)

AudioFlinger 优先完成注册:

// AudioFlinger.cpp,第303‑308行
void AudioFlinger::instantiate() {
sp<IServiceManager> sm(defaultServiceManager());
sm->addService(String16(IAudioFlinger::DEFAULT_SERVICE_NAME),
new AudioFlingerServerAdapter(new AudioFlinger()), false,
IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT);
}

15.1.3 信号流向图 

15.1.4 数据通路与控制通路 

音频系统存在两条完全独立的通路:

数据通路 —— 实际 PCM 采样数据。普通混音通路的数据流向:

  • 应用向共享内存环形缓冲区(“cblk” 控制块)写入数据。
  • AudioFlinger 的MixerThread读取所有处于激活状态的 Track,执行混音。
  • 将混音结果写入 HAL 输出流。
  • 控制通路 —— 路由决策、音量变更、设备连接事件:

  • 应用调用 Java 层AudioManager。
  • AudioPolicyService通过 Binder 接收请求。
  • AudioPolicyManager完成路由决策。
  • 指令下发至 AudioFlinger,创建 / 修改线程与音频通路。
  • 15.1.5 共享内存架构 

    客户端与服务端之间所有音频数据传输均使用共享内存,不使用 Binder 事务。核心结构体audio_track_cblk_t定义位置:

    frameworks/av/include/private/media/AudioTrackShared.h

    该控制块包含:

    • 读位置(服务端)、写位置(客户端)
    • 欠载 / 过载检测标志位
    • 音量与静音状态
    • 基于 futex 的低延迟唤醒信号机制

    实际音频缓冲区存放在另一块独立共享内存区域,同时映射至客户端、服务端地址空间。进程间音频数据传输完全消除数据拷贝。

    15.1.6 audioserver 进程 

    audioserver二进制程序是托管全部音频服务的原生守护进程,由 init 在开机早期启动:

    # audioserver.rc(简化版)
    service audioserver /system/bin/audioserver
    class core
    user audioserver
    group audio camera drmrpc media mediadrm net_bt net_bt_admin
    capabilities BLOCK_SUSPEND SYS_NICE
    ioprio rt 4
    task_profiles ProcessCapacityHigh HighPerformance
    onrestart restart vendor.audio‑hal

    audioserver 进程关键特性:

    • 以audioserver用户运行,具备 audio 用户组权限。
    • 拥有BLOCK_SUSPEND能力,播放期间可阻止设备休眠。
    • 拥有SYS_NICE能力,用于设置实时线程优先级。
    • I/O 优先级设置为实时 rt 4。
    • 应用ProcessCapacityHigh与HighPerformance任务配置,做 CPU 调度优化。
    • 重启 audioserver 的同时会重启厂商音频 HAL。

    进程内部结构

    15.1.7 线程类型总览 

    AudioFlinger 会根据输出设备创建不同类型线程:

    线程类型
    类名
    用途
    源码位置
    Mixer MixerThread 多路 PCM 音轨混音 Threads.cpp 约 3700 行起
    Direct DirectOutputThread 单路 PCM 或压缩音轨 Threads.cpp
    Offload OffloadThread 硬件压缩播放 Threads.cpp
    Duplicating DuplicatingThread 输出镜像至多个输出设备 Threads.cpp
    Record RecordThread 音频输入采集 Threads.cpp
    Mmap MmapPlaybackThread / MmapCaptureThread MMAP 零拷贝通路 Threads.cpp
    Spatializer SpatializerThread 空间音频混音 Threads.cpp

    每一类线程绑定一个 HAL 输入 / 输出流,运行在高优先级实时线程。

    15.1.8 音频格式支持 

    Android 支持丰富的音频格式:

    分类
    格式
    PCM 16‑bit、24‑bit packed、32‑bit、8.24 定点、float 浮点
    有损压缩 MP3、AAC、AAC‑LC、HE‑AAC、Vorbis、Opus
    无损压缩 FLAC、ALAC
    空间音频 Dolby Atmos、DTS:X(透传 passthrough)
    语音 AMR‑NB、AMR‑WB、EVS

    PCM 格式流经混音器与音效链路。压缩格式可通过MediaCodec软件解码后送入 AudioTrack,也可直接下发至 HAL 做硬件解码(offload 通路)。

    15.2 AudioFlinger

    AudioFlinger 是 Android 音频的核心混音引擎,是音频栈中复杂度最高的组件。核心实现分布在 6 个源码文件,总代码量超 27000 行:

    文件
    行数
    用途
    AudioFlinger.cpp 5288 服务入口、Binder 接口实现
    Threads.cpp 12053 全部线程循环逻辑实现
    Tracks.cpp 4057 Track 对象(播放、录音、mmap)
    Effects.cpp 3898 音效链路管理
    PatchPanel.cpp 1085 音频路由通路管理
    fastpath/FastMixer.cpp 517 低延迟 fast mixer 通路

    前 5 个文件位于frameworks/av/services/audioflinger/。fastpath 相关代码独立存放于fastpath/子目录(包含 FastMixer.cpp、FastCapture.cpp、FastThread.cpp、StateQueue.cpp 以及 dump/state 辅助文件);audioflinger 目录下还包含afutils/、datapath/、sounddose/、timing/子目录,分别存放工具函数、HAL 流、声音剂量、帧计数相关辅助代码。线程类声明在Threads.h(2573 行),实现在Threads.cpp。

    15.2.1 AudioFlinger 初始化 

    AudioFlinger 构造函数逻辑十分简洁,繁重初始化工作在onFirstRef()中执行:

    // AudioFlinger.cpp,第310‑341行
    AudioFlinger::AudioFlinger()
    {
    // 随时间推移,移动音频会话唯一ID生成器起始基准值
    // 降低audioserver重启后ID重复生成的风险
    timespec ts{};
    clock_gettime(CLOCK_MONOTONIC, &ts);
    uint32_t movingBase = (uint32_t)std::max((long)1, ts.tv_sec);
    for (unsigned use = AUDIO_UNIQUE_ID_USE_UNSPECIFIED;
    use < AUDIO_UNIQUE_ID_USE_MAX; use++) {
    mNextUniqueIds[use] =
    ((use == AUDIO_UNIQUE_ID_USE_SESSION
    || use == AUDIO_UNIQUE_ID_USE_CLIENT) ?
    movingBase : 1) * AUDIO_UNIQUE_ID_USE_MAX;
    }
    BatteryNotifier::getInstance().noteResetAudio();
    }

    会话 ID 生成器基于单调时间偏移,避免 audioserver 重启后 ID 冲突。这一点至关重要:客户端重连时会复用之前分配的会话 ID。

    onFirstRef()内部,基于工厂模式完成设备发现:

    // AudioFlinger.cpp,第342‑363行
    void AudioFlinger::onFirstRef()
    {
    audio_utils::lock_guard _l(mutex());
    mMode = AUDIO_MODE_NORMAL;
    mDeviceEffectManager = sp<DeviceEffectManager>::make(
    sp<IAfDeviceEffectManagerCallback>::fromExisting(this)),
    mDevicesFactoryHalCallback = new DevicesFactoryHalCallbackImpl;
    mDevicesFactoryHal->setCallbackOnce(mDevicesFactoryHalCallback);
    // …
    mPatchPanel = IAfPatchPanel::create(
    sp<IAfPatchPanelCallback>::fromExisting(this));
    mMelReporter = sp<MelReporter>::make(
    sp<IAfMelReporterCallback>::fromExisting(this),
    mPatchPanel);
    }

    15.2.2 类继承关系 

    AudioFlinger 通过菱形继承模式实现多个回调接口:

    // AudioFlinger.h,第60‑67行
    class AudioFlinger
    : public AudioFlingerServerAdapter::Delegate // IAudioFlinger客户端接口
    , public IAfClientCallback
    , public IAfDeviceEffectManagerCallback
    , public IAfMelReporterCallback
    , public IAfPatchPanelCallback
    , public IAfThreadCallback
    {

    15.2.3 Binder 接口 

    AudioFlinger 对外暴露超过 50 个方法的 Binder 接口。完整方法列表以宏的形式定义在 AudioFlinger.cpp:

    // AudioFlinger.cpp,第173‑244行
    #define IAUDIOFLINGER_BINDER_METHOD_MACRO_LIST \\
    BINDER_METHOD_ENTRY(createTrack) \\
    BINDER_METHOD_ENTRY(createRecord) \\
    BINDER_METHOD_ENTRY(sampleRate) \\
    BINDER_METHOD_ENTRY(format) \\
    BINDER_METHOD_ENTRY(frameCount) \\
    BINDER_METHOD_ENTRY(latency) \\
    BINDER_METHOD_ENTRY(setMasterVolume) \\
    BINDER_METHOD_ENTRY(setMasterMute) \\
    // … 40+个其余条目
    BINDER_METHOD_ENTRY(getSoundDoseInterface) \\
    BINDER_METHOD_ENTRY(getAudioPolicyConfig) \\
    BINDER_METHOD_ENTRY(getAudioMixPort) \\
    BINDER_METHOD_ENTRY(resetReferencesForTest) \\

    每一个 Binder 方法都会通过MethodStatistics基础设施做统计与性能采集。

    15.2.4 Track 创建流程 

    应用执行new AudioTrack()时,会调用 Binder 的createTrack方法。关键参数(AudioFlinger.h 第 82‑83 行):

    status_t createTrack(const media::CreateTrackRequest& input,
    media::CreateTrackResponse& output) final EXCLUDES_AudioFlinger_Mutex;

    请求参数包含音频属性(usage、content type)、格式、采样率、通道掩码、帧计数、标志位。AudioFlinger 执行逻辑:

  • 校验调用来源(AudioFlinger.cpp 第 126‑157 行)。
  • 向 AudioPolicyService 查询正确输出句柄。
  • 查找或创建对应的播放线程。
  • 为 Track 音频缓冲区分配共享内存。
  • 创建 Track 对象并挂载到线程。
  • 15.2.5 硬件模块加载 

    AudioFlinger 使用工厂模式加载 HAL 模块。已知模块 ID:

    // AudioFlinger.cpp,第684‑688行
    static const char * const audio_interfaces[] = {
    AUDIO_HARDWARE_MODULE_ID_PRIMARY,
    AUDIO_HARDWARE_MODULE_ID_A2DP,
    AUDIO_HARDWARE_MODULE_ID_USB,
    };

    findSuitableHwDev_l()(第 690 行)遍历已加载 HAL 模块,筛选支持目标设备类型的硬件模块。

    15.2.6 MixerThread 循环 

    混音工作发生在MixerThread。Threads.cpp中的threadLoop()是 Android 音频的核心心脏。循环逻辑结构:

    Threads.cpp 中关键时间常量:

    // Threads.cpp,第132‑134行
    static const int8_t kMaxTrackRetries = 50;
    static const int8_t kMaxTrackStartupRetries = 50;

    // Threads.cpp,第154行
    static const int32_t kMaxTrackRetriesDirectMs = 200;

    // Threads.cpp,第169行
    static const uint32_t kMinThreadSleepTimeUs = 5000;

    // Threads.cpp,第175‑177行
    static const uint32_t kMinNormalSinkBufferSizeMs = 20;
    static const uint32_t kMaxNormalSinkBufferSizeMs = 24;

    混音循环周期约 20ms。每个周期执行:

  • prepareTracks_l():评估全部 Track,筛选激活 Track,为每个激活 Track 配置 AudioMixer(采样率、音量、格式)。
  • threadLoop_mix():调用AudioMixer::process()读取所有激活 Track 缓冲区,混音写入mMixerBuffer。
  • processEffects_l():对混音完成的音频执行音效链路处理。
  • threadLoop_write():将最终缓冲区写入 HAL。
  • 15.2.7 threadLoop_write () 方法 

    写通路存在两个分支(Threads.cpp 第 3557‑3616 行):

    // Threads.cpp,第3557‑3626行
    ssize_t PlaybackThread::threadLoop_write()
    {
    LOG_HIST_TS();
    mInWrite = true;
    ssize_t bytesWritten;
    const size_t offset = mCurrentWriteLength – mBytesRemaining;

    // 如果存在NBAIO sink,使用它写入普通混音器的子混音数据
    if (mNormalSink != 0) {
    const size_t count = mBytesRemaining / mFrameSize;
    ATRACE_BEGIN(\”write\”);
    // AudioFlinger::mScreenState变化时更新setpoint
    const uint32_t screenState = mAfThreadCallback->getScreenState();
    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();
    // …
    } else {
    // direct输出与offload线程
    ATRACE_BEGIN(\”write\”);
    bytesWritten = mOutput->write(
    (char *)mSinkBuffer + offset, mBytesRemaining);
    ATRACE_END();
    }
    // …
    }

    对于 MixerThread,写操作经过 NBAIO(非阻塞音频 I/O)MonoPipe转发至 FastMixer。Direct 与 Offload 线程直接写入 HAL 流。

    屏幕状态优化逻辑值得关注:屏幕点亮时,管道平均帧阈值提升至最大值的 7/8,降低 UI 活跃时音频欠载概率;屏幕熄灭时,阈值降为普通帧数量的 2 倍,节省功耗。

    15.2.8 待机管理 

    线程等待可配置时长(默认 3 秒)后进入待机状态:

    // Threads.cpp,第252‑262行
    static const nsecs_t kDefaultStandbyTimeInNsecs = seconds(3);

    static nsecs_t getStandbyTimeInNanos() {
    static nsecs_t standbyTimeInNanos = []() {
    const int ms = property_get_int32(
    \”ro.audio.flinger_standbytime_ms\”,
    kDefaultStandbyTimeInNsecs / NANOS_PER_MILLISECOND);
    ALOGI(\”%s: Using %d ms as standby time\”, __func__, ms);
    return milliseconds(ms);
    }();
    return standbyTimeInNanos;
    }

    待机状态下,线程释放 HAL 流,释放唤醒锁,显著降低功耗。offload 输出的待机延迟更短:

    // Threads.cpp,第184行
    static const nsecs_t kOffloadStandbyDelayNs = seconds(1);

    15.2.9 Tracks

    Track 对象代表线程内部独立音频流。基类TrackBase定义在 Tracks.cpp:

    // Tracks.cpp,第89‑138行
    TrackBase::TrackBase(
    IAfThreadBase *thread,
    const sp<Client>& client,
    const audio_attributes_t& attr,
    uint32_t sampleRate,
    audio_format_t format,
    audio_channel_mask_t channelMask,
    size_t frameCount,
    void *buffer,
    size_t bufferSize,
    audio_session_t sessionId,
    pid_t creatorPid,
    uid_t clientUid,
    bool isOut,
    const alloc_type alloc,
    track_type type,
    audio_port_handle_t portId,
    std::string metricsId)
    : mThread(thread),
    mAllocType(alloc),
    mClient(client),
    mCblk(NULL),
    mState(IDLE),
    mAttr(attr),
    mSampleRate(sampleRate),
    mFormat(format),
    mChannelMask(channelMask),
    mChannelCount(isOut ?
    audio_channel_count_from_out_mask(channelMask) :
    audio_channel_count_from_in_mask(channelMask)),
    mFrameSize(audio_bytes_per_frame(mChannelCount, format)),
    mFrameCount(frameCount),
    mSessionId(sessionId),
    // …

    每个 Track 拥有原子生成的唯一 ID:

    // Tracks.cpp,第86行
    static volatile int32_t nextTrackId = 55;

    Track 继承层级:

    15.2.10 FastMixer —— 低延迟通路 

    FastMixer 是独立高优先级线程,对延迟敏感的音轨可以绕过普通混音循环。定义位置:

    frameworks/av/services/audioflinger/fastpath/FastMixer.cpp(517 行)

    FastMixer 严格的设计约束(源码头部注释):

    // FastMixer.cpp,第17‑21行
    // <IMPORTANT_WARNING>
    // threadLoop()的设计约束见StateQueue.h中“Fast mixer thread”章节注释。
    // 特别注意:仅可在明确允许的位置调用库与系统调用。
    // </IMPORTANT_WARNING>

    FastMixer 支持 4 种工作策略:

    // Threads.cpp,第202‑216行
    static const enum {
    FastMixer_Never, // 绝不初始化、绝不使用,仅用于调试
    FastMixer_Always, // 始终初始化并启用,即使没有需求
    FastMixer_Static, // 需要时初始化,之后持续运行
    FastMixer_Dynamic, // 需要时初始化,动态启停
    } kUseFastMixer = FastMixer_Static;

    默认策略FastMixer_Static:一旦初始化完成,FastMixer 持续运行。优先级配置:

    // Threads.cpp,第226‑228行
    static const int kPriorityAudioApp = 2;
    static const int kPriorityFastMixer = 3;
    static const int kPriorityFastCapture = 3;

    Fast track 乘数控制共享缓冲区大小:

    // Threads.cpp,第237‑244行
    static const int kFastTrackMultiplier = 2;
    static const int kFastTrackMultiplierMin = 1;
    static const int kFastTrackMultiplierMax = 2;
    static int sFastTrackMultiplier = kFastTrackMultiplier;

    FastMixer 线程循环 

    FastMixer 的onWork()(328 行)是紧凑内层循环:

    // FastMixer.cpp,第328‑333行
    void FastMixer::onWork()
    {
    const FastMixerState * const current =
    (const FastMixerState *) mCurrent;
    FastMixerDumpState * const dumpState =
    (FastMixerDumpState *) mDumpState;

    处理三类命令:

    • MIX —— 将音轨混音写入混音缓冲区
    • WRITE —— 将缓冲区写入输出 sink
    • MIX_WRITE —— 同时执行混音与写操作

    输出配置变更时,FastMixer 重新配置:

    // FastMixer.cpp,第245‑270行
    if (frameCount > 0 && mSampleRate > 0) {
    mMixer = new AudioMixer(frameCount, mSampleRate);
    // …
    mPeriodNs = (frameCount * 1000000000LL) / mSampleRate; // 1.00
    mUnderrunNs = (frameCount * 1750000000LL) / mSampleRate; // 1.75
    mOverrunNs = (frameCount * 500000000LL) / mSampleRate; // 0.50
    mForceNs = (frameCount * 950000000LL) / mSampleRate; // 0.95
    mWarmupNsMin = (frameCount * 750000000LL) / mSampleRate; // 0.75
    mWarmupNsMax = (frameCount * 1250000000LL) / mSampleRate; // 1.25
    }

    以上时间阈值定义判定标准:周期 1.75 倍判定欠载,0.5 倍判定过载。

    FastMixer 内 Track 更新 

    单条音轨更新在updateMixerTrack()完成:

    // FastMixer.cpp,第123‑191行
    void FastMixer::updateMixerTrack(int index, Reason reason) {
    // …
    switch (reason) {
    case REASON_REMOVE:
    mMixer->destroy(index);
    break;
    case REASON_ADD: {
    const status_t status = mMixer->create(
    index, fastTrack->mChannelMask,
    fastTrack->mFormat, AUDIO_SESSION_OUTPUT_MIX);
    // …
    }
    [[fallthrough]];
    case REASON_MODIFY:
    mMixer->setBufferProvider(index, fastTrack->mBufferProvider);
    // 设置音量、重采样、格式、通道掩码、触觉反馈参数
    mMixer->enable(index);
    break;
    }
    }

    音量从 Track 的VolumeProvider获取:

    // FastMixer.cpp,第155‑161行
    float vlf, vrf;
    if (fastTrack->mVolumeProvider != nullptr) {
    const gain_minifloat_packed_t vlr =
    fastTrack->mVolumeProvider->getVolumeLR();
    vlf = float_from_gain(gain_minifloat_unpack_left(vlr));
    vrf = float_from_gain(gain_minifloat_unpack_right(vlr));
    } else {
    vlf = vrf = AudioMixer::UNITY_GAIN_FLOAT;
    }

    15.2.11 PatchPanel —— 音频路由 

    PatchPanel 管理源端与接收端之间的音频路由通路:

    frameworks/av/services/audioflinger/PatchPanel.cpp(1085 行)

    一条 patch 连接多个音频端口;可以是硬件直通(设备‑设备)、设备‑混音器、混音器‑设备。创建逻辑处理多种场景:

    // PatchPanel.cpp,第112‑135行
    status_t PatchPanel::createAudioPatch_l(
    const struct audio_patch* patch,
    audio_patch_handle_t *handle,
    bool endpointPatch)
    {
    // …
    if (!audio_patch_is_valid(patch) ||
    (patch->num_sinks == 0 && patch->num_sources != 2)) {
    return BAD_VALUE;
    }
    // 当前限制源端数量最大为1;跨硬件模块特殊场景允许2个源端
    if (patch->num_sources > 2) {
    return INVALID_OPERATION;
    }

    源端数量等于 2 的特殊场景用于跨 HAL 模块路由,音频需要在两套不同 HAL 模块之间转发(例如主音频设备转发至 USB 音频)。

    15.2.12 扩展声道与精度 

    MixerThread 支持立体声之外的扩展声道配置:

    // Threads.cpp,第267行
    constexpr bool kEnableExtendedChannels = true;

    同时支持扩展精度格式:

    // Threads.cpp,第301行
    constexpr bool kEnableExtendedPrecision = true;

    合法 PCM 输出 sink 格式(305‑317 行):

    bool IAfThreadBase::isValidPcmSinkFormat(audio_format_t format) {
    switch (format) {
    case AUDIO_FORMAT_PCM_16_BIT:
    return true;
    case AUDIO_FORMAT_PCM_FLOAT:
    case AUDIO_FORMAT_PCM_24_BIT_PACKED:
    case AUDIO_FORMAT_PCM_32_BIT:
    case AUDIO_FORMAT_PCM_8_24_BIT:
    return kEnableExtendedPrecision;
    default:
    return false;
    }
    }

    15.2.13 createTrack () 深度解析 

    完整createTrack()实现(AudioFlinger.cpp 第 1038 行)展示完整 Track 创建流水线:

    // AudioFlinger.cpp,第1038‑1075行
    status_t AudioFlinger::createTrack(
    const media::CreateTrackRequest& _input,
    media::CreateTrackResponse& _output)
    {
    ATRACE_CALL();
    CreateTrackInput input =
    VALUE_OR_RETURN_STATUS(CreateTrackInput::fromAidl(_input));
    CreateTrackOutput output;

    sp<IAfTrack> track;
    sp<Client> client;
    status_t lStatus;
    audio_stream_type_t streamType;
    audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE;
    std::vector<audio_io_handle_t> secondaryOutputs;
    bool isSpatialized = false;
    bool isBitPerfect = false;

    audio_io_handle_t effectThreadId = AUDIO_IO_HANDLE_NONE;
    std::vector<int> effectIds;
    audio_attributes_t localAttr = input.attr;

    该方法校验调用来源;需要时分配会话 ID;向 AudioPolicyService 查询正确输出:

    // AudioFlinger.cpp,第1069‑1091行
    sessionId = input.sessionId;
    if (sessionId == AUDIO_SESSION_ALLOCATE) {
    sessionId = (audio_session_t)
    newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
    }

    lStatus = AudioSystem::getOutputForAttr(
    &localAttr, &output.outputId, sessionId,
    &streamType, adjAttributionSource,
    &input.config, input.flags,
    &selectedDeviceIds, &portId, &secondaryOutputs,
    &isSpatialized, &isBitPerfect);

    获取输出之后,校验格式、通道掩码,定位播放线程,注册客户端,处理音效链路迁移:

    // AudioFlinger.cpp,第1114‑1157行
    {
    audio_utils::lock_guard _l(mutex());
    IAfPlaybackThread* thread =
    checkPlaybackThread_l(output.outputId);
    client = registerClient(
    adjAttributionSource.pid,
    adjAttributionSource.uid);

    // 检查是否存在同session ID的音效链路运行在其他输出线程,需要迁移至此
    for (const auto& [outputId, t] : mPlaybackThreads) {
    if (outputId != output.outputId) {
    uint32_t sessions =
    t->hasAudioSession(sessionId);
    if (sessions & IAfThreadBase::EFFECT_SESSION) {
    effectThread = t.get();
    break;
    }
    }
    }

    track = thread->createTrack_l(client, streamType,
    localAttr, &output.sampleRate,
    input.config.format,
    input.config.channel_mask,
    &output.frameCount,
    &output.notificationFrameCount,
    input.notificationsPerBuffer, input.speed,
    input.sharedBuffer, sessionId,
    &output.flags, callingPid,
    adjAttributionSource,
    input.clientInfo.clientTid,
    &lStatus, portId,
    input.audioTrackCallback,
    isSpatialized, isBitPerfect,
    &output.afTrackFlags);

    输出结构体记录线程实际配置关键信息:

    // AudioFlinger.cpp,第1161‑1167行
    output.afFrameCount = thread->frameCount();
    output.afSampleRate = thread->sampleRate();
    output.afChannelMask =
    static_cast<audio_channel_mask_t>(
    thread->channelMask() |
    thread->hapticChannelMask());
    output.afFormat = thread->format();
    output.afLatencyMs = thread->latency();
    output.portId = portId;

    15.2.14 dump () 调试输出系统 

    AudioFlinger 的 dump 系统功能完备,支持选择性调试:

    // AudioFlinger.cpp,第838‑849行
    static void dump_printHelp(int fd) {
    constexpr static auto helpStr =
    \”AudioFlinger dumpsys help options\\n\”
    \” -h/–help: Print this help text\\n\”
    \” –hal: Include dump of audio hal\\n\”
    \” –stats: Include call/lock/watchdog stats\\n\”
    \” –effects: Include effect definitions\\n\”
    \” –memory: Include memory dump\\n\”
    \” -a/–all: Print all except –memory\\n\”sv;
    write(fd, helpStr.data(), helpStr.length());
    }

    dump 方法遍历全部线程类型:

    // AudioFlinger.cpp,第930‑952行
    // dump播放线程
    for (const auto& [_, thread] : mPlaybackThreads) {
    thread->dump(fd, args);
    }
    // dump录音线程
    for (const auto& [_, thread] : mRecordThreads) {
    thread->dump(fd, args);
    }
    // dump mmap线程
    for (const auto& [_, thread] : mMmapThreads) {
    thread->dump(fd, args);
    }
    // dump孤立音效链路
    if (mOrphanEffectChains.size() != 0) {
    writeStr(fd, \” Orphan Effect Chains\\n\”);
    for (const auto& [_, effectChain] :
    mOrphanEffectChains) {
    effectChain->dump(fd, args);
    }
    }

    同时输出电源管理、互斥锁统计、内存状态:

    // AudioFlinger.cpp,第974‑979行
    dprintf(fd, \”\\n ## BEGIN power dump\\n\”);
    writeStr(fd, media::psh_utils::AudioPowerManager::
    getAudioPowerManager().toString());

    // AudioFlinger.cpp,第819‑822行
    writeStr(fd, audio_utils::mutex::all_stats_to_string());
    writeStr(fd, audio_utils::mutex::all_threads_to_string());

    15.2.15 线程循环中的音效处理 

    混音线程循环内的音效处理阶段值得重点关注。混音完成后执行音效链路处理:

    // Threads.cpp,第4322‑4348行
    if (mSleepTimeUs == 0 && mType != OFFLOAD) {
    for (size_t i = 0; i < effectChains.size(); i++) {
    effectChains[i]->process_l();
    // 处理音效链路输出的触觉反馈数据
    if (activeHapticSessionId != AUDIO_SESSION_NONE
    && activeHapticSessionId ==
    effectChains[i]->sessionId()) {
    uint32_t hapticSessionChannelCount =
    mEffectBufferValid ?
    audio_channel_count_from_out_mask(
    mMixerChannelMask) :
    mChannelCount;
    const size_t audioBufferSize =
    mNormalFrameCount *
    audio_bytes_per_frame(
    hapticSessionChannelCount,
    AUDIO_FORMAT_PCM_FLOAT);
    memcpy_by_audio_format(
    (uint8_t*)effectChains[i]->outBuffer()
    + audioBufferSize,
    AUDIO_FORMAT_PCM_FLOAT,
    (const uint8_t*)effectChains[i]->inBuffer()
    + audioBufferSize,
    AUDIO_FORMAT_PCM_FLOAT,
    mNormalFrameCount * mHapticChannelCount);
    }
    }
    }

    触觉反馈数据做特殊处理:直接从音效输入缓冲区拷贝至输出缓冲区,跳过后续音效处理。因为触觉通道由HapticGenerator生成,不应该被链路中后续音效修改。

    offload 类型 Track 即使没有音频数据,依然执行音效处理:

    // Threads.cpp,第4350‑4358行
    if (mType == OFFLOAD) {
    for (size_t i = 0; i < effectChains.size(); i++) {
    effectChains[i]->process_l();
    }
    }

    音效处理完成后,将音效缓冲区拷贝至 sink 缓冲区,对 float PCM 做限幅保护,保障 HAL 安全:

    // Threads.cpp,第4398‑4405行
    static constexpr float HAL_FLOAT_SAMPLE_LIMIT = 2.0f;
    memcpy_to_float_from_float_with_clamping(
    static_cast<float*>(mSinkBuffer),
    static_cast<const float*>(effectBuffer),
    framesToCopy,
    HAL_FLOAT_SAMPLE_LIMIT /* absMax */);

    限幅到 ±2.0f,用于保护无法处理 NaN、超大浮点数值的 HAL 实现。

    15.2.16 写操作时间与抖动统计 

    写入 HAL 之后,线程循环统计时间抖动:

    // Threads.cpp,第4436‑4476行
    const int64_t lastIoBeginNs = systemTime();
    ret = threadLo

    赞(0)
    未经允许不得转载:171主机测评 » 第 15 章:音频系统
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址