blob: ba8bd5e08f71b91922eac04405c21400a8a3f8a2 [file] [log] [blame]
Darren Hsu673d3b02021-12-28 21:31:24 +08001/*
2 * Copyright (C) 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#include "DvfsStateResidencyDataProvider.h"
17
18#include <android-base/logging.h>
19#include <android-base/parseint.h>
20#include <android-base/strings.h>
21
22#include <string>
23#include <utility>
24
25using android::base::ParseUint;
26using android::base::Split;
27using android::base::StartsWith;
28using android::base::Trim;
29
30static const std::string nameSuffix = "-DVFS";
31
32namespace aidl {
33namespace android {
34namespace hardware {
35namespace power {
36namespace stats {
37
38DvfsStateResidencyDataProvider::DvfsStateResidencyDataProvider(std::string path, uint64_t clockRate,
39 std::vector<Config> cfgs)
Darren Hsu5f322222023-03-13 11:11:55 +080040 : mPowerEntities(std::move(cfgs)), mPath(std::move(path)), mClockRate(clockRate) {}
Darren Hsu673d3b02021-12-28 21:31:24 +080041
42int32_t DvfsStateResidencyDataProvider::matchEntity(char const *line) {
43 for (int32_t i = 0; i < mPowerEntities.size(); i++) {
44 if (mPowerEntities[i].powerEntityName == Trim(std::string(line))) {
45 return i;
46 }
47 }
48 return -1;
49}
50
51int32_t DvfsStateResidencyDataProvider::matchState(char const *line, const Config& powerEntity) {
52 for (int32_t i = 0; i < powerEntity.states.size(); i++) {
53 if (StartsWith(Trim(std::string(line)), powerEntity.states[i].second)) {
54 return i;
55 }
56 }
57 return -1;
58}
59
60bool DvfsStateResidencyDataProvider::parseState(char const *line, uint64_t *duration,
61 uint64_t *count) {
62 std::vector<std::string> parts = Split(line, " ");
63 if (parts.size() != 7) {
64 return false;
65 }
66 if (!ParseUint(Trim(parts[3]), count)) {
67 return false;
68 }
69 if (!ParseUint(Trim(parts[6]), duration)) {
70 return false;
71 }
72 return true;
73}
74
75bool DvfsStateResidencyDataProvider::getStateResidencies(
76 std::unordered_map<std::string, std::vector<StateResidency>> *residencies) {
77 std::unique_ptr<FILE, decltype(&fclose)> fp(fopen(mPath.c_str(), "r"), fclose);
78 if (!fp) {
79 PLOG(ERROR) << __func__ << ":Failed to open file " << mPath;
80 return false;
81 }
82
83 for (const Config &powerEntity : mPowerEntities) {
84 std::vector<StateResidency> stateResidency(powerEntity.states.size());
85 for (int32_t i = 0; i < stateResidency.size(); i++) {
86 stateResidency[i].id = i;
87 }
88 residencies->emplace(powerEntity.powerEntityName + nameSuffix, stateResidency);
89 }
90
91 size_t len = 0;
92 char *line = nullptr;
93
94 int32_t temp, powerEntityIndex, stateId = -1;
95 uint64_t duration, count;
96 auto it = residencies->end();
97
98 while (getline(&line, &len, fp.get()) != -1) {
99 temp = matchEntity(line);
100 // Assign new index only when a new valid entity is encountered.
101 if (temp >= 0) {
102 powerEntityIndex = temp;
103 it = residencies->find(mPowerEntities[powerEntityIndex].powerEntityName + nameSuffix);
104 }
105
Darren Hsu529b6182023-03-14 14:31:43 +0800106 // The given string is last state for each entity.
107 if (StartsWith(Trim(std::string(line)), "last_freq_change_time_ns:"))
108 it = residencies->end();
109
Darren Hsu673d3b02021-12-28 21:31:24 +0800110 if (it != residencies->end()) {
111 stateId = matchState(line, mPowerEntities[powerEntityIndex]);
112
113 if (stateId >= 0) {
114 if (parseState(line, &duration, &count)) {
115 it->second[stateId].totalTimeInStateMs =
116 duration / mClockRate;
117 it->second[stateId].totalStateEntryCount = count;
118 } else {
119 LOG(ERROR) << "Failed to parse duration and count from [" << std::string(line)
120 << "]";
121 return false;
122 }
123 }
124 }
125 }
126
127 free(line);
128
129 return true;
130}
131
132std::unordered_map<std::string, std::vector<State>> DvfsStateResidencyDataProvider::getInfo() {
133 std::unordered_map<std::string, std::vector<State>> info;
134 for (auto const &entity : mPowerEntities) {
135 std::vector<State> stateInfo(entity.states.size());
136 int32_t stateId = 0;
137 for (auto const &state : entity.states) {
138 stateInfo[stateId] = State{
139 .id = stateId,
140 .name = state.first
141 };
142 stateId++;
143 }
144 info.emplace(entity.powerEntityName + nameSuffix, stateInfo);
145 }
146 return info;
147}
148
149} // namespace stats
150} // namespace power
151} // namespace hardware
152} // namespace android
153} // namespace aidl