首页 > 其他分享 >AudioFlinger构造函数解析

AudioFlinger构造函数解析

时间:2024-06-13 10:11:50浏览次数:17  
标签:初始化 UNIQUE 解析 false use AudioFlinger AUDIO ID 构造函数

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 对象在创建时的正确初始化和配置,有助于系统的稳定性和性能。

标签:初始化,UNIQUE,解析,false,use,AudioFlinger,AUDIO,ID,构造函数
From: https://www.cnblogs.com/gzcwin/p/18245319

相关文章

  • 从源码到市场:数字人技术源头厂商全解析
    随着数字人直播的热度持续上涨,应用场景日益丰富,数字人系统OEM源码(源码部署:ai6ai69)模式作为最常见的入局方式之一,备受瞩目。本文将深入探讨数字人技术源头厂商的技术原理和应用优势,以及如何选择合适的数字人源码公司。一、数字人技术原理数字人技术基于人工智能和计算机图形......
  • 【文档智能 & RAG】RAG增强之路:增强PDF解析并结构化技术路线方案及思路
    前言现阶段,尽管大模型在生成式问答上取得了很大的成功,但由于大部分的数据都是私有数据,大模型的训练及微调成本非常高,RAG的方式逐渐成为落地应用的一种重要的选择方式。然而,如何准确的对文档进行划分chunks,成为一种挑战,在现实中,大部分的专业文档都是以PDF格式存储,低精度的......
  • 利用cJSON库解析http返回参数
    利用cJSON库解析http返回参数在C语言中,使用cJSON库来解析HTTP响应返回的JSON参数通常涉及几个步骤:发送HTTP请求(可以利用soket库进行http请求)接收HTTP响应的数据将接收到的数据作为字符串传递给cJSON库进行解析使用cJSONAPI访问和提取JSON数据以下是一个示例,展示了如何使......
  • 深入解析 JMeter TPS 测试:从理论到实践
    前言作为一名测试工程师,理解并能够准确测量每秒事务数(TransactionsPerSecond,TPS)是确保系统性能的关键指标之一。本文将详细介绍如何使用ApacheJMeter进行TPS测试,包括理论基础、配置步骤和结果分析。什么是TPS?TPS(TransactionsPerSecond)表示系统每秒能够处理的事务......
  • 掌握JMeter:深入解析如何提取和利用JSON数据
    前言ApacheJMeter不仅是一个功能强大的性能测试工具,它还可以用于提取和处理响应中的数据。对于现代Web应用,JSON(JavaScriptObjectNotation)已经成为主要的数据交换格式。本文将详细介绍如何在JMeter中提取JSON数据,并将其用于后续的请求或断言。环境准备在开始之前,请确保已经......
  • 域名解析很重要吗?
    互联网已经成为我们生活和工作中不可或缺的一部分。当我们畅游在网络世界时,经常会听到一个术语——域名解析。一、域名是什么?域名,简单来说,就是互联网上识别和定位计算机的层次结构式的字符标识。它就如同是网络世界里的“地址”。我们可以将其类比为现实世界中的地址。在现实中......
  • AIGC绘画设计:深入浅出完整解析Stable Diffusion(SD)核心基础知识
    心血来潮再加上想要督促自己,所以决定开始搞AI绘画技术的分享。如果觉得我写的好,又很久没更新,请多点我,因为可能我的懒癌又犯了,哈哈哈哈哈......没有本人帅,十分之一都没有不多废话,切入主题。学一门技术什么最难?当然是入门最难!从0到1,远远比从1到100要难一百倍,为啥?因为你之前......
  • Ton 区块链的官方 类ERC20-Token 智能合约代码-Transfer部分解析
    作者:林冠宏/指尖下的幽灵。转载者,请:务必标明出处。掘金:https://juejin.im/user/1785262612681997GitHub:https://github.com/af913337456/出版的书籍:《1.0-区块链DApp开发实战》《2.0-区块链DApp开发:基于公链》Ton区块链的官方类ERC20-Token智能合约代码-Trans......
  • 浅拷贝与深拷贝全面解析及实战
    在JavaScript学习中,拷贝是很重要的一个知识点。拷贝主要分为浅拷贝(ShallowCopy)和深拷贝(DeepCopy)。本文将阐述两者的概念,还将通过手写示例深入探讨如何实现这两种拷贝方式,以及它们在实际应用中的考量。浅拷贝:表面级复制浅拷贝只复制对象的第一层属性,对于嵌套对象或数组,仅复......
  • TimerWheel(计时轮)在Rust中的实现及源码解析
    计时器轮(TimerWheel),模拟时钟格式组成的高效计时器TimerWheel算法原理环形数据结构:TimerWheel,即时间轮,是一个环形的数据结构,类似于时钟的面,被等分为多个格子或槽位(slot)。槽位时间间隔:每个槽位代表一个固定的时间间隔,例如1毫秒、1秒等。这个时间间隔决定了定时器的精度。......