• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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