• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "cpu_time_reader.h"
17 
18 #include <fstream>
19 #include "string_ex.h"
20 
21 #include "battery_stats_service.h"
22 #include "stats_helper.h"
23 #include "stats_log.h"
24 #include "stats_utils.h"
25 
26 namespace OHOS {
27 namespace PowerMgr {
28 namespace {
29 static const std::string UID_CPU_ACTIVE_TIME_FILE = "/proc/uid_concurrent_active_time";
30 static const std::string UID_CPU_CLUSTER_TIME_FILE = "/proc/uid_concurrent_policy_time";
31 static const std::string UID_CPU_FREQ_TIME_FILE = "/proc/uid_time_in_state";
32 static const std::string UID_CPU_TIME_FILE = "/proc/uid_cputime/show_uid_stat";
33 } // namespace
Init()34 bool CpuTimeReader::Init()
35 {
36     if (!UpdateCpuTime()) {
37         STATS_HILOGW(COMP_SVC, "Update cpu time failed");
38     }
39     return true;
40 }
41 
GetUidCpuActiveTimeMs(int32_t uid)42 int64_t CpuTimeReader::GetUidCpuActiveTimeMs(int32_t uid)
43 {
44     int64_t cpuActiveTime = 0;
45     auto iter = activeTimeMap_.find(uid);
46     if (iter != activeTimeMap_.end()) {
47         cpuActiveTime = iter->second;
48         STATS_HILOGD(COMP_SVC, "Get cpu active time: %{public}s for uid: %{public}d",
49             std::to_string(cpuActiveTime).c_str(), uid);
50     } else {
51         STATS_HILOGD(COMP_SVC, "No cpu active time found for uid: %{public}d, return 0", uid);
52     }
53     return cpuActiveTime;
54 }
55 
DumpInfo(std::string & result,int32_t uid)56 void CpuTimeReader::DumpInfo(std::string& result, int32_t uid)
57 {
58     auto uidIter = lastUidTimeMap_.find(uid);
59     if (uidIter == lastUidTimeMap_.end()) {
60         STATS_HILOGE(COMP_SVC, "No related CPU info for uid: %{public}d", uid);
61         return;
62     }
63     std::string freqTime = "";
64     auto freqIter = lastFreqTimeMap_.find(uid);
65     if (freqIter != lastFreqTimeMap_.end()) {
66         for (auto timeIter = freqIter->second.begin(); timeIter != freqIter->second.end(); timeIter++) {
67             for (uint32_t i = 0; i < timeIter->second.size(); i++) {
68                 freqTime.append(ToString(timeIter->second[i]))
69                     .append(" ");
70             }
71         }
72     }
73     result.append("Total cpu time: userSpaceTime=")
74         .append(ToString(uidIter->second[0]))
75         .append("ms, systemSpaceTime=")
76         .append(ToString(uidIter->second[1]))
77         .append("ms\n")
78         .append("Total cpu time per freq: ")
79         .append(freqTime)
80         .append("\n");
81 }
82 
GetUidCpuClusterTimeMs(int32_t uid,uint32_t cluster)83 int64_t CpuTimeReader::GetUidCpuClusterTimeMs(int32_t uid, uint32_t cluster)
84 {
85     int64_t cpuClusterTime = 0;
86     auto iter = clusterTimeMap_.find(uid);
87     if (iter != clusterTimeMap_.end()) {
88         auto cpuClusterTimeVector = iter->second;
89         if (cluster < cpuClusterTimeVector.size()) {
90             cpuClusterTime = cpuClusterTimeVector[cluster];
91             STATS_HILOGD(COMP_SVC, "Get cpu cluster time: %{public}s of cluster: %{public}d",
92                 std::to_string(cpuClusterTime).c_str(), cluster);
93         } else {
94             STATS_HILOGD(COMP_SVC, "No cpu cluster time of cluster: %{public}d found, return 0", cluster);
95         }
96     } else {
97         STATS_HILOGD(COMP_SVC, "No cpu cluster time vector found for uid: %{public}d, return 0", uid);
98     }
99     return cpuClusterTime;
100 }
101 
GetUidCpuFreqTimeMs(int32_t uid,uint32_t cluster,uint32_t speed)102 int64_t CpuTimeReader::GetUidCpuFreqTimeMs(int32_t uid, uint32_t cluster, uint32_t speed)
103 {
104     int64_t cpuFreqTime = 0;
105     auto uidIter = freqTimeMap_.find(uid);
106     if (uidIter != freqTimeMap_.end()) {
107         auto cpuFreqTimeMap = uidIter->second;
108         auto clusterIter = cpuFreqTimeMap.find(cluster);
109         if (clusterIter != cpuFreqTimeMap.end()) {
110             auto cpuFreqTimeVector = clusterIter->second;
111             if (speed < cpuFreqTimeVector.size()) {
112                 cpuFreqTime = cpuFreqTimeVector[speed];
113                 STATS_HILOGD(COMP_SVC, "Get cpu freq time: %{public}s of speed: %{public}d",
114                     std::to_string(cpuFreqTime).c_str(), speed);
115             } else {
116                 STATS_HILOGD(COMP_SVC, "No cpu freq time of speed: %{public}d found, return 0", speed);
117             }
118         } else {
119             STATS_HILOGD(COMP_SVC, "No cluster cpu freq time vector of cluster: %{public}d found, return 0",
120                 cluster);
121         }
122     } else {
123         STATS_HILOGD(COMP_SVC, "No uid cpu freq time map found for uid: %{public}d, return 0", uid);
124     }
125     return cpuFreqTime;
126 }
127 
GetUidCpuTimeMs(int32_t uid)128 std::vector<int64_t> CpuTimeReader::GetUidCpuTimeMs(int32_t uid)
129 {
130     std::vector<int64_t> cpuTimeVec;
131     auto iter = uidTimeMap_.find(uid);
132     if (iter != uidTimeMap_.end()) {
133         cpuTimeVec = iter->second;
134         STATS_HILOGD(COMP_SVC, "Get uid cpu time vector for uid: %{public}d, size: %{public}d", uid,
135             static_cast<int32_t>(cpuTimeVec.size()));
136     } else {
137         STATS_HILOGD(COMP_SVC, "No uid cpu time vector found for uid: %{public}d, return null", uid);
138     }
139     return cpuTimeVec;
140 }
141 
UpdateCpuTime()142 bool CpuTimeReader::UpdateCpuTime()
143 {
144     bool result = true;
145     if (!ReadUidCpuClusterTime()) {
146         STATS_HILOGW(COMP_SVC, "Read uid cpu cluster time failed");
147         result = false;
148     }
149 
150     if (!ReadUidCpuTime()) {
151         STATS_HILOGW(COMP_SVC, "Read uid cpu time failed");
152         result = false;
153     }
154 
155     if (!ReadUidCpuActiveTime()) {
156         STATS_HILOGW(COMP_SVC, "Read uid cpu active time failed");
157         result = false;
158     }
159 
160     if (!ReadUidCpuFreqTime()) {
161         STATS_HILOGW(COMP_SVC, "Read uid cpu freq time failed");
162         result = false;
163     }
164     return result;
165 }
166 
ReadUidCpuActiveTimeImpl(std::string & line,int32_t uid)167 bool CpuTimeReader::ReadUidCpuActiveTimeImpl(std::string& line, int32_t uid)
168 {
169     int64_t timeMs = 0;
170     std::vector<std::string> splitedTime;
171     Split(line, ' ', splitedTime);
172     for (uint16_t i = 0; i < splitedTime.size(); i++) {
173         int64_t result = 0;
174         if (!StatsUtils::ParseStrtollResult(splitedTime[i], result)) {
175             continue;
176         }
177         timeMs += result * 10; // Unit is 10ms
178     }
179 
180     int64_t increment = 0;
181     if (timeMs > 0) {
182         auto iterLast = lastActiveTimeMap_.find(uid);
183         if (iterLast != lastActiveTimeMap_.end()) {
184             increment = timeMs - iterLast->second;
185             if (increment >= 0) {
186                 iterLast->second = timeMs;
187             } else {
188                 STATS_HILOGI(COMP_SVC, "Negative cpu active time increment");
189                 return false;
190             }
191         } else {
192             lastActiveTimeMap_.insert(std::pair<int32_t, int64_t>(uid, timeMs));
193             increment = timeMs;
194         }
195     }
196 
197     if (StatsHelper::IsOnBattery()) {
198         STATS_HILOGD(COMP_SVC, "Power supply is not connected. Add the increment");
199         auto iter = activeTimeMap_.find(uid);
200         if (iter != activeTimeMap_.end()) {
201             iter->second += increment;
202         } else {
203             activeTimeMap_.insert(std::pair<int32_t, int64_t>(uid, increment));
204             STATS_HILOGI(COMP_SVC, "Add active time: %{public}sms, uid: %{public}d",
205                 std::to_string(increment).c_str(), uid);
206         }
207     }
208     return true;
209 }
210 
ReadUidCpuActiveTime()211 bool CpuTimeReader::ReadUidCpuActiveTime()
212 {
213     std::ifstream input(UID_CPU_ACTIVE_TIME_FILE);
214     if (!input) {
215         STATS_HILOGW(COMP_SVC, "Open file failed");
216         return false;
217     }
218 
219     std::string line;
220     const int32_t INDEX_0 = 0;
221     const int32_t INDEX_1 = 1;
222     while (getline(input, line)) {
223         int32_t uid = StatsUtils::INVALID_VALUE;
224         std::vector<std::string> splitedLine;
225         Split(line, ':', splitedLine);
226         if (splitedLine[INDEX_0] == "cpus") {
227             continue;
228         } else {
229             int64_t result = 0;
230             if (!StatsUtils::ParseStrtollResult(splitedLine[INDEX_0], result)) {
231                 continue;
232             }
233             uid = static_cast<int32_t>(result);
234         }
235 
236         if (uid > StatsUtils::INVALID_VALUE) {
237             auto bss = BatteryStatsService::GetInstance();
238             auto uidEntity =
239                 bss->GetBatteryStatsCore()->GetEntity(BatteryStatsInfo::CONSUMPTION_TYPE_APP);
240             if (uidEntity) {
241                 uidEntity->UpdateUidMap(uid);
242             }
243         }
244 
245         if (ReadUidCpuActiveTimeImpl(splitedLine[INDEX_1], uid)) {
246             continue;
247         } else {
248             return false;
249         }
250     }
251     return true;
252 }
253 
ReadPolicy(std::vector<uint16_t> & clusters,std::string & line)254 void CpuTimeReader::ReadPolicy(std::vector<uint16_t>& clusters, std::string& line)
255 {
256     std::vector<std::string> splitedPolicy;
257     Split(line, ' ', splitedPolicy);
258     uint32_t step = 2;
259     for (uint32_t i = 0; i < splitedPolicy.size(); i += step) {
260         int64_t result = 0;
261         if (!StatsUtils::ParseStrtollResult(splitedPolicy[i + 1], result)) {
262             continue;
263         }
264         uint16_t coreNum = static_cast<uint16_t>(result);
265         clusters.push_back(coreNum);
266         clustersMap_.insert(std::pair<uint16_t, uint16_t>(i, coreNum));
267     }
268 }
269 
ReadClusterTimeIncrement(std::vector<int64_t> & clusterTime,std::vector<int64_t> & increments,int32_t uid,std::vector<uint16_t> & clusters,std::string & timeLine)270 bool CpuTimeReader::ReadClusterTimeIncrement(std::vector<int64_t>& clusterTime, std::vector<int64_t>& increments,
271     int32_t uid, std::vector<uint16_t>& clusters, std::string& timeLine)
272 {
273     std::vector<std::string> splitedTime;
274     Split(timeLine, ' ', splitedTime);
275     uint16_t count = 0;
276     for (uint16_t i = 0; i < clusters.size(); i++) {
277         int64_t tempTimeMs = 0;
278         for (uint16_t j = 0; j < clusters[i]; j++) {
279             int64_t result = 0;
280             if (!StatsUtils::ParseStrtollResult(splitedTime[count++], result)) {
281                 continue;
282             }
283             tempTimeMs += result * 10; // Unit is 10ms
284         }
285         clusterTime.push_back(tempTimeMs);
286     }
287 
288     auto iterLast = lastClusterTimeMap_.find(uid);
289     if (iterLast != lastClusterTimeMap_.end()) {
290         for (uint16_t i = 0; i < clusters.size(); i++) {
291             int64_t increment = clusterTime[i] - iterLast->second[i];
292             if (increment >= 0) {
293                 iterLast->second[i] = clusterTime[i];
294                 increments.push_back(increment);
295             } else {
296                 STATS_HILOGD(COMP_SVC, "Negative cpu cluster time increment");
297                 return false;
298             }
299         }
300     } else {
301         lastClusterTimeMap_.insert(std::pair<int32_t, std::vector<int64_t>>(uid, clusterTime));
302         increments = clusterTime;
303         STATS_HILOGI(COMP_SVC, "Add last cpu cluster time for uid: %{public}d", uid);
304     }
305     return true;
306 }
307 
ReadUidCpuClusterTime()308 bool CpuTimeReader::ReadUidCpuClusterTime()
309 {
310     std::ifstream input(UID_CPU_CLUSTER_TIME_FILE);
311     if (!input) {
312         STATS_HILOGW(COMP_SVC, "Open file failed");
313         return false;
314     }
315     std::string line;
316     int32_t uid = -1;
317     std::vector<uint16_t> clusters;
318     std::vector<int64_t> clusterTime;
319     while (getline(input, line)) {
320         clusterTime.clear();
321         if (line.find("policy") != line.npos) {
322             ReadPolicy(clusters, line);
323             continue;
324         }
325 
326         std::vector<std::string> splitedLine;
327         Split(line, ':', splitedLine);
328         int64_t result = 0;
329         if (!StatsUtils::ParseStrtollResult(splitedLine[0], result)) {
330             continue;
331         }
332         uid = static_cast<int32_t>(result);
333         if (uid > StatsUtils::INVALID_VALUE) {
334             auto bss = BatteryStatsService::GetInstance();
335             auto uidEntity = bss->GetBatteryStatsCore()->GetEntity(BatteryStatsInfo::CONSUMPTION_TYPE_APP);
336             if (uidEntity) {
337                 uidEntity->UpdateUidMap(uid);
338             }
339         }
340 
341         std::vector<int64_t> increments;
342         if (!ReadClusterTimeIncrement(clusterTime, increments, uid, clusters, splitedLine[1])) {
343             return false;
344         }
345 
346         if (StatsHelper::IsOnBattery()) {
347             STATS_HILOGD(COMP_SVC, "Power supply is not connected. Add the increment");
348             auto iter = clusterTimeMap_.find(uid);
349             if (iter != clusterTimeMap_.end()) {
350                 AddIncrementsToClusterTime(iter->second, increments, clusters);
351             } else {
352                 clusterTimeMap_.insert(std::pair<int32_t, std::vector<int64_t>>(uid, increments));
353                 STATS_HILOGI(COMP_SVC, "Add cpu cluster time for uid: %{public}d", uid);
354             }
355         }
356     }
357     return true;
358 }
359 
AddIncrementsToClusterTime(std::vector<int64_t> & clusterTime,const std::vector<int64_t> & increments,const std::vector<uint16_t> & clusters)360 void CpuTimeReader::AddIncrementsToClusterTime(std::vector<int64_t>& clusterTime,
361     const std::vector<int64_t>& increments, const std::vector<uint16_t>& clusters)
362 {
363     for (uint16_t i = 0; i < clusters.size(); i++) {
364         clusterTime[i] += increments[i];
365     }
366 }
367 
ProcessFreqTime(std::map<uint32_t,std::vector<int64_t>> & map,std::map<uint32_t,std::vector<int64_t>> & increments,std::map<uint32_t,std::vector<int64_t>> & speedTime,int32_t index,int32_t uid)368 bool CpuTimeReader::ProcessFreqTime(std::map<uint32_t, std::vector<int64_t>>& map, std::map<uint32_t,
369     std::vector<int64_t>>& increments, std::map<uint32_t, std::vector<int64_t>>& speedTime, int32_t index, int32_t uid)
370 {
371     auto iterLastTemp = map.find(index);
372     if (iterLastTemp != map.end()) {
373         std::vector<int64_t> lastSpeedTimes = iterLastTemp->second;
374         std::vector<int64_t> newIncrementTimes;
375         newIncrementTimes.clear();
376         for (uint16_t j = 0; j < lastSpeedTimes.size(); j++) {
377             int64_t increment = speedTime.at(index)[j] - lastSpeedTimes[j];
378             if (increment >= 0) {
379                 newIncrementTimes.push_back(increment);
380                 increments.insert(std::pair<uint32_t, std::vector<int64_t>>(index, newIncrementTimes));
381             } else {
382                 STATS_HILOGI(COMP_SVC, "Negative cpu freq time increment");
383                 return false;
384             }
385         }
386         iterLastTemp->second = speedTime.at(index);
387     }
388     return true;
389 }
390 
ReadFreqTimeIncrement(std::map<uint32_t,std::vector<int64_t>> & speedTime,std::map<uint32_t,std::vector<int64_t>> & increments,int32_t uid,std::vector<std::string> & splitedTime)391 bool CpuTimeReader::ReadFreqTimeIncrement(std::map<uint32_t, std::vector<int64_t>>& speedTime,
392     std::map<uint32_t, std::vector<int64_t>>& increments, int32_t uid, std::vector<std::string>& splitedTime)
393 {
394     auto bss = BatteryStatsService::GetInstance();
395     auto parser = bss->GetBatteryStatsParser();
396     uint16_t clusterNum = parser->GetClusterNum();
397     uint16_t count = 0;
398     for (uint16_t i = 0; i < clusterNum; i++) {
399         std::vector<int64_t> tempSpeedTimes;
400         tempSpeedTimes.clear();
401         for (uint16_t j = 0; j < parser->GetSpeedNum(i); j++) {
402             int64_t result = 0;
403             if (!StatsUtils::ParseStrtollResult(splitedTime[count++], result)) {
404                 continue;
405             }
406             int64_t tempTimeMs = result * 10; // Unit is 10ms
407             tempSpeedTimes.push_back(tempTimeMs);
408         }
409         speedTime.insert(std::pair<uint32_t, std::vector<int64_t>>(i, tempSpeedTimes));
410     }
411 
412     auto iterLast = lastFreqTimeMap_.find(uid);
413     if (iterLast == lastFreqTimeMap_.end()) {
414         lastFreqTimeMap_.insert(std::pair<int32_t, std::map<uint32_t, std::vector<int64_t>>>(uid, speedTime));
415         increments = speedTime;
416         STATS_HILOGI(COMP_SVC, "Add last cpu freq time for uid: %{public}d", uid);
417         return true;
418     }
419     for (uint16_t i = 0; i < lastFreqTimeMap_.size(); i++) {
420         if (!ProcessFreqTime(iterLast->second, increments, speedTime, i, uid)) {
421             return false;
422         }
423     }
424     return true;
425 }
426 
DistributeFreqTime(std::map<uint32_t,std::vector<int64_t>> & uidIncrements,std::map<uint32_t,std::vector<int64_t>> & increments)427 void CpuTimeReader::DistributeFreqTime(std::map<uint32_t, std::vector<int64_t>>& uidIncrements,
428     std::map<uint32_t, std::vector<int64_t>>& increments)
429 {
430     auto bss = BatteryStatsService::GetInstance();
431     auto parser = bss->GetBatteryStatsParser();
432     uint16_t clusterNum = parser->GetClusterNum();
433     if (wakelockCounts_ > 0) {
434         for (uint16_t i = 0; i < clusterNum; i++) {
435             uint16_t speedNum = parser->GetSpeedNum(i);
436             for (uint16_t j = 0; j < speedNum; j++) {
437                 int32_t step = 2;
438                 uidIncrements.at(i)[j] = increments.at(i)[j] / step;
439             }
440         }
441         // TO-DO, distribute half of cpu freq time to wakelock holders
442     }
443 }
444 
AddFreqTimeToUid(std::map<uint32_t,std::vector<int64_t>> & uidIncrements,int32_t uid)445 void CpuTimeReader::AddFreqTimeToUid(std::map<uint32_t, std::vector<int64_t>>& uidIncrements, int32_t uid)
446 {
447     auto bss = BatteryStatsService::GetInstance();
448     auto parser = bss->GetBatteryStatsParser();
449     uint16_t clusterNum = parser->GetClusterNum();
450     auto iter = freqTimeMap_.find(uid);
451     if (iter != freqTimeMap_.end()) {
452         for (uint16_t i = 0; i < clusterNum; i++) {
453             uint16_t speedNum = parser->GetSpeedNum(i);
454             for (uint16_t j = 0; j < speedNum; j++) {
455                 iter->second.at(i)[j] += uidIncrements.at(i)[j];
456             }
457         }
458     } else {
459         freqTimeMap_.insert(std::pair<int32_t, std::map<uint32_t, std::vector<int64_t>>>(uid, uidIncrements));
460         STATS_HILOGI(COMP_SVC, "Add cpu freq time for uid: %{public}d", uid);
461     }
462 }
463 
ReadUidCpuFreqTime()464 bool CpuTimeReader::ReadUidCpuFreqTime()
465 {
466     std::ifstream input(UID_CPU_FREQ_TIME_FILE);
467     if (!input) {
468         STATS_HILOGW(COMP_SVC, "Open file failed");
469         return false;
470     }
471     std::string line;
472     int32_t uid = -1;
473     std::map<uint32_t, std::vector<int64_t>> speedTime;
474     while (getline(input, line)) {
475         speedTime.clear();
476         std::vector<std::string> splitedLine;
477         Split(line, ':', splitedLine);
478         if (splitedLine[0] == "uid") {
479             continue;
480         } else {
481             int64_t result = 0;
482             if (!StatsUtils::ParseStrtollResult(splitedLine[0], result)) {
483                 continue;
484             }
485             uid = static_cast<int32_t>(result);
486         }
487         if (uid > StatsUtils::INVALID_VALUE) {
488             auto bss = BatteryStatsService::GetInstance();
489             auto uidEntity =
490                 bss->GetBatteryStatsCore()->GetEntity(BatteryStatsInfo::CONSUMPTION_TYPE_APP);
491             if (uidEntity) {
492                 uidEntity->UpdateUidMap(uid);
493             }
494         }
495         std::vector<std::string> splitedTime;
496         Split(splitedLine[1], ' ', splitedTime);
497 
498         std::map<uint32_t, std::vector<int64_t>> increments;
499         if (!ReadFreqTimeIncrement(speedTime, increments, uid, splitedTime)) {
500             return false;
501         }
502 
503         std::map<uint32_t, std::vector<int64_t>> uidIncrements = increments;
504         DistributeFreqTime(uidIncrements, increments);
505 
506         if (!StatsHelper::IsOnBattery()) {
507             STATS_HILOGD(COMP_SVC, "Power supply is connected, don't add the increment");
508             continue;
509         }
510         AddFreqTimeToUid(uidIncrements, uid);
511     }
512     return true;
513 }
514 
ReadUidTimeIncrement(std::vector<int64_t> & cpuTime,std::vector<int64_t> & uidIncrements,int32_t uid,std::string & timeLine)515 bool CpuTimeReader::ReadUidTimeIncrement(std::vector<int64_t>& cpuTime, std::vector<int64_t>& uidIncrements,
516     int32_t uid, std::string& timeLine)
517 {
518     std::vector<std::string> splitedTime;
519     Split(timeLine, ' ', splitedTime);
520     for (uint16_t i = 0; i < splitedTime.size(); i++) {
521         int64_t tempTime = 0;
522         int64_t result = 0;
523         if (!StatsUtils::ParseStrtollResult(splitedTime[i], result)) {
524             continue;
525         }
526         tempTime = result;
527         cpuTime.push_back(tempTime);
528     }
529 
530     std::vector<int64_t> increments;
531     auto iterLast = lastUidTimeMap_.find(uid);
532     if (iterLast != lastUidTimeMap_.end()) {
533         for (uint16_t i = 0; i < splitedTime.size(); i++) {
534             int64_t increment = 0;
535             increment = cpuTime[i] - iterLast->second[i];
536             if (increment >= 0) {
537                 iterLast->second[i] = cpuTime[i];
538                 increments.push_back(increment);
539             } else {
540                 STATS_HILOGI(COMP_SVC, "Negative cpu time increment");
541                 return false;
542             }
543         }
544     } else {
545         lastUidTimeMap_.insert(std::pair<int32_t, std::vector<int64_t>>(uid, cpuTime));
546         increments = cpuTime;
547         STATS_HILOGI(COMP_SVC, "Add last cpu time for uid: %{public}d", uid);
548     }
549 
550     uidIncrements = increments;
551 
552     if (wakelockCounts_ > 0) {
553         double weight = 0.5;
554         uidIncrements[0] = increments[0] / (StatsUtils::US_IN_MS * 1.0) * weight;
555         uidIncrements[1] = increments[1] / (StatsUtils::US_IN_MS * 1.0) * weight;
556         // TO-DO, distribute half of cpu time to wakelock holders
557     }
558     return true;
559 }
560 
ReadUidCpuTime()561 bool CpuTimeReader::ReadUidCpuTime()
562 {
563     std::ifstream input(UID_CPU_TIME_FILE);
564     if (!input) {
565         STATS_HILOGW(COMP_SVC, "Open file failed");
566         return false;
567     }
568     std::string line;
569     std::vector<int64_t> cpuTime;
570     while (getline(input, line)) {
571         cpuTime.clear();
572         std::vector<std::string> splitedLine;
573         Split(line, ':', splitedLine);
574         int64_t result = 0;
575         if (!StatsUtils::ParseStrtollResult(splitedLine[0], result)) {
576             continue;
577         }
578         int32_t uid = static_cast<int32_t>(result);
579         if (uid > StatsUtils::INVALID_VALUE) {
580             auto bss = BatteryStatsService::GetInstance();
581             auto uidEntity =
582                 bss->GetBatteryStatsCore()->GetEntity(BatteryStatsInfo::CONSUMPTION_TYPE_APP);
583             if (uidEntity) {
584                 uidEntity->UpdateUidMap(uid);
585             }
586         }
587 
588         std::vector<int64_t> uidIncrements;
589         if (!ReadUidTimeIncrement(cpuTime, uidIncrements, uid, splitedLine[1])) {
590             return false;
591         }
592 
593         if (StatsHelper::IsOnBattery()) {
594             STATS_HILOGD(COMP_SVC, "Power supply is not connected. Add the increment");
595             UpdateUidTimeMap(uid, uidIncrements);
596         }
597     }
598     return true;
599 }
600 
UpdateUidTimeMap(int32_t uid,const std::vector<int64_t> & uidIncrements)601 void CpuTimeReader::UpdateUidTimeMap(int32_t uid, const std::vector<int64_t>& uidIncrements)
602 {
603     auto iter = uidTimeMap_.find(uid);
604     if (iter != uidTimeMap_.end()) {
605         for (uint16_t i = 0; i < uidIncrements.size(); i++) {
606             iter->second[i] = uidIncrements[i];
607         }
608     } else {
609         uidTimeMap_.insert(std::pair<int32_t, std::vector<int64_t>>(uid, uidIncrements));
610         STATS_HILOGI(COMP_SVC, "Add cpu time for uid: %{public}d", uid);
611     }
612 }
613 
Split(std::string & origin,char delimiter,std::vector<std::string> & splited)614 void CpuTimeReader::Split(std::string &origin, char delimiter, std::vector<std::string> &splited)
615 {
616     size_t start;
617     size_t end = 0;
618 
619     while ((start = origin.find_first_not_of(delimiter, end)) != std::string::npos) {
620         end = origin.find(delimiter, start);
621         splited.push_back(origin.substr(start, end - start));
622     }
623 }
624 } // namespace PowerMgr
625 } // namespace OHOS