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

Commit d3525198 authored by Yi Jin's avatar Yi Jin Committed by Android (Google) Code Review
Browse files

Merge "This cl implements CommandSection and use it to add procrank.proto Section"

parents 4411448a b44f7d46
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ cc_library {
            // needed by the device.
            srcs: [
                "core/proto/android/os/kernelwake.proto",
                "core/proto/android/os/procrank.proto",
                "core/proto/android/service/graphicsstats.proto",
            ],
            shared: {
+2 −1
Original line number Diff line number Diff line
@@ -10,7 +10,7 @@ cc_defaults {

    srcs: [
        "IncidentHelper.cpp",
        "strutil.cpp",
        "ih_util.cpp",
    ],

    shared_libs: [
@@ -38,6 +38,7 @@ cc_test {

    srcs: [
        "tests/IncidentHelper_test.cpp",
        "tests/ih_util_test.cpp",
    ],

    data: [
+111 −31
Original line number Diff line number Diff line
@@ -17,14 +17,13 @@
#define LOG_TAG "incident_helper"

#include "IncidentHelper.h"
#include "strutil.h"
#include "ih_util.h"

#include "frameworks/base/core/proto/android/os/kernelwake.pb.h"
#include "frameworks/base/core/proto/android/os/procrank.pb.h"

#include <algorithm>
#include <android-base/file.h>
#include <unistd.h>
#include <sstream>
#include <string>
#include <vector>

@@ -67,37 +66,29 @@ const char* kernel_wake_headers[] = {
const string KERNEL_WAKEUP_LINE_DELIMITER = "\t";

status_t KernelWakesParser::Parse(const int in, const int out) const {
    // read the content, this is not memory-efficient though since it loads everything
    // However the data will be held in proto anyway, and incident_helper is less critical
    string content;
    if (!ReadFdToString(in, &content)) {
        fprintf(stderr, "[%s]Failed to read data from incidentd\n", this->name.string());
        return -1;
    }

    istringstream iss(content);
    Reader reader(in);
    string line;
    vector<string> header;  // the header of /d/wakeup_sources
    vector<string> record;  // retain each record
    header_t header;  // the header of /d/wakeup_sources
    record_t record;  // retain each record
    int nline = 0;

    KernelWakeSources proto;

    // parse line by line
    while (getline(iss, line)) {
    while (reader.readLine(line)) {
        if (line.empty()) continue;
        // parse head line
        if (nline == 0) {
          split(line, &header);
        if (nline++ == 0) {
            split(line, header, KERNEL_WAKEUP_LINE_DELIMITER);
            if (!assertHeaders(kernel_wake_headers, header)) {
                fprintf(stderr, "[%s]Bad header:\n%s\n", this->name.string(), line.c_str());
                return BAD_VALUE;
            }
          nline++;
            continue;
        }

        // parse for each record, the line delimiter is \t only!
        split(line, &record, KERNEL_WAKEUP_LINE_DELIMITER);
        split(line, record, KERNEL_WAKEUP_LINE_DELIMITER);

        if (record.size() != header.size()) {
            // TODO: log this to incident report!
@@ -118,17 +109,106 @@ status_t KernelWakesParser::Parse(const int in, const int out) const {
        source->set_max_time(atol(record.at(7).c_str()));
        source->set_last_change(atol(record.at(8).c_str()));
        source->set_prevent_suspend_time(atol(record.at(9).c_str()));
    }

        nline++;
    if (!reader.ok(line)) {
        fprintf(stderr, "Bad read from fd %d: %s\n", in, line.c_str());
        return -1;
    }

    if (!proto.SerializeToFileDescriptor(out)) {
        fprintf(stderr, "[%s]Error writing proto back\n", this->name.string());
        return -1;
    }
    fprintf(stderr, "[%s]Proto size: %d bytes\n", this->name.string(), proto.ByteSize());
    return NO_ERROR;
}

// ================================================================================
const char* procrank_headers[] = {
    "PID",          // id:  1
    "Vss",          // id:  2
    "Rss",          // id:  3
    "Pss",          // id:  4
    "Uss",          // id:  5
    "Swap",         // id:  6
    "PSwap",        // id:  7
    "USwap",        // id:  8
    "ZSwap",        // id:  9
    "cmdline",      // id: 10
};

status_t ProcrankParser::Parse(const int in, const int out) const {
    Reader reader(in);
    string line, content;
    header_t header;  // the header of /d/wakeup_sources
    record_t record;  // retain each record
    int nline = 0;

    Procrank proto;

    // parse line by line
    while (reader.readLine(line)) {
        if (line.empty()) continue;

        // parse head line
        if (nline++ == 0) {
            split(line, header);
            if (!assertHeaders(procrank_headers, header)) {
                fprintf(stderr, "[%s]Bad header:\n%s\n", this->name.string(), line.c_str());
                return BAD_VALUE;
            }
            continue;
        }

        split(line, record);
        if (record.size() != header.size()) {
            if (record[record.size() - 1] == "TOTAL") { // TOTAL record
                ProcessProto* total = proto.mutable_summary()->mutable_total();
                total->set_pss(atol(record.at(0).substr(0, record.at(0).size() - 1).c_str()));
                total->set_uss(atol(record.at(1).substr(0, record.at(1).size() - 1).c_str()));
                total->set_swap(atol(record.at(2).substr(0, record.at(2).size() - 1).c_str()));
                total->set_pswap(atol(record.at(3).substr(0, record.at(3).size() - 1).c_str()));
                total->set_uswap(atol(record.at(4).substr(0, record.at(4).size() - 1).c_str()));
                total->set_zswap(atol(record.at(5).substr(0, record.at(5).size() - 1).c_str()));
            } else if (record[0] == "ZRAM:") {
                split(line, record, ":");
                proto.mutable_summary()->mutable_zram()->set_raw_text(record[1]);
            } else if (record[0] == "RAM:") {
                split(line, record, ":");
                proto.mutable_summary()->mutable_ram()->set_raw_text(record[1]);
            } else {
                fprintf(stderr, "[%s]Line %d has missing fields\n%s\n", this->name.string(), nline,
                    line.c_str());
            }
            continue;
        }

        ProcessProto* process = proto.add_processes();
        // int32
        process->set_pid(atoi(record.at(0).c_str()));
        // int64, remove 'K' at the end
        process->set_vss(atol(record.at(1).substr(0, record.at(1).size() - 1).c_str()));
        process->set_rss(atol(record.at(2).substr(0, record.at(2).size() - 1).c_str()));
        process->set_pss(atol(record.at(3).substr(0, record.at(3).size() - 1).c_str()));
        process->set_uss(atol(record.at(4).substr(0, record.at(4).size() - 1).c_str()));
        process->set_swap(atol(record.at(5).substr(0, record.at(5).size() - 1).c_str()));
        process->set_pswap(atol(record.at(6).substr(0, record.at(6).size() - 1).c_str()));
        process->set_uswap(atol(record.at(7).substr(0, record.at(7).size() - 1).c_str()));
        process->set_zswap(atol(record.at(8).substr(0, record.at(8).size() - 1).c_str()));
        // string
        process->set_cmdline(record.at(9));
    }

    if (!reader.ok(line)) {
        fprintf(stderr, "Bad read from fd %d: %s\n", in, line.c_str());
        return -1;
    }

    if (!proto.SerializeToFileDescriptor(out)) {
        fprintf(stderr, "[%s]Error writing proto back\n", this->name.string());
        return -1;
    }
    close(out);

    fprintf(stderr, "[%s]Proto size: %d bytes\n", this->name.string(), proto.ByteSize());
    return NO_ERROR;
}
 No newline at end of file
+13 −0
Original line number Diff line number Diff line
@@ -70,4 +70,17 @@ public:
    virtual status_t Parse(const int in, const int out) const;
};

/**
 * Procrank parser, parses text produced by command procrank
 */
extern const char* procrank_headers[];

class ProcrankParser : public TextParserBase {
public:
    ProcrankParser() : TextParserBase(String8("ProcrankParser")) {};
    ~ProcrankParser() {};

    virtual status_t Parse(const int in, const int out) const;
};

#endif  // INCIDENT_HELPER_H
+9 −0
Original line number Diff line number Diff line
# incident_helper

It is an executable used to help parsing text format data to protobuf.

## How to build, deploy, unit test

For the first time, build the test and create an empty directly on device:
@@ -15,3 +17,10 @@ root$ mmm -j frameworks/base/cmds/incident_helper && \
adb push $OUT/data/nativetest64/incident_helper_test/* /data/nativetest64/incident_helper_test/ && \
adb shell /data/nativetest64/incident_helper_test/incident_helper_test 2>/dev/null
```
## How to adapt proto changes

If add a new proto file, add it in Android.bp under frameworks/base/ and make incident helper

```
root$ make -j48 incident_helper
```
Loading