Loading media/libnblog/PerformanceAnalysis.cpp +3 −80 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ #include <sys/prctl.h> #include <time.h> #include <new> #include <audio_utils/LogPlot.h> #include <audio_utils/roundup.h> #include <media/nblog/NBLog.h> #include <media/nblog/PerformanceAnalysis.h> Loading Loading @@ -208,27 +209,6 @@ bool PerformanceAnalysis::detectAndStoreOutlier(const msInterval diffMs) { return isOutlier; } static int widthOf(int x) { int width = 0; if (x < 0) { width++; x = x == INT_MIN ? INT_MAX : -x; } // assert (x >= 0) do { ++width; x /= 10; } while (x > 0); return width; } // computes the column width required for a specific histogram value inline int numberWidth(double number, int leftPadding) { // Added values account for whitespaces needed around numbers, and for the // dot and decimal digit not accounted for by widthOf return std::max(std::max(widthOf(static_cast<int>(number)) + 3, 2), leftPadding + 1); } // rounds value to precision based on log-distance from mean __attribute__((no_sanitize("signed-integer-overflow"))) inline double logRound(double x, double mean) { Loading Loading @@ -281,65 +261,8 @@ void PerformanceAnalysis::reportPerformance(String8 *body, int author, log_hash_ static_cast<long long>(hash), static_cast<long long>(startingTs)); static const char * const kLabel = "ms"; auto it = buckets.begin(); double maxDelta = it->first; int maxCount = it->second; // Compute maximum values while (++it != buckets.end()) { if (it->first > maxDelta) { maxDelta = it->first; } if (it->second > maxCount) { maxCount = it->second; } } int height = log2(maxCount) + 1; // maxCount > 0, safe to call log2 const int leftPadding = widthOf(1 << height); const int bucketWidth = numberWidth(maxDelta, leftPadding); int scalingFactor = 1; // scale data if it exceeds maximum height if (height > maxHeight) { scalingFactor = (height + maxHeight) / maxHeight; height /= scalingFactor; } body->appendFormat("%s", title); // write histogram label line with bucket values body->appendFormat("\n%s", " "); body->appendFormat("%*s", leftPadding, " "); for (auto const &x : buckets) { const int colWidth = numberWidth(x.first, leftPadding); body->appendFormat("%*d", colWidth, x.second); } // write histogram ascii art // underscores and spaces length corresponds to maximum width of histogram static const int kLen = 200; static const std::string underscores(kLen, '_'); static const std::string spaces(kLen, ' '); body->appendFormat("\n%s", " "); for (int row = height * scalingFactor; row >= 0; row -= scalingFactor) { const int value = 1 << row; body->appendFormat("%.*s", leftPadding, spaces.c_str()); for (auto const &x : buckets) { const int colWidth = numberWidth(x.first, leftPadding); body->appendFormat("%.*s%s", colWidth - 1, spaces.c_str(), x.second < value ? " " : "|"); } body->appendFormat("\n%s", " "); } // print x-axis const int columns = static_cast<int>(buckets.size()); body->appendFormat("%*c", leftPadding, ' '); body->appendFormat("%.*s", (columns + 1) * bucketWidth, underscores.c_str()); body->appendFormat("\n%s", " "); // write footer with bucket labels body->appendFormat("%*s", leftPadding, " "); for (auto const &x : buckets) { const int colWidth = numberWidth(x.first, leftPadding); body->appendFormat("%*.*f", colWidth, 1, x.first); } body->appendFormat("%.*s%s\n", bucketWidth, spaces.c_str(), kLabel); body->appendFormat("%s", audio_utils_plot_histogram(buckets, title, kLabel, maxHeight).c_str()); // Now report glitches body->appendFormat("\ntime elapsed between glitches and glitch timestamps:\n"); Loading media/libnblog/include/media/nblog/PerformanceAnalysis.h +2 −0 Original line number Diff line number Diff line Loading @@ -25,6 +25,8 @@ namespace android { class String8; namespace ReportPerformance { class PerformanceAnalysis; Loading media/libnblog/include/media/nblog/ReportPerformance.h +0 −3 Original line number Diff line number Diff line Loading @@ -23,9 +23,6 @@ namespace android { // The String8 class is used by reportPerformance function class String8; namespace ReportPerformance { constexpr int kMsPerSec = 1000; Loading services/audioflinger/Threads.cpp +8 −8 Original line number Diff line number Diff line Loading @@ -3354,7 +3354,7 @@ bool AudioFlinger::PlaybackThread::threadLoop() continue; } if ((!mActiveTracks.size() && systemTime() > mStandbyTimeNs) || if ((mActiveTracks.isEmpty() && systemTime() > mStandbyTimeNs) || isSuspended()) { // put audio hardware into standby after short delay if (shouldStandby_l()) { Loading @@ -3368,7 +3368,7 @@ bool AudioFlinger::PlaybackThread::threadLoop() mStandby = true; } if (!mActiveTracks.size() && mConfigEvents.isEmpty()) { if (mActiveTracks.isEmpty() && mConfigEvents.isEmpty()) { // we're about to wait, flush the binder command buffer IPCThreadState::self()->flushCommands(); Loading Loading @@ -6649,7 +6649,7 @@ reacquire_wakelock: } // sleep if there are no active tracks to process if (activeTracks.size() == 0) { if (activeTracks.isEmpty()) { if (sleepUs == 0) { sleepUs = kRecordThreadSleepUs; } Loading Loading @@ -7443,7 +7443,7 @@ void AudioFlinger::RecordThread::dumpInternals(int fd, const Vector<String16>& a audio_input_flags_t flags = input != NULL ? input->flags : AUDIO_INPUT_FLAG_NONE; dprintf(fd, " AudioStreamIn: %p flags %#x (%s)\n", input, flags, inputFlagsToString(flags).c_str()); if (mActiveTracks.size() == 0) { if (mActiveTracks.isEmpty()) { dprintf(fd, " No active record clients\n"); } Loading Loading @@ -7909,7 +7909,7 @@ sp<StreamHalInterface> AudioFlinger::RecordThread::stream() const status_t AudioFlinger::RecordThread::addEffectChain_l(const sp<EffectChain>& chain) { // only one chain per input thread if (mEffectChains.size() != 0) { if (!mEffectChains.isEmpty()) { ALOGW("addEffectChain_l() already one chain %p on thread %p", chain.get(), this); return INVALID_OPERATION; } Loading Loading @@ -8245,7 +8245,7 @@ status_t AudioFlinger::MmapThread::start(const AudioClient& client, // abort if start is rejected by audio policy manager if (ret != NO_ERROR) { ALOGE("%s: error start rejected by AudioPolicyManager = %d", __FUNCTION__, ret); if (mActiveTracks.size() != 0) { if (!mActiveTracks.isEmpty()) { mLock.unlock(); if (isOutput()) { AudioSystem::releaseOutput(portId); Loading Loading @@ -8346,7 +8346,7 @@ status_t AudioFlinger::MmapThread::standby() if (mHalStream == 0) { return NO_INIT; } if (mActiveTracks.size() != 0) { if (!mActiveTracks.isEmpty()) { return INVALID_OPERATION; } mHalStream->standby(); Loading Loading @@ -8784,7 +8784,7 @@ void AudioFlinger::MmapThread::dumpInternals(int fd, const Vector<String16>& arg dprintf(fd, " Attributes: content type %d usage %d source %d\n", mAttr.content_type, mAttr.usage, mAttr.source); dprintf(fd, " Session: %d port Id: %d\n", mSessionId, mPortId); if (mActiveTracks.size() == 0) { if (mActiveTracks.isEmpty()) { dprintf(fd, " No active clients\n"); } } Loading services/audioflinger/Threads.h +3 −0 Original line number Diff line number Diff line Loading @@ -555,6 +555,9 @@ protected: size_t size() const { return mActiveTracks.size(); } bool isEmpty() const { return mActiveTracks.isEmpty(); } ssize_t indexOf(const sp<T>& item) { return mActiveTracks.indexOf(item); } Loading Loading
media/libnblog/PerformanceAnalysis.cpp +3 −80 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ #include <sys/prctl.h> #include <time.h> #include <new> #include <audio_utils/LogPlot.h> #include <audio_utils/roundup.h> #include <media/nblog/NBLog.h> #include <media/nblog/PerformanceAnalysis.h> Loading Loading @@ -208,27 +209,6 @@ bool PerformanceAnalysis::detectAndStoreOutlier(const msInterval diffMs) { return isOutlier; } static int widthOf(int x) { int width = 0; if (x < 0) { width++; x = x == INT_MIN ? INT_MAX : -x; } // assert (x >= 0) do { ++width; x /= 10; } while (x > 0); return width; } // computes the column width required for a specific histogram value inline int numberWidth(double number, int leftPadding) { // Added values account for whitespaces needed around numbers, and for the // dot and decimal digit not accounted for by widthOf return std::max(std::max(widthOf(static_cast<int>(number)) + 3, 2), leftPadding + 1); } // rounds value to precision based on log-distance from mean __attribute__((no_sanitize("signed-integer-overflow"))) inline double logRound(double x, double mean) { Loading Loading @@ -281,65 +261,8 @@ void PerformanceAnalysis::reportPerformance(String8 *body, int author, log_hash_ static_cast<long long>(hash), static_cast<long long>(startingTs)); static const char * const kLabel = "ms"; auto it = buckets.begin(); double maxDelta = it->first; int maxCount = it->second; // Compute maximum values while (++it != buckets.end()) { if (it->first > maxDelta) { maxDelta = it->first; } if (it->second > maxCount) { maxCount = it->second; } } int height = log2(maxCount) + 1; // maxCount > 0, safe to call log2 const int leftPadding = widthOf(1 << height); const int bucketWidth = numberWidth(maxDelta, leftPadding); int scalingFactor = 1; // scale data if it exceeds maximum height if (height > maxHeight) { scalingFactor = (height + maxHeight) / maxHeight; height /= scalingFactor; } body->appendFormat("%s", title); // write histogram label line with bucket values body->appendFormat("\n%s", " "); body->appendFormat("%*s", leftPadding, " "); for (auto const &x : buckets) { const int colWidth = numberWidth(x.first, leftPadding); body->appendFormat("%*d", colWidth, x.second); } // write histogram ascii art // underscores and spaces length corresponds to maximum width of histogram static const int kLen = 200; static const std::string underscores(kLen, '_'); static const std::string spaces(kLen, ' '); body->appendFormat("\n%s", " "); for (int row = height * scalingFactor; row >= 0; row -= scalingFactor) { const int value = 1 << row; body->appendFormat("%.*s", leftPadding, spaces.c_str()); for (auto const &x : buckets) { const int colWidth = numberWidth(x.first, leftPadding); body->appendFormat("%.*s%s", colWidth - 1, spaces.c_str(), x.second < value ? " " : "|"); } body->appendFormat("\n%s", " "); } // print x-axis const int columns = static_cast<int>(buckets.size()); body->appendFormat("%*c", leftPadding, ' '); body->appendFormat("%.*s", (columns + 1) * bucketWidth, underscores.c_str()); body->appendFormat("\n%s", " "); // write footer with bucket labels body->appendFormat("%*s", leftPadding, " "); for (auto const &x : buckets) { const int colWidth = numberWidth(x.first, leftPadding); body->appendFormat("%*.*f", colWidth, 1, x.first); } body->appendFormat("%.*s%s\n", bucketWidth, spaces.c_str(), kLabel); body->appendFormat("%s", audio_utils_plot_histogram(buckets, title, kLabel, maxHeight).c_str()); // Now report glitches body->appendFormat("\ntime elapsed between glitches and glitch timestamps:\n"); Loading
media/libnblog/include/media/nblog/PerformanceAnalysis.h +2 −0 Original line number Diff line number Diff line Loading @@ -25,6 +25,8 @@ namespace android { class String8; namespace ReportPerformance { class PerformanceAnalysis; Loading
media/libnblog/include/media/nblog/ReportPerformance.h +0 −3 Original line number Diff line number Diff line Loading @@ -23,9 +23,6 @@ namespace android { // The String8 class is used by reportPerformance function class String8; namespace ReportPerformance { constexpr int kMsPerSec = 1000; Loading
services/audioflinger/Threads.cpp +8 −8 Original line number Diff line number Diff line Loading @@ -3354,7 +3354,7 @@ bool AudioFlinger::PlaybackThread::threadLoop() continue; } if ((!mActiveTracks.size() && systemTime() > mStandbyTimeNs) || if ((mActiveTracks.isEmpty() && systemTime() > mStandbyTimeNs) || isSuspended()) { // put audio hardware into standby after short delay if (shouldStandby_l()) { Loading @@ -3368,7 +3368,7 @@ bool AudioFlinger::PlaybackThread::threadLoop() mStandby = true; } if (!mActiveTracks.size() && mConfigEvents.isEmpty()) { if (mActiveTracks.isEmpty() && mConfigEvents.isEmpty()) { // we're about to wait, flush the binder command buffer IPCThreadState::self()->flushCommands(); Loading Loading @@ -6649,7 +6649,7 @@ reacquire_wakelock: } // sleep if there are no active tracks to process if (activeTracks.size() == 0) { if (activeTracks.isEmpty()) { if (sleepUs == 0) { sleepUs = kRecordThreadSleepUs; } Loading Loading @@ -7443,7 +7443,7 @@ void AudioFlinger::RecordThread::dumpInternals(int fd, const Vector<String16>& a audio_input_flags_t flags = input != NULL ? input->flags : AUDIO_INPUT_FLAG_NONE; dprintf(fd, " AudioStreamIn: %p flags %#x (%s)\n", input, flags, inputFlagsToString(flags).c_str()); if (mActiveTracks.size() == 0) { if (mActiveTracks.isEmpty()) { dprintf(fd, " No active record clients\n"); } Loading Loading @@ -7909,7 +7909,7 @@ sp<StreamHalInterface> AudioFlinger::RecordThread::stream() const status_t AudioFlinger::RecordThread::addEffectChain_l(const sp<EffectChain>& chain) { // only one chain per input thread if (mEffectChains.size() != 0) { if (!mEffectChains.isEmpty()) { ALOGW("addEffectChain_l() already one chain %p on thread %p", chain.get(), this); return INVALID_OPERATION; } Loading Loading @@ -8245,7 +8245,7 @@ status_t AudioFlinger::MmapThread::start(const AudioClient& client, // abort if start is rejected by audio policy manager if (ret != NO_ERROR) { ALOGE("%s: error start rejected by AudioPolicyManager = %d", __FUNCTION__, ret); if (mActiveTracks.size() != 0) { if (!mActiveTracks.isEmpty()) { mLock.unlock(); if (isOutput()) { AudioSystem::releaseOutput(portId); Loading Loading @@ -8346,7 +8346,7 @@ status_t AudioFlinger::MmapThread::standby() if (mHalStream == 0) { return NO_INIT; } if (mActiveTracks.size() != 0) { if (!mActiveTracks.isEmpty()) { return INVALID_OPERATION; } mHalStream->standby(); Loading Loading @@ -8784,7 +8784,7 @@ void AudioFlinger::MmapThread::dumpInternals(int fd, const Vector<String16>& arg dprintf(fd, " Attributes: content type %d usage %d source %d\n", mAttr.content_type, mAttr.usage, mAttr.source); dprintf(fd, " Session: %d port Id: %d\n", mSessionId, mPortId); if (mActiveTracks.size() == 0) { if (mActiveTracks.isEmpty()) { dprintf(fd, " No active clients\n"); } } Loading
services/audioflinger/Threads.h +3 −0 Original line number Diff line number Diff line Loading @@ -555,6 +555,9 @@ protected: size_t size() const { return mActiveTracks.size(); } bool isEmpty() const { return mActiveTracks.isEmpty(); } ssize_t indexOf(const sp<T>& item) { return mActiveTracks.indexOf(item); } Loading