summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Schwartz <bsschwar@google.com>2018-11-28 09:34:02 -0800
committerBenjamin Schwartz <bsschwar@google.com>2018-11-29 14:13:57 -0800
commit3b2518da882d6c1963c617a4ff5753cc2acf6139 (patch)
tree46f80cd5432d1c092f61cc2b9d8ec0399bbe57ae
parent6d141702f127ed334d346db1f19377f904552a17 (diff)
downloadpixel-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.bp4
-rw-r--r--powerstats/GenericStateResidencyDataProvider.cpp47
-rw-r--r--powerstats/PowerStats.cpp38
-rw-r--r--powerstats/PowerStatsUtils.cpp42
-rw-r--r--powerstats/WlanStateResidencyDataProvider.cpp92
-rw-r--r--powerstats/include/pixelpowerstats/PowerStats.h2
-rw-r--r--powerstats/include/pixelpowerstats/PowerStatsUtils.h23
-rw-r--r--powerstats/include/pixelpowerstats/WlanStateResidencyDataProvider.h29
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