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 17 #include "CycleCountBackupRestore.h" 18 19 namespace device { 20 namespace google { 21 namespace marlin { 22 namespace health { 23 24 static constexpr char kCycCntFile[] = "sys/class/power_supply/bms/device/cycle_counts_bins"; 25 static constexpr char kSysPersistFile[] = "/persist/battery/qcom_cycle_counts_bins"; 26 static constexpr int kBuffSize = 256; 27 28 CycleCountBackupRestore::CycleCountBackupRestore() { } 29 30 void CycleCountBackupRestore::Restore() 31 { 32 ReadFromStorage(); 33 ReadFromSRAM(); 34 UpdateAndSave(); 35 } 36 37 void CycleCountBackupRestore::Backup() 38 { 39 ReadFromSRAM(); 40 UpdateAndSave(); 41 } 42 43 void CycleCountBackupRestore::ReadFromStorage() 44 { 45 std::string buffer; 46 47 if (!android::base::ReadFileToString(std::string(kSysPersistFile), &buffer)) { 48 LOG(ERROR) << "Cannot read the storage file"; 49 return; 50 } 51 52 if (sscanf(buffer.c_str(), "%d %d %d %d %d %d %d %d", 53 &sw_bins_[0], &sw_bins_[1], &sw_bins_[2], &sw_bins_[3], 54 &sw_bins_[4], &sw_bins_[5], &sw_bins_[6], &sw_bins_[7]) 55 != kBucketCount) 56 LOG(ERROR) << "data format is wrong in the storage file: " << buffer; 57 else 58 LOG(INFO) << "Storage data: " << buffer; 59 } 60 61 void CycleCountBackupRestore::SaveToStorage() 62 { 63 char strData[kBuffSize]; 64 65 snprintf(strData, kBuffSize, "%d %d %d %d %d %d %d %d", 66 sw_bins_[0], sw_bins_[1], sw_bins_[2], sw_bins_[3], 67 sw_bins_[4], sw_bins_[5], sw_bins_[6], sw_bins_[7]); 68 69 LOG(INFO) << "Save to Storage: " << strData; 70 71 if (!android::base::WriteStringToFile(strData, std::string(kSysPersistFile))) 72 LOG(ERROR) << "Write file error: " << strerror(errno); 73 } 74 75 void CycleCountBackupRestore::ReadFromSRAM() 76 { 77 std::string buffer; 78 79 if (!android::base::ReadFileToString(std::string(kCycCntFile), &buffer)) { 80 LOG(ERROR) << "Read cycle counter error: " << strerror(errno); 81 return; 82 } 83 84 buffer = android::base::Trim(buffer); 85 86 if (sscanf(buffer.c_str(), "%d %d %d %d %d %d %d %d", 87 &hw_bins_[0], &hw_bins_[1], &hw_bins_[2], &hw_bins_[3], 88 &hw_bins_[4], &hw_bins_[5], &hw_bins_[6], &hw_bins_[7]) 89 != kBucketCount) 90 LOG(ERROR) << "Failed to parse SRAM bins: " << buffer; 91 else 92 LOG(INFO) << "SRAM data: " << buffer; 93 } 94 95 void CycleCountBackupRestore::SaveToSRAM() 96 { 97 char strData[kBuffSize]; 98 99 snprintf(strData, kBuffSize, "%d %d %d %d %d %d %d %d", 100 hw_bins_[0], hw_bins_[1], hw_bins_[2], hw_bins_[3], 101 hw_bins_[4], hw_bins_[5], hw_bins_[6], hw_bins_[7]); 102 103 LOG(INFO) << "Save to SRAM: " << strData ; 104 105 if (!android::base::WriteStringToFile(strData, std::string(kCycCntFile))) 106 LOG(ERROR) << "Write data error: " << strerror(errno); 107 } 108 109 110 void CycleCountBackupRestore::UpdateAndSave() 111 { 112 bool backup = false; 113 bool restore = false; 114 for (int i = 0; i < kBucketCount; i++) { 115 if (hw_bins_[i] < sw_bins_[i]) { 116 hw_bins_[i] = sw_bins_[i]; 117 restore = true; 118 } else if (hw_bins_[i] > sw_bins_[i]) { 119 sw_bins_[i] = hw_bins_[i]; 120 backup = true; 121 } 122 } 123 if (restore) 124 SaveToSRAM(); 125 if (backup) 126 SaveToStorage(); 127 } 128 129 } // namespace health 130 } // namespace marlin 131 } // namespace google 132 } // namespace device 133