1*4d7e907cSAndroid Build Coastguard Worker /*
2*4d7e907cSAndroid Build Coastguard Worker * Copyright (C) 2020 The Android Open Source Project
3*4d7e907cSAndroid Build Coastguard Worker *
4*4d7e907cSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*4d7e907cSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*4d7e907cSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*4d7e907cSAndroid Build Coastguard Worker *
8*4d7e907cSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*4d7e907cSAndroid Build Coastguard Worker *
10*4d7e907cSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*4d7e907cSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*4d7e907cSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*4d7e907cSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*4d7e907cSAndroid Build Coastguard Worker * limitations under the License.
15*4d7e907cSAndroid Build Coastguard Worker */
16*4d7e907cSAndroid Build Coastguard Worker
17*4d7e907cSAndroid Build Coastguard Worker #include "PowerStats.h"
18*4d7e907cSAndroid Build Coastguard Worker
19*4d7e907cSAndroid Build Coastguard Worker #include <android-base/logging.h>
20*4d7e907cSAndroid Build Coastguard Worker
21*4d7e907cSAndroid Build Coastguard Worker #include <numeric>
22*4d7e907cSAndroid Build Coastguard Worker
23*4d7e907cSAndroid Build Coastguard Worker namespace aidl {
24*4d7e907cSAndroid Build Coastguard Worker namespace android {
25*4d7e907cSAndroid Build Coastguard Worker namespace hardware {
26*4d7e907cSAndroid Build Coastguard Worker namespace power {
27*4d7e907cSAndroid Build Coastguard Worker namespace stats {
28*4d7e907cSAndroid Build Coastguard Worker
addStateResidencyDataProvider(std::unique_ptr<IStateResidencyDataProvider> p)29*4d7e907cSAndroid Build Coastguard Worker void PowerStats::addStateResidencyDataProvider(std::unique_ptr<IStateResidencyDataProvider> p) {
30*4d7e907cSAndroid Build Coastguard Worker if (!p) {
31*4d7e907cSAndroid Build Coastguard Worker return;
32*4d7e907cSAndroid Build Coastguard Worker }
33*4d7e907cSAndroid Build Coastguard Worker
34*4d7e907cSAndroid Build Coastguard Worker int32_t id = mPowerEntityInfos.size();
35*4d7e907cSAndroid Build Coastguard Worker auto info = p->getInfo();
36*4d7e907cSAndroid Build Coastguard Worker
37*4d7e907cSAndroid Build Coastguard Worker size_t index = mStateResidencyDataProviders.size();
38*4d7e907cSAndroid Build Coastguard Worker mStateResidencyDataProviders.emplace_back(std::move(p));
39*4d7e907cSAndroid Build Coastguard Worker
40*4d7e907cSAndroid Build Coastguard Worker for (const auto& [entityName, states] : info) {
41*4d7e907cSAndroid Build Coastguard Worker PowerEntity i = {
42*4d7e907cSAndroid Build Coastguard Worker .id = id++,
43*4d7e907cSAndroid Build Coastguard Worker .name = entityName,
44*4d7e907cSAndroid Build Coastguard Worker .states = states,
45*4d7e907cSAndroid Build Coastguard Worker };
46*4d7e907cSAndroid Build Coastguard Worker mPowerEntityInfos.emplace_back(i);
47*4d7e907cSAndroid Build Coastguard Worker mStateResidencyDataProviderIndex.emplace_back(index);
48*4d7e907cSAndroid Build Coastguard Worker }
49*4d7e907cSAndroid Build Coastguard Worker }
50*4d7e907cSAndroid Build Coastguard Worker
addEnergyConsumer(std::unique_ptr<IEnergyConsumer> p)51*4d7e907cSAndroid Build Coastguard Worker void PowerStats::addEnergyConsumer(std::unique_ptr<IEnergyConsumer> p) {
52*4d7e907cSAndroid Build Coastguard Worker if (!p) {
53*4d7e907cSAndroid Build Coastguard Worker return;
54*4d7e907cSAndroid Build Coastguard Worker }
55*4d7e907cSAndroid Build Coastguard Worker
56*4d7e907cSAndroid Build Coastguard Worker EnergyConsumerType type = p->getType();
57*4d7e907cSAndroid Build Coastguard Worker std::string name = p->getName();
58*4d7e907cSAndroid Build Coastguard Worker int32_t count = count_if(mEnergyConsumerInfos.begin(), mEnergyConsumerInfos.end(),
59*4d7e907cSAndroid Build Coastguard Worker [&type](const EnergyConsumer& c) { return type == c.type; });
60*4d7e907cSAndroid Build Coastguard Worker int32_t id = mEnergyConsumers.size();
61*4d7e907cSAndroid Build Coastguard Worker mEnergyConsumerInfos.emplace_back(
62*4d7e907cSAndroid Build Coastguard Worker EnergyConsumer{.id = id, .ordinal = count, .type = type, .name = name});
63*4d7e907cSAndroid Build Coastguard Worker mEnergyConsumers.emplace_back(std::move(p));
64*4d7e907cSAndroid Build Coastguard Worker }
65*4d7e907cSAndroid Build Coastguard Worker
setEnergyMeter(std::unique_ptr<IEnergyMeter> p)66*4d7e907cSAndroid Build Coastguard Worker void PowerStats::setEnergyMeter(std::unique_ptr<IEnergyMeter> p) {
67*4d7e907cSAndroid Build Coastguard Worker mEnergyMeter = std::move(p);
68*4d7e907cSAndroid Build Coastguard Worker }
69*4d7e907cSAndroid Build Coastguard Worker
getPowerEntityInfo(std::vector<PowerEntity> * _aidl_return)70*4d7e907cSAndroid Build Coastguard Worker ndk::ScopedAStatus PowerStats::getPowerEntityInfo(std::vector<PowerEntity>* _aidl_return) {
71*4d7e907cSAndroid Build Coastguard Worker *_aidl_return = mPowerEntityInfos;
72*4d7e907cSAndroid Build Coastguard Worker return ndk::ScopedAStatus::ok();
73*4d7e907cSAndroid Build Coastguard Worker }
74*4d7e907cSAndroid Build Coastguard Worker
getStateResidency(const std::vector<int32_t> & in_powerEntityIds,std::vector<StateResidencyResult> * _aidl_return)75*4d7e907cSAndroid Build Coastguard Worker ndk::ScopedAStatus PowerStats::getStateResidency(const std::vector<int32_t>& in_powerEntityIds,
76*4d7e907cSAndroid Build Coastguard Worker std::vector<StateResidencyResult>* _aidl_return) {
77*4d7e907cSAndroid Build Coastguard Worker if (mPowerEntityInfos.empty()) {
78*4d7e907cSAndroid Build Coastguard Worker return ndk::ScopedAStatus::ok();
79*4d7e907cSAndroid Build Coastguard Worker }
80*4d7e907cSAndroid Build Coastguard Worker
81*4d7e907cSAndroid Build Coastguard Worker // If in_powerEntityIds is empty then return data for all supported entities
82*4d7e907cSAndroid Build Coastguard Worker if (in_powerEntityIds.empty()) {
83*4d7e907cSAndroid Build Coastguard Worker std::vector<int32_t> v(mPowerEntityInfos.size());
84*4d7e907cSAndroid Build Coastguard Worker std::iota(std::begin(v), std::end(v), 0);
85*4d7e907cSAndroid Build Coastguard Worker return getStateResidency(v, _aidl_return);
86*4d7e907cSAndroid Build Coastguard Worker }
87*4d7e907cSAndroid Build Coastguard Worker
88*4d7e907cSAndroid Build Coastguard Worker std::unordered_map<std::string, std::vector<StateResidency>> stateResidencies;
89*4d7e907cSAndroid Build Coastguard Worker
90*4d7e907cSAndroid Build Coastguard Worker for (const int32_t id : in_powerEntityIds) {
91*4d7e907cSAndroid Build Coastguard Worker // check for invalid ids
92*4d7e907cSAndroid Build Coastguard Worker if (id < 0 || id >= mPowerEntityInfos.size()) {
93*4d7e907cSAndroid Build Coastguard Worker return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_ILLEGAL_ARGUMENT));
94*4d7e907cSAndroid Build Coastguard Worker }
95*4d7e907cSAndroid Build Coastguard Worker
96*4d7e907cSAndroid Build Coastguard Worker // Check to see if we already have data for the given id
97*4d7e907cSAndroid Build Coastguard Worker std::string powerEntityName = mPowerEntityInfos[id].name;
98*4d7e907cSAndroid Build Coastguard Worker if (stateResidencies.find(powerEntityName) == stateResidencies.end()) {
99*4d7e907cSAndroid Build Coastguard Worker mStateResidencyDataProviders.at(mStateResidencyDataProviderIndex.at(id))
100*4d7e907cSAndroid Build Coastguard Worker ->getStateResidencies(&stateResidencies);
101*4d7e907cSAndroid Build Coastguard Worker }
102*4d7e907cSAndroid Build Coastguard Worker
103*4d7e907cSAndroid Build Coastguard Worker // Append results if we have them
104*4d7e907cSAndroid Build Coastguard Worker auto stateResidency = stateResidencies.find(powerEntityName);
105*4d7e907cSAndroid Build Coastguard Worker if (stateResidency != stateResidencies.end()) {
106*4d7e907cSAndroid Build Coastguard Worker StateResidencyResult res = {
107*4d7e907cSAndroid Build Coastguard Worker .id = id,
108*4d7e907cSAndroid Build Coastguard Worker .stateResidencyData = stateResidency->second,
109*4d7e907cSAndroid Build Coastguard Worker };
110*4d7e907cSAndroid Build Coastguard Worker _aidl_return->emplace_back(res);
111*4d7e907cSAndroid Build Coastguard Worker } else {
112*4d7e907cSAndroid Build Coastguard Worker // Failed to get results for the given id.
113*4d7e907cSAndroid Build Coastguard Worker LOG(ERROR) << "Failed to get results for " << powerEntityName;
114*4d7e907cSAndroid Build Coastguard Worker }
115*4d7e907cSAndroid Build Coastguard Worker }
116*4d7e907cSAndroid Build Coastguard Worker
117*4d7e907cSAndroid Build Coastguard Worker return ndk::ScopedAStatus::ok();
118*4d7e907cSAndroid Build Coastguard Worker }
119*4d7e907cSAndroid Build Coastguard Worker
getEnergyConsumerInfo(std::vector<EnergyConsumer> * _aidl_return)120*4d7e907cSAndroid Build Coastguard Worker ndk::ScopedAStatus PowerStats::getEnergyConsumerInfo(std::vector<EnergyConsumer>* _aidl_return) {
121*4d7e907cSAndroid Build Coastguard Worker *_aidl_return = mEnergyConsumerInfos;
122*4d7e907cSAndroid Build Coastguard Worker return ndk::ScopedAStatus::ok();
123*4d7e907cSAndroid Build Coastguard Worker }
124*4d7e907cSAndroid Build Coastguard Worker
getEnergyConsumed(const std::vector<int32_t> & in_energyConsumerIds,std::vector<EnergyConsumerResult> * _aidl_return)125*4d7e907cSAndroid Build Coastguard Worker ndk::ScopedAStatus PowerStats::getEnergyConsumed(const std::vector<int32_t>& in_energyConsumerIds,
126*4d7e907cSAndroid Build Coastguard Worker std::vector<EnergyConsumerResult>* _aidl_return) {
127*4d7e907cSAndroid Build Coastguard Worker if (mEnergyConsumers.empty()) {
128*4d7e907cSAndroid Build Coastguard Worker return ndk::ScopedAStatus::ok();
129*4d7e907cSAndroid Build Coastguard Worker }
130*4d7e907cSAndroid Build Coastguard Worker
131*4d7e907cSAndroid Build Coastguard Worker // If in_powerEntityIds is empty then return data for all supported energy consumers
132*4d7e907cSAndroid Build Coastguard Worker if (in_energyConsumerIds.empty()) {
133*4d7e907cSAndroid Build Coastguard Worker std::vector<int32_t> v(mEnergyConsumerInfos.size());
134*4d7e907cSAndroid Build Coastguard Worker std::iota(std::begin(v), std::end(v), 0);
135*4d7e907cSAndroid Build Coastguard Worker return getEnergyConsumed(v, _aidl_return);
136*4d7e907cSAndroid Build Coastguard Worker }
137*4d7e907cSAndroid Build Coastguard Worker
138*4d7e907cSAndroid Build Coastguard Worker for (const auto id : in_energyConsumerIds) {
139*4d7e907cSAndroid Build Coastguard Worker // check for invalid ids
140*4d7e907cSAndroid Build Coastguard Worker if (id < 0 || id >= mEnergyConsumers.size()) {
141*4d7e907cSAndroid Build Coastguard Worker return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_ILLEGAL_ARGUMENT));
142*4d7e907cSAndroid Build Coastguard Worker }
143*4d7e907cSAndroid Build Coastguard Worker
144*4d7e907cSAndroid Build Coastguard Worker auto optionalResult = mEnergyConsumers[id]->getEnergyConsumed();
145*4d7e907cSAndroid Build Coastguard Worker if (optionalResult) {
146*4d7e907cSAndroid Build Coastguard Worker EnergyConsumerResult result = optionalResult.value();
147*4d7e907cSAndroid Build Coastguard Worker result.id = id;
148*4d7e907cSAndroid Build Coastguard Worker _aidl_return->emplace_back(result);
149*4d7e907cSAndroid Build Coastguard Worker } else {
150*4d7e907cSAndroid Build Coastguard Worker // Failed to get results for the given id.
151*4d7e907cSAndroid Build Coastguard Worker LOG(ERROR) << "Failed to get results for " << mEnergyConsumerInfos[id].name;
152*4d7e907cSAndroid Build Coastguard Worker }
153*4d7e907cSAndroid Build Coastguard Worker }
154*4d7e907cSAndroid Build Coastguard Worker
155*4d7e907cSAndroid Build Coastguard Worker return ndk::ScopedAStatus::ok();
156*4d7e907cSAndroid Build Coastguard Worker }
157*4d7e907cSAndroid Build Coastguard Worker
getEnergyMeterInfo(std::vector<Channel> * _aidl_return)158*4d7e907cSAndroid Build Coastguard Worker ndk::ScopedAStatus PowerStats::getEnergyMeterInfo(std::vector<Channel>* _aidl_return) {
159*4d7e907cSAndroid Build Coastguard Worker if (!mEnergyMeter) {
160*4d7e907cSAndroid Build Coastguard Worker return ndk::ScopedAStatus::ok();
161*4d7e907cSAndroid Build Coastguard Worker }
162*4d7e907cSAndroid Build Coastguard Worker
163*4d7e907cSAndroid Build Coastguard Worker return mEnergyMeter->getEnergyMeterInfo(_aidl_return);
164*4d7e907cSAndroid Build Coastguard Worker }
165*4d7e907cSAndroid Build Coastguard Worker
readEnergyMeter(const std::vector<int32_t> & in_channelIds,std::vector<EnergyMeasurement> * _aidl_return)166*4d7e907cSAndroid Build Coastguard Worker ndk::ScopedAStatus PowerStats::readEnergyMeter(const std::vector<int32_t>& in_channelIds,
167*4d7e907cSAndroid Build Coastguard Worker std::vector<EnergyMeasurement>* _aidl_return) {
168*4d7e907cSAndroid Build Coastguard Worker if (!mEnergyMeter) {
169*4d7e907cSAndroid Build Coastguard Worker return ndk::ScopedAStatus::ok();
170*4d7e907cSAndroid Build Coastguard Worker }
171*4d7e907cSAndroid Build Coastguard Worker
172*4d7e907cSAndroid Build Coastguard Worker return mEnergyMeter->readEnergyMeter(in_channelIds, _aidl_return);
173*4d7e907cSAndroid Build Coastguard Worker }
174*4d7e907cSAndroid Build Coastguard Worker
175*4d7e907cSAndroid Build Coastguard Worker } // namespace stats
176*4d7e907cSAndroid Build Coastguard Worker } // namespace power
177*4d7e907cSAndroid Build Coastguard Worker } // namespace hardware
178*4d7e907cSAndroid Build Coastguard Worker } // namespace android
179*4d7e907cSAndroid Build Coastguard Worker } // namespace aidl
180