Loading services/audioflinger/AudioFlinger.cpp +42 −1 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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) { Loading @@ -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) { Loading Loading @@ -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); Loading services/audioflinger/AudioFlinger.h +3 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,8 @@ #include <mutex> #include <deque> #include <map> #include <memory> #include <string> #include <vector> #include <stdint.h> #include <sys/types.h> Loading Loading @@ -112,6 +114,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, Loading services/audioflinger/Configuration.h +1 −1 Original line number Diff line number Diff line Loading @@ -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 Loading services/audioflinger/FastMixerDumpState.cpp +56 −3 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ #include <cpustats/ThreadCpuUsage.h> #endif #endif #include <string> #include <utils/Debug.h> #include <utils/Log.h> #include "FastMixerDumpState.h" Loading Loading @@ -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); Loading Loading @@ -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 services/audioflinger/FastMixerDumpState.h +3 −1 Original line number Diff line number Diff line Loading @@ -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" Loading Loading @@ -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 Loading
services/audioflinger/AudioFlinger.cpp +42 −1 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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) { Loading @@ -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) { Loading Loading @@ -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); Loading
services/audioflinger/AudioFlinger.h +3 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,8 @@ #include <mutex> #include <deque> #include <map> #include <memory> #include <string> #include <vector> #include <stdint.h> #include <sys/types.h> Loading Loading @@ -112,6 +114,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, Loading
services/audioflinger/Configuration.h +1 −1 Original line number Diff line number Diff line Loading @@ -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 Loading
services/audioflinger/FastMixerDumpState.cpp +56 −3 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ #include <cpustats/ThreadCpuUsage.h> #endif #endif #include <string> #include <utils/Debug.h> #include <utils/Log.h> #include "FastMixerDumpState.h" Loading Loading @@ -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); Loading Loading @@ -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
services/audioflinger/FastMixerDumpState.h +3 −1 Original line number Diff line number Diff line Loading @@ -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" Loading Loading @@ -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