• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2013 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define LOG_TAG "healthd"
18 
19 #include <healthd/healthd.h>
20 #include <healthd/BatteryMonitor.h>
21 
22 #include <dirent.h>
23 #include <errno.h>
24 #include <fcntl.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <sys/types.h>
28 #include <unistd.h>
29 
30 #include <algorithm>
31 #include <memory>
32 
33 #include <android-base/file.h>
34 #include <android-base/parseint.h>
35 #include <android-base/strings.h>
36 #include <batteryservice/BatteryService.h>
37 #include <cutils/klog.h>
38 #include <cutils/properties.h>
39 #include <utils/Errors.h>
40 #include <utils/String8.h>
41 #include <utils/Vector.h>
42 
43 #define POWER_SUPPLY_SUBSYSTEM "power_supply"
44 #define POWER_SUPPLY_SYSFS_PATH "/sys/class/" POWER_SUPPLY_SUBSYSTEM
45 #define FAKE_BATTERY_CAPACITY 42
46 #define FAKE_BATTERY_TEMPERATURE 424
47 #define MILLION 1.0e6
48 #define DEFAULT_VBUS_VOLTAGE 5000000
49 
50 namespace android {
51 
52 struct sysfsStringEnumMap {
53     const char* s;
54     int val;
55 };
56 
mapSysfsString(const char * str,struct sysfsStringEnumMap map[])57 static int mapSysfsString(const char* str,
58                           struct sysfsStringEnumMap map[]) {
59     for (int i = 0; map[i].s; i++)
60         if (!strcmp(str, map[i].s))
61             return map[i].val;
62 
63     return -1;
64 }
65 
initBatteryProperties(BatteryProperties * props)66 static void initBatteryProperties(BatteryProperties* props) {
67     props->chargerAcOnline = false;
68     props->chargerUsbOnline = false;
69     props->chargerWirelessOnline = false;
70     props->maxChargingCurrent = 0;
71     props->maxChargingVoltage = 0;
72     props->batteryStatus = BATTERY_STATUS_UNKNOWN;
73     props->batteryHealth = BATTERY_HEALTH_UNKNOWN;
74     props->batteryPresent = false;
75     props->batteryLevel = 0;
76     props->batteryVoltage = 0;
77     props->batteryTemperature = 0;
78     props->batteryCurrent = 0;
79     props->batteryCycleCount = 0;
80     props->batteryFullCharge = 0;
81     props->batteryChargeCounter = 0;
82     props->batteryTechnology.clear();
83 }
84 
BatteryMonitor()85 BatteryMonitor::BatteryMonitor()
86     : mHealthdConfig(nullptr),
87       mBatteryDevicePresent(false),
88       mBatteryFixedCapacity(0),
89       mBatteryFixedTemperature(0) {
90     initBatteryProperties(&props);
91 }
92 
getBatteryProperties(BatteryMonitor * batteryMonitor)93 struct BatteryProperties getBatteryProperties(BatteryMonitor* batteryMonitor) {
94     return batteryMonitor->props;
95 }
96 
getBatteryStatus(const char * status)97 int BatteryMonitor::getBatteryStatus(const char* status) {
98     int ret;
99     struct sysfsStringEnumMap batteryStatusMap[] = {
100         { "Unknown", BATTERY_STATUS_UNKNOWN },
101         { "Charging", BATTERY_STATUS_CHARGING },
102         { "Discharging", BATTERY_STATUS_DISCHARGING },
103         { "Not charging", BATTERY_STATUS_NOT_CHARGING },
104         { "Full", BATTERY_STATUS_FULL },
105         { NULL, 0 },
106     };
107 
108     ret = mapSysfsString(status, batteryStatusMap);
109     if (ret < 0) {
110         KLOG_WARNING(LOG_TAG, "Unknown battery status '%s'\n", status);
111         ret = BATTERY_STATUS_UNKNOWN;
112     }
113 
114     return ret;
115 }
116 
getBatteryHealth(const char * status)117 int BatteryMonitor::getBatteryHealth(const char* status) {
118     int ret;
119     struct sysfsStringEnumMap batteryHealthMap[] = {
120         { "Unknown", BATTERY_HEALTH_UNKNOWN },
121         { "Good", BATTERY_HEALTH_GOOD },
122         { "Overheat", BATTERY_HEALTH_OVERHEAT },
123         { "Dead", BATTERY_HEALTH_DEAD },
124         { "Over voltage", BATTERY_HEALTH_OVER_VOLTAGE },
125         { "Unspecified failure", BATTERY_HEALTH_UNSPECIFIED_FAILURE },
126         { "Cold", BATTERY_HEALTH_COLD },
127         // battery health values from JEITA spec
128         { "Warm", BATTERY_HEALTH_GOOD },
129         { "Cool", BATTERY_HEALTH_GOOD },
130         { "Hot", BATTERY_HEALTH_OVERHEAT },
131         { NULL, 0 },
132     };
133 
134     ret = mapSysfsString(status, batteryHealthMap);
135     if (ret < 0) {
136         KLOG_WARNING(LOG_TAG, "Unknown battery health '%s'\n", status);
137         ret = BATTERY_HEALTH_UNKNOWN;
138     }
139 
140     return ret;
141 }
142 
readFromFile(const String8 & path,std::string * buf)143 int BatteryMonitor::readFromFile(const String8& path, std::string* buf) {
144     if (android::base::ReadFileToString(path.c_str(), buf)) {
145         *buf = android::base::Trim(*buf);
146     }
147     return buf->length();
148 }
149 
readPowerSupplyType(const String8 & path)150 BatteryMonitor::PowerSupplyType BatteryMonitor::readPowerSupplyType(const String8& path) {
151     std::string buf;
152     int ret;
153     struct sysfsStringEnumMap supplyTypeMap[] = {
154             { "Unknown", ANDROID_POWER_SUPPLY_TYPE_UNKNOWN },
155             { "Battery", ANDROID_POWER_SUPPLY_TYPE_BATTERY },
156             { "UPS", ANDROID_POWER_SUPPLY_TYPE_AC },
157             { "Mains", ANDROID_POWER_SUPPLY_TYPE_AC },
158             { "USB", ANDROID_POWER_SUPPLY_TYPE_USB },
159             { "USB_DCP", ANDROID_POWER_SUPPLY_TYPE_AC },
160             { "USB_HVDCP", ANDROID_POWER_SUPPLY_TYPE_AC },
161             { "USB_CDP", ANDROID_POWER_SUPPLY_TYPE_AC },
162             { "USB_ACA", ANDROID_POWER_SUPPLY_TYPE_AC },
163             { "USB_C", ANDROID_POWER_SUPPLY_TYPE_AC },
164             { "USB_PD", ANDROID_POWER_SUPPLY_TYPE_AC },
165             { "USB_PD_DRP", ANDROID_POWER_SUPPLY_TYPE_USB },
166             { "Wireless", ANDROID_POWER_SUPPLY_TYPE_WIRELESS },
167             { NULL, 0 },
168     };
169 
170     if (readFromFile(path, &buf) <= 0)
171         return ANDROID_POWER_SUPPLY_TYPE_UNKNOWN;
172 
173     ret = mapSysfsString(buf.c_str(), supplyTypeMap);
174     if (ret < 0) {
175         KLOG_WARNING(LOG_TAG, "Unknown power supply type '%s'\n", buf.c_str());
176         ret = ANDROID_POWER_SUPPLY_TYPE_UNKNOWN;
177     }
178 
179     return static_cast<BatteryMonitor::PowerSupplyType>(ret);
180 }
181 
getBooleanField(const String8 & path)182 bool BatteryMonitor::getBooleanField(const String8& path) {
183     std::string buf;
184     bool value = false;
185 
186     if (readFromFile(path, &buf) > 0)
187         if (buf[0] != '0')
188             value = true;
189 
190     return value;
191 }
192 
getIntField(const String8 & path)193 int BatteryMonitor::getIntField(const String8& path) {
194     std::string buf;
195     int value = 0;
196 
197     if (readFromFile(path, &buf) > 0)
198         android::base::ParseInt(buf, &value);
199 
200     return value;
201 }
202 
update(void)203 bool BatteryMonitor::update(void) {
204     bool logthis;
205 
206     initBatteryProperties(&props);
207 
208     if (!mHealthdConfig->batteryPresentPath.isEmpty())
209         props.batteryPresent = getBooleanField(mHealthdConfig->batteryPresentPath);
210     else
211         props.batteryPresent = mBatteryDevicePresent;
212 
213     props.batteryLevel = mBatteryFixedCapacity ?
214         mBatteryFixedCapacity :
215         getIntField(mHealthdConfig->batteryCapacityPath);
216     props.batteryVoltage = getIntField(mHealthdConfig->batteryVoltagePath) / 1000;
217 
218     if (!mHealthdConfig->batteryCurrentNowPath.isEmpty())
219         props.batteryCurrent = getIntField(mHealthdConfig->batteryCurrentNowPath) / 1000;
220 
221     if (!mHealthdConfig->batteryFullChargePath.isEmpty())
222         props.batteryFullCharge = getIntField(mHealthdConfig->batteryFullChargePath);
223 
224     if (!mHealthdConfig->batteryCycleCountPath.isEmpty())
225         props.batteryCycleCount = getIntField(mHealthdConfig->batteryCycleCountPath);
226 
227     if (!mHealthdConfig->batteryChargeCounterPath.isEmpty())
228         props.batteryChargeCounter = getIntField(mHealthdConfig->batteryChargeCounterPath);
229 
230     props.batteryTemperature = mBatteryFixedTemperature ?
231         mBatteryFixedTemperature :
232         getIntField(mHealthdConfig->batteryTemperaturePath);
233 
234     std::string buf;
235 
236     if (readFromFile(mHealthdConfig->batteryStatusPath, &buf) > 0)
237         props.batteryStatus = getBatteryStatus(buf.c_str());
238 
239     if (readFromFile(mHealthdConfig->batteryHealthPath, &buf) > 0)
240         props.batteryHealth = getBatteryHealth(buf.c_str());
241 
242     if (readFromFile(mHealthdConfig->batteryTechnologyPath, &buf) > 0)
243         props.batteryTechnology = String8(buf.c_str());
244 
245     double MaxPower = 0;
246 
247     for (size_t i = 0; i < mChargerNames.size(); i++) {
248         String8 path;
249         path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH,
250                           mChargerNames[i].string());
251         if (getIntField(path)) {
252             path.clear();
253             path.appendFormat("%s/%s/type", POWER_SUPPLY_SYSFS_PATH,
254                               mChargerNames[i].string());
255             switch(readPowerSupplyType(path)) {
256             case ANDROID_POWER_SUPPLY_TYPE_AC:
257                 props.chargerAcOnline = true;
258                 break;
259             case ANDROID_POWER_SUPPLY_TYPE_USB:
260                 props.chargerUsbOnline = true;
261                 break;
262             case ANDROID_POWER_SUPPLY_TYPE_WIRELESS:
263                 props.chargerWirelessOnline = true;
264                 break;
265             default:
266                 KLOG_WARNING(LOG_TAG, "%s: Unknown power supply type\n",
267                              mChargerNames[i].string());
268             }
269             path.clear();
270             path.appendFormat("%s/%s/current_max", POWER_SUPPLY_SYSFS_PATH,
271                               mChargerNames[i].string());
272             int ChargingCurrent =
273                     (access(path.string(), R_OK) == 0) ? getIntField(path) : 0;
274 
275             path.clear();
276             path.appendFormat("%s/%s/voltage_max", POWER_SUPPLY_SYSFS_PATH,
277                               mChargerNames[i].string());
278 
279             int ChargingVoltage =
280                 (access(path.string(), R_OK) == 0) ? getIntField(path) :
281                 DEFAULT_VBUS_VOLTAGE;
282 
283             double power = ((double)ChargingCurrent / MILLION) *
284                            ((double)ChargingVoltage / MILLION);
285             if (MaxPower < power) {
286                 props.maxChargingCurrent = ChargingCurrent;
287                 props.maxChargingVoltage = ChargingVoltage;
288                 MaxPower = power;
289             }
290         }
291     }
292 
293     logthis = !healthd_board_battery_update(&props);
294 
295     if (logthis) {
296         char dmesgline[256];
297         size_t len;
298         if (props.batteryPresent) {
299             snprintf(dmesgline, sizeof(dmesgline),
300                  "battery l=%d v=%d t=%s%d.%d h=%d st=%d",
301                  props.batteryLevel, props.batteryVoltage,
302                  props.batteryTemperature < 0 ? "-" : "",
303                  abs(props.batteryTemperature / 10),
304                  abs(props.batteryTemperature % 10), props.batteryHealth,
305                  props.batteryStatus);
306 
307             len = strlen(dmesgline);
308             if (!mHealthdConfig->batteryCurrentNowPath.isEmpty()) {
309                 len += snprintf(dmesgline + len, sizeof(dmesgline) - len,
310                                 " c=%d", props.batteryCurrent);
311             }
312 
313             if (!mHealthdConfig->batteryFullChargePath.isEmpty()) {
314                 len += snprintf(dmesgline + len, sizeof(dmesgline) - len,
315                                 " fc=%d", props.batteryFullCharge);
316             }
317 
318             if (!mHealthdConfig->batteryCycleCountPath.isEmpty()) {
319                 len += snprintf(dmesgline + len, sizeof(dmesgline) - len,
320                                 " cc=%d", props.batteryCycleCount);
321             }
322         } else {
323             len = snprintf(dmesgline, sizeof(dmesgline),
324                  "battery none");
325         }
326 
327         snprintf(dmesgline + len, sizeof(dmesgline) - len, " chg=%s%s%s",
328                  props.chargerAcOnline ? "a" : "",
329                  props.chargerUsbOnline ? "u" : "",
330                  props.chargerWirelessOnline ? "w" : "");
331 
332         KLOG_WARNING(LOG_TAG, "%s\n", dmesgline);
333     }
334 
335     healthd_mode_ops->battery_update(&props);
336     return props.chargerAcOnline | props.chargerUsbOnline |
337             props.chargerWirelessOnline;
338 }
339 
getChargeStatus()340 int BatteryMonitor::getChargeStatus() {
341     int result = BATTERY_STATUS_UNKNOWN;
342     if (!mHealthdConfig->batteryStatusPath.isEmpty()) {
343         std::string buf;
344         if (readFromFile(mHealthdConfig->batteryStatusPath, &buf) > 0)
345             result = getBatteryStatus(buf.c_str());
346     }
347     return result;
348 }
349 
getProperty(int id,struct BatteryProperty * val)350 status_t BatteryMonitor::getProperty(int id, struct BatteryProperty *val) {
351     status_t ret = BAD_VALUE;
352     std::string buf;
353 
354     val->valueInt64 = LONG_MIN;
355 
356     switch(id) {
357     case BATTERY_PROP_CHARGE_COUNTER:
358         if (!mHealthdConfig->batteryChargeCounterPath.isEmpty()) {
359             val->valueInt64 =
360                 getIntField(mHealthdConfig->batteryChargeCounterPath);
361             ret = OK;
362         } else {
363             ret = NAME_NOT_FOUND;
364         }
365         break;
366 
367     case BATTERY_PROP_CURRENT_NOW:
368         if (!mHealthdConfig->batteryCurrentNowPath.isEmpty()) {
369             val->valueInt64 =
370                 getIntField(mHealthdConfig->batteryCurrentNowPath);
371             ret = OK;
372         } else {
373             ret = NAME_NOT_FOUND;
374         }
375         break;
376 
377     case BATTERY_PROP_CURRENT_AVG:
378         if (!mHealthdConfig->batteryCurrentAvgPath.isEmpty()) {
379             val->valueInt64 =
380                 getIntField(mHealthdConfig->batteryCurrentAvgPath);
381             ret = OK;
382         } else {
383             ret = NAME_NOT_FOUND;
384         }
385         break;
386 
387     case BATTERY_PROP_CAPACITY:
388         if (!mHealthdConfig->batteryCapacityPath.isEmpty()) {
389             val->valueInt64 =
390                 getIntField(mHealthdConfig->batteryCapacityPath);
391             ret = OK;
392         } else {
393             ret = NAME_NOT_FOUND;
394         }
395         break;
396 
397     case BATTERY_PROP_ENERGY_COUNTER:
398         if (mHealthdConfig->energyCounter) {
399             ret = mHealthdConfig->energyCounter(&val->valueInt64);
400         } else {
401             ret = NAME_NOT_FOUND;
402         }
403         break;
404 
405     case BATTERY_PROP_BATTERY_STATUS:
406         val->valueInt64 = getChargeStatus();
407         ret = OK;
408         break;
409 
410     default:
411         break;
412     }
413 
414     return ret;
415 }
416 
dumpState(int fd)417 void BatteryMonitor::dumpState(int fd) {
418     int v;
419     char vs[128];
420 
421     snprintf(vs, sizeof(vs), "ac: %d usb: %d wireless: %d current_max: %d voltage_max: %d\n",
422              props.chargerAcOnline, props.chargerUsbOnline,
423              props.chargerWirelessOnline, props.maxChargingCurrent,
424              props.maxChargingVoltage);
425     write(fd, vs, strlen(vs));
426     snprintf(vs, sizeof(vs), "status: %d health: %d present: %d\n",
427              props.batteryStatus, props.batteryHealth, props.batteryPresent);
428     write(fd, vs, strlen(vs));
429     snprintf(vs, sizeof(vs), "level: %d voltage: %d temp: %d\n",
430              props.batteryLevel, props.batteryVoltage,
431              props.batteryTemperature);
432     write(fd, vs, strlen(vs));
433 
434     if (!mHealthdConfig->batteryCurrentNowPath.isEmpty()) {
435         v = getIntField(mHealthdConfig->batteryCurrentNowPath);
436         snprintf(vs, sizeof(vs), "current now: %d\n", v);
437         write(fd, vs, strlen(vs));
438     }
439 
440     if (!mHealthdConfig->batteryCurrentAvgPath.isEmpty()) {
441         v = getIntField(mHealthdConfig->batteryCurrentAvgPath);
442         snprintf(vs, sizeof(vs), "current avg: %d\n", v);
443         write(fd, vs, strlen(vs));
444     }
445 
446     if (!mHealthdConfig->batteryChargeCounterPath.isEmpty()) {
447         v = getIntField(mHealthdConfig->batteryChargeCounterPath);
448         snprintf(vs, sizeof(vs), "charge counter: %d\n", v);
449         write(fd, vs, strlen(vs));
450     }
451 
452     if (!mHealthdConfig->batteryCurrentNowPath.isEmpty()) {
453         snprintf(vs, sizeof(vs), "current now: %d\n", props.batteryCurrent);
454         write(fd, vs, strlen(vs));
455     }
456 
457     if (!mHealthdConfig->batteryCycleCountPath.isEmpty()) {
458         snprintf(vs, sizeof(vs), "cycle count: %d\n", props.batteryCycleCount);
459         write(fd, vs, strlen(vs));
460     }
461 
462     if (!mHealthdConfig->batteryFullChargePath.isEmpty()) {
463         snprintf(vs, sizeof(vs), "Full charge: %d\n", props.batteryFullCharge);
464         write(fd, vs, strlen(vs));
465     }
466 }
467 
init(struct healthd_config * hc)468 void BatteryMonitor::init(struct healthd_config *hc) {
469     String8 path;
470     char pval[PROPERTY_VALUE_MAX];
471 
472     mHealthdConfig = hc;
473     std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(POWER_SUPPLY_SYSFS_PATH), closedir);
474     if (dir == NULL) {
475         KLOG_ERROR(LOG_TAG, "Could not open %s\n", POWER_SUPPLY_SYSFS_PATH);
476     } else {
477         struct dirent* entry;
478 
479         while ((entry = readdir(dir.get()))) {
480             const char* name = entry->d_name;
481             std::vector<String8>::iterator itIgnoreName;
482 
483             if (!strcmp(name, ".") || !strcmp(name, ".."))
484                 continue;
485 
486             itIgnoreName = find(hc->ignorePowerSupplyNames.begin(),
487                                 hc->ignorePowerSupplyNames.end(), String8(name));
488             if (itIgnoreName != hc->ignorePowerSupplyNames.end())
489                 continue;
490 
491             // Look for "type" file in each subdirectory
492             path.clear();
493             path.appendFormat("%s/%s/type", POWER_SUPPLY_SYSFS_PATH, name);
494             switch(readPowerSupplyType(path)) {
495             case ANDROID_POWER_SUPPLY_TYPE_AC:
496             case ANDROID_POWER_SUPPLY_TYPE_USB:
497             case ANDROID_POWER_SUPPLY_TYPE_WIRELESS:
498                 path.clear();
499                 path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH, name);
500                 if (access(path.string(), R_OK) == 0)
501                     mChargerNames.add(String8(name));
502                 break;
503 
504             case ANDROID_POWER_SUPPLY_TYPE_BATTERY:
505                 mBatteryDevicePresent = true;
506 
507                 if (mHealthdConfig->batteryStatusPath.isEmpty()) {
508                     path.clear();
509                     path.appendFormat("%s/%s/status", POWER_SUPPLY_SYSFS_PATH,
510                                       name);
511                     if (access(path, R_OK) == 0)
512                         mHealthdConfig->batteryStatusPath = path;
513                 }
514 
515                 if (mHealthdConfig->batteryHealthPath.isEmpty()) {
516                     path.clear();
517                     path.appendFormat("%s/%s/health", POWER_SUPPLY_SYSFS_PATH,
518                                       name);
519                     if (access(path, R_OK) == 0)
520                         mHealthdConfig->batteryHealthPath = path;
521                 }
522 
523                 if (mHealthdConfig->batteryPresentPath.isEmpty()) {
524                     path.clear();
525                     path.appendFormat("%s/%s/present", POWER_SUPPLY_SYSFS_PATH,
526                                       name);
527                     if (access(path, R_OK) == 0)
528                         mHealthdConfig->batteryPresentPath = path;
529                 }
530 
531                 if (mHealthdConfig->batteryCapacityPath.isEmpty()) {
532                     path.clear();
533                     path.appendFormat("%s/%s/capacity", POWER_SUPPLY_SYSFS_PATH,
534                                       name);
535                     if (access(path, R_OK) == 0)
536                         mHealthdConfig->batteryCapacityPath = path;
537                 }
538 
539                 if (mHealthdConfig->batteryVoltagePath.isEmpty()) {
540                     path.clear();
541                     path.appendFormat("%s/%s/voltage_now",
542                                       POWER_SUPPLY_SYSFS_PATH, name);
543                     if (access(path, R_OK) == 0) {
544                         mHealthdConfig->batteryVoltagePath = path;
545                     }
546                 }
547 
548                 if (mHealthdConfig->batteryFullChargePath.isEmpty()) {
549                     path.clear();
550                     path.appendFormat("%s/%s/charge_full",
551                                       POWER_SUPPLY_SYSFS_PATH, name);
552                     if (access(path, R_OK) == 0)
553                         mHealthdConfig->batteryFullChargePath = path;
554                 }
555 
556                 if (mHealthdConfig->batteryCurrentNowPath.isEmpty()) {
557                     path.clear();
558                     path.appendFormat("%s/%s/current_now",
559                                       POWER_SUPPLY_SYSFS_PATH, name);
560                     if (access(path, R_OK) == 0)
561                         mHealthdConfig->batteryCurrentNowPath = path;
562                 }
563 
564                 if (mHealthdConfig->batteryCycleCountPath.isEmpty()) {
565                     path.clear();
566                     path.appendFormat("%s/%s/cycle_count",
567                                       POWER_SUPPLY_SYSFS_PATH, name);
568                     if (access(path, R_OK) == 0)
569                         mHealthdConfig->batteryCycleCountPath = path;
570                 }
571 
572                 if (mHealthdConfig->batteryCurrentAvgPath.isEmpty()) {
573                     path.clear();
574                     path.appendFormat("%s/%s/current_avg",
575                                       POWER_SUPPLY_SYSFS_PATH, name);
576                     if (access(path, R_OK) == 0)
577                         mHealthdConfig->batteryCurrentAvgPath = path;
578                 }
579 
580                 if (mHealthdConfig->batteryChargeCounterPath.isEmpty()) {
581                     path.clear();
582                     path.appendFormat("%s/%s/charge_counter",
583                                       POWER_SUPPLY_SYSFS_PATH, name);
584                     if (access(path, R_OK) == 0)
585                         mHealthdConfig->batteryChargeCounterPath = path;
586                 }
587 
588                 if (mHealthdConfig->batteryTemperaturePath.isEmpty()) {
589                     path.clear();
590                     path.appendFormat("%s/%s/temp", POWER_SUPPLY_SYSFS_PATH,
591                                       name);
592                     if (access(path, R_OK) == 0) {
593                         mHealthdConfig->batteryTemperaturePath = path;
594                     }
595                 }
596 
597                 if (mHealthdConfig->batteryTechnologyPath.isEmpty()) {
598                     path.clear();
599                     path.appendFormat("%s/%s/technology",
600                                       POWER_SUPPLY_SYSFS_PATH, name);
601                     if (access(path, R_OK) == 0)
602                         mHealthdConfig->batteryTechnologyPath = path;
603                 }
604 
605                 break;
606 
607             case ANDROID_POWER_SUPPLY_TYPE_UNKNOWN:
608                 break;
609             }
610         }
611     }
612 
613     // Typically the case for devices which do not have a battery and
614     // and are always plugged into AC mains.
615     if (!mBatteryDevicePresent) {
616         KLOG_WARNING(LOG_TAG, "No battery devices found\n");
617         hc->periodic_chores_interval_fast = -1;
618         hc->periodic_chores_interval_slow = -1;
619     } else {
620         if (mHealthdConfig->batteryStatusPath.isEmpty())
621             KLOG_WARNING(LOG_TAG, "BatteryStatusPath not found\n");
622         if (mHealthdConfig->batteryHealthPath.isEmpty())
623             KLOG_WARNING(LOG_TAG, "BatteryHealthPath not found\n");
624         if (mHealthdConfig->batteryPresentPath.isEmpty())
625             KLOG_WARNING(LOG_TAG, "BatteryPresentPath not found\n");
626         if (mHealthdConfig->batteryCapacityPath.isEmpty())
627             KLOG_WARNING(LOG_TAG, "BatteryCapacityPath not found\n");
628         if (mHealthdConfig->batteryVoltagePath.isEmpty())
629             KLOG_WARNING(LOG_TAG, "BatteryVoltagePath not found\n");
630         if (mHealthdConfig->batteryTemperaturePath.isEmpty())
631             KLOG_WARNING(LOG_TAG, "BatteryTemperaturePath not found\n");
632         if (mHealthdConfig->batteryTechnologyPath.isEmpty())
633             KLOG_WARNING(LOG_TAG, "BatteryTechnologyPath not found\n");
634         if (mHealthdConfig->batteryCurrentNowPath.isEmpty())
635             KLOG_WARNING(LOG_TAG, "BatteryCurrentNowPath not found\n");
636         if (mHealthdConfig->batteryFullChargePath.isEmpty())
637             KLOG_WARNING(LOG_TAG, "BatteryFullChargePath not found\n");
638         if (mHealthdConfig->batteryCycleCountPath.isEmpty())
639             KLOG_WARNING(LOG_TAG, "BatteryCycleCountPath not found\n");
640     }
641 
642     if (property_get("ro.boot.fake_battery", pval, NULL) > 0
643                                                && strtol(pval, NULL, 10) != 0) {
644         mBatteryFixedCapacity = FAKE_BATTERY_CAPACITY;
645         mBatteryFixedTemperature = FAKE_BATTERY_TEMPERATURE;
646     }
647 }
648 
649 }; // namespace android
650