diff --git a/device.mk b/device.mk index d9ee5e0..d6a156c 100644 --- a/device.mk +++ b/device.mk @@ -16,3 +16,6 @@ PRODUCT_COPY_FILES += \ device/google/gs-common/default-talkback-permissions.xml:$(TARGET_COPY_OUT_PRODUCT)/etc/default-permissions/default-talkback-permissions.xml + +PRODUCT_SOONG_NAMESPACES += \ + device/google/gs-common/powerstats diff --git a/powerstats/Android.bp b/powerstats/Android.bp new file mode 100644 index 0000000..74935c7 --- /dev/null +++ b/powerstats/Android.bp @@ -0,0 +1,24 @@ +soong_namespace { + imports: [ + "hardware/google/pixel", + ], +} + +package { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +cc_library { + name: "android.hardware.power.stats-impl.gs-common", + vendor_available: true, + export_include_dirs: ["include"], + defaults: ["powerstats_pixel_defaults"], + + srcs: [ + "*.cpp", + ], + + shared_libs: [ + "android.hardware.power.stats-impl.pixel", + ], +} diff --git a/powerstats/AocStateResidencyDataProvider.cpp b/powerstats/AocStateResidencyDataProvider.cpp new file mode 100644 index 0000000..c64496d --- /dev/null +++ b/powerstats/AocStateResidencyDataProvider.cpp @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "AocStateResidencyDataProvider.h" + +#include <android-base/logging.h> + +namespace aidl { +namespace android { +namespace hardware { +namespace power { +namespace stats { + +AocStateResidencyDataProvider::AocStateResidencyDataProvider(std::vector<std::pair<std::string, + std::string>> ids, std::vector<std::pair<std::string, std::string>> states) { + // AoC stats are reported in ticks of 244.140625ns. The transform + // function converts ticks to milliseconds. + // 1000000 / 244.140625 = 4096. + static const uint64_t AOC_CLK = 4096; + std::function<uint64_t(uint64_t)> aocTickToMs = [](uint64_t a) { return a / AOC_CLK; }; + GenericStateResidencyDataProvider::StateResidencyConfig config = { + .entryCountSupported = true, + .entryCountPrefix = "Counter:", + .totalTimeSupported = true, + .totalTimePrefix = "Cumulative time:", + .totalTimeTransform = aocTickToMs, + .lastEntrySupported = true, + .lastEntryPrefix = "Time last entered:", + .lastEntryTransform = aocTickToMs, + }; + for (const auto &id : ids) { + for (const auto &state : states) { + std::vector<std::pair<std::string, std::string>> aocStateHeaders = { + std::make_pair(state.first, ""), + }; + std::vector<GenericStateResidencyDataProvider::PowerEntityConfig> cfgs; + cfgs.emplace_back(generateGenericStateResidencyConfigs(config, aocStateHeaders), + id.first, ""); + std::unique_ptr<GenericStateResidencyDataProvider> sdp( + new GenericStateResidencyDataProvider(id.second + state.second, cfgs)); + mProviders[id.first].push_back(std::move(sdp)); + } + } +} + +bool AocStateResidencyDataProvider::getStateResidencies( + std::unordered_map<std::string, std::vector<StateResidency>> *residencies) { + // States from the same power entity are merged. + bool ret = true; + for (const auto &providerList : mProviders) { + int32_t stateId = 0; + std::string curEntity = providerList.first; + std::vector<StateResidency> stateResidencies; + + // Iterate over each provider in the providerList, appending each of the states + for (const auto &provider : providerList.second) { + std::unordered_map<std::string, std::vector<StateResidency>> residency; + ret &= provider->getStateResidencies(&residency); + + // Each provider should only return data for curEntity but checking anyway + if (residency.find(curEntity) != residency.end()) { + for (auto &r : residency.at(curEntity)) { + /* + * Modifying stateId here because we are stitching together infos from + * multiple GenericStateResidencyDataProviders. stateId must be modified + * to maintain uniqueness for a given entity + */ + r.id = stateId++; + stateResidencies.push_back(r); + } + } + } + + residencies->emplace(curEntity, stateResidencies); + } + return ret; +} + +std::unordered_map<std::string, std::vector<State>> AocStateResidencyDataProvider::getInfo() { + // States from the same power entity are merged + std::unordered_map<std::string, std::vector<State>> infos; + for (const auto &providerList : mProviders) { + int32_t stateId = 0; + std::string curEntity = providerList.first; + std::vector<State> stateInfos; + + // Iterate over each provider in the providerList, appending each of the states + for (const auto &provider : providerList.second) { + std::unordered_map<std::string, std::vector<State>> info = provider->getInfo(); + + // Each provider should only return data for curEntity but checking anyway + if (info.find(curEntity) != info.end()) { + for (auto &i : info.at(curEntity)) { + /* + * Modifying stateId because we are stitching together infos from + * multiple GenericStateResidencyDataProviders. stateId must be modified + * to maintain uniqueness for a given entity + */ + i.id = stateId++; + stateInfos.push_back(i); + } + } + } + + infos.emplace(curEntity, stateInfos); + } + + return infos; +} + +} // namespace stats +} // namespace power +} // namespace hardware +} // namespace android +} // namespace aidl diff --git a/powerstats/DevfreqStateResidencyDataProvider.cpp b/powerstats/DevfreqStateResidencyDataProvider.cpp new file mode 100644 index 0000000..d59e1e5 --- /dev/null +++ b/powerstats/DevfreqStateResidencyDataProvider.cpp @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "DevfreqStateResidencyDataProvider.h" + +#include <android-base/logging.h> + +static const std::string nameSuffix = "-DVFS"; +static const std::string pathSuffix = "/time_in_state"; + +namespace aidl { +namespace android { +namespace hardware { +namespace power { +namespace stats { + +DevfreqStateResidencyDataProvider::DevfreqStateResidencyDataProvider(const std::string& name, + const std::string& path) : mName(name + nameSuffix), mPath(path + pathSuffix) {} + +bool DevfreqStateResidencyDataProvider::extractNum(const char *str, char **str_end, int base, + int64_t* num) { + // errno can be set to any non-zero value by a library function call + // regardless of whether there was an error, so it needs to be cleared + // in order to check the error set by strtoll + errno = 0; + *num = std::strtoll(str, str_end, base); + return (errno != ERANGE); +} + +std::vector<std::pair<int64_t, int64_t>> DevfreqStateResidencyDataProvider::parseTimeInState() { + // Using FILE* instead of std::ifstream for performance reasons + std::unique_ptr<FILE, decltype(&fclose)> fp(fopen(mPath.c_str(), "r"), fclose); + if (!fp) { + PLOG(ERROR) << "Failed to open file " << mPath; + return {}; + } + + std::vector<std::pair<int64_t, int64_t>> timeInState; + + char *line = nullptr; + size_t len = 0; + while (getline(&line, &len, fp.get()) != -1) { + char* pEnd; + int64_t frequencyHz, totalTimeMs; + if (!extractNum(line, &pEnd, 10, &frequencyHz) || + !extractNum(pEnd, &pEnd, 10, &totalTimeMs)) { + PLOG(ERROR) << "Failed to parse " << mPath; + free(line); + return {}; + } + + timeInState.push_back({frequencyHz, totalTimeMs}); + } + + free(line); + return timeInState; +} + +bool DevfreqStateResidencyDataProvider::getStateResidencies( + std::unordered_map<std::string, std::vector<StateResidency>> *residencies) { + std::vector<std::pair<int64_t, int64_t>> timeInState = parseTimeInState(); + + if (timeInState.empty()) { + return false; + } + + int32_t id = 0; + std::vector<StateResidency> stateResidencies; + for (const auto[frequencyHz, totalTimeMs] : timeInState) { + StateResidency s = {.id = id++, .totalTimeInStateMs = totalTimeMs}; + stateResidencies.push_back(s); + } + + residencies->emplace(mName, stateResidencies); + return true; +} + +std::unordered_map<std::string, std::vector<State>> DevfreqStateResidencyDataProvider::getInfo() { + std::vector<std::pair<int64_t, int64_t>> timeInState = parseTimeInState(); + + if (timeInState.empty()) { + return {}; + } + + int32_t id = 0; + std::vector<State> states; + for (const auto[frequencyHz, totalTimeMs] : timeInState) { + State s = {.id = id++, .name = std::to_string(frequencyHz / 1000) + "MHz"}; + states.push_back(s); + } + + return {{mName, states}}; +} + +} // namespace stats +} // namespace power +} // namespace hardware +} // namespace android +} // namespace aidl diff --git a/powerstats/DvfsStateResidencyDataProvider.cpp b/powerstats/DvfsStateResidencyDataProvider.cpp new file mode 100644 index 0000000..511159e --- /dev/null +++ b/powerstats/DvfsStateResidencyDataProvider.cpp @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "DvfsStateResidencyDataProvider.h" + +#include <android-base/logging.h> +#include <android-base/parseint.h> +#include <android-base/strings.h> + +#include <string> +#include <utility> + +using android::base::ParseUint; +using android::base::Split; +using android::base::StartsWith; +using android::base::Trim; + +static const std::string nameSuffix = "-DVFS"; + +namespace aidl { +namespace android { +namespace hardware { +namespace power { +namespace stats { + +DvfsStateResidencyDataProvider::DvfsStateResidencyDataProvider(std::string path, uint64_t clockRate, + std::vector<Config> cfgs) + : mPath(std::move(path)), mClockRate(clockRate), mPowerEntities(std::move(cfgs)) {} + +int32_t DvfsStateResidencyDataProvider::matchEntity(char const *line) { + for (int32_t i = 0; i < mPowerEntities.size(); i++) { + if (mPowerEntities[i].powerEntityName == Trim(std::string(line))) { + return i; + } + } + return -1; +} + +int32_t DvfsStateResidencyDataProvider::matchState(char const *line, const Config& powerEntity) { + for (int32_t i = 0; i < powerEntity.states.size(); i++) { + if (StartsWith(Trim(std::string(line)), powerEntity.states[i].second)) { + return i; + } + } + return -1; +} + +bool DvfsStateResidencyDataProvider::parseState(char const *line, uint64_t *duration, + uint64_t *count) { + std::vector<std::string> parts = Split(line, " "); + if (parts.size() != 7) { + return false; + } + if (!ParseUint(Trim(parts[3]), count)) { + return false; + } + if (!ParseUint(Trim(parts[6]), duration)) { + return false; + } + return true; +} + +bool DvfsStateResidencyDataProvider::getStateResidencies( + std::unordered_map<std::string, std::vector<StateResidency>> *residencies) { + std::unique_ptr<FILE, decltype(&fclose)> fp(fopen(mPath.c_str(), "r"), fclose); + if (!fp) { + PLOG(ERROR) << __func__ << ":Failed to open file " << mPath; + return false; + } + + for (const Config &powerEntity : mPowerEntities) { + std::vector<StateResidency> stateResidency(powerEntity.states.size()); + for (int32_t i = 0; i < stateResidency.size(); i++) { + stateResidency[i].id = i; + } + residencies->emplace(powerEntity.powerEntityName + nameSuffix, stateResidency); + } + + size_t len = 0; + char *line = nullptr; + + int32_t temp, powerEntityIndex, stateId = -1; + uint64_t duration, count; + auto it = residencies->end(); + + while (getline(&line, &len, fp.get()) != -1) { + temp = matchEntity(line); + // Assign new index only when a new valid entity is encountered. + if (temp >= 0) { + powerEntityIndex = temp; + it = residencies->find(mPowerEntities[powerEntityIndex].powerEntityName + nameSuffix); + } + + if (it != residencies->end()) { + stateId = matchState(line, mPowerEntities[powerEntityIndex]); + + if (stateId >= 0) { + if (parseState(line, &duration, &count)) { + it->second[stateId].totalTimeInStateMs = + duration / mClockRate; + it->second[stateId].totalStateEntryCount = count; + } else { + LOG(ERROR) << "Failed to parse duration and count from [" << std::string(line) + << "]"; + return false; + } + } + } + } + + free(line); + + return true; +} + +std::unordered_map<std::string, std::vector<State>> DvfsStateResidencyDataProvider::getInfo() { + std::unordered_map<std::string, std::vector<State>> info; + for (auto const &entity : mPowerEntities) { + std::vector<State> stateInfo(entity.states.size()); + int32_t stateId = 0; + for (auto const &state : entity.states) { + stateInfo[stateId] = State{ + .id = stateId, + .name = state.first + }; + stateId++; + } + info.emplace(entity.powerEntityName + nameSuffix, stateInfo); + } + return info; +} + +} // namespace stats +} // namespace power +} // namespace hardware +} // namespace android +} // namespace aidl diff --git a/powerstats/UfsStateResidencyDataProvider.cpp b/powerstats/UfsStateResidencyDataProvider.cpp new file mode 100644 index 0000000..aec7724 --- /dev/null +++ b/powerstats/UfsStateResidencyDataProvider.cpp @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "UfsStateResidencyDataProvider.h" + +#include <android-base/logging.h> +#include <android-base/parseint.h> +#include <android-base/strings.h> + +#include <string> +#include <utility> + +using android::base::ParseInt; +using android::base::Split; +using android::base::StartsWith; +using android::base::Trim; + +namespace aidl { +namespace android { +namespace hardware { +namespace power { +namespace stats { + +const int32_t HIBERNATE_STATE_ID = 0; +const std::string UFS_NAME = "UFS"; + +UfsStateResidencyDataProvider::UfsStateResidencyDataProvider(std::string prefix) : kPrefix(prefix) {} + +bool UfsStateResidencyDataProvider::getStateResidencies( + std::unordered_map<std::string, std::vector<StateResidency>> *residencies) { + StateResidency residency; + residency.id = HIBERNATE_STATE_ID; + + // The transform function converts microseconds to milliseconds. + std::function<uint64_t(uint64_t)> usecToMs = [](uint64_t a) { return a / 1000; }; + + residency.totalTimeInStateMs = usecToMs(readStat(kPrefix + "hibern8_total_us")); + residency.totalStateEntryCount = readStat(kPrefix + "hibern8_exit_cnt"); + residency.lastEntryTimestampMs = usecToMs(readStat(kPrefix + "last_hibern8_enter_time")); + + residencies->emplace(UFS_NAME, std::vector<StateResidency>{residency}); + return true; +} + +std::unordered_map<std::string, std::vector<State>> UfsStateResidencyDataProvider::getInfo() { + return {{UFS_NAME, std::vector<State>{{HIBERNATE_STATE_ID, "HIBERN8"}} }}; +} + +int64_t UfsStateResidencyDataProvider::readStat(std::string path) { + std::unique_ptr<FILE, decltype(&fclose)> fp(fopen(path.c_str(), "r"), fclose); + if (!fp) { + PLOG(ERROR) << __func__ << ":Failed to open file " << path + << " Error = " << strerror(errno); + return 0; + } + const size_t size = 20; + char buf[size]; + (void)fread(&buf, sizeof(char), size, fp.get()); + int64_t ret; + if (!ParseInt(Trim(std::string(buf)), &ret)) { + LOG(ERROR) << "Failed to parse int64 from [" << std::string(buf) << "]"; + } + return ret; +} + +} // namespace stats +} // namespace power +} // namespace hardware +} // namespace android +} // namespace aidl diff --git a/powerstats/include/AocStateResidencyDataProvider.h b/powerstats/include/AocStateResidencyDataProvider.h new file mode 100644 index 0000000..5008912 --- /dev/null +++ b/powerstats/include/AocStateResidencyDataProvider.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#pragma once + +#include <dataproviders/GenericStateResidencyDataProvider.h> +#include <PowerStatsAidl.h> + +namespace aidl { +namespace android { +namespace hardware { +namespace power { +namespace stats { + +class AocStateResidencyDataProvider : public PowerStats::IStateResidencyDataProvider { + public: + AocStateResidencyDataProvider(std::vector<std::pair<std::string, std::string>> ids, + std::vector<std::pair<std::string, std::string>> states); + ~AocStateResidencyDataProvider() = default; + bool getStateResidencies( + std::unordered_map<std::string, std::vector<StateResidency>> *residencies) override; + std::unordered_map<std::string, std::vector<State>> getInfo() override; + + private: + std::unordered_map<std::string /* entity name */, + std::vector<std::unique_ptr<GenericStateResidencyDataProvider>> /* providers */> mProviders; +}; + +} // namespace stats +} // namespace power +} // namespace hardware +} // namespace android +} // namespace aidl \ No newline at end of file diff --git a/powerstats/include/DevfreqStateResidencyDataProvider.h b/powerstats/include/DevfreqStateResidencyDataProvider.h new file mode 100644 index 0000000..8341b43 --- /dev/null +++ b/powerstats/include/DevfreqStateResidencyDataProvider.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#pragma once + +#include <PowerStatsAidl.h> + +namespace aidl { +namespace android { +namespace hardware { +namespace power { +namespace stats { + +class DevfreqStateResidencyDataProvider : public PowerStats::IStateResidencyDataProvider { + public: + DevfreqStateResidencyDataProvider(const std::string& name, const std::string& path); + ~DevfreqStateResidencyDataProvider() = default; + + /* + * See IStateResidencyDataProvider::getStateResidencies + */ + bool getStateResidencies( + std::unordered_map<std::string, std::vector<StateResidency>> *residencies) override; + + /* + * See IStateResidencyDataProvider::getInfo + */ + std::unordered_map<std::string, std::vector<State>> getInfo() override; + + private: + bool extractNum(const char *str, char **str_end, int base, int64_t* num); + std::vector<std::pair<int64_t, int64_t>> parseTimeInState(); + const std::string mName; + const std::string mPath; +}; + +} // namespace stats +} // namespace power +} // namespace hardware +} // namespace android +} // namespace aidl diff --git a/powerstats/include/DvfsStateResidencyDataProvider.h b/powerstats/include/DvfsStateResidencyDataProvider.h new file mode 100644 index 0000000..ca8ab22 --- /dev/null +++ b/powerstats/include/DvfsStateResidencyDataProvider.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#pragma once + +#include <PowerStatsAidl.h> + +namespace aidl { +namespace android { +namespace hardware { +namespace power { +namespace stats { + +class DvfsStateResidencyDataProvider : public PowerStats::IStateResidencyDataProvider { + public: + class Config { + public: + // Power entity name to parse. + std::string powerEntityName; + + // List of state pairs (name to display, name to parse). + std::vector<std::pair<std::string, std::string>> states; + }; + /* + * path - path to dvfs sysfs node. + * clockRate - clock rate in KHz. + */ + DvfsStateResidencyDataProvider(std::string path, uint64_t clockRate, std::vector<Config> cfgs); + ~DvfsStateResidencyDataProvider() = default; + + /* + * See IStateResidencyDataProvider::getStateResidencies + */ + bool getStateResidencies( + std::unordered_map<std::string, std::vector<StateResidency>> *residencies) override; + + /* + * See IStateResidencyDataProvider::getInfo + */ + std::unordered_map<std::string, std::vector<State>> getInfo() override; + + private: + int32_t matchEntity(char const *line); + int32_t matchState(char const *line, const Config& powerEntity); + bool parseState(char const *line, uint64_t *duration, uint64_t *count); + + const std::string mPath; + const uint64_t mClockRate; + std::vector<Config> mPowerEntities; +}; + +} // namespace stats +} // namespace power +} // namespace hardware +} // namespace android +} // namespace aidl diff --git a/powerstats/include/UfsStateResidencyDataProvider.h b/powerstats/include/UfsStateResidencyDataProvider.h new file mode 100644 index 0000000..f4ef268 --- /dev/null +++ b/powerstats/include/UfsStateResidencyDataProvider.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#pragma once + +#include <PowerStatsAidl.h> + +namespace aidl { +namespace android { +namespace hardware { +namespace power { +namespace stats { + +class UfsStateResidencyDataProvider : public PowerStats::IStateResidencyDataProvider { + public: + UfsStateResidencyDataProvider(std::string prefix); + ~UfsStateResidencyDataProvider() = default; + + /* + * See IStateResidencyDataProvider::getStateResidencies + */ + bool getStateResidencies( + std::unordered_map<std::string, std::vector<StateResidency>> *residencies) override; + + /* + * See IStateResidencyDataProvider::getInfo + */ + std::unordered_map<std::string, std::vector<State>> getInfo() override; + + private: + int64_t readStat(std::string path); + + const std::string kPrefix; +}; + +} // namespace stats +} // namespace power +} // namespace hardware +} // namespace android +} // namespace aidl