1 /*
2 * Copyright (C) 2022 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 "pixelstats: BrownoutDetected"
18
19 #include <aidl/android/frameworks/stats/IStats.h>
20 #include <android-base/file.h>
21 #include <android-base/parseint.h>
22 #include <android-base/properties.h>
23 #include <android-base/stringprintf.h>
24 #include <android-base/strings.h>
25 #include <android/binder_manager.h>
26 #include <hardware/google/pixel/pixelstats/pixelatoms.pb.h>
27 #include <pixelstats/BrownoutDetectedReporter.h>
28 #include <time.h>
29 #include <utils/Log.h>
30
31 #include <map>
32 #include <regex>
33
34 namespace android {
35 namespace hardware {
36 namespace google {
37 namespace pixel {
38
39 using aidl::android::frameworks::stats::IStats;
40 using aidl::android::frameworks::stats::VendorAtom;
41 using aidl::android::frameworks::stats::VendorAtomValue;
42 using android::base::ReadFileToString;
43 using android::hardware::google::pixel::PixelAtoms::BrownoutDetected;
44
45 #define READING_IDX 2
46 #define KEY_IDX 0
47 #define DEFAULT_BATTERY_TEMP 9999999
48 #define DEFAULT_BATTERY_SOC 100
49 #define DEFAULT_BATTERY_VOLT 5000000
50 #define ONE_SECOND_IN_US 1000000
51
52 const std::regex kTimestampPattern("^\\S+\\s[0-9]+:[0-9]+:[0-9]+\\S+$");
53 const std::regex kIrqPattern("^(\\S+)\\striggered\\sat\\s\\S+$");
54 const std::regex kOdpmPattern("^CH\\d+\\[(\\S+)\\],\\s(\\d+)$");
55 const std::regex kDvfsPattern("^([A-Z1-9]+):(\\d+)$");
56 const std::regex kFgPattern("^(voltage_now):(\\d+)$");
57 const std::regex kBatteryTempPattern("^(battery):(\\d+)$");
58 const std::regex kBatteryCyclePattern("^(battery_cycle):(\\d+)$");
59 const std::regex kBatterySocPattern("^(soc):(\\d+)$");
60 const std::regex kAlreadyUpdatedPattern("^(LASTMEAL_UPDATED)$");
61
62 const std::map<std::string, int> kBrownoutReason = {{"uvlo,pmic,if", BrownoutDetected::UVLO_IF},
63 {"ocp,pmic,if", BrownoutDetected::OCP_IF},
64 {"ocp2,pmic,if", BrownoutDetected::OCP2_IF},
65 {"uvlo,pmic,main", BrownoutDetected::UVLO_MAIN},
66 {"uvlo,pmic,sub", BrownoutDetected::UVLO_SUB},
67 {"ocp,buck1m", BrownoutDetected::OCP_B1M},
68 {"ocp,buck2m", BrownoutDetected::OCP_B2M},
69 {"ocp,buck3m", BrownoutDetected::OCP_B3M},
70 {"ocp,buck4m", BrownoutDetected::OCP_B4M},
71 {"ocp,buck5m", BrownoutDetected::OCP_B5M},
72 {"ocp,buck6m", BrownoutDetected::OCP_B6M},
73 {"ocp,buck7m", BrownoutDetected::OCP_B7M},
74 {"ocp,buck8m", BrownoutDetected::OCP_B8M},
75 {"ocp,buck9m", BrownoutDetected::OCP_B9M},
76 {"ocp,buck10m", BrownoutDetected::OCP_B10M},
77 {"ocp,buck1s", BrownoutDetected::OCP_B1S},
78 {"ocp,buck2s", BrownoutDetected::OCP_B2S},
79 {"ocp,buck3s", BrownoutDetected::OCP_B3S},
80 {"ocp,buck4s", BrownoutDetected::OCP_B4S},
81 {"ocp,buck5s", BrownoutDetected::OCP_B5S},
82 {"ocp,buck6s", BrownoutDetected::OCP_B6S},
83 {"ocp,buck7s", BrownoutDetected::OCP_B7S},
84 {"ocp,buck8s", BrownoutDetected::OCP_B8S},
85 {"ocp,buck9s", BrownoutDetected::OCP_B9S},
86 {"ocp,buck10s", BrownoutDetected::OCP_B10S},
87 {"ocp,buckas", BrownoutDetected::OCP_BAS},
88 {"ocp,buckbs", BrownoutDetected::OCP_BBS},
89 {"ocp,buckcs", BrownoutDetected::OCP_BCS},
90 {"ocp,buckds", BrownoutDetected::OCP_BDS}};
91
updateIfFound(std::string line,std::regex pattern,int * current_value,Update flag)92 bool BrownoutDetectedReporter::updateIfFound(std::string line, std::regex pattern,
93 int *current_value, Update flag) {
94 bool found = false;
95 std::smatch pattern_match;
96 if (std::regex_match(line, pattern_match, pattern)) {
97 if (pattern_match.size() < (READING_IDX + 1)) {
98 return found;
99 }
100 found = true;
101 int reading = std::stoi(pattern_match[READING_IDX].str());
102 if (flag == kUpdateMax) {
103 if (*current_value < reading) {
104 *current_value = reading;
105 }
106 } else {
107 if (*current_value > reading) {
108 *current_value = reading;
109 }
110 }
111 }
112 return found;
113 }
114
setAtomFieldValue(std::vector<VendorAtomValue> & values,int offset,int content)115 void BrownoutDetectedReporter::setAtomFieldValue(std::vector<VendorAtomValue> &values, int offset,
116 int content) {
117 if (offset - kVendorAtomOffset < values.size()) {
118 ALOGW("VendorAtomValue size is smaller than offset");
119 values[offset - kVendorAtomOffset].set<VendorAtomValue::intValue>(content);
120 }
121 }
122
uploadData(const std::shared_ptr<IStats> & stats_client,const struct BrownoutDetectedInfo max_value)123 void BrownoutDetectedReporter::uploadData(const std::shared_ptr<IStats> &stats_client,
124 const struct BrownoutDetectedInfo max_value) {
125 // Load values array
126 VendorAtomValue tmp;
127 std::vector<VendorAtomValue> values(90);
128 setAtomFieldValue(values, BrownoutDetected::kTriggeredIrqFieldNumber, max_value.triggered_irq_);
129 setAtomFieldValue(values, BrownoutDetected::kTriggeredTimestampFieldNumber,
130 max_value.triggered_timestamp_);
131 setAtomFieldValue(values, BrownoutDetected::kBatteryTempFieldNumber, max_value.battery_temp_);
132 setAtomFieldValue(values, BrownoutDetected::kBatterySocFieldNumber,
133 100 - max_value.battery_soc_);
134 setAtomFieldValue(values, BrownoutDetected::kBatteryCycleFieldNumber, max_value.battery_cycle_);
135 setAtomFieldValue(values, BrownoutDetected::kVoltageNowFieldNumber, max_value.voltage_now_);
136
137 setAtomFieldValue(values, BrownoutDetected::kOdpmChannel01FieldNumber,
138 max_value.odpm_value_[0]);
139 setAtomFieldValue(values, BrownoutDetected::kOdpmChannel02FieldNumber,
140 max_value.odpm_value_[1]);
141 setAtomFieldValue(values, BrownoutDetected::kOdpmChannel03FieldNumber,
142 max_value.odpm_value_[2]);
143 setAtomFieldValue(values, BrownoutDetected::kOdpmChannel04FieldNumber,
144 max_value.odpm_value_[3]);
145 setAtomFieldValue(values, BrownoutDetected::kOdpmChannel05FieldNumber,
146 max_value.odpm_value_[4]);
147 setAtomFieldValue(values, BrownoutDetected::kOdpmChannel06FieldNumber,
148 max_value.odpm_value_[5]);
149 setAtomFieldValue(values, BrownoutDetected::kOdpmChannel07FieldNumber,
150 max_value.odpm_value_[6]);
151 setAtomFieldValue(values, BrownoutDetected::kOdpmChannel08FieldNumber,
152 max_value.odpm_value_[7]);
153 setAtomFieldValue(values, BrownoutDetected::kOdpmChannel09FieldNumber,
154 max_value.odpm_value_[8]);
155 setAtomFieldValue(values, BrownoutDetected::kOdpmChannel10FieldNumber,
156 max_value.odpm_value_[9]);
157 setAtomFieldValue(values, BrownoutDetected::kOdpmChannel11FieldNumber,
158 max_value.odpm_value_[10]);
159 setAtomFieldValue(values, BrownoutDetected::kOdpmChannel12FieldNumber,
160 max_value.odpm_value_[11]);
161 setAtomFieldValue(values, BrownoutDetected::kOdpmChannel13FieldNumber,
162 max_value.odpm_value_[12]);
163 setAtomFieldValue(values, BrownoutDetected::kOdpmChannel14FieldNumber,
164 max_value.odpm_value_[13]);
165 setAtomFieldValue(values, BrownoutDetected::kOdpmChannel15FieldNumber,
166 max_value.odpm_value_[14]);
167 setAtomFieldValue(values, BrownoutDetected::kOdpmChannel16FieldNumber,
168 max_value.odpm_value_[15]);
169 setAtomFieldValue(values, BrownoutDetected::kOdpmChannel17FieldNumber,
170 max_value.odpm_value_[16]);
171 setAtomFieldValue(values, BrownoutDetected::kOdpmChannel18FieldNumber,
172 max_value.odpm_value_[17]);
173 setAtomFieldValue(values, BrownoutDetected::kOdpmChannel19FieldNumber,
174 max_value.odpm_value_[18]);
175 setAtomFieldValue(values, BrownoutDetected::kOdpmChannel20FieldNumber,
176 max_value.odpm_value_[19]);
177 setAtomFieldValue(values, BrownoutDetected::kOdpmChannel21FieldNumber,
178 max_value.odpm_value_[20]);
179 setAtomFieldValue(values, BrownoutDetected::kOdpmChannel22FieldNumber,
180 max_value.odpm_value_[21]);
181 setAtomFieldValue(values, BrownoutDetected::kOdpmChannel23FieldNumber,
182 max_value.odpm_value_[22]);
183 setAtomFieldValue(values, BrownoutDetected::kOdpmChannel24FieldNumber,
184 max_value.odpm_value_[23]);
185
186 setAtomFieldValue(values, BrownoutDetected::kDvfsChannel1FieldNumber, max_value.dvfs_value_[0]);
187 setAtomFieldValue(values, BrownoutDetected::kDvfsChannel2FieldNumber, max_value.dvfs_value_[1]);
188 setAtomFieldValue(values, BrownoutDetected::kDvfsChannel3FieldNumber, max_value.dvfs_value_[2]);
189 setAtomFieldValue(values, BrownoutDetected::kDvfsChannel4FieldNumber, max_value.dvfs_value_[3]);
190 setAtomFieldValue(values, BrownoutDetected::kDvfsChannel5FieldNumber, max_value.dvfs_value_[4]);
191 setAtomFieldValue(values, BrownoutDetected::kDvfsChannel6FieldNumber, max_value.dvfs_value_[5]);
192 setAtomFieldValue(values, BrownoutDetected::kBrownoutReasonFieldNumber,
193 max_value.brownout_reason_);
194
195 setAtomFieldValue(values, BrownoutDetected::kMaxCurrentFieldNumber, max_value.max_curr_);
196 setAtomFieldValue(values, BrownoutDetected::kEvtCntUvlo1FieldNumber, max_value.evt_cnt_uvlo1_);
197 setAtomFieldValue(values, BrownoutDetected::kEvtCntUvlo2FieldNumber, max_value.evt_cnt_uvlo2_);
198 setAtomFieldValue(values, BrownoutDetected::kEvtCntOilo1FieldNumber, max_value.evt_cnt_oilo1_);
199 setAtomFieldValue(values, BrownoutDetected::kEvtCntOilo2FieldNumber, max_value.evt_cnt_oilo2_);
200 setAtomFieldValue(values, BrownoutDetected::kVimonVbattFieldNumber, max_value.vimon_vbatt_);
201 setAtomFieldValue(values, BrownoutDetected::kVimonIbattFieldNumber, max_value.vimon_ibatt_);
202
203 setAtomFieldValue(values, BrownoutDetected::kMitigationMethod0FieldNumber,
204 max_value.mitigation_method_0_);
205 setAtomFieldValue(values, BrownoutDetected::kMitigationMethod0CountFieldNumber,
206 max_value.mitigation_method_0_count_);
207 setAtomFieldValue(values, BrownoutDetected::kMitigationMethod0TimeUsFieldNumber,
208 max_value.mitigation_method_0_time_us_);
209
210 setAtomFieldValue(values, BrownoutDetected::kPreOcpCpu1BckupFieldNumber,
211 max_value.pre_ocp_cpu1_bckup_);
212 setAtomFieldValue(values, BrownoutDetected::kPreOcpCpu2BckupFieldNumber,
213 max_value.pre_ocp_cpu2_bckup_);
214 setAtomFieldValue(values, BrownoutDetected::kPreOcpTpuBckupFieldNumber,
215 max_value.pre_ocp_tpu_bckup_);
216 setAtomFieldValue(values, BrownoutDetected::kPreOcpGpuBckupFieldNumber,
217 max_value.pre_ocp_gpu_bckup_);
218 setAtomFieldValue(values, BrownoutDetected::kPreUvloHitCntMFieldNumber,
219 max_value.pre_uvlo_hit_cnt_m_);
220 setAtomFieldValue(values, BrownoutDetected::kPreUvloHitCntSFieldNumber,
221 max_value.pre_uvlo_hit_cnt_s_);
222 setAtomFieldValue(values, BrownoutDetected::kPreUvloDurFieldNumber, max_value.uvlo_dur_);
223
224 setAtomFieldValue(values, BrownoutDetected::kOdpmIrqStat0SysEvtMainBckupFieldNumber,
225 max_value.odpm_irq_stat_0_sys_evt_main_bckup_);
226 setAtomFieldValue(values, BrownoutDetected::kOdpmIrqStat1SysEvtMainBckupFieldNumber,
227 max_value.odpm_irq_stat_1_sys_evt_main_bckup_);
228 setAtomFieldValue(values, BrownoutDetected::kOdpmIrqStat2SysEvtMainBckupFieldNumber,
229 max_value.odpm_irq_stat_2_sys_evt_main_bckup_);
230 setAtomFieldValue(values, BrownoutDetected::kOdpmIrqStat3SysEvtMainBckupFieldNumber,
231 max_value.odpm_irq_stat_3_sys_evt_main_bckup_);
232 setAtomFieldValue(values, BrownoutDetected::kOdpmIrqStat4SysEvtMainBckupFieldNumber,
233 max_value.odpm_irq_stat_4_sys_evt_main_bckup_);
234 setAtomFieldValue(values, BrownoutDetected::kOdpmIrqStat5SysEvtMainBckupFieldNumber,
235 max_value.odpm_irq_stat_5_sys_evt_main_bckup_);
236 setAtomFieldValue(values, BrownoutDetected::kOdpmIrqStat6SysEvtMainBckupFieldNumber,
237 max_value.odpm_irq_stat_6_sys_evt_main_bckup_);
238 setAtomFieldValue(values, BrownoutDetected::kOdpmIrqStat7SysEvtMainBckupFieldNumber,
239 max_value.odpm_irq_stat_7_sys_evt_main_bckup_);
240 setAtomFieldValue(values, BrownoutDetected::kOdpmIrqStat8SysEvtMainBckupFieldNumber,
241 max_value.odpm_irq_stat_8_sys_evt_main_bckup_);
242 setAtomFieldValue(values, BrownoutDetected::kOdpmIrqStat9SysEvtMainBckupFieldNumber,
243 max_value.odpm_irq_stat_9_sys_evt_main_bckup_);
244 setAtomFieldValue(values, BrownoutDetected::kOdpmIrqStat10SysEvtMainBckupFieldNumber,
245 max_value.odpm_irq_stat_10_sys_evt_main_bckup_);
246 setAtomFieldValue(values, BrownoutDetected::kOdpmIrqStat11SysEvtMainBckupFieldNumber,
247 max_value.odpm_irq_stat_11_sys_evt_main_bckup_);
248
249 setAtomFieldValue(values, BrownoutDetected::kOdpmIrqStat0SysEvtSubBckupFieldNumber,
250 max_value.odpm_irq_stat_0_sys_evt_sub_bckup_);
251 setAtomFieldValue(values, BrownoutDetected::kOdpmIrqStat1SysEvtSubBckupFieldNumber,
252 max_value.odpm_irq_stat_1_sys_evt_sub_bckup_);
253 setAtomFieldValue(values, BrownoutDetected::kOdpmIrqStat2SysEvtSubBckupFieldNumber,
254 max_value.odpm_irq_stat_2_sys_evt_sub_bckup_);
255 setAtomFieldValue(values, BrownoutDetected::kOdpmIrqStat3SysEvtSubBckupFieldNumber,
256 max_value.odpm_irq_stat_3_sys_evt_sub_bckup_);
257 setAtomFieldValue(values, BrownoutDetected::kOdpmIrqStat4SysEvtSubBckupFieldNumber,
258 max_value.odpm_irq_stat_4_sys_evt_sub_bckup_);
259 setAtomFieldValue(values, BrownoutDetected::kOdpmIrqStat5SysEvtSubBckupFieldNumber,
260 max_value.odpm_irq_stat_5_sys_evt_sub_bckup_);
261 setAtomFieldValue(values, BrownoutDetected::kOdpmIrqStat6SysEvtSubBckupFieldNumber,
262 max_value.odpm_irq_stat_6_sys_evt_sub_bckup_);
263 setAtomFieldValue(values, BrownoutDetected::kOdpmIrqStat7SysEvtSubBckupFieldNumber,
264 max_value.odpm_irq_stat_7_sys_evt_sub_bckup_);
265 setAtomFieldValue(values, BrownoutDetected::kOdpmIrqStat8SysEvtSubBckupFieldNumber,
266 max_value.odpm_irq_stat_8_sys_evt_sub_bckup_);
267 setAtomFieldValue(values, BrownoutDetected::kOdpmIrqStat9SysEvtSubBckupFieldNumber,
268 max_value.odpm_irq_stat_9_sys_evt_sub_bckup_);
269 setAtomFieldValue(values, BrownoutDetected::kOdpmIrqStat10SysEvtSubBckupFieldNumber,
270 max_value.odpm_irq_stat_10_sys_evt_sub_bckup_);
271 setAtomFieldValue(values, BrownoutDetected::kOdpmIrqStat11SysEvtSubBckupFieldNumber,
272 max_value.odpm_irq_stat_11_sys_evt_sub_bckup_);
273
274 setAtomFieldValue(values, BrownoutDetected::kOdpmIrqStatExt0SysEvtMainBckupFieldNumber,
275 max_value.odpm_irq_stat_ext_0_sys_evt_main_bckup_);
276 setAtomFieldValue(values, BrownoutDetected::kOdpmIrqStatExt1SysEvtMainBckupFieldNumber,
277 max_value.odpm_irq_stat_ext_1_sys_evt_main_bckup_);
278 setAtomFieldValue(values, BrownoutDetected::kOdpmIrqStatExt2SysEvtMainBckupFieldNumber,
279 max_value.odpm_irq_stat_ext_2_sys_evt_main_bckup_);
280 setAtomFieldValue(values, BrownoutDetected::kOdpmIrqStatExt3SysEvtMainBckupFieldNumber,
281 max_value.odpm_irq_stat_ext_3_sys_evt_main_bckup_);
282
283 setAtomFieldValue(values, BrownoutDetected::kOdpmIrqStatExt0SysEvtSubBckupFieldNumber,
284 max_value.odpm_irq_stat_ext_0_sys_evt_sub_bckup_);
285 setAtomFieldValue(values, BrownoutDetected::kOdpmIrqStatExt1SysEvtSubBckupFieldNumber,
286 max_value.odpm_irq_stat_ext_1_sys_evt_sub_bckup_);
287 setAtomFieldValue(values, BrownoutDetected::kOdpmIrqStatExt2SysEvtSubBckupFieldNumber,
288 max_value.odpm_irq_stat_ext_2_sys_evt_sub_bckup_);
289 setAtomFieldValue(values, BrownoutDetected::kOdpmIrqStatExt3SysEvtSubBckupFieldNumber,
290 max_value.odpm_irq_stat_ext_3_sys_evt_sub_bckup_);
291
292 setAtomFieldValue(values, BrownoutDetected::kOdpmIrqStatGpuBckupFieldNumber,
293 max_value.odpm_irq_stat_gpu_bckup_);
294 setAtomFieldValue(values, BrownoutDetected::kOdpmIrqStatTpuBckupFieldNumber,
295 max_value.odpm_irq_stat_tpu_bckup_);
296 setAtomFieldValue(values, BrownoutDetected::kOdpmIrqStatCpu1BckupFieldNumber,
297 max_value.odpm_irq_stat_cpu1_bckup_);
298 setAtomFieldValue(values, BrownoutDetected::kOdpmIrqStatCpu2BckupFieldNumber,
299 max_value.odpm_irq_stat_cpu2_bckup_);
300
301 // Send vendor atom to IStats HAL
302 VendorAtom event = {.reverseDomainName = "",
303 .atomId = PixelAtoms::Atom::kBrownoutDetected,
304 .values = std::move(values)};
305 const ndk::ScopedAStatus ret = stats_client->reportVendorAtom(event);
306 if (!ret.isOk())
307 ALOGE("Unable to report ChargeStats to Stats service");
308 }
309
parseTimestamp(std::string timestamp)310 long BrownoutDetectedReporter::parseTimestamp(std::string timestamp) {
311 struct tm triggeredTimestamp = {};
312 std::string timestampFormat = "%Y-%m-%d %H:%M:%S";
313 if (strptime(timestamp.substr(0, 19).c_str(), timestampFormat.c_str(), &triggeredTimestamp)) {
314 auto logFileTime = std::chrono::system_clock::from_time_t(mktime(&triggeredTimestamp));
315 return logFileTime.time_since_epoch().count() / ONE_SECOND_IN_US;
316 }
317 return 0;
318 }
319
brownoutReasonCheck(const std::string & brownoutReasonProp)320 int BrownoutDetectedReporter::brownoutReasonCheck(const std::string &brownoutReasonProp) {
321 std::string reason = android::base::GetProperty(brownoutReasonProp.c_str(), "");
322 if (reason.empty()) {
323 // Brownout not found
324 return -1;
325 }
326 auto key = kBrownoutReason.find(reason);
327 if (key == kBrownoutReason.end()) {
328 return -1;
329 }
330 return key->second;
331 }
332
parseIRQ(const std::string & element)333 int parseIRQ(const std::string &element) {
334 int idx = atoi(element.c_str());
335 if (idx == SMPL_WARN) {
336 return BrownoutDetected::SMPL_WARN;
337 } else if (idx == UVLO1) {
338 return BrownoutDetected::UVLO1;
339 } else if (idx == UVLO2) {
340 return BrownoutDetected::UVLO2;
341 } else if (idx == BATOILO) {
342 return BrownoutDetected::BATOILO;
343 } else if (idx == BATOILO2) {
344 return BrownoutDetected::BATOILO2;
345 }
346 return -1;
347 }
348
logBrownoutCsv(const std::shared_ptr<IStats> & stats_client,const std::string & CsvFilePath,const std::string & brownoutReasonProp)349 void BrownoutDetectedReporter::logBrownoutCsv(const std::shared_ptr<IStats> &stats_client,
350 const std::string &CsvFilePath,
351 const std::string &brownoutReasonProp) {
352 std::string csvFile;
353 if (!android::base::ReadFileToString(CsvFilePath, &csvFile)) {
354 return;
355 }
356 std::istringstream content(csvFile);
357 std::string line;
358 struct BrownoutDetectedInfo max_value = {};
359 max_value.voltage_now_ = DEFAULT_BATTERY_VOLT;
360 max_value.battery_soc_ = DEFAULT_BATTERY_SOC;
361 max_value.battery_temp_ = DEFAULT_BATTERY_TEMP;
362 std::smatch pattern_match;
363 max_value.brownout_reason_ = brownoutReasonCheck(brownoutReasonProp);
364 if (max_value.brownout_reason_ < 0) {
365 return;
366 }
367 bool isAlreadyUpdated = false;
368 std::vector<std::vector<std::string>> rows;
369 int row_num = 0;
370 while (std::getline(content, line)) {
371 if (std::regex_match(line, pattern_match, kAlreadyUpdatedPattern)) {
372 isAlreadyUpdated = true;
373 break;
374 }
375 row_num++;
376 if (row_num == 1) {
377 continue;
378 }
379 std::vector<std::string> row;
380 std::stringstream ss(line);
381 std::string field;
382 while (getline(ss, field, ',')) {
383 row.push_back(field);
384 }
385
386 max_value.triggered_timestamp_ = parseTimestamp(row[TIMESTAMP_IDX].c_str());
387 max_value.triggered_irq_ = parseIRQ(row[IRQ_IDX]);
388 max_value.battery_soc_ = atoi(row[SOC_IDX].c_str());
389 max_value.battery_temp_ = atoi(row[TEMP_IDX].c_str());
390 max_value.battery_cycle_ = atoi(row[CYCLE_IDX].c_str());
391 max_value.voltage_now_ = atoi(row[VOLTAGE_IDX].c_str());
392 for (int i = 0; i < DVFS_MAX_IDX; i++) {
393 max_value.dvfs_value_[i] = atoi(row[i + DVFS_CHANNEL_0].c_str());
394 }
395 for (int i = 0; i < ODPM_MAX_IDX; i++) {
396 max_value.odpm_value_[i] = atoi(row[i + ODPM_CHANNEL_0].c_str());
397 }
398 if (row.size() > MAX_CURR) {
399 max_value.evt_cnt_oilo1_ = atoi(row[EVT_CNT_IDX_OILO1].c_str());
400 max_value.evt_cnt_oilo2_ = atoi(row[EVT_CNT_IDX_OILO2].c_str());
401 max_value.evt_cnt_uvlo1_ = atoi(row[EVT_CNT_IDX_UVLO1].c_str());
402 max_value.evt_cnt_uvlo2_ = atoi(row[EVT_CNT_IDX_UVLO2].c_str());
403 max_value.max_curr_ = atoi(row[MAX_CURR].c_str());
404 }
405 if (row.size() > IDX_VIMON_I) {
406 max_value.vimon_vbatt_ = atoi(row[IDX_VIMON_V].c_str());
407 max_value.vimon_ibatt_ = atoi(row[IDX_VIMON_I].c_str());
408 }
409 if (row.size() > UVLO_DUR_IDX) {
410 max_value.pre_ocp_cpu1_bckup_ = atoi(row[PRE_OCP_CPU1_BCKUP_IDX].c_str());
411 max_value.pre_ocp_cpu2_bckup_ = atoi(row[PRE_OCP_CPU2_BCKUP_IDX].c_str());
412 max_value.pre_ocp_tpu_bckup_ = atoi(row[PRE_OCP_TPU_BCKUP_IDX].c_str());
413 max_value.pre_ocp_gpu_bckup_ = atoi(row[PRE_OCP_GPU_BCKUP_IDX].c_str());
414 max_value.pre_uvlo_hit_cnt_m_ = atoi(row[PRE_UVLO_HIT_CNT_M_IDX].c_str());
415 max_value.pre_uvlo_hit_cnt_s_ = atoi(row[PRE_UVLO_HIT_CNT_S_IDX].c_str());
416 max_value.uvlo_dur_ = atoi(row[UVLO_DUR_IDX].c_str());
417 }
418 if (row.size() > ODPM_IRQ_STAT_CPU2_BCKUP_IDX) {
419 max_value.pre_ocp_cpu1_bckup_ = atoi(row[PRE_OCP_CPU1_BCKUP_IDX].c_str());
420 max_value.pre_ocp_cpu2_bckup_ = atoi(row[PRE_OCP_CPU2_BCKUP_IDX].c_str());
421
422 max_value.odpm_irq_stat_0_sys_evt_main_bckup_ =
423 atoi(row[ODPM_IRQ_STAT_0_SYS_EVT_MAIN_BCKUP_IDX].c_str());
424 max_value.odpm_irq_stat_1_sys_evt_main_bckup_ =
425 atoi(row[ODPM_IRQ_STAT_1_SYS_EVT_MAIN_BCKUP_IDX].c_str());
426 max_value.odpm_irq_stat_2_sys_evt_main_bckup_ =
427 atoi(row[ODPM_IRQ_STAT_2_SYS_EVT_MAIN_BCKUP_IDX].c_str());
428 max_value.odpm_irq_stat_3_sys_evt_main_bckup_ =
429 atoi(row[ODPM_IRQ_STAT_3_SYS_EVT_MAIN_BCKUP_IDX].c_str());
430 max_value.odpm_irq_stat_4_sys_evt_main_bckup_ =
431 atoi(row[ODPM_IRQ_STAT_4_SYS_EVT_MAIN_BCKUP_IDX].c_str());
432 max_value.odpm_irq_stat_5_sys_evt_main_bckup_ =
433 atoi(row[ODPM_IRQ_STAT_5_SYS_EVT_MAIN_BCKUP_IDX].c_str());
434 max_value.odpm_irq_stat_6_sys_evt_main_bckup_ =
435 atoi(row[ODPM_IRQ_STAT_6_SYS_EVT_MAIN_BCKUP_IDX].c_str());
436 max_value.odpm_irq_stat_7_sys_evt_main_bckup_ =
437 atoi(row[ODPM_IRQ_STAT_7_SYS_EVT_MAIN_BCKUP_IDX].c_str());
438 max_value.odpm_irq_stat_8_sys_evt_main_bckup_ =
439 atoi(row[ODPM_IRQ_STAT_8_SYS_EVT_MAIN_BCKUP_IDX].c_str());
440 max_value.odpm_irq_stat_9_sys_evt_main_bckup_ =
441 atoi(row[ODPM_IRQ_STAT_9_SYS_EVT_MAIN_BCKUP_IDX].c_str());
442 max_value.odpm_irq_stat_10_sys_evt_main_bckup_ =
443 atoi(row[ODPM_IRQ_STAT_10_SYS_EVT_MAIN_BCKUP_IDX].c_str());
444 max_value.odpm_irq_stat_11_sys_evt_main_bckup_ =
445 atoi(row[ODPM_IRQ_STAT_11_SYS_EVT_MAIN_BCKUP_IDX].c_str());
446
447 max_value.odpm_irq_stat_0_sys_evt_sub_bckup_ =
448 atoi(row[ODPM_IRQ_STAT_0_SYS_EVT_SUB_BCKUP_IDX].c_str());
449 max_value.odpm_irq_stat_1_sys_evt_sub_bckup_ =
450 atoi(row[ODPM_IRQ_STAT_1_SYS_EVT_SUB_BCKUP_IDX].c_str());
451 max_value.odpm_irq_stat_2_sys_evt_sub_bckup_ =
452 atoi(row[ODPM_IRQ_STAT_2_SYS_EVT_SUB_BCKUP_IDX].c_str());
453 max_value.odpm_irq_stat_3_sys_evt_sub_bckup_ =
454 atoi(row[ODPM_IRQ_STAT_3_SYS_EVT_SUB_BCKUP_IDX].c_str());
455 max_value.odpm_irq_stat_4_sys_evt_sub_bckup_ =
456 atoi(row[ODPM_IRQ_STAT_4_SYS_EVT_SUB_BCKUP_IDX].c_str());
457 max_value.odpm_irq_stat_5_sys_evt_sub_bckup_ =
458 atoi(row[ODPM_IRQ_STAT_5_SYS_EVT_SUB_BCKUP_IDX].c_str());
459 max_value.odpm_irq_stat_6_sys_evt_sub_bckup_ =
460 atoi(row[ODPM_IRQ_STAT_6_SYS_EVT_SUB_BCKUP_IDX].c_str());
461 max_value.odpm_irq_stat_7_sys_evt_sub_bckup_ =
462 atoi(row[ODPM_IRQ_STAT_7_SYS_EVT_SUB_BCKUP_IDX].c_str());
463 max_value.odpm_irq_stat_8_sys_evt_sub_bckup_ =
464 atoi(row[ODPM_IRQ_STAT_8_SYS_EVT_SUB_BCKUP_IDX].c_str());
465 max_value.odpm_irq_stat_9_sys_evt_sub_bckup_ =
466 atoi(row[ODPM_IRQ_STAT_9_SYS_EVT_SUB_BCKUP_IDX].c_str());
467 max_value.odpm_irq_stat_10_sys_evt_sub_bckup_ =
468 atoi(row[ODPM_IRQ_STAT_10_SYS_EVT_SUB_BCKUP_IDX].c_str());
469 max_value.odpm_irq_stat_11_sys_evt_sub_bckup_ =
470 atoi(row[ODPM_IRQ_STAT_11_SYS_EVT_SUB_BCKUP_IDX].c_str());
471
472 max_value.odpm_irq_stat_ext_0_sys_evt_main_bckup_ =
473 atoi(row[ODPM_IRQ_STAT_EXT_0_SYS_EVT_MAIN_BCKUP_IDX].c_str());
474 max_value.odpm_irq_stat_ext_1_sys_evt_main_bckup_ =
475 atoi(row[ODPM_IRQ_STAT_EXT_1_SYS_EVT_MAIN_BCKUP_IDX].c_str());
476 max_value.odpm_irq_stat_ext_2_sys_evt_main_bckup_ =
477 atoi(row[ODPM_IRQ_STAT_EXT_2_SYS_EVT_MAIN_BCKUP_IDX].c_str());
478 max_value.odpm_irq_stat_ext_3_sys_evt_main_bckup_ =
479 atoi(row[ODPM_IRQ_STAT_EXT_3_SYS_EVT_MAIN_BCKUP_IDX].c_str());
480
481 max_value.odpm_irq_stat_ext_0_sys_evt_sub_bckup_ =
482 atoi(row[ODPM_IRQ_STAT_EXT_0_SYS_EVT_SUB_BCKUP_IDX].c_str());
483 max_value.odpm_irq_stat_ext_1_sys_evt_sub_bckup_ =
484 atoi(row[ODPM_IRQ_STAT_EXT_1_SYS_EVT_SUB_BCKUP_IDX].c_str());
485 max_value.odpm_irq_stat_ext_2_sys_evt_sub_bckup_ =
486 atoi(row[ODPM_IRQ_STAT_EXT_2_SYS_EVT_SUB_BCKUP_IDX].c_str());
487 max_value.odpm_irq_stat_ext_3_sys_evt_sub_bckup_ =
488 atoi(row[ODPM_IRQ_STAT_EXT_3_SYS_EVT_SUB_BCKUP_IDX].c_str());
489 }
490 }
491 if (!isAlreadyUpdated && max_value.battery_temp_ != DEFAULT_BATTERY_TEMP) {
492 std::string file_content = "LASTMEAL_UPDATED\n" + csvFile;
493 android::base::WriteStringToFile(file_content, CsvFilePath);
494 uploadData(stats_client, max_value);
495 }
496 }
497
logBrownout(const std::shared_ptr<IStats> & stats_client,const std::string & logFilePath,const std::string & brownoutReasonProp)498 void BrownoutDetectedReporter::logBrownout(const std::shared_ptr<IStats> &stats_client,
499 const std::string &logFilePath,
500 const std::string &brownoutReasonProp) {
501 std::string logFile;
502 if (!android::base::ReadFileToString(logFilePath, &logFile)) {
503 return;
504 }
505 std::istringstream content(logFile);
506 std::string line;
507 struct BrownoutDetectedInfo max_value = {};
508 max_value.voltage_now_ = DEFAULT_BATTERY_VOLT;
509 max_value.battery_soc_ = DEFAULT_BATTERY_SOC;
510 max_value.battery_temp_ = DEFAULT_BATTERY_TEMP;
511 std::smatch pattern_match;
512 int odpm_index = 0, dvfs_index = 0;
513 max_value.brownout_reason_ = brownoutReasonCheck(brownoutReasonProp);
514 if (max_value.brownout_reason_ < 0) {
515 return;
516 }
517 bool isAlreadyUpdated = false;
518 while (std::getline(content, line)) {
519 if (std::regex_match(line, pattern_match, kAlreadyUpdatedPattern)) {
520 isAlreadyUpdated = true;
521 break;
522 }
523 if (std::regex_match(line, pattern_match, kIrqPattern)) {
524 if (pattern_match.size() < (KEY_IDX + 1)) {
525 return;
526 }
527 std::ssub_match irq = pattern_match[KEY_IDX];
528 if (irq.str().find("batoilo") != std::string::npos) {
529 max_value.triggered_irq_ = BrownoutDetected::BATOILO;
530 continue;
531 }
532 if (irq.str().find("vdroop1") != std::string::npos) {
533 max_value.triggered_irq_ = BrownoutDetected::UVLO1;
534 continue;
535 }
536 if (irq.str().find("vdroop2") != std::string::npos) {
537 max_value.triggered_irq_ = BrownoutDetected::UVLO2;
538 continue;
539 }
540 if (irq.str().find("smpl_gm") != std::string::npos) {
541 max_value.triggered_irq_ = BrownoutDetected::SMPL_WARN;
542 continue;
543 }
544 continue;
545 }
546 if (std::regex_match(line, pattern_match, kTimestampPattern)) {
547 max_value.triggered_timestamp_ = parseTimestamp(line.c_str());
548 continue;
549 }
550 if (updateIfFound(line, kBatterySocPattern, &max_value.battery_soc_, kUpdateMin)) {
551 continue;
552 }
553 if (updateIfFound(line, kBatteryTempPattern, &max_value.battery_temp_, kUpdateMin)) {
554 continue;
555 }
556 if (updateIfFound(line, kBatteryCyclePattern, &max_value.battery_cycle_, kUpdateMax)) {
557 continue;
558 }
559 if (updateIfFound(line, kFgPattern, &max_value.voltage_now_, kUpdateMin)) {
560 continue;
561 }
562 if (updateIfFound(line, kDvfsPattern, &max_value.dvfs_value_[dvfs_index], kUpdateMax)) {
563 dvfs_index++;
564 // Discarding previous value and update with new DVFS value
565 if (dvfs_index == DVFS_MAX_IDX) {
566 dvfs_index = 0;
567 }
568 continue;
569 }
570 if (updateIfFound(line, kOdpmPattern, &max_value.odpm_value_[odpm_index], kUpdateMax)) {
571 odpm_index++;
572 // Discarding previous value and update with new ODPM value
573 if (odpm_index == ODPM_MAX_IDX) {
574 odpm_index = 0;
575 }
576 continue;
577 }
578 }
579 if (!isAlreadyUpdated && max_value.battery_temp_ != DEFAULT_BATTERY_TEMP) {
580 std::string file_content = "LASTMEAL_UPDATED\n" + logFile;
581 android::base::WriteStringToFile(file_content, logFilePath);
582 uploadData(stats_client, max_value);
583 }
584 }
585
586 } // namespace pixel
587 } // namespace google
588 } // namespace hardware
589 } // namespace android
590