diff options
author | Benjamin Schwartz <bsschwar@google.com> | 2019-07-26 09:47:57 -0700 |
---|---|---|
committer | Benjamin Schwartz <bsschwar@google.com> | 2019-07-30 14:12:06 -0700 |
commit | d14a96e65cc9e72fb40d7982d9d142d2328530a6 (patch) | |
tree | d6dd81ca4441afd404918db313966daedf548dab /pwrstats_util | |
parent | ca7da7ba52a35d57603dff299df37800d312c423 (diff) |
pwrstats_util: refactor
In order to be able to add new tool options and stats that get collected,
pwrstats_util needs to be refactored. Refactoring will attempt to do the following:
1. Most code is common across devices.
2. Adding new types of stats that get collected is as simple
as possible without losing valuable flexibility.
Bug: 138136821
Test: adb shell pwrstats_util
Test: adb shell pwrstats_util -d /data/local/tmp/tempfile.txt
Change-Id: Ieeb9338caddd954a96052fca893348784fef27f3
Diffstat (limited to 'pwrstats_util')
-rw-r--r-- | pwrstats_util/Android.bp | 29 | ||||
-rw-r--r-- | pwrstats_util/PowerStatsAggregator.cpp | 41 | ||||
-rw-r--r-- | pwrstats_util/PowerStatsAggregator.h (renamed from pwrstats_util/PowerStatsUtil.h) | 24 | ||||
-rw-r--r-- | pwrstats_util/PowerStatsUtil.cpp | 155 | ||||
-rw-r--r-- | pwrstats_util/dataproviders/PowerEntityResidencyDataProvider.cpp | 82 | ||||
-rw-r--r-- | pwrstats_util/dataproviders/PowerEntityResidencyDataProvider.h | 28 | ||||
-rw-r--r-- | pwrstats_util/pwrstats_util.cpp (renamed from pwrstats_util/main.cpp) | 24 |
7 files changed, 197 insertions, 186 deletions
diff --git a/pwrstats_util/Android.bp b/pwrstats_util/Android.bp index e32624d..647c4d4 100644 --- a/pwrstats_util/Android.bp +++ b/pwrstats_util/Android.bp @@ -12,14 +12,32 @@ // 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. -cc_binary { - name: "pwrstats_util", +cc_library_static { + name: "libpowerstatsutil", + defaults: ["pwrstatsutil_defaults"], + export_include_dirs: ["."], srcs: [ - "main.cpp", - "PowerStatsUtil.cpp", + "pwrstats_util.cpp", + "PowerStatsAggregator.cpp", + "dataproviders/PowerEntityResidencyDataProvider.cpp", ], + shared_libs: [ + "libhidlbase", + "android.hardware.power.stats@1.0", + ], +} + +// Useful defaults for pwrstats_util +cc_defaults { + name: "pwrstatsutil_defaults", + vendor: true, cflags: [ "-Wall", + + // Try to catch typical 32-bit assumptions that break with 64-bit pointers. + "-Werror=pointer-to-int-cast", + "-Werror=int-to-pointer-cast", + "-Werror=type-limits", "-Werror", ], tidy: true, @@ -44,8 +62,5 @@ cc_binary { "libbase", "libutils", "liblog", - "libhidlbase", - "android.hardware.power.stats@1.0", ], - vendor: true, } diff --git a/pwrstats_util/PowerStatsAggregator.cpp b/pwrstats_util/PowerStatsAggregator.cpp new file mode 100644 index 0000000..c320505 --- /dev/null +++ b/pwrstats_util/PowerStatsAggregator.cpp @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2019 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 "pwrstats_util" + +#include "PowerStatsAggregator.h" + +#include <android-base/logging.h> +#include <android-base/parsedouble.h> + +#include <iostream> +#include <memory> +#include <unordered_map> + +void PowerStatsAggregator::addDataProvider(std::unique_ptr<IPowerStatsDataProvider> p) { + mDataProviders.emplace_back(std::move(p)); +} + +int PowerStatsAggregator::getData(std::unordered_map<std::string, uint64_t>* data) const { + data->clear(); + for (auto&& provider : mDataProviders) { + int ret = provider->get(data); + if (ret != 0) { + data->clear(); + return ret; + } + } + return 0; +} diff --git a/pwrstats_util/PowerStatsUtil.h b/pwrstats_util/PowerStatsAggregator.h index 3e685e5..70ff70f 100644 --- a/pwrstats_util/PowerStatsUtil.h +++ b/pwrstats_util/PowerStatsAggregator.h @@ -13,11 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#ifndef POWERSTATSUTIL_H -#define POWERSTATSUTIL_H +#ifndef POWERSTATSAGGREGATOR_H +#define POWERSTATSAGGREGATOR_H #include <memory> -#include <string> #include <unordered_map> #include <vector> @@ -25,23 +24,26 @@ * Classes that implement this interface can be used to provide stats in the form of key/value * pairs to PwrStatsUtil. **/ -class IPwrStatsUtilDataProvider { +class IPowerStatsDataProvider { public: - virtual ~IPwrStatsUtilDataProvider() = default; - virtual int get(std::unordered_map<std::string, uint64_t>& data) = 0; + virtual ~IPowerStatsDataProvider() = default; + virtual int get(std::unordered_map<std::string, uint64_t>* data) = 0; }; /** * This class is used to return stats in the form of key/value pairs for all registered classes * that implement IPwrStatsUtilDataProvider. **/ -class PowerStatsUtil { +class PowerStatsAggregator { public: - PowerStatsUtil(); - int getData(std::unordered_map<std::string, uint64_t>& data); + PowerStatsAggregator() = default; + int getData(std::unordered_map<std::string, uint64_t>* data) const; + void addDataProvider(std::unique_ptr<IPowerStatsDataProvider> dataProvider); private: - std::vector<std::unique_ptr<IPwrStatsUtilDataProvider>> mDataProviders; + std::vector<std::unique_ptr<IPowerStatsDataProvider>> mDataProviders; }; -#endif // POWERSTATSUTIL_H +int run(int argc, char** argv, const PowerStatsAggregator& agg); + +#endif // POWERSTATSAGGREGATOR_H diff --git a/pwrstats_util/PowerStatsUtil.cpp b/pwrstats_util/PowerStatsUtil.cpp deleted file mode 100644 index ffd4d30..0000000 --- a/pwrstats_util/PowerStatsUtil.cpp +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright (C) 2019 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 "pwrstats_util" - -#include "PowerStatsUtil.h" - -#include <android-base/logging.h> -#include <android-base/parsedouble.h> -#include <android/hardware/power/stats/1.0/IPowerStats.h> - -#include <fstream> -#include <iostream> -#include <memory> -#include <regex> -#include <string> -#include <unordered_map> - -using android::sp; -using android::hardware::Return; - -/** - * C-state residency data provider: - * Provides C-state residency information for each of the CPUs and L3 cache. - **/ -class CstateDataProvider : public IPwrStatsUtilDataProvider { - public: - CstateDataProvider() = default; - - int get(std::unordered_map<std::string, uint64_t>& data) override { - // example accessing a sysfs node - std::ifstream file("/sys/kernel/debug/lpm_stats/stats"); - - std::smatch matches; - const std::regex searchExpr("\\[(.*?)\\] (.*?):"); - std::string line; - const std::string searchStr = "total success time:"; - - while (std::getline(file, line)) { - if (std::regex_search(line, matches, searchExpr)) { - std::ostringstream key; - key << matches[1] << "__" << matches[2]; - - while (std::getline(file, line)) { - size_t pos = line.find(searchStr); - if (pos != std::string::npos) { - float val; - if (android::base::ParseFloat(line.substr(pos + searchStr.size()), &val)) { - data.emplace(key.str(), static_cast<uint64_t>(val * 1000)); - } else { - LOG(ERROR) << __func__ << ": failed to parse c-state data"; - } - break; - } - } - } - } - - return 0; - } -}; - -/** - * Power Stats HAL data provider: - * Provides data monitored by Power Stats HAL 1.0 - **/ -class PwrStatsHalDataProvider : public IPwrStatsUtilDataProvider { - public: - PwrStatsHalDataProvider() = default; - - int get(std::unordered_map<std::string, uint64_t>& data) override { - // example using the power stats HAL - sp<android::hardware::power::stats::V1_0::IPowerStats> powerStatsService = - android::hardware::power::stats::V1_0::IPowerStats::getService(); - if (powerStatsService == nullptr) { - LOG(ERROR) << "Unable to get power.stats HAL service."; - return 1; - } - - std::unordered_map<uint32_t, std::string> entityNames; - std::unordered_map<uint32_t, std::unordered_map<uint32_t, std::string>> stateNames; - - Return<void> ret; - ret = powerStatsService->getPowerEntityInfo([&entityNames](auto infos, auto /* status */) { - for (auto const& info : infos) { - entityNames.emplace(info.powerEntityId, info.powerEntityName); - } - }); - if (!ret.isOk()) { - return 1; - } - - ret = powerStatsService->getPowerEntityStateInfo({}, [&stateNames](auto stateSpaces, - auto /* status */) { - for (auto const& stateSpace : stateSpaces) { - stateNames.emplace(stateSpace.powerEntityId, - std::unordered_map<uint32_t, std::string>()); - auto& entityStateNames = stateNames.at(stateSpace.powerEntityId); - for (auto const& state : stateSpace.states) { - entityStateNames.emplace(state.powerEntityStateId, state.powerEntityStateName); - } - } - }); - if (!ret.isOk()) { - return 1; - } - - ret = powerStatsService->getPowerEntityStateResidencyData( - {}, [&entityNames, &stateNames, &data](auto results, auto /* status */) { - for (auto const& result : results) { - for (auto stateResidency : result.stateResidencyData) { - std::ostringstream key; - key << entityNames.at(result.powerEntityId) << "__" - << stateNames.at(result.powerEntityId) - .at(stateResidency.powerEntityStateId); - data.emplace(key.str(), - static_cast<uint64_t>(stateResidency.totalTimeInStateMs)); - } - } - }); - if (!ret.isOk()) { - return 1; - } - - return 0; - } -}; - -PowerStatsUtil::PowerStatsUtil() { - mDataProviders.emplace_back(std::make_unique<CstateDataProvider>()); - mDataProviders.emplace_back(std::make_unique<PwrStatsHalDataProvider>()); -} - -int PowerStatsUtil::getData(std::unordered_map<std::string, uint64_t>& data) { - data.clear(); - for (auto&& provider : mDataProviders) { - int ret = provider->get(data); - if (ret != 0) { - return ret; - } - } - return 0; -} diff --git a/pwrstats_util/dataproviders/PowerEntityResidencyDataProvider.cpp b/pwrstats_util/dataproviders/PowerEntityResidencyDataProvider.cpp new file mode 100644 index 0000000..ae5eff4 --- /dev/null +++ b/pwrstats_util/dataproviders/PowerEntityResidencyDataProvider.cpp @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2019 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 "pwrstats_util" + +#include "PowerEntityResidencyDataProvider.h" +#include <android-base/logging.h> +#include <android/hardware/power/stats/1.0/IPowerStats.h> +using android::sp; +using android::hardware::Return; + +/** + * Power Entity State Residency data provider: + * Provides data monitored by Power Stats HAL 1.0 + **/ + +int PowerEntityResidencyDataProvider::get(std::unordered_map<std::string, uint64_t>* data) { + sp<android::hardware::power::stats::V1_0::IPowerStats> powerStatsService = + android::hardware::power::stats::V1_0::IPowerStats::getService(); + if (powerStatsService == nullptr) { + LOG(ERROR) << "Unable to get power.stats HAL service."; + return 1; + } + + std::unordered_map<uint32_t, std::string> entityNames; + std::unordered_map<uint32_t, std::unordered_map<uint32_t, std::string>> stateNames; + + Return<void> ret; + ret = powerStatsService->getPowerEntityInfo([&entityNames](auto infos, auto /* status */) { + for (auto const& info : infos) { + entityNames.emplace(info.powerEntityId, info.powerEntityName); + } + }); + if (!ret.isOk()) { + return 1; + } + + ret = powerStatsService->getPowerEntityStateInfo({}, [&stateNames](auto stateSpaces, + auto /* status */) { + for (auto const& stateSpace : stateSpaces) { + stateNames.emplace(stateSpace.powerEntityId, + std::unordered_map<uint32_t, std::string>()); + auto& entityStateNames = stateNames.at(stateSpace.powerEntityId); + for (auto const& state : stateSpace.states) { + entityStateNames.emplace(state.powerEntityStateId, state.powerEntityStateName); + } + } + }); + if (!ret.isOk()) { + return 1; + } + + ret = powerStatsService->getPowerEntityStateResidencyData({}, [&entityNames, &stateNames, + &data](auto results, + auto /* status */) { + for (auto const& result : results) { + for (auto stateResidency : result.stateResidencyData) { + std::ostringstream key; + key << entityNames.at(result.powerEntityId) << "__" + << stateNames.at(result.powerEntityId).at(stateResidency.powerEntityStateId); + data->emplace(key.str(), static_cast<uint64_t>(stateResidency.totalTimeInStateMs)); + } + } + }); + if (!ret.isOk()) { + return 1; + } + + return 0; +} diff --git a/pwrstats_util/dataproviders/PowerEntityResidencyDataProvider.h b/pwrstats_util/dataproviders/PowerEntityResidencyDataProvider.h new file mode 100644 index 0000000..73bb453 --- /dev/null +++ b/pwrstats_util/dataproviders/PowerEntityResidencyDataProvider.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2019 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 POWERENTITYRESIDENCYDATAPROVIDER_H +#define POWERENTITYRESIDENCYDATAPROVIDER_H + +#include "PowerStatsAggregator.h" + +class PowerEntityResidencyDataProvider : public IPowerStatsDataProvider { + public: + PowerEntityResidencyDataProvider() = default; + + int get(std::unordered_map<std::string, uint64_t>* data) override; +}; + +#endif // POWERENTITYRESIDENCYDATAPROVIDER_H diff --git a/pwrstats_util/main.cpp b/pwrstats_util/pwrstats_util.cpp index 8f82d6f..b28b4b0 100644 --- a/pwrstats_util/main.cpp +++ b/pwrstats_util/pwrstats_util.cpp @@ -27,7 +27,7 @@ #include <iostream> #include <unordered_map> -#include "PowerStatsUtil.h" +#include "PowerStatsAggregator.h" namespace { volatile std::sig_atomic_t gSignalStatus; @@ -72,10 +72,9 @@ static Options parseArgs(int argc, char** argv) { return opt; } -static void snapshot(void) { +static void snapshot(const PowerStatsAggregator& agg) { std::unordered_map<std::string, uint64_t> data; - PowerStatsUtil util; - int ret = util.getData(data); + int ret = agg.getData(&data); if (ret) { exit(EXIT_FAILURE); } @@ -87,7 +86,7 @@ static void snapshot(void) { exit(EXIT_SUCCESS); } -static void daemon(const std::string& filePath) { +static void daemon(const std::string& filePath, const PowerStatsAggregator& agg) { // Following a subset of steps outlined in http://man7.org/linux/man-pages/man7/daemon.7.html // Call fork to create child process @@ -145,9 +144,8 @@ static void daemon(const std::string& filePath) { // get the start_data auto start_time = std::chrono::system_clock::now(); - PowerStatsUtil util; std::unordered_map<std::string, uint64_t> start_data; - int ret = util.getData(start_data); + int ret = agg.getData(&start_data); if (ret) { LOG(ERROR) << "failed to get start data"; exit(EXIT_FAILURE); @@ -160,7 +158,7 @@ static void daemon(const std::string& filePath) { // get the end data std::unordered_map<std::string, uint64_t> end_data; - ret = util.getData(end_data); + ret = agg.getData(&end_data); if (ret) { LOG(ERROR) << "failed to get end data"; exit(EXIT_FAILURE); @@ -185,18 +183,18 @@ static void daemon(const std::string& filePath) { exit(EXIT_SUCCESS); } -void run(const Options& opt) { +static void runWithOptions(const Options& opt, const PowerStatsAggregator& agg) { if (opt.daemonMode) { - daemon(opt.filePath); + daemon(opt.filePath, agg); } else { - snapshot(); + snapshot(agg); } } -int main(int argc, char** argv) { +int run(int argc, char** argv, const PowerStatsAggregator& agg) { Options opt = parseArgs(argc, argv); - run(opt); + runWithOptions(opt, agg); return 0; } |