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
25 using namespace android::os;
26
27 status_t
Parse(const int in,const int out) const28 CpuFreqParser::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