Merge "health: add libhealthshim" am: 4c12800dd8
am: e6c4962d8b
am: 2032ec93e2
Original change: https://android-review.googlesource.com/c/platform/hardware/interfaces/+/1884456 Change-Id: I291f9f3c552219628f4715b2db1d35bdd34bff0b
This commit is contained in:
commit
f874942181
7 changed files with 557 additions and 28 deletions
|
@ -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 {
|
||||
|
|
|
@ -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 =
|
||||
|
|
|
@ -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);
|
||||
|
|
78
health/utils/libhealthshim/Android.bp
Normal file
78
health/utils/libhealthshim/Android.bp
Normal 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,
|
||||
},
|
||||
}
|
55
health/utils/libhealthshim/include/health-shim/shim.h
Normal file
55
health/utils/libhealthshim/include/health-shim/shim.h
Normal 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
|
220
health/utils/libhealthshim/shim.cpp
Normal file
220
health/utils/libhealthshim/shim.cpp
Normal 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
|
163
health/utils/libhealthshim/test.cpp
Normal file
163
health/utils/libhealthshim/test.cpp
Normal 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
|
Loading…
Reference in a new issue