Android 音频子系统(2) ---- AudioServer


前言

本系列文章基于Android14源码进行分析解读,部分框图直接使用了原作者的图片,侵权必删。

我们既生成文章,也是各路文章的搬运工。


一、What&Why AudioFlinger

        AudioHAL(AHAL)提供隔离Vendor硬件差异的抽象,通过tinyalsa实现对底层硬件声卡节点的操作。AHAL作为一个独立的service,在Android系统中肯定有client通过binder与其通信,实现数据流与控制流的交互,完成对声卡节点数据的访问。

        AudioTrack.java和AudioRecord.java是应用层的API,透过GNI访问了Native层的AudioTrack.cpp和AudioRecord.cpp,AudioTrack和AudioRecord又是如何把数据写进和读出底层声卡的呢?

        Linux声卡设备节点是一个互斥的节点,每次只能被一个应用打开,其他应用尝试open一个已经打开的节点会返回device busy的错误。但是在实际Android使用过程中又存在多个音频数据流同时播放的场景,这是如何做到的呢?

        所有这些疑问都会在AudioFlinger服务中解决。AudioFlinger向下访问AudioHardware,实现输出音频数据,控制音频参数;AudioFlinger向上通过IAudioFinger接口对AudioTrack和AudioRecord供服务。AudioFlinger在Android的音频系统框架中起着承上启下的作用,地位相当重要。

AudioFlinger创建PlaybackThread/RecordThread服务线程,实现对AHAL层音频节点的独占操作。多个AudioTrack/AudioRecord作为Clinet端同PlaybackThread/RecordThread服务线程交互,Thread实现音频流的mix/snoop,来实现整个音频框架。

下面通过分析代码,完成对AudioFlinger的深入理解。

二、AudioFlinger初始化

AudioFlinger在audioserver中启动,代码在:

frameworks/av/media/audioserver/main_audioserver.cpp

#define LOG_TAG "audioserver"

int main(int argc __unused, char **argv)
{
     ......
    这里修改了AudioFling和AudioPolicyService的初始化方式,以解决独立初始化模式下引起的
    服务启动时间差,这个时间差会导致部分服务时间检测异常而强行退出。
    // Instantiating AudioFlinger (making it public, e.g. through ::initialize())
    // and then instantiating AudioPolicy (and making it public)
    // leads to situations where AudioFlinger is accessed remotely before
    // AudioPolicy is initialized.  Not only might this
    // cause inaccurate results, but if AudioPolicy has slow audio HAL
    // initialization, it can cause a TimeCheck abort to occur on an AudioFlinger
    // call which tries to access AudioPolicy.
    //
    // We create AudioFlinger and AudioPolicy locally then make it public to ServiceManager.
    // This requires both AudioFlinger and AudioPolicy to be in-proc.
    //

    /* 1、创建AudioFling实例,必须在AudioPolicyService之前,因为aps会访问af中的接口 */
    const auto af = sp<AudioFlinger>::make(); 
    const auto afAdapter = sp<AudioFlingerServerAdapter>::make(af);
   
    /* 2、创建AudioPolicyService实例 */
    const auto aps = sp<AudioPolicyService>::make();

    /* 3、添加AudioFlinger和AudioPolicyService服务到ServiceManager */    
    // Add AudioFlinger and AudioPolicy to ServiceManager.
    sp<IServiceManager> sm = defaultServiceManager();
    sm->addService(String16(IAudioFlinger::DEFAULT_SERVICE_NAME), afAdapter,
            false /* allowIsolated */, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT);
    sm->addService(String16(AudioPolicyService::getServiceName()), aps,
            false /* allowIsolated */, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT);
    
    // AAudioService should only be used in OC-MR1 and later.
    // And only enable the AAudioService if the system MMAP policy explicitly allows it.
    std::vector<AudioMMapPolicyInfo> policyInfos;
    status_t status = af->getMmapPolicyInfos(
            AudioMMapPolicyType::DEFAULT, &policyInfos);
    // Initialize aaudio service when querying mmap policy succeeds and
    // any of the policy supports MMAP.
    if (status == NO_ERROR &&
        std::any_of(policyInfos.begin(), policyInfos.end(), [](const auto& info) {
                return info.mmapPolicy == AudioMMapPolicy::AUTO ||
                       info.mmapPolicy == AudioMMapPolicy::ALWAYS;
        })) {
        
        /* 4、创建AAudioService实例 */
        AAudioService::instantiate();
    }

    ......

    IPCThreadState::self()->joinThreadPool();
    }
}

        主函数里面没有做太多的任务,创建了AudioFlinger和AudioPolicyService两个实例,并将服务注册到servicemanager中,除此之外还检测并创建了AAudioService。


1、AudioFlinger实例构建

AudioFlinger::AudioFlinger() {
    ......

    // reset battery stats.
    // if the audio service has crashed, battery stats could be left
    // in bad state, reset the state upon service start.
    BatteryNotifier::getInstance().noteResetAudio();

    /* 构建音频device和音效effect实例 */
    mDevicesFactoryHal = DevicesFactoryHalInterface::create();
    mEffectsFactoryHal = EffectsFactoryHalInterface::create();
}

AudioFlinger的实例没有做太多的工作:

  1. 完成电池状态的复位;
  2. 构建音频设备Device工厂实例;
  3. 构建音效Effect工厂实例;
sp<DevicesFactoryHalInterface> DevicesFactoryHalInterface::create() {
      return createPreferredImpl<DevicesFactoryHalInterface>(true /* isDevice */);
}


void *createPreferredImpl(bool isDevice) {
    ......
    if (...) {
       .....
        /*  1、创建AudioHal服务  */
        if (createHalService(std::max(*ifaceVersionIt, *siblingVersionIt), isDevice,
                             &rawInterface)) {
            return rawInterface;
        } 
    return nullptr;
}


bool createHalService(const AudioHalVersionInfo& version, bool isDevice, void** rawInterface) {
    const std::string libName = "libaudiohal@" + version.toVersionString() + ".so";
    const std::string factoryFunctionName =
            isDevice ? "createIDevicesFactory" : "createIEffectsFactory";
    constexpr int dlMode = RTLD_LAZY;
    void* handle = nullptr;
    dlerror(); // clear
    /*  2、打开 [email protected] 动态库 */
    handle = dlopen(libName.c_str(), dlMode);
    ......
    void* (*factoryFunction)();
    /*3、函数进来后首先初始化factoryFunctionName为createIDevicesFactory, 所以这里获取到的factoryFunction句柄为createIDevicesFactory函数 */
    *(void **)(&factoryFunction) = dlsym(handle, factoryFunctionName.c_str());
    if (!factoryFunction) {
       ......
    }
    /* 4、调用libaudiohal动态库的createIDevicesFactory函数,完成AHAL句柄的创建 */
    *rawInterface = (*factoryFunction)();
    return true;
}


extern "C" __attribute__((visibility("default"))) void* createIDevicesFactory() {
    return createIDevicesFactoryImpl();
}

extern "C" __attribute__((visibility("default"))) void* createIDevicesFactoryImpl() {
    auto service = hardware::audio::CPP_VERSION::IDevicesFactory::getService();
    return service ? new DevicesFactoryHalHidl(service) : nullptr;
}
DevicesFactoryHalEntry.cpp::createIDevicesFactory() ->
    DevicesFactoryHalHidl.cpp::createIDevicesFactoryImpl() ->         
         DevicesFactoryHalHidl.cpp::DevicesFactoryHalHidl()

具体逻辑这里不做深入的分析了,后面有机会再展开。

        整个AudioFlinger完成初始化之后,并没有做太多的任务。而是作为一个服务运行在系统中,等待客户端与其进行通信:这也符合AF的功能,我只做一个执行者,不做决策。那谁优势决策者呢?别忘了我们还没有分析AudioPolicyService呢。

2、AudioPolicyService实例构建

AudioPolicyService::AudioPolicyService()
    : BnAudioPolicyService(),
      mAudioPolicyManager(NULL),
      mAudioPolicyClient(NULL),
      mPhoneState(AUDIO_MODE_INVALID),
      mCaptureStateNotifier(false),
     /* 1 - 初始化mCreateAudioPolicyManager为createAudioPolicyManager */
      mCreateAudioPolicyManager(createAudioPolicyManager), 
      mDestroyAudioPolicyManager(destroyAudioPolicyManager) {
      setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
}

/* 在完成实例后,首先调用的函数就是onFirstRef,具体原因请搜索其他文章 */
void AudioPolicyService::onFirstRef()
{
     {
        Mutex::Autolock _l(mLock);

        /* 2 - 创建两个命令线程,用于接收并处理其他服务发送的命令 */
        // start audio commands thread
        mAudioCommandThread = new AudioCommandThread(String8("ApmAudio"), this);
        // start output activity command thread
        mOutputCommandThread = new AudioCommandThread(String8("ApmOutput"), this);
        
        /* 3 - 构造AudioPolicyClient实例:APC是AF的clinet端,很多任务都是通过跨进程调用到AF中 */
        mAudioPolicyClient = new AudioPolicyClient(this);

        /* 4 - 加载用户自定义的的AudioPolicyManager实现:libaudiopolicymanagercustom.so */
        loadAudioPolicyManager();

        /* 5 - 调用createAudioPolicyManager接口 */
        mAudioPolicyManager = mCreateAudioPolicyManager(mAudioPolicyClient);
    }

2.1、createAudioPolicyManager

static AudioPolicyInterface* createAudioPolicyManager(AudioPolicyClientInterface *clientInterface)
{
    AudioPolicyManager *apm = nullptr;
    media::AudioPolicyConfig apmConfig;
    /* 1、与AHAL交互获取modules信息,以确定是否存在用户自定义的configurable AudioPolicyConfig */
    if (status_t status = clientInterface->getAudioPolicyConfig(&apmConfig); status == OK) {
        auto config = AudioPolicyConfig::loadFromApmAidlConfigWithFallback(apmConfig);
        LOG_ALWAYS_FATAL_IF(config->getEngineLibraryNameSuffix() !=
                AudioPolicyConfig::kDefaultEngineLibraryNameSuffix,
                "Only default engine is currently supported with the AIDL HAL");
        apm = new AudioPolicyManager(config,
                loadApmEngineLibraryAndCreateEngine(
                        config->getEngineLibraryNameSuffix(), apmConfig.engineConfig),
                clientInterface);
    } else {
        /* 2、加载系统预定义的audio_policy_configuration配置 */
        auto config = AudioPolicyConfig::loadFromApmXmlConfigWithFallback();
         /* 3、config->getEngineLibraryNameSuffix()返回的
             字符串为“default”(kDefaultEngineLibraryNameSuffix),
             加载libaudiopolicyengine.default.so并完成AudioPolicyManager实例构造 */
        apm = new AudioPolicyManager(config,
                loadApmEngineLibraryAndCreateEngine(config->getEngineLibraryNameSuffix()),
                clientInterface);
    }
    /* 4、初始化AudioPolicyManager */
    status_t status = apm->initialize();
    if (status != NO_ERROR) {
        delete apm;
        apm = nullptr;
    }
    return apm;
}

// static
sp<const AudioPolicyConfig> AudioPolicyConfig::loadFromApmXmlConfigWithFallback(
        const std::string& xmlFilePath) {
    /* 2.1 - xmlFilePath为空,audio_get_audio_policy_config_file获取到的路径为/vendor/etc/audio_policy_configuration.xml */
    const std::string filePath =
            xmlFilePath.empty() ? audio_get_audio_policy_config_file() : xmlFilePath;
    auto config = sp<AudioPolicyConfig>::make();
    /* 2.2 - 解析audio_policy_configuration.xml 文件并获得音频策略配置信息 */
    if (status_t status = config->loadFromXml(filePath, false /*forVts*/); status == NO_ERROR) {
        return config;
    }
     /* 2.3 - 不会运行到这里 */
    return createDefault();
}


status_t AudioPolicyConfig::loadFromXml(const std::string& xmlFilePath, bool forVts) {
    ...
    status_t status = deserializeAudioPolicyFile(xmlFilePath.c_str(), this);
    ...
}

status_t deserializeAudioPolicyFile(const char *fileName, AudioPolicyConfig *config)
{
    PolicySerializer serializer;
    return status = serializer.deserialize(fileName, config);
}

status_t PolicySerializer::deserialize(const char *configFile, AudioPolicyConfig *config,
                                       bool ignoreVendorExtensions)
{
    /* 完成audio_policy_configuration.xml的解析*/
    ......
}

以Android的car/emulator的audio_policy_configuration.xml文件为例,下图是xml文件解析后得到的结果,整个解析按照mixPort,devicePort和route的属性解析并最终形成HwModule,条理比较简单,读者自行撸代码也能看懂。

 

得益于Android丰富的工具,可以通过 dumpsys media.audio_policy 命令查看最终配置的路由策略。

dumpsys media.audio_policy
Supported System Usages:
  AUDIO_USAGE_CALL_ASSISTANT, AUDIO_USAGE_EMERGENCY, AUDIO_USAGE_SAFETY, AUDIO_USAGE_VEHICLE_STATUS, AUDIO_USAGE_ANNOUNCEMENT
UID Policy:
        mObserverRegistered=True
        Assistants UIDs:
                No UIDs present.
        Active Assistants UIDs:
                No UIDs present.
        Accessibility UIDs:
                No UIDs present.
        Input Method Service UID=1010067
        Is RTT Enabled: False
AudioCommandThread: 0xb400007416624090
- Commands:
   Command Time        Wait pParam
  Last Command
   05      092141.687  0    0xb40000739666f2e0
OutputCommandThread: 0xb400007416625950
- Commands:
   Command Time        Wait pParam
  Last Command
   09      092141.966  0    0xb400007306620340

AudioPolicyManager Dump: 0xb4000074466246b0
 Primary Output I/O handle: 13
 Phone state: AUDIO_MODE_NORMAL
 Force use for communications: 0
 Force use for media: 10
 Force use for record: 0
 Force use for dock: 9
 Force use for system: 0
 Force use for HDMI system audio: 0
 Force use for encoded surround output: 0
 Force use for vibrate ringing: 0
 TTS output not available
 Master mono: off
 Communication Strategy id: 14
 Config source: /vendor/etc/audio_policy_configuration.xml

 Available output devices (17):
  1. Port ID: 50; "bus1000_mirror_device"; {AUDIO_DEVICE_OUT_BUS, @:bus1000_mirror_device}
     Encapsulation modes: 0, metadata types: 0
   - Profiles (1):
      1. ""; AUDIO_FORMAT_PCM_16_BIT (0x1)
         sampling rates: 48000
         channel masks: 0x0003
         AUDIO_ENCAPSULATION_TYPE_NONE
     - gains:
       Gain 1:
       - mode: 00000001
       - channel_mask: 00000000
       - min_value: -3200 mB
       - max_value: 600 mB
       - default_value: 0 mB
       - step_value: 100 mB
       - min_ramp_ms: 0 ms
       - max_ramp_ms: 0 ms
  2. Port ID: 47; "bus211_audio_zone_2"; {AUDIO_DEVICE_OUT_BUS, @:bus211_audio_zone_2}
     Encapsulation modes: 0, metadata types: 0
   - Profiles (1):
      1. ""; AUDIO_FORMAT_PCM_16_BIT (0x1)
         sampling rates: 48000
         channel masks: 0x0003
         AUDIO_ENCAPSULATION_TYPE_NONE
     - gains:
       Gain 1:
       - mode: 00000001
       - channel_mask: 00000000
       - min_value: -3200 mB
       - max_value: 600 mB
       - default_value: 0 mB
       - step_value: 100 mB
       - min_ramp_ms: 0 ms
       - max_ramp_ms: 0 ms
  ...
  6. Port ID: 35; "bus111_audio_zone_1"; {AUDIO_DEVICE_OUT_BUS, @:bus111_audio_zone_1}
     Encapsulation modes: 0, metadata types: 0
   - Profiles (1):
      1. ""; AUDIO_FORMAT_PCM_16_BIT (0x1)
         sampling rates: 48000
         channel masks: 0x0003
         AUDIO_ENCAPSULATION_TYPE_NONE
     - gains:
       Gain 1:
       - mode: 00000001
       - channel_mask: 00000000
       - min_value: -3200 mB
       - max_value: 600 mB
       - default_value: 0 mB
       - step_value: 100 mB
       - min_ramp_ms: 0 ms
       - max_ramp_ms: 0 ms
   ...
  10. Port ID: 23; "bus7_system_sound_out"; {AUDIO_DEVICE_OUT_BUS, @:bus7_system_sound_out}
      Encapsulation modes: 0, metadata types: 0
    - Profiles (1):
       1. ""; AUDIO_FORMAT_PCM_16_BIT (0x1)
          sampling rates: 48000
          channel masks: 0x0003
          AUDIO_ENCAPSULATION_TYPE_NONE
      - gains:
        Gain 1:
        - mode: 00000001
        - channel_mask: 00000000
        - min_value: -3200 mB
        - max_value: 600 mB
        - default_value: 0 mB
        - step_value: 100 mB
        - min_ramp_ms: 0 ms
        - max_ramp_ms: 0 ms
  17. Port ID: 2; "bus0_media_out"; {AUDIO_DEVICE_OUT_BUS, @:bus0_media_out}
      Encapsulation modes: 0, metadata types: 0
    - Profiles (1):
       1. ""; AUDIO_FORMAT_PCM_16_BIT (0x1)
          sampling rates: 48000
          channel masks: 0x0003
          AUDIO_ENCAPSULATION_TYPE_NONE
      - gains:
        Gain 1:
        - mode: 00000001
        - channel_mask: 00000000
        - min_value: -3200 mB
        - max_value: 600 mB
        - default_value: 0 mB
        - step_value: 100 mB
        - min_ramp_ms: 0 ms
        - max_ramp_ms: 0 ms

 Available input devices (7):
  1. Port ID: 53; "Built-In Mic"; {AUDIO_DEVICE_IN_BUILTIN_MIC, @:Built-In Mic}
     Encapsulation modes: 0, metadata types: 0
   - Profiles (1):
      1. ""; AUDIO_FORMAT_PCM_16_BIT (0x1)
         sampling rates: 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000
         channel masks: 0x000c, 0x0010, 0x0030
         AUDIO_ENCAPSULATION_TYPE_NONE
  2. Port ID: 54; "Built-In Back Mic"; {AUDIO_DEVICE_IN_BACK_MIC, @:Built-In Back Mic}
     Encapsulation modes: 0, metadata types: 0
   - Profiles (1):
      1. ""; AUDIO_FORMAT_PCM_16_BIT (0x1)
         sampling rates: 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000
         channel masks: 0x000c, 0x0010, 0x0030
         AUDIO_ENCAPSULATION_TYPE_NONE
     ...

 Hardware modules (3):
  1. Handle: 10; "primary"
   - Output MixPorts (17):
      1. "mixport_bus0_media_out"; 0x0002 (AUDIO_OUTPUT_FLAG_PRIMARY)
       - Profiles (1):
          1. ""; AUDIO_FORMAT_PCM_16_BIT (0x1)
             sampling rates: 48000
             channel masks: 0x0003
             AUDIO_ENCAPSULATION_TYPE_NONE
       - Supported devices (1):
        1. Port ID: 2; "bus0_media_out"; {AUDIO_DEVICE_OUT_BUS, @:bus0_media_out}
           Encapsulation modes: 0, metadata types: 0
       - maxOpenCount: 1; curOpenCount: 1
       - maxActiveCount: 1; curActiveCount: 0
       - recommendedMuteDurationMs: 0 ms
      2. "mixport_bus1_navigation_out"; 0x0000 (AUDIO_OUTPUT_FLAG_NONE)
       - Profiles (1):
          1. ""; AUDIO_FORMAT_PCM_16_BIT (0x1)
             sampling rates: 48000
             channel masks: 0x0003
             AUDIO_ENCAPSULATION_TYPE_NONE
       - Supported devices (1):
        1. Port ID: 5; "bus1_navigation_out"; {AUDIO_DEVICE_OUT_BUS, @:bus1_navigation_out}
           Encapsulation modes: 0, metadata types: 0
       - maxOpenCount: 1; curOpenCount: 1
       - maxActiveCount: 1; curActiveCount: 0
       - recommendedMuteDurationMs: 0 ms
      ...
   - Input MixPorts (4):
      1. "primary input"; 0x0000 (AUDIO_INPUT_FLAG_NONE)
       - Profiles (1):
          1. ""; AUDIO_FORMAT_PCM_16_BIT (0x1)
             sampling rates: 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000
             channel masks: 0x000c, 0x0010, 0x0030
             AUDIO_ENCAPSULATION_TYPE_NONE
       - Supported devices (3):
        1. Port ID: 53; "Built-In Mic"; {AUDIO_DEVICE_IN_BUILTIN_MIC, @:Built-In Mic}
           Encapsulation modes: 0, metadata types: 0
        2. Port ID: 54; "Built-In Back Mic"; {AUDIO_DEVICE_IN_BACK_MIC, @:Built-In Back Mic}
           Encapsulation modes: 0, metadata types: 0
        3. Port ID: 55; "Echo-Reference Mic"; {AUDIO_DEVICE_IN_ECHO_REFERENCE, @:Echo-Reference Mic}
           Encapsulation modes: 0, metadata types: 0
       - maxOpenCount: 1; curOpenCount: 0
       - maxActiveCount: 1; curActiveCount: 0
       - recommendedMuteDurationMs: 0 ms
      ...
   - Declared devices (23):
    1. Port ID: 50; "bus1000_mirror_device"; {AUDIO_DEVICE_OUT_BUS, @:bus1000_mirror_device}
       Encapsulation modes: 0, metadata types: 0
     - Profiles (1):
        1. ""; AUDIO_FORMAT_PCM_16_BIT (0x1)
           sampling rates: 48000
           channel masks: 0x0003
           AUDIO_ENCAPSULATION_TYPE_NONE
       - gains:
         Gain 1:
         - mode: 00000001
         - channel_mask: 00000000
         - min_value: -3200 mB
         - max_value: 600 mB
         - default_value: 0 mB
         - step_value: 100 mB
         - min_ramp_ms: 0 ms
         - max_ramp_ms: 0 ms
    ...
   - Audio Routes (21):
      1. Mix; Sink: "bus0_media_out"
         Sources: "mixport_bus0_media_out"
      2. Mix; Sink: "bus1_navigation_out"
         Sources: "mixport_bus1_navigation_out"
      3. Mix; Sink: "bus2_voice_command_out"
         Sources: "mixport_bus2_voice_command_out"
     ...
  

2.2 AudioPolicyManager实例构建 

static AudioPolicyInterface* createAudioPolicyManager(AudioPolicyClientInterface *clientInterface)
{
    ...
        apm = new AudioPolicyManager(config,
                loadApmEngineLibraryAndCreateEngine(config->getEngineLibraryNameSuffix()),
                clientInterface);
}
2.2.1  loadApmEngineLibraryAndCreateEngine 

在2.1章的第3步中config->getEngineLibraryNameSuffix()返回的字符串为“default”(kDefaultEngineLibraryNameSuffix),所以loadApmEngineLibraryAndCreateEngine传入的参数为("default”,null)。

EngineInstance loadApmEngineLibraryAndCreateEngine(const std::string& librarySuffix,
        const std::string& configXmlFilePath)
{
    /* 1 - 加载libaudiopolicyengine.default.so,获取createEngineInstance句柄并赋值给mCreateEngineInstance */
    auto engLib = EngineLibrary::load(librarySuffix);
    if (!engLib) {
        ALOGE("%s: Failed to load the engine library, suffix \"%s\"",
                __func__, librarySuffix.c_str());
        return nullptr;
    }

    /* 2 - 创建ape,这里的configXmlFilePath为空 */
    auto engine = engLib->createEngineUsingXmlConfig(configXmlFilePath);
    if (engine == nullptr) {
        ALOGE("%s: Failed to instantiate the APM engine", __func__);
        return nullptr;
    }
    return engine;
}


EngineInstance EngineLibrary::createEngineUsingXmlConfig(const std::string& xmlFilePath)
{
    auto instance = createEngine();
    if (instance != nullptr) {
        /* 2.1 - xmlFilePath为空,加载engine 配置文件*/
        if (status_t status = instance->loadFromXmlConfigWithFallback(xmlFilePath);
                status == OK) {
            return instance;
        } else {
            ALOGE("%s: loading of the engine config with XML configuration file \"%s\" failed: %d",
                    __func__, xmlFilePath.empty() ? "default" : xmlFilePath.c_str(), status);
        }
    }
    return nullptr;
}

status_t Engine::loadFromXmlConfigWithFallback(const std::string& xmlFilePath) {
    return loadWithFallback(xmlFilePath);
}

template<typename T>
status_t Engine::loadWithFallback(const T& configSource) {
    /* 2.1.1 - 加载engineConfig::DEFAULT_PATH("/vendor/etc/audio_policy_engine_configuration.xml") 下的ape配置文件 */
    auto result = EngineBase::loadAudioPolicyEngineConfig(configSource);
    auto legacyStrategy = getLegacyStrategy();
    for (const auto &strategy : legacyStrategy) {
        mLegacyStrategyMap[getProductStrategyByName(strategy.name)] = strategy.id;
    }

    return OK;
}

        APE的调用逻辑比较繁琐,但是原理很清晰:首先确定是否存在用户自定义的configurable engine,如果不存在则使用default engine;确认之后逐步调用并解析相关的APE配置文件。譬如车机的APE配置如下:/frameworks/av/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_configuration.xml

<configuration version="1.0" xmlns:xi="http://www.w3.org/2001/XInclude">

    <xi:include href="audio_policy_engine_product_strategies.xml"/>
    <xi:include href="audio_policy_engine_criterion_types.xml"/>
    <xi:include href="audio_policy_engine_criteria.xml"/>
    <xi:include href="audio_policy_engine_volumes.xml"/>

</configuration>

具体内容在后续使用的过程中分析。

2.3、AudioPolicyManager::initialize

        回到2.1的第4步,也是最后一步:AudioPolicyManager的initialize。


status_t AudioPolicyManager::initialize() {
    /* 1 - 这里的mEngine就是上面分析的APE,肯定非空了 */
    if (mEngine == nullptr) {
        return NO_INIT;
    }

    /* 2 - 将APM设置为Engine的观察器(mApmObserver=APM),
           允许Engine检索Devices、Streams、HwModules的信息:
           Engine通过APM获取/设置相关信息 */
    mEngine->setObserver(this);
    
    /* 3 - 检测Engine是否被正确初始化:mApmObserver!=null, 这不是废话吗?
           前面刚设置完成*/
    status_t status = mEngine->initCheck();
    if (status != NO_ERROR) {
        LOG_FATAL("Policy engine not initialized(err=%d)", status);
        return status;
    }

    // The actual device selection cache will be updated when calling `updateDevicesAndOutputs`
    // at the end of this function.
    /* 4 - 使用产品策略初始化设备,这些设备的策略会在音频模块初始化后更新。*/
    mEngine->initializeDeviceSelectionCache();
    mCommunnicationStrategy = mEngine->getProductStrategyForAttributes(
        mEngine->getAttributesForStreamType(AUDIO_STREAM_VOICE_CALL));

     /* 5 - 有音频模块可用(实际上是首次初始化),完成模块的初始化。*/
    // after parsing the config, mConfig contain all known devices;
    // open all output streams needed to access attached devices
    onNewAudioModulesAvailableInt(nullptr /*newDevices*/);

    // make sure default device is reachable
    if (const auto defaultOutputDevice = mConfig->getDefaultOutputDevice();
            defaultOutputDevice == nullptr ||
            !mAvailableOutputDevices.contains(defaultOutputDevice)) {
        ALOGE_IF(defaultOutputDevice != nullptr, "Default device %s is unreachable",
                 defaultOutputDevice->toString().c_str());
        status = NO_INIT;
    }
      
    /* 6 - 第5步中完成了整个音频模块的初始化,跟新相关信息到Cache缓存中。
       在音频系统稳定后,为了加快处理速度,引擎会缓存基于AudioAttribute/Streams的设备选择。当一个设备连接时,Android的模式会发生变化,引擎会收到通知并更新缓存。如果某个输出上音频流的启动/停止可能影响通知时,引擎需要通过updateDevicesAndOutputs函数更新缓存。*/
    updateDevicesAndOutputs();

    return status;
}
2.3.1、AudioPolicyManager::onNewAudioModulesAvailableInt

        经过2.2章节的分析,我们已经清楚系统已经完成xml配置文件的解析并形成HwModule的多维数据,该函数就是根据先前分析的数据完成音频系统的最重要的一步:调用AF->AHAL完成设备节

点的open,并在AF中创建数据流播放/录制线程,为后面AudioTrack做好准备

void AudioPolicyManager::onNewAudioModulesAvailableInt(DeviceVector *newDevices)
{
    ALOGD("AudioAnt: onNewAudioModulesAvailableInt enter ......");

    /* 1. 遍历audio_policy_configuration.xml中配置的所有模块 */
    for (const auto& hwModule : mConfig->getHwModules()) {
        if (std::find(mHwModules.begin(), mHwModules.end(), hwModule) != mHwModules.end()) {
            continue;
        }
        if (hwModule->getHandle() == AUDIO_MODULE_HANDLE_NONE) {
            ALOGD("AudioAnt: loadHwModule with module name %s", hwModule->getName());
            /* 2. 加载相关module,获取module的句柄handle */
            if (audio_module_handle_t handle = mpClientInterface->loadHwModule(hwModule->getName());
                    handle != AUDIO_MODULE_HANDLE_NONE) {
                hwModule->setHandle(handle);
            } else {
                ALOGW("could not load HW module %s", hwModule->getName());
                continue;
            }
        }

        /* 3. 如果xml中配置的module存在,则记录到mHwModules容器中以便后面访问使用 */
        mHwModules.push_back(hwModule);
 
        /* 4. 遍历当前模块支持的profiles */
        for (const auto& outProfile : hwModule->getOutputProfiles()) {
            ALOGD("AudioAnt: outProfile with name: %s", outProfile->getTagName().c_str());
            
            /* 5. 获取当前profile支持的设备 */
            const DeviceVector &supportedDevices = outProfile->getSupportedDevices();
            for(auto& device: supportedDevices) {
                ALOGD("AudioAnt: supportedDevices with name: %s", device->getTagName().c_str());
            }

            DeviceVector availProfileDevices = supportedDevices.filter(mConfig->getOutputDevices());
            sp<DeviceDescriptor> supportedDevice = 0;
            if (supportedDevices.contains(mConfig->getDefaultOutputDevice())) {
                supportedDevice = mConfig->getDefaultOutputDevice();
            } else {
                // choose first device present in profile's SupportedDevices also part of
                // mAvailableOutputDevices.
                if (availProfileDevices.isEmpty()) {
                    continue;
                }
                supportedDevice = availProfileDevices.itemAt(0);
            }
            if (!mConfig->getOutputDevices().contains(supportedDevice)) {
                continue;
            }
            sp<SwAudioOutputDescriptor> outputDesc = new SwAudioOutputDescriptor(outProfile, mpClientInterface);
            audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
            
            /* 6. 打开设备,涉及AHAL的open操作,并在AF中创建相关播放/录制线程 */
            status_t status = outputDesc->open(nullptr /* halConfig */, nullptr /* mixerConfig */,
                                               DeviceVector(supportedDevice),
                                               AUDIO_STREAM_DEFAULT,
                                               AUDIO_OUTPUT_FLAG_NONE, &output);
            if (status != NO_ERROR) {
                ALOGW("Cannot open output stream for devices %s on hw module %s",
                      supportedDevice->toString().c_str(), hwModule->getName());
                continue;
            }
            for (const auto &device : availProfileDevices) {
                ALOGD("AudioAnt: availProfileDevices with name: %s", device->getTagName().c_str());
                // give a valid ID to an attached device once confirmed it is reachable
                if (!device->isAttached()) {
                    device->attach(hwModule);
                    mAvailableOutputDevices.add(device);
                    device->setEncapsulationInfoFromHal(mpClientInterface);
                    if (newDevices) newDevices->add(device);
                    setEngineDeviceConnectionState(device, AUDIO_POLICY_DEVICE_STATE_AVAILABLE);
                }
            }
            if (mPrimaryOutput == nullptr &&
                    outProfile->getFlags() & AUDIO_OUTPUT_FLAG_PRIMARY) {
                mPrimaryOutput = outputDesc;
            }
            if ((outProfile->getFlags() & AUDIO_OUTPUT_FLAG_DIRECT) != 0) {
                outputDesc->close();
            } else {
                addOutput(output, outputDesc);
                setOutputDevices(outputDesc,
                                 DeviceVector(supportedDevice),
                                 true,
                                 0,
                                 NULL);
            }
        }
        
        /* 7. 同输出设置一样的操作逻辑,不赘述 */
        // open input streams needed to access attached devices to validate
        // mAvailableInputDevices list
        for (const auto& inProfile : hwModule->getInputProfiles()) {
        }
    }

    /* 8. 如果有声场相关输出,在使用之前先关闭它 */
    // Check if spatializer outputs can be closed until used.
    // mOutputs vector never contains duplicated outputs at this point.
    std::vector<audio_io_handle_t> outputsClosed;
    for (size_t i = 0; i < mOutputs.size(); i++) {
        sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
        if ((desc->mFlags & AUDIO_OUTPUT_FLAG_SPATIALIZER) != 0
                && !isOutputOnlyAvailableRouteToSomeDevice(desc)) {
            outputsClosed.push_back(desc->mIoHandle);
            desc->close();
        }
    }
    for (auto output : outputsClosed) {
        removeOutput(output);
    }
}

        最终的操作输出如下:

06-06 21:51:06.077 16876 16876 D APM_AudioPolicyManager: AudioAnt: onNewAudioModulesAvailableInt enter ......
06-06 21:51:06.077 16876 16876 D APM_AudioPolicyManager: AudioAnt: loadHwModule with module name primary
06-06 21:51:09.092 16876 16876 D APM_AudioPolicyManager: AudioAnt: outProfile with name: mixport_bus0_media_out
06-06 21:51:09.092 16876 16876 D APM_AudioPolicyManager: AudioAnt: supportedDevices with name: bus0_media_out
06-06 21:51:09.096 16876 16876 I AudioFlinger: AudioAnt: openOutput() this 0xb40000738661f010, module 10 Device AUDIO_DEVICE_OUT_BUS, @:bus0_media_out, SamplingRate
 48000, Format 0x000001, Channels 0x3, flags 0x2
06-06 21:51:09.266 16876 16876 D APM_AudioPolicyManager: AudioAnt: availProfileDevices with name: bus0_media_out
06-06 21:51:09.316 16876 16876 D APM_AudioPolicyManager: AudioAnt: outProfile with name: mixport_bus1_navigation_out
06-06 21:51:09.316 16876 16876 D APM_AudioPolicyManager: AudioAnt: supportedDevices with name: bus1_navigation_out
06-06 21:51:09.316 16876 16876 I AudioFlinger: AudioAnt: openOutput() this 0xb40000738661f010, module 10 Device AUDIO_DEVICE_OUT_BUS, @:bus1_navigation_out, Samplin
gRate 48000, Format 0x000001, Channels 0x3, flags 0
06-06 21:51:09.327 16876 16876 D APM_AudioPolicyManager: AudioAnt: availProfileDevices with name: bus1_navigation_out
06-06 21:51:09.354 16876 16876 D APM_AudioPolicyManager: AudioAnt: outProfile with name: mixport_bus2_voice_command_out
06-06 21:51:09.354 16876 16876 D APM_AudioPolicyManager: AudioAnt: supportedDevices with name: bus2_voice_command_out
06-06 21:51:09.354 16876 16876 I AudioFlinger: AudioAnt: openOutput() this 0xb40000738661f010, module 10 Device AUDIO_DEVICE_OUT_BUS, @:bus2_voice_command_out, Samp
lingRate 48000, Format 0x000001, Channels 0x3, flags 0
06-06 21:51:09.365 16876 16876 D APM_AudioPolicyManager: AudioAnt: availProfileDevices with name: bus2_voice_command_out
06-06 21:51:09.391 16876 16876 D APM_AudioPolicyManager: AudioAnt: outProfile with name: mixport_bus3_call_ring_out
06-06 21:51:09.392 16876 16876 D APM_AudioPolicyManager: AudioAnt: supportedDevices with name: bus3_call_ring_out
06-06 21:51:09.392 16876 16876 I AudioFlinger: AudioAnt: openOutput() this 0xb40000738661f010, module 10 Device AUDIO_DEVICE_OUT_BUS, @:bus3_call_ring_out, Sampling
Rate 48000, Format 0x000001, Channels 0x3, flags 0
06-06 21:51:09.403 16876 16876 D APM_AudioPolicyManager: AudioAnt: availProfileDevices with name: bus3_call_ring_out
06-06 21:51:09.416 16876 16876 D APM_AudioPolicyManager: AudioAnt: outProfile with name: mixport_bus4_call_out
06-06 21:51:09.416 16876 16876 D APM_AudioPolicyManager: AudioAnt: supportedDevices with name: bus4_call_out
06-06 21:51:09.416 16876 16876 I AudioFlinger: AudioAnt: openOutput() this 0xb40000738661f010, module 10 Device AUDIO_DEVICE_OUT_BUS, @:bus4_call_out, SamplingRate
48000, Format 0x000001, Channels 0x3, flags 0
06-06 21:51:09.423 16876 16876 D APM_AudioPolicyManager: AudioAnt: availProfileDevices with name: bus4_call_out
06-06 21:51:09.441 16876 16876 D APM_AudioPolicyManager: AudioAnt: outProfile with name: mixport_bus5_alarm_out
06-06 21:51:09.442 16876 16876 D APM_AudioPolicyManager: AudioAnt: supportedDevices with name: bus5_alarm_out
06-06 21:51:09.442 16876 16876 I AudioFlinger: AudioAnt: openOutput() this 0xb40000738661f010, module 10 Device AUDIO_DEVICE_OUT_BUS, @:bus5_alarm_out, SamplingRate
 48000, Format 0x000001, Channels 0x3, flags 0
06-06 21:51:09.451 16876 16876 D APM_AudioPolicyManager: AudioAnt: availProfileDevices with name: bus5_alarm_out
06-06 21:51:09.463 16876 16876 D APM_AudioPolicyManager: AudioAnt: outProfile with name: mixport_bus6_notification_out
06-06 21:51:09.463 16876 16876 D APM_AudioPolicyManager: AudioAnt: supportedDevices with name: bus6_notification_out
06-06 21:51:09.463 16876 16876 I AudioFlinger: AudioAnt: openOutput() this 0xb40000738661f010, module 10 Device AUDIO_DEVICE_OUT_BUS, @:bus6_notification_out, Sampl
ingRate 48000, Format 0x000001, Channels 0x3, flags 0
06-06 21:51:09.471 16876 16876 D APM_AudioPolicyManager: AudioAnt: availProfileDevices with name: bus6_notification_out
06-06 21:51:09.491 16876 16876 D APM_AudioPolicyManager: AudioAnt: outProfile with name: mixport_bus7_system_sound_out
06-06 21:51:09.491 16876 16876 D APM_AudioPolicyManager: AudioAnt: supportedDevices with name: bus7_system_sound_out
06-06 21:51:09.491 16876 16876 I AudioFlinger: AudioAnt: openOutput() this 0xb40000738661f010, module 10 Device AUDIO_DEVICE_OUT_BUS, @:bus7_system_sound_out, Sampl
ingRate 48000, Format 0x000001, Channels 0x3, flags 0
06-06 21:51:09.499 16876 16876 D APM_AudioPolicyManager: AudioAnt: availProfileDevices with name: bus7_system_sound_out
06-06 21:51:09.519 16876 16876 D APM_AudioPolicyManager: AudioAnt: outProfile with name: mixport_bus100_audio_zone_1
06-06 21:51:09.519 16876 16876 D APM_AudioPolicyManager: AudioAnt: supportedDevices with name: bus100_audio_zone_1
06-06 21:51:09.520 16876 16876 I AudioFlinger: AudioAnt: openOutput() this 0xb40000738661f010, module 10 Device AUDIO_DEVICE_OUT_BUS, @:bus100_audio_zone_1, Samplin
gRate 48000, Format 0x000001, Channels 0x3, flags 0
06-06 21:51:09.530 16876 16876 D APM_AudioPolicyManager: AudioAnt: availProfileDevices with name: bus100_audio_zone_1
06-06 21:51:09.557 16876 16876 D APM_AudioPolicyManager: AudioAnt: outProfile with name: mixport_bus101_audio_zone_1
06-06 21:51:09.558 16876 16876 D APM_AudioPolicyManager: AudioAnt: supportedDevices with name: bus101_audio_zone_1
06-06 21:51:09.558 16876 16876 I AudioFlinger: AudioAnt: openOutput() this 0xb40000738661f010, module 10 Device AUDIO_DEVICE_OUT_BUS, @:bus101_audio_zone_1, Samplin
gRate 48000, Format 0x000001, Channels 0x3, flags 0
06-06 21:51:09.569 16876 16876 D APM_AudioPolicyManager: AudioAnt: availProfileDevices with name: bus101_audio_zone_1
06-06 21:51:09.598 16876 16876 D APM_AudioPolicyManager: AudioAnt: outProfile with name: mixport_bus110_audio_zone_1
06-06 21:51:09.598 16876 16876 D APM_AudioPolicyManager: AudioAnt: supportedDevices with name: bus110_audio_zone_1
06-06 21:51:09.598 16876 16876 I AudioFlinger: AudioAnt: openOutput() this 0xb40000738661f010, module 10 Device AUDIO_DEVICE_OUT_BUS, @:bus110_audio_zone_1, Samplin
gRate 48000, Format 0x000001, Channels 0x3, flags 0
06-06 21:51:09.604 16876 16876 D APM_AudioPolicyManager: AudioAnt: availProfileDevices with name: bus110_audio_zone_1
06-06 21:51:09.630 16876 16876 D APM_AudioPolicyManager: AudioAnt: outProfile with name: mixport_bus111_audio_zone_1
06-06 21:51:09.630 16876 16876 D APM_AudioPolicyManager: AudioAnt: supportedDevices with name: bus111_audio_zone_1
06-06 21:51:09.631 16876 16876 I AudioFlinger: AudioAnt: openOutput() this 0xb40000738661f010, module 10 Device AUDIO_DEVICE_OUT_BUS, @:bus111_audio_zone_1, Samplin
gRate 48000, Format 0x000001, Channels 0x3, flags 0
06-06 21:51:09.642 16876 16876 D APM_AudioPolicyManager: AudioAnt: availProfileDevices with name: bus111_audio_zone_1
06-06 21:51:09.678 16876 16876 D APM_AudioPolicyManager: AudioAnt: outProfile with name: mixport_bus200_audio_zone_2
06-06 21:51:09.679 16876 16876 D APM_AudioPolicyManager: AudioAnt: supportedDevices with name: bus200_audio_zone_2
06-06 21:51:09.679 16876 16876 I AudioFlinger: AudioAnt: openOutput() this 0xb40000738661f010, module 10 Device AUDIO_DEVICE_OUT_BUS, @:bus200_audio_zone_2, Samplin
gRate 48000, Format 0x000001, Channels 0x3, flags 0
06-06 21:51:09.690 16876 16876 D APM_AudioPolicyManager: AudioAnt: availProfileDevices with name: bus200_audio_zone_2
06-06 21:51:09.713 16876 16876 D APM_AudioPolicyManager: AudioAnt: outProfile with name: mixport_bus201_audio_zone_2
06-06 21:51:09.713 16876 16876 D APM_AudioPolicyManager: AudioAnt: supportedDevices with name: bus201_audio_zone_2
06-06 21:51:09.713 16876 16876 I AudioFlinger: AudioAnt: openOutput() this 0xb40000738661f010, module 10 Device AUDIO_DEVICE_OUT_BUS, @:bus201_audio_zone_2, Samplin
gRate 48000, Format 0x000001, Channels 0x3, flags 0
06-06 21:51:09.720 16876 16876 D APM_AudioPolicyManager: AudioAnt: availProfileDevices with name: bus201_audio_zone_2
06-06 21:51:09.742 16876 16876 D APM_AudioPolicyManager: AudioAnt: outProfile with name: mixport_bus210_audio_zone_2
06-06 21:51:09.742 16876 16876 D APM_AudioPolicyManager: AudioAnt: supportedDevices with name: bus210_audio_zone_2
06-06 21:51:09.742 16876 16876 I AudioFlinger: AudioAnt: openOutput() this 0xb40000738661f010, module 10 Device AUDIO_DEVICE_OUT_BUS, @:bus210_audio_zone_2, Samplin
gRate 48000, Format 0x000001, Channels 0x3, flags 0
06-06 21:51:09.747 16876 16876 D APM_AudioPolicyManager: AudioAnt: availProfileDevices with name: bus210_audio_zone_2
06-06 21:51:09.773 16876 16876 D APM_AudioPolicyManager: AudioAnt: outProfile with name: mixport_bus211_audio_zone_2
06-06 21:51:09.773 16876 16876 D APM_AudioPolicyManager: AudioAnt: supportedDevices with name: bus211_audio_zone_2
06-06 21:51:09.773 16876 16876 I AudioFlinger: AudioAnt: openOutput() this 0xb40000738661f010, module 10 Device AUDIO_DEVICE_OUT_BUS, @:bus211_audio_zone_2, Samplin
gRate 48000, Format 0x000001, Channels 0x3, flags 0
06-06 21:51:09.779 16876 16876 D APM_AudioPolicyManager: AudioAnt: availProfileDevices with name: bus211_audio_zone_2
06-06 21:51:09.810 16876 16876 D APM_AudioPolicyManager: AudioAnt: outProfile with name: mixport_bus1000_mirror_device
06-06 21:51:09.810 16876 16876 D APM_AudioPolicyManager: AudioAnt: supportedDevices with name: bus1000_mirror_device
06-06 21:51:09.810 16876 16876 I AudioFlinger: AudioAnt: openOutput() this 0xb40000738661f010, module 10 Device AUDIO_DEVICE_OUT_BUS, @:bus1000_mirror_device, Sampl
ingRate 48000, Format 0x000001, Channels 0x3, flags 0
06-06 21:51:09.817 16876 16876 D APM_AudioPolicyManager: AudioAnt: availProfileDevices with name: bus1000_mirror_device
06-06 21:51:09.881 16876 16876 D APM_AudioPolicyManager: AudioAnt: loadHwModule with module name a2dp
06-06 21:51:09.882 16876 16876 D APM_AudioPolicyManager: AudioAnt: loadHwModule with module name usb
06-06 21:51:09.884 16876 16876 D APM_AudioPolicyManager: AudioAnt: outProfile with name: usb_accessory output
06-06 21:51:09.884 16876 16876 D APM_AudioPolicyManager: AudioAnt: supportedDevices with name: USB Host Out
06-06 21:51:09.884 16876 16876 D APM_AudioPolicyManager: AudioAnt: outProfile with name: usb_device output
06-06 21:51:09.884 16876 16876 D APM_AudioPolicyManager: AudioAnt: supportedDevices with name: USB Device Out
06-06 21:51:09.885 16876 16876 D APM_AudioPolicyManager: AudioAnt: supportedDevices with name: USB Headset Out
06-06 21:51:09.885 16876 16876 D APM_AudioPolicyManager: AudioAnt: loadHwModule with module name r_submix
06-06 21:51:09.888 16876 16876 D APM_AudioPolicyManager: AudioAnt: outProfile with name: r_submix output
06-06 21:51:09.888 16876 16876 D APM_AudioPolicyManager: AudioAnt: supportedDevices with name: Remote Submix Out

        可以看到此时系统已经创建了多个AudioOut线程(主进程为audioservice),随后如果应用创建了AudioTrack,就可以根据strategy绑定到相关线程,触发或者加入到播放/录制线程。

auto8678p1_64_bsp_vm:/ # ps -ef | grep audioserver
audioserver  16876     1 0 21:51:04 ?     00:00:02 audioserver

auto8678p1_64_bsp_vm:/ # ps -T -p 16876
USER           PID   TID  PPID        VSZ    RSS WCHAN            ADDR S CMD
audioserver  16876 16876     1   12552792  50996 binder_th+          0 S audioserver
audioserver  16876 16884     1   12552792  50996 binder_th+          0 S binder:16876_1
audioserver  16876 16885     1   12552792  50996 futex_wai+          0 S AudioFlinger_Pa
audioserver  16876 16886     1   12552792  50996 binder_th+          0 S binder:16876_2
audioserver  16876 16887     1   12552792  50996 binder_th+          0 S HwBinder:16876_
audioserver  16876 16888     1   12552792  50996 binder_th+          0 S HwBinder:16876_
audioserver  16876 16889     1   12552792  50996 binder_th+          0 S HwBinder:16876_
audioserver  16876 16891     1   12552792  50996 futex_wai+          0 S AudioUtilThread
audioserver  16876 16892     1   12552792  50996 futex_wai+          0 S ApmAudio
audioserver  16876 16893     1   12552792  50996 futex_wai+          0 S ApmOutput
audioserver  16876 16913     1   12552792  50996 futex_wai+          0 S TimerThread
audioserver  16876 16914     1   12552792  50996 futex_wai+          0 S AudioOut_D
audioserver  16876 16915     1   12552792  50996 futex_wai+          0 S AudioOut_15
audioserver  16876 16916     1   12552792  50996 futex_wai+          0 S AudioOut_1D
audioserver  16876 16917     1   12552792  50996 futex_wai+          0 S AudioOut_25
audioserver  16876 16918     1   12552792  50996 futex_wai+          0 S AudioOut_2D
audioserver  16876 16919     1   12552792  50996 futex_wai+          0 S AudioOut_35
audioserver  16876 16920     1   12552792  50996 futex_wai+          0 S AudioOut_3D
audioserver  16876 16921     1   12552792  50996 futex_wai+          0 S AudioOut_45
audioserver  16876 16922     1   12552792  50996 futex_wai+          0 S AudioOut_4D
audioserver  16876 16923     1   12552792  50996 futex_wai+          0 S AudioOut_55
audioserver  16876 16924     1   12552792  50996 futex_wai+          0 S AudioOut_5D
audioserver  16876 16925     1   12552792  50996 futex_wai+          0 S AudioOut_65
audioserver  16876 16926     1   12552792  50996 futex_wai+          0 S AudioOut_6D
audioserver  16876 16927     1   12552792  50996 futex_wai+          0 S AudioOut_75
audioserver  16876 16928     1   12552792  50996 futex_wai+          0 S AudioOut_7D
audioserver  16876 16929     1   12552792  50996 futex_wai+          0 S AudioOut_85
audioserver  16876 16930     1   12552792  50996 futex_wai+          0 S AudioOut_8D
audioserver  16876 16945     1   12552792  50996 binder_th+          0 S binder:16876_3
audioserver  16876 16948     1   12552792  50996 binder_th+          0 S binder:16876_4
audioserver  16876 17743     1   12552792  50996 binder_th+          0 S binder:16876_5

总结

整体音频链路的准备工作暂时画上一个句号,复杂但是容易理解。音频服务端已经准备就绪,等待音频客户端(AudioTrack/AudioRecord)的加入并开始奇妙的音频之旅。

猜你喜欢

转载自blog.csdn.net/yong_i7/article/details/140405074