1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 #define LOG_TAG "incident_helper" 17 18 #include <android/util/ProtoOutputStream.h> 19 20 #include "frameworks/base/core/proto/android/os/procrank.proto.h" 21 #include "ih_util.h" 22 #include "ProcrankParser.h" 23 24 using namespace android::os; 25 26 status_t 27 ProcrankParser::Parse(const int in, const int out) const 28 { 29 Reader reader(in); 30 string line; 31 header_t header; // the header of /d/wakeup_sources 32 record_t record; // retain each record 33 int nline = 0; 34 35 ProtoOutputStream proto; 36 Table table(ProcrankProto::Process::_FIELD_NAMES, ProcrankProto::Process::_FIELD_IDS, ProcrankProto::Process::_FIELD_COUNT); 37 string zram, ram, total; 38 39 // parse line by line 40 while (reader.readLine(&line)) { 41 if (line.empty()) continue; 42 43 // parse head line 44 if (nline++ == 0) { 45 header = parseHeader(line); 46 continue; 47 } 48 49 if (stripPrefix(&line, "ZRAM:")) { 50 zram = line; 51 continue; 52 } 53 if (stripPrefix(&line, "RAM:")) { 54 ram = line; 55 continue; 56 } 57 58 record = parseRecord(line); 59 if (record.size() != header.size()) { 60 if (record[record.size() - 1] == "TOTAL") { // TOTAL record 61 total = line; 62 } else { 63 fprintf(stderr, "[%s]Line %d has missing fields\n%s\n", this->name.string(), nline, 64 line.c_str()); 65 } 66 continue; 67 } 68 69 uint64_t token = proto.start(ProcrankProto::PROCESSES); 70 for (int i=0; i<(int)record.size(); i++) { 71 if (!table.insertField(&proto, header[i], record[i])) { 72 fprintf(stderr, "[%s]Line %d has bad value %s of %s\n", 73 this->name.string(), nline, header[i].c_str(), record[i].c_str()); 74 } 75 } 76 proto.end(token); 77 } 78 79 // add summary 80 uint64_t token = proto.start(ProcrankProto::SUMMARY); 81 if (!total.empty()) { 82 record = parseRecord(total); 83 uint64_t token = proto.start(ProcrankProto::Summary::TOTAL); 84 for (int i=(int)record.size(); i>0; i--) { 85 table.insertField(&proto, header[header.size() - i].c_str(), record[record.size() - i].c_str()); 86 } 87 proto.end(token); 88 } 89 if (!zram.empty()) { 90 uint64_t token = proto.start(ProcrankProto::Summary::ZRAM); 91 proto.write(ProcrankProto::Summary::Zram::RAW_TEXT, zram); 92 proto.end(token); 93 } 94 if (!ram.empty()) { 95 uint64_t token = proto.start(ProcrankProto::Summary::RAM); 96 proto.write(ProcrankProto::Summary::Ram::RAW_TEXT, ram); 97 proto.end(token); 98 } 99 proto.end(token); 100 101 if (!reader.ok(&line)) { 102 fprintf(stderr, "Bad read from fd %d: %s\n", in, line.c_str()); 103 return -1; 104 } 105 106 if (!proto.flush(out)) { 107 fprintf(stderr, "[%s]Error writing proto back\n", this->name.string()); 108 return -1; 109 } 110 fprintf(stderr, "[%s]Proto size: %zu bytes\n", this->name.string(), proto.size()); 111 return NO_ERROR; 112 } 113