From 0d6392efa620a19b51b1c2ccd329df72a531d26d Mon Sep 17 00:00:00 2001 From: Benjamin Schwartz Date: Tue, 9 Mar 2021 09:02:06 -0800 Subject: [PATCH] Remove power stats HAL 1.0 service Bug: 179527556 Test: dumpsys android.hardware.power.stats.IPowerStats/default Test: device boot and examined logs to make sure no errors related to missing power stats 1.0 Change-Id: Ib8cc394f9968edaf948a2d9700e9f7fcaa5b9dc0 --- CleanSpec.mk | 5 + device.mk | 4 - powerstats/Android.bp | 41 +- powerstats/AocStateResidencyDataProvider.cpp | 123 +-- powerstats/AocStateResidencyDataProvider.h | 34 +- .../AocStateResidencyDataProviderAidl.cpp | 128 --- .../AocStateResidencyDataProviderAidl.h | 45 - powerstats/DvfsStateResidencyDataProvider.cpp | 115 ++- powerstats/DvfsStateResidencyDataProvider.h | 89 +- .../DvfsStateResidencyDataProviderAidl.cpp | 149 ---- .../DvfsStateResidencyDataProviderAidl.h | 68 -- powerstats/RailDataProvider.cpp | 340 -------- powerstats/RailDataProvider.h | 55 -- powerstats/UfsStateResidencyDataProvider.cpp | 90 -- powerstats/UfsStateResidencyDataProvider.h | 58 -- ....hardware.power.stats@1.0-service.gs101.rc | 5 - ...hardware.power.stats@1.0-service.gs101.xml | 11 - powerstats/service.cpp | 792 +++++++++--------- powerstats/serviceaidl.cpp | 523 ------------ 19 files changed, 597 insertions(+), 2078 deletions(-) delete mode 100644 powerstats/AocStateResidencyDataProviderAidl.cpp delete mode 100644 powerstats/AocStateResidencyDataProviderAidl.h delete mode 100644 powerstats/DvfsStateResidencyDataProviderAidl.cpp delete mode 100644 powerstats/DvfsStateResidencyDataProviderAidl.h delete mode 100644 powerstats/RailDataProvider.cpp delete mode 100644 powerstats/RailDataProvider.h delete mode 100644 powerstats/UfsStateResidencyDataProvider.cpp delete mode 100644 powerstats/UfsStateResidencyDataProvider.h delete mode 100644 powerstats/android.hardware.power.stats@1.0-service.gs101.rc delete mode 100644 powerstats/android.hardware.power.stats@1.0-service.gs101.xml delete mode 100644 powerstats/serviceaidl.cpp diff --git a/CleanSpec.mk b/CleanSpec.mk index 10cf0fb5..1ca5183f 100644 --- a/CleanSpec.mk +++ b/CleanSpec.mk @@ -72,3 +72,8 @@ $(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/etc/vintf/manifest/android.h $(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/bin/hw/android.hardware.usb@1.3-service.slider) $(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/etc/init/android.hardware.usb@1.3-service.slider.rc) $(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/etc/vintf/manifest/android.hardware.usb@1.3-service.slider.xml) + +# Power Stats HAL 1.0 to AIDL +$(call add-clean-step, rm -f $(PRODUCT_OUT)/vendor/bin/hw/android.hardware.power.stats@1.0-service.gs101) +$(call add-clean-step, rm -f $(PRODUCT_OUT)/vendor/etc/init/android.hardware.power.stats@1.0-service.gs101.rc) +$(call add-clean-step, rm -f $(PRODUCT_OUT)/vendor/etc/vintf/manifest/android.hardware.power.stats@1.0-service.gs101.xml) diff --git a/device.mk b/device.mk index 194ba720..065d5038 100644 --- a/device.mk +++ b/device.mk @@ -364,10 +364,6 @@ PRODUCT_COPY_FILES += \ -include hardware/google/pixel/power-libperfmgr/aidl/device.mk # PowerStats HAL -PRODUCT_PACKAGES += \ - android.hardware.power.stats@1.0-service.gs101 - -# PowerStats AIDL HAL PRODUCT_PACKAGES += \ android.hardware.power.stats-service.pixel diff --git a/powerstats/Android.bp b/powerstats/Android.bp index fa73e51d..7c7066c1 100644 --- a/powerstats/Android.bp +++ b/powerstats/Android.bp @@ -22,51 +22,12 @@ package { ], } -cc_binary { - // TODO(b/167628903) : remove this - name: "android.hardware.power.stats@1.0-service.gs101", - header_libs: [ - "device_kernel_headers", - ], - relative_install_path: "hw", - init_rc: ["android.hardware.power.stats@1.0-service.gs101.rc"], - vintf_fragments: ["android.hardware.power.stats@1.0-service.gs101.xml"], - srcs: [ - "AocStateResidencyDataProvider.cpp", - "DvfsStateResidencyDataProvider.cpp", - "RailDataProvider.cpp", - "service.cpp", - "UfsStateResidencyDataProvider.cpp", - ], - cflags: [ - "-Wall", - "-Werror", - ], - static_libs: [ - "libpixelpowerstats", - ], - shared_libs: [ - "android.hardware.power.stats@1.0", - "pixelpowerstats_provider_aidl_interface-cpp", - "libbase", - "libbinder", - "libcutils", - "libfmq", - "libhidlbase", - "liblog", - "libutils", - ], - vendor: true, -} - cc_binary { name: "android.hardware.power.stats-service.pixel", init_rc: ["android.hardware.power.stats-service.pixel.rc"], vintf_fragments: ["android.hardware.power.stats-service.pixel.xml"], srcs: [ - "AocStateResidencyDataProviderAidl.cpp", - "DvfsStateResidencyDataProviderAidl.cpp", - "serviceaidl.cpp" + "*.cpp", ], cflags: [ "-Wall", diff --git a/powerstats/AocStateResidencyDataProvider.cpp b/powerstats/AocStateResidencyDataProvider.cpp index 41c75bcf..c64496dd 100644 --- a/powerstats/AocStateResidencyDataProvider.cpp +++ b/powerstats/AocStateResidencyDataProvider.cpp @@ -13,29 +13,25 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#define LOG_TAG "libpixelpowerstats" #include "AocStateResidencyDataProvider.h" #include -#include - +namespace aidl { namespace android { namespace hardware { -namespace google { -namespace pixel { -namespace powerstats { +namespace power { +namespace stats { -AocStateResidencyDataProvider::AocStateResidencyDataProvider( - std::vector> ids, - std::vector> states) { +AocStateResidencyDataProvider::AocStateResidencyDataProvider(std::vector> ids, std::vector> 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 aocTickToMs = [](uint64_t a) { return a / AOC_CLK; }; - StateResidencyConfig config = { + GenericStateResidencyDataProvider::StateResidencyConfig config = { .entryCountSupported = true, .entryCountPrefix = "Counter:", .totalTimeSupported = true, @@ -45,61 +41,88 @@ AocStateResidencyDataProvider::AocStateResidencyDataProvider( .lastEntryPrefix = "Time last entered:", .lastEntryTransform = aocTickToMs, }; - uint32_t state_id; - for (auto &id : ids) { - state_id = 1; - for (auto &state : states) { + for (const auto &id : ids) { + for (const auto &state : states) { std::vector> aocStateHeaders = { - std::make_pair(state.first, ""), + std::make_pair(state.first, ""), }; + std::vector cfgs; + cfgs.emplace_back(generateGenericStateResidencyConfigs(config, aocStateHeaders), + id.first, ""); std::unique_ptr sdp( - new GenericStateResidencyDataProvider(id.second + state.second)); - sdp->addEntity(id.first, PowerEntityConfig(state_id++, "", - generateGenericStateResidencyConfigs( - config, aocStateHeaders))); - mProviders.push_back(std::move(sdp)); + new GenericStateResidencyDataProvider(id.second + state.second, cfgs)); + mProviders[id.first].push_back(std::move(sdp)); } } } -bool AocStateResidencyDataProvider::getResults( - std::unordered_map &results) { - for (auto &provider : mProviders) { - provider->getResults(results); - } - return true; -} - -std::vector AocStateResidencyDataProvider::getStateSpaces() { - // Return state spaces based on all configured providers. +bool AocStateResidencyDataProvider::getStateResidencies( + std::unordered_map> *residencies) { // States from the same power entity are merged. - std::map stateSpaces; - for (auto &provider : mProviders) { - for (auto &stateSpace : provider->getStateSpaces()) { - auto it = stateSpaces.find(stateSpace.powerEntityId); - if (it != stateSpaces.end()) { - auto &states = it->second.states; - auto size = states.size(); - states.resize(size + stateSpace.states.size()); - for (uint32_t i = 0; i < stateSpace.states.size(); i++) { - states[size + i] = stateSpace.states[i]; + bool ret = true; + for (const auto &providerList : mProviders) { + int32_t stateId = 0; + std::string curEntity = providerList.first; + std::vector stateResidencies; + + // Iterate over each provider in the providerList, appending each of the states + for (const auto &provider : providerList.second) { + std::unordered_map> 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); } - } else { - stateSpaces.insert(std::pair( - stateSpace.powerEntityId, stateSpace)); } } - } - std::vector ret; - for (auto &stateSpace : stateSpaces) { - ret.push_back(stateSpace.second); + residencies->emplace(curEntity, stateResidencies); } return ret; } -} // namespace powerstats -} // namespace pixel -} // namespace google +std::unordered_map> AocStateResidencyDataProvider::getInfo() { + // States from the same power entity are merged + std::unordered_map> infos; + for (const auto &providerList : mProviders) { + int32_t stateId = 0; + std::string curEntity = providerList.first; + std::vector stateInfos; + + // Iterate over each provider in the providerList, appending each of the states + for (const auto &provider : providerList.second) { + std::unordered_map> 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/AocStateResidencyDataProvider.h b/powerstats/AocStateResidencyDataProvider.h index eef7ce7b..50089121 100644 --- a/powerstats/AocStateResidencyDataProvider.h +++ b/powerstats/AocStateResidencyDataProvider.h @@ -13,35 +13,33 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#ifndef HARDWARE_GOOGLE_PIXEL_POWERSTATS_AOCSTATERESIDENCYDATAPROVIDER_H -#define HARDWARE_GOOGLE_PIXEL_POWERSTATS_AOCSTATERESIDENCYDATAPROVIDER_H +#pragma once -#include -#include +#include +#include +namespace aidl { namespace android { namespace hardware { -namespace google { -namespace pixel { -namespace powerstats { +namespace power { +namespace stats { -class AocStateResidencyDataProvider : public IStateResidencyDataProvider { +class AocStateResidencyDataProvider : public PowerStats::IStateResidencyDataProvider { public: - AocStateResidencyDataProvider(std::vector> ids, + AocStateResidencyDataProvider(std::vector> ids, std::vector> states); ~AocStateResidencyDataProvider() = default; - bool getResults( - std::unordered_map &results) override; - std::vector getStateSpaces() override; + bool getStateResidencies( + std::unordered_map> *residencies) override; + std::unordered_map> getInfo() override; private: - std::vector> mProviders; + std::unordered_map> /* providers */> mProviders; }; -} // namespace powerstats -} // namespace pixel -} // namespace google +} // namespace stats +} // namespace power } // namespace hardware } // namespace android - -#endif // HARDWARE_GOOGLE_PIXEL_POWERSTATS_AOCSTATERESIDENCYDATAPROVIDER_H +} // namespace aidl \ No newline at end of file diff --git a/powerstats/AocStateResidencyDataProviderAidl.cpp b/powerstats/AocStateResidencyDataProviderAidl.cpp deleted file mode 100644 index 3759a66a..00000000 --- a/powerstats/AocStateResidencyDataProviderAidl.cpp +++ /dev/null @@ -1,128 +0,0 @@ -/* - * 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 "AocStateResidencyDataProviderAidl.h" - -#include - -namespace aidl { -namespace android { -namespace hardware { -namespace power { -namespace stats { - -AocStateResidencyDataProvider::AocStateResidencyDataProvider(std::vector> ids, std::vector> 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 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> aocStateHeaders = { - std::make_pair(state.first, ""), - }; - std::vector cfgs; - cfgs.emplace_back(generateGenericStateResidencyConfigs(config, aocStateHeaders), - id.first, ""); - std::unique_ptr sdp( - new GenericStateResidencyDataProvider(id.second + state.second, cfgs)); - mProviders[id.first].push_back(std::move(sdp)); - } - } -} - -bool AocStateResidencyDataProvider::getStateResidencies( - std::unordered_map> *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 stateResidencies; - - // Iterate over each provider in the providerList, appending each of the states - for (const auto &provider : providerList.second) { - std::unordered_map> 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> AocStateResidencyDataProvider::getInfo() { - // States from the same power entity are merged - std::unordered_map> infos; - for (const auto &providerList : mProviders) { - int32_t stateId = 0; - std::string curEntity = providerList.first; - std::vector stateInfos; - - // Iterate over each provider in the providerList, appending each of the states - for (const auto &provider : providerList.second) { - std::unordered_map> 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/AocStateResidencyDataProviderAidl.h b/powerstats/AocStateResidencyDataProviderAidl.h deleted file mode 100644 index 50089121..00000000 --- a/powerstats/AocStateResidencyDataProviderAidl.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * 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 -#include - -namespace aidl { -namespace android { -namespace hardware { -namespace power { -namespace stats { - -class AocStateResidencyDataProvider : public PowerStats::IStateResidencyDataProvider { - public: - AocStateResidencyDataProvider(std::vector> ids, - std::vector> states); - ~AocStateResidencyDataProvider() = default; - bool getStateResidencies( - std::unordered_map> *residencies) override; - std::unordered_map> getInfo() override; - - private: - std::unordered_map> /* providers */> mProviders; -}; - -} // namespace stats -} // namespace power -} // namespace hardware -} // namespace android -} // namespace aidl \ No newline at end of file diff --git a/powerstats/DvfsStateResidencyDataProvider.cpp b/powerstats/DvfsStateResidencyDataProvider.cpp index 95289bd6..511159ef 100644 --- a/powerstats/DvfsStateResidencyDataProvider.cpp +++ b/powerstats/DvfsStateResidencyDataProvider.cpp @@ -13,8 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#define LOG_TAG "libpixelpowerstats" - #include "DvfsStateResidencyDataProvider.h" #include @@ -29,97 +27,90 @@ 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 google { -namespace pixel { -namespace powerstats { +namespace power { +namespace stats { -DvfsStateResidencyDataProvider::DvfsStateResidencyDataProvider(std::string path, uint64_t clockRate) - : mPath(std::move(path)), mClockRate(clockRate) {} +DvfsStateResidencyDataProvider::DvfsStateResidencyDataProvider(std::string path, uint64_t clockRate, + std::vector cfgs) + : mPath(std::move(path)), mClockRate(clockRate), mPowerEntities(std::move(cfgs)) {} -void DvfsStateResidencyDataProvider::addEntity( - uint32_t id, std::string name, std::vector> states) { - mPowerEntities.push_back({id, name, states}); -} - -int32_t DvfsStateResidencyDataProvider::matchEntity(char *line) { - for (auto const &entity : mPowerEntities) { - if (entity.powerEntityName == Trim(std::string(line))) { - return entity.powerEntityId; +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 *line, int32_t entityId) { - uint32_t stateId = 0; - for (auto const &entity : mPowerEntities) { - if (entityId == entity.powerEntityId) { - for (auto const &state : entity.states) { - if (StartsWith(Trim(std::string(line)), state.second)) { - return stateId; - } - stateId++; - } - 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 *line, uint64_t &duration, uint64_t &count) { +bool DvfsStateResidencyDataProvider::parseState(char const *line, uint64_t *duration, + uint64_t *count) { std::vector parts = Split(line, " "); if (parts.size() != 7) { return false; } - if (!ParseUint(Trim(parts[3]), &count)) { + if (!ParseUint(Trim(parts[3]), count)) { return false; } - if (!ParseUint(Trim(parts[6]), &duration)) { + if (!ParseUint(Trim(parts[6]), duration)) { return false; } return true; } -bool DvfsStateResidencyDataProvider::getResults( - std::unordered_map &results) { +bool DvfsStateResidencyDataProvider::getStateResidencies( + std::unordered_map> *residencies) { std::unique_ptr fp(fopen(mPath.c_str(), "r"), fclose); if (!fp) { - PLOG(ERROR) << __func__ << ":Failed to open file " << mPath - << " Error = " << strerror(errno); + PLOG(ERROR) << __func__ << ":Failed to open file " << mPath; return false; } - for (auto const &stateSpace : getStateSpaces()) { - PowerEntityStateResidencyResult result = {.powerEntityId = stateSpace.powerEntityId}; - result.stateResidencyData.resize(stateSpace.states.size()); - for (uint32_t i = 0; i < result.stateResidencyData.size(); i++) { - result.stateResidencyData[i].powerEntityStateId = - stateSpace.states[i].powerEntityStateId; + for (const Config &powerEntity : mPowerEntities) { + std::vector stateResidency(powerEntity.states.size()); + for (int32_t i = 0; i < stateResidency.size(); i++) { + stateResidency[i].id = i; } - results.insert(std::make_pair(stateSpace.powerEntityId, result)); + residencies->emplace(powerEntity.powerEntityName + nameSuffix, stateResidency); } size_t len = 0; char *line = nullptr; - int32_t temp = -1, entityId = -1, stateId = -1; + 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 entityId only when a new valid entity is encountered. + // Assign new index only when a new valid entity is encountered. if (temp >= 0) { - entityId = temp; + powerEntityIndex = temp; + it = residencies->find(mPowerEntities[powerEntityIndex].powerEntityName + nameSuffix); } - if (entityId >= 0) { - stateId = matchState(line, entityId); + + if (it != residencies->end()) { + stateId = matchState(line, mPowerEntities[powerEntityIndex]); + if (stateId >= 0) { - if (parseState(line, duration, count)) { - results[entityId].stateResidencyData[stateId].totalTimeInStateMs = + if (parseState(line, &duration, &count)) { + it->second[stateId].totalTimeInStateMs = duration / mClockRate; - results[entityId].stateResidencyData[stateId].totalStateEntryCount = count; + it->second[stateId].totalStateEntryCount = count; } else { LOG(ERROR) << "Failed to parse duration and count from [" << std::string(line) << "]"; @@ -134,25 +125,25 @@ bool DvfsStateResidencyDataProvider::getResults( return true; } -std::vector DvfsStateResidencyDataProvider::getStateSpaces() { - std::vector stateSpaces; - stateSpaces.reserve(mPowerEntities.size()); +std::unordered_map> DvfsStateResidencyDataProvider::getInfo() { + std::unordered_map> info; for (auto const &entity : mPowerEntities) { - PowerEntityStateSpace s = {.powerEntityId = entity.powerEntityId}; - s.states.resize(entity.states.size()); - uint32_t stateId = 0; + std::vector stateInfo(entity.states.size()); + int32_t stateId = 0; for (auto const &state : entity.states) { - s.states[stateId] = {.powerEntityStateId = stateId, - .powerEntityStateName = state.first}; + stateInfo[stateId] = State{ + .id = stateId, + .name = state.first + }; stateId++; } - stateSpaces.emplace_back(s); + info.emplace(entity.powerEntityName + nameSuffix, stateInfo); } - return stateSpaces; + return info; } -} // namespace powerstats -} // namespace pixel -} // namespace google +} // namespace stats +} // namespace power } // namespace hardware } // namespace android +} // namespace aidl diff --git a/powerstats/DvfsStateResidencyDataProvider.h b/powerstats/DvfsStateResidencyDataProvider.h index ffa14146..ca8ab22b 100644 --- a/powerstats/DvfsStateResidencyDataProvider.h +++ b/powerstats/DvfsStateResidencyDataProvider.h @@ -13,71 +13,56 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#ifndef HARDWARE_GOOGLE_PIXEL_POWERSTATS_DVFSSTATERESIDENCYDATAPROVIDER_H -#define HARDWARE_GOOGLE_PIXEL_POWERSTATS_DVFSSTATERESIDENCYDATAPROVIDER_H +#pragma once -#include +#include +namespace aidl { namespace android { namespace hardware { -namespace google { -namespace pixel { -namespace powerstats { +namespace power { +namespace stats { -class DvfsStateResidencyDataProvider : public IStateResidencyDataProvider { +class DvfsStateResidencyDataProvider : public PowerStats::IStateResidencyDataProvider { public: - /* - * path - path to dvfs sysfs node. - * clockRate - clock rate in KHz. - */ - DvfsStateResidencyDataProvider(std::string path, uint64_t clockRate); - ~DvfsStateResidencyDataProvider() = default; - - /* - * id - the power entity id - * name - the power entity name to parse from sysfs node - * frequencies - list of pairs (frequency display name, frequency in sysfs - * node). - */ - void addEntity(uint32_t id, std::string name, - std::vector> frequencies); - - /* - * See IStateResidencyDataProvider::getResults. - */ - bool getResults( - std::unordered_map &results) override; - - /* - * See IStateResidencyDataProvider::getStateSpaces. - */ - std::vector getStateSpaces() override; - - private: - int32_t matchEntity(char *line); - int32_t matchState(char *line, int32_t entityId); - bool parseState(char *line, uint64_t &duration, uint64_t &count); - - const std::string mPath; - const uint64_t mClockRate; - - struct config { - // Power entity id. - uint32_t powerEntityId; - + class Config { + public: // Power entity name to parse. std::string powerEntityName; // List of state pairs (name to display, name to parse). std::vector> states; }; - std::vector mPowerEntities; + /* + * path - path to dvfs sysfs node. + * clockRate - clock rate in KHz. + */ + DvfsStateResidencyDataProvider(std::string path, uint64_t clockRate, std::vector cfgs); + ~DvfsStateResidencyDataProvider() = default; + + /* + * See IStateResidencyDataProvider::getStateResidencies + */ + bool getStateResidencies( + std::unordered_map> *residencies) override; + + /* + * See IStateResidencyDataProvider::getInfo + */ + std::unordered_map> 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 mPowerEntities; }; -} // namespace powerstats -} // namespace pixel -} // namespace google +} // namespace stats +} // namespace power } // namespace hardware } // namespace android - -#endif // HARDWARE_GOOGLE_PIXEL_POWERSTATS_DVFSSTATERESIDENCYDATAPROVIDER_H +} // namespace aidl diff --git a/powerstats/DvfsStateResidencyDataProviderAidl.cpp b/powerstats/DvfsStateResidencyDataProviderAidl.cpp deleted file mode 100644 index ca6ea9ad..00000000 --- a/powerstats/DvfsStateResidencyDataProviderAidl.cpp +++ /dev/null @@ -1,149 +0,0 @@ -/* - * 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 "DvfsStateResidencyDataProviderAidl.h" - -#include -#include -#include - -#include -#include - -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 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 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> *residencies) { - std::unique_ptr 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(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> DvfsStateResidencyDataProvider::getInfo() { - std::unordered_map> info; - for (auto const &entity : mPowerEntities) { - std::vector 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/DvfsStateResidencyDataProviderAidl.h b/powerstats/DvfsStateResidencyDataProviderAidl.h deleted file mode 100644 index ca8ab22b..00000000 --- a/powerstats/DvfsStateResidencyDataProviderAidl.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * 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 - -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> states; - }; - /* - * path - path to dvfs sysfs node. - * clockRate - clock rate in KHz. - */ - DvfsStateResidencyDataProvider(std::string path, uint64_t clockRate, std::vector cfgs); - ~DvfsStateResidencyDataProvider() = default; - - /* - * See IStateResidencyDataProvider::getStateResidencies - */ - bool getStateResidencies( - std::unordered_map> *residencies) override; - - /* - * See IStateResidencyDataProvider::getInfo - */ - std::unordered_map> 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 mPowerEntities; -}; - -} // namespace stats -} // namespace power -} // namespace hardware -} // namespace android -} // namespace aidl diff --git a/powerstats/RailDataProvider.cpp b/powerstats/RailDataProvider.cpp deleted file mode 100644 index d0efc174..00000000 --- a/powerstats/RailDataProvider.cpp +++ /dev/null @@ -1,340 +0,0 @@ -/* - * Copyright (C) 2018 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. - */ - -#define LOG_TAG "libpixelpowerstats" - -#include "RailDataProvider.h" - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -namespace android { -namespace hardware { -namespace google { -namespace pixel { -namespace powerstats { - -#define MAX_FILE_PATH_LEN 128 -#define MAX_DEVICE_NAME_LEN 64 -#define MAX_QUEUE_SIZE 8192 - -constexpr char kIioDirRoot[] = "/sys/bus/iio/devices/"; -const char *const kDeviceNames[] = {"s2mpg10-odpm", "s2mpg11-odpm"}; -constexpr char kDeviceType[] = "iio:device"; -constexpr uint32_t MAX_SAMPLING_RATE = 10; -constexpr uint64_t WRITE_TIMEOUT_NS = 1000000000; - -#define MAX_RAIL_NAME_LEN 50 -#define STR(s) #s -#define XSTR(s) STR(s) - -void RailDataProvider::findIioPowerMonitorNodes() { - struct dirent *ent; - int fd; - char devName[MAX_DEVICE_NAME_LEN]; - char filePath[MAX_FILE_PATH_LEN]; - DIR *iioDir = opendir(kIioDirRoot); - if (!iioDir) { - ALOGE("Error opening directory: %s, error: %d", kIioDirRoot, errno); - return; - } - while (ent = readdir(iioDir), ent) { - if (strcmp(ent->d_name, ".") != 0 && strcmp(ent->d_name, "..") != 0 && - strlen(ent->d_name) > strlen(kDeviceType) && - strncmp(ent->d_name, kDeviceType, strlen(kDeviceType)) == 0) { - snprintf(filePath, MAX_FILE_PATH_LEN, "%s/%s", ent->d_name, "name"); - fd = openat(dirfd(iioDir), filePath, O_RDONLY); - if (fd < 0) { - ALOGW("Failed to open directory: %s, error: %d", filePath, errno); - continue; - } - if (read(fd, devName, MAX_DEVICE_NAME_LEN) < 0) { - ALOGW("Failed to read device name from file: %s(%d)", filePath, fd); - close(fd); - continue; - } - - for (const auto &kDeviceName : kDeviceNames) { - if (strncmp(devName, kDeviceName, strlen(kDeviceName)) == 0) { - snprintf(filePath, MAX_FILE_PATH_LEN, "%s/%s", kIioDirRoot, ent->d_name); - mOdpm.devicePaths.push_back(filePath); - } - } - close(fd); - } - } - closedir(iioDir); - return; -} - -size_t RailDataProvider::parsePowerRails() { - std::string data; - std::string railFileName; - std::string spsFileName; - uint32_t index = 0; - uint32_t samplingRate; - for (const auto &path : mOdpm.devicePaths) { - railFileName = path + "/enabled_rails"; - spsFileName = path + "/sampling_rate"; - if (!android::base::ReadFileToString(spsFileName, &data)) { - ALOGW("Error reading file: %s", spsFileName.c_str()); - continue; - } - samplingRate = strtoul(data.c_str(), NULL, 10); - if (!samplingRate || samplingRate == ULONG_MAX) { - ALOGE("Error parsing: %s", spsFileName.c_str()); - break; - } - if (!android::base::ReadFileToString(railFileName, &data)) { - ALOGW("Error reading file: %s", railFileName.c_str()); - continue; - } - std::istringstream railNames(data); - std::string line; - while (std::getline(railNames, line)) { - std::vector words = android::base::Split(line, ":]["); - if (words.size() == 4) { - const std::string channelName = words[1]; - if (mOdpm.railsInfo.count(channelName) == 0) { - const std::string subsysName = words[3]; - mOdpm.railsInfo.emplace(channelName, RailData{.devicePath = path, - .index = index, - .subsysName = subsysName, - .samplingRate = samplingRate}); - index++; - } else { - ALOGW("There exists rails with the same name (not supported): %s." \ - " Only the last occurrence of rail energy will be provided.", - channelName.c_str()); - } - } else { - ALOGW("Unexpected format in file: %s", railFileName.c_str()); - } - } - } - return index; -} - -int RailDataProvider::parseIioEnergyNodeString(const std::string &contents, OnDeviceMmt &odpm) { - std::istringstream energyData(contents); - std::string line; - - int ret = 0; - uint64_t timestamp = 0; - bool timestampRead = false; - - while (std::getline(energyData, line)) { - bool parseLineSuccess = false; - - if (timestampRead == false) { - /* Read timestamp from boot (ms) */ - if (sscanf(line.c_str(), "t=%" PRIu64, ×tamp) == 1) { - if (timestamp == 0 || timestamp == ULLONG_MAX) { - ALOGW("Potentially wrong timestamp: %" PRIu64, timestamp); - } - timestampRead = true; - parseLineSuccess = true; - } - - } else { - /* Read rail energy */ - uint64_t energy = 0; - char railNameRaw[MAX_RAIL_NAME_LEN + 1]; - if (sscanf(line.c_str(), - "CH%*d(T=%*" PRIu64 ")[%" XSTR(MAX_RAIL_NAME_LEN) "[^]]], %" PRIu64, - railNameRaw, &energy) == 2) { - std::string railName(railNameRaw); - - /* If the count == 0, the rail may not be enabled */ - /* The count cannot be > 1; mChannelIds is a map */ - if (odpm.railsInfo.count(railName) == 1) { - size_t index = odpm.railsInfo[railName].index; - odpm.reading[index].index = index; - odpm.reading[index].timestamp = timestamp; - odpm.reading[index].energy = energy; - if (odpm.reading[index].energy == ULLONG_MAX) { - ALOGW("Potentially wrong energy value on rail: %s", railName.c_str()); - } - } - parseLineSuccess = true; - } - } - - if (parseLineSuccess == false) { - ret = -1; - break; - } - } - - return ret; -} - -int RailDataProvider::parseIioEnergyNode(std::string devName) { - int ret; - std::string data; - std::string fileName = devName + "/energy_value"; - if (!android::base::ReadFileToString(fileName, &data)) { - ALOGE("Error reading file: %s", fileName.c_str()); - return -1; - } - - ret = parseIioEnergyNodeString(data, mOdpm); - if (ret != 0) { - ALOGW("Unexpected format in file: %s", fileName.c_str()); - } - return ret; -} - -Status RailDataProvider::parseIioEnergyNodes() { - Status ret = Status::SUCCESS; - if (mOdpm.hwEnabled == false) { - return Status::NOT_SUPPORTED; - } - - for (const auto &devicePath : mOdpm.devicePaths) { - if (parseIioEnergyNode(devicePath) < 0) { - ALOGE("Error in parsing power stats"); - ret = Status::FILESYSTEM_ERROR; - break; - } - } - return ret; -} - -RailDataProvider::RailDataProvider() { - findIioPowerMonitorNodes(); - size_t numRails = parsePowerRails(); - if (mOdpm.devicePaths.empty() || numRails == 0) { - mOdpm.hwEnabled = false; - } else { - mOdpm.hwEnabled = true; - mOdpm.reading.resize(numRails); - } -} - -Return RailDataProvider::getRailInfo(IPowerStats::getRailInfo_cb _hidl_cb) { - hidl_vec rInfo; - Status ret = Status::SUCCESS; - size_t index; - std::lock_guard _lock(mOdpm.mLock); - if (mOdpm.hwEnabled == false) { - ALOGI("getRailInfo not supported"); - _hidl_cb(rInfo, Status::NOT_SUPPORTED); - return Void(); - } - rInfo.resize(mOdpm.railsInfo.size()); - for (const auto &railData : mOdpm.railsInfo) { - index = railData.second.index; - rInfo[index].railName = railData.first; - rInfo[index].subsysName = railData.second.subsysName; - rInfo[index].index = index; - rInfo[index].samplingRate = railData.second.samplingRate; - } - _hidl_cb(rInfo, ret); - return Void(); -} - -Return RailDataProvider::getEnergyData(const hidl_vec &railIndices, - IPowerStats::getEnergyData_cb _hidl_cb) { - hidl_vec eVal; - std::lock_guard _lock(mOdpm.mLock); - Status ret = parseIioEnergyNodes(); - - if (ret != Status::SUCCESS) { - ALOGE("Failed to getEnergyData"); - _hidl_cb(eVal, ret); - return Void(); - } - - if (railIndices.size() == 0) { - eVal.resize(mOdpm.railsInfo.size()); - memcpy(&eVal[0], &mOdpm.reading[0], mOdpm.reading.size() * sizeof(EnergyData)); - } else { - eVal.resize(railIndices.size()); - int i = 0; - for (const auto &railIndex : railIndices) { - if (railIndex >= mOdpm.reading.size()) { - ret = Status::INVALID_INPUT; - eVal.resize(0); - break; - } - memcpy(&eVal[i], &mOdpm.reading[railIndex], sizeof(EnergyData)); - i++; - } - } - _hidl_cb(eVal, ret); - return Void(); -} - -Return RailDataProvider::streamEnergyData(uint32_t timeMs, uint32_t samplingRate, - IPowerStats::streamEnergyData_cb _hidl_cb) { - std::lock_guard _lock(mOdpm.mLock); - if (mOdpm.fmqSynchronized != nullptr) { - _hidl_cb(MessageQueueSync::Descriptor(), 0, 0, Status::INSUFFICIENT_RESOURCES); - return Void(); - } - uint32_t sps = std::min(samplingRate, MAX_SAMPLING_RATE); - uint32_t numSamples = timeMs * sps / 1000; - mOdpm.fmqSynchronized.reset(new (std::nothrow) MessageQueueSync(MAX_QUEUE_SIZE, true)); - if (mOdpm.fmqSynchronized == nullptr || mOdpm.fmqSynchronized->isValid() == false) { - mOdpm.fmqSynchronized = nullptr; - _hidl_cb(MessageQueueSync::Descriptor(), 0, 0, Status::INSUFFICIENT_RESOURCES); - return Void(); - } - std::thread pollThread = std::thread([this, sps, numSamples]() { - uint64_t sleepTimeUs = 1000000 / sps; - uint32_t currSamples = 0; - while (currSamples < numSamples) { - mOdpm.mLock.lock(); - if (parseIioEnergyNodes() == Status::SUCCESS) { - mOdpm.fmqSynchronized->writeBlocking(&mOdpm.reading[0], mOdpm.reading.size(), - WRITE_TIMEOUT_NS); - mOdpm.mLock.unlock(); - currSamples++; - if (usleep(sleepTimeUs) < 0) { - ALOGW("Sleep interrupted"); - break; - } - } else { - mOdpm.mLock.unlock(); - break; - } - } - mOdpm.mLock.lock(); - mOdpm.fmqSynchronized = nullptr; - mOdpm.mLock.unlock(); - return; - }); - pollThread.detach(); - _hidl_cb(*(mOdpm.fmqSynchronized)->getDesc(), numSamples, mOdpm.reading.size(), - Status::SUCCESS); - return Void(); -} - -} // namespace powerstats -} // namespace pixel -} // namespace google -} // namespace hardware -} // namespace android diff --git a/powerstats/RailDataProvider.h b/powerstats/RailDataProvider.h deleted file mode 100644 index 61313e20..00000000 --- a/powerstats/RailDataProvider.h +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef ANDROID_HARDWARE_POWERSTATS_RAILDATAPROVIDER_H -#define ANDROID_HARDWARE_POWERSTATS_RAILDATAPROVIDER_H - -#include -#include - -namespace android { -namespace hardware { -namespace google { -namespace pixel { -namespace powerstats { - -typedef MessageQueue MessageQueueSync; -struct RailData { - std::string devicePath; - uint32_t index; - std::string subsysName; - uint32_t samplingRate; -}; - -struct OnDeviceMmt { - std::mutex mLock; - bool hwEnabled; - std::vector devicePaths; - std::map railsInfo; - std::vector reading; - std::unique_ptr fmqSynchronized; -}; - -class RailDataProvider : public IRailDataProvider { -public: - RailDataProvider(); - // Methods from ::android::hardware::power::stats::V1_0::IPowerStats follow. - Return getRailInfo(IPowerStats::getRailInfo_cb _hidl_cb) override; - Return getEnergyData(const hidl_vec& railIndices, - IPowerStats::getEnergyData_cb _hidl_cb) override; - Return streamEnergyData(uint32_t timeMs, uint32_t samplingRate, - IPowerStats::streamEnergyData_cb _hidl_cb) override; - private: - OnDeviceMmt mOdpm; - void findIioPowerMonitorNodes(); - size_t parsePowerRails(); - int parseIioEnergyNodeString(const std::string &contents, - OnDeviceMmt &odpm); - int parseIioEnergyNode(std::string devName); - Status parseIioEnergyNodes(); -}; - -} // namespace powerstats -} // namespace pixel -} // namespace google -} // namespace hardware -} // namespace android - -#endif // ANDROID_HARDWARE_POWERSTATS_RAILDATAPROVIDER_H diff --git a/powerstats/UfsStateResidencyDataProvider.cpp b/powerstats/UfsStateResidencyDataProvider.cpp deleted file mode 100644 index 7ca6f3bb..00000000 --- a/powerstats/UfsStateResidencyDataProvider.cpp +++ /dev/null @@ -1,90 +0,0 @@ -/* - * 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. - */ -#define LOG_TAG "libpixelpowerstats" - -#include "UfsStateResidencyDataProvider.h" - -#include -#include -#include - -#include -#include - -using android::base::ParseUint; -using android::base::Split; -using android::base::StartsWith; -using android::base::Trim; - -namespace android { -namespace hardware { -namespace google { -namespace pixel { -namespace powerstats { - -const uint32_t HIBERNATE_STATE_ID = 0; - -UfsStateResidencyDataProvider::UfsStateResidencyDataProvider(uint32_t powerEntityId) - : mPowerEntityId(powerEntityId) {} - -bool UfsStateResidencyDataProvider::getResults( - std::unordered_map &results) { - PowerEntityStateResidencyResult result = { - .powerEntityId = mPowerEntityId, - .stateResidencyData = {{.powerEntityStateId = HIBERNATE_STATE_ID}}}; - - // The transform function converts microseconds to milliseconds. - std::function usecToMs = [](uint64_t a) { return a / 1000; }; - - std::string prefix = "/sys/bus/platform/devices/14700000.ufs/ufs_stats/"; - - result.stateResidencyData[0].totalTimeInStateMs = - usecToMs(readStat(prefix + "hibern8_total_us")); - result.stateResidencyData[0].totalStateEntryCount = readStat(prefix + "hibern8_exit_cnt"); - result.stateResidencyData[0].lastEntryTimestampMs = - usecToMs(readStat(prefix + "last_hibern8_enter_time")); - results.insert(std::make_pair(mPowerEntityId, result)); - return true; -} - -std::vector UfsStateResidencyDataProvider::getStateSpaces() { - return {{.powerEntityId = mPowerEntityId, - .states = {{.powerEntityStateId = HIBERNATE_STATE_ID, - .powerEntityStateName = "HIBERN8"}}}}; -} - -uint64_t UfsStateResidencyDataProvider::readStat(std::string path) { - std::unique_ptr 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()); - uint64_t ret; - if (!ParseUint(Trim(std::string(buf)), &ret)) { - LOG(ERROR) << "Failed to parse uint64 from [" << std::string(buf) << "]"; - } - return ret; -} - -} // namespace powerstats -} // namespace pixel -} // namespace google -} // namespace hardware -} // namespace android diff --git a/powerstats/UfsStateResidencyDataProvider.h b/powerstats/UfsStateResidencyDataProvider.h deleted file mode 100644 index 8d1ea736..00000000 --- a/powerstats/UfsStateResidencyDataProvider.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * 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. - */ -#ifndef HARDWARE_GOOGLE_PIXEL_POWERSTATS_UFSSTATERESIDENCYDATAPROVIDER_H -#define HARDWARE_GOOGLE_PIXEL_POWERSTATS_UFSSTATERESIDENCYDATAPROVIDER_H - -#include - -namespace android { -namespace hardware { -namespace google { -namespace pixel { -namespace powerstats { - -class UfsStateResidencyDataProvider : public IStateResidencyDataProvider { - public: - /* - * powerEntityId - id for the UFS power entity. - */ - UfsStateResidencyDataProvider(uint32_t powerEntityId); - ~UfsStateResidencyDataProvider() = default; - - /* - * See IStateResidencyDataProvider::getResults. - */ - bool getResults( - std::unordered_map &results) override; - - /* - * See IStateResidencyDataProvider::getStateSpaces. - */ - std::vector getStateSpaces() override; - - private: - uint64_t readStat(std::string path); - - uint32_t mPowerEntityId; -}; - -} // namespace powerstats -} // namespace pixel -} // namespace google -} // namespace hardware -} // namespace android - -#endif // HARDWARE_GOOGLE_PIXEL_POWERSTATS_UFSSTATERESIDENCYDATAPROVIDER_H diff --git a/powerstats/android.hardware.power.stats@1.0-service.gs101.rc b/powerstats/android.hardware.power.stats@1.0-service.gs101.rc deleted file mode 100644 index afc35804..00000000 --- a/powerstats/android.hardware.power.stats@1.0-service.gs101.rc +++ /dev/null @@ -1,5 +0,0 @@ -service vendor.power.stats-hal-1-0 /vendor/bin/hw/android.hardware.power.stats@1.0-service.gs101 - interface android.hardware.power.stats@1.0::IPowerStats default - class hal - user system - group system diff --git a/powerstats/android.hardware.power.stats@1.0-service.gs101.xml b/powerstats/android.hardware.power.stats@1.0-service.gs101.xml deleted file mode 100644 index 2e9956ff..00000000 --- a/powerstats/android.hardware.power.stats@1.0-service.gs101.xml +++ /dev/null @@ -1,11 +0,0 @@ - - -    android.hardware.power.stats -    hwbinder -    1.0 -    -       IPowerStats -       default -    - - diff --git a/powerstats/service.cpp b/powerstats/service.cpp index 4cf1f357..632de322 100644 --- a/powerstats/service.cpp +++ b/powerstats/service.cpp @@ -14,313 +14,174 @@ * limitations under the License. */ -#define LOG_TAG "android.hardware.power.stats@1.0-service.gs101" - -#include -#include -#include -#include -#include -#include -#include -#include +#define LOG_TAG "android.hardware.power.stats-service.pixel" +#include #include "AocStateResidencyDataProvider.h" #include "DvfsStateResidencyDataProvider.h" -#include "RailDataProvider.h" -#include "UfsStateResidencyDataProvider.h" +#include +#include +#include +#include +#include +#include -using android::OK; -using android::sp; -using android::status_t; +#include +#include +#include +#include +#include -// libhwbinder: -using android::hardware::configureRpcThreadpool; -using android::hardware::joinRpcThreadpool; +using aidl::android::hardware::power::stats::AocStateResidencyDataProvider; +using aidl::android::hardware::power::stats::DisplayStateResidencyDataProvider; +using aidl::android::hardware::power::stats::DvfsStateResidencyDataProvider; +using aidl::android::hardware::power::stats::EnergyConsumerType; +using aidl::android::hardware::power::stats::GenericStateResidencyDataProvider; +using aidl::android::hardware::power::stats::IioEnergyMeterDataProvider; +using aidl::android::hardware::power::stats::PixelStateResidencyDataProvider; +using aidl::android::hardware::power::stats::PowerStats; +using aidl::android::hardware::power::stats::PowerStatsEnergyConsumer; -// Generated HIDL files -using android::hardware::power::stats::V1_0::IPowerStats; -using android::hardware::power::stats::V1_0::PowerEntityType; -using android::hardware::power::stats::V1_0::implementation::PowerStats; +constexpr char kBootHwSoCRev[] = "ro.boot.hw.soc.rev"; -// Pixel specific -using android::hardware::google::pixel::powerstats::AidlStateResidencyDataProvider; -using android::hardware::google::pixel::powerstats::AocStateResidencyDataProvider; -using android::hardware::google::pixel::powerstats::DvfsStateResidencyDataProvider; -using android::hardware::google::pixel::powerstats::generateGenericStateResidencyConfigs; -using android::hardware::google::pixel::powerstats::GenericStateResidencyDataProvider; -using android::hardware::google::pixel::powerstats::PowerEntityConfig; -using android::hardware::google::pixel::powerstats::RailDataProvider; -using android::hardware::google::pixel::powerstats::StateResidencyConfig; -using android::hardware::google::pixel::powerstats::UfsStateResidencyDataProvider; - -// A constant to represnt the number of nanoseconds in one millisecond. -static const int NS_TO_MS = 1000000; - -void addAoCStats(PowerStats *const service) { +void addAoC(std::shared_ptr p) { std::string prefix = "/sys/devices/platform/19000000.aoc/control/"; // Add AoC cores (a32, ff1, hf0, and hf1) - std::vector> coreIds = { - {service->addPowerEntity("AoC-A32", PowerEntityType::SUBSYSTEM), prefix + "a32_"}, - {service->addPowerEntity("AoC-FF1", PowerEntityType::SUBSYSTEM), prefix + "ff1_"}, - {service->addPowerEntity("AoC-HF1", PowerEntityType::SUBSYSTEM), prefix + "hf1_"}, - {service->addPowerEntity("AoC-HF0", PowerEntityType::SUBSYSTEM), prefix + "hf0_"}, + std::vector> coreIds = { + {"AoC-A32", prefix + "a32_"}, + {"AoC-FF1", prefix + "ff1_"}, + {"AoC-HF1", prefix + "hf1_"}, + {"AoC-HF0", prefix + "hf0_"}, }; std::vector> coreStates = { {"DWN", "off"}, {"RET", "retention"}, {"WFI", "wfi"}}; - service->addStateResidencyDataProvider(new AocStateResidencyDataProvider(coreIds, coreStates)); + p->addStateResidencyDataProvider(std::make_shared(coreIds, + coreStates)); // Add AoC voltage stats - std::vector> voltageIds = { - {service->addPowerEntity("AoC-Voltage", PowerEntityType::SUBSYSTEM), - prefix + "voltage_"}, + std::vector> voltageIds = { + {"AoC-Voltage", prefix + "voltage_"}, }; std::vector> voltageStates = {{"NOM", "nominal"}, {"SUD", "super_underdrive"}, {"UUD", "ultra_underdrive"}, {"UD", "underdrive"}}; - service->addStateResidencyDataProvider( - new AocStateResidencyDataProvider(voltageIds, voltageStates)); + p->addStateResidencyDataProvider( + std::make_shared(voltageIds, voltageStates)); // Add AoC monitor mode - std::vector> monitorIds = { - {service->addPowerEntity("AoC", PowerEntityType::SUBSYSTEM), prefix + "monitor_"}, + std::vector> monitorIds = { + {"AoC", prefix + "monitor_"}, }; std::vector> monitorStates = { {"MON", "mode"}, }; - service->addStateResidencyDataProvider( - new AocStateResidencyDataProvider(monitorIds, monitorStates)); + p->addStateResidencyDataProvider( + std::make_shared(monitorIds, monitorStates)); } -void addCpuCStateStats(PowerStats *const service) { - // CPU stats are reported in nanoseconds. The transform function - // converts nanoseconds to milliseconds. - std::function cpuNsToMs = [](uint64_t a) { return a / NS_TO_MS; }; - StateResidencyConfig cStateConfig = { - .entryCountSupported = true, - .entryCountPrefix = "down_count:", - .totalTimeSupported = true, - .totalTimePrefix = "total_down_time_ns:", - .totalTimeTransform = cpuNsToMs, - .lastEntrySupported = true, - .lastEntryPrefix = "last_down_time_ns:", - .lastEntryTransform = cpuNsToMs, - }; +void addDvfsStats(std::shared_ptr p) { + // A constant to represent the number of nanoseconds in one millisecond + const int NS_TO_MS = 1000000; - sp cStateSdp = new GenericStateResidencyDataProvider( - "/sys/devices/platform/1742048c.acpm_stats/core_stats"); - for (std::string state : - {"CORE00", "CORE01", "CORE02", "CORE03", "CORE10", "CORE11", "CORE20", "CORE21"}) { - cStateSdp->addEntity(service->addPowerEntity(state, PowerEntityType::SUBSYSTEM), - PowerEntityConfig("CORES:", generateGenericStateResidencyConfigs( - cStateConfig, - {std::make_pair("DOWN", state)}))); - } - for (std::string state : {"CLUSTER0", "CLUSTER1", "CLUSTER2"}) { - cStateSdp->addEntity( - service->addPowerEntity(state, PowerEntityType::SUBSYSTEM), - PowerEntityConfig("CLUSTERS:", - generateGenericStateResidencyConfigs( - cStateConfig, {std::make_pair("DOWN", state)}))); - } - service->addStateResidencyDataProvider(cStateSdp); + std::vector cfgs; + + cfgs.push_back({"MIF", { + std::make_pair("3172KHz", "3172000"), + std::make_pair("2730KHz", "2730000"), + std::make_pair("2535KHz", "2535000"), + std::make_pair("2288KHz", "2288000"), + std::make_pair("2028KHz", "2028000"), + std::make_pair("1716KHz", "1716000"), + std::make_pair("1539KHz", "1539000"), + std::make_pair("1352KHz", "1352000"), + std::make_pair("1014KHz", "1014000"), + std::make_pair("845KHz", "845000"), + std::make_pair("676KHz", "676000"), + std::make_pair("546KHz", "546000"), + std::make_pair("421KHz", "421000"), + std::make_pair("0KHz", "0"), + }}); + + cfgs.push_back({"CL0", { + std::make_pair("2024KHz", "2024000"), + std::make_pair("1950KHz", "1950000"), + std::make_pair("1868KHz", "1868000"), + std::make_pair("1803KHz", "1803000"), + std::make_pair("1745KHz", "1745000"), + std::make_pair("1704KHz", "1704000"), + std::make_pair("1598KHz", "1598000"), + std::make_pair("1459KHz", "1459000"), + std::make_pair("1401KHz", "1401000"), + std::make_pair("1328KHz", "1328000"), + std::make_pair("1197KHz", "1197000"), + std::make_pair("1098KHz", "1098000"), + std::make_pair("930KHz", "930000"), + std::make_pair("889KHz", "889000"), + std::make_pair("738KHz", "738000"), + std::make_pair("574KHz", "574000"), + std::make_pair("300KHz", "300000"), + std::make_pair("0KHz", "0"), + }}); + + cfgs.push_back({"CL1", { + std::make_pair("2253KHz", "2253000"), + std::make_pair("2130KHz", "2130000"), + std::make_pair("1999KHz", "1999000"), + std::make_pair("1836KHz", "1836000"), + std::make_pair("1663KHz", "1663000"), + std::make_pair("1491KHz", "1491000"), + std::make_pair("1328KHz", "1328000"), + std::make_pair("1197KHz", "1197000"), + std::make_pair("1024KHz", "1024000"), + std::make_pair("910KHz", "910000"), + std::make_pair("799KHz", "799000"), + std::make_pair("696KHz", "696000"), + std::make_pair("533KHz", "533000"), + std::make_pair("400KHz", "400000"), + std::make_pair("0KHz", "0"), + }}); + + cfgs.push_back({"CL2", { + std::make_pair("2630KHz", "2630000"), + std::make_pair("2507KHz", "2507000"), + std::make_pair("2401KHz", "2401000"), + std::make_pair("2302KHz", "2302000"), + std::make_pair("2252KHz", "2252000"), + std::make_pair("2188KHz", "2188000"), + std::make_pair("2048KHz", "2048000"), + std::make_pair("1901KHz", "1901000"), + std::make_pair("1826KHz", "1826000"), + std::make_pair("1745KHz", "1745000"), + std::make_pair("1582KHz", "1582000"), + std::make_pair("1426KHz", "1426000"), + std::make_pair("1277KHz", "1277000"), + std::make_pair("1237KHz", "1237000"), + std::make_pair("1106KHz", "1106000"), + std::make_pair("984KHz", "984000"), + std::make_pair("851KHz", "851000"), + std::make_pair("848KHz", "848000"), + std::make_pair("500KHz", "500000"), + std::make_pair("0KHz", "0"), + }}); + + cfgs.push_back({"TPU", { + std::make_pair("1066MHz", "1066000000"), + }}); + + p->addStateResidencyDataProvider(std::make_shared( + "/sys/devices/platform/1742048c.acpm_stats/fvp_stats", NS_TO_MS, cfgs)); } -void addDvfsStats(PowerStats *const service) { - sp dvfsSdp = new DvfsStateResidencyDataProvider( - "/sys/devices/platform/1742048c.acpm_stats/fvp_stats", NS_TO_MS); +void addSoC(std::shared_ptr p) { + // A constant to represent the number of nanoseconds in one millisecond. + const int NS_TO_MS = 1000000; - dvfsSdp->addEntity(service->addPowerEntity("MIF-DVFS", PowerEntityType::SUBSYSTEM), "MIF", - { - std::make_pair("3172KHz", "3172000"), - std::make_pair("2730KHz", "2730000"), - std::make_pair("2535KHz", "2535000"), - std::make_pair("2288KHz", "2288000"), - std::make_pair("2028KHz", "2028000"), - std::make_pair("1716KHz", "1716000"), - std::make_pair("1539KHz", "1539000"), - std::make_pair("1352KHz", "1352000"), - std::make_pair("1014KHz", "1014000"), - std::make_pair("845KHz", "845000"), - std::make_pair("676KHz", "676000"), - std::make_pair("546KHz", "546000"), - std::make_pair("421KHz", "421000"), - std::make_pair("0KHz", "0"), - }); - - dvfsSdp->addEntity(service->addPowerEntity("CL0-DVFS", PowerEntityType::SUBSYSTEM), "CL0", - { - std::make_pair("2196KHz", "2196000"), - std::make_pair("2098KHz", "2098000"), - std::make_pair("2024KHz", "2024000"), - std::make_pair("1950KHz", "1950000"), - std::make_pair("1868KHz", "1868000"), - std::make_pair("1745KHz", "1745000"), - std::make_pair("1598KHz", "1598000"), - std::make_pair("1459KHz", "1459000"), - std::make_pair("1328KHz", "1328000"), - std::make_pair("1197KHz", "1197000"), - std::make_pair("1098KHz", "1098000"), - std::make_pair("889KHz", "889000"), - std::make_pair("738KHz", "738000"), - std::make_pair("574KHz", "574000"), - std::make_pair("300KHz", "300000"), - std::make_pair("0KHz", "0"), - }); - - dvfsSdp->addEntity(service->addPowerEntity("CL1-DVFS", PowerEntityType::SUBSYSTEM), "CL1", - { - std::make_pair("2466KHz", "2466000"), - std::make_pair("2393KHz", "2393000"), - std::make_pair("2348KHz", "2348000"), - std::make_pair("2253KHz", "2253000"), - std::make_pair("2130KHz", "2130000"), - std::make_pair("1999KHz", "1999000"), - std::make_pair("1836KHz", "1836000"), - std::make_pair("1663KHz", "1663000"), - std::make_pair("1491KHz", "1491000"), - std::make_pair("1328KHz", "1328000"), - std::make_pair("1197KHz", "1197000"), - std::make_pair("1024KHz", "1024000"), - std::make_pair("910KHz", "910000"), - std::make_pair("799KHz", "799000"), - std::make_pair("696KHz", "696000"), - std::make_pair("533KHz", "533000"), - std::make_pair("400KHz", "400000"), - std::make_pair("0KHz", "0"), - }); - - dvfsSdp->addEntity(service->addPowerEntity("CL2-DVFS", PowerEntityType::SUBSYSTEM), "CL2", - { - std::make_pair("3195KHz", "3195000"), - std::make_pair("3097KHz", "3097000"), - std::make_pair("2999KHz", "2999000"), - std::make_pair("2900KHz", "2900000"), - std::make_pair("2802KHz", "2802000"), - std::make_pair("2704KHz", "2704000"), - std::make_pair("2630KHz", "2630000"), - std::make_pair("2507KHz", "2507000"), - std::make_pair("2401KHz", "2401000"), - std::make_pair("2302KHz", "2302000"), - std::make_pair("2188KHz", "2188000"), - std::make_pair("2048KHz", "2048000"), - std::make_pair("1901KHz", "1901000"), - std::make_pair("1745KHz", "1745000"), - std::make_pair("1582KHz", "1582000"), - std::make_pair("1426KHz", "1426000"), - std::make_pair("1237KHz", "1237000"), - std::make_pair("1106KHz", "1106000"), - std::make_pair("984KHz", "984000"), - std::make_pair("848KHz", "848000"), - std::make_pair("500KHz", "500000"), - std::make_pair("0KHz", "0"), - }); - - // TODO(sujee): Complete frequency table for TPU. - dvfsSdp->addEntity(service->addPowerEntity("TPU-DVFS", PowerEntityType::SUBSYSTEM), "TPU", - { - std::make_pair("1066MHz", "1066000000"), - }); - - service->addStateResidencyDataProvider(dvfsSdp); -} - -void addGPUStats(PowerStats *const service) { - StateResidencyConfig gpuStateConfig = { - .entryCountSupported = true, - .entryCountPrefix = "count = ", - .totalTimeSupported = true, - .totalTimePrefix = "total_time = ", - .lastEntrySupported = true, - .lastEntryPrefix = "last_entry_time = ", - }; - - sp gpu = new GenericStateResidencyDataProvider( - "/sys/devices/platform/1c500000.mali/power_stats"); - - PowerEntityConfig onOffConfig("Summary stats: (times in ms)", - generateGenericStateResidencyConfigs( - gpuStateConfig, {{"DOWN", "OFF:"}, {"UP", "ON:"}})); - gpu->addEntity(service->addPowerEntity("GPU", PowerEntityType::SUBSYSTEM), onOffConfig); - - PowerEntityConfig DVFSConfig( - "DVFS stats: (times in ms)", - generateGenericStateResidencyConfigs(gpuStateConfig, {{"996MHz", "996000:"}, - {"885MHz", "885000:"}, - {"750MHz", "750000:"}, - {"434MHz", "434000:"}, - {"302MHz", "302000:"}, - {"151MHz", "151000:"}})); - gpu->addEntity(service->addPowerEntity("GPU-DVFS", PowerEntityType::SUBSYSTEM), DVFSConfig); - service->addStateResidencyDataProvider(gpu); -} - -void addNFCStats(PowerStats *const service) { - StateResidencyConfig nfcStateConfig = { - .entryCountSupported = true, - .entryCountPrefix = "Cumulative count:", - .totalTimeSupported = true, - .totalTimePrefix = "Cumulative duration msec:", - .lastEntrySupported = true, - .lastEntryPrefix = "Last entry timestamp msec:", - }; - std::vector> nfcStateHeaders = { - std::make_pair("IDLE", "Idle mode:"), - std::make_pair("ACTIVE", "Active mode:"), - std::make_pair("ACTIVE-RW", "Active Reader/Writer mode:"), - }; - - sp nfcSdp = new GenericStateResidencyDataProvider( - "/sys/devices/platform/10960000.hsi2c/i2c-4/4-0008/power_stats"); - nfcSdp->addEntity(service->addPowerEntity("NFC", PowerEntityType::SUBSYSTEM), - PowerEntityConfig("NFC subsystem", generateGenericStateResidencyConfigs( - nfcStateConfig, nfcStateHeaders))); - service->addStateResidencyDataProvider(nfcSdp); -} - -void addPCIeStats(PowerStats *const service) { - // Add PCIe power entities for Modem and WiFi - StateResidencyConfig pcieStateConfig = { - .entryCountSupported = true, - .entryCountPrefix = "Cumulative count:", - .totalTimeSupported = true, - .totalTimePrefix = "Cumulative duration msec:", - .lastEntrySupported = true, - .lastEntryPrefix = "Last entry timestamp msec:", - }; - std::vector> pcieStateHeaders = { - std::make_pair("UP", "Link up:"), - std::make_pair("DOWN", "Link down:"), - }; - - // Add PCIe - Modem - sp pcieModemSdp = new GenericStateResidencyDataProvider( - "/sys/devices/platform/11920000.pcie/power_stats"); - uint32_t pcieModemId = service->addPowerEntity("PCIe-Modem", PowerEntityType::SUBSYSTEM); - pcieModemSdp->addEntity( - pcieModemId, - PowerEntityConfig("Version: 1", generateGenericStateResidencyConfigs( - pcieStateConfig, pcieStateHeaders))); - service->addStateResidencyDataProvider(pcieModemSdp); - - // Add PCIe - WiFi - sp pcieWifiSdp = new GenericStateResidencyDataProvider( - "/sys/devices/platform/14520000.pcie/power_stats"); - uint32_t pcieWifiId = service->addPowerEntity("PCIe-WiFi", PowerEntityType::SUBSYSTEM); - pcieWifiSdp->addEntity( - pcieWifiId, - PowerEntityConfig("Version: 1", generateGenericStateResidencyConfigs( - pcieStateConfig, pcieStateHeaders))); - service->addStateResidencyDataProvider(pcieWifiSdp); -} - -void addSocStats(PowerStats *const service) { // ACPM stats are reported in nanoseconds. The transform function // converts nanoseconds to milliseconds. std::function acpmNsToMs = [](uint64_t a) { return a / NS_TO_MS; }; - StateResidencyConfig lpmStateConfig = { + const GenericStateResidencyDataProvider::StateResidencyConfig lpmStateConfig = { .entryCountSupported = true, .entryCountPrefix = "success_count:", .totalTimeSupported = true, @@ -330,7 +191,7 @@ void addSocStats(PowerStats *const service) { .lastEntryPrefix = "last_entry_time_ns:", .lastEntryTransform = acpmNsToMs, }; - StateResidencyConfig downStateConfig = { + const GenericStateResidencyDataProvider::StateResidencyConfig downStateConfig = { .entryCountSupported = true, .entryCountPrefix = "down_count:", .totalTimeSupported = true, @@ -340,7 +201,7 @@ void addSocStats(PowerStats *const service) { .lastEntryPrefix = "last_down_time_ns:", .lastEntryTransform = acpmNsToMs, }; - StateResidencyConfig reqStateConfig = { + const GenericStateResidencyDataProvider::StateResidencyConfig reqStateConfig = { .entryCountSupported = true, .entryCountPrefix = "req_up_count:", .totalTimeSupported = true, @@ -351,141 +212,312 @@ void addSocStats(PowerStats *const service) { .lastEntryTransform = acpmNsToMs, }; - std::vector> powerStateHeaders = { + const std::vector> powerStateHeaders = { std::make_pair("SICD", "SICD"), std::make_pair("SLEEP", "SLEEP"), std::make_pair("SLEEP_SLCMON", "SLEEP_SLCMON"), std::make_pair("STOP", "STOP"), }; - std::vector> mifReqStateHeaders = { + const std::vector> mifReqStateHeaders = { std::make_pair("AOC", "AOC"), std::make_pair("GSA", "GSA"), }; - std::vector> slcReqStateHeaders = { + const std::vector> slcReqStateHeaders = { std::make_pair("AOC", "AOC"), }; - sp socSdp = new GenericStateResidencyDataProvider( - "/sys/devices/platform/1742048c.acpm_stats/soc_stats"); + std::vector cfgs; + cfgs.emplace_back(generateGenericStateResidencyConfigs(lpmStateConfig, powerStateHeaders), + "LPM", "LPM:"); + cfgs.emplace_back(generateGenericStateResidencyConfigs(downStateConfig, powerStateHeaders), + "MIF", "MIF:"); + cfgs.emplace_back(generateGenericStateResidencyConfigs(reqStateConfig, mifReqStateHeaders), + "MIF-REQ", "MIF_REQ:"); + cfgs.emplace_back(generateGenericStateResidencyConfigs(downStateConfig, powerStateHeaders), + "SLC", "SLC:"); + cfgs.emplace_back(generateGenericStateResidencyConfigs(reqStateConfig, slcReqStateHeaders), + "SLC-REQ", "SLC_REQ:"); - socSdp->addEntity(service->addPowerEntity("LPM", PowerEntityType::SUBSYSTEM), - PowerEntityConfig("LPM:", generateGenericStateResidencyConfigs( - lpmStateConfig, powerStateHeaders))); - socSdp->addEntity(service->addPowerEntity("MIF", PowerEntityType::SUBSYSTEM), - PowerEntityConfig("MIF:", generateGenericStateResidencyConfigs( - downStateConfig, powerStateHeaders))); - socSdp->addEntity(service->addPowerEntity("MIF-REQ", PowerEntityType::SUBSYSTEM), - PowerEntityConfig("MIF_REQ:", generateGenericStateResidencyConfigs( - reqStateConfig, mifReqStateHeaders))); - socSdp->addEntity(service->addPowerEntity("SLC", PowerEntityType::SUBSYSTEM), - PowerEntityConfig("SLC:", generateGenericStateResidencyConfigs( - downStateConfig, powerStateHeaders))); - socSdp->addEntity(service->addPowerEntity("SLC-REQ", PowerEntityType::SUBSYSTEM), - PowerEntityConfig("SLC_REQ:", generateGenericStateResidencyConfigs( - reqStateConfig, slcReqStateHeaders))); + auto socSdp = std::make_shared( + "/sys/devices/platform/1742048c.acpm_stats/soc_stats", cfgs); - service->addStateResidencyDataProvider(socSdp); + p->addStateResidencyDataProvider(socSdp); } -void addUfsStats(PowerStats *const service) { - sp ufsSdp = new UfsStateResidencyDataProvider( - service->addPowerEntity("UFS", PowerEntityType::SUBSYSTEM)); - service->addStateResidencyDataProvider(ufsSdp); +void setEnergyMeter(std::shared_ptr p) { + std::vector deviceNames { "s2mpg10-odpm", "s2mpg11-odpm" }; + p->setEnergyMeterDataProvider(std::make_unique(deviceNames, true)); } -void addWifiStats(PowerStats *const service) { - sp wifiSdp = - new GenericStateResidencyDataProvider("/sys/wifi/power_stats"); +void addDisplay(std::shared_ptr p) { + // Add display residency stats - // The transform function converts microseconds to milliseconds. - std::function usecToMs = [](uint64_t a) { return a / 1000; }; - StateResidencyConfig stateConfig = { + /* + * TODO(b/167216667): Add complete set of display states here. Must account + * for ALL devices built using this source + */ + std::vector states = { + "Off", + "LP: 1440x3040@30", + "On: 1440x3040@60", + "On: 1440x3040@90", + "HBM: 1440x3040@60", + "HBM: 1440x3040@90"}; + + auto displaySdp = + std::make_shared("Display", + "/sys/class/backlight/panel0-backlight/state", + states); + p->addStateResidencyDataProvider(displaySdp); + + // Add display energy consumer + /* + * TODO(b/167216667): Add correct display power model here. Must read from display rail + * and include proper coefficients for display states. Must account for ALL devices built + * using this source. + */ + auto displayConsumer = PowerStatsEnergyConsumer::createMeterAndEntityConsumer(p, + EnergyConsumerType::DISPLAY, "display", {"PPVAR_VSYS_PWR_DISP"}, "Display", + {{"LP: 1440x3040@30", 1}, + {"On: 1440x3040@60", 2}, + {"On: 1440x3040@90", 3}}); + + p->addEnergyConsumer(displayConsumer); +} + +void addCPUclusters(std::shared_ptr p) { + p->addEnergyConsumer(PowerStatsEnergyConsumer::createMeterConsumer(p, + EnergyConsumerType::CPU_CLUSTER, "CPUCL0", {"S4M_VDD_CPUCL0"})); + p->addEnergyConsumer(PowerStatsEnergyConsumer::createMeterConsumer(p, + EnergyConsumerType::CPU_CLUSTER, "CPUCL1", {"S3M_VDD_CPUCL1"})); + p->addEnergyConsumer(PowerStatsEnergyConsumer::createMeterConsumer(p, + EnergyConsumerType::CPU_CLUSTER, "CPUCL2", {"S2M_VDD_CPUCL2"})); +} + +void addGPU(std::shared_ptr p) { + // Add gpu energy consumer + std::map stateCoeffs; + const int socRev = android::base::GetIntProperty(kBootHwSoCRev, 0); + + // B0/B1 chips have different GPU DVFS operating points than A0/A1 SoC + if (socRev >= 2) { + stateCoeffs = { + {"151000", 10}, + {"202000", 20}, + {"251000", 30}, + {"302000", 40}, + {"351000", 50}, + {"400000", 60}, + {"471000", 70}, + {"510000", 80}, + {"572000", 90}, + {"701000", 100}, + {"762000", 110}, + {"848000", 120}}; + } else { + stateCoeffs = { + {"151000", 10}, + {"302000", 20}, + {"455000", 30}, + {"572000", 40}, + {"670000", 50}}; + } + + auto gpuConsumer = PowerStatsEnergyConsumer::createMeterAndAttrConsumer(p, + EnergyConsumerType::OTHER, "GPU", {"S2S_VDD_G3D"}, + {{UID_TIME_IN_STATE, "/sys/devices/platform/1c500000.mali/uid_time_in_state"}}, + stateCoeffs); + + p->addEnergyConsumer(gpuConsumer); +} + +void addMobileRadio(std::shared_ptr p) +{ + // A constant to represent the number of microseconds in one millisecond. + const int US_TO_MS = 1000; + + // modem power_stats are reported in microseconds. The transform function + // converts microseconds to milliseconds. + std::function modemUsToMs = [](uint64_t a) { return a / US_TO_MS; }; + const GenericStateResidencyDataProvider::StateResidencyConfig powerStateConfig = { .entryCountSupported = true, .entryCountPrefix = "count:", .totalTimeSupported = true, .totalTimePrefix = "duration_usec:", - .totalTimeTransform = usecToMs, + .totalTimeTransform = modemUsToMs, .lastEntrySupported = true, .lastEntryPrefix = "last_entry_timestamp_usec:", - .lastEntryTransform = usecToMs, + .lastEntryTransform = modemUsToMs, }; - StateResidencyConfig pcieStateConfig = { - .entryCountSupported = true, - .entryCountPrefix = "count:", - .totalTimeSupported = true, - .totalTimePrefix = "duration_usec:", - .totalTimeTransform = usecToMs, + const std::vector> powerStateHeaders = { + std::make_pair("SLEEP", "SLEEP:"), }; - std::vector> stateHeaders = { - std::make_pair("AWAKE", "AWAKE:"), - std::make_pair("ASLEEP", "ASLEEP:"), - }; - std::vector> pcieStateHeaders = { - std::make_pair("L0", "L0:"), std::make_pair("L1", "L1:"), - std::make_pair("L1_1", "L1_1:"), std::make_pair("L1_2", "L1_2:"), - std::make_pair("L2", "L2:"), - }; + std::vector cfgs; + cfgs.emplace_back(generateGenericStateResidencyConfigs(powerStateConfig, powerStateHeaders), + "MODEM", ""); - wifiSdp->addEntity( - service->addPowerEntity("WIFI", PowerEntityType::SUBSYSTEM), - PowerEntityConfig(generateGenericStateResidencyConfigs(stateConfig, stateHeaders))); - wifiSdp->addEntity(service->addPowerEntity("WIFI-PCIE", PowerEntityType::SUBSYSTEM), - PowerEntityConfig(generateGenericStateResidencyConfigs(pcieStateConfig, - pcieStateHeaders))); + p->addStateResidencyDataProvider(std::make_shared( + "/sys/devices/platform/cpif/modem/power_stats", cfgs)); - service->addStateResidencyDataProvider(wifiSdp); + p->addEnergyConsumer(PowerStatsEnergyConsumer::createMeterConsumer(p, + EnergyConsumerType::MOBILE_RADIO, "MODEM", {"VSYS_PWR_MODEM", "VSYS_PWR_RFFE"})); } -int main(int /* argc */, char ** /* argv */) { - ALOGI("power.stats service 1.0 is starting."); - - PowerStats *service = new PowerStats(); - - // Add rail data provider - service->setRailDataProvider(std::make_unique()); - - addAoCStats(service); - addCpuCStateStats(service); - addDvfsStats(service); - addGPUStats(service); - addNFCStats(service); - addPCIeStats(service); - addSocStats(service); - addUfsStats(service); - addWifiStats(service); - - // Add Power Entities that require the Aidl data provider - sp aidlSdp = new AidlStateResidencyDataProvider(); - uint32_t bluetoothId = service->addPowerEntity("Bluetooth", PowerEntityType::SUBSYSTEM); - aidlSdp->addEntity(bluetoothId, "Bluetooth", {"Idle", "Active", "Tx", "Rx"}); - uint32_t citadelId = service->addPowerEntity("Citadel", PowerEntityType::SUBSYSTEM); - aidlSdp->addEntity(citadelId, "Citadel", {"Last-Reset", "Active", "Deep-Sleep"}); - service->addStateResidencyDataProvider(aidlSdp); - - auto serviceStatus = android::defaultServiceManager()->addService( - android::String16("power.stats-vendor"), aidlSdp); - if (serviceStatus != android::OK) { - ALOGE("Unable to register power.stats-vendor service %d", serviceStatus); - return 1; - } - - sp ps{android::ProcessState::self()}; // Create non-HW binder threadpool - ps->startThreadPool(); - - // Configure the threadpool - configureRpcThreadpool(1, true /*callerWillJoin*/); - - status_t status = service->registerAsService(); - if (status != OK) { - ALOGE("Could not register service for power.stats HAL Iface (%d), exiting.", status); - return 1; - } - - ALOGI("power.stats service is ready"); - joinRpcThreadpool(); - - // In normal operation, we don't expect the thread pool to exit - ALOGE("power.stats service is shutting down"); - return 1; +void addGNSS(std::shared_ptr p) +{ + p->addEnergyConsumer(PowerStatsEnergyConsumer::createMeterConsumer(p, + EnergyConsumerType::GNSS, "GPS", {"L9S_GNSS_CORE"})); +} + +void addNFC(std::shared_ptr p) { + const GenericStateResidencyDataProvider::StateResidencyConfig nfcStateConfig = { + .entryCountSupported = true, + .entryCountPrefix = "Cumulative count:", + .totalTimeSupported = true, + .totalTimePrefix = "Cumulative duration msec:", + .lastEntrySupported = true, + .lastEntryPrefix = "Last entry timestamp msec:", + }; + const std::vector> nfcStateHeaders = { + std::make_pair("IDLE", "Idle mode:"), + std::make_pair("ACTIVE", "Active mode:"), + std::make_pair("ACTIVE-RW", "Active Reader/Writer mode:"), + }; + + std::vector cfgs; + cfgs.emplace_back(generateGenericStateResidencyConfigs(nfcStateConfig, nfcStateHeaders), + "NFC", "NFC subsystem"); + + auto nfcSdp = std::make_shared( + "/sys/devices/platform/10960000.hsi2c/i2c-3/3-0008/power_stats", cfgs); + + p->addStateResidencyDataProvider(nfcSdp); +} + +void addPCIe(std::shared_ptr p) { + // Add PCIe power entities for Modem and WiFi + const GenericStateResidencyDataProvider::StateResidencyConfig pcieStateConfig = { + .entryCountSupported = true, + .entryCountPrefix = "Cumulative count:", + .totalTimeSupported = true, + .totalTimePrefix = "Cumulative duration msec:", + .lastEntrySupported = true, + .lastEntryPrefix = "Last entry timestamp msec:", + }; + const std::vector> pcieStateHeaders = { + std::make_pair("UP", "Link up:"), + std::make_pair("DOWN", "Link down:"), + }; + + // Add PCIe - Modem + const std::vector pcieModemCfgs = { + {generateGenericStateResidencyConfigs(pcieStateConfig, pcieStateHeaders), "PCIe-Modem", + "Version: 1"} + }; + auto pcieModemSdp = std::make_shared( + "/sys/devices/platform/11920000.pcie/power_stats", pcieModemCfgs); + p->addStateResidencyDataProvider(pcieModemSdp); + + // Add PCIe - WiFi + const std::vector pcieWifiCfgs = { + {generateGenericStateResidencyConfigs(pcieStateConfig, pcieStateHeaders), + "PCIe-WiFi", "Version: 1"} + }; + auto pcieWifiSdp = std::make_shared( + "/sys/devices/platform/14520000.pcie/power_stats", pcieWifiCfgs); + p->addStateResidencyDataProvider(pcieWifiSdp); +} + +void addWifi(std::shared_ptr p) { + // The transform function converts microseconds to milliseconds. + std::function usecToMs = [](uint64_t a) { return a / 1000; }; + const GenericStateResidencyDataProvider::StateResidencyConfig stateConfig = { + .entryCountSupported = true, + .entryCountPrefix = "count:", + .totalTimeSupported = true, + .totalTimePrefix = "duration_usec:", + .totalTimeTransform = usecToMs, + .lastEntrySupported = true, + .lastEntryPrefix = "last_entry_timestamp_usec:", + .lastEntryTransform = usecToMs, + }; + const GenericStateResidencyDataProvider::StateResidencyConfig pcieStateConfig = { + .entryCountSupported = true, + .entryCountPrefix = "count:", + .totalTimeSupported = true, + .totalTimePrefix = "duration_usec:", + .totalTimeTransform = usecToMs, + .lastEntrySupported = false, + }; + + const std::vector> stateHeaders = { + std::make_pair("AWAKE", "AWAKE:"), + std::make_pair("ASLEEP", "ASLEEP:"), + + }; + const std::vector> pcieStateHeaders = { + std::make_pair("L0", "L0:"), + std::make_pair("L1", "L1:"), + std::make_pair("L1_1", "L1_1:"), + std::make_pair("L1_2", "L1_2:"), + std::make_pair("L2", "L2:"), + }; + + const std::vector cfgs = { + {generateGenericStateResidencyConfigs(stateConfig, stateHeaders), "WIFI", "WIFI"}, + {generateGenericStateResidencyConfigs(pcieStateConfig, pcieStateHeaders), "WIFI-PCIE", + "WIFI-PCIE"} + }; + + auto wifiSdp = std::make_shared("/sys/wifi/power_stats", + cfgs); + p->addStateResidencyDataProvider(wifiSdp); +} + +/** + * Unlike other data providers, which source power entity state residency data from the kernel, + * this data provider acts as a general-purpose channel for state residency data providers + * that live in user space. Entities are defined here and user space clients of this provider's + * vendor service register callbacks to provide state residency data for their given pwoer entity. + */ +void addPixelStateResidencyDataProvider(std::shared_ptr p) { + std::shared_ptr pixelSdp = + ndk::SharedRefBase::make(); + + pixelSdp->addEntity("Bluetooth", {{0, "Idle"}, {1, "Active"}, {2, "Tx"}, {3, "Rx"}}); + + pixelSdp->start(); + p->addStateResidencyDataProvider(pixelSdp); +} + +int main() { + LOG(INFO) << "Pixel PowerStats HAL AIDL Service is starting."; + + // single thread + ABinderProcess_setThreadPoolMaxThreadCount(0); + + std::shared_ptr p = ndk::SharedRefBase::make(); + + setEnergyMeter(p); + + addPixelStateResidencyDataProvider(p); + addAoC(p); + addDisplay(p); + addDvfsStats(p); + addSoC(p); + addCPUclusters(p); + addGPU(p); + addMobileRadio(p); + addGNSS(p); + addNFC(p); + addPCIe(p); + addWifi(p); + + const std::string instance = std::string() + PowerStats::descriptor + "/default"; + binder_status_t status = AServiceManager_addService(p->asBinder().get(), instance.c_str()); + LOG_ALWAYS_FATAL_IF(status != STATUS_OK); + + ABinderProcess_joinThreadPool(); + return EXIT_FAILURE; // should not reach } diff --git a/powerstats/serviceaidl.cpp b/powerstats/serviceaidl.cpp deleted file mode 100644 index 8c15775c..00000000 --- a/powerstats/serviceaidl.cpp +++ /dev/null @@ -1,523 +0,0 @@ -/* - * 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. - */ - -#define LOG_TAG "android.hardware.power.stats-service.pixel" - -#include -#include "AocStateResidencyDataProviderAidl.h" -#include "DvfsStateResidencyDataProviderAidl.h" -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -using aidl::android::hardware::power::stats::AocStateResidencyDataProvider; -using aidl::android::hardware::power::stats::DisplayStateResidencyDataProvider; -using aidl::android::hardware::power::stats::DvfsStateResidencyDataProvider; -using aidl::android::hardware::power::stats::EnergyConsumerType; -using aidl::android::hardware::power::stats::GenericStateResidencyDataProvider; -using aidl::android::hardware::power::stats::IioEnergyMeterDataProvider; -using aidl::android::hardware::power::stats::PixelStateResidencyDataProvider; -using aidl::android::hardware::power::stats::PowerStats; -using aidl::android::hardware::power::stats::PowerStatsEnergyConsumer; - -constexpr char kBootHwSoCRev[] = "ro.boot.hw.soc.rev"; - -void addAoC(std::shared_ptr p) { - std::string prefix = "/sys/devices/platform/19000000.aoc/control/"; - - // Add AoC cores (a32, ff1, hf0, and hf1) - std::vector> coreIds = { - {"AoC-A32", prefix + "a32_"}, - {"AoC-FF1", prefix + "ff1_"}, - {"AoC-HF1", prefix + "hf1_"}, - {"AoC-HF0", prefix + "hf0_"}, - }; - std::vector> coreStates = { - {"DWN", "off"}, {"RET", "retention"}, {"WFI", "wfi"}}; - p->addStateResidencyDataProvider(std::make_shared(coreIds, - coreStates)); - - // Add AoC voltage stats - std::vector> voltageIds = { - {"AoC-Voltage", prefix + "voltage_"}, - }; - std::vector> voltageStates = {{"NOM", "nominal"}, - {"SUD", "super_underdrive"}, - {"UUD", "ultra_underdrive"}, - {"UD", "underdrive"}}; - p->addStateResidencyDataProvider( - std::make_shared(voltageIds, voltageStates)); - - // Add AoC monitor mode - std::vector> monitorIds = { - {"AoC", prefix + "monitor_"}, - }; - std::vector> monitorStates = { - {"MON", "mode"}, - }; - p->addStateResidencyDataProvider( - std::make_shared(monitorIds, monitorStates)); -} - -void addDvfsStats(std::shared_ptr p) { - // A constant to represent the number of nanoseconds in one millisecond - const int NS_TO_MS = 1000000; - - std::vector cfgs; - - cfgs.push_back({"MIF", { - std::make_pair("3172KHz", "3172000"), - std::make_pair("2730KHz", "2730000"), - std::make_pair("2535KHz", "2535000"), - std::make_pair("2288KHz", "2288000"), - std::make_pair("2028KHz", "2028000"), - std::make_pair("1716KHz", "1716000"), - std::make_pair("1539KHz", "1539000"), - std::make_pair("1352KHz", "1352000"), - std::make_pair("1014KHz", "1014000"), - std::make_pair("845KHz", "845000"), - std::make_pair("676KHz", "676000"), - std::make_pair("546KHz", "546000"), - std::make_pair("421KHz", "421000"), - std::make_pair("0KHz", "0"), - }}); - - cfgs.push_back({"CL0", { - std::make_pair("2024KHz", "2024000"), - std::make_pair("1950KHz", "1950000"), - std::make_pair("1868KHz", "1868000"), - std::make_pair("1803KHz", "1803000"), - std::make_pair("1745KHz", "1745000"), - std::make_pair("1704KHz", "1704000"), - std::make_pair("1598KHz", "1598000"), - std::make_pair("1459KHz", "1459000"), - std::make_pair("1401KHz", "1401000"), - std::make_pair("1328KHz", "1328000"), - std::make_pair("1197KHz", "1197000"), - std::make_pair("1098KHz", "1098000"), - std::make_pair("930KHz", "930000"), - std::make_pair("889KHz", "889000"), - std::make_pair("738KHz", "738000"), - std::make_pair("574KHz", "574000"), - std::make_pair("300KHz", "300000"), - std::make_pair("0KHz", "0"), - }}); - - cfgs.push_back({"CL1", { - std::make_pair("2253KHz", "2253000"), - std::make_pair("2130KHz", "2130000"), - std::make_pair("1999KHz", "1999000"), - std::make_pair("1836KHz", "1836000"), - std::make_pair("1663KHz", "1663000"), - std::make_pair("1491KHz", "1491000"), - std::make_pair("1328KHz", "1328000"), - std::make_pair("1197KHz", "1197000"), - std::make_pair("1024KHz", "1024000"), - std::make_pair("910KHz", "910000"), - std::make_pair("799KHz", "799000"), - std::make_pair("696KHz", "696000"), - std::make_pair("533KHz", "533000"), - std::make_pair("400KHz", "400000"), - std::make_pair("0KHz", "0"), - }}); - - cfgs.push_back({"CL2", { - std::make_pair("2630KHz", "2630000"), - std::make_pair("2507KHz", "2507000"), - std::make_pair("2401KHz", "2401000"), - std::make_pair("2302KHz", "2302000"), - std::make_pair("2252KHz", "2252000"), - std::make_pair("2188KHz", "2188000"), - std::make_pair("2048KHz", "2048000"), - std::make_pair("1901KHz", "1901000"), - std::make_pair("1826KHz", "1826000"), - std::make_pair("1745KHz", "1745000"), - std::make_pair("1582KHz", "1582000"), - std::make_pair("1426KHz", "1426000"), - std::make_pair("1277KHz", "1277000"), - std::make_pair("1237KHz", "1237000"), - std::make_pair("1106KHz", "1106000"), - std::make_pair("984KHz", "984000"), - std::make_pair("851KHz", "851000"), - std::make_pair("848KHz", "848000"), - std::make_pair("500KHz", "500000"), - std::make_pair("0KHz", "0"), - }}); - - cfgs.push_back({"TPU", { - std::make_pair("1066MHz", "1066000000"), - }}); - - p->addStateResidencyDataProvider(std::make_shared( - "/sys/devices/platform/1742048c.acpm_stats/fvp_stats", NS_TO_MS, cfgs)); -} - -void addSoC(std::shared_ptr p) { - // A constant to represent the number of nanoseconds in one millisecond. - const int NS_TO_MS = 1000000; - - // ACPM stats are reported in nanoseconds. The transform function - // converts nanoseconds to milliseconds. - std::function acpmNsToMs = [](uint64_t a) { return a / NS_TO_MS; }; - const GenericStateResidencyDataProvider::StateResidencyConfig lpmStateConfig = { - .entryCountSupported = true, - .entryCountPrefix = "success_count:", - .totalTimeSupported = true, - .totalTimePrefix = "total_time_ns:", - .totalTimeTransform = acpmNsToMs, - .lastEntrySupported = true, - .lastEntryPrefix = "last_entry_time_ns:", - .lastEntryTransform = acpmNsToMs, - }; - const GenericStateResidencyDataProvider::StateResidencyConfig downStateConfig = { - .entryCountSupported = true, - .entryCountPrefix = "down_count:", - .totalTimeSupported = true, - .totalTimePrefix = "total_down_time_ns:", - .totalTimeTransform = acpmNsToMs, - .lastEntrySupported = true, - .lastEntryPrefix = "last_down_time_ns:", - .lastEntryTransform = acpmNsToMs, - }; - const GenericStateResidencyDataProvider::StateResidencyConfig reqStateConfig = { - .entryCountSupported = true, - .entryCountPrefix = "req_up_count:", - .totalTimeSupported = true, - .totalTimePrefix = "total_req_up_time_ns:", - .totalTimeTransform = acpmNsToMs, - .lastEntrySupported = true, - .lastEntryPrefix = "last_req_up_time_ns:", - .lastEntryTransform = acpmNsToMs, - - }; - const std::vector> powerStateHeaders = { - std::make_pair("SICD", "SICD"), - std::make_pair("SLEEP", "SLEEP"), - std::make_pair("SLEEP_SLCMON", "SLEEP_SLCMON"), - std::make_pair("STOP", "STOP"), - }; - const std::vector> mifReqStateHeaders = { - std::make_pair("AOC", "AOC"), - std::make_pair("GSA", "GSA"), - }; - const std::vector> slcReqStateHeaders = { - std::make_pair("AOC", "AOC"), - }; - - std::vector cfgs; - cfgs.emplace_back(generateGenericStateResidencyConfigs(lpmStateConfig, powerStateHeaders), - "LPM", "LPM:"); - cfgs.emplace_back(generateGenericStateResidencyConfigs(downStateConfig, powerStateHeaders), - "MIF", "MIF:"); - cfgs.emplace_back(generateGenericStateResidencyConfigs(reqStateConfig, mifReqStateHeaders), - "MIF-REQ", "MIF_REQ:"); - cfgs.emplace_back(generateGenericStateResidencyConfigs(downStateConfig, powerStateHeaders), - "SLC", "SLC:"); - cfgs.emplace_back(generateGenericStateResidencyConfigs(reqStateConfig, slcReqStateHeaders), - "SLC-REQ", "SLC_REQ:"); - - auto socSdp = std::make_shared( - "/sys/devices/platform/1742048c.acpm_stats/soc_stats", cfgs); - - p->addStateResidencyDataProvider(socSdp); -} - -void setEnergyMeter(std::shared_ptr p) { - std::vector deviceNames { "s2mpg10-odpm", "s2mpg11-odpm" }; - p->setEnergyMeterDataProvider(std::make_unique(deviceNames, true)); -} - -void addDisplay(std::shared_ptr p) { - // Add display residency stats - - /* - * TODO(b/167216667): Add complete set of display states here. Must account - * for ALL devices built using this source - */ - std::vector states = { - "Off", - "LP: 1440x3040@30", - "On: 1440x3040@60", - "On: 1440x3040@90", - "HBM: 1440x3040@60", - "HBM: 1440x3040@90"}; - - auto displaySdp = - std::make_shared("Display", - "/sys/class/backlight/panel0-backlight/state", - states); - p->addStateResidencyDataProvider(displaySdp); - - // Add display energy consumer - /* - * TODO(b/167216667): Add correct display power model here. Must read from display rail - * and include proper coefficients for display states. Must account for ALL devices built - * using this source. - */ - auto displayConsumer = PowerStatsEnergyConsumer::createMeterAndEntityConsumer(p, - EnergyConsumerType::DISPLAY, "display", {"PPVAR_VSYS_PWR_DISP"}, "Display", - {{"LP: 1440x3040@30", 1}, - {"On: 1440x3040@60", 2}, - {"On: 1440x3040@90", 3}}); - - p->addEnergyConsumer(displayConsumer); -} - -void addCPUclusters(std::shared_ptr p) { - p->addEnergyConsumer(PowerStatsEnergyConsumer::createMeterConsumer(p, - EnergyConsumerType::CPU_CLUSTER, "CPUCL0", {"S4M_VDD_CPUCL0"})); - p->addEnergyConsumer(PowerStatsEnergyConsumer::createMeterConsumer(p, - EnergyConsumerType::CPU_CLUSTER, "CPUCL1", {"S3M_VDD_CPUCL1"})); - p->addEnergyConsumer(PowerStatsEnergyConsumer::createMeterConsumer(p, - EnergyConsumerType::CPU_CLUSTER, "CPUCL2", {"S2M_VDD_CPUCL2"})); -} - -void addGPU(std::shared_ptr p) { - // Add gpu energy consumer - std::map stateCoeffs; - const int socRev = android::base::GetIntProperty(kBootHwSoCRev, 0); - - // B0/B1 chips have different GPU DVFS operating points than A0/A1 SoC - if (socRev >= 2) { - stateCoeffs = { - {"151000", 10}, - {"202000", 20}, - {"251000", 30}, - {"302000", 40}, - {"351000", 50}, - {"400000", 60}, - {"471000", 70}, - {"510000", 80}, - {"572000", 90}, - {"701000", 100}, - {"762000", 110}, - {"848000", 120}}; - } else { - stateCoeffs = { - {"151000", 10}, - {"302000", 20}, - {"455000", 30}, - {"572000", 40}, - {"670000", 50}}; - } - - auto gpuConsumer = PowerStatsEnergyConsumer::createMeterAndAttrConsumer(p, - EnergyConsumerType::OTHER, "GPU", {"S2S_VDD_G3D"}, - {{UID_TIME_IN_STATE, "/sys/devices/platform/1c500000.mali/uid_time_in_state"}}, - stateCoeffs); - - p->addEnergyConsumer(gpuConsumer); -} - -void addMobileRadio(std::shared_ptr p) -{ - // A constant to represent the number of microseconds in one millisecond. - const int US_TO_MS = 1000; - - // modem power_stats are reported in microseconds. The transform function - // converts microseconds to milliseconds. - std::function modemUsToMs = [](uint64_t a) { return a / US_TO_MS; }; - const GenericStateResidencyDataProvider::StateResidencyConfig powerStateConfig = { - .entryCountSupported = true, - .entryCountPrefix = "count:", - .totalTimeSupported = true, - .totalTimePrefix = "duration_usec:", - .totalTimeTransform = modemUsToMs, - .lastEntrySupported = true, - .lastEntryPrefix = "last_entry_timestamp_usec:", - .lastEntryTransform = modemUsToMs, - }; - const std::vector> powerStateHeaders = { - std::make_pair("SLEEP", "SLEEP:"), - }; - - std::vector cfgs; - cfgs.emplace_back(generateGenericStateResidencyConfigs(powerStateConfig, powerStateHeaders), - "MODEM", ""); - - p->addStateResidencyDataProvider(std::make_shared( - "/sys/devices/platform/cpif/modem/power_stats", cfgs)); - - p->addEnergyConsumer(PowerStatsEnergyConsumer::createMeterConsumer(p, - EnergyConsumerType::MOBILE_RADIO, "MODEM", {"VSYS_PWR_MODEM", "VSYS_PWR_RFFE"})); -} - -void addGNSS(std::shared_ptr p) -{ - p->addEnergyConsumer(PowerStatsEnergyConsumer::createMeterConsumer(p, - EnergyConsumerType::GNSS, "GPS", {"L9S_GNSS_CORE"})); -} - -void addNFC(std::shared_ptr p) { - const GenericStateResidencyDataProvider::StateResidencyConfig nfcStateConfig = { - .entryCountSupported = true, - .entryCountPrefix = "Cumulative count:", - .totalTimeSupported = true, - .totalTimePrefix = "Cumulative duration msec:", - .lastEntrySupported = true, - .lastEntryPrefix = "Last entry timestamp msec:", - }; - const std::vector> nfcStateHeaders = { - std::make_pair("IDLE", "Idle mode:"), - std::make_pair("ACTIVE", "Active mode:"), - std::make_pair("ACTIVE-RW", "Active Reader/Writer mode:"), - }; - - std::vector cfgs; - cfgs.emplace_back(generateGenericStateResidencyConfigs(nfcStateConfig, nfcStateHeaders), - "NFC", "NFC subsystem"); - - auto nfcSdp = std::make_shared( - "/sys/devices/platform/10960000.hsi2c/i2c-3/3-0008/power_stats", cfgs); - - p->addStateResidencyDataProvider(nfcSdp); -} - -void addPCIe(std::shared_ptr p) { - // Add PCIe power entities for Modem and WiFi - const GenericStateResidencyDataProvider::StateResidencyConfig pcieStateConfig = { - .entryCountSupported = true, - .entryCountPrefix = "Cumulative count:", - .totalTimeSupported = true, - .totalTimePrefix = "Cumulative duration msec:", - .lastEntrySupported = true, - .lastEntryPrefix = "Last entry timestamp msec:", - }; - const std::vector> pcieStateHeaders = { - std::make_pair("UP", "Link up:"), - std::make_pair("DOWN", "Link down:"), - }; - - // Add PCIe - Modem - const std::vector pcieModemCfgs = { - {generateGenericStateResidencyConfigs(pcieStateConfig, pcieStateHeaders), "PCIe-Modem", - "Version: 1"} - }; - auto pcieModemSdp = std::make_shared( - "/sys/devices/platform/11920000.pcie/power_stats", pcieModemCfgs); - p->addStateResidencyDataProvider(pcieModemSdp); - - // Add PCIe - WiFi - const std::vector pcieWifiCfgs = { - {generateGenericStateResidencyConfigs(pcieStateConfig, pcieStateHeaders), - "PCIe-WiFi", "Version: 1"} - }; - auto pcieWifiSdp = std::make_shared( - "/sys/devices/platform/14520000.pcie/power_stats", pcieWifiCfgs); - p->addStateResidencyDataProvider(pcieWifiSdp); -} - -void addWifi(std::shared_ptr p) { - // The transform function converts microseconds to milliseconds. - std::function usecToMs = [](uint64_t a) { return a / 1000; }; - const GenericStateResidencyDataProvider::StateResidencyConfig stateConfig = { - .entryCountSupported = true, - .entryCountPrefix = "count:", - .totalTimeSupported = true, - .totalTimePrefix = "duration_usec:", - .totalTimeTransform = usecToMs, - .lastEntrySupported = true, - .lastEntryPrefix = "last_entry_timestamp_usec:", - .lastEntryTransform = usecToMs, - }; - const GenericStateResidencyDataProvider::StateResidencyConfig pcieStateConfig = { - .entryCountSupported = true, - .entryCountPrefix = "count:", - .totalTimeSupported = true, - .totalTimePrefix = "duration_usec:", - .totalTimeTransform = usecToMs, - .lastEntrySupported = false, - }; - - const std::vector> stateHeaders = { - std::make_pair("AWAKE", "AWAKE:"), - std::make_pair("ASLEEP", "ASLEEP:"), - - }; - const std::vector> pcieStateHeaders = { - std::make_pair("L0", "L0:"), - std::make_pair("L1", "L1:"), - std::make_pair("L1_1", "L1_1:"), - std::make_pair("L1_2", "L1_2:"), - std::make_pair("L2", "L2:"), - }; - - const std::vector cfgs = { - {generateGenericStateResidencyConfigs(stateConfig, stateHeaders), "WIFI", "WIFI"}, - {generateGenericStateResidencyConfigs(pcieStateConfig, pcieStateHeaders), "WIFI-PCIE", - "WIFI-PCIE"} - }; - - auto wifiSdp = std::make_shared("/sys/wifi/power_stats", - cfgs); - p->addStateResidencyDataProvider(wifiSdp); -} - -/** - * Unlike other data providers, which source power entity state residency data from the kernel, - * this data provider acts as a general-purpose channel for state residency data providers - * that live in user space. Entities are defined here and user space clients of this provider's - * vendor service register callbacks to provide state residency data for their given pwoer entity. - */ -void addPixelStateResidencyDataProvider(std::shared_ptr p) { - std::shared_ptr pixelSdp = - ndk::SharedRefBase::make(); - - pixelSdp->addEntity("Bluetooth", {{0, "Idle"}, {1, "Active"}, {2, "Tx"}, {3, "Rx"}}); - - pixelSdp->start(); - p->addStateResidencyDataProvider(pixelSdp); -} - -int main() { - LOG(INFO) << "Pixel PowerStats HAL AIDL Service is starting."; - - // single thread - ABinderProcess_setThreadPoolMaxThreadCount(0); - - std::shared_ptr p = ndk::SharedRefBase::make(); - - setEnergyMeter(p); - - addPixelStateResidencyDataProvider(p); - addAoC(p); - addDisplay(p); - addDvfsStats(p); - addSoC(p); - addCPUclusters(p); - addGPU(p); - addMobileRadio(p); - addGNSS(p); - addNFC(p); - addPCIe(p); - addWifi(p); - - const std::string instance = std::string() + PowerStats::descriptor + "/default"; - binder_status_t status = AServiceManager_addService(p->asBinder().get(), instance.c_str()); - LOG_ALWAYS_FATAL_IF(status != STATUS_OK); - - ABinderProcess_joinThreadPool(); - return EXIT_FAILURE; // should not reach -}