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