1 /*
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 "AdaptiveDvfsStateResidencyDataProvider.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
25 using android::base::Split;
26 using android::base::Trim;
27
28 static const std::string pathSuffix = "/time_in_state";
29 static const std::string stateSuffix = "MHz";
30
31 namespace aidl {
32 namespace android {
33 namespace hardware {
34 namespace power {
35 namespace stats {
36
AdaptiveDvfsStateResidencyDataProvider(std::string path,uint64_t clockRate,std::vector<std::pair<std::string,std::string>> powerEntities)37 AdaptiveDvfsStateResidencyDataProvider::AdaptiveDvfsStateResidencyDataProvider(
38 std::string path,
39 uint64_t clockRate,
40 std::vector<std::pair<std::string, std::string>> powerEntities)
41 : DvfsStateResidencyDataProvider(path, clockRate, {}) {
42 size_t len = 0;
43 char *line = nullptr;
44 std::vector<std::pair<std::string, std::string>> states = {};
45 std::vector<std::string> parts;
46
47 for (int32_t i = 0; i < powerEntities.size(); i++) {
48 std::string freqPath = powerEntities[i].second + pathSuffix;
49 std::unique_ptr<FILE, decltype(&fclose)> fp(fopen(freqPath.c_str(), "r"), fclose);
50 if (!fp) {
51 PLOG(ERROR) << __func__ << ":Failed to open file " << freqPath;
52 continue;
53 }
54
55 while (getline(&line, &len, fp.get()) != -1) {
56 parts = Split(Trim(std::string(line)), " ");
57 if (parts.size() > 0) {
58 std::string freqStr = Trim(parts[0]);
59 states.push_back(std::make_pair(
60 freqStr.substr(0, freqStr.length() - 3) + stateSuffix,
61 freqStr));
62 }
63 }
64
65 // Cpufreq data is sorted in ascending order, but power stats are sorted
66 // in descending order. Reverse sorting to maintain consistency with
67 // other power stats.
68 if (states.size() > 1 &&
69 std::atoll(states[0].second.c_str()) < std::atoll(states[1].second.c_str())) {
70 std::reverse(states.begin(), states.end());
71 }
72
73 mPowerEntities.push_back({powerEntities[i].first, std::move(states)});
74 }
75
76 free(line);
77 }
78
getStateResidencies(std::unordered_map<std::string,std::vector<StateResidency>> * residencies)79 bool AdaptiveDvfsStateResidencyDataProvider::getStateResidencies(
80 std::unordered_map<std::string, std::vector<StateResidency>> *residencies) {
81 return DvfsStateResidencyDataProvider::getStateResidencies(residencies);
82 }
83
84 std::unordered_map<std::string, std::vector<State>>
getInfo()85 AdaptiveDvfsStateResidencyDataProvider::getInfo() {
86 return DvfsStateResidencyDataProvider::getInfo();
87 }
88
89 } // namespace stats
90 } // namespace power
91 } // namespace hardware
92 } // namespace android
93 } // namespace aidl
94