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
This commit is contained in:
parent
d287e223f4
commit
0d6392efa6
19 changed files with 597 additions and 2078 deletions
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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 <android-base/logging.h>
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace aidl {
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace google {
|
||||
namespace pixel {
|
||||
namespace powerstats {
|
||||
namespace power {
|
||||
namespace stats {
|
||||
|
||||
AocStateResidencyDataProvider::AocStateResidencyDataProvider(
|
||||
std::vector<std::pair<uint32_t, std::string>> ids,
|
||||
std::vector<std::pair<std::string, std::string>> states) {
|
||||
AocStateResidencyDataProvider::AocStateResidencyDataProvider(std::vector<std::pair<std::string,
|
||||
std::string>> ids, std::vector<std::pair<std::string, std::string>> states) {
|
||||
// AoC stats are reported in ticks of 244.140625ns. The transform
|
||||
// function converts ticks to milliseconds.
|
||||
// 1000000 / 244.140625 = 4096.
|
||||
static const uint64_t AOC_CLK = 4096;
|
||||
std::function<uint64_t(uint64_t)> aocTickToMs = [](uint64_t a) { return a / AOC_CLK; };
|
||||
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<std::pair<std::string, std::string>> aocStateHeaders = {
|
||||
std::make_pair(state.first, ""),
|
||||
};
|
||||
std::vector<GenericStateResidencyDataProvider::PowerEntityConfig> cfgs;
|
||||
cfgs.emplace_back(generateGenericStateResidencyConfigs(config, aocStateHeaders),
|
||||
id.first, "");
|
||||
std::unique_ptr<GenericStateResidencyDataProvider> sdp(
|
||||
new GenericStateResidencyDataProvider(id.second + state.second));
|
||||
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<uint32_t, PowerEntityStateResidencyResult> &results) {
|
||||
for (auto &provider : mProviders) {
|
||||
provider->getResults(results);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<PowerEntityStateSpace> AocStateResidencyDataProvider::getStateSpaces() {
|
||||
// Return state spaces based on all configured providers.
|
||||
bool AocStateResidencyDataProvider::getStateResidencies(
|
||||
std::unordered_map<std::string, std::vector<StateResidency>> *residencies) {
|
||||
// States from the same power entity are merged.
|
||||
std::map<uint32_t, PowerEntityStateSpace> 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];
|
||||
}
|
||||
} else {
|
||||
stateSpaces.insert(std::pair<uint32_t, PowerEntityStateSpace>(
|
||||
stateSpace.powerEntityId, stateSpace));
|
||||
bool ret = true;
|
||||
for (const auto &providerList : mProviders) {
|
||||
int32_t stateId = 0;
|
||||
std::string curEntity = providerList.first;
|
||||
std::vector<StateResidency> stateResidencies;
|
||||
|
||||
// Iterate over each provider in the providerList, appending each of the states
|
||||
for (const auto &provider : providerList.second) {
|
||||
std::unordered_map<std::string, std::vector<StateResidency>> residency;
|
||||
ret &= provider->getStateResidencies(&residency);
|
||||
|
||||
// Each provider should only return data for curEntity but checking anyway
|
||||
if (residency.find(curEntity) != residency.end()) {
|
||||
for (auto &r : residency.at(curEntity)) {
|
||||
/*
|
||||
* Modifying stateId here because we are stitching together infos from
|
||||
* multiple GenericStateResidencyDataProviders. stateId must be modified
|
||||
* to maintain uniqueness for a given entity
|
||||
*/
|
||||
r.id = stateId++;
|
||||
stateResidencies.push_back(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<PowerEntityStateSpace> 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<std::string, std::vector<State>> AocStateResidencyDataProvider::getInfo() {
|
||||
// States from the same power entity are merged
|
||||
std::unordered_map<std::string, std::vector<State>> infos;
|
||||
for (const auto &providerList : mProviders) {
|
||||
int32_t stateId = 0;
|
||||
std::string curEntity = providerList.first;
|
||||
std::vector<State> stateInfos;
|
||||
|
||||
// Iterate over each provider in the providerList, appending each of the states
|
||||
for (const auto &provider : providerList.second) {
|
||||
std::unordered_map<std::string, std::vector<State>> info = provider->getInfo();
|
||||
|
||||
// Each provider should only return data for curEntity but checking anyway
|
||||
if (info.find(curEntity) != info.end()) {
|
||||
for (auto &i : info.at(curEntity)) {
|
||||
/*
|
||||
* Modifying stateId because we are stitching together infos from
|
||||
* multiple GenericStateResidencyDataProviders. stateId must be modified
|
||||
* to maintain uniqueness for a given entity
|
||||
*/
|
||||
i.id = stateId++;
|
||||
stateInfos.push_back(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
infos.emplace(curEntity, stateInfos);
|
||||
}
|
||||
|
||||
return infos;
|
||||
}
|
||||
|
||||
} // namespace stats
|
||||
} // namespace power
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
} // namespace aidl
|
||||
|
|
|
@ -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 <pixelpowerstats/GenericStateResidencyDataProvider.h>
|
||||
#include <pixelpowerstats/PowerStats.h>
|
||||
#include <dataproviders/GenericStateResidencyDataProvider.h>
|
||||
#include <PowerStatsAidl.h>
|
||||
|
||||
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<std::pair<uint32_t, std::string>> ids,
|
||||
AocStateResidencyDataProvider(std::vector<std::pair<std::string, std::string>> ids,
|
||||
std::vector<std::pair<std::string, std::string>> states);
|
||||
~AocStateResidencyDataProvider() = default;
|
||||
bool getResults(
|
||||
std::unordered_map<uint32_t, PowerEntityStateResidencyResult> &results) override;
|
||||
std::vector<PowerEntityStateSpace> getStateSpaces() override;
|
||||
bool getStateResidencies(
|
||||
std::unordered_map<std::string, std::vector<StateResidency>> *residencies) override;
|
||||
std::unordered_map<std::string, std::vector<State>> getInfo() override;
|
||||
|
||||
private:
|
||||
std::vector<std::unique_ptr<GenericStateResidencyDataProvider>> mProviders;
|
||||
std::unordered_map<std::string /* entity name */,
|
||||
std::vector<std::unique_ptr<GenericStateResidencyDataProvider>> /* 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
|
|
@ -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 <android-base/logging.h>
|
||||
|
||||
namespace aidl {
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace power {
|
||||
namespace stats {
|
||||
|
||||
AocStateResidencyDataProvider::AocStateResidencyDataProvider(std::vector<std::pair<std::string,
|
||||
std::string>> ids, std::vector<std::pair<std::string, std::string>> states) {
|
||||
// AoC stats are reported in ticks of 244.140625ns. The transform
|
||||
// function converts ticks to milliseconds.
|
||||
// 1000000 / 244.140625 = 4096.
|
||||
static const uint64_t AOC_CLK = 4096;
|
||||
std::function<uint64_t(uint64_t)> aocTickToMs = [](uint64_t a) { return a / AOC_CLK; };
|
||||
GenericStateResidencyDataProvider::StateResidencyConfig config = {
|
||||
.entryCountSupported = true,
|
||||
.entryCountPrefix = "Counter:",
|
||||
.totalTimeSupported = true,
|
||||
.totalTimePrefix = "Cumulative time:",
|
||||
.totalTimeTransform = aocTickToMs,
|
||||
.lastEntrySupported = true,
|
||||
.lastEntryPrefix = "Time last entered:",
|
||||
.lastEntryTransform = aocTickToMs,
|
||||
};
|
||||
for (const auto &id : ids) {
|
||||
for (const auto &state : states) {
|
||||
std::vector<std::pair<std::string, std::string>> aocStateHeaders = {
|
||||
std::make_pair(state.first, ""),
|
||||
};
|
||||
std::vector<GenericStateResidencyDataProvider::PowerEntityConfig> cfgs;
|
||||
cfgs.emplace_back(generateGenericStateResidencyConfigs(config, aocStateHeaders),
|
||||
id.first, "");
|
||||
std::unique_ptr<GenericStateResidencyDataProvider> sdp(
|
||||
new GenericStateResidencyDataProvider(id.second + state.second, cfgs));
|
||||
mProviders[id.first].push_back(std::move(sdp));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool AocStateResidencyDataProvider::getStateResidencies(
|
||||
std::unordered_map<std::string, std::vector<StateResidency>> *residencies) {
|
||||
// States from the same power entity are merged.
|
||||
bool ret = true;
|
||||
for (const auto &providerList : mProviders) {
|
||||
int32_t stateId = 0;
|
||||
std::string curEntity = providerList.first;
|
||||
std::vector<StateResidency> stateResidencies;
|
||||
|
||||
// Iterate over each provider in the providerList, appending each of the states
|
||||
for (const auto &provider : providerList.second) {
|
||||
std::unordered_map<std::string, std::vector<StateResidency>> residency;
|
||||
ret &= provider->getStateResidencies(&residency);
|
||||
|
||||
// Each provider should only return data for curEntity but checking anyway
|
||||
if (residency.find(curEntity) != residency.end()) {
|
||||
for (auto &r : residency.at(curEntity)) {
|
||||
/*
|
||||
* Modifying stateId here because we are stitching together infos from
|
||||
* multiple GenericStateResidencyDataProviders. stateId must be modified
|
||||
* to maintain uniqueness for a given entity
|
||||
*/
|
||||
r.id = stateId++;
|
||||
stateResidencies.push_back(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
residencies->emplace(curEntity, stateResidencies);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::unordered_map<std::string, std::vector<State>> AocStateResidencyDataProvider::getInfo() {
|
||||
// States from the same power entity are merged
|
||||
std::unordered_map<std::string, std::vector<State>> infos;
|
||||
for (const auto &providerList : mProviders) {
|
||||
int32_t stateId = 0;
|
||||
std::string curEntity = providerList.first;
|
||||
std::vector<State> stateInfos;
|
||||
|
||||
// Iterate over each provider in the providerList, appending each of the states
|
||||
for (const auto &provider : providerList.second) {
|
||||
std::unordered_map<std::string, std::vector<State>> info = provider->getInfo();
|
||||
|
||||
// Each provider should only return data for curEntity but checking anyway
|
||||
if (info.find(curEntity) != info.end()) {
|
||||
for (auto &i : info.at(curEntity)) {
|
||||
/*
|
||||
* Modifying stateId because we are stitching together infos from
|
||||
* multiple GenericStateResidencyDataProviders. stateId must be modified
|
||||
* to maintain uniqueness for a given entity
|
||||
*/
|
||||
i.id = stateId++;
|
||||
stateInfos.push_back(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
infos.emplace(curEntity, stateInfos);
|
||||
}
|
||||
|
||||
return infos;
|
||||
}
|
||||
|
||||
} // namespace stats
|
||||
} // namespace power
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
} // namespace aidl
|
|
@ -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 <dataproviders/GenericStateResidencyDataProvider.h>
|
||||
#include <PowerStatsAidl.h>
|
||||
|
||||
namespace aidl {
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace power {
|
||||
namespace stats {
|
||||
|
||||
class AocStateResidencyDataProvider : public PowerStats::IStateResidencyDataProvider {
|
||||
public:
|
||||
AocStateResidencyDataProvider(std::vector<std::pair<std::string, std::string>> ids,
|
||||
std::vector<std::pair<std::string, std::string>> states);
|
||||
~AocStateResidencyDataProvider() = default;
|
||||
bool getStateResidencies(
|
||||
std::unordered_map<std::string, std::vector<StateResidency>> *residencies) override;
|
||||
std::unordered_map<std::string, std::vector<State>> getInfo() override;
|
||||
|
||||
private:
|
||||
std::unordered_map<std::string /* entity name */,
|
||||
std::vector<std::unique_ptr<GenericStateResidencyDataProvider>> /* providers */> mProviders;
|
||||
};
|
||||
|
||||
} // namespace stats
|
||||
} // namespace power
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
} // namespace aidl
|
|
@ -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 <android-base/logging.h>
|
||||
|
@ -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<Config> cfgs)
|
||||
: mPath(std::move(path)), mClockRate(clockRate), mPowerEntities(std::move(cfgs)) {}
|
||||
|
||||
void DvfsStateResidencyDataProvider::addEntity(
|
||||
uint32_t id, std::string name, std::vector<std::pair<std::string, std::string>> 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<std::string> 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<uint32_t, PowerEntityStateResidencyResult> &results) {
|
||||
bool DvfsStateResidencyDataProvider::getStateResidencies(
|
||||
std::unordered_map<std::string, std::vector<StateResidency>> *residencies) {
|
||||
std::unique_ptr<FILE, decltype(&fclose)> fp(fopen(mPath.c_str(), "r"), fclose);
|
||||
if (!fp) {
|
||||
PLOG(ERROR) << __func__ << ":Failed to open file " << mPath
|
||||
<< " 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> 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<PowerEntityStateSpace> DvfsStateResidencyDataProvider::getStateSpaces() {
|
||||
std::vector<PowerEntityStateSpace> stateSpaces;
|
||||
stateSpaces.reserve(mPowerEntities.size());
|
||||
std::unordered_map<std::string, std::vector<State>> DvfsStateResidencyDataProvider::getInfo() {
|
||||
std::unordered_map<std::string, std::vector<State>> info;
|
||||
for (auto const &entity : mPowerEntities) {
|
||||
PowerEntityStateSpace s = {.powerEntityId = entity.powerEntityId};
|
||||
s.states.resize(entity.states.size());
|
||||
uint32_t stateId = 0;
|
||||
std::vector<State> 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
|
||||
|
|
|
@ -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 <pixelpowerstats/PowerStats.h>
|
||||
#include <PowerStatsAidl.h>
|
||||
|
||||
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:
|
||||
class Config {
|
||||
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<std::pair<std::string, std::string>> frequencies);
|
||||
|
||||
/*
|
||||
* See IStateResidencyDataProvider::getResults.
|
||||
*/
|
||||
bool getResults(
|
||||
std::unordered_map<uint32_t, PowerEntityStateResidencyResult> &results) override;
|
||||
|
||||
/*
|
||||
* See IStateResidencyDataProvider::getStateSpaces.
|
||||
*/
|
||||
std::vector<PowerEntityStateSpace> 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;
|
||||
|
||||
// Power entity name to parse.
|
||||
std::string powerEntityName;
|
||||
|
||||
// List of state pairs (name to display, name to parse).
|
||||
std::vector<std::pair<std::string, std::string>> states;
|
||||
};
|
||||
std::vector<config> mPowerEntities;
|
||||
/*
|
||||
* path - path to dvfs sysfs node.
|
||||
* clockRate - clock rate in KHz.
|
||||
*/
|
||||
DvfsStateResidencyDataProvider(std::string path, uint64_t clockRate, std::vector<Config> cfgs);
|
||||
~DvfsStateResidencyDataProvider() = default;
|
||||
|
||||
/*
|
||||
* See IStateResidencyDataProvider::getStateResidencies
|
||||
*/
|
||||
bool getStateResidencies(
|
||||
std::unordered_map<std::string, std::vector<StateResidency>> *residencies) override;
|
||||
|
||||
/*
|
||||
* See IStateResidencyDataProvider::getInfo
|
||||
*/
|
||||
std::unordered_map<std::string, std::vector<State>> getInfo() override;
|
||||
|
||||
private:
|
||||
int32_t matchEntity(char const *line);
|
||||
int32_t matchState(char const *line, const Config& powerEntity);
|
||||
bool parseState(char const *line, uint64_t *duration, uint64_t *count);
|
||||
|
||||
const std::string mPath;
|
||||
const uint64_t mClockRate;
|
||||
std::vector<Config> mPowerEntities;
|
||||
};
|
||||
|
||||
} // namespace powerstats
|
||||
} // namespace pixel
|
||||
} // namespace google
|
||||
} // namespace stats
|
||||
} // namespace power
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
|
||||
#endif // HARDWARE_GOOGLE_PIXEL_POWERSTATS_DVFSSTATERESIDENCYDATAPROVIDER_H
|
||||
} // namespace aidl
|
||||
|
|
|
@ -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 <android-base/logging.h>
|
||||
#include <android-base/parseint.h>
|
||||
#include <android-base/strings.h>
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
using android::base::ParseUint;
|
||||
using android::base::Split;
|
||||
using android::base::StartsWith;
|
||||
using android::base::Trim;
|
||||
|
||||
static const std::string nameSuffix = "-DVFS";
|
||||
|
||||
namespace aidl {
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace power {
|
||||
namespace stats {
|
||||
|
||||
DvfsStateResidencyDataProvider::DvfsStateResidencyDataProvider(std::string path, uint64_t clockRate,
|
||||
std::vector<Config> cfgs)
|
||||
: mPath(std::move(path)), mClockRate(clockRate), mPowerEntities(std::move(cfgs)) {}
|
||||
|
||||
int32_t DvfsStateResidencyDataProvider::matchEntity(char const *line) {
|
||||
for (int32_t i = 0; i < mPowerEntities.size(); i++) {
|
||||
if (mPowerEntities[i].powerEntityName == Trim(std::string(line))) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t DvfsStateResidencyDataProvider::matchState(char const *line, const Config& powerEntity) {
|
||||
for (int32_t i = 0; i < powerEntity.states.size(); i++) {
|
||||
if (StartsWith(Trim(std::string(line)), powerEntity.states[i].second)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool DvfsStateResidencyDataProvider::parseState(char const *line, uint64_t *duration,
|
||||
uint64_t *count) {
|
||||
std::vector<std::string> parts = Split(line, " ");
|
||||
if (parts.size() != 7) {
|
||||
return false;
|
||||
}
|
||||
if (!ParseUint(Trim(parts[3]), count)) {
|
||||
return false;
|
||||
}
|
||||
if (!ParseUint(Trim(parts[6]), duration)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DvfsStateResidencyDataProvider::getStateResidencies(
|
||||
std::unordered_map<std::string, std::vector<StateResidency>> *residencies) {
|
||||
std::unique_ptr<FILE, decltype(&fclose)> fp(fopen(mPath.c_str(), "r"), fclose);
|
||||
if (!fp) {
|
||||
PLOG(ERROR) << __func__ << ":Failed to open file " << mPath;
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const Config &powerEntity : mPowerEntities) {
|
||||
std::vector<StateResidency> stateResidency(powerEntity.states.size());
|
||||
for (int32_t i = 0; i < stateResidency.size(); i++) {
|
||||
stateResidency[i].id = i;
|
||||
}
|
||||
residencies->emplace(powerEntity.powerEntityName + nameSuffix, stateResidency);
|
||||
}
|
||||
|
||||
size_t len = 0;
|
||||
char *line = nullptr;
|
||||
|
||||
int32_t temp, powerEntityIndex, stateId = -1;
|
||||
uint64_t duration, count;
|
||||
auto it = residencies->end();
|
||||
|
||||
while (getline(&line, &len, fp.get()) != -1) {
|
||||
temp = matchEntity(line);
|
||||
// Assign new index only when a new valid entity is encountered.
|
||||
if (temp >= 0) {
|
||||
powerEntityIndex = temp;
|
||||
it = residencies->find(mPowerEntities[powerEntityIndex].powerEntityName + nameSuffix);
|
||||
}
|
||||
|
||||
if (it != residencies->end()) {
|
||||
stateId = matchState(line, mPowerEntities[powerEntityIndex]);
|
||||
|
||||
if (stateId >= 0) {
|
||||
if (parseState(line, &duration, &count)) {
|
||||
it->second[stateId].totalTimeInStateMs =
|
||||
duration / mClockRate;
|
||||
it->second[stateId].totalStateEntryCount = count;
|
||||
} else {
|
||||
LOG(ERROR) << "Failed to parse duration and count from [" << std::string(line)
|
||||
<< "]";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(line);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::unordered_map<std::string, std::vector<State>> DvfsStateResidencyDataProvider::getInfo() {
|
||||
std::unordered_map<std::string, std::vector<State>> info;
|
||||
for (auto const &entity : mPowerEntities) {
|
||||
std::vector<State> stateInfo(entity.states.size());
|
||||
int32_t stateId = 0;
|
||||
for (auto const &state : entity.states) {
|
||||
stateInfo[stateId] = State{
|
||||
.id = stateId,
|
||||
.name = state.first
|
||||
};
|
||||
stateId++;
|
||||
}
|
||||
info.emplace(entity.powerEntityName + nameSuffix, stateInfo);
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
} // namespace stats
|
||||
} // namespace power
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
} // namespace aidl
|
|
@ -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 <PowerStatsAidl.h>
|
||||
|
||||
namespace aidl {
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace power {
|
||||
namespace stats {
|
||||
|
||||
class DvfsStateResidencyDataProvider : public PowerStats::IStateResidencyDataProvider {
|
||||
public:
|
||||
class Config {
|
||||
public:
|
||||
// Power entity name to parse.
|
||||
std::string powerEntityName;
|
||||
|
||||
// List of state pairs (name to display, name to parse).
|
||||
std::vector<std::pair<std::string, std::string>> states;
|
||||
};
|
||||
/*
|
||||
* path - path to dvfs sysfs node.
|
||||
* clockRate - clock rate in KHz.
|
||||
*/
|
||||
DvfsStateResidencyDataProvider(std::string path, uint64_t clockRate, std::vector<Config> cfgs);
|
||||
~DvfsStateResidencyDataProvider() = default;
|
||||
|
||||
/*
|
||||
* See IStateResidencyDataProvider::getStateResidencies
|
||||
*/
|
||||
bool getStateResidencies(
|
||||
std::unordered_map<std::string, std::vector<StateResidency>> *residencies) override;
|
||||
|
||||
/*
|
||||
* See IStateResidencyDataProvider::getInfo
|
||||
*/
|
||||
std::unordered_map<std::string, std::vector<State>> getInfo() override;
|
||||
|
||||
private:
|
||||
int32_t matchEntity(char const *line);
|
||||
int32_t matchState(char const *line, const Config& powerEntity);
|
||||
bool parseState(char const *line, uint64_t *duration, uint64_t *count);
|
||||
|
||||
const std::string mPath;
|
||||
const uint64_t mClockRate;
|
||||
std::vector<Config> mPowerEntities;
|
||||
};
|
||||
|
||||
} // namespace stats
|
||||
} // namespace power
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
} // namespace aidl
|
|
@ -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 <android-base/file.h>
|
||||
#include <android-base/logging.h>
|
||||
#include <android-base/properties.h>
|
||||
#include <android-base/stringprintf.h>
|
||||
#include <android-base/strings.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <exception>
|
||||
#include <thread>
|
||||
|
||||
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<std::string> 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<void> RailDataProvider::getRailInfo(IPowerStats::getRailInfo_cb _hidl_cb) {
|
||||
hidl_vec<RailInfo> rInfo;
|
||||
Status ret = Status::SUCCESS;
|
||||
size_t index;
|
||||
std::lock_guard<std::mutex> _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<void> RailDataProvider::getEnergyData(const hidl_vec<uint32_t> &railIndices,
|
||||
IPowerStats::getEnergyData_cb _hidl_cb) {
|
||||
hidl_vec<EnergyData> eVal;
|
||||
std::lock_guard<std::mutex> _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<void> RailDataProvider::streamEnergyData(uint32_t timeMs, uint32_t samplingRate,
|
||||
IPowerStats::streamEnergyData_cb _hidl_cb) {
|
||||
std::lock_guard<std::mutex> _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
|
|
@ -1,55 +0,0 @@
|
|||
#ifndef ANDROID_HARDWARE_POWERSTATS_RAILDATAPROVIDER_H
|
||||
#define ANDROID_HARDWARE_POWERSTATS_RAILDATAPROVIDER_H
|
||||
|
||||
#include <fmq/MessageQueue.h>
|
||||
#include <pixelpowerstats/PowerStats.h>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace google {
|
||||
namespace pixel {
|
||||
namespace powerstats {
|
||||
|
||||
typedef MessageQueue<EnergyData, kSynchronizedReadWrite> MessageQueueSync;
|
||||
struct RailData {
|
||||
std::string devicePath;
|
||||
uint32_t index;
|
||||
std::string subsysName;
|
||||
uint32_t samplingRate;
|
||||
};
|
||||
|
||||
struct OnDeviceMmt {
|
||||
std::mutex mLock;
|
||||
bool hwEnabled;
|
||||
std::vector<std::string> devicePaths;
|
||||
std::map<std::string, RailData> railsInfo;
|
||||
std::vector<EnergyData> reading;
|
||||
std::unique_ptr<MessageQueueSync> fmqSynchronized;
|
||||
};
|
||||
|
||||
class RailDataProvider : public IRailDataProvider {
|
||||
public:
|
||||
RailDataProvider();
|
||||
// Methods from ::android::hardware::power::stats::V1_0::IPowerStats follow.
|
||||
Return<void> getRailInfo(IPowerStats::getRailInfo_cb _hidl_cb) override;
|
||||
Return<void> getEnergyData(const hidl_vec<uint32_t>& railIndices,
|
||||
IPowerStats::getEnergyData_cb _hidl_cb) override;
|
||||
Return<void> 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
|
|
@ -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 <android-base/logging.h>
|
||||
#include <android-base/parseint.h>
|
||||
#include <android-base/strings.h>
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
using android::base::ParseUint;
|
||||
using android::base::Split;
|
||||
using android::base::StartsWith;
|
||||
using android::base::Trim;
|
||||
|
||||
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<uint32_t, PowerEntityStateResidencyResult> &results) {
|
||||
PowerEntityStateResidencyResult result = {
|
||||
.powerEntityId = mPowerEntityId,
|
||||
.stateResidencyData = {{.powerEntityStateId = HIBERNATE_STATE_ID}}};
|
||||
|
||||
// The transform function converts microseconds to milliseconds.
|
||||
std::function<uint64_t(uint64_t)> 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<PowerEntityStateSpace> UfsStateResidencyDataProvider::getStateSpaces() {
|
||||
return {{.powerEntityId = mPowerEntityId,
|
||||
.states = {{.powerEntityStateId = HIBERNATE_STATE_ID,
|
||||
.powerEntityStateName = "HIBERN8"}}}};
|
||||
}
|
||||
|
||||
uint64_t UfsStateResidencyDataProvider::readStat(std::string path) {
|
||||
std::unique_ptr<FILE, decltype(&fclose)> fp(fopen(path.c_str(), "r"), fclose);
|
||||
if (!fp) {
|
||||
PLOG(ERROR) << __func__ << ":Failed to open file " << path
|
||||
<< " Error = " << strerror(errno);
|
||||
return 0;
|
||||
}
|
||||
const size_t size = 20;
|
||||
char buf[size];
|
||||
(void)fread(&buf, sizeof(char), size, fp.get());
|
||||
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
|
|
@ -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 <pixelpowerstats/PowerStats.h>
|
||||
|
||||
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<uint32_t, PowerEntityStateResidencyResult> &results) override;
|
||||
|
||||
/*
|
||||
* See IStateResidencyDataProvider::getStateSpaces.
|
||||
*/
|
||||
std::vector<PowerEntityStateSpace> 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
|
|
@ -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
|
|
@ -1,11 +0,0 @@
|
|||
<manifest version="1.0" type="device">
|
||||
<hal format="hidl">
|
||||
<name>android.hardware.power.stats</name>
|
||||
<transport>hwbinder</transport>
|
||||
<version>1.0</version>
|
||||
<interface>
|
||||
<name>IPowerStats</name>
|
||||
<instance>default</instance>
|
||||
</interface>
|
||||
</hal>
|
||||
</manifest>
|
|
@ -14,126 +14,80 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "android.hardware.power.stats@1.0-service.gs101"
|
||||
|
||||
#include <android/log.h>
|
||||
#include <binder/IPCThreadState.h>
|
||||
#include <binder/IServiceManager.h>
|
||||
#include <binder/ProcessState.h>
|
||||
#include <hidl/HidlTransportSupport.h>
|
||||
#include <pixelpowerstats/AidlStateResidencyDataProvider.h>
|
||||
#include <pixelpowerstats/GenericStateResidencyDataProvider.h>
|
||||
#include <pixelpowerstats/PowerStats.h>
|
||||
#define LOG_TAG "android.hardware.power.stats-service.pixel"
|
||||
|
||||
#include <PowerStatsAidl.h>
|
||||
#include "AocStateResidencyDataProvider.h"
|
||||
#include "DvfsStateResidencyDataProvider.h"
|
||||
#include "RailDataProvider.h"
|
||||
#include "UfsStateResidencyDataProvider.h"
|
||||
#include <dataproviders/DisplayStateResidencyDataProvider.h>
|
||||
#include <dataproviders/GenericStateResidencyDataProvider.h>
|
||||
#include <dataproviders/IioEnergyMeterDataProvider.h>
|
||||
#include <dataproviders/PowerStatsEnergyConsumer.h>
|
||||
#include <dataproviders/PowerStatsEnergyAttribution.h>
|
||||
#include <dataproviders/PixelStateResidencyDataProvider.h>
|
||||
|
||||
using android::OK;
|
||||
using android::sp;
|
||||
using android::status_t;
|
||||
#include <android-base/logging.h>
|
||||
#include <android-base/properties.h>
|
||||
#include <android/binder_manager.h>
|
||||
#include <android/binder_process.h>
|
||||
#include <log/log.h>
|
||||
|
||||
// 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<PowerStats> p) {
|
||||
std::string prefix = "/sys/devices/platform/19000000.aoc/control/";
|
||||
|
||||
// Add AoC cores (a32, ff1, hf0, and hf1)
|
||||
std::vector<std::pair<uint32_t, std::string>> 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<std::pair<std::string, std::string>> coreIds = {
|
||||
{"AoC-A32", prefix + "a32_"},
|
||||
{"AoC-FF1", prefix + "ff1_"},
|
||||
{"AoC-HF1", prefix + "hf1_"},
|
||||
{"AoC-HF0", prefix + "hf0_"},
|
||||
};
|
||||
std::vector<std::pair<std::string, std::string>> coreStates = {
|
||||
{"DWN", "off"}, {"RET", "retention"}, {"WFI", "wfi"}};
|
||||
service->addStateResidencyDataProvider(new AocStateResidencyDataProvider(coreIds, coreStates));
|
||||
p->addStateResidencyDataProvider(std::make_shared<AocStateResidencyDataProvider>(coreIds,
|
||||
coreStates));
|
||||
|
||||
// Add AoC voltage stats
|
||||
std::vector<std::pair<uint32_t, std::string>> voltageIds = {
|
||||
{service->addPowerEntity("AoC-Voltage", PowerEntityType::SUBSYSTEM),
|
||||
prefix + "voltage_"},
|
||||
std::vector<std::pair<std::string, std::string>> voltageIds = {
|
||||
{"AoC-Voltage", prefix + "voltage_"},
|
||||
};
|
||||
std::vector<std::pair<std::string, std::string>> voltageStates = {{"NOM", "nominal"},
|
||||
{"SUD", "super_underdrive"},
|
||||
{"UUD", "ultra_underdrive"},
|
||||
{"UD", "underdrive"}};
|
||||
service->addStateResidencyDataProvider(
|
||||
new AocStateResidencyDataProvider(voltageIds, voltageStates));
|
||||
p->addStateResidencyDataProvider(
|
||||
std::make_shared<AocStateResidencyDataProvider>(voltageIds, voltageStates));
|
||||
|
||||
// Add AoC monitor mode
|
||||
std::vector<std::pair<uint32_t, std::string>> monitorIds = {
|
||||
{service->addPowerEntity("AoC", PowerEntityType::SUBSYSTEM), prefix + "monitor_"},
|
||||
std::vector<std::pair<std::string, std::string>> monitorIds = {
|
||||
{"AoC", prefix + "monitor_"},
|
||||
};
|
||||
std::vector<std::pair<std::string, std::string>> monitorStates = {
|
||||
{"MON", "mode"},
|
||||
};
|
||||
service->addStateResidencyDataProvider(
|
||||
new AocStateResidencyDataProvider(monitorIds, monitorStates));
|
||||
p->addStateResidencyDataProvider(
|
||||
std::make_shared<AocStateResidencyDataProvider>(monitorIds, monitorStates));
|
||||
}
|
||||
|
||||
void addCpuCStateStats(PowerStats *const service) {
|
||||
// CPU stats are reported in nanoseconds. The transform function
|
||||
// converts nanoseconds to milliseconds.
|
||||
std::function<uint64_t(uint64_t)> 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<PowerStats> p) {
|
||||
// A constant to represent the number of nanoseconds in one millisecond
|
||||
const int NS_TO_MS = 1000000;
|
||||
|
||||
sp<GenericStateResidencyDataProvider> 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<DvfsStateResidencyDataProvider::Config> cfgs;
|
||||
|
||||
void addDvfsStats(PowerStats *const service) {
|
||||
sp<DvfsStateResidencyDataProvider> dvfsSdp = new DvfsStateResidencyDataProvider(
|
||||
"/sys/devices/platform/1742048c.acpm_stats/fvp_stats", NS_TO_MS);
|
||||
|
||||
dvfsSdp->addEntity(service->addPowerEntity("MIF-DVFS", PowerEntityType::SUBSYSTEM), "MIF",
|
||||
{
|
||||
cfgs.push_back({"MIF", {
|
||||
std::make_pair("3172KHz", "3172000"),
|
||||
std::make_pair("2730KHz", "2730000"),
|
||||
std::make_pair("2535KHz", "2535000"),
|
||||
|
@ -148,33 +102,30 @@ void addDvfsStats(PowerStats *const service) {
|
|||
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"),
|
||||
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"),
|
||||
});
|
||||
}});
|
||||
|
||||
dvfsSdp->addEntity(service->addPowerEntity("CL1-DVFS", PowerEntityType::SUBSYSTEM), "CL1",
|
||||
{
|
||||
std::make_pair("2466KHz", "2466000"),
|
||||
std::make_pair("2393KHz", "2393000"),
|
||||
std::make_pair("2348KHz", "2348000"),
|
||||
cfgs.push_back({"CL1", {
|
||||
std::make_pair("2253KHz", "2253000"),
|
||||
std::make_pair("2130KHz", "2130000"),
|
||||
std::make_pair("1999KHz", "1999000"),
|
||||
|
@ -190,137 +141,47 @@ void addDvfsStats(PowerStats *const service) {
|
|||
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"),
|
||||
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"),
|
||||
});
|
||||
}});
|
||||
|
||||
// TODO(sujee): Complete frequency table for TPU.
|
||||
dvfsSdp->addEntity(service->addPowerEntity("TPU-DVFS", PowerEntityType::SUBSYSTEM), "TPU",
|
||||
{
|
||||
cfgs.push_back({"TPU", {
|
||||
std::make_pair("1066MHz", "1066000000"),
|
||||
});
|
||||
}});
|
||||
|
||||
service->addStateResidencyDataProvider(dvfsSdp);
|
||||
p->addStateResidencyDataProvider(std::make_shared<DvfsStateResidencyDataProvider>(
|
||||
"/sys/devices/platform/1742048c.acpm_stats/fvp_stats", NS_TO_MS, cfgs));
|
||||
}
|
||||
|
||||
void addGPUStats(PowerStats *const service) {
|
||||
StateResidencyConfig gpuStateConfig = {
|
||||
.entryCountSupported = true,
|
||||
.entryCountPrefix = "count = ",
|
||||
.totalTimeSupported = true,
|
||||
.totalTimePrefix = "total_time = ",
|
||||
.lastEntrySupported = true,
|
||||
.lastEntryPrefix = "last_entry_time = ",
|
||||
};
|
||||
void addSoC(std::shared_ptr<PowerStats> p) {
|
||||
// A constant to represent the number of nanoseconds in one millisecond.
|
||||
const int NS_TO_MS = 1000000;
|
||||
|
||||
sp<GenericStateResidencyDataProvider> 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<std::pair<std::string, std::string>> nfcStateHeaders = {
|
||||
std::make_pair("IDLE", "Idle mode:"),
|
||||
std::make_pair("ACTIVE", "Active mode:"),
|
||||
std::make_pair("ACTIVE-RW", "Active Reader/Writer mode:"),
|
||||
};
|
||||
|
||||
sp<GenericStateResidencyDataProvider> 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<std::pair<std::string, std::string>> pcieStateHeaders = {
|
||||
std::make_pair("UP", "Link up:"),
|
||||
std::make_pair("DOWN", "Link down:"),
|
||||
};
|
||||
|
||||
// Add PCIe - Modem
|
||||
sp<GenericStateResidencyDataProvider> 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<GenericStateResidencyDataProvider> 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<uint64_t(uint64_t)> 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,55 +212,227 @@ void addSocStats(PowerStats *const service) {
|
|||
.lastEntryTransform = acpmNsToMs,
|
||||
|
||||
};
|
||||
std::vector<std::pair<std::string, std::string>> powerStateHeaders = {
|
||||
const std::vector<std::pair<std::string, std::string>> 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<std::pair<std::string, std::string>> mifReqStateHeaders = {
|
||||
const std::vector<std::pair<std::string, std::string>> mifReqStateHeaders = {
|
||||
std::make_pair("AOC", "AOC"),
|
||||
std::make_pair("GSA", "GSA"),
|
||||
};
|
||||
std::vector<std::pair<std::string, std::string>> slcReqStateHeaders = {
|
||||
const std::vector<std::pair<std::string, std::string>> slcReqStateHeaders = {
|
||||
std::make_pair("AOC", "AOC"),
|
||||
};
|
||||
|
||||
sp<GenericStateResidencyDataProvider> socSdp = new GenericStateResidencyDataProvider(
|
||||
"/sys/devices/platform/1742048c.acpm_stats/soc_stats");
|
||||
std::vector<GenericStateResidencyDataProvider::PowerEntityConfig> 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<GenericStateResidencyDataProvider>(
|
||||
"/sys/devices/platform/1742048c.acpm_stats/soc_stats", cfgs);
|
||||
|
||||
service->addStateResidencyDataProvider(socSdp);
|
||||
p->addStateResidencyDataProvider(socSdp);
|
||||
}
|
||||
|
||||
void addUfsStats(PowerStats *const service) {
|
||||
sp<UfsStateResidencyDataProvider> ufsSdp = new UfsStateResidencyDataProvider(
|
||||
service->addPowerEntity("UFS", PowerEntityType::SUBSYSTEM));
|
||||
service->addStateResidencyDataProvider(ufsSdp);
|
||||
void setEnergyMeter(std::shared_ptr<PowerStats> p) {
|
||||
std::vector<const std::string> deviceNames { "s2mpg10-odpm", "s2mpg11-odpm" };
|
||||
p->setEnergyMeterDataProvider(std::make_unique<IioEnergyMeterDataProvider>(deviceNames, true));
|
||||
}
|
||||
|
||||
void addWifiStats(PowerStats *const service) {
|
||||
sp<GenericStateResidencyDataProvider> wifiSdp =
|
||||
new GenericStateResidencyDataProvider("/sys/wifi/power_stats");
|
||||
void addDisplay(std::shared_ptr<PowerStats> 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<std::string> states = {
|
||||
"Off",
|
||||
"LP: 1440x3040@30",
|
||||
"On: 1440x3040@60",
|
||||
"On: 1440x3040@90",
|
||||
"HBM: 1440x3040@60",
|
||||
"HBM: 1440x3040@90"};
|
||||
|
||||
auto displaySdp =
|
||||
std::make_shared<DisplayStateResidencyDataProvider>("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<PowerStats> 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<PowerStats> p) {
|
||||
// Add gpu energy consumer
|
||||
std::map<std::string, int32_t> 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<PowerStats> 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<uint64_t(uint64_t)> 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<std::pair<std::string, std::string>> powerStateHeaders = {
|
||||
std::make_pair("SLEEP", "SLEEP:"),
|
||||
};
|
||||
|
||||
std::vector<GenericStateResidencyDataProvider::PowerEntityConfig> cfgs;
|
||||
cfgs.emplace_back(generateGenericStateResidencyConfigs(powerStateConfig, powerStateHeaders),
|
||||
"MODEM", "");
|
||||
|
||||
p->addStateResidencyDataProvider(std::make_shared<GenericStateResidencyDataProvider>(
|
||||
"/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<PowerStats> p)
|
||||
{
|
||||
p->addEnergyConsumer(PowerStatsEnergyConsumer::createMeterConsumer(p,
|
||||
EnergyConsumerType::GNSS, "GPS", {"L9S_GNSS_CORE"}));
|
||||
}
|
||||
|
||||
void addNFC(std::shared_ptr<PowerStats> 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<std::pair<std::string, std::string>> nfcStateHeaders = {
|
||||
std::make_pair("IDLE", "Idle mode:"),
|
||||
std::make_pair("ACTIVE", "Active mode:"),
|
||||
std::make_pair("ACTIVE-RW", "Active Reader/Writer mode:"),
|
||||
};
|
||||
|
||||
std::vector<GenericStateResidencyDataProvider::PowerEntityConfig> cfgs;
|
||||
cfgs.emplace_back(generateGenericStateResidencyConfigs(nfcStateConfig, nfcStateHeaders),
|
||||
"NFC", "NFC subsystem");
|
||||
|
||||
auto nfcSdp = std::make_shared<GenericStateResidencyDataProvider>(
|
||||
"/sys/devices/platform/10960000.hsi2c/i2c-3/3-0008/power_stats", cfgs);
|
||||
|
||||
p->addStateResidencyDataProvider(nfcSdp);
|
||||
}
|
||||
|
||||
void addPCIe(std::shared_ptr<PowerStats> 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<std::pair<std::string, std::string>> pcieStateHeaders = {
|
||||
std::make_pair("UP", "Link up:"),
|
||||
std::make_pair("DOWN", "Link down:"),
|
||||
};
|
||||
|
||||
// Add PCIe - Modem
|
||||
const std::vector<GenericStateResidencyDataProvider::PowerEntityConfig> pcieModemCfgs = {
|
||||
{generateGenericStateResidencyConfigs(pcieStateConfig, pcieStateHeaders), "PCIe-Modem",
|
||||
"Version: 1"}
|
||||
};
|
||||
auto pcieModemSdp = std::make_shared<GenericStateResidencyDataProvider>(
|
||||
"/sys/devices/platform/11920000.pcie/power_stats", pcieModemCfgs);
|
||||
p->addStateResidencyDataProvider(pcieModemSdp);
|
||||
|
||||
// Add PCIe - WiFi
|
||||
const std::vector<GenericStateResidencyDataProvider::PowerEntityConfig> pcieWifiCfgs = {
|
||||
{generateGenericStateResidencyConfigs(pcieStateConfig, pcieStateHeaders),
|
||||
"PCIe-WiFi", "Version: 1"}
|
||||
};
|
||||
auto pcieWifiSdp = std::make_shared<GenericStateResidencyDataProvider>(
|
||||
"/sys/devices/platform/14520000.pcie/power_stats", pcieWifiCfgs);
|
||||
p->addStateResidencyDataProvider(pcieWifiSdp);
|
||||
}
|
||||
|
||||
void addWifi(std::shared_ptr<PowerStats> p) {
|
||||
// The transform function converts microseconds to milliseconds.
|
||||
std::function<uint64_t(uint64_t)> usecToMs = [](uint64_t a) { return a / 1000; };
|
||||
StateResidencyConfig stateConfig = {
|
||||
const GenericStateResidencyDataProvider::StateResidencyConfig stateConfig = {
|
||||
.entryCountSupported = true,
|
||||
.entryCountPrefix = "count:",
|
||||
.totalTimeSupported = true,
|
||||
|
@ -409,83 +442,82 @@ void addWifiStats(PowerStats *const service) {
|
|||
.lastEntryPrefix = "last_entry_timestamp_usec:",
|
||||
.lastEntryTransform = usecToMs,
|
||||
};
|
||||
StateResidencyConfig pcieStateConfig = {
|
||||
const GenericStateResidencyDataProvider::StateResidencyConfig pcieStateConfig = {
|
||||
.entryCountSupported = true,
|
||||
.entryCountPrefix = "count:",
|
||||
.totalTimeSupported = true,
|
||||
.totalTimePrefix = "duration_usec:",
|
||||
.totalTimeTransform = usecToMs,
|
||||
.lastEntrySupported = false,
|
||||
};
|
||||
|
||||
std::vector<std::pair<std::string, std::string>> stateHeaders = {
|
||||
const std::vector<std::pair<std::string, std::string>> stateHeaders = {
|
||||
std::make_pair("AWAKE", "AWAKE:"),
|
||||
std::make_pair("ASLEEP", "ASLEEP:"),
|
||||
|
||||
};
|
||||
std::vector<std::pair<std::string, std::string>> 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:"),
|
||||
const std::vector<std::pair<std::string, std::string>> 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:"),
|
||||
};
|
||||
|
||||
wifiSdp->addEntity(
|
||||
service->addPowerEntity("WIFI", PowerEntityType::SUBSYSTEM),
|
||||
PowerEntityConfig(generateGenericStateResidencyConfigs(stateConfig, stateHeaders)));
|
||||
wifiSdp->addEntity(service->addPowerEntity("WIFI-PCIE", PowerEntityType::SUBSYSTEM),
|
||||
PowerEntityConfig(generateGenericStateResidencyConfigs(pcieStateConfig,
|
||||
pcieStateHeaders)));
|
||||
const std::vector<GenericStateResidencyDataProvider::PowerEntityConfig> cfgs = {
|
||||
{generateGenericStateResidencyConfigs(stateConfig, stateHeaders), "WIFI", "WIFI"},
|
||||
{generateGenericStateResidencyConfigs(pcieStateConfig, pcieStateHeaders), "WIFI-PCIE",
|
||||
"WIFI-PCIE"}
|
||||
};
|
||||
|
||||
service->addStateResidencyDataProvider(wifiSdp);
|
||||
auto wifiSdp = std::make_shared<GenericStateResidencyDataProvider>("/sys/wifi/power_stats",
|
||||
cfgs);
|
||||
p->addStateResidencyDataProvider(wifiSdp);
|
||||
}
|
||||
|
||||
int main(int /* argc */, char ** /* argv */) {
|
||||
ALOGI("power.stats service 1.0 is starting.");
|
||||
/**
|
||||
* 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<PowerStats> p) {
|
||||
std::shared_ptr<PixelStateResidencyDataProvider> pixelSdp =
|
||||
ndk::SharedRefBase::make<PixelStateResidencyDataProvider>();
|
||||
|
||||
PowerStats *service = new PowerStats();
|
||||
pixelSdp->addEntity("Bluetooth", {{0, "Idle"}, {1, "Active"}, {2, "Tx"}, {3, "Rx"}});
|
||||
|
||||
// Add rail data provider
|
||||
service->setRailDataProvider(std::make_unique<RailDataProvider>());
|
||||
|
||||
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<AidlStateResidencyDataProvider> 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;
|
||||
pixelSdp->start();
|
||||
p->addStateResidencyDataProvider(pixelSdp);
|
||||
}
|
||||
|
||||
sp<android::ProcessState> ps{android::ProcessState::self()}; // Create non-HW binder threadpool
|
||||
ps->startThreadPool();
|
||||
int main() {
|
||||
LOG(INFO) << "Pixel PowerStats HAL AIDL Service is starting.";
|
||||
|
||||
// Configure the threadpool
|
||||
configureRpcThreadpool(1, true /*callerWillJoin*/);
|
||||
// single thread
|
||||
ABinderProcess_setThreadPoolMaxThreadCount(0);
|
||||
|
||||
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;
|
||||
std::shared_ptr<PowerStats> p = ndk::SharedRefBase::make<PowerStats>();
|
||||
|
||||
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
|
||||
}
|
||||
|
|
|
@ -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 <PowerStatsAidl.h>
|
||||
#include "AocStateResidencyDataProviderAidl.h"
|
||||
#include "DvfsStateResidencyDataProviderAidl.h"
|
||||
#include <dataproviders/DisplayStateResidencyDataProvider.h>
|
||||
#include <dataproviders/GenericStateResidencyDataProvider.h>
|
||||
#include <dataproviders/IioEnergyMeterDataProvider.h>
|
||||
#include <dataproviders/PowerStatsEnergyConsumer.h>
|
||||
#include <dataproviders/PowerStatsEnergyAttribution.h>
|
||||
#include <dataproviders/PixelStateResidencyDataProvider.h>
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include <android-base/properties.h>
|
||||
#include <android/binder_manager.h>
|
||||
#include <android/binder_process.h>
|
||||
#include <log/log.h>
|
||||
|
||||
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<PowerStats> p) {
|
||||
std::string prefix = "/sys/devices/platform/19000000.aoc/control/";
|
||||
|
||||
// Add AoC cores (a32, ff1, hf0, and hf1)
|
||||
std::vector<std::pair<std::string, std::string>> coreIds = {
|
||||
{"AoC-A32", prefix + "a32_"},
|
||||
{"AoC-FF1", prefix + "ff1_"},
|
||||
{"AoC-HF1", prefix + "hf1_"},
|
||||
{"AoC-HF0", prefix + "hf0_"},
|
||||
};
|
||||
std::vector<std::pair<std::string, std::string>> coreStates = {
|
||||
{"DWN", "off"}, {"RET", "retention"}, {"WFI", "wfi"}};
|
||||
p->addStateResidencyDataProvider(std::make_shared<AocStateResidencyDataProvider>(coreIds,
|
||||
coreStates));
|
||||
|
||||
// Add AoC voltage stats
|
||||
std::vector<std::pair<std::string, std::string>> voltageIds = {
|
||||
{"AoC-Voltage", prefix + "voltage_"},
|
||||
};
|
||||
std::vector<std::pair<std::string, std::string>> voltageStates = {{"NOM", "nominal"},
|
||||
{"SUD", "super_underdrive"},
|
||||
{"UUD", "ultra_underdrive"},
|
||||
{"UD", "underdrive"}};
|
||||
p->addStateResidencyDataProvider(
|
||||
std::make_shared<AocStateResidencyDataProvider>(voltageIds, voltageStates));
|
||||
|
||||
// Add AoC monitor mode
|
||||
std::vector<std::pair<std::string, std::string>> monitorIds = {
|
||||
{"AoC", prefix + "monitor_"},
|
||||
};
|
||||
std::vector<std::pair<std::string, std::string>> monitorStates = {
|
||||
{"MON", "mode"},
|
||||
};
|
||||
p->addStateResidencyDataProvider(
|
||||
std::make_shared<AocStateResidencyDataProvider>(monitorIds, monitorStates));
|
||||
}
|
||||
|
||||
void addDvfsStats(std::shared_ptr<PowerStats> p) {
|
||||
// A constant to represent the number of nanoseconds in one millisecond
|
||||
const int NS_TO_MS = 1000000;
|
||||
|
||||
std::vector<DvfsStateResidencyDataProvider::Config> 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<DvfsStateResidencyDataProvider>(
|
||||
"/sys/devices/platform/1742048c.acpm_stats/fvp_stats", NS_TO_MS, cfgs));
|
||||
}
|
||||
|
||||
void addSoC(std::shared_ptr<PowerStats> 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<uint64_t(uint64_t)> 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<std::pair<std::string, std::string>> 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<std::pair<std::string, std::string>> mifReqStateHeaders = {
|
||||
std::make_pair("AOC", "AOC"),
|
||||
std::make_pair("GSA", "GSA"),
|
||||
};
|
||||
const std::vector<std::pair<std::string, std::string>> slcReqStateHeaders = {
|
||||
std::make_pair("AOC", "AOC"),
|
||||
};
|
||||
|
||||
std::vector<GenericStateResidencyDataProvider::PowerEntityConfig> 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<GenericStateResidencyDataProvider>(
|
||||
"/sys/devices/platform/1742048c.acpm_stats/soc_stats", cfgs);
|
||||
|
||||
p->addStateResidencyDataProvider(socSdp);
|
||||
}
|
||||
|
||||
void setEnergyMeter(std::shared_ptr<PowerStats> p) {
|
||||
std::vector<const std::string> deviceNames { "s2mpg10-odpm", "s2mpg11-odpm" };
|
||||
p->setEnergyMeterDataProvider(std::make_unique<IioEnergyMeterDataProvider>(deviceNames, true));
|
||||
}
|
||||
|
||||
void addDisplay(std::shared_ptr<PowerStats> 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<std::string> states = {
|
||||
"Off",
|
||||
"LP: 1440x3040@30",
|
||||
"On: 1440x3040@60",
|
||||
"On: 1440x3040@90",
|
||||
"HBM: 1440x3040@60",
|
||||
"HBM: 1440x3040@90"};
|
||||
|
||||
auto displaySdp =
|
||||
std::make_shared<DisplayStateResidencyDataProvider>("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<PowerStats> 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<PowerStats> p) {
|
||||
// Add gpu energy consumer
|
||||
std::map<std::string, int32_t> 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<PowerStats> 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<uint64_t(uint64_t)> 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<std::pair<std::string, std::string>> powerStateHeaders = {
|
||||
std::make_pair("SLEEP", "SLEEP:"),
|
||||
};
|
||||
|
||||
std::vector<GenericStateResidencyDataProvider::PowerEntityConfig> cfgs;
|
||||
cfgs.emplace_back(generateGenericStateResidencyConfigs(powerStateConfig, powerStateHeaders),
|
||||
"MODEM", "");
|
||||
|
||||
p->addStateResidencyDataProvider(std::make_shared<GenericStateResidencyDataProvider>(
|
||||
"/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<PowerStats> p)
|
||||
{
|
||||
p->addEnergyConsumer(PowerStatsEnergyConsumer::createMeterConsumer(p,
|
||||
EnergyConsumerType::GNSS, "GPS", {"L9S_GNSS_CORE"}));
|
||||
}
|
||||
|
||||
void addNFC(std::shared_ptr<PowerStats> 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<std::pair<std::string, std::string>> nfcStateHeaders = {
|
||||
std::make_pair("IDLE", "Idle mode:"),
|
||||
std::make_pair("ACTIVE", "Active mode:"),
|
||||
std::make_pair("ACTIVE-RW", "Active Reader/Writer mode:"),
|
||||
};
|
||||
|
||||
std::vector<GenericStateResidencyDataProvider::PowerEntityConfig> cfgs;
|
||||
cfgs.emplace_back(generateGenericStateResidencyConfigs(nfcStateConfig, nfcStateHeaders),
|
||||
"NFC", "NFC subsystem");
|
||||
|
||||
auto nfcSdp = std::make_shared<GenericStateResidencyDataProvider>(
|
||||
"/sys/devices/platform/10960000.hsi2c/i2c-3/3-0008/power_stats", cfgs);
|
||||
|
||||
p->addStateResidencyDataProvider(nfcSdp);
|
||||
}
|
||||
|
||||
void addPCIe(std::shared_ptr<PowerStats> 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<std::pair<std::string, std::string>> pcieStateHeaders = {
|
||||
std::make_pair("UP", "Link up:"),
|
||||
std::make_pair("DOWN", "Link down:"),
|
||||
};
|
||||
|
||||
// Add PCIe - Modem
|
||||
const std::vector<GenericStateResidencyDataProvider::PowerEntityConfig> pcieModemCfgs = {
|
||||
{generateGenericStateResidencyConfigs(pcieStateConfig, pcieStateHeaders), "PCIe-Modem",
|
||||
"Version: 1"}
|
||||
};
|
||||
auto pcieModemSdp = std::make_shared<GenericStateResidencyDataProvider>(
|
||||
"/sys/devices/platform/11920000.pcie/power_stats", pcieModemCfgs);
|
||||
p->addStateResidencyDataProvider(pcieModemSdp);
|
||||
|
||||
// Add PCIe - WiFi
|
||||
const std::vector<GenericStateResidencyDataProvider::PowerEntityConfig> pcieWifiCfgs = {
|
||||
{generateGenericStateResidencyConfigs(pcieStateConfig, pcieStateHeaders),
|
||||
"PCIe-WiFi", "Version: 1"}
|
||||
};
|
||||
auto pcieWifiSdp = std::make_shared<GenericStateResidencyDataProvider>(
|
||||
"/sys/devices/platform/14520000.pcie/power_stats", pcieWifiCfgs);
|
||||
p->addStateResidencyDataProvider(pcieWifiSdp);
|
||||
}
|
||||
|
||||
void addWifi(std::shared_ptr<PowerStats> p) {
|
||||
// The transform function converts microseconds to milliseconds.
|
||||
std::function<uint64_t(uint64_t)> 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<std::pair<std::string, std::string>> stateHeaders = {
|
||||
std::make_pair("AWAKE", "AWAKE:"),
|
||||
std::make_pair("ASLEEP", "ASLEEP:"),
|
||||
|
||||
};
|
||||
const std::vector<std::pair<std::string, std::string>> 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<GenericStateResidencyDataProvider::PowerEntityConfig> cfgs = {
|
||||
{generateGenericStateResidencyConfigs(stateConfig, stateHeaders), "WIFI", "WIFI"},
|
||||
{generateGenericStateResidencyConfigs(pcieStateConfig, pcieStateHeaders), "WIFI-PCIE",
|
||||
"WIFI-PCIE"}
|
||||
};
|
||||
|
||||
auto wifiSdp = std::make_shared<GenericStateResidencyDataProvider>("/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<PowerStats> p) {
|
||||
std::shared_ptr<PixelStateResidencyDataProvider> pixelSdp =
|
||||
ndk::SharedRefBase::make<PixelStateResidencyDataProvider>();
|
||||
|
||||
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<PowerStats> p = ndk::SharedRefBase::make<PowerStats>();
|
||||
|
||||
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
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue