1 /*
2 * Copyright (c) 2021-2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "battery_stats_parser.h"
17
18 #include <algorithm>
19 #include <fstream>
20 #include <sstream>
21
22 #include <cJSON.h>
23
24 #include "ios"
25 #include "string_ex.h"
26
27 #include "stats_cjson_utils.h"
28 #include "stats_utils.h"
29 #include "config_policy_utils.h"
30
31 namespace OHOS {
32 namespace PowerMgr {
33 namespace {
34 static const std::string POWER_AVERAGE_FILE = "etc/power_config/power_average.json";
35 static const std::string VENDOR_POWER_AVERAGE_FILE = "/vendor/etc/power_config/power_average.json";
36 static const std::string SYSTEM_POWER_AVERAGE_FILE = "/system/etc/power_config/power_average.json";
37 } // namespace
Init()38 bool BatteryStatsParser::Init()
39 {
40 char buf[MAX_PATH_LEN];
41 char* path = GetOneCfgFile(POWER_AVERAGE_FILE.c_str(), buf, MAX_PATH_LEN);
42 if (path != nullptr && *path != '\0') {
43 if (LoadAveragePowerFromFile(path)) {
44 return true;
45 }
46 return false;
47 }
48 if (!LoadAveragePowerFromFile(VENDOR_POWER_AVERAGE_FILE)) {
49 STATS_HILOGE(COMP_SVC, "Failed to load vendor average power file");
50 if (!LoadAveragePowerFromFile(SYSTEM_POWER_AVERAGE_FILE)) {
51 STATS_HILOGE(COMP_SVC, "Failed to load system average power file");
52 return false;
53 }
54 }
55 return true;
56 }
57
GetSpeedNum(uint16_t cluster)58 uint16_t BatteryStatsParser::GetSpeedNum(uint16_t cluster)
59 {
60 for (uint16_t i = 0; i < speedNum_.size(); i++) {
61 if (cluster == i) {
62 STATS_HILOGD(COMP_SVC, "Get speed num: %{public}d, for cluster: %{public}d", speedNum_[i],
63 cluster);
64 return speedNum_[i];
65 }
66 }
67 STATS_HILOGW(COMP_SVC, "No related speed number, return 0");
68 return StatsUtils::DEFAULT_VALUE;
69 }
70
LoadAveragePowerFromFile(const std::string & path)71 bool BatteryStatsParser::LoadAveragePowerFromFile(const std::string& path)
72 {
73 std::ifstream ifs(path, std::ios::binary);
74 if (!ifs.is_open()) {
75 STATS_HILOGE(COMP_SVC, "Json file doesn't exist");
76 return false;
77 }
78 std::stringstream buffer;
79 buffer << ifs.rdbuf();
80 std::string jsonStr = buffer.str();
81 ifs.close();
82
83 cJSON* root = cJSON_Parse(jsonStr.c_str());
84 if (!root) {
85 STATS_HILOGE(COMP_SVC, "Failed to parse the JSON file");
86 return false;
87 }
88 if (!StatsJsonUtils::IsValidJsonObjectOrJsonArray(root)) {
89 STATS_HILOGE(COMP_SVC, "root invalid[%{public}s]", path.c_str());
90 cJSON_Delete(root);
91 return false;
92 }
93 cJSON* currentElement = nullptr;
94 cJSON_ArrayForEach(currentElement, root) {
95 const char* type = currentElement->string;
96 if (type == nullptr) {
97 STATS_HILOGE(COMP_SVC, "Invalid key.");
98 continue;
99 }
100 std::string keyStr(type);
101 if (keyStr == StatsUtils::CURRENT_CPU_CLUSTER && StatsJsonUtils::IsValidJsonArray(currentElement)) {
102 clusterNum_ = static_cast<uint16_t>(cJSON_GetArraySize(currentElement));
103 STATS_HILOGD(COMP_SVC, "Read cluster num: %{public}d", clusterNum_);
104 }
105 if (keyStr.find(StatsUtils::CURRENT_CPU_SPEED) != std::string::npos &&
106 StatsJsonUtils::IsValidJsonArray(currentElement)) {
107 STATS_HILOGD(COMP_SVC, "Read speed num: %{public}d",
108 static_cast<int32_t>(cJSON_GetArraySize(currentElement)));
109 speedNum_.push_back(static_cast<uint16_t>(cJSON_GetArraySize(currentElement)));
110 }
111 if (cJSON_IsArray(currentElement)) {
112 ParsingArray(keyStr, currentElement);
113 } else if (cJSON_IsNumber(currentElement)) {
114 averageMap_.insert(std::pair<std::string, double>(keyStr, currentElement->valuedouble));
115 }
116 }
117 cJSON_Delete(root);
118 return true;
119 }
120
ParsingArray(const std::string & type,const cJSON * array)121 void BatteryStatsParser::ParsingArray(const std::string& type, const cJSON* array)
122 {
123 std::vector<double> listValues;
124
125 int size = cJSON_GetArraySize(array);
126 for (int i = 0; i < size; i++) {
127 cJSON* item = cJSON_GetArrayItem(array, i);
128 if (StatsJsonUtils::IsValidJsonNumber(item)) {
129 listValues.push_back(item->valuedouble);
130 }
131 }
132
133 averageVecMap_.insert(std::pair<std::string, std::vector<double>>(type, listValues));
134 }
135
GetAveragePowerMa(std::string type)136 double BatteryStatsParser::GetAveragePowerMa(std::string type)
137 {
138 double average = 0.0;
139 auto iter = averageMap_.find(type);
140 if (iter != averageMap_.end()) {
141 average = iter->second;
142 }
143 STATS_HILOGD(COMP_SVC, "Get average power: %{public}lfma of %{public}s", average, type.c_str());
144 return average;
145 }
146
GetAveragePowerMa(std::string type,uint16_t level)147 double BatteryStatsParser::GetAveragePowerMa(std::string type, uint16_t level)
148 {
149 double average = 0.0;
150 auto iter = averageVecMap_.find(type);
151 if (iter != averageVecMap_.end()) {
152 if (level < iter->second.size()) {
153 average = iter->second[level];
154 }
155 }
156 STATS_HILOGD(COMP_SVC, "Get average power: %{public}lf of %{public}s, level: %{public}d",
157 average, type.c_str(), level);
158 return average;
159 }
160
GetClusterNum()161 uint16_t BatteryStatsParser::GetClusterNum()
162 {
163 return clusterNum_;
164 }
165
DumpInfo(std::string & result)166 void BatteryStatsParser::DumpInfo(std::string& result)
167 {
168 result.append("POWER AVERAGE CONFIGATION DUMP:\n");
169 result.append("\n");
170 for (auto iter : averageMap_) {
171 result.append(iter.first).append(" : ").append(ToString(iter.second)).append("\n");
172 }
173 for (auto vecIter : averageVecMap_) {
174 result.append(vecIter.first).append(" : [");
175 for (auto levelIter : vecIter.second) {
176 result.append(" ").append(ToString(levelIter));
177 }
178 result.append(" ]").append("\n");
179 }
180 }
181 } // namespace PowerMgr
182 } // namespace OHOS
183