blob: 95289bd69917dd29011bfc47851feb0240981f66 [file] [log] [blame]
Robin Pengc2b5ca92021-02-23 20:00:28 +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#define LOG_TAG "libpixelpowerstats"
17
18#include "DvfsStateResidencyDataProvider.h"
19
20#include <android-base/logging.h>
21#include <android-base/parseint.h>
22#include <android-base/strings.h>
23
24#include <string>
25#include <utility>
26
27using android::base::ParseUint;
28using android::base::Split;
29using android::base::StartsWith;
30using android::base::Trim;
31
32namespace android {
33namespace hardware {
34namespace google {
35namespace pixel {
36namespace powerstats {
37
38DvfsStateResidencyDataProvider::DvfsStateResidencyDataProvider(std::string path, uint64_t clockRate)
39 : mPath(std::move(path)), mClockRate(clockRate) {}
40
41void DvfsStateResidencyDataProvider::addEntity(
42 uint32_t id, std::string name, std::vector<std::pair<std::string, std::string>> states) {
43 mPowerEntities.push_back({id, name, states});
44}
45
46int32_t DvfsStateResidencyDataProvider::matchEntity(char *line) {
47 for (auto const &entity : mPowerEntities) {
48 if (entity.powerEntityName == Trim(std::string(line))) {
49 return entity.powerEntityId;
50 }
51 }
52 return -1;
53}
54
55int32_t DvfsStateResidencyDataProvider::matchState(char *line, int32_t entityId) {
56 uint32_t stateId = 0;
57 for (auto const &entity : mPowerEntities) {
58 if (entityId == entity.powerEntityId) {
59 for (auto const &state : entity.states) {
60 if (StartsWith(Trim(std::string(line)), state.second)) {
61 return stateId;
62 }
63 stateId++;
64 }
65 return -1;
66 }
67 }
68 return -1;
69}
70
71bool DvfsStateResidencyDataProvider::parseState(char *line, uint64_t &duration, uint64_t &count) {
72 std::vector<std::string> parts = Split(line, " ");
73 if (parts.size() != 7) {
74 return false;
75 }
76 if (!ParseUint(Trim(parts[3]), &count)) {
77 return false;
78 }
79 if (!ParseUint(Trim(parts[6]), &duration)) {
80 return false;
81 }
82 return true;
83}
84
85bool DvfsStateResidencyDataProvider::getResults(
86 std::unordered_map<uint32_t, PowerEntityStateResidencyResult> &results) {
87 std::unique_ptr<FILE, decltype(&fclose)> fp(fopen(mPath.c_str(), "r"), fclose);
88 if (!fp) {
89 PLOG(ERROR) << __func__ << ":Failed to open file " << mPath
90 << " Error = " << strerror(errno);
91 return false;
92 }
93
94 for (auto const &stateSpace : getStateSpaces()) {
95 PowerEntityStateResidencyResult result = {.powerEntityId = stateSpace.powerEntityId};
96 result.stateResidencyData.resize(stateSpace.states.size());
97 for (uint32_t i = 0; i < result.stateResidencyData.size(); i++) {
98 result.stateResidencyData[i].powerEntityStateId =
99 stateSpace.states[i].powerEntityStateId;
100 }
101 results.insert(std::make_pair(stateSpace.powerEntityId, result));
102 }
103
104 size_t len = 0;
105 char *line = nullptr;
106
107 int32_t temp = -1, entityId = -1, stateId = -1;
108 uint64_t duration, count;
109
110 while (getline(&line, &len, fp.get()) != -1) {
111 temp = matchEntity(line);
112 // Assign entityId only when a new valid entity is encountered.
113 if (temp >= 0) {
114 entityId = temp;
115 }
116 if (entityId >= 0) {
117 stateId = matchState(line, entityId);
118 if (stateId >= 0) {
119 if (parseState(line, duration, count)) {
120 results[entityId].stateResidencyData[stateId].totalTimeInStateMs =
121 duration / mClockRate;
122 results[entityId].stateResidencyData[stateId].totalStateEntryCount = count;
123 } else {
124 LOG(ERROR) << "Failed to parse duration and count from [" << std::string(line)
125 << "]";
126 return false;
127 }
128 }
129 }
130 }
131
132 free(line);
133
134 return true;
135}
136
137std::vector<PowerEntityStateSpace> DvfsStateResidencyDataProvider::getStateSpaces() {
138 std::vector<PowerEntityStateSpace> stateSpaces;
139 stateSpaces.reserve(mPowerEntities.size());
140 for (auto const &entity : mPowerEntities) {
141 PowerEntityStateSpace s = {.powerEntityId = entity.powerEntityId};
142 s.states.resize(entity.states.size());
143 uint32_t stateId = 0;
144 for (auto const &state : entity.states) {
145 s.states[stateId] = {.powerEntityStateId = stateId,
146 .powerEntityStateName = state.first};
147 stateId++;
148 }
149 stateSpaces.emplace_back(s);
150 }
151 return stateSpaces;
152}
153
154} // namespace powerstats
155} // namespace pixel
156} // namespace google
157} // namespace hardware
158} // namespace android