diff options
author | Andy Hung <hunga@google.com> | 2019-02-21 15:51:44 -0800 |
---|---|---|
committer | Andy Hung <hunga@google.com> | 2019-03-06 14:50:35 -0800 |
commit | d097981afa129353c42660869e284ae1784506c2 (patch) | |
tree | c035d2a90097094a87c153fe97b3b5b5ba766c7a /services/audioflinger/Threads.cpp | |
parent | f03cb213d22b238cbd0b72ded36048f0549f921f (diff) | |
download | frameworks_av-d097981afa129353c42660869e284ae1784506c2.tar.gz frameworks_av-d097981afa129353c42660869e284ae1784506c2.tar.bz2 frameworks_av-d097981afa129353c42660869e284ae1784506c2.zip |
AudioFlinger: Send Thread statistics to mediametrics
Unify with AudioRecord and AudioTrack mediametrics.
Test: mediametrics dumpsys after record, playback
Test: CTS Audio(Record|Track)Test#testMediaMetrics
Bug: 114112762
Change-Id: I6eb554cbf6ff760f9dea568abd3cde82366b51a7
Diffstat (limited to 'services/audioflinger/Threads.cpp')
-rw-r--r-- | services/audioflinger/Threads.cpp | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp index 8f181a4038..468676af00 100644 --- a/services/audioflinger/Threads.cpp +++ b/services/audioflinger/Threads.cpp @@ -488,6 +488,8 @@ AudioFlinger::ThreadBase::~ThreadBase() sp<IBinder> binder = IInterface::asBinder(mPowerManager); binder->unlinkToDeath(mDeathRecipient); } + + sendStatistics(true /* force */); } status_t AudioFlinger::ThreadBase::readyToRun() @@ -571,6 +573,15 @@ void AudioFlinger::ThreadBase::sendIoConfigEvent(audio_io_config_event event, pi // sendIoConfigEvent_l() must be called with ThreadBase::mLock held void AudioFlinger::ThreadBase::sendIoConfigEvent_l(audio_io_config_event event, pid_t pid) { + // The audio statistics history is exponentially weighted to forget events + // about five or more seconds in the past. In order to have + // crisper statistics for mediametrics, we reset the statistics on + // an IoConfigEvent, to reflect different properties for a new device. + mIoJitterMs.reset(); + mLatencyMs.reset(); + mProcessTimeMs.reset(); + mTimestampVerifier.discontinuity(); + sp<ConfigEvent> configEvent = (ConfigEvent *)new IoConfigEvent(event, pid); sendConfigEvent_l(configEvent); } @@ -1651,6 +1662,65 @@ void AudioFlinger::ThreadBase::broadcast_l() mWaitWorkCV.broadcast(); } +// Call only from threadLoop() or when it is idle. +// Do not call from high performance code as this may do binder rpc to the MediaMetrics service. +void AudioFlinger::ThreadBase::sendStatistics(bool force) +{ + // Do not log if we have no stats. + // We choose the timestamp verifier because it is the most likely item to be present. + const int64_t nstats = mTimestampVerifier.getN() - mLastRecordedTimestampVerifierN; + if (nstats == 0) { + return; + } + + // Don't log more frequently than once per 12 hours. + // We use BOOTTIME to include suspend time. + const int64_t timeNs = systemTime(SYSTEM_TIME_BOOTTIME); + const int64_t sinceNs = timeNs - mLastRecordedTimeNs; // ok if mLastRecordedTimeNs = 0 + if (!force && sinceNs <= 12 * NANOS_PER_HOUR) { + return; + } + + mLastRecordedTimestampVerifierN = mTimestampVerifier.getN(); + mLastRecordedTimeNs = timeNs; + + std::unique_ptr<MediaAnalyticsItem> item(MediaAnalyticsItem::create("audiothread")); + +#define MM_PREFIX "android.media.audiothread." // avoid cut-n-paste errors. + + // thread configuration + item->setInt32(MM_PREFIX "id", (int32_t)mId); // IO handle + // item->setInt32(MM_PREFIX "portId", (int32_t)mPortId); + item->setCString(MM_PREFIX "type", threadTypeToString(mType)); + item->setInt32(MM_PREFIX "sampleRate", (int32_t)mSampleRate); + item->setInt64(MM_PREFIX "channelMask", (int64_t)mChannelMask); + item->setCString(MM_PREFIX "encoding", toString(mFormat).c_str()); + item->setInt32(MM_PREFIX "frameCount", (int32_t)mFrameCount); + item->setCString(MM_PREFIX "outDevice", toString(mOutDevice).c_str()); + item->setCString(MM_PREFIX "inDevice", toString(mInDevice).c_str()); + + // thread statistics + if (mIoJitterMs.getN() > 0) { + item->setDouble(MM_PREFIX "ioJitterMs.mean", mIoJitterMs.getMean()); + item->setDouble(MM_PREFIX "ioJitterMs.std", mIoJitterMs.getStdDev()); + } + if (mProcessTimeMs.getN() > 0) { + item->setDouble(MM_PREFIX "processTimeMs.mean", mProcessTimeMs.getMean()); + item->setDouble(MM_PREFIX "processTimeMs.std", mProcessTimeMs.getStdDev()); + } + const auto tsjitter = mTimestampVerifier.getJitterMs(); + if (tsjitter.getN() > 0) { + item->setDouble(MM_PREFIX "timestampJitterMs.mean", tsjitter.getMean()); + item->setDouble(MM_PREFIX "timestampJitterMs.std", tsjitter.getStdDev()); + } + if (mLatencyMs.getN() > 0) { + item->setDouble(MM_PREFIX "latencyMs.mean", mLatencyMs.getMean()); + item->setDouble(MM_PREFIX "latencyMs.std", mLatencyMs.getStdDev()); + } + + item->selfrecord(); +} + // ---------------------------------------------------------------------------- // Playback // ---------------------------------------------------------------------------- @@ -3447,6 +3517,7 @@ bool AudioFlinger::PlaybackThread::threadLoop() LOG_AUDIO_STATE(); } mStandby = true; + sendStatistics(false /* force */); } if (mActiveTracks.isEmpty() && mConfigEvents.isEmpty()) { |