Android Audio System深入探究之AudioFlinger(基于Android9)

AudioFlinger初始化分析

  • 1. AudioFlinger初始化
  • 2. AF中的createTrack
  • 3. AF中的openOutput
  • 4. TrackHandle分析
  • 5. AF中类结构分析
    • 5.1 AudioFlinger结构分析
    • 5.2 AF线程分析
    • 5.3 AF数据流模型
    • 5.4 Track类分析

1. AudioFlinger初始化

基于安全加强的考虑, 自Android6.0后,Audio模块便从 mediaserver进程中分离开,作为独立的进程运行,是为audioserver进程。
那么audioserver入口在哪呢?通过源码文件查找,我们找到了其模块位置

frameworks/av/media/audioserver

看下有那些文件组成, 使用tree命令

Android Audio System深入探究之AudioFlinger(基于Android9)_第1张图片
android6.0以后, google将init.rc文件做了拆分, 由模块独立管理其rc文件,不再由init进程集中管理, 这里audioserver.rc 便是audio系统的启动文件, 看下其内容

[–> audioserver.rc]

# 作为service启动,说明启动路径
service audioserver /system/bin/audioserver 
	# 核心
    class core
    #用户为audioserver
    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

再看audioserver的启动入口main函数

[–>main_audioserver.cpp]

int main(int argc __unused, char **argv)
{
    // 限制audioserver内存使用上限
    limitProcessMemory(
        "audio.maxmem", /* "ro.audio.maxmem", property that defines limit */
        (size_t)512 * (1 << 20), /* SIZE_MAX, upper limit in bytes */
        20 /* upper limit as percentage of physical RAM */);

    signal(SIGPIPE, SIG_IGN);

    bool doLog = (bool) property_get_bool("ro.test_harness", 0);

    pid_t childPid;
    //是否启动子进程启动log记录,这里不是流程分析关注点
    if (doLog && (childPid = fork()) != 0) {
        ......
    } else {
        // all other services
       ......
        android::hardware::configureRpcThreadpool(4, false /*callerWillJoin*/);
        sp<ProcessState> proc(ProcessState::self());
        sp<IServiceManager> sm = defaultServiceManager();
        ALOGI("ServiceManager: %p", sm.get());
        //(1) 启动AF
        AudioFlinger::instantiate();
        //(2) 启动APS
        AudioPolicyService::instantiate();
       .......
       //(3)和语音唤醒及识别有关的服务
        SoundTriggerHwService::instantiate();
        ProcessState::self()->startThreadPool();
        IPCThreadState::self()->joinThreadPool();
    }
}

好了,看到了AF和APS启动的身影了,那么进入其instantiate函数看下其初始化都做了哪些事吧

先看下AF的初始化

然而,我们在AudioFlinger.cpp文件中并没在找到instantiate函数,那么想必定义在其父类,AudioFlinger类继承关系如下
[–>AudioFlinger.h]

class AudioFlinger :
    public BinderService<AudioFlinger>,
    public BnAudioFlinger {
    }

我们在BinderService模板类中找到了instantiate函数的定义

[–>BinderService.h]

template<typename SERVICE>
class BinderService
{
public:
    //(1) 创建服务对象并加入到Sm中
    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 publishAndJoinThreadPool(
            bool allowIsolated = false,
            int dumpFlags = IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT) {
        publish(allowIsolated, dumpFlags);
        joinThreadPool();
    }
	//(2)静态方法调用
    static void instantiate() { publish(); }
	.......
};


}; // namespace android

instantiate静态方法直接调用publish创建对象,并加入到ServiceManager中,便于其他模块路由到AF模块。

Android Audio System深入探究之AudioFlinger(基于Android9)_第2张图片
看下AF生命周期相关的三个函数, 构造函数AudioFlinger、onFirstRef在类初始化调用,~AudioFlinger是析构函数,类销毁时调用。
[–>AudioFlinger.cpp]

AudioFlinger::AudioFlinger()
    : BnAudioFlinger(),
      mMediaLogNotifier(new AudioFlinger::MediaLogNotifier()),
      mPrimaryHardwareDev(NULL), //主硬件设备,  audio_policy_configuration.xml配置的
      mAudioHwDevs(NULL), //所有硬件设备, audio_policy_configuration.xml配置的
      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)
{
    // 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++) {
        // zero ID has a special meaning, so unavailable
        mNextUniqueIds[use] = AUDIO_UNIQUE_ID_USE_MAX;
    }

    getpid_cached = getpid();
    const bool doLog = property_get_bool("ro.test_harness", false);
    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();
	//设备Hal加载使用,设备加载使用了懒加载,看openOutput >> openOutput_l >> findSuitableHwDev_l >>outHwDev->openOutputStream
    mDevicesFactoryHal = DevicesFactoryHalInterface::create();
    mEffectsFactoryHal = EffectsFactoryHalInterface::create();

    mMediaLogNotifier->run("MediaLogNotifier");
	......
}
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) {
    ......
    }
    mPatchPanel = new PatchPanel(this);
    mMode = AUDIO_MODE_NORMAL;
    //保存全局引用
    gAudioFlinger = this;
}
AudioFlinger::~AudioFlinger()
{
	//关闭reocrd线程
    while (!mRecordThreads.isEmpty()) {
        // closeInput_nonvirtual() will remove specified entry from mRecordThreads
        closeInput_nonvirtual(mRecordThreads.keyAt(0));
    }
    //关闭playback线程
    while (!mPlaybackThreads.isEmpty()) {
        // closeOutput_nonvirtual() will remove specified entry from mPlaybackThreads
        closeOutput_nonvirtual(mPlaybackThreads.keyAt(0));
    }
    //回收硬件设备占用内存
    for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
        // no mHardwareLock needed, as there are no other references to this
        delete mAudioHwDevs.valueAt(i);
    }
    // Tell media.log service about any old writers that still need to be unregistered
    if (sMediaLogService != 0) {
		.......
    }
}

2. AF中的createTrack

AF的初始化我们找到了,那么我们继续跟踪
Android Audio System深入探究之AudioTrack
中AF创建Track的流程吧,AT中调用AF的createTrack是Binder调用,代码如下:

[–>AudioTrack.cpp]

......
IAudioFlinger::CreateTrackOutput output;
	//(1) Binder调用AF的createTrack方法
    sp<IAudioTrack> track = audioFlinger->createTrack(input,
                                                      output,
                                                      &status);
......                                                     

继续看标号(1)处的调用

[–>AudioFlinger.cpp]

sp<IAudioTrack> AudioFlinger::createTrack(const CreateTrackInput& input,
                                          CreateTrackOutput& output,
                                          status_t *status) {
sp<PlaybackThread::Track> track;
sp<TrackHandle> trackHandle;

......
//Binder调用APS,根据input参数获取output相关参数
 lStatus = AudioSystem::getOutputForAttr(&input.attr, &output.outputId, sessionId, &streamType,
                                            clientPid, clientUid, &input.config, input.flags,
                                            &output.selectedDeviceId, &portId);
,,,,,,
//(1)这里直接根据outputId拿到了PlaybackThread线程,那么PlayBackThread线程在哪创建的呢?                                          
PlaybackThread *thread = checkPlaybackThread_l(output.outputId);
......
//在PlaybackThread中创建track
track = thread->createTrack_l(client, streamType, input.attr, &output.sampleRate,
                                      input.config.format, input.config.channel_mask,
                                      &output.frameCount, &output.notificationFrameCount,
                                      input.notificationsPerBuffer, input.speed,
                                      input.sharedBuffer, sessionId, &output.flags,
                                      input.clientInfo.clientTid, clientUid, &lStatus, portId);
......
 // return handle to client
trackHandle = new TrackHandle(track);// (2)注意,其对象实例没有在AF中保存, TrackHandle对象是什么?
......
return trackHandle;	
}

AudioFlinger::PlaybackThread *AudioFlinger::checkPlaybackThread_l(audio_io_handle_t output) const
{
    return mPlaybackThreads.valueFor(output).get();
}

上面的代码有两个问题
(1)PlaybackThread在哪创建的呢?
(2)TrackHandle对象是什么?

3. AF中的openOutput

针对问题:PlaybackThread在哪创建的呢?
我们首先在AF代码先找找,看看有没有PlayBackThread创建的线索

openOutput中调用了openOutput_l, 主要工作在openOutput_l中完成

我们在AF的openOutput_l函数中找到一些线索

sp<AudioFlinger::ThreadBase> 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)
{

......
//(1)找到合适的输出设备
 AudioHwDevice *outHwDev = findSuitableHwDev_l(module, devices);
 
......
// (2) 打开输出流
 AudioStreamOut *outputStream = NULL;
    status_t status = outHwDev->openOutputStream(
            &outputStream,
            *output,
            devices,
            flags,
            config,
            address.string());
...... 
//创建PlaybackThread, 通过源码我们可知OffloadThread、DirectOutputThread及 MixerThread 都是
//PlaybackThread的子类  
//根据flags, 不做特殊设置情况下,我们走的是Mix线程
if (status == NO_ERROR) {
            sp<PlaybackThread> thread;
            if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
                thread = new OffloadThread(this, outputStream, *output, devices, mSystemReady);
                ALOGV("openOutput_l() created offload output: ID %d thread %p",
                      *output, thread.get());
            } else if ((flags & AUDIO_OUTPUT_FLAG_DIRECT)
                    || !isValidPcmSinkFormat(config->format)
                    || !isValidPcmSinkChannelMask(config->channel_mask)) {
                thread = new DirectOutputThread(this, outputStream, *output, devices, mSystemReady);
                ALOGV("openOutput_l() created direct output: ID %d thread %p",
                      *output, thread.get());
            } else {
                thread = new MixerThread(this, outputStream, *output, devices, mSystemReady);
                ALOGV("openOutput_l() created mixer output: ID %d thread %p",
                      *output, thread.get());
            }
            //注意`checkPlaybackThread_l`调用就是从这里找到的PlaybackThread
            mPlaybackThreads.add(*output, thread);
            return thread;
        }
}

上面的标号(1)、(2)、(3) 暴露了音频放音的重要步骤流程, 打开设备、创建输出流、创建放音线程, 那剩下的工作不就是向输出流写入数据了吗。

那么问题又来了,AudioFlinger->openOutput_l又是被谁调用的呢?

通过代码追踪,我们发现 openOutput_l函数调用原来实在APS初始化时完成,APS初始化时,会读取audio_policy.conf文件,解析HwModule、Device 的profile等信息,然后通过调用AF的openOutput打开相关的设备。

[–>AudioPolicyClientImpl.cpp]

sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
    ......
    //调用AF的openOutput函数
    return af->openOutput(module, output, config, devices, address, latencyMs, flags);

APS的初始化流程参考如下
Android Audio System深入探究之AudioPolicyService

4. TrackHandle分析

AF中createTrack返回的是TrackHandle对象,它以Track为参数构造。那么两者有什么关系呢?

  1. TrackHandle代理
    通过查看源码我们得知,android这里使用了Proxy模式,即TrackHandle是Track的代理,那么TrackHandle实现了怎样的代理呢?
    (1)Track没有BInder通信,不能接收来自远端进程的请求。
    (2)TrackHandle能基于Binder通信,它可以接收来自远端进程的请求,能够调用Track对应的函数。
    那么Android为什么不直接让Track从IBinder派生,直接支持Binder通信呢?

  2. 职责分担
    从查看代码我们得知,Track承担的职责非常重,如果再承担Binder通信的任务,可能整个类将显得无比巨大,逻辑也变得很复杂。

5. AF中类结构分析

5.1 AudioFlinger结构分析

AF是Audio系统核心,看下其继承关系:

[–> AudioFlinger.h]

class AudioFlinger :
    public BinderService<AudioFlinger>,
    public BnAudioFlinger
{
	......
}

AudioFlinger主要工作由其许多内部类完成,看下其内部类构成吧。图中大括号是包含与被包含的关系。
Android Audio System深入探究之AudioFlinger(基于Android9)_第3张图片
相关类功能介绍:
PlaybackThread: 放音线程,用于音频输出。
RecordThread:录音线程,用于音频输入。

PlaybackThread有三个派生类

MixerThread: 混音线程,它将来自多个源的音频数据混合后再输出。
DirectOutputThread:直接输出线程,它会选择一路音频流将数据直接输出,由于没有混音,可以减少很多延时。
DuplicatingThread:多路输出线程,它从MixerThread派生,意味着他也能混音。它最终会把混音后的数据写道多个输出中,也就是一份数据多个接收者。这就是Duplicate含义。在蓝牙A2DP设备输出有使用。

5.2 AF线程分析

另外从下图中AF Thread的UML图还可以看出:

PlaybackThread维护两个Track列表,一个mActiveTracks,表示当前活跃的Track; 另一个mTracks,表示这个线程创建的所有Track。

DuplicatingThread还维护了一个mOutputTracks, 表示多路输出的目的端。

下面是AF涉及的Thread 的UML图
Android Audio System深入探究之AudioFlinger(基于Android9)_第4张图片

5.3 AF数据流模型

在上面UML图中,我们可以发现PlaybackThread线程有一个AudioStreamOutput类型对象,这个对象提供了音频数据输出功能。下面的图大致可以示意音频数据的流动轨迹。以最常用的MixThread为代表。
Android Audio System深入探究之AudioFlinger(基于Android9)_第5张图片
根据上图可以大致描述MixerThread线程的工作流程:

  • 接收凯子AT的数据。
  • 对这些数据进行混音。
  • 把混音的结果写入到AudioStreamOutput中,这样就完成了音频数据输出。

5.4 Track类分析

工作线程中最重要的工作是围绕Track展开的,看下Track家族组成。
Android Audio System深入探究之AudioFlinger(基于Android9)_第6张图片
TrackHandle和RecordHandle是基于BInder通信的,作为Server端的Proxy,接收来自Client的请求并派发到对应的Track和RecordTrack。

Track类作为工作线程的内部类来实现的,其中:

  • TrackBase定义在ThreadBase中。
  • Track定义在PlaybackThread中,RecordTrack定义在RecordThread中。
  • OutputTrack定义在DuplicatingThread中。

你可能感兴趣的:(Android源码剖析,android系统分析)