深入解析 Android 音频策略:onNewAudioModulesAvailableInt 的全链路探索

请先阅读 AudioFlinger 与 Audio HAL 的“握手”及硬件发现全链路

1. 核心流程总览:从扫描到激活

在 Android 音频策略管理器(AudioPolicyManager)中,onNewAudioModulesAvailableInt 是一个承上启下的核心函数。它的核心任务是将 XML 配置文件中的“静态描述”转化为系统中“动态可用”的音频资源。

本分析基于以下环境日志:
log路径: /home/leo/data_4t/debug/03.work/26-02_09--02_14/test_audio_channel/log/android/logcat.log


2. 核心源码级深度解析:onNewAudioModulesAvailableInt

如果您对 mHwModulesAll 的初始加载过程尚不熟悉,建议先阅读前置文章:

2.1 源码全貌与关键点注解

 /**
  * 函数背景:
  * 此函数是 Android 音频策略管理器的“拓扑扫描仪”。
  * 它的核心任务是扫描系统所有预定义的音频硬件模块,并驱动 HAL 完成加载。
  */
 void AudioPolicyManager::onNewAudioModulesAvailableInt(DeviceVector *newDevices)
 {
     // 遍历从 XML 解析出的全量硬件模块列表
     for (const auto& hwModule : mHwModulesAll) {
         // 去重检查:防止重复加载已激活的模块
         if (std::find(mHwModules.begin(), mHwModules.end(), hwModule) != mHwModules.end()) {
             continue;
         }

         /**
          * 【重点分析点 1:驱动加载入口】
          * 逻辑:通过 mpClientInterface (即 AudioPolicyService) 通知 AudioFlinger。
          * 动作:AudioFlinger 执行 dlopen 加载厂商的 audio.primary.xxx.so 库。
          */
         hwModule->setHandle(mpClientInterface->loadHwModule(hwModule->getName()));

         // 容错处理:如果 HAL 库加载失败,则跳过该模块
         if (hwModule->getHandle() == AUDIO_MODULE_HANDLE_NONE) {
             ALOGW("could not open HW module %s", hwModule->getName());
             continue;
         }

         // 将加载成功的模块加入活跃列表
         mHwModules.push_back(hwModule);

         /**
          * 阶段一:输出能力探测 (Output Profiles)。
          * 遍历每一个 mixPort,验证其支持的采样率、格式等是否能真正被底层接收。
          */
         for (const auto& outProfile : hwModule->getOutputProfiles()) {
             ALOGV("%s: Intializing output profile(mixport): %s", __func__, (outProfile->getTagName()).c_str());

             // 检查并发上限 (maxOpenCount)
             if (!outProfile->canOpenNewIo()) {
                 ALOGE("Invalid Output profile max open count %u for profile %s",
                       outProfile->maxOpenCount, outProfile->getTagName().c_str());
                 continue;
             }

             // 检查是否有关联的物理设备
             if (!outProfile->hasSupportedDevices()) {
                 ALOGW("Output profile contains no device on module %s", hwModule->getName());
                 continue;
             }

             // TTS/超声波能力特殊标记
             if ((outProfile->getFlags() & AUDIO_OUTPUT_FLAG_TTS) != 0 ||
                 (outProfile->getFlags() & AUDIO_OUTPUT_FLAG_ULTRASOUND) != 0) {
                 mTtsOutputAvailable = true;
             }

             // 筛选当前通路支持且在系统全量设备表中的设备
             const DeviceVector &supportedDevices = outProfile->getSupportedDevices();
             DeviceVector availProfileDevices = supportedDevices.filter(mOutputDevicesAll);
             sp<DeviceDescriptor> supportedDevice = 0;

             // 优先选择默认输出设备进行“开流测试”
             if (supportedDevices.contains(mDefaultOutputDevice)) {
                 supportedDevice = mDefaultOutputDevice;
             } else {
                 if (availProfileDevices.isEmpty()) {
                     continue;
                 }
                 supportedDevice = availProfileDevices.itemAt(0);
             }

             if (!mOutputDevicesAll.contains(supportedDevice)) {
                 continue;
             }

             /**
              * 【重点分析点 2:物理链路试开流】
              * 目的:真正去调用 AudioFlinger 的 openOutput 接口。
              * 意义:只有底层 HAL 成功返回 OK,系统才认为这条硬件通路是真实的、可用的。
              */
             sp<SwAudioOutputDescriptor> outputDesc = new SwAudioOutputDescriptor(outProfile,
                                                                                  mpClientInterface);
             audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
             status_t status = outputDesc->open(nullptr /* halConfig */, nullptr /* mixerConfig */,
                                                DeviceVector(supportedDevice),
                                                AUDIO_STREAM_DEFAULT,
                                                AUDIO_OUTPUT_FLAG_NONE, &output);

             // 如果底层物理链路打不开(如 DSP 还没准备好),则跳过此通路
             if (status != NO_ERROR) {
                 ALOGW("Cannot open output stream for devices %s on hw module %s",
                       supportedDevice->toString().c_str(), hwModule->getName());
                 continue;
             }

             /**
              * 阶段二:设备激活与挂载。
              * 只有开流成功的通路,其关联的设备才会被加入到 mAvailableOutputDevices 中。
              */
             for (const auto &device : availProfileDevices) {
                 if (!device->isAttached()) {
                     device->attach(hwModule); // 建立模块绑定关系
                     mAvailableOutputDevices.add(device); // 加入可用设备池
                     device->setEncapsulationInfoFromHal(mpClientInterface);
                     if (newDevices) newDevices->add(device);
                     // 通知路由引擎 (Engine):新设备已上线,可以参与路由决策了
                     setEngineDeviceConnectionState(device, AUDIO_POLICY_DEVICE_STATE_AVAILABLE);
                 }
             }

             // 确立系统的“主输出”地位
             if (mPrimaryOutput == nullptr &&
                     outProfile->getFlags() & AUDIO_OUTPUT_FLAG_PRIMARY) {
                 mPrimaryOutput = outputDesc;
             }

             /**
              * 阶段三:资源动态优化。
              * DIRECT 通路验证完即关(省电),普通混合通路保持开启(提升响应速度)。
              */
             if ((outProfile->getFlags() & AUDIO_OUTPUT_FLAG_DIRECT) != 0) {
                 outputDesc->close();
             } else {
                 addOutput(output, outputDesc);
                 // 设置初始路由
                 setOutputDevices(outputDesc,
                                  DeviceVector(supportedDevice),
                                  true,
                                  0,
                                  NULL);
             }
         }

         /**
          * 阶段四:输入能力探测 (Input Profiles)。
          * 逻辑与输出侧镜像,重点验证麦克风等输入通道。
          */
         for (const auto& inProfile : hwModule->getInputProfiles()) {
             if (!inProfile->canOpenNewIo()) {
                 continue;
             }
             if (!inProfile->hasSupportedDevices()) {
                 continue;
             }

             const DeviceVector &supportedDevices = inProfile->getSupportedDevices();
             DeviceVector availProfileDevices = supportedDevices.filter(mInputDevicesAll);
             if (availProfileDevices.isEmpty()) {
                 continue;
             }

             sp<AudioInputDescriptor> inputDesc =
                     new AudioInputDescriptor(inProfile, mpClientInterface);
             audio_io_handle_t input = AUDIO_IO_HANDLE_NONE;

             // 试开录音流
             status_t status = inputDesc->open(nullptr,
                                               availProfileDevices.itemAt(0),
                                               AUDIO_SOURCE_MIC,
                                               AUDIO_INPUT_FLAG_NONE,
                                               &input);
             if (status != NO_ERROR) {
                 continue;
             }

             for (const auto &device : availProfileDevices) {
                 if (!device->isAttached()) {
                     device->attach(hwModule);
                     device->importAudioPortAndPickAudioProfile(inProfile, true);
                     mAvailableInputDevices.add(device);
                     if (newDevices) newDevices->add(device);
                     setEngineDeviceConnectionState(device, AUDIO_POLICY_DEVICE_STATE_AVAILABLE);
                 }
             }
             // 录音流验证完立即关闭
             inputDesc->close();
         }
     }

     /**
      * 阶段五:空间音频 (Spatializer) 策略检查。
      */
     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);
     }
 }

3. 跨进程的奥秘:mpClientInterface->loadHwModule

loadHwModule 是 APM 呼叫外界执行动作的“手臂”。

详细调用链可参考:

核心路径总结:

  1. APM 调用 mpClientInterface->loadHwModule
  2. AudioPolicyService 转发请求给 AudioFlinger
  3. AudioFlinger 最终触发 mDevicesFactoryHal->openDevice(name, &dev)
  4. HIDL 接口:调用 factory->openPrimaryDevice 跨进程进入 audio.hal 服务进程。

4. 服务端实现:Audio HAL 如何 handle openPrimaryDevice

core/all-versions/default/DevicesFactory.cpp 中,我们能看到 HAL 层的具体响应:

#define AUDIO_HARDWARE_MODULE_ID_PRIMARY "primary"

// 响应 HIDL 请求:打开主音频设备
Return<void> DevicesFactory::openPrimaryDevice(openPrimaryDevice_cb _hidl_cb) {
    return openDevice<PrimaryDevice>(AUDIO_HARDWARE_MODULE_ID_PRIMARY, _hidl_cb);
}

Return<void> DevicesFactory::openDevice(const char* moduleName, Callback _hidl_cb) {
    audio_hw_device_t* halDevice;
    Result retval(Result::INVALID_ARGUMENTS);
    sp<DeviceShim> result;
    
    // 1. 加载真正的底层 .so 驱动接口
    int halStatus = loadAudioInterface(moduleName, &halDevice);
    if (halStatus == OK) {
        // 2. 将原始 C 风格的 halDevice 包装成 HIDL 对象 DeviceShim
        result = new DeviceShim(halDevice);
        // 设置音频线程的调度策略为实时(ANDROID_PRIORITY_AUDIO)
        android::hardware::setMinSchedulerPolicy(result, SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
        retval = Result::OK;
    } 
    // ...
    _hidl_cb(retval, result); // 通过回调将结果返回给客户端
    return Void();
}

int DevicesFactory::loadAudioInterface(const char* if_name, audio_hw_device_t** dev) {
    const hw_module_t* mod;
    int rc;

    // A. 加载硬件模块描述符
    rc = hw_get_module_by_class(AUDIO_HARDWARE_MODULE_ID, if_name, &mod);
    
    // B. 调用厂商实现的 open 方法(即 adev_open)
    rc = audio_hw_device_open(mod, dev);
    // ...
    return OK;
}

5. 厂商的具体实现:以高通 PAL 为例

在高通的方案中,audio_hw_device_open 最终会调到 hal-pal/AudioDevice.cpp 中的 adev_open

// 厂商实现的入口符号
struct audio_module HAL_MODULE_INFO_SYM = {
    .common = {
        .tag = HARDWARE_MODULE_TAG,
        .methods = &hal_module_methods, // 挂载方法表
    },
};

static struct hw_module_methods_t hal_module_methods = {
    .open = adev_open, // HAL 框架调用这里的 open
};

static int adev_open(const hw_module_t *module, const char *name __unused,
                     hw_device_t **device) {
    // ...
    // 1. 获取 AudioDevice 单例
    std::shared_ptr<AudioDevice> adevice = AudioDevice::GetInstance();

    // 2. 引用计数管理:如果已经初始化过,直接返回现有实例
    adevice->adev_init_mutex.lock();
    if (adevice->adev_init_ref_count != 0) {
        *device = adevice->GetAudioDeviceCommon();
        adevice->adev_init_ref_count++;
        adevice->adev_init_mutex.unlock();
        return 0;
    }

    // 3. 核心初始化:这是 AHAL 与底层 PAL 引擎握手的关键
    ret = adevice->Init(device, module); 

    // ...
    adevice->adev_init_mutex.unlock();
    return 0;
}

6. 总结:系统启动时的“蝴蝶效应”

通过上述源码解析,我们可以清晰地勾勒出音频设备“从无到有”的演进全链路:

  1. 解析期:APM 解析 audio_policy_configuration.xml,心中有了“蓝图”(mHwModulesAll)。
  2. 指令期:APM 调用 loadHwModule 发出加载指令。
  3. 穿梭期:信号跨越 APS -> AF -> HIDL -> HAL 服务进程。
  4. 激活期:底层调用 adev_open,高通 Init 启动 PAL 引擎。
  5. 验证期:APM 通过“试开流”(outputDesc->open)确认链路可用。
  6. 注册期:设备正式加入 mAvailableOutputDevices,从此 Android 系统的状态栏和设置界面才真正“认识”了这些硬件。

这种“静态配置 + 跨进程指令 + 动态链路验证”的设计,保证了 Android 音频系统在复杂硬件拓扑下的极高健壮性。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐