audiotrack的create流程(mode_stream)

简述

这部分,我们主要讲解两个函数getMinBufferSizeAudioTrack

正文

一、getMinBufferSize函数解析

直接帖整段的代码,不打算省略了。可能很占空间,但是我们可以把每个变量都看一遍。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
static public int getMinBufferSize(int sampleRateInHz, int channelConfig, int audioFormat) {
int channelCount = 0;
// 传入的声道配置。CHANNEL_OUT_MONO、CHANNEL_CONFIGURATION_MONO是一样的主要是为了兼容以前。
// CHANNEL_OUT_MONO单声道 CHANNEL_OUT_STEREO 双声道。
switch(channelConfig) {
case AudioFormat.CHANNEL_OUT_MONO:
case AudioFormat.CHANNEL_CONFIGURATION_MONO:
channelCount = 1;
break;
case AudioFormat.CHANNEL_OUT_STEREO:
case AudioFormat.CHANNEL_CONFIGURATION_STEREO:
channelCount = 2;
break;
default:
// 判断是否支持全方位的声道数,总共是8个,支持的话,需要支持前左、前右、后左、后右、左边、右边
if (!isMultichannelConfigSupported(channelConfig)) {
loge("getMinBufferSize(): Invalid channel configuration.");
return ERROR_BAD_VALUE;
} else {
// 如果支持,就计算出它的声道数。
channelCount = AudioFormat.channelCountFromOutChannelMask(channelConfig);
}
}
// 检查下format的格式是否正确。
if (!AudioFormat.isPublicEncoding(audioFormat)) {
loge("getMinBufferSize(): Invalid audio format.");
return ERROR_BAD_VALUE;
}

// sample rate, note these values are subject to change
// 确保采样率在我们规定的范围,如果自行扩展采样率的话,就需要修改这边的静态变量。
if ( (sampleRateInHz < SAMPLE_RATE_HZ_MIN) || (sampleRateInHz > SAMPLE_RATE_HZ_MAX) ) {
loge("getMinBufferSize(): " + sampleRateInHz + " Hz is not a supported sample rate.");
return ERROR_BAD_VALUE;
}
// 接下来就直接调用native的方法了。
int size = native_get_min_buff_size(sampleRateInHz, channelCount, audioFormat);
if (size <= 0) {
loge("getMinBufferSize(): error querying hardware");
return ERROR;
}
else {
return size;
}
}

上面的函数做了几件事:

  1. 将上层的channelconfig转变为声道的数量
  2. 判断audioformat是否是我们定义的
  3. 调用native的min buffer size

接着来看native的代码。

static jint android_media_AudioTrack_get_min_buff_size(JNIEnv *env,  jobject thiz,
    jint sampleRateInHertz, jint channelCount, jint audioFormat) {

    size_t frameCount;
    // 通过AudioTrack去获取需要的最少的帧数。
    const status_t status = AudioTrack::getMinFrameCount(&frameCount, AUDIO_STREAM_DEFAULT,
            sampleRateInHertz);
    if (status != NO_ERROR) {
        return -1;
    }
    // 将上层的audioFormat转换成native的格式 java层是一个递增索引,在native是位活的形式
    const audio_format_t format = audioFormatToNative(audioFormat);
    // 判断是否是线性的pcm数据流,因为只有线性数据流我们才能计算出帧对应多少字节。
    if (audio_is_linear_pcm(format)) {
        // 获取每一帧占多少个字节
        const size_t bytesPerSample = audio_bytes_per_sample(format);
        // 帧数 * 每帧字节数 * 通道数 就是我们所要得到的buffer的字节数了。
        return frameCount * channelCount * bytesPerSample;
    } else {
        return frameCount;
    }
}

上面的代码牵扯到一个帧到字节的计算方式。
buffersize = 帧数 x 每帧占用字节数 x 通道数

format这个参数,我们可以理解为采样精度,每帧占用字节数如下图:

现在还有frameCount这个变量是未知的,我们来看下函数AudioTrack::getMinFrameCount

status_t AudioTrack::getMinFrameCount(
        size_t* frameCount,
        audio_stream_type_t streamType,
        uint32_t sampleRate)
{
    if (frameCount == NULL) {
        return BAD_VALUE;
    }

    // FIXME handle in server, like createTrack_l(), possible missing info:
    //          audio_io_handle_t output
    //          audio_format_t format
    //          audio_channel_mask_t channelMask
    //          audio_output_flags_t flags (FAST)
    uint32_t afSampleRate;
    status_t status;
    // 获取streamtype下,对应output的采样率
    status = AudioSystem::getOutputSamplingRate(&afSampleRate, streamType);
    if (status != NO_ERROR) {
        return status;
    }
    size_t afFrameCount;
    // 获取streamtype下,对应output的hal层的buffer size对应的帧数,采样率为当时output默认。
    status = AudioSystem::getOutputFrameCount(&afFrameCount, streamType);
    if (status != NO_ERROR) {
        return status;
    }
    uint32_t afLatency;
    // 获取streamtype下,对应output的hal层latency的大小,单位是ms
    status = AudioSystem::getOutputLatency(&afLatency, streamType);
    if (status != NO_ERROR) {
        return status;
    }

    // When called from createTrack, speed is 1.0f (normal speed).
    // This is rechecked again on setting playback rate (TODO: on setting sample rate, too).
    // 开始计算所需要的最少帧数
    *frameCount = calculateMinFrameCount(afLatency, afFrameCount, afSampleRate, sampleRate, 1.0f);

    if (*frameCount == 0) {
        return BAD_VALUE;
    }
    return NO_ERROR;
}

该函数的逻辑,主要是去获取output的一些信息,采样率、latency、底层buffer对应的帧数,然后计算所需要的最少帧数。

static size_t calculateMinFrameCount(
        uint32_t afLatencyMs, uint32_t afFrameCount, uint32_t afSampleRate,
        uint32_t sampleRate, float speed)
{
    // Ensure that buffer depth covers at least audio hardware latency
    // 确保buffer大小最少能够覆盖硬件的延时
    // 算法就是latency 除以 底层buffer大小在当前采样率下播放完所需花费的时间,这个就是多少倍了。
    uint32_t minBufCount = afLatencyMs / ((1000 * afFrameCount) / afSampleRate);
    // 这个倍数不能小于2,最少必须等于2.就是说,如果latencyms比buffer还短,那就只需要两倍buffer的ms
    if (minBufCount < 2) {
        minBufCount = 2;
    }
    // sourceFramesNeededWithTimestretch这个函数里面包括了SRC的计算,和spee的的部分我们就不贴了。
    return minBufCount * sourceFramesNeededWithTimestretch(
            sampleRate, afFrameCount, afSampleRate, speed);
}

上面的计算过程就不再细看了,算法:
size_t((uint64_t)dstFramesRequired x srcSampleRate / dstSampleRate + 1 + 1)

我们继续看函数AudioSystem::getOutputSamplingRate.

status_t AudioSystem::getOutputSamplingRate(uint32_t* samplingRate, audio_stream_type_t streamType)
{
    audio_io_handle_t output;
    // 如果stream type为默认的话,则改成为music,其实java层获取minsize的时候,并没有传递该参数
    // 所以获取的是music类型的。
    if (streamType == AUDIO_STREAM_DEFAULT) {
        streamType = AUDIO_STREAM_MUSIC;
    }
    // 通过该stream type去寻找对应的output
    output = getOutput(streamType);
    if (output == 0) {
        return PERMISSION_DENIED;
    }
    // 通过output去获取samplingRate
    return getSamplingRate(output, samplingRate);
}

该函数的逻辑:

  1. 获取output,这个output对应到AudioFlinger中的某个output thread,每个thread都会含有一个hal的output。
  2. 通过这个output去获取hal层当前设置的samplingRate。

我们一起来看下getOutput函数,由于这个函数会一路调用到AudioPolicyManager中,所以我这边直接就贴AudioPolicy部分的代码。

这部分牵扯到了AudioPolicy部分。每一个output都对应到audio_policy.conf中的一个port节点。

audio_io_handle_t AudioPolicyManager::getOutput(audio_stream_type_t stream,
                                                uint32_t samplingRate,
                                                audio_format_t format,
                                                audio_channel_mask_t channelMask,
                                                audio_output_flags_t flags,
                                                const audio_offload_info_t *offloadInfo)
{
    // 通过stream type去获取路由策略
    routing_strategy strategy = getStrategy(stream);
    // 通过策略去选择输出的device
    audio_devices_t device = getDeviceForStrategy(strategy, false /*fromCache*/);
    // 通过device来选择输出的output
    return getOutputForDevice(device, AUDIO_SESSION_ALLOCATE,
                              stream, samplingRate,format, channelMask,
                              flags, offloadInfo);
}

audio_io_handle_t AudioPolicyManager::getOutputForDevice(
        audio_devices_t device,
        audio_session_t session __unused,
        audio_stream_type_t stream,
        uint32_t samplingRate,
        audio_format_t format,
        audio_channel_mask_t channelMask,
        audio_output_flags_t flags,
        const audio_offload_info_t *offloadInfo)
{
    audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
    uint32_t latency = 0;
    status_t status;

    // open a direct output if required by specified parameters
    //force direct flag if offload flag is set: offloading implies a direct output stream
    // and all common behaviors are driven by checking only the direct flag
    // this should normally be set appropriately in the policy configuration file
    // 如果flag中指定AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD、AUDIO_OUTPUT_FLAG_HW_AV_SYNC则会
    // 强制成AUDIO_OUTPUT_FLAG_DIRECT,因为offloading就意味着direct output,后面只需要判断该flag
    // 就可以了。
    if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) {
        flags = (audio_output_flags_t)(flags | AUDIO_OUTPUT_FLAG_DIRECT);
    }
    if ((flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC) != 0) {
        flags = (audio_output_flags_t)(flags | AUDIO_OUTPUT_FLAG_DIRECT);
    }
    // 只允许stream type为music的可以使用deep buffer
    if (stream != AUDIO_STREAM_MUSIC) {
        flags = (audio_output_flags_t)(flags &~AUDIO_OUTPUT_FLAG_DEEP_BUFFER);
    } else if (/* stream == AUDIO_STREAM_MUSIC && */
            flags == AUDIO_OUTPUT_FLAG_NONE &&
            property_get_bool("audio.deep_buffer.media", false /* default_value */)) {
        // use DEEP_BUFFER as default output for music stream type
        flags = (audio_output_flags_t)AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
    }
    if (stream == AUDIO_STREAM_TTS) {
        flags = AUDIO_OUTPUT_FLAG_TTS;
    }

    sp<IOProfile> profile;

    // 如果明显是使用mixed output或者没有明确要求的使用direct output,则直接调到non_direct_output
    if (((flags & AUDIO_OUTPUT_FLAG_DIRECT) == 0) &&
            audio_is_linear_pcm(format) && samplingRate <= MAX_MIXER_SAMPLING_RATE &&
            audio_channel_count_from_out_mask(channelMask) <= 2) {
        goto non_direct_output;
    }

    // Do not allow offloading if one non offloadable effect is enabled. This prevents from
    // creating an offloaded track and tearing it down immediately after start when audioflinger
    // detects there is an active non offloadable effect.
    // FIXME: We should check the audio session here but we do not have it in this context.
    // This may prevent offloading in rare situations where effects are left active by apps
    // in the background.
    // 必须保证mEffects中的效果,所有的使能的效果并且属于media必须support offload effect,或者没有
    // 效果才可以offloading。
    // isNonOffloadableEffectEnabled该函数的实现是,只有effect使能并且属于media策略
    // 并且不support offload effect的时候才返回true。默认基本上都是返回false的。
    if (((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) == 0) ||
            !mEffects.isNonOffloadableEffectEnabled()) {
        profile = getProfileForDirectOutput(device,
                                           samplingRate,
                                           format,
                                           channelMask,
                                           (audio_output_flags_t)flags);
    }

    if (profile != 0) {
        sp<SwAudioOutputDescriptor> outputDesc = NULL;

        for (size_t i = 0; i < mOutputs.size(); i++) {
            sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
            if (!desc->isDuplicated() && (profile == desc->mProfile)) {
                outputDesc = desc;
                // 如果找到互相匹配的direct output则直接复用,引用计数+1
                if ((samplingRate == outputDesc->mSamplingRate) &&
                        (format == outputDesc->mFormat) &&
                        (channelMask == outputDesc->mChannelMask)) {
                    outputDesc->mDirectOpenCount++;
                    return mOutputs.keyAt(i);
                }
            }
        }
        // 如果有找到对应的direct output,但是参数不一样,则先关闭处理,如果当前该output
        // 有音频流在输出的话,会怎么样呢??
        if (outputDesc != NULL) {
            closeOutput(outputDesc->mIoHandle);
        }

        // 如果选中的profile是一个offloaded,但是没有指定特殊参数,则使用默认值
        audio_offload_info_t defaultOffloadInfo = AUDIO_INFO_INITIALIZER;
        if ((profile->mFlags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) && !offloadInfo) {
            flags = (audio_output_flags_t)(flags | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD);
            defaultOffloadInfo.sample_rate = samplingRate;
            defaultOffloadInfo.channel_mask = channelMask;
            defaultOffloadInfo.format = format;
            defaultOffloadInfo.stream_type = stream;
            defaultOffloadInfo.bit_rate = 0;
            defaultOffloadInfo.duration_us = -1;
            defaultOffloadInfo.has_video = true; // conservative
            defaultOffloadInfo.is_streaming = true; // likely
            offloadInfo = &defaultOffloadInfo;
        }
        // 重新构造对象
        outputDesc = new SwAudioOutputDescriptor(profile, mpClientInterface);
        // 设置这个output当前选择的输出设备
        outputDesc->mDevice = device;
        // output latency设置为0
        outputDesc->mLatency = 0;
        outputDesc->mFlags = (audio_output_flags_t)(outputDesc->mFlags | flags);
        audio_config_t config = AUDIO_CONFIG_INITIALIZER;
        config.sample_rate = samplingRate;
        config.channel_mask = channelMask;
        config.format = format;
        if (offloadInfo != NULL) {
            config.offload_info = *offloadInfo;
        }
        // 这是要通知到AudioFlinger那边去打开output,并且让output thread跑起来
        status = mpClientInterface->openOutput(profile->getModuleHandle(),
                                               &output,
                                               &config,
                                               &outputDesc->mDevice,
                                               String8(""),
                                               &outputDesc->mLatency,
                                               outputDesc->mFlags);

        // 只能接受符合要求参数的output
        if (status != NO_ERROR ||
            (samplingRate != 0 && samplingRate != config.sample_rate) ||
            (format != AUDIO_FORMAT_DEFAULT && format != config.format) ||
            (channelMask != 0 && channelMask != config.channel_mask)) {
            if (output != AUDIO_IO_HANDLE_NONE) {
                mpClientInterface->closeOutput(output);
            }
            // 如果direct output没有被打开,并且符合下面条件,则回到mixer output去。
            if (audio_is_linear_pcm(format) && samplingRate <= MAX_MIXER_SAMPLING_RATE) {
                goto non_direct_output;
            }
            return AUDIO_IO_HANDLE_NONE;
        }
        outputDesc->mSamplingRate = config.sample_rate;
        outputDesc->mChannelMask = config.channel_mask;
        outputDesc->mFormat = config.format;
        outputDesc->mRefCount[stream] = 0;
        outputDesc->mStopTime[stream] = 0;
        outputDesc->mDirectOpenCount = 1;
        // 未将该output添加进来之前,先获取一次output,对于打开的output中,优先offload、
        // deep buffer,(通过flag判断)最后选择打开列表中的第一个。
        audio_io_handle_t srcOutput = getOutputForEffect();
        // 将这个output添加到AudioPolicy的mOutputs中来。
        addOutput(output, outputDesc);
        audio_io_handle_t dstOutput = getOutputForEffect();
        // output发生迁移,全局效果跟着迁移。
        if (dstOutput == output) {
            mpClientInterface->moveEffects(AUDIO_SESSION_OUTPUT_MIX, srcOutput, dstOutput);
        }
        mPreviousOutputs = mOutputs;
        mpClientInterface->onAudioPortListUpdate();
        return output;
    }

non_direct_output:
    // 这边不用去管channel mask,因为mixer具有downmix的能力
    // 打开一个非direct output
    // 对于非direct output,只支持pcm
    if (audio_is_linear_pcm(format)) {
        // get which output is suitable for the specified stream. The actual
        // routing change will happen when startOutput() will be called
        // 根据指定的stream type获取哪一些output是合适的。发生routing是在startOutput函数。
        SortedVector<audio_io_handle_t> outputs = getOutputsForDevice(device, mOutputs);

        // 到这个阶段,我们可以去掉DIRECT flag,因为没有direct output会被发现了。
        flags = (audio_output_flags_t)(flags & ~AUDIO_OUTPUT_FLAG_DIRECT);
        // 获取output,优先级:flag一致越多的 > primary output > 数组中第一个output
        output = selectOutput(outputs, flags, format);
    }
    return output;
}

函数的主要逻辑是:

  1. 通过stream type获取路由策略
  2. 通过路由策略获取输出设备
  3. 通过输出设备获取输出的output 到这边就跟AudioFlinger中的output thread挂钩了。

getOutputForDevice这个函数的主要逻辑是:

  1. 根据传入的flag进行判断选择什么样的output。
  2. 如果是direct的output,则需要参数完全一致,否则关闭,重新配置打开这个direct output,打开失败回到non direct output来。
  3. 如果是non direct output的话,会按照一定优先级来选择

这边留下一个疑问,如果一个offload的output当前正在playback,那上面的close会触发什么,或者带来什么改变?

我们一开始只是关注获取output,结果却看了如此多的代码。。。output值其实是AudioFlinger那边一个thread的索引,通过这个值,我们就可以从AudioFlinger中拿到这个对象。

我们回到函数AudioSystem::getOutputSamplingRate,接着看里面的getSamplingRate部分。

status_t AudioSystem::getSamplingRate(audio_io_handle_t output,
                                      uint32_t* samplingRate)
{
    // 获取到AudioFlinger的binder。
    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
    if (af == 0) return PERMISSION_DENIED;
    // 看本地是否有存储该output对应的对象,如果有则直接获取,如果没有则通过AudioFlinger去获取
    sp<AudioIoDescriptor> outputDesc = getIoDescriptor(output);
    if (outputDesc == 0) {
        *samplingRate = af->sampleRate(output);
    } else {
        *samplingRate = outputDesc->mSamplingRate;
    }
    if (*samplingRate == 0) {
        return BAD_VALUE;
    }
    return NO_ERROR;
}
// 我们来看下这个获取flinger的函数,因为它会注册当前的信息到AudioFlinger,所以显得较为重要。
const sp<IAudioFlinger> AudioSystem::get_audio_flinger()
{
    sp<IAudioFlinger> af;
    sp<AudioFlingerClient> afc;
    {
        Mutex::Autolock _l(gLock);
        // 全局变量gAudioFlinger如果为0,说明这个进程第一次访问AudioFlinger,才需要去获取跟注册。
        if (gAudioFlinger == 0) {
            // 获取service的逻辑
            sp<IServiceManager> sm = defaultServiceManager();
            sp<IBinder> binder;
            do {
                binder = sm->getService(String16("media.audio_flinger"));
                if (binder != 0)
                    break;
                ALOGW("AudioFlinger not published, waiting...");
                usleep(500000); // 0.5 s
            } while (true);
            // 如果全局gAudioFlingerClient为null 说明尚未注册到AudioFlinger中,则创建一个。
            if (gAudioFlingerClient == NULL) {
                gAudioFlingerClient = new AudioFlingerClient();
            } else {
                // 否则看下是否有这个回调函数,有的话则回调。
                if (gAudioErrorCallback) {
                    gAudioErrorCallback(NO_ERROR);
                }
            }
            // AudioFlinger挂掉的话会通知gAudioFlingerClient去调用自己的binderDied方法
            binder->linkToDeath(gAudioFlingerClient);
            // 将该binder对象存储起来
            gAudioFlinger = interface_cast<IAudioFlinger>(binder);
            // 将client对象存储起来
            afc = gAudioFlingerClient;
        }
        af = gAudioFlinger;
    }
    // 如果afc不为空,则注册到AudioFlinger中去。AudioFlinger中会根据pid进行绑定。
    // AudioFlinger那边会给thread发送open output的信息,这样thread会拼装一个iodesc回来给到
    // AudioSystem,由这边来进行维护output的信息。
    if (afc != 0) {
        af->registerClient(afc);
    }
    return af;
}

到这边我们就知道怎么获取到的samplingRate了,它的值是存储在output thread中的,你可能还是想知道这个samplingRate是从哪里来的,前面我们其实也看到了open output的一些代码了,那边我们是有传递samplingRate进去的,也就是说,这个samplingRate的值基本上就是第一个打开这个output的时候设置的,除非后面有通过setparameter进行重新设置,否则这个值就是这样了。它也必须跟audio_policy.conf中一致的。

到这边我们就回过头来看函数AudioTrack::getMinFrameCount

我们已经有output了,并且获取到了samplingRate了,那接下来就是framecount和latency,而这两个值都是hal层的数据。并不是我们open output的时候传递进去的,不过获取的逻辑基本上跟上面获取samplingRate是一致的。

这样我们就获取到所有我们想要的数据了。就可以计算出MinBufferSize

由于我们是通过getMinBufferSize一路调下来的,它传递给底层的参数实在太有限了,所以基本上这个获取到的是primary的相关信息。我们可以看到在AudioTrack中调用getMinFrameCount也就只有采样率会保存下来,但是并不会用来跟AudioPolicy和AudioFlinger打交道。所以获取到的buffersize是跟实际有点差别的。但是你又不得不遵循就是了。

二、AudioTrack的创建流程

我们从java这边的构造函数开始。

public AudioTrack(AudioAttributes attributes, AudioFormat format, int bufferSizeInBytes,
        int mode, int sessionId)
                throws IllegalArgumentException {
    // mState already == STATE_UNINITIALIZED
    // 例行检查
    if (attributes == null) {
        throw new IllegalArgumentException("Illegal null AudioAttributes");
    }
    if (format == null) {
        throw new IllegalArgumentException("Illegal null AudioFormat");
    }

    // 记录下和audiotrack实例关联的looper。
    Looper looper;
    if ((looper = Looper.myLooper()) == null) {
        looper = Looper.getMainLooper();
    }

    int rate = 0;
    // 看下format参数中是否带有采样率,如果有,则直接从format对象中获取,否则从获取primary output的
    if ((format.getPropertySetMask() & AudioFormat.AUDIO_FORMAT_HAS_PROPERTY_SAMPLE_RATE) != 0)
    {
        rate = format.getSampleRate();
    } else {
        rate = AudioSystem.getPrimaryOutputSamplingRate();
        if (rate <= 0) {
            rate = 44100;
        }
    }
    int channelIndexMask = 0;
    // 同上,看下是否包含channel的信息。
    if ((format.getPropertySetMask()
            & AudioFormat.AUDIO_FORMAT_HAS_PROPERTY_CHANNEL_INDEX_MASK) != 0) {
        channelIndexMask = format.getChannelIndexMask();
    }
    int channelMask = 0;
    if ((format.getPropertySetMask()
            & AudioFormat.AUDIO_FORMAT_HAS_PROPERTY_CHANNEL_MASK) != 0) {
        channelMask = format.getChannelMask();
    } else if (channelIndexMask == 0) { // if no masks at all, use stereo
        channelMask = AudioFormat.CHANNEL_OUT_FRONT_LEFT
                | AudioFormat.CHANNEL_OUT_FRONT_RIGHT;
    }
    int encoding = AudioFormat.ENCODING_DEFAULT;
    if ((format.getPropertySetMask() & AudioFormat.AUDIO_FORMAT_HAS_PROPERTY_ENCODING) != 0) {
        encoding = format.getEncoding();
    }
    // 检测参数是否正确
    audioParamCheck(rate, channelMask, channelIndexMask, encoding, mode);
    // 采用AudioAttributes的形式,则该变量会被设置为default
    mStreamType = AudioSystem.STREAM_DEFAULT;
    // 很粗略的判断了下我们申请的buffersize是否合法。
    audioBuffSizeCheck(bufferSizeInBytes);

    mInitializationLooper = looper;
    IBinder b = ServiceManager.getService(Context.APP_OPS_SERVICE);
    mAppOps = IAppOpsService.Stub.asInterface(b);

    mAttributes = new AudioAttributes.Builder(attributes).build();
    // sessionId和音效挂钩部分
    if (sessionId < 0) {
        throw new IllegalArgumentException("Invalid audio session ID: "+sessionId);
    }

    int[] session = new int[1];
    session[0] = sessionId;
    // 调用native的函数进行初始化 数据加载模式被传到jni了
    int initResult = native_setup(new WeakReference<AudioTrack>(this), mAttributes,
            mSampleRate, mChannelMask, mChannelIndexMask, mAudioFormat,
            mNativeBufferSizeInBytes, mDataLoadMode, session);
    if (initResult != SUCCESS) {
        return; // with mState == STATE_UNINITIALIZED
    }

    mSessionId = session[0];
    // 数据加载模式 针对已经native出来之后状态的设置。非static的,设置成STATE_INITIALIZED
    if (mDataLoadMode == MODE_STATIC) {
        mState = STATE_NO_STATIC_DATA;
    } else {
        mState = STATE_INITIALIZED;
    }
}

上面基本上大部分都在核对参数是否合理,然后调用native的函数进行初始化。

接下来我们来看下native的初始化函数:

static jint
android_media_AudioTrack_setup(JNIEnv *env, jobject thiz, jobject weak_this,
        jobject jaa,
        jint sampleRateInHertz, jint channelPositionMask, jint channelIndexMask,
        jint audioFormat, jint buffSizeInBytes, jint memoryMode, jintArray jSession) {
    // jaa是AudioAttributes对象,这个对象不允许为空
    if (jaa == 0) {
        return (jint) AUDIO_JAVA_ERROR;
    }

    // Invalid channel representations are caught by !audio_is_output_channel() below.
    // 将java的channelmask映射成native的ChannelMask。
    audio_channel_mask_t nativeChannelMask = nativeChannelMaskFromJavaChannelMasks(
            channelPositionMask, channelIndexMask);
    if (!audio_is_output_channel(nativeChannelMask)) {
        return (jint) AUDIOTRACK_ERROR_SETUP_INVALIDCHANNELMASK;
    }
    // 换算出channelCount
    uint32_t channelCount = audio_channel_count_from_out_mask(nativeChannelMask);

    // 检查format
    audio_format_t format = audioFormatToNative(audioFormat);
    if (format == AUDIO_FORMAT_INVALID) {
        return (jint) AUDIOTRACK_ERROR_SETUP_INVALIDFORMAT;
    }

    // 计算frame count
    size_t frameCount;
    if (audio_is_linear_pcm(format)) {
        const size_t bytesPerSample = audio_bytes_per_sample(format);
        frameCount = buffSizeInBytes / (channelCount * bytesPerSample);
    } else {
        frameCount = buffSizeInBytes;
    }

    jclass clazz = env->GetObjectClass(thiz);
    if (clazz == NULL) {
        return (jint) AUDIOTRACK_ERROR_SETUP_NATIVEINITFAILED;
    }
    // session数组不能为空
    if (jSession == NULL) {
        return (jint) AUDIO_JAVA_ERROR;
    }
    // session中不能一个对象都没有。
    jint* nSession = (jint *) env->GetPrimitiveArrayCritical(jSession, NULL);
    if (nSession == NULL) {
        return (jint) AUDIO_JAVA_ERROR;
    }
    int sessionId = nSession[0];
    env->ReleasePrimitiveArrayCritical(jSession, nSession, 0);
    nSession = NULL;

    // 创建native版本的audiotrack
    sp<AudioTrack> lpTrack = new AudioTrack();

    audio_attributes_t *paa = NULL;
    // 初始化native的attribute。接下来基本上是从java的attribute搬到native的attribute中来。
    paa = (audio_attributes_t *) calloc(1, sizeof(audio_attributes_t));
    const jstring jtags =
            (jstring) env->GetObjectField(jaa, javaAudioAttrFields.fieldFormattedTags);
    const char* tags = env->GetStringUTFChars(jtags, NULL);
    // copying array size -1, char array for tags was calloc'd, no need to NULL-terminate it
    strncpy(paa->tags, tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1);
    env->ReleaseStringUTFChars(jtags, tags);
    paa->usage = (audio_usage_t) env->GetIntField(jaa, javaAudioAttrFields.fieldUsage);
    paa->content_type =
            (audio_content_type_t) env->GetIntField(jaa, javaAudioAttrFields.fieldContentType);
    paa->flags = env->GetIntField(jaa, javaAudioAttrFields.fieldFlags);

    // initialize the callback information:
    // this data will be passed with every AudioTrack callback
    // 初始化callback信息,这个数据将被传递通过audiotrack的callback
    AudioTrackJniStorage* lpJniStorage = new AudioTrackJniStorage();
    lpJniStorage->mCallbackData.audioTrack_class = (jclass)env->NewGlobalRef(clazz);
    // 这边使用弱引用,这样audiotrack才能被垃圾回收给回收。
    lpJniStorage->mCallbackData.audioTrack_ref = env->NewGlobalRef(weak_this);
    lpJniStorage->mCallbackData.busy = false;

    // 初始化native的audiotrack
    status_t status = NO_ERROR;
    switch (memoryMode) {
    // 加载模式是stream
    case MODE_STREAM:

        status = lpTrack->set(
                AUDIO_STREAM_DEFAULT,// stream type, 更多的信息会通过paa来传递。
                sampleRateInHertz,
                format,// word length, PCM
                nativeChannelMask,
                frameCount,
                AUDIO_OUTPUT_FLAG_NONE,
                audioCallback, &(lpJniStorage->mCallbackData),//callback, callback data (user)
                0,// notificationFrames == 0 因为没有使用EVENT_MORE_DATA来给audiotrack填充数据
                0,// shared mem
                true,// thread can call Java
                sessionId,// audio session ID
                AudioTrack::TRANSFER_SYNC,
                NULL,                         // default offloadInfo
                -1, -1,                       // default uid, pid values
                paa);
        break;
    // 加载模式为static
    case MODE_STATIC:
        // AudioTrack使用shared memory
        // 这部分 我们后面在另作分析
        if (!lpJniStorage->allocSharedMem(buffSizeInBytes)) {
            goto native_init_failure;
        }

        status = lpTrack->set(
                AUDIO_STREAM_DEFAULT,// stream type, but more info conveyed in paa (last argument)
                sampleRateInHertz,
                format,// word length, PCM
                nativeChannelMask,
                frameCount,
                AUDIO_OUTPUT_FLAG_NONE,
                audioCallback, &(lpJniStorage->mCallbackData),//callback, callback data (user));
                0,// notificationFrames == 0 since not using EVENT_MORE_DATA to feed the AudioTrack
                lpJniStorage->mMemBase,// shared mem
                true,// thread can call Java
                sessionId,// audio session ID
                AudioTrack::TRANSFER_SHARED,
                NULL,                         // default offloadInfo
                -1, -1,                       // default uid, pid values
                paa);
        break;

    default:
        goto native_init_failure;
    }

    if (status != NO_ERROR) {
        goto native_init_failure;
    }

    nSession = (jint *) env->GetPrimitiveArrayCritical(jSession, NULL);
    if (nSession == NULL) {
        goto native_init_failure;
    }
    // 从audiotrack那边读取sessionid,防止我们创建了个新的session
    nSession[0] = lpTrack->getSessionId();
    env->ReleasePrimitiveArrayCritical(jSession, nSession, 0);
    nSession = NULL;

    {   // scope for the lock
        Mutex::Autolock l(sLock);
        // 将这次的lpJniStorage->mCallbackData添加到全局的sAudioTrackCallBackCookies数组中
        sAudioTrackCallBackCookies.add(&lpJniStorage->mCallbackData);
    }

    // 将native的audiotrack赋值被java的audiotrack类中的变量mNativeTrackInJavaObj
    setAudioTrack(env, thiz, lpTrack);

    // save the JNI resources so we can free them later
    // 保存jni的资源,这样我们后面好释放他们。
    env->SetLongField(thiz, javaAudioTrackFields.jniData, (jlong)lpJniStorage);

    // 既然我们已经有了audio attributes,stream type是来自于它们,我们将这个值保存回java。
    env->SetIntField(thiz, javaAudioTrackFields.fieldStreamType, (jint) lpTrack->streamType());
    // audio attributes 已经没用了 释放掉。
    free(paa);
    paa = NULL;

    return (jint) AUDIO_JAVA_SUCCESS;

// 创建失败的释放流程。
native_init_failure:
    if (paa != NULL) {
        free(paa);
    }
    if (nSession != NULL) {
        env->ReleasePrimitiveArrayCritical(jSession, nSession, 0);
    }
    env->DeleteGlobalRef(lpJniStorage->mCallbackData.audioTrack_class);
    env->DeleteGlobalRef(lpJniStorage->mCallbackData.audioTrack_ref);
    delete lpJniStorage;
    env->SetLongField(thiz, javaAudioTrackFields.jniData, 0);

    // lpTrack goes out of scope, so reference count drops to zero
    return (jint) AUDIOTRACK_ERROR_SETUP_NATIVEINITFAILED;
}

该函数主要做了几件事:

  1. 类型检测、转换,计算framecount,callback信息的记录
  2. 创建native的audiotrack
  3. 设置audiotrack

接下来我们来看audiotrack的设置函数:AudioTrack::set

status_t AudioTrack::set(
        audio_stream_type_t streamType,
        uint32_t sampleRate,
        audio_format_t format,
        audio_channel_mask_t channelMask,
        size_t frameCount,
        audio_output_flags_t flags,
        callback_t cbf,
        void* user,
        uint32_t notificationFrames, // 这个为0
        const sp<IMemory>& sharedBuffer, // 这个为0
        bool threadCanCallJava,
        int sessionId,
        transfer_type transferType,//TRANSFER_SYNC 
        const audio_offload_info_t *offloadInfo,
        int uid,
        pid_t pid,
        const audio_attributes_t* pAttributes,
        bool doNotReconnect)
{

    switch (transferType) {
    case TRANSFER_DEFAULT:
        if (sharedBuffer != 0) {
            transferType = TRANSFER_SHARED;
        } else if (cbf == NULL || threadCanCallJava) {
            transferType = TRANSFER_SYNC;
        } else {
            transferType = TRANSFER_CALLBACK;
        }
        break;
    case TRANSFER_CALLBACK:
        if (cbf == NULL || sharedBuffer != 0) {
            return BAD_VALUE;
        }
        break;
    case TRANSFER_OBTAIN:
    case TRANSFER_SYNC:
        // 要求sharedBuffer必须为0
        if (sharedBuffer != 0) {
            return BAD_VALUE;
        }
        break;
    case TRANSFER_SHARED:
        if (sharedBuffer == 0) {
            return BAD_VALUE;
        }
        break;
    default:
        return BAD_VALUE;
    }
    mSharedBuffer = sharedBuffer;
    mTransfer = transferType;
    mDoNotReconnect = doNotReconnect;

    // mAudioTrack != 0为true,只有在成功跑完set之后才会成立。
    if (mAudioTrack != 0) {
        return INVALID_OPERATION;
    }

    // handle default values first.
    if (streamType == AUDIO_STREAM_DEFAULT) {
        streamType = AUDIO_STREAM_MUSIC;
    }
    if (pAttributes == NULL) {
        if (uint32_t(streamType) >= AUDIO_STREAM_PUBLIC_CNT) {
            return BAD_VALUE;
        }
        mStreamType = streamType;

    } else {
        // 拷贝属性,并且设置mStreamType为默认值,stream type不用去看,因为有audio attribute
        memcpy(&mAttributes, pAttributes, sizeof(audio_attributes_t));
        mStreamType = AUDIO_STREAM_DEFAULT;
        if ((mAttributes.flags & AUDIO_FLAG_HW_AV_SYNC) != 0) {
            flags = (audio_output_flags_t)(flags | AUDIO_OUTPUT_FLAG_HW_AV_SYNC);
        }
    }

    // these below should probably come from the audioFlinger too...
    // 下面的这些应该可能来自AudioFlinger。
    if (format == AUDIO_FORMAT_DEFAULT) {
        format = AUDIO_FORMAT_PCM_16_BIT;
    }

    // validate parameters
    if (!audio_is_valid_format(format)) {
        return BAD_VALUE;
    }
    mFormat = format;

    if (!audio_is_output_channel(channelMask)) {
        return BAD_VALUE;
    }
    mChannelMask = channelMask;
    uint32_t channelCount = audio_channel_count_from_out_mask(channelMask);
    mChannelCount = channelCount;

    // 如果format不是一个线性PCM或者要求是offload的话,则强制打上direct flag。
    if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
            || !audio_is_linear_pcm(format)) {
        flags = (audio_output_flags_t)
                // fast跟direct不能共存。fast在mixer线程,direct在direct线程
                ((flags | AUDIO_OUTPUT_FLAG_DIRECT) & ~AUDIO_OUTPUT_FLAG_FAST);
    }

    // 如果要求音视频同步,也强制打上direct flag
    if ((flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC) != 0) {
        flags = (audio_output_flags_t)(flags | AUDIO_OUTPUT_FLAG_DIRECT);
    }

    if (flags & AUDIO_OUTPUT_FLAG_DIRECT) {
        // 如果是含有direct flag,并且是线性pcm的话,我们需要根据fomat和channelCount来计算帧大小
        // 否则,如果不是线性pcm的话,那帧大小设置为1个字节,8位。
        if (audio_is_linear_pcm(format)) {
            mFrameSize = channelCount * audio_bytes_per_sample(format);
        } else {
            mFrameSize = sizeof(uint8_t);
        }
    } else {
        // 非direct的话,那计算就按照线性PCM的方式计算。
        ALOG_ASSERT(audio_is_linear_pcm(format));
        mFrameSize = channelCount * audio_bytes_per_sample(format);
        // 如果PCM format不被AudioFlinger所支持的话,则会在createTrack中返回一个错误,
        // 所以我们这边不需要特意去检测format。
    }

    // 对于带有direct flag的track,需要指定samplingRate。
    if (sampleRate == 0 && (flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0) {
        return BAD_VALUE;
    }
    mSampleRate = sampleRate;
    mOriginalSampleRate = sampleRate;
    mPlaybackRate = AUDIO_PLAYBACK_RATE_DEFAULT;

    // Make copy of input parameter offloadInfo so that in the future:
    //  (a) createTrack_l doesn't need it as an input parameter
    //  (b) we can support re-creation of offloaded tracks
    if (offloadInfo != NULL) {
        mOffloadInfoCopy = *offloadInfo;
        mOffloadInfo = &mOffloadInfoCopy;
    } else {
        mOffloadInfo = NULL;
    }

    mVolume[AUDIO_INTERLEAVE_LEFT] = 1.0f;
    mVolume[AUDIO_INTERLEAVE_RIGHT] = 1.0f;
    mSendLevel = 0.0f;
    // mFrameCount在createTrack_l中被初始化
    mReqFrameCount = frameCount;
    mNotificationFramesReq = notificationFrames;
    mNotificationFramesAct = 0;
    // sessionId如果为0,则表示需要系统帮忙分配。
    if (sessionId == AUDIO_SESSION_ALLOCATE) {
        mSessionId = AudioSystem::newAudioUniqueId();
    } else {
        mSessionId = sessionId;
    }
    int callingpid = IPCThreadState::self()->getCallingPid();
    int mypid = getpid();
    if (uid == -1 || (callingpid != mypid)) {
        mClientUid = IPCThreadState::self()->getCallingUid();
    } else {
        mClientUid = uid;
    }
    if (pid == -1 || (callingpid != mypid)) {
        mClientPid = callingpid;
    } else {
        mClientPid = pid;
    }
    mAuxEffectId = 0;
    mFlags = flags;
    mCbf = cbf;
    // java调用下来的,这边cbf是不为null的。所以java创建的audiotrack都是会创建AudioTrackThread的
    if (cbf != NULL) {
        mAudioTrackThread = new AudioTrackThread(*this, threadCanCallJava);
        mAudioTrackThread->run("AudioTrack", ANDROID_PRIORITY_AUDIO, 0 /*stack*/);
        // 线程一开始会被paused状态所暂停,直到我们调用了start函数
    }

    // 创建binder IAudioTrack
    status_t status = createTrack_l();
    // 如果出现问题,则销毁mAudioTrackThread
    if (status != NO_ERROR) {
        if (mAudioTrackThread != 0) {
            mAudioTrackThread->requestExit();   // see comment in AudioTrack.h
            mAudioTrackThread->requestExitAndWait();
            mAudioTrackThread.clear();
        }
        return status;
    }

    mStatus = NO_ERROR;
    mState = STATE_STOPPED;
    mUserData = user;
    mLoopCount = 0;
    mLoopStart = 0;
    mLoopEnd = 0;
    mLoopCountNotified = 0;
    mMarkerPosition = 0;
    mMarkerReached = false;
    mNewPosition = 0;
    mUpdatePeriod = 0;
    mPosition = 0;
    mReleased = 0;
    mStartUs = 0;
    // 这个函数会在AudioFlinger中创建AudioSessionRef对象,并且进行保存。
    AudioSystem::acquireAudioSessionId(mSessionId, mClientPid);
    mSequence = 1;
    mObservedSequence = mSequence;
    mInUnderrun = false;
    mPreviousTimestampValid = false;
    mTimestampStartupGlitchReported = false;
    mRetrogradeMotionReported = false;

    return NO_ERROR;
}

上面的函数主要干了几件事:

  1. 对参数的转换和检验,主要是对flag的特殊处理,并且保存了一些数据
  2. audiotrack的回调线程的创建和运行
  3. 创建IAudioTrack,这是个binder对象,这个对象是audiotrack在AudioFlinger的代理
  4. acquireAudioSessionId的调用,会在AudioFlinger中对sessionid进行记录。

我们来看下关键性函数:createTrack_l

status_t AudioTrack::createTrack_l()
{
    // 这个我们上面已经看过了,获取AudioFlinger binder对象。
    const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
    if (audioFlinger == 0) {
        return NO_INIT;
    }
    // 这个需要在set函数调用之前,通过addAudioDeviceCallback进行设置。
    if (mDeviceCallback != 0 && mOutput != AUDIO_IO_HANDLE_NONE) {
        AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mOutput);
    }
    audio_io_handle_t output;
    audio_stream_type_t streamType = mStreamType;
    // 有属性就会选择属性,这个做法是为了兼容老版本没有属性的时候
    audio_attributes_t *attr = (mStreamType == AUDIO_STREAM_DEFAULT) ? &mAttributes : NULL;

    status_t status;
    // 获取output的操作,从函数名字可以知道是根据attribute来获取。
    status = AudioSystem::getOutputForAttr(attr, &output,
                                           (audio_session_t)mSessionId, &streamType, mClientUid,
                                           mSampleRate, mFormat, mChannelMask,
                                           mFlags, mSelectedDeviceId, mOffloadInfo);
    // 获取失败
    if (status != NO_ERROR || output == AUDIO_IO_HANDLE_NONE) {
        return BAD_VALUE;
    }
    // 获取成功
    {
    // 由于上面获取output成功的话,则会在AudioPolicy那边注册mOutputRoutes,并且对于direct output
    // 如果获取到的是已经创建过的,则会增加引用计数。
    // 但是我们还没用通过这个io索引去跟AudioFlinger交互,尚未被登记到AudioFlinger,
    // 如果该track被登记到AudioFlinger,AudioFlinger就会维护output的信息,但是我们目前没有注册过去
    // 所以下面我们一旦有出错,我们必须自己手动释放掉该output。

    // 获取output的latency
    status = AudioSystem::getLatency(output, &mAfLatency);
    if (status != NO_ERROR) {
        goto release;
    }
    // 获取output的mAfFrameCount
    status = AudioSystem::getFrameCount(output, &mAfFrameCount);
    if (status != NO_ERROR) {
        goto release;
    }
    // 获取output的mAfSampleRate
    status = AudioSystem::getSamplingRate(output, &mAfSampleRate);
    if (status != NO_ERROR) {
        goto release;
    }
    // 如果之前没有设置采样率,则使用该output当前的采样率
    if (mSampleRate == 0) {
        mSampleRate = mAfSampleRate;
        mOriginalSampleRate = mAfSampleRate;
    }
    // Client decides whether the track is TIMED (see below), but can only express a preference
    // for FAST.  Server will perform additional tests.
    // 如果你想采用FAST模式,那你只能用共享内存,或者Callback、TRANSFER_OBTAIN的形式,并且必须保证
    // 采样率跟对应的output一致才行。这个是client端这边的要求,server端也有要求。
    if ((mFlags & AUDIO_OUTPUT_FLAG_FAST) && !((
            (mSharedBuffer != 0) ||
            (mTransfer == TRANSFER_CALLBACK) ||
            (mTransfer == TRANSFER_OBTAIN)) &&
            (mSampleRate == mAfSampleRate))) {
        // once denied, do not request again if IAudioTrack is re-created
        mFlags = (audio_output_flags_t) (mFlags & ~AUDIO_OUTPUT_FLAG_FAST);
    }

    // The client's AudioTrack buffer is divided into n parts for purpose of wakeup by server, where
    // client端的audiotrack的buffer被分成几部分,server端根据这个来唤醒client填充数据
    //  n = 1   fast track with single buffering; nBuffering is ignored
    //  n = 2   fast track with double buffering
    //  n = 2   normal track, (including those with sample rate conversion)
    //  n >= 3  very high latency or very small notification interval (unused).
    const uint32_t nBuffering = 2;

    mNotificationFramesAct = mNotificationFramesReq;
    // mReqFrameCount这个就是app申请的大小
    size_t frameCount = mReqFrameCount;
    // 如果不是线性pcm的话,并且采用share memory则获取share memory的size,不是采用share memory并
    // 且framecount为0, 则用hal的framecount, 如果mNotificationFramesAct不等于framecount,则用
    // framecount赋值给mNotificationFramesAct
    // 如果是线性pcm的话,如果采用的是share memory,先不说了。。。。
    // 如果是线性pcm的话,不是采用share memory,对于非fast track,会先计算下所需要的
    // calculateMinFrameCount,这边用的是获取到的值就有参考意义了,因为这边的output获取的是最后会
    // 用来播放output thread。
    if (!audio_is_linear_pcm(mFormat)) {

        if (mSharedBuffer != 0) {
            // Same comment as below about ignoring frameCount parameter for set()
            frameCount = mSharedBuffer->size();
        } else if (frameCount == 0) {
            frameCount = mAfFrameCount;
        }
        if (mNotificationFramesAct != frameCount) {
            mNotificationFramesAct = frameCount;
        }
    } else if (mSharedBuffer != 0) {
        // FIXME: Ensure client side memory buffers need
        // not have additional alignment beyond sample
        // (e.g. 16 bit stereo accessed as 32 bit frame).
        size_t alignment = audio_bytes_per_sample(mFormat);
        if (alignment & 1) {
            // for AUDIO_FORMAT_PCM_24_BIT_PACKED (not exposed through Java).
            alignment = 1;
        }
        if (mChannelCount > 1) {
            // More than 2 channels does not require stronger alignment than stereo
            alignment <<= 1;
        }
        if (((uintptr_t)mSharedBuffer->pointer() & (alignment - 1)) != 0) {
            status = BAD_VALUE;
            goto release;
        }

        // When initializing a shared buffer AudioTrack via constructors,
        // there's no frameCount parameter.
        // But when initializing a shared buffer AudioTrack via set(),
        // there _is_ a frameCount parameter.  We silently ignore it.
        frameCount = mSharedBuffer->size() / mFrameSize;
    } else {
        // 对于fast tracks framecount是在server端进行计算和检测的。

        if ((mFlags & AUDIO_OUTPUT_FLAG_FAST) == 0) {
            // 对于普通的tracks,之前计算是基于速度的。
            const size_t minFrameCount = calculateMinFrameCount(
                    mAfLatency, mAfFrameCount, mAfSampleRate, mSampleRate,
                    mPlaybackRate.mSpeed);
            if (frameCount < minFrameCount) {
                frameCount = minFrameCount;
            }
        }
    }

    IAudioFlinger::track_flags_t trackFlags = IAudioFlinger::TRACK_DEFAULT;
    // 如果是timetrack的话,加上TRACK_TIMED
    if (mIsTimed) {
        trackFlags |= IAudioFlinger::TRACK_TIMED;
    }

    pid_t tid = -1;
    if (mFlags & AUDIO_OUTPUT_FLAG_FAST) {
        trackFlags |= IAudioFlinger::TRACK_FAST;
        if (mAudioTrackThread != 0) {
            tid = mAudioTrackThread->getTid();
        }
    }

    if (mFlags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
        trackFlags |= IAudioFlinger::TRACK_OFFLOAD;
    }

    if (mFlags & AUDIO_OUTPUT_FLAG_DIRECT) {
        trackFlags |= IAudioFlinger::TRACK_DIRECT;
    }

    size_t temp = frameCount;   // temp may be replaced by a revised value of frameCount,
                                // but we will still need the original value also
    int originalSessionId = mSessionId;
    // 这个函数后面拉出来分析
    sp<IAudioTrack> track = audioFlinger->createTrack(streamType,
                                                      mSampleRate,
                                                      mFormat,
                                                      mChannelMask,
                                                      &temp,
                                                      &trackFlags,
                                                      mSharedBuffer,
                                                      output,
                                                      tid,
                                                      &mSessionId,
                                                      mClientUid,
                                                      &status);

    if (status != NO_ERROR) {
        goto release;
    }
    ALOG_ASSERT(track != 0);

    // 通过AudioFlinger去创建track之后,AudioFlinger就已经拥有I/O handle的引用了
    // 所以我们就不用再去负责释放handle的释放问题了。

    sp<IMemory> iMem = track->getCblk();
    if (iMem == 0) {
        return NO_INIT;
    }
    void *iMemPointer = iMem->pointer();
    if (iMemPointer == NULL) {
        return NO_INIT;
    }
    // 只有set成功之后,mAudioTrack才不为0,这边先释放mDeathNotifier
    if (mAudioTrack != 0) {
        IInterface::asBinder(mAudioTrack)->unlinkToDeath(mDeathNotifier, this);
        mDeathNotifier.clear();
    }
    mAudioTrack = track;
    mCblkMemory = iMem;
    IPCThreadState::self()->flushCommands();

    audio_track_cblk_t* cblk = static_cast<audio_track_cblk_t*>(iMemPointer);
    mCblk = cblk;
    // temp可能是被修改过了。如果被修改的话,只可能变大。
    if (temp < frameCount || (frameCount == 0 && temp == 0)) {
        // 在当前这种设计,AudioTrack这边会先检查并且确认这个值是有效的才会传递给AudioFlinger,所
        // 以AudioFlinger是不会返回一个不一样的值的,除了fast track,它使用的是一个特殊的方法来指
        // 定frame count
        ALOGW("Requested frameCount %zu but received frameCount %zu", frameCount, temp);
    }
    frameCount = temp;

    // 是否等待线程的优先级设置成功了。这个是针对fast track的变量
    mAwaitBoost = false;
    if (mFlags & AUDIO_OUTPUT_FLAG_FAST) {
        if (trackFlags & IAudioFlinger::TRACK_FAST) {
            // 如果这个track申请fast通过AudioFlinger那边的审查之后,就需要等待线程优先级设置了。
            mAwaitBoost = true;
        } else {
            // once denied, do not request again if IAudioTrack is re-created
            // 将该标志移除,只要失败一次,下次re-created的话也不会再触发fast的判断了。
            mFlags = (audio_output_flags_t) (mFlags & ~AUDIO_OUTPUT_FLAG_FAST);
        }
    }
    if (mFlags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
        if (trackFlags & IAudioFlinger::TRACK_OFFLOAD) {
            ALOGV("AUDIO_OUTPUT_FLAG_OFFLOAD successful");
        } else {
            // 申请offload失败
            mFlags = (audio_output_flags_t) (mFlags & ~AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD);
        }
    }
    if (mFlags & AUDIO_OUTPUT_FLAG_DIRECT) {
        if (trackFlags & IAudioFlinger::TRACK_DIRECT) {
            ALOGV("AUDIO_OUTPUT_FLAG_DIRECT successful");
        } else {
            mFlags = (audio_output_flags_t) (mFlags & ~AUDIO_OUTPUT_FLAG_DIRECT);
        }
    }
    // Make sure that application is notified with sufficient margin before underrun
    // 确保及时问app要数据,在buffer内还有不少数据的情况下,防止出现underrun
    if (mSharedBuffer == 0 && audio_is_linear_pcm(mFormat)) {
        // Theoretically double-buffering is not required for fast tracks,
        // due to tighter scheduling.  But in practice, to accommodate kernels with
        // scheduling jitter, and apps with computation jitter, we use double-buffering
        // for fast tracks just like normal streaming tracks.
        // 确定消费了多少帧可以唤醒audiotrack来填充数据。
        if (mNotificationFramesAct == 0 || mNotificationFramesAct > frameCount / nBuffering) {
            mNotificationFramesAct = frameCount / nBuffering;
        }
    }

    // We retain a copy of the I/O handle, but don't own the reference
    mOutput = output;
    mRefreshRemaining = true;
    // 确定buffer的地址,对于非share memory的话,在cblk下面。
    void* buffers;
    if (mSharedBuffer == 0) {
        buffers = cblk + 1;
    } else {
        buffers = mSharedBuffer->pointer();
        if (buffers == NULL) {
            ALOGE("Could not get buffer pointer");
            return NO_INIT;
        }
    }
    // 这部分后面再做补充吧。关于AuxEffect
    mAudioTrack->attachAuxEffect(mAuxEffectId);
    // 如果申请OFFLAOD成功的话,latency采用hal的latency,否则我们自己计算一个latency
    if (mFlags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
        // Use latency given by HAL in offload mode
        mLatency = mAfLatency;
    } else {
        // FIXME doesn't take into account speed or future sample rate changes (until restoreTrack)
        // FIXME don't believe this lie
        // 这个是上层计算的延时,申请的空间所花费时间+hal的latency。
        mLatency = mAfLatency + (1000*frameCount) / mSampleRate;
    }
    mFrameCount = frameCount;

    // 如果出现IAudioTrack的re-created的话,为了防止分配空间不一致,所以将申请到的空间直接替换用户
    // 请求的。什么情况下出现re-created的场景?为什么需要如此?
    if (frameCount > mReqFrameCount) {
        mReqFrameCount = frameCount;
    }

    // reset server position to 0 as we have new cblk.
    mServer = 0;

    // 更新proxy
    if (mSharedBuffer == 0) {
        mStaticProxy.clear();
        mProxy = new AudioTrackClientProxy(cblk, buffers, frameCount, mFrameSize);
    } else {
        mStaticProxy = new StaticAudioTrackClientProxy(cblk, buffers, frameCount, mFrameSize);
        mProxy = mStaticProxy;
    }

    mProxy->setVolumeLR(gain_minifloat_pack(
            gain_from_float(mVolume[AUDIO_INTERLEAVE_LEFT]),
            gain_from_float(mVolume[AUDIO_INTERLEAVE_RIGHT])));

    mProxy->setSendLevel(mSendLevel);
    const uint32_t effectiveSampleRate = adjustSampleRate(mSampleRate, mPlaybackRate.mPitch);
    const float effectiveSpeed = adjustSpeed(mPlaybackRate.mSpeed, mPlaybackRate.mPitch);
    const float effectivePitch = adjustPitch(mPlaybackRate.mPitch);
    mProxy->setSampleRate(effectiveSampleRate);

    AudioPlaybackRate playbackRateTemp = mPlaybackRate;
    playbackRateTemp.mSpeed = effectiveSpeed;
    playbackRateTemp.mPitch = effectivePitch;
    mProxy->setPlaybackRate(playbackRateTemp);
    // 将刚才计算出来server端消费多少可以通知app的数值告诉代理。
    mProxy->setMinimum(mNotificationFramesAct);
    // 如果IAudioTrack挂掉了,做一些后续工作,让audiotrack不用等待了,并且设置INVALID状态
    mDeathNotifier = new DeathNotifier(this);
    IInterface::asBinder(mAudioTrack)->linkToDeath(mDeathNotifier, this);

    if (mDeviceCallback != 0) {
        AudioSystem::addAudioDeviceCallback(mDeviceCallback, mOutput);
    }

    return NO_ERROR;
    }

release:
    // 释放output
    AudioSystem::releaseOutput(output, streamType, (audio_session_t)mSessionId);
    if (status == NO_ERROR) {
        status = NO_INIT;
    }
    return status;
}

上面函数主要干了几件事:

  1. 通过创建的audiotrack的attribute来获取对应的output thread。
  2. 针对fast track进行过滤,并且构造track的flag
  3. 接下来让AudioFlinger去创建IAudioTrack对象,由于server端也需要检测track类型,所以返回后需要更新audiotrack这边的flag的信息。
  4. 通知proxy什么时候可以通知audiotrack填充数据。

AudioPolicyManager::getOutputForAttr()这个函数的实现跟我们上面加过的getOutput差不多,只是这边传递attribute来获取,并且这次获取的,跟我们本次申请的是一致的。

我们来看AudioFlinger的createTrack的实现

sp<IAudioTrack> AudioFlinger::createTrack(
        audio_stream_type_t streamType,
        uint32_t sampleRate,
        audio_format_t format,
        audio_channel_mask_t channelMask,
        size_t *frameCount,
        IAudioFlinger::track_flags_t *flags,
        const sp<IMemory>& sharedBuffer,
        audio_io_handle_t output,// 这个是output的索引
        pid_t tid,
        int *sessionId,
        int clientUid,
        status_t *status)
{
    sp<PlaybackThread::Track> track;
    sp<TrackHandle> trackHandle;
    sp<Client> client;
    status_t lStatus;
    int lSessionId;

    // client AudioTrack::set already implements AUDIO_STREAM_DEFAULT => AUDIO_STREAM_MUSIC,
    // but if someone uses binder directly they could bypass that and cause us to crash
    if (uint32_t(streamType) >= AUDIO_STREAM_CNT) {
        lStatus = BAD_VALUE;
        goto Exit;
    }

    // further sample rate checks are performed by createTrack_l() depending on the thread type
    if (sampleRate == 0) {
        lStatus = BAD_VALUE;
        goto Exit;
    }

    // further channel mask checks are performed by createTrack_l() depending on the thread type
    if (!audio_is_output_channel(channelMask)) {
        lStatus = BAD_VALUE;
        goto Exit;
    }

    // further format checks are performed by createTrack_l() depending on the thread type
    if (!audio_is_valid_format(format)) {
        lStatus = BAD_VALUE;
        goto Exit;
    }

    if (sharedBuffer != 0 && sharedBuffer->pointer() == NULL) {
        lStatus = BAD_VALUE;
        goto Exit;
    }

    {
        Mutex::Autolock _l(mLock);
        // 根据output索引获取到output thread对象
        PlaybackThread *thread = checkPlaybackThread_l(output);
        if (thread == NULL) {
            lStatus = BAD_VALUE;
            goto Exit;
        }
        // 这边又注册了一次client。
        pid_t pid = IPCThreadState::self()->getCallingPid();
        client = registerPid(pid);

        PlaybackThread *effectThread = NULL;
        if (sessionId != NULL && *sessionId != AUDIO_SESSION_ALLOCATE) {
            lSessionId = *sessionId;
            // 检测是否有一个相同session id的效果链在另外一个output thread,有的话则移过来。
            for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
                sp<PlaybackThread> t = mPlaybackThreads.valueAt(i);
                if (mPlaybackThreads.keyAt(i) != output) {
                    uint32_t sessions = t->hasAudioSession(lSessionId);
                    if (sessions & PlaybackThread::EFFECT_SESSION) {
                        effectThread = t.get();
                        break;
                    }
                }
            }
        } else {
            // sessionid没有指定,则给自动分配一个
            lSessionId = nextUniqueId();
            if (sessionId != NULL) {
                *sessionId = lSessionId;
            }
        }
        // 让对应的output thread去创建track
        track = thread->createTrack_l(client, streamType, sampleRate, format,
                channelMask, frameCount, sharedBuffer, lSessionId, flags, tid, clientUid, &lStatus);
        LOG_ALWAYS_FATAL_IF((lStatus == NO_ERROR) && (track == 0));
        // we don't abort yet if lStatus != NO_ERROR; there is still work to be done regardless

        // move effect chain to this output thread if an effect on same session was waiting
        // for a track to be created
        // 如果track被创建成功,并且存在effectThread的话,我们就将效果给移过来。
        if (lStatus == NO_ERROR && effectThread != NULL) {
            // no risk of deadlock because AudioFlinger::mLock is held
            Mutex::Autolock _dl(thread->mLock);
            Mutex::Autolock _sl(effectThread->mLock);
            moveEffectChain_l(lSessionId, effectThread, thread, true);
        }

        // Look for sync events awaiting for a session to be used.
        // 这部分不太清楚作用,后面再看看
        for (size_t i = 0; i < mPendingSyncEvents.size(); i++) {
            if (mPendingSyncEvents[i]->triggerSession() == lSessionId) {
                if (thread->isValidSyncEvent(mPendingSyncEvents[i])) {
                    if (lStatus == NO_ERROR) {
                        (void) track->setSyncEvent(mPendingSyncEvents[i]);
                    } else {
                        mPendingSyncEvents[i]->cancel();
                    }
                    mPendingSyncEvents.removeAt(i);
                    i--;
                }
            }
        }

        setAudioHwSyncForSession_l(thread, (audio_session_t)lSessionId);
    }

    if (lStatus != NO_ERROR) {
        // remove local strong reference to Client before deleting the Track so that the
        // Client destructor is called by the TrackBase destructor with mClientLock held
        // Don't hold mClientLock when releasing the reference on the track as the
        // destructor will acquire it.
        {
            Mutex::Autolock _cl(mClientLock);
            client.clear();
        }
        track.clear();
        goto Exit;
    }

    // return handle to client
    // 封装一个binder对象给audiotrack.
    trackHandle = new TrackHandle(track);

Exit:
    *status = lStatus;
    return trackHandle;
}

上面函数主要也是对一些参数的检测,以及确认是否有效果需要转移过来,如果有则转移.
这边又对pid注册了一个client在AudioFlinger。
但是我们主体逻辑还是在output thread去createTrack_l的。

sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrack_l(
        const sp<AudioFlinger::Client>& client,
        audio_stream_type_t streamType,
        uint32_t sampleRate,
        audio_format_t format,
        audio_channel_mask_t channelMask,
        size_t *pFrameCount,
        const sp<IMemory>& sharedBuffer,
        int sessionId,
        IAudioFlinger::track_flags_t *flags,
        pid_t tid,
        int uid,
        status_t *status)
{
    size_t frameCount = *pFrameCount;
    sp<Track> track;
    status_t lStatus;

    bool isTimed = (*flags & IAudioFlinger::TRACK_TIMED) != 0;

    // fast track能否成功最后还是AudioFlinger说的算。
    if (*flags & IAudioFlinger::TRACK_FAST) {
        // 要想通过fast的确认,可以看出要求很严格,首先不能是timeAudioTrack,其次可以是
        // sharebuffer,或者是有Callback并且申请的framecount大于hal层的framecount,再次,必须是
        // pcm流,在再次,channel一致或者channel为单声道或者线程不为立体声道,在在再次,采样率一致,
        // 在在在再次,有关联的fast mixer,在在在在再次,还有坑。。
      if (
            // not timed
            (!isTimed) &&
            // either of these use cases:
            (
              // use case 1: shared buffer with any frame count
              (
                (sharedBuffer != 0)
              ) ||
              // use case 2: frame count is default or at least as large as HAL
              (
                // we formerly checked for a callback handler (non-0 tid),
                // but that is no longer required for TRANSFER_OBTAIN mode
                ((frameCount == 0) ||
                (frameCount >= mFrameCount))
              )
            ) &&
            // PCM data
            audio_is_linear_pcm(format) &&
            // TODO: extract as a data library function that checks that a computationally
            // expensive downmixer is not required: isFastOutputChannelConversion()
            (channelMask == mChannelMask ||
                    mChannelMask != AUDIO_CHANNEL_OUT_STEREO ||
                    (channelMask == AUDIO_CHANNEL_OUT_MONO
                            /* && mChannelMask == AUDIO_CHANNEL_OUT_STEREO */)) &&
            // hardware sample rate
            (sampleRate == mSampleRate) &&
            // 普通mixer线程会有一个关联的fast mixer
            hasFastMixer() &&
            // there are sufficient fast track slots available
            (mFastTrackAvailMask != 0)
            // FIXME test that MixerThread for this fast track has a capable output HAL
            // FIXME add a permission test also?
        ) {
        // if frameCount not specified, then it defaults to fast mixer (HAL) frame count
        if (frameCount == 0) {
            // read the fast track multiplier property the first time it is needed
            int ok = pthread_once(&sFastTrackMultiplierOnce, sFastTrackMultiplierInit);
            if (ok != 0) {
                ALOGE("%s pthread_once failed: %d", __func__, ok);
            }
            // 为fast track计算framecount
            frameCount = mFrameCount * sFastTrackMultiplier;
        }
      } else {
        *flags &= ~IAudioFlinger::TRACK_FAST;
      }
    }
    // For normal PCM streaming tracks, update minimum frame count.
    // For compatibility with AudioTrack calculation, buffer depth is forced
    // to be at least 2 x the normal mixer frame count and cover audio hardware latency.
    // This is probably too conservative, but legacy application code may depend on it.
    // If you change this calculation, also review the start threshold which is related.
    // 更新最小的framecount,如果framecount小于最低的,则用最低来替换。
    if (!(*flags & IAudioFlinger::TRACK_FAST)
            && audio_is_linear_pcm(format) && sharedBuffer == 0) {
        // this must match AudioTrack.cpp calculateMinFrameCount().
        // TODO: Move to a common library
        uint32_t latencyMs = mOutput->stream->get_latency(mOutput->stream);
        uint32_t minBufCount = latencyMs / ((1000 * mNormalFrameCount) / mSampleRate);
        if (minBufCount < 2) {
            minBufCount = 2;
        }
        // For normal mixing tracks, if speed is > 1.0f (normal), AudioTrack
        // or the client should compute and pass in a larger buffer request.
        size_t minFrameCount =
                minBufCount * sourceFramesNeededWithTimestretch(
                        sampleRate, mNormalFrameCount,
                        mSampleRate, AUDIO_TIMESTRETCH_SPEED_NORMAL /*speed*/);
        if (frameCount < minFrameCount) { // including frameCount == 0
            frameCount = minFrameCount;
        }
    }
    *pFrameCount = frameCount;

    switch (mType) {
    // DIRECT 线程 如果是线性PCM, 要求所有的参数都必须符合。
    case DIRECT:
        if (audio_is_linear_pcm(format)) {
            if (sampleRate != mSampleRate || format != mFormat || channelMask != mChannelMask) {
                lStatus = BAD_VALUE;
                goto Exit;
            }
        }
        break;
    // OFFLOAD 线程 要求所有的参数必须符合。
    case OFFLOAD:
        if (sampleRate != mSampleRate || format != mFormat || channelMask != mChannelMask) {
            lStatus = BAD_VALUE;
            goto Exit;
        }
        break;

    default:
        if (!audio_is_linear_pcm(format)) {
                lStatus = BAD_VALUE;
                goto Exit;
        }
        // 如果采样率要src到很低的阈值,则ERROR提示。
        if (sampleRate > mSampleRate * AUDIO_RESAMPLER_DOWN_RATIO_MAX) {
            lStatus = BAD_VALUE;
            goto Exit;
        }
        break;

    }
    // 只是单纯的判断了下mOutput这个成员是否为空
    lStatus = initCheck();
    if (lStatus != NO_ERROR) {
        goto Exit;
    }

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

        // 所有的tracks使用相同的audio session必须共享相同的路由策略,否则当AudioPolicyManager在
        // 将tracks从一个output移到另外一个output的时候会产生冲突。
        uint32_t strategy = AudioSystem::getStrategyForStream(streamType);
        for (size_t i = 0; i < mTracks.size(); ++i) {
            sp<Track> t = mTracks[i];
            if (t != 0 && t->isExternalTrack()) {
                uint32_t actual = AudioSystem::getStrategyForStream(t->streamType());
                if (sessionId == t->sessionId() && strategy != actual) {
                    lStatus = BAD_VALUE;
                    goto Exit;
                }
            }
        }

        if (!isTimed) {
            // 创建track实例
            track = new Track(this, client, streamType, sampleRate, format,
                              channelMask, frameCount, NULL, sharedBuffer,
                              sessionId, uid, *flags, TrackBase::TYPE_DEFAULT);
        } else {
            // 创建timetrack实例
            track = TimedTrack::create(this, client, streamType, sampleRate, format,
                    channelMask, frameCount, sharedBuffer, sessionId, uid);
        }

        // Track通过new的方式,所以它肯定是non-NULL,所以需要进一步initCheck。
        // 而TimedTrack是通过工厂方法进行创建的,所以它可能返回null。
        lStatus = track != 0 ? track->initCheck() : (status_t) NO_MEMORY;
        if (lStatus != NO_ERROR) {
            // track must be cleared from the caller as the caller has the AF lock
            goto Exit;
        }
        // 将该track添加到thread的mTracks中。
        mTracks.add(track);
        // 获取这个sessionid的效果链
        sp<EffectChain> chain = getEffectChain_l(sessionId);
        if (chain != 0) {
            // 不为0的话,则设置track的输出output为效果链的InBuffer。
            track->setMainBuffer(chain->inBuffer());
            // 设置效果链的策略为当前这个track的streamtype所获取到的策略。
            chain->setStrategy(AudioSystem::getStrategyForStream(track->streamType()));
            // 效果链中track引用计数加1.
            chain->incTrackCnt();
        }
        // flag含有fast标志,并且存在Callback。
        if ((*flags & IAudioFlinger::TRACK_FAST) && (tid != -1)) {
            pid_t callingPid = IPCThreadState::self()->getCallingPid();
            // 用户进程没有CAP_SYS_NICE,但是我们又想该进程能够获取得高的调度权限(FIFO或者RR),
            // 所以只能让系统进程管理(scheduling_policy)代我们来帮忙获取。
            sendPrioConfigEvent_l(callingPid, tid, kPriorityAudioApp);
        }
    }

    lStatus = NO_ERROR;

Exit:
    *status = lStatus;
    return track;
}

上面函数主要做了几件事:

  1. 确认fast是否符合server端的要求
  2. 重新计算framecount
  3. output的类型判断是否符合要求
  4. 创建track的实例
  5. 效果方面的设置
  6. 如果是fast的话,则申请调度权限

我们重点是来看Track的创建了。

这个我们要分两部分来看,先看Track的基类TrackBase的构造函数:

AudioFlinger::ThreadBase::TrackBase::TrackBase(
            ThreadBase *thread,
            const sp<Client>& client,// 这个是AudioFlinger那边给构造的client
            uint32_t sampleRate,
            audio_format_t format,
            audio_channel_mask_t channelMask,
            size_t frameCount,
            void *buffer,
            int sessionId,
            int clientUid,
            IAudioFlinger::track_flags_t flags,
            bool isOut,
            alloc_type alloc,
            track_type type)
    :   RefBase(),
        mThread(thread),
        mClient(client),
        mCblk(NULL),
        // mBuffer
        mState(IDLE),//Track的初始状态为IDLE
        mSampleRate(sampleRate),
        mFormat(format),
        mChannelMask(channelMask),
        mChannelCount(isOut ?
                audio_channel_count_from_out_mask(channelMask) :
                audio_channel_count_from_in_mask(channelMask)),
        // mFrameSize,如果是线性pcm的话,则用通道数*采样精度。
        mFrameSize(audio_is_linear_pcm(format) ?
                mChannelCount * audio_bytes_per_sample(format) : sizeof(int8_t)),
        mFrameCount(frameCount),
        mSessionId(sessionId),
        mFlags(flags),
        mIsOut(isOut),
        mServerProxy(NULL),
        mId(android_atomic_inc(&nextTrackId)),
        mTerminated(false),
        mType(type),
        mThreadIoHandle(thread->id())
{
    // if the caller is us, trust the specified uid
    if (IPCThreadState::self()->getCallingPid() != getpid_cached || clientUid == -1) {
        int newclientUid = IPCThreadState::self()->getCallingUid();
        if (clientUid != -1 && clientUid != newclientUid) {
            ALOGW("uid %d tried to pass itself off as %d", newclientUid, clientUid);
        }
        clientUid = newclientUid;
    }
    // clientUid contains the uid of the app that is responsible for this track, so we can blame
    // battery usage on it.
    // clientUid包含app的uid,是这个track的owner,所以对于耗电量我们可以来找它。
    mUid = clientUid;

    size_t size = sizeof(audio_track_cblk_t);
    // 如果buffer是为空,则roundup(frameCount),否则就自带的
    // roundup(frameCount)就是的多一位2进制位。thread创建track的时候,传递进来的buffer为NULL
    size_t bufferSize = (buffer == NULL ? roundup(frameCount) : frameCount) * mFrameSize;
    if (buffer == NULL && alloc == ALLOC_CBLK) {
        size += bufferSize;
    }

    if (client != 0) {
        // 这边采用到client进行空间的分配,后面针对这点在分析下
        mCblkMemory = client->heap()->allocate(size);
        if (mCblkMemory == 0 ||
                // 注意这边是有mCblk的赋值操作。
                (mCblk = static_cast<audio_track_cblk_t *>(mCblkMemory->pointer())) == NULL) {
            client->heap()->dump("AudioTrack");
            mCblkMemory.clear();
            return;
        }
    } else {
        // 如果client为0的话,则走这个分支,这种分配空间方式,可以免去调用结构体的构造函数。
        mCblk = (audio_track_cblk_t *) new uint8_t[size];
        // assume mCblk != NULL
    }

    // construct the shared structure in-place.
    if (mCblk != NULL) {
        // 在指定的空间,调用audio_track_cblk_t的构造函数。
        new(mCblk) audio_track_cblk_t();
        switch (alloc) {
        case ALLOC_READONLY: {
            const sp<MemoryDealer> roHeap(thread->readOnlyHeap());
            if (roHeap == 0 ||
                    (mBufferMemory = roHeap->allocate(bufferSize)) == 0 ||
                    (mBuffer = mBufferMemory->pointer()) == NULL) {
                ALOGE("not enough memory for read-only buffer size=%zu", bufferSize);
                if (roHeap != 0) {
                    roHeap->dump("buffer");
                }
                mCblkMemory.clear();
                mBufferMemory.clear();
                return;
            }
            memset(mBuffer, 0, bufferSize);
            } break;
        case ALLOC_PIPE:
            mBufferMemory = thread->pipeMemory();
            // mBuffer is the virtual address as seen from current process (mediaserver),
            // and should normally be coming from mBufferMemory->pointer().
            // However in this case the TrackBase does not reference the buffer directly.
            // It should references the buffer via the pipe.
            // Therefore, to detect incorrect usage of the buffer, we set mBuffer to NULL.
            mBuffer = NULL;
            break;
        case ALLOC_CBLK:
            // clear all buffers
            if (buffer == NULL) {
                mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
                memset(mBuffer, 0, bufferSize);
            } else {
                mBuffer = buffer;
#if 0
                mCblk->mFlags = CBLK_FORCEREADY;    // FIXME hack, need to fix the track ready logic
#endif
            }
            break;
        case ALLOC_LOCAL:
            mBuffer = calloc(1, bufferSize);
            break;
        case ALLOC_NONE:
            mBuffer = buffer;
            break;
        }

#ifdef TEE_SINK
        if (mTeeSinkTrackEnabled) {
            NBAIO_Format pipeFormat = Format_from_SR_C(mSampleRate, mChannelCount, mFormat);
            if (Format_isValid(pipeFormat)) {
                Pipe *pipe = new Pipe(mTeeSinkTrackFrames, pipeFormat);
                size_t numCounterOffers = 0;
                const NBAIO_Format offers[1] = {pipeFormat};
                ssize_t index = pipe->negotiate(offers, 1, NULL, numCounterOffers);
                ALOG_ASSERT(index == 0);
                PipeReader *pipeReader = new PipeReader(*pipe);
                numCounterOffers = 0;
                index = pipeReader->negotiate(offers, 1, NULL, numCounterOffers);
                ALOG_ASSERT(index == 0);
                mTeeSink = pipe;
                mTeeSource = pipeReader;
            }
        }
#endif

    }
}

这个函数主要是分配了buffer,并且初始化的cblk这个重要的管理结构体。需要注意的是,buffer的大小,并不是framecount*framesize,如果传进来的buffer是null的话,是有进行roundup的操作的,否则是原值(比如说sharebuffer的情况)。

接下来要看track的构造函数了:

AudioFlinger::PlaybackThread::Track::Track(
            PlaybackThread *thread,
            const sp<Client>& client,
            audio_stream_type_t streamType,
            uint32_t sampleRate,
            audio_format_t format,
            audio_channel_mask_t channelMask,
            size_t frameCount,
            void *buffer,
            const sp<IMemory>& sharedBuffer,
            int sessionId,
            int uid,
            IAudioFlinger::track_flags_t flags,
            track_type type)
    :   TrackBase(thread, client, sampleRate, format, channelMask, frameCount,
                  (sharedBuffer != 0) ? sharedBuffer->pointer() : buffer,
                  sessionId, uid, flags, true /*isOut*/,
                  // 分配空间的方式,如果类型是patch,则选第一种方案,否则选择第二种方案
                  // ALLOC_CBLK,第一种方案还看buffer是否为NULL,为空的话就选择ALLOC_LOCAL,
                  // 否则为ALLOC_NONE
                  (type == TYPE_PATCH) ? ( buffer == NULL ? ALLOC_LOCAL : ALLOC_NONE) : ALLOC_CBLK,
                  type),
    mFillingUpStatus(FS_INVALID),
    // mRetryCount initialized later when needed
    mSharedBuffer(sharedBuffer),
    mStreamType(streamType),
    mName(-1),  // see note below
    mMainBuffer(thread->mixBuffer()),// 如果有效果链的话,会被替换,目前还是指向线程的mixBuffer
    mAuxBuffer(NULL),
    mAuxEffectId(0), mHasVolumeController(false),
    mPresentationCompleteFrames(0),
    mFastIndex(-1),
    mCachedVolume(1.0),
    mIsInvalid(false),
    mAudioTrackServerProxy(NULL),
    mResumeToStopping(false),
    mFlushHwPending(false)
{
    // client == 0 意味着必须 sharedBuffer == 0
    // 但是目前位置client是不为0的,所以sharebuffer就随意了。
    ALOG_ASSERT(!(client == 0 && sharedBuffer != 0));

    ALOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %d", sharedBuffer->pointer(),
            sharedBuffer->size());

    if (mCblk == NULL) {
        return;
    }

    if (sharedBuffer == 0) {
        // 创建AudioTrack server端的代理,流模式的。
        mAudioTrackServerProxy = new AudioTrackServerProxy(mCblk, mBuffer, frameCount,
                mFrameSize, !isExternalTrack(), sampleRate);
    } else {
        // 创建静态的AudioTrack server端的代理。
        mAudioTrackServerProxy = new StaticAudioTrackServerProxy(mCblk, mBuffer, frameCount,
                mFrameSize);
    }
    mServerProxy = mAudioTrackServerProxy;

    mName = thread->getTrackName_l(channelMask, format, sessionId);
    if (mName < 0) {
        ALOGE("no more track names available");
        return;
    }
    // only allocate a fast track index if we were able to allocate a normal track name
    if (flags & IAudioFlinger::TRACK_FAST) {
        // 设置mFramesReadyIsCalledByMultipleThreads变量为true
        mAudioTrackServerProxy->framesReadyIsCalledByMultipleThreads();
        ALOG_ASSERT(thread->mFastTrackAvailMask != 0);
        // 获取从左往右第一个1的index
        int i = __builtin_ctz(thread->mFastTrackAvailMask);
        ALOG_ASSERT(0 < i && i < (int)FastMixerState::kMaxFastTracks);
        // 既然fast track是稀缺资源,我们在fast track被激活前就给分配了,这样会把后面更重要的fast
        // track给拒之门外。
        // 动态的创建将会是更好的方案。 所以亟待解决。。。
        mFastIndex = i;
        thread->mFastTrackAvailMask &= ~(1 << i);
    }
}

这边完成创建了server端的proxy了,刚才我们在看audiotrack那边的创建的时候也创建了自己的代理。

总结创建流

把所有的代码贴出来,主要是为了看到整个创建的细节,并不是为了单纯完成对流程的梳理,创建流程可以看下图:

补充

这边我们再补充下AudioTrack那边创建的线程现在的状态:

AudioTrack::AudioTrackThread::AudioTrackThread(AudioTrack& receiver, bool bCanCallJava)
    : Thread(bCanCallJava), mReceiver(receiver), mPaused(true), mPausedInt(false), mPausedNs(0LL),
      mIgnoreNextPausedInt(false)
{
}

bool AudioTrack::AudioTrackThread::threadLoop()
{
    {
        AutoMutex _l(mMyLock);
        // 从构造函数中,我们看到了mPaused一开始被设置为true,所以线程刚跑起来是在这边等待的。
        if (mPaused) {
            mMyCond.wait(mMyLock);
            // caller will check for exitPending()
            return true;
        }
        if (mIgnoreNextPausedInt) {
            mIgnoreNextPausedInt = false;
            mPausedInt = false;
        }
        if (mPausedInt) {
            if (mPausedNs > 0) {
                (void) mMyCond.waitRelative(mMyLock, mPausedNs);
            } else {
                mMyCond.wait(mMyLock);
            }
            mPausedInt = false;
            return true;
        }
    }
    if (exitPending()) {
        return false;
    }
    nsecs_t ns = mReceiver.processAudioBuffer();
    switch (ns) {
    case 0:
        return true;
    case NS_INACTIVE:
        pauseInternal();
        return true;
    case NS_NEVER:
        return false;
    case NS_WHENEVER:
        // Event driven: call wake() when callback notifications conditions change.
        ns = INT64_MAX;
        // fall through
    default:
        LOG_ALWAYS_FATAL_IF(ns < 0, "processAudioBuffer() returned %" PRId64, ns);
        pauseInternal(ns);
        return true;
    }
}

由于就算不是采用callback的形式,但是一旦是从java层创建的audiotrack都是必然会产生该线程的,并且会进入run的状态,但是由于一开始是会被pause住的,pause的取消是在后面audiotrack的start函数被触发。
我们来看jni帮java提供的回调函数的实现吧:

static void audioCallback(int event, void* user, void *info) {

    audiotrack_callback_cookie *callbackInfo = (audiotrack_callback_cookie *)user;
    {
        Mutex::Autolock l(sLock);
        if (sAudioTrackCallBackCookies.indexOf(callbackInfo) < 0) {
            return;
        }
        callbackInfo->busy = true;
    }

    switch (event) {
    case AudioTrack::EVENT_MARKER: {
        JNIEnv *env = AndroidRuntime::getJNIEnv();
        if (user != NULL && env != NULL) {
            env->CallStaticVoidMethod(
                callbackInfo->audioTrack_class,
                javaAudioTrackFields.postNativeEventInJava,
                callbackInfo->audioTrack_ref, event, 0,0, NULL);
            if (env->ExceptionCheck()) {
                env->ExceptionDescribe();
                env->ExceptionClear();
            }
        }
        } break;

    case AudioTrack::EVENT_NEW_POS: {
        JNIEnv *env = AndroidRuntime::getJNIEnv();
        if (user != NULL && env != NULL) {
            env->CallStaticVoidMethod(
                callbackInfo->audioTrack_class,
                javaAudioTrackFields.postNativeEventInJava,
                callbackInfo->audioTrack_ref, event, 0,0, NULL);
            if (env->ExceptionCheck()) {
                env->ExceptionDescribe();
                env->ExceptionClear();
            }
        }
        } break;
    }

    {
        Mutex::Autolock l(sLock);
        callbackInfo->busy = false;
        callbackInfo->cond.broadcast();
    }
}

可以看出来只是提供了两个事件的回调,一个是EVENT_MARKER一个是EVENT_NEW_POS一个是设置警戒线,一个是设置提示的帧的位置。而触发回调audiotrack的processAudioBuffer中,那我们可以猜想,java下来的audiotrack的话,该线程是不需要跑的,除非需要知道marker和new pos,否则可以一直进入sleep状态。
那如果上层设置了,但是我们并不是采用callback的形式提供数据,那线程每次执行一次的processAudioBuffer就会触发一次数据的更新,这个时候就可以反馈marker和new pos了。