AudioFlinger构造函数解析

AudioFlinger::AudioFlinger()
    : mMediaLogNotifier(new AudioFlinger::MediaLogNotifier()),
      mPrimaryHardwareDev(NULL),
      mAudioHwDevs(NULL),
      mHardwareStatus(AUDIO_HW_IDLE),
      mMasterVolume(1.0f),
      mMasterMute(false),
      // mNextUniqueId(AUDIO_UNIQUE_ID_USE_MAX),
      mMode(AUDIO_MODE_INVALID),
      mBtNrecIsOff(false),
      mIsLowRamDevice(true),
      mIsDeviceTypeKnown(false),
      mTotalMemory(0),
      mClientSharedHeapSize(kMinimumClientSharedHeapSizeBytes),
      mGlobalEffectEnableTime(0),
      mPatchPanel(this),
      mDeviceEffectManager(this),
      mSystemReady(false)
{
    // Move the audio session unique ID generator start base as time passes to limit risk of
    // generating the same ID again after an audioserver restart.
    // This is important because clients will reuse previously allocated audio session IDs
    // when reconnecting after an audioserver restart and newly allocated IDs may conflict with
    // active clients.
    // Moving the base by 1 for each elapsed second is a good compromise between avoiding overlap
    // between allocation ranges and not reaching wrap around too soon.
    timespec ts{};
    clock_gettime(CLOCK_MONOTONIC, &ts);
    // zero ID has a special meaning, so start allocation at least at AUDIO_UNIQUE_ID_USE_MAX
    uint32_t movingBase = (uint32_t)std::max((long)1, ts.tv_sec);
    // unsigned instead of audio_unique_id_use_t, because ++ operator is unavailable for enum
    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;
    }

#if 1
    // FIXME See bug 165702394 and bug 168511485
    const bool doLog = false;
#else
    const bool doLog = property_get_bool("ro.test_harness", false);
#endif
    if (doLog) {
        mLogMemoryDealer = new MemoryDealer(kLogMemorySize, "LogWriters",
                MemoryHeapBase::READ_ONLY);
        (void) pthread_once(&sMediaLogOnce, sMediaLogInit);
    }

    // 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();

    mDevicesFactoryHal = DevicesFactoryHalInterface::create();
    mEffectsFactoryHal = EffectsFactoryHalInterface::create();

    mMediaLogNotifier->run("MediaLogNotifier");
    std::vector<pid_t> halPids;
    mDevicesFactoryHal->getHalPids(&halPids);
    TimeCheck::setAudioHalPids(halPids);

    // Notify that we have started (also called when audioserver service restarts)
    mediametrics::LogItem(mMetricsId)
        .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_CTOR)
        .record();
}

以下是对 AudioFlinger 构造函数的解析,以及对函数流程和功能的详细说明:

构造函数签名

AudioFlinger::AudioFlinger()

该构造函数用于初始化 AudioFlinger 类的实例。

初始化成员变量

构造函数使用初始化列表来初始化类的成员变量:

: mMediaLogNotifier(new AudioFlinger::MediaLogNotifier()), // 初始化日志通知对象
  mPrimaryHardwareDev(NULL), // 初始化主音频硬件设备指针为NULL
  mAudioHwDevs(NULL), // 初始化音频硬件设备列表指针为NULL
  mHardwareStatus(AUDIO_HW_IDLE), // 初始化硬件状态为闲置
  mMasterVolume(1.0f), // 初始化主音量为1.0(最大音量)
  mMasterMute(false), // 初始化主静音状态为未静音
  // mNextUniqueId(AUDIO_UNIQUE_ID_USE_MAX), // 注释掉的唯一ID初始化
  mMode(AUDIO_MODE_INVALID), // 初始化音频模式为无效
  mBtNrecIsOff(false), // 蓝牙降噪关闭状态初始化为false
  mIsLowRamDevice(true), // 低内存设备状态初始化为true
  mIsDeviceTypeKnown(false), // 设备类型已知状态初始化为false
  mTotalMemory(0), // 总内存初始化为0
  mClientSharedHeapSize(kMinimumClientSharedHeapSizeBytes), // 初始化客户端共享堆大小
  mGlobalEffectEnableTime(0), // 全局效果启用时间初始化为0
  mPatchPanel(this), // 初始化PatchPanel对象,传递当前对象指针
  mDeviceEffectManager(this), // 初始化设备效果管理器,传递当前对象指针
  mSystemReady(false) // 系统准备状态初始化为false

使用初始化列表有助于提高性能,并确保成员变量在构造函数体之前完成初始化。

重要逻辑

构造函数体内实现了一些重要的初始化和配置逻辑:

唯一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;
}

这段代码用于初始化音频会话的唯一ID生成器。通过基于时间的变量 movingBase,生成不同的唯一ID以避免重启服务后ID冲突的问题。

日志系统初始化

#if 1
    const bool doLog = false;
#else
    const bool doLog = property_get_bool("ro.test_harness", false);
#endif
if (doLog) {
    mLogMemoryDealer = new MemoryDealer(kLogMemorySize, "LogWriters",
            MemoryHeapBase::READ_ONLY);
    (void) pthread_once(&sMediaLogOnce, sMediaLogInit);
}

这段代码控制是否初始化日志系统,根据条件编译标志选择是否启用日志记录功能。

重置电池统计

BatteryNotifier::getInstance().noteResetAudio();

调用 BatteryNotifier 类的单例实例的 noteResetAudio 方法来重置电池统计信息。这一步的目的是在音频服务启动时清除可能的错误电池状态。

初始化硬件接口

mDevicesFactoryHal = DevicesFactoryHalInterface::create();
mEffectsFactoryHal = EffectsFactoryHalInterface::create();

创建用于与音频硬件设备和音效工厂进行交互的接口实例。

运行日志通知线程

mMediaLogNotifier->run("MediaLogNotifier");

启动 MediaLogNotifier 线程来处理日志通知。

设置音频硬件HAL进程ID

std::vector<pid_t> halPids;
mDevicesFactoryHal->getHalPids(&halPids);
TimeCheck::setAudioHalPids(halPids);

获取音频硬件HAL的进程ID并将其传递给 TimeCheck 类,以便进行时间检查和性能监测。

记录构造函数调用事件

mediametrics::LogItem(mMetricsId)
    .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_CTOR)
    .record();

记录构造函数调用事件,用于媒体指标和性能分析。

总结

AudioFlinger 构造函数执行了以下主要任务:

  1. 初始化成员变量。
  2. 通过基于时间的机制初始化音频会话的唯一ID生成器,避免重启服务后ID冲突。
  3. 条件编译控制日志系统的初始化。
  4. 重置电池统计信息,确保服务启动时电池状态正确。
  5. 创建音频硬件设备和音效工厂的接口实例。
  6. 启动日志通知线程。
  7. 设置音频硬件HAL的进程ID,用于时间检查和性能监测。
  8. 记录构造函数调用事件,用于媒体指标和性能分析。

这些步骤共同确保了 AudioFlinger 对象在创建时的正确初始化和配置,有助于系统的稳定性和性能。

posted on 2024-06-13 10:08  懒只是一种生活态度  阅读(21)  评论(0编辑  收藏  举报