blob: 574a23d63311a052aef90206a996776e575c93d4 [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
17#include "AocStateResidencyDataProvider.h"
18
19#include <android-base/logging.h>
Darren Hsudf08a312022-04-19 08:40:05 +080020#include <chrono>
21#include <pthread.h>
Darren Hsu673d3b02021-12-28 21:31:24 +080022
23namespace aidl {
24namespace android {
25namespace hardware {
26namespace power {
27namespace stats {
28
Darren Hsudf08a312022-04-19 08:40:05 +080029struct async_data_t {
30 pthread_cond_t *cond;
31 pthread_mutex_t *lock;
32 uint64_t timeoutMillis;
33 std::unordered_map<std::string, std::vector<StateResidency>> *residencies;
34 std::unordered_map<std::string,
35 std::vector<std::unique_ptr<GenericStateResidencyDataProvider>>> *providers;
36};
37
Darren Hsu673d3b02021-12-28 21:31:24 +080038AocStateResidencyDataProvider::AocStateResidencyDataProvider(std::vector<std::pair<std::string,
Darren Hsudf08a312022-04-19 08:40:05 +080039 std::string>> ids, std::vector<std::pair<std::string, std::string>> states,
40 const uint64_t timeoutMillis) {
Darren Hsu673d3b02021-12-28 21:31:24 +080041 // AoC stats are reported in ticks of 244.140625ns. The transform
42 // function converts ticks to milliseconds.
43 // 1000000 / 244.140625 = 4096.
44 static const uint64_t AOC_CLK = 4096;
Darren Hsudf08a312022-04-19 08:40:05 +080045 static const uint64_t TIMEOUT_MILLIS = 120;
Darren Hsu673d3b02021-12-28 21:31:24 +080046 std::function<uint64_t(uint64_t)> aocTickToMs = [](uint64_t a) { return a / AOC_CLK; };
47 GenericStateResidencyDataProvider::StateResidencyConfig config = {
48 .entryCountSupported = true,
49 .entryCountPrefix = "Counter:",
50 .totalTimeSupported = true,
51 .totalTimePrefix = "Cumulative time:",
52 .totalTimeTransform = aocTickToMs,
53 .lastEntrySupported = true,
54 .lastEntryPrefix = "Time last entered:",
55 .lastEntryTransform = aocTickToMs,
56 };
57 for (const auto &id : ids) {
58 for (const auto &state : states) {
59 std::vector<std::pair<std::string, std::string>> aocStateHeaders = {
60 std::make_pair(state.first, ""),
61 };
62 std::vector<GenericStateResidencyDataProvider::PowerEntityConfig> cfgs;
63 cfgs.emplace_back(generateGenericStateResidencyConfigs(config, aocStateHeaders),
64 id.first, "");
65 std::unique_ptr<GenericStateResidencyDataProvider> sdp(
66 new GenericStateResidencyDataProvider(id.second + state.second, cfgs));
67 mProviders[id.first].push_back(std::move(sdp));
68 }
69 }
Darren Hsudf08a312022-04-19 08:40:05 +080070 mStateCount = states.size();
71 mTimeoutMillis = timeoutMillis == 0 ? TIMEOUT_MILLIS : timeoutMillis;
Darren Hsu673d3b02021-12-28 21:31:24 +080072}
73
Darren Hsudf08a312022-04-19 08:40:05 +080074void *getStateResidenciesAsync(void *arg) {
75 struct timespec start, end;
76 struct async_data_t *async = (struct async_data_t*)arg;
77 uint64_t timeoutUs = async->timeoutMillis * 1000;
78
Darren Hsu673d3b02021-12-28 21:31:24 +080079 // States from the same power entity are merged.
Darren Hsudf08a312022-04-19 08:40:05 +080080 for (const auto &providerList : *async->providers) {
Darren Hsu673d3b02021-12-28 21:31:24 +080081 int32_t stateId = 0;
82 std::string curEntity = providerList.first;
83 std::vector<StateResidency> stateResidencies;
84
85 // Iterate over each provider in the providerList, appending each of the states
86 for (const auto &provider : providerList.second) {
87 std::unordered_map<std::string, std::vector<StateResidency>> residency;
Darren Hsudf08a312022-04-19 08:40:05 +080088
89 clock_gettime(CLOCK_REALTIME, &start);
90 provider->getStateResidencies(&residency);
91 clock_gettime(CLOCK_REALTIME, &end);
92 uint64_t elapsedUs =
93 ((end.tv_sec - start.tv_sec) * 1000000) + ((end.tv_nsec - start.tv_nsec) / 1000);
94
95 if (elapsedUs >= timeoutUs) {
96 LOG(WARNING) << "getStateResidencies latency for " << curEntity
97 << " exceeds time allowed: " << elapsedUs << " us";
98 return 0;
99 }
Darren Hsu673d3b02021-12-28 21:31:24 +0800100
101 // Each provider should only return data for curEntity but checking anyway
102 if (residency.find(curEntity) != residency.end()) {
103 for (auto &r : residency.at(curEntity)) {
104 /*
105 * Modifying stateId here because we are stitching together infos from
106 * multiple GenericStateResidencyDataProviders. stateId must be modified
107 * to maintain uniqueness for a given entity
108 */
109 r.id = stateId++;
110 stateResidencies.push_back(r);
111 }
112 }
113 }
114
Darren Hsudf08a312022-04-19 08:40:05 +0800115 async->residencies->emplace(curEntity, stateResidencies);
Darren Hsu673d3b02021-12-28 21:31:24 +0800116 }
Darren Hsudf08a312022-04-19 08:40:05 +0800117
118 pthread_mutex_lock(async->lock);
119 pthread_cond_signal(async->cond);
120 pthread_mutex_unlock(async->lock);
121
122 return 0;
123}
124
125bool AocStateResidencyDataProvider::getStateResidencies(
126 std::unordered_map<std::string, std::vector<StateResidency>> *residencies) {
127 bool ret = true;
128 int condResult = 0;
129 pthread_t tid;
130 pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
131 pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
132 std::unordered_map<std::string, std::vector<StateResidency>> stateResidencies;
133 struct timespec start, timeout;
134 struct async_data_t async = {
135 .cond = &cond,
136 .lock = &lock,
137 .timeoutMillis = mTimeoutMillis,
138 .residencies = &stateResidencies,
139 .providers = &mProviders
140 };
141
142 pthread_create(&tid, NULL, &getStateResidenciesAsync, (void*)&async);
143
144 clock_gettime(CLOCK_REALTIME, &start);
145
146 uint64_t expirationMillis = mTimeoutMillis * mStateCount;
147 timeout.tv_sec = start.tv_sec + expirationMillis / 1000;
148 uint64_t nsec = start.tv_nsec + (expirationMillis % 1000) * 1000000;
149 if (nsec < 1000000000) {
150 timeout.tv_nsec = nsec;
151 } else {
152 timeout.tv_sec += 1;
153 timeout.tv_nsec = nsec - 1000000000;
154 }
155
156 pthread_mutex_lock(&lock);
157 condResult = pthread_cond_timedwait(&cond, &lock, &timeout);
158 pthread_mutex_unlock(&lock);
159
160 if (condResult != 0) {
161 if (condResult == ETIMEDOUT) {
162 LOG(WARNING) << __func__ << " latency for AoC timeout: " << expirationMillis << " ms";
163 } else {
164 LOG(ERROR) << "Failed to wait for the condition variable: " << condResult;
165 }
166 ret = false;
167 } else {
168 for (const auto &residency : stateResidencies) {
169 residencies->emplace(residency.first, residency.second);
170 }
171 }
172
Darren Hsu673d3b02021-12-28 21:31:24 +0800173 return ret;
174}
175
176std::unordered_map<std::string, std::vector<State>> AocStateResidencyDataProvider::getInfo() {
177 // States from the same power entity are merged
178 std::unordered_map<std::string, std::vector<State>> infos;
179 for (const auto &providerList : mProviders) {
180 int32_t stateId = 0;
181 std::string curEntity = providerList.first;
182 std::vector<State> stateInfos;
183
184 // Iterate over each provider in the providerList, appending each of the states
185 for (const auto &provider : providerList.second) {
186 std::unordered_map<std::string, std::vector<State>> info = provider->getInfo();
187
188 // Each provider should only return data for curEntity but checking anyway
189 if (info.find(curEntity) != info.end()) {
190 for (auto &i : info.at(curEntity)) {
191 /*
192 * Modifying stateId because we are stitching together infos from
193 * multiple GenericStateResidencyDataProviders. stateId must be modified
194 * to maintain uniqueness for a given entity
195 */
196 i.id = stateId++;
197 stateInfos.push_back(i);
198 }
199 }
200 }
201
202 infos.emplace(curEntity, stateInfos);
203 }
204
205 return infos;
206}
207
208} // namespace stats
209} // namespace power
210} // namespace hardware
211} // namespace android
212} // namespace aidl