目录
Android PowerSupply (二)power_supply_core
Android PowerSupply (三)power_supply_sys
Android PowerSupply (四)ChargeIC SGM41511 IC driver调试
Android PowerSupply (五)ChargeIC SGM41511 IC简介
Android Healthd BartteryMonitor
Healthd
health@1.0:android.hardware.health@1.0
的缩写,指的是 Android 8.0 中发布的运行状况 HIDL 的 1.0 版 HAL。
health@2.0:android.hardware.health@2.0
的缩写,指的是 Android 9 中发布的运行状况 HIDL 的 2.0 版 HAL。
AndroidP 引入了从 health@1.0 HAL 升级的主要版本 android.hardware.health
HAL 2.0。新版 HAL 具有以下优势:
- 框架代码和供应商代码之间的区别更清楚。
- 弃用了不必要的
healthd
守护进程。 - 供应商对运行状况信息报告进行自定义的自由度更高。
- 更多设备运行状况信息(不仅包括电池信息)。
代码路径:android9/code/system/core/healthd
代码结构:
:~/prj/android9/code/system/core/healthd$ tree -l
.
├── Android.bp
├── android.hardware.health@2.0-service.rc
├── Android.mk
├── animation.h
├── AnimationParser.cpp
├── AnimationParser.h
├── BatteryMonitor.cpp
├── charger.cpp
├── charger_test.cpp
├── healthd_draw.cpp
├── healthd_draw.h
├── healthd_mode_charger.cpp
├── healthd.rc
├── HealthServiceDefault.cpp
├── HealthServiceHealthd.cpp
├── images
│ ├── battery_fail.png
│ └── battery_scale.png
├── include
│ └── healthd
│ ├── BatteryMonitor.h
│ └── healthd.h
├── OWNERS
└── tests
├── Android.mk
└── AnimationParser_test.cpp
在Android9 中运行的情况
该框架尝试从 hwservicemanager
中检索 health@2.0 服务。如果检索失败,它将调用 health@1.0(在 Android 8.x 中提供)。同时,它还会保留原有代码路径,以便 Android 9 系统映像与 Android 8.x 供应商映像兼容。框架不会同时从两个 HAL 中检索信息,因为设备上只能存在一个服务版本(1.0 或 2.0)。
注意:对于原有代码路径,进程/库将一直保留到 health@1.0 被弃用。
对于其他模式:
BartteryMonitor Class类
BatteryMonitor类
class BatteryMonitor {
public:
enum PowerSupplyType {
ANDROID_POWER_SUPPLY_TYPE_UNKNOWN = 0,
ANDROID_POWER_SUPPLY_TYPE_AC,
ANDROID_POWER_SUPPLY_TYPE_USB,
ANDROID_POWER_SUPPLY_TYPE_WIRELESS,
ANDROID_POWER_SUPPLY_TYPE_BATTERY
};
//!< Battery关注点在系统供电上,获取power supply的类型分别有 AC, usb, wireless battery 4种类型 By: jixuan 2021年6月10日
BatteryMonitor();
void init(struct healthd_config *hc); //!< 初始化
bool update(void); //!< Battery信息的更新
int getChargeStatus(); //!< 充电状态获取
status_t getProperty(int id, struct BatteryProperty *val);
void dumpState(int fd);
friend struct BatteryProperties getBatteryProperties(BatteryMonitor* batteryMonitor);
private:
struct healthd_config *mHealthdConfig;
Vector<String8> mChargerNames;
bool mBatteryDevicePresent;
int mBatteryFixedCapacity;
int mBatteryFixedTemperature;
struct BatteryProperties props;
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);
int getIntField(const String8& path);
};
init函数
void BatteryMonitor::init(struct healthd_config *hc) {
String8 path;
char pval[PROPERTY_VALUE_MAX];
mHealthdConfig = hc;
std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(POWER_SUPPLY_SYSFS_PATH), closedir);
//!< unique_ptr C++11 智能指针的一种,用于内存管理
//!< decltype 为了解决复杂的类型声明 是decltype类型说明符关键字
if (dir == NULL) { //!< 打开powersupply目录,默认sys/class/power_supply
KLOG_ERROR(LOG_TAG, "Could not open %s\n", POWER_SUPPLY_SYSFS_PATH);
} else {
struct dirent* entry;
while ((entry = readdir(dir.get()))) { //!< 获取powersupply下每一个目录名
const char* name = entry->d_name;
path.clear();
path.appendFormat("%s/%s/type", POWER_SUPPLY_SYSFS_PATH, name);
switch(readPowerSupplyType(path)) { //!< 判断powersupply类型
case ANDROID_POWER_SUPPLY_TYPE_AC:
case ANDROID_POWER_SUPPLY_TYPE_WIRELESS:
path.clear();
path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH, name);
if (access(path.string(), R_OK) == 0)
mChargerNames.add(String8(name));
//!< 添加一个charge类型 powersupply 基础属性online
break;
case ANDROID_POWER_SUPPLY_TYPE_BATTERY:
mBatteryDevicePresent = true;
//!< 找到battery powersupply存在
//!< 逐个判断battery下存在的属性
if (mHealthdConfig->batteryStatusPath.isEmpty()) {
path.clear();
path.appendFormat("%s/%s/status", POWER_SUPPLY_SYSFS_PATH,
name);
if (access(path, R_OK) == 0)
mHealthdConfig->batteryStatusPath = path;
} //!< 查找status 若存在配置路径
if (mHealthdConfig->batteryHealthPath.isEmpty()) {
path.clear();
path.appendFormat("%s/%s/health", POWER_SUPPLY_SYSFS_PATH,
name);
if (access(path, R_OK) == 0)
mHealthdConfig->batteryHealthPath = path;
} //!< 查找Health 若存在配置路径
if (mHealthdConfig->batteryPresentPath.isEmpty()) {
path.clear();
path.appendFormat("%s/%s/present", POWER_SUPPLY_SYSFS_PATH,
name);
if (access(path, R_OK) == 0)
mHealthdConfig->batteryPresentPath = path;
} //!< 查找Present 若存在配置路径
if (mHealthdConfig->batteryCapacityPath.isEmpty()) {
path.clear();
path.appendFormat("%s/%s/capacity", POWER_SUPPLY_SYSFS_PATH,
name);
if (access(path, R_OK) == 0)
mHealthdConfig->batteryCapacityPath = path;
} //!< 查找Capacity 若存在配置路径
if (mHealthdConfig->batteryVoltagePath.isEmpty()) {
path.clear();
path.appendFormat("%s/%s/voltage_now",
POWER_SUPPLY_SYSFS_PATH, name);
if (access(path, R_OK) == 0) {
mHealthdConfig->batteryVoltagePath = path;
}
} //!< 查找voltage_now 若存在配置路径
if (mHealthdConfig->batteryFullChargePath.isEmpty()) {
path.clear();
path.appendFormat("%s/%s/charge_full",
POWER_SUPPLY_SYSFS_PATH, name);
if (access(path, R_OK) == 0)
mHealthdConfig->batteryFullChargePath = path;
} //!< 查找charge_full 若存在配置路径
if (mHealthdConfig->batteryCurrentNowPath.isEmpty()) {
path.clear();
path.appendFormat("%s/%s/current_now",
POWER_SUPPLY_SYSFS_PATH, name);
if (access(path, R_OK) == 0)
mHealthdConfig->batteryCurrentNowPath = path;
} //!< 查找current_now 若存在配置路径
if (mHealthdConfig->batteryCycleCountPath.isEmpty()) {
path.clear();
path.appendFormat("%s/%s/cycle_count",
POWER_SUPPLY_SYSFS_PATH, name);
if (access(path, R_OK) == 0)
mHealthdConfig->batteryCycleCountPath = path;
}//!< 查找cycle_count 若存在配置路径
if (mHealthdConfig->batteryCurrentAvgPath.isEmpty()) {
path.clear();
path.appendFormat("%s/%s/current_avg",
POWER_SUPPLY_SYSFS_PATH, name);
if (access(path, R_OK) == 0)
mHealthdConfig->batteryCurrentAvgPath = path;
}//!< 查找current_avg 若存在配置路径
if (mHealthdConfig->batteryTemperaturePath.isEmpty()) {
path.clear();
path.appendFormat("%s/%s/temp", POWER_SUPPLY_SYSFS_PATH,
name);
if (access(path, R_OK) == 0) {
mHealthdConfig->batteryTemperaturePath = path;
}
}//!< 查找temp 若存在配置路径
break;
case ANDROID_POWER_SUPPLY_TYPE_UNKNOWN:
break;
}
}
}
//!< 无电池状态,长供电设备
if (!mBatteryDevicePresent) {
KLOG_WARNING(LOG_TAG, "No battery devices found\n");
hc->periodic_chores_interval_fast = -1;
hc->periodic_chores_interval_slow = -1;
} else {
if (mHealthdConfig->batteryStatusPath.isEmpty())
KLOG_WARNING(LOG_TAG, "BatteryStatusPath not found\n");
。。。
//!< 不存在的属性 log输出
}
if (property_get("ro.boot.fake_battery", pval, NULL) > 0
&& strtol(pval, NULL, 10) != 0) {
mBatteryFixedCapacity = FAKE_BATTERY_CAPACITY;
mBatteryFixedTemperature = FAKE_BATTERY_TEMPERATURE;
}
}
Update函数
bool BatteryMonitor::update(void) {
bool logthis;
initBatteryProperties(&props);
//!< 赋初值,设置属性为0活false
if (!mHealthdConfig->batteryPresentPath.isEmpty())
props.batteryPresent = getBooleanField(mHealthdConfig->batteryPresentPath);
else
props.batteryPresent = mBatteryDevicePresent;
//!< 通过获取到的路径,读取节点属性 进行更新
props.batteryLevel = mBatteryFixedCapacity ?
mBatteryFixedCapacity :
getIntField(mHealthdConfig->batteryCapacityPath);
props.batteryVoltage = getIntField(mHealthdConfig->batteryVoltagePath) / 1000;
//!< 若存Capacity 属性 在根据读到的值 计算容量
if (!mHealthdConfig->batteryCurrentNowPath.isEmpty())
props.batteryCurrent = getIntField(mHealthdConfig->batteryCurrentNowPath) / 1000;
//!< 同上 By: jixuan 2021年6月10日
if (!mHealthdConfig->batteryFullChargePath.isEmpty())
props.batteryFullCharge = getIntField(mHealthdConfig->batteryFullChargePath);
//!< 同上 By: jixuan 2021年6月10日
if (!mHealthdConfig->batteryCycleCountPath.isEmpty())
props.batteryCycleCount = getIntField(mHealthdConfig->batteryCycleCountPath);
if (!mHealthdConfig->batteryChargeCounterPath.isEmpty())
props.batteryChargeCounter = getIntField(mHealthdConfig->batteryChargeCounterPath);
props.batteryTemperature = mBatteryFixedTemperature ?
mBatteryFixedTemperature :
getIntField(mHealthdConfig->batteryTemperaturePath);
std::string buf;
if (readFromFile(mHealthdConfig->batteryStatusPath, &buf) > 0)
props.batteryStatus = getBatteryStatus(buf.c_str());
//!< 若存在status,更新status
if (readFromFile(mHealthdConfig->batteryHealthPath, &buf) > 0)
props.batteryHealth = getBatteryHealth(buf.c_str());
//!< 若存在Health,更新Health
unsigned int i;
double MaxPower = 0;
for (i = 0; i < mChargerNames.size(); i++) {
//!< 解析每一个power Charger type
String8 path;
path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH,
mChargerNames[i].string());
if (getIntField(path)) {
path.clear();
path.appendFormat("%s/%s/type", POWER_SUPPLY_SYSFS_PATH,
mChargerNames[i].string());
switch(readPowerSupplyType(path)) {
//!< 判断是哪种power supply type By: jixuan 2021年6月10日
case ANDROID_POWER_SUPPLY_TYPE_AC:
props.chargerAcOnline = true;
break;
case ANDROID_POWER_SUPPLY_TYPE_USB:
props.chargerUsbOnline = true;
break;
case ANDROID_POWER_SUPPLY_TYPE_WIRELESS:
props.chargerWirelessOnline = true;
break;
default:
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,
mChargerNames[i].string());
int ChargingCurrent =
(access(path.string(), R_OK) == 0) ? getIntField(path) : 0;
path.clear();
path.appendFormat("%s/%s/voltage_max", POWER_SUPPLY_SYSFS_PATH,
mChargerNames[i].string());
int ChargingVoltage =
(access(path.string(), R_OK) == 0) ? getIntField(path) :
DEFAULT_VBUS_VOLTAGE;
double power = ((double)ChargingCurrent / MILLION) *
((double)ChargingVoltage / MILLION);
if (MaxPower < power) {
props.maxChargingCurrent = ChargingCurrent;
props.maxChargingVoltage = ChargingVoltage;
MaxPower = power;
}
}
}
if(!mBatteryDevicePresent) {
props.batteryPresent = true;
props.batteryStatus = 3;
props.batteryHealth = 2;
props.batteryLevel = 80;
props.batteryVoltage = 4000;
props.batteryTemperature = 250;
props.batteryCurrent = 288;
props.batteryCycleCount = 0;
props.batteryFullCharge = 3481000;
props.batteryChargeCounter = 2828520;
props.batteryTechnology = "Li-ion";
}
//!< 配置默认值
logthis = !healthd_board_battery_update(&props);
if (logthis) {
//!< 若需要监听Battery相关的状态log,可以从这里输出
char dmesgline[256];
size_t len;
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);
len = strlen(dmesgline);
if (!mHealthdConfig->batteryCurrentNowPath.isEmpty()) {
len += snprintf(dmesgline + len, sizeof(dmesgline) - len,
" c=%d", props.batteryCurrent);
}
if (!mHealthdConfig->batteryFullChargePath.isEmpty()) {
len += snprintf(dmesgline + len, sizeof(dmesgline) - len,
" fc=%d", props.batteryFullCharge);
}
if (!mHealthdConfig->batteryCycleCountPath.isEmpty()) {
len += snprintf(dmesgline + len, sizeof(dmesgline) - len,
" cc=%d", props.batteryCycleCount);
}
} else {
len = snprintf(dmesgline, sizeof(dmesgline),
"battery none");
}
snprintf(dmesgline + len, sizeof(dmesgline) - len, " chg=%s%s%s",
props.chargerAcOnline ? "a" : "",
props.chargerUsbOnline ? "u" : "",
props.chargerWirelessOnline ? "w" : "");
KLOG_WARNING(LOG_TAG, "%s\n", dmesgline);
}
//!< 输出此刻读取到的状态
healthd_mode_ops->battery_update(&props);
//!< 调用update 接口上报更新
return props.chargerAcOnline | props.chargerUsbOnline |
props.chargerWirelessOnline;
}