AudioFlinger

概述

    AudioFlinger向下访问AudioHardware,实现输出音频数据,控制音频参数。同时,
AudioFlinger向上通过IAudioFinger接口提供服务。所以,AudioFlinger在Android的
音频系统框架中起着承上启下的作用,地位相当重要。

功能描述

AudioFlinger初始化

AudioFlinger::AudioFlinger

AudioFlinger::AudioFlinger() : BnAudioFlinger(),
        mAudioHardware(0), mMasterVolume(1.0f), mMasterMute(false), mNextUniqueId(1)
{
    // 获取hardware模块对象
    mHardwareStatus = AUDIO_HW_IDLE;
    mAudioHardware = AudioHardwareInterface::create();
    mHardwareStatus = AUDIO_HW_INIT;
    
    if (mAudioHardware->initCheck() == NO_ERROR) {
        // open 16-bit output stream for s/w mixer
        mMode = AudioSystem::MODE_NORMAL;
        setMode(mMode);

        setMasterVolume(1.0f);
        setMasterMute(false);
    } else {
    }
}

音轨抽象类和共享内存

AudioFlinger::ThreadBase::TrackBase::TrackBase

AudioFlinger::ThreadBase::TrackBase::TrackBase(
            ......
            int sessionId) : RefBase(), ......
{
    ......
    if (client != NULL) {
        mCblkMemory = client->heap()->allocate(size);
        if (mCblkMemory != 0) {
            mCblk = static_cast<audio_track_cblk_t *>(mCblkMemory->pointer());
            if (mCblk) {
                // C++的new操作符的替换,在特定的mCblk对象上分配内存
                new(mCblk) audio_track_cblk_t();
                ......
            }
        } else {
            return;
        }
    } else {
        mCblk = (audio_track_cblk_t *)(new uint8_t[size]);
        if (mCblk) {
            // C++的new操作符的替换,在特定的mCblk对象上分配内存
            new(mCblk) audio_track_cblk_t();
            ......
        }
    }
}

AudioFlinger::PlaybackThread::Track::Track

AudioFlinger::PlaybackThread::Track::Track(
            ......
            int sessionId) : TrackBase(thread, ......)
{
    if (mCblk != NULL) {
        sp<ThreadBase> baseThread = thread.promote();
        if (baseThread != 0) {
            PlaybackThread *playbackThread = (PlaybackThread *)baseThread.get();
            mName = playbackThread->getTrackName_l();
            mMainBuffer = playbackThread->mixBuffer();
        }
        if (mName < 0) {
        }
        mVolume[0] = 1.0f;
        mVolume[1] = 1.0f;
        mStreamType = streamType;
        mCblk->frameSize = audio_is_linear_pcm(format) ? mChannelCount * sizeof(int16_t) : sizeof(uint8_t);
    }
}

AudioFlinger::RecordThread::RecordTrack::RecordTrack

AudioFlinger::RecordThread::RecordTrack::RecordTrack(
            ......
            int sessionId) : TrackBase(thread, ......),
{
    if (mCblk != NULL) {
       if (format == AUDIO_FORMAT_PCM_16_BIT) {
           mCblk->frameSize = mChannelCount * sizeof(int16_t);
       } else if (format == AUDIO_FORMAT_PCM_8_BIT) {
           mCblk->frameSize = mChannelCount * sizeof(int8_t);
       } else {
           mCblk->frameSize = sizeof(int8_t);
       }
    }
}

音频输出流程

创建硬件抽象层的I/O对象

AudioSystem::getOutput

audio_io_handle_t AudioSystem::getOutput(audio_stream_type_t stream, uint32_t samplingRate,
                                    uint32_t format, uint32_t channels,
                                    audio_policy_output_flags_t flags)
{
    audio_io_handle_t output = 0;
    if ((flags & AUDIO_POLICY_OUTPUT_FLAG_DIRECT) == 0 &&
        ((stream != AUDIO_STREAM_VOICE_CALL && stream != AUDIO_STREAM_BLUETOOTH_SCO) ||
         channels != AUDIO_CHANNEL_OUT_MONO ||
         (samplingRate != 8000 && samplingRate != 16000))) {
        Mutex::Autolock _l(gLock);
        // 如果有符合条件的io句柄,则在容器中查找
        output = AudioSystem::gStreamOutputMap.valueFor(stream);
    }
    if (output == 0) {
        const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
        if (aps == 0) return 0;
        // 否则,调用IAudioPolicyService接口,创建一个新的audio_io_handle_t
        output = aps->getOutput(stream, samplingRate, format, channels, flags);
        if ((flags & AUDIO_POLICY_OUTPUT_FLAG_DIRECT) == 0) {
            Mutex::Autolock _l(gLock);
            // 加入到容器中,以便下次快速获取
            AudioSystem::gStreamOutputMap.add(stream, output);
        }
    }
    return output;
}

AudioPolicyService::getOutput

audio_io_handle_t AudioPolicyService::getOutput(AudioSystem::stream_type stream,
                                    uint32_t samplingRate, uint32_t format,
                                    uint32_t channels, AudioSystem::output_flags flags)
{
    if (mpPolicyManager == NULL) {
        return 0;
    }
    Mutex::Autolock _l(mLock);
    return mpPolicyManager->getOutput(stream, samplingRate, format, channels, flags);
}

播放线程初始化

AudioFlinger::openOutput

int AudioFlinger::openOutput(uint32_t *pDevices, uint32_t *pSamplingRate,
                                uint32_t *pFormat, uint32_t *pChannels,
                                uint32_t *pLatencyMs, uint32_t flags)
{
    ......
    Mutex::Autolock _l(mLock);
    AudioStreamOut *output = mAudioHardware->openOutputStream(*pDevices,
                                                             (int *)&format,
                                                             &channels,
                                                             &samplingRate,
                                                             &status);
    ......
    if (output != 0) {
        int id = nextUniqueId();
        if ((flags & AudioSystem::OUTPUT_FLAG_DIRECT) ||
            (format != AudioSystem::PCM_16_BIT) ||
            (channels != AudioSystem::CHANNEL_OUT_STEREO)) {
            // 创建DirectOutputThread
            thread = new DirectOutputThread(this, output, id, *pDevices);
        } else {
            // 创建MixerThread
            thread = new MixerThread(this, output, id, *pDevices);
        }
        // 加入线程ID
        mPlaybackThreads.add(id, thread);

        // 通知上层i/o配置发生变化 
        thread->audioConfigChanged_l(AudioSystem::OUTPUT_OPENED);
        return id;
    }

    return 0;
}

通过TrackHandle播放

AudioFlinger::createTrack

sp<IAudioTrack> AudioFlinger::createTrack(
        ......
        status_t *status)
{
    sp<PlaybackThread::Track> track;
    sp<TrackHandle> trackHandle;
    sp<Client> client;
    wp<Client> wclient;

    if (streamType >= AUDIO_STREAM_CNT) {
        lStatus = BAD_VALUE;
        goto Exit;
    }

    Mutex::Autolock _l(mLock);
    // 查找音频输出的工作线程
    PlaybackThread *thread = checkPlaybackThread_l(output);
    PlaybackThread *effectThread = NULL;
    if (thread == NULL) {
        LOGE("unknown output thread");
        lStatus = BAD_VALUE;
        goto Exit;
    }

    sp<PlaybackThread::Track> track;
    sp<TrackHandle> trackHandle;
    ......
    {
        track = thread->createTrack_l(client, streamType, sampleRate, format,
                channelCount, frameCount, sharedBuffer, lSessionId, &lStatus);

        // move effect chain to this output thread if an effect on same session was waiting
        // for a track to be created
        if (lStatus == NO_ERROR && effectThread != NULL) {
            Mutex::Autolock _dl(thread->mLock);
            Mutex::Autolock _sl(effectThread->mLock);
            moveEffectChain_l(lSessionId, effectThread, thread, true);
        }
    }
    
    if (lStatus == NO_ERROR) {
        // 创建TrackHandle
        trackHandle = new TrackHandle(track);
    } else {
        ......
    }

Exit:
    ......
    return trackHandle;
}

AudioFlinger::checkPlaybackThread_l

AudioFlinger::PlaybackThread *AudioFlinger::checkPlaybackThread_l(int output) const
{
    PlaybackThread *thread = NULL;
    if (mPlaybackThreads.indexOfKey(output) >= 0) {
        thread = (PlaybackThread *)mPlaybackThreads.valueFor(output).get();
    }
    return thread;
}

AudioFlinger::PlaybackThread::createTrack_l

sp<AudioFlinger::PlaybackThread::Track>  AudioFlinger::PlaybackThread::createTrack_l(
        ......
        status_t *status)
{
    sp<Track> track;
    status_t lStatus;

    ......
    { 
        Mutex::Autolock _l(mLock);
        ...... 
        // 创建Track
        track = new Track(this, client, streamType, sampleRate, format,
                channelCount, frameCount, sharedBuffer, sessionId);
        if (track->getCblk() == NULL || track->name() < 0) {
            lStatus = NO_MEMORY;
            goto Exit;
        }
        // 将新创建的Track加入内部数组
        mTracks.add(track);

        sp<EffectChain> chain = getEffectChain_l(sessionId);
        if (chain != 0) {
            track->setMainBuffer(chain->inBuffer());
            chain->setStrategy(AudioSystem::getStrategyForStream((AudioSystem::stream_type)track->type()));
        }
    }
    lStatus = NO_ERROR;

Exit:
    ......
    return track;
}

播放线程堆栈图

音频采集流程

创建硬件抽象层的I/O对象

AudioSystem::getInput

audio_io_handle_t AudioSystem::getInput(int inputSource,
                                    uint32_t samplingRate,
                                    uint32_t format,
                                    uint32_t channels,
                                    audio_in_acoustics_t acoustics,
                                    int sessionId)
{
    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
    if (aps == 0) return 0;
    return aps->getInput(inputSource, samplingRate, format, channels, acoustics, sessionId);
}

AudioPolicyService::getInput

audio_io_handle_t AudioPolicyService::getInput(int inputSource,
                                    uint32_t samplingRate, uint32_t format,
                                    uint32_t channels, AudioSystem::audio_in_acoustics acoustics)
{
    if (mpPolicyManager == NULL) {
        return 0;
    }
    Mutex::Autolock _l(mLock);
    return mpPolicyManager->getInput(inputSource, samplingRate, format, channels, acoustics);
}

录音线程初始化

AudioFlinger::openInput

int AudioFlinger::openInput(uint32_t *pDevices, uint32_t *pSamplingRate,
                                uint32_t *pFormat, uint32_t *pChannels,
                                uint32_t acoustics)
{
    ......
    Mutex::Autolock _l(mLock);
    AudioStreamIn *input = 
        mAudioHardware->openInputStream(*pDevices, (int *)&format,
                                        &channels, &samplingRate, &status, 
                                        (AudioSystem::audio_in_acoustics)acoustics);

    if (input != 0) {
        int id = nextUniqueId();
        // 创建RecordThread线程
        thread = new RecordThread(this, input, reqSamplingRate, reqChannels, id);
        // 加入线程列表
        mRecordThreads.add(id, thread);
        ...... 
        input->standby();

        // 通知i/o设备变更
        thread->audioConfigChanged_l(AudioSystem::INPUT_OPENED);
        return id;
    }

    return 0;
}

通过RecordHandle录音

AudioFlinger::openRecord

sp<IAudioRecord> AudioFlinger::openRecord(
        pid_t pid,
        int input,
        uint32_t sampleRate,
        uint32_t format,
        uint32_t channelMask,
        int frameCount,
        uint32_t flags,
        int *sessionId,
        status_t *status)
{
    sp<RecordThread::RecordTrack> recordTrack;
    sp<RecordHandle> recordHandle;
    RecordThread *thread;
    ......

    { 
        Mutex::Autolock _l(mLock);
        // 根据io句柄获取一个线程对象
        thread = checkRecordThread_l(input);

        // 创建一个RecordTrack
        recordTrack = thread->createRecordTrack_l(client, sampleRate, format,
                                                channelMask, frameCount, flags,
                                                lSessionId, &lStatus);
    }

    // 创建一个RecordHandle对象
    recordHandle = new RecordHandle(recordTrack);

Exit:
    ...... 
    return recordHandle;
}

AudioFlinger::checkRecordThread_l

AudioFlinger::RecordThread *AudioFlinger::checkRecordThread_l(int input) const
{
    RecordThread *thread = NULL;
    if (mRecordThreads.indexOfKey(input) >= 0) {
        thread = (RecordThread *)mRecordThreads.valueFor(input).get();
    }
    return thread;
}

AudioFlinger::RecordThread::createRecordTrack_l

sp<AudioFlinger::RecordThread::RecordTrack> AudioFlinger::RecordThread::createRecordTrack_l(
        ......
        status_t *status)
{
    sp<RecordTrack> track;
    status_t lStatus;

    lStatus = initCheck();
    if (lStatus != NO_ERROR) {
        goto Exit;
    }

    { // scope for mLock
        Mutex::Autolock _l(mLock);

        track = new RecordTrack(this, client, sampleRate,
                      format, channelMask, frameCount, flags, sessionId);

        if (track->getCblk() == NULL) {
            lStatus = NO_MEMORY;
            goto Exit;
        }

        mTrack = track.get();
        // disable AEC and NS if the device is a BT SCO headset supporting those pre processings
        bool suspend = audio_is_bluetooth_sco_device(
                (audio_devices_t)(mDevice & AUDIO_DEVICE_IN_ALL)) && mAudioFlinger->btNrecIsOff();
        setEffectSuspended_l(FX_IID_AEC, suspend, sessionId);
        setEffectSuspended_l(FX_IID_NS, suspend, sessionId);
    }
    lStatus = NO_ERROR;

Exit:
    return track;
}