health: add libhealthshim
This is a shim library that wraps a HIDL IHealth to
an AIDL BnHealth.
Also add tests for the library.
Bug: 177269435
Test: libhealthshim_test
Change-Id: Ia5f32c1ae0693c70cf698b46b48d5f77006cf6c7
diff --git a/health/utils/libhealthshim/test.cpp b/health/utils/libhealthshim/test.cpp
new file mode 100644
index 0000000..d1dfb8b
--- /dev/null
+++ b/health/utils/libhealthshim/test.cpp
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <health-shim/shim.h>
+
+#include <android/hardware/health/translate-ndk.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+using HidlHealth = android::hardware::health::V2_0::IHealth;
+using HidlHealthInfoCallback = android::hardware::health::V2_0::IHealthInfoCallback;
+using HidlStorageInfo = android::hardware::health::V2_0::StorageInfo;
+using HidlDiskStats = android::hardware::health::V2_0::DiskStats;
+using HidlHealthInfo = android::hardware::health::V2_0::HealthInfo;
+using HidlBatteryStatus = android::hardware::health::V1_0::BatteryStatus;
+using android::sp;
+using android::hardware::Return;
+using android::hardware::Void;
+using android::hardware::health::V2_0::Result;
+using ndk::SharedRefBase;
+using testing::Invoke;
+using testing::NiceMock;
+
+namespace aidl::android::hardware::health {
+MATCHER(IsOk, "") {
+ *result_listener << "status is " << arg.getDescription();
+ return arg.isOk();
+}
+
+MATCHER_P(ExceptionIs, exception_code, "") {
+ *result_listener << "status is " << arg.getDescription();
+ return arg.getExceptionCode() == exception_code;
+}
+
+class MockHidlHealth : public HidlHealth {
+ public:
+ MOCK_METHOD(Return<Result>, registerCallback, (const sp<HidlHealthInfoCallback>& callback),
+ (override));
+ MOCK_METHOD(Return<Result>, unregisterCallback, (const sp<HidlHealthInfoCallback>& callback),
+ (override));
+ MOCK_METHOD(Return<Result>, update, (), (override));
+ MOCK_METHOD(Return<void>, getChargeCounter, (getChargeCounter_cb _hidl_cb), (override));
+ MOCK_METHOD(Return<void>, getCurrentNow, (getCurrentNow_cb _hidl_cb), (override));
+ MOCK_METHOD(Return<void>, getCurrentAverage, (getCurrentAverage_cb _hidl_cb), (override));
+ MOCK_METHOD(Return<void>, getCapacity, (getCapacity_cb _hidl_cb), (override));
+ MOCK_METHOD(Return<void>, getEnergyCounter, (getEnergyCounter_cb _hidl_cb), (override));
+ MOCK_METHOD(Return<void>, getChargeStatus, (getChargeStatus_cb _hidl_cb), (override));
+ MOCK_METHOD(Return<void>, getStorageInfo, (getStorageInfo_cb _hidl_cb), (override));
+ MOCK_METHOD(Return<void>, getDiskStats, (getDiskStats_cb _hidl_cb), (override));
+ MOCK_METHOD(Return<void>, getHealthInfo, (getHealthInfo_cb _hidl_cb), (override));
+};
+
+class HealthShimTest : public ::testing::Test {
+ public:
+ void SetUp() override {
+ hidl = new NiceMock<MockHidlHealth>();
+ shim = SharedRefBase::make<HealthShim>(hidl);
+ }
+ sp<MockHidlHealth> hidl;
+ std::shared_ptr<IHealth> shim;
+};
+
+#define ADD_TEST(name, aidl_name, AidlValueType, hidl_value, not_supported_hidl_value) \
+ TEST_F(HealthShimTest, name) { \
+ ON_CALL(*hidl, name).WillByDefault(Invoke([](auto cb) { \
+ cb(Result::SUCCESS, hidl_value); \
+ return Void(); \
+ })); \
+ AidlValueType value; \
+ ASSERT_THAT(shim->aidl_name(&value), IsOk()); \
+ ASSERT_EQ(value, static_cast<AidlValueType>(hidl_value)); \
+ } \
+ \
+ TEST_F(HealthShimTest, name##Unsupported) { \
+ ON_CALL(*hidl, name).WillByDefault(Invoke([](auto cb) { \
+ cb(Result::NOT_SUPPORTED, not_supported_hidl_value); \
+ return Void(); \
+ })); \
+ AidlValueType value; \
+ ASSERT_THAT(shim->aidl_name(&value), ExceptionIs(EX_UNSUPPORTED_OPERATION)); \
+ }
+
+ADD_TEST(getChargeCounter, getChargeCounterUah, int32_t, 0xFEEDBEEF, 0)
+ADD_TEST(getCurrentNow, getCurrentNowMicroamps, int32_t, 0xC0FFEE, 0)
+ADD_TEST(getCurrentAverage, getCurrentAverageMicroamps, int32_t, 0xA2D401D, 0)
+ADD_TEST(getCapacity, getCapacity, int32_t, 77, 0)
+ADD_TEST(getEnergyCounter, getEnergyCounterNwh, int64_t, 0x1234567887654321, 0)
+ADD_TEST(getChargeStatus, getChargeStatus, BatteryStatus, HidlBatteryStatus::CHARGING,
+ HidlBatteryStatus::UNKNOWN)
+
+#undef ADD_TEST
+
+template <typename AidlValueType, typename HidlValueType>
+bool Translate(const HidlValueType& hidl_value, AidlValueType* aidl_value) {
+ return ::android::h2a::translate(hidl_value, aidl_value);
+}
+
+template <typename AidlValueType, typename HidlValueType>
+bool Translate(const std::vector<HidlValueType>& hidl_vec, std::vector<AidlValueType>* aidl_vec) {
+ aidl_vec->clear();
+ aidl_vec->reserve(hidl_vec.size());
+ for (const auto& hidl_value : hidl_vec) {
+ auto& aidl_value = aidl_vec->emplace_back();
+ if (!Translate(hidl_value, &aidl_value)) return false;
+ }
+ return true;
+}
+
+#define ADD_INFO_TEST(name, AidlValueType, hidl_value) \
+ TEST_F(HealthShimTest, name) { \
+ AidlValueType expected_aidl_value; \
+ ASSERT_TRUE(Translate(hidl_value, &expected_aidl_value)); \
+ ON_CALL(*hidl, name).WillByDefault(Invoke([&](auto cb) { \
+ cb(Result::SUCCESS, hidl_value); \
+ return Void(); \
+ })); \
+ AidlValueType aidl_value; \
+ ASSERT_THAT(shim->name(&aidl_value), IsOk()); \
+ ASSERT_EQ(aidl_value, expected_aidl_value); \
+ } \
+ \
+ TEST_F(HealthShimTest, name##Unsupported) { \
+ ON_CALL(*hidl, name).WillByDefault(Invoke([](auto cb) { \
+ cb(Result::NOT_SUPPORTED, {}); \
+ return Void(); \
+ })); \
+ AidlValueType aidl_value; \
+ ASSERT_THAT(shim->name(&aidl_value), ExceptionIs(EX_UNSUPPORTED_OPERATION)); \
+ }
+
+ADD_INFO_TEST(getStorageInfo, std::vector<StorageInfo>,
+ (std::vector<HidlStorageInfo>{{
+ .lifetimeA = 15,
+ .lifetimeB = 18,
+ }}))
+
+ADD_INFO_TEST(getDiskStats, std::vector<DiskStats>,
+ (std::vector<HidlDiskStats>{{
+ .reads = 100,
+ .writes = 200,
+ }}))
+
+ADD_INFO_TEST(getHealthInfo, HealthInfo,
+ (HidlHealthInfo{
+ .batteryCurrentAverage = 999,
+ }))
+
+#undef ADD_INFO_TEST
+
+} // namespace aidl::android::hardware::health