Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d33b067f authored by Yifan Hong's avatar Yifan Hong Committed by Gerrit Code Review
Browse files

Merge "GetBatteryInfo() also reads AIDL health HAL."

parents 90064ac2 67a8fd21
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -157,6 +157,7 @@ cc_binary {
    ],

    shared_libs: [
        "android.hardware.health-V1-ndk", // from librecovery_utils
        "librecovery_ui",
    ],

+2 −0
Original line number Diff line number Diff line
@@ -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",
+12 −0
Original line number Diff line number Diff line
@@ -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",
    ],
+45 −28
Original line number Diff line number Diff line
@@ -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;
    if (health != nullptr) {
      auto res = health->getChargeStatus(&charge_status);
      if (!res.isOk()) {
        LOG(WARNING) << "Unable to call getChargeStatus: " << res.getDescription();
        charge_status = BatteryStatus::UNKNOWN;
      }
          })
          .isOk();  // should not have transport error
    }

    // 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 };
  }
}
+7 −0
Original line number Diff line number Diff line
@@ -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",