Loading media/libmediametrics/include/media/MediaMetricsItem.h +2 −2 Original line number Diff line number Diff line Loading @@ -208,11 +208,11 @@ static inline constexpr const char *BUNDLE_PROPERTY_COUNT = "_propertyCount"; template<size_t N> static inline bool startsWith(const std::string &s, const char (&comp)[N]) { return !strncmp(s.c_str(), comp, N - 1); return !strncmp(s.c_str(), comp, N - 1); // last char is null termination } static inline bool startsWith(const std::string& s, const std::string& comp) { return !strncmp(s.c_str(), comp.c_str(), comp.size() - 1); return !strncmp(s.c_str(), comp.c_str(), comp.size()); } /** Loading services/mediametrics/AnalyticsState.h +8 −5 Original line number Diff line number Diff line Loading @@ -84,8 +84,11 @@ public: * delivered. * * \param lines the maximum number of lines in the string returned. * \param sinceNs the nanoseconds since Unix epoch to start dump (0 shows all) * \param prefix the desired key prefix to match (nullptr shows all) */ std::pair<std::string, int32_t> dump(int32_t lines = INT32_MAX) const { std::pair<std::string, int32_t> dump( int32_t lines = INT32_MAX, int64_t sinceNs = 0, const char *prefix = nullptr) const { std::stringstream ss; int32_t ll = lines; Loading @@ -94,8 +97,8 @@ public: --ll; } if (ll > 0) { auto [s, l] = mTransactionLog.dump(ll); ss << s; auto [s, l] = mTransactionLog.dump(ll, sinceNs, prefix); ss << std::move(s); ll -= l; } if (ll > 0) { Loading @@ -103,8 +106,8 @@ public: --ll; } if (ll > 0) { auto [s, l] = mTimeMachine.dump(ll); ss << s; auto [s, l] = mTimeMachine.dump(ll, sinceNs, prefix); ss << std::move(s); ll -= l; } return { ss.str(), lines - ll }; Loading services/mediametrics/AudioAnalytics.cpp +6 −5 Original line number Diff line number Diff line Loading @@ -107,14 +107,15 @@ status_t AudioAnalytics::submit( return NO_ERROR; } std::pair<std::string, int32_t> AudioAnalytics::dump(int32_t lines) const std::pair<std::string, int32_t> AudioAnalytics::dump( int32_t lines, int64_t sinceNs, const char *prefix) const { std::stringstream ss; int32_t ll = lines; if (ll > 0) { auto [s, l] = mAnalyticsState->dump(ll); ss << s; auto [s, l] = mAnalyticsState->dump(ll, sinceNs, prefix); ss << std::move(s); ll -= l; } if (ll > 0) { Loading @@ -122,8 +123,8 @@ std::pair<std::string, int32_t> AudioAnalytics::dump(int32_t lines) const --ll; } if (ll > 0) { auto [s, l] = mPreviousAnalyticsState->dump(ll); ss << s; auto [s, l] = mPreviousAnalyticsState->dump(ll, sinceNs, prefix); ss << std::move(s); ll -= l; } return { ss.str(), lines - ll }; Loading services/mediametrics/AudioAnalytics.h +10 −1 Original line number Diff line number Diff line Loading @@ -60,8 +60,17 @@ public: * delivered. * * \param lines the maximum number of lines in the string returned. * \param sinceNs the nanoseconds since Unix epoch to start dump (0 shows all) * \param prefix the desired key prefix to match (nullptr shows all) */ std::pair<std::string, int32_t> dump(int32_t lines = INT32_MAX) const; std::pair<std::string, int32_t> dump( int32_t lines = INT32_MAX, int64_t sinceNs = 0, const char *prefix = nullptr) const; void clear() { // underlying state is locked. mPreviousAnalyticsState->clear(); mAnalyticsState->clear(); } private: Loading services/mediametrics/MediaMetricsService.cpp +79 −98 Original line number Diff line number Diff line Loading @@ -207,69 +207,66 @@ status_t MediaMetricsService::dump(int fd, const Vector<String16>& args) return NO_ERROR; } static const String16 allOption("--all"); static const String16 clearOption("--clear"); static const String16 heapOption("--heap"); static const String16 helpOption("--help"); static const String16 prefixOption("--prefix"); static const String16 sinceOption("--since"); static const String16 unreachableOption("--unreachable"); bool heap = false; bool unreachable = false; const String16 protoOption("--proto"); const String16 clearOption("--clear"); bool all = false; bool clear = false; const String16 sinceOption("--since"); nsecs_t ts_since = 0; const String16 helpOption("--help"); const String16 onlyOption("--only"); std::string only; const int n = args.size(); for (int i = 0; i < n; i++) { if (args[i] == clearOption) { bool heap = false; bool unreachable = false; int64_t sinceNs = 0; std::string prefix; const size_t n = args.size(); for (size_t i = 0; i < n; i++) { if (args[i] == allOption) { all = true; } else if (args[i] == clearOption) { clear = true; } else if (args[i] == heapOption) { heap = true; } else if (args[i] == protoOption) { i++; } else if (args[i] == helpOption) { // TODO: consider function area dumping. // dumpsys media.metrics audiotrack,codec // or dumpsys media.metrics audiotrack codec result.append("Recognized parameters:\n"); result.append("--all show all records\n"); result.append("--clear clear out saved records\n"); result.append("--heap show heap usage (top 100)\n"); result.append("--help display help\n"); result.append("--prefix X process records for component X\n"); result.append("--since X X < 0: records from -X seconds in the past\n"); result.append(" X = 0: ignore\n"); result.append(" X > 0: records from X seconds since Unix epoch\n"); result.append("--unreachable show unreachable memory (leaks)\n"); write(fd, result.string(), result.size()); return NO_ERROR; } else if (args[i] == prefixOption) { ++i; if (i < n) { // ignore } else { result.append("missing value for -proto\n\n"); prefix = String8(args[i]).string(); } } else if (args[i] == sinceOption) { i++; ++i; if (i < n) { String8 value(args[i]); char *endp; const char *p = value.string(); ts_since = strtoll(p, &endp, 10); if (endp == p || *endp != '\0') { ts_since = 0; } long long sec = strtoll(p, &endp, 10); if (endp == p || *endp != '\0' || sec == 0) { sinceNs = 0; } else if (sec < 0) { sinceNs = systemTime(SYSTEM_TIME_REALTIME) + sec * NANOS_PER_SECOND; } else { ts_since = 0; sinceNs = sec * NANOS_PER_SECOND; } // command line is milliseconds; internal units are nano-seconds ts_since *= NANOS_PER_MILLISECOND; } else if (args[i] == onlyOption) { i++; if (i < n) { String8 value(args[i]); only = value.string(); } } else if (args[i] == helpOption) { // TODO: consider function area dumping. // dumpsys media.metrics audiotrack,codec // or dumpsys media.metrics audiotrack codec result.append("Recognized parameters:\n"); result.append("--heap heap usage (top 100)\n"); result.append("--help this help message\n"); result.append("--proto # dump using protocol #"); result.append("--clear clears out saved records\n"); result.append("--only X process records for component X\n"); result.append("--since X include records since X\n"); result.append(" (X is milliseconds since the UNIX epoch)\n"); result.append("--unreachable unreachable memory (leaks)\n"); write(fd, result.string(), result.size()); return NO_ERROR; } else if (args[i] == unreachableOption) { unreachable = true; } Loading @@ -278,23 +275,25 @@ status_t MediaMetricsService::dump(int fd, const Vector<String16>& args) { std::lock_guard _l(mLock); result.appendFormat("Dump of the %s process:\n", kServiceName); dumpHeaders_l(result, ts_since); dumpRecent_l(result, ts_since, only.c_str()); if (clear) { mItemsDiscarded += mItems.size(); mItems.clear(); // shall we clear the summary data too? } mAudioAnalytics.clear(); } else { result.appendFormat("Dump of the %s process:\n", kServiceName); const char *prefixptr = prefix.size() > 0 ? prefix.c_str() : nullptr; dumpHeaders_l(result, sinceNs, prefixptr); dumpQueue_l(result, sinceNs, prefixptr); // TODO: maybe consider a better way of dumping audio analytics info. constexpr int32_t linesToDump = 1000; auto [ dumpString, lines ] = mAudioAnalytics.dump(linesToDump); const int32_t linesToDump = all ? INT32_MAX : 1000; auto [ dumpString, lines ] = mAudioAnalytics.dump(linesToDump, sinceNs, prefixptr); result.append(dumpString.c_str()); if (lines == linesToDump) { result.append("-- some lines may be truncated --\n"); } } } write(fd, result.string(), result.size()); // Check heap and unreachable memory outside of lock. Loading @@ -313,7 +312,7 @@ status_t MediaMetricsService::dump(int fd, const Vector<String16>& args) } // dump headers void MediaMetricsService::dumpHeaders_l(String8 &result, nsecs_t ts_since) void MediaMetricsService::dumpHeaders_l(String8 &result, int64_t sinceNs, const char* prefix) { if (mediametrics::Item::isEnabled()) { result.append("Metrics gathering: enabled\n"); Loading @@ -327,56 +326,38 @@ void MediaMetricsService::dumpHeaders_l(String8 &result, nsecs_t ts_since) "Records Discarded: %lld (by Count: %lld by Expiration: %lld)\n", (long long)mItemsDiscarded, (long long)mItemsDiscardedCount, (long long)mItemsDiscardedExpire); if (ts_since != 0) { if (prefix != nullptr) { result.appendFormat("Restricting to prefix %s", prefix); } if (sinceNs != 0) { result.appendFormat( "Emitting Queue entries more recent than: %lld\n", (long long)ts_since); (long long)sinceNs); } } void MediaMetricsService::dumpRecent_l( String8 &result, nsecs_t ts_since, const char * only) // TODO: should prefix be a set<string>? void MediaMetricsService::dumpQueue_l(String8 &result, int64_t sinceNs, const char* prefix) { if (only != nullptr && *only == '\0') { only = nullptr; } result.append("\nFinalized Metrics (oldest first):\n"); dumpQueue_l(result, ts_since, only); // show who is connected and injecting records? // talk about # records fed to the 'readers' // talk about # records we discarded, perhaps "discarded w/o reading" too } void MediaMetricsService::dumpQueue_l(String8 &result) { dumpQueue_l(result, (nsecs_t) 0, nullptr /* only */); if (mItems.empty()) { result.append("empty\n"); return; } void MediaMetricsService::dumpQueue_l( String8 &result, nsecs_t ts_since, const char * only) { int slot = 0; if (mItems.empty()) { result.append("empty\n"); } else { for (const auto &item : mItems) { nsecs_t when = item->getTimestamp(); if (when < ts_since) { for (const auto &item : mItems) { // TODO: consider std::lower_bound() on mItems if (item->getTimestamp() < sinceNs) { // sinceNs == 0 means all items shown continue; } // TODO: Only should be a set<string> if (only != nullptr && item->getKey() /* std::string */ != only) { if (prefix != nullptr && !startsWith(item->getKey(), prefix)) { ALOGV("%s: omit '%s', it's not '%s'", __func__, item->getKey().c_str(), only); __func__, item->getKey().c_str(), prefix); continue; } result.appendFormat("%5d: %s\n", slot, item->toString().c_str()); result.appendFormat("%5d: %s\n", slot, item->toString().c_str()); slot++; } } } // // Our Cheap in-core, non-persistent records management. Loading Loading
media/libmediametrics/include/media/MediaMetricsItem.h +2 −2 Original line number Diff line number Diff line Loading @@ -208,11 +208,11 @@ static inline constexpr const char *BUNDLE_PROPERTY_COUNT = "_propertyCount"; template<size_t N> static inline bool startsWith(const std::string &s, const char (&comp)[N]) { return !strncmp(s.c_str(), comp, N - 1); return !strncmp(s.c_str(), comp, N - 1); // last char is null termination } static inline bool startsWith(const std::string& s, const std::string& comp) { return !strncmp(s.c_str(), comp.c_str(), comp.size() - 1); return !strncmp(s.c_str(), comp.c_str(), comp.size()); } /** Loading
services/mediametrics/AnalyticsState.h +8 −5 Original line number Diff line number Diff line Loading @@ -84,8 +84,11 @@ public: * delivered. * * \param lines the maximum number of lines in the string returned. * \param sinceNs the nanoseconds since Unix epoch to start dump (0 shows all) * \param prefix the desired key prefix to match (nullptr shows all) */ std::pair<std::string, int32_t> dump(int32_t lines = INT32_MAX) const { std::pair<std::string, int32_t> dump( int32_t lines = INT32_MAX, int64_t sinceNs = 0, const char *prefix = nullptr) const { std::stringstream ss; int32_t ll = lines; Loading @@ -94,8 +97,8 @@ public: --ll; } if (ll > 0) { auto [s, l] = mTransactionLog.dump(ll); ss << s; auto [s, l] = mTransactionLog.dump(ll, sinceNs, prefix); ss << std::move(s); ll -= l; } if (ll > 0) { Loading @@ -103,8 +106,8 @@ public: --ll; } if (ll > 0) { auto [s, l] = mTimeMachine.dump(ll); ss << s; auto [s, l] = mTimeMachine.dump(ll, sinceNs, prefix); ss << std::move(s); ll -= l; } return { ss.str(), lines - ll }; Loading
services/mediametrics/AudioAnalytics.cpp +6 −5 Original line number Diff line number Diff line Loading @@ -107,14 +107,15 @@ status_t AudioAnalytics::submit( return NO_ERROR; } std::pair<std::string, int32_t> AudioAnalytics::dump(int32_t lines) const std::pair<std::string, int32_t> AudioAnalytics::dump( int32_t lines, int64_t sinceNs, const char *prefix) const { std::stringstream ss; int32_t ll = lines; if (ll > 0) { auto [s, l] = mAnalyticsState->dump(ll); ss << s; auto [s, l] = mAnalyticsState->dump(ll, sinceNs, prefix); ss << std::move(s); ll -= l; } if (ll > 0) { Loading @@ -122,8 +123,8 @@ std::pair<std::string, int32_t> AudioAnalytics::dump(int32_t lines) const --ll; } if (ll > 0) { auto [s, l] = mPreviousAnalyticsState->dump(ll); ss << s; auto [s, l] = mPreviousAnalyticsState->dump(ll, sinceNs, prefix); ss << std::move(s); ll -= l; } return { ss.str(), lines - ll }; Loading
services/mediametrics/AudioAnalytics.h +10 −1 Original line number Diff line number Diff line Loading @@ -60,8 +60,17 @@ public: * delivered. * * \param lines the maximum number of lines in the string returned. * \param sinceNs the nanoseconds since Unix epoch to start dump (0 shows all) * \param prefix the desired key prefix to match (nullptr shows all) */ std::pair<std::string, int32_t> dump(int32_t lines = INT32_MAX) const; std::pair<std::string, int32_t> dump( int32_t lines = INT32_MAX, int64_t sinceNs = 0, const char *prefix = nullptr) const; void clear() { // underlying state is locked. mPreviousAnalyticsState->clear(); mAnalyticsState->clear(); } private: Loading
services/mediametrics/MediaMetricsService.cpp +79 −98 Original line number Diff line number Diff line Loading @@ -207,69 +207,66 @@ status_t MediaMetricsService::dump(int fd, const Vector<String16>& args) return NO_ERROR; } static const String16 allOption("--all"); static const String16 clearOption("--clear"); static const String16 heapOption("--heap"); static const String16 helpOption("--help"); static const String16 prefixOption("--prefix"); static const String16 sinceOption("--since"); static const String16 unreachableOption("--unreachable"); bool heap = false; bool unreachable = false; const String16 protoOption("--proto"); const String16 clearOption("--clear"); bool all = false; bool clear = false; const String16 sinceOption("--since"); nsecs_t ts_since = 0; const String16 helpOption("--help"); const String16 onlyOption("--only"); std::string only; const int n = args.size(); for (int i = 0; i < n; i++) { if (args[i] == clearOption) { bool heap = false; bool unreachable = false; int64_t sinceNs = 0; std::string prefix; const size_t n = args.size(); for (size_t i = 0; i < n; i++) { if (args[i] == allOption) { all = true; } else if (args[i] == clearOption) { clear = true; } else if (args[i] == heapOption) { heap = true; } else if (args[i] == protoOption) { i++; } else if (args[i] == helpOption) { // TODO: consider function area dumping. // dumpsys media.metrics audiotrack,codec // or dumpsys media.metrics audiotrack codec result.append("Recognized parameters:\n"); result.append("--all show all records\n"); result.append("--clear clear out saved records\n"); result.append("--heap show heap usage (top 100)\n"); result.append("--help display help\n"); result.append("--prefix X process records for component X\n"); result.append("--since X X < 0: records from -X seconds in the past\n"); result.append(" X = 0: ignore\n"); result.append(" X > 0: records from X seconds since Unix epoch\n"); result.append("--unreachable show unreachable memory (leaks)\n"); write(fd, result.string(), result.size()); return NO_ERROR; } else if (args[i] == prefixOption) { ++i; if (i < n) { // ignore } else { result.append("missing value for -proto\n\n"); prefix = String8(args[i]).string(); } } else if (args[i] == sinceOption) { i++; ++i; if (i < n) { String8 value(args[i]); char *endp; const char *p = value.string(); ts_since = strtoll(p, &endp, 10); if (endp == p || *endp != '\0') { ts_since = 0; } long long sec = strtoll(p, &endp, 10); if (endp == p || *endp != '\0' || sec == 0) { sinceNs = 0; } else if (sec < 0) { sinceNs = systemTime(SYSTEM_TIME_REALTIME) + sec * NANOS_PER_SECOND; } else { ts_since = 0; sinceNs = sec * NANOS_PER_SECOND; } // command line is milliseconds; internal units are nano-seconds ts_since *= NANOS_PER_MILLISECOND; } else if (args[i] == onlyOption) { i++; if (i < n) { String8 value(args[i]); only = value.string(); } } else if (args[i] == helpOption) { // TODO: consider function area dumping. // dumpsys media.metrics audiotrack,codec // or dumpsys media.metrics audiotrack codec result.append("Recognized parameters:\n"); result.append("--heap heap usage (top 100)\n"); result.append("--help this help message\n"); result.append("--proto # dump using protocol #"); result.append("--clear clears out saved records\n"); result.append("--only X process records for component X\n"); result.append("--since X include records since X\n"); result.append(" (X is milliseconds since the UNIX epoch)\n"); result.append("--unreachable unreachable memory (leaks)\n"); write(fd, result.string(), result.size()); return NO_ERROR; } else if (args[i] == unreachableOption) { unreachable = true; } Loading @@ -278,23 +275,25 @@ status_t MediaMetricsService::dump(int fd, const Vector<String16>& args) { std::lock_guard _l(mLock); result.appendFormat("Dump of the %s process:\n", kServiceName); dumpHeaders_l(result, ts_since); dumpRecent_l(result, ts_since, only.c_str()); if (clear) { mItemsDiscarded += mItems.size(); mItems.clear(); // shall we clear the summary data too? } mAudioAnalytics.clear(); } else { result.appendFormat("Dump of the %s process:\n", kServiceName); const char *prefixptr = prefix.size() > 0 ? prefix.c_str() : nullptr; dumpHeaders_l(result, sinceNs, prefixptr); dumpQueue_l(result, sinceNs, prefixptr); // TODO: maybe consider a better way of dumping audio analytics info. constexpr int32_t linesToDump = 1000; auto [ dumpString, lines ] = mAudioAnalytics.dump(linesToDump); const int32_t linesToDump = all ? INT32_MAX : 1000; auto [ dumpString, lines ] = mAudioAnalytics.dump(linesToDump, sinceNs, prefixptr); result.append(dumpString.c_str()); if (lines == linesToDump) { result.append("-- some lines may be truncated --\n"); } } } write(fd, result.string(), result.size()); // Check heap and unreachable memory outside of lock. Loading @@ -313,7 +312,7 @@ status_t MediaMetricsService::dump(int fd, const Vector<String16>& args) } // dump headers void MediaMetricsService::dumpHeaders_l(String8 &result, nsecs_t ts_since) void MediaMetricsService::dumpHeaders_l(String8 &result, int64_t sinceNs, const char* prefix) { if (mediametrics::Item::isEnabled()) { result.append("Metrics gathering: enabled\n"); Loading @@ -327,56 +326,38 @@ void MediaMetricsService::dumpHeaders_l(String8 &result, nsecs_t ts_since) "Records Discarded: %lld (by Count: %lld by Expiration: %lld)\n", (long long)mItemsDiscarded, (long long)mItemsDiscardedCount, (long long)mItemsDiscardedExpire); if (ts_since != 0) { if (prefix != nullptr) { result.appendFormat("Restricting to prefix %s", prefix); } if (sinceNs != 0) { result.appendFormat( "Emitting Queue entries more recent than: %lld\n", (long long)ts_since); (long long)sinceNs); } } void MediaMetricsService::dumpRecent_l( String8 &result, nsecs_t ts_since, const char * only) // TODO: should prefix be a set<string>? void MediaMetricsService::dumpQueue_l(String8 &result, int64_t sinceNs, const char* prefix) { if (only != nullptr && *only == '\0') { only = nullptr; } result.append("\nFinalized Metrics (oldest first):\n"); dumpQueue_l(result, ts_since, only); // show who is connected and injecting records? // talk about # records fed to the 'readers' // talk about # records we discarded, perhaps "discarded w/o reading" too } void MediaMetricsService::dumpQueue_l(String8 &result) { dumpQueue_l(result, (nsecs_t) 0, nullptr /* only */); if (mItems.empty()) { result.append("empty\n"); return; } void MediaMetricsService::dumpQueue_l( String8 &result, nsecs_t ts_since, const char * only) { int slot = 0; if (mItems.empty()) { result.append("empty\n"); } else { for (const auto &item : mItems) { nsecs_t when = item->getTimestamp(); if (when < ts_since) { for (const auto &item : mItems) { // TODO: consider std::lower_bound() on mItems if (item->getTimestamp() < sinceNs) { // sinceNs == 0 means all items shown continue; } // TODO: Only should be a set<string> if (only != nullptr && item->getKey() /* std::string */ != only) { if (prefix != nullptr && !startsWith(item->getKey(), prefix)) { ALOGV("%s: omit '%s', it's not '%s'", __func__, item->getKey().c_str(), only); __func__, item->getKey().c_str(), prefix); continue; } result.appendFormat("%5d: %s\n", slot, item->toString().c_str()); result.appendFormat("%5d: %s\n", slot, item->toString().c_str()); slot++; } } } // // Our Cheap in-core, non-persistent records management. Loading