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#include <unistd.h> 20 21#include "frameworks/base/core/proto/android/os/cpufreq.proto.h" 22#include "ih_util.h" 23#include "CpuFreqParser.h" 24 25using namespace android::os; 26 27status_t 28CpuFreqParser::Parse(const int in, const int out) const 29{ 30 Reader reader(in); 31 string line; 32 33 // parse header 34 reader.readLine(&line); 35 header_t header = parseHeader(line, TAB_DELIMITER); 36 if (header.size() < 1) { 37 fprintf(stderr, "Bad header: %s\n", line.c_str()); 38 return BAD_VALUE; 39 } 40 const int numCpus = (int)header.size() - 1; 41 vector<pair<int, long long>> cpucores[numCpus]; 42 43 // parse freq and time 44 while (reader.readLine(&line)) { 45 if (line.empty()) continue; 46 47 record_t record = parseRecord(line, TAB_DELIMITER); 48 if (record.size() != header.size()) { 49 fprintf(stderr, "Bad line: %s\n", line.c_str()); 50 continue; 51 } 52 53 int freq = toInt(record[0]); 54 for (int i=0; i<numCpus; i++) { 55 if (strcmp(record[i+1].c_str(), "N/A") == 0) { 56 continue; 57 } 58 cpucores[i].push_back(make_pair(freq, toLongLong(record[i+1]))); 59 } 60 } 61 62 ProtoOutputStream proto; 63 64 long jiffyHz = sysconf(_SC_CLK_TCK); 65 proto.write(CpuFreqProto::JIFFY_HZ, (int)jiffyHz); 66 67 for (int i=0; i<numCpus; i++) { 68 uint64_t token = proto.start(CpuFreqProto::CPU_FREQS); 69 proto.write(CpuFreqProto::Stats::CPU_NAME, header[i+1]); 70 for (vector<pair<int, long long>>::iterator it = cpucores[i].begin(); it != cpucores[i].end(); it++) { 71 uint64_t stateToken = proto.start(CpuFreqProto::Stats::TIMES); 72 proto.write(CpuFreqProto::Stats::TimeInState::STATE_KHZ, it->first); 73 proto.write(CpuFreqProto::Stats::TimeInState::TIME_JIFFY, it->second); 74 proto.end(stateToken); 75 } 76 proto.end(token); 77 } 78 79 if (!reader.ok(&line)) { 80 fprintf(stderr, "Bad read from fd %d: %s\n", in, line.c_str()); 81 return -1; 82 } 83 84 if (!proto.flush(out)) { 85 fprintf(stderr, "[%s]Error writing proto back\n", this->name.string()); 86 return -1; 87 } 88 fprintf(stderr, "[%s]Proto size: %zu bytes\n", this->name.string(), proto.size()); 89 return NO_ERROR; 90} 91