android kernel log中会打印出如下healthd log,这些log是什么意思?来自哪里?这篇文章为你解读。
<12>[ 191.726280] .(4)[418:[email protected]]healthd: battery l=4 v=3575 t=30.0 h=2 st=3 c=-248 fc=2946000 cc=1 chg=
<12>[ 191.753749] .(5)[418:[email protected]]healthd: battery l=4 v=3567 t=30.0 h=2 st=3 c=-258 fc=2946000 cc=1 chg=
<12>[ 195.114317] .(5)[418:[email protected]]healthd: battery l=4 v=3667 t=30.0 h=2 st=2 c=446 fc=2946000 cc=1 chg=a
<12>[ 195.122295] .(7)[418:[email protected]]healthd: battery l=4 v=3667 t=30.0 h=2 st=2 c=406 fc=2946000 cc=1 chg=a
<12>[ 195.149265] .(4)[418:[email protected]]healthd: battery l=4 v=3667 t=30.0 h=2 st=2 c=407 fc=2946000 cc=1 chg=a
<12>[ 195.151107] .(4)[418:[email protected]]healthd: battery l=4 v=3652 t=30.0 h=2 st=2 c=304 fc=2946000 cc=1 chg=a
<12>[ 195.162849] .(4)[418:[email protected]]healthd: battery l=4 v=3647 t=30.0 h=2 st=2 c=299 fc=2946000 cc=1 chg=a
<12>[ 200.414571] .(7)[418:[email protected]]healthd: battery l=4 v=3572 t=30.0 h=2 st=3 c=-258 fc=2946000 cc=1 chg=
<12>[ 200.417265] .(7)[418:[email protected]]healthd: battery l=4 v=3572 t=30.0 h=2 st=3 c=-253 fc=2946000 cc=1 chg=
<12>[ 200.420810] .(7)[418:[email protected]]healthd: battery l=4 v=3572 t=30.0 h=2 st=3 c=-274 fc=2946000 cc=1 chg=
<12>[ 203.755133] .(6)[418:[email protected]]healthd: battery l=4 v=3806 t=30.0 h=2 st=3 c=1365 fc=2946000 cc=1 chg=
<12>[ 203.994594] .(6)[418:[email protected]]healthd: battery l=4 v=3606 t=30.0 h=2 st=2 c=-29 fc=2946000 cc=1 chg=a
<12>[ 203.997249] .(5)[418:[email protected]]healthd: battery l=4 v=3606 t=30.0 h=2 st=2 c=-32 fc=2946000 cc=1 chg=a
<12>[ 203.999349] .(5)[418:[email protected]]healthd: battery l=4 v=3606 t=30.0 h=2 st=2 c=-28 fc=2946000 cc=1 chg=a
[ 6883.388565] (1)[486:[email protected]]healthd: battery l=25 v=3830 t=30.5 h=2 st=2 c=453400 fc=2946000 cc=0 chg=u
[ 6899.524245] (2)[486:[email protected]]healthd: battery l=25 v=3830 t=30.6 h=2 st=2 c=473600 fc=2946000 cc=0 chg=u
[ 6937.475240] (5)[486:[email protected]]healthd: battery l=25 v=3826 t=30.7 h=2 st=2 c=407700 fc=2946000 cc=0 chg=u
[ 6959.521355] (1)[486:[email protected]]healthd: battery l=25 v=3826 t=30.7 h=2 st=2 c=406400 fc=2946000 cc=0 chg=u
[ 7002.385107] (0)[486:[email protected]]healthd: battery l=26 v=3827 t=30.8 h=2 st=2 c=370400 fc=2946000 cc=0 chg=u
[ 7019.522528] (1)[486:[email protected]]healthd: battery l=26 v=3827 t=30.9 h=2 st=2 c=469300 fc=2946000 cc=0 chg=u
通过代码跟踪可以大概知道log含义:
/frameworks/native/services/batteryservice/include/batteryservice/BatteryServiceConstants.h
18 enum {
19 BATTERY_HEALTH_UNKNOWN = 1,
20 BATTERY_HEALTH_GOOD = 2,
21 BATTERY_HEALTH_OVERHEAT = 3,
22 BATTERY_HEALTH_DEAD = 4,
23 BATTERY_HEALTH_OVER_VOLTAGE = 5,
24 BATTERY_HEALTH_UNSPECIFIED_FAILURE = 6,
25 BATTERY_HEALTH_COLD = 7,
26 };
kernel log中的healthd log是从android 代码 /system/core/healthd/BatteryMonitor.cpp
打印出来的:
201 bool BatteryMonitor::update(void) {
...
214 props.batteryVoltage = getIntField(mHealthdConfig->batteryVoltagePath) / 1000;
215
216 if (!mHealthdConfig->batteryCurrentNowPath.isEmpty())
217 props.batteryCurrent = getIntField(mHealthdConfig->batteryCurrentNowPath) / 1000;
218
219 if (!mHealthdConfig->batteryFullChargePath.isEmpty())
220 props.batteryFullCharge = getIntField(mHealthdConfig->batteryFullChargePath);
221
222 if (!mHealthdConfig->batteryCycleCountPath.isEmpty())
223 props.batteryCycleCount = getIntField(mHealthdConfig->batteryCycleCountPath);
224
225 if (!mHealthdConfig->batteryChargeCounterPath.isEmpty())
226 props.batteryChargeCounter = getIntField(mHealthdConfig->batteryChargeCounterPath);
227
...
234 if (readFromFile(mHealthdConfig->batteryStatusPath, &buf) > 0)
235 props.batteryStatus = getBatteryStatus(buf.c_str());
236
237 if (readFromFile(mHealthdConfig->batteryHealthPath, &buf) > 0)
238 props.batteryHealth = getBatteryHealth(buf.c_str());
...
294 if (logthis) {
295 char dmesgline[256];
296 size_t len;
297 if (props.batteryPresent) {
298 snprintf(dmesgline, sizeof(dmesgline),
299 "battery l=%d v=%d t=%s%d.%d h=%d st=%d",
300 props.batteryLevel, props.batteryVoltage,
301 props.batteryTemperature < 0 ? "-" : "",
302 abs(props.batteryTemperature / 10),
303 abs(props.batteryTemperature % 10), props.batteryHealth,
304 props.batteryStatus);
305
306 len = strlen(dmesgline);
307 if (!mHealthdConfig->batteryCurrentNowPath.isEmpty()) {
308 len += snprintf(dmesgline + len, sizeof(dmesgline) - len,
309 " c=%d", props.batteryCurrent);
310 }
311
312 if (!mHealthdConfig->batteryFullChargePath.isEmpty()) {
313 len += snprintf(dmesgline + len, sizeof(dmesgline) - len,
314 " fc=%d", props.batteryFullCharge);
315 }
316
317 if (!mHealthdConfig->batteryCycleCountPath.isEmpty()) {
318 len += snprintf(dmesgline + len, sizeof(dmesgline) - len,
319 " cc=%d", props.batteryCycleCount);
320 }
321 } else {
322 len = snprintf(dmesgline, sizeof(dmesgline),
323 "battery none");
324 }
325
326 snprintf(dmesgline + len, sizeof(dmesgline) - len, " chg=%s%s%s",
327 props.chargerAcOnline ? "a" : "",
328 props.chargerUsbOnline ? "u" : "",
329 props.chargerWirelessOnline ? "w" : "");
330
331 KLOG_WARNING(LOG_TAG, "%s\n", dmesgline);
332 }
android 上层打印的log是通过读power_supply 相关的节点数据:
# ls sys/class/power_supply/
ac battery charger usb
# ls sys/class/power_supply/battery/
capacity charge_counter charge_full current_avg current_now cycle_count device health power present status subsystem technology temp type uevent voltage_now wakeup13
文件节点:
/kernel-4.9/drivers/power/supply/power_supply_sysfs.c
43 static ssize_t power_supply_show_property(struct device *dev,
44 struct device_attribute *attr,
45 char *buf) {
46 static char *type_text[] = {
47 "Unknown", "Battery", "UPS", "Mains", "USB",
48 "USB_DCP", "USB_CDP", "USB_ACA", "Wireless", "USB_C",
49 "USB_PD", "USB_PD_DRP"
50 };
51 static char *status_text[] = {
52 "Unknown", "Charging", "Discharging", "Not charging", "Full",
53 "Cmd discharging"
54 };
55 static char *charge_type[] = {
56 "Unknown", "N/A", "Trickle", "Fast"
57 };
58 static char *health_text[] = {
59 "Unknown", "Good", "Overheat", "Dead", "Over voltage",
60 "Unspecified failure", "Cold", "Watchdog timer expire",
61 "Safety timer expire"
62 };
63 static char *technology_text[] = {
64 "Unknown", "NiMH", "Li-ion", "Li-poly", "LiFe", "NiCd",
65 "LiMn"
66 };
67 static char *capacity_level_text[] = {
68 "Unknown", "Critical", "Low", "Normal", "High", "Full"
69 };
70 static char *scope_text[] = {
71 "Unknown", "System", "Device"
72 };
73 ssize_t ret = 0;
74 struct power_supply *psy = dev_get_drvdata(dev);
75 const ptrdiff_t off = attr - power_supply_attrs;
76 union power_supply_propval value;
77
78 if (off == POWER_SUPPLY_PROP_TYPE) {
79 value.intval = psy->desc->type;
80 } else {
81 ret = power_supply_get_property(psy, off, &value);
82
83 if (ret < 0) {
84 if (ret == -ENODATA)
85 dev_dbg(dev, "driver has no data for `%s' property\n",
86 attr->attr.name);
87 else if (ret != -ENODEV && ret != -EAGAIN)
88 dev_err(dev, "driver failed to report `%s' property: %zd\n",
89 attr->attr.name, ret);
90 return ret;
91 }
92 }
93
94 if (off == POWER_SUPPLY_PROP_STATUS)
95 return sprintf(buf, "%s\n", status_text[value.intval]);
96 else if (off == POWER_SUPPLY_PROP_CHARGE_TYPE)
97 return sprintf(buf, "%s\n", charge_type[value.intval]);
98 else if (off == POWER_SUPPLY_PROP_HEALTH)
99 return sprintf(buf, "%s\n", health_text[value.intval]);
100 else if (off == POWER_SUPPLY_PROP_TECHNOLOGY)
101 return sprintf(buf, "%s\n", technology_text[value.intval]);
102 else if (off == POWER_SUPPLY_PROP_CAPACITY_LEVEL)
103 return sprintf(buf, "%s\n", capacity_level_text[value.intval]);
104 else if (off == POWER_SUPPLY_PROP_TYPE)
105 return sprintf(buf, "%s\n", type_text[value.intval]);
106 else if (off == POWER_SUPPLY_PROP_SCOPE)
107 return sprintf(buf, "%s\n", scope_text[value.intval]);
108 else if (off >= POWER_SUPPLY_PROP_MODEL_NAME)
109 return sprintf(buf, "%s\n", value.strval);
110
111 if (off == POWER_SUPPLY_PROP_CHARGE_COUNTER_EXT)
112 return sprintf(buf, "%lld\n", value.int64val);
113 else
114 return sprintf(buf, "%d\n", value.intval);
115 }
注册power_supply:
/kernel-4.9/drivers/power/supply/power_supply_core.c
833 struct power_supply *__must_check power_supply_register(struct device *parent,
834 const struct power_supply_desc *desc,
835 const struct power_supply_config *cfg)
836 {
837 return __power_supply_register(parent, desc, cfg, true);
838 }
839 EXPORT_SYMBOL_GPL(power_supply_register);
每个平台的芯片产的实现方法不一样,如下的文件节点可知有ac battery charger usb 几个地方调用power_supply_register 注册这个power_supply。
# ls sys/class/power_supply/
ac battery charger usb
而android 上层在kernel 打印的healthd 数据就是每个产商实现方法而来的。