/* * 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 "PowerStats.h" #include #include namespace aidl { namespace android { namespace hardware { namespace power { namespace stats { void PowerStats::addStateResidencyDataProvider(std::unique_ptr p) { if (!p) { return; } int32_t id = mPowerEntityInfos.size(); auto info = p->getInfo(); size_t index = mStateResidencyDataProviders.size(); mStateResidencyDataProviders.emplace_back(std::move(p)); for (const auto& [entityName, states] : info) { PowerEntity i = { .id = id++, .name = entityName, .states = states, }; mPowerEntityInfos.emplace_back(i); mStateResidencyDataProviderIndex.emplace_back(index); } } void PowerStats::addEnergyConsumer(std::unique_ptr p) { if (!p) { return; } EnergyConsumerType type = p->getType(); std::string name = p->getName(); int32_t count = count_if(mEnergyConsumerInfos.begin(), mEnergyConsumerInfos.end(), [&type](const EnergyConsumer& c) { return type == c.type; }); int32_t id = mEnergyConsumers.size(); mEnergyConsumerInfos.emplace_back( EnergyConsumer{.id = id, .ordinal = count, .type = type, .name = name}); mEnergyConsumers.emplace_back(std::move(p)); } void PowerStats::setEnergyMeter(std::unique_ptr p) { mEnergyMeter = std::move(p); } ndk::ScopedAStatus PowerStats::getPowerEntityInfo(std::vector* _aidl_return) { *_aidl_return = mPowerEntityInfos; return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus PowerStats::getStateResidency(const std::vector& in_powerEntityIds, std::vector* _aidl_return) { if (mPowerEntityInfos.empty()) { return ndk::ScopedAStatus::ok(); } // If in_powerEntityIds is empty then return data for all supported entities if (in_powerEntityIds.empty()) { std::vector v(mPowerEntityInfos.size()); std::iota(std::begin(v), std::end(v), 0); return getStateResidency(v, _aidl_return); } std::unordered_map> stateResidencies; for (const int32_t id : in_powerEntityIds) { // check for invalid ids if (id < 0 || id >= mPowerEntityInfos.size()) { return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_ILLEGAL_ARGUMENT)); } // Check to see if we already have data for the given id std::string powerEntityName = mPowerEntityInfos[id].name; if (stateResidencies.find(powerEntityName) == stateResidencies.end()) { mStateResidencyDataProviders.at(mStateResidencyDataProviderIndex.at(id)) ->getStateResidencies(&stateResidencies); } // Append results if we have them auto stateResidency = stateResidencies.find(powerEntityName); if (stateResidency != stateResidencies.end()) { StateResidencyResult res = { .id = id, .stateResidencyData = stateResidency->second, }; _aidl_return->emplace_back(res); } else { // Failed to get results for the given id. LOG(ERROR) << "Failed to get results for " << powerEntityName; } } return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus PowerStats::getEnergyConsumerInfo(std::vector* _aidl_return) { *_aidl_return = mEnergyConsumerInfos; return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus PowerStats::getEnergyConsumed(const std::vector& in_energyConsumerIds, std::vector* _aidl_return) { if (mEnergyConsumers.empty()) { return ndk::ScopedAStatus::ok(); } // If in_powerEntityIds is empty then return data for all supported energy consumers if (in_energyConsumerIds.empty()) { std::vector v(mEnergyConsumerInfos.size()); std::iota(std::begin(v), std::end(v), 0); return getEnergyConsumed(v, _aidl_return); } for (const auto id : in_energyConsumerIds) { // check for invalid ids if (id < 0 || id >= mEnergyConsumers.size()) { return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_ILLEGAL_ARGUMENT)); } auto optionalResult = mEnergyConsumers[id]->getEnergyConsumed(); if (optionalResult) { EnergyConsumerResult result = optionalResult.value(); result.id = id; _aidl_return->emplace_back(result); } else { // Failed to get results for the given id. LOG(ERROR) << "Failed to get results for " << mEnergyConsumerInfos[id].name; } } return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus PowerStats::getEnergyMeterInfo(std::vector* _aidl_return) { if (!mEnergyMeter) { return ndk::ScopedAStatus::ok(); } return mEnergyMeter->getEnergyMeterInfo(_aidl_return); } ndk::ScopedAStatus PowerStats::readEnergyMeter(const std::vector& in_channelIds, std::vector* _aidl_return) { if (!mEnergyMeter) { return ndk::ScopedAStatus::ok(); } return mEnergyMeter->readEnergyMeter(in_channelIds, _aidl_return); } } // namespace stats } // namespace power } // namespace hardware } // namespace android } // namespace aidl