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 <pixelhealth/LowBatteryShutdownMetrics.h>
19 #include <pixelhealth/StatsHelper.h>
20
21 namespace hardware {
22 namespace google {
23 namespace pixel {
24 namespace health {
25
26 using android::BATTERY_STATUS_DISCHARGING;
27 using android::base::GetProperty;
28 using android::base::ReadFileToString;
29 using android::base::SetProperty;
30
LowBatteryShutdownMetrics(const char * const voltage_avg,const char * const persist_prop)31 LowBatteryShutdownMetrics::LowBatteryShutdownMetrics(const char *const voltage_avg,
32 const char *const persist_prop)
33 : kVoltageAvg(voltage_avg), kPersistProp(persist_prop) {
34 prop_written_ = false;
35 prop_empty_ = false;
36 }
37
uploadVoltageAvg(void)38 bool LowBatteryShutdownMetrics::uploadVoltageAvg(void) {
39 std::string prop_contents = GetProperty(kPersistProp, "");
40 LOG(INFO) << kPersistProp << " property contents: " << prop_contents;
41 if (prop_contents.size() == 0) { // we don't have anything to upload
42 prop_empty_ = true;
43 return false;
44 }
45
46 std::shared_ptr<IStats> stats_client = getStatsService();
47 if (!stats_client) {
48 LOG(ERROR) << "Unable to connect to IStats service";
49 return false;
50 }
51
52 // Process and upload comma-delimited last voltage values
53 VendorBatteryCausedShutdown shutdown;
54 int32_t voltage_avg;
55 for (const auto &item : android::base::Split(prop_contents, ",")) {
56 if (!(voltage_avg = stoi(item))) {
57 LOG(ERROR) << "Couldn't process voltage value " << item;
58 continue;
59 }
60 LOG(INFO) << "Uploading voltage_avg: " << std::to_string(voltage_avg);
61 shutdown.set_last_recorded_micro_volt(voltage_avg);
62 reportBatteryCausedShutdown(stats_client, shutdown);
63 }
64
65 // Clear property now that we've uploaded its contents
66 SetProperty(kPersistProp, "");
67 return true;
68 }
69
saveVoltageAvg(void)70 bool LowBatteryShutdownMetrics::saveVoltageAvg(void) {
71 std::string voltage_avg;
72 std::string prop_contents;
73
74 if (!ReadFileToString(kVoltageAvg, &voltage_avg)) {
75 LOG(ERROR) << "Can't read the Maxim fuel gauge average voltage value";
76 return false;
77 }
78 voltage_avg = ::android::base::Trim(voltage_avg);
79 prop_contents = GetProperty(kPersistProp, "");
80
81 // Comma delimit additional values
82 if (prop_contents.size() > 0)
83 prop_contents += ",";
84 prop_contents += voltage_avg;
85
86 LOG(INFO) << "Saving \"" << prop_contents << "\" to " << kPersistProp;
87
88 return SetProperty(kPersistProp, prop_contents);
89 }
90
logShutdownVoltage(struct android::BatteryProperties * props)91 void LowBatteryShutdownMetrics::logShutdownVoltage(struct android::BatteryProperties *props) {
92 // If we're about to shut down due to low battery, save voltage_avg
93 if (!prop_written_ && props->batteryLevel == 0 &&
94 props->batteryStatus == android::BATTERY_STATUS_DISCHARGING) {
95 prop_written_ = saveVoltageAvg();
96 } else if (!prop_empty_) { // We have data to upload
97 uploadVoltageAvg();
98 }
99
100 return;
101 }
102
103 } // namespace health
104 } // namespace pixel
105 } // namespace google
106 } // namespace hardware
107