1 
2 /*
3  * Copyright (C) 2018 The Android Open Source Project
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #include <android/frameworks/stats/1.0/IStats.h>
19 #include <pixelhealth/LowBatteryShutdownMetrics.h>
20 
21 namespace hardware {
22 namespace google {
23 namespace pixel {
24 namespace health {
25 
26 using android::BATTERY_STATUS_DISCHARGING;
27 using android::sp;
28 using android::base::GetProperty;
29 using android::base::ReadFileToString;
30 using android::base::SetProperty;
31 using android::frameworks::stats::V1_0::BatteryCausedShutdown;
32 using android::frameworks::stats::V1_0::IStats;
33 
LowBatteryShutdownMetrics(const char * const voltage_avg,const char * const persist_prop)34 LowBatteryShutdownMetrics::LowBatteryShutdownMetrics(const char *const voltage_avg,
35                                                      const char *const persist_prop)
36     : kVoltageAvg(voltage_avg), kPersistProp(persist_prop) {
37     prop_written_ = false;
38     prop_empty_ = false;
39 }
40 
uploadVoltageAvg(void)41 bool LowBatteryShutdownMetrics::uploadVoltageAvg(void) {
42     std::string prop_contents = GetProperty(kPersistProp, "");
43     LOG(INFO) << kPersistProp << " property contents: " << prop_contents;
44     if (prop_contents.size() == 0) {  // we don't have anything to upload
45         prop_empty_ = true;
46         return false;
47     }
48 
49     sp<IStats> stats_client = IStats::tryGetService();
50     if (!stats_client) {
51         LOG(ERROR) << "Unable to connect to Stats service";
52         return false;
53     }
54 
55     // Process and upload comma-delimited last voltage values
56     int32_t voltage_avg;
57     for (const auto &item : android::base::Split(prop_contents, ",")) {
58         if (!(voltage_avg = stoi(item))) {
59             LOG(ERROR) << "Couldn't process voltage value " << item;
60             continue;
61         }
62         LOG(INFO) << "Uploading voltage_avg: " << std::to_string(voltage_avg);
63         BatteryCausedShutdown shutdown = {.voltageMicroV = voltage_avg};
64         stats_client->reportBatteryCausedShutdown(shutdown);
65     }
66 
67     // Clear property now that we've uploaded its contents
68     SetProperty(kPersistProp, "");
69     return true;
70 }
71 
saveVoltageAvg(void)72 bool LowBatteryShutdownMetrics::saveVoltageAvg(void) {
73     std::string voltage_avg;
74     std::string prop_contents;
75 
76     if (!ReadFileToString(kVoltageAvg, &voltage_avg)) {
77         LOG(ERROR) << "Can't read the Maxim fuel gauge average voltage value";
78         return false;
79     }
80     voltage_avg = ::android::base::Trim(voltage_avg);
81     prop_contents = GetProperty(kPersistProp, "");
82 
83     // Comma delimit additional values
84     if (prop_contents.size() > 0)
85         prop_contents += ",";
86     prop_contents += voltage_avg;
87 
88     LOG(INFO) << "Saving \"" << prop_contents << "\" to " << kPersistProp;
89 
90     return SetProperty(kPersistProp, prop_contents);
91 }
92 
logShutdownVoltage(struct android::BatteryProperties * props)93 void LowBatteryShutdownMetrics::logShutdownVoltage(struct android::BatteryProperties *props) {
94     // If we're about to shut down due to low battery, save voltage_avg
95     if (!prop_written_ && props->batteryLevel == 0 &&
96         props->batteryStatus == android::BATTERY_STATUS_DISCHARGING) {
97         prop_written_ = saveVoltageAvg();
98     } else if (!prop_empty_) {  // We have data to upload
99         uploadVoltageAvg();
100     }
101 
102     return;
103 }
104 
105 }  // namespace health
106 }  // namespace pixel
107 }  // namespace google
108 }  // namespace hardware
109