diff options
author | Benjamin Schwartz <bsschwar@google.com> | 2018-11-28 09:34:02 -0800 |
---|---|---|
committer | Benjamin Schwartz <bsschwar@google.com> | 2018-11-29 14:13:57 -0800 |
commit | 3b2518da882d6c1963c617a4ff5753cc2acf6139 (patch) | |
tree | 46f80cd5432d1c092f61cc2b9d8ec0399bbe57ae | |
parent | 6d141702f127ed334d346db1f19377f904552a17 (diff) | |
download | pixel-3b2518da882d6c1963c617a4ff5753cc2acf6139.tar.gz |
power.stats Adding Wlan power entity
Adding Wlan power entity Pixel devices
Bug: 117887759
Bug: 111185513
Test: run vts -m VtsHalPowerStatsV1_0Target
Change-Id: I3edc3efa4447beeedee49afd8576b36c1d6dc995
-rw-r--r-- | powerstats/Android.bp | 4 | ||||
-rw-r--r-- | powerstats/GenericStateResidencyDataProvider.cpp | 47 | ||||
-rw-r--r-- | powerstats/PowerStats.cpp | 38 | ||||
-rw-r--r-- | powerstats/PowerStatsUtils.cpp | 42 | ||||
-rw-r--r-- | powerstats/WlanStateResidencyDataProvider.cpp | 92 | ||||
-rw-r--r-- | powerstats/include/pixelpowerstats/PowerStats.h | 2 | ||||
-rw-r--r-- | powerstats/include/pixelpowerstats/PowerStatsUtils.h | 23 | ||||
-rw-r--r-- | powerstats/include/pixelpowerstats/WlanStateResidencyDataProvider.h | 29 |
8 files changed, 231 insertions, 46 deletions
diff --git a/powerstats/Android.bp b/powerstats/Android.bp index 2354519e..ced86371 100644 --- a/powerstats/Android.bp +++ b/powerstats/Android.bp @@ -6,7 +6,9 @@ cc_library_static { srcs: [ "Debugging.cpp", "PowerStats.cpp", - "GenericStateResidencyDataProvider.cpp" + "PowerStatsUtils.cpp", + "GenericStateResidencyDataProvider.cpp", + "WlanStateResidencyDataProvider.cpp", ], cflags: [ diff --git a/powerstats/GenericStateResidencyDataProvider.cpp b/powerstats/GenericStateResidencyDataProvider.cpp index 214f051b..7ee2e1f0 100644 --- a/powerstats/GenericStateResidencyDataProvider.cpp +++ b/powerstats/GenericStateResidencyDataProvider.cpp @@ -18,6 +18,7 @@ #include <android-base/logging.h> #include <pixelpowerstats/GenericStateResidencyDataProvider.h> +#include <pixelpowerstats/PowerStatsUtils.h> #include <fstream> namespace android { @@ -37,19 +38,8 @@ PowerEntityConfig::PowerEntityConfig(std::string header, } } -bool extractStat(const std::string &line, const std::string &prefix, uint64_t &stat) { - size_t found = line.find(prefix); - if (found == std::string::npos) { - // Did not find the given prefix - return false; - } - - stat = static_cast<uint64_t>(std::stoull(line.substr(found + prefix.length()), nullptr, 0)); - return true; -} - -bool parseState(PowerEntityStateResidencyData &data, const StateResidencyConfig &config, - std::istream &inFile) { +static bool parseState(PowerEntityStateResidencyData &data, const StateResidencyConfig &config, + std::istream &inFile) { size_t numFieldsRead = 0; const size_t numFields = config.entryCountSupported + config.totalTimeSupported + config.lastEntrySupported; @@ -57,18 +47,20 @@ bool parseState(PowerEntityStateResidencyData &data, const StateResidencyConfig while (numFieldsRead < numFields && std::getline(inFile, line)) { uint64_t stat = 0; // Attempt to extract data from the current line - if (config.entryCountSupported && extractStat(line, config.entryCountPrefix, stat)) { + if (config.entryCountSupported && utils::extractStat(line, config.entryCountPrefix, stat)) { data.totalStateEntryCount = config.entryCountTransform ? config.entryCountTransform(stat) : stat; - numFieldsRead++; - } else if (config.totalTimeSupported && extractStat(line, config.totalTimePrefix, stat)) { + ++numFieldsRead; + } else if (config.totalTimeSupported && + utils::extractStat(line, config.totalTimePrefix, stat)) { data.totalTimeInStateMs = config.totalTimeTransform ? config.totalTimeTransform(stat) : stat; - numFieldsRead++; - } else if (config.lastEntrySupported && extractStat(line, config.lastEntryPrefix, stat)) { + ++numFieldsRead; + } else if (config.lastEntrySupported && + utils::extractStat(line, config.lastEntryPrefix, stat)) { data.lastEntryTimestampMs = config.lastEntryTransform ? config.lastEntryTransform(stat) : stat; - numFieldsRead++; + ++numFieldsRead; } } @@ -83,8 +75,9 @@ bool parseState(PowerEntityStateResidencyData &data, const StateResidencyConfig } template <class T> -auto findNext(const std::vector<T> &collection, std::istream &inFile, - const std::function<bool(T const &, std::string)> &pred) { +static auto findNext(const std::vector<T> &collection, std::istream &inFile, + const std::function<bool(T const &, std::string)> &pred) { + // handling the case when there is no header to look for if (pred(collection.front(), "")) { return collection.cbegin(); } @@ -101,9 +94,10 @@ auto findNext(const std::vector<T> &collection, std::istream &inFile, return collection.cend(); } -bool getStateData(PowerEntityStateResidencyResult &result, - std::vector<std::pair<uint32_t, StateResidencyConfig>> stateResidencyConfigs, - std::istream &inFile) { +static bool getStateData( + PowerEntityStateResidencyResult &result, + std::vector<std::pair<uint32_t, StateResidencyConfig>> stateResidencyConfigs, + std::istream &inFile) { size_t numStatesRead = 0; size_t numStates = stateResidencyConfigs.size(); auto nextState = stateResidencyConfigs.cbegin(); @@ -152,10 +146,10 @@ bool GenericStateResidencyDataProvider::getResults( while ((numEntitiesRead < numEntities) && (nextConfig = findNext<decltype(mPowerEntityConfigs)::value_type>( mPowerEntityConfigs, inFile, pred)) != endConfig) { - // Found a matching header. Retreive its state data + // Found a matching header. Retrieve its state data PowerEntityStateResidencyResult result = {.powerEntityId = nextConfig->first}; if (getStateData(result, nextConfig->second.mStateResidencyConfigs, inFile)) { - results[nextConfig->first] = result; + results.insert(std::make_pair(nextConfig->first, result)); ++numEntitiesRead; } else { break; @@ -177,6 +171,7 @@ void GenericStateResidencyDataProvider::addEntity(uint32_t id, PowerEntityConfig std::vector<PowerEntityStateSpace> GenericStateResidencyDataProvider::getStateSpaces() { std::vector<PowerEntityStateSpace> stateSpaces; + stateSpaces.reserve(mPowerEntityConfigs.size()); for (auto config : mPowerEntityConfigs) { PowerEntityStateSpace s = {.powerEntityId = config.first}; s.states.resize(config.second.mStateResidencyConfigs.size()); diff --git a/powerstats/PowerStats.cpp b/powerstats/PowerStats.cpp index 7ce4ddce..69beb87d 100644 --- a/powerstats/PowerStats.cpp +++ b/powerstats/PowerStats.cpp @@ -92,31 +92,31 @@ Return<void> PowerStats::getPowerEntityStateInfo(const hidl_vec<uint32_t> &power return Void(); } - std::vector<PowerEntityStateSpace> s; + std::vector<PowerEntityStateSpace> stateSpaces; // If powerEntityIds is empty then return state space info for all entities if (powerEntityIds.size() == 0) { + stateSpaces.reserve(mPowerEntityStateSpaces.size()); for (auto i : mPowerEntityStateSpaces) { - s.push_back(i.second); + stateSpaces.push_back(i.second); } - _hidl_cb(s, Status::SUCCESS); + _hidl_cb(stateSpaces, Status::SUCCESS); return Void(); } // Return state space information only for valid ids auto ret = Status::SUCCESS; - for (const uint32_t i : powerEntityIds) { - if (mPowerEntityStateSpaces.find(i) != mPowerEntityStateSpaces.end()) { - s.push_back(mPowerEntityStateSpaces.at(i)); + stateSpaces.reserve(powerEntityIds.size()); + for (const uint32_t id : powerEntityIds) { + auto stateSpace = mPowerEntityStateSpaces.find(id); + if (stateSpace != mPowerEntityStateSpaces.end()) { + stateSpaces.push_back(stateSpace->second); } else { ret = Status::INVALID_INPUT; - // TODO(117887759) should we bail here? - // s.resize(0); - // break; } } - _hidl_cb(s, ret); + _hidl_cb(stateSpaces, ret); return Void(); } @@ -131,38 +131,38 @@ Return<void> PowerStats::getPowerEntityStateResidencyData( // If powerEntityIds is empty then return data for all supported entities if (powerEntityIds.size() == 0) { std::vector<uint32_t> ids; - for (auto i : mPowerEntityStateSpaces) { - ids.push_back(i.first); + for (auto stateSpace : mPowerEntityStateSpaces) { + ids.push_back(stateSpace.first); } return getPowerEntityStateResidencyData(ids, _hidl_cb); } std::map<uint32_t, PowerEntityStateResidencyResult> stateResidencies; std::vector<PowerEntityStateResidencyResult> results; + results.reserve(powerEntityIds.size()); // return results for only the given powerEntityIds bool invalidInput = false; bool filesystemError = false; for (auto id : powerEntityIds) { + auto dataProvider = mStateResidencyDataProviders.find(id); // skip if the given powerEntityId does not have an associated StateResidencyDataProvider - if (mStateResidencyDataProviders.find(id) == mStateResidencyDataProviders.end()) { + if (dataProvider == mStateResidencyDataProviders.end()) { invalidInput = true; - // TODO(117887759) should we bail here? - // results.resize(0); - // break; continue; } // get the results if we have not already done so. if (stateResidencies.find(id) == stateResidencies.end()) { - if (!mStateResidencyDataProviders.at(id)->getResults(stateResidencies)) { + if (!dataProvider->second->getResults(stateResidencies)) { filesystemError = true; } } // append results - if (stateResidencies.find(id) != stateResidencies.end()) { - results.push_back(stateResidencies.at(id)); + auto stateResidency = stateResidencies.find(id); + if (stateResidency != stateResidencies.end()) { + results.push_back(stateResidency->second); } } diff --git a/powerstats/PowerStatsUtils.cpp b/powerstats/PowerStatsUtils.cpp new file mode 100644 index 00000000..2c20ec74 --- /dev/null +++ b/powerstats/PowerStatsUtils.cpp @@ -0,0 +1,42 @@ +/* + * 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. + */ + +#include <pixelpowerstats/PowerStatsUtils.h> + +namespace android { +namespace hardware { +namespace google { +namespace pixel { +namespace powerstats { +namespace utils { + +bool extractStat(const std::string &line, const std::string &prefix, uint64_t &stat) { + size_t found = line.find(prefix); + if (found == std::string::npos) { + // Did not find the given prefix + return false; + } + + stat = static_cast<uint64_t>(std::stoull(line.substr(found + prefix.length()), nullptr, 0)); + return true; +} + +} // namespace utils +} // namespace powerstats +} // namespace pixel +} // namespace google +} // namespace hardware +} // namespace android
\ No newline at end of file diff --git a/powerstats/WlanStateResidencyDataProvider.cpp b/powerstats/WlanStateResidencyDataProvider.cpp new file mode 100644 index 00000000..86403e0e --- /dev/null +++ b/powerstats/WlanStateResidencyDataProvider.cpp @@ -0,0 +1,92 @@ +/* + * 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 <android-base/logging.h> +#include <pixelpowerstats/PowerStatsUtils.h> +#include <pixelpowerstats/WlanStateResidencyDataProvider.h> +#include <fstream> + +namespace android { +namespace hardware { +namespace google { +namespace pixel { +namespace powerstats { + +const uint32_t ACTIVE_ID = 0; +const uint32_t DEEPSLEEP_ID = 1; + +WlanStateResidencyDataProvider::WlanStateResidencyDataProvider(uint32_t id) : mPowerEntityId(id) {} + +bool WlanStateResidencyDataProvider::getResults( + std::map<uint32_t, PowerEntityStateResidencyResult> &results) { + const std::string path = "/d/wlan0/power_stats"; + std::ifstream inFile(path, std::ifstream::in); + if (!inFile.is_open()) { + LOG(ERROR) << __func__ << ":Failed to open file " << path; + return false; + } + + PowerEntityStateResidencyResult result = { + .powerEntityId = mPowerEntityId, + .stateResidencyData = {{.powerEntityStateId = ACTIVE_ID}, + {.powerEntityStateId = DEEPSLEEP_ID}}}; + + size_t numFieldsRead = 0; + const size_t numFields = 4; + std::string line; + while ((numFieldsRead < numFields) && std::getline(inFile, line)) { + uint64_t stat = 0; + if (utils::extractStat(line, "cumulative_sleep_time_ms:", stat)) { + result.stateResidencyData[1].totalTimeInStateMs = stat; + ++numFieldsRead; + } else if (utils::extractStat(line, "cumulative_total_on_time_ms:", stat)) { + result.stateResidencyData[0].totalTimeInStateMs = stat; + ++numFieldsRead; + } else if (utils::extractStat(line, "deep_sleep_enter_counter:", stat)) { + result.stateResidencyData[0].totalStateEntryCount = stat; + result.stateResidencyData[1].totalStateEntryCount = stat; + ++numFieldsRead; + } else if (utils::extractStat(line, "last_deep_sleep_enter_tstamp_ms:", stat)) { + result.stateResidencyData[1].lastEntryTimestampMs = stat; + ++numFieldsRead; + } + } + + // End of file was reached and not all state data was parsed. Something + // went wrong + if (numFieldsRead != numFields) { + LOG(ERROR) << __func__ << ": failed to parse stats for wlan"; + return false; + } + + results.insert(std::make_pair(mPowerEntityId, result)); + return true; +} + +std::vector<PowerEntityStateSpace> WlanStateResidencyDataProvider::getStateSpaces() { + return { + {.powerEntityId = mPowerEntityId, + .states = {{.powerEntityStateId = ACTIVE_ID, .powerEntityStateName = "Active"}, + {.powerEntityStateId = DEEPSLEEP_ID, .powerEntityStateName = "Deep-Sleep"}}}}; +} + +} // namespace powerstats +} // namespace pixel +} // namespace google +} // namespace hardware +} // namespace android
\ No newline at end of file diff --git a/powerstats/include/pixelpowerstats/PowerStats.h b/powerstats/include/pixelpowerstats/PowerStats.h index 38d09f5f..c20bea8f 100644 --- a/powerstats/include/pixelpowerstats/PowerStats.h +++ b/powerstats/include/pixelpowerstats/PowerStats.h @@ -64,6 +64,8 @@ class PowerStats : public IPowerStats { PowerStats() = default; void setRailDataProvider(std::unique_ptr<IRailDataProvider> dataProvider); uint32_t addPowerEntity(std::string name, PowerEntityType type); + // Using shared_ptr here because multiple power entities could depend on the + // same IStateResidencyDataProvider. void addStateResidencyDataProvider(std::shared_ptr<IStateResidencyDataProvider> p); // Methods from ::android::hardware::power::stats::V1_0::IPowerStats follow. diff --git a/powerstats/include/pixelpowerstats/PowerStatsUtils.h b/powerstats/include/pixelpowerstats/PowerStatsUtils.h new file mode 100644 index 00000000..eaed4a4c --- /dev/null +++ b/powerstats/include/pixelpowerstats/PowerStatsUtils.h @@ -0,0 +1,23 @@ +#ifndef HARDWARE_GOOGLE_PIXEL_POWERSTATS_POWERSTATSUTILS_H +#define HARDWARE_GOOGLE_PIXEL_POWERSTATS_POWERSTATSUTILS_H + +#include <cstdint> +#include <string> + +namespace android { +namespace hardware { +namespace google { +namespace pixel { +namespace powerstats { +namespace utils { + +bool extractStat(const std::string &line, const std::string &prefix, uint64_t &stat); + +} // namespace utils +} // namespace powerstats +} // namespace pixel +} // namespace google +} // namespace hardware +} // namespace android + +#endif // HARDWARE_GOOGLE_PIXEL_POWERSTATS_POWERSTATSUTILS_H
\ No newline at end of file diff --git a/powerstats/include/pixelpowerstats/WlanStateResidencyDataProvider.h b/powerstats/include/pixelpowerstats/WlanStateResidencyDataProvider.h new file mode 100644 index 00000000..c1f862d1 --- /dev/null +++ b/powerstats/include/pixelpowerstats/WlanStateResidencyDataProvider.h @@ -0,0 +1,29 @@ +#ifndef HARDWARE_GOOGLE_PIXEL_POWERSTATS_WLANSTATERESIDENCYDATAPROVIDER_H +#define HARDWARE_GOOGLE_PIXEL_POWERSTATS_WLANSTATERESIDENCYDATAPROVIDER_H + +#include <pixelpowerstats/PowerStats.h> + +namespace android { +namespace hardware { +namespace google { +namespace pixel { +namespace powerstats { + +class WlanStateResidencyDataProvider : public IStateResidencyDataProvider { + public: + WlanStateResidencyDataProvider(uint32_t id); + ~WlanStateResidencyDataProvider() = default; + bool getResults(std::map<uint32_t, PowerEntityStateResidencyResult> &results) override; + std::vector<PowerEntityStateSpace> getStateSpaces() override; + + private: + uint32_t mPowerEntityId; +}; + +} // namespace powerstats +} // namespace pixel +} // namespace google +} // namespace hardware +} // namespace android + +#endif // HARDWARE_GOOGLE_PIXEL_POWERSTATS_WLANSTATERESIDENCYDATAPROVIDER_H
\ No newline at end of file |