blob: c963f78c8df94a11ec5e248776ae3d05ebc0cd2b [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
Darren Hsud094ba62023-02-07 10:45:26 +0800103 if (stateId < 0) continue;
Darren Hsua3792b22023-01-07 13:43:26 +0800104
Darren Hsud094ba62023-02-07 10:45:26 +0800105 entityIndex = matchEntity(line);
106
107 if (entityIndex < 0) continue;
108
109 it = residencies->find(mConfig.entities[entityIndex].first);
110 if (it != residencies->end()) {
111 if (parseState(line, &duration, &count)) {
112 it->second[stateId].totalTimeInStateMs = duration / US_TO_MS;
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;
Darren Hsua3792b22023-01-07 13:43:26 +0800118 }
119 }
120 }
121
122 free(line);
123
124 return true;
125}
126
127std::unordered_map<std::string, std::vector<State>> CpupmStateResidencyDataProvider::getInfo() {
128 std::unordered_map<std::string, std::vector<State>> info;
129 for (auto const &entity : mConfig.entities) {
130 std::vector<State> stateInfo(mConfig.states.size());
131 int32_t stateId = 0;
132 for (auto const &state : mConfig.states) {
133 stateInfo[stateId] = State{
134 .id = stateId,
135 .name = state.first
136 };
137 stateId++;
138 }
139 info.emplace(entity.first, stateInfo);
140 }
141 return info;
142}
143
144} // namespace stats
145} // namespace power
146} // namespace hardware
147} // namespace android
148} // namespace aidl