blob: 012988387e8f5888fde8ebd82fdd715b291cb027 [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
19#include <mutex>
Yifan Hong03b2a342019-03-08 11:37:33 -080020#include <set>
21#include <string>
Yifan Hong69c22542017-10-03 17:40:24 -070022
Yifan Hong69c22542017-10-03 17:40:24 -070023#include <android-base/logging.h>
24#include <android/hardware/health/2.0/IHealth.h>
25#include <android/hardware/health/2.0/types.h>
Yifan Honge6807dd2019-03-07 13:04:33 -080026#include <gflags/gflags.h>
nelsonli4da3ca52019-12-10 17:17:09 +080027#include <gtest/gtest.h>
28#include <hidl/GtestPrinter.h>
29#include <hidl/ServiceManagement.h>
30#include <log/log.h>
Yifan Hong69c22542017-10-03 17:40:24 -070031
32using ::testing::AssertionFailure;
33using ::testing::AssertionResult;
34using ::testing::AssertionSuccess;
Yifan Hong69c22542017-10-03 17:40:24 -070035
Yifan Honge6807dd2019-03-07 13:04:33 -080036DEFINE_bool(force, false, "Force test healthd even when the default instance is present.");
37
Yifan Hong69c22542017-10-03 17:40:24 -070038namespace android {
39namespace hardware {
40namespace health {
41namespace V2_0 {
42
43using V1_0::BatteryStatus;
Yifan Hong69c22542017-10-03 17:40:24 -070044
nelsonli4da3ca52019-12-10 17:17:09 +080045class HealthHidlTest : public ::testing::TestWithParam<std::string> {
Yifan Hong69c22542017-10-03 17:40:24 -070046 public:
47 virtual void SetUp() override {
nelsonli4da3ca52019-12-10 17:17:09 +080048 std::string serviceName = GetParam();
Yifan Honge6807dd2019-03-07 13:04:33 -080049
50 if (serviceName == "backup" && !FLAGS_force &&
nelsonli4da3ca52019-12-10 17:17:09 +080051 IHealth::getService() != nullptr) {
Yifan Honge6807dd2019-03-07 13:04:33 -080052 LOG(INFO) << "Skipping tests on healthd because the default instance is present. "
53 << "Use --force if you really want to test healthd.";
54 GTEST_SKIP();
55 }
56
Yifan Hong69c22542017-10-03 17:40:24 -070057 LOG(INFO) << "get service with name:" << serviceName;
58 ASSERT_FALSE(serviceName.empty());
nelsonli4da3ca52019-12-10 17:17:09 +080059 mHealth = IHealth::getService(serviceName);
Yifan Hong69c22542017-10-03 17:40:24 -070060 ASSERT_NE(mHealth, nullptr);
61 }
62
63 sp<IHealth> mHealth;
64};
65
66class Callback : public IHealthInfoCallback {
Yifan Hong69c22542017-10-03 17:40:24 -070067 public:
Hridya Valsarajud31932a2018-01-17 23:09:24 -080068 Return<void> healthInfoChanged(const HealthInfo&) override {
Yifan Hongd6ea57e2017-11-20 14:41:09 -080069 std::lock_guard<std::mutex> lock(mMutex);
70 mInvoked = true;
71 mInvokedNotify.notify_all();
Yifan Hong69c22542017-10-03 17:40:24 -070072 return Void();
73 }
Yifan Hongd6ea57e2017-11-20 14:41:09 -080074 template <typename R, typename P>
75 bool waitInvoke(std::chrono::duration<R, P> duration) {
Yifan Hong69c22542017-10-03 17:40:24 -070076 std::unique_lock<std::mutex> lock(mMutex);
Yifan Hongd6ea57e2017-11-20 14:41:09 -080077 bool r = mInvokedNotify.wait_for(lock, duration, [this] { return this->mInvoked; });
78 mInvoked = false;
79 return r;
Yifan Hong69c22542017-10-03 17:40:24 -070080 }
Yifan Hong69c22542017-10-03 17:40:24 -070081 private:
82 std::mutex mMutex;
Yifan Hongd6ea57e2017-11-20 14:41:09 -080083 std::condition_variable mInvokedNotify;
84 bool mInvoked = false;
Yifan Hong69c22542017-10-03 17:40:24 -070085};
86
87#define ASSERT_OK(r) ASSERT_TRUE(isOk(r))
88#define EXPECT_OK(r) EXPECT_TRUE(isOk(r))
89template <typename T>
90AssertionResult isOk(const Return<T>& r) {
91 return r.isOk() ? AssertionSuccess() : (AssertionFailure() << r.description());
92}
93
94#define ASSERT_ALL_OK(r) ASSERT_TRUE(isAllOk(r))
95// Both isOk() and Result::SUCCESS
96AssertionResult isAllOk(const Return<Result>& r) {
97 if (!r.isOk()) {
98 return AssertionFailure() << r.description();
99 }
100 if (static_cast<Result>(r) != Result::SUCCESS) {
101 return AssertionFailure() << toString(static_cast<Result>(r));
102 }
103 return AssertionSuccess();
104}
105
106/**
107 * Test whether callbacks work. Tested functions are IHealth::registerCallback,
108 * unregisterCallback, and update.
109 */
nelsonli4da3ca52019-12-10 17:17:09 +0800110TEST_P(HealthHidlTest, Callbacks) {
Yifan Hong69c22542017-10-03 17:40:24 -0700111 using namespace std::chrono_literals;
Yifan Hongd6ea57e2017-11-20 14:41:09 -0800112 sp<Callback> firstCallback = new Callback();
113 sp<Callback> secondCallback = new Callback();
Yifan Hong69c22542017-10-03 17:40:24 -0700114
115 ASSERT_ALL_OK(mHealth->registerCallback(firstCallback));
116 ASSERT_ALL_OK(mHealth->registerCallback(secondCallback));
117
Yifan Hongd6ea57e2017-11-20 14:41:09 -0800118 // registerCallback may or may not invoke the callback immediately, so the test needs
119 // to wait for the invocation. If the implementation chooses not to invoke the callback
120 // immediately, just wait for some time.
121 firstCallback->waitInvoke(200ms);
122 secondCallback->waitInvoke(200ms);
Yifan Hong69c22542017-10-03 17:40:24 -0700123
Yifan Hongd6ea57e2017-11-20 14:41:09 -0800124 // assert that the first callback is invoked when update is called.
Yifan Hong69c22542017-10-03 17:40:24 -0700125 ASSERT_ALL_OK(mHealth->update());
126
Yifan Hongd6ea57e2017-11-20 14:41:09 -0800127 ASSERT_TRUE(firstCallback->waitInvoke(1s));
128 ASSERT_TRUE(secondCallback->waitInvoke(1s));
Yifan Hong69c22542017-10-03 17:40:24 -0700129
130 ASSERT_ALL_OK(mHealth->unregisterCallback(firstCallback));
131
Yifan Hongd6ea57e2017-11-20 14:41:09 -0800132 // clear any potentially pending callbacks result from wakealarm / kernel events
133 // If there is none, just wait for some time.
134 firstCallback->waitInvoke(200ms);
135 secondCallback->waitInvoke(200ms);
Yifan Hong69c22542017-10-03 17:40:24 -0700136
Yifan Hongd6ea57e2017-11-20 14:41:09 -0800137 // assert that the second callback is still invoked even though the first is unregistered.
Yifan Hong69c22542017-10-03 17:40:24 -0700138 ASSERT_ALL_OK(mHealth->update());
139
Yifan Hongd6ea57e2017-11-20 14:41:09 -0800140 ASSERT_FALSE(firstCallback->waitInvoke(200ms));
141 ASSERT_TRUE(secondCallback->waitInvoke(1s));
Yifan Hong69c22542017-10-03 17:40:24 -0700142
143 ASSERT_ALL_OK(mHealth->unregisterCallback(secondCallback));
Yifan Hong69c22542017-10-03 17:40:24 -0700144}
145
nelsonli4da3ca52019-12-10 17:17:09 +0800146TEST_P(HealthHidlTest, UnregisterNonExistentCallback) {
Yifan Hongd6ea57e2017-11-20 14:41:09 -0800147 sp<Callback> callback = new Callback();
Yifan Hong69c22542017-10-03 17:40:24 -0700148 auto ret = mHealth->unregisterCallback(callback);
149 ASSERT_OK(ret);
150 ASSERT_EQ(Result::NOT_FOUND, static_cast<Result>(ret)) << "Actual: " << toString(ret);
151}
152
153/**
154 * Pass the test if:
155 * - Property is not supported (res == NOT_SUPPORTED)
156 * - Result is success, and predicate is true
157 * @param res the Result value.
158 * @param valueStr the string representation for actual value (for error message)
159 * @param pred a predicate that test whether the value is valid
160 */
161#define EXPECT_VALID_OR_UNSUPPORTED_PROP(res, valueStr, pred) \
162 EXPECT_TRUE(isPropertyOk(res, valueStr, pred, #pred))
163
164AssertionResult isPropertyOk(Result res, const std::string& valueStr, bool pred,
165 const std::string& predStr) {
166 if (res == Result::SUCCESS) {
167 if (pred) {
168 return AssertionSuccess();
169 }
170 return AssertionFailure() << "value doesn't match.\nActual: " << valueStr
171 << "\nExpected: " << predStr;
172 }
173 if (res == Result::NOT_SUPPORTED) {
174 return AssertionSuccess();
175 }
176 return AssertionFailure() << "Result is not SUCCESS or NOT_SUPPORTED: " << toString(res);
177}
178
Hridya Valsaraju2120ecc2017-12-20 13:27:52 -0800179bool verifyStorageInfo(const hidl_vec<struct StorageInfo>& info) {
180 for (size_t i = 0; i < info.size(); i++) {
181 if (!(0 <= info[i].eol && info[i].eol <= 3 && 0 <= info[i].lifetimeA &&
182 info[i].lifetimeA <= 0x0B && 0 <= info[i].lifetimeB && info[i].lifetimeB <= 0x0B)) {
183 return false;
184 }
185 }
186
187 return true;
188}
189
Hridya Valsaraju87e29602018-01-12 17:46:22 -0800190template <typename T>
191bool verifyEnum(T value) {
Steven Morelandc90461c2018-05-01 16:54:09 -0700192 for (auto it : hidl_enum_range<T>()) {
Hridya Valsaraju87e29602018-01-12 17:46:22 -0800193 if (it == value) {
194 return true;
195 }
196 }
197
198 return false;
199}
200
201bool verifyHealthInfo(const HealthInfo& health_info) {
Hridya Valsaraju075c1822018-04-03 11:19:08 -0700202 if (!verifyStorageInfo(health_info.storageInfos)) {
Hridya Valsaraju87e29602018-01-12 17:46:22 -0800203 return false;
204 }
205
206 using V1_0::BatteryStatus;
207 using V1_0::BatteryHealth;
208
Robin Leeac5a0d32019-10-09 15:48:17 +0200209 if (!((health_info.legacy.batteryCurrent != INT32_MIN) &&
Hridya Valsaraju87e29602018-01-12 17:46:22 -0800210 (0 <= health_info.legacy.batteryLevel && health_info.legacy.batteryLevel <= 100) &&
211 verifyEnum<BatteryHealth>(health_info.legacy.batteryHealth) &&
Hridya Valsaraju87e29602018-01-12 17:46:22 -0800212 verifyEnum<BatteryStatus>(health_info.legacy.batteryStatus))) {
213 return false;
214 }
215
Robin Leeac5a0d32019-10-09 15:48:17 +0200216 if (health_info.legacy.batteryPresent) {
217 // If a battery is present, the battery status must be known.
218 if (!((health_info.legacy.batteryChargeCounter > 0) &&
219 (health_info.legacy.batteryStatus != BatteryStatus::UNKNOWN))) {
220 return false;
221 }
222 }
223
Hridya Valsaraju87e29602018-01-12 17:46:22 -0800224 return true;
225}
226
227/*
Yifan Hong26c12002018-10-02 14:52:02 -0700228 * Tests the values returned by getChargeCounter() from interface IHealth.
Hridya Valsaraju87e29602018-01-12 17:46:22 -0800229 */
nelsonli4da3ca52019-12-10 17:17:09 +0800230TEST_P(HealthHidlTest, getChargeCounter) {
Yifan Hong69c22542017-10-03 17:40:24 -0700231 EXPECT_OK(mHealth->getChargeCounter([](auto result, auto value) {
232 EXPECT_VALID_OR_UNSUPPORTED_PROP(result, std::to_string(value), value > 0);
233 }));
Yifan Hong26c12002018-10-02 14:52:02 -0700234}
235
236/*
237 * Tests the values returned by getCurrentNow() from interface IHealth.
238 */
nelsonli4da3ca52019-12-10 17:17:09 +0800239TEST_P(HealthHidlTest, getCurrentNow) {
Yifan Hong69c22542017-10-03 17:40:24 -0700240 EXPECT_OK(mHealth->getCurrentNow([](auto result, auto value) {
241 EXPECT_VALID_OR_UNSUPPORTED_PROP(result, std::to_string(value), value != INT32_MIN);
242 }));
Yifan Hong26c12002018-10-02 14:52:02 -0700243}
244
245/*
246 * Tests the values returned by getCurrentAverage() from interface IHealth.
247 */
nelsonli4da3ca52019-12-10 17:17:09 +0800248TEST_P(HealthHidlTest, getCurrentAverage) {
Yifan Hong69c22542017-10-03 17:40:24 -0700249 EXPECT_OK(mHealth->getCurrentAverage([](auto result, auto value) {
250 EXPECT_VALID_OR_UNSUPPORTED_PROP(result, std::to_string(value), value != INT32_MIN);
251 }));
Yifan Hong26c12002018-10-02 14:52:02 -0700252}
253
254/*
255 * Tests the values returned by getCapacity() from interface IHealth.
256 */
nelsonli4da3ca52019-12-10 17:17:09 +0800257TEST_P(HealthHidlTest, getCapacity) {
Yifan Hong69c22542017-10-03 17:40:24 -0700258 EXPECT_OK(mHealth->getCapacity([](auto result, auto value) {
259 EXPECT_VALID_OR_UNSUPPORTED_PROP(result, std::to_string(value), 0 <= value && value <= 100);
260 }));
Yifan Hong26c12002018-10-02 14:52:02 -0700261}
262
263/*
264 * Tests the values returned by getEnergyCounter() from interface IHealth.
265 */
nelsonli4da3ca52019-12-10 17:17:09 +0800266TEST_P(HealthHidlTest, getEnergyCounter) {
Yifan Hong69c22542017-10-03 17:40:24 -0700267 EXPECT_OK(mHealth->getEnergyCounter([](auto result, auto value) {
268 EXPECT_VALID_OR_UNSUPPORTED_PROP(result, std::to_string(value), value != INT64_MIN);
269 }));
Yifan Hong26c12002018-10-02 14:52:02 -0700270}
271
272/*
273 * Tests the values returned by getChargeStatus() from interface IHealth.
274 */
nelsonli4da3ca52019-12-10 17:17:09 +0800275TEST_P(HealthHidlTest, getChargeStatus) {
Yifan Hong69c22542017-10-03 17:40:24 -0700276 EXPECT_OK(mHealth->getChargeStatus([](auto result, auto value) {
Yifan Hong5ac6f5b2020-01-27 16:20:49 -0800277 EXPECT_VALID_OR_UNSUPPORTED_PROP(result, toString(value), verifyEnum<BatteryStatus>(value));
Yifan Hong69c22542017-10-03 17:40:24 -0700278 }));
Yifan Hong26c12002018-10-02 14:52:02 -0700279}
280
281/*
282 * Tests the values returned by getStorageInfo() from interface IHealth.
283 */
nelsonli4da3ca52019-12-10 17:17:09 +0800284TEST_P(HealthHidlTest, getStorageInfo) {
Hridya Valsaraju2120ecc2017-12-20 13:27:52 -0800285 EXPECT_OK(mHealth->getStorageInfo([](auto result, auto& value) {
Hridya Valsaraju87e29602018-01-12 17:46:22 -0800286 EXPECT_VALID_OR_UNSUPPORTED_PROP(result, toString(value), verifyStorageInfo(value));
Hridya Valsaraju2120ecc2017-12-20 13:27:52 -0800287 }));
Yifan Hong26c12002018-10-02 14:52:02 -0700288}
289
290/*
291 * Tests the values returned by getDiskStats() from interface IHealth.
292 */
nelsonli4da3ca52019-12-10 17:17:09 +0800293TEST_P(HealthHidlTest, getDiskStats) {
Hridya Valsaraju2120ecc2017-12-20 13:27:52 -0800294 EXPECT_OK(mHealth->getDiskStats([](auto result, auto& value) {
Hridya Valsaraju075c1822018-04-03 11:19:08 -0700295 EXPECT_VALID_OR_UNSUPPORTED_PROP(result, toString(value), true);
Hridya Valsaraju2120ecc2017-12-20 13:27:52 -0800296 }));
Yifan Hong26c12002018-10-02 14:52:02 -0700297}
298
299/*
300 * Tests the values returned by getHealthInfo() from interface IHealth.
301 */
nelsonli4da3ca52019-12-10 17:17:09 +0800302TEST_P(HealthHidlTest, getHealthInfo) {
Hridya Valsaraju87e29602018-01-12 17:46:22 -0800303 EXPECT_OK(mHealth->getHealthInfo([](auto result, auto& value) {
304 EXPECT_VALID_OR_UNSUPPORTED_PROP(result, toString(value), verifyHealthInfo(value));
305 }));
Yifan Hong69c22542017-10-03 17:40:24 -0700306}
307
nelsonli4da3ca52019-12-10 17:17:09 +0800308INSTANTIATE_TEST_SUITE_P(
309 PerInstance, HealthHidlTest,
310 testing::ValuesIn(android::hardware::getAllHalInstanceNames(IHealth::descriptor)),
311 android::hardware::PrintInstanceNameToString);
Yifan Hong69c22542017-10-03 17:40:24 -0700312} // namespace V2_0
313} // namespace health
314} // namespace hardware
315} // namespace android
316
317int main(int argc, char** argv) {
Yifan Hong69c22542017-10-03 17:40:24 -0700318 ::testing::InitGoogleTest(&argc, argv);
Yifan Honge6807dd2019-03-07 13:04:33 -0800319 gflags::ParseCommandLineFlags(&argc, &argv, true /* remove flags */);
nelsonli4da3ca52019-12-10 17:17:09 +0800320 return RUN_ALL_TESTS();
Yifan Hong69c22542017-10-03 17:40:24 -0700321}