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
21namespace OHOS {
22namespace PowerMgr {
23namespace {
24}
25
26CpuEntity::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
36int64_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
50void 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
61void 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
102double 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
123double 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
146double 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
172double 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
187double 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
225void 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
253void 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