blob: 033bf1a3a443f94df82926922c37ed869d7fd788 [file] [log] [blame]
Benjamin Schwartz40492c22020-08-31 11:55:55 -07001/*
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#include <aidl/Gtest.h>
17#include <aidl/Vintf.h>
18
Benjamin Schwartz71c6f8b2020-10-05 15:44:19 -070019#include <aidl/android/hardware/power/stats/IPowerStats.h>
Benjamin Schwartz40492c22020-08-31 11:55:55 -070020#include <android-base/properties.h>
21#include <android/binder_manager.h>
22#include <android/binder_process.h>
23
Benjamin Schwartz5e3298c2021-01-26 10:15:23 -080024#include <algorithm>
25#include <iterator>
26#include <random>
27#include <unordered_map>
28
Benjamin Schwartz8ddf2982020-12-21 14:57:45 -080029using aidl::android::hardware::power::stats::Channel;
Benjamin Schwartz5e3298c2021-01-26 10:15:23 -080030using aidl::android::hardware::power::stats::EnergyConsumer;
31using aidl::android::hardware::power::stats::EnergyConsumerAttribution;
32using aidl::android::hardware::power::stats::EnergyConsumerResult;
33using aidl::android::hardware::power::stats::EnergyConsumerType;
Benjamin Schwartz71c6f8b2020-10-05 15:44:19 -070034using aidl::android::hardware::power::stats::EnergyMeasurement;
35using aidl::android::hardware::power::stats::IPowerStats;
Benjamin Schwartz8ddf2982020-12-21 14:57:45 -080036using aidl::android::hardware::power::stats::PowerEntity;
Benjamin Schwartz5e3298c2021-01-26 10:15:23 -080037using aidl::android::hardware::power::stats::State;
38using aidl::android::hardware::power::stats::StateResidency;
Benjamin Schwartz71c6f8b2020-10-05 15:44:19 -070039using aidl::android::hardware::power::stats::StateResidencyResult;
Benjamin Schwartz42408272020-09-28 14:33:59 -070040
Benjamin Schwartz40492c22020-08-31 11:55:55 -070041using ndk::SpAIBinder;
42
43class PowerStatsAidl : public testing::TestWithParam<std::string> {
44 public:
45 virtual void SetUp() override {
46 powerstats = IPowerStats::fromBinder(
47 SpAIBinder(AServiceManager_waitForService(GetParam().c_str())));
48 ASSERT_NE(nullptr, powerstats.get());
49 }
50
Benjamin Schwartz5e3298c2021-01-26 10:15:23 -080051 template <typename T>
52 std::vector<T> getRandomSubset(std::vector<T> const& collection);
53
54 void testNameValid(const std::string& name);
55
56 template <typename T, typename S>
57 void testUnique(std::vector<T> const& collection, S T::*field);
58
59 template <typename T, typename S, typename R>
60 void testMatching(std::vector<T> const& c1, R T::*f1, std::vector<S> const& c2, R S::*f2);
61
Benjamin Schwartz40492c22020-08-31 11:55:55 -070062 std::shared_ptr<IPowerStats> powerstats;
63};
64
Benjamin Schwartz5e3298c2021-01-26 10:15:23 -080065// Returns a random subset from a collection
66template <typename T>
67std::vector<T> PowerStatsAidl::getRandomSubset(std::vector<T> const& collection) {
68 if (collection.empty()) {
69 return {};
70 }
71
72 std::vector<T> selected;
73 std::sample(collection.begin(), collection.end(), std::back_inserter(selected),
74 rand() % collection.size() + 1, std::mt19937{std::random_device{}()});
75
76 return selected;
77}
78
79// Tests whether a name is valid
80void PowerStatsAidl::testNameValid(const std::string& name) {
81 EXPECT_NE(name, "");
82}
83
84// Tests whether the fields in a given collection are unique
85template <typename T, typename S>
86void PowerStatsAidl::testUnique(std::vector<T> const& collection, S T::*field) {
87 std::set<S> cSet;
88 for (auto const& elem : collection) {
89 EXPECT_TRUE(cSet.insert(elem.*field).second);
90 }
91}
92
93template <typename T, typename S, typename R>
94void PowerStatsAidl::testMatching(std::vector<T> const& c1, R T::*f1, std::vector<S> const& c2,
95 R S::*f2) {
96 std::set<R> c1fields, c2fields;
97 for (auto elem : c1) {
98 c1fields.insert(elem.*f1);
99 }
100
101 for (auto elem : c2) {
102 c2fields.insert(elem.*f2);
103 }
104
105 EXPECT_EQ(c1fields, c2fields);
Benjamin Schwartz40492c22020-08-31 11:55:55 -0700106}
107
Benjamin Schwartzc4529fb2020-09-01 11:57:53 -0700108// Each PowerEntity must have a valid name
109TEST_P(PowerStatsAidl, ValidatePowerEntityNames) {
Benjamin Schwartz8ddf2982020-12-21 14:57:45 -0800110 std::vector<PowerEntity> infos;
Benjamin Schwartzc4529fb2020-09-01 11:57:53 -0700111 ASSERT_TRUE(powerstats->getPowerEntityInfo(&infos).isOk());
112
113 for (auto info : infos) {
Benjamin Schwartz5e3298c2021-01-26 10:15:23 -0800114 testNameValid(info.name);
Benjamin Schwartzc4529fb2020-09-01 11:57:53 -0700115 }
Benjamin Schwartz40492c22020-08-31 11:55:55 -0700116}
117
Benjamin Schwartzc4529fb2020-09-01 11:57:53 -0700118// Each power entity must have a unique name
119TEST_P(PowerStatsAidl, ValidatePowerEntityUniqueNames) {
Benjamin Schwartz5e3298c2021-01-26 10:15:23 -0800120 std::vector<PowerEntity> entities;
121 ASSERT_TRUE(powerstats->getPowerEntityInfo(&entities).isOk());
Benjamin Schwartzc4529fb2020-09-01 11:57:53 -0700122
Benjamin Schwartz5e3298c2021-01-26 10:15:23 -0800123 testUnique(entities, &PowerEntity::name);
Benjamin Schwartzc4529fb2020-09-01 11:57:53 -0700124}
125
126// Each PowerEntity must have a unique ID
127TEST_P(PowerStatsAidl, ValidatePowerEntityIds) {
Benjamin Schwartz5e3298c2021-01-26 10:15:23 -0800128 std::vector<PowerEntity> entities;
129 ASSERT_TRUE(powerstats->getPowerEntityInfo(&entities).isOk());
Benjamin Schwartzc4529fb2020-09-01 11:57:53 -0700130
Benjamin Schwartz5e3298c2021-01-26 10:15:23 -0800131 testUnique(entities, &PowerEntity::id);
132}
133
134// Each power entity must have at least one state
135TEST_P(PowerStatsAidl, ValidateStateSize) {
136 std::vector<PowerEntity> entities;
137 ASSERT_TRUE(powerstats->getPowerEntityInfo(&entities).isOk());
138
139 for (auto entity : entities) {
140 EXPECT_GT(entity.states.size(), 0);
Benjamin Schwartzc4529fb2020-09-01 11:57:53 -0700141 }
142}
143
144// Each state must have a valid name
145TEST_P(PowerStatsAidl, ValidateStateNames) {
Benjamin Schwartz5e3298c2021-01-26 10:15:23 -0800146 std::vector<PowerEntity> entities;
147 ASSERT_TRUE(powerstats->getPowerEntityInfo(&entities).isOk());
Benjamin Schwartzc4529fb2020-09-01 11:57:53 -0700148
Benjamin Schwartz5e3298c2021-01-26 10:15:23 -0800149 for (auto entity : entities) {
150 for (auto state : entity.states) {
151 testNameValid(state.name);
Benjamin Schwartzc4529fb2020-09-01 11:57:53 -0700152 }
153 }
154}
155
156// Each state must have a name that is unique to the given PowerEntity
157TEST_P(PowerStatsAidl, ValidateStateUniqueNames) {
Benjamin Schwartz5e3298c2021-01-26 10:15:23 -0800158 std::vector<PowerEntity> entities;
159 ASSERT_TRUE(powerstats->getPowerEntityInfo(&entities).isOk());
Benjamin Schwartzc4529fb2020-09-01 11:57:53 -0700160
Benjamin Schwartz5e3298c2021-01-26 10:15:23 -0800161 for (auto entity : entities) {
162 testUnique(entity.states, &State::name);
Benjamin Schwartzc4529fb2020-09-01 11:57:53 -0700163 }
164}
165
166// Each state must have an ID that is unique to the given PowerEntity
167TEST_P(PowerStatsAidl, ValidateStateUniqueIds) {
Benjamin Schwartz5e3298c2021-01-26 10:15:23 -0800168 std::vector<PowerEntity> entities;
169 ASSERT_TRUE(powerstats->getPowerEntityInfo(&entities).isOk());
Benjamin Schwartzc4529fb2020-09-01 11:57:53 -0700170
Benjamin Schwartz5e3298c2021-01-26 10:15:23 -0800171 for (auto entity : entities) {
172 testUnique(entity.states, &State::id);
Benjamin Schwartzc4529fb2020-09-01 11:57:53 -0700173 }
Benjamin Schwartz40492c22020-08-31 11:55:55 -0700174}
175
Benjamin Schwartz5e3298c2021-01-26 10:15:23 -0800176// State residency must return a valid status
Benjamin Schwartz53456242020-10-03 12:54:35 -0700177TEST_P(PowerStatsAidl, TestGetStateResidency) {
178 std::vector<StateResidencyResult> results;
179 ASSERT_TRUE(powerstats->getStateResidency({}, &results).isOk());
Benjamin Schwartz40492c22020-08-31 11:55:55 -0700180}
181
Benjamin Schwartz5e3298c2021-01-26 10:15:23 -0800182// State residency must return all results
183TEST_P(PowerStatsAidl, TestGetStateResidencyAllResults) {
184 std::vector<PowerEntity> entities;
185 ASSERT_TRUE(powerstats->getPowerEntityInfo(&entities).isOk());
186
187 std::vector<StateResidencyResult> results;
188 ASSERT_TRUE(powerstats->getStateResidency({}, &results).isOk());
189
190 testMatching(entities, &PowerEntity::id, results, &StateResidencyResult::id);
191}
192
193// Each result must contain all state residencies
194TEST_P(PowerStatsAidl, TestGetStateResidencyAllStateResidencies) {
195 std::vector<PowerEntity> entities;
196 ASSERT_TRUE(powerstats->getPowerEntityInfo(&entities).isOk());
197
198 std::vector<StateResidencyResult> results;
199 ASSERT_TRUE(powerstats->getStateResidency({}, &results).isOk());
200
201 for (auto entity : entities) {
202 auto it = std::find_if(results.begin(), results.end(),
203 [&entity](const auto& x) { return x.id == entity.id; });
204 ASSERT_NE(it, results.end());
205
206 testMatching(entity.states, &State::id, it->stateResidencyData, &StateResidency::id);
207 }
208}
209
210// State residency must return results for each requested power entity
211TEST_P(PowerStatsAidl, TestGetStateResidencySelectedResults) {
212 std::vector<PowerEntity> entities;
213 ASSERT_TRUE(powerstats->getPowerEntityInfo(&entities).isOk());
214 if (entities.empty()) {
215 return;
216 }
217
218 std::vector<PowerEntity> selectedEntities = getRandomSubset(entities);
219 std::vector<int32_t> selectedIds;
220 for (auto const& entity : selectedEntities) {
221 selectedIds.push_back(entity.id);
222 }
223
224 std::vector<StateResidencyResult> selectedResults;
225 ASSERT_TRUE(powerstats->getStateResidency(selectedIds, &selectedResults).isOk());
226
227 testMatching(selectedEntities, &PowerEntity::id, selectedResults, &StateResidencyResult::id);
228}
229
230// Energy meter info must return a valid status
Benjamin Schwartz42408272020-09-28 14:33:59 -0700231TEST_P(PowerStatsAidl, TestGetEnergyMeterInfo) {
Benjamin Schwartz8ddf2982020-12-21 14:57:45 -0800232 std::vector<Channel> info;
Benjamin Schwartz42408272020-09-28 14:33:59 -0700233 ASSERT_TRUE(powerstats->getEnergyMeterInfo(&info).isOk());
Benjamin Schwartz40492c22020-08-31 11:55:55 -0700234}
235
Benjamin Schwartz5e3298c2021-01-26 10:15:23 -0800236// Each channel must have a valid name and subsystem
237TEST_P(PowerStatsAidl, ValidateChannelNames) {
238 std::vector<Channel> channels;
239 ASSERT_TRUE(powerstats->getEnergyMeterInfo(&channels).isOk());
240 for (auto channel : channels) {
241 testNameValid(channel.name);
242 testNameValid(channel.subsystem);
243 }
244}
245
246// Each channel must have a unique name
247TEST_P(PowerStatsAidl, ValidateChannelUniqueNames) {
248 std::vector<Channel> channels;
249 ASSERT_TRUE(powerstats->getEnergyMeterInfo(&channels).isOk());
250
251 testUnique(channels, &Channel::name);
252}
253
254// Each channel must have a unique ID
255TEST_P(PowerStatsAidl, ValidateChannelUniqueIds) {
256 std::vector<Channel> channels;
257 ASSERT_TRUE(powerstats->getEnergyMeterInfo(&channels).isOk());
258
259 testUnique(channels, &Channel::id);
260}
261
262// Reading energy meter must return a valid status
263TEST_P(PowerStatsAidl, TestReadEnergyMeter) {
264 std::vector<EnergyMeasurement> data;
265 ASSERT_TRUE(powerstats->readEnergyMeters({}, &data).isOk());
266}
267
268// Reading energy meter must return results for all available channels
269TEST_P(PowerStatsAidl, TestGetAllEnergyMeasurements) {
270 std::vector<Channel> channels;
271 ASSERT_TRUE(powerstats->getEnergyMeterInfo(&channels).isOk());
272
273 std::vector<EnergyMeasurement> measurements;
274 ASSERT_TRUE(powerstats->readEnergyMeters({}, &measurements).isOk());
275
276 testMatching(channels, &Channel::id, measurements, &EnergyMeasurement::id);
277}
278
279// Reading energy must must return results for each selected channel
280TEST_P(PowerStatsAidl, TestGetSelectedEnergyMeasurements) {
281 std::vector<Channel> channels;
282 ASSERT_TRUE(powerstats->getEnergyMeterInfo(&channels).isOk());
283 if (channels.empty()) {
284 return;
285 }
286
287 std::vector<Channel> selectedChannels = getRandomSubset(channels);
288 std::vector<int32_t> selectedIds;
289 for (auto const& channel : selectedChannels) {
290 selectedIds.push_back(channel.id);
291 }
292
293 std::vector<EnergyMeasurement> selectedMeasurements;
294 ASSERT_TRUE(powerstats->readEnergyMeters(selectedIds, &selectedMeasurements).isOk());
295
296 testMatching(selectedChannels, &Channel::id, selectedMeasurements, &EnergyMeasurement::id);
297}
298
299// Energy consumer info must return a valid status
300TEST_P(PowerStatsAidl, TestGetEnergyConsumerInfo) {
301 std::vector<EnergyConsumer> consumers;
302 ASSERT_TRUE(powerstats->getEnergyConsumerInfo(&consumers).isOk());
303}
304
305// Each energy consumer must have a unique id
306TEST_P(PowerStatsAidl, TestGetEnergyConsumerUniqueId) {
307 std::vector<EnergyConsumer> consumers;
308 ASSERT_TRUE(powerstats->getEnergyConsumerInfo(&consumers).isOk());
309
310 testUnique(consumers, &EnergyConsumer::id);
311}
312
313// Each energy consumer must have a valid name
314TEST_P(PowerStatsAidl, ValidateEnergyConsumerNames) {
315 std::vector<EnergyConsumer> consumers;
316 ASSERT_TRUE(powerstats->getEnergyConsumerInfo(&consumers).isOk());
317
318 for (auto consumer : consumers) {
319 testNameValid(consumer.name);
320 }
321}
322
323// Each energy consumer must have a unique name
324TEST_P(PowerStatsAidl, ValidateEnergyConsumerUniqueNames) {
325 std::vector<EnergyConsumer> consumers;
326 ASSERT_TRUE(powerstats->getEnergyConsumerInfo(&consumers).isOk());
327
328 testUnique(consumers, &EnergyConsumer::name);
329}
330
331// Energy consumers of the same type must have ordinals that are 0,1,2,..., N - 1
332TEST_P(PowerStatsAidl, ValidateEnergyConsumerOrdinals) {
333 std::vector<EnergyConsumer> consumers;
334 ASSERT_TRUE(powerstats->getEnergyConsumerInfo(&consumers).isOk());
335
336 std::unordered_map<EnergyConsumerType, std::set<int32_t>> ordinalMap;
337
338 // Ordinals must be unique for each type
339 for (auto consumer : consumers) {
340 EXPECT_TRUE(ordinalMap[consumer.type].insert(consumer.ordinal).second);
341 }
342
343 // Min ordinal must be 0, max ordinal must be N - 1
344 for (const auto& [unused, ordinals] : ordinalMap) {
345 EXPECT_EQ(0, *std::min_element(ordinals.begin(), ordinals.end()));
346 EXPECT_EQ(ordinals.size() - 1, *std::max_element(ordinals.begin(), ordinals.end()));
347 }
348}
349
350// Energy consumed must return a valid status
351TEST_P(PowerStatsAidl, TestGetEnergyConsumed) {
352 std::vector<EnergyConsumerResult> results;
353 ASSERT_TRUE(powerstats->getEnergyConsumed({}, &results).isOk());
354}
355
356// Energy consumed must return data for all energy consumers
357TEST_P(PowerStatsAidl, TestGetAllEnergyConsumed) {
358 std::vector<EnergyConsumer> consumers;
359 ASSERT_TRUE(powerstats->getEnergyConsumerInfo(&consumers).isOk());
360
361 std::vector<EnergyConsumerResult> results;
362 ASSERT_TRUE(powerstats->getEnergyConsumed({}, &results).isOk());
363
364 testMatching(consumers, &EnergyConsumer::id, results, &EnergyConsumerResult::id);
365}
366
367// Energy consumed must return data for each selected energy consumer
368TEST_P(PowerStatsAidl, TestGetSelectedEnergyConsumed) {
369 std::vector<EnergyConsumer> consumers;
370 ASSERT_TRUE(powerstats->getEnergyConsumerInfo(&consumers).isOk());
371 if (consumers.empty()) {
372 return;
373 }
374
375 std::vector<EnergyConsumer> selectedConsumers = getRandomSubset(consumers);
376 std::vector<int32_t> selectedIds;
377 for (auto const& consumer : selectedConsumers) {
378 selectedIds.push_back(consumer.id);
379 }
380
381 std::vector<EnergyConsumerResult> selectedResults;
382 ASSERT_TRUE(powerstats->getEnergyConsumed(selectedIds, &selectedResults).isOk());
383
384 testMatching(selectedConsumers, &EnergyConsumer::id, selectedResults,
385 &EnergyConsumerResult::id);
386}
387
388// Energy consumed attribution uids must be unique for a given energy consumer
389TEST_P(PowerStatsAidl, ValidateEnergyConsumerAttributionUniqueUids) {
390 std::vector<EnergyConsumerResult> results;
391 ASSERT_TRUE(powerstats->getEnergyConsumed({}, &results).isOk());
392
393 for (auto result : results) {
394 testUnique(result.attribution, &EnergyConsumerAttribution::uid);
395 }
396}
397
398// Energy consumed total energy >= sum total of uid-attributed energy
399TEST_P(PowerStatsAidl, TestGetEnergyConsumedAttributedEnergy) {
400 std::vector<EnergyConsumerResult> results;
401 ASSERT_TRUE(powerstats->getEnergyConsumed({}, &results).isOk());
402
403 for (auto result : results) {
404 int64_t totalAttributedEnergyUWs = 0;
405 for (auto attribution : result.attribution) {
406 totalAttributedEnergyUWs += attribution.energyUWs;
407 }
408 EXPECT_TRUE(result.energyUWs >= totalAttributedEnergyUWs);
409 }
410}
411
Benjamin Schwartz40492c22020-08-31 11:55:55 -0700412GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(PowerStatsAidl);
413INSTANTIATE_TEST_SUITE_P(
414 PowerStats, PowerStatsAidl,
415 testing::ValuesIn(android::getAidlHalInstanceNames(IPowerStats::descriptor)),
416 android::PrintInstanceNameToString);
417
418int main(int argc, char** argv) {
419 ::testing::InitGoogleTest(&argc, argv);
420 ABinderProcess_setThreadPoolMaxThreadCount(1);
421 ABinderProcess_startThreadPool();
422 return RUN_ALL_TESTS();
423}