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/kernelwake.proto.h" 21#include "ih_util.h" 22#include "KernelWakesParser.h" 23 24using namespace android::os; 25 26status_t 27KernelWakesParser::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(KernelWakeSourcesProto::WakeupSource::_FIELD_NAMES, 37 KernelWakeSourcesProto::WakeupSource::_FIELD_IDS, 38 KernelWakeSourcesProto::WakeupSource::_FIELD_COUNT); 39 40 // parse line by line 41 while (reader.readLine(&line)) { 42 if (line.empty()) continue; 43 // parse head line 44 if (nline++ == 0) { 45 header = parseHeader(line, TAB_DELIMITER); 46 continue; 47 } 48 49 // parse for each record, the line delimiter is \t only! 50 record = parseRecord(line, TAB_DELIMITER); 51 52 if (record.size() < header.size()) { 53 // TODO: log this to incident report! 54 fprintf(stderr, "[%s]Line %d has missing fields\n%s\n", this->name.string(), nline, line.c_str()); 55 continue; 56 } else if (record.size() > header.size()) { 57 // TODO: log this to incident report! 58 fprintf(stderr, "[%s]Line %d has extra fields\n%s\n", this->name.string(), nline, line.c_str()); 59 continue; 60 } 61 62 uint64_t token = proto.start(KernelWakeSourcesProto::WAKEUP_SOURCES); 63 for (int i=0; i<(int)record.size(); i++) { 64 if (!table.insertField(&proto, header[i], record[i])) { 65 fprintf(stderr, "[%s]Line %d has bad value %s of %s\n", 66 this->name.string(), nline, header[i].c_str(), record[i].c_str()); 67 } 68 } 69 proto.end(token); 70 } 71 72 if (!reader.ok(&line)) { 73 fprintf(stderr, "Bad read from fd %d: %s\n", in, line.c_str()); 74 return -1; 75 } 76 77 if (!proto.flush(out)) { 78 fprintf(stderr, "[%s]Error writing proto back\n", this->name.string()); 79 return -1; 80 } 81 fprintf(stderr, "[%s]Proto size: %zu bytes\n", this->name.string(), proto.size()); 82 return NO_ERROR; 83} 84