blob: e75b299b0b3939b63a3ebfad77822f9de8df4edb [file] [log] [blame]
Yifan Honged0fead2019-10-02 18:22:12 -07001/*
2 * Copyright (C) 2019 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 "health_hidl_hal_test"
18
19#include <mutex>
20#include <set>
21#include <string>
22
23#include <android-base/logging.h>
24#include <android/hardware/health/1.0/types.h>
25#include <android/hardware/health/2.0/types.h>
26#include <android/hardware/health/2.1/IHealth.h>
27#include <android/hardware/health/2.1/IHealthInfoCallback.h>
28#include <android/hardware/health/2.1/types.h>
29#include <gmock/gmock.h>
30#include <gtest/gtest.h>
31#include <hidl/GtestPrinter.h>
32#include <hidl/ServiceManagement.h>
33
34using ::android::hardware::health::V1_0::BatteryStatus;
35using ::android::hardware::health::V2_0::Result;
36using ::testing::AnyOf;
37using ::testing::AssertionFailure;
38using ::testing::AssertionResult;
39using ::testing::AssertionSuccess;
40using namespace std::chrono_literals;
41
42using ::android::hardware::health::V1_0::toString;
43using ::android::hardware::health::V2_0::toString;
44using ::android::hardware::health::V2_1::toString;
45
46// Return expr if it is evaluated to false.
47#define TEST_AND_RETURN(expr) \
48 do { \
49 auto res = (expr); \
50 if (!res) return res; \
51 } while (0)
52
53// Return a descriptive AssertionFailure() if expr is evaluated to false.
54#define TEST_AND_RETURN_FAILURE(expr) \
55 do { \
56 auto res = (expr); \
57 if (!res) { \
58 return AssertionFailure() << #expr " is false"; \
59 } \
60 } while (0)
61
62namespace android {
63namespace hardware {
64namespace health {
65
66namespace V2_0 {
67std::ostream& operator<<(std::ostream& os, const Result& res) {
68 return os << toString(res);
69}
70} // namespace V2_0
71
72namespace V2_1 {
73
74class HealthHidlTest : public testing::TestWithParam<std::string> {
75 public:
76 virtual void SetUp() override {
77 service_ = IHealth::getService(GetParam());
78 ASSERT_NE(nullptr, service_.get()) << "Instance '" << GetParam() << "'' is not available.";
79 }
80
81 sp<IHealth> service_;
82};
83
84class CallbackBase {
85 public:
86 Return<void> healthInfoChangedInternal() {
87 std::lock_guard<std::mutex> lock(mutex_);
88 invoked_ = true;
89 invoked_notify_.notify_all();
90 return Void();
91 }
92 template <typename R, typename P>
93 bool waitInvoke(std::chrono::duration<R, P> duration) {
94 std::unique_lock<std::mutex> lock(mutex_);
95 bool r = invoked_notify_.wait_for(lock, duration, [this] { return this->invoked_; });
96 invoked_ = false;
97 return r;
98 }
99
100 private:
101 std::mutex mutex_;
102 std::condition_variable invoked_notify_;
103 bool invoked_ = false;
104};
105
106class Callback_2_0 : public android::hardware::health::V2_0::IHealthInfoCallback,
107 public CallbackBase {
108 Return<void> healthInfoChanged(const android::hardware::health::V2_0::HealthInfo&) override {
109 return healthInfoChangedInternal();
110 }
111};
112
113class Callback_2_1 : public android::hardware::health::V2_1::IHealthInfoCallback,
114 public CallbackBase {
115 Return<void> healthInfoChanged(const android::hardware::health::V2_0::HealthInfo&) override {
116 ADD_FAILURE() << "android::hardware::health::V2_1::IHealthInfoCallback::healthInfoChanged "
117 << "is called, but it shouldn't be";
118 return Void();
119 }
120 Return<void> healthInfoChanged_2_1(const HealthInfo&) override {
121 return healthInfoChangedInternal();
122 }
123};
124
125template <typename T>
126AssertionResult IsOk(const Return<T>& r) {
127 return r.isOk() ? AssertionSuccess() : (AssertionFailure() << r.description());
128}
129
130// Both IsOk() and Result::SUCCESS
131AssertionResult ResultIsSuccess(const Return<Result>& r) {
132 if (!r.isOk()) {
133 return AssertionFailure() << r.description();
134 }
135 if (static_cast<Result>(r) != Result::SUCCESS) {
136 return AssertionFailure() << toString(static_cast<Result>(r));
137 }
138 return AssertionSuccess();
139}
140
141/**
142 * Test whether callbacks work. Tested functions are IHealth::registerCallback,
143 * unregisterCallback, and update.
144 */
145template <typename Callback>
146AssertionResult TestCallbacks(sp<IHealth> service) {
147 sp<Callback> first = new Callback();
148 sp<Callback> second = new Callback();
149
150 TEST_AND_RETURN(ResultIsSuccess(service->registerCallback(first)));
151 TEST_AND_RETURN(ResultIsSuccess(service->registerCallback(second)));
152
153 // registerCallback may or may not invoke the callback immediately, so the test needs
154 // to wait for the invocation. If the implementation chooses not to invoke the callback
155 // immediately, just wait for some time.
156 first->waitInvoke(200ms);
157 second->waitInvoke(200ms);
158
159 // assert that the first callback is invoked when update is called.
160 TEST_AND_RETURN(ResultIsSuccess(service->update()));
161
162 TEST_AND_RETURN_FAILURE(first->waitInvoke(1s));
163 TEST_AND_RETURN_FAILURE(second->waitInvoke(1s));
164
165 TEST_AND_RETURN(ResultIsSuccess(service->unregisterCallback(first)));
166
167 // clear any potentially pending callbacks result from wakealarm / kernel events
168 // If there is none, just wait for some time.
169 first->waitInvoke(200ms);
170 second->waitInvoke(200ms);
171
172 // assert that the second callback is still invoked even though the first is unregistered.
173 TEST_AND_RETURN(ResultIsSuccess(service->update()));
174
175 TEST_AND_RETURN_FAILURE(!first->waitInvoke(200ms));
176 TEST_AND_RETURN_FAILURE(second->waitInvoke(1s));
177
178 TEST_AND_RETURN(ResultIsSuccess(service->unregisterCallback(second)));
179 return AssertionSuccess();
180}
181
182TEST_P(HealthHidlTest, Callbacks_2_0) {
183 EXPECT_TRUE(TestCallbacks<Callback_2_0>(service_));
184}
185
186TEST_P(HealthHidlTest, Callbacks_2_1) {
187 EXPECT_TRUE(TestCallbacks<Callback_2_1>(service_));
188}
189
190template <typename Callback>
191AssertionResult TestUnregisterNonExistentCallback(sp<IHealth> service) {
192 sp<Callback> callback = new Callback();
193 auto ret = service->unregisterCallback(callback);
194 TEST_AND_RETURN(IsOk(ret));
195 if (static_cast<Result>(ret) != Result::NOT_FOUND) {
196 return AssertionFailure()
197 << "Unregistering non-existent callback should return NOT_FOUND, but returned "
198 << static_cast<Result>(ret);
199 }
200 return AssertionSuccess();
201}
202
203TEST_P(HealthHidlTest, UnregisterNonExistentCallback_2_0) {
204 EXPECT_TRUE(TestUnregisterNonExistentCallback<Callback_2_0>(service_));
205}
206
207TEST_P(HealthHidlTest, UnregisterNonExistentCallback_2_1) {
208 EXPECT_TRUE(TestUnregisterNonExistentCallback<Callback_2_1>(service_));
209}
210
211template <typename T>
212AssertionResult IsEnum(T value) {
213 for (auto it : hidl_enum_range<T>()) {
214 if (it == value) {
215 return AssertionSuccess();
216 }
217 }
218
219 return AssertionFailure() << static_cast<std::underlying_type_t<T>>(value) << " is not valid";
220}
221
222/*
223 * Tests the values returned by getHealthInfo() from interface IHealth.
224 */
225TEST_P(HealthHidlTest, getHealthInfo_2_1) {
226 EXPECT_TRUE(IsOk(service_->getHealthInfo_2_1([](auto result, const auto& value) {
227 if (result == Result::NOT_SUPPORTED) {
228 return;
229 }
230 ASSERT_EQ(Result::SUCCESS, result);
231 const auto& legacy = value.legacy.legacy;
232
233 EXPECT_TRUE(IsEnum(value.batteryCapacityLevel)) << " BatteryCapacityLevel";
234 EXPECT_GE(value.batteryChargeTimeToFullNowSeconds, 0);
235
Yifan Hong3f91f292020-01-28 18:48:11 -0800236 EXPECT_GE(value.batteryFullCapacityUah, 0)
237 << "batteryFullCapacityUah should not be negative";
238
239 if (value.batteryFullCapacityUah > 0) {
240 EXPECT_GE(value.batteryFullCapacityUah, legacy.batteryFullCharge * 0.50);
241 EXPECT_LE(value.batteryFullCapacityUah, legacy.batteryFullCharge * 1.20);
242 }
Yifan Honged0fead2019-10-02 18:22:12 -0700243 })));
244}
245
246TEST_P(HealthHidlTest, getHealthConfig) {
247 EXPECT_TRUE(IsOk(service_->getHealthConfig([](auto result, const auto&) {
248 EXPECT_THAT(result, AnyOf(Result::SUCCESS, Result::NOT_SUPPORTED));
249 })));
250}
251
252TEST_P(HealthHidlTest, shouldKeepScreenOn) {
253 EXPECT_TRUE(IsOk(service_->shouldKeepScreenOn([](auto result, const auto&) {
254 EXPECT_THAT(result, AnyOf(Result::SUCCESS, Result::NOT_SUPPORTED));
255 })));
256}
257
258INSTANTIATE_TEST_SUITE_P(
Haibo Huang83b4c1e2019-11-08 11:59:40 -0800259 PerInstance, HealthHidlTest,
Yifan Honged0fead2019-10-02 18:22:12 -0700260 testing::ValuesIn(android::hardware::getAllHalInstanceNames(IHealth::descriptor)),
261 android::hardware::PrintInstanceNameToString);
262
263} // namespace V2_1
264} // namespace health
265} // namespace hardware
266} // namespace android
267
268int main(int argc, char** argv) {
269 ::testing::InitGoogleTest(&argc, argv);
270 int status = RUN_ALL_TESTS();
271 LOG(INFO) << "Test result = " << status;
272 return status;
273}