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