summaryrefslogtreecommitdiff
path: root/health
diff options
context:
space:
mode:
authorMaggie White <maggiewhite@google.com>2018-09-28 16:18:35 -0700
committerMaggie White <maggiewhite@google.com>2018-10-01 18:29:25 -0700
commit8c72de9446b713eae311bb125983a8293f55d487 (patch)
tree273563044a6f90564537ab32bdd6fb4a4d3c65d3 /health
parent7640c2489408063953b0f5cab47ae706de949b15 (diff)
downloadpixel-8c72de9446b713eae311bb125983a8293f55d487.tar.gz
health HAL: Add device-agnostic tools from P18
Bug: 116825947 Test: Tested battery metrics and shutdown logging on P18 Change-Id: Icf955bb955a0791bb3e49fcb77eed77616bec8b8 Signed-off-by: Maggie White <maggiewhite@google.com>
Diffstat (limited to 'health')
-rw-r--r--health/Android.bp31
-rw-r--r--health/BatteryMetricsLogger.cpp202
-rw-r--r--health/CycleCountBackupRestore.cpp148
-rw-r--r--health/DeviceHealth.cpp44
-rw-r--r--health/LowBatteryShutdownMetrics.cpp105
-rw-r--r--health/include/pixelhealth/BatteryMetricsLogger.h97
-rw-r--r--health/include/pixelhealth/CycleCountBackupRestore.h60
-rw-r--r--health/include/pixelhealth/DeviceHealth.h40
-rw-r--r--health/include/pixelhealth/LowBatteryShutdownMetrics.h63
9 files changed, 790 insertions, 0 deletions
diff --git a/health/Android.bp b/health/Android.bp
new file mode 100644
index 00000000..76b0df66
--- /dev/null
+++ b/health/Android.bp
@@ -0,0 +1,31 @@
+cc_library_static {
+ name: "libpixelhealth",
+ vendor_available: true,
+ export_include_dirs: ["include"],
+
+ srcs: [
+ "LowBatteryShutdownMetrics.cpp",
+ "CycleCountBackupRestore.cpp",
+ "DeviceHealth.cpp",
+ "BatteryMetricsLogger.cpp",
+ ],
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+
+ static_libs: [
+ "libbatterymonitor",
+ ],
+
+ shared_libs: [
+ "hardware.google.pixelstats@1.0",
+ "libbase",
+ "libcutils",
+ "libhidlbase",
+ "libhidltransport",
+ "libhwbinder",
+ "libutils",
+ ],
+}
diff --git a/health/BatteryMetricsLogger.cpp b/health/BatteryMetricsLogger.cpp
new file mode 100644
index 00000000..e226e1ce
--- /dev/null
+++ b/health/BatteryMetricsLogger.cpp
@@ -0,0 +1,202 @@
+
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <pixelhealth/BatteryMetricsLogger.h>
+
+namespace hardware {
+namespace google {
+namespace pixel {
+namespace health {
+
+using ::hardware::google::pixelstats::V1_0::IPixelStats;
+using BatteryHealthSnapshotArgs =
+ ::hardware::google::pixelstats::V1_0::IPixelStats::BatteryHealthSnapshotArgs;
+using android::sp;
+
+BatteryMetricsLogger::BatteryMetricsLogger(const char *const batt_res, const char *const batt_ocv,
+ int sample_period, int upload_period)
+ : kBatteryResistance(batt_res),
+ kBatteryOCV(batt_ocv),
+ kSamplePeriod(sample_period),
+ kUploadPeriod(upload_period),
+ kMaxSamples(upload_period / sample_period) {
+ last_sample_ = 0;
+ last_upload_ = 0;
+ num_res_samples_ = 0;
+ num_samples_ = 0;
+ memset(min_, 0, sizeof(min_));
+ memset(max_, 0, sizeof(max_));
+ accum_resistance_ = 0;
+}
+
+int64_t BatteryMetricsLogger::getTime(void) {
+ return nanoseconds_to_seconds(systemTime(SYSTEM_TIME_BOOTTIME));
+}
+
+bool BatteryMetricsLogger::uploadOutlierMetric(sp<IPixelStats> client, sampleType type) {
+ BatteryHealthSnapshotArgs min_ss = {static_cast<BatterySnapshotType>(0),
+ min_[type][TEMP],
+ min_[type][VOLT],
+ min_[type][CURR],
+ min_[type][OCV],
+ min_[type][RES],
+ min_[type][SOC]};
+ BatteryHealthSnapshotArgs max_ss = {static_cast<BatterySnapshotType>(0),
+ max_[type][TEMP],
+ max_[type][VOLT],
+ max_[type][CURR],
+ max_[type][OCV],
+ max_[type][RES],
+ max_[type][SOC]};
+
+ if (kSnapshotType[type] < 0)
+ return false;
+
+ min_ss.type = (BatterySnapshotType)kSnapshotType[type];
+ max_ss.type = (BatterySnapshotType)(kSnapshotType[type] + 1);
+
+ client->reportBatteryHealthSnapshot(min_ss);
+ client->reportBatteryHealthSnapshot(max_ss);
+ return true;
+}
+
+bool BatteryMetricsLogger::uploadMetrics(void) {
+ int64_t time = getTime();
+ int32_t avg_resistance = 0;
+
+ if (last_sample_ == 0)
+ return false;
+
+ LOG(INFO) << "Uploading metrics at time " << std::to_string(time) << " w/ "
+ << std::to_string(num_samples_) << " samples";
+
+ if (num_res_samples_)
+ avg_resistance = accum_resistance_ / num_res_samples_;
+
+ LOG(INFO) << "Logging metrics to tron";
+
+ sp<IPixelStats> client = IPixelStats::tryGetService();
+ if (!client) {
+ LOG(ERROR) << "Unable to connect to PixelStats service";
+ return false;
+ }
+
+ // Only log and upload the min and max for metric types we want to upload
+ for (int metric = 0; metric < NUM_FIELDS; metric++) {
+ if ((metric == RES && num_res_samples_ == 0) || kSnapshotType[metric] < 0)
+ continue;
+ std::string log_min = "min-" + std::to_string(metric) + " ";
+ std::string log_max = "max-" + std::to_string(metric) + " ";
+ for (int j = 0; j < NUM_FIELDS; j++) {
+ log_min += std::to_string(min_[metric][j]) + " ";
+ log_max += std::to_string(max_[metric][j]) + " ";
+ }
+ LOG(INFO) << log_min;
+ LOG(INFO) << log_max;
+ // Upload min/max metrics
+ uploadOutlierMetric(client, static_cast<sampleType>(metric));
+ }
+
+ // Upload average metric
+ BatteryHealthSnapshotArgs avg_res_ss = {
+ BatterySnapshotType::AVG_RESISTANCE, 0, 0, 0, 0, avg_resistance, 0};
+ if (num_res_samples_)
+ client->reportBatteryHealthSnapshot(avg_res_ss);
+
+ // Clear existing data
+ memset(min_, 0, sizeof(min_));
+ memset(max_, 0, sizeof(max_));
+ num_res_samples_ = 0;
+ num_samples_ = 0;
+ last_upload_ = time;
+ accum_resistance_ = 0;
+ LOG(INFO) << "Finished uploading to tron";
+ return true;
+}
+
+bool BatteryMetricsLogger::recordSample(struct android::BatteryProperties *props) {
+ std::string resistance_str, ocv_str;
+ int32_t resistance, ocv;
+ int32_t time = getTime();
+
+ LOG(INFO) << "Recording a sample at time " << std::to_string(time);
+
+ if (!android::base::ReadFileToString(kBatteryResistance, &resistance_str)) {
+ LOG(ERROR) << "Can't read the battery resistance";
+ resistance = 0;
+ } else if (!(resistance = stoi(resistance_str))) {
+ LOG(ERROR) << "Can't parse battery resistance value " << resistance_str;
+ }
+
+ if (!android::base::ReadFileToString(kBatteryOCV, &ocv_str)) {
+ LOG(ERROR) << "Can't read the open-circuit voltage (ocv) value";
+ ocv = 0;
+ } else if (!(ocv = stoi(ocv_str))) {
+ LOG(ERROR) << "Can't parse open-circuit voltage (ocv) value " << ocv_str;
+ }
+
+ int32_t sample[NUM_FIELDS] = {time,
+ resistance,
+ props->batteryCurrent,
+ props->batteryVoltage,
+ props->batteryTemperature,
+ props->batteryLevel,
+ ocv};
+ if (props->batteryStatus != android::BATTERY_STATUS_CHARGING) {
+ accum_resistance_ += resistance;
+ num_res_samples_++;
+ }
+
+ // Only calculate the min and max for metric types we want to upload
+ for (int metric = 0; metric < NUM_FIELDS; metric++) {
+ // Discard resistance min/max when charging
+ if ((metric == RES && props->batteryStatus == android::BATTERY_STATUS_CHARGING) ||
+ kSnapshotType[metric] < 0)
+ continue;
+ if (num_samples_ == 0 || (metric == RES && num_res_samples_ == 0) ||
+ sample[metric] < min_[metric][metric]) {
+ for (int i = 0; i < NUM_FIELDS; i++) { // update new min with current sample
+ min_[metric][i] = sample[i];
+ }
+ }
+ if (num_samples_ == 0 || (metric == RES && num_res_samples_ == 0) ||
+ sample[metric] > max_[metric][metric]) {
+ for (int i = 0; i < NUM_FIELDS; i++) { // update new max with current sample
+ max_[metric][i] = sample[i];
+ }
+ }
+ }
+
+ num_samples_++;
+ last_sample_ = time;
+ return true;
+}
+
+void BatteryMetricsLogger::logBatteryProperties(struct android::BatteryProperties *props) {
+ int32_t time = getTime();
+ if (last_sample_ == 0 || time - last_sample_ >= kSamplePeriod)
+ recordSample(props);
+ if (last_sample_ - last_upload_ > kUploadPeriod || num_samples_ >= kMaxSamples)
+ uploadMetrics();
+
+ return;
+}
+
+} // namespace health
+} // namespace pixel
+} // namespace google
+} // namespace hardware
diff --git a/health/CycleCountBackupRestore.cpp b/health/CycleCountBackupRestore.cpp
new file mode 100644
index 00000000..9b5b1006
--- /dev/null
+++ b/health/CycleCountBackupRestore.cpp
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <pixelhealth/CycleCountBackupRestore.h>
+
+namespace hardware {
+namespace google {
+namespace pixel {
+namespace health {
+
+static constexpr int kBackupTrigger = 20;
+
+CycleCountBackupRestore::CycleCountBackupRestore(int nb_buckets, const char *sysfs_path,
+ const char *persist_path, const char *serial_path)
+ : nb_buckets_(nb_buckets),
+ saved_soc_(-1),
+ soc_inc_(0),
+ sysfs_path_(sysfs_path),
+ persist_path_(persist_path),
+ serial_path_(serial_path) {
+ sw_bins_ = new int[nb_buckets]();
+ hw_bins_ = new int[nb_buckets]();
+}
+
+void CycleCountBackupRestore::Restore() {
+ if (CheckSerial()) {
+ Read(persist_path_, sw_bins_);
+ }
+ Read(sysfs_path_, hw_bins_);
+ UpdateAndSave();
+}
+
+bool CycleCountBackupRestore::CheckSerial() {
+ std::string device_battery_serial;
+ std::string persist_battery_serial;
+
+ if (serial_path_.empty())
+ return true;
+
+ if (!android::base::ReadFileToString(serial_path_, &device_battery_serial)) {
+ LOG(ERROR) << "Failed to read " << serial_path_;
+ return true;
+ }
+
+ if (!android::base::ReadFileToString(kPersistSerial, &persist_battery_serial)) {
+ LOG(ERROR) << "Failed to read " << kPersistSerial;
+ }
+
+ if (device_battery_serial != persist_battery_serial) {
+ // Battery pack has been changed or first time,
+ // cycle counts on the pack are the ones to save
+ if (!android::base::WriteStringToFile(device_battery_serial, kPersistSerial)) {
+ LOG(ERROR) << "Write to " << kPersistSerial << " error: " << strerror(errno);
+ }
+ return false;
+ }
+
+ return true;
+}
+
+void CycleCountBackupRestore::Backup(int battery_level) {
+ if (saved_soc_ == -1) {
+ saved_soc_ = battery_level;
+ return;
+ }
+ // Cycle counts only increases on increasing level
+ if (battery_level > saved_soc_) {
+ soc_inc_ += battery_level - saved_soc_;
+ }
+ saved_soc_ = battery_level;
+ // To avoid writting file too often just rate limit it
+ if (soc_inc_ >= kBackupTrigger) {
+ Read(sysfs_path_, hw_bins_);
+ UpdateAndSave();
+ soc_inc_ = 0;
+ }
+}
+
+void CycleCountBackupRestore::Read(const std::string &path, int *bins) {
+ std::string buffer;
+
+ if (!android::base::ReadFileToString(path, &buffer)) {
+ LOG(ERROR) << "Failed to read " << path;
+ return;
+ }
+
+ buffer = ::android::base::Trim(buffer);
+ std::vector<std::string> counts = android::base::Split(buffer, " ");
+ if (counts.size() != (size_t)nb_buckets_) {
+ LOG(ERROR) << "data format \"" << buffer << "\" is wrong in " << path;
+ } else {
+ LOG(INFO) << "Read: \"" << buffer << "\" from " << path;
+ for (int i = 0; i < nb_buckets_; ++i) {
+ bins[i] = std::stoi(counts[i]);
+ }
+ }
+}
+
+void CycleCountBackupRestore::Write(int *bins, const std::string &path) {
+ std::string str_data = "";
+
+ for (int i = 0; i < nb_buckets_; ++i) {
+ if (i) {
+ str_data += " ";
+ }
+ str_data += std::to_string(bins[i]);
+ }
+
+ LOG(INFO) << "Write: \"" << str_data << "\" to " << path;
+ if (!android::base::WriteStringToFile(str_data, path))
+ LOG(ERROR) << "Write to " << path << " error: " << strerror(errno);
+}
+
+void CycleCountBackupRestore::UpdateAndSave() {
+ bool backup = false;
+ bool restore = false;
+ for (int i = 0; i < nb_buckets_; i++) {
+ if (hw_bins_[i] < sw_bins_[i]) {
+ hw_bins_[i] = sw_bins_[i];
+ restore = true;
+ } else if (hw_bins_[i] > sw_bins_[i]) {
+ sw_bins_[i] = hw_bins_[i];
+ backup = true;
+ }
+ }
+ if (restore)
+ Write(hw_bins_, sysfs_path_);
+ if (backup)
+ Write(sw_bins_, persist_path_);
+}
+
+} // namespace health
+} // namespace pixel
+} // namespace google
+} // namespace hardware
diff --git a/health/DeviceHealth.cpp b/health/DeviceHealth.cpp
new file mode 100644
index 00000000..7054b2d9
--- /dev/null
+++ b/health/DeviceHealth.cpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "dhealth"
+
+#include <pixelhealth/DeviceHealth.h>
+
+#include <android-base/properties.h>
+#include <cutils/klog.h>
+
+namespace hardware {
+namespace google {
+namespace pixel {
+namespace health {
+
+DeviceHealth::DeviceHealth() {
+ is_user_build_ = android::base::GetProperty("ro.build.type", "") == "user";
+}
+
+void DeviceHealth::update(struct android::BatteryProperties *props) {
+ if (!is_user_build_ &&
+ (android::base::GetProperty("persist.vendor.disable.thermal.control", "") == "1" ||
+ android::base::GetProperty("persist.vendor.fake.battery.temperature", "") == "1")) {
+ props->batteryTemperature = 200;
+ }
+}
+
+} // namespace health
+} // namespace pixel
+} // namespace google
+} // namespace hardware
diff --git a/health/LowBatteryShutdownMetrics.cpp b/health/LowBatteryShutdownMetrics.cpp
new file mode 100644
index 00000000..68645eb6
--- /dev/null
+++ b/health/LowBatteryShutdownMetrics.cpp
@@ -0,0 +1,105 @@
+
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <pixelhealth/LowBatteryShutdownMetrics.h>
+
+namespace hardware {
+namespace google {
+namespace pixel {
+namespace health {
+
+using android::BATTERY_STATUS_DISCHARGING;
+using android::sp;
+using android::base::GetProperty;
+using android::base::ReadFileToString;
+using android::base::SetProperty;
+using ::hardware::google::pixelstats::V1_0::IPixelStats;
+
+LowBatteryShutdownMetrics::LowBatteryShutdownMetrics(const char *const voltage_avg,
+ const char *const persist_prop)
+ : kVoltageAvg(voltage_avg), kPersistProp(persist_prop) {
+ prop_written_ = false;
+ prop_empty_ = false;
+}
+
+bool LowBatteryShutdownMetrics::uploadVoltageAvg(void) {
+ std::string prop_contents = GetProperty(kPersistProp, "");
+ LOG(INFO) << kPersistProp << " property contents: " << prop_contents;
+ if (prop_contents.size() == 0) { // we don't have anything to upload
+ prop_empty_ = true;
+ return false;
+ }
+
+ sp<IPixelStats> client = IPixelStats::tryGetService();
+ if (!client) {
+ LOG(ERROR) << "Unable to connect to PixelStats service";
+ return false;
+ }
+
+ // Process and upload comma-delimited last voltage values
+ int32_t voltage_avg;
+ for (const auto &item : android::base::Split(prop_contents, ",")) {
+ if (!(voltage_avg = stoi(item))) {
+ LOG(ERROR) << "Couldn't process voltage value " << item;
+ continue;
+ }
+ LOG(INFO) << "Uploading voltage_avg: " << std::to_string(voltage_avg);
+ client->reportBatteryCausedShutdown(voltage_avg);
+ }
+
+ // Clear property now that we've uploaded its contents
+ SetProperty(kPersistProp, "");
+ return true;
+}
+
+bool LowBatteryShutdownMetrics::saveVoltageAvg(void) {
+ std::string voltage_avg;
+ std::string prop_contents;
+
+ if (!ReadFileToString(kVoltageAvg, &voltage_avg)) {
+ LOG(ERROR) << "Can't read the Maxim fuel gauge average voltage value";
+ return false;
+ }
+ voltage_avg = ::android::base::Trim(voltage_avg);
+ prop_contents = GetProperty(kPersistProp, "");
+
+ // Comma delimit additional values
+ if (prop_contents.size() > 0)
+ prop_contents += ",";
+ prop_contents += voltage_avg;
+
+ LOG(INFO) << "Saving \"" << prop_contents << "\" to " << kPersistProp;
+
+ return SetProperty(kPersistProp, prop_contents);
+}
+
+void LowBatteryShutdownMetrics::logShutdownVoltage(struct android::BatteryProperties *props) {
+ // If we're about to shut down due to low battery, save voltage_avg
+ if (!prop_written_ && props->batteryLevel == 0 &&
+ props->batteryStatus == android::BATTERY_STATUS_DISCHARGING) {
+ prop_written_ = saveVoltageAvg();
+ } else if (!prop_empty_) { // We have data to upload
+ uploadVoltageAvg();
+ }
+
+ return;
+}
+
+} // namespace health
+} // namespace pixel
+} // namespace google
+} // namespace hardware
diff --git a/health/include/pixelhealth/BatteryMetricsLogger.h b/health/include/pixelhealth/BatteryMetricsLogger.h
new file mode 100644
index 00000000..2c760474
--- /dev/null
+++ b/health/include/pixelhealth/BatteryMetricsLogger.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef HARDWARE_GOOGLE_PIXEL_HEALTH_BATTERYMETRICSLOGGER_H
+#define HARDWARE_GOOGLE_PIXEL_HEALTH_BATTERYMETRICSLOGGER_H
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/strings.h>
+#include <batteryservice/BatteryService.h>
+#include <math.h>
+#include <time.h>
+#include <utils/Timers.h>
+#include <string>
+
+#include <hardware/google/pixelstats/1.0/IPixelStats.h>
+
+namespace hardware {
+namespace google {
+namespace pixel {
+namespace health {
+
+using BatterySnapshotType = ::hardware::google::pixelstats::V1_0::IPixelStats::BatterySnapshotType;
+
+class BatteryMetricsLogger {
+ public:
+ BatteryMetricsLogger(const char *const batt_res, const char *const batt_ocv,
+ int sample_period = TEN_MINUTES_SEC, int upload_period = ONE_DAY_SEC);
+ void logBatteryProperties(struct android::BatteryProperties *props);
+
+ private:
+ enum sampleType {
+ TIME, // time in seconds
+ CURR, // current in mA
+ VOLT, // voltage in mV
+ TEMP, // temp in deci-degC
+ SOC, // SoC in % battery level
+ RES, // resistance in milli-ohms
+ OCV, // open-circuit voltage in mV
+ NUM_FIELDS, // do not reference
+ };
+
+ const int kSnapshotType[NUM_FIELDS] = {
+ -1,
+ (int)BatterySnapshotType::MIN_CURRENT,
+ (int)BatterySnapshotType::MIN_VOLTAGE,
+ (int)BatterySnapshotType::MIN_TEMP,
+ (int)BatterySnapshotType::MIN_BATT_LEVEL,
+ (int)BatterySnapshotType::MIN_RESISTANCE,
+ -1,
+ };
+
+ const char *const kBatteryResistance;
+ const char *const kBatteryOCV;
+ const int kSamplePeriod;
+ const int kUploadPeriod;
+ const int kMaxSamples;
+ static constexpr int TEN_MINUTES_SEC = 10 * 60;
+ static constexpr int ONE_DAY_SEC = 24 * 60 * 60;
+
+ // min and max are referenced by type in both the X and Y axes
+ // i.e. min[TYPE] is the event where the minimum of that type occurred, and
+ // min[TYPE][TYPE] is the reading of that type at that minimum event
+ int32_t min_[NUM_FIELDS][NUM_FIELDS];
+ int32_t max_[NUM_FIELDS][NUM_FIELDS];
+ int32_t num_res_samples_; // number of res samples since last upload
+ int32_t num_samples_; // number of min/max samples since last upload
+ int64_t accum_resistance_; // accumulative resistance
+ int64_t last_sample_; // time in seconds since boot of last sample
+ int64_t last_upload_; // time in seconds since boot of last upload
+
+ int64_t getTime();
+ bool recordSample(struct android::BatteryProperties *props);
+ bool uploadMetrics();
+ bool uploadOutlierMetric(android::sp<::hardware::google::pixelstats::V1_0::IPixelStats> client,
+ sampleType type);
+};
+
+} // namespace health
+} // namespace pixel
+} // namespace google
+} // namespace hardware
+
+#endif
diff --git a/health/include/pixelhealth/CycleCountBackupRestore.h b/health/include/pixelhealth/CycleCountBackupRestore.h
new file mode 100644
index 00000000..bdac8899
--- /dev/null
+++ b/health/include/pixelhealth/CycleCountBackupRestore.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef HARDWARE_GOOGLE_PIXEL_HEALTH_CYCLECOUNTBACKUPRESTORE_H
+#define HARDWARE_GOOGLE_PIXEL_HEALTH_CYCLECOUNTBACKUPRESTORE_H
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/strings.h>
+#include <string>
+
+namespace hardware {
+namespace google {
+namespace pixel {
+namespace health {
+
+class CycleCountBackupRestore {
+ public:
+ CycleCountBackupRestore(int nb_buckets, const char *sysfs_path, const char *persist_path,
+ const char *serial_path = "");
+ void Restore();
+ void Backup(int battery_level);
+
+ private:
+ const char *kPersistSerial = "/persist/battery/serial_number";
+
+ int nb_buckets_;
+ int *sw_bins_;
+ int *hw_bins_;
+ int saved_soc_;
+ int soc_inc_;
+ std::string sysfs_path_;
+ std::string persist_path_;
+ std::string serial_path_;
+
+ void Read(const std::string &path, int *bins);
+ void Write(int *bins, const std::string &path);
+ void UpdateAndSave();
+ bool CheckSerial();
+};
+
+} // namespace health
+} // namespace pixel
+} // namespace google
+} // namespace hardware
+
+#endif // #ifndef HARDWARE_GOOGLE_PIXEL_HEALTH_CYCLECOUNTBACKUPRESTORE_H
diff --git a/health/include/pixelhealth/DeviceHealth.h b/health/include/pixelhealth/DeviceHealth.h
new file mode 100644
index 00000000..037a9aca
--- /dev/null
+++ b/health/include/pixelhealth/DeviceHealth.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef HARDWARE_GOOGLE_PIXEL_HEALTH_DEVICEHEALTH_H
+
+#include <batteryservice/BatteryService.h>
+
+namespace hardware {
+namespace google {
+namespace pixel {
+namespace health {
+
+class DeviceHealth {
+ public:
+ DeviceHealth();
+ void update(struct android::BatteryProperties *props);
+
+ private:
+ bool is_user_build_;
+};
+
+} // namespace health
+} // namespace pixel
+} // namespace google
+} // namespace hardware
+
+#endif
diff --git a/health/include/pixelhealth/LowBatteryShutdownMetrics.h b/health/include/pixelhealth/LowBatteryShutdownMetrics.h
new file mode 100644
index 00000000..2fa7e4b0
--- /dev/null
+++ b/health/include/pixelhealth/LowBatteryShutdownMetrics.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef HARDWARE_GOOGLE_PIXEL_HEALTH_LOWBATTERYSHUTDOWNMETRICS_H
+#define HARDWARE_GOOGLE_PIXEL_HEALTH_LOWBATTERYSHUTDOWNMETRICS_H
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <android-base/strings.h>
+#include <batteryservice/BatteryService.h>
+#include <math.h>
+#include <time.h>
+#include <utils/Timers.h>
+#include <string>
+
+#include <hardware/google/pixelstats/1.0/IPixelStats.h>
+
+namespace hardware {
+namespace google {
+namespace pixel {
+namespace health {
+
+class LowBatteryShutdownMetrics {
+ public:
+ LowBatteryShutdownMetrics(
+ const char *const voltage_avg,
+ const char *const persist_prop = "persist.vendor.shutdown.voltage_avg");
+ void logShutdownVoltage(struct android::BatteryProperties *props);
+
+ private:
+ const char *const kVoltageAvg;
+ const char *const kPersistProp;
+
+ // Helps enforce that we only record kVoltageAvg once per boot cycle
+ bool prop_written_;
+ // Help us avoid polling kPersistProp if it's empty
+ bool prop_empty_;
+
+ bool saveVoltageAvg();
+ void readStatus();
+ bool uploadVoltageAvg();
+};
+
+} // namespace health
+} // namespace pixel
+} // namespace google
+} // namespace hardware
+
+#endif