blob: 89d89471369067342e92de322ab4d54e5cb78c25 [file] [log] [blame]
Yi Jin0a3406f2017-06-22 19:23:11 -07001/*
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
17#define LOG_TAG "incident_helper"
18
19#include "IncidentHelper.h"
20#include "strutil.h"
21
22#include "frameworks/base/core/proto/android/os/kernelwake.pb.h"
23
24#include <algorithm>
25#include <android-base/file.h>
26#include <unistd.h>
27#include <sstream>
28#include <string>
29#include <vector>
30
31using namespace android::base;
32using namespace android::os;
33using namespace std;
34
35// ================================================================================
36status_t ReverseParser::Parse(const int in, const int out) const
37{
38 string content;
39 if (!ReadFdToString(in, &content)) {
40 fprintf(stderr, "[%s]Failed to read data from incidentd\n", this->name.string());
41 return -1;
42 }
43 // reverse the content
44 reverse(content.begin(), content.end());
45 if (!WriteStringToFd(content, out)) {
46 fprintf(stderr, "[%s]Failed to write data to incidentd\n", this->name.string());
47 return -1;
48 }
49 return NO_ERROR;
50}
51
52// ================================================================================
53// This list must be in order and sync with kernelwake.proto
54const char* kernel_wake_headers[] = {
55 "name", // id: 1
56 "active_count", // id: 2
57 "event_count", // id: 3
58 "wakeup_count", // id: 4
59 "expire_count", // id: 5
60 "active_since", // id: 6
61 "total_time", // id: 7
62 "max_time", // id: 8
63 "last_change", // id: 9
64 "prevent_suspend_time", // id: 10
65};
66
67const string KERNEL_WAKEUP_LINE_DELIMITER = "\t";
68
69status_t KernelWakesParser::Parse(const int in, const int out) const {
70 // read the content, this is not memory-efficient though since it loads everything
71 // However the data will be held in proto anyway, and incident_helper is less critical
72 string content;
73 if (!ReadFdToString(in, &content)) {
74 fprintf(stderr, "[%s]Failed to read data from incidentd\n", this->name.string());
75 return -1;
76 }
77
78 istringstream iss(content);
79 string line;
80 vector<string> header; // the header of /d/wakeup_sources
81 vector<string> record; // retain each record
82 int nline = 0;
83
84 KernelWakeSources proto;
85
86 // parse line by line
87 while (getline(iss, line)) {
88 // parse head line
89 if (nline == 0) {
90 split(line, &header);
91 if (!assertHeaders(kernel_wake_headers, header)) {
92 fprintf(stderr, "[%s]Bad header:\n%s\n", this->name.string(), line.c_str());
93 return BAD_VALUE;
94 }
95 nline++;
96 continue;
97 }
98
99 // parse for each record, the line delimiter is \t only!
100 split(line, &record, KERNEL_WAKEUP_LINE_DELIMITER);
101
102 if (record.size() != header.size()) {
103 // TODO: log this to incident report!
104 fprintf(stderr, "[%s]Line %d has missing fields\n%s\n", this->name.string(), nline, line.c_str());
105 continue;
106 }
107
108 WakeupSourceProto* source = proto.add_wakeup_sources();
109 source->set_name(record.at(0).c_str());
110 // below are int32
111 source->set_active_count(atoi(record.at(1).c_str()));
112 source->set_event_count(atoi(record.at(2).c_str()));
113 source->set_wakeup_count(atoi(record.at(3).c_str()));
114 source->set_expire_count(atoi(record.at(4).c_str()));
115 // below are int64
116 source->set_active_since(atol(record.at(5).c_str()));
117 source->set_total_time(atol(record.at(6).c_str()));
118 source->set_max_time(atol(record.at(7).c_str()));
119 source->set_last_change(atol(record.at(8).c_str()));
120 source->set_prevent_suspend_time(atol(record.at(9).c_str()));
121
122 nline++;
123 }
124
125 fprintf(stderr, "[%s]Proto size: %d bytes\n", this->name.string(), proto.ByteSize());
126
127 if (!proto.SerializeToFileDescriptor(out)) {
128 fprintf(stderr, "[%s]Error writing proto back\n", this->name.string());
129 return -1;
130 }
131 close(out);
132
133 return NO_ERROR;
134}