Android13 AudioFlinger PlaybackThread threadLoop分析

PlaybackThread类继承ThreadBase,而ThreadBase又继承Thread ,在调用PlaybackThread.run的方法由父类的父类Thread时序,在Thread的run方法中会创建一个线程,并且允许其_threadLoop方法,在_threadLoop方法中会允许其子类的threadLoop方法,PlaybackThread 的threadLoop方法如下:

//frameworks/av/services/audioflinger/Threads.cpp
bool AudioFlinger::PlaybackThread::threadLoop()
{
    tlNBLogWriter = mNBLogWriter.get();


    Vector< sp<Track> > tracksToRemove;


    mStandbyTimeNs = systemTime();
    int64_t lastLoopCountWritten = -2; // never matches "previous" loop, when loopCount = 0.


    // MIXER
    nsecs_t lastWarning = 0;


    // DUPLICATING
    // FIXME could this be made local to while loop?
    writeFrames = 0;


    cacheParameters_l();
    mSleepTimeUs = mIdleSleepTimeUs;


    if (mType == MIXER || mType == SPATIALIZER) {
        sleepTimeShift = 0;
    }


    CpuStats cpuStats;
    const String8 myName(String8::format("thread %p type %d TID %d", this, mType, gettid()));


    acquireWakeLock();


    // mNBLogWriter logging APIs can only be called by a single thread, typically the
    // thread associated with this PlaybackThread.
    // If you want to share the mNBLogWriter with other threads (for example, binder threads)
    // then all such threads must agree to hold a common mutex before logging.
    // So if you need to log when mutex is unlocked, set logString to a non-NULL string,
    // and then that string will be logged at the next convenient opportunity.
    // See reference to logString below.
    const char *logString = NULL;


    // Estimated time for next buffer to be written to hal. This is used only on
    // suspended mode (for now) to help schedule the wait time until next iteration.
    nsecs_t timeLoopNextNs = 0;


    checkSilentMode_l();


    audio_patch_handle_t lastDownstreamPatchHandle = AUDIO_PATCH_HANDLE_NONE;


    sendCheckOutputStageEffectsEvent();


    // loopCount is used for statistics and diagnostics.
    for (int64_t loopCount = 0; !exitPending(); ++loopCount)
    {
        // Log merge requests are performed during AudioFlinger binder transactions, but
        // that does not cover audio playback. It's requested here for that reason.
        mAudioFlinger->requestLogMerge();


        cpuStats.sample(myName);


        Vector< sp<EffectChain> > effectChains;
        audio_session_t activeHapticSessionId = AUDIO_SESSION_NONE;
        bool isHapticSessionSpatialized = false;
        std::vector<sp<Track>> activeTracks;


        // If the device is AUDIO_DEVICE_OUT_BUS, check for downstream latency.
        //
        // Note: we access outDeviceTypes() outside of mLock.
        if (isMsdDevice() && outDeviceTypes().count(AUDIO_DEVICE_OUT_BUS) != 0) {
            // Here, we try for the AF lock, but do not block on it as the latency
            // is more informational.
            if (mAudioFlinger->mLock.tryLock() == NO_ERROR) {
                std::vector<PatchPanel::SoftwarePatch> swPatches;
                double latencyMs;
                status_t status = INVALID_OPERATION;
                audio_patch_handle_t downstreamPatchHandle = AUDIO_PATCH_HANDLE_NONE;
                if (mAudioFlinger->mPatchPanel.getDownstreamSoftwarePatches(id(), &swPatches) == OK
                        && swPatches.size() > 0) {
                        status = swPatches[0].getLatencyMs_l(&latencyMs);
                        downstreamPatchHandle = swPatches[0].getPatchHandle();
                }
                if (downstreamPatchHandle != lastDownstreamPatchHandle) {
                    mDownstreamLatencyStatMs.reset();
                    lastDownstreamPatchHandle = downstreamPatchHandle;
                }
                if (status == OK) {
                    // verify downstream latency (we assume a max reasonable
                    // latency of 5 seconds).
                    const double minLatency = 0., maxLatency = 5000.;
                    if (latencyMs >= minLatency && latencyMs <= maxLatency) {
                        ALOGVV("new downstream latency %lf ms", latencyMs);
                    } else {
                        ALOGD("out of range downstream latency %lf ms", latencyMs);
                        if (latencyMs < minLatency) latencyMs = minLatency;
                        else if (latencyMs > maxLatency) latencyMs = maxLatency;
                    }
                    mDownstreamLatencyStatMs.add(latencyMs);
                }
                mAudioFlinger->mLock.unlock();
            }
        } else {
            if (lastDownstreamPatchHandle != AUDIO_PATCH_HANDLE_NONE) {
                // our device is no longer AUDIO_DEVICE_OUT_BUS, reset patch handle and stats.
                mDownstreamLatencyStatMs.reset();
                lastDownstreamPatchHandle = AUDIO_PATCH_HANDLE_NONE;
            }
        }


        if (mCheckOutputStageEffects.exchange(false)) {
            checkOutputStageEffects();
        }


        { // scope for mLock


            Mutex::Autolock _l(mLock);


            processConfigEvents_l();
            if (mCheckOutputStageEffects.load()) {
                continue;
            }


            // See comment at declaration of logString for why this is done under mLock
            if (logString != NULL) {
                mNBLogWriter->logTimestamp();
                mNBLogWriter->log(logString);
                logString = NULL;
            }


            collectTimestamps_l();


            saveOutputTracks();
            if (mSignalPending) {
                // A signal was raised while we were unlocked
                mSignalPending = false;
            } else if (waitingAsyncCallback_l()) {
                if (exitPending()) {
                    break;
                }
                bool released = false;
                if (!keepWakeLock()) {
                    releaseWakeLock_l();
                    released = true;
                }


                const int64_t waitNs = computeWaitTimeNs_l();
                ALOGV("wait async completion (wait time: %lld)", (long long)waitNs);
                status_t status = mWaitWorkCV.waitRelative(mLock, waitNs); //然后Thread会在这里睡眠等待,直到AudioTrack:: start发送广播唤醒或超时
                if (status == TIMED_OUT) {
                    mSignalPending = true; // if timeout recheck everything
                }
                ALOGV("async completion/wake");
                if (released) {
                    acquireWakeLock_l();
                }
                mStandbyTimeNs = systemTime() + mStandbyDelayNs;
                mSleepTimeUs = 0;


                continue;
            }
            if ((mActiveTracks.isEmpty() && systemTime() > mStandbyTimeNs) ||
                                   isSuspended()) {
                // put audio hardware into standby after short delay
                if (shouldStandby_l()) {


                    threadLoop_standby();


                    // This is where we go into standby
                    if (!mStandby) {
                        LOG_AUDIO_STATE();
                        mThreadMetrics.logEndInterval();
                        mThreadSnapshot.onEnd();
                        mStandby = true;
                    }
                    sendStatistics(false /* force */);
                }


                if (mActiveTracks.isEmpty() && mConfigEvents.isEmpty()) {
                    // we're about to wait, flush the binder command buffer
                    IPCThreadState::self()->flushCommands();


                    clearOutputTracks();


                    if (exitPending()) {
                        break;
                    }


                    releaseWakeLock_l();
                    // wait until we have something to do...
                    ALOGV("%s going to sleep", myName.string());
                    mWaitWorkCV.wait(mLock); //然后Thread会在这里睡眠等待,直到AudioTrack:: start发送广播唤醒
                    ALOGV("%s waking up", myName.string());
                    acquireWakeLock_l();


                    mMixerStatus = MIXER_IDLE;
                    mMixerStatusIgnoringFastTracks = MIXER_IDLE;
                    mBytesWritten = 0;
                    mBytesRemaining = 0;
                    checkSilentMode_l();


                    mStandbyTimeNs = systemTime() + mStandbyDelayNs;
                    mSleepTimeUs = mIdleSleepTimeUs;
                    if (mType == MIXER || mType == SPATIALIZER) {
                        sleepTimeShift = 0;
                    }


                    continue;
                }
            }
            // mMixerStatusIgnoringFastTracks is also updated internally
            mMixerStatus = prepareTracks_l(&tracksToRemove); //track预处理


            mActiveTracks.updatePowerState(this);


            updateMetadata_l();


            // prevent any changes in effect chain list and in each effect chain
            // during mixing and effect process as the audio buffers could be deleted
            // or modified if an effect is created or deleted
            lockEffectChains_l(effectChains);


            // Determine which session to pick up haptic data.
            // This must be done under the same lock as prepareTracks_l().
            // The haptic data from the effect is at a higher priority than the one from track.
            // TODO: Write haptic data directly to sink buffer when mixing.
            if (mHapticChannelCount > 0) {
                for (const auto& track : mActiveTracks) {
                    sp<EffectChain> effectChain = getEffectChain_l(track->sessionId());
                    if (effectChain != nullptr
                            && effectChain->containsHapticGeneratingEffect_l()) {
                        activeHapticSessionId = track->sessionId();
                        isHapticSessionSpatialized =
                                mType == SPATIALIZER && track->isSpatialized();
                        break;
                    }
                    if (activeHapticSessionId == AUDIO_SESSION_NONE
                            && track->getHapticPlaybackEnabled()) {
                        activeHapticSessionId = track->sessionId();
                        isHapticSessionSpatialized =
                                mType == SPATIALIZER && track->isSpatialized();
                    }
                }
            }


            // Acquire a local copy of active tracks with lock (release w/o lock).
            //
            // Control methods on the track acquire the ThreadBase lock (e.g. start()
            // stop(), pause(), etc.), but the threadLoop is entitled to call audio
            // data / buffer methods on tracks from activeTracks without the ThreadBase lock.
            activeTracks.insert(activeTracks.end(), mActiveTracks.begin(), mActiveTracks.end());
        } // mLock scope ends


        if (mBytesRemaining == 0) {
            mCurrentWriteLength = 0;
            if (mMixerStatus == MIXER_TRACKS_READY) { //只有当音轨准备就绪,才能进入到混音处理
                // threadLoop_mix() sets mCurrentWriteLength
                threadLoop_mix(); //混音处理
            } else if ((mMixerStatus != MIXER_DRAIN_TRACK)
                        && (mMixerStatus != MIXER_DRAIN_ALL)) {
                // threadLoop_sleepTime sets mSleepTimeUs to 0 if data
                // must be written to HAL
                threadLoop_sleepTime(); //休眠一段时间
                if (mSleepTimeUs == 0) {
                    mCurrentWriteLength = mSinkBufferSize;


                    // Tally underrun frames as we are inserting 0s here.
                    for (const auto& track : activeTracks) {
                        if (track->mFillingUpStatus == Track::FS_ACTIVE
                                && !track->isStopped()
                                && !track->isPaused()
                                && !track->isTerminated()) {
                            ALOGV("%s: track(%d) %s underrun due to thread sleep of %zu frames",
                                    __func__, track->id(), track->getTrackStateAsString(),
                                    mNormalFrameCount);
                            track->mAudioTrackServerProxy->tallyUnderrunFrames(mNormalFrameCount);
                        }
                    }
                }
            }
            // Either threadLoop_mix() or threadLoop_sleepTime() should have set
            // mMixerBuffer with data if mMixerBufferValid is true and mSleepTimeUs == 0.
            // Merge mMixerBuffer data into mEffectBuffer (if any effects are valid)
            // or mSinkBuffer (if there are no effects).
            //
            // This is done pre-effects computation; if effects change to
            // support higher precision, this needs to move.
            //
            // mMixerBufferValid is only set true by MixerThread::prepareTracks_l().
            // TODO use mSleepTimeUs == 0 as an additional condition.
            uint32_t mixerChannelCount = mEffectBufferValid ?
                        audio_channel_count_from_out_mask(mMixerChannelMask) : mChannelCount;
            if (mMixerBufferValid) {
                void *buffer = mEffectBufferValid ? mEffectBuffer : mSinkBuffer;
                audio_format_t format = mEffectBufferValid ? mEffectBufferFormat : mFormat;


                // mono blend occurs for mixer threads only (not direct or offloaded)
                // and is handled here if we're going directly to the sink.
                if (requireMonoBlend() && !mEffectBufferValid) {
                    mono_blend(mMixerBuffer, mMixerBufferFormat, mChannelCount, mNormalFrameCount,
                               true /*limit*/);
                }


                if (!hasFastMixer()) {
                    // Balance must take effect after mono conversion.
                    // We do it here if there is no FastMixer.
                    // mBalance detects zero balance within the class for speed (not needed here).
                    mBalance.setBalance(mMasterBalance.load());
                    mBalance.process((float *)mMixerBuffer, mNormalFrameCount);
                }


                memcpy_by_audio_format(buffer, format, mMixerBuffer, mMixerBufferFormat,
                        mNormalFrameCount * (mixerChannelCount + mHapticChannelCount));


                // If we're going directly to the sink and there are haptic channels,
                // we should adjust channels as the sample data is partially interleaved
                // in this case.
                if (!mEffectBufferValid && mHapticChannelCount > 0) {
                    adjust_channels_non_destructive(buffer, mChannelCount, buffer,
                            mChannelCount + mHapticChannelCount,
                            audio_bytes_per_sample(format),
                            audio_bytes_per_frame(mChannelCount, format) * mNormalFrameCount);
                }
            }


            mBytesRemaining = mCurrentWriteLength;
            if (isSuspended()) {
                // Simulate write to HAL when suspended (e.g. BT SCO phone call).
                mSleepTimeUs = suspendSleepTimeUs(); // assumes full buffer.
                const size_t framesRemaining = mBytesRemaining / mFrameSize;
                mBytesWritten += mBytesRemaining;
                mFramesWritten += framesRemaining;
                mSuspendedFrames += framesRemaining; // to adjust kernel HAL position
                mBytesRemaining = 0;
            }


            // only process effects if we're going to write
            if (mSleepTimeUs == 0 && mType != OFFLOAD) {
                for (size_t i = 0; i < effectChains.size(); i ++) {
                    effectChains[i]->process_l();
                    // TODO: Write haptic data directly to sink buffer when mixing.
                    if (activeHapticSessionId != AUDIO_SESSION_NONE
                            && activeHapticSessionId == effectChains[i]->sessionId()) {
                        // Haptic data is active in this case, copy it directly from
                        // in buffer to out buffer.
                        uint32_t hapticSessionChannelCount = mEffectBufferValid ?
                                            audio_channel_count_from_out_mask(mMixerChannelMask) :
                                            mChannelCount;
                        if (mType == SPATIALIZER && !isHapticSessionSpatialized) {
                            hapticSessionChannelCount = mChannelCount;
                        }


                        const size_t audioBufferSize = mNormalFrameCount
                            * audio_bytes_per_frame(hapticSessionChannelCount,
                                                    EFFECT_BUFFER_FORMAT);
                        memcpy_by_audio_format(
                                (uint8_t*)effectChains[i]->outBuffer() + audioBufferSize,
                                EFFECT_BUFFER_FORMAT,
                                (const uint8_t*)effectChains[i]->inBuffer() + audioBufferSize,
                                EFFECT_BUFFER_FORMAT, mNormalFrameCount * mHapticChannelCount);
                    }
                }
            }
        }
        // Process effect chains for offloaded thread even if no audio
        // was read from audio track: process only updates effect state
        // and thus does have to be synchronized with audio writes but may have
        // to be called while waiting for async write callback
        if (mType == OFFLOAD) {
            for (size_t i = 0; i < effectChains.size(); i ++) {
                effectChains[i]->process_l();
            }
        }


        // Only if the Effects buffer is enabled and there is data in the
        // Effects buffer (buffer valid), we need to
        // copy into the sink buffer.
        // TODO use mSleepTimeUs == 0 as an additional condition.
        if (mEffectBufferValid) {
            //ALOGV("writing effect buffer to sink buffer format %#x", mFormat);
            void *effectBuffer = (mType == SPATIALIZER) ? mPostSpatializerBuffer : mEffectBuffer;
            if (requireMonoBlend()) {
                mono_blend(effectBuffer, mEffectBufferFormat, mChannelCount, mNormalFrameCount,
                           true /*limit*/);
            }


            if (!hasFastMixer()) {
                // Balance must take effect after mono conversion.
                // We do it here if there is no FastMixer.
                // mBalance detects zero balance within the class for speed (not needed here).
                mBalance.setBalance(mMasterBalance.load());
                mBalance.process((float *)effectBuffer, mNormalFrameCount);
            }


            // for SPATIALIZER thread, Move haptics channels from mEffectBuffer to
            // mPostSpatializerBuffer if the haptics track is spatialized.
            // Otherwise, the haptics channels are already in mPostSpatializerBuffer.
            // For other thread types, the haptics channels are already in mEffectBuffer.
            if (mType == SPATIALIZER && isHapticSessionSpatialized) {
                const size_t srcBufferSize = mNormalFrameCount *
                        audio_bytes_per_frame(audio_channel_count_from_out_mask(mMixerChannelMask),
                                              mEffectBufferFormat);
                const size_t dstBufferSize = mNormalFrameCount
                        * audio_bytes_per_frame(mChannelCount, mEffectBufferFormat);


                memcpy_by_audio_format((uint8_t*)mPostSpatializerBuffer + dstBufferSize,
                                       mEffectBufferFormat,
                                       (uint8_t*)mEffectBuffer + srcBufferSize,
                                       mEffectBufferFormat,
                                       mNormalFrameCount * mHapticChannelCount);
            }


            memcpy_by_audio_format(mSinkBuffer, mFormat, effectBuffer, mEffectBufferFormat,
                    mNormalFrameCount * (mChannelCount + mHapticChannelCount));


            // The sample data is partially interleaved when haptic channels exist,
            // we need to adjust channels here.
            if (mHapticChannelCount > 0) {
                adjust_channels_non_destructive(mSinkBuffer, mChannelCount, mSinkBuffer,
                        mChannelCount + mHapticChannelCount,
                        audio_bytes_per_sample(mFormat),
                        audio_bytes_per_frame(mChannelCount, mFormat) * mNormalFrameCount);
            }
        }


        // enable changes in effect chain
        unlockEffectChains(effectChains);


        if (!waitingAsyncCallback()) {
            // mSleepTimeUs == 0 means we must write to audio hardware
            if (mSleepTimeUs == 0) {
                ssize_t ret = 0;
                // writePeriodNs is updated >= 0 when ret > 0.
                int64_t writePeriodNs = -1;
                if (mBytesRemaining) {
                    // FIXME rewrite to reduce number of system calls
                    const int64_t lastIoBeginNs = systemTime();
                    ret = threadLoop_write(); //音频输出(向硬件抽象层写数据,写入HAL)
                    const int64_t lastIoEndNs = systemTime();
                    if (ret < 0) {
                        mBytesRemaining = 0;
                    } else if (ret > 0) {
                        mBytesWritten += ret;
                        mBytesRemaining -= ret;
                        const int64_t frames = ret / mFrameSize;
                        mFramesWritten += frames;


                        writePeriodNs = lastIoEndNs - mLastIoEndNs;
                        // process information relating to write time.
                        if (audio_has_proportional_frames(mFormat)) {
                            // we are in a continuous mixing cycle
                            if (mMixerStatus == MIXER_TRACKS_READY &&
                                    loopCount == lastLoopCountWritten + 1) {


                                const double jitterMs =
                                        TimestampVerifier<int64_t, int64_t>::computeJitterMs(
                                                {frames, writePeriodNs},
                                                {0, 0} /* lastTimestamp */, mSampleRate);
                                const double processMs =
                                       (lastIoBeginNs - mLastIoEndNs) * 1e-6;


                                Mutex::Autolock _l(mLock);
                                mIoJitterMs.add(jitterMs);
                                mProcessTimeMs.add(processMs);


                                if (mPipeSink.get() != nullptr) {
                                    // Using the Monopipe availableToWrite, we estimate the current
                                    // buffer size.
                                    MonoPipe* monoPipe = static_cast<MonoPipe*>(mPipeSink.get());
                                    const ssize_t
                                            availableToWrite = mPipeSink->availableToWrite();
                                    const size_t pipeFrames = monoPipe->maxFrames();
                                    const size_t
                                            remainingFrames = pipeFrames - max(availableToWrite, 0);
                                    mMonopipePipeDepthStats.add(remainingFrames);
                                }
                            }


                            // write blocked detection
                            const int64_t deltaWriteNs = lastIoEndNs - lastIoBeginNs;
                            if ((mType == MIXER || mType == SPATIALIZER)
                                    && deltaWriteNs > maxPeriod) {
                                mNumDelayedWrites++;
                                if ((lastIoEndNs - lastWarning) > kWarningThrottleNs) {
                                    ATRACE_NAME("underrun");
                                    ALOGW("write blocked for %lld msecs, "
                                            "%d delayed writes, thread %d",
                                            (long long)deltaWriteNs / NANOS_PER_MILLISECOND,
                                            mNumDelayedWrites, mId);
                                    lastWarning = lastIoEndNs;
                                }
                            }
                        }
                        // update timing info.
                        mLastIoBeginNs = lastIoBeginNs;
                        mLastIoEndNs = lastIoEndNs;
                        lastLoopCountWritten = loopCount;
                    }
                } else if ((mMixerStatus == MIXER_DRAIN_TRACK) ||
                        (mMixerStatus == MIXER_DRAIN_ALL)) {
                    threadLoop_drain();
                }
                if ((mType == MIXER || mType == SPATIALIZER) && !mStandby) {


                    if (mThreadThrottle
                            && mMixerStatus == MIXER_TRACKS_READY // we are mixing (active tracks)
                            && writePeriodNs > 0) {               // we have write period info
                        // Limit MixerThread data processing to no more than twice the
                        // expected processing rate.
                        //
                        // This helps prevent underruns with NuPlayer and other applications
                        // which may set up buffers that are close to the minimum size, or use
                        // deep buffers, and rely on a double-buffering sleep strategy to fill.
                        //
                        // The throttle smooths out sudden large data drains from the device,
                        // e.g. when it comes out of standby, which often causes problems with
                        // (1) mixer threads without a fast mixer (which has its own warm-up)
                        // (2) minimum buffer sized tracks (even if the track is full,
                        //     the app won't fill fast enough to handle the sudden draw).
                        //
                        // Total time spent in last processing cycle equals time spent in
                        // 1. threadLoop_write, as well as time spent in
                        // 2. threadLoop_mix (significant for heavy mixing, especially
                        //                    on low tier processors)


                        // it's OK if deltaMs is an overestimate.


                        const int32_t deltaMs = writePeriodNs / NANOS_PER_MILLISECOND;


                        const int32_t throttleMs = (int32_t)mHalfBufferMs - deltaMs;
                        if ((signed)mHalfBufferMs >= throttleMs && throttleMs > 0) {
                            mThreadMetrics.logThrottleMs((double)throttleMs);


                            usleep(throttleMs * 1000);
                            // notify of throttle start on verbose log
                            ALOGV_IF(mThreadThrottleEndMs == mThreadThrottleTimeMs,
                                    "mixer(%p) throttle begin:"
                                    " ret(%zd) deltaMs(%d) requires sleep %d ms",
                                    this, ret, deltaMs, throttleMs);
                            mThreadThrottleTimeMs += throttleMs;
                            // Throttle must be attributed to the previous mixer loop's write time
                            // to allow back-to-back throttling.
                            // This also ensures proper timing statistics.
                            mLastIoEndNs = systemTime();  // we fetch the write end time again.
                        } else {
                            uint32_t diff = mThreadThrottleTimeMs - mThreadThrottleEndMs;
                            if (diff > 0) {
                                // notify of throttle end on debug log
                                // but prevent spamming for bluetooth
                                ALOGD_IF(!isSingleDeviceType(
                                                 outDeviceTypes(), audio_is_a2dp_out_device) &&
                                         !isSingleDeviceType(
                                                 outDeviceTypes(), audio_is_hearing_aid_out_device),
                                        "mixer(%p) throttle end: throttle time(%u)", this, diff);
                                mThreadThrottleEndMs = mThreadThrottleTimeMs;
                            }
                        }
                    }
                }


            } else {
                ATRACE_BEGIN("sleep");
                Mutex::Autolock _l(mLock);
                // suspended requires accurate metering of sleep time.
                if (isSuspended()) {
                    // advance by expected sleepTime
                    timeLoopNextNs += microseconds((nsecs_t)mSleepTimeUs);
                    const nsecs_t nowNs = systemTime();


                    // compute expected next time vs current time.
                    // (negative deltas are treated as delays).
                    nsecs_t deltaNs = timeLoopNextNs - nowNs;
                    if (deltaNs < -kMaxNextBufferDelayNs) {
                        // Delays longer than the max allowed trigger a reset.
                        ALOGV("DelayNs: %lld, resetting timeLoopNextNs", (long long) deltaNs);
                        deltaNs = microseconds((nsecs_t)mSleepTimeUs);
                        timeLoopNextNs = nowNs + deltaNs;
                    } else if (deltaNs < 0) {
                        // Delays within the max delay allowed: zero the delta/sleepTime
                        // to help the system catch up in the next iteration(s)
                        ALOGV("DelayNs: %lld, catching-up", (long long) deltaNs);
                        deltaNs = 0;
                    }
                    // update sleep time (which is >= 0)
                    mSleepTimeUs = deltaNs / 1000;
                }
                if (!mSignalPending && mConfigEvents.isEmpty() && !exitPending()) {
                    mWaitWorkCV.waitRelative(mLock, microseconds((nsecs_t)mSleepTimeUs)); //然后Thread会在这里睡眠等待,直到AudioTrack:: start发送广播唤醒或超时
                }
                ATRACE_END();
            }
        }


        // Finally let go of removed track(s), without the lock held
        // since we can't guarantee the destructors won't acquire that
        // same lock.  This will also mutate and push a new fast mixer state.
        threadLoop_removeTracks(tracksToRemove); //移除相关track
        tracksToRemove.clear();


        // FIXME I don't understand the need for this here;
        //       it was in the original code but maybe the
        //       assignment in saveOutputTracks() makes this unnecessary?
        clearOutputTracks();


        // Effect chains will be actually deleted here if they were removed from
        // mEffectChains list during mixing or effects processing
        effectChains.clear();


        // FIXME Note that the above .clear() is no longer necessary since effectChains
        // is now local to this block, but will keep it for now (at least until merge done).
    }


    threadLoop_exit();


    if (!mStandby) {
        threadLoop_standby();
        mStandby = true;
    }


    releaseWakeLock();


    ALOGV("Thread %p type %d exiting", this, mType);
    return false;
}

以上函数主要进行3步处理:

1、调用子类MixerThread的prepareTracks_l函数进行track预处理。

2、调用子类MixerThread的threadLoop_mix进行混音处理。

3、调用threadLoop_write函数,向硬件抽象层写数据,写入HAL。

AudioFlinger MixerThread prepareTracks_l

我们先看MixerThread的prepareTracks_l:

//frameworks/av/services/audioflinger/Threads.cpp
//重新准备音频流和混音器:ACTIVE 状态的 Track 会添加到 mActiveTracks,此外的Track 会从 mActiveTracks 上移除出来,然后重新准备 AudioMixer
AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTracks_l(
        Vector< sp<Track> > *tracksToRemove)
{
    // clean up deleted track ids in AudioMixer before allocating new tracks
    (void)mTracks.processDeletedTrackIds([this](int trackId) {
        // for each trackId, destroy it in the AudioMixer
        if (mAudioMixer->exists(trackId)) {
            mAudioMixer->destroy(trackId);
        }
    });
    mTracks.clearDeletedTrackIds();


    mixer_state mixerStatus = MIXER_IDLE;
    // find out which tracks need to be processed
    size_t count = mActiveTracks.size();
    size_t mixedTracks = 0;
    size_t tracksWithEffect = 0;
    // counts only _active_ fast tracks
    size_t fastTracks = 0;
    uint32_t resetMask = 0; // bit mask of fast tracks that need to be reset


    float masterVolume = mMasterVolume;
    bool masterMute = mMasterMute;


    if (masterMute) {
        masterVolume = 0;
    }
    // Delegate master volume control to effect in output mix effect chain if needed
    sp<EffectChain> chain = getEffectChain_l(AUDIO_SESSION_OUTPUT_MIX);
    if (chain != 0) {
        uint32_t v = (uint32_t)(masterVolume * (1 << 24));
        chain->setVolume_l(&v, &v);
        masterVolume = (float)((v + (1 << 23)) >> 24);
        chain.clear();
    }


    // prepare a new state to push
    FastMixerStateQueue *sq = NULL;
    FastMixerState *state = NULL;
    bool didModify = false;
    FastMixerStateQueue::block_t block = FastMixerStateQueue::BLOCK_UNTIL_PUSHED;
    bool coldIdle = false;
    if (mFastMixer != 0) {
        sq = mFastMixer->sq();
        state = sq->begin();
        coldIdle = state->mCommand == FastMixerState::COLD_IDLE;
    }


    mMixerBufferValid = false;  // mMixerBuffer has no valid data until appropriate tracks found.
    mEffectBufferValid = false; // mEffectBuffer has no valid data until tracks found.


    // DeferredOperations handles statistics after setting mixerStatus.
    class DeferredOperations {
    public:
        DeferredOperations(mixer_state *mixerStatus, ThreadMetrics *threadMetrics)
            : mMixerStatus(mixerStatus)
            , mThreadMetrics(threadMetrics) {}


        // when leaving scope, tally frames properly.
        ~DeferredOperations() {
            // Tally underrun frames only if we are actually mixing (MIXER_TRACKS_READY)
            // because that is when the underrun occurs.
            // We do not distinguish between FastTracks and NormalTracks here.
            size_t maxUnderrunFrames = 0;
            if (*mMixerStatus == MIXER_TRACKS_READY && mUnderrunFrames.size() > 0) {
                for (const auto &underrun : mUnderrunFrames) {
                    underrun.first->tallyUnderrunFrames(underrun.second);
                    maxUnderrunFrames = max(underrun.second, maxUnderrunFrames);
                }
            }
            // send the max underrun frames for this mixer period
            mThreadMetrics->logUnderrunFrames(maxUnderrunFrames);
        }


        // tallyUnderrunFrames() is called to update the track counters
        // with the number of underrun frames for a particular mixer period.
        // We defer tallying until we know the final mixer status.
        void tallyUnderrunFrames(sp<Track> track, size_t underrunFrames) {
            mUnderrunFrames.emplace_back(track, underrunFrames);
        }


    private:
        const mixer_state * const mMixerStatus;
        ThreadMetrics * const mThreadMetrics;
        std::vector<std::pair<sp<Track>, size_t>> mUnderrunFrames;
    } deferredOperations(&mixerStatus, &mThreadMetrics);
    // implicit nested scope for variable capture


    bool noFastHapticTrack = true;
    for (size_t i=0 ; i<count ; i++) {
        const sp<Track> t = mActiveTracks[i];


        // this const just means the local variable doesn't change
        Track* const track = t.get();


        // process fast tracks
        if (track->isFastTrack()) {
            LOG_ALWAYS_FATAL_IF(mFastMixer.get() == nullptr,
                    "%s(%d): FastTrack(%d) present without FastMixer",
                     __func__, id(), track->id());


            if (track->getHapticPlaybackEnabled()) {
                noFastHapticTrack = false;
            }


            // It's theoretically possible (though unlikely) for a fast track to be created
            // and then removed within the same normal mix cycle.  This is not a problem, as
            // the track never becomes active so it's fast mixer slot is never touched.
            // The converse, of removing an (active) track and then creating a new track
            // at the identical fast mixer slot within the same normal mix cycle,
            // is impossible because the slot isn't marked available until the end of each cycle.
            int j = track->mFastIndex;
            ALOG_ASSERT(0 < j && j < (int)FastMixerState::sMaxFastTracks);
            ALOG_ASSERT(!(mFastTrackAvailMask & (1 << j)));
            FastTrack *fastTrack = &state->mFastTracks[j];


            // Determine whether the track is currently in underrun condition,
            // and whether it had a recent underrun.
            FastTrackDump *ftDump = &mFastMixerDumpState.mTracks[j];
            FastTrackUnderruns underruns = ftDump->mUnderruns;
            uint32_t recentFull = (underruns.mBitFields.mFull -
                    track->mObservedUnderruns.mBitFields.mFull) & UNDERRUN_MASK;
            uint32_t recentPartial = (underruns.mBitFields.mPartial -
                    track->mObservedUnderruns.mBitFields.mPartial) & UNDERRUN_MASK;
            uint32_t recentEmpty = (underruns.mBitFields.mEmpty -
                    track->mObservedUnderruns.mBitFields.mEmpty) & UNDERRUN_MASK;
            uint32_t recentUnderruns = recentPartial + recentEmpty;
            track->mObservedUnderruns = underruns;
            // don't count underruns that occur while stopping or pausing
            // or stopped which can occur when flush() is called while active
            size_t underrunFrames = 0;
            if (!(track->isStopping() || track->isPausing() || track->isStopped()) &&
                    recentUnderruns > 0) {
                // FIXME fast mixer will pull & mix partial buffers, but we count as a full underrun
                underrunFrames = recentUnderruns * mFrameCount;
            }
            // Immediately account for FastTrack underruns.
            track->mAudioTrackServerProxy->tallyUnderrunFrames(underrunFrames);


            // This is similar to the state machine for normal tracks,
            // with a few modifications for fast tracks.
            bool isActive = true;
            switch (track->mState) {
            case TrackBase::STOPPING_1:
                // track stays active in STOPPING_1 state until first underrun
                if (recentUnderruns > 0 || track->isTerminated()) {
                    track->mState = TrackBase::STOPPING_2;
                }
                break;
            case TrackBase::PAUSING:
                // ramp down is not yet implemented
                track->setPaused();
                break;
            case TrackBase::RESUMING:
                // ramp up is not yet implemented
                track->mState = TrackBase::ACTIVE;
                break;
            case TrackBase::ACTIVE:
                if (recentFull > 0 || recentPartial > 0) {
                    // track has provided at least some frames recently: reset retry count
                    track->mRetryCount = kMaxTrackRetries;
                }
                if (recentUnderruns == 0) {
                    // no recent underruns: stay active
                    break;
                }
                // there has recently been an underrun of some kind
                if (track->sharedBuffer() == 0) {
                    // were any of the recent underruns "empty" (no frames available)?
                    if (recentEmpty == 0) {
                        // no, then ignore the partial underruns as they are allowed indefinitely
                        break;
                    }
                    // there has recently been an "empty" underrun: decrement the retry counter
                    if (--(track->mRetryCount) > 0) {
                        break;
                    }
                    // indicate to client process that the track was disabled because of underrun;
                    // it will then automatically call start() when data is available
                    track->disable();
                    // remove from active list, but state remains ACTIVE [confusing but true]
                    isActive = false;
                    break;
                }
                FALLTHROUGH_INTENDED;
            case TrackBase::STOPPING_2:
            case TrackBase::PAUSED:
            case TrackBase::STOPPED:
            case TrackBase::FLUSHED:   // flush() while active
                // Check for presentation complete if track is inactive
                // We have consumed all the buffers of this track.
                // This would be incomplete if we auto-paused on underrun
                {
                    uint32_t latency = 0;
                    status_t result = mOutput->stream->getLatency(&latency);
                    ALOGE_IF(result != OK,
                            "Error when retrieving output stream latency: %d", result);
                    size_t audioHALFrames = (latency * mSampleRate) / 1000;
                    int64_t framesWritten = mBytesWritten / mFrameSize;
                    if (!(mStandby || track->presentationComplete(framesWritten, audioHALFrames))) {
                        // track stays in active list until presentation is complete
                        break;
                    }
                }
                if (track->isStopping_2()) {
                    track->mState = TrackBase::STOPPED;
                }
                if (track->isStopped()) {
                    // Can't reset directly, as fast mixer is still polling this track
                    //   track->reset();
                    // So instead mark this track as needing to be reset after push with ack
                    resetMask |= 1 << i;
                }
                isActive = false;
                break;
            case TrackBase::IDLE:
            default:
                LOG_ALWAYS_FATAL("unexpected track state %d", (int)track->mState);
            }


            if (isActive) {
                // was it previously inactive?
                if (!(state->mTrackMask & (1 << j))) {
                    ExtendedAudioBufferProvider *eabp = track;
                    VolumeProvider *vp = track;
                    fastTrack->mBufferProvider = eabp;
                    fastTrack->mVolumeProvider = vp;
                    fastTrack->mChannelMask = track->mChannelMask;
                    fastTrack->mFormat = track->mFormat;
                    fastTrack->mHapticPlaybackEnabled = track->getHapticPlaybackEnabled();
                    fastTrack->mHapticIntensity = track->getHapticIntensity();
                    fastTrack->mHapticMaxAmplitude = track->getHapticMaxAmplitude();
                    fastTrack->mGeneration++;
                    state->mTrackMask |= 1 << j;
                    didModify = true;
                    // no acknowledgement required for newly active tracks
                }
                sp<AudioTrackServerProxy> proxy = track->mAudioTrackServerProxy;
                float volume;
                if (track->isPlaybackRestricted() || mStreamTypes[track->streamType()].mute) {
                    volume = 0.f;
                } else {
                    volume = masterVolume * mStreamTypes[track->streamType()].volume;
                }


                handleVoipVolume_l(&volume);


                // cache the combined master volume and stream type volume for fast mixer; this
                // lacks any synchronization or barrier so VolumeProvider may read a stale value
                const float vh = track->getVolumeHandler()->getVolume(
                    proxy->framesReleased()).first;
                volume *= vh;
                track->mCachedVolume = volume;
                gain_minifloat_packed_t vlr = proxy->getVolumeLR();
                float vlf = volume * float_from_gain(gain_minifloat_unpack_left(vlr));
                float vrf = volume * float_from_gain(gain_minifloat_unpack_right(vlr));


                track->setFinalVolume((vlf + vrf) / 2.f);
                ++fastTracks;
            } else {
                // was it previously active?
                if (state->mTrackMask & (1 << j)) {
                    fastTrack->mBufferProvider = NULL;
                    fastTrack->mGeneration++;
                    state->mTrackMask &= ~(1 << j);
                    didModify = true;
                    // If any fast tracks were removed, we must wait for acknowledgement
                    // because we're about to decrement the last sp<> on those tracks.
                    block = FastMixerStateQueue::BLOCK_UNTIL_ACKED;
                } else {
                    // ALOGW rather than LOG_ALWAYS_FATAL because it seems there are cases where an
                    // AudioTrack may start (which may not be with a start() but with a write()
                    // after underrun) and immediately paused or released.  In that case the
                    // FastTrack state hasn't had time to update.
                    // TODO Remove the ALOGW when this theory is confirmed.
                    ALOGW("fast track %d should have been active; "
                            "mState=%d, mTrackMask=%#x, recentUnderruns=%u, isShared=%d",
                            j, (int)track->mState, state->mTrackMask, recentUnderruns,
                            track->sharedBuffer() != 0);
                    // Since the FastMixer state already has the track inactive, do nothing here.
                }
                tracksToRemove->add(track);
                // Avoids a misleading display in dumpsys
                track->mObservedUnderruns.mBitFields.mMostRecent = UNDERRUN_FULL;
            }
            if (fastTrack->mHapticPlaybackEnabled != track->getHapticPlaybackEnabled()) {
                fastTrack->mHapticPlaybackEnabled = track->getHapticPlaybackEnabled();
                didModify = true;
            }
            continue;
        }


        {   // local variable scope to avoid goto warning


        audio_track_cblk_t* cblk = track->cblk();


        // The first time a track is added we wait
        // for all its buffers to be filled before processing it
        const int trackId = track->id();


        // if an active track doesn't exist in the AudioMixer, create it.
        // use the trackId as the AudioMixer name.
        if (!mAudioMixer->exists(trackId)) {
            status_t status = mAudioMixer->create(
                    trackId,
                    track->mChannelMask,
                    track->mFormat,
                    track->mSessionId);
            if (status != OK) {
                ALOGW("%s(): AudioMixer cannot create track(%d)"
                        " mask %#x, format %#x, sessionId %d",
                        __func__, trackId,
                        track->mChannelMask, track->mFormat, track->mSessionId);
                tracksToRemove->add(track);
                track->invalidate(); // consider it dead.
                continue;
            }
        }


        // make sure that we have enough frames to mix one full buffer.
        // enforce this condition only once to enable draining the buffer in case the client
        // app does not call stop() and relies on underrun to stop:
        // hence the test on (mMixerStatus == MIXER_TRACKS_READY) meaning the track was mixed
        // during last round
        size_t desiredFrames;
        const uint32_t sampleRate = track->mAudioTrackServerProxy->getSampleRate();
        AudioPlaybackRate playbackRate = track->mAudioTrackServerProxy->getPlaybackRate();


        desiredFrames = sourceFramesNeededWithTimestretch(
                sampleRate, mNormalFrameCount, mSampleRate, playbackRate.mSpeed);
        // TODO: ONLY USED FOR LEGACY RESAMPLERS, remove when they are removed.
        // add frames already consumed but not yet released by the resampler
        // because mAudioTrackServerProxy->framesReady() will include these frames
        desiredFrames += mAudioMixer->getUnreleasedFrames(trackId);


        uint32_t minFrames = 1;
        if ((track->sharedBuffer() == 0) && !track->isStopped() && !track->isPausing() &&
                (mMixerStatusIgnoringFastTracks == MIXER_TRACKS_READY)) {
            minFrames = desiredFrames;
        }


        size_t framesReady = track->framesReady(); //数据准备完毕,设置音量、设置一些参数(混音的状态下,frameReady = 1,那么会进入下面的条件,进行AudioMixer参数设置)
        if (ATRACE_ENABLED()) {
            // I wish we had formatted trace names
            std::string traceName("nRdy");
            traceName += std::to_string(trackId);
            ATRACE_INT(traceName.c_str(), framesReady);
        }
        if ((framesReady >= minFrames) && track->isReady() &&
                !track->isPaused() && !track->isTerminated())
        {
            ALOGVV("track(%d) s=%08x [OK] on thread %p", trackId, cblk->mServer, this);


            mixedTracks++;


            // track->mainBuffer() != mSinkBuffer or mMixerBuffer means
            // there is an effect chain connected to the track
            chain.clear();
            if (track->mainBuffer() != mSinkBuffer &&
                    track->mainBuffer() != mMixerBuffer) {
                if (mEffectBufferEnabled) {
                    mEffectBufferValid = true; // Later can set directly.
                }
                chain = getEffectChain_l(track->sessionId());
                // Delegate volume control to effect in track effect chain if needed
                if (chain != 0) {
                    tracksWithEffect++;
                } else {
                    ALOGW("prepareTracks_l(): track(%d) attached to effect but no chain found on "
                            "session %d",
                            trackId, track->sessionId());
                }
            }


           //音量参数设置:设置AudioMixer参数、音量、音轨、音频格式、重采样、混音(设置混音所需要的参数,包括:音量,混音的源buffer,目的buffer,音频格式,是否重采样等)
            int param = AudioMixer::VOLUME;
            if (track->mFillingUpStatus == Track::FS_FILLED) {
                // no ramp for the first volume setting
                track->mFillingUpStatus = Track::FS_ACTIVE;
                if (track->mState == TrackBase::RESUMING) {
                    track->mState = TrackBase::ACTIVE;
                    // If a new track is paused immediately after start, do not ramp on resume.
                    if (cblk->mServer != 0) {
                        param = AudioMixer::RAMP_VOLUME;
                    }
                }
                mAudioMixer->setParameter(trackId, AudioMixer::RESAMPLE, AudioMixer::RESET, NULL);
                mLeftVolFloat = -1.0;
            // FIXME should not make a decision based on mServer
            } else if (cblk->mServer != 0) {
                // If the track is stopped before the first frame was mixed,
                // do not apply ramp
                param = AudioMixer::RAMP_VOLUME;
            }


            // compute volume for this track
            uint32_t vl, vr;       // in U8.24 integer format
            float vlf, vrf, vaf;   // in [0.0, 1.0] float format
            // read original volumes with volume control
            float v = masterVolume * mStreamTypes[track->streamType()].volume;
            // Always fetch volumeshaper volume to ensure state is updated.
            const sp<AudioTrackServerProxy> proxy = track->mAudioTrackServerProxy;
            const float vh = track->getVolumeHandler()->getVolume(
                    track->mAudioTrackServerProxy->framesReleased()).first;


            if (mStreamTypes[track->streamType()].mute || track->isPlaybackRestricted()) {
                v = 0;
            }


            handleVoipVolume_l(&v);


            if (track->isPausing()) {
                vl = vr = 0;
                vlf = vrf = vaf = 0.;
                track->setPaused();
            } else {
                gain_minifloat_packed_t vlr = proxy->getVolumeLR();
                vlf = float_from_gain(gain_minifloat_unpack_left(vlr));
                vrf = float_from_gain(gain_minifloat_unpack_right(vlr));
                // track volumes come from shared memory, so can't be trusted and must be clamped
                if (vlf > GAIN_FLOAT_UNITY) {
                    ALOGV("Track left volume out of range: %.3g", vlf);
                    vlf = GAIN_FLOAT_UNITY;
                }
                if (vrf > GAIN_FLOAT_UNITY) {
                    ALOGV("Track right volume out of range: %.3g", vrf);
                    vrf = GAIN_FLOAT_UNITY;
                }
                // now apply the master volume and stream type volume and shaper volume
                vlf *= v * vh;
                vrf *= v * vh;
                // assuming master volume and stream type volume each go up to 1.0,
                // then derive vl and vr as U8.24 versions for the effect chain
                const float scaleto8_24 = MAX_GAIN_INT * MAX_GAIN_INT;
                vl = (uint32_t) (scaleto8_24 * vlf);
                vr = (uint32_t) (scaleto8_24 * vrf);
                // vl and vr are now in U8.24 format
                uint16_t sendLevel = proxy->getSendLevel_U4_12();
                // send level comes from shared memory and so may be corrupt
                if (sendLevel > MAX_GAIN_INT) {
                    ALOGV("Track send level out of range: %04X", sendLevel);
                    sendLevel = MAX_GAIN_INT;
                }
                // vaf is represented as [0.0, 1.0] float by rescaling sendLevel
                vaf = v * sendLevel * (1. / MAX_GAIN_INT);
            }


            track->setFinalVolume((vrf + vlf) / 2.f);


            // Delegate volume control to effect in track effect chain if needed
            if (chain != 0 && chain->setVolume_l(&vl, &vr)) {
                // Do not ramp volume if volume is controlled by effect
                param = AudioMixer::VOLUME;
                // Update remaining floating point volume levels
                vlf = (float)vl / (1 << 24);
                vrf = (float)vr / (1 << 24);
                track->mHasVolumeController = true;
            } else {
                // force no volume ramp when volume controller was just disabled or removed
                // from effect chain to avoid volume spike
                if (track->mHasVolumeController) {
                    param = AudioMixer::VOLUME;
                }
                track->mHasVolumeController = false;
            }


            // XXX: these things DON'T need to be done each time
            mAudioMixer->setBufferProvider(trackId, track);
            mAudioMixer->enable(trackId);


            mAudioMixer->setParameter(trackId, param, AudioMixer::VOLUME0, &vlf);
            mAudioMixer->setParameter(trackId, param, AudioMixer::VOLUME1, &vrf);
            mAudioMixer->setParameter(trackId, param, AudioMixer::AUXLEVEL, &vaf);
            mAudioMixer->setParameter(
                trackId,
                AudioMixer::TRACK,
                AudioMixer::FORMAT, (void *)track->format());
            mAudioMixer->setParameter(
                trackId,
                AudioMixer::TRACK,
                AudioMixer::CHANNEL_MASK, (void *)(uintptr_t)track->channelMask());


            if (mType == SPATIALIZER && !track->isSpatialized()) {
                mAudioMixer->setParameter(
                    trackId,
                    AudioMixer::TRACK,
                    AudioMixer::MIXER_CHANNEL_MASK,
                    (void *)(uintptr_t)(mChannelMask | mHapticChannelMask));
            } else {
                mAudioMixer->setParameter(
                    trackId,
                    AudioMixer::TRACK,
                    AudioMixer::MIXER_CHANNEL_MASK,
                    (void *)(uintptr_t)(mMixerChannelMask | mHapticChannelMask));
            }


            // limit track sample rate to 2 x output sample rate, which changes at re-configuration
            uint32_t maxSampleRate = mSampleRate * AUDIO_RESAMPLER_DOWN_RATIO_MAX;
            uint32_t reqSampleRate = proxy->getSampleRate();
            if (reqSampleRate == 0) {
                reqSampleRate = mSampleRate;
            } else if (reqSampleRate > maxSampleRate) {
                reqSampleRate = maxSampleRate;
            }
            mAudioMixer->setParameter(
                trackId,
                AudioMixer::RESAMPLE,
                AudioMixer::SAMPLE_RATE,
                (void *)(uintptr_t)reqSampleRate);


            AudioPlaybackRate playbackRate = proxy->getPlaybackRate();
            mAudioMixer->setParameter(
                trackId,
                AudioMixer::TIMESTRETCH,
                AudioMixer::PLAYBACK_RATE,
                &playbackRate);


            /*
             * Select the appropriate output buffer for the track.
             *
             * Tracks with effects go into their own effects chain buffer
             * and from there into either mEffectBuffer or mSinkBuffer.
             *
             * Other tracks can use mMixerBuffer for higher precision
             * channel accumulation.  If this buffer is enabled
             * (mMixerBufferEnabled true), then selected tracks will accumulate
             * into it.
             *
             */
            if (mMixerBufferEnabled
                    && (track->mainBuffer() == mSinkBuffer
                            || track->mainBuffer() == mMixerBuffer)) {
                if (mType == SPATIALIZER && !track->isSpatialized()) {
                    mAudioMixer->setParameter(
                            trackId,
                            AudioMixer::TRACK,
                            AudioMixer::MIXER_FORMAT, (void *)mEffectBufferFormat);
                    mAudioMixer->setParameter(
                            trackId,
                            AudioMixer::TRACK,
                            AudioMixer::MAIN_BUFFER, (void *)mPostSpatializerBuffer);
                } else {
                    mAudioMixer->setParameter(
                            trackId,
                            AudioMixer::TRACK,
                            AudioMixer::MIXER_FORMAT, (void *)mMixerBufferFormat);
                    mAudioMixer->setParameter(
                            trackId,
                            AudioMixer::TRACK,
                            AudioMixer::MAIN_BUFFER, (void *)mMixerBuffer);
                    // TODO: override track->mainBuffer()?
                    mMixerBufferValid = true;
                }
            } else {
                mAudioMixer->setParameter(
                        trackId,
                        AudioMixer::TRACK,
                        AudioMixer::MIXER_FORMAT, (void *)EFFECT_BUFFER_FORMAT);
                mAudioMixer->setParameter(
                        trackId,
                        AudioMixer::TRACK,
                        AudioMixer::MAIN_BUFFER, (void *)track->mainBuffer());
            }
            mAudioMixer->setParameter(
                trackId,
                AudioMixer::TRACK,
                AudioMixer::AUX_BUFFER, (void *)track->auxBuffer());
            mAudioMixer->setParameter(
                trackId,
                AudioMixer::TRACK,
                AudioMixer::HAPTIC_ENABLED, (void *)(uintptr_t)track->getHapticPlaybackEnabled());
            mAudioMixer->setParameter(
                trackId,
                AudioMixer::TRACK,
                AudioMixer::HAPTIC_INTENSITY, (void *)(uintptr_t)track->getHapticIntensity());
            mAudioMixer->setParameter(
                trackId,
                AudioMixer::TRACK,
                AudioMixer::HAPTIC_MAX_AMPLITUDE, (void *)(&(track->mHapticMaxAmplitude)));


            // reset retry count
            track->mRetryCount = kMaxTrackRetries;


            // If one track is ready, set the mixer ready if:
            //  - the mixer was not ready during previous round OR
            //  - no other track is not ready
            if (mMixerStatusIgnoringFastTracks != MIXER_TRACKS_READY ||
                    mixerStatus != MIXER_TRACKS_ENABLED) {
                mixerStatus = MIXER_TRACKS_READY;
            }


            // Enable the next few lines to instrument a test for underrun log handling.
            // TODO: Remove when we have a better way of testing the underrun log.
#if 0
            static int i;
            if ((++i & 0xf) == 0) {
                deferredOperations.tallyUnderrunFrames(track, 10 /* underrunFrames */);
            }
#endif
        } else {
            size_t underrunFrames = 0;
            if (framesReady < desiredFrames && !track->isStopped() && !track->isPaused()) {
                ALOGV("track(%d) underrun, track state %s  framesReady(%zu) < framesDesired(%zd)",
                        trackId, track->getTrackStateAsString(), framesReady, desiredFrames);
                underrunFrames = desiredFrames;
            }
            deferredOperations.tallyUnderrunFrames(track, underrunFrames);


            // clear effect chain input buffer if an active track underruns to avoid sending
            // previous audio buffer again to effects
            chain = getEffectChain_l(track->sessionId());
            if (chain != 0) {
                chain->clearInputBuffer();
            }


            ALOGVV("track(%d) s=%08x [NOT READY] on thread %p", trackId, cblk->mServer, this);
            if ((track->sharedBuffer() != 0) || track->isTerminated() ||
                    track->isStopped() || track->isPaused()) {
                // We have consumed all the buffers of this track.
                // Remove it from the list of active tracks.
                // TODO: use actual buffer filling status instead of latency when available from
                // audio HAL
                size_t audioHALFrames = (latency_l() * mSampleRate) / 1000;
                int64_t framesWritten = mBytesWritten / mFrameSize;
                if (mStandby || track->presentationComplete(framesWritten, audioHALFrames)) {
                    if (track->isStopped()) {
                        track->reset();
                    }
                    tracksToRemove->add(track);
                }
            } else {
                // No buffers for this track. Give it a few chances to
                // fill a buffer, then remove it from active list.
                if (--(track->mRetryCount) <= 0) {
                    ALOGI("BUFFER TIMEOUT: remove(%d) from active list on thread %p",
                            trackId, this);
                    tracksToRemove->add(track);
                    // indicate to client process that the track was disabled because of underrun;
                    // it will then automatically call start() when data is available
                    track->disable();
                // If one track is not ready, mark the mixer also not ready if:
                //  - the mixer was ready during previous round OR
                //  - no other track is ready
                } else if (mMixerStatusIgnoringFastTracks == MIXER_TRACKS_READY ||
                                mixerStatus != MIXER_TRACKS_READY) {
                    mixerStatus = MIXER_TRACKS_ENABLED;
                }
            }
            mAudioMixer->disable(trackId);
        }


        }   // local variable scope to avoid goto warning


    }


    if (mHapticChannelMask != AUDIO_CHANNEL_NONE && sq != NULL) {
        // When there is no fast track playing haptic and FastMixer exists,
        // enabling the first FastTrack, which provides mixed data from normal
        // tracks, to play haptic data.
        FastTrack *fastTrack = &state->mFastTracks[0];
        if (fastTrack->mHapticPlaybackEnabled != noFastHapticTrack) {
            fastTrack->mHapticPlaybackEnabled = noFastHapticTrack;
            didModify = true;
        }
    }


    // Push the new FastMixer state if necessary
    bool pauseAudioWatchdog = false;
    if (didModify) {
        state->mFastTracksGen++;
        // if the fast mixer was active, but now there are no fast tracks, then put it in cold idle
        if (kUseFastMixer == FastMixer_Dynamic &&
                state->mCommand == FastMixerState::MIX_WRITE && state->mTrackMask <= 1) {
            state->mCommand = FastMixerState::COLD_IDLE;
            state->mColdFutexAddr = &mFastMixerFutex;
            state->mColdGen++;
            mFastMixerFutex = 0;
            if (kUseFastMixer == FastMixer_Dynamic) {
                mNormalSink = mOutputSink;
            }
            // If we go into cold idle, need to wait for acknowledgement
            // so that fast mixer stops doing I/O.
            block = FastMixerStateQueue::BLOCK_UNTIL_ACKED;
            pauseAudioWatchdog = true;
        }
    }
    if (sq != NULL) {
        sq->end(didModify);
        // No need to block if the FastMixer is in COLD_IDLE as the FastThread
        // is not active. (We BLOCK_UNTIL_ACKED when entering COLD_IDLE
        // when bringing the output sink into standby.)
        //
        // We will get the latest FastMixer state when we come out of COLD_IDLE.
        //
        // This occurs with BT suspend when we idle the FastMixer with
        // active tracks, which may be added or removed.
        sq->push(coldIdle ? FastMixerStateQueue::BLOCK_NEVER : block);
    }
#ifdef AUDIO_WATCHDOG
    if (pauseAudioWatchdog && mAudioWatchdog != 0) {
        mAudioWatchdog->pause();
    }
#endif


    // Now perform the deferred reset on fast tracks that have stopped
    while (resetMask != 0) {
        size_t i = __builtin_ctz(resetMask);
        ALOG_ASSERT(i < count);
        resetMask &= ~(1 << i);
        sp<Track> track = mActiveTracks[i];
        ALOG_ASSERT(track->isFastTrack() && track->isStopped());
        track->reset();
    }


    // Track destruction may occur outside of threadLoop once it is removed from active tracks.
    // Ensure the AudioMixer doesn't have a raw "buffer provider" pointer to the track if
    // it ceases to be active, to allow safe removal from the AudioMixer at the start
    // of prepareTracks_l(); this releases any outstanding buffer back to the track.
    // See also the implementation of destroyTrack_l().
    for (const auto &track : *tracksToRemove) {
        const int trackId = track->id();
        if (mAudioMixer->exists(trackId)) { // Normal tracks here, fast tracks in FastMixer.
            mAudioMixer->setBufferProvider(trackId, nullptr /* bufferProvider */);
        }
    }


    // remove all the tracks that need to be...
    removeTracks_l(*tracksToRemove); //从mActiveTracks删除需要移除的track


    if (getEffectChain_l(AUDIO_SESSION_OUTPUT_MIX) != 0 ||
            getEffectChain_l(AUDIO_SESSION_OUTPUT_STAGE) != 0) {
        mEffectBufferValid = true;
    }


    if (mEffectBufferValid) {
        // as long as there are effects we should clear the effects buffer, to avoid
        // passing a non-clean buffer to the effect chain
        memset(mEffectBuffer, 0, mEffectBufferSize);
        if (mType == SPATIALIZER) {
            memset(mPostSpatializerBuffer, 0, mPostSpatializerBufferSize);
        }
    }
    // sink or mix buffer must be cleared if all tracks are connected to an
    // effect chain as in this case the mixer will not write to the sink or mix buffer
    // and track effects will accumulate into it
    // always clear sink buffer for spatializer output as the output of the spatializer
    // effect will be accumulated into it
    if ((mBytesRemaining == 0) && (((mixedTracks != 0 && mixedTracks == tracksWithEffect) ||
            (mixedTracks == 0 && fastTracks > 0)) || (mType == SPATIALIZER))) {
        // FIXME as a performance optimization, should remember previous zero status
        if (mMixerBufferValid) {
            memset(mMixerBuffer, 0, mMixerBufferSize);
            // TODO: In testing, mSinkBuffer below need not be cleared because
            // the PlaybackThread::threadLoop() copies mMixerBuffer into mSinkBuffer
            // after mixing.
            //
            // To enforce this guarantee:
            // ((mixedTracks != 0 && mixedTracks == tracksWithEffect) ||
            // (mixedTracks == 0 && fastTracks > 0))
            // must imply MIXER_TRACKS_READY.
            // Later, we may clear buffers regardless, and skip much of this logic.
        }
        // FIXME as a performance optimization, should remember previous zero status
        memset(mSinkBuffer, 0, mNormalFrameCount * mFrameSize);
    }


    // if any fast tracks, then status is ready
    mMixerStatusIgnoringFastTracks = mixerStatus;
    if (fastTracks > 0) {
        mixerStatus = MIXER_TRACKS_READY;
    }
    return mixerStatus; //返回当前状态mMixerStatus
}

AudioFlinger MixerThread threadLoop_mix

然后是调用子类MixerThread的threadLoop_mix进行混音处理:

//frameworks/av/services/audioflinger/Threads.cpp
//混音处理(有了prepareTrack_l设置的参数,在threadLoop_mix中需要做的就是调用AudioMixer的process方法进行混音)
void AudioFlinger::MixerThread::threadLoop_mix()
{
    // mix buffers...
    mAudioMixer->process(); //调用AudioMixer的process方法
    mCurrentWriteLength = mSinkBufferSize;//混音了多少数据
    // increase sleep time progressively when application underrun condition clears.
    // Only increase sleep time if the mixer is ready for two consecutive times to avoid
    // that a steady state of alternating ready/not ready conditions keeps the sleep time
    // such that we would underrun the audio HAL.
    if ((mSleepTimeUs == 0) && (sleepTimeShift > 0)) {
        sleepTimeShift--;
    }
    mSleepTimeUs = 0;
    mStandbyTimeNs = systemTime() + mStandbyDelayNs;  //待机时间更新
    //TODO: delay standby when effects have a tail


}

AudioFlinger PlaybackThread threadLoop_write

调用threadLoop_write函数,向硬件抽象层写数据,写入HAL:

//frameworks/av/services/audioflinger/Threads.h
    AudioStreamOut                  *mOutput;
//frameworks/av/services/audioflinger/Threads.cpp
// shared by MIXER and DIRECT, overridden by DUPLICATING
ssize_t AudioFlinger::PlaybackThread::threadLoop_write()
{
    LOG_HIST_TS();
    mInWrite = true;
    ssize_t bytesWritten;
    const size_t offset = mCurrentWriteLength - mBytesRemaining;


    // If an NBAIO sink is present, use it to write the normal mixer's submix
    if (mNormalSink != 0) {


        const size_t count = mBytesRemaining / mFrameSize;


        ATRACE_BEGIN("write");
        // update the setpoint when AudioFlinger::mScreenState changes
        uint32_t screenState = AudioFlinger::mScreenState;
        if (screenState != mScreenState) {
            mScreenState = screenState;
            MonoPipe *pipe = (MonoPipe *)mPipeSink.get();
            if (pipe != NULL) {
                pipe->setAvgFrames((mScreenState & 1) ?
                        (pipe->maxFrames() * 7) / 8 : mNormalFrameCount * 2);
            }
        }
        ssize_t framesWritten = mNormalSink->write((char *)mSinkBuffer + offset, count);
        ATRACE_END();
        if (framesWritten > 0) {
            bytesWritten = framesWritten * mFrameSize;
#ifdef TEE_SINK
            mTee.write((char *)mSinkBuffer + offset, framesWritten);
#endif
        } else {
            bytesWritten = framesWritten;
        }
    // otherwise use the HAL / AudioStreamOut directly
    } else {
        // Direct output and offload threads


        if (mUseAsyncWrite) {
            ALOGW_IF(mWriteAckSequence & 1, "threadLoop_write(): out of sequence write request");
            mWriteAckSequence += 2;
            mWriteAckSequence |= 1;
            ALOG_ASSERT(mCallbackThread != 0);
            mCallbackThread->setWriteBlocked(mWriteAckSequence); 
        }
        ATRACE_BEGIN("write");
        // FIXME We should have an implementation of timestamps for direct output threads.
        // They are used e.g for multichannel PCM playback over HDMI.
        bytesWritten = mOutput->write((char *)mSinkBuffer + offset, mBytesRemaining); //调用AudioStreamOut的write函数
        ATRACE_END();


        if (mUseAsyncWrite &&
                ((bytesWritten < 0) || (bytesWritten == (ssize_t)mBytesRemaining))) {
            // do not wait for async callback in case of error of full write
            mWriteAckSequence &= ~1;
            ALOG_ASSERT(mCallbackThread != 0);
            mCallbackThread->setWriteBlocked(mWriteAckSequence);
        }
    }


    mNumWrites++;
    mInWrite = false;
    if (mStandby) {
        mThreadMetrics.logBeginInterval();
        mThreadSnapshot.onBegin();
        mStandby = false;
    }
    return bytesWritten;
}

在threadLoop_write中调用AudioStreamOut的write函数:

//frameworks/av/services/audioflinger/AudioStreamOut.h
    sp<StreamOutHalInterface> stream;
//frameworks/av/services/audioflinger/AudioStreamOut.cpp
ssize_t AudioStreamOut::write(const void *buffer, size_t numBytes)
{
    size_t bytesWritten;
    status_t result = stream->write(buffer, numBytes, &bytesWritten);
    if (result == OK && bytesWritten > 0 && mHalFrameSize > 0) {
        mFramesWritten += bytesWritten / mHalFrameSize;
    }
    return result == OK ? bytesWritten : result;
}

在AudioStreamOut的write函数中调用StreamOutHalInterface的write函数,StreamOutHalInterface是一个接口,它的具体实现为StreamOutHalHidl:

//frameworks/av/media/libaudiohal/impl/StreamHalHidl.cpp
status_t StreamOutHalHidl::write(const void *buffer, size_t bytes, size_t *written) {
    TIME_CHECK();
    if (mStream == 0) return NO_INIT;
    *written = 0;


    if (bytes == 0 && !mDataMQ) {
        // Can't determine the size for the MQ buffer. Wait for a non-empty write request.
        ALOGW_IF(mCallback.load().unsafe_get(), "First call to async write with 0 bytes");
        return OK;
    }


    status_t status;
    if (!mDataMQ) {
        // In case if playback starts close to the end of a compressed track, the bytes
        // that need to be written is less than the actual buffer size. Need to use
        // full buffer size for the MQ since otherwise after seeking back to the middle
        // data will be truncated.
        size_t bufferSize;
        if ((status = getCachedBufferSize(&bufferSize)) != OK) {
            return status;
        }
        if (bytes > bufferSize) bufferSize = bytes;
        if ((status = prepareForWriting(bufferSize)) != OK) {
            return status;
        }
    }


    status = callWriterThread(
            WriteCommand::WRITE, "write", static_cast<const uint8_t*>(buffer), bytes,
            [&] (const WriteStatus& writeStatus) {
                *written = writeStatus.reply.written;
                // Diagnostics of the cause of b/35813113.
                ALOGE_IF(*written > bytes,
                        "hal reports more bytes written than asked for: %lld > %lld",
                        (long long)*written, (long long)bytes);
            });
    mStreamPowerLog.log(buffer, *written);
    return status;
}

在StreamOutHalHidl的write函数中调用callWriterThread函数:

//frameworks/av/media/libaudiohal/impl/StreamHalHidl.h
    std::unique_ptr<CommandMQ> mCommandMQ;
    std::unique_ptr<DataMQ> mDataMQ;
    std::unique_ptr<StatusMQ> mStatusMQ;
    std::atomic<pid_t> mWriterClient;
    EventFlag* mEfGroup;
//frameworks/av/media/libaudiohal/impl/StreamHalHidl.cpp
status_t StreamOutHalHidl::callWriterThread(
        WriteCommand cmd, const char* cmdName,
        const uint8_t* data, size_t dataSize, StreamOutHalHidl::WriterCallback callback) {
    if (!mCommandMQ->write(&cmd)) {
        ALOGE("command message queue write failed for \"%s\"", cmdName);
        return -EAGAIN;
    }
    if (data != nullptr) {
        size_t availableToWrite = mDataMQ->availableToWrite();
        if (dataSize > availableToWrite) {
            ALOGW("truncating write data from %lld to %lld due to insufficient data queue space",
                    (long long)dataSize, (long long)availableToWrite);
            dataSize = availableToWrite;
        }
        if (!mDataMQ->write(data, dataSize)) { //向数据消息队列中写入数据
            ALOGE("data message queue write failed for \"%s\"", cmdName);
        }
    }
    mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY)); //唤醒数据写入线程


    // TODO: Remove manual event flag handling once blocking MQ is implemented. b/33815422
    uint32_t efState = 0;
retry:
    status_t ret = mEfGroup->wait(static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL), &efState);
    if (efState & static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL)) {
        WriteStatus writeStatus;
        writeStatus.retval = Result::NOT_INITIALIZED;
        if (!mStatusMQ->read(&writeStatus)) {
            ALOGE("status message read failed for \"%s\"", cmdName);
        }
        if (writeStatus.retval == Result::OK) {
            ret = OK;
            callback(writeStatus);
        } else {
            ret = processReturn(cmdName, writeStatus.retval);
        }
        return ret;
    }
    if (ret == -EAGAIN || ret == -EINTR) {
        // Spurious wakeup. This normally retries no more than once.
        goto retry;
    }
    return ret;
}
  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值