blob: bb0e61faca9c35408a6459983db15b99f3f6bc49 [file] [log] [blame]
Darren Hsua3792b22023-01-07 13:43:26 +08001/*
2 * Copyright (C) 2023 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 "CpupmStateResidencyDataProvider.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
30namespace aidl {
31namespace android {
32namespace hardware {
33namespace power {
34namespace stats {
35
36CpupmStateResidencyDataProvider::CpupmStateResidencyDataProvider(
37 const std::string &path, const Config &config)
38 : mPath(std::move(path)), mConfig(std::move(config)) {}
39
40int32_t CpupmStateResidencyDataProvider::matchState(char const *line) {
41 for (int32_t i = 0; i < mConfig.states.size(); i++) {
42 if (mConfig.states[i].second == Trim(std::string(line))) {
43 return i;
44 }
45 }
46 return -1;
47}
48
49int32_t CpupmStateResidencyDataProvider::matchEntity(char const *line) {
50 for (int32_t i = 0; i < mConfig.entities.size(); i++) {
51 if (StartsWith(Trim(std::string(line)), mConfig.entities[i].second)) {
52 return i;
53 }
54 }
55 return -1;
56}
57
58bool CpupmStateResidencyDataProvider::parseState(
59 char const *line, uint64_t *duration, uint64_t *count) {
60 std::vector<std::string> parts = Split(line, " ");
61 if (parts.size() != 5) {
62 return false;
63 }
64 if (!ParseUint(Trim(parts[1]), count)) {
65 return false;
66 }
67 if (!ParseUint(Trim(parts[3]), duration)) {
68 return false;
69 }
70 return true;
71}
72
73bool CpupmStateResidencyDataProvider::getStateResidencies(
74 std::unordered_map<std::string, std::vector<StateResidency>> *residencies) {
75 std::unique_ptr<FILE, decltype(&fclose)> fp(fopen(mPath.c_str(), "r"), fclose);
76 if (!fp) {
77 PLOG(ERROR) << __func__ << ":Failed to open file " << mPath;
78 return false;
79 }
80
81 for (int32_t i = 0; i < mConfig.entities.size(); i++) {
82 std::vector<StateResidency> stateResidencies(mConfig.states.size());
83 for (int32_t j = 0; j < stateResidencies.size(); j++) {
84 stateResidencies[j].id = j;
85 }
86 residencies->emplace(mConfig.entities[i].first, stateResidencies);
87 }
88
89 size_t len = 0;
90 char *line = nullptr;
91
92 int32_t temp, entityIndex, stateId = -1;
93 uint64_t duration, count;
94 auto it = residencies->end();
95
96 while (getline(&line, &len, fp.get()) != -1) {
97 temp = matchState(line);
98 // Assign new id only when a new valid state is encountered.
99 if (temp >= 0) {
100 stateId = temp;
101 }
102
103 if (stateId >= 0) {
104 entityIndex = matchEntity(line);
105 it = residencies->find(mConfig.entities[entityIndex].first);
106
107 if (it != residencies->end()) {
108 if (parseState(line, &duration, &count)) {
109 it->second[stateId].totalTimeInStateMs = duration / US_TO_MS;
110 it->second[stateId].totalStateEntryCount = count;
111 } else {
112 LOG(ERROR) << "Failed to parse duration and count from [" << std::string(line)
113 << "]";
114 return false;
115 }
116 }
117 }
118 }
119
120 free(line);
121
122 return true;
123}
124
125std::unordered_map<std::string, std::vector<State>> CpupmStateResidencyDataProvider::getInfo() {
126 std::unordered_map<std::string, std::vector<State>> info;
127 for (auto const &entity : mConfig.entities) {
128 std::vector<State> stateInfo(mConfig.states.size());
129 int32_t stateId = 0;
130 for (auto const &state : mConfig.states) {
131 stateInfo[stateId] = State{
132 .id = stateId,
133 .name = state.first
134 };
135 stateId++;
136 }
137 info.emplace(entity.first, stateInfo);
138 }
139 return info;
140}
141
142} // namespace stats
143} // namespace power
144} // namespace hardware
145} // namespace android
146} // namespace aidl