blob: c7561d61d1ebb3f198a8dc53765c7ac860d69fc0 [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
106 if (it != residencies->end()) {
107 stateId = matchState(line, mPowerEntities[powerEntityIndex]);
108
109 if (stateId >= 0) {
110 if (parseState(line, &duration, &count)) {
111 it->second[stateId].totalTimeInStateMs =
112 duration / mClockRate;
113 it->second[stateId].totalStateEntryCount = count;
114 } else {
115 LOG(ERROR) << "Failed to parse duration and count from [" << std::string(line)
116 << "]";
117 return false;
118 }
119 }
120 }
121 }
122
123 free(line);
124
125 return true;
126}
127
128std::unordered_map<std::string, std::vector<State>> DvfsStateResidencyDataProvider::getInfo() {
129 std::unordered_map<std::string, std::vector<State>> info;
130 for (auto const &entity : mPowerEntities) {
131 std::vector<State> stateInfo(entity.states.size());
132 int32_t stateId = 0;
133 for (auto const &state : entity.states) {
134 stateInfo[stateId] = State{
135 .id = stateId,
136 .name = state.first
137 };
138 stateId++;
139 }
140 info.emplace(entity.powerEntityName + nameSuffix, stateInfo);
141 }
142 return info;
143}
144
145} // namespace stats
146} // namespace power
147} // namespace hardware
148} // namespace android
149} // namespace aidl