Android Framework 音频子系统(04)AudioFlinger启动分析

该系列文章总纲链接:专题分纲目录 Android Framework 音频子系统​​​​​​​


本章关键点总结 & 说明:

本章节主要关注➕ 以上思维导图左上 AudioFlinger启动分析 部分 即可。主要是对 AudioFlinger启动的分析,涉及从AudioFlinger启动到Audio构造器执行结束、AudioFlinger的loadHwModule分析(HAL操作)、AudioFlinger的openOutput实现(创建MixerThread),同时承接了上一节的部分流程分析。


1 从AudioFlinger启动到Audio构造器执行结束

AudioFlinger的启动是在Main_mediaserver.cpp中实现,代码如下:

int main(int argc __unused, char** argv)
{
    signal(SIGPIPE, SIG_IGN);
    char value[PROPERTY_VALUE_MAX];
    //...
    sp<ProcessState> proc(ProcessState::self());
    sp<IServiceManager> sm = defaultServiceManager();
    //...
    AudioFlinger::instantiate();//AudioFlinger
    MediaPlayerService::instantiate();
    CameraService::instantiate();
    AudioPolicyService::instantiate();//AudioPolicyService
    SoundTriggerHwService::instantiate();
    registerExtensions();
    ProcessState::self()->startThreadPool();
    IPCThreadState::self()->joinThreadPool();
	//...
}

这里专注分析AudioFlinger::instantiate()的实现,代码如下:

static void instantiate() { publish(); }

继续分析publish,代码如下:

    static status_t publish(bool allowIsolated = false) {
        sp<IServiceManager> sm(defaultServiceManager());
        return sm->addService(//注册服务到servicemanager中
                String16(SERVICE::getServiceName()),
                new SERVICE(), allowIsolated);
    }

这里将服务注册到service_manager 中。同时这里会 创建 一个AudioFlinger,即执行AudioFlinger的构造器,代码如下:

AudioFlinger::AudioFlinger()
    : BnAudioFlinger(),
      mPrimaryHardwareDev(NULL),
      //...
      mGlobalEffectEnableTime(0),
      mPrimaryOutputSampleRate(0)
{
    getpid_cached = getpid();
    char value[PROPERTY_VALUE_MAX];
	//...
}

主要是一些变量的初始化,之后主要看onFirstRef的实现,代码如下:

void AudioFlinger::onFirstRef()
{
    int rc = 0;
    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;
        }
    }
	//这里将AudioFlinger传递给PatchPanel,其他并没有做什么
    mPatchPanel = new PatchPanel(this);
    mMode = AUDIO_MODE_NORMAL;
}

经过上面的分析可以知道,AudioFlinger注册服务后 还是很被动的,并不会主动创建线程和执行操作。之后便一直等待被调用。这里基于上一章节的loadHwModule 和 openOutput 进行分析。


2 AudioFlinger的loadHwModule分析

这里继续上一章节af->loadHwModule(name);进行分析,AudioFlinger的loadHwModle代码实现如下:

audio_module_handle_t AudioFlinger::loadHwModule(const char *name)
{
    if (name == NULL) {
        return 0;
    }
    if (!settingsAllowed()) {
        return 0;
    }
    Mutex::Autolock _l(mLock);
    return loadHwModule_l(name);
}

这里继续分析loadHwModule_l,代码实现如下:

// loadHwModule_l() must be called with AudioFlinger::mLock held
audio_module_handle_t AudioFlinger::loadHwModule_l(const char *name)
{
    //是否已经加载过这个interface
    for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
        if (strncmp(mAudioHwDevs.valueAt(i)->moduleName(), name, strlen(name)) == 0) {
            ALOGW("loadHwModule() module %s already loaded", name);
            return mAudioHwDevs.keyAt(i);
        }
    }

    audio_hw_device_t *dev;
    //关键点:打开audio.primary.XXX.so,构造audio_hw_device
    int rc = load_audio_interface(name, &dev);
    //...
    mHardwareStatus = AUDIO_HW_INIT;
    //初始化
    rc = dev->init_check(dev);
    mHardwareStatus = AUDIO_HW_IDLE;
    AudioHwDevice::Flags flags = static_cast<AudioHwDevice::Flags>(0);
    //...
    audio_module_handle_t handle = nextUniqueId();
    //通过dev构建AudioHwDevice,将AudioHwDevice加入到mAudioHwDevs中
    mAudioHwDevs.add(handle, new AudioHwDevice(handle, name, dev, flags));

    return handle;
}

这里继续分析load_audio_interface,代码实现如下:

static int load_audio_interface(const char *if_name, audio_hw_device_t **dev)
{
    const hw_module_t *mod;
    int rc;

    //通过hw_get_module_by_class->load->dlopen->dlsym->dlclose)
    //获得第三方厂家库的hw_module_t结构体指针 &mod
    rc = hw_get_module_by_class(AUDIO_HARDWARE_MODULE_ID, if_name, &mod);
    //...
    //通过&mod构建audio_hw_device_t类型结构体 dev
    rc = audio_hw_device_open(mod, dev);
    //...
}

这里总结下 loadHwModule对硬件的封装:

  • AudioFlinger           : AudioHwDevice (放入mAudioHwDevs数组中)
  • audio_hw_hal.cpp   : audio_hw_device
  • 厂家                         : AudioHardware (派生自: AudioHardwareInterface)
  • AudioHwDevice      :对audio_hw_device的封装,
  • audio_hw_device     :函数的实现要通过AudioHardware类对象

3 AudioFlinger的openOutput实现

这里继续上一章节af->openOutput(module, output, config, devices, address, latencyMs, flags);进行分析,AudioFlinger的openOutput代码实现如下:

status_t AudioFlinger::openOutput(audio_module_handle_t module,
                                  audio_io_handle_t *output,
                                  audio_config_t *config,
                                  audio_devices_t *devices,
                                  const String8& address,
                                  uint32_t *latencyMs,
                                  audio_output_flags_t flags)
{
    //...
    Mutex::Autolock _l(mLock);
    //关键点
    sp<PlaybackThread> thread = openOutput_l(module, output, config, *devices, address, flags);
    if (thread != 0) {
        *latencyMs = thread->latency();

        // notify client processes of the new output creation
        thread->audioConfigChanged(AudioSystem::OUTPUT_OPENED);

        // the first primary output opened designates the primary hw device
        if ((mPrimaryHardwareDev == NULL) && (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
            ALOGI("Using module %d has the primary audio interface", module);
            mPrimaryHardwareDev = thread->getOutput()->audioHwDev;

            AutoMutex lock(mHardwareLock);
            mHardwareStatus = AUDIO_HW_SET_MODE;
            mPrimaryHardwareDev->hwDevice()->set_mode(mPrimaryHardwareDev->hwDevice(), mMode);
            mHardwareStatus = AUDIO_HW_IDLE;

            mPrimaryOutputSampleRate = config->sample_rate;
        }
        return NO_ERROR;
    }
    return NO_INIT;
}

这里专注openOutput_l的实现,代码如下:

sp<AudioFlinger::PlaybackThread> AudioFlinger::openOutput_l(audio_module_handle_t module,
                                                            audio_io_handle_t *output,
                                                            audio_config_t *config,
                                                            audio_devices_t devices,
                                                            const String8& address,
                                                            audio_output_flags_t flags)
{
    //查找相应的audio interface
    AudioHwDevice *outHwDev = findSuitableHwDev_l(module, devices);
    //...
    audio_hw_device_t *hwDevHal = outHwDev->hwDevice();
    if (*output == AUDIO_IO_HANDLE_NONE) {
        *output = nextUniqueId();
    }

    mHardwareStatus = AUDIO_HW_OUTPUT_OPEN;
    audio_stream_out_t *outStream = NULL;
    //对于每个module中每一个output profile,
    //如果flags不是特殊的则执行open_output_stream
    status_t status = hwDevHal->open_output_stream(hwDevHal,
                                                   *output,
                                                   devices,
                                                   flags,
                                                   config,
                                                   &outStream,
                                                   address.string());

    mHardwareStatus = AUDIO_HW_IDLE;

    //创建playbackThread
    if (status == NO_ERROR && outStream != NULL) {
        AudioStreamOut *outputStream = new AudioStreamOut(outHwDev, outStream, flags);

        PlaybackThread *thread;
        if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
            thread = new OffloadThread(this, outputStream, *output, devices);
        } else if ((flags & AUDIO_OUTPUT_FLAG_DIRECT)
                || !isValidPcmSinkFormat(config->format)
                || !isValidPcmSinkChannelMask(config->channel_mask)) {
            thread = new DirectOutputThread(this, outputStream, *output, devices);
        } else {
            //一般是创建混音线程,代表AudioStreamOut对象的output也传递进去了
            thread = new MixerThread(this, outputStream, *output, devices);
        }
        //将创建的线程添加到播放线程列表 mPlaybackThreads中
        mPlaybackThreads.add(*output, thread);
        return thread;
    }
    return 0;
}

这里最关键的是创建了一个MixerThread。这里的每一个线程都对应一个output。

发布了289 篇原创文章 · 获赞 47 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/vviccc/article/details/105275199