1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 #define LOG_TAG "android.hardware.health (at) 2.0-service.wahoo" 17 #include <android-base/logging.h> 18 19 #include <healthd/healthd.h> 20 #include <health2/Health.h> 21 #include <health2/service.h> 22 #include <hidl/HidlTransportSupport.h> 23 24 #include <android-base/file.h> 25 #include <android-base/strings.h> 26 27 #include <vector> 28 #include <string> 29 30 #include "CycleCountBackupRestore.h" 31 #include "LearnedCapacityBackupRestore.h" 32 33 using android::hardware::health::V2_0::StorageInfo; 34 using android::hardware::health::V2_0::DiskStats; 35 using ::device::google::wahoo::health::CycleCountBackupRestore; 36 using ::device::google::wahoo::health::LearnedCapacityBackupRestore; 37 38 static constexpr int kBackupTrigger = 20; 39 static CycleCountBackupRestore ccBackupRestore; 40 static LearnedCapacityBackupRestore lcBackupRestore; 41 42 int cycle_count_backup(int battery_level) 43 { 44 static int saved_soc = 0; 45 static int soc_inc = 0; 46 static bool is_first = true; 47 48 if (is_first) { 49 is_first = false; 50 saved_soc = battery_level; 51 return 0; 52 } 53 54 if (battery_level > saved_soc) { 55 soc_inc += battery_level - saved_soc; 56 } 57 58 saved_soc = battery_level; 59 60 if (soc_inc >= kBackupTrigger) { 61 ccBackupRestore.Backup(); 62 soc_inc = 0; 63 } 64 return 0; 65 } 66 67 // See : hardware/interfaces/health/2.0/README 68 69 void healthd_board_init(struct healthd_config*) 70 { 71 ccBackupRestore.Restore(); 72 lcBackupRestore.Restore(); 73 } 74 75 int healthd_board_battery_update(struct android::BatteryProperties *props) 76 { 77 cycle_count_backup(props->batteryLevel); 78 lcBackupRestore.Backup(); 79 return 0; 80 } 81 82 const char kUFSHealthFile[] = "/sys/kernel/debug/ufshcd0/dump_health_desc"; 83 const char kUFSHealthVersionFile[] = "/sys/kernel/debug/ufshcd0/show_hba"; 84 const char kDiskStatsFile[] = "/sys/block/sda/stat"; 85 const char kUFSName[] = "UFS0"; 86 87 /* 88 * Implementation based on system/core/storaged/storaged_info.cc 89 */ 90 void get_storage_info(std::vector<StorageInfo>& vec_storage_info) { 91 StorageInfo storage_info = {}; 92 std::string buffer, version; 93 94 storage_info.attr.isInternal = true; 95 storage_info.attr.isBootDevice = true; 96 storage_info.attr.name = std::string(kUFSName); 97 98 if (!android::base::ReadFileToString(std::string(kUFSHealthVersionFile), &version)) { 99 return; 100 } 101 102 std::vector<std::string> lines = android::base::Split(version, "\n"); 103 if (lines.empty()) { 104 return; 105 } 106 107 char rev[8]; 108 if (sscanf(lines[6].c_str(), "hba->ufs_version = 0x%7s\n", rev) < 1) { 109 return; 110 } 111 112 storage_info.version = "ufs " + std::string(rev); 113 114 if (!android::base::ReadFileToString(std::string(kUFSHealthFile), &buffer)) { 115 return; 116 } 117 118 lines = android::base::Split(buffer, "\n"); 119 if (lines.empty()) { 120 return; 121 } 122 123 for (size_t i = 1; i < lines.size(); i++) { 124 char token[32]; 125 uint16_t val; 126 int ret; 127 if ((ret = sscanf(lines[i].c_str(), 128 "Health Descriptor[Byte offset 0x%*d]: %31s = 0x%hx", 129 token, &val)) < 2) { 130 continue; 131 } 132 133 if (std::string(token) == "bPreEOLInfo") { 134 storage_info.eol = val; 135 } else if (std::string(token) == "bDeviceLifeTimeEstA") { 136 storage_info.lifetimeA = val; 137 } else if (std::string(token) == "bDeviceLifeTimeEstB") { 138 storage_info.lifetimeB = val; 139 } 140 } 141 142 vec_storage_info.resize(1); 143 vec_storage_info[0] = storage_info; 144 return; 145 } 146 147 /* 148 * Implementation based on parse_disk_stats() in system/core/storaged_diskstats.cpp 149 */ 150 void get_disk_stats(std::vector<DiskStats>& vec_stats) { 151 const size_t kDiskStatsSize = 11; 152 struct DiskStats stats = {}; 153 154 stats.attr.isInternal = true; 155 stats.attr.isBootDevice = true; 156 stats.attr.name = std::string(kUFSName); 157 158 159 std::string buffer; 160 if (!android::base::ReadFileToString(std::string(kDiskStatsFile), &buffer)) { 161 LOG(ERROR) << kDiskStatsFile << ": ReadFileToString failed."; 162 return; 163 } 164 165 // Regular diskstats entries 166 std::stringstream ss(buffer); 167 for (uint i = 0; i < kDiskStatsSize; ++i) { 168 ss >> *(reinterpret_cast<uint64_t*>(&stats) + i); 169 } 170 vec_stats.resize(1); 171 vec_stats[0] = stats; 172 173 return; 174 } 175 176 int main(void) { 177 return health_service_main(); 178 } 179