]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - android/platform-hardware-interfaces.git/blob - health/2.0/vts/functional/VtsHalHealthV2_0TargetTest.cpp
health: registerCallback() and getHealthInfo() does not notify all callbacks
[android/platform-hardware-interfaces.git] / health / 2.0 / vts / functional / VtsHalHealthV2_0TargetTest.cpp
1 /*
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  */
17 #define LOG_TAG "health_hidl_hal_test"
19 #include <mutex>
21 #include <VtsHalHidlTargetTestBase.h>
22 #include <android-base/logging.h>
23 #include <android/hardware/health/2.0/IHealth.h>
24 #include <android/hardware/health/2.0/types.h>
26 using ::testing::AssertionFailure;
27 using ::testing::AssertionResult;
28 using ::testing::AssertionSuccess;
29 using ::testing::VtsHalHidlTargetTestBase;
30 using ::testing::VtsHalHidlTargetTestEnvBase;
32 namespace android {
33 namespace hardware {
34 namespace health {
35 namespace V2_0 {
37 using V1_0::BatteryStatus;
39 // Test environment for graphics.composer
40 class HealthHidlEnvironment : public VtsHalHidlTargetTestEnvBase {
41    public:
42     // get the test environment singleton
43     static HealthHidlEnvironment* Instance() {
44         static HealthHidlEnvironment* instance = new HealthHidlEnvironment;
45         return instance;
46     }
48     virtual void registerTestServices() override { registerTestService<IHealth>(); }
50    private:
51     HealthHidlEnvironment() {}
53     GTEST_DISALLOW_COPY_AND_ASSIGN_(HealthHidlEnvironment);
54 };
56 class HealthHidlTest : public ::testing::VtsHalHidlTargetTestBase {
57    public:
58     virtual void SetUp() override {
59         std::string serviceName = HealthHidlEnvironment::Instance()->getServiceName<IHealth>();
60         LOG(INFO) << "get service with name:" << serviceName;
61         ASSERT_FALSE(serviceName.empty());
62         mHealth = ::testing::VtsHalHidlTargetTestBase::getService<IHealth>(serviceName);
63         ASSERT_NE(mHealth, nullptr);
64     }
66     sp<IHealth> mHealth;
67 };
69 class Callback : public IHealthInfoCallback {
70    public:
71     Return<void> healthInfoChanged(const HealthInfo&) override {
72         std::lock_guard<std::mutex> lock(mMutex);
73         mInvoked = true;
74         mInvokedNotify.notify_all();
75         return Void();
76     }
77     template <typename R, typename P>
78     bool waitInvoke(std::chrono::duration<R, P> duration) {
79         std::unique_lock<std::mutex> lock(mMutex);
80         bool r = mInvokedNotify.wait_for(lock, duration, [this] { return this->mInvoked; });
81         mInvoked = false;
82         return r;
83     }
84    private:
85     std::mutex mMutex;
86     std::condition_variable mInvokedNotify;
87     bool mInvoked = false;
88 };
90 #define ASSERT_OK(r) ASSERT_TRUE(isOk(r))
91 #define EXPECT_OK(r) EXPECT_TRUE(isOk(r))
92 template <typename T>
93 AssertionResult isOk(const Return<T>& r) {
94     return r.isOk() ? AssertionSuccess() : (AssertionFailure() << r.description());
95 }
97 #define ASSERT_ALL_OK(r) ASSERT_TRUE(isAllOk(r))
98 // Both isOk() and Result::SUCCESS
99 AssertionResult isAllOk(const Return<Result>& r) {
100     if (!r.isOk()) {
101         return AssertionFailure() << r.description();
102     }
103     if (static_cast<Result>(r) != Result::SUCCESS) {
104         return AssertionFailure() << toString(static_cast<Result>(r));
105     }
106     return AssertionSuccess();
109 /**
110  * Test whether callbacks work. Tested functions are IHealth::registerCallback,
111  * unregisterCallback, and update.
112  */
113 TEST_F(HealthHidlTest, Callbacks) {
114     using namespace std::chrono_literals;
115     sp<Callback> firstCallback = new Callback();
116     sp<Callback> secondCallback = new Callback();
118     ASSERT_ALL_OK(mHealth->registerCallback(firstCallback));
119     ASSERT_ALL_OK(mHealth->registerCallback(secondCallback));
121     // registerCallback may or may not invoke the callback immediately, so the test needs
122     // to wait for the invocation. If the implementation chooses not to invoke the callback
123     // immediately, just wait for some time.
124     firstCallback->waitInvoke(200ms);
125     secondCallback->waitInvoke(200ms);
127     // assert that the first callback is invoked when update is called.
128     ASSERT_ALL_OK(mHealth->update());
130     ASSERT_TRUE(firstCallback->waitInvoke(1s));
131     ASSERT_TRUE(secondCallback->waitInvoke(1s));
133     ASSERT_ALL_OK(mHealth->unregisterCallback(firstCallback));
135     // clear any potentially pending callbacks result from wakealarm / kernel events
136     // If there is none, just wait for some time.
137     firstCallback->waitInvoke(200ms);
138     secondCallback->waitInvoke(200ms);
140     // assert that the second callback is still invoked even though the first is unregistered.
141     ASSERT_ALL_OK(mHealth->update());
143     ASSERT_FALSE(firstCallback->waitInvoke(200ms));
144     ASSERT_TRUE(secondCallback->waitInvoke(1s));
146     ASSERT_ALL_OK(mHealth->unregisterCallback(secondCallback));
149 TEST_F(HealthHidlTest, UnregisterNonExistentCallback) {
150     sp<Callback> callback = new Callback();
151     auto ret = mHealth->unregisterCallback(callback);
152     ASSERT_OK(ret);
153     ASSERT_EQ(Result::NOT_FOUND, static_cast<Result>(ret)) << "Actual: " << toString(ret);
156 /**
157  * Pass the test if:
158  *  - Property is not supported (res == NOT_SUPPORTED)
159  *  - Result is success, and predicate is true
160  * @param res the Result value.
161  * @param valueStr the string representation for actual value (for error message)
162  * @param pred a predicate that test whether the value is valid
163  */
164 #define EXPECT_VALID_OR_UNSUPPORTED_PROP(res, valueStr, pred) \
165     EXPECT_TRUE(isPropertyOk(res, valueStr, pred, #pred))
167 AssertionResult isPropertyOk(Result res, const std::string& valueStr, bool pred,
168                              const std::string& predStr) {
169     if (res == Result::SUCCESS) {
170         if (pred) {
171             return AssertionSuccess();
172         }
173         return AssertionFailure() << "value doesn't match.\nActual: " << valueStr
174                                   << "\nExpected: " << predStr;
175     }
176     if (res == Result::NOT_SUPPORTED) {
177         return AssertionSuccess();
178     }
179     return AssertionFailure() << "Result is not SUCCESS or NOT_SUPPORTED: " << toString(res);
182 bool verifyStorageInfo(const hidl_vec<struct StorageInfo>& info) {
183     for (size_t i = 0; i < info.size(); i++) {
184         if (!(0 <= info[i].eol && info[i].eol <= 3 && 0 <= info[i].lifetimeA &&
185               info[i].lifetimeA <= 0x0B && 0 <= info[i].lifetimeB && info[i].lifetimeB <= 0x0B)) {
186             return false;
187         }
188     }
190     return true;
193 template <typename T>
194 bool verifyEnum(T value) {
195     for (auto it : hidl_enum_range<T>()) {
196         if (it == value) {
197             return true;
198         }
199     }
201     return false;
204 bool verifyHealthInfo(const HealthInfo& health_info) {
205     if (!verifyStorageInfo(health_info.storageInfos)) {
206         return false;
207     }
209     using V1_0::BatteryStatus;
210     using V1_0::BatteryHealth;
212     if (!((health_info.legacy.batteryChargeCounter > 0) &&
213           (health_info.legacy.batteryCurrent != INT32_MIN) &&
214           (0 <= health_info.legacy.batteryLevel && health_info.legacy.batteryLevel <= 100) &&
215           verifyEnum<BatteryHealth>(health_info.legacy.batteryHealth) &&
216           (health_info.legacy.batteryStatus != BatteryStatus::UNKNOWN) &&
217           verifyEnum<BatteryStatus>(health_info.legacy.batteryStatus))) {
218         return false;
219     }
221     return true;
224 /*
225  * Tests the values returned by getChargeCounter(),
226  * getCurrentNow(), getCurrentAverage(), getCapacity(), getEnergyCounter(),
227  * getChargeStatus(), getStorageInfo(), getDiskStats() and getHealthInfo() from
228  * interface IHealth.
229  */
230 TEST_F(HealthHidlTest, Properties) {
231     EXPECT_OK(mHealth->getChargeCounter([](auto result, auto value) {
232         EXPECT_VALID_OR_UNSUPPORTED_PROP(result, std::to_string(value), value > 0);
233     }));
234     EXPECT_OK(mHealth->getCurrentNow([](auto result, auto value) {
235         EXPECT_VALID_OR_UNSUPPORTED_PROP(result, std::to_string(value), value != INT32_MIN);
236     }));
237     EXPECT_OK(mHealth->getCurrentAverage([](auto result, auto value) {
238         EXPECT_VALID_OR_UNSUPPORTED_PROP(result, std::to_string(value), value != INT32_MIN);
239     }));
240     EXPECT_OK(mHealth->getCapacity([](auto result, auto value) {
241         EXPECT_VALID_OR_UNSUPPORTED_PROP(result, std::to_string(value), 0 <= value && value <= 100);
242     }));
243     EXPECT_OK(mHealth->getEnergyCounter([](auto result, auto value) {
244         EXPECT_VALID_OR_UNSUPPORTED_PROP(result, std::to_string(value), value != INT64_MIN);
245     }));
246     EXPECT_OK(mHealth->getChargeStatus([](auto result, auto value) {
247         EXPECT_VALID_OR_UNSUPPORTED_PROP(
248             result, toString(value),
249             value != BatteryStatus::UNKNOWN && verifyEnum<BatteryStatus>(value));
250     }));
251     EXPECT_OK(mHealth->getStorageInfo([](auto result, auto& value) {
252         EXPECT_VALID_OR_UNSUPPORTED_PROP(result, toString(value), verifyStorageInfo(value));
253     }));
254     EXPECT_OK(mHealth->getDiskStats([](auto result, auto& value) {
255         EXPECT_VALID_OR_UNSUPPORTED_PROP(result, toString(value), true);
256     }));
257     EXPECT_OK(mHealth->getHealthInfo([](auto result, auto& value) {
258         EXPECT_VALID_OR_UNSUPPORTED_PROP(result, toString(value), verifyHealthInfo(value));
259     }));
262 }  // namespace V2_0
263 }  // namespace health
264 }  // namespace hardware
265 }  // namespace android
267 int main(int argc, char** argv) {
268     using ::android::hardware::health::V2_0::HealthHidlEnvironment;
269     ::testing::AddGlobalTestEnvironment(HealthHidlEnvironment::Instance());
270     ::testing::InitGoogleTest(&argc, argv);
271     HealthHidlEnvironment::Instance()->init(&argc, argv);
272     int status = RUN_ALL_TESTS();
273     LOG(INFO) << "Test result = " << status;
274     return status;