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