xref: /aosp_15_r20/hardware/interfaces/power/stats/aidl/default/PowerStats.cpp (revision 4d7e907c777eeecc4c5bd7cf640a754fac206ff7)
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