Android AudioFlinger(二)——AndroidAudio Flinger的启动流程

一、启动

audioflinger是整个Android音频系统的核心,起到了承上启下的作用,承上就是为上层应用提供了各种访问和管理的接口,启下就是通过HAL来管理各种音频设备。

首先我们来看AudioFlinger是如何启动的。

c 复制代码
int main(int argc __unused, char **argv)
{
    ......
    signal(SIGPIPE, SIG_IGN);

    ......
    sp<ProcessState> proc(ProcessState::self());
    sp<IServiceManager> sm = defaultServiceManager();
    ALOGI("ServiceManager: %p", sm.get());
    AudioFlinger::instantiate();
    AudioPolicyService::instantiate();
    if (mmapPolicy == AAUDIO_POLICY_AUTO || mmapPolicy == AAUDIO_POLICY_ALWAYS) {
        AAudioService::instantiate();
    }
    SoundTriggerHwService::instantiate();
    ProcessState::self()->startThreadPool();
    IPCThreadState::self()->joinThreadPool();
    }
}

这个audioserver主要做的就是把audio相关的一些服务给启动,我们仔细观察会发现同步路下还有一个rc文件

c 复制代码
service audioserver /system/bin/audioserver
    class core
    user audioserver
    # media gid needed for /dev/fm (radio) and for /data/misc/media (tee)
    group audio camera drmrpc inet media mediadrm net_bt net_bt_admin net_bw_acct
    ioprio rt 4
    writepid /dev/cpuset/foreground/tasks /dev/stune/foreground/tasks
    onrestart restart vendor.audio-hal-2-0
    # Keep the original service name for backward compatibility when upgrading
    # O-MR1 devices with framework-only.
    onrestart restart audio-hal-2-0

on property:vts.native_server.on=1
    stop audioserver
on property:vts.native_server.on=0
    start audioserver

这里就通过vts.native_server.on开控制audioserver的start/stop,兵器在启动的时候会restart audio-hal,这部分后面再探讨。

下面我们来看看 AudioFlinger::instantiate(),这里的instantiate其实不是AudioFlinger内部的静态函数,而是BinderService类的一个实现,像AudioFlinger、AudioPolicyService等几个服务都继承自这个统一的Binder服务类。

java 复制代码
class AudioFlinger :
    public BinderService<AudioFlinger>,
    public BnAudioFlinger

看名称可以知道这个就是实现了Binder跨进程通信相关的功能,看代码实际上他是一个模板类,其中instantiate用于把模板中的服务创建出来,然后添加到ServiceManager中。

c 复制代码
template<typename SERVICE>
class BinderService
{
public:
    static status_t publish(bool allowIsolated = false,
                            int dumpFlags = IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT) {
        sp<IServiceManager> sm(defaultServiceManager());
        return sm->addService(String16(SERVICE::getServiceName()), new SERVICE(), allowIsolated,
                              dumpFlags);
    }

    static void instantiate() { publish(); }

};

回过头来我们看看AudioFlinger的构造函数,其实里面基本没做什么,初始化了一些变量,还有log和debug相关的控制。

c 复制代码
AudioFlinger::AudioFlinger()
    : BnAudioFlinger(),
      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),
      mSystemReady(false)

那AudioFlinger实际是怎么启动工作的呢?刚刚我们提到了AudioFlinger继承BinderService,其实还集成了一个BnAudioFlinger,BnAudioFlinger又是由RefBase层层集成而来的,并且IServiceManager->addService的第二个参数是是一个强指针引用,(const sp&),所以AudioFlinger还具备了强指针的一个特性,就是第一次引用时调用onFirstRef。

c 复制代码
void AudioFlinger::onFirstRef()
{
    Mutex::Autolock _l(mLock);
    /* TODO: move all this work into an Init() function */
    char val_str[PROPERTY_VALUE_MAX] = { 0 };
    if (property_get("ro.audio.flinger_standbytime_ms", val_str, NULL) >= 0) {
        uint32_t int_val;
        if (1 == sscanf(val_str, "%u", &int_val)) {
            mStandbyTimeInNsecs = milliseconds(int_val);
        } else {
            mStandbyTimeInNsecs = kDefaultStandbyTimeInNsecs;
        }
    }
    mPatchPanel = new PatchPanel(this);
    mMode = AUDIO_MODE_NORMAL;
    gAudioFlinger = this;
}

ro.audio.flinger_standbytime_ms为用户调整standby时间提供了一个接口 。接着初始化了一些有效的变量,从这个时候开始,AudioFlinger就是一个有意义的实体了,其他进程就可以通过ServiceManager去访问AudioFlinger,并且调用其中的一些接口来驱使AudioFlinger执行音频的处理操作。

到这里audioflinger就启动完成了,后面我们来看下audioflinger如何对音频设备进行管理。

相关推荐
小蒜学长6 分钟前
“喵汪联盟”宠物领养系统的设计与实现(代码+数据库+LW)
java·spring boot·后端·宠物
程序员黑豆7 分钟前
Java字符串常量池完全指南:原理、intern()方法与性能优化最佳实践
java·前端·ai编程
AI人工智能+电脑小能手10 分钟前
大白话说Java设计模式-14-适配器模式(业务实战篇)
java·设计模式·适配器模式·系统兼容·多渠道对接
xbgRS3 小时前
springboot的自动装配
java·spring boot
嘻哈∠※10 小时前
0061基于 SpringBoot 的投稿与稿件处理系统设计与实现
java·spring boot·后端
白狐_79811 小时前
408数据结构第8章:排序②——性质对比秒杀、场景选择与外部排序
java·数据结构·算法
zander25811 小时前
LeetCode 84:柱状图中的最大矩形——单调栈如何确定左右边界
java·数据结构·算法
码匠许师傅12 小时前
【C++ 面试真题】聊聊 C++ 的拷贝构造与拷贝赋值
java·c++·面试
极创信息13 小时前
系统安全隐患全方位排查方案:标准化渗透测试全流程
java·opencv·struts·数据挖掘·eclipse·语音识别·hibernate
汉字萌萌哒14 小时前
2019CCF-CSP入门级C++试题解析
java·开发语言·c++