Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7b651154 authored by Eric Tan's avatar Eric Tan
Browse files

dumpsys: add --json option to media.audio_flinger.

Currently only extracting audio performance data.

Test: dumpsys media.audio_flinger --json
Bug: 68148948
Change-Id: If207e7e20683dcf8d8d5874417cd7466c78a5df0
parent 8180b74a
Loading
Loading
Loading
Loading
+42 −1
Original line number Diff line number Diff line
@@ -20,9 +20,11 @@
//#define LOG_NDEBUG 0

#include "Configuration.h"
#include <algorithm>    // std::any_of
#include <dirent.h>
#include <math.h>
#include <signal.h>
#include <string>
#include <sys/time.h>
#include <sys/resource.h>

@@ -434,6 +436,15 @@ status_t AudioFlinger::dump(int fd, const Vector<String16>& args)
    if (!dumpAllowed()) {
        dumpPermissionDenial(fd, args);
    } else {
        // XXX This is sort of hacky for now.
        const bool formatJson = std::any_of(args.begin(), args.end(),
                [](const String16 &arg) { return arg == String16("--json"); });
        if (formatJson) {
            // XXX consider buffering if the string happens to be too long.
            dprintf(fd, "%s", getJsonString().c_str());
            return NO_ERROR;
        }

        // get state of hardware lock
        bool hardwareLocked = dumpTryLock(mHardwareLock);
        if (!hardwareLocked) {
@@ -443,7 +454,7 @@ status_t AudioFlinger::dump(int fd, const Vector<String16>& args)
            mHardwareLock.unlock();
        }

        bool locked = dumpTryLock(mLock);
        const bool locked = dumpTryLock(mLock);

        // failed to lock - AudioFlinger is probably deadlocked
        if (!locked) {
@@ -545,6 +556,36 @@ status_t AudioFlinger::dump(int fd, const Vector<String16>& args)
    return NO_ERROR;
}

std::string AudioFlinger::getJsonString()
{
    std::string jsonStr = "{\n";
    const bool locked = dumpTryLock(mLock);

    // failed to lock - AudioFlinger is probably deadlocked
    if (!locked) {
        jsonStr += "    \"deadlock_message\": ";
        jsonStr += kDeadlockedString;
        jsonStr += ",\n";
    }
    // FIXME risky to access data structures without a lock held?

    jsonStr += "  \"Playback_Threads\": [\n";
    // dump playback threads
    for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
        if (i != 0) {
            jsonStr += ",\n";
        }
        jsonStr += mPlaybackThreads.valueAt(i)->getJsonString();
    }
    jsonStr += "\n  ]\n}\n";

    if (locked) {
        mLock.unlock();
    }

    return jsonStr;
}

sp<AudioFlinger::Client> AudioFlinger::registerPid(pid_t pid)
{
    Mutex::Autolock _cl(mClientLock);
+3 −0
Original line number Diff line number Diff line
@@ -23,6 +23,8 @@
#include <mutex>
#include <deque>
#include <map>
#include <memory>
#include <string>
#include <vector>
#include <stdint.h>
#include <sys/types.h>
@@ -111,6 +113,7 @@ public:
    static const char* getServiceName() ANDROID_API { return "media.audio_flinger"; }

    virtual     status_t    dump(int fd, const Vector<String16>& args);
                std::string getJsonString();

    // IAudioFlinger interface, in binder opcode order
    virtual sp<IAudioTrack> createTrack(const CreateTrackInput& input,
+1 −1
Original line number Diff line number Diff line
@@ -27,7 +27,7 @@
//#define AUDIO_WATCHDOG

// uncomment to display CPU load adjusted for CPU frequency
//#define CPU_FREQUENCY_STATISTICS
#define CPU_FREQUENCY_STATISTICS

// uncomment to enable fast threads to take performance samples for later statistical analysis
#define FAST_THREAD_STATISTICS
+56 −3
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@
#include <cpustats/ThreadCpuUsage.h>
#endif
#endif
#include <string>
#include <utils/Debug.h>
#include <utils/Log.h>
#include "FastMixerDumpState.h"
@@ -76,14 +77,14 @@ void FastMixerDumpState::dump(int fd) const
    dprintf(fd, "  FastMixer Timestamp stats: %s\n", mTimestampVerifier.toString().c_str());
#ifdef FAST_THREAD_STATISTICS
    // find the interval of valid samples
    uint32_t bounds = mBounds;
    uint32_t newestOpen = bounds & 0xFFFF;
    const uint32_t bounds = mBounds;
    const uint32_t newestOpen = bounds & 0xFFFF;
    uint32_t oldestClosed = bounds >> 16;

    //uint32_t n = (newestOpen - oldestClosed) & 0xFFFF;
    uint32_t n;
    __builtin_sub_overflow(newestOpen, oldestClosed, &n);
    n = n & 0xFFFF;
    n &= 0xFFFF;

    if (n > mSamplingN) {
        ALOGE("too many samples %u", n);
@@ -204,4 +205,56 @@ void FastMixerDumpState::dump(int fd) const
    }
}

// TODO get rid of extraneous lines and use better key names.
// TODO may go back to using a library to do the json formatting.
std::string FastMixerDumpState::getJsonString() const
{
    if (mCommand == FastMixerState::INITIAL) {
        return "    {\n      \"status\": \"uninitialized\"\n    }";
    }
    std::string jsonStr = "    {\n";
#ifdef FAST_THREAD_STATISTICS
    // find the interval of valid samples
    const uint32_t bounds = mBounds;
    const uint32_t newestOpen = bounds & 0xFFFF;
    uint32_t oldestClosed = bounds >> 16;

    //uint32_t n = (newestOpen - oldestClosed) & 0xFFFF;
    uint32_t n;
    __builtin_sub_overflow(newestOpen, oldestClosed, &n);
    n &= 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
    std::string jsonWallStr = "      \"wall_clock_time\":[";
    std::string jsonLoadNsStr = "      \"raw_cpu_load\":[";
    // 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 (j != 0) {
            jsonWallStr += ',';
            jsonLoadNsStr += ',';
        }
        /* jsonObject["wall"].append(wallNs); */
        jsonWallStr += std::to_string(wallNs);
        uint32_t sampleLoadNs = mLoadNs[i];
        jsonLoadNsStr += std::to_string(sampleLoadNs);
    }
    jsonWallStr += ']';
    jsonLoadNsStr += ']';
    if (n) {
        jsonStr += jsonWallStr + ",\n" + jsonLoadNsStr + "\n";
    } else {
        //dprintf(fd, "  No FastMixer statistics available currently\n");
    }
#endif
    jsonStr += "    }";
    return jsonStr;
}

}   // android
+3 −1
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
#define ANDROID_AUDIO_FAST_MIXER_DUMP_STATE_H

#include <stdint.h>
#include <string>
#include <audio_utils/TimestampVerifier.h>
#include "Configuration.h"
#include "FastThreadDumpState.h"
@@ -66,6 +67,7 @@ struct FastMixerDumpState : FastThreadDumpState {
    /*virtual*/ ~FastMixerDumpState();

    void dump(int fd) const;             // should only be called on a stable copy, not the original
    std::string getJsonString() const;   // should only be called on a stable copy, not the original

    double   mLatencyMs = 0.;   // measured latency, default of 0 if no valid timestamp read.
    uint32_t mWriteSequence;    // incremented before and after each write()
Loading