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