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