GetBatteryInfo() also reads AIDL health HAL.

Test: call GetBatteryInfo manually with and without AIDL health HAL
Bug: 170338625
Bug: 177269435
Change-Id: I123739e5bc372d5198fd711f592ceac04d46ab28
This commit is contained in:
Yifan Hong 2021-11-30 16:39:00 -08:00
parent 436a520a57
commit 67a8fd2175
5 changed files with 67 additions and 28 deletions

View file

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

View file

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

View file

@ -31,6 +31,7 @@ cc_defaults {
shared_libs: [ shared_libs: [
"android.hardware.health@2.0", "android.hardware.health@2.0",
"libbase", "libbase",
"libbinder_ndk",
"libext4_utils", "libext4_utils",
"libfs_mgr", "libfs_mgr",
"libhidlbase", "libhidlbase",
@ -42,8 +43,10 @@ cc_defaults {
"libotautil", "libotautil",
// External dependencies. // External dependencies.
"android.hardware.health-translate-ndk",
"libfstab", "libfstab",
"libhealthhalutils", "libhealthhalutils",
"libhealthshim",
], ],
} }
@ -70,6 +73,15 @@ cc_library_static {
"libvold_headers", "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: [ export_include_dirs: [
"include", "include",
], ],

View file

@ -20,59 +20,74 @@
#include <unistd.h> #include <unistd.h>
#include <android-base/logging.h> #include <android-base/logging.h>
#include <android/binder_manager.h>
#include <health-shim/shim.h>
#include <healthhalutils/HealthHalUtils.h> #include <healthhalutils/HealthHalUtils.h>
BatteryInfo GetBatteryInfo() { BatteryInfo GetBatteryInfo() {
using android::hardware::health::V1_0::BatteryStatus;
using android::hardware::health::V2_0::get_health_service; using android::hardware::health::V2_0::get_health_service;
using android::hardware::health::V2_0::IHealth; using HidlHealth = android::hardware::health::V2_0::IHealth;
using android::hardware::health::V2_0::Result; using aidl::android::hardware::health::BatteryStatus;
using android::hardware::health::V2_0::toString; 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; int wait_second = 0;
while (true) { while (true) {
auto charge_status = BatteryStatus::UNKNOWN; auto charge_status = BatteryStatus::UNKNOWN;
if (health != nullptr) {
if (health == nullptr) { auto res = health->getChargeStatus(&charge_status);
LOG(WARNING) << "No health implementation is found; assuming defaults"; if (!res.isOk()) {
} else { LOG(WARNING) << "Unable to call getChargeStatus: " << res.getDescription();
health charge_status = BatteryStatus::UNKNOWN;
->getChargeStatus([&charge_status](auto res, auto out_status) {
if (res == Result::SUCCESS) {
charge_status = out_status;
} }
})
.isOk(); // should not have transport error
} }
// Treat unknown status as on charger. See hardware/interfaces/health/1.0/types.hal for the // Treat unknown status as on charger. See hardware/interfaces/health/aidl/BatteryStatus.aidl
// meaning of the return values. // for the meaning of the return values.
bool charging = (charge_status != BatteryStatus::DISCHARGING && bool charging = (charge_status != BatteryStatus::DISCHARGING &&
charge_status != BatteryStatus::NOT_CHARGING); charge_status != BatteryStatus::NOT_CHARGING);
Result res = Result::UNKNOWN;
int32_t capacity = INT32_MIN; int32_t capacity = INT32_MIN;
if (health != nullptr) { if (health != nullptr) {
health auto res = health->getCapacity(&capacity);
->getCapacity([&res, &capacity](auto out_res, auto out_capacity) { if (!res.isOk()) {
res = out_res; LOG(WARNING) << "Unable to call getCapacity: " << res.getDescription();
capacity = out_capacity; capacity = INT32_MIN;
}) }
.isOk(); // should not have transport error
} }
LOG(INFO) << "charge_status " << toString(charge_status) << ", charging " << charging LOG(INFO) << "charge_status " << toString(charge_status) << ", charging " << charging
<< ", status " << toString(res) << ", capacity " << capacity; << ", capacity " << capacity;
constexpr int BATTERY_READ_TIMEOUT_IN_SEC = 10; constexpr int BATTERY_READ_TIMEOUT_IN_SEC = 10;
// At startup, the battery drivers in devices like N5X/N6P take some time to load // 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 // 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 // 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. // 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) { 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); sleep(1);
wait_second++; wait_second++;
continue; continue;
@ -80,10 +95,12 @@ BatteryInfo GetBatteryInfo() {
} }
// If we can't read battery percentage, it may be a device without battery. In this // If we can't read battery percentage, it may be a device without battery. In this
// situation, use 100 as a fake battery percentage. // 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; capacity = 100;
} }
LOG(INFO) << "GetBatteryInfo() reporting charging " << charging << ", capacity " << capacity;
return BatteryInfo{ charging, capacity }; return BatteryInfo{ charging, capacity };
} }
} }

View file

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