Merge "healthd: batterymonitor uses AIDL HealthInfo."

This commit is contained in:
Yifan Hong 2022-03-02 19:20:31 +00:00 committed by Gerrit Code Review
commit 0326984c42
3 changed files with 147 additions and 78 deletions

View file

@ -22,9 +22,15 @@ cc_library_static {
"libutils",
"libbase",
// Need latest HealthInfo definition from headers of this shared
// library. Clients don't need to link to this.
// Need HealthInfo definition from headers of these shared
// libraries. Clients don't need to link to these.
"android.hardware.health@2.1",
"android.hardware.health-V1-ndk",
],
whole_static_libs: [
// Need to translate HIDL to AIDL to support legacy APIs in
// BatteryMonitor.
"android.hardware.health-translate-ndk",
],
header_libs: ["libhealthd_headers"],
export_header_lib_headers: ["libhealthd_headers"],

View file

@ -31,10 +31,12 @@
#include <memory>
#include <optional>
#include <aidl/android/hardware/health/HealthInfo.h>
#include <android-base/file.h>
#include <android-base/parseint.h>
#include <android-base/strings.h>
#include <android/hardware/health/2.1/types.h>
#include <android/hardware/health/translate-ndk.h>
#include <batteryservice/BatteryService.h>
#include <cutils/klog.h>
#include <cutils/properties.h>
@ -52,10 +54,54 @@
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;
using android::hardware::health::V2_1::Constants;
using aidl::android::hardware::health::BatteryCapacityLevel;
using aidl::android::hardware::health::BatteryHealth;
using aidl::android::hardware::health::BatteryStatus;
using aidl::android::hardware::health::HealthInfo;
namespace {
// Translate from AIDL back to HIDL definition for getHealthInfo_*_* calls.
// Skips storageInfo and diskStats.
void translateToHidl(const ::aidl::android::hardware::health::HealthInfo& in,
::android::hardware::health::V1_0::HealthInfo* out) {
out->chargerAcOnline = in.chargerAcOnline;
out->chargerUsbOnline = in.chargerUsbOnline;
out->chargerWirelessOnline = in.chargerWirelessOnline;
out->maxChargingCurrent = in.maxChargingCurrentMicroamps;
out->maxChargingVoltage = in.maxChargingVoltageMicrovolts;
out->batteryStatus =
static_cast<::android::hardware::health::V1_0::BatteryStatus>(in.batteryStatus);
out->batteryHealth =
static_cast<::android::hardware::health::V1_0::BatteryHealth>(in.batteryHealth);
out->batteryPresent = in.batteryPresent;
out->batteryLevel = in.batteryLevel;
out->batteryVoltage = in.batteryVoltageMillivolts;
out->batteryTemperature = in.batteryTemperatureTenthsCelsius;
out->batteryCurrent = in.batteryCurrentMicroamps;
out->batteryCycleCount = in.batteryCycleCount;
out->batteryFullCharge = in.batteryFullChargeUah;
out->batteryChargeCounter = in.batteryChargeCounterUah;
out->batteryTechnology = in.batteryTechnology;
}
void translateToHidl(const ::aidl::android::hardware::health::HealthInfo& in,
::android::hardware::health::V2_0::HealthInfo* out) {
translateToHidl(in, &out->legacy);
out->batteryCurrentAverage = in.batteryCurrentAverageMicroamps;
// Skip storageInfo and diskStats
}
void translateToHidl(const ::aidl::android::hardware::health::HealthInfo& in,
::android::hardware::health::V2_1::HealthInfo* out) {
translateToHidl(in, &out->legacy);
out->batteryCapacityLevel = static_cast<android::hardware::health::V2_1::BatteryCapacityLevel>(
in.batteryCapacityLevel);
out->batteryChargeTimeToFullNowSeconds = in.batteryChargeTimeToFullNowSeconds;
out->batteryFullChargeDesignCapacityUah = in.batteryFullChargeDesignCapacityUah;
}
} // namespace
namespace android {
@ -74,17 +120,15 @@ static std::optional<T> mapSysfsString(const char* str, SysfsStringEnumMap<T> ma
return std::nullopt;
}
static void initHealthInfo(HealthInfo_2_1* health_info_2_1) {
*health_info_2_1 = HealthInfo_2_1{};
static void initHealthInfo(HealthInfo* health_info) {
*health_info = HealthInfo{};
// HIDL enum values are zero initialized, so they need to be initialized
// properly.
health_info_2_1->batteryCapacityLevel = BatteryCapacityLevel::UNSUPPORTED;
health_info_2_1->batteryChargeTimeToFullNowSeconds =
(int64_t)Constants::BATTERY_CHARGE_TIME_TO_FULL_NOW_SECONDS_UNSUPPORTED;
auto* props = &health_info_2_1->legacy.legacy;
props->batteryStatus = BatteryStatus::UNKNOWN;
props->batteryHealth = BatteryHealth::UNKNOWN;
// Enum values may be zero initialized, so they need to be initialized properly.
health_info->batteryCapacityLevel = BatteryCapacityLevel::UNSUPPORTED;
health_info->batteryChargeTimeToFullNowSeconds =
(int64_t)HealthInfo::BATTERY_CHARGE_TIME_TO_FULL_NOW_SECONDS_UNSUPPORTED;
health_info->batteryStatus = BatteryStatus::UNKNOWN;
health_info->batteryHealth = BatteryHealth::UNKNOWN;
}
BatteryMonitor::BatteryMonitor()
@ -92,22 +136,31 @@ BatteryMonitor::BatteryMonitor()
mBatteryDevicePresent(false),
mBatteryFixedCapacity(0),
mBatteryFixedTemperature(0),
mChargerDockOnline(false),
mHealthInfo(std::make_unique<HealthInfo_2_1>()) {
mHealthInfo(std::make_unique<HealthInfo>()) {
initHealthInfo(mHealthInfo.get());
}
BatteryMonitor::~BatteryMonitor() {}
const HealthInfo_1_0& BatteryMonitor::getHealthInfo_1_0() const {
return getHealthInfo_2_0().legacy;
HealthInfo_1_0 BatteryMonitor::getHealthInfo_1_0() const {
HealthInfo_1_0 health_info_1_0;
translateToHidl(*mHealthInfo, &health_info_1_0);
return health_info_1_0;
}
const HealthInfo_2_0& BatteryMonitor::getHealthInfo_2_0() const {
return getHealthInfo_2_1().legacy;
HealthInfo_2_0 BatteryMonitor::getHealthInfo_2_0() const {
HealthInfo_2_0 health_info_2_0;
translateToHidl(*mHealthInfo, &health_info_2_0);
return health_info_2_0;
}
const HealthInfo_2_1& BatteryMonitor::getHealthInfo_2_1() const {
HealthInfo_2_1 BatteryMonitor::getHealthInfo_2_1() const {
HealthInfo_2_1 health_info_2_1;
translateToHidl(*mHealthInfo, &health_info_2_1);
return health_info_2_1;
}
const HealthInfo& BatteryMonitor::getHealthInfo() const {
return *mHealthInfo;
}
@ -247,32 +300,31 @@ bool BatteryMonitor::isScopedPowerSupply(const char* name) {
void BatteryMonitor::updateValues(void) {
initHealthInfo(mHealthInfo.get());
HealthInfo_1_0& props = mHealthInfo->legacy.legacy;
if (!mHealthdConfig->batteryPresentPath.isEmpty())
props.batteryPresent = getBooleanField(mHealthdConfig->batteryPresentPath);
mHealthInfo->batteryPresent = getBooleanField(mHealthdConfig->batteryPresentPath);
else
props.batteryPresent = mBatteryDevicePresent;
mHealthInfo->batteryPresent = mBatteryDevicePresent;
props.batteryLevel = mBatteryFixedCapacity ?
mBatteryFixedCapacity :
getIntField(mHealthdConfig->batteryCapacityPath);
props.batteryVoltage = getIntField(mHealthdConfig->batteryVoltagePath) / 1000;
mHealthInfo->batteryLevel = mBatteryFixedCapacity
? mBatteryFixedCapacity
: getIntField(mHealthdConfig->batteryCapacityPath);
mHealthInfo->batteryVoltageMillivolts = getIntField(mHealthdConfig->batteryVoltagePath) / 1000;
if (!mHealthdConfig->batteryCurrentNowPath.isEmpty())
props.batteryCurrent = getIntField(mHealthdConfig->batteryCurrentNowPath);
mHealthInfo->batteryCurrentMicroamps = getIntField(mHealthdConfig->batteryCurrentNowPath);
if (!mHealthdConfig->batteryFullChargePath.isEmpty())
props.batteryFullCharge = getIntField(mHealthdConfig->batteryFullChargePath);
mHealthInfo->batteryFullChargeUah = getIntField(mHealthdConfig->batteryFullChargePath);
if (!mHealthdConfig->batteryCycleCountPath.isEmpty())
props.batteryCycleCount = getIntField(mHealthdConfig->batteryCycleCountPath);
mHealthInfo->batteryCycleCount = getIntField(mHealthdConfig->batteryCycleCountPath);
if (!mHealthdConfig->batteryChargeCounterPath.isEmpty())
props.batteryChargeCounter = getIntField(mHealthdConfig->batteryChargeCounterPath);
mHealthInfo->batteryChargeCounterUah =
getIntField(mHealthdConfig->batteryChargeCounterPath);
if (!mHealthdConfig->batteryCurrentAvgPath.isEmpty())
mHealthInfo->legacy.batteryCurrentAverage =
mHealthInfo->batteryCurrentAverageMicroamps =
getIntField(mHealthdConfig->batteryCurrentAvgPath);
if (!mHealthdConfig->batteryChargeTimeToFullNowPath.isEmpty())
@ -283,9 +335,9 @@ void BatteryMonitor::updateValues(void) {
mHealthInfo->batteryFullChargeDesignCapacityUah =
getIntField(mHealthdConfig->batteryFullChargeDesignCapacityUahPath);
props.batteryTemperature = mBatteryFixedTemperature ?
mBatteryFixedTemperature :
getIntField(mHealthdConfig->batteryTemperaturePath);
mHealthInfo->batteryTemperatureTenthsCelsius =
mBatteryFixedTemperature ? mBatteryFixedTemperature
: getIntField(mHealthdConfig->batteryTemperaturePath);
std::string buf;
@ -293,13 +345,13 @@ void BatteryMonitor::updateValues(void) {
mHealthInfo->batteryCapacityLevel = getBatteryCapacityLevel(buf.c_str());
if (readFromFile(mHealthdConfig->batteryStatusPath, &buf) > 0)
props.batteryStatus = getBatteryStatus(buf.c_str());
mHealthInfo->batteryStatus = getBatteryStatus(buf.c_str());
if (readFromFile(mHealthdConfig->batteryHealthPath, &buf) > 0)
props.batteryHealth = getBatteryHealth(buf.c_str());
mHealthInfo->batteryHealth = getBatteryHealth(buf.c_str());
if (readFromFile(mHealthdConfig->batteryTechnologyPath, &buf) > 0)
props.batteryTechnology = String8(buf.c_str());
mHealthInfo->batteryTechnology = String8(buf.c_str());
double MaxPower = 0;
@ -313,29 +365,26 @@ void BatteryMonitor::updateValues(void) {
mChargerNames[i].string());
switch(readPowerSupplyType(path)) {
case ANDROID_POWER_SUPPLY_TYPE_AC:
props.chargerAcOnline = true;
mHealthInfo->chargerAcOnline = true;
break;
case ANDROID_POWER_SUPPLY_TYPE_USB:
props.chargerUsbOnline = true;
mHealthInfo->chargerUsbOnline = true;
break;
case ANDROID_POWER_SUPPLY_TYPE_WIRELESS:
props.chargerWirelessOnline = true;
mHealthInfo->chargerWirelessOnline = true;
break;
case ANDROID_POWER_SUPPLY_TYPE_DOCK:
mChargerDockOnline = true;
mHealthInfo->chargerDockOnline = true;
break;
default:
path.clear();
path.appendFormat("%s/%s/is_dock", POWER_SUPPLY_SYSFS_PATH,
mChargerNames[i].string());
if (access(path.string(), R_OK) == 0) {
mChargerDockOnline = true;
KLOG_INFO(LOG_TAG, "%s: online\n",
mChargerNames[i].string());
} else {
if (access(path.string(), R_OK) == 0)
mHealthInfo->chargerDockOnline = true;
else
KLOG_WARNING(LOG_TAG, "%s: Unknown power supply type\n",
mChargerNames[i].string());
}
}
path.clear();
path.appendFormat("%s/%s/current_max", POWER_SUPPLY_SYSFS_PATH,
@ -354,8 +403,8 @@ void BatteryMonitor::updateValues(void) {
double power = ((double)ChargingCurrent / MILLION) *
((double)ChargingVoltage / MILLION);
if (MaxPower < power) {
props.maxChargingCurrent = ChargingCurrent;
props.maxChargingVoltage = ChargingVoltage;
mHealthInfo->maxChargingCurrentMicroamps = ChargingCurrent;
mHealthInfo->maxChargingVoltageMicrovolts = ChargingVoltage;
MaxPower = power;
}
}
@ -366,26 +415,34 @@ void BatteryMonitor::logValues(void) {
logValues(*mHealthInfo, *mHealthdConfig);
}
void BatteryMonitor::logValues(const android::hardware::health::V2_1::HealthInfo& health_info,
void BatteryMonitor::logValues(const HealthInfo_2_1& health_info,
const struct healthd_config& healthd_config) {
HealthInfo aidl_health_info;
(void)android::h2a::translate(health_info, &aidl_health_info);
logValues(aidl_health_info, healthd_config);
}
void BatteryMonitor::logValues(const HealthInfo& props,
const struct healthd_config& healthd_config) {
char dmesgline[256];
size_t len;
const HealthInfo_1_0& props = health_info.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 ? "-" : "",
abs(props.batteryTemperature / 10), abs(props.batteryTemperature % 10),
props.batteryHealth, props.batteryStatus);
props.batteryLevel, props.batteryVoltageMillivolts,
props.batteryTemperatureTenthsCelsius < 0 ? "-" : "",
abs(props.batteryTemperatureTenthsCelsius / 10),
abs(props.batteryTemperatureTenthsCelsius % 10), props.batteryHealth,
props.batteryStatus);
len = strlen(dmesgline);
if (!healthd_config.batteryCurrentNowPath.isEmpty()) {
len += snprintf(dmesgline + len, sizeof(dmesgline) - len, " c=%d",
props.batteryCurrent);
props.batteryCurrentMicroamps);
}
if (!healthd_config.batteryFullChargePath.isEmpty()) {
len += snprintf(dmesgline + len, sizeof(dmesgline) - len, " fc=%d",
props.batteryFullCharge);
props.batteryFullChargeUah);
}
if (!healthd_config.batteryCycleCountPath.isEmpty()) {
@ -396,17 +453,17 @@ void BatteryMonitor::logValues(const android::hardware::health::V2_1::HealthInfo
len = snprintf(dmesgline, sizeof(dmesgline), "battery none");
}
snprintf(dmesgline + len, sizeof(dmesgline) - len, " chg=%s%s%s",
snprintf(dmesgline + len, sizeof(dmesgline) - len, " chg=%s%s%s%s",
props.chargerAcOnline ? "a" : "", props.chargerUsbOnline ? "u" : "",
props.chargerWirelessOnline ? "w" : "");
props.chargerWirelessOnline ? "w" : "", props.chargerDockOnline ? "d" : "");
KLOG_WARNING(LOG_TAG, "%s\n", dmesgline);
}
bool BatteryMonitor::isChargerOnline() {
const HealthInfo_1_0& props = mHealthInfo->legacy.legacy;
const HealthInfo& props = *mHealthInfo;
return props.chargerAcOnline | props.chargerUsbOnline | props.chargerWirelessOnline |
mChargerDockOnline;
props.chargerDockOnline;
}
int BatteryMonitor::getChargeStatus() {
@ -489,19 +546,19 @@ 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;
const HealthInfo& props = *mHealthInfo;
snprintf(vs, sizeof(vs),
"ac: %d usb: %d wireless: %d dock: %d current_max: %d voltage_max: %d\n",
props.chargerAcOnline, props.chargerUsbOnline, props.chargerWirelessOnline,
mChargerDockOnline, props.maxChargingCurrent, props.maxChargingVoltage);
props.chargerDockOnline, props.maxChargingCurrentMicroamps,
props.maxChargingVoltageMicrovolts);
write(fd, vs, strlen(vs));
snprintf(vs, sizeof(vs), "status: %d health: %d present: %d\n",
props.batteryStatus, props.batteryHealth, props.batteryPresent);
write(fd, vs, strlen(vs));
snprintf(vs, sizeof(vs), "level: %d voltage: %d temp: %d\n",
props.batteryLevel, props.batteryVoltage,
props.batteryTemperature);
snprintf(vs, sizeof(vs), "level: %d voltage: %d temp: %d\n", props.batteryLevel,
props.batteryVoltageMillivolts, props.batteryTemperatureTenthsCelsius);
write(fd, vs, strlen(vs));
if (!mHealthdConfig->batteryCurrentNowPath.isEmpty()) {
@ -523,7 +580,7 @@ void BatteryMonitor::dumpState(int fd) {
}
if (!mHealthdConfig->batteryCurrentNowPath.isEmpty()) {
snprintf(vs, sizeof(vs), "current now: %d\n", props.batteryCurrent);
snprintf(vs, sizeof(vs), "current now: %d\n", props.batteryCurrentMicroamps);
write(fd, vs, strlen(vs));
}
@ -533,7 +590,7 @@ void BatteryMonitor::dumpState(int fd) {
}
if (!mHealthdConfig->batteryFullChargePath.isEmpty()) {
snprintf(vs, sizeof(vs), "Full charge: %d\n", props.batteryFullCharge);
snprintf(vs, sizeof(vs), "Full charge: %d\n", props.batteryFullChargeUah);
write(fd, vs, strlen(vs));
}
}

View file

@ -25,6 +25,10 @@
#include <healthd/healthd.h>
namespace aidl::android::hardware::health {
class HealthInfo;
} // namespace aidl::android::hardware::health
namespace android {
namespace hardware {
namespace health {
@ -59,9 +63,10 @@ class BatteryMonitor {
status_t getProperty(int id, struct BatteryProperty *val);
void dumpState(int fd);
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;
android::hardware::health::V1_0::HealthInfo getHealthInfo_1_0() const;
android::hardware::health::V2_0::HealthInfo getHealthInfo_2_0() const;
android::hardware::health::V2_1::HealthInfo getHealthInfo_2_1() const;
const aidl::android::hardware::health::HealthInfo& getHealthInfo() const;
void updateValues(void);
void logValues(void);
@ -76,15 +81,16 @@ class BatteryMonitor {
bool mBatteryDevicePresent;
int mBatteryFixedCapacity;
int mBatteryFixedTemperature;
// TODO(b/214126090): to migrate to AIDL HealthInfo
bool mChargerDockOnline;
std::unique_ptr<android::hardware::health::V2_1::HealthInfo> mHealthInfo;
std::unique_ptr<aidl::android::hardware::health::HealthInfo> mHealthInfo;
int readFromFile(const String8& path, std::string* buf);
PowerSupplyType readPowerSupplyType(const String8& path);
bool getBooleanField(const String8& path);
int getIntField(const String8& path);
bool isScopedPowerSupply(const char* name);
static void logValues(const aidl::android::hardware::health::HealthInfo& health_info,
const struct healthd_config& healthd_config);
};
}; // namespace android