Home | History | Annotate | Download | only in audioflinger
      1 /*
      2  * Copyright (C) 2012 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 // <IMPORTANT_WARNING>
     18 // Design rules for threadLoop() are given in the comments at section "Fast mixer thread" of
     19 // StateQueue.h.  In particular, avoid library and system calls except at well-known points.
     20 // The design rules are only for threadLoop(), and don't apply to FastMixerDumpState methods.
     21 // </IMPORTANT_WARNING>
     22 
     23 #define LOG_TAG "FastMixer"
     24 //#define LOG_NDEBUG 0
     25 
     26 #define ATRACE_TAG ATRACE_TAG_AUDIO
     27 
     28 #include "Configuration.h"
     29 #include <time.h>
     30 #include <utils/Log.h>
     31 #include <utils/Trace.h>
     32 #include <system/audio.h>
     33 #ifdef FAST_MIXER_STATISTICS
     34 #include <cpustats/CentralTendencyStatistics.h>
     35 #ifdef CPU_FREQUENCY_STATISTICS
     36 #include <cpustats/ThreadCpuUsage.h>
     37 #endif
     38 #endif
     39 #include <audio_utils/format.h>
     40 #include "AudioMixer.h"
     41 #include "FastMixer.h"
     42 
     43 #define FCC_2                       2   // fixed channel count assumption
     44 
     45 namespace android {
     46 
     47 /*static*/ const FastMixerState FastMixer::initial;
     48 
     49 FastMixer::FastMixer() : FastThread(),
     50     slopNs(0),
     51     // fastTrackNames
     52     // generations
     53     outputSink(NULL),
     54     outputSinkGen(0),
     55     mixer(NULL),
     56     mSinkBuffer(NULL),
     57     mSinkBufferSize(0),
     58     mSinkChannelCount(FCC_2),
     59     mMixerBuffer(NULL),
     60     mMixerBufferSize(0),
     61     mMixerBufferFormat(AUDIO_FORMAT_PCM_16_BIT),
     62     mMixerBufferState(UNDEFINED),
     63     format(Format_Invalid),
     64     sampleRate(0),
     65     fastTracksGen(0),
     66     totalNativeFramesWritten(0),
     67     // timestamp
     68     nativeFramesWrittenButNotPresented(0)   // the = 0 is to silence the compiler
     69 {
     70     // FIXME pass initial as parameter to base class constructor, and make it static local
     71     previous = &initial;
     72     current = &initial;
     73 
     74     mDummyDumpState = &dummyDumpState;
     75     // TODO: Add channel mask to NBAIO_Format.
     76     // We assume that the channel mask must be a valid positional channel mask.
     77     mSinkChannelMask = audio_channel_out_mask_from_count(mSinkChannelCount);
     78 
     79     unsigned i;
     80     for (i = 0; i < FastMixerState::kMaxFastTracks; ++i) {
     81         fastTrackNames[i] = -1;
     82         generations[i] = 0;
     83     }
     84 #ifdef FAST_MIXER_STATISTICS
     85     oldLoad.tv_sec = 0;
     86     oldLoad.tv_nsec = 0;
     87 #endif
     88 }
     89 
     90 FastMixer::~FastMixer()
     91 {
     92 }
     93 
     94 FastMixerStateQueue* FastMixer::sq()
     95 {
     96     return &mSQ;
     97 }
     98 
     99 const FastThreadState *FastMixer::poll()
    100 {
    101     return mSQ.poll();
    102 }
    103 
    104 void FastMixer::setLog(NBLog::Writer *logWriter)
    105 {
    106     if (mixer != NULL) {
    107         mixer->setLog(logWriter);
    108     }
    109 }
    110 
    111 void FastMixer::onIdle()
    112 {
    113     preIdle = *(const FastMixerState *)current;
    114     current = &preIdle;
    115 }
    116 
    117 void FastMixer::onExit()
    118 {
    119     delete mixer;
    120     free(mMixerBuffer);
    121     free(mSinkBuffer);
    122 }
    123 
    124 bool FastMixer::isSubClassCommand(FastThreadState::Command command)
    125 {
    126     switch ((FastMixerState::Command) command) {
    127     case FastMixerState::MIX:
    128     case FastMixerState::WRITE:
    129     case FastMixerState::MIX_WRITE:
    130         return true;
    131     default:
    132         return false;
    133     }
    134 }
    135 
    136 void FastMixer::onStateChange()
    137 {
    138     const FastMixerState * const current = (const FastMixerState *) this->current;
    139     const FastMixerState * const previous = (const FastMixerState *) this->previous;
    140     FastMixerDumpState * const dumpState = (FastMixerDumpState *) this->dumpState;
    141     const size_t frameCount = current->mFrameCount;
    142 
    143     // handle state change here, but since we want to diff the state,
    144     // we're prepared for previous == &initial the first time through
    145     unsigned previousTrackMask;
    146 
    147     // check for change in output HAL configuration
    148     NBAIO_Format previousFormat = format;
    149     if (current->mOutputSinkGen != outputSinkGen) {
    150         outputSink = current->mOutputSink;
    151         outputSinkGen = current->mOutputSinkGen;
    152         if (outputSink == NULL) {
    153             format = Format_Invalid;
    154             sampleRate = 0;
    155             mSinkChannelCount = 0;
    156             mSinkChannelMask = AUDIO_CHANNEL_NONE;
    157         } else {
    158             format = outputSink->format();
    159             sampleRate = Format_sampleRate(format);
    160             mSinkChannelCount = Format_channelCount(format);
    161             LOG_ALWAYS_FATAL_IF(mSinkChannelCount > AudioMixer::MAX_NUM_CHANNELS);
    162 
    163             // TODO: Add channel mask to NBAIO_Format
    164             // We assume that the channel mask must be a valid positional channel mask.
    165             mSinkChannelMask = audio_channel_out_mask_from_count(mSinkChannelCount);
    166         }
    167         dumpState->mSampleRate = sampleRate;
    168     }
    169 
    170     if ((!Format_isEqual(format, previousFormat)) || (frameCount != previous->mFrameCount)) {
    171         // FIXME to avoid priority inversion, don't delete here
    172         delete mixer;
    173         mixer = NULL;
    174         free(mMixerBuffer);
    175         mMixerBuffer = NULL;
    176         free(mSinkBuffer);
    177         mSinkBuffer = NULL;
    178         if (frameCount > 0 && sampleRate > 0) {
    179             // FIXME new may block for unbounded time at internal mutex of the heap
    180             //       implementation; it would be better to have normal mixer allocate for us
    181             //       to avoid blocking here and to prevent possible priority inversion
    182             mixer = new AudioMixer(frameCount, sampleRate, FastMixerState::kMaxFastTracks);
    183             const size_t mixerFrameSize = mSinkChannelCount
    184                     * audio_bytes_per_sample(mMixerBufferFormat);
    185             mMixerBufferSize = mixerFrameSize * frameCount;
    186             (void)posix_memalign(&mMixerBuffer, 32, mMixerBufferSize);
    187             const size_t sinkFrameSize = mSinkChannelCount
    188                     * audio_bytes_per_sample(format.mFormat);
    189             if (sinkFrameSize > mixerFrameSize) { // need a sink buffer
    190                 mSinkBufferSize = sinkFrameSize * frameCount;
    191                 (void)posix_memalign(&mSinkBuffer, 32, mSinkBufferSize);
    192             }
    193             periodNs = (frameCount * 1000000000LL) / sampleRate;    // 1.00
    194             underrunNs = (frameCount * 1750000000LL) / sampleRate;  // 1.75
    195             overrunNs = (frameCount * 500000000LL) / sampleRate;    // 0.50
    196             forceNs = (frameCount * 950000000LL) / sampleRate;      // 0.95
    197             warmupNs = (frameCount * 500000000LL) / sampleRate;     // 0.50
    198         } else {
    199             periodNs = 0;
    200             underrunNs = 0;
    201             overrunNs = 0;
    202             forceNs = 0;
    203             warmupNs = 0;
    204         }
    205         mMixerBufferState = UNDEFINED;
    206 #if !LOG_NDEBUG
    207         for (unsigned i = 0; i < FastMixerState::kMaxFastTracks; ++i) {
    208             fastTrackNames[i] = -1;
    209         }
    210 #endif
    211         // we need to reconfigure all active tracks
    212         previousTrackMask = 0;
    213         fastTracksGen = current->mFastTracksGen - 1;
    214         dumpState->mFrameCount = frameCount;
    215     } else {
    216         previousTrackMask = previous->mTrackMask;
    217     }
    218 
    219     // check for change in active track set
    220     const unsigned currentTrackMask = current->mTrackMask;
    221     dumpState->mTrackMask = currentTrackMask;
    222     if (current->mFastTracksGen != fastTracksGen) {
    223         ALOG_ASSERT(mMixerBuffer != NULL);
    224         int name;
    225 
    226         // process removed tracks first to avoid running out of track names
    227         unsigned removedTracks = previousTrackMask & ~currentTrackMask;
    228         while (removedTracks != 0) {
    229             int i = __builtin_ctz(removedTracks);
    230             removedTracks &= ~(1 << i);
    231             const FastTrack* fastTrack = &current->mFastTracks[i];
    232             ALOG_ASSERT(fastTrack->mBufferProvider == NULL);
    233             if (mixer != NULL) {
    234                 name = fastTrackNames[i];
    235                 ALOG_ASSERT(name >= 0);
    236                 mixer->deleteTrackName(name);
    237             }
    238 #if !LOG_NDEBUG
    239             fastTrackNames[i] = -1;
    240 #endif
    241             // don't reset track dump state, since other side is ignoring it
    242             generations[i] = fastTrack->mGeneration;
    243         }
    244 
    245         // now process added tracks
    246         unsigned addedTracks = currentTrackMask & ~previousTrackMask;
    247         while (addedTracks != 0) {
    248             int i = __builtin_ctz(addedTracks);
    249             addedTracks &= ~(1 << i);
    250             const FastTrack* fastTrack = &current->mFastTracks[i];
    251             AudioBufferProvider *bufferProvider = fastTrack->mBufferProvider;
    252             ALOG_ASSERT(bufferProvider != NULL && fastTrackNames[i] == -1);
    253             if (mixer != NULL) {
    254                 name = mixer->getTrackName(fastTrack->mChannelMask,
    255                         fastTrack->mFormat, AUDIO_SESSION_OUTPUT_MIX);
    256                 ALOG_ASSERT(name >= 0);
    257                 fastTrackNames[i] = name;
    258                 mixer->setBufferProvider(name, bufferProvider);
    259                 mixer->setParameter(name, AudioMixer::TRACK, AudioMixer::MAIN_BUFFER,
    260                         (void *)mMixerBuffer);
    261                 // newly allocated track names default to full scale volume
    262                 mixer->setParameter(
    263                         name,
    264                         AudioMixer::TRACK,
    265                         AudioMixer::MIXER_FORMAT, (void *)mMixerBufferFormat);
    266                 mixer->setParameter(name, AudioMixer::TRACK, AudioMixer::FORMAT,
    267                         (void *)(uintptr_t)fastTrack->mFormat);
    268                 mixer->setParameter(name, AudioMixer::TRACK, AudioMixer::CHANNEL_MASK,
    269                         (void *)(uintptr_t)fastTrack->mChannelMask);
    270                 mixer->setParameter(name, AudioMixer::TRACK, AudioMixer::MIXER_CHANNEL_MASK,
    271                         (void *)(uintptr_t)mSinkChannelMask);
    272                 mixer->enable(name);
    273             }
    274             generations[i] = fastTrack->mGeneration;
    275         }
    276 
    277         // finally process (potentially) modified tracks; these use the same slot
    278         // but may have a different buffer provider or volume provider
    279         unsigned modifiedTracks = currentTrackMask & previousTrackMask;
    280         while (modifiedTracks != 0) {
    281             int i = __builtin_ctz(modifiedTracks);
    282             modifiedTracks &= ~(1 << i);
    283             const FastTrack* fastTrack = &current->mFastTracks[i];
    284             if (fastTrack->mGeneration != generations[i]) {
    285                 // this track was actually modified
    286                 AudioBufferProvider *bufferProvider = fastTrack->mBufferProvider;
    287                 ALOG_ASSERT(bufferProvider != NULL);
    288                 if (mixer != NULL) {
    289                     name = fastTrackNames[i];
    290                     ALOG_ASSERT(name >= 0);
    291                     mixer->setBufferProvider(name, bufferProvider);
    292                     if (fastTrack->mVolumeProvider == NULL) {
    293                         float f = AudioMixer::UNITY_GAIN_FLOAT;
    294                         mixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::VOLUME0, &f);
    295                         mixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::VOLUME1, &f);
    296                     }
    297                     mixer->setParameter(name, AudioMixer::RESAMPLE,
    298                             AudioMixer::REMOVE, NULL);
    299                     mixer->setParameter(
    300                             name,
    301                             AudioMixer::TRACK,
    302                             AudioMixer::MIXER_FORMAT, (void *)mMixerBufferFormat);
    303                     mixer->setParameter(name, AudioMixer::TRACK, AudioMixer::FORMAT,
    304                             (void *)(uintptr_t)fastTrack->mFormat);
    305                     mixer->setParameter(name, AudioMixer::TRACK, AudioMixer::CHANNEL_MASK,
    306                             (void *)(uintptr_t)fastTrack->mChannelMask);
    307                     mixer->setParameter(name, AudioMixer::TRACK, AudioMixer::MIXER_CHANNEL_MASK,
    308                             (void *)(uintptr_t)mSinkChannelMask);
    309                     // already enabled
    310                 }
    311                 generations[i] = fastTrack->mGeneration;
    312             }
    313         }
    314 
    315         fastTracksGen = current->mFastTracksGen;
    316 
    317         dumpState->mNumTracks = popcount(currentTrackMask);
    318     }
    319 }
    320 
    321 void FastMixer::onWork()
    322 {
    323     const FastMixerState * const current = (const FastMixerState *) this->current;
    324     FastMixerDumpState * const dumpState = (FastMixerDumpState *) this->dumpState;
    325     const FastMixerState::Command command = this->command;
    326     const size_t frameCount = current->mFrameCount;
    327 
    328     if ((command & FastMixerState::MIX) && (mixer != NULL) && isWarm) {
    329         ALOG_ASSERT(mMixerBuffer != NULL);
    330         // for each track, update volume and check for underrun
    331         unsigned currentTrackMask = current->mTrackMask;
    332         while (currentTrackMask != 0) {
    333             int i = __builtin_ctz(currentTrackMask);
    334             currentTrackMask &= ~(1 << i);
    335             const FastTrack* fastTrack = &current->mFastTracks[i];
    336 
    337             // Refresh the per-track timestamp
    338             if (timestampStatus == NO_ERROR) {
    339                 uint32_t trackFramesWrittenButNotPresented =
    340                     nativeFramesWrittenButNotPresented;
    341                 uint32_t trackFramesWritten = fastTrack->mBufferProvider->framesReleased();
    342                 // Can't provide an AudioTimestamp before first frame presented,
    343                 // or during the brief 32-bit wraparound window
    344                 if (trackFramesWritten >= trackFramesWrittenButNotPresented) {
    345                     AudioTimestamp perTrackTimestamp;
    346                     perTrackTimestamp.mPosition =
    347                             trackFramesWritten - trackFramesWrittenButNotPresented;
    348                     perTrackTimestamp.mTime = timestamp.mTime;
    349                     fastTrack->mBufferProvider->onTimestamp(perTrackTimestamp);
    350                 }
    351             }
    352 
    353             int name = fastTrackNames[i];
    354             ALOG_ASSERT(name >= 0);
    355             if (fastTrack->mVolumeProvider != NULL) {
    356                 gain_minifloat_packed_t vlr = fastTrack->mVolumeProvider->getVolumeLR();
    357                 float vlf = float_from_gain(gain_minifloat_unpack_left(vlr));
    358                 float vrf = float_from_gain(gain_minifloat_unpack_right(vlr));
    359 
    360                 mixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::VOLUME0, &vlf);
    361                 mixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::VOLUME1, &vrf);
    362             }
    363             // FIXME The current implementation of framesReady() for fast tracks
    364             // takes a tryLock, which can block
    365             // up to 1 ms.  If enough active tracks all blocked in sequence, this would result
    366             // in the overall fast mix cycle being delayed.  Should use a non-blocking FIFO.
    367             size_t framesReady = fastTrack->mBufferProvider->framesReady();
    368             if (ATRACE_ENABLED()) {
    369                 // I wish we had formatted trace names
    370                 char traceName[16];
    371                 strcpy(traceName, "fRdy");
    372                 traceName[4] = i + (i < 10 ? '0' : 'A' - 10);
    373                 traceName[5] = '\0';
    374                 ATRACE_INT(traceName, framesReady);
    375             }
    376             FastTrackDump *ftDump = &dumpState->mTracks[i];
    377             FastTrackUnderruns underruns = ftDump->mUnderruns;
    378             if (framesReady < frameCount) {
    379                 if (framesReady == 0) {
    380                     underruns.mBitFields.mEmpty++;
    381                     underruns.mBitFields.mMostRecent = UNDERRUN_EMPTY;
    382                     mixer->disable(name);
    383                 } else {
    384                     // allow mixing partial buffer
    385                     underruns.mBitFields.mPartial++;
    386                     underruns.mBitFields.mMostRecent = UNDERRUN_PARTIAL;
    387                     mixer->enable(name);
    388                 }
    389             } else {
    390                 underruns.mBitFields.mFull++;
    391                 underruns.mBitFields.mMostRecent = UNDERRUN_FULL;
    392                 mixer->enable(name);
    393             }
    394             ftDump->mUnderruns = underruns;
    395             ftDump->mFramesReady = framesReady;
    396         }
    397 
    398         int64_t pts;
    399         if (outputSink == NULL || (OK != outputSink->getNextWriteTimestamp(&pts))) {
    400             pts = AudioBufferProvider::kInvalidPTS;
    401         }
    402 
    403         // process() is CPU-bound
    404         mixer->process(pts);
    405         mMixerBufferState = MIXED;
    406     } else if (mMixerBufferState == MIXED) {
    407         mMixerBufferState = UNDEFINED;
    408     }
    409     //bool didFullWrite = false;    // dumpsys could display a count of partial writes
    410     if ((command & FastMixerState::WRITE) && (outputSink != NULL) && (mMixerBuffer != NULL)) {
    411         if (mMixerBufferState == UNDEFINED) {
    412             memset(mMixerBuffer, 0, mMixerBufferSize);
    413             mMixerBufferState = ZEROED;
    414         }
    415         void *buffer = mSinkBuffer != NULL ? mSinkBuffer : mMixerBuffer;
    416         if (format.mFormat != mMixerBufferFormat) { // sink format not the same as mixer format
    417             memcpy_by_audio_format(buffer, format.mFormat, mMixerBuffer, mMixerBufferFormat,
    418                     frameCount * Format_channelCount(format));
    419         }
    420         // if non-NULL, then duplicate write() to this non-blocking sink
    421         NBAIO_Sink* teeSink;
    422         if ((teeSink = current->mTeeSink) != NULL) {
    423             (void) teeSink->write(buffer, frameCount);
    424         }
    425         // FIXME write() is non-blocking and lock-free for a properly implemented NBAIO sink,
    426         //       but this code should be modified to handle both non-blocking and blocking sinks
    427         dumpState->mWriteSequence++;
    428         ATRACE_BEGIN("write");
    429         ssize_t framesWritten = outputSink->write(buffer, frameCount);
    430         ATRACE_END();
    431         dumpState->mWriteSequence++;
    432         if (framesWritten >= 0) {
    433             ALOG_ASSERT((size_t) framesWritten <= frameCount);
    434             totalNativeFramesWritten += framesWritten;
    435             dumpState->mFramesWritten = totalNativeFramesWritten;
    436             //if ((size_t) framesWritten == frameCount) {
    437             //    didFullWrite = true;
    438             //}
    439         } else {
    440             dumpState->mWriteErrors++;
    441         }
    442         attemptedWrite = true;
    443         // FIXME count # of writes blocked excessively, CPU usage, etc. for dump
    444 
    445         timestampStatus = outputSink->getTimestamp(timestamp);
    446         if (timestampStatus == NO_ERROR) {
    447             uint32_t totalNativeFramesPresented = timestamp.mPosition;
    448             if (totalNativeFramesPresented <= totalNativeFramesWritten) {
    449                 nativeFramesWrittenButNotPresented =
    450                     totalNativeFramesWritten - totalNativeFramesPresented;
    451             } else {
    452                 // HAL reported that more frames were presented than were written
    453                 timestampStatus = INVALID_OPERATION;
    454             }
    455         }
    456     }
    457 }
    458 
    459 FastMixerDumpState::FastMixerDumpState(
    460 #ifdef FAST_MIXER_STATISTICS
    461         uint32_t samplingN
    462 #endif
    463         ) : FastThreadDumpState(),
    464     mWriteSequence(0), mFramesWritten(0),
    465     mNumTracks(0), mWriteErrors(0),
    466     mSampleRate(0), mFrameCount(0),
    467     mTrackMask(0)
    468 {
    469 #ifdef FAST_MIXER_STATISTICS
    470     increaseSamplingN(samplingN);
    471 #endif
    472 }
    473 
    474 #ifdef FAST_MIXER_STATISTICS
    475 void FastMixerDumpState::increaseSamplingN(uint32_t samplingN)
    476 {
    477     if (samplingN <= mSamplingN || samplingN > kSamplingN || roundup(samplingN) != samplingN) {
    478         return;
    479     }
    480     uint32_t additional = samplingN - mSamplingN;
    481     // sample arrays aren't accessed atomically with respect to the bounds,
    482     // so clearing reduces chance for dumpsys to read random uninitialized samples
    483     memset(&mMonotonicNs[mSamplingN], 0, sizeof(mMonotonicNs[0]) * additional);
    484     memset(&mLoadNs[mSamplingN], 0, sizeof(mLoadNs[0]) * additional);
    485 #ifdef CPU_FREQUENCY_STATISTICS
    486     memset(&mCpukHz[mSamplingN], 0, sizeof(mCpukHz[0]) * additional);
    487 #endif
    488     mSamplingN = samplingN;
    489 }
    490 #endif
    491 
    492 FastMixerDumpState::~FastMixerDumpState()
    493 {
    494 }
    495 
    496 // helper function called by qsort()
    497 static int compare_uint32_t(const void *pa, const void *pb)
    498 {
    499     uint32_t a = *(const uint32_t *)pa;
    500     uint32_t b = *(const uint32_t *)pb;
    501     if (a < b) {
    502         return -1;
    503     } else if (a > b) {
    504         return 1;
    505     } else {
    506         return 0;
    507     }
    508 }
    509 
    510 void FastMixerDumpState::dump(int fd) const
    511 {
    512     if (mCommand == FastMixerState::INITIAL) {
    513         dprintf(fd, "  FastMixer not initialized\n");
    514         return;
    515     }
    516 #define COMMAND_MAX 32
    517     char string[COMMAND_MAX];
    518     switch (mCommand) {
    519     case FastMixerState::INITIAL:
    520         strcpy(string, "INITIAL");
    521         break;
    522     case FastMixerState::HOT_IDLE:
    523         strcpy(string, "HOT_IDLE");
    524         break;
    525     case FastMixerState::COLD_IDLE:
    526         strcpy(string, "COLD_IDLE");
    527         break;
    528     case FastMixerState::EXIT:
    529         strcpy(string, "EXIT");
    530         break;
    531     case FastMixerState::MIX:
    532         strcpy(string, "MIX");
    533         break;
    534     case FastMixerState::WRITE:
    535         strcpy(string, "WRITE");
    536         break;
    537     case FastMixerState::MIX_WRITE:
    538         strcpy(string, "MIX_WRITE");
    539         break;
    540     default:
    541         snprintf(string, COMMAND_MAX, "%d", mCommand);
    542         break;
    543     }
    544     double measuredWarmupMs = (mMeasuredWarmupTs.tv_sec * 1000.0) +
    545             (mMeasuredWarmupTs.tv_nsec / 1000000.0);
    546     double mixPeriodSec = (double) mFrameCount / (double) mSampleRate;
    547     dprintf(fd, "  FastMixer command=%s writeSequence=%u framesWritten=%u\n"
    548                 "            numTracks=%u writeErrors=%u underruns=%u overruns=%u\n"
    549                 "            sampleRate=%u frameCount=%zu measuredWarmup=%.3g ms, warmupCycles=%u\n"
    550                 "            mixPeriod=%.2f ms\n",
    551                  string, mWriteSequence, mFramesWritten,
    552                  mNumTracks, mWriteErrors, mUnderruns, mOverruns,
    553                  mSampleRate, mFrameCount, measuredWarmupMs, mWarmupCycles,
    554                  mixPeriodSec * 1e3);
    555 #ifdef FAST_MIXER_STATISTICS
    556     // find the interval of valid samples
    557     uint32_t bounds = mBounds;
    558     uint32_t newestOpen = bounds & 0xFFFF;
    559     uint32_t oldestClosed = bounds >> 16;
    560     uint32_t n = (newestOpen - oldestClosed) & 0xFFFF;
    561     if (n > mSamplingN) {
    562         ALOGE("too many samples %u", n);
    563         n = mSamplingN;
    564     }
    565     // statistics for monotonic (wall clock) time, thread raw CPU load in time, CPU clock frequency,
    566     // and adjusted CPU load in MHz normalized for CPU clock frequency
    567     CentralTendencyStatistics wall, loadNs;
    568 #ifdef CPU_FREQUENCY_STATISTICS
    569     CentralTendencyStatistics kHz, loadMHz;
    570     uint32_t previousCpukHz = 0;
    571 #endif
    572     // Assuming a normal distribution for cycle times, three standard deviations on either side of
    573     // the mean account for 99.73% of the population.  So if we take each tail to be 1/1000 of the
    574     // sample set, we get 99.8% combined, or close to three standard deviations.
    575     static const uint32_t kTailDenominator = 1000;
    576     uint32_t *tail = n >= kTailDenominator ? new uint32_t[n] : NULL;
    577     // loop over all the samples
    578     for (uint32_t j = 0; j < n; ++j) {
    579         size_t i = oldestClosed++ & (mSamplingN - 1);
    580         uint32_t wallNs = mMonotonicNs[i];
    581         if (tail != NULL) {
    582             tail[j] = wallNs;
    583         }
    584         wall.sample(wallNs);
    585         uint32_t sampleLoadNs = mLoadNs[i];
    586         loadNs.sample(sampleLoadNs);
    587 #ifdef CPU_FREQUENCY_STATISTICS
    588         uint32_t sampleCpukHz = mCpukHz[i];
    589         // skip bad kHz samples
    590         if ((sampleCpukHz & ~0xF) != 0) {
    591             kHz.sample(sampleCpukHz >> 4);
    592             if (sampleCpukHz == previousCpukHz) {
    593                 double megacycles = (double) sampleLoadNs * (double) (sampleCpukHz >> 4) * 1e-12;
    594                 double adjMHz = megacycles / mixPeriodSec;  // _not_ wallNs * 1e9
    595                 loadMHz.sample(adjMHz);
    596             }
    597         }
    598         previousCpukHz = sampleCpukHz;
    599 #endif
    600     }
    601     if (n) {
    602         dprintf(fd, "  Simple moving statistics over last %.1f seconds:\n",
    603                     wall.n() * mixPeriodSec);
    604         dprintf(fd, "    wall clock time in ms per mix cycle:\n"
    605                     "      mean=%.2f min=%.2f max=%.2f stddev=%.2f\n",
    606                     wall.mean()*1e-6, wall.minimum()*1e-6, wall.maximum()*1e-6,
    607                     wall.stddev()*1e-6);
    608         dprintf(fd, "    raw CPU load in us per mix cycle:\n"
    609                     "      mean=%.0f min=%.0f max=%.0f stddev=%.0f\n",
    610                     loadNs.mean()*1e-3, loadNs.minimum()*1e-3, loadNs.maximum()*1e-3,
    611                     loadNs.stddev()*1e-3);
    612     } else {
    613         dprintf(fd, "  No FastMixer statistics available currently\n");
    614     }
    615 #ifdef CPU_FREQUENCY_STATISTICS
    616     dprintf(fd, "  CPU clock frequency in MHz:\n"
    617                 "    mean=%.0f min=%.0f max=%.0f stddev=%.0f\n",
    618                 kHz.mean()*1e-3, kHz.minimum()*1e-3, kHz.maximum()*1e-3, kHz.stddev()*1e-3);
    619     dprintf(fd, "  adjusted CPU load in MHz (i.e. normalized for CPU clock frequency):\n"
    620                 "    mean=%.1f min=%.1f max=%.1f stddev=%.1f\n",
    621                 loadMHz.mean(), loadMHz.minimum(), loadMHz.maximum(), loadMHz.stddev());
    622 #endif
    623     if (tail != NULL) {
    624         qsort(tail, n, sizeof(uint32_t), compare_uint32_t);
    625         // assume same number of tail samples on each side, left and right
    626         uint32_t count = n / kTailDenominator;
    627         CentralTendencyStatistics left, right;
    628         for (uint32_t i = 0; i < count; ++i) {
    629             left.sample(tail[i]);
    630             right.sample(tail[n - (i + 1)]);
    631         }
    632         dprintf(fd, "  Distribution of mix cycle times in ms for the tails (> ~3 stddev outliers):\n"
    633                     "    left tail: mean=%.2f min=%.2f max=%.2f stddev=%.2f\n"
    634                     "    right tail: mean=%.2f min=%.2f max=%.2f stddev=%.2f\n",
    635                     left.mean()*1e-6, left.minimum()*1e-6, left.maximum()*1e-6, left.stddev()*1e-6,
    636                     right.mean()*1e-6, right.minimum()*1e-6, right.maximum()*1e-6,
    637                     right.stddev()*1e-6);
    638         delete[] tail;
    639     }
    640 #endif
    641     // The active track mask and track states are updated non-atomically.
    642     // So if we relied on isActive to decide whether to display,
    643     // then we might display an obsolete track or omit an active track.
    644     // Instead we always display all tracks, with an indication
    645     // of whether we think the track is active.
    646     uint32_t trackMask = mTrackMask;
    647     dprintf(fd, "  Fast tracks: kMaxFastTracks=%u activeMask=%#x\n",
    648             FastMixerState::kMaxFastTracks, trackMask);
    649     dprintf(fd, "  Index Active Full Partial Empty  Recent Ready\n");
    650     for (uint32_t i = 0; i < FastMixerState::kMaxFastTracks; ++i, trackMask >>= 1) {
    651         bool isActive = trackMask & 1;
    652         const FastTrackDump *ftDump = &mTracks[i];
    653         const FastTrackUnderruns& underruns = ftDump->mUnderruns;
    654         const char *mostRecent;
    655         switch (underruns.mBitFields.mMostRecent) {
    656         case UNDERRUN_FULL:
    657             mostRecent = "full";
    658             break;
    659         case UNDERRUN_PARTIAL:
    660             mostRecent = "partial";
    661             break;
    662         case UNDERRUN_EMPTY:
    663             mostRecent = "empty";
    664             break;
    665         default:
    666             mostRecent = "?";
    667             break;
    668         }
    669         dprintf(fd, "  %5u %6s %4u %7u %5u %7s %5zu\n", i, isActive ? "yes" : "no",
    670                 (underruns.mBitFields.mFull) & UNDERRUN_MASK,
    671                 (underruns.mBitFields.mPartial) & UNDERRUN_MASK,
    672                 (underruns.mBitFields.mEmpty) & UNDERRUN_MASK,
    673                 mostRecent, ftDump->mFramesReady);
    674     }
    675 }
    676 
    677 }   // namespace android
    678