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