blob: 3afba456c9317dff6873e4f419facbf93ff739d0 [file] [log] [blame]
Yifan Hong69c22542017-10-03 17:40:24 -07001/*
2 * Copyright (C) 2017 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
Yifan Hongf86271d2017-11-06 12:52:20 -080017#define LOG_TAG "health_hidl_hal_test"
Yifan Hong69c22542017-10-03 17:40:24 -070018
Yifan Hong94841c92020-01-28 16:11:39 -080019#include <chrono>
Yifan Hong69c22542017-10-03 17:40:24 -070020#include <mutex>
Yifan Hong03b2a342019-03-08 11:37:33 -080021#include <set>
22#include <string>
Yifan Hong94841c92020-01-28 16:11:39 -080023#include <thread>
Yifan Hong69c22542017-10-03 17:40:24 -070024
Yifan Hong69c22542017-10-03 17:40:24 -070025#include <android-base/logging.h>
Yifan Hong94841c92020-01-28 16:11:39 -080026#include <android-base/properties.h>
27#include <android/hardware/health/1.0/types.h>
Yifan Hong69c22542017-10-03 17:40:24 -070028#include <android/hardware/health/2.0/IHealth.h>
29#include <android/hardware/health/2.0/types.h>
Yifan Honge6807dd2019-03-07 13:04:33 -080030#include <gflags/gflags.h>
nelsonli4da3ca52019-12-10 17:17:09 +080031#include <gtest/gtest.h>
Yifan Hong2200cff2021-10-28 12:18:35 -070032#include <health-test/TestUtils.h>
nelsonli4da3ca52019-12-10 17:17:09 +080033#include <hidl/GtestPrinter.h>
34#include <hidl/ServiceManagement.h>
35#include <log/log.h>
Yifan Hong69c22542017-10-03 17:40:24 -070036
37using ::testing::AssertionFailure;
38using ::testing::AssertionResult;
39using ::testing::AssertionSuccess;
Yifan Hong94841c92020-01-28 16:11:39 -080040using namespace std::chrono_literals;
Yifan Hong69c22542017-10-03 17:40:24 -070041
Yifan Honge6807dd2019-03-07 13:04:33 -080042DEFINE_bool(force, false, "Force test healthd even when the default instance is present.");
43
Yifan Hong94841c92020-01-28 16:11:39 -080044// Return expr if it is evaluated to false.
45#define TEST_AND_RETURN(expr) \
46 do { \
47 auto res = (expr); \
48 if (!res) return res; \
49 } while (0)
50
Yifan Hong69c22542017-10-03 17:40:24 -070051namespace android {
52namespace hardware {
53namespace health {
Yifan Hong69c22542017-10-03 17:40:24 -070054
Yifan Hong2200cff2021-10-28 12:18:35 -070055using test_utils::SucceedOnce;
Yifan Hong69c22542017-10-03 17:40:24 -070056using V1_0::BatteryStatus;
Yifan Hong94841c92020-01-28 16:11:39 -080057using V1_0::toString;
58
59namespace V2_0 {
Yifan Hong69c22542017-10-03 17:40:24 -070060
nelsonli4da3ca52019-12-10 17:17:09 +080061class HealthHidlTest : public ::testing::TestWithParam<std::string> {
Yifan Hong69c22542017-10-03 17:40:24 -070062 public:
63 virtual void SetUp() override {
nelsonli4da3ca52019-12-10 17:17:09 +080064 std::string serviceName = GetParam();
Yifan Honge6807dd2019-03-07 13:04:33 -080065
66 if (serviceName == "backup" && !FLAGS_force &&
nelsonli4da3ca52019-12-10 17:17:09 +080067 IHealth::getService() != nullptr) {
Yifan Honge6807dd2019-03-07 13:04:33 -080068 LOG(INFO) << "Skipping tests on healthd because the default instance is present. "
69 << "Use --force if you really want to test healthd.";
70 GTEST_SKIP();
71 }
72
Yifan Hong69c22542017-10-03 17:40:24 -070073 LOG(INFO) << "get service with name:" << serviceName;
74 ASSERT_FALSE(serviceName.empty());
nelsonli4da3ca52019-12-10 17:17:09 +080075 mHealth = IHealth::getService(serviceName);
Yifan Hong69c22542017-10-03 17:40:24 -070076 ASSERT_NE(mHealth, nullptr);
77 }
78
79 sp<IHealth> mHealth;
80};
81
82class Callback : public IHealthInfoCallback {
Yifan Hong69c22542017-10-03 17:40:24 -070083 public:
Hridya Valsarajud31932a2018-01-17 23:09:24 -080084 Return<void> healthInfoChanged(const HealthInfo&) override {
Yifan Hongd6ea57e2017-11-20 14:41:09 -080085 std::lock_guard<std::mutex> lock(mMutex);
86 mInvoked = true;
87 mInvokedNotify.notify_all();
Yifan Hong69c22542017-10-03 17:40:24 -070088 return Void();
89 }
Yifan Hongd6ea57e2017-11-20 14:41:09 -080090 template <typename R, typename P>
91 bool waitInvoke(std::chrono::duration<R, P> duration) {
Yifan Hong69c22542017-10-03 17:40:24 -070092 std::unique_lock<std::mutex> lock(mMutex);
Yifan Hongd6ea57e2017-11-20 14:41:09 -080093 bool r = mInvokedNotify.wait_for(lock, duration, [this] { return this->mInvoked; });
94 mInvoked = false;
95 return r;
Yifan Hong69c22542017-10-03 17:40:24 -070096 }
Yifan Hong69c22542017-10-03 17:40:24 -070097 private:
98 std::mutex mMutex;
Yifan Hongd6ea57e2017-11-20 14:41:09 -080099 std::condition_variable mInvokedNotify;
100 bool mInvoked = false;
Yifan Hong69c22542017-10-03 17:40:24 -0700101};
102
103#define ASSERT_OK(r) ASSERT_TRUE(isOk(r))
104#define EXPECT_OK(r) EXPECT_TRUE(isOk(r))
105template <typename T>
106AssertionResult isOk(const Return<T>& r) {
107 return r.isOk() ? AssertionSuccess() : (AssertionFailure() << r.description());
108}
109
110#define ASSERT_ALL_OK(r) ASSERT_TRUE(isAllOk(r))
111// Both isOk() and Result::SUCCESS
112AssertionResult isAllOk(const Return<Result>& r) {
113 if (!r.isOk()) {
114 return AssertionFailure() << r.description();
115 }
116 if (static_cast<Result>(r) != Result::SUCCESS) {
117 return AssertionFailure() << toString(static_cast<Result>(r));
118 }
119 return AssertionSuccess();
120}
121
122/**
123 * Test whether callbacks work. Tested functions are IHealth::registerCallback,
124 * unregisterCallback, and update.
125 */
nelsonli4da3ca52019-12-10 17:17:09 +0800126TEST_P(HealthHidlTest, Callbacks) {
Yifan Hong69c22542017-10-03 17:40:24 -0700127 using namespace std::chrono_literals;
Yifan Hongd6ea57e2017-11-20 14:41:09 -0800128 sp<Callback> firstCallback = new Callback();
129 sp<Callback> secondCallback = new Callback();
Yifan Hong69c22542017-10-03 17:40:24 -0700130
131 ASSERT_ALL_OK(mHealth->registerCallback(firstCallback));
132 ASSERT_ALL_OK(mHealth->registerCallback(secondCallback));
133
Yifan Hongd6ea57e2017-11-20 14:41:09 -0800134 // registerCallback may or may not invoke the callback immediately, so the test needs
135 // to wait for the invocation. If the implementation chooses not to invoke the callback
136 // immediately, just wait for some time.
137 firstCallback->waitInvoke(200ms);
138 secondCallback->waitInvoke(200ms);
Yifan Hong69c22542017-10-03 17:40:24 -0700139
Yifan Hongd6ea57e2017-11-20 14:41:09 -0800140 // assert that the first callback is invoked when update is called.
Yifan Hong69c22542017-10-03 17:40:24 -0700141 ASSERT_ALL_OK(mHealth->update());
142
Yifan Hongd6ea57e2017-11-20 14:41:09 -0800143 ASSERT_TRUE(firstCallback->waitInvoke(1s));
144 ASSERT_TRUE(secondCallback->waitInvoke(1s));
Yifan Hong69c22542017-10-03 17:40:24 -0700145
146 ASSERT_ALL_OK(mHealth->unregisterCallback(firstCallback));
147
Yifan Hongd6ea57e2017-11-20 14:41:09 -0800148 // clear any potentially pending callbacks result from wakealarm / kernel events
149 // If there is none, just wait for some time.
150 firstCallback->waitInvoke(200ms);
151 secondCallback->waitInvoke(200ms);
Yifan Hong69c22542017-10-03 17:40:24 -0700152
Yifan Hongd6ea57e2017-11-20 14:41:09 -0800153 // assert that the second callback is still invoked even though the first is unregistered.
Yifan Hong69c22542017-10-03 17:40:24 -0700154 ASSERT_ALL_OK(mHealth->update());
155
Yifan Hongd6ea57e2017-11-20 14:41:09 -0800156 ASSERT_FALSE(firstCallback->waitInvoke(200ms));
157 ASSERT_TRUE(secondCallback->waitInvoke(1s));
Yifan Hong69c22542017-10-03 17:40:24 -0700158
159 ASSERT_ALL_OK(mHealth->unregisterCallback(secondCallback));
Yifan Hong69c22542017-10-03 17:40:24 -0700160}
161
nelsonli4da3ca52019-12-10 17:17:09 +0800162TEST_P(HealthHidlTest, UnregisterNonExistentCallback) {
Yifan Hongd6ea57e2017-11-20 14:41:09 -0800163 sp<Callback> callback = new Callback();
Yifan Hong69c22542017-10-03 17:40:24 -0700164 auto ret = mHealth->unregisterCallback(callback);
165 ASSERT_OK(ret);
166 ASSERT_EQ(Result::NOT_FOUND, static_cast<Result>(ret)) << "Actual: " << toString(ret);
167}
168
169/**
170 * Pass the test if:
171 * - Property is not supported (res == NOT_SUPPORTED)
172 * - Result is success, and predicate is true
173 * @param res the Result value.
174 * @param valueStr the string representation for actual value (for error message)
175 * @param pred a predicate that test whether the value is valid
176 */
177#define EXPECT_VALID_OR_UNSUPPORTED_PROP(res, valueStr, pred) \
178 EXPECT_TRUE(isPropertyOk(res, valueStr, pred, #pred))
179
180AssertionResult isPropertyOk(Result res, const std::string& valueStr, bool pred,
181 const std::string& predStr) {
182 if (res == Result::SUCCESS) {
183 if (pred) {
184 return AssertionSuccess();
185 }
186 return AssertionFailure() << "value doesn't match.\nActual: " << valueStr
187 << "\nExpected: " << predStr;
188 }
189 if (res == Result::NOT_SUPPORTED) {
190 return AssertionSuccess();
191 }
192 return AssertionFailure() << "Result is not SUCCESS or NOT_SUPPORTED: " << toString(res);
193}
194
Hridya Valsaraju2120ecc2017-12-20 13:27:52 -0800195bool verifyStorageInfo(const hidl_vec<struct StorageInfo>& info) {
196 for (size_t i = 0; i < info.size(); i++) {
197 if (!(0 <= info[i].eol && info[i].eol <= 3 && 0 <= info[i].lifetimeA &&
198 info[i].lifetimeA <= 0x0B && 0 <= info[i].lifetimeB && info[i].lifetimeB <= 0x0B)) {
199 return false;
200 }
201 }
202
203 return true;
204}
205
Hridya Valsaraju87e29602018-01-12 17:46:22 -0800206template <typename T>
207bool verifyEnum(T value) {
Steven Morelandc90461c2018-05-01 16:54:09 -0700208 for (auto it : hidl_enum_range<T>()) {
Hridya Valsaraju87e29602018-01-12 17:46:22 -0800209 if (it == value) {
210 return true;
211 }
212 }
213
214 return false;
215}
216
217bool verifyHealthInfo(const HealthInfo& health_info) {
Hridya Valsaraju075c1822018-04-03 11:19:08 -0700218 if (!verifyStorageInfo(health_info.storageInfos)) {
Hridya Valsaraju87e29602018-01-12 17:46:22 -0800219 return false;
220 }
221
222 using V1_0::BatteryStatus;
223 using V1_0::BatteryHealth;
224
Robin Leeac5a0d32019-10-09 15:48:17 +0200225 if (!((health_info.legacy.batteryCurrent != INT32_MIN) &&
Hridya Valsaraju87e29602018-01-12 17:46:22 -0800226 (0 <= health_info.legacy.batteryLevel && health_info.legacy.batteryLevel <= 100) &&
227 verifyEnum<BatteryHealth>(health_info.legacy.batteryHealth) &&
Hridya Valsaraju87e29602018-01-12 17:46:22 -0800228 verifyEnum<BatteryStatus>(health_info.legacy.batteryStatus))) {
229 return false;
230 }
231
Robin Leeac5a0d32019-10-09 15:48:17 +0200232 if (health_info.legacy.batteryPresent) {
233 // If a battery is present, the battery status must be known.
234 if (!((health_info.legacy.batteryChargeCounter > 0) &&
235 (health_info.legacy.batteryStatus != BatteryStatus::UNKNOWN))) {
236 return false;
237 }
238 }
239
Hridya Valsaraju87e29602018-01-12 17:46:22 -0800240 return true;
241}
242
243/*
Yifan Hong26c12002018-10-02 14:52:02 -0700244 * Tests the values returned by getChargeCounter() from interface IHealth.
Hridya Valsaraju87e29602018-01-12 17:46:22 -0800245 */
nelsonli4da3ca52019-12-10 17:17:09 +0800246TEST_P(HealthHidlTest, getChargeCounter) {
Yifan Hong69c22542017-10-03 17:40:24 -0700247 EXPECT_OK(mHealth->getChargeCounter([](auto result, auto value) {
248 EXPECT_VALID_OR_UNSUPPORTED_PROP(result, std::to_string(value), value > 0);
249 }));
Yifan Hong26c12002018-10-02 14:52:02 -0700250}
251
252/*
253 * Tests the values returned by getCurrentNow() from interface IHealth.
254 */
nelsonli4da3ca52019-12-10 17:17:09 +0800255TEST_P(HealthHidlTest, getCurrentNow) {
Yifan Hong69c22542017-10-03 17:40:24 -0700256 EXPECT_OK(mHealth->getCurrentNow([](auto result, auto value) {
257 EXPECT_VALID_OR_UNSUPPORTED_PROP(result, std::to_string(value), value != INT32_MIN);
258 }));
Yifan Hong26c12002018-10-02 14:52:02 -0700259}
260
261/*
262 * Tests the values returned by getCurrentAverage() from interface IHealth.
263 */
nelsonli4da3ca52019-12-10 17:17:09 +0800264TEST_P(HealthHidlTest, getCurrentAverage) {
Yifan Hong69c22542017-10-03 17:40:24 -0700265 EXPECT_OK(mHealth->getCurrentAverage([](auto result, auto value) {
266 EXPECT_VALID_OR_UNSUPPORTED_PROP(result, std::to_string(value), value != INT32_MIN);
267 }));
Yifan Hong26c12002018-10-02 14:52:02 -0700268}
269
270/*
271 * Tests the values returned by getCapacity() from interface IHealth.
272 */
nelsonli4da3ca52019-12-10 17:17:09 +0800273TEST_P(HealthHidlTest, getCapacity) {
Yifan Hong69c22542017-10-03 17:40:24 -0700274 EXPECT_OK(mHealth->getCapacity([](auto result, auto value) {
275 EXPECT_VALID_OR_UNSUPPORTED_PROP(result, std::to_string(value), 0 <= value && value <= 100);
276 }));
Yifan Hong26c12002018-10-02 14:52:02 -0700277}
278
279/*
280 * Tests the values returned by getEnergyCounter() from interface IHealth.
281 */
nelsonli4da3ca52019-12-10 17:17:09 +0800282TEST_P(HealthHidlTest, getEnergyCounter) {
Yifan Hong69c22542017-10-03 17:40:24 -0700283 EXPECT_OK(mHealth->getEnergyCounter([](auto result, auto value) {
284 EXPECT_VALID_OR_UNSUPPORTED_PROP(result, std::to_string(value), value != INT64_MIN);
285 }));
Yifan Hong26c12002018-10-02 14:52:02 -0700286}
287
288/*
289 * Tests the values returned by getChargeStatus() from interface IHealth.
290 */
nelsonli4da3ca52019-12-10 17:17:09 +0800291TEST_P(HealthHidlTest, getChargeStatus) {
Yifan Hong69c22542017-10-03 17:40:24 -0700292 EXPECT_OK(mHealth->getChargeStatus([](auto result, auto value) {
Yifan Hong5ac6f5b2020-01-27 16:20:49 -0800293 EXPECT_VALID_OR_UNSUPPORTED_PROP(result, toString(value), verifyEnum<BatteryStatus>(value));
Yifan Hong69c22542017-10-03 17:40:24 -0700294 }));
Yifan Hong26c12002018-10-02 14:52:02 -0700295}
296
297/*
298 * Tests the values returned by getStorageInfo() from interface IHealth.
299 */
nelsonli4da3ca52019-12-10 17:17:09 +0800300TEST_P(HealthHidlTest, getStorageInfo) {
Hridya Valsaraju2120ecc2017-12-20 13:27:52 -0800301 EXPECT_OK(mHealth->getStorageInfo([](auto result, auto& value) {
Hridya Valsaraju87e29602018-01-12 17:46:22 -0800302 EXPECT_VALID_OR_UNSUPPORTED_PROP(result, toString(value), verifyStorageInfo(value));
Hridya Valsaraju2120ecc2017-12-20 13:27:52 -0800303 }));
Yifan Hong26c12002018-10-02 14:52:02 -0700304}
305
306/*
307 * Tests the values returned by getDiskStats() from interface IHealth.
308 */
nelsonli4da3ca52019-12-10 17:17:09 +0800309TEST_P(HealthHidlTest, getDiskStats) {
Hridya Valsaraju2120ecc2017-12-20 13:27:52 -0800310 EXPECT_OK(mHealth->getDiskStats([](auto result, auto& value) {
Hridya Valsaraju075c1822018-04-03 11:19:08 -0700311 EXPECT_VALID_OR_UNSUPPORTED_PROP(result, toString(value), true);
Hridya Valsaraju2120ecc2017-12-20 13:27:52 -0800312 }));
Yifan Hong26c12002018-10-02 14:52:02 -0700313}
314
315/*
316 * Tests the values returned by getHealthInfo() from interface IHealth.
317 */
nelsonli4da3ca52019-12-10 17:17:09 +0800318TEST_P(HealthHidlTest, getHealthInfo) {
Hridya Valsaraju87e29602018-01-12 17:46:22 -0800319 EXPECT_OK(mHealth->getHealthInfo([](auto result, auto& value) {
320 EXPECT_VALID_OR_UNSUPPORTED_PROP(result, toString(value), verifyHealthInfo(value));
321 }));
Yifan Hong69c22542017-10-03 17:40:24 -0700322}
323
Dan Shiba4d5322020-07-28 13:09:30 -0700324GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(HealthHidlTest);
nelsonli4da3ca52019-12-10 17:17:09 +0800325INSTANTIATE_TEST_SUITE_P(
326 PerInstance, HealthHidlTest,
327 testing::ValuesIn(android::hardware::getAllHalInstanceNames(IHealth::descriptor)),
328 android::hardware::PrintInstanceNameToString);
Yifan Hong94841c92020-01-28 16:11:39 -0800329
330// For battery current tests, value may not be stable if the battery current has fluctuated.
331// Retry in a bit more time (with the following timeout) and consider the test successful if it
332// has succeed once.
333static constexpr auto gBatteryTestTimeout = 1min;
334// Tests on battery current signs are only enforced on devices launching with Android 11.
335static constexpr int64_t gBatteryTestMinShippingApiLevel = 30;
336static constexpr double gCurrentCompareFactor = 0.50;
337
338// Tuple for all IHealth::get* API return values.
339template <typename T>
340struct HalResult {
341 Result result;
342 T value;
343};
344
345// Needs to be called repeatedly within a period of time to ensure values are initialized.
346static AssertionResult IsBatteryCurrentSignCorrect(HalResult<BatteryStatus> status,
347 HalResult<int32_t> current,
348 bool acceptZeroCurrentAsUnknown) {
349 // getChargeStatus / getCurrentNow / getCurrentAverage / getHealthInfo already tested above.
350 // Here, just skip if not ok.
351 if (status.result != Result::SUCCESS) {
352 return AssertionSuccess() << "getChargeStatus / getHealthInfo returned "
353 << toString(status.result) << ", skipping";
354 }
355
356 if (current.result != Result::SUCCESS) {
357 return AssertionSuccess() << "getCurrentNow / getCurrentAverage returned "
358 << toString(current.result) << ", skipping";
359 }
360
Yifan Hong2200cff2021-10-28 12:18:35 -0700361 return test_utils::IsBatteryCurrentSignCorrect(
362 status.value, current.value, acceptZeroCurrentAsUnknown,
363 [](BatteryStatus status) { return toString(status); });
Yifan Hong94841c92020-01-28 16:11:39 -0800364}
365
366static AssertionResult IsBatteryCurrentSimilar(HalResult<BatteryStatus> status,
367 HalResult<int32_t> currentNow,
368 HalResult<int32_t> currentAverage) {
369 if (status.result == Result::SUCCESS && status.value == BatteryStatus::FULL) {
370 // No reason to test on full battery because battery current load fluctuates.
371 return AssertionSuccess() << "Battery is full, skipping";
372 }
373
374 // getCurrentNow / getCurrentAverage / getHealthInfo already tested above. Here, just skip if
375 // not SUCCESS or value 0.
376 if (currentNow.result != Result::SUCCESS || currentNow.value == 0) {
377 return AssertionSuccess() << "getCurrentNow returned " << toString(currentNow.result)
378 << " with value " << currentNow.value << ", skipping";
379 }
380
381 if (currentAverage.result != Result::SUCCESS || currentAverage.value == 0) {
382 return AssertionSuccess() << "getCurrentAverage returned "
383 << toString(currentAverage.result) << " with value "
384 << currentAverage.value << ", skipping";
385 }
386
Yifan Hong2200cff2021-10-28 12:18:35 -0700387 return test_utils::IsBatteryCurrentSimilar(currentNow.value, currentAverage.value,
388 gCurrentCompareFactor);
Yifan Hong94841c92020-01-28 16:11:39 -0800389}
390
391uint64_t GetShippingApiLevel() {
392 uint64_t api_level = android::base::GetUintProperty<uint64_t>("ro.product.first_api_level", 0);
393 if (api_level != 0) {
394 return api_level;
395 }
396 return android::base::GetUintProperty<uint64_t>("ro.build.version.sdk", 0);
397}
398
399class BatteryTest : public HealthHidlTest {
400 public:
401 void SetUp() override {
402 HealthHidlTest::SetUp();
403
404 auto shippingApiLevel = GetShippingApiLevel();
405 if (shippingApiLevel < gBatteryTestMinShippingApiLevel) {
406 GTEST_SKIP() << "Skipping on devices with first API level " << shippingApiLevel;
407 }
408 }
409};
410
411TEST_P(BatteryTest, InstantCurrentAgainstChargeStatusInHealthInfo) {
412 auto testOnce = [&]() -> AssertionResult {
413 HalResult<HealthInfo> healthInfo;
414 TEST_AND_RETURN(isOk(mHealth->getHealthInfo([&](auto result, const auto& value) {
415 healthInfo = {result, value};
416 })));
417
418 return IsBatteryCurrentSignCorrect(
419 {healthInfo.result, healthInfo.value.legacy.batteryStatus},
420 {healthInfo.result, healthInfo.value.legacy.batteryCurrent},
421 true /* accept zero current as unknown */);
422 };
423 EXPECT_TRUE(SucceedOnce(gBatteryTestTimeout, testOnce))
424 << "You may want to try again later when current_now becomes stable.";
425}
426
427TEST_P(BatteryTest, AverageCurrentAgainstChargeStatusInHealthInfo) {
428 auto testOnce = [&]() -> AssertionResult {
429 HalResult<HealthInfo> healthInfo;
430 TEST_AND_RETURN(isOk(mHealth->getHealthInfo([&](auto result, const auto& value) {
431 healthInfo = {result, value};
432 })));
433 return IsBatteryCurrentSignCorrect(
434 {healthInfo.result, healthInfo.value.legacy.batteryStatus},
435 {healthInfo.result, healthInfo.value.batteryCurrentAverage},
436 true /* accept zero current as unknown */);
437 };
438
439 EXPECT_TRUE(SucceedOnce(gBatteryTestTimeout, testOnce))
440 << "You may want to try again later when current_average becomes stable.";
441}
442
443TEST_P(BatteryTest, InstantCurrentAgainstAverageCurrentInHealthInfo) {
444 auto testOnce = [&]() -> AssertionResult {
445 HalResult<HealthInfo> healthInfo;
446 TEST_AND_RETURN(isOk(mHealth->getHealthInfo([&](auto result, const auto& value) {
447 healthInfo = {result, value};
448 })));
449 return IsBatteryCurrentSimilar({healthInfo.result, healthInfo.value.legacy.batteryStatus},
450 {healthInfo.result, healthInfo.value.legacy.batteryCurrent},
451 {healthInfo.result, healthInfo.value.batteryCurrentAverage});
452 };
453
454 EXPECT_TRUE(SucceedOnce(gBatteryTestTimeout, testOnce))
455 << "You may want to try again later when current_now and current_average becomes "
456 "stable.";
457}
458
459TEST_P(BatteryTest, InstantCurrentAgainstChargeStatusFromHal) {
460 auto testOnce = [&]() -> AssertionResult {
461 HalResult<BatteryStatus> status;
462 HalResult<int32_t> currentNow;
463 TEST_AND_RETURN(isOk(mHealth->getChargeStatus([&](auto result, auto value) {
464 status = {result, value};
465 })));
466 TEST_AND_RETURN(isOk(mHealth->getCurrentNow([&](auto result, auto value) {
467 currentNow = {result, value};
468 })));
469
470 return IsBatteryCurrentSignCorrect(status, currentNow,
471 false /* accept zero current as unknown */);
472 };
473
474 EXPECT_TRUE(SucceedOnce(gBatteryTestTimeout, testOnce))
475 << "You may want to try again later when current_now becomes stable.";
476}
477
478TEST_P(BatteryTest, AverageCurrentAgainstChargeStatusFromHal) {
479 auto testOnce = [&]() -> AssertionResult {
480 HalResult<BatteryStatus> status;
481 TEST_AND_RETURN(isOk(mHealth->getChargeStatus([&](auto result, auto value) {
482 status = {result, value};
483 })));
484 HalResult<int32_t> currentAverage;
485 TEST_AND_RETURN(isOk(mHealth->getCurrentAverage([&](auto result, auto value) {
486 currentAverage = {result, value};
487 })));
488 return IsBatteryCurrentSignCorrect(status, currentAverage,
489 false /* accept zero current as unknown */);
490 };
491
492 EXPECT_TRUE(SucceedOnce(gBatteryTestTimeout, testOnce))
493 << "You may want to try again later when current_average becomes stable.";
494}
495
496TEST_P(BatteryTest, InstantCurrentAgainstAverageCurrentFromHal) {
497 auto testOnce = [&]() -> AssertionResult {
498 HalResult<BatteryStatus> status;
499 TEST_AND_RETURN(isOk(mHealth->getChargeStatus([&](auto result, auto value) {
500 status = {result, value};
501 })));
502 HalResult<int32_t> currentNow;
503 TEST_AND_RETURN(isOk(mHealth->getCurrentNow([&](auto result, auto value) {
504 currentNow = {result, value};
505 })));
506 HalResult<int32_t> currentAverage;
507 TEST_AND_RETURN(isOk(mHealth->getCurrentAverage([&](auto result, auto value) {
508 currentAverage = {result, value};
509 })));
510 return IsBatteryCurrentSimilar(status, currentNow, currentAverage);
511 };
512
513 EXPECT_TRUE(SucceedOnce(gBatteryTestTimeout, testOnce))
514 << "You may want to try again later when current_average becomes stable.";
515}
516
517AssertionResult IsBatteryStatusCorrect(HalResult<BatteryStatus> status,
518 HalResult<HealthInfo> healthInfo) {
519 // getChargetStatus / getHealthInfo is already tested above. Here, just skip if not ok.
520 if (healthInfo.result != Result::SUCCESS) {
521 return AssertionSuccess() << "getHealthInfo returned " << toString(healthInfo.result)
522 << ", skipping";
523 }
524 if (status.result != Result::SUCCESS) {
525 return AssertionSuccess() << "getChargeStatus returned " << toString(status.result)
526 << ", skipping";
527 }
528
529 const auto& batteryInfo = healthInfo.value.legacy;
Yifan Hong2200cff2021-10-28 12:18:35 -0700530 return test_utils::IsBatteryStatusCorrect(
531 status.value, batteryInfo, [](BatteryStatus status) { return toString(status); });
Yifan Hong94841c92020-01-28 16:11:39 -0800532}
533
534TEST_P(BatteryTest, ConnectedAgainstStatusFromHal) {
535 auto testOnce = [&]() -> AssertionResult {
536 HalResult<BatteryStatus> status;
537 TEST_AND_RETURN(isOk(mHealth->getChargeStatus([&](auto result, auto value) {
538 status = {result, value};
539 })));
540 HalResult<HealthInfo> healthInfo;
541 TEST_AND_RETURN(isOk(mHealth->getHealthInfo([&](auto result, const auto& value) {
542 healthInfo = {result, value};
543 })));
544 return IsBatteryStatusCorrect(status, healthInfo);
545 };
546
547 EXPECT_TRUE(SucceedOnce(gBatteryTestTimeout, testOnce))
548 << "You may want to try again later when battery_status becomes stable.";
549}
550
551TEST_P(BatteryTest, ConnectedAgainstStatusInHealthInfo) {
552 auto testOnce = [&]() -> AssertionResult {
553 HalResult<HealthInfo> healthInfo;
554 TEST_AND_RETURN(isOk(mHealth->getHealthInfo([&](auto result, const auto& value) {
555 healthInfo = {result, value};
556 })));
557 return IsBatteryStatusCorrect({healthInfo.result, healthInfo.value.legacy.batteryStatus},
558 healthInfo);
559 };
560
561 EXPECT_TRUE(SucceedOnce(gBatteryTestTimeout, testOnce))
562 << "You may want to try again later when getHealthInfo becomes stable.";
563}
564
Dan Shiba4d5322020-07-28 13:09:30 -0700565GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(BatteryTest);
Yifan Hong94841c92020-01-28 16:11:39 -0800566INSTANTIATE_TEST_SUITE_P(
567 PerInstance, BatteryTest,
568 testing::ValuesIn(android::hardware::getAllHalInstanceNames(IHealth::descriptor)),
569 android::hardware::PrintInstanceNameToString);
570
Yifan Hong69c22542017-10-03 17:40:24 -0700571} // namespace V2_0
572} // namespace health
573} // namespace hardware
574} // namespace android
575
576int main(int argc, char** argv) {
Yifan Hong69c22542017-10-03 17:40:24 -0700577 ::testing::InitGoogleTest(&argc, argv);
Yifan Honge6807dd2019-03-07 13:04:33 -0800578 gflags::ParseCommandLineFlags(&argc, &argv, true /* remove flags */);
nelsonli4da3ca52019-12-10 17:17:09 +0800579 return RUN_ALL_TESTS();
Yifan Hong69c22542017-10-03 17:40:24 -0700580}