1 /*
2 * Copyright (C) 2023 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: PowerMitigationDurationCounts"
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/MitigationDurationReporter.h>
28 #include <utils/Log.h>
29
30 namespace android {
31 namespace hardware {
32 namespace google {
33 namespace pixel {
34
35 using aidl::android::frameworks::stats::IStats;
36 using aidl::android::frameworks::stats::VendorAtom;
37 using aidl::android::frameworks::stats::VendorAtomValue;
38 using android::base::ReadFileToString;
39 using android::hardware::google::pixel::PixelAtoms::PowerMitigationDurationCounts;
40
41 enum DurationOutputOrder {
42 UVLO1,
43 UVLO1_MMWAVE,
44 UVLO1_RFFE,
45 UVLO2,
46 UVLO2_MMWAVE,
47 UVLO2_RFFE,
48 BATOILO,
49 BATOILO_MMWAVE,
50 BATOILO_RFFE,
51 MAIN0,
52 MAIN1,
53 MAIN2,
54 MAIN3,
55 MAIN4,
56 MAIN5,
57 MAIN6,
58 MAIN7,
59 MAIN8,
60 MAIN9,
61 MAIN10,
62 MAIN11,
63 SUB0,
64 SUB1,
65 SUB2,
66 SUB3,
67 SUB4,
68 SUB5,
69 SUB6,
70 SUB7,
71 SUB8,
72 SUB9,
73 SUB10,
74 SUB11,
75 };
76
MitigationDurationReporter()77 MitigationDurationReporter::MitigationDurationReporter() {}
78
getStatFromLine(const std::string * line,int * val)79 bool MitigationDurationReporter::getStatFromLine(const std::string *line, int *val) {
80 std::vector<std::string> strs = android::base::Split(*line, ":");
81 if (strs.size() != 2) {
82 ALOGI("Unable to split %s", line->c_str());
83 return false;
84 }
85 std::string str = strs[1];
86 str = android::base::Trim(str);
87 str.erase(std::remove(str.begin(), str.end(), '\n'), str.cend());
88 if (!android::base::ParseInt(str, val)) {
89 ALOGI("Unable to convert %s to int - %s", str.c_str(), strerror(errno));
90 return false;
91 }
92 return true;
93 }
94
valueAssignmentHelper(std::vector<VendorAtomValue> * values,int * val,int fieldNumber)95 void MitigationDurationReporter::valueAssignmentHelper(std::vector<VendorAtomValue> *values,
96 int *val, int fieldNumber) {
97 VendorAtomValue tmp;
98 tmp.set<VendorAtomValue::intValue>(*val);
99 (*values)[fieldNumber - kVendorAtomOffset] = tmp;
100 }
101
logMitigationDuration(const std::shared_ptr<IStats> & stats_client,const std::string & path)102 void MitigationDurationReporter::logMitigationDuration(const std::shared_ptr<IStats> &stats_client,
103 const std::string &path) {
104 struct IrqDurationCounts greater_than_thresh = {};
105
106 if (!getIrqDurationCountHelper(path + kGreaterThanTenMsSysfsNode, &greater_than_thresh))
107 return;
108
109 VendorAtomValue tmp;
110 std::vector<VendorAtomValue> values(33);
111
112 valueAssignmentHelper(&values, &greater_than_thresh.uvlo1_none,
113 PowerMitigationDurationCounts::kGreaterThanThreshUvlo1NoneFieldNumber);
114 valueAssignmentHelper(&values, &greater_than_thresh.uvlo1_mmwave,
115 PowerMitigationDurationCounts::kGreaterThanThreshUvlo1MmwaveFieldNumber);
116 valueAssignmentHelper(&values, &greater_than_thresh.uvlo1_rffe,
117 PowerMitigationDurationCounts::kGreaterThanThreshUvlo1RffeFieldNumber);
118
119 valueAssignmentHelper(&values, &greater_than_thresh.uvlo2_none,
120 PowerMitigationDurationCounts::kGreaterThanThreshUvlo2NoneFieldNumber);
121 valueAssignmentHelper(&values, &greater_than_thresh.uvlo2_mmwave,
122 PowerMitigationDurationCounts::kGreaterThanThreshUvlo2MmwaveFieldNumber);
123 valueAssignmentHelper(&values, &greater_than_thresh.uvlo2_rffe,
124 PowerMitigationDurationCounts::kGreaterThanThreshUvlo2RffeFieldNumber);
125
126 valueAssignmentHelper(&values, &greater_than_thresh.batoilo_none,
127 PowerMitigationDurationCounts::kGreaterThanThreshBatoiloNoneFieldNumber);
128 valueAssignmentHelper(
129 &values, &greater_than_thresh.batoilo_mmwave,
130 PowerMitigationDurationCounts::kGreaterThanThreshBatoiloMmwaveFieldNumber);
131 valueAssignmentHelper(&values, &greater_than_thresh.batoilo_rffe,
132 PowerMitigationDurationCounts::kGreaterThanThreshBatoiloRffeFieldNumber);
133
134 int i;
135 for (i = 0; i < MITIGATION_DURATION_MAIN_COUNT; i++) {
136 valueAssignmentHelper(
137 &values, &greater_than_thresh.main[i],
138 PowerMitigationDurationCounts::kGreaterThanThreshMain0FieldNumber + i);
139 }
140
141 for (i = 0; i < MITIGATION_DURATION_SUB_COUNT; i++) {
142 valueAssignmentHelper(&values, &greater_than_thresh.sub[i],
143 PowerMitigationDurationCounts::kGreaterThanThreshSub0FieldNumber + i);
144 }
145
146 // Send vendor atom to IStats HAL
147 VendorAtom event = {.reverseDomainName = "",
148 .atomId = PixelAtoms::Atom::kMitigationDuration,
149 .values = std::move(values)};
150 const ndk::ScopedAStatus ret = stats_client->reportVendorAtom(event);
151 if (!ret.isOk())
152 ALOGE("Unable to report to Stats service");
153 }
154
updateStat(const std::string * line,int * val)155 int MitigationDurationReporter::updateStat(const std::string *line, int *val) {
156 int stat_value;
157 if (!getStatFromLine(line, &stat_value) || *val == stat_value) {
158 return 0;
159 }
160
161 *val = stat_value;
162 return 1;
163 }
164
getIrqDurationCountHelper(const std::string kMitigationDurationFile,struct IrqDurationCounts * counts)165 bool MitigationDurationReporter::getIrqDurationCountHelper(
166 const std::string kMitigationDurationFile, struct IrqDurationCounts *counts) {
167 std::string file_contents;
168
169 if (!ReadFileToString(kMitigationDurationFile, &file_contents)) {
170 ALOGI("Unable to read %s - %s", kMitigationDurationFile.c_str(), strerror(errno));
171 return false;
172 }
173
174 std::vector<std::string> lines = android::base::Split(file_contents, "\n");
175 if (lines.size() < kExpectedNumberOfLines) {
176 ALOGI("Readback size is invalid");
177 return false;
178 }
179
180 int16_t i;
181 int num_stats = 0;
182
183 num_stats += updateStat(&lines[UVLO1], &counts->uvlo1_none);
184 num_stats += updateStat(&lines[UVLO1_MMWAVE], &counts->uvlo1_mmwave);
185 num_stats += updateStat(&lines[UVLO1_RFFE], &counts->uvlo1_rffe);
186 num_stats += updateStat(&lines[UVLO2], &counts->uvlo2_none);
187 num_stats += updateStat(&lines[UVLO2_MMWAVE], &counts->uvlo2_mmwave);
188 num_stats += updateStat(&lines[UVLO2_RFFE], &counts->uvlo2_rffe);
189 num_stats += updateStat(&lines[BATOILO], &counts->batoilo_none);
190 num_stats += updateStat(&lines[BATOILO_MMWAVE], &counts->batoilo_mmwave);
191 num_stats += updateStat(&lines[BATOILO_RFFE], &counts->batoilo_rffe);
192
193 for (i = MAIN0; i <= MAIN11; i++) {
194 num_stats += updateStat(&lines[i], &counts->main[i - MAIN0]);
195 }
196
197 for (i = SUB0; i <= SUB11; i++) {
198 num_stats += updateStat(&lines[i], &counts->sub[i - SUB0]);
199 }
200
201 return num_stats > 0;
202 }
203
204 } // namespace pixel
205 } // namespace google
206 } // namespace hardware
207 } // namespace android
208