summaryrefslogtreecommitdiff
path: root/health
diff options
context:
space:
mode:
authorWasb Liu <wasbliu@google.com>2018-09-17 14:51:30 +0800
committerWasb Liu <wasbliu@google.com>2018-10-04 14:57:13 +0800
commitbae3a655a0fd922f08ea79c1e68f01b57cd38b3a (patch)
tree6f37f1596534099c0f9713d15a982786d45ef34f /health
parent031f601477540fbd92cb5494cfcdd90c9e35f3eb (diff)
downloadbonito-bae3a655a0fd922f08ea79c1e68f01b57cd38b3a.tar.gz
HealthService: save and restore charge cycle counts
Bug: 115849755 Test: boot to home and cycle count works Change-Id: I1e4390bf538a368544d5469e1e21457b0a7bd3fc Signed-off-by: Wasb Liu <wasbliu@google.com>
Diffstat (limited to 'health')
-rw-r--r--health/Android.bp1
-rw-r--r--health/CycleCountBackupRestore.cpp151
-rw-r--r--health/CycleCountBackupRestore.h60
-rw-r--r--health/HealthService.cpp7
4 files changed, 219 insertions, 0 deletions
diff --git a/health/Android.bp b/health/Android.bp
index ab6a52aa..735e0325 100644
--- a/health/Android.bp
+++ b/health/Android.bp
@@ -21,6 +21,7 @@ cc_binary {
srcs: [
"HealthService.cpp",
"BatteryRechargingControl.cpp",
+ "CycleCountBackupRestore.cpp",
],
cflags: [
diff --git a/health/CycleCountBackupRestore.cpp b/health/CycleCountBackupRestore.cpp
new file mode 100644
index 00000000..05f656ab
--- /dev/null
+++ b/health/CycleCountBackupRestore.cpp
@@ -0,0 +1,151 @@
+/*
+ * 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 "CycleCountBackupRestore.h"
+
+namespace device {
+namespace google {
+namespace bonito {
+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];
+ memset(sw_bins_, 0, sizeof(sw_bins_));
+ hw_bins_ = new int[nb_buckets];
+ memset(hw_bins_, 0, sizeof(hw_bins_));
+}
+
+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 bonito
+} // namespace google
+} // namespace device
+
diff --git a/health/CycleCountBackupRestore.h b/health/CycleCountBackupRestore.h
new file mode 100644
index 00000000..e2ba1f21
--- /dev/null
+++ b/health/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 DEVICE_GOOGLE_BONITO_HEALTH_CYCLECOUNTBACKUPRESTORE_H
+#define DEVICE_GOOGLE_BONITO_HEALTH_CYCLECOUNTBACKUPRESTORE_H
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/strings.h>
+#include <string>
+
+namespace device {
+namespace google {
+namespace bonito {
+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 bonito
+} // namespace google
+} // namespace device
+
+#endif // #ifndef DEVICE_GOOGLE_BONITO_HEALTH_CYCLECOUNTBACKUPRESTORE_H
diff --git a/health/HealthService.cpp b/health/HealthService.cpp
index 88103f81..db3730d0 100644
--- a/health/HealthService.cpp
+++ b/health/HealthService.cpp
@@ -30,6 +30,7 @@
#include <vector>
#include "BatteryRechargingControl.h"
+#include "CycleCountBackupRestore.h"
namespace {
@@ -37,8 +38,12 @@ using android::hardware::health::V2_0::DiskStats;
using android::hardware::health::V2_0::StorageAttribute;
using android::hardware::health::V2_0::StorageInfo;
using ::device::google::bonito::health::BatteryRechargingControl;
+using ::device::google::bonito::health::CycleCountBackupRestore;
static BatteryRechargingControl battRechargingControl;
+static CycleCountBackupRestore ccBackupRestoreBMS(
+ 8, "/sys/class/power_supply/bms/device/cycle_counts_bins",
+ "/persist/battery/qcom_cycle_counts_bins");
#define EMMC_DIR "/sys/devices/platform/soc/7c4000.sdhci"
const std::string kEmmcHealthEol{EMMC_DIR "/health/eol"};
@@ -80,10 +85,12 @@ void fill_emmc_storage_attribute(StorageAttribute* attr) {
} // anonymous namespace
void healthd_board_init(struct healthd_config*) {
+ ccBackupRestoreBMS.Restore();
}
int healthd_board_battery_update(struct android::BatteryProperties *props) {
battRechargingControl.updateBatteryProperties(props);
+ ccBackupRestoreBMS.Backup(props->batteryLevel);
return 0;
}