Loading media/utils/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -49,6 +49,7 @@ cc_library { "libcutils", "liblog", "libutils", "libutilscallstack", "libhidlbase", "libpermission", "android.hardware.graphics.bufferqueue@1.0", Loading media/utils/TimeCheck.cpp +18 −2 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ #include <optional> #include <android-base/logging.h> #include <audio_utils/clock.h> #include <mediautils/EventLog.h> #include <mediautils/MethodStatistics.h> Loading Loading @@ -199,8 +200,23 @@ void TimeCheck::TimeCheckHandler::onTimeout() const } LOG_EVENT_STRING(LOGTAG_AUDIO_BINDER_TIMEOUT, tag.c_str()); LOG_ALWAYS_FATAL("TimeCheck timeout for %s scheduled %s on thread %d\n%s", tag.c_str(), formatTime(startTime).c_str(), tid, summary.c_str()); // Create abort message string - caution: this can be very large. const std::string abortMessage = std::string("TimeCheck timeout for ") .append(tag) .append(" scheduled ").append(formatTime(startTime)) .append(" on thread ").append(std::to_string(tid)).append("\n") .append(summary); // Note: LOG_ALWAYS_FATAL limits the size of the string - per log/log.h: // Log message text may be truncated to less than an // implementation-specific limit (1023 bytes). // // Here, we send the string through android-base/logging.h LOG() // to avoid the size limitation. LOG(FATAL) does an abort whereas // LOG(FATAL_WITHOUT_ABORT) does not abort. LOG(FATAL) << abortMessage; } // Automatically create a TimeCheck class for a class and method. Loading media/utils/TimerThread.cpp +24 −1 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ #include <vector> #include <mediautils/TimerThread.h> #include <utils/CallStack.h> #include <utils/ThreadDefs.h> namespace android::mediautils { Loading Loading @@ -68,6 +69,19 @@ std::string TimerThread::toString(size_t retiredCount) const { if (!analysis.summary.empty()) { analysisSummary = std::string("\nanalysis [ ").append(analysis.summary).append(" ]"); } std::string timeoutStack; if (analysis.timeoutTid != -1) { timeoutStack = std::string("\ntimeout(") .append(std::to_string(analysis.timeoutTid)).append(") callstack [\n") .append(tidCallStackString(analysis.timeoutTid)).append("]"); } std::string blockedStack; if (analysis.HALBlockedTid != -1) { blockedStack = std::string("\nblocked(") .append(std::to_string(analysis.HALBlockedTid)).append(") callstack [\n") .append(tidCallStackString(analysis.HALBlockedTid)).append("]"); } return std::string("now ") .append(formatTime(std::chrono::system_clock::now())) .append(analysisSummary) Loading @@ -77,7 +91,9 @@ std::string TimerThread::toString(size_t retiredCount) const { .append(requestsToString(pendingRequests)) .append(" ]\nretired [ ") .append(requestsToString(retiredRequests)) .append(" ]"); .append(" ]") .append(timeoutStack) .append(blockedStack); } // A HAL method is where the substring "Hidl" is in the class name. Loading Loading @@ -197,6 +213,13 @@ std::string TimerThread::timeoutToString(size_t n) const { return requestsToString(timeoutRequests); } /* static */ std::string TimerThread::tidCallStackString(pid_t tid) { CallStack cs{}; cs.update(0 /* ignoreDepth */, tid); return cs.toString().c_str(); } std::string TimerThread::Request::toString() const { const auto scheduledString = formatTime(scheduled); const auto deadlineString = formatTime(deadline); Loading media/utils/include/mediautils/TimerThread.h +5 −0 Original line number Diff line number Diff line Loading @@ -125,6 +125,11 @@ class TimerThread { return s; } /** * Returns callstack of tid as a string. */ static std::string tidCallStackString(pid_t tid); private: // To minimize movement of data, we pass around shared_ptrs to Requests. // These are allocated and deallocated outside of the lock. Loading Loading
media/utils/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -49,6 +49,7 @@ cc_library { "libcutils", "liblog", "libutils", "libutilscallstack", "libhidlbase", "libpermission", "android.hardware.graphics.bufferqueue@1.0", Loading
media/utils/TimeCheck.cpp +18 −2 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ #include <optional> #include <android-base/logging.h> #include <audio_utils/clock.h> #include <mediautils/EventLog.h> #include <mediautils/MethodStatistics.h> Loading Loading @@ -199,8 +200,23 @@ void TimeCheck::TimeCheckHandler::onTimeout() const } LOG_EVENT_STRING(LOGTAG_AUDIO_BINDER_TIMEOUT, tag.c_str()); LOG_ALWAYS_FATAL("TimeCheck timeout for %s scheduled %s on thread %d\n%s", tag.c_str(), formatTime(startTime).c_str(), tid, summary.c_str()); // Create abort message string - caution: this can be very large. const std::string abortMessage = std::string("TimeCheck timeout for ") .append(tag) .append(" scheduled ").append(formatTime(startTime)) .append(" on thread ").append(std::to_string(tid)).append("\n") .append(summary); // Note: LOG_ALWAYS_FATAL limits the size of the string - per log/log.h: // Log message text may be truncated to less than an // implementation-specific limit (1023 bytes). // // Here, we send the string through android-base/logging.h LOG() // to avoid the size limitation. LOG(FATAL) does an abort whereas // LOG(FATAL_WITHOUT_ABORT) does not abort. LOG(FATAL) << abortMessage; } // Automatically create a TimeCheck class for a class and method. Loading
media/utils/TimerThread.cpp +24 −1 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ #include <vector> #include <mediautils/TimerThread.h> #include <utils/CallStack.h> #include <utils/ThreadDefs.h> namespace android::mediautils { Loading Loading @@ -68,6 +69,19 @@ std::string TimerThread::toString(size_t retiredCount) const { if (!analysis.summary.empty()) { analysisSummary = std::string("\nanalysis [ ").append(analysis.summary).append(" ]"); } std::string timeoutStack; if (analysis.timeoutTid != -1) { timeoutStack = std::string("\ntimeout(") .append(std::to_string(analysis.timeoutTid)).append(") callstack [\n") .append(tidCallStackString(analysis.timeoutTid)).append("]"); } std::string blockedStack; if (analysis.HALBlockedTid != -1) { blockedStack = std::string("\nblocked(") .append(std::to_string(analysis.HALBlockedTid)).append(") callstack [\n") .append(tidCallStackString(analysis.HALBlockedTid)).append("]"); } return std::string("now ") .append(formatTime(std::chrono::system_clock::now())) .append(analysisSummary) Loading @@ -77,7 +91,9 @@ std::string TimerThread::toString(size_t retiredCount) const { .append(requestsToString(pendingRequests)) .append(" ]\nretired [ ") .append(requestsToString(retiredRequests)) .append(" ]"); .append(" ]") .append(timeoutStack) .append(blockedStack); } // A HAL method is where the substring "Hidl" is in the class name. Loading Loading @@ -197,6 +213,13 @@ std::string TimerThread::timeoutToString(size_t n) const { return requestsToString(timeoutRequests); } /* static */ std::string TimerThread::tidCallStackString(pid_t tid) { CallStack cs{}; cs.update(0 /* ignoreDepth */, tid); return cs.toString().c_str(); } std::string TimerThread::Request::toString() const { const auto scheduledString = formatTime(scheduled); const auto deadlineString = formatTime(deadline); Loading
media/utils/include/mediautils/TimerThread.h +5 −0 Original line number Diff line number Diff line Loading @@ -125,6 +125,11 @@ class TimerThread { return s; } /** * Returns callstack of tid as a string. */ static std::string tidCallStackString(pid_t tid); private: // To minimize movement of data, we pass around shared_ptrs to Requests. // These are allocated and deallocated outside of the lock. Loading