1 /*
2  * Copyright (C) 2021 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-uevent"
18 
19 #include <android-base/file.h>
20 #include <android-base/logging.h>
21 #include <android-base/parseint.h>
22 #include <android-base/strings.h>
23 #include <hardware/google/pixel/pixelstats/pixelatoms.pb.h>
24 #include <log/log.h>
25 #include <pixelstats/WirelessChargeStats.h>
26 
27 namespace android {
28 namespace hardware {
29 namespace google {
30 namespace pixel {
31 
32 using android::base::ReadFileToString;
33 using android::base::WriteStringToFile;
34 
35 /*  Reference to <kernel>/private/google-modules/bms/p9221_charger.h
36  *  translate sys_mode value to enum define in pixelatoms.proto
37  */
TranslateSysModeToAtomValue(const int sys_mode)38 int WirelessChargeStats::TranslateSysModeToAtomValue(const int sys_mode) {
39     switch (sys_mode) {
40         case 1:
41             return PixelAtoms::ChargeStats::ADAPTER_TYPE_WPC_BPP;
42         case 2:
43             return PixelAtoms::ChargeStats::ADAPTER_TYPE_WPC_EPP;
44         case 3:
45             return PixelAtoms::ChargeStats::ADAPTER_TYPE_WPC_L7;
46         case 0xe0:
47             return PixelAtoms::ChargeStats::ADAPTER_TYPE_DL;
48         case 0xa0:
49             return PixelAtoms::ChargeStats::ADAPTER_TYPE_L7;
50         default:
51             return PixelAtoms::ChargeStats::ADAPTER_TYPE_WLC;
52     }
53 }
54 
CheckWirelessContentsAndAck(std::string * file_contents)55 bool WirelessChargeStats::CheckWirelessContentsAndAck(std::string *file_contents) {
56     std::string line;
57     std::istringstream ss;
58 
59     if (!ReadFileToString(kWirelessChargeMetricsPath.c_str(), file_contents))
60         return false;
61 
62     ss.str(*file_contents);
63 
64     if (!std::getline(ss, line)) {
65         ALOGE("Unable to read first line %s - %s", kWirelessChargeMetricsPath.c_str(),
66               strerror(errno));
67         return false;
68     }
69     if (!WriteStringToFile(std::to_string(0), kWirelessChargeMetricsPath.c_str())) {
70         ALOGE("Couldn't clear %s - %s", kWirelessChargeMetricsPath.c_str(), strerror(errno));
71         return false;
72     }
73     return true;
74 }
75 
ResetChargeMetrics()76 void WirelessChargeStats::ResetChargeMetrics() {
77     pout_min_ = 0;
78     pout_avg_ = 0;
79     pout_max_ = 0;
80     of_freq_ = 0;
81     alignment_ = 0;
82     count_ = 0;
83 }
84 
CalculateWirelessChargeMetrics(const int pout_min,const int pout_avg,const int pout_max,const int of_freq,const int alignment)85 void WirelessChargeStats::CalculateWirelessChargeMetrics(const int pout_min, const int pout_avg,
86                                                          const int pout_max, const int of_freq,
87                                                          const int alignment) {
88     if ((pout_min_ == 0) || (pout_min_ > pout_min))
89         pout_min_ = pout_min;
90 
91     pout_avg_ += pout_avg;
92     count_++;
93 
94     if ((pout_max_ == 0) || (pout_max_ < pout_max))
95         pout_max_ = pout_max;
96 
97     if (alignment_ == 0 || ((alignment >= 0) && (alignment_ > alignment))) {
98         of_freq_ = of_freq;
99         alignment_ = alignment;
100     }
101 }
102 
CalculateWirelessChargeStats(const int ssoc_tmp,const std::string file_contents)103 void WirelessChargeStats::CalculateWirelessChargeStats(const int ssoc_tmp,
104                                                        const std::string file_contents) {
105     std::string line;
106     std::istringstream ss;
107 
108     ResetChargeMetrics();
109     ss.str(file_contents);
110 
111     while (std::getline(ss, line)) {
112         int32_t buf[11] = {0};
113         if (sscanf(line.c_str(), "%d:%d, %d,%d,%d, %d,%d, %d,%d,%d,%d", &buf[0], &buf[1], &buf[2],
114                    &buf[3], &buf[4], &buf[5], &buf[6], &buf[7], &buf[8], &buf[9], &buf[10]) == 11) {
115             const int32_t soc = buf[0];
116 
117             /* calculate wireless charge stats of next voltage tier */
118             if (soc > tier_soc_) {
119                 const int32_t alignment = buf[6];
120 
121                 if (alignment >= 0 && alignment < 100)
122                     ALOGD("WirelessChargeStats: misalignment %s", line.c_str());
123 
124                 CalculateWirelessChargeMetrics(buf[2], buf[3], buf[4], buf[5], buf[6]);
125                 if (soc >= ssoc_tmp) {
126                     /* reach next voltage tier, restore final results before sending out*/
127                     pout_avg_ = (pout_avg_ / count_);
128                     tier_soc_ = soc;
129                     ALOGD("WirelessChargeStats: atoms %d %d %d %d", pout_min_, pout_avg_, pout_max_,
130                           of_freq_);
131                     return;
132                 }
133             }
134         }
135     }
136 }
137 
WirelessChargeStats(const std::string wireless_charge_metrics_path)138 WirelessChargeStats::WirelessChargeStats(const std::string wireless_charge_metrics_path)
139     : kWirelessChargeMetricsPath(wireless_charge_metrics_path) {}
140 
141 }  // namespace pixel
142 }  // namespace google
143 }  // namespace hardware
144 }  // namespace android
145