1  /*
2   * Copyright (c) 2021-2022 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 "entities/cpu_entity.h"
17  
18  #include "battery_stats_service.h"
19  #include "stats_log.h"
20  
21  namespace OHOS {
22  namespace PowerMgr {
23  namespace {
24  }
25  
CpuEntity()26  CpuEntity::CpuEntity()
27  {
28      STATS_HILOGD(COMP_SVC, "Created cpu entity");
29      consumptionType_ = BatteryStatsInfo::CONSUMPTION_TYPE_CPU;
30      if (!cpuReader_) {
31          cpuReader_ = std::make_shared<CpuTimeReader>();
32          cpuReader_->Init();
33      }
34  }
35  
GetCpuTimeMs(int32_t uid)36  int64_t CpuEntity::GetCpuTimeMs(int32_t uid)
37  {
38      int64_t cpuTimeMs = StatsUtils::DEFAULT_VALUE;
39      auto iter = cpuTimeMap_.find(uid);
40      if (iter != cpuTimeMap_.end()) {
41          STATS_HILOGD(COMP_SVC, "Get cpu time: %{public}sms for uid: %{public}d",
42              std::to_string(cpuTimeMs).c_str(), uid);
43          cpuTimeMs = iter->second;
44      } else {
45          STATS_HILOGD(COMP_SVC, "No cpu time realted to uid: %{public}d was found, return 0", uid);
46      }
47      return cpuTimeMs;
48  }
49  
UpdateCpuTime()50  void CpuEntity::UpdateCpuTime()
51  {
52      if (cpuReader_) {
53          if (!cpuReader_->UpdateCpuTime()) {
54              STATS_HILOGE(COMP_SVC, "Update CPU time failed");
55          }
56      } else {
57          STATS_HILOGW(COMP_SVC, "CPU reader is nullptr");
58      }
59  }
60  
Calculate(int32_t uid)61  void CpuEntity::Calculate(int32_t uid)
62  {
63      double cpuTotalPowerMah = StatsUtils::DEFAULT_VALUE;
64      // Get cpu time related with uid
65      std::vector<int64_t> cpuTimeVec = cpuReader_->GetUidCpuTimeMs(uid);
66      int64_t cpuTimeMs = StatsUtils::DEFAULT_VALUE;
67      for (uint32_t i = 0; i < cpuTimeVec.size(); i++) {
68          cpuTimeMs += cpuTimeVec[i];
69      }
70      auto cpuTimeIter = cpuTimeMap_.find(uid);
71      if (cpuTimeIter != cpuTimeMap_.end()) {
72          STATS_HILOGD(COMP_SVC, "Update cpu time: %{public}sms for uid: %{public}d",
73              std::to_string(cpuTimeMs).c_str(), uid);
74          cpuTimeIter->second = cpuTimeMs;
75      } else {
76          STATS_HILOGD(COMP_SVC, "Create cpu time: %{public}sms for uid: %{public}d",
77              std::to_string(cpuTimeMs).c_str(), uid);
78          cpuTimeMap_.insert(std::pair<int32_t, int64_t>(uid, cpuTimeMs));
79      }
80  
81      // Calculate cpu active power
82      cpuTotalPowerMah += CalculateCpuActivePower(uid);
83  
84      // Calculate cpu cluster power
85      cpuTotalPowerMah += CalculateCpuClusterPower(uid);
86  
87      // Calculate cpu speed power
88      cpuTotalPowerMah += CalculateCpuSpeedPower(uid);
89  
90      auto cpuTotalIter = cpuTotalPowerMap_.find(uid);
91      if (cpuTotalIter != cpuTotalPowerMap_.end()) {
92          STATS_HILOGD(COMP_SVC, "Update cpu speed power consumption: %{public}lfmAh for uid: %{public}d",
93              cpuTotalPowerMah, uid);
94          cpuTotalIter->second = cpuTotalPowerMah;
95      } else {
96          STATS_HILOGD(COMP_SVC, "Create cpu speed power consumption: %{public}lfmAh for uid: %{public}d",
97              cpuTotalPowerMah, uid);
98          cpuTotalPowerMap_.insert(std::pair<int32_t, double>(uid, cpuTotalPowerMah));
99      }
100  }
101  
CalculateCpuActivePower(int32_t uid)102  double CpuEntity::CalculateCpuActivePower(int32_t uid)
103  {
104      auto bss = BatteryStatsService::GetInstance();
105      double cpuActiveAverageMa =
106          bss->GetBatteryStatsParser()->GetAveragePowerMa(StatsUtils::CURRENT_CPU_ACTIVE);
107      int64_t cpuActiveTimeMs = cpuReader_->GetUidCpuActiveTimeMs(uid);
108      double cpuActivePower = cpuActiveAverageMa * cpuActiveTimeMs / StatsUtils::MS_IN_HOUR;
109  
110      auto cpuActiveIter = cpuActivePowerMap_.find(uid);
111      if (cpuActiveIter != cpuActivePowerMap_.end()) {
112          STATS_HILOGD(COMP_SVC, "Update cpu active power consumption: %{public}lfmAh for uid: %{public}d",
113              cpuActivePower, uid);
114          cpuActiveIter->second = cpuActivePower;
115      } else {
116          STATS_HILOGD(COMP_SVC, "Create cpu active power consumption: %{public}lfmAh for uid: %{public}d",
117              cpuActivePower, uid);
118          cpuActivePowerMap_.insert(std::pair<int32_t, double>(uid, cpuActivePower));
119      }
120      return cpuActivePower;
121  }
122  
CalculateCpuClusterPower(int32_t uid)123  double CpuEntity::CalculateCpuClusterPower(int32_t uid)
124  {
125      double cpuClusterPower = StatsUtils::DEFAULT_VALUE;
126      auto bss = BatteryStatsService::GetInstance();
127      for (uint16_t i = 0; i < bss->GetBatteryStatsParser()->GetClusterNum(); i++) {
128          double cpuClusterAverageMa =
129              bss->GetBatteryStatsParser()->GetAveragePowerMa(StatsUtils::CURRENT_CPU_CLUSTER, i);
130          int64_t cpuClusterTimeMs = cpuReader_->GetUidCpuClusterTimeMs(uid, i);
131          cpuClusterPower += cpuClusterAverageMa * cpuClusterTimeMs / StatsUtils::MS_IN_HOUR;
132      }
133      auto cpuClusterIter = cpuClusterPowerMap_.find(uid);
134      if (cpuClusterIter != cpuClusterPowerMap_.end()) {
135          STATS_HILOGD(COMP_SVC, "Update cpu cluster power consumption: %{public}lfmAh for uid: %{public}d",
136              cpuClusterPower, uid);
137          cpuClusterIter->second = cpuClusterPower;
138      } else {
139          STATS_HILOGD(COMP_SVC, "Create cpu cluster power consumption: %{public}lfmAh for uid: %{public}d",
140              cpuClusterPower, uid);
141          cpuClusterPowerMap_.insert(std::pair<int32_t, double>(uid, cpuClusterPower));
142      }
143      return cpuClusterPower;
144  }
145  
CalculateCpuSpeedPower(int32_t uid)146  double CpuEntity::CalculateCpuSpeedPower(int32_t uid)
147  {
148      double cpuSpeedPower = StatsUtils::DEFAULT_VALUE;
149      auto bss = BatteryStatsService::GetInstance();
150      for (uint16_t i = 0; i < bss->GetBatteryStatsParser()->GetClusterNum(); i++) {
151          for (uint16_t j = 0; j < bss->GetBatteryStatsParser()->GetSpeedNum(i); j++) {
152              STATS_HILOGD(COMP_SVC, "Calculate cluster: %{public}d, speed: %{public}d", j, i);
153              std::string statType = StatsUtils::CURRENT_CPU_SPEED + std::to_string(i);
154              double cpuSpeedAverageMa = bss->GetBatteryStatsParser()->GetAveragePowerMa(statType, j);
155              int64_t cpuSpeedTimeMs = cpuReader_->GetUidCpuFreqTimeMs(uid, i, j);
156              cpuSpeedPower += cpuSpeedAverageMa * cpuSpeedTimeMs / StatsUtils::MS_IN_HOUR;
157          }
158      }
159      auto cpuSpeedIter = cpuSpeedPowerMap_.find(uid);
160      if (cpuSpeedIter != cpuSpeedPowerMap_.end()) {
161          STATS_HILOGD(COMP_SVC, "Update cpu speed power consumption: %{public}lfmAh for uid: %{public}d",
162              cpuSpeedPower, uid);
163          cpuSpeedIter->second = cpuSpeedPower;
164      } else {
165          STATS_HILOGD(COMP_SVC, "Create cpu speed power consumption: %{public}lfmAh for uid: %{public}d",
166              cpuSpeedPower, uid);
167          cpuSpeedPowerMap_.insert(std::pair<int32_t, double>(uid, cpuSpeedPower));
168      }
169      return cpuSpeedPower;
170  }
171  
GetEntityPowerMah(int32_t uidOrUserId)172  double CpuEntity::GetEntityPowerMah(int32_t uidOrUserId)
173  {
174      double power = StatsUtils::DEFAULT_VALUE;
175      auto iter = cpuTotalPowerMap_.find(uidOrUserId);
176      if (iter != cpuTotalPowerMap_.end()) {
177          power = iter->second;
178          STATS_HILOGD(COMP_SVC, "Get app cpu total power consumption: %{public}lfmAh for uid: %{public}d",
179              power, uidOrUserId);
180      } else {
181          STATS_HILOGD(COMP_SVC,
182              "No app cpu total power consumption related to uid: %{public}d was found, return 0", uidOrUserId);
183      }
184      return power;
185  }
186  
GetStatsPowerMah(StatsUtils::StatsType statsType,int32_t uid)187  double CpuEntity::GetStatsPowerMah(StatsUtils::StatsType statsType, int32_t uid)
188  {
189      double power = StatsUtils::DEFAULT_VALUE;
190  
191      if (statsType == StatsUtils::STATS_TYPE_CPU_ACTIVE) {
192          auto cpuActiveIter = cpuActivePowerMap_.find(uid);
193          if (cpuActiveIter != cpuActivePowerMap_.end()) {
194              power = cpuActiveIter->second;
195              STATS_HILOGD(COMP_SVC, "Get cpu active power consumption: %{public}lfmAh for uid: %{public}d",
196                  power, uid);
197          } else {
198              STATS_HILOGD(COMP_SVC,
199                  "No cpu active power consumption related to uid: %{public}d was found, return 0", uid);
200          }
201      } else if (statsType == StatsUtils::STATS_TYPE_CPU_CLUSTER) {
202          auto cpuClusterIter = cpuClusterPowerMap_.find(uid);
203          if (cpuClusterIter != cpuClusterPowerMap_.end()) {
204              power = cpuClusterIter->second;
205              STATS_HILOGD(COMP_SVC, "Get cpu cluster power consumption: %{public}lfmAh for uid: %{public}d",
206                  power, uid);
207          } else {
208              STATS_HILOGD(COMP_SVC,
209                  "No cpu cluster power consumption related to uid: %{public}d was found, return 0", uid);
210          }
211      } else if (statsType == StatsUtils::STATS_TYPE_CPU_SPEED) {
212          auto cpuSpeedIter = cpuSpeedPowerMap_.find(uid);
213          if (cpuSpeedIter != cpuSpeedPowerMap_.end()) {
214              power = cpuSpeedIter->second;
215              STATS_HILOGD(COMP_SVC, "Get cpu speed power consumption: %{public}lfmAh for uid: %{public}d",
216                  power, uid);
217          } else {
218              STATS_HILOGD(COMP_SVC,
219                  "No cpu speed power consumption related to uid: %{public}d was found, return 0", uid);
220          }
221      }
222      return power;
223  }
224  
Reset()225  void CpuEntity::Reset()
226  {
227      // Reset app Cpu time
228      for (auto& iter : cpuTimeMap_) {
229          iter.second = StatsUtils::DEFAULT_VALUE;
230      }
231  
232      // Reset app Cpu total power consumption
233      for (auto& iter : cpuTotalPowerMap_) {
234          iter.second = StatsUtils::DEFAULT_VALUE;
235      }
236  
237      // Reset app Cpu active power consumption
238      for (auto& iter : cpuActivePowerMap_) {
239          iter.second = StatsUtils::DEFAULT_VALUE;
240      }
241  
242      // Reset app Cpu cluster power consumption
243      for (auto& iter : cpuClusterPowerMap_) {
244          iter.second = StatsUtils::DEFAULT_VALUE;
245      }
246  
247      // Reset app Cpu speed power consumption
248      for (auto& iter : cpuSpeedPowerMap_) {
249          iter.second = StatsUtils::DEFAULT_VALUE;
250      }
251  }
252  
DumpInfo(std::string & result,int32_t uid)253  void CpuEntity::DumpInfo(std::string& result, int32_t uid)
254  {
255      if (cpuReader_) {
256          cpuReader_->DumpInfo(result, uid);
257      }
258  }
259  } // namespace PowerMgr
260  } // namespace OHOS
261