diff options
author | Yi Jin <jinyithu@google.com> | 2017-09-11 19:01:08 -0700 |
---|---|---|
committer | Yi Jin <jinyithu@google.com> | 2017-09-14 11:47:44 -0700 |
commit | 810b14f5c24a9517dd6ded3ce5a38cfc8e29b3ed (patch) | |
tree | 1aef1e5be35bdd5e37403db26a9f6ed9287a39fd | |
parent | e57a4f85bf1948d316a90ca354b5bf84aa99b448 (diff) |
Implement PageTypeInfo section
Bug: 65560369
Test: unit tests written, manually tested in incident_report tool
Change-Id: Ibb588fe3affc9675db4cfc2835eea31d1bbb701b
-rw-r--r-- | Android.bp | 1 | ||||
-rw-r--r-- | cmds/incident_helper/IncidentHelper.cpp | 158 | ||||
-rw-r--r-- | cmds/incident_helper/IncidentHelper.h | 11 | ||||
-rw-r--r-- | cmds/incident_helper/ih_util.cpp | 24 | ||||
-rw-r--r-- | cmds/incident_helper/ih_util.h | 24 | ||||
-rw-r--r-- | cmds/incident_helper/main.cpp | 2 | ||||
-rw-r--r-- | cmds/incident_helper/testdata/pagetypeinfo.txt | 10 | ||||
-rw-r--r-- | cmds/incident_helper/tests/IncidentHelper_test.cpp | 72 | ||||
-rw-r--r-- | cmds/incident_helper/tests/ih_util_test.cpp | 46 | ||||
-rw-r--r-- | core/proto/android/os/incident.proto | 10 | ||||
-rw-r--r-- | core/proto/android/os/pagetypeinfo.proto | 81 |
11 files changed, 383 insertions, 56 deletions
diff --git a/Android.bp b/Android.bp index 33acffa306da..d7254786efe2 100644 --- a/Android.bp +++ b/Android.bp @@ -40,6 +40,7 @@ cc_library { // needed by the device. srcs: [ "core/proto/android/os/kernelwake.proto", + "core/proto/android/os/pagetypeinfo.proto", "core/proto/android/os/procrank.proto", "core/proto/android/service/graphicsstats.proto", ], diff --git a/cmds/incident_helper/IncidentHelper.cpp b/cmds/incident_helper/IncidentHelper.cpp index 787d3a1557d6..7b06d42cbb55 100644 --- a/cmds/incident_helper/IncidentHelper.cpp +++ b/cmds/incident_helper/IncidentHelper.cpp @@ -20,6 +20,7 @@ #include "ih_util.h" #include "frameworks/base/core/proto/android/os/kernelwake.pb.h" +#include "frameworks/base/core/proto/android/os/pagetypeinfo.pb.h" #include "frameworks/base/core/proto/android/os/procrank.pb.h" #include <android-base/file.h> @@ -32,6 +33,22 @@ using namespace android::os; using namespace google::protobuf; using namespace std; + +static const string TAB_DELIMITER = "\t"; +static const string COMMA_DELIMITER = ","; + +static inline int toInt(const string& s) { + return atoi(s.c_str()); +} + +static inline long toLong(const string& s) { + return atol(s.c_str()); +} + +/** + * Sets the given protobuf message when the field name matches one of the + * fields. It is useful to set values to proto from table-like plain texts. + */ static bool SetTableField(::google::protobuf::Message* message, string field_name, string field_value) { const Descriptor* descriptor = message->GetDescriptor(); @@ -43,16 +60,16 @@ SetTableField(::google::protobuf::Message* message, string field_name, string fi reflection->SetString(message, field, field_value); return true; case FieldDescriptor::TYPE_INT64: - reflection->SetInt64(message, field, atol(field_value.c_str())); + reflection->SetInt64(message, field, toLong(field_value)); return true; case FieldDescriptor::TYPE_UINT64: - reflection->SetUInt64(message, field, atol(field_value.c_str())); + reflection->SetUInt64(message, field, toLong(field_value)); return true; case FieldDescriptor::TYPE_INT32: - reflection->SetInt32(message, field, atoi(field_value.c_str())); + reflection->SetInt32(message, field, toInt(field_value)); return true; case FieldDescriptor::TYPE_UINT32: - reflection->SetUInt32(message, field, atoi(field_value.c_str())); + reflection->SetUInt32(message, field, toInt(field_value)); return true; default: // Add new scalar types @@ -93,8 +110,6 @@ status_t ReverseParser::Parse(const int in, const int out) const } // ================================================================================ -static const string KERNEL_WAKEUP_LINE_DELIMITER = "\t"; - status_t KernelWakesParser::Parse(const int in, const int out) const { Reader reader(in); string line; @@ -105,16 +120,16 @@ status_t KernelWakesParser::Parse(const int in, const int out) const { KernelWakeSources proto; // parse line by line - while (reader.readLine(line)) { + while (reader.readLine(&line)) { if (line.empty()) continue; // parse head line if (nline++ == 0) { - header = parseHeader(line, KERNEL_WAKEUP_LINE_DELIMITER); + header = parseHeader(line, TAB_DELIMITER); continue; } // parse for each record, the line delimiter is \t only! - record = parseRecord(line, KERNEL_WAKEUP_LINE_DELIMITER); + record = parseRecord(line, TAB_DELIMITER); if (record.size() != header.size()) { // TODO: log this to incident report! @@ -131,7 +146,7 @@ status_t KernelWakesParser::Parse(const int in, const int out) const { } } - if (!reader.ok(line)) { + if (!reader.ok(&line)) { fprintf(stderr, "Bad read from fd %d: %s\n", in, line.c_str()); return -1; } @@ -147,7 +162,7 @@ status_t KernelWakesParser::Parse(const int in, const int out) const { // ================================================================================ status_t ProcrankParser::Parse(const int in, const int out) const { Reader reader(in); - string line, content; + string line; header_t header; // the header of /d/wakeup_sources record_t record; // retain each record int nline = 0; @@ -155,7 +170,7 @@ status_t ProcrankParser::Parse(const int in, const int out) const { Procrank proto; // parse line by line - while (reader.readLine(line)) { + while (reader.readLine(&line)) { if (line.empty()) continue; // parse head line @@ -164,6 +179,15 @@ status_t ProcrankParser::Parse(const int in, const int out) const { continue; } + if (hasPrefix(&line, "ZRAM:")) { + proto.mutable_summary()->mutable_zram()->set_raw_text(line); + continue; + } + if (hasPrefix(&line, "RAM:")) { + proto.mutable_summary()->mutable_ram()->set_raw_text(line); + continue; + } + record = parseRecord(line); if (record.size() != header.size()) { if (record[record.size() - 1] == "TOTAL") { // TOTAL record @@ -171,12 +195,6 @@ status_t ProcrankParser::Parse(const int in, const int out) const { for (int i=1; i<=(int)record.size(); i++) { SetTableField(total, header[header.size() - i], record[record.size() - i]); } - } else if (record[0] == "ZRAM:") { - record = parseRecord(line, ":"); - proto.mutable_summary()->mutable_zram()->set_raw_text(record[1]); - } else if (record[0] == "RAM:") { - record = parseRecord(line, ":"); - 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()); @@ -193,7 +211,7 @@ status_t ProcrankParser::Parse(const int in, const int out) const { } } - if (!reader.ok(line)) { + if (!reader.ok(&line)) { fprintf(stderr, "Bad read from fd %d: %s\n", in, line.c_str()); return -1; } @@ -205,3 +223,105 @@ status_t ProcrankParser::Parse(const int in, const int out) const { fprintf(stderr, "[%s]Proto size: %d bytes\n", this->name.string(), proto.ByteSize()); return NO_ERROR; } + +// ================================================================================ +status_t PageTypeInfoParser::Parse(const int in, const int out) const { + Reader reader(in); + string line; + bool migrateTypeSession = false; + int pageBlockOrder; + header_t blockHeader; + + PageTypeInfo pageTypeInfo; + + while (reader.readLine(&line)) { + if (line.empty()) { + migrateTypeSession = false; + blockHeader.clear(); + continue; + } + + if (hasPrefix(&line, "Page block order:")) { + pageBlockOrder = toInt(line); + pageTypeInfo.set_page_block_order(pageBlockOrder); + continue; + } + if (hasPrefix(&line, "Pages per block:")) { + pageTypeInfo.set_pages_per_block(toInt(line)); + continue; + } + if (hasPrefix(&line, "Free pages count per migrate type at order")) { + migrateTypeSession = true; + continue; + } + if (hasPrefix(&line, "Number of blocks type")) { + blockHeader = parseHeader(line); + continue; + } + + record_t record = parseRecord(line, COMMA_DELIMITER); + if (migrateTypeSession && record.size() == 3) { + MigrateTypeProto* migrateType = pageTypeInfo.add_migrate_types(); + // expect part 0 starts with "Node" + if (hasPrefix(&record[0], "Node")) { + migrateType->set_node(toInt(record[0])); + } else goto ERROR; + // expect part 1 starts with "zone" + if (hasPrefix(&record[1], "zone")) { + migrateType->set_zone(record[1]); + } else goto ERROR; + // expect part 2 starts with "type" + if (hasPrefix(&record[2], "type")) { + // expect the rest of part 2 has number of (pageBlockOrder + 2) parts + // An example looks like: + // header line: type 0 1 2 3 4 5 6 7 8 9 10 + // record line: Unmovable 426 279 226 1 1 1 0 0 2 2 0 + // The pageBlockOrder = 10 and it's zero-indexed. so total parts + // are 10 + 1(zero-indexed) + 1(the type part) = 12. + record_t pageCounts = parseRecord(record[2]); + int pageCountsSize = pageBlockOrder + 2; + if ((int)pageCounts.size() != pageCountsSize) goto ERROR; + + migrateType->set_type(pageCounts[0]); + for (auto i=1; i<pageCountsSize; i++) { + migrateType->add_free_pages_count(toInt(pageCounts[i])); + } + } else goto ERROR; + continue; + } + + if (!blockHeader.empty() && record.size() == 2) { + BlockProto* block = pageTypeInfo.add_blocks(); + + if (hasPrefix(&record[0], "Node")) { + block->set_node(toInt(record[0])); + } else goto ERROR; + + if (hasPrefix(&record[1], "zone")) { + record_t blockCounts = parseRecord(record[1]); + block->set_zone(blockCounts[0]); + for (size_t i=0; i<blockHeader.size(); i++) { + if (!SetTableField(block, blockHeader[i], blockCounts[i+1])) goto ERROR; + } + } else goto ERROR; + + continue; + } + +ERROR: // print out error for this single line and continue parsing + fprintf(stderr, "[%s]Bad line: %s\n", this->name.string(), line.c_str()); + } + + if (!reader.ok(&line)) { + fprintf(stderr, "Bad read from fd %d: %s\n", in, line.c_str()); + return -1; + } + + if (!pageTypeInfo.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(), pageTypeInfo.ByteSize()); + return NO_ERROR; +} diff --git a/cmds/incident_helper/IncidentHelper.h b/cmds/incident_helper/IncidentHelper.h index f6579a2d3736..d24d7173aa26 100644 --- a/cmds/incident_helper/IncidentHelper.h +++ b/cmds/incident_helper/IncidentHelper.h @@ -80,6 +80,17 @@ public: }; /** + * PageTypeInfo parser, parses text to protobuf in /proc/pageinfotype + */ +class PageTypeInfoParser : public TextParserBase { +public: + PageTypeInfoParser() : TextParserBase(String8("PageTypeInfo")) {}; + ~PageTypeInfoParser() {}; + + virtual status_t Parse(const int in, const int out) const; +}; + +/** * Procrank parser, parses text produced by command procrank */ class ProcrankParser : public TextParserBase { diff --git a/cmds/incident_helper/ih_util.cpp b/cmds/incident_helper/ih_util.cpp index b2fda23ac391..2ab4b54e193f 100644 --- a/cmds/incident_helper/ih_util.cpp +++ b/cmds/incident_helper/ih_util.cpp @@ -18,6 +18,7 @@ #include "ih_util.h" +#include <algorithm> #include <sstream> #include <unistd.h> @@ -72,6 +73,20 @@ record_t parseRecord(const std::string& line, const std::string& delimiters) { return record; } +bool hasPrefix(std::string* line, const char* key) { + const auto head = line->find_first_not_of(DEFAULT_WHITESPACE); + if (head == std::string::npos) return false; + auto i = 0; + auto j = head; + while (key[i] != '\0') { + if (j >= line->size() || key[i++] != line->at(j++)) { + return false; + } + } + line->assign(trim(line->substr(j))); + return true; +} + Reader::Reader(const int fd) : Reader(fd, BUFFER_SIZE) {}; Reader::Reader(const int fd, const size_t capacity) @@ -86,8 +101,9 @@ Reader::~Reader() free(mBuf); } -bool Reader::readLine(std::string& line, const char newline) { +bool Reader::readLine(std::string* line, const char newline) { if (!ok(line)) return false; // bad status + line->clear(); std::stringstream ss; while (!EOR()) { // read if available @@ -124,14 +140,14 @@ bool Reader::readLine(std::string& line, const char newline) { if (mFlushed >= (int) mMaxSize) mFlushed = 0; if (EOR() || meetsNewLine) { - line.assign(ss.str()); + line->assign(ss.str()); return true; } } return false; } -bool Reader::ok(std::string& error) { - error.assign(mStatus); +bool Reader::ok(std::string* error) { + error->assign(mStatus); return mStatus.empty(); } diff --git a/cmds/incident_helper/ih_util.h b/cmds/incident_helper/ih_util.h index 5598eed8d824..ce5baeef0dc3 100644 --- a/cmds/incident_helper/ih_util.h +++ b/cmds/incident_helper/ih_util.h @@ -28,10 +28,30 @@ typedef std::string (*trans_func) (const std::string&); const char DEFAULT_NEWLINE = '\n'; const std::string DEFAULT_WHITESPACE = " \t"; +/** + * When a text has a table format like this + * line 1: HeadA HeadB HeadC + * line 2: v1 v2 v3 + * line 3: v11 v12 v13 + * + * We want to parse the line in structure given the delimiter. + * parseHeader is used to parse the firse line of the table and returns a list of strings in lower case + * parseRecord is used to parse other lines and returns a list of strings + * empty strings are skipped + */ header_t parseHeader(const std::string& line, const std::string& delimiters = DEFAULT_WHITESPACE); record_t parseRecord(const std::string& line, const std::string& delimiters = DEFAULT_WHITESPACE); /** + * When the line starts with the given key, the function returns true + * as well as the line argument is changed to the rest part of the original. + * e.g. "ZRAM: 6828K physical used for 31076K in swap (524284K total swap)" becomes + * "6828K physical used for 31076K in swap (524284K total swap)" when given key "ZRAM:", + * otherwise the line is not changed. + */ +bool hasPrefix(std::string* line, const char* key); + +/** * Reader class reads data from given fd in streaming fashion. * The buffer size is controlled by capacity parameter. */ @@ -42,8 +62,8 @@ public: Reader(const int fd, const size_t capacity); ~Reader(); - bool readLine(std::string& line, const char newline = DEFAULT_NEWLINE); - bool ok(std::string& error); + bool readLine(std::string* line, const char newline = DEFAULT_NEWLINE); + bool ok(std::string* error); private: int mFd; // set mFd to -1 when read EOF() diff --git a/cmds/incident_helper/main.cpp b/cmds/incident_helper/main.cpp index 296d3001b7bb..52ff77720d70 100644 --- a/cmds/incident_helper/main.cpp +++ b/cmds/incident_helper/main.cpp @@ -48,6 +48,8 @@ static TextParserBase* selectParser(int section) { // IDs larger than 1 are section ids reserved in incident.proto case 2000: return new ProcrankParser(); + case 2001: + return new PageTypeInfoParser(); case 2002: return new KernelWakesParser(); default: diff --git a/cmds/incident_helper/testdata/pagetypeinfo.txt b/cmds/incident_helper/testdata/pagetypeinfo.txt new file mode 100644 index 000000000000..d45ddc408c0f --- /dev/null +++ b/cmds/incident_helper/testdata/pagetypeinfo.txt @@ -0,0 +1,10 @@ +Page block order: 10 +Pages per block: 1024 + +Free pages count per migrate type at order 0 1 2 3 4 5 6 7 8 9 10 +Node 0, zone DMA, type Unmovable 426 279 226 1 1 1 0 0 2 2 0 +Node 0, zone Normal, type Reclaimable 953 773 437 154 92 26 15 14 12 7 0 + +Number of blocks type Unmovable Reclaimable Movable CMA Reserve Isolate +Node 0, zone DMA 74 9 337 41 1 0 +Node 0, zone Normal 70 12 423 0 1 0 diff --git a/cmds/incident_helper/tests/IncidentHelper_test.cpp b/cmds/incident_helper/tests/IncidentHelper_test.cpp index 04dd8de11a15..c44a163efa11 100644 --- a/cmds/incident_helper/tests/IncidentHelper_test.cpp +++ b/cmds/incident_helper/tests/IncidentHelper_test.cpp @@ -17,6 +17,7 @@ #include "IncidentHelper.h" #include "frameworks/base/core/proto/android/os/kernelwake.pb.h" +#include "frameworks/base/core/proto/android/os/pagetypeinfo.pb.h" #include "frameworks/base/core/proto/android/os/procrank.pb.h" #include <android-base/file.h> @@ -29,6 +30,7 @@ using namespace android::base; using namespace android::os; +using namespace std; using ::testing::StrEq; using ::testing::Test; using ::testing::internal::CaptureStderr; @@ -42,8 +44,8 @@ public: ASSERT_TRUE(tf.fd != -1); } - std::string getSerializedString(::google::protobuf::Message& message) { - std::string expectedStr; + string getSerializedString(::google::protobuf::Message& message) { + string expectedStr; message.SerializeToFileDescriptor(tf.fd); ReadFileToString(tf.path, &expectedStr); return expectedStr; @@ -52,8 +54,8 @@ public: protected: TemporaryFile tf; - const std::string kTestPath = GetExecutableDirectory(); - const std::string kTestDataPath = kTestPath + "/testdata/"; + const string kTestPath = GetExecutableDirectory(); + const string kTestDataPath = kTestPath + "/testdata/"; }; TEST_F(IncidentHelperTest, ReverseParser) { @@ -69,7 +71,7 @@ TEST_F(IncidentHelperTest, ReverseParser) { } TEST_F(IncidentHelperTest, KernelWakesParser) { - const std::string testFile = kTestDataPath + "kernel_wakeups.txt"; + const string testFile = kTestDataPath + "kernel_wakeups.txt"; KernelWakesParser parser; KernelWakeSources expected; @@ -107,7 +109,7 @@ TEST_F(IncidentHelperTest, KernelWakesParser) { } TEST_F(IncidentHelperTest, ProcrankParser) { - const std::string testFile = kTestDataPath + "procrank.txt"; + const string testFile = kTestDataPath + "procrank.txt"; ProcrankParser parser; Procrank expected; @@ -159,7 +161,7 @@ TEST_F(IncidentHelperTest, ProcrankParser) { } TEST_F(IncidentHelperTest, ProcrankParserShortHeader) { - const std::string testFile = kTestDataPath + "procrank_short.txt"; + const string testFile = kTestDataPath + "procrank_short.txt"; ProcrankParser parser; Procrank expected; @@ -195,3 +197,59 @@ TEST_F(IncidentHelperTest, ProcrankParserShortHeader) { EXPECT_EQ(GetCapturedStdout(), getSerializedString(expected)); close(fd); } + +TEST_F(IncidentHelperTest, PageTypeInfoParser) { + const string testFile = kTestDataPath + "pagetypeinfo.txt"; + PageTypeInfoParser parser; + PageTypeInfo expected; + + expected.set_page_block_order(10); + expected.set_pages_per_block(1024); + + MigrateTypeProto* mt1 = expected.add_migrate_types(); + mt1->set_node(0); + mt1->set_zone("DMA"); + mt1->set_type("Unmovable"); + int arr1[] = { 426, 279, 226, 1, 1, 1, 0, 0, 2, 2, 0}; + for (auto i=0; i<11; i++) { + mt1->add_free_pages_count(arr1[i]); + } + + MigrateTypeProto* mt2 = expected.add_migrate_types(); + mt2->set_node(0); + mt2->set_zone("Normal"); + mt2->set_type("Reclaimable"); + int arr2[] = { 953, 773, 437, 154, 92, 26, 15, 14, 12, 7, 0}; + for (auto i=0; i<11; i++) { + mt2->add_free_pages_count(arr2[i]); + } + + BlockProto* block1 = expected.add_blocks(); + block1->set_node(0); + block1->set_zone("DMA"); + block1->set_unmovable(74); + block1->set_reclaimable(9); + block1->set_movable(337); + block1->set_cma(41); + block1->set_reserve(1); + block1->set_isolate(0); + + + BlockProto* block2 = expected.add_blocks(); + block2->set_node(0); + block2->set_zone("Normal"); + block2->set_unmovable(70); + block2->set_reclaimable(12); + block2->set_movable(423); + block2->set_cma(0); + block2->set_reserve(1); + block2->set_isolate(0); + + int fd = open(testFile.c_str(), O_RDONLY); + ASSERT_TRUE(fd != -1); + + CaptureStdout(); + ASSERT_EQ(NO_ERROR, parser.Parse(fd, STDOUT_FILENO)); + EXPECT_EQ(GetCapturedStdout(), getSerializedString(expected)); + close(fd); +}
\ No newline at end of file diff --git a/cmds/incident_helper/tests/ih_util_test.cpp b/cmds/incident_helper/tests/ih_util_test.cpp index 3b9ed403b77a..da88ee3a0120 100644 --- a/cmds/incident_helper/tests/ih_util_test.cpp +++ b/cmds/incident_helper/tests/ih_util_test.cpp @@ -69,14 +69,14 @@ TEST(IhUtilTest, Reader) { Reader r(tf.fd); string line; - ASSERT_TRUE(r.readLine(line)); + ASSERT_TRUE(r.readLine(&line)); EXPECT_THAT(line, StrEq("test string")); - ASSERT_TRUE(r.readLine(line)); + ASSERT_TRUE(r.readLine(&line)); EXPECT_THAT(line, StrEq("second")); - ASSERT_TRUE(r.readLine(line)); + ASSERT_TRUE(r.readLine(&line)); EXPECT_THAT(line, StrEq("ooo")); - ASSERT_FALSE(r.readLine(line)); - ASSERT_TRUE(r.ok(line)); + ASSERT_FALSE(r.readLine(&line)); + ASSERT_TRUE(r.ok(&line)); } TEST(IhUtilTest, ReaderSmallBufSize) { @@ -86,14 +86,14 @@ TEST(IhUtilTest, ReaderSmallBufSize) { Reader r(tf.fd, 5); string line; - ASSERT_TRUE(r.readLine(line)); + ASSERT_TRUE(r.readLine(&line)); EXPECT_THAT(line, StrEq("test string")); - ASSERT_TRUE(r.readLine(line)); + ASSERT_TRUE(r.readLine(&line)); EXPECT_THAT(line, StrEq("second")); - ASSERT_TRUE(r.readLine(line)); + ASSERT_TRUE(r.readLine(&line)); EXPECT_THAT(line, StrEq("ooiecccojreo")); - ASSERT_FALSE(r.readLine(line)); - ASSERT_TRUE(r.ok(line)); + ASSERT_FALSE(r.readLine(&line)); + ASSERT_TRUE(r.ok(&line)); } TEST(IhUtilTest, ReaderEmpty) { @@ -103,10 +103,10 @@ TEST(IhUtilTest, ReaderEmpty) { Reader r(tf.fd); string line; - ASSERT_TRUE(r.readLine(line)); + ASSERT_TRUE(r.readLine(&line)); EXPECT_THAT(line, StrEq("")); - ASSERT_FALSE(r.readLine(line)); - ASSERT_TRUE(r.ok(line)); + ASSERT_FALSE(r.readLine(&line)); + ASSERT_TRUE(r.ok(&line)); } TEST(IhUtilTest, ReaderMultipleEmptyLines) { @@ -116,35 +116,35 @@ TEST(IhUtilTest, ReaderMultipleEmptyLines) { Reader r(tf.fd); string line; - ASSERT_TRUE(r.readLine(line)); + ASSERT_TRUE(r.readLine(&line)); EXPECT_THAT(line, StrEq("")); - ASSERT_TRUE(r.readLine(line)); + ASSERT_TRUE(r.readLine(&line)); EXPECT_THAT(line, StrEq("")); - ASSERT_FALSE(r.readLine(line)); + ASSERT_FALSE(r.readLine(&line)); EXPECT_THAT(line, StrEq("")); - ASSERT_TRUE(r.ok(line)); + ASSERT_TRUE(r.ok(&line)); } TEST(IhUtilTest, ReaderFailedNegativeFd) { Reader r(-123); string line; - EXPECT_FALSE(r.readLine(line)); - EXPECT_FALSE(r.ok(line)); + EXPECT_FALSE(r.readLine(&line)); + EXPECT_FALSE(r.ok(&line)); EXPECT_THAT(line, StrEq("Negative fd")); } TEST(IhUtilTest, ReaderFailedZeroBufferSize) { Reader r(23, 0); string line; - EXPECT_FALSE(r.readLine(line)); - EXPECT_FALSE(r.ok(line)); + EXPECT_FALSE(r.readLine(&line)); + EXPECT_FALSE(r.ok(&line)); EXPECT_THAT(line, StrEq("Zero buffer capacity")); } TEST(IhUtilTest, ReaderFailedBadFd) { Reader r(1231432); string line; - EXPECT_FALSE(r.readLine(line)); - EXPECT_FALSE(r.ok(line)); + EXPECT_FALSE(r.readLine(&line)); + EXPECT_FALSE(r.ok(&line)); EXPECT_THAT(line, StrEq("Fail to read from fd")); } diff --git a/core/proto/android/os/incident.proto b/core/proto/android/os/incident.proto index aab4142d252f..7331a64789b5 100644 --- a/core/proto/android/os/incident.proto +++ b/core/proto/android/os/incident.proto @@ -33,6 +33,7 @@ import "frameworks/base/core/proto/android/service/print.proto"; import "frameworks/base/core/proto/android/providers/settings.proto"; import "frameworks/base/core/proto/android/os/incidentheader.proto"; import "frameworks/base/core/proto/android/os/kernelwake.proto"; +import "frameworks/base/core/proto/android/os/pagetypeinfo.proto"; import "frameworks/base/core/proto/android/os/procrank.proto"; package android.os; @@ -52,17 +53,24 @@ message IncidentProto { (section).type = SECTION_COMMAND, (section).args = "/system/xbin/procrank" ]; - //PageTypeInfo page_type_info = 2001; + + PageTypeInfo page_type_info = 2001 [ + (section).type = SECTION_FILE, + (section).args = "/proc/pagetypeinfo" + ]; + KernelWakeSources kernel_wake_sources = 2002 [ (section).type = SECTION_FILE, (section).args = "/d/wakeup_sources" ]; + // System Services android.service.fingerprint.FingerprintServiceDumpProto fingerprint = 3000 [ (section).type = SECTION_DUMPSYS, (section).args = "fingerprint --proto --incident" ]; + android.service.NetworkStatsServiceDumpProto netstats = 3001; android.providers.settings.SettingsServiceDumpProto settings = 3002; android.service.appwidget.AppWidgetServiceDumpProto appwidget = 3003; diff --git a/core/proto/android/os/pagetypeinfo.proto b/core/proto/android/os/pagetypeinfo.proto new file mode 100644 index 000000000000..fbb4ee52c3b0 --- /dev/null +++ b/core/proto/android/os/pagetypeinfo.proto @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +syntax = "proto3"; + +option java_multiple_files = true; +option java_outer_classname = "PageTypeInfoProto"; + +package android.os; + +/* + * /proc/pagetypeinfo exports free memory distributions. + * + * For example, the order of a page ranges form 0 to 10. + * An order-0 page is 4 KB in size and 4 KB aligned. + * An order-1 page is 8 KB in size and 8 KB aligned. + * An order-10 page is 4096 KB in size and 4096 aligned. + * The memory has multiple zones, e.g. DMA zone, Normal zone + * Each zone has 11 free area. Each free area corresponds to pages of the same order. + * Each free area has 6 free list. Each corresponds to one migration type. + * The six migration types are Unmovable, Reclaimable, Movable, Reserve, CMA, and Isolate. + * Each zone has 11 * 6 = 66 free list. + * + * Next tag: 5 + */ +message PageTypeInfo { + + int32 page_block_order = 1; + + int32 pages_per_block = 2; + + repeated MigrateTypeProto migrate_types = 3; + + repeated BlockProto blocks = 4; +} + +// Next tag: 5 +message MigrateTypeProto { + + int32 node = 1; + + string zone = 2; + + string type = 3; + + // order level starts from 0 for 4KB to page_block_order defined above, e.g. 10 for 4096KB + repeated int32 free_pages_count = 4; +} + +// Next tag: 9 +message BlockProto { + + int32 node = 1; + + string zone = 2; + + int32 unmovable = 3; + + int32 reclaimable = 4; + + int32 movable = 5; + + int32 cma = 6; + + int32 reserve = 7; + + int32 isolate = 8; +} |