• Android音频系统


    1 分析思路

    1. Thread如何创建?
      AudioPolicyService是策略的制定者,AudioFlinger是策略的执行者,
      所以: AudioPolicyService根据配置文件使唤AudioFlinger来创建Thread

    2. Thread对应output, output对应哪些设备节点?

    3. AudioTrack和Track的创建过程: AudioTrack对应哪一个Thread, 对应哪一个output?

    4. AudioTrack如何传输数据给Thread?

    5. AudioTrack如何播放、暂停、关闭?

    2 以例子说明几个重要概念

    stream type, strategy, device, output, profile, module : policy

    out flag : 比如对于某个专业APP, 它只从HDMI播放声音, 这时就可以指定out flag为AUDIO_OUTPUT_FLAG_DIRECT,这会导致最终的声音无需混音即直接输出到对应的device

    Android系统里使用hardware module来访问硬件, 比如声卡
    声卡上有喇叭、耳机等等,称为device
    为了便于管理, 把一个设备上具有相同参数的一组device称为output,
    一个module能支持哪些output,一个output能支持哪些device,使用配置文件/system/etc/audio_policy.conf来描述

    app要播放声音, 要指定声音类型: stream type有那么多的类型, 来来来, 先看它属于哪一类(策略): strategy

    根据strategy确定要用什么设备播放: device, 喇叭、耳机还是蓝牙?
    根据device确定output, 进而知道对应的playbackthread,
    把声音数据传给这个thread

    一个stream如何最终选择到一个device,这些stream如何互相影响(一个高优先级的声音会使得其他声音静音),等等等, 统称为policy (政策)

    输出、输入设备:
    https://blog.csdn.net/zzqhost/article/details/7711935

    3 所涉及文件形象讲解

    系统服务APP:

    frameworks/av/media/mediaserver/main_mediaserver.cpp

    AudioFlinger :

    AudioFlinger.cpp
    (frameworks/av/services/audioflinger/AudioFlinger.cpp)

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

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

    audio_hw_hal.cpp (hardware/libhardware_legacy/audio/Audio_hw_hal.cpp)

    AudioHardware.cpp (device/friendly-arm/common/libaudio/AudioHardware.cpp)

    AudioPolicyService:

    AudioPolicyService.cpp (frameworks/av/services/audiopolicy/AudioPolicyService.cpp)

    AudioPolicyClientImpl.cpp (frameworks/av/services/audiopolicy/AudioPolicyClientImpl.cpp)

    AudioPolicyInterfaceImpl.cpp(frameworks/av/services/audiopolicy/AudioPolicyInterfaceImpl.cpp)

    AudioPolicyManager.cpp (device/friendly-arm/common/libaudio/AudioPolicyManager.cpp)

    AudioPolicyManager.h (device/friendly-arm/common/libaudio/AudioPolicyManager.h)

    AudioPolicyManagerBase.cpp (hardware/libhardware_legacy/audio/AudioPolicyManagerBase.cpp)

    堪误: 上面3个文件被以下文件替代
    AudioPolicyManager.cpp (frameworks/av/services/audiopolicy/AudioPolicyManager.cpp)

    应用程序APP所用文件:

    AudioTrack.java (frameworks/base/media/java/android/media/AudioTrack.java)

    android_media_AudioTrack.cpp (frameworks/base/core/jni/android_media_AudioTrack.cpp)

    AudioTrack.cpp (frameworks/av/media/libmedia/AudioTrack.cpp)

    AudioSystem.cpp (frameworks/av/media/libmedia/AudioSystem.cpp)

    4 AudioPolicyService启动过程分析

    比如一部典型的手机,它既有听筒、耳机接口,还有蓝牙设备。假设默认情况下播放音乐是通过听筒喇叭输出的,那么当用户插入耳机时,这个策略就会改变——从耳机输出,而不再是听筒;又比如在机器插着耳机时,播放音乐不应该从喇叭输出,但是当有来电铃声时,就需要同时从喇叭和耳机输出音频。这些“音频策略”的制定,主导者就是AudioPolicyService

    在AudioFlinger小节,我们反复强调它只是策略的执行者,而AudioPolicyService则是策略的制定者。这种分离方式有效地降低了整个系统的藕合性,而且为各个模块独立扩展功能提供了保障。

    1. 加载解析/vendor/etc/audio_policy.conf/system/etc/audio_policy.conf
      • 对于配置文件里的每一个module项, new HwModule(name), 放入mHwModules数组;
      • 对于module里的每一个output, new IOProfile,放入module的mOutputProfiles
      • 对于module里的每一个input, new IOProfile, 放入module的mInputProfiles
    2. 根据module的name加载厂家提供的so文件(通过AudioFlinger来加载)
    3. 打开对应的output(通过AudioFlinger来open output)

    为了让大家对AudioPolicyService有个感性的认识,我们以下图来形象地表示它与AudioTrack及AudioFlinger间的关系:

    5 AudioFlinger启动过程分析

    1. 注册AudioFlinger服务
    2. 被AudioPolicyService调用以打开厂家提供的so文件
      1. 加载哪个so文件? 文件名是什么? 文件名从何而来?
        名字从/system/etc/audio_policy.conf得到 : primary
        所以so文件就是 : audio.primary.XXX.so, eg. audio.primary.tiny4412.so
      2. 该so文件由什么源文件组成? 查看Android.mk
    audio.primary.$(TARGET_DEVICE) : device/friendly-arm/common/libaudio/AudioHardware.cpp
    libhardware_legacy
        libhardware_legacy : 	hardware/libhardware_legacy/audio/audio_hw_hal.cpp
    
    1. 对硬件的封装:
    AudioFlinger       : AudioHwDevice (放入mAudioHwDevs数组中)
    audio_hw_hal.cpp   : audio_hw_device
    
    厂家               : AudioHardware (派生自: AudioHardwareInterface)
    

    AudioHwDevice是对audio_hw_device的封装,audio_hw_device中函数的实现要通过AudioHardware类对象

    6 AudioTrack创建过程概述

    1. 体验测试程序: frameworks/base/media/tests/audiotests/shared_mem_test.cpp

    frameworks/base/media/tests/mediaframeworktest/src/com/android/mediaframeworktest/functional/audio/MediaAudioTrackTest.java

    播放声音时都要创建AudioTrack对象,java的AudioTrack对象创建时会导致c++的AudioTrack对象被创建;

    所以分析的核心是c++的AudioTrack类,创建AudioTrack时涉及一个重要函数: set()函数

    1. 猜测创建过程的主要工作

      1. 使用AudioTrack的属性, 根据AudioPolicy找到对应的output、playbackThread
      2. 在playbackThread中创建对应的track
      3. APP的AudioTrack 和 playbackThread的mTracks中的track之间建立共享内存
    2. 源码时序图

    7 AudioTrack创建过程_Track和共享内存

    回顾:

    1. APP创建AudioTrack AudioFlinger中PlaybackThread创建对应的Track

    b. APP给AudioTrack提供音频数据有2种方式: 一次性提供(MODE_STATIC)、边播放边提供(MODE_STREAM)

    问:

    1. 音频数据存在buffer中, 这个buffer由谁提供? APP 还是 PlaybackThread ?
    2. APP提供数据, PlaybackThread消耗数据, 如何同步?

    8 音频数据的传递

    1. APP创建AudioTrack, playbackThread创建对应的Track
      它们之间通过共享内存传递音频数据
    2. APP有2种使用共享内存的方式:
      1. MODE_STATIC:
        APP创建共享内存, APP一次性填充数据
      2. MODE_STREAM:
        APP使用obtainBuffer获得空白内存, 填充数据后使用releaseBuffer释放内存
    3. playbackThread使用obtainBuffer获得含有数据的内存, 使用数据后使用releaseBuffer释放内存
    4. AudioTrack中含有mProxy, 它被用来管理共享内存, 里面含有obtainBuffer, releaseBuffer函数。Track中含有mServerProxy, 它被用来管理共享内存, 里面含有obtainBuffer, releaseBuffer函数。对于不同的MODE, 这些Proxy指向不同的对象
    5. 对于MODE_STREAM, APP和playbackThread使用环型缓冲区的方式传递数据

    9 PlaybackThread处理流程

    1. prepareTracks_l :
      确定enabled track, disabled track
      对于enabled track, 设置mState.tracks[x]中的参数

    2. threadLoop_mix : 处理数据(比如重采样)、混音
      确定hook:
      逐个分析mState.tracks[x]的数据, 根据它的格式确定tracks[x].hook
      再确定总的mState.hook

      调用hook:
      调用总的mState.hook即可, 它会再去调用每一个mState.tracks[x].hook

      混音后的数据会放在mState.outputTemp临时BUFFER中
      然后转换格式后存入 thread.mMixerBuffer

    3. memcpy_by_audio_format :
      把数据从thread.mMixerBuffer或thread.mEffectBuffer复制到thread.mSinkBuffer

    4. threadLoop_write:
      把thread.mSinkBuffer写到声卡上

    5. threadLoop_exit

  • 相关阅读:
    echarts3.0 实例容器不实时更新页面的问题
    Mac下搭建atx2环境
    MAC 下SFT环境搭建及使用
    【转发】基本adbui命令使用 可做图像识别
    UIAutomator2的API文档(三)
    UIAutomator2的API文档(二)
    UIAutomator2的API文档(一)
    UIAutomator2安装及连接
    uiautomator2通过wifi操作手机
    ATX-UI自动化环境搭建
  • 原文地址:https://www.cnblogs.com/linhaostudy/p/9694078.html
Copyright © 2020-2023  润新知