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