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

Commit 0ba39338 authored by Andy Hung's avatar Andy Hung Committed by Automerger Merge Worker
Browse files

Merge "MediaMetrics: Update dumpsys parameters" into rvc-dev am: 44e8ff24

Change-Id: I607ebd09035f463fef8eef09155956e7423bad4a
parents 69446be7 44e8ff24
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -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());
}

/**
+8 −5
Original line number Diff line number Diff line
@@ -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;

@@ -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) {
@@ -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 };
+6 −5
Original line number Diff line number Diff line
@@ -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) {
@@ -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 };
+10 −1
Original line number Diff line number Diff line
@@ -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:

+79 −98
Original line number Diff line number Diff line
@@ -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;
        }
@@ -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.
@@ -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");
@@ -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