1 /*
2 * Copyright (C) 2019 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 "pwrstats_util"
17
18 #include "CstateResidencyDataProvider.h"
19 #include <dataproviders/DataProviderHelper.h>
20
21 #include <regex>
22 #include <string>
23 #include <fstream>
24 #include <iostream>
25 #include <string>
26
27 #include <android-base/parsedouble.h>
28 #include <android-base/logging.h>
29
getImpl(PowerStatistic * stat) const30 int CstateResidencyDataProvider::getImpl(PowerStatistic* stat) const {
31 std::ifstream file("/sys/kernel/debug/lpm_stats/stats");
32
33 std::smatch matches;
34 const std::regex searchExpr("\\[(.*?)\\] (.*?):");
35 std::string line;
36 const std::string searchStr = "total success time:";
37
38 auto residencies = stat->mutable_c_state_residency();
39 while (std::getline(file, line)) {
40 if (std::regex_search(line, matches, searchExpr)) {
41 auto residency = residencies->add_residency();
42 residency->set_entity_name(matches[1]);
43 residency->set_state_name(matches[2]);
44
45 while (std::getline(file, line)) {
46 size_t pos = line.find(searchStr);
47 if (pos != std::string::npos) {
48 float val;
49 if (android::base::ParseFloat(line.substr(pos + searchStr.size()), &val)) {
50 residency->set_time_ms(static_cast<uint64_t>(val * 1000));
51 } else {
52 LOG(ERROR) << __func__ << ": failed to parse c-state data";
53 }
54 break;
55 }
56 }
57 }
58 }
59
60 // Sort entries first by entity_name, then by state_name.
61 // Sorting is needed to make interval processing efficient.
62 std::sort(residencies->mutable_residency()->begin(),
63 residencies->mutable_residency()->end(),
64 [](const auto& a, const auto& b) {
65 // First sort by entity_name, then by state_name
66 if (a.entity_name() != b.entity_name()) {
67 return a.entity_name() < b.entity_name();
68 }
69
70 return a.state_name() < b.state_name();
71 });
72 return 0;
73 }
74
getImpl(const PowerStatistic & start,PowerStatistic * interval) const75 int CstateResidencyDataProvider::getImpl(const PowerStatistic& start, PowerStatistic* interval) const {
76 auto startResidency = start.c_state_residency().residency();
77 auto intervalResidency = interval->mutable_c_state_residency()->mutable_residency();
78
79 if (0 != StateResidencyInterval(startResidency, intervalResidency)) {
80 interval->clear_c_state_residency();
81 return 1;
82 }
83
84 return 0;
85 }
86
dumpImpl(const PowerStatistic & stat,std::ostream * output) const87 void CstateResidencyDataProvider::dumpImpl(const PowerStatistic& stat,
88 std::ostream* output) const {
89 *output << "C-State Residencies:" << std::endl;
90 StateResidencyDump(stat.c_state_residency().residency(), output);
91 }
92
typeOf() const93 PowerStatCase CstateResidencyDataProvider::typeOf() const {
94 return PowerStatCase::kCStateResidency;
95 }
96