summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGlenn Kasten <gkasten@google.com>2015-02-17 16:23:03 -0800
committerGlenn Kasten <gkasten@google.com>2015-02-19 09:47:39 -0800
commit04333cdc8d6a3c8e4a11835371e8ad13adf3f7f0 (patch)
treeff205682f760786e3d195f297d60207af0e40792
parent658fc18d8e632441cd5d83a4f74b53620cbac1fe (diff)
downloadframeworks_av-04333cdc8d6a3c8e4a11835371e8ad13adf3f7f0.zip
frameworks_av-04333cdc8d6a3c8e4a11835371e8ad13adf3f7f0.tar.gz
frameworks_av-04333cdc8d6a3c8e4a11835371e8ad13adf3f7f0.tar.bz2
Pull out FastCaptureDumpState and FastMixerDumpState
Change-Id: I8e44dbfe02338622eb69193b234743b50f0dd79f
-rw-r--r--services/audioflinger/Android.mk2
-rw-r--r--services/audioflinger/FastCapture.cpp9
-rw-r--r--services/audioflinger/FastCapture.h14
-rw-r--r--services/audioflinger/FastCaptureDumpState.cpp30
-rw-r--r--services/audioflinger/FastCaptureDumpState.h40
-rw-r--r--services/audioflinger/FastMixer.cpp219
-rw-r--r--services/audioflinger/FastMixerDumpState.cpp252
-rw-r--r--services/audioflinger/FastMixerDumpState.h2
8 files changed, 327 insertions, 241 deletions
diff --git a/services/audioflinger/Android.mk b/services/audioflinger/Android.mk
index f029333..642ff82 100644
--- a/services/audioflinger/Android.mk
+++ b/services/audioflinger/Android.mk
@@ -77,8 +77,10 @@ LOCAL_32_BIT_ONLY := true
LOCAL_SRC_FILES += \
AudioWatchdog.cpp \
FastCapture.cpp \
+ FastCaptureDumpState.cpp \
FastCaptureState.cpp \
FastMixer.cpp \
+ FastMixerDumpState.cpp \
FastMixerState.cpp \
FastThread.cpp \
FastThreadDumpState.cpp \
diff --git a/services/audioflinger/FastCapture.cpp b/services/audioflinger/FastCapture.cpp
index 0c9b976..1c4f670 100644
--- a/services/audioflinger/FastCapture.cpp
+++ b/services/audioflinger/FastCapture.cpp
@@ -210,13 +210,4 @@ void FastCapture::onWork()
}
}
-FastCaptureDumpState::FastCaptureDumpState() : FastThreadDumpState(),
- mReadSequence(0), mFramesRead(0), mReadErrors(0), mSampleRate(0), mFrameCount(0)
-{
-}
-
-FastCaptureDumpState::~FastCaptureDumpState()
-{
-}
-
} // namespace android
diff --git a/services/audioflinger/FastCapture.h b/services/audioflinger/FastCapture.h
index e61e026..da0fe2f 100644
--- a/services/audioflinger/FastCapture.h
+++ b/services/audioflinger/FastCapture.h
@@ -20,24 +20,12 @@
#include "FastThread.h"
#include "StateQueue.h"
#include "FastCaptureState.h"
-#include "FastThreadDumpState.h"
+#include "FastCaptureDumpState.h"
namespace android {
typedef StateQueue<FastCaptureState> FastCaptureStateQueue;
-struct FastCaptureDumpState : FastThreadDumpState {
- FastCaptureDumpState();
- /*virtual*/ ~FastCaptureDumpState();
-
- // FIXME by renaming, could pull up many of these to FastThreadDumpState
- uint32_t mReadSequence; // incremented before and after each read()
- uint32_t mFramesRead; // total number of frames read successfully
- uint32_t mReadErrors; // total number of read() errors
- uint32_t mSampleRate;
- size_t mFrameCount;
-};
-
class FastCapture : public FastThread {
public:
diff --git a/services/audioflinger/FastCaptureDumpState.cpp b/services/audioflinger/FastCaptureDumpState.cpp
new file mode 100644
index 0000000..00f8da0
--- /dev/null
+++ b/services/audioflinger/FastCaptureDumpState.cpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "FastCaptureDumpState.h"
+
+namespace android {
+
+FastCaptureDumpState::FastCaptureDumpState() : FastThreadDumpState(),
+ mReadSequence(0), mFramesRead(0), mReadErrors(0), mSampleRate(0), mFrameCount(0)
+{
+}
+
+FastCaptureDumpState::~FastCaptureDumpState()
+{
+}
+
+} // android
diff --git a/services/audioflinger/FastCaptureDumpState.h b/services/audioflinger/FastCaptureDumpState.h
new file mode 100644
index 0000000..ee99099
--- /dev/null
+++ b/services/audioflinger/FastCaptureDumpState.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_AUDIO_FAST_CAPTURE_DUMP_STATE_H
+#define ANDROID_AUDIO_FAST_CAPTURE_DUMP_STATE_H
+
+#include <stdint.h>
+#include "Configuration.h"
+#include "FastThreadDumpState.h"
+
+namespace android {
+
+struct FastCaptureDumpState : FastThreadDumpState {
+ FastCaptureDumpState();
+ /*virtual*/ ~FastCaptureDumpState();
+
+ // FIXME by renaming, could pull up many of these to FastThreadDumpState
+ uint32_t mReadSequence; // incremented before and after each read()
+ uint32_t mFramesRead; // total number of frames read successfully
+ uint32_t mReadErrors; // total number of read() errors
+ uint32_t mSampleRate;
+ size_t mFrameCount;
+};
+
+} // android
+
+#endif // ANDROID_AUDIO_FAST_CAPTURE_DUMP_STATE_H
diff --git a/services/audioflinger/FastMixer.cpp b/services/audioflinger/FastMixer.cpp
index 141a79e..8f05ef0 100644
--- a/services/audioflinger/FastMixer.cpp
+++ b/services/audioflinger/FastMixer.cpp
@@ -456,223 +456,4 @@ void FastMixer::onWork()
}
}
-FastMixerDumpState::FastMixerDumpState(
-#ifdef FAST_MIXER_STATISTICS
- uint32_t samplingN
-#endif
- ) : FastThreadDumpState(),
- mWriteSequence(0), mFramesWritten(0),
- mNumTracks(0), mWriteErrors(0),
- mSampleRate(0), mFrameCount(0),
- mTrackMask(0)
-{
-#ifdef FAST_MIXER_STATISTICS
- increaseSamplingN(samplingN);
-#endif
-}
-
-#ifdef FAST_MIXER_STATISTICS
-void FastMixerDumpState::increaseSamplingN(uint32_t samplingN)
-{
- if (samplingN <= mSamplingN || samplingN > kSamplingN || roundup(samplingN) != samplingN) {
- return;
- }
- uint32_t additional = samplingN - mSamplingN;
- // sample arrays aren't accessed atomically with respect to the bounds,
- // so clearing reduces chance for dumpsys to read random uninitialized samples
- memset(&mMonotonicNs[mSamplingN], 0, sizeof(mMonotonicNs[0]) * additional);
- memset(&mLoadNs[mSamplingN], 0, sizeof(mLoadNs[0]) * additional);
-#ifdef CPU_FREQUENCY_STATISTICS
- memset(&mCpukHz[mSamplingN], 0, sizeof(mCpukHz[0]) * additional);
-#endif
- mSamplingN = samplingN;
-}
-#endif
-
-FastMixerDumpState::~FastMixerDumpState()
-{
-}
-
-// helper function called by qsort()
-static int compare_uint32_t(const void *pa, const void *pb)
-{
- uint32_t a = *(const uint32_t *)pa;
- uint32_t b = *(const uint32_t *)pb;
- if (a < b) {
- return -1;
- } else if (a > b) {
- return 1;
- } else {
- return 0;
- }
-}
-
-void FastMixerDumpState::dump(int fd) const
-{
- if (mCommand == FastMixerState::INITIAL) {
- dprintf(fd, " FastMixer not initialized\n");
- return;
- }
-#define COMMAND_MAX 32
- char string[COMMAND_MAX];
- switch (mCommand) {
- case FastMixerState::INITIAL:
- strcpy(string, "INITIAL");
- break;
- case FastMixerState::HOT_IDLE:
- strcpy(string, "HOT_IDLE");
- break;
- case FastMixerState::COLD_IDLE:
- strcpy(string, "COLD_IDLE");
- break;
- case FastMixerState::EXIT:
- strcpy(string, "EXIT");
- break;
- case FastMixerState::MIX:
- strcpy(string, "MIX");
- break;
- case FastMixerState::WRITE:
- strcpy(string, "WRITE");
- break;
- case FastMixerState::MIX_WRITE:
- strcpy(string, "MIX_WRITE");
- break;
- default:
- snprintf(string, COMMAND_MAX, "%d", mCommand);
- break;
- }
- double measuredWarmupMs = (mMeasuredWarmupTs.tv_sec * 1000.0) +
- (mMeasuredWarmupTs.tv_nsec / 1000000.0);
- double mixPeriodSec = (double) mFrameCount / (double) mSampleRate;
- dprintf(fd, " FastMixer command=%s writeSequence=%u framesWritten=%u\n"
- " numTracks=%u writeErrors=%u underruns=%u overruns=%u\n"
- " sampleRate=%u frameCount=%zu measuredWarmup=%.3g ms, warmupCycles=%u\n"
- " mixPeriod=%.2f ms\n",
- string, mWriteSequence, mFramesWritten,
- mNumTracks, mWriteErrors, mUnderruns, mOverruns,
- mSampleRate, mFrameCount, measuredWarmupMs, mWarmupCycles,
- mixPeriodSec * 1e3);
-#ifdef FAST_MIXER_STATISTICS
- // find the interval of valid samples
- uint32_t bounds = mBounds;
- uint32_t newestOpen = bounds & 0xFFFF;
- uint32_t oldestClosed = bounds >> 16;
- uint32_t n = (newestOpen - oldestClosed) & 0xFFFF;
- if (n > mSamplingN) {
- ALOGE("too many samples %u", n);
- n = mSamplingN;
- }
- // statistics for monotonic (wall clock) time, thread raw CPU load in time, CPU clock frequency,
- // and adjusted CPU load in MHz normalized for CPU clock frequency
- CentralTendencyStatistics wall, loadNs;
-#ifdef CPU_FREQUENCY_STATISTICS
- CentralTendencyStatistics kHz, loadMHz;
- uint32_t previousCpukHz = 0;
-#endif
- // Assuming a normal distribution for cycle times, three standard deviations on either side of
- // the mean account for 99.73% of the population. So if we take each tail to be 1/1000 of the
- // sample set, we get 99.8% combined, or close to three standard deviations.
- static const uint32_t kTailDenominator = 1000;
- uint32_t *tail = n >= kTailDenominator ? new uint32_t[n] : NULL;
- // loop over all the samples
- for (uint32_t j = 0; j < n; ++j) {
- size_t i = oldestClosed++ & (mSamplingN - 1);
- uint32_t wallNs = mMonotonicNs[i];
- if (tail != NULL) {
- tail[j] = wallNs;
- }
- wall.sample(wallNs);
- uint32_t sampleLoadNs = mLoadNs[i];
- loadNs.sample(sampleLoadNs);
-#ifdef CPU_FREQUENCY_STATISTICS
- uint32_t sampleCpukHz = mCpukHz[i];
- // skip bad kHz samples
- if ((sampleCpukHz & ~0xF) != 0) {
- kHz.sample(sampleCpukHz >> 4);
- if (sampleCpukHz == previousCpukHz) {
- double megacycles = (double) sampleLoadNs * (double) (sampleCpukHz >> 4) * 1e-12;
- double adjMHz = megacycles / mixPeriodSec; // _not_ wallNs * 1e9
- loadMHz.sample(adjMHz);
- }
- }
- previousCpukHz = sampleCpukHz;
-#endif
- }
- if (n) {
- dprintf(fd, " Simple moving statistics over last %.1f seconds:\n",
- wall.n() * mixPeriodSec);
- dprintf(fd, " wall clock time in ms per mix cycle:\n"
- " mean=%.2f min=%.2f max=%.2f stddev=%.2f\n",
- wall.mean()*1e-6, wall.minimum()*1e-6, wall.maximum()*1e-6,
- wall.stddev()*1e-6);
- dprintf(fd, " raw CPU load in us per mix cycle:\n"
- " mean=%.0f min=%.0f max=%.0f stddev=%.0f\n",
- loadNs.mean()*1e-3, loadNs.minimum()*1e-3, loadNs.maximum()*1e-3,
- loadNs.stddev()*1e-3);
- } else {
- dprintf(fd, " No FastMixer statistics available currently\n");
- }
-#ifdef CPU_FREQUENCY_STATISTICS
- dprintf(fd, " CPU clock frequency in MHz:\n"
- " mean=%.0f min=%.0f max=%.0f stddev=%.0f\n",
- kHz.mean()*1e-3, kHz.minimum()*1e-3, kHz.maximum()*1e-3, kHz.stddev()*1e-3);
- dprintf(fd, " adjusted CPU load in MHz (i.e. normalized for CPU clock frequency):\n"
- " mean=%.1f min=%.1f max=%.1f stddev=%.1f\n",
- loadMHz.mean(), loadMHz.minimum(), loadMHz.maximum(), loadMHz.stddev());
-#endif
- if (tail != NULL) {
- qsort(tail, n, sizeof(uint32_t), compare_uint32_t);
- // assume same number of tail samples on each side, left and right
- uint32_t count = n / kTailDenominator;
- CentralTendencyStatistics left, right;
- for (uint32_t i = 0; i < count; ++i) {
- left.sample(tail[i]);
- right.sample(tail[n - (i + 1)]);
- }
- dprintf(fd, " Distribution of mix cycle times in ms for the tails "
- "(> ~3 stddev outliers):\n"
- " left tail: mean=%.2f min=%.2f max=%.2f stddev=%.2f\n"
- " right tail: mean=%.2f min=%.2f max=%.2f stddev=%.2f\n",
- left.mean()*1e-6, left.minimum()*1e-6, left.maximum()*1e-6, left.stddev()*1e-6,
- right.mean()*1e-6, right.minimum()*1e-6, right.maximum()*1e-6,
- right.stddev()*1e-6);
- delete[] tail;
- }
-#endif
- // The active track mask and track states are updated non-atomically.
- // So if we relied on isActive to decide whether to display,
- // then we might display an obsolete track or omit an active track.
- // Instead we always display all tracks, with an indication
- // of whether we think the track is active.
- uint32_t trackMask = mTrackMask;
- dprintf(fd, " Fast tracks: kMaxFastTracks=%u activeMask=%#x\n",
- FastMixerState::kMaxFastTracks, trackMask);
- dprintf(fd, " Index Active Full Partial Empty Recent Ready\n");
- for (uint32_t i = 0; i < FastMixerState::kMaxFastTracks; ++i, trackMask >>= 1) {
- bool isActive = trackMask & 1;
- const FastTrackDump *ftDump = &mTracks[i];
- const FastTrackUnderruns& underruns = ftDump->mUnderruns;
- const char *mostRecent;
- switch (underruns.mBitFields.mMostRecent) {
- case UNDERRUN_FULL:
- mostRecent = "full";
- break;
- case UNDERRUN_PARTIAL:
- mostRecent = "partial";
- break;
- case UNDERRUN_EMPTY:
- mostRecent = "empty";
- break;
- default:
- mostRecent = "?";
- break;
- }
- dprintf(fd, " %5u %6s %4u %7u %5u %7s %5zu\n", i, isActive ? "yes" : "no",
- (underruns.mBitFields.mFull) & UNDERRUN_MASK,
- (underruns.mBitFields.mPartial) & UNDERRUN_MASK,
- (underruns.mBitFields.mEmpty) & UNDERRUN_MASK,
- mostRecent, ftDump->mFramesReady);
- }
-}
-
} // namespace android
diff --git a/services/audioflinger/FastMixerDumpState.cpp b/services/audioflinger/FastMixerDumpState.cpp
new file mode 100644
index 0000000..0ddd908
--- /dev/null
+++ b/services/audioflinger/FastMixerDumpState.cpp
@@ -0,0 +1,252 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "FastMixerDumpState"
+//#define LOG_NDEBUG 0
+
+#include "Configuration.h"
+#ifdef FAST_MIXER_STATISTICS
+#include <cpustats/CentralTendencyStatistics.h>
+#ifdef CPU_FREQUENCY_STATISTICS
+#include <cpustats/ThreadCpuUsage.h>
+#endif
+#endif
+#include <utils/Debug.h>
+#include <utils/Log.h>
+#include "FastMixerDumpState.h"
+
+namespace android {
+
+FastMixerDumpState::FastMixerDumpState(
+#ifdef FAST_MIXER_STATISTICS
+ uint32_t samplingN
+#endif
+ ) : FastThreadDumpState(),
+ mWriteSequence(0), mFramesWritten(0),
+ mNumTracks(0), mWriteErrors(0),
+ mSampleRate(0), mFrameCount(0),
+ mTrackMask(0)
+{
+#ifdef FAST_MIXER_STATISTICS
+ increaseSamplingN(samplingN);
+#endif
+}
+
+#ifdef FAST_MIXER_STATISTICS
+void FastMixerDumpState::increaseSamplingN(uint32_t samplingN)
+{
+ if (samplingN <= mSamplingN || samplingN > kSamplingN || roundup(samplingN) != samplingN) {
+ return;
+ }
+ uint32_t additional = samplingN - mSamplingN;
+ // sample arrays aren't accessed atomically with respect to the bounds,
+ // so clearing reduces chance for dumpsys to read random uninitialized samples
+ memset(&mMonotonicNs[mSamplingN], 0, sizeof(mMonotonicNs[0]) * additional);
+ memset(&mLoadNs[mSamplingN], 0, sizeof(mLoadNs[0]) * additional);
+#ifdef CPU_FREQUENCY_STATISTICS
+ memset(&mCpukHz[mSamplingN], 0, sizeof(mCpukHz[0]) * additional);
+#endif
+ mSamplingN = samplingN;
+}
+#endif
+
+FastMixerDumpState::~FastMixerDumpState()
+{
+}
+
+// helper function called by qsort()
+static int compare_uint32_t(const void *pa, const void *pb)
+{
+ uint32_t a = *(const uint32_t *)pa;
+ uint32_t b = *(const uint32_t *)pb;
+ if (a < b) {
+ return -1;
+ } else if (a > b) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+void FastMixerDumpState::dump(int fd) const
+{
+ if (mCommand == FastMixerState::INITIAL) {
+ dprintf(fd, " FastMixer not initialized\n");
+ return;
+ }
+#define COMMAND_MAX 32
+ char string[COMMAND_MAX];
+ switch (mCommand) {
+ case FastMixerState::INITIAL:
+ strcpy(string, "INITIAL");
+ break;
+ case FastMixerState::HOT_IDLE:
+ strcpy(string, "HOT_IDLE");
+ break;
+ case FastMixerState::COLD_IDLE:
+ strcpy(string, "COLD_IDLE");
+ break;
+ case FastMixerState::EXIT:
+ strcpy(string, "EXIT");
+ break;
+ case FastMixerState::MIX:
+ strcpy(string, "MIX");
+ break;
+ case FastMixerState::WRITE:
+ strcpy(string, "WRITE");
+ break;
+ case FastMixerState::MIX_WRITE:
+ strcpy(string, "MIX_WRITE");
+ break;
+ default:
+ snprintf(string, COMMAND_MAX, "%d", mCommand);
+ break;
+ }
+ double measuredWarmupMs = (mMeasuredWarmupTs.tv_sec * 1000.0) +
+ (mMeasuredWarmupTs.tv_nsec / 1000000.0);
+ double mixPeriodSec = (double) mFrameCount / (double) mSampleRate;
+ dprintf(fd, " FastMixer command=%s writeSequence=%u framesWritten=%u\n"
+ " numTracks=%u writeErrors=%u underruns=%u overruns=%u\n"
+ " sampleRate=%u frameCount=%zu measuredWarmup=%.3g ms, warmupCycles=%u\n"
+ " mixPeriod=%.2f ms\n",
+ string, mWriteSequence, mFramesWritten,
+ mNumTracks, mWriteErrors, mUnderruns, mOverruns,
+ mSampleRate, mFrameCount, measuredWarmupMs, mWarmupCycles,
+ mixPeriodSec * 1e3);
+#ifdef FAST_MIXER_STATISTICS
+ // find the interval of valid samples
+ uint32_t bounds = mBounds;
+ uint32_t newestOpen = bounds & 0xFFFF;
+ uint32_t oldestClosed = bounds >> 16;
+ uint32_t n = (newestOpen - oldestClosed) & 0xFFFF;
+ if (n > mSamplingN) {
+ ALOGE("too many samples %u", n);
+ n = mSamplingN;
+ }
+ // statistics for monotonic (wall clock) time, thread raw CPU load in time, CPU clock frequency,
+ // and adjusted CPU load in MHz normalized for CPU clock frequency
+ CentralTendencyStatistics wall, loadNs;
+#ifdef CPU_FREQUENCY_STATISTICS
+ CentralTendencyStatistics kHz, loadMHz;
+ uint32_t previousCpukHz = 0;
+#endif
+ // Assuming a normal distribution for cycle times, three standard deviations on either side of
+ // the mean account for 99.73% of the population. So if we take each tail to be 1/1000 of the
+ // sample set, we get 99.8% combined, or close to three standard deviations.
+ static const uint32_t kTailDenominator = 1000;
+ uint32_t *tail = n >= kTailDenominator ? new uint32_t[n] : NULL;
+ // loop over all the samples
+ for (uint32_t j = 0; j < n; ++j) {
+ size_t i = oldestClosed++ & (mSamplingN - 1);
+ uint32_t wallNs = mMonotonicNs[i];
+ if (tail != NULL) {
+ tail[j] = wallNs;
+ }
+ wall.sample(wallNs);
+ uint32_t sampleLoadNs = mLoadNs[i];
+ loadNs.sample(sampleLoadNs);
+#ifdef CPU_FREQUENCY_STATISTICS
+ uint32_t sampleCpukHz = mCpukHz[i];
+ // skip bad kHz samples
+ if ((sampleCpukHz & ~0xF) != 0) {
+ kHz.sample(sampleCpukHz >> 4);
+ if (sampleCpukHz == previousCpukHz) {
+ double megacycles = (double) sampleLoadNs * (double) (sampleCpukHz >> 4) * 1e-12;
+ double adjMHz = megacycles / mixPeriodSec; // _not_ wallNs * 1e9
+ loadMHz.sample(adjMHz);
+ }
+ }
+ previousCpukHz = sampleCpukHz;
+#endif
+ }
+ if (n) {
+ dprintf(fd, " Simple moving statistics over last %.1f seconds:\n",
+ wall.n() * mixPeriodSec);
+ dprintf(fd, " wall clock time in ms per mix cycle:\n"
+ " mean=%.2f min=%.2f max=%.2f stddev=%.2f\n",
+ wall.mean()*1e-6, wall.minimum()*1e-6, wall.maximum()*1e-6,
+ wall.stddev()*1e-6);
+ dprintf(fd, " raw CPU load in us per mix cycle:\n"
+ " mean=%.0f min=%.0f max=%.0f stddev=%.0f\n",
+ loadNs.mean()*1e-3, loadNs.minimum()*1e-3, loadNs.maximum()*1e-3,
+ loadNs.stddev()*1e-3);
+ } else {
+ dprintf(fd, " No FastMixer statistics available currently\n");
+ }
+#ifdef CPU_FREQUENCY_STATISTICS
+ dprintf(fd, " CPU clock frequency in MHz:\n"
+ " mean=%.0f min=%.0f max=%.0f stddev=%.0f\n",
+ kHz.mean()*1e-3, kHz.minimum()*1e-3, kHz.maximum()*1e-3, kHz.stddev()*1e-3);
+ dprintf(fd, " adjusted CPU load in MHz (i.e. normalized for CPU clock frequency):\n"
+ " mean=%.1f min=%.1f max=%.1f stddev=%.1f\n",
+ loadMHz.mean(), loadMHz.minimum(), loadMHz.maximum(), loadMHz.stddev());
+#endif
+ if (tail != NULL) {
+ qsort(tail, n, sizeof(uint32_t), compare_uint32_t);
+ // assume same number of tail samples on each side, left and right
+ uint32_t count = n / kTailDenominator;
+ CentralTendencyStatistics left, right;
+ for (uint32_t i = 0; i < count; ++i) {
+ left.sample(tail[i]);
+ right.sample(tail[n - (i + 1)]);
+ }
+ dprintf(fd, " Distribution of mix cycle times in ms for the tails "
+ "(> ~3 stddev outliers):\n"
+ " left tail: mean=%.2f min=%.2f max=%.2f stddev=%.2f\n"
+ " right tail: mean=%.2f min=%.2f max=%.2f stddev=%.2f\n",
+ left.mean()*1e-6, left.minimum()*1e-6, left.maximum()*1e-6, left.stddev()*1e-6,
+ right.mean()*1e-6, right.minimum()*1e-6, right.maximum()*1e-6,
+ right.stddev()*1e-6);
+ delete[] tail;
+ }
+#endif
+ // The active track mask and track states are updated non-atomically.
+ // So if we relied on isActive to decide whether to display,
+ // then we might display an obsolete track or omit an active track.
+ // Instead we always display all tracks, with an indication
+ // of whether we think the track is active.
+ uint32_t trackMask = mTrackMask;
+ dprintf(fd, " Fast tracks: kMaxFastTracks=%u activeMask=%#x\n",
+ FastMixerState::kMaxFastTracks, trackMask);
+ dprintf(fd, " Index Active Full Partial Empty Recent Ready\n");
+ for (uint32_t i = 0; i < FastMixerState::kMaxFastTracks; ++i, trackMask >>= 1) {
+ bool isActive = trackMask & 1;
+ const FastTrackDump *ftDump = &mTracks[i];
+ const FastTrackUnderruns& underruns = ftDump->mUnderruns;
+ const char *mostRecent;
+ switch (underruns.mBitFields.mMostRecent) {
+ case UNDERRUN_FULL:
+ mostRecent = "full";
+ break;
+ case UNDERRUN_PARTIAL:
+ mostRecent = "partial";
+ break;
+ case UNDERRUN_EMPTY:
+ mostRecent = "empty";
+ break;
+ default:
+ mostRecent = "?";
+ break;
+ }
+ dprintf(fd, " %5u %6s %4u %7u %5u %7s %5zu\n", i, isActive ? "yes" : "no",
+ (underruns.mBitFields.mFull) & UNDERRUN_MASK,
+ (underruns.mBitFields.mPartial) & UNDERRUN_MASK,
+ (underruns.mBitFields.mEmpty) & UNDERRUN_MASK,
+ mostRecent, ftDump->mFramesReady);
+ }
+}
+
+} // android
diff --git a/services/audioflinger/FastMixerDumpState.h b/services/audioflinger/FastMixerDumpState.h
index 1ae191c..f8354dd 100644
--- a/services/audioflinger/FastMixerDumpState.h
+++ b/services/audioflinger/FastMixerDumpState.h
@@ -17,8 +17,10 @@
#ifndef ANDROID_AUDIO_FAST_MIXER_DUMP_STATE_H
#define ANDROID_AUDIO_FAST_MIXER_DUMP_STATE_H
+#include <stdint.h>
#include "Configuration.h"
#include "FastThreadDumpState.h"
+#include "FastMixerState.h"
namespace android {