Merge "GetBatteryInfo() also reads AIDL health HAL." am: d33b067f04

Original change: https://android-review.googlesource.com/c/platform/bootable/recovery/+/1906334

Change-Id: I5d7635ec6dc52f9349f7ebaed304f26fd445239f
This commit is contained in:
Yifan Hong 2021-12-07 18:37:33 +00:00 committed by Automerger Merge Worker
commit 9113d57446
5 changed files with 67 additions and 28 deletions

View file

@ -157,6 +157,7 @@ cc_binary {
],
shared_libs: [
"android.hardware.health-V1-ndk", // from librecovery_utils
"librecovery_ui",
],

View file

@ -97,6 +97,7 @@ cc_binary {
],
shared_libs: [
"android.hardware.health-V1-ndk", // from librecovery_utils
"libbase",
"libcrypto",
],
@ -128,6 +129,7 @@ cc_test {
],
static_libs: [
"android.hardware.health-V1-ndk", // from librecovery_utils
"libminadbd_services",
"libfusesideload",
"librecovery_utils",

View file

@ -31,6 +31,7 @@ cc_defaults {
shared_libs: [
"android.hardware.health@2.0",
"libbase",
"libbinder_ndk",
"libext4_utils",
"libfs_mgr",
"libhidlbase",
@ -42,8 +43,10 @@ cc_defaults {
"libotautil",
// External dependencies.
"android.hardware.health-translate-ndk",
"libfstab",
"libhealthhalutils",
"libhealthshim",
],
}
@ -70,6 +73,15 @@ cc_library_static {
"libvold_headers",
],
shared_libs: [
// The following cannot be placed in librecovery_utils_defaults,
// because at the time of writing, android.hardware.health-V1-ndk.so
// is not installed to the system image yet. (It is installed
// to the recovery ramdisk.) Hence, minadbd_test must link to it
// statically.
"android.hardware.health-V1-ndk",
],
export_include_dirs: [
"include",
],

View file

@ -20,59 +20,74 @@
#include <unistd.h>
#include <android-base/logging.h>
#include <android/binder_manager.h>
#include <health-shim/shim.h>
#include <healthhalutils/HealthHalUtils.h>
BatteryInfo GetBatteryInfo() {
using android::hardware::health::V1_0::BatteryStatus;
using android::hardware::health::V2_0::get_health_service;
using android::hardware::health::V2_0::IHealth;
using android::hardware::health::V2_0::Result;
using android::hardware::health::V2_0::toString;
using HidlHealth = android::hardware::health::V2_0::IHealth;
using aidl::android::hardware::health::BatteryStatus;
using aidl::android::hardware::health::HealthShim;
using aidl::android::hardware::health::IHealth;
using aidl::android::hardware::health::toString;
using std::string_literals::operator""s;
android::sp<IHealth> health = get_health_service();
auto service_name = IHealth::descriptor + "/default"s;
std::shared_ptr<IHealth> health;
if (AServiceManager_isDeclared(service_name.c_str())) {
ndk::SpAIBinder binder(AServiceManager_waitForService(service_name.c_str()));
health = IHealth::fromBinder(binder);
}
if (health == nullptr) {
LOG(INFO) << "Unable to get AIDL health service, trying HIDL...";
android::sp<HidlHealth> hidl_health = get_health_service();
if (hidl_health != nullptr) {
health = ndk::SharedRefBase::make<HealthShim>(hidl_health);
}
}
if (health == nullptr) {
LOG(WARNING) << "No health implementation is found; assuming defaults";
}
int wait_second = 0;
while (true) {
auto charge_status = BatteryStatus::UNKNOWN;
if (health == nullptr) {
LOG(WARNING) << "No health implementation is found; assuming defaults";
} else {
health
->getChargeStatus([&charge_status](auto res, auto out_status) {
if (res == Result::SUCCESS) {
charge_status = out_status;
}
})
.isOk(); // should not have transport error
if (health != nullptr) {
auto res = health->getChargeStatus(&charge_status);
if (!res.isOk()) {
LOG(WARNING) << "Unable to call getChargeStatus: " << res.getDescription();
charge_status = BatteryStatus::UNKNOWN;
}
}
// Treat unknown status as on charger. See hardware/interfaces/health/1.0/types.hal for the
// meaning of the return values.
// Treat unknown status as on charger. See hardware/interfaces/health/aidl/BatteryStatus.aidl
// for the meaning of the return values.
bool charging = (charge_status != BatteryStatus::DISCHARGING &&
charge_status != BatteryStatus::NOT_CHARGING);
Result res = Result::UNKNOWN;
int32_t capacity = INT32_MIN;
if (health != nullptr) {
health
->getCapacity([&res, &capacity](auto out_res, auto out_capacity) {
res = out_res;
capacity = out_capacity;
})
.isOk(); // should not have transport error
auto res = health->getCapacity(&capacity);
if (!res.isOk()) {
LOG(WARNING) << "Unable to call getCapacity: " << res.getDescription();
capacity = INT32_MIN;
}
}
LOG(INFO) << "charge_status " << toString(charge_status) << ", charging " << charging
<< ", status " << toString(res) << ", capacity " << capacity;
<< ", capacity " << capacity;
constexpr int BATTERY_READ_TIMEOUT_IN_SEC = 10;
// At startup, the battery drivers in devices like N5X/N6P take some time to load
// the battery profile. Before the load finishes, it reports value 50 as a fake
// capacity. BATTERY_READ_TIMEOUT_IN_SEC is set that the battery drivers are expected
// to finish loading the battery profile earlier than 10 seconds after kernel startup.
if (res == Result::SUCCESS && capacity == 50) {
if (capacity == 50) {
if (wait_second < BATTERY_READ_TIMEOUT_IN_SEC) {
LOG(INFO) << "Battery capacity == 50, waiting "
<< (BATTERY_READ_TIMEOUT_IN_SEC - wait_second)
<< " seconds to ensure this is not a fake value...";
sleep(1);
wait_second++;
continue;
@ -80,10 +95,12 @@ BatteryInfo GetBatteryInfo() {
}
// If we can't read battery percentage, it may be a device without battery. In this
// situation, use 100 as a fake battery percentage.
if (res != Result::SUCCESS) {
if (capacity == INT32_MIN) {
LOG(WARNING) << "Using fake battery capacity 100.";
capacity = 100;
}
LOG(INFO) << "GetBatteryInfo() reporting charging " << charging << ", capacity " << capacity;
return BatteryInfo{ charging, capacity };
}
}

View file

@ -138,7 +138,14 @@ cc_test {
"unit/*.cpp",
],
shared_libs: [
"libbinder_ndk",
],
static_libs: libapplypatch_static_libs + librecovery_static_libs + [
"android.hardware.health-translate-ndk",
"android.hardware.health-V1-ndk",
"libhealthshim",
"librecovery_ui",
"libfusesideload",
"libminui",