/* * Copyright (C) 2024 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 "PowerStatsProvider.h" #include #include #include #include using ::android::hardware::power::stats::IPowerStats; namespace android::media::psh_utils { static auto getPowerStatsService() { return mediautils::getService(); } status_t RailEnergyDataProvider::fill(PowerStats *stat) const { if (stat == nullptr) return BAD_VALUE; auto powerStatsService = getPowerStatsService(); if (powerStatsService == nullptr) { return NO_INIT; } std::unordered_map channelMap; { std::vector<::android::hardware::power::stats::Channel> channels; if (!powerStatsService->getEnergyMeterInfo(&channels).isOk()) { LOG(ERROR) << "unable to get energy meter info"; return INVALID_OPERATION; } for (auto& channel : channels) { channelMap.emplace(channel.id, std::move(channel)); } } std::vector<::android::hardware::power::stats::EnergyMeasurement> measurements; if (!powerStatsService->readEnergyMeter({}, &measurements).isOk()) { LOG(ERROR) << "unable to get energy measurements"; return INVALID_OPERATION; } for (const auto& measurement : measurements) { stat->rail_energy.emplace_back( channelMap.at(measurement.id).subsystem, channelMap.at(measurement.id).name, measurement.energyUWs); } // Sort entries first by subsystem_name, then by rail_name. // Sorting is needed to make interval processing efficient. std::sort(stat->rail_energy.begin(), stat->rail_energy.end(), [](const auto& a, const auto& b) { if (a.subsystem_name != b.subsystem_name) { return a.subsystem_name < b.subsystem_name; } return a.rail_name < b.rail_name; }); return NO_ERROR; } status_t PowerEntityResidencyDataProvider::fill(PowerStats* stat) const { if (stat == nullptr) return BAD_VALUE; auto powerStatsService = getPowerStatsService(); if (powerStatsService == nullptr) { return NO_INIT; } // these are based on entityId std::unordered_map entityNames; std::unordered_map> stateNames; std::vector powerEntityIds; // ids to use { std::vector<::android::hardware::power::stats::PowerEntity> entities; if (!powerStatsService->getPowerEntityInfo(&entities).isOk()) { LOG(ERROR) << __func__ << ": unable to get entity info"; return INVALID_OPERATION; } std::vector powerEntityNames; for (const auto& entity : entities) { std::unordered_map states; for (const auto& state : entity.states) { states.emplace(state.id, state.name); } if (std::find(powerEntityNames.begin(), powerEntityNames.end(), entity.name) != powerEntityNames.end()) { powerEntityIds.emplace_back(entity.id); } entityNames.emplace(entity.id, std::move(entity.name)); stateNames.emplace(entity.id, std::move(states)); } } std::vector<::android::hardware::power::stats::StateResidencyResult> results; if (!powerStatsService->getStateResidency(powerEntityIds, &results).isOk()) { LOG(ERROR) << __func__ << ": Unable to get state residency"; return INVALID_OPERATION; } for (const auto& result : results) { for (const auto& curStateResidency : result.stateResidencyData) { stat->power_entity_state_residency.emplace_back( entityNames.at(result.id), stateNames.at(result.id).at(curStateResidency.id), static_cast(curStateResidency.totalTimeInStateMs), static_cast(curStateResidency.totalStateEntryCount)); } } // Sort entries first by entity_name, then by state_name. // Sorting is needed to make interval processing efficient. std::sort(stat->power_entity_state_residency.begin(), stat->power_entity_state_residency.end(), [](const auto& a, const auto& b) { if (a.entity_name != b.entity_name) { return a.entity_name < b.entity_name; } return a.state_name < b.state_name; }); return NO_ERROR; } } // namespace android::media::psh_utils