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

Commit a1015599 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge changes from topic "batt_mon_2_1_types"

* changes:
  healthd: partially fill in health 2.1 HAL fields
  [REFACTOR] healthd: BatteryMonitor use health 2.1 types
parents 51c41e94 35cb0838
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -17,6 +17,10 @@ cc_library_static {
    shared_libs: [
        "libutils",
        "libbase",

        // Need latest HealthInfo definition from headers of this shared
        // library. Clients don't need to link to this.
        "android.hardware.health@2.1",
    ],
    header_libs: ["libhealthd_headers"],
    export_header_lib_headers: ["libhealthd_headers"],
+94 −83
Original line number Diff line number Diff line
@@ -29,10 +29,12 @@

#include <algorithm>
#include <memory>
#include <optional>

#include <android-base/file.h>
#include <android-base/parseint.h>
#include <android-base/strings.h>
#include <android/hardware/health/2.1/types.h>
#include <batteryservice/BatteryService.h>
#include <cutils/klog.h>
#include <cutils/properties.h>
@@ -47,97 +49,93 @@
#define MILLION 1.0e6
#define DEFAULT_VBUS_VOLTAGE 5000000

using HealthInfo_1_0 = android::hardware::health::V1_0::HealthInfo;
using HealthInfo_2_0 = android::hardware::health::V2_0::HealthInfo;
using HealthInfo_2_1 = android::hardware::health::V2_1::HealthInfo;
using android::hardware::health::V1_0::BatteryHealth;
using android::hardware::health::V1_0::BatteryStatus;
using android::hardware::health::V2_1::BatteryCapacityLevel;

namespace android {

struct sysfsStringEnumMap {
template <typename T>
struct SysfsStringEnumMap {
    const char* s;
    int val;
    T val;
};

static int mapSysfsString(const char* str,
                          struct sysfsStringEnumMap map[]) {
template <typename T>
static std::optional<T> mapSysfsString(const char* str, SysfsStringEnumMap<T> map[]) {
    for (int i = 0; map[i].s; i++)
        if (!strcmp(str, map[i].s))
            return map[i].val;

    return -1;
}

static void initBatteryProperties(BatteryProperties* props) {
    props->chargerAcOnline = false;
    props->chargerUsbOnline = false;
    props->chargerWirelessOnline = false;
    props->maxChargingCurrent = 0;
    props->maxChargingVoltage = 0;
    props->batteryStatus = BATTERY_STATUS_UNKNOWN;
    props->batteryHealth = BATTERY_HEALTH_UNKNOWN;
    props->batteryPresent = false;
    props->batteryLevel = 0;
    props->batteryVoltage = 0;
    props->batteryTemperature = 0;
    props->batteryCurrent = 0;
    props->batteryCycleCount = 0;
    props->batteryFullCharge = 0;
    props->batteryChargeCounter = 0;
    props->batteryTechnology.clear();
    return std::nullopt;
}

BatteryMonitor::BatteryMonitor()
    : mHealthdConfig(nullptr),
      mBatteryDevicePresent(false),
      mBatteryFixedCapacity(0),
      mBatteryFixedTemperature(0) {
    initBatteryProperties(&props);
      mBatteryFixedTemperature(0),
      mHealthInfo(std::make_unique<HealthInfo_2_1>()) {}

BatteryMonitor::~BatteryMonitor() {}

const HealthInfo_1_0& BatteryMonitor::getHealthInfo_1_0() const {
    return getHealthInfo_2_0().legacy;
}

struct BatteryProperties getBatteryProperties(BatteryMonitor* batteryMonitor) {
    return batteryMonitor->props;
const HealthInfo_2_0& BatteryMonitor::getHealthInfo_2_0() const {
    return getHealthInfo_2_1().legacy;
}

int BatteryMonitor::getBatteryStatus(const char* status) {
    int ret;
    struct sysfsStringEnumMap batteryStatusMap[] = {
        { "Unknown", BATTERY_STATUS_UNKNOWN },
        { "Charging", BATTERY_STATUS_CHARGING },
        { "Discharging", BATTERY_STATUS_DISCHARGING },
        { "Not charging", BATTERY_STATUS_NOT_CHARGING },
        { "Full", BATTERY_STATUS_FULL },
        { NULL, 0 },
const HealthInfo_2_1& BatteryMonitor::getHealthInfo_2_1() const {
    return *mHealthInfo;
}

BatteryStatus getBatteryStatus(const char* status) {
    static SysfsStringEnumMap<BatteryStatus> batteryStatusMap[] = {
            {"Unknown", BatteryStatus::UNKNOWN},
            {"Charging", BatteryStatus::CHARGING},
            {"Discharging", BatteryStatus::DISCHARGING},
            {"Not charging", BatteryStatus::NOT_CHARGING},
            {"Full", BatteryStatus::FULL},
            {NULL, BatteryStatus::UNKNOWN},
    };

    ret = mapSysfsString(status, batteryStatusMap);
    if (ret < 0) {
    auto ret = mapSysfsString(status, batteryStatusMap);
    if (!ret) {
        KLOG_WARNING(LOG_TAG, "Unknown battery status '%s'\n", status);
        ret = BATTERY_STATUS_UNKNOWN;
        *ret = BatteryStatus::UNKNOWN;
    }

    return ret;
    return *ret;
}

int BatteryMonitor::getBatteryHealth(const char* status) {
    int ret;
    struct sysfsStringEnumMap batteryHealthMap[] = {
        { "Unknown", BATTERY_HEALTH_UNKNOWN },
        { "Good", BATTERY_HEALTH_GOOD },
        { "Overheat", BATTERY_HEALTH_OVERHEAT },
        { "Dead", BATTERY_HEALTH_DEAD },
        { "Over voltage", BATTERY_HEALTH_OVER_VOLTAGE },
        { "Unspecified failure", BATTERY_HEALTH_UNSPECIFIED_FAILURE },
        { "Cold", BATTERY_HEALTH_COLD },
BatteryHealth getBatteryHealth(const char* status) {
    static SysfsStringEnumMap<BatteryHealth> batteryHealthMap[] = {
            {"Unknown", BatteryHealth::UNKNOWN},
            {"Good", BatteryHealth::GOOD},
            {"Overheat", BatteryHealth::OVERHEAT},
            {"Dead", BatteryHealth::DEAD},
            {"Over voltage", BatteryHealth::OVER_VOLTAGE},
            {"Unspecified failure", BatteryHealth::UNSPECIFIED_FAILURE},
            {"Cold", BatteryHealth::COLD},
            // battery health values from JEITA spec
        { "Warm", BATTERY_HEALTH_GOOD },
        { "Cool", BATTERY_HEALTH_GOOD },
        { "Hot", BATTERY_HEALTH_OVERHEAT },
        { NULL, 0 },
            {"Warm", BatteryHealth::GOOD},
            {"Cool", BatteryHealth::GOOD},
            {"Hot", BatteryHealth::OVERHEAT},
            {NULL, BatteryHealth::UNKNOWN},
    };

    ret = mapSysfsString(status, batteryHealthMap);
    if (ret < 0) {
    auto ret = mapSysfsString(status, batteryHealthMap);
    if (!ret) {
        KLOG_WARNING(LOG_TAG, "Unknown battery health '%s'\n", status);
        ret = BATTERY_HEALTH_UNKNOWN;
        *ret = BatteryHealth::UNKNOWN;
    }

    return ret;
    return *ret;
}

int BatteryMonitor::readFromFile(const String8& path, std::string* buf) {
@@ -148,9 +146,7 @@ int BatteryMonitor::readFromFile(const String8& path, std::string* buf) {
}

BatteryMonitor::PowerSupplyType BatteryMonitor::readPowerSupplyType(const String8& path) {
    std::string buf;
    int ret;
    struct sysfsStringEnumMap supplyTypeMap[] = {
    static SysfsStringEnumMap<int> supplyTypeMap[] = {
            {"Unknown", ANDROID_POWER_SUPPLY_TYPE_UNKNOWN},
            {"Battery", ANDROID_POWER_SUPPLY_TYPE_BATTERY},
            {"UPS", ANDROID_POWER_SUPPLY_TYPE_AC},
@@ -166,17 +162,18 @@ BatteryMonitor::PowerSupplyType BatteryMonitor::readPowerSupplyType(const String
            {"Wireless", ANDROID_POWER_SUPPLY_TYPE_WIRELESS},
            {NULL, 0},
    };
    std::string buf;

    if (readFromFile(path, &buf) <= 0)
        return ANDROID_POWER_SUPPLY_TYPE_UNKNOWN;

    ret = mapSysfsString(buf.c_str(), supplyTypeMap);
    auto ret = mapSysfsString(buf.c_str(), supplyTypeMap);
    if (ret < 0) {
        KLOG_WARNING(LOG_TAG, "Unknown power supply type '%s'\n", buf.c_str());
        ret = ANDROID_POWER_SUPPLY_TYPE_UNKNOWN;
        *ret = ANDROID_POWER_SUPPLY_TYPE_UNKNOWN;
    }

    return static_cast<BatteryMonitor::PowerSupplyType>(ret);
    return static_cast<BatteryMonitor::PowerSupplyType>(*ret);
}

bool BatteryMonitor::getBooleanField(const String8& path) {
@@ -201,7 +198,9 @@ int BatteryMonitor::getIntField(const String8& path) {
}

void BatteryMonitor::updateValues(void) {
    initBatteryProperties(&props);
    *mHealthInfo = HealthInfo_2_1{};

    HealthInfo_1_0& props = mHealthInfo->legacy.legacy;

    if (!mHealthdConfig->batteryPresentPath.isEmpty())
        props.batteryPresent = getBooleanField(mHealthdConfig->batteryPresentPath);
@@ -225,6 +224,15 @@ void BatteryMonitor::updateValues(void) {
    if (!mHealthdConfig->batteryChargeCounterPath.isEmpty())
        props.batteryChargeCounter = getIntField(mHealthdConfig->batteryChargeCounterPath);

    if (!mHealthdConfig->batteryCurrentAvgPath.isEmpty())
        mHealthInfo->legacy.batteryCurrentAverage =
                getIntField(mHealthdConfig->batteryCurrentAvgPath);

    // TODO(b/142260281): Retrieve these values correctly.
    mHealthInfo->batteryCapacityLevel = BatteryCapacityLevel::UNKNOWN;
    mHealthInfo->batteryChargeTimeToFullNowSeconds = 0;
    mHealthInfo->batteryFullCapacityUah = props.batteryFullCharge;

    props.batteryTemperature = mBatteryFixedTemperature ?
        mBatteryFixedTemperature :
        getIntField(mHealthdConfig->batteryTemperaturePath);
@@ -292,6 +300,7 @@ void BatteryMonitor::updateValues(void) {
void BatteryMonitor::logValues(void) {
    char dmesgline[256];
    size_t len;
    const HealthInfo_1_0& props = mHealthInfo->legacy.legacy;
    if (props.batteryPresent) {
        snprintf(dmesgline, sizeof(dmesgline), "battery l=%d v=%d t=%s%d.%d h=%d st=%d",
                 props.batteryLevel, props.batteryVoltage, props.batteryTemperature < 0 ? "-" : "",
@@ -325,18 +334,19 @@ void BatteryMonitor::logValues(void) {
}

bool BatteryMonitor::isChargerOnline() {
    const HealthInfo_1_0& props = mHealthInfo->legacy.legacy;
    return props.chargerAcOnline | props.chargerUsbOnline |
            props.chargerWirelessOnline;
}

int BatteryMonitor::getChargeStatus() {
    int result = BATTERY_STATUS_UNKNOWN;
    BatteryStatus result = BatteryStatus::UNKNOWN;
    if (!mHealthdConfig->batteryStatusPath.isEmpty()) {
        std::string buf;
        if (readFromFile(mHealthdConfig->batteryStatusPath, &buf) > 0)
            result = getBatteryStatus(buf.c_str());
    }
    return result;
    return static_cast<int>(result);
}

status_t BatteryMonitor::getProperty(int id, struct BatteryProperty *val) {
@@ -409,6 +419,7 @@ status_t BatteryMonitor::getProperty(int id, struct BatteryProperty *val) {
void BatteryMonitor::dumpState(int fd) {
    int v;
    char vs[128];
    const HealthInfo_1_0& props = mHealthInfo->legacy.legacy;

    snprintf(vs, sizeof(vs), "ac: %d usb: %d wireless: %d current_max: %d voltage_max: %d\n",
             props.chargerAcOnline, props.chargerUsbOnline,
+21 −4
Original line number Diff line number Diff line
@@ -17,6 +17,8 @@
#ifndef HEALTHD_BATTERYMONITOR_H
#define HEALTHD_BATTERYMONITOR_H

#include <memory>

#include <batteryservice/BatteryService.h>
#include <utils/String8.h>
#include <utils/Vector.h>
@@ -24,6 +26,19 @@
#include <healthd/healthd.h>

namespace android {
namespace hardware {
namespace health {
namespace V1_0 {
struct HealthInfo;
}  // namespace V1_0
namespace V2_0 {
struct HealthInfo;
}  // namespace V2_0
namespace V2_1 {
struct HealthInfo;
}  // namespace V2_1
}  // namespace health
}  // namespace hardware

class BatteryMonitor {
  public:
@@ -37,11 +52,15 @@ class BatteryMonitor {
    };

    BatteryMonitor();
    ~BatteryMonitor();
    void init(struct healthd_config *hc);
    int getChargeStatus();
    status_t getProperty(int id, struct BatteryProperty *val);
    void dumpState(int fd);
    friend struct BatteryProperties getBatteryProperties(BatteryMonitor* batteryMonitor);

    const android::hardware::health::V1_0::HealthInfo& getHealthInfo_1_0() const;
    const android::hardware::health::V2_0::HealthInfo& getHealthInfo_2_0() const;
    const android::hardware::health::V2_1::HealthInfo& getHealthInfo_2_1() const;

    void updateValues(void);
    void logValues(void);
@@ -53,10 +72,8 @@ class BatteryMonitor {
    bool mBatteryDevicePresent;
    int mBatteryFixedCapacity;
    int mBatteryFixedTemperature;
    struct BatteryProperties props;
    std::unique_ptr<android::hardware::health::V2_1::HealthInfo> mHealthInfo;

    int getBatteryStatus(const char* status);
    int getBatteryHealth(const char* status);
    int readFromFile(const String8& path, std::string* buf);
    PowerSupplyType readPowerSupplyType(const String8& path);
    bool getBooleanField(const String8& path);