1 /*
2 * Copyright (C) 2018 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 #define LOG_TAG "android.power.stats.vts"
18
19 #include <android-base/logging.h>
20 #include <android/hardware/power/stats/1.0/IPowerStats.h>
21 #include <fmq/MessageQueue.h>
22 #include <gtest/gtest.h>
23 #include <hidl/GtestPrinter.h>
24 #include <hidl/MQDescriptor.h>
25 #include <hidl/ServiceManagement.h>
26 #include <inttypes.h>
27
28 #include <algorithm>
29 #include <random>
30 #include <thread>
31
32 namespace android {
33 namespace power {
34 namespace stats {
35 namespace vts {
36 namespace {
37
38 using android::sp;
39 using android::hardware::hidl_vec;
40 using android::hardware::kSynchronizedReadWrite;
41 using android::hardware::Return;
42 using android::hardware::Void;
43 using android::hardware::power::stats::V1_0::EnergyData;
44 using android::hardware::power::stats::V1_0::IPowerStats;
45 using android::hardware::power::stats::V1_0::PowerEntityInfo;
46 using android::hardware::power::stats::V1_0::PowerEntityStateResidencyResult;
47 using android::hardware::power::stats::V1_0::PowerEntityStateSpace;
48 using android::hardware::power::stats::V1_0::RailInfo;
49 using android::hardware::power::stats::V1_0::Status;
50
51 } // namespace
52
53 typedef hardware::MessageQueue<EnergyData, kSynchronizedReadWrite> MessageQueueSync;
54
55 class PowerStatsHidlTest : public ::testing::TestWithParam<std::string> {
56 public:
SetUp()57 virtual void SetUp() override {
58 service_ = IPowerStats::getService(GetParam());
59 ASSERT_NE(service_, nullptr);
60 }
61
TearDown()62 virtual void TearDown() override {}
63
64 void getInfos(hidl_vec<PowerEntityInfo>& infos);
65 void getStateSpaces(hidl_vec<PowerEntityStateSpace>& stateSpaces,
66 const std::vector<uint32_t>& ids);
67 void getResidencyResults(hidl_vec<PowerEntityStateResidencyResult>& results,
68 const std::vector<uint32_t>& ids);
69 void getRandomIds(std::vector<uint32_t>& ids);
70
71 sp<IPowerStats> service_;
72 };
73
getInfos(hidl_vec<PowerEntityInfo> & infos)74 void PowerStatsHidlTest::getInfos(hidl_vec<PowerEntityInfo>& infos) {
75 Status status;
76 Return<void> ret = service_->getPowerEntityInfo([&status, &infos](auto rInfos, auto rStatus) {
77 status = rStatus;
78 infos = rInfos;
79 });
80 ASSERT_TRUE(ret.isOk());
81
82 if (status == Status::SUCCESS) {
83 ASSERT_NE(infos.size(), 0) << "powerEntityInfos must have entries if supported";
84 } else {
85 ASSERT_EQ(status, Status::NOT_SUPPORTED);
86 ASSERT_EQ(infos.size(), 0);
87 LOG(INFO) << "getPowerEntityInfo not supported";
88 }
89 }
90
getStateSpaces(hidl_vec<PowerEntityStateSpace> & stateSpaces,const std::vector<uint32_t> & ids={})91 void PowerStatsHidlTest::getStateSpaces(hidl_vec<PowerEntityStateSpace>& stateSpaces,
92 const std::vector<uint32_t>& ids = {}) {
93 Status status;
94 Return<void> ret = service_->getPowerEntityStateInfo(
__anon4a02aa110302(auto rStateSpaces, auto rStatus) 95 ids, [&status, &stateSpaces](auto rStateSpaces, auto rStatus) {
96 status = rStatus;
97 stateSpaces = rStateSpaces;
98 });
99 ASSERT_TRUE(ret.isOk());
100
101 if (status == Status::SUCCESS) {
102 ASSERT_NE(stateSpaces.size(), 0) << "powerEntityStateSpaces must have entries if supported";
103 } else {
104 ASSERT_EQ(status, Status::NOT_SUPPORTED);
105 ASSERT_EQ(stateSpaces.size(), 0);
106 LOG(INFO) << "getPowerEntityStateInfo not supported";
107 }
108 }
109
getResidencyResults(hidl_vec<PowerEntityStateResidencyResult> & results,const std::vector<uint32_t> & ids={})110 void PowerStatsHidlTest::getResidencyResults(hidl_vec<PowerEntityStateResidencyResult>& results,
111 const std::vector<uint32_t>& ids = {}) {
112 Status status;
113 Return<void> ret = service_->getPowerEntityStateResidencyData(
__anon4a02aa110402(auto rResults, auto rStatus) 114 ids, [&status, &results](auto rResults, auto rStatus) {
115 status = rStatus;
116 results = rResults;
117 });
118 ASSERT_TRUE(ret.isOk());
119
120 if (status == Status::SUCCESS) {
121 ASSERT_NE(results.size(), 0);
122 } else {
123 ASSERT_EQ(status, Status::NOT_SUPPORTED);
124 ASSERT_EQ(results.size(), 0);
125 LOG(INFO) << "getPowerEntityStateResidencyData not supported";
126 }
127 }
128
getRandomIds(std::vector<uint32_t> & ids)129 void PowerStatsHidlTest::getRandomIds(std::vector<uint32_t>& ids) {
130 hidl_vec<PowerEntityStateSpace> stateSpaces;
131 getStateSpaces(stateSpaces);
132
133 if (stateSpaces.size() == 0) {
134 return;
135 }
136
137 for (auto stateSpace : stateSpaces) {
138 ids.push_back(stateSpace.powerEntityId);
139 }
140
141 unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
142 auto gen = std::default_random_engine(seed);
143 std::uniform_int_distribution<uint32_t> dist(1, stateSpaces.size());
144
145 std::shuffle(ids.begin(), ids.end(), gen);
146 ids.resize(dist(gen));
147 }
148
149 // Each PowerEntity must have a valid name
TEST_P(PowerStatsHidlTest,ValidatePowerEntityNames)150 TEST_P(PowerStatsHidlTest, ValidatePowerEntityNames) {
151 hidl_vec<PowerEntityInfo> infos;
152 getInfos(infos);
153 for (auto info : infos) {
154 ASSERT_NE(info.powerEntityName, "");
155 }
156 }
157
158 // Each PowerEntity must have a unique ID
TEST_P(PowerStatsHidlTest,ValidatePowerEntityIds)159 TEST_P(PowerStatsHidlTest, ValidatePowerEntityIds) {
160 hidl_vec<PowerEntityInfo> infos;
161 getInfos(infos);
162
163 std::set<uint32_t> ids;
164 for (auto info : infos) {
165 ASSERT_TRUE(ids.insert(info.powerEntityId).second);
166 }
167 }
168
169 // Each PowerEntityStateSpace must have an associated PowerEntityInfo
TEST_P(PowerStatsHidlTest,ValidateStateInfoAssociation)170 TEST_P(PowerStatsHidlTest, ValidateStateInfoAssociation) {
171 hidl_vec<PowerEntityInfo> infos;
172 getInfos(infos);
173
174 hidl_vec<PowerEntityStateSpace> stateSpaces;
175 getStateSpaces(stateSpaces);
176
177 std::set<uint32_t> ids;
178 for (auto info : infos) {
179 ids.insert(info.powerEntityId);
180 }
181
182 for (auto stateSpace : stateSpaces) {
183 ASSERT_NE(ids.count(stateSpace.powerEntityId), 0);
184 }
185 }
186
187 // Each state must have a valid name
TEST_P(PowerStatsHidlTest,ValidateStateNames)188 TEST_P(PowerStatsHidlTest, ValidateStateNames) {
189 hidl_vec<PowerEntityStateSpace> stateSpaces;
190 getStateSpaces(stateSpaces);
191
192 for (auto stateSpace : stateSpaces) {
193 for (auto state : stateSpace.states) {
194 ASSERT_NE(state.powerEntityStateName, "");
195 }
196 }
197 }
198
199 // Each state must have an ID that is unique to the PowerEntityStateSpace
TEST_P(PowerStatsHidlTest,ValidateStateUniqueIds)200 TEST_P(PowerStatsHidlTest, ValidateStateUniqueIds) {
201 hidl_vec<PowerEntityStateSpace> stateSpaces;
202 getStateSpaces(stateSpaces);
203
204 for (auto stateSpace : stateSpaces) {
205 std::set<uint32_t> stateIds;
206 for (auto state : stateSpace.states) {
207 ASSERT_TRUE(stateIds.insert(state.powerEntityStateId).second);
208 }
209 }
210 }
211
212 // getPowerEntityStateInfo must support passing in requested IDs
213 // Results must contain state space information for all requested IDs
TEST_P(PowerStatsHidlTest,ValidateStateInfoAssociationSelect)214 TEST_P(PowerStatsHidlTest, ValidateStateInfoAssociationSelect) {
215 std::vector<uint32_t> randomIds;
216 getRandomIds(randomIds);
217
218 if (randomIds.empty()) {
219 return;
220 }
221
222 hidl_vec<PowerEntityStateSpace> stateSpaces;
223 getStateSpaces(stateSpaces, randomIds);
224
225 ASSERT_EQ(stateSpaces.size(), randomIds.size());
226
227 std::set<uint32_t> ids;
228 for (auto id : randomIds) {
229 ids.insert(id);
230 }
231 for (auto stateSpace : stateSpaces) {
232 ASSERT_NE(ids.count(stateSpace.powerEntityId), 0);
233 }
234 }
235
236 // Requested state space info must match initially obtained stateinfos
TEST_P(PowerStatsHidlTest,ValidateStateInfoSelect)237 TEST_P(PowerStatsHidlTest, ValidateStateInfoSelect) {
238 hidl_vec<PowerEntityStateSpace> stateSpaces;
239 getStateSpaces(stateSpaces);
240 if (stateSpaces.size() == 0) {
241 return;
242 }
243
244 std::vector<uint32_t> randomIds;
245 getRandomIds(randomIds);
246 ASSERT_FALSE(randomIds.empty());
247
248 hidl_vec<PowerEntityStateSpace> selectedStateSpaces;
249 getStateSpaces(selectedStateSpaces, randomIds);
250
251 std::map<uint32_t, PowerEntityStateSpace> stateSpaceMap;
252 for (auto stateSpace : stateSpaces) {
253 stateSpaceMap[stateSpace.powerEntityId] = stateSpace;
254 }
255
256 for (auto stateSpace : selectedStateSpaces) {
257 auto it = stateSpaceMap.find(stateSpace.powerEntityId);
258 ASSERT_NE(it, stateSpaceMap.end());
259
260 ASSERT_EQ(stateSpace.states.size(), it->second.states.size());
261 for (auto i = 0; i < stateSpace.states.size(); i++) {
262 ASSERT_EQ(stateSpace.states[i].powerEntityStateId,
263 it->second.states[i].powerEntityStateId);
264 ASSERT_EQ(stateSpace.states[i].powerEntityStateName,
265 it->second.states[i].powerEntityStateName);
266 }
267 }
268 }
269
270 // stateResidencyResults must contain results for every PowerEntityStateSpace
271 // returned by getPowerEntityStateInfo
TEST_P(PowerStatsHidlTest,ValidateResidencyResultsAssociation)272 TEST_P(PowerStatsHidlTest, ValidateResidencyResultsAssociation) {
273 hidl_vec<PowerEntityStateSpace> stateSpaces;
274 getStateSpaces(stateSpaces);
275
276 hidl_vec<PowerEntityStateResidencyResult> results;
277 getResidencyResults(results);
278
279 std::map<uint32_t, PowerEntityStateResidencyResult> resultsMap;
280 for (auto result : results) {
281 resultsMap[result.powerEntityId] = result;
282 }
283
284 for (auto stateSpace : stateSpaces) {
285 auto it = resultsMap.find(stateSpace.powerEntityId);
286 ASSERT_NE(it, resultsMap.end());
287
288 ASSERT_EQ(stateSpace.states.size(), it->second.stateResidencyData.size());
289
290 std::set<uint32_t> stateIds;
291 for (auto residency : it->second.stateResidencyData) {
292 stateIds.insert(residency.powerEntityStateId);
293 }
294
295 for (auto state : stateSpace.states) {
296 ASSERT_NE(stateIds.count(state.powerEntityStateId), 0);
297 }
298 }
299 }
300
301 // getPowerEntityStateResidencyData must support passing in requested IDs
302 // stateResidencyResults must contain results for each PowerEntityStateSpace
303 // returned by getPowerEntityStateInfo
TEST_P(PowerStatsHidlTest,ValidateResidencyResultsAssociationSelect)304 TEST_P(PowerStatsHidlTest, ValidateResidencyResultsAssociationSelect) {
305 std::vector<uint32_t> randomIds;
306 getRandomIds(randomIds);
307 if (randomIds.empty()) {
308 return;
309 }
310
311 hidl_vec<PowerEntityStateSpace> stateSpaces;
312 getStateSpaces(stateSpaces, randomIds);
313
314 hidl_vec<PowerEntityStateResidencyResult> results;
315 getResidencyResults(results, randomIds);
316
317 std::map<uint32_t, PowerEntityStateResidencyResult> resultsMap;
318 for (auto result : results) {
319 resultsMap[result.powerEntityId] = result;
320 }
321
322 for (auto stateSpace : stateSpaces) {
323 auto it = resultsMap.find(stateSpace.powerEntityId);
324 ASSERT_NE(it, resultsMap.end());
325
326 ASSERT_EQ(stateSpace.states.size(), it->second.stateResidencyData.size());
327
328 std::set<uint32_t> stateIds;
329 for (auto residency : it->second.stateResidencyData) {
330 stateIds.insert(residency.powerEntityStateId);
331 }
332
333 for (auto state : stateSpace.states) {
334 ASSERT_NE(stateIds.count(state.powerEntityStateId), 0);
335 }
336 }
337 }
338
TEST_P(PowerStatsHidlTest,ValidateRailInfo)339 TEST_P(PowerStatsHidlTest, ValidateRailInfo) {
340 hidl_vec<RailInfo> rails[2];
341 Status s;
342 auto cb = [&rails, &s](hidl_vec<RailInfo> rail_subsys, Status status) {
343 rails[0] = rail_subsys;
344 s = status;
345 };
346 Return<void> ret = service_->getRailInfo(cb);
347 EXPECT_TRUE(ret.isOk());
348 if (s == Status::SUCCESS) {
349 /* Rails size should be non-zero on SUCCESS*/
350 ASSERT_NE(rails[0].size(), 0);
351 /* check if indices returned are unique*/
352 std::set<uint32_t> ids;
353 for (auto rail : rails[0]) {
354 ASSERT_TRUE(ids.insert(rail.index).second);
355 }
356 auto cb = [&rails, &s](hidl_vec<RailInfo> rail_subsys, Status status) {
357 rails[1] = rail_subsys;
358 s = status;
359 };
360 Return<void> ret = service_->getRailInfo(cb);
361 EXPECT_TRUE(ret.isOk());
362 ASSERT_EQ(s, Status::SUCCESS);
363 ASSERT_EQ(rails[0].size(), rails[1].size());
364 /* check if data returned by two calls to getRailInfo is same*/
365 for (int i = 0; i < rails[0].size(); i++) {
366 ASSERT_NE(rails[0][i].railName, "");
367 ASSERT_NE(rails[0][i].subsysName, "");
368 int j = 0;
369 bool match = false;
370 for (j = 0; j < rails[1].size(); j++) {
371 if (rails[0][i].index == rails[1][j].index) {
372 ASSERT_EQ(rails[0][i].railName, rails[1][i].railName);
373 ASSERT_EQ(rails[0][i].subsysName, rails[1][i].subsysName);
374 match = true;
375 break;
376 }
377 }
378 ASSERT_TRUE(match);
379 }
380 } else if (s == Status::FILESYSTEM_ERROR) {
381 ALOGI("ValidateRailInfo returned FILESYSTEM_ERROR");
382 ASSERT_EQ(rails[0].size(), 0);
383 } else if (s == Status::NOT_SUPPORTED) {
384 ALOGI("ValidateRailInfo returned NOT_SUPPORTED");
385 ASSERT_EQ(rails[0].size(), 0);
386 } else if (s == Status::INVALID_INPUT) {
387 ALOGI("ValidateRailInfo returned INVALID_INPUT");
388 ASSERT_EQ(rails[0].size(), 0);
389 } else if (s == Status::INSUFFICIENT_RESOURCES) {
390 ALOGI("ValidateRailInfo returned INSUFFICIENT_RESOURCES");
391 ASSERT_EQ(rails[0].size(), 0);
392 }
393 }
394
TEST_P(PowerStatsHidlTest,ValidateAllPowerData)395 TEST_P(PowerStatsHidlTest, ValidateAllPowerData) {
396 hidl_vec<EnergyData> measurements[2];
397 Status s;
398 auto cb = [&measurements, &s](hidl_vec<EnergyData> measure, Status status) {
399 measurements[0] = measure;
400 s = status;
401 };
402 Return<void> ret = service_->getEnergyData(hidl_vec<uint32_t>(), cb);
403 EXPECT_TRUE(ret.isOk());
404 if (s == Status::SUCCESS) {
405 /*measurements size should be non-zero on SUCCESS*/
406 ASSERT_NE(measurements[0].size(), 0);
407 auto cb = [&measurements, &s](hidl_vec<EnergyData> measure, Status status) {
408 measurements[1] = measure;
409 s = status;
410 };
411 Return<void> ret = service_->getEnergyData(hidl_vec<uint32_t>(), cb);
412 EXPECT_TRUE(ret.isOk());
413 ASSERT_EQ(s, Status::SUCCESS);
414 /*Both calls should returns same amount of data*/
415 ASSERT_EQ(measurements[0].size(), measurements[1].size());
416 /*Check is energy and timestamp are monotonically increasing*/
417 for (int i = 0; i < measurements[0].size(); i++) {
418 int j;
419 for (j = 0; j < measurements[1].size(); j++) {
420 if (measurements[0][i].index == measurements[1][j].index) {
421 EXPECT_GE(measurements[1][j].timestamp, measurements[0][i].timestamp);
422 EXPECT_GE(measurements[1][j].energy, measurements[0][i].energy);
423 break;
424 }
425 }
426 /*Check is indices for two call match*/
427 ASSERT_NE(j, measurements[1].size());
428 }
429 } else if (s == Status::FILESYSTEM_ERROR) {
430 ALOGI("ValidateAllPowerData returned FILESYSTEM_ERROR");
431 ASSERT_EQ(measurements[0].size(), 0);
432 } else if (s == Status::NOT_SUPPORTED) {
433 ALOGI("ValidateAllPowerData returned NOT_SUPPORTED");
434 ASSERT_EQ(measurements[0].size(), 0);
435 } else if (s == Status::INVALID_INPUT) {
436 ALOGI("ValidateAllPowerData returned INVALID_INPUT");
437 ASSERT_EQ(measurements[0].size(), 0);
438 } else if (s == Status::INSUFFICIENT_RESOURCES) {
439 ALOGI("ValidateAllPowerData returned INSUFFICIENT_RESOURCES");
440 ASSERT_EQ(measurements[0].size(), 0);
441 }
442 }
443
TEST_P(PowerStatsHidlTest,ValidateFilteredPowerData)444 TEST_P(PowerStatsHidlTest, ValidateFilteredPowerData) {
445 hidl_vec<RailInfo> rails;
446 hidl_vec<EnergyData> measurements;
447 hidl_vec<uint32_t> indices;
448 std::string debugString;
449 Status s;
450 auto cb = [&rails, &s](hidl_vec<RailInfo> rail_subsys, Status status) {
451 rails = rail_subsys;
452 s = status;
453 };
454 Return<void> ret = service_->getRailInfo(cb);
455 EXPECT_TRUE(ret.isOk());
456 std::time_t seed = std::time(nullptr);
457 std::srand(seed);
458 if (s == Status::SUCCESS) {
459 size_t sz = std::max(1, (int)(std::rand() % rails.size()));
460 indices.resize(sz);
461 for (int i = 0; i < sz; i++) {
462 int j = std::rand() % rails.size();
463 indices[i] = rails[j].index;
464 debugString += std::to_string(indices[i]) + ", ";
465 }
466 debugString += "\n";
467 ALOGI("ValidateFilteredPowerData for indices: %s", debugString.c_str());
468 auto cb = [&measurements, &s](hidl_vec<EnergyData> measure, Status status) {
469 measurements = measure;
470 s = status;
471 };
472 Return<void> ret = service_->getEnergyData(indices, cb);
473 EXPECT_TRUE(ret.isOk());
474 if (s == Status::SUCCESS) {
475 /* Make sure that all the measurements are returned */
476 ASSERT_EQ(sz, measurements.size());
477 for (int i = 0; i < measurements.size(); i++) {
478 int j;
479 bool match = false;
480 /* Check that the measurement belongs to the requested index */
481 for (j = 0; j < indices.size(); j++) {
482 if (indices[j] == measurements[i].index) {
483 match = true;
484 break;
485 }
486 }
487 ASSERT_TRUE(match);
488 }
489 }
490 } else {
491 /* size should be zero is stats is NOT SUCCESS */
492 ASSERT_EQ(rails.size(), 0);
493 }
494 }
495
readEnergy(sp<IPowerStats> service_,uint32_t timeMs)496 void readEnergy(sp<IPowerStats> service_, uint32_t timeMs) {
497 std::unique_ptr<MessageQueueSync> mQueue;
498 Status s;
499 uint32_t railsInSample;
500 uint32_t totalSamples;
501 auto cb = [&s, &mQueue, &totalSamples, &railsInSample](
502 const hardware::MQDescriptorSync<EnergyData>& in, uint32_t numSamples,
503 uint32_t railsPerSample, Status status) {
504 mQueue.reset(new (std::nothrow) MessageQueueSync(in));
505 s = status;
506 totalSamples = numSamples;
507 railsInSample = railsPerSample;
508 };
509 service_->streamEnergyData(timeMs, 10, cb);
510 if (s == Status::SUCCESS) {
511 ASSERT_NE(nullptr, mQueue);
512 ASSERT_TRUE(mQueue->isValid());
513 bool rc;
514 int sampleCount = 0;
515 uint32_t totalQuants = railsInSample * totalSamples;
516 uint64_t timeout_ns = 10000000000;
517 if (totalSamples > 0) {
518 uint32_t batch = std::max(1, (int)((std::rand() % totalSamples) * railsInSample));
519 ALOGI("Read energy, timsMs: %u, batch: %u", timeMs, batch);
520 std::vector<EnergyData> data(batch);
521 while (sampleCount < totalQuants) {
522 rc = mQueue->readBlocking(&data[0], batch, timeout_ns);
523 if (rc == false) {
524 break;
525 }
526 sampleCount = sampleCount + batch;
527 if (batch > totalQuants - sampleCount) {
528 batch = 1;
529 }
530 }
531 ASSERT_EQ(totalQuants, sampleCount);
532 }
533 } else if (s == Status::FILESYSTEM_ERROR) {
534 ASSERT_FALSE(mQueue->isValid());
535 ASSERT_EQ(totalSamples, 0);
536 ASSERT_EQ(railsInSample, 0);
537 } else if (s == Status::NOT_SUPPORTED) {
538 ASSERT_FALSE(mQueue->isValid());
539 ASSERT_EQ(totalSamples, 0);
540 ASSERT_EQ(railsInSample, 0);
541 } else if (s == Status::INVALID_INPUT) {
542 ASSERT_FALSE(mQueue->isValid());
543 ASSERT_EQ(totalSamples, 0);
544 ASSERT_EQ(railsInSample, 0);
545 } else if (s == Status::INSUFFICIENT_RESOURCES) {
546 ASSERT_FALSE(mQueue->isValid());
547 ASSERT_EQ(totalSamples, 0);
548 ASSERT_EQ(railsInSample, 0);
549 }
550 }
551
TEST_P(PowerStatsHidlTest,StreamEnergyData)552 TEST_P(PowerStatsHidlTest, StreamEnergyData) {
553 std::time_t seed = std::time(nullptr);
554 std::srand(seed);
555 std::thread thread1 = std::thread(readEnergy, service_, std::rand() % 5000);
556 thread1.join();
557 }
558
559 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(PowerStatsHidlTest);
560 INSTANTIATE_TEST_SUITE_P(
561 PerInstance, PowerStatsHidlTest,
562 testing::ValuesIn(android::hardware::getAllHalInstanceNames(IPowerStats::descriptor)),
563 android::hardware::PrintInstanceNameToString);
564
565 } // namespace vts
566 } // namespace stats
567 } // namespace power
568 } // namespace android
569