Audioflinger dumpsys: Use libjsoncpp for json dump

Test: dumpsys media.audio_flinger --json
Bug: 68148948
Change-Id: Ieebe2c52e3613e48a5ec5cbb2b1f167a32d5a47d
gugelfrei
Eric Tan 6 years ago
parent 5b13ff8f66
commit 1882f16c80

@ -21,6 +21,9 @@ LOCAL_SHARED_LIBRARIES := \
libsoundtriggerservice \
libutils
LOCAL_STATIC_LIBRARIES := \
libjsoncpp
# TODO oboeservice is the old folder name for aaudioservice. It will be changed.
LOCAL_C_INCLUDES := \
frameworks/av/services/audioflinger \

@ -42,6 +42,7 @@ LOCAL_SHARED_LIBRARIES := \
LOCAL_STATIC_LIBRARIES := \
libcpustats \
libjsoncpp \
libsndfile \
LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB)

@ -58,6 +58,8 @@
#include <audio_utils/primitives.h>
#include <json/json.h>
#include <powermanager/PowerManager.h>
#include <media/IMediaLogService.h>
@ -440,8 +442,11 @@ status_t AudioFlinger::dump(int fd, const Vector<String16>& args)
const bool formatJson = std::any_of(args.begin(), args.end(),
[](const String16 &arg) { return arg == String16("--json"); });
if (formatJson) {
Json::Value root = getJsonDump();
Json::FastWriter writer;
std::string rootStr = writer.write(root);
// XXX consider buffering if the string happens to be too long.
dprintf(fd, "%s", getJsonString().c_str());
dprintf(fd, "%s", rootStr.c_str());
return NO_ERROR;
}
@ -556,34 +561,30 @@ status_t AudioFlinger::dump(int fd, const Vector<String16>& args)
return NO_ERROR;
}
std::string AudioFlinger::getJsonString()
Json::Value AudioFlinger::getJsonDump()
{
std::string jsonStr = "{\n";
Json::Value root(Json::objectValue);
const bool locked = dumpTryLock(mLock);
// failed to lock - AudioFlinger is probably deadlocked
if (!locked) {
jsonStr += " \"deadlock_message\": ";
jsonStr += kDeadlockedString;
jsonStr += ",\n";
root["deadlock_message"] = kDeadlockedString;
}
// FIXME risky to access data structures without a lock held?
jsonStr += " \"Playback_Threads\": [\n";
Json::Value playbackThreads = Json::arrayValue;
// dump playback threads
for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
if (i != 0) {
jsonStr += ",\n";
}
jsonStr += mPlaybackThreads.valueAt(i)->getJsonString();
playbackThreads.append(mPlaybackThreads.valueAt(i)->getJsonDump());
}
jsonStr += "\n ]\n}\n";
if (locked) {
mLock.unlock();
}
return jsonStr;
root["playback_threads"] = playbackThreads;
return root;
}
sp<AudioFlinger::Client> AudioFlinger::registerPid(pid_t pid)

@ -79,6 +79,7 @@
#include <powermanager/IPowerManager.h>
#include <json/json.h>
#include <media/nblog/NBLog.h>
#include <private/media/AudioEffectShared.h>
#include <private/media/AudioTrackShared.h>
@ -114,7 +115,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();
Json::Value getJsonDump();
// IAudioFlinger interface, in binder opcode order
virtual sp<IAudioTrack> createTrack(const CreateTrackInput& input,

@ -24,6 +24,7 @@
#include <cpustats/ThreadCpuUsage.h>
#endif
#endif
#include <json/json.h>
#include <string>
#include <utils/Debug.h>
#include <utils/Log.h>
@ -205,14 +206,13 @@ 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
Json::Value FastMixerDumpState::getJsonDump() const
{
Json::Value root(Json::objectValue);
if (mCommand == FastMixerState::INITIAL) {
return " {\n \"status\": \"uninitialized\"\n }";
root["status"] = "uninitialized";
return root;
}
std::string jsonStr = " {\n";
#ifdef FAST_THREAD_STATISTICS
// find the interval of valid samples
const uint32_t bounds = mBounds;
@ -230,31 +230,25 @@ std::string FastMixerDumpState::getJsonString() const
}
// 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\":[";
Json::Value jsonWall(Json::arrayValue);
Json::Value jsonLoadNs(Json::arrayValue);
// 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);
jsonWall.append(wallNs);
uint32_t sampleLoadNs = mLoadNs[i];
jsonLoadNsStr += std::to_string(sampleLoadNs);
jsonLoadNs.append(sampleLoadNs);
}
jsonWallStr += ']';
jsonLoadNsStr += ']';
if (n) {
jsonStr += jsonWallStr + ",\n" + jsonLoadNsStr + "\n";
root["wall_clock_time_ns"] = jsonWall;
root["raw_cpu_load_ns"] = jsonLoadNs;
root["status"] = "ok";
} else {
//dprintf(fd, " No FastMixer statistics available currently\n");
root["status"] = "unavailable";
}
#endif
jsonStr += " }";
return jsonStr;
return root;
}
} // android

@ -20,6 +20,7 @@
#include <stdint.h>
#include <string>
#include <audio_utils/TimestampVerifier.h>
#include <json/json.h>
#include "Configuration.h"
#include "FastThreadDumpState.h"
#include "FastMixerState.h"
@ -67,7 +68,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
Json::Value getJsonDump() 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()

@ -42,6 +42,7 @@
#include <audio_utils/primitives.h>
#include <audio_utils/format.h>
#include <audio_utils/minifloat.h>
#include <json/json.h>
#include <system/audio_effects/effect_ns.h>
#include <system/audio_effects/effect_aec.h>
#include <system/audio.h>
@ -1763,9 +1764,9 @@ void AudioFlinger::PlaybackThread::dump(int fd, const Vector<String16>& args)
mLocalLog.dump(fd, " " /* prefix */, 40 /* lines */);
}
std::string AudioFlinger::PlaybackThread::getJsonString() const
Json::Value AudioFlinger::PlaybackThread::getJsonDump() const
{
return "{}";
return Json::Value(Json::objectValue);
}
void AudioFlinger::PlaybackThread::dumpTracks(int fd, const Vector<String16>& args __unused)
@ -5141,14 +5142,20 @@ void AudioFlinger::MixerThread::dumpInternals(int fd, const Vector<String16>& ar
}
}
std::string AudioFlinger::MixerThread::getJsonString() const
Json::Value AudioFlinger::MixerThread::getJsonDump() const
{
// Make a non-atomic copy of fast mixer dump state so it won't change underneath us
// while we are dumping it. It may be inconsistent, but it won't mutate!
// This is a large object so we place it on the heap.
// FIXME 25972958: Need an intelligent copy constructor that does not touch unused pages.
return std::unique_ptr<FastMixerDumpState>(new FastMixerDumpState(mFastMixerDumpState))
->getJsonString();
Json::Value root;
if (hasFastMixer()) {
// Make a non-atomic copy of fast mixer dump state so it won't change underneath us
// while we are dumping it. It may be inconsistent, but it won't mutate!
// This is a large object so we place it on the heap.
// FIXME 25972958: Need an intelligent copy constructor that does not touch unused pages.
const std::unique_ptr<FastMixerDumpState> copy(new FastMixerDumpState(mFastMixerDumpState));
root["fastmixer_stats"] = copy->getJsonDump();
} else {
root["fastmixer_stats"] = "no_fastmixer";
}
return root;
}
uint32_t AudioFlinger::MixerThread::idleSleepTimeUs() const

@ -662,7 +662,7 @@ public:
void dump(int fd, const Vector<String16>& args);
// returns a string of audio performance related data in JSON format.
virtual std::string getJsonString() const;
virtual Json::Value getJsonDump() const;
// Thread virtuals
virtual bool threadLoop();
@ -1108,7 +1108,7 @@ public:
virtual bool checkForNewParameter_l(const String8& keyValuePair,
status_t& status);
virtual void dumpInternals(int fd, const Vector<String16>& args);
std::string getJsonString() const override;
Json::Value getJsonDump() const override;
virtual bool isTrackAllowed_l(
audio_channel_mask_t channelMask, audio_format_t format,

Loading…
Cancel
Save