Home | History | Annotate | Download | only in health
      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