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
构造函数执行了以下主要任务:
- 初始化成员变量。
- 通过基于时间的机制初始化音频会话的唯一ID生成器,避免重启服务后ID冲突。
- 条件编译控制日志系统的初始化。
- 重置电池统计信息,确保服务启动时电池状态正确。
- 创建音频硬件设备和音效工厂的接口实例。
- 启动日志通知线程。
- 设置音频硬件HAL的进程ID,用于时间检查和性能监测。
- 记录构造函数调用事件,用于媒体指标和性能分析。
这些步骤共同确保了 AudioFlinger
对象在创建时的正确初始化和配置,有助于系统的稳定性和性能。