Merge "health: add libhealthshim" am: 4c12800dd8

Original change: https://android-review.googlesource.com/c/platform/hardware/interfaces/+/1884456

Change-Id: I40aca8d33109a2abcf805206d9e8472c8ad8de43
This commit is contained in:
Yifan Hong 2021-12-07 18:37:33 +00:00 committed by Automerger Merge Worker
commit e6c4962d8b
7 changed files with 557 additions and 28 deletions

View file

@ -25,6 +25,7 @@ aidl_interface {
name: "android.hardware.health",
vendor_available: true,
recovery_available: true,
host_supported: true,
srcs: ["android/hardware/health/*.aidl"],
stability: "vintf",
backend: {
@ -48,6 +49,7 @@ cc_library {
name: "android.hardware.health-translate-ndk",
vendor_available: true,
recovery_available: true,
host_supported: true,
srcs: ["android/hardware/health/translate-ndk.cpp"],
shared_libs: [
"libbinder_ndk",
@ -61,6 +63,9 @@ cc_library {
"android.hardware.health@2.0",
"android.hardware.health@2.1",
],
defaults: [
"libbinder_ndk_host_user",
],
}
java_library {

View file

@ -105,37 +105,42 @@ __attribute__((warn_unused_result)) bool translate(
return true;
}
__attribute__((warn_unused_result)) bool translate(
const ::android::hardware::health::V2_0::HealthInfo& in,
aidl::android::hardware::health::HealthInfo* out) {
out->chargerAcOnline = static_cast<bool>(in.legacy.chargerAcOnline);
out->chargerUsbOnline = static_cast<bool>(in.legacy.chargerUsbOnline);
out->chargerWirelessOnline = static_cast<bool>(in.legacy.chargerWirelessOnline);
out->maxChargingCurrentMicroamps = static_cast<int32_t>(in.legacy.maxChargingCurrent);
out->maxChargingVoltageMicrovolts = static_cast<int32_t>(in.legacy.maxChargingVoltage);
out->batteryStatus =
static_cast<aidl::android::hardware::health::BatteryStatus>(in.legacy.batteryStatus);
out->batteryHealth =
static_cast<aidl::android::hardware::health::BatteryHealth>(in.legacy.batteryHealth);
out->batteryPresent = static_cast<bool>(in.legacy.batteryPresent);
out->batteryLevel = static_cast<int32_t>(in.legacy.batteryLevel);
out->batteryVoltageMillivolts = static_cast<int32_t>(in.legacy.batteryVoltage);
out->batteryTemperatureTenthsCelsius = static_cast<int32_t>(in.legacy.batteryTemperature);
out->batteryCurrentMicroamps = static_cast<int32_t>(in.legacy.batteryCurrent);
out->batteryCycleCount = static_cast<int32_t>(in.legacy.batteryCycleCount);
out->batteryFullChargeUah = static_cast<int32_t>(in.legacy.batteryFullCharge);
out->batteryChargeCounterUah = static_cast<int32_t>(in.legacy.batteryChargeCounter);
out->batteryTechnology = in.legacy.batteryTechnology;
out->batteryCurrentAverageMicroamps = static_cast<int32_t>(in.batteryCurrentAverage);
out->diskStats.clear();
out->diskStats.resize(in.diskStats.size());
for (size_t i = 0; i < in.diskStats.size(); ++i)
if (!translate(in.diskStats[i], &out->diskStats[i])) return false;
out->storageInfos.clear();
out->storageInfos.resize(in.storageInfos.size());
for (size_t i = 0; i < in.storageInfos.size(); ++i)
if (!translate(in.storageInfos[i], &out->storageInfos[i])) return false;
return true;
}
__attribute__((warn_unused_result)) bool translate(
const ::android::hardware::health::V2_1::HealthInfo& in,
aidl::android::hardware::health::HealthInfo* out) {
out->chargerAcOnline = static_cast<bool>(in.legacy.legacy.chargerAcOnline);
out->chargerUsbOnline = static_cast<bool>(in.legacy.legacy.chargerUsbOnline);
out->chargerWirelessOnline = static_cast<bool>(in.legacy.legacy.chargerWirelessOnline);
out->maxChargingCurrentMicroamps = static_cast<int32_t>(in.legacy.legacy.maxChargingCurrent);
out->maxChargingVoltageMicrovolts = static_cast<int32_t>(in.legacy.legacy.maxChargingVoltage);
out->batteryStatus = static_cast<aidl::android::hardware::health::BatteryStatus>(
in.legacy.legacy.batteryStatus);
out->batteryHealth = static_cast<aidl::android::hardware::health::BatteryHealth>(
in.legacy.legacy.batteryHealth);
out->batteryPresent = static_cast<bool>(in.legacy.legacy.batteryPresent);
out->batteryLevel = static_cast<int32_t>(in.legacy.legacy.batteryLevel);
out->batteryVoltageMillivolts = static_cast<int32_t>(in.legacy.legacy.batteryVoltage);
out->batteryTemperatureTenthsCelsius =
static_cast<int32_t>(in.legacy.legacy.batteryTemperature);
out->batteryCurrentMicroamps = static_cast<int32_t>(in.legacy.legacy.batteryCurrent);
out->batteryCycleCount = static_cast<int32_t>(in.legacy.legacy.batteryCycleCount);
out->batteryFullChargeUah = static_cast<int32_t>(in.legacy.legacy.batteryFullCharge);
out->batteryChargeCounterUah = static_cast<int32_t>(in.legacy.legacy.batteryChargeCounter);
out->batteryTechnology = in.legacy.legacy.batteryTechnology;
out->batteryCurrentAverageMicroamps = static_cast<int32_t>(in.legacy.batteryCurrentAverage);
out->diskStats.clear();
out->diskStats.resize(in.legacy.diskStats.size());
for (size_t i = 0; i < in.legacy.diskStats.size(); ++i)
if (!translate(in.legacy.diskStats[i], &out->diskStats[i])) return false;
out->storageInfos.clear();
out->storageInfos.resize(in.legacy.storageInfos.size());
for (size_t i = 0; i < in.legacy.storageInfos.size(); ++i)
if (!translate(in.legacy.storageInfos[i], &out->storageInfos[i])) return false;
if (!translate(in.legacy, out)) return false;
out->batteryCapacityLevel = static_cast<aidl::android::hardware::health::BatteryCapacityLevel>(
in.batteryCapacityLevel);
out->batteryChargeTimeToFullNowSeconds =

View file

@ -32,6 +32,9 @@ __attribute__((warn_unused_result)) bool translate(
__attribute__((warn_unused_result)) bool translate(
const ::android::hardware::health::V2_0::DiskStats& in,
aidl::android::hardware::health::DiskStats* out);
__attribute__((warn_unused_result)) bool translate(
const ::android::hardware::health::V2_0::HealthInfo& in,
aidl::android::hardware::health::HealthInfo* out);
__attribute__((warn_unused_result)) bool translate(
const ::android::hardware::health::V2_1::HealthInfo& in,
aidl::android::hardware::health::HealthInfo* out);

View file

@ -0,0 +1,78 @@
// 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.
package {
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
// all of the 'license_kinds' from "hardware_interfaces_license"
// to get the below license kinds:
// SPDX-license-identifier-Apache-2.0
default_applicable_licenses: ["hardware_interfaces_license"],
}
cc_defaults {
name: "libhealthshim_defaults",
host_supported: true, // for testing
defaults: [
"libbinder_ndk_host_user",
],
cflags: [
"-Wall",
"-Werror",
],
static_libs: [
"android.hardware.health-V1-ndk",
"android.hardware.health-translate-ndk",
"android.hardware.health@1.0",
"android.hardware.health@2.0",
],
shared_libs: [
// These can be expected from the device or from host.
"libbase",
"libbinder_ndk",
"libcutils",
"libhidlbase",
"liblog",
"libutils",
],
}
// Shim library that wraps a HIDL IHealth object into an AIDL IHealth object.
cc_library_static {
name: "libhealthshim",
defaults: ["libhealthshim_defaults"],
recovery_available: true,
srcs: [
"shim.cpp",
],
export_include_dirs: [
"include",
],
}
cc_test {
name: "libhealthshim_test",
defaults: ["libhealthshim_defaults"],
static_libs: [
"libhealthshim",
"libgmock",
],
srcs: [
"test.cpp",
],
test_suites: ["general-tests"],
test_options: {
unit_test: true,
},
}

View file

@ -0,0 +1,55 @@
/*
* 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.
*/
#pragma once
#include <map>
#include <aidl/android/hardware/health/BnHealth.h>
#include <android/hardware/health/2.0/IHealth.h>
namespace aidl::android::hardware::health {
// Shim that wraps HIDL IHealth with an AIDL BnHealth.
// The wrapper always have isRemote() == false because it is BnHealth.
class HealthShim : public BnHealth {
using HidlHealth = ::android::hardware::health::V2_0::IHealth;
using HidlHealthInfoCallback = ::android::hardware::health::V2_0::IHealthInfoCallback;
public:
explicit HealthShim(const ::android::sp<HidlHealth>& service);
ndk::ScopedAStatus registerCallback(
const std::shared_ptr<IHealthInfoCallback>& in_callback) override;
ndk::ScopedAStatus unregisterCallback(
const std::shared_ptr<IHealthInfoCallback>& in_callback) override;
ndk::ScopedAStatus update() override;
ndk::ScopedAStatus getChargeCounterUah(int32_t* _aidl_return) override;
ndk::ScopedAStatus getCurrentNowMicroamps(int32_t* _aidl_return) override;
ndk::ScopedAStatus getCurrentAverageMicroamps(int32_t* _aidl_return) override;
ndk::ScopedAStatus getCapacity(int32_t* _aidl_return) override;
ndk::ScopedAStatus getEnergyCounterNwh(int64_t* _aidl_return) override;
ndk::ScopedAStatus getChargeStatus(BatteryStatus* _aidl_return) override;
ndk::ScopedAStatus getStorageInfo(std::vector<StorageInfo>* _aidl_return) override;
ndk::ScopedAStatus getDiskStats(std::vector<DiskStats>* _aidl_return) override;
ndk::ScopedAStatus getHealthInfo(HealthInfo* _aidl_return) override;
private:
::android::sp<HidlHealth> service_;
std::map<std::shared_ptr<IHealthInfoCallback>, ::android::sp<HidlHealthInfoCallback>>
callback_map_;
};
} // namespace aidl::android::hardware::health

View file

@ -0,0 +1,220 @@
/*
* 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 <android-base/logging.h>
#include <android/hardware/health/translate-ndk.h>
#include <health-shim/shim.h>
using ::android::sp;
using ::android::h2a::translate;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::hardware::health::V2_0::Result;
using ::android::hardware::health::V2_0::toString;
using ::ndk::ScopedAStatus;
using HidlHealth = ::android::hardware::health::V2_0::IHealth;
using HidlHealthInfoCallback = ::android::hardware::health::V2_0::IHealthInfoCallback;
using HidlHealthInfo = ::android::hardware::health::V2_0::HealthInfo;
namespace aidl::android::hardware::health {
namespace {
class HealthInfoCallbackShim : public HidlHealthInfoCallback {
using AidlHealthInfoCallback = ::aidl::android::hardware::health::IHealthInfoCallback;
using AidlHealthInfo = ::aidl::android::hardware::health::HealthInfo;
public:
explicit HealthInfoCallbackShim(const std::shared_ptr<AidlHealthInfoCallback>& impl)
: impl_(impl) {}
Return<void> healthInfoChanged(const HidlHealthInfo& info) override {
AidlHealthInfo aidl_info;
// translate() should always return true.
CHECK(translate(info, &aidl_info));
// This is a oneway function, so we can't (and shouldn't) check for errors.
(void)impl_->healthInfoChanged(aidl_info);
return Void();
}
private:
std::shared_ptr<AidlHealthInfoCallback> impl_;
};
ScopedAStatus ResultToStatus(Result result) {
switch (result) {
case Result::SUCCESS:
return ScopedAStatus::ok();
case Result::NOT_SUPPORTED:
return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
case Result::UNKNOWN:
return ScopedAStatus::fromServiceSpecificError(IHealth::STATUS_UNKNOWN);
case Result::NOT_FOUND:
return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
case Result::CALLBACK_DIED:
return ScopedAStatus::fromServiceSpecificError(IHealth::STATUS_CALLBACK_DIED);
}
return ScopedAStatus::fromServiceSpecificErrorWithMessage(
IHealth::STATUS_UNKNOWN, ("Unrecognized result value " + toString(result)).c_str());
}
template <typename T>
ScopedAStatus ReturnAndResultToStatus(const Return<T>& ret, Result result) {
if (ret.isOk()) {
return ResultToStatus(result);
}
if (ret.isDeadObject()) {
return ScopedAStatus::fromStatus(STATUS_DEAD_OBJECT);
}
return ScopedAStatus::fromServiceSpecificErrorWithMessage(IHealth::STATUS_UNKNOWN,
ret.description().c_str());
}
ScopedAStatus ReturnResultToStatus(const Return<Result>& return_result) {
return ReturnAndResultToStatus(return_result, return_result.isOk()
? static_cast<Result>(return_result)
: Result::UNKNOWN);
}
} // namespace
HealthShim::HealthShim(const sp<HidlHealth>& service) : service_(service) {}
ScopedAStatus HealthShim::registerCallback(
const std::shared_ptr<IHealthInfoCallback>& in_callback) {
sp<HidlHealthInfoCallback> shim(new HealthInfoCallbackShim(in_callback));
callback_map_.emplace(in_callback, shim);
return ReturnResultToStatus(service_->registerCallback(shim));
}
ScopedAStatus HealthShim::unregisterCallback(
const std::shared_ptr<IHealthInfoCallback>& in_callback) {
auto it = callback_map_.find(in_callback);
if (it == callback_map_.end()) {
return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
}
sp<HidlHealthInfoCallback> shim = it->second;
callback_map_.erase(it);
return ReturnResultToStatus(service_->unregisterCallback(shim));
}
ScopedAStatus HealthShim::update() {
return ReturnResultToStatus(service_->update());
}
ScopedAStatus HealthShim::getChargeCounterUah(int32_t* out) {
Result out_result = Result::UNKNOWN;
auto ret = service_->getChargeCounter([out, &out_result](auto result, auto value) {
out_result = result;
if (out_result != Result::SUCCESS) return;
*out = value;
});
return ReturnAndResultToStatus(ret, out_result);
}
ScopedAStatus HealthShim::getCurrentNowMicroamps(int32_t* out) {
Result out_result = Result::UNKNOWN;
auto ret = service_->getCurrentNow([out, &out_result](auto result, auto value) {
out_result = result;
if (out_result != Result::SUCCESS) return;
*out = value;
});
return ReturnAndResultToStatus(ret, out_result);
}
ScopedAStatus HealthShim::getCurrentAverageMicroamps(int32_t* out) {
Result out_result = Result::UNKNOWN;
auto ret = service_->getCurrentAverage([out, &out_result](auto result, auto value) {
out_result = result;
if (out_result != Result::SUCCESS) return;
*out = value;
});
return ReturnAndResultToStatus(ret, out_result);
}
ScopedAStatus HealthShim::getCapacity(int32_t* out) {
Result out_result = Result::UNKNOWN;
auto ret = service_->getCapacity([out, &out_result](auto result, auto value) {
out_result = result;
if (out_result != Result::SUCCESS) return;
*out = value;
});
return ReturnAndResultToStatus(ret, out_result);
}
ScopedAStatus HealthShim::getEnergyCounterNwh(int64_t* out) {
Result out_result = Result::UNKNOWN;
auto ret = service_->getEnergyCounter([out, &out_result](auto result, auto value) {
out_result = result;
if (out_result != Result::SUCCESS) return;
*out = value;
});
return ReturnAndResultToStatus(ret, out_result);
}
ScopedAStatus HealthShim::getChargeStatus(BatteryStatus* out) {
Result out_result = Result::UNKNOWN;
auto ret = service_->getChargeStatus([out, &out_result](auto result, auto value) {
out_result = result;
if (out_result != Result::SUCCESS) return;
*out = static_cast<BatteryStatus>(value);
});
return ReturnAndResultToStatus(ret, out_result);
}
ScopedAStatus HealthShim::getStorageInfo(std::vector<StorageInfo>* out) {
Result out_result = Result::UNKNOWN;
auto ret = service_->getStorageInfo([out, &out_result](auto result, const auto& value) {
out_result = result;
if (out_result != Result::SUCCESS) return;
out->clear();
out->reserve(value.size());
for (const auto& hidl_info : value) {
auto& aidl_info = out->emplace_back();
// translate() should always return true.
CHECK(translate(hidl_info, &aidl_info));
}
});
return ReturnAndResultToStatus(ret, out_result);
}
ScopedAStatus HealthShim::getDiskStats(std::vector<DiskStats>* out) {
Result out_result = Result::UNKNOWN;
auto ret = service_->getDiskStats([out, &out_result](auto result, const auto& value) {
out_result = result;
if (out_result != Result::SUCCESS) return;
out->clear();
out->reserve(value.size());
for (const auto& hidl_info : value) {
auto& aidl_info = out->emplace_back();
// translate() should always return true.
CHECK(translate(hidl_info, &aidl_info));
}
});
return ReturnAndResultToStatus(ret, out_result);
}
ScopedAStatus HealthShim::getHealthInfo(HealthInfo* out) {
Result out_result = Result::UNKNOWN;
auto ret = service_->getHealthInfo([out, &out_result](auto result, const auto& value) {
out_result = result;
if (out_result != Result::SUCCESS) return;
// translate() should always return true.
CHECK(translate(value, out));
});
return ReturnAndResultToStatus(ret, out_result);
}
} // namespace aidl::android::hardware::health

View file

@ -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